新しもの好きプログラマの耳より情報ブログ

仕事でもあるプログラミングについて役に立ちそうな情報を発信していこうというブログです。役に立たなそうな情報はfacebookで。

Yaml.NETのデシリアライズで、対応するメンバが無い場合に例外を出さず処理する方法

以前の記事で書いたとおり、Yaml.NETのデシリアライズは対応するメンバが無い場合に例外を出す処理になっている。(YAMLファイルにある値が、デシリアライズ先のクラスのメンバに無い場合)

この処理は、データを増減させると前方・後方互換が無くなるので、データの増減がありうるバージョンアップをする場合には相性が悪いという問題があった。

この処理を「対応するメンバが無い場合は、無視して処理続行する」という処理に変更する方法を見つけた。試したところ期待通りに動くので、データ増減があっても互換が切れないようにするという目的は達成できそうだ。

方法は簡単で、次のようにデシリアライザの作成時にIgnoreUnmatchedProperties()を指定するだけ。

var deserializer = new DeserializerBuilder().IgnoreUnmatchedProperties().Build();

この動作を試したコミット

このIgnoreUnmatchedPropertiesは、ドキュメントには記載されていない。

しかし、ソースコード上のコメントが次の内容である事、

Determines if an exception or null should be returned if name can't be found in type

それと次のプルリクもあったことから、

https://github.com/aaubry/YamlDotNet/pull/88

上記の使い方で合っているようだ。

これで、バージョンアップによるデータ増減がありうる場合でも、安心してYaml.NETを使えるようになった。

急にVisualStudioのインテリセンスが異常な動きをした場合、Resharperのキャッシュが原因かもしれない

結論から言うと、Resharperで対象ソリューションのキャッシュを削除する事で解決した。

https://pleiades.io/help/resharper/Configuring_Caches_Location.html

VisualStudioを使っていたら、急にインテリセンスの候補が表示されなくなった。マウスでポイントしてみると「Can't resolve Symbol」といったエラーがあちこちで出ている。 VSを立ち上げ直しても、.vsフォルダを削除してみても解決しない。

Resharperを導入していたので、それが原因かもしれないという点に気づいた。 試しにResharperをSuspendしてみたところ解決し、Resumeすると再発した。

https://resharper-support.jetbrains.com/hc/en-us/articles/206546999-How-can-I-temporary-disable-turn-off-ReSharper-

ならおそらくResharperのキャッシュのようなものが原因だろうと思って調べてみたら、やはり独自に持っているようだ。

この「キャッシュのクリーンアップ」の手順を実行する事で、問題が解決した。

https://pleiades.io/help/resharper/Configuring_Caches_Location.html

インテリセンスの問題という事でVisualStudioを最初に疑ってしまったが、Resharperを使っている人はそちらのキャッシュも疑った方が良い。

SlackとTeamsの使い分け方 社内で併用してみて考えたこと

ビジネスチャットツールの中で比較的メジャーな2つ、SlackとTeamsを社内で使っている。この2つは似ているようでいて、使ってみるとかなり違いがある。社内でも使い分けに悩むという声が上がっているので、違いをまとめてみようと思う。

まとめ

Teamsはタスクフォースを作るツール。事前に決めたメンバーの中で、会話もファイルもすべてを共有する。

Slackは個人単位の即席コラボレーションを作るツール。話題ごとにメンバーが変わり、別部署の人が会話に参加したりもする。

つまり、同じ「ビジネスチャットツール」だが、導入することで促進されるコミュニケーションの形が違う。どちらも無料プランがあるし、棲み分けができるので、プロジェクトの性質によって使い分けるのがよさそう。

例えば営業と開発で使うとしたら、

営業と開発それぞれの中で議論し、後で結論だけ部署間の議論へエスカレーションするのがTeams。

営業の会話に、急に開発が「それならこういう提案ができる」などと割り込んでくるのがSlack。

実例

自分が関わっている開発では、次の要求からSlackを主体に使っている。

  • 開発ラインごとに縦割りではなく、ラインを超えた情報共有やアドバイスが出るようなチームにしたい
  • それほど大きくないチームなので、リーダーなど全体を見る立場の人は、全部の会話を流し読みしておきたい(メンションされたときだけ読むのではなく)

逆に、チームごとにきちんと情報統制をしたかったり、上下関係がしっかりしていてエスカレーションという形で相談を受け取りたいなら、Teamsの方が向いている。

それぞれの特徴

