概要
ここ一年ほど、シリアル通信を使ったWindows Formアプリを業務で作成していた。
その際に「こうすればよかったな」が集まったので業務の棚卸しを兼ねて書いてみることにする。
前提
アプリ概要
大雑把に言うと、スーパーにあるような自動レジみたいなもの。
WindowsPCに様々な機械が接続されていて、ユーザの入力や払ったお金に応じてサービスを行う機械のUIを作成した。
なお、各機械はシリアル通信でやり取りしており、リアルタイムで監視をする必要があった。
そもそもなんでDIコンテナ?
このUIを作るにあたり、次の問題があったから開発の柔軟性を持たせるためにDIコンテナを使い、
画面の仕様変更への耐性を高めることにした。
- 仕様や要件を把握して音頭をとる人が居ないため、手直しが多くなることが予想される
- 最終的に現行の機械(これも仕様不明)にもアプリを導入する計画があるため、UIを分離しておくと嬉しい
DIコンテナ導入でやったこと
異なる画面で一つしかないインスタンスを無理なく使い回す
一つのシリアルポートにUIの都合とは関係なく送受信で制御を行わなければならないため、
デバイスの大半は別スレッド上でメッセージループを組んで制御していた。
そのため単一の制御用のインスタンスを多数の画面などで使い回す必要があり、
そのクラスへの紐づけ作業などの手間をDIコンテナに押し付けて楽ができた。
UI側を交換可能にする
実際に実装していたときに思いがけず助かった点。
特にシリアル通信はいろいろな理由で接続が切れる。断線、ノイズ、設定ミス、何でもありだ。
こんなとき、「実際に本番コードで使われているプログラム」を使ったテストツールがあれば
最低限の労力で各デバイスの生存確認ができる。
DIコンテナの利用を前提とした疎結合なコードにしていた事により、
逆にUI側のコードも交換可能になっていてこのテストツールの作成が無理なくできていた。
DIコンテナ導入でやったほうが良かったこと
FormのコードにUIスレッド外のコードが入らないようにする
UIスレッド以外からUIを触ってしまうことにより例外を吐かせてしまうのはきっと誰でもやっていることだと思う。
例えばこんな感じのコードを仕込んでおいて、ほかスレッドからのイベントをすべてこのインタフェースを介して処理することにより、
UIコード内にそもそもUIスレッドの外からのコードが入らないようにしておけば、
かなり取り回しが良くなってたと思われる。
ただし、例えばここでForm1クラスがデバイスを使う場合は、互いが互いをインスタンスとして保つ必要が出てしまうから面倒になる。
Form内の画面などにデバイスへの参照をもたせるか、デバイス側が必要になったタイミングでIInvokerクラスのインスタンスを探すなどして、
互いのコンストラクタ内にもう片方のインスタンスを要求しないようにする必要があることには注意。
// DIで指定するインタフェース
public interface IInvoker
{
void Invoke(Action action);
void BeginInvoke(Action action);
}
// デバイスを使うクラス
public class Form1 : Form, IInvoker
{
public void Invoke(Action action) => base.Invoke(action);
public void BeginInvoke(Action action) => base.BeginInvoke(action);
}
// 使われるデバイス
public class Dewice
{
private IInvoker Invoker;
private void OnSomethingOccured()
{
IInvoker.Invoke(() => SomeEvent.BeginInvoke())
}
}
そもそもプロジェクトとしてやるべきだったこと
早い段階でプロジェクトのコントロール権を奪っておく
最初に言った通り、私の視点では開発の音頭を取れる人が自分以外いないように見えた。
曲がりなりにも開発が一段落した今、当時の状況を考えてみると、
もし現在の会社に見切りをつけなかったら、「検証→設計→実装→テスト」の流れと開発スケジュールをこちらから提示して、
どうにかしてプロジェクトのコントロール権をマネージャから奪っておく必要があった。
コードは定期的にコミットする・させる
未熟なマネージメントとリソース不足の恒として、開発中盤以降でスケジュールが危なくなってから人員を補充された。
その人達や今まで自分が仕事で関わってきた人を見ていて気がついたのが、
「コミットの頻度とその人の能力は反比例する」といったことであった。
コミットが小さく適切なコメントを残せる場合、その人は「自分の仕事を小さく分割でき、簡潔に説明できる」能力がある。
適当なコミットや粒度の大きなコミットをしている人が居たらしっかり指導しておくべきだったなと思った。