Forkwell Press | フォークウェルプレス

SHARE

目次

目次

SHARE

ソフトウェア設計とメンテナンス

「良い設計・悪い設計を理解:コードの不吉な臭いを察知し嗅覚を磨く」増田 亨

principles-of-the-systems-architecture-new-img
この記事は2017年7月5日発売現場で役立つシステム設計の原則〜変更を楽で安全にするオブジェクト指向の実践技法』を取り上げた connpass勉強会 を再編集し、記事化したものです。

「良い設計は悪い設計より変更が楽で安全である」これが『現場で役立つシステム設計の原則』の根底にある考え方です。

・変更容易性はどんな効果を生み出すのか
・どうやれば変更を楽に安全にできるのか

最近の技術動向に触れながら説明します。 オブジェクト指向プログラミングの考え方の変化、クラウドベースの分散処理の進展、ドメイン駆動設計の広がりなどを取り上げます。

 良い設計と悪い設計の違い

  • 良い設計 → 変更が楽で安全
  • 悪い設計 → 変更が厄介で危険

設計を評価する一番のポイントは「変更容易性」です。

だからといって、目の前のソフトウェアのあらゆる箇所を実際に変更してみて良し悪しの評価をすることってできないですよね。では、どうするのかというと「不吉な臭い」を察知することです。悪い設計のコードには「不吉な臭い」があります。これは実際に変更をしなくても、コードを見て判断できます。(後ほど詳しく解説します。)

そもそも、ソフトウェアを変更する理由って? 

事業視点

ソフトウェアを変更する理由はさまざまですが、根本は事業の存続性を改善することでしょう。企業存続のためには、可能な限り収益をあげ、生き残ることが不可欠です。そのために存続優位性を保つこと、存続劣位から脱却することは常に必要です。この10〜20年で、事業のあらゆる部分にソフトウェアが入り込んでいます。『企業存続 = 常にソフトウェアに関する何らかの変更要求』が考えられるわけです。

開発者視点

これは私自身が一番感じることですが、顧客と会話しながらソフトウェアを設計する段階、リリース段階、運用段階など、過程によって事業活動への理解度は変わります。時間とともに、事業活動や会社の特性、こだわりポイントなど、より深く理解できるようになるでしょう。当然、理解度にあわせて設計も変えていくべき要因になります。

また開発者としてのスキルも上がってきますから、同じ要件でも実現したいことに合わせて変更する可能性も出てきます。

<利用できる技術の費用対効果が変わる>

新しい技術を導入することで費用対効果を高くできる可能性が増えています。ソフトウェアの変更なしに移行できればベストですが、そうもいきません。やはりソフトウェア変更が前提になることが多いでしょう。

principles-of-the-systems-architecture-01

良い設計が生み出す効果

ソフトウェアの変更が楽で安全であれば、さまざまなメリットを享受できます。

事業活動は仮説検証の塊である

変更が楽で安全であれば「一度やってみて駄目なら別のものをやってみよう」という仮説検証のハードルが下がります。事業活動はある意味で仮説検証の塊ですから、トライアルコストを抑えることができるのは、大きなメリットといえるでしょう。

変更の多さは開発者としてのスキルアップになる

『変更が多い = ソフトウェアの設計改善を学ぶ機会が増える』といえます。開発者としてのスキルアップにつながり、その学びをソフトウェアに反映できます。

ソフトウェアの変更がやっかいで危険だと・・・

事業活動の変化のスピードは下がり、コストが増えます。当然のようにマイナスポイントが顕在化してしまいます。

principles-of-the-systems-architecture-02

「新しい決済方法を追加したいが、1年半で5,000万円かかる」という事例があったとします。決済方法を増やすことが競争劣位を軽減するキーなのに、そのコストが事業存続にかかわるような現象が起きてしまうのではないでしょうか。ちょっとした変更のたびに何千万かかるのでは積極的な事業展開ができず、システムが足枷になってしまいます。

歪んだスキルや発想が染み付き、逃れられないループに陥る

どうしても既存の設計や都合にガチガチに縛られ、そのルールのなかで無理やり抜け道を探すようなスキルが染み付いてしまうんです。本来は「このソフトウェアでこういう事業価値を生み出したいから、こう変更したい」という前向きな成長をしていきたいですよね。

そして、成長の機会が狭まると勉強会や技術書など、他の場に学びの機会を求めます。しかし、せっかく学んだことを実際に自分の仕事に反映できないので、開発者としては、ますますつらくなってしまうでしょう。

「良い設計」知識と技能を習得する、3つのポイント

1. コードの不吉な臭いを嗅ぎ分ける

コードの不吉な臭い(設計の良し悪し)を判断できる嗅覚を身に付けましょう。

周りの環境や現場の状況によってさまざまですが、私自身が重視しているのは「コードの不吉な臭い」を判断する嗅覚を身に付けることです。これがわかると、「良い形」の習得につながります。下記は、リファクタリング本の中から私が普段コードレビューで気にしているポイントをリストアップしたものです。

principles-of-the-systems-architecture-03

2. 4つの「良い形」を習得する