それぞれの特徴を、思いつくままいくつかの比較ポイントでまとめてみる。

  • Teamsは、「他のチーム」に話しかけるハードルが高い。自分が所属するチームの中での会話になる。
  • Slackは、「話題を作って、話しかけたいメンバーを呼ぶ」という使い方になるので、チームに話しかけるという考え方が薄い。

  • Teamsは、全員と会話できるチャンネルが無い。まずチームありき。

  • Slackは、全員所属するチャンネルがまず最初に作られる。

  • Teamsは、自分の関わる会話だけを読むという使い方になりやすい。チャンネル内にさらに「会話」があり、会話単位で通知有無が決まっているので。

  • Slackは、すべての会話に目を通す使い方になりやすい。チャンネル単位で通知が来るし、「次の未読の会話へジャンプ」というショートカットキーがある。

  • Teamsは検索機能が大雑把で、チャンネル内検索もない。どちらかというと、検索ではなく会話全体を保存して読み直す使い方になる。

  • Slackは検索機能が強く、チャンネル内や発言者などでの絞り込みもできるので、雑多な会話からキーワードを拾って読み直す使い方になる。

  • Teamsは会話上でできる操作が少なく、Office365の他のアプリを追加してそれを共有する形になる。例えばTODOを管理するなら、Plannerなどをタブで追加してチーム内で共有する。

  • Slackは会話上でできる操作が多く、会話に対して操作したりコマンドを打つ形になる。例えばTODOを管理するなら、会話自体をそのままピン止めしたりリマインドしたりできる。bot系が目立ち、チームで共有するより個人で操作するシーンが多い。

このような特徴から、Teamsは事前に決めたチーム内での強い情報共有(情報統制でもある)を狙った作りで、Slackは全てを共有した上で話題ごとに即席のチームがあちこちで生じる使い方を狙ったツールだと考えられる。

※どの指摘もそうだが、TeamsをSlackっぽく運用することもできるし、その逆もできる。これは、どの運用をやりやすいようにデザインされたツールなのか、という話。

XML,JSON,YAMLの主要シリアライザで、クラスメンバが増減してもデシリアライズできるか調べてみた

結論

OSSを導入できる環境ならJSON.NETで問題なく実現できる。.NET Frameworkだけで使用可能なXmlSerializerも、扱いが少し面倒だが同等に実現できる。

YamlDotNetは、増加は問題ないが減少で問題が出る。

調べた内容

クラスの中身を文字列化してファイル保存する処理(いわゆるシリアライズ)について、主要ないくつかのライブラリで「クラスのメンバが増減しても、デシリアライズできるかどうか」を調べてみた。

確認したのは実際の動作であり、ドキュメントの記載ではない。そのため、残念ながら今後のバージョンアップなどで動作が変わる可能性はある。

なぜ調べたのか

シリアライズは、設定ファイルなどを作成する上でかなり便利に使える。設定項目ごとに処理を書く必要が無いため、項目が多数になることの多い設定ファイルに向いていると思う。

しかし、設定ファイルはバージョンアップ時に設定項目が増減することが多い。 そのため、クラスのメンバが増減した場合でもそのファイルを読み込み(デシリアライズ)できるかどうかが、採用する上では重要なポイントになる。

その点は、ドキュメントにはなかなか明記されていない。元々想定された使い方と違っているので、仕様として保証されていないのは仕方ない。

仕方ないので、バージョンを決めてその実際の動作を調べてみた。

結果のデータ

JSON.NET

.NET Framework 4.5.2 + Newtonsoft.Json 12.0.2 を使用。

変数の追加:デシリアライズ成功。追加された変数は、new時のデフォルト値となった

変数の削除:デシリアライズ成功。削除された変数は、無視された。

注意点:Listにデフォルト値がある場合、デシリアライズ時に上書きではなく追加される(直観と反する動き)

https://github.com/suusanex/sample_json_serialize

YamlDotNet

YamlDotNet 6.1.2 + .NET Framework 4.7.2を使用。

変数の追加:デシリアライズ成功。追加された変数は、new時のデフォルト値となった

変数の削除:デシリアライズ失敗。同名の変数が必ず存在している必要があるため、不要になった変数であっても、過去バージョンとの互換のために残しておく必要がある。プレフィックスobsolete_を付けた変数名を用意し、YamlMemberのAliasで過去バージョンの名前を指定することで、不要な変数を分かりやすく分類することはできた。

リストの読み込み:読み込み対象のリストにデフォルト値がある場合、上書きされる(デフォルト値は消える)。直観通りの動作。

https://github.com/suusanex/sample_yamldotnet_serialize

XmlSerializer

.NET Framework 4.7.2を使用。

前提条件:XmlSerializerは、シリアライズした時のXMLのルート要素が「クラス名」になる。そのため、別のクラスに対してデシリアライズすることができない。サンプルでは、名前空間を分けることで新旧のクラスのクラス名を同一にしている。

変数の追加:デシリアライズ成功。追加された変数は、new時のデフォルト値となった

変数の削除:デシリアライズ成功。削除された変数は、無視された。

注意点:Listにデフォルト値がある場合、デシリアライズ時に上書きではなく追加される(直観と反する動き)

https://github.com/suusanex/sample_xmlserializer_serialize

