MVCについて本格的に触れたのはここ数年のことで、きっかけとしては仕事を発注してくれたとこの開発責任者から、
「コードが複雑化してきたので、MVC的な形にできたら修正していってくれませんか?」
と、言われてからだった。
MVC化する前のプロジェクト
プロジェクトが始まって大体3~4か月ぐらいで、実際のプロジェクトはさらに半年前から始まっていた感じあたりで上のMVCへの修正依頼?が来たのだった。
プロジェクト自体は大手の請負で、開発責任者(発注者側)がアプリの設計を議論、検討したのちに こちらがそれに従って実装するというものでこちらは請け負っていたのだが、徐々に崩れていって、
発注者が「こんな形に実装してね」といい、こちらが「こんな感じでどうですか?」とソースコードを提出する流れになっていた。(実態はもっとフラットでドライな感じだった)
一応、クラス図的なものを提出することもあったのだが、プロジェクト全体ではそう活発に行われていなかったし、締め切りに追われていたときは省略されていたので、アプリの実態はソースコードから確認する状態ではあった。(終盤あたりでは発注者側である程度アプリ仕様書の方もまとまったのか、仕様書が機能する状態にはなっていた)
また、こちらが提出したコードのレビューも実質なく、後日まとめてバグ報告という形でコードの修正を行うものであった。
そんな感じのプロジェクトで、コード量も増えていき、途中開発者が抜けて、その受け継ぎ作業もだんだん増えていった中、一部を修正すると他のところにも影響が出てくる乱雑したコード状況※になってきて頭を抱えていたところに
先の「MVC化に修正していってくれない?」というお言葉がかかったのであった。
(※基本的な分割はできていたので、そこまでひどいものではなかったと思う)
作業しやすくなるのはこちらとしても大歓迎な状況ではあったので、「渡りに船」、プログラマーあるあるの、「一からソースコードから作り直し症候群」、「他の人が書いたコードはひどいコードという認識」も手助けし、こちらが携わるコードあたりをMVC化し始めていったのであった※。
(※全部が全部ひどいコードではなかったのだが、途中で抜けた開発者の部分を修正するときは大変苦労をした覚えがあるし、重大なバグもそのあたりに固まっていた。)
実際にMVCへコードを修正
といっても、そこまでMVCに精通しているわけではなかったのでこちらが認識しているMVCを下に挙げると、
- Modelクラスにアプリで使用するデータをまとめ、
- それらが変更されたときにViewクラス側を変更する
みたいな認識であることを先に断っておく。
(ControllerについてはViewクラス側にだいたいまとめておく感じではあった。)
あとMVC化する上ではUniRxを利用していた。
初めてMVC化した部分はまあまあ問題なく修正でき、かつデータ操作がModelクラスにまとまったので、非常にわかりやすくなって、MVC化の効果をよく実感できたのだが、
この成功体験が次のよくない結果を生んだ要因にはなったのかと思う。
締め切り前
締め切り前にはよくバグやら追加仕様やらで忙しくなるのはよくあるとは思うが、このプロジェクトでも同じような状況ではあったと思う。
そんな中でも、「コードを整理したほうが後々の人の手助けになるという善意」と「先に経験したMVC化の効果の高さ」から、実際の作業に加えてMVC化も一緒に進めていいったのだが、プロジェクト終盤で行うべきではないほど複雑な部分に手をつけてしまったという過ちを犯してしまった。(この辺りはこちらの経験不足だったと反省している。)
初めにMVC化した部分は比較的に修正した場合の影響範囲も小さくて、やりやすかったのだが、この失敗した部分は影響範囲が広くかつ、コードもマルチスレッドやら複雑になりやすい部分も手助けし、
「修正すると次から次へと問題が絡まってでてくるというひどい状態」に出くわしてしまった。
結局、一回ですべての部分をMVC化するのを諦めて、部分部分でMVC化をする方針にしたのだが、それもうまくできなかった。
MVC化した部分と元のコードでは処理の流れが異なり、それらを連結するコードがさらに必要になって、MVC化するメリットが生まれづらい状況になっていることに作業をし終えてから気づいたのだが、後の祭りだった。
MVC化した部分でバグが出てしまったので、元の状態に戻す必要があったのだが、その間に「色々な機能追加がありコードが追加」、「MVC化によってコード内容が大きく変わってしまった」ことも手助けとなり、バージョンコントロール機能をプロジェクトでは使用していたのだが、それでも元に戻すには難しい状態になっていたため、ひたすらバグ修正を行う形をとった。
特にMVC化によってイベントのコールバックの多重ネストによるバグは把握しづらいものであった。
この辺りはこちらとしても非常に反省していて、発注者側にも申し訳ないと思っていて、非常に苦い経験であった。
作業時間以外にもこの部分のすべてのMVC化を進めていったところ、全体をMVC化できるなら非常に効果があるとは感じたのだが、MVC化したコードには特にテストコードもなく、バグがないと保証できなかったため、提出はしないでおき、新しく発生したバグを修正していったのであった。
(テストコードについてはプロジェクト自体にはなく、参加してから途中のあたりに開発責任者から「やっぱりテストコードも必要になるかな?」的なこともあって、クラス図と同じく少しはしたのだがプロジェクトに定着しなかった+仕様変更したときにテストコードも一緒に変更する維持コストもあり、最終的にはないものとしてあつかっていたことを追記しておく。)
一応、発注者側もプロジェクトのすべての情報をこちらに開示していたわけではない、とは思うので、もしかしたら内部ではテストコードがあって、きれいな仕様書、クラス図一覧、UMLの資料がある理想的な開発環境だったかもしれないことを追記しておくが、真相の方はこちらはわからないことを了承していただきたい。
そんなこんなでプロジェクトの締め切りは延び 、後半にこちらの失態もあり迷惑も掛けたのではあるが、最後の最後で一番高い報酬金(普段の倍近く)をいただくことができたのは発注者側の寛容の精神の賜物ではあったと思い、数年遅いのではあるのだがここに感謝の言葉を残しておく。
結論
MVC化およびこのプロジェクトから得た教訓を列挙しておきたい。
- MVC化するならはじめから(異なる設計思想を同じプロジェクトには混ぜない)
- 乱雑なコードを修正する労力より、一から作成する労力の方が簡単。(特に精神的な面で)
- イベントコールバックの多重ネストには気をつけろ
- テストコードは複雑になってから効果を生むため一緒に作成する必要があるが、仕様変更という維持コストもある
その後
このプロジェクトの後に他のプロジェクトにも携わり、そちらでは初めからMVCを意識したつくりにしたおかげか、変更があったときにも楽に対応できたかなと思う。
また、 一応この経験からこちらが公開しているUnityライブラリにはMVC的な作りを手助けするクラス・機能を持たせている。
その際の試行錯誤でちょっと使えないものもライブラリ内には存在するのだが、今のところは削除せず、お暇な方が覗けるよう残しておいている。(ルートフォルダーのMVCフォルダーの中がそれにあたり、ドキュメントの方も特に残していない。使えないと思ったのは管理するには大きくなりすぎたが大きな理由である)
これを書いている時ではMonoBehaviourWithSubComponentsクラスとそれに関係するAttributeでMVC化を行えるようにしていて、今のところはそれに満足している。
Unityライブラリの方はAppacheライセンスVer2で使用していることを明記していただければ無保証ではあるが、自由に使用していただいて構わないことを追記してこの記事の方を閉終えようと思う。