「不吉な臭い」を見つけたら「良い形」にリファクタリングする改善サイクルが自然に回り始めるようになります。普段から「良い形」を意識し、コードを書く習慣を身に付けておきましょう。

良い形:値オブジェクト

principles-of-the-systems-architecture-04

良い形:区分オブジェクト

principles-of-the-systems-architecture-04 (2)

▲if文・switch文のコードが重複してる場合に、特効薬のように効く良い形です。とくに私自身が役に立っていると実感するのは、既存の区分を整理できる点です。排他網羅的に綺麗に整理できた区分オブジェクトの良い形を体で覚えると、業務アプリケーションの場合、非常にコードがすっきりしてきます。効果絶大です。

良い形:コレクションオブジェクト

principles-of-the-systems-architecture-04 (3)

▲for文 / Streamメソッドチェーンのコードの重複の防止に対する特効薬です。コードレベルが綺麗になるだけでなく、業務で関心のある対象の「集まり」に何らかの名前を付ける形になります。例えば「出荷待ち一覧」というコレクションから、優先出荷対象のものだけ選ぶ、抽出する、というようなロジックを実現したい場合に、コレクションオブジェクトの中に閉じ込めることで非常にすっきりと整理でき、変更もクラス内で解決できるため、変更が楽で安全になります

良い形:名前空間

principles-of-the-systems-architecture-04 (4)

「良い形」の背景にある考え方

私自身は、設計に対し「型に基づいて構造を考えることが良いプログラムに繋がる」ことを非常に重視しています。アプリケーションで扱う値の種類を分類し、値の種類ごとの特徴(どんな操作・計算・判断をしたいのか)を、型として定義します。型を実際にコードに落とすときは、カプセル化(オブジェクト指向の基本中の基本)を徹底します。

契約プログラミングは、バートランド・メイヤーの著書『オブジェクト指向 入門』で説明されている概念で、事前条件や事後条件を型で制限し表明する方法です。出版当時は、オブジェクト = 変更を管理するための道具、という考え方が主流でしたが、最近はオプジェクトの状態を変更しない考え方が主流になってきています。不変条件も昔はめんどうでしたが「いやいや、オブジェクトって、一度作ったら内部状態変わらないよ」というように振り切ってしまえば、変更も楽で安全安心です。

principles-of-the-systems-architecture-04 (5)

3.「分け方・集め方・つなぎ方」を習得する

より複雑で高レベルな課題には「良い形」だけで対応できない場合があります。良い設計をするためには「分け方・集め方・つなぎ方」の習得も必要です。

設計原則と設計パターン

設計原則と設計パターンを自分のものにするためには、とにかく手を動かし効果を実感するしかありません。

principles-of-the-systems-architecture-04 (6)

▲良い設計の基準は「変更が楽で安全」な点に振り切っています。このポイントを言語化したものが「設計原則と設計パターン」といえます。

principles-of-the-systems-architecture-04 (7)

▲「分け方・集め方・つなぎ方」の習得には大きく3つのレベルがあります。クラス設計やテーブル設計という小さい範囲。単独のアプリケーションのアーキテクチャという中範囲。そして分散アーキテクチャという広い範囲です。これからは「分散アーキテクチャの時代」なので、広い範囲の原則とパターンを学ぶと現場で役立つスキルになりそうです。

principles-of-the-systems-architecture-04 (8)

▲中範囲の分け方は図のように分け、それぞれの関心事ごとにクラスロジックを集め、それぞれをつなぐ方法です。

principles-of-the-systems-architecture-04 (9)

▲この本は名著だと思っています。分散アーキテクチャをとても分かりやすく言語化しています。この本を参考に設計・実装し現場の経験知を集めていくと、数年後には分散アーキテクチャの具体的なノウハウや事例が出てくるのではないでしょうか。

まとめ:変更を楽で安全にする設計、それが開発者がやるべき仕事

私が実践する設計の考え方と手法は、この価値観に基づいています。良い設計は悪い設計より変更が楽で安全であることです。

Q:オブジェクト指向のデータが mutable からimmutable に変化していった歴史とは?

—歴史を伺うのに増田さん以上の方はいらっしゃらないかと。

増田:最初にコンピュータに触ったのは20世紀のこと。もう40年近くも前ですね。実は40年前から immutable な考え方や言語は存在していました。ただメモリーやCPUを考えると、アプリケーションではとても採用できなかった。それが Java が出てきたことで、めちゃくちゃメモリー管理が楽になったんですね。かつては、immutable はアカデミックな世界、現場は mutable しかなかった。なぜ mutable から immutable へ変化したかを考えると、メモリーが格安で使えるようになったし、CPU性能も爆上がりしたからですよね。

Q:設計やアーキテクチャを意識できるレベルにない技術者や現場へのアドバイスは?

—ボトムアップで意識改革するか、レベルの高い技術者がいる現場を求めて次に行くか葛藤中とのことです。

増田:私は自分で興味があるところに自分の場を求めることを繰り返してきた人間なので、後者ですね。

—なかなか外に出られない方もいると思いますが、何かアドバイスはありますか?