結果の検討

.NET Frameworkだけを使用するXmlSerializerでも、バージョンアップに耐える処理は実現可能だった。JSON.NETも、それと同様の動きになった。

XmlSerializerは前提条件があるし、設定ファイルくらいの目的だとXMLはパワフルすぎる感があるので、気軽に使うならJSON.NETの方が良さそうだ。(OSSを採用可能な案件であれば)

YamlDotNetは意外にも、YAML内に存在する値がクラスに定義されていないとエラーになってしまう。デシリアライザの設定などで回避できないかを調べたが、良い方法が見つからなかった。

2020/2/14追記:見つかった。この記事を参照。

YAMLにはアンカーとエイリアスがあるためC#のクラスとはXMLJSON以上に相性が良く、最有力候補だと思ったが・・・。バージョンアップがありうる設定ファイルに使用するには、注意が必要になるようだ。

C#で不要な戻り値やout引数を捨てるには_(アンダーバー)を使ったほうが良い

C#で、関数の戻り値やout引数が不要なので捨てたいという場合がある。

今まではnotUseのような適当な名前でダミーの変数を宣言していたが、C# 7.0からはもっと良い書き方が登場していた。

_(アンダーバー)を書けばよい。

これなら型指定もいらないし、書きやすいだけでなく実際にメモリ確保処理がスキップされるのでパフォーマンスにも良いようだ。

async関数の完了を待たない事を明示するためにとりあえず変数で受ける場合にも、これは有効だと思う。

最近のC#はこういう「知らなくても動くコードを書く上では困らないが、知っているとパフォーマンスが上がったりコードが読みやすくなって便利」という改善が多い。意識して調べないと腕が落ちてしまうので、普段から情報収集して色々試す必要がある。

参考:https://docs.microsoft.com/ja-jp/dotnet/csharp/discards

JSON.NETのデシリアライズは、変数が増減していた場合も使える

この記事の内容に加えてXMLYAMLも試してみた、より新しい記事はこちら。 http://suusanex.hatenablog.jp/entry/2019/09/23/171255


JSON.NETのシリアライズ・デシリアライズを採用しようとして、1つ気になる点があったので実験した。.NET 4.5.2 + Newtonsoft.Json 12.0.2 を使用。

用途の都合で、バージョン1でシリアライズした文字列を、ファイル等を介してバージョン2で読み込む可能性がある。

ここで、バージョン2で対象クラスの変数が増減することがありうる。その場合でもデシリアライズは可能なのか?

「クラスが異なるので例外」となるようでは、採用が難しい。デシリアライズに成功し、次のようになってほしい。

  • 増えた変数(JSONには無いが、クラスにはある):クラスのデフォルト値のまま
  • 減った変数(JSONにはあるが、クラスには無い):JSONを無視

実験したところ、期待通りの動作になった。これなら、バージョンアップ可能性がある場合も使えそうだ。

https://github.com/suusanex/sample_json_serialize

横浜駅近くでIT系技術書のある本屋

技術書もビジネス書も何でも揃っていたブックファースト(旧あおい書店)が、ダイエー横浜西口店と共に閉店してしまった・・・。難民となったので、代わりになる本屋を探してみた。

結論

ソフトウェア工学系なら紀伊国屋そごう横浜店が強い。言語・フレームワーク系なら有隣堂横浜駅西口ジョイナス店(エキニア地下)が強い。他はいまいち。

有隣堂の方は22時までだが、そごうは20時まで。ブックファーストの23時には及ばない。平日就業後に本を探す時は早めに帰宅を。

紀伊国屋そごう横浜店

良い。棚4段8個くらいあり、特にPM・モデリング等の設計などのソフトウェア工学系も充実。バラバラではなく、ちゃんとカテゴリごとに良著を揃えてる印象がある。もちろん言語やDB・ネットワーク・クラウドなどもバッチリ。

有隣堂横浜駅西口ジョイナス店(エキニア地下)

良い。棚4段8個くらいあり、雑多な印象は受けるが冊数は多い。どちらかというと言語やフレームワーク系が多く、ソフトウェア工学系は少なめ。少なめと言ってもこの後出てくる店舗より多い。

有隣堂ルミネ横浜店

ダメ。言語の本くらいはあるが、ソフトウェア工学系やDBなど詳細技術本が無い。

有隣堂伊勢佐木町本店

そこそこ。6段2個くらいあり、ソフトウェア工学系が充実。しかしUnityの文字を見かけないなど、スペースの限界を感じる。むしろIT以外の技術書が手厚く見えるので、そちら目当てなら良さそう。

紀伊国屋みなとみらい(コレットマーレ)店

そこそこ。4段2個くらいあり、言語・ソフトウェア工学系に加えてUnityなどのゲーム開発系もあり、バランスは良い。しかし、多いとは言えない。