どこかのだれかへ

ボク、プログラマ。

バイナリデータを拡張性高くするためにXmlみたいな構造を作ってみた感想

バイナリデータって拡張にすごく弱くて、以前苦労しました。バージョンごとに構造体を書いていて管理が面倒でコードも汚くなっていきました。

そこで考えました。key-valueみたく、識別子・サイズ・値を1セットとして、すべてのメンバーやブロックを構成することで、自由にパラメータを追加したり削除することができるんじゃないだろうかと。つまり、JsonXmlのバイナリ化です。

仕事でやる機会がなかったので、現在家で開発中のゲームのフォントデータで採用してみました。

で、実際試したところ、

  • 書くのがめっちゃ面倒
  • ファイルサイズがでかくなる
  • 読み込みが遅い

という問題が出たので止めました。

書くのがめっちゃ面倒、に関してはおそらくXmlからコードに変換するツールとか作れば解決できるとは思います。

実は同じような構想のフレームワークはすでに存在していて、Message PackやGoogleのProtocl Buffersが該当します。Protocol Buffersを見つけたときは「まさにこれだ!」と思ったんですが、生成されるコードが非常に大きく複雑でわかりにくかったので止めました。もっとシンプルなものが欲しかったです。

ファイルサイズがでかくなる、はそりゃ当然で、全部の変数にID(4byte)とサイズ(4byte)を付けたためです。4byte整数1つのために8byteつけりゃ当たり前です。ちなみに当初924KBあったフォントデータは、現在ベタなやり方でやり直した結果、245KBになっています。差がひどい!

読み込みが遅い、も当然で構造体のコピーとメンバ一つ一つswitchに分岐して読み込むじゃ全然違うよねっていう。これは測定していないのでなんともですが、まあ書くのもしんどいです。

つまり拡張性を得るための犠牲がでかすぎたので止めました。今はベタに構造体並べたフォーマットでやっています。フォーマットが変わったら?もう全コンバートでいいんじゃないですかね。

でもいつかは、シンプルで、追加に強いバイナリフォーマットというのを考え出したいところです。

MVVMのViewModelの必要性を感じた

WPFではMVVM(Model/View/ViewModel)パターンを利用しますが、簡単なツールの場合はViewModelの存在意義があんまり無く、恩恵を受けにくく、その存在意義を忘れがちです。

ViewModelがある理由はView(WPFでいえばxaml関係)に関する都合を吸収するためですが、今まで作ってきた小さなツールの場合はそれを必要とすることがあまりなく存在意義は分かっていた物の結構適当に作っていました。

例えば今までだと、ModelにObservableCollectionのプロパティがあるとしたら、ViewModelではそのインスタンスを受け取って同じインスタンスをViewに渡していました。

しかし現在ツールを作っている中で、このコレクションヘのデータの追加を別スレッドでやりたいと思いました。しかしインスタンスをそのままViewに渡しています。ViewはUIスレッドじゃないと更新できません(例外が発生する)つまり、View側の都合でModelに制限が掛かっている状況なのです。せっかくのMVVMなのに、VMが機能してないせいでなんの意味もない状況だと気付きました。

たしかに、ViewModelは結果的に小さいツールでは要らない子になるかもしれまんが、こういうこともあるので、今後はちゃんとViewModel作ろうと思いました。

Google XML Document Format Style Guide

UIエディタの保存にXMLを使用としたときに、要素と属性の使い分けをどうすればいいんだろうかと考えてたときに出会ったのが、Google XML Document Format Style Guideでした。

https://google.github.io/styleguide/xmlstyle.html

C++のスタイルガイドはよく見てましたが、XMLのスタイルガイドもあるのは知りませんでした。

BitmapImageをbyte[]に変換する

各フォーマット毎にBitmapEncorderがあるので、コレを使います。

BitmapImage image = /*pngイメージ*/;
var encorder = new PngBitmapEncoder();
encorder.Frames.Add( BitmapFrame.Create( image ) );
using( var stream = new MemoryStream() )
{
    encorder.Save( stream );
    data = stream.ToArray();
}

1行インライン関数は止めて欲しい

C++の話です。メンバ関数をインラインで書くときに1行で書く場合はありますが、これは避けて欲しいです。なぜならここにブレークポイントを置いたときに引数の値とかを確認することが出来ないからです。

class Hoge{
public:
    // これはヤダ
    void Set( int value ) { value_ = value; }
    
    // これはいい
    void Set( int value )
    {
        value_ = value; // ここにブレークポイント置けば値を確認出来る
    }

private:
    int value_;
};

Null条件演算子というのを初めて知った

WPFとMVVMについて色々調べていたら、C# 6.0からの可能でNull条件演算子があることを知りました。これめっちゃ便利ですね、だいぶコードがすっきりします。

C#はどんどん新しくなっていきますが、全然追ってないのでこんな浦島太郎状態なことに鳴ってしまいます・・・・・・。

eventのnull回避法のメモのほうもNull条件演算子を使うように修正しました。
EventのNullチェックを省略する

そして更新して思ったのは、やっぱ普通に空デリゲートのほうが好きかも知れません(複数からイベントを呼ぶ時に?つけ忘れによる事故がないため)

Elastic tabstops、というコードの整列を勝手にやってくれるヤツ。

Vimプラグインでコードを整列してくれる良いプラグインないかと探しているときに見つけたのがElastic tabstopsです。

f:id:Tepp:20181225200131g:plain

※Elastic tabstopsのWebサイトより引用。
Elastic tabstops - a better way to indent and align code

公式サイトではVisual Studioプラグイン版の紹介もあるので、普段Visual Studioでコーディングしている人は導入してみても良いんじゃないでしょうか。 Webサイトではその実装方法までもが載っているので、いつかVimに組み込みたいです。