増田:「アーキテクチャや設計のレベルを上げよう」という掛け声は、あまり効果がないような気がします。目先の変更が厄介で危険で困っていて「これが楽になるなら、何でも飛びつきます!」くらいの現場だと、実際にリファクタリングしながら、気が付いたら良い設計の仕方を覚えてるパターンはあります。「今のままでもいいんだ」という現場では、もう絶対無理です。エネルギーのある現場ならそこで頑張ってみるのはアリかも知れないですね。

—外に機会を求める場合はぜひ、 Forkwell に登録いただけますと嬉しいですね!

Q:システム設計の根幹は時代で大きく変化する?トレンドがある?

増田:簡単にいうと見方によるっていう感じかな。天動説と地動説のように同じ現象でも人によって見方や捉え方が変わるというか。そういう意味だと、ソフトウェア開発は、あまり変わっていないかも。ただし、システム設計の根幹が、モノリスにアプリケーションを作るという考え方であれば、今は分散ありきという方向に根本的に変わった可能性があります。

Q:トレンドのキャッチアップ方法は?

いい仕事をしてそうなエンジニアが何に手を出そうとしているか

増田:もともと技術的なことが好きなのでアンテナは張っているのですが、実は結構フィルタリングをかけているんです。2〜3年後に残るネタって少ないじゃないですか。基本的に新しいものは残らないことが多い。だから人単位で見ることが多いですね。SNSで「この人の考え方は共感できる」「この人は本当に厳しい現場で仕事しているな」と感じる人。そういう人たちが何に手を出そうとしているのか?というポイントで見るようにしています。最新技術ってすべて追いきれないので、私自身は、ある程度「枯れた技術」を使うようにしています。やっぱり失敗談が山ほど手に入るし、失敗談が出だしたら本物かなと思います。

Q:「良くない設計のソフトウェア」を保守している場合の改善方法は?

—「大々的にリファクタリングの工数を取ることが難しい、とくに大きな構造に問題がある場合、 小さなリファクタリングを続けても根本的な改善にはならない」ということで非常に現場レベルのご相談ですね。

増田:まず「小さなリファクタリングを続けても根本的な改善にならない」ということですが、私は改善に取り組む価値はあると思っています。改善の余地があるならチャレンジすると良いですよ。エンジニアとしての学びにもなるし、ソフトウェアにとっても良い変化があるはずです。良くないコードとの格闘は勉強という意味では悪くないですよ。私自身は何度もそういった経験をしているからこそ、今があると思っています。

Q:悪い設計だらけの現場で、良い経験や学びを得るためには?

—「OSSのコードを読むことで学びが得ることができますか」と続いていますが、いかがでしょう。

増田:OSSは、特定のアプリケーションではなく、より一般的な課題に対して、汎用的な解を提供しようという設計です。業務アプリケーションは、特有の問題、特定の文脈での解決策を作ろうという設計です。その違いを理解したうえで、OSSコードを読むのであれば、価値があると思い ます。

Q:DDDの手法を取り入れるべき?

—質問者の方のチームは平均的なスキルがあまり高くないそうですが、この点を踏まえていかがでしょうか。

増田:平均的なスキルが高くないチームであれば、失敗する可能性は極めて高い。だからいきなり大規模に取り組まずに小さな失敗を重ねていくしかないです。例えば、自分達の裁量でできる範囲で挑戦してみるとかですね。DDDの手法を取り入れるべきかという質問の答えは「やる一択」です。事業、開発プロジェクト、個人に良い影響が約束されているようなものですから。

Q:未経験者にプログラミングやオブジェクト指向を教える良い方法は?

増田:私の時代は「勝手に育て」という風潮でしたが、結果的にはそれが良かったです。小さなプログラムをテストで動かしたり、クラス設計やメソッドの書き方を学ぶことよりも、フルセットのアプリケーションの一部を変更するという覚え方が良いと思います。アプリケーション全体の仕組みを理解したうえで、一部のエラーに対応するなど「変更する感触」を掴んでもらうと良いのかなと。

Q:リファクタリングや設計改善などを理解してもらうには?

—技術的負債の解消は直接、企業利益になりませんよね。この点を理解してもらうにはどうすればいいでしょうか。

増田:これはもうはっきりしていて、リファクタリングや設計改善は最初から見積もりに入れる。そもそも設計は一発で決まるものではなく、2〜3回やる前提なので、セットで入れてしまいましょう。

イベント動画

ForlkwellPress ロゴ画像

フォークウェルプレス編集部

Follow

記事一覧へ

本サイト掲載の全て記事は、フォークウェル編集部が監修しています。編集部では、企画・執筆・編集・入稿の全工程をチェックしています。

増田 亨
有限会社システム設計

代表取締役

富士通株式会社、日本オラクル株式会社、独立系のソフトウェアハウスなどで主に業務系のアプリケーション開発に従事。技術者コミュニティ「現場から学ぶモデル駆動の設計」主催。業務系アプリケーション開発。技術スタック(Java / Spring / IntelliJ IDEA / JIG)