目次
■ソフトウェア設計とメンテナンス
2022.12.05 2024.03.05 約4分
この記事は2017年7月5日発売 『現場で役立つシステム設計の原則〜変更を楽で安全にするオブジェクト指向の実践技法』を取り上げた connpass勉強会 を再編集し、記事化したものです。 |
「良い設計は悪い設計より変更が楽で安全である」これが『現場で役立つシステム設計の原則』の根底にある考え方です。
・変更容易性はどんな効果を生み出すのか
・どうやれば変更を楽に安全にできるのか
最近の技術動向に触れながら説明します。 オブジェクト指向プログラミングの考え方の変化、クラウドベースの分散処理の進展、ドメイン駆動設計の広がりなどを取り上げます。
設計を評価する一番のポイントは「変更容易性」です。
だからといって、目の前のソフトウェアのあらゆる箇所を実際に変更してみて良し悪しの評価をすることってできないですよね。では、どうするのかというと「不吉な臭い」を察知することです。悪い設計のコードには「不吉な臭い」があります。これは実際に変更をしなくても、コードを見て判断できます。(後ほど詳しく解説します。)
ソフトウェアを変更する理由はさまざまですが、根本は事業の存続性を改善することでしょう。企業存続のためには、可能な限り収益をあげ、生き残ることが不可欠です。そのために存続優位性を保つこと、存続劣位から脱却することは常に必要です。この10〜20年で、事業のあらゆる部分にソフトウェアが入り込んでいます。『企業存続 = 常にソフトウェアに関する何らかの変更要求』が考えられるわけです。
これは私自身が一番感じることですが、顧客と会話しながらソフトウェアを設計する段階、リリース段階、運用段階など、過程によって事業活動への理解度は変わります。時間とともに、事業活動や会社の特性、こだわりポイントなど、より深く理解できるようになるでしょう。当然、理解度にあわせて設計も変えていくべき要因になります。
また開発者としてのスキルも上がってきますから、同じ要件でも実現したいことに合わせて変更する可能性も出てきます。
新しい技術を導入することで費用対効果を高くできる可能性が増えています。ソフトウェアの変更なしに移行できればベストですが、そうもいきません。やはりソフトウェア変更が前提になることが多いでしょう。
ソフトウェアの変更が楽で安全であれば、さまざまなメリットを享受できます。
変更が楽で安全であれば「一度やってみて駄目なら別のものをやってみよう」という仮説検証のハードルが下がります。事業活動はある意味で仮説検証の塊ですから、トライアルコストを抑えることができるのは、大きなメリットといえるでしょう。
『変更が多い = ソフトウェアの設計改善を学ぶ機会が増える』といえます。開発者としてのスキルアップにつながり、その学びをソフトウェアに反映できます。
事業活動の変化のスピードは下がり、コストが増えます。当然のようにマイナスポイントが顕在化してしまいます。
「新しい決済方法を追加したいが、1年半で5,000万円かかる」という事例があったとします。決済方法を増やすことが競争劣位を軽減するキーなのに、そのコストが事業存続にかかわるような現象が起きてしまうのではないでしょうか。ちょっとした変更のたびに何千万かかるのでは積極的な事業展開ができず、システムが足枷になってしまいます。
どうしても既存の設計や都合にガチガチに縛られ、そのルールのなかで無理やり抜け道を探すようなスキルが染み付いてしまうんです。本来は「このソフトウェアでこういう事業価値を生み出したいから、こう変更したい」という前向きな成長をしていきたいですよね。
そして、成長の機会が狭まると勉強会や技術書など、他の場に学びの機会を求めます。しかし、せっかく学んだことを実際に自分の仕事に反映できないので、開発者としては、ますますつらくなってしまうでしょう。
コードの不吉な臭い(設計の良し悪し)を判断できる嗅覚を身に付けましょう。
周りの環境や現場の状況によってさまざまですが、私自身が重視しているのは「コードの不吉な臭い」を判断する嗅覚を身に付けることです。これがわかると、「良い形」の習得につながります。下記は、リファクタリング本の中から私が普段コードレビューで気にしているポイントをリストアップしたものです。
「不吉な臭い」を見つけたら「良い形」にリファクタリングする改善サイクルが自然に回り始めるようになります。普段から「良い形」を意識し、コードを書く習慣を身に付けておきましょう。
私自身は、設計に対し「型に基づいて構造を考えることが良いプログラムに繋がる」ことを非常に重視しています。アプリケーションで扱う値の種類を分類し、値の種類ごとの特徴(どんな操作・計算・判断をしたいのか)を、型として定義します。型を実際にコードに落とすときは、カプセル化(オブジェクト指向の基本中の基本)を徹底します。
契約プログラミングは、バートランド・メイヤーの著書『オブジェクト指向 入門』で説明されている概念で、事前条件や事後条件を型で制限し表明する方法です。出版当時は、オブジェクト = 変更を管理するための道具、という考え方が主流でしたが、最近はオプジェクトの状態を変更しない考え方が主流になってきています。不変条件も昔はめんどうでしたが「いやいや、オブジェクトって、一度作ったら内部状態変わらないよ」というように振り切ってしまえば、変更も楽で安全安心です。
より複雑で高レベルな課題には「良い形」だけで対応できない場合があります。良い設計をするためには「分け方・集め方・つなぎ方」の習得も必要です。
設計原則と設計パターンを自分のものにするためには、とにかく手を動かし効果を実感するしかありません。
私が実践する設計の考え方と手法は、この価値観に基づいています。良い設計は悪い設計より変更が楽で安全であることです。
—歴史を伺うのに増田さん以上の方はいらっしゃらないかと。
増田:最初にコンピュータに触ったのは20世紀のこと。もう40年近くも前ですね。実は40年前から immutable な考え方や言語は存在していました。ただメモリーやCPUを考えると、アプリケーションではとても採用できなかった。それが Java が出てきたことで、めちゃくちゃメモリー管理が楽になったんですね。かつては、immutable はアカデミックな世界、現場は mutable しかなかった。なぜ mutable から immutable へ変化したかを考えると、メモリーが格安で使えるようになったし、CPU性能も爆上がりしたからですよね。
—ボトムアップで意識改革するか、レベルの高い技術者がいる現場を求めて次に行くか葛藤中とのことです。
増田:私は自分で興味があるところに自分の場を求めることを繰り返してきた人間なので、後者ですね。
—なかなか外に出られない方もいると思いますが、何かアドバイスはありますか?
増田:「アーキテクチャや設計のレベルを上げよう」という掛け声は、あまり効果がないような気がします。目先の変更が厄介で危険で困っていて「これが楽になるなら、何でも飛びつきます!」くらいの現場だと、実際にリファクタリングしながら、気が付いたら良い設計の仕方を覚えてるパターンはあります。「今のままでもいいんだ」という現場では、もう絶対無理です。エネルギーのある現場ならそこで頑張ってみるのはアリかも知れないですね。
—外に機会を求める場合はぜひ、 Forkwell に登録いただけますと嬉しいですね!
増田:簡単にいうと見方によるっていう感じかな。天動説と地動説のように同じ現象でも人によって見方や捉え方が変わるというか。そういう意味だと、ソフトウェア開発は、あまり変わっていないかも。ただし、システム設計の根幹が、モノリスにアプリケーションを作るという考え方であれば、今は分散ありきという方向に根本的に変わった可能性があります。
増田:もともと技術的なことが好きなのでアンテナは張っているのですが、実は結構フィルタリングをかけているんです。2〜3年後に残るネタって少ないじゃないですか。基本的に新しいものは残らないことが多い。だから人単位で見ることが多いですね。SNSで「この人の考え方は共感できる」「この人は本当に厳しい現場で仕事しているな」と感じる人。そういう人たちが何に手を出そうとしているのか?というポイントで見るようにしています。最新技術ってすべて追いきれないので、私自身は、ある程度「枯れた技術」を使うようにしています。やっぱり失敗談が山ほど手に入るし、失敗談が出だしたら本物かなと思います。
—「大々的にリファクタリングの工数を取ることが難しい、とくに大きな構造に問題がある場合、 小さなリファクタリングを続けても根本的な改善にはならない」ということで非常に現場レベルのご相談ですね。
増田:まず「小さなリファクタリングを続けても根本的な改善にならない」ということですが、私は改善に取り組む価値はあると思っています。改善の余地があるならチャレンジすると良いですよ。エンジニアとしての学びにもなるし、ソフトウェアにとっても良い変化があるはずです。良くないコードとの格闘は勉強という意味では悪くないですよ。私自身は何度もそういった経験をしているからこそ、今があると思っています。
—「OSSのコードを読むことで学びが得ることができますか」と続いていますが、いかがでしょう。
増田:OSSは、特定のアプリケーションではなく、より一般的な課題に対して、汎用的な解を提供しようという設計です。業務アプリケーションは、特有の問題、特定の文脈での解決策を作ろうという設計です。その違いを理解したうえで、OSSコードを読むのであれば、価値があると思い ます。
—質問者の方のチームは平均的なスキルがあまり高くないそうですが、この点を踏まえていかがでしょうか。
増田:平均的なスキルが高くないチームであれば、失敗する可能性は極めて高い。だからいきなり大規模に取り組まずに小さな失敗を重ねていくしかないです。例えば、自分達の裁量でできる範囲で挑戦してみるとかですね。DDDの手法を取り入れるべきかという質問の答えは「やる一択」です。事業、開発プロジェクト、個人に良い影響が約束されているようなものですから。
増田:私の時代は「勝手に育て」という風潮でしたが、結果的にはそれが良かったです。小さなプログラムをテストで動かしたり、クラス設計やメソッドの書き方を学ぶことよりも、フルセットのアプリケーションの一部を変更するという覚え方が良いと思います。アプリケーション全体の仕組みを理解したうえで、一部のエラーに対応するなど「変更する感触」を掴んでもらうと良いのかなと。
—技術的負債の解消は直接、企業利益になりませんよね。この点を理解してもらうにはどうすればいいでしょうか。
増田:これはもうはっきりしていて、リファクタリングや設計改善は最初から見積もりに入れる。そもそも設計は一発で決まるものではなく、2〜3回やる前提なので、セットで入れてしまいましょう。