先日の JXUG の MVVM の補足 を書いたので、どうせだからもうちょっと突っ込んだ話題を残しておきます。Xamarin.Forms などを使う場合は、そんなに多くの人は関わらないでしょう。勉強会でもちらっと話しましたが、ひとりで MVVM すべてを作ったり、数名で MVVM を分け合ったりするのがほとんです。
せっかく V-VM-M と分かれているのだから、ある程度規模が大きくなれば分担しないといけません。最初に2つのパターンが考えられて、
- 縦割りにして、画面ごとに MVVM を一貫して作る。
- 横割りにして、V-VM-M を別々の人に割り当てる。
ことが考えられます。理想的には View をデザイナが受け持ち、VM をプログラマが、M をデータベーススペシャリストが担当するのが良いのですが、人数的な問題や規模的な問題、開発者のスキルのばらつき、遠地なのか近地なのか、同じ会社なのか別会社なのか、という様々な「政治的な」問題が絡み合って、理想的にはできません。となれば、プロジェクトマネジメントも含めて、何らかの妥協点を見つけて、ソフトウェア開発を進めていくことになります。まあ、それこそが「マネジメント」なのですが。
かれこれ5年前の話から
NDA 的には5年経っているので話しても大丈夫なのですが、まあ細かい話は無しにして、Silverlight + MVVM モデルで DataGrid をバインドの落とし穴 をやっていたころです。Silverlight が流行っていて、ActiveX コントロールではなくてブラウザ上に高機能なインターフェースを乗せようとしていた時期ですね。折しも、ちょうど MVVM が発表されたあたりで初期のブームだったのです。
経理系のシステムで、結構規模が大きくかかわっていたのはマネージャ等を除いても30名ぐらいいます。銀行系の大規模とは違うのですが、最近のスマートフォンの開発や、WEB開発に比べれば十分に大きく、そして混乱しやすい人数でもあります。そこに新技術としての Sliverlight と MVVM を同時にぶち込んだところに悲劇があったわけですが…まあ、仕事なのであれこれのトラブルがあってもそれなりに収めるわけなんですがね。
コンサルティング的な立場で入ったはずなのですが、複数の画面を担当することになりました。これもよくありがちで、技術的な点よりも人手でなんとかしようとする人海戦術パターンです。初期の頃から入っていれば設計的になんとかできたのでしょうが、結果的にみれば火消的な時期に入ってしまったため既存の設計に引きずられています。
MVVM パターンのライブラリが別会社だった
ある程度の画面数を超えると、人海戦術的にモノ作りをするパターンにおちいります。まあ、その手のプログラミング自体、労働集約的なところから抜け出せないので、仕方がないといえば仕方ないところです。いまだと、画面数をぐっと減らしてしまうか、共通化することで手数を減らしますよね。あと画面生成を自動化するとか。
そういうものはなくて(今でもそういうものがない会社はたくさんあります)、ひたすら手作業であ画面を作っていきます。Silverlight で画面を作るのですが、画面の部品は別の会社が作っていました。どうやら、ほかのプロジェクトで使ったらしい Sliverlight の画面部品を今回のプロジェクトに流用しようとしたらしく、そこに MVVM のバインドを入れ込んだという訳です。
いやいや、この別会社の部品がひどくて、そもそも Silverlight の Binding は元から揃っているにも関わらず、さらにそれをラップするような同じコントロールをひとつひとつ提供するという技をやってきました。当時、私も MVVM をやり始めたばかりなので、なんでこんな変な形になっているのかわからなかったのですが、あとから考えれば根本的に設計を間違えていたのでしょう。なんだかよくわからない Binding を付加したなんだかよくわからないラップされただけのコントロールで画面を組み合わせると、なんだかよくわからない形で画面部品にアクセスしないといけなくなります。だから、余計混乱するし、別会社のコントロールに不具合が発生するたびにあれこれと時間をロスしていました。
まあ、この手の共通部品は社内で作るのがベストですよね。あるいは、綿密なサンプルと設計をしたうえで社内に持ち込むのがベターです。
画面ごとに縦割りの MVVM は効率が悪い
画面部品を作っている別会社の MVVM の知識も足りないし、まして使う側の社内のメンバの MVVM の知識も足りません。そういう足りない上に、従来の画面ごとに担当を分けていったので更に混乱しています。よくわからない MVVM の知識は、それぞれ V-VM-M に分けて考えてインターフェースをきちっと作ると作業分担をして効率よく進めることができるのですが、従来通り縦割りに MVVM を作りました。このため V-VM-M のすべての知識がないと画面がうまく作れないわけです。
MVVM の社内講習会などはありませんでした。理由としては、MVVM が「解らなくても使いやすい」とされていた画面の部品を別会社から購入したことにより、それをクリアする話だったのですが、実際には VM の Binding が必須なコードになっているので、全然ラップされていません。というか、MVVM の構造を理解せずに画面を作るのであれば、MVVM パターン自体を導入する必要はありませんよね。本末転倒です。
- MVVM を完全にラップする → 従来のイベントベースでコーディングできる
- MVVM を使いやすくラップする → View の Binding 記述などを減らす
のどちらかの方法に進むべきだったのですが、結果的にどちらの悪いところを取ってしまって、MVVM をラップしているけども Binding がむき出しなコントロールを使う羽目に陥りました。そんなややこしいことをするならば、そのまま標準コントロールを使ったほうが楽です。
なので、MVVM をある程度の多人数で作る場合には、
- 全員が MVVM の構造を理解して、画面ごとに縦割りで作る
- MVVM の概要だけ理解して、インターフェースを守って V-VM-M で担当を分ける
というパターンになります。一見、V-VM-M で分けたほうが効率が良いように見えますが、現実は異なります。というのも、構造的に V-VM-M と分けえるとそれぞれの層に特化することはできるのですが、画面ごとに異なるドメインの知識が必要になってしまいます。このため、プロジェクト全体の業務知識がないと、VM が作れないというところに陥ります。
5名ぐらいで分担している場合は、プロジェクト全体の業務知識はさほどではないのですが、30名レベルになると結構なボリュームになります。分業するならば、業務知識はそれぞれで分担できるほうが効率がよいので、MVVM パターンを画面単位で作るのが良いのですが、これ先に言った通りに MVVM パターン全体の知識が必要となってしまいます。そういうジレンマが MVVM パターンにはあるということを理解して MVVM パターンを導入してください。
テスト可能な VM, M を作る
xUnit を使ってテスト可能なコードを書くことにより、コードの品質は上がるしリファクタリングがやりやすくなります。これも数名で書いている分にはちょこちょこと変えられる程度なのでしょうが、30名レベルになるとかなり混雑してきます。
先のプロジェクトでは Model の部分は WCF を通じて SQL Server にアクセスしていました。このため DBA チームがあって、SQL Server の構造にあった Model を返すのですが、これが曲者です。当然、View は Model に合うような構造になっていないので、VM あたりで構造を変えないといけません。いわゆるインピーダンスミスマッチというやつですね。
MVVM パターンのひとつの回避策としては、画面に即した Model をもうひとつ作り、データベースの Model をうまく組み合わせることです。多少冗長にはなりますが、VM が比較的に簡単になるので、これは有効な手段です。ただし、実装中にコロコロとデータベースのテーブル構造が変わるたびに画面用の Model も変更しないといけないためインテグレーション的に不利なところがあります。
もうひとつのパターンは、VM 内で変換する方法です。もとも View と Model のつなぎを担当する VM なのですから、業務ロジック(画面の操作ロジック)も含めて ViewModel をコーディングしていくことも可能です。ただし、これもデータベースのテーブル構造が変わると VM に手を入れなければならず、さらに VM 自体が画面と密着しているために、テーブル構造の変化が VM –> View にまで伝播してしまうことが多く再テストが大変です。
このようなことから、Model の自動テストだけでなく、ViewModel の自動テストも行えると、上記の2つのパターンの複雑さが多少改善されます。Model だけのテストだと VM の再テストが画面操作からしかできなくなって膨大な打鍵試験が発生します。この打鍵試験を減らすことが xUnit の目的なので、このままは本末転倒です。そこで、自動テストがしやすいように VM を作っているスタイルが必須になります。
まあ、担当した画面だけは自動テストっぽい VM の作りをしていたのですが、もともとそういう文化がない会社だったので、そのあたりはダメダメでした。Excel な設計書をきっちりと書いて、なぜか別の人がコーディングして、なぜか別な人がテストするという従来の方法でやっていたので炎上は必須です、といいますか、炎上していました。設計した会社とコーディングをしていた会社がかなり険悪な状態になっていたんですよね。設計する会社が親会社で、コーディングが子会社だったので猶さらその無茶ぶりな圧力は異常なところがありました。別会社ではありますがパワハラに近いものです。
で、オチはどうなったか?
この話、実はオチがあります。
設計するのが親会社、下請けが子会社だったのですが、ある日突然、子会社が親会社を買収することになってですね、プロジェクト間の立場が一転したのです。へこへことコーディングしていた会社が一夜明けて、設計してた会社の上に立つことになって、進捗会議なども一遍しました。なんだかなー、笑えます。会議のパワハラも、いままでのストレスも相まって、えらいことになってました。
で、私はどうなったかというと、元親会社の契約更新ができなくなって2か月程度でお払い箱ですよ。それ以来、その手の技術支援っぽい派遣には手を付けないことにしています 安い派遣で働くよりも、うちで地道に勉強していたほうが将来的に有利ってことですね。