大規模なプログラミングをする場合に、依存は大敵です。
ここで言っている
大規模というのは、BtoC系で、アクセスの多い公開型のサービスの事を言っています。
小さなスニペットレベルのライブラリなどは、単体で機能が完結できるのでいいのですが、
それらが組み合わさってできあがるサービスはもはや大規模サービスと言ってもいいかもですね。
こうしたいわゆる
Webサービスを構築するチームに入った経験がある人であれば、
依存関係がどれほど自分たちを苦しめるかを十分理解している事でしょう。
世の中の、コード記述の参考になる書籍などは、依存関係を無くすことが正解として書かれいているので、
依存関係って、良質なプログラミングの大敵と言ってもいいかもしれません。
個人的な経験と元に、どうすれば依存関係をプログラミングで防げるかを考えてみたいと思います。
依存関係がなぜ厄介なのか
プログラムの些細な一つの変更が、他のモジュールやライブラリに波及してしまう事を依存状態というのですが、
テストが壊れやすくなり、CI/CDの信頼性が落ちるため、依存は良くないと言われ続けています。
外部のアップデートに自分たちのスケジュールが引っ張られることもあり、ライブラリなどを使う場合のバージョン管理にも気を使わなければいけません。
また、不具合発生時に、デバッグ時に原因の追跡が難しくなるので、どこでバグが起きたのか分かりづらいというのは、本当に厄介なんですね。
依存関係を減らす基本的な考え方
機能が有すれば、インターフェース(抽象)に依存し、実装に依存しないようにするというのがいいでしょう。
モジュールやクラスは単一責任を意識し、他に必要以上に干渉しない。
グローバルな状態(シングルトンや静的変数)をなるべく使わない。
外部ライブラリへの依存は明確に「入口」を決めておく(ラッパーを作る)。
こうした事を念頭に設計をすると、依存しずらい構造を作ることはできますが、
慣れていないといきなりの依存しなラブル状態は作れないでしょう。
実際にやってみてよかった設計パターン
DI(Dependency Injection:依存性の注入)を使うと、テストもしやすくなるし、依存の制御がしやすくなります。
レイヤードアーキテクチャ(例:Controller → Service → Repository)で、レイヤー間の責任を分離するという方法があるので、MVCの少し先の手法について学ぶのも悪くないでしょう。
ドメイン駆動設計(DDD)で「ドメインモデル」を中心に据えることで、インフラ依存が減る。
色々書いてみたが、難しい事を考えずに、まず依存する場合としない場合について深く考えてみると、設計もスムーズにできてしまいます。
図などに書いていくうちに思考がまとまってくる事も多いし、ドキュメントはやっぱり作る事でまとまり方が違ってきます。
現実的にどう対処すべきか
すべての依存を排除するのは非現実的。(ていうか、無理ゲー)
大事なのは「依存の可視化」と「管理」です。
Webサービスというのは、その後の運用もセットで考えなければいけません。
一度作ったら手放しになる開発というのは、あまりみたことがありません。
悪い意味で放置サービスはたくさんあるのですが、インフラや、基盤モジュールなどのセキュリティアップデートもできないという依存っぷりのサービスもこれまでたくさん見てきました。
チームでの
コードレビューでは「依存増えてない?」という観点を持つと良いかも。
CIで依存ライブラリのバージョン変更検知や互換性チェックを自動化するのも効果的。
この辺はまるっきり別ライブラリを使ったほうが、依存チェックが効率的(高発見率)かもですね。
あとがき
依存はゼロにできないが、「健全に管理する」ことはできるので、
依存しなラブル状態というのは、できる限りという状態がベストだと考えたられる。
設計の段階で意識しないと、後で返ってくるツケは大きいんだけど、実際に開発着手してから気が付く事も多々ある。(経験談)
プログラミングとは、コードを書くことではなく、依存を調整する技術でもあるというのは、全然言い過ぎじゃなく、プログラマー全員相違なはず。
依存システムを見つけたら、「自分ならこうする・・・」という思考を持てるようになったら、十分な上級プログラマーと言ってもいいかも。
あれ?そう考えたら、依存システムって、ある意味、「謎解きプログラム」と考えてもいいかもですね。
0 件のコメント:
コメントを投稿