【修正】フラグ(Booleanのプロパティ)を作らない【補足】複数のフラグを1つの状態変数にまとめる【コード例追加】ラフコードを書く【追加】インターフェースを使ってラフコードをプロダクトコードにする概要チームによる継続的開発を前提としたコーディングのガイドライン。特定の言語を対象としたものではないが、主に静的型付けのオブジェクト指向言語を想定している。サンプルコードは別段の定めがなければSwiftで記載。高いほどシステムに与える影響が大きいが、低いものの方が影響が小さく改修しやすいものが多い。5】変数のスコープを小さくする変わり得る値は複雑さを生み誤解やバグに繋がるため、プログラムは変数が少ないほど問題が生まれづらい。プログラミングの大原則として、変数は必要最低限を心がけ、むやみに増やさないようにする。変数はスコープや寿命が大きいほど悪影響が大きいため、変数を使う場合はスコープと寿命を最小にするよう心がける。基本的には以下の上のもの程スコープが広くなるので使用を避けるよう心がける。前述のとおり変数はスコープが大きいほど害が大きいため、一番スコープが大きいグローバル変数は極力使用を避ける。グローバル変数とは何かどこからでも読み書きできる変数をグローバル変数と言う。C言語などのいわゆるグローバル変数に加えて、Javaなどのstatic変数(クラス変数)もグローバル変数と呼ばれることが多い。ここではもう少し意味を広げて、どこからでもアクセス可能なシングルトンや共有オブジェクトなどもグローバル変数として話を進める。データベースやファイルなどのストレージも、どこからでも読み書きできるという性質は同じなため、若干イレギュラーだがここではグローバル変数の一種として扱う。グローバル変数はなぜダメなのかグローバル変数はどこからでも値を読み書きできる特性上、以下のような問題を生み出す可能性が高い。色々なところから値が変更されてプログラムが複雑になり、処理の流れを追いづらくなる問題があったときに原因が何なのか特定しづらくなる想定外のところで値が変更されてしまう加えて、グローバル変数が存在すると、本来無関係なはずのクラスやモジュールが、グローバル変数を通して互いに影響を与え合ってしまう可能性がある(いわゆる密結合な状態になる)その結果、クラスやモジュールを再利用しづらくなったり、問題の切り分けや、ユニットテストがしづらくなるのも大きな弊害である。使ってはいけないのかでは、グローバル変数を全く使ってはいけないのかと言うと、そんなことはない。ここでは前述のとおり、シングルトンや共有オブジェクト、DBもグローバル変数の一種と定義しているが、それらを全く使わずアプリケーションを作るのは難しい。アプリケーションには設定やセッション情報など、全体で共通的に必要になるコンテキストのような情報がある場合が多い。いった情報は関数の引数などでバケツリレーのように別のオブジェクトに渡していくより、グローバル変数のようにどこからでもアクセスできる方法を用意した方が実装が簡単になる。グローバル変数の使用を避けるという方針は変わらない。全体の設計を慎重に検討した上で、どうしても必要な最低限のものだけグローバルなアクセス方法を用意するようにする。バックエンドのグローバル変数HTMLをサーバー側で生成するタイプのWEBアプリ(PHP、Rails、SpringMVC、ASPなど)では、DBやセッションなどがグローバル変数の役割を担うため、厳密な意味でのいわゆるグローバル変数(PHPのグローバル変数やJavaのstatic変数など)が必要になることはほとんどない。WEBアプリでいわゆるグローバル変数を使っている場合、設計に問題がある可能性が高い。バッチ処理のような短期のプロセスも、DBを除いたいわゆるグローバル変数が必要になることはあまりないように思われる。対して、スマホやデスクトップアプリ、SPAなどのフロントエンドアプリケーションでは、グローバル変数を自前で用意して使う場合が多い。そのような場合は、以下のような使い方を避ける。一時的なデータの受け渡しのためにグローバル変数を使うアプリケーションの一部の機能でしか使わないデータをグローバル変数にするグローバル変数にアクセスするクラスを制限せず、無差別にどこからでもアクセスする裏を返すとグローバル変数は、一時的ではなく永続的に存在し、アプリケーションの様々な機能で共通して利用される情報のために用意され、アクセスするクラスが一部に制限されるなら使って良いということになる。グローバル変数を使う際のポイントグローバル変数やstatic変数を作る場合は、IntやStringのような単純なデータ型をそのまま変数に保持するのではなく、関連のあるデータをオブジェクトにして、シングルトンや共有オブジェクトの形にして保持するのが良い。""}また、このような共有オブジェクトを誰もが無制限に追加できると収拾がつかなくなるため、共有オブジェクトの設計はチーム内の一部の有識者で行うのが好ましい。グローバル変数を作っても、むやみに色々なクラスから参照してはならない。グローバル変数にアクセスしても良いレイヤーを決めて、それ以外のレイヤーからはアクセスしない。シングルトンより共有オブジェクトグローバル変数はシングルトンや共有オブジェクトの形にするのが良いと書いたが、実際にはシングルトンより差し替え可能な共有オブジェクトの方が良い。Sample()}シングルトンはインスタンスが一つしかないため以下のデメリットがある。これらのデメリットは特にUnitTestで障害になる上、アプリケーションの実装上問題になるケースもある。インスタンスを複数作りたい場合に作れない保持する情報をクリアしたい場合にオブジェクトを破棄して作り直すことができないインスタンスの動作をカスタマイズしたい場合に継承ができない共有オブジェクトならシングルトン的な機能を持たせつつ、上記のデメリットを解消できる。共有オブジェクトはシングルトンと異なり、インスタンスが一つであることが機械的に保証されるわけではないが、インスタンスを一つにしたいのであれば開発チーム内でそのような設計方針を共有すれば良い。関連記事シングルトンパターンの誘惑に負けないグローバル変数はデータベースとしてとらえる関連のあるデータをまとめてオブジェクトとして保存する一時的ではなく永続的に存在するデータを保存するアプリケーションの様々な機能で共通して利用されるデータを保存するグローバル変数にアクセスするクラスは一部に制限する誰もが自由に追加するのではなく、チーム内の一部の有識者が設計する共有オブジェクトを用いたグローバル変数について、これまでの項で書いた上記のことを振り返ると、これはDBの位置づけとよく似ている。グローバル変数はデータベースやMVCパターンで語られるRepositoryのようなものととらえて設計するとイメージしやすい。DIコンテナDIコンテナがあるプラットフォーム(SpringやAngularなど)では、DIコンテナで共有オブジェクトを管理するのが良い。DIコンテナのある環境ではアプリケーション全体がDIコンテナにべったり依存した設計になりがちだ。それが良いか悪いかはさて置き、そのような環境では自前で共有オブジェクトを管理するのではなく、DIコンテナに管理を任せた方が統一感があって分かりやすい。グローバル変数を全く使わない設計は可能か?必要な情報を全てバケツリレーのように引数で渡していけば、グローバル変数を全く使わずにアプリケーションを作ることもできる。必要な情報を使用者が取りに行くのではなく外から渡される形(以下これをDIと呼ぶ)である。DIの形をとっても、状態変更可能なオブジェクトを渡してしまうと、そのオブジェクトが複数の使用者に変更されてグローバル変数のように扱われてしまうため、DIで渡す情報は状態変更できない(書き込み不可の)値オブジェクトだけにする必要がある。このように変更不可なオブジェクトをバケツリレーのように渡していくことを徹底すれば、グローバル変数のようなものを完全に排除でき、一見疎結合で綺麗な設計になると思われるが、この方針には実は落とし穴がある。この方針の問題は、バケツリレーの末端のオブジェクトで必要な情報を、仲介する全てのオブジェクト(バケツリレーの渡し役)が一時的に持たなければいけなくなる点だ。この問題により特定のクラスが一時的に無関係な情報を持つ必要がでてくるので、一概に疎結合になるとも言えない。結局のところ、グローバル変数の使用を避けろとは言うものの、全く使わないのも現実的ではなく、適切な方針のもとでグローバル変数を使用することが最善の設計なのかもしれない。インスタンス変数(クラスのメンバー変数)グローバル変数同様、インスタンス変数も可能な限り使用を避ける。新たに変数を追加する場合は、気軽に追加するのではなくどうしても必要かをしっかり考える。同じ機能を実装したクラスが2つあった場合、インスタンス変数が少ない方が良い設計だと言ってしまっていいくらい重要なポイントだ。インスタンス変数を少なくする方法インスタンス変数の使用を極力避けると書いたが、具体的にどうやって変数を少なくするかというと、まずは以下の三つが基本になる。関数の引数で足りるデータをインスタンス変数にしない加工した値をインスタンス変数に保持しないプログラムで取得できる情報をインスタンス変数に保持しない関数の引数で足りるデータをインスタンス変数にしない初心者によく見られるが、複数の関数でデータを使い回すためだけにインスタンス変数を使ってはいけない。長期保存する必要のないデータであればインスタンス変数を使わず関数の引数で渡すようにする。加工した値をインスタンス変数に保持しないパフォーマンス最適化のためにやむを得ない場合もあるが、基本的に何らかの値を加工した値をインスタンス変数に保持しない。itemsBを生成すればよい。}}プログラムで取得できる情報をインスタンス変数に保持しない「加工した値をインスタンス変数に保持しない」と少し被るが、他の値から判定できる情報や、何らかのAPIやプログラムで取得できる情報はインスタンス変数に保存せず、必要になったタイミングで都度プログラムを実行して取得する。クロージャを使ってインスタンス変数を消す初心者には少し難しいが、クロージャを使って無用なインスタンス変数を減らすことができる。基本的にインスタンス変数はデータを長期間保持するために使われるが、クロージャを使うとインスタンス変数を使わずにデータを長期間保持することができる。保持することができる。}}関数型プログラミングを活用すると、変数を減らしたり、変数のスコープを狭めたりすることができる。Haskellなどの一部の関数型言語では、そもそも変数に再代入ができないので、ある意味変数がないとも言える。関数型プログラミングを使っても結局はどこかにデータが保存されるが、スコープや影響範囲が小さくなり、より害のないコードを書けるようになる。使ってもよいが、必要になったときに初めて定義して、スコープを最小にするよう心がける。print(num)}ただし、一部の言語(C言語やJavaScriptのvarの巻き上げへの対処など)ではスコープの先頭で変数を宣言する必要がある場合もある。説明変数は積極的に使って良い可読性のため、実装上必ずしも必要ではない変数を作り、式の結果をいったん代入する場合がある。そのような変数は説明変数といい、他の変数と異なり必要であれば積極的に使って良い。説明変数には値の再代入をすることがなく、定数のように扱われるため増やしてもあまり害がない。includesTaxRate説明変数を使うとコードの行数は多くなるが可読性は上がり、式の途中結果がわかるためブレイクポイントを使ったデバッグがやり易くなるメリットもある。変数の寿命を短くする何らかの状態を変数に保存する場合、値の存在期間はできる限り短くする。必要になったタイミングで値を保存し、必要なくなったタイミングでなるべく早くクリアする。変数に保存した値はその瞬間のスナップショットであり、時間が経つほど最新の状態とズレてしまう危険性があるため、変数に保存した値の寿命は極力短くする。同じ情報を重複して複数保持しない。以下の例では年齢を別の形で2つのフィールドに保持しており、情報が重複している。"17歳"}このような場合、以下のように保持する情報は一つにして、その値を加工して使うのが良い。}}情報の重複はシステムに以下のような悪影響をもたらす。複数ある情報のどれを使っていいか分からなくなる複数ある情報の一部しか更新されないと、差異や矛盾ができる誤った情報を参照、または更新してしまう可能性がある情報を変更する場合、複数のフィールドを変更する必要があるこの例は単純で分かりやすい情報重複だが、他にも様々な形の情報重複がある。以下の例ではDBのデータを読み込んでインスタンス変数に保持(キャッシュ)しているが、これによりインスタンス変数に保持した情報とDB内の情報が重複してしまう。}}DBから読み込んだデータを上記のようにインスタンス変数に保持するのはなるべく避けた方が良い。Fooオブジェクトが長期間存在する場合、その間にDBが更新されるとFooが持つインスタンス変数の情報と、DBの情報に差異が出てしまう。分かりきった情報をコード化しない以下の例ではDictionary(Map)のキーに0、1、2を使用しているが、Arrayにすればインデックスがあるので、順番をとりたいのであれば不要な情報だ。map[index]}Arrayにすればインデックスでのアクセスが可能なので0〜2の情報は不要になる。情報を重複させないという方針は、プログラミングに限らずドキュメント管理などでも役に立つ。Badローカルマシンに仕様書をコピーして見ていたら、仕様書が更新されており、古い仕様書を元にコーディングしていた。諸々の事情によりローカルにコピーせざるを得ない場合もあるが、上記の例ではコピーして仕様書が重複したことにより問題が発生している。Good仕様書は共有のサーバーに1つしかないので、常に最新の仕様が見れる。コードの重複を禁じるものではないこの項で問題にしているのはあくまで情報を重複して持たないことであり、同じようなロジックのコードを重複させないことではない。「コードをコピペして似たようなコードを複数作る」ようなケースはここで言う重複とは異なるので誤解なきよう。同じようなロジックのコードを共通化するのはまた別の話で、もっと優先度の低い方針になる。一つのフィールドに複数種類の情報を持たせない逆に一つのフィールド(変数、DBカラム、テキストUIなど)に複数種類の情報を持たせるのも避ける。一つのフィールドに複数種類の情報を入れると実装が複雑化し、様々なバグを生み出すリスクが発生する。間違っても一つの変数を複数の用途で使い回すということはしないようにしよう。5】適切な名前をつけるクラス、プロパティ、関数、定数など、プログラムで定義する要素には適切な名前をつける。クラスの名前は設計に大きく関わり重要性が高い。クラス名、プロパティ名、関数名を適切につけることができれば、それはクラス設計、データ設計、インターフェース設計が適切になされたのとほぼ同義である。ある意味プログラミングとは名前を付ける作業だと言っても過言ではない。名前をつけるときは、以下を心がける。他人が見ても名前から目的や意味がわかる実際の用途や処理と名前が合っている名前に書かれている以外の処理や役目を持たないまた、関数や変数はスコープの広いものほど丁寧な名前をつけるようにする。名前に書かれていること以上の役割を持たせない変数は名前に書かれた以上の役割を持たせない。関数は名前に書かれたこと以外の処理をしない。いうクラスであれば、そこにはLoginのViewをControllする処理のみを記載し、それ以外の例えばログイン認証などの処理は原則として記載しない。ようなゲッターで何かの状態の更新をするなど、もってのほかである。vol_03}上記のような数字やIDは、知らない人には何を意味するのか分からないため、プログラム内で名前に使用するのは避ける。コードにIDを使うと、IDが変わった場合にプログラムの修正が必要になってしまう。このような単語の省略はプログラマーの伝統文化だが、現代ではIDEによるコード補完があることがほとんどなので、省略してもあまりメリットはない。第三者に意味がわかりづらくなるため、単語は省略しないようにする。"円"値の具体的な内容をそのまま名前にするのは、拡張性が無いので避ける。このような場合は、この定数が何であるかではなく、どういった役割・意味を持つかから名前をつける。falseflagという言葉はBooleanであることを表すだけで、用途や意味を何も表現できないため、Booleanの変数名にflagを使うのは避ける。Boolean変数の命名は以下のようなお決まりパターンがあるので、この形に従うと良い。英名を知らないものに変数名をつける場合、まずはネットで調べるケースが多いと思うが、Google翻訳などの機械翻訳は単語が適切に翻訳されない場合が多いので気をつける。英語を調べる場合は、Google翻訳だけでなく、辞書、Wikipediaなどで例文も含めて調べるのが良い。チームメンバーがみんな英語が苦手で、英語を調べるのに時間がかかるのなら、英語を諦めローマ字の日本語で書くのも一つの手である。格好悪いが、大切なのはチームメンバー全員の可読性と生産性であると思う。ユニットテストの関数名は説明的な文章になる場合が多いので、関数名に日本語を使える環境であれば、日本語で書くのも良い。{}汎用的な名前を避ける汎用的な名前はなるべく避ける。あるのはなんとかManagerとなんとかController。汎用的な名前は様々な処理を押しつけやすくクラスが肥大化しがち。辞書を作るチームで開発をする場合は、アプリケーションで使う用語の辞書を作り、用語の認識をメンバーで合わせた上で開発を始めると良い。辞書を作ることで、同じものが開発者によって別の名前で定義される不整合を防ぐことができるし、個々の開発者が同じものの名付けで別々に頭を悩ますという無駄を省くことができる。関連記事モデルやメソッドに名前を付けるときは英語の品詞に気をつけようクラスの命名のアンチパターンコードスタイルの一貫性を重視するクラスや変数の命名規則などのコードスタイルは、プロジェクト内で統一して一貫性をもたせる。プロジェクトの一部に例外的な名前やスタイルを使うと、可読性が損なわれ誤解や見落としの原因となりやすい。View001、View002、View003というクラスが既にあれば、次にViewクラスを追加する場合は名前の付け方を統一してView004にするのが良い。これは上に記載した「記号やIDを名前に使わない」の項に反するが、プロジェクト内で名前に一貫性を持たせることの方がより重要になる。現在の命名規則やスタイルに問題があり変更したいなら、チームメンバーの了解をとった上で、一部だけでなく全てまとめて修正するのが良いだろう。5】function(object)の形よりobject.function()の形を好む関数にオブジェクトを渡す形function(object)より、オブジェクトの関数を呼び出す形object.function()を好む。{}これにはいくつかの理由があるので以下に説明する。可読性のため関数にオブジェクトを渡す形function(object)は、複数の処理を重ねると括弧が入れ子になり読みづらくなるが、オブジェクトの関数を呼び出す形object.function()はドットで繋いで複数の処理を行えるため可読性がよい。function(object)の場合、functionは何らかのクラスやモジュールに定義され、処理を行うにはfunctionが定義されたクラスやモジュールと引数のobjectの2つが必要になる。対して、object.function()の場合はobject単体で処理を行うことができるため再利用性が高い。形はオブジェクト指向の真髄だ。初心者にオブジェクト指向を教えるのは難しい。オブジェクト指向について教えるべきことはたくさんありそうに思える。形を体に染み込ませることが、オブジェクト指向を身につける最短ルートではないかと考える。propertyの機能により、functionをpropertyとして扱うことができる。propertyにしていこう。形がいいのかと言うと、そうではない場合もある。クラスに必要のない依存関係や、負うべきでない役割を持たせてしまう場合だ。不要なViewクラスへの依存を作ってしまっている。形をとった方が良いだろう。error}前者のような依存関係を作るべきでない理由は、下にある「依存の向きを意識する」の項で詳しく説明している。5】継承より包含とインターフェースを好むクラスの継承には問題がある。継承は強力な機能だが、その代りに多くのリスクもはらんでいる。クラス継承は柔軟性がなく変更に弱い。修正により無関係な機能に影響を与えてしまう例えばBaseクラスを継承したAとBのクラスがあったとして、Aの機能を改修するためにBaseを修正したら、無関係なBの機能がバグってしまうようなケース。これはクラス設計に問題があると言えるが、継承を使うとこのような問題は起こり得る。複数の親を継承できないC++など一部の言語を除き、複数のクラスを継承することはできない。現実に存在するものには、複数の上位概念(親カテゴリー)が存在することが多い。唐突だがインドカレーについて考えてみると、その親はカレーとすることもできるし、インド料理とすることもできる。インド料理もう少し実装の流れにそった例をあげると、例えばWEBでスマホの契約ができるシステムがあったとする。契約画面は新規契約と乗り換え(MNP)契約の2つに別れていて、それぞれに対応するクラスがある。新規契約と乗り換え契約には共通する部分が多いので、共通の親クラスとして基盤契約クラスを作る。次に契約変更画面を実装することを考える。契約変更用に新規契約クラスを継承した新規契約変更と乗り換え契約クラスを継承した乗り換え契約変更のクラスを作ったとすると、契約変更という観点では継承で処理を共通化できなくなってしまう。共通の親クラスが肥大化しがち例えば、全てのControllerクラスの親クラスになるBaseControllerというクラスを作ったとすると、BaseControllerクラスは様々なControllerで使われる機能が盛り込まれ肥大化しがちだ。必要最低限の機能であればよいが、基本的に共通の親クラスは機能を提供するのではなく、共通のインターフェースとして扱うために用意するのがよい。4】分岐をシンプルにするif文やswitch文によるロジックの分岐は、プログラムの可読性を損ないバグの原因になりやすいので、なるべくシンプルな形になるよう心がける。ネストを深くしないif文やfor文などのネスト(入れ子)が深くなるとコードが読みづらくなるため、なるべくネストを深くしない。ネストが深くなるのを防ぐには「早期return」と「ロジックの切り出し」を行うと良い。以下のコードに「早期return」と「ロジックの切り出し」を適用するとどうなるか例を用いて説明する。}}早期return例外的なケースを先にreturnすることで、メインロジックのネストを浅くする。以下のサンプルコードではtextがnilの場合を例外パターンとして先にreturnしている。処理2}ただし、早期returnは名前のとおり早期にreturnする必要がある。基本的に関数は末尾行まで処理が実行されることが期待されるため、長い関数の途中にreturnがあると、見落とされてバグを生んでしまうリスクがある。ロジックの切り出しif文やfor文などのネストを含む処理をメソッドやプロパティに切り出して、メインロジックのネストを浅くする。以下のサンプルコードではtextが”A”か判定して何らかの処理をする部分を、Textクラスのクラスメソッドとして切り出している。}}関連情報ブロックネストの数を減らそう呼び出し元による場合分けをしない様々なところから呼び出される関数には、呼び出し元による場合分けを入れてはいけない。以下のケースは、画面によって処理の場合分けをしているが、この書き方では画面が増えるほど際限なく関数が大きくなってしまう。}}この書き方をすると一つの関数に様々な処理が詰め込まれ、読みづらく、バグりやすく、修正もしづらい巨大な関数になってしまう可能性が高い。ポリモーフィズム上記のような関数内の場合分けはポリモーフィズムを使って解消することができる。ポリモーフィズムについての詳しい説明は長くなるので割愛するが、インターフェース(プロトコル)や継承によるメソッドのオーバーライドにより、場合分けされた各処理を子クラスにそれぞれ記載することができる。}}関数を引き渡すまた、関数を関数の引数にして渡すことによって、if文などの分岐を解消することもできる。以下のように引数に関数を受け取るようにすれば、somethingの処理は呼び出し元で自由に設定できるので、分岐をなくすことができる。この例では受け取った関数を実行するだけの意味のない関数になってしまっているが、呼び出し元によって異なる完了処理やエラー処理を引数として渡すようなことが多い。}}Javaのような関数をオブジェクトとして扱えない言語でも、インターフェースを使って同じようなことが実現できる。分岐ブロック内の行数を少なくする分岐を見やすくするため、if文などの分岐ブロック内の行数はなるべく少なくなるよう心がける。ここに長い処理を書かない}コマンドとクエリを分離する全てのメソッドは、アクションを実行するコマンドか、データを返すクエリかのどちらかであるべきで、両方を行ってはならない。separation)と言われる考え方だ。データを返すメソッド(クエリ)の中でアクションを行ってはいけない。ゲッターの中で更新処理をしないと言い換えると分かりやすいかもしれない。これは当然のこととして心がけている人が多いと思う。次に、アクションを実行するメソッド(コマンド)の中にクエリをなるべく記載しない。こちらは前者よりわかりづらく、もしかするとCQS本家の人が言ってることとはズレているかもしれないが、例をあげて説明する。ユーザーネームとセッションIDが両方ある場合にログイン済みとみなして次のページに進む関数を考える。なるが、ログインしているかどうかを判定する部分はBoolの値を取得するクエリになるため、「コマンド」と「クエリ」が混在している。この関数からログイン判定の部分をクエリとして別関数に切り出すと以下のようになる。sessionId.isNotEmpty}if文の条件式がごく短いものであれば、それを別関数に切り出すかは迷うところだが、ある程度の長さのクエリであれば別関数やプロパティとしてアクションから切り出すのがいいだろう。4】クラス、ファンクションを大きくしすぎないクラスは50〜350行程度、ファンクションは5〜25行程度を目安とし、これを超える場合はクラスやファンクションの分割を検討する。行数はあくまで目安で、これを超える行数でも同じクラスやファンクションに収めた方が良い場合もあるが、キリがいい上限として1000行を超えるクラスはヤバイと思っておこう。言語や書き方や機能によって変わるので一概にこのサイズが正解とは言えないが、クラスの行数に対するざっくりしたサイズ感を記載する。ヤバイとはいえ、基盤となる機能や、要素の多いUIクラスなどは上記のサイズ感を逸脱する場合もある。AndroidのViewクラスは2万7千行あるし、極端な例だが異なる処理をするボタンが1000個ある画面は、簡潔に書いても1000行を超えてしまう。4】フラグ(Booleanのプロパティ)を作らない「変数のスコープを小さくする」の項に記載したインスタンス変数をなるべく持たない方針と近いが、Bool値のフラグはさらに厳しくインスタンス変数に保持しないよう心がける。フラグ(Boolの変数)が持つ情報はある一時点での判定結果であり、基本的に過去の情報になる。そのため時間が経つほど実際の状態と乖離してしまう危険性がある。}}上の例ではデータを受け取ったかどうかをフラグで保持しているが、data変数を見ればデータを受け取ったことは分かるのでフラグは必要ない。データの多重管理になってしまうため、このようなフラグの作成は避ける。フラグをなくすためには、まずフラグの代わりに他の状態で判断できないかを検討する。フラグは何らかの状態を判定するものだが、フラグがなくても他のものを見て状態を判定できることは多い。複数のフラグを1つの状態変数にまとめる複数のフラグがある場合、状態を表すEnumを作ることで複数のフラグを1つのEnum変数にまとめることができる。.admin}ただし、Enumにまとめるのは必ず一種類の情報だけにし、複数種類の情報を一つのEnumにまとめてはいけない。上の例で言えば、「ユーザータイプ」に「ログイン状態」を加えて、以下のようなEnumを作ることは避ける。数字や文字列をデータのキーにしない数字を条件分岐の判定に使わない0、1、2などの数字を条件分岐の判定に使うのは避ける。代替方法はケースにより様々だが、配列やListを使うことで数字の使用を避けられることが多い。""}ただし、0、1、-1は最初の要素を取得したり、APIのエラーや成功を表したりと、特殊な役目を持つ場合が多いため、環境によっては使わざるを得ない場合もある。配列で複数種類のデータの受け渡しをしない静的型付け言語では配列(Array、List)を使って複数種類のデータの受け渡しをしない。以下の関数は数字を使ってListの1番目に名前、2番目に郵便番号、3番目に住所の情報を格納しているが、何番目に何の情報が入っているかはList型からは判別できないため、可読性が悪くなり間違いも起こりやすくなる。userData}決まったデータ構造を受け渡す場合は、以下のようにstructやclassを作ってデータを受け渡す。"東京都豊島区")}ただし、名前の一覧を受け渡したり、ファイルの一覧を受け渡したり、同じ種類のデータの一覧を受け渡す場合は配列やListを使って良い。Mapで複数種類のデータの受け渡しをしない全く同じ理由で、Map(Dictionary)で複数種類のデータを受け渡すのも避ける。静的型付け言語であれば、配列の例と同様にデータ受け渡しのためのstructやclassを作成する。4】コメントアウトしない不要になったコードはコメントアウトせず削除する。ローカルでの修正中に一時的にコメントアウトするのは構わないが、基本的にコメントアウトしたものはコミットしないようにしよう。コメントアウトした行が増えると、コードが読みづらくなる、検索時に使われていない箇所が引っかかるなど結構な害がある。削除や変更の履歴はGitなどの管理ツールで分かるので、不要なコードは消すことを心がける。3】依存の向きを意識するプログラム間の依存関係にはルールを設けて、無計画に依存をしないようにする。抽象的な説明になってしまうが、以下の向きで依存して、この逆方向の依存を避ける。具象から抽象に依存する大きな機能から小さな機能に依存する専用的な機能から汎用的な機能に依存する依存とは何か?あるプログラムが、何らかの別のクラスやモジュール、ライブラリなどを使っており、それがないとコンパイルできなかったり、動作できないことを依存していると言う。コンパイルレベルの依存の他に、特定の仕様を前提として作られており、その仕様がなければ動かない場合なども、仕様に依存していると言える。専用的な機能から汎用的な機能に依存する汎用的に使われるクラスは、専用的なクラスに依存しないようにする。極端な例だが、文字列を表すStringクラス(汎用的な機能)が、ログイン画面のクラスLoginView(専用的な機能)に依存していたとすると、Stringを使う全てのシステムはLoginViewも無駄に取り込む必要ができてしまい、Stringクラスが再利用しづらくなってしまう。クラスは別のアプリに移植することができなくなってしまう。汎用的な機能のクラス内で、アプリ独自の専用的な画面クラスやIDを判定に使うことは、汎用クラス内に過剰な分岐を生み出して複雑化させる弊害もあるので避ける。ライブラリに依存するところは一箇所にまとめる現代ではアプリの実装に何らかのオープンソースライブラリを使うのは当たり前だが、特定のライブラリを使った処理は一つのクラスやファイルにまとめて、様々なクラスがライブラリに依存するのは避ける。面で依存するのではなく、点で依存するようなイメージだ。ライブラリを使ったコードを一箇所にまとめることにより、以下のような変更があった場合の影響や修正を最小限にすることができる。使っているライブラリを別のライブラリに差し替えたいライブラリに仕様変更が入り使い方が変わったデータクラスは具体的な機能や仕様に依存させない「専用的な機能から汎用的な機能に依存する」の項に書いたことと若干被るが、DTOのようなデータの保持を目的としたクラスはなるべくシンプルにして、別の機能に依存したり、特定の仕様に依存させない方が良い。String}このようなシンプルなデータクラスは多くのレイヤーをまたいで使われたり、ときには別のアプリケーションに移植されたりするが、その際に余計な依存があると色々と弊害が出ることがある。インターフェースを使って具象への依存を断ち切る多くの静的型付け言語ではインターフェース(プロトコル)を使って具体的な実装クラスへの依存をなくすことができる。クラスに依存している。クラスが何らかの通信ライブラリを使っていると、Exampleクラスは間接的にその通信ライブラリに依存することになってしまう。以下のようにHTTPConnectorをインターフェース(プロトコル)に変えれば、Exampleクラスが通信ライブラリに依存しないようにすることができる。Data)}外部システムとの連携は一箇所にまとめるアプリケーション外部のシステムとの連携やインターフェースに関わるコードは、なるべく一箇所にまとめる。外部システムは色々なものが考えられるが、よくあるものとしてはHTTPのAPI、データベースなどがある。オープンソースライブラリへの依存について書いたことと同じだが、外部システムとの連携を一箇所にまとめることにより、外部システムの変更の影響や修正を最小限にすることができる。こちらもまた、インターフェース(プロトコル)を使って具体的な実装クラスへの依存をなくせると良い。コード値などで複数の値があるものはEnumを定義する。}}想定外の値を考慮する必要があるときEnumはあらかじめ定めた値しか取り扱うことができないが、APIのステータスコードなど想定外の値に対しても何らかの処理が必要な場合がある。propertyでEnumを取得できるようにするとよい。3】コメントを書く分かりづらいコードを説明する第三者が見て分かりづらいコードにはコメントを書く。特殊な仕様を満たすためのコードや、バグ修正のためのトリッキーなコードなど、他人が読んだときすぐに意味が理解できないコードには、コメントでコードの説明を記載する。バグ修正のための特殊なコード正攻法でバグを修正できず、仕方なく汚いコードをいれざるを得ないときはままある。そのような場合は、後で見る人のためになぜそうしたのかコメントを記載しておく。以下のようなケースは、コメントで説明を書いておいたほうが良い。以下のコードは3が何を意味するか第三者には分からないため、コメントが必要になる。情報のない言葉や重複する言葉を削る日本語はそれなりに回りくどく、何も考えずに文章を書くとたいてい情報量のない言葉がいくつか含まれる。文章を書いたら一度見直して、重複する言葉や必要のない言葉がないか確認し、あれば削除して短くする。以下のような言葉は言い回しを簡潔にして、意味を変えずに短くすることができる。敬語や丁寧語を使わない日本語は丁寧な言い回しになるほど文字数が増える。「した」が2文字なのに対して「しました」は4文字になる。好みの問題もあるが、必要なければ丁寧語や敬語を使わない方がコメントを短くできる。※お客さん向けのドキュメントなど、TPOに合わせて敬語が必要な場合も当然ある小学生や外国人に言い聞かせるようになるべく難しい言葉、言い回し、漢字、専門用語を使わず、簡単でより多くの人に伝わる文章を心がける。カタカナの外来語も逆に英語圏の人に伝わりづらいことが多いので注意する。専門用語はなるべく使わない方がいいが、プログラムを説明するにあたり必要なものは使っても問題ない。「Socket通信」という言葉は専門用語だが、「Socket通信」関連のプログラムのコメントでは使わざるをえない場合もある。様々な国籍の人が参加するプロジェクトであれば、コメントを英語で統一するのも良い。カッコつけなくていい一番大切なのは、読む人が理解しやすいこと。極端な話、読み手が理解できるなら、文法が間違っていても、英語が間違っていても問題ない。改まって綺麗な文章を書くことに時間をかける必要はなく、フランクでもいいので読み手にとって役立つコメントを書くことが大切。無責任なコメントもないよりはマシ?以下のような目を疑うようなコメントも、一応情報ではあるのでないよりマシかもしれない。ここでメモリリークします。ここの分岐はあまり意味ないかも。3】サービスの可用性を意識するアプリケーションをクラッシュさせない大前提として、アプリは落ちない方がいい。当たり前のことだと思われるかもしれないが、現代のプログラミング言語は簡単にクラッシュする。要素数3の配列の4番目にアクセスすれば多くの言語はクラッシュする。この手のバグは容易に発生するし、ものによっては気づかれないままリリースされることも珍しくない。不正な状態ならExceptionを吐いてしかるべきという考えも一理あるが、それによりアプリケーション全体がクラッシュするのはよろしくない。APIやバッチなどバックエンド系のプログラムでは、Exceptionがシステム全体を止めてしまうことはあまりないのでExceptionを積極的に活用するのも良いが、フロントエンドアプリケーションでは、一つのExceptionがアプリを完全停止させてしまうことが多いので、なるべくExceptionを吐かないようにした方が良い。このようなクラッシュをできる限り防ぐには、以下のような工夫が必要になる。適切なガードを実装するクラッシュする可能性があるコードにif文などを加えて、クラッシュする場合は処理を行わなくする。JavaのようなNULL安全でない言語でのNULLチェックなどがこれにあたる。hoge.fuga();}しかし、このようなガードはバグを握りつぶして隠蔽してしまうリスクがあるため、開発環境でのみ不正時に処理を止めるassertの仕組みがあれば代わりにそれを用いるのが良い。Swiftのassert関数はDEBUGビルドの場合のみ、条件チェックを行い不正な場合にクラッシュさせることができる。通常時の処理}もしくは、if文でガードを入れるとしても、不正な状態が発生したら最低限ログ出力くらいはしておいた方が良いだろう。そもそもクラッシュしないようにする可能ならクラッシュするコードがそもそも書きづらい開発環境を作るのが良い。これはガードを実装するより根本的な解決になる。NullPointerExceptionに対する一つの根本解決として「JavaをやめてNULL安全なKotlinを使う」ことができる。言語を変えるまでいかなくても、NULL安全でない言語にOptionalクラスを追加するなど、安全にコードを書くための拡張を追加することはできる。以下はSwiftのCollectionを拡張して、範囲外のインデックスを指定してもクラッシュせずnilを返すgetter(subscript)を追加した例。クラッシュせずnilになるNULLアクセス、配列の範囲外アクセスなど一般的でよく起こるクラッシュについては、このような関数などを追加することで対策できる。不正なデータがあってもできる限りのことはするデータの一部に不正な状態や想定外の状態があっても、問題のない部分についてはなるべく通常通り処理が行われるようにする。銀行口座の明細が見れるシステムを考える。利用明細データの1つがおかしいと何も見れなくなるシステムと、利用明細データの1つがおかしくても他の明細と口座残高は見れるシステムを比べると、ユーザーにとっては当然後者の方が使い勝手が良い。アプリケーションはユーザーをサポートする優秀な執事のように振る舞うのが理想だ(少なくとも私はそう思っている)一つ予想外のことが起こっただけで全ての職務を放棄するようでは優秀な執事とは程遠い。この方針が当てはまるのは情報を見る機能に限定される。後戻りのできない更新処理などの場合は、異常を検知したらただちに処理を取りやめるのが無難だ。3】同じ処理を何度も書かない複数箇所に書かれた同じ処理を一つにまとめることで、コード量を減らし可読性を高めるとともに、修正のコストを少なくすることができる。汎用的な機能は共通クラスや関数に切り出すビジネス要件に左右されない汎用的な機能は、共通のクラスや関数として切り出して利用する。以下は、文字列をURLエンコードする機能を共通関数として定義している。}}if文やswitch文内の記述は最低限にするif文やswitch文で処理を分岐させる場合、分岐内に同じ処理があるなら、重複部分はif文やswitch文の外に出すようにする。部分がifブロックとelseブロックの両方にあり重複している。"bbb"}このケースでは重複部分を外に出すとif文自体を消すことができる。"bbb"共通化のデメリットロジックやデータ構造の共通化にはデメリットもある。同じ処理をむやみやたらと共通化することは、むしろ保守性の低下を招くことも多い。処理を共通化することには以下のようなデメリットがあるロジックが複雑になり分かりづらくなる仕様変更により共通化したロジックを場合分けしなくてはいけなくなった場合に修正がたいへん共通化したロジックの修正が、意図しないところに影響を与えてしまう特にクラス継承による共通化は強い密結合を生み出し、プログラムの柔軟性を失わせてしまうこともあるので十分注意する。共通化すべきものとするべきでないものでは、どんなときに共通化するべきで、どんなときに共通化すべきでないか。最初に挙げたように、ビジネス要件に左右されない汎用的な機能は積極的に共通化を目指す。ビジネス要件に絡むロジックやデータの場合、共通化するかしないかはケースバイケースだが、以下を満たしていることが共通化の指針になる。コードを書く前にスケッチを作るアプリケーションを作るとき最初にワイヤーフレームやラフスケッチを作るように、プログラムもコードを書き始める前にワイヤーフレームやラフスケッチを作ると効率良く進めることができる。より手戻りが発生することが多い。コードを書けば一見進捗しているように見えるが、下手なコードは最終的に全くの無駄であったり、むしろ害悪であることすらよくある。プログラムのラフスケッチを作る方がプロジェクト全体で見ると効率が良い。プログラムのラフスケッチとはここで言うプログラムのラフスケッチはクラス図や概略のコードなどを想定している。ある必要はなく、以下のことがわかれば別の形でもいい。各クラスが保持するデータ(プロパティなど)と、他のクラスから呼び出される関数のインターフェース各クラスがどのようにインスタンス化され、どのように他のクラスと連携するか各画面遷移やUIイベントで何をするかクラス図を書く最初はクラス間の包含関係と参照関係を考えるためにクラス図を作るとわかりやすい。この段階のクラス図はルール無用、思うがままのスケッチでいい。試行錯誤しながら書き直すため手書きで作るのがおすすめだ。一対NのN側を複数書いたり、包含を線で囲んで表したりして、UML図をもっと簡単で直感的にした形にするとわかりやすい。クラスの保持するデータとインターフェースを決めるクラスの構成が決まったら、次は各クラスが保持するデータと外部との連携に必要な関数のインターフェースを決める。保持するデータというのは具体的にはインスタンス変数(メンバー変数)のことだ。クラス図と異なり、この段階でインスタンス変数はなるべく網羅しておこう。最初の方の項に書いたが、クラスのインスタンス変数はなるべく少なくする必要がある。しても必要なものだけをインスタンス変数にして、設計後はなるべく予定外のインスタンス変数を追加しないよう心がける。ラフコードを書くクラスの構成が決まったら、詳細を省略したラフコードを書いていく。ここでは大筋を決めることが目的なので、細かな文法にとらわれず自分が分かりやすい書き方書く。そのためコンパイルエラーがチェックされるIDEより、シンプルなエディターに書くのがお勧めだ。ラフコードでは処理の流れと、他クラスの呼び出し方や情報の受け渡しのインターフェースが大まかに決められれば良い。Session()}インターフェースを使ってラフコードをプロダクトコードにするインターフェースを使うと、細かな実装や未決事項を保留して骨組みになるビジネスロジックを実装することができる。コンパイルが通り、そのままプロダクトで使える形でラフコードを作ることができる。この方法はDIコンテナのあるバックエンドプログラムで非常に有効だ。bootでインターフェースを活用したラフコードの例(言語はJava)。このプログラムはファイルサーバーに写真をアップロードして、ファイルのURLをDBから取得したユーザーのメールアドレスにメールで送信する。インターフェースを使うことで、データベースもファイルサーバーもメールサーバーも、使うライブラリも決めずにビジネスロジックを実装することができる。fileData);}このようなインターフェースに簡単なモック実装を入れてシステムのプロトタイプを作ると、DBやサーバーをひとまず無視して柔軟で迅速な開発をすることができる。仕様書の不備を見つける仕様書の不備を見つけることもラフスケッチを作る目的の一つだ。いうことを念頭に置く必要がある。仕様書の間違いに実装の後に気づくと、それまでの作業が無駄になってしまう。そのためラフスケッチを書く際には、仕様書に不備がないかを意識する。2】関連するものは近くにおく関連するコードを同じディレクトリや同じファイルに配置すると、コードリーディングの際にファイルを探したり切り替えたりする手間を減らせる。同じ機能で使うファイル群を同じディレクトリに置いたり、特定のクラス内でしか使わないクラスをインナークラスにしたりと、関連するコードは近くに配置してコードを探しやすくする。ディレクトリを機能で分けるか種類で分けるかディレクトリやパッケージにファイルをまとめる場合、大きく分けて機能単位でまとめる方法と、ファイルの種類でまとめる方法がある。TimeLineViewUseCase.swift上記はどちらの例も同じファイルを持っているが、ディレクトリの分け方が異なっている。ファイルの種類でまとめる方法はレイヤー設計がわかりやすく、複数機能で使われるファイルも矛盾なく配置できるが、1つの画面のコードを読むために5ディレクトリにまたがってファイルを探す必要があり煩雑になるというデメリットもある。この2つの分け方はどちらが良いというものではなく状況に応じた使い分けが必要だが、他の機能から使われることのないファイル群であれば、機能によってディレクトリをまとめた方が開発は楽になるケースが多い。疎結合と密結合のバランス一般にプログラムは疎結合である方が汎用性やメンテナンス性に優れるが、本項の方針はそれに反してプログラムの結合度を高めるものだ。結合度を高めすぎると、1つのファイルが肥大しすぎたり密結合により汎用性やメンテナンス性を損なってしまうが、不必要で過剰な疎結合もまたメリットよりコストが大きくなってしまうというデメリットがある。何がベストかはケースバイケースで正解のない課題ではあるが、適切なバランスでコードをまとめることは意識する必要がある。UnitTestを作るここで言うUnitTestは手動のものではなく、JUnitなどのプログラムテストを指す。データを加工などの小さな機能に対して、開発初期からUnitTestを積極的に作成する。事前確認をすることで全体コストを減らすシステムに問題が見つかった場合、規模が大きい機能ほど原因調査に時間がかかる。後ろの工程になるほどプログラムの修正は他機能への影響や考慮しなければならない点が大きくなる。小さな機能に対して早い段階でUnitTestによる動作確認をしておくことで、これらのコストを減らすことができる。実際に動かしてテストするのが難しい処理の動作確認をするイレギュラーなデータや状態に対する処理は、実際にアプリケーションを動かしてテストするのが難しいケースも多い。そのようなテストでも、UnitTestであればイレギュラーな状況をプログラムで作り出してテストをすることができる。クラスや関数の使い心地を確認するUnitTestを書くことでプログラマーはテスト対象のクラスや関数を実際にプログラムで使うことになる。このときにクラスや関数の使い心地を体験することで、クラスや関数のインターフェースをより使いやすい形にブラッシュアップすることができる。副次的な効果だがUnitTestを実行するにはプログラムが疎結合であることが求められるので、クリーンな設計の勉強にもなるかもしれない。仕様を明確にするテストを作るには何が正しいかを定める必要がある。テストを考えることにより、イレギュラーケースでどうあるべきかなどの仕様や課題がより明確になる。UnitTestは開発スピードを上げるためにやるUnitTestは品質を担保するためではなく、全体の開発スピードを上げるために行う。そのため、全てのコードを網羅する必要はないし、実装が難しいテストを無理に作る必要もない。UI、通信、DBなどが絡むとUnitTestは様々な考慮が必要になるので、そのようなUnitTestを作成すると開発効率が下がるリスクがある。UnitTestをやったから品質が担保されるという考えもやめた方がいいだろう。どれだけUnitTestをやろうが、最終的に人力でのテストは必要になる。小さな機能をテストするUnitTestは基本的に小さくて独立した機能に対して行うようにする。大きな一連の操作を自動で確認するプログラムを作る場合もあるが、そういうものはUnitTestとは目的が異なる。業務ロジックの計算には数値クラスを使う業務ロジックの計算にはInt、Float、Doubleなどの基本データ型を使わず、JavaならBigDecimal、SwiftならNSDecimalNumberやDecimalなどの数値クラスを使う。Double、Floatなど浮動小数点数は基本的に業務ロジックに使わないDouble、Floatなどの浮動小数点数は、誤差が生じるので安易に使ってはいけない。浮動小数点を使うのは、おおむね座標計算などの描画処理と、性能を重視する科学計算に限られる。間違っても金額の計算にDoubleやFloatを使ってはいけない。金額の計算に32bitのIntを使用しない例えばJavaのIntは32bitで最大値が約21億だが、これは金額を扱うには小さすぎる。21億円というと大金だが、会社レベルの経理ならこれを超える金額は普通にあるし、個人資産でもあり得ない金額ではない。Intなどの組み込み整数型は桁数に上限があるため、なるべく業務ロジックでの使用は避け、使用する場合は桁あふれするケースがないかを十分考慮する。金額であれば64bitの整数値(JavaならLong型)を使えばほぼ十分だろう。64bit整数値の最大値は約900京なので、アメリカの国家予算(約400兆円)の100倍でも余裕でおさまる。2】クラス、インターフェースを増やしすぎないクラスは大きくなり過ぎないように心がけるべきだが、過剰にクラスを分割してクラスやインターフェースが増えすぎるのにも以下のようなデメリットがある。クラス結合のためのコードが必要になり全体のコード量が増えるクラス同士の関係が複雑になりコードが難しくなるコードを読解・編集する際にファイル切り替が必要になり作業効率が落ちるクラスやレイヤー構成を設計する際は、これらのデメリットを考慮した上で、メリットがデメリットを上回る設計をする必要がある。クラスを切り出すポイント何らかの機能をクラスに切り出す場合、その機能は以下のどれかである可能性が高い。再利用性(汎用性)がある単独でテストする必要がある単独でデプロイ(リリース)する必要がある逆に、再利用性がなく単独でテストもデプロイもしない機能群は、クラスを分けずに一つのクラスとして提供した方が良い可能性が高い。機能を疎結合にすることはシステムの保守性を保つのに役立つ考え方だが、そこにはコストやデメリットもあり疎結合が常に密結合より優れているわけではない。iOSアプリでは、特定の画面に対してViewControllerとカスタムのViewをそれぞれ作成する設計パターンがあるが、そのようなViewControllerとViewは必ず1対1で紐付き、再利用性がない上、単独でテストやデプロイもしないので、ViewとViewControllerに分けずに1つのクラスにした方が良いケースが多い。※LoginViewControllerに対してLoginViewを作成するようなケース有名な設計パターンを機械的に模倣しない過剰なクラスの細分化は、しばしばDDDやクリーンアーキテクチャーなど有名な設計パターンの機械的な模倣によって生まれる。設計パターンを紹介する書籍や記事は、設計パターンの良いところばかりを強調し、悪いところや面倒な点には触れない傾向にある。プロダクトやチームの規模によって最適な設計は変わってくるので、既存の設計パターンを機械的に模倣するのではなく、実際に自分たちのプロダクトに適用してメリットがデメリットに勝る形であるかを十分検討する。いえ、特定の設計パターンがどのようなデメリットを秘めているかは一度試してみないと把握するのが難しい。最適な設計パターンは、検討、実行、フィードバック、改良といったPDCAサイクルを回して徐々に洗練させていく必要がある。Worldを出力するだけのプログラムにたくさんのクラスや複雑なアーキテクチャーを適用するのは無駄である。やることがあまりないので、何もすることのないクラスやレイヤーが出てきてしまう。いったクラスやレイヤーを用意するのが妥当かは、実装する機能の性質や複雑さによって変わる。何にでもマッチする都合のいいクラス構成やアーキテクチャーはないのだ。一般的なアプリケーションには複数の画面や機能があり、性質や複雑さはそれぞれ異なるので、それら全てに同じレイヤー構成を当てはめれば、無駄やミスマッチが生じることになる。そのため、すべての機能に同じ構成を適用するのでなく、もっと柔軟に、機能ごとに適切な設計を選択していく方が良いと思われる。同じ機能であっても、要件や仕様の変化にともない最善の構成は変わっていく。良い設計を保つためには、大胆なリファクタリングや、既存のコードを完全に捨ててしまうこともときには必要になる。レイヤーのショートカットクリーンアーキテクチャーなどレイヤーが細かく分かれたアーキテクチャーでファイル数を抑える1つの方法は、レイヤーのショートカットを許容することだ。プログラムが以下のようなレイヤー構成を持つ場合でも、UseCaseとPresenterでやることがなければ、Controllerが直接Entityを参照すれば良い。EntityUseCasePresenterControllerView前項に記載したとおり、レイヤーの構成はアプリケーション内で統一する必要はなく、もっと自由に機能によって変えてしまって良いと思う。「依存の向きを意識する」の項に記載したとおり、EntityからViewを参照するような通常と逆向きの参照はしないようにしよう。インターフェース(プロトコル)をクロージャに置き換える関数型言語など関数を引数として受け渡しできる言語であれば、メソッドが一つしかないような簡単なインターフェース(プロトコル)を関数渡しやクロージャに置き換えることができる。以下はPresenterのOutputをprotocolから関数渡しに置き換えている。}}同じようなデータモデルを複数作らないレイヤーの分離に執着し過ぎると、同じようなデータモデルが無意味に複数できてしまう場合がある。ドメイン層にUserクラスがあり、その情報をUseCaseに渡すためのUserDTOがあり、さらにViewで使うためのUserViewModelがあるが、3つがほとんど同じコードになってしまうようなケースだ。ほとんど同じでも分離しなければならないケースもあるが、分けずに使い回して良いケースもある。以下の条件を満たすなら複数のレイヤーをまたいで上層のデータモデルを使っても良い。2】Exceptionをcatchして握りつぶさない基本的にExceptionはcatchせず呼び出し元にthrowし、上層のレイヤーで一括してエラー処理をするようにする。Exceptionをcatchする場合は以下を心がける。適切なエラー処理をするエラー処理ができないのであれば、エラーログを出力する明確な意図がありログすら出さずExceptionを隠蔽する場合は、その理由をコメントで記載するこの項に記載する内容は「サービスの可用性を意識する」の項に書いていることと少し矛盾するが、上層のレイヤーで適切にExceptionを処理できるならそれが一番良い。「サービスの可用性を意識する」の項に記載した方針は、上層レイヤーでExceptionを適切に処理しきれない可能性があり、それがシステム全体のクラッシュにつながるなら、Exceptionを吐かないようにしようというものだ。例外をロジックの分岐に使わない例外を上層で処理するとはいえ、通常の制御フローで例外をif文のように条件分岐に使うのはやめよう。例外はあくまで例外であり、例外的な状況以外では使わないよう心がける。すると呼び出し元の関数はcatchするか再throwするかのどちらかを強いられる。つける必要が出てきてしまう。ときにこれは鬱陶しい仕様だが、かといって例外をcatchして隠蔽したくもない場合、RuntimeExceptionにラップしてthrowすることで、呼び出し元に変更を行わず例外をthrowすることができる。外から参照されない変数や関数はprivateにするクラスの外から使われないプロパティや関数はprivateやprotectedにする。クラスはコードやドキュメントを見なくてもコード補完で何となく使い方が分かるのが望ましいが、privateやprotectedにしないと外から使われる前提でないプロパティや関数もコード補完で候補として出てしまい、使いづらくなる。privateなどのアクセス修飾子がないプログラミング言語もあり、その場合は特殊な実装でprivateを実現するより、シンプルで標準的なコードであることを優先して、privateを諦める方が良い。してもprivateを導入したいなら、そもそも言語を変えることをお勧めする(JavaScriptからTypeScriptにするなど)また、privateメソッドは別クラスのpublicメソッドに処理を切り出すことで実装がすっきりすることが多いので、汎用的な処理であったりクラスサイズが大きい場合はクラスの切り分けも検討する。三項演算子に複雑な記述を組み込まない三項演算子のネストは分かりづらいので避ける。cネストが必要になる場合は、途中の演算結果をローカル変数(説明変数)に入れてネストを解消すると良い。cまた、三項演算子内に長い式や長い関数のチェインなどが含まれる場合も、それぞれの結果をローカル変数に入れてから、三項演算子で使う。コード内にベタ書きしがちだ。Boolを返すのでtrue/falseを書く必要はなく、より簡潔に以下のように書ける。0}必ずtrueを返すケースや必ずfalseを返すケースではtrue/falseをべた書きする必要があるが、上記の例のように何らかの判定結果を返す場合は、true/falseをベタ書きするのは避ける。この書き方は初心者には分かりづらい。チーム内に初心者がいる場合は説明してあげるのが良いだろう。enumの持つコード値を使わないSwiftのenumのrawValueのように、enumは何らかのコード値を保有することが多い。このコード値を判定などに使ってしまうと、enumの存在意義が半減してしまう。"1"}例えば上記のようにコード値をもったEnumがある場合、コード値を判定などに使わず、Enumを直接使うようにする。{}引数で渡す場合もコード値は使わず、Enumを直接渡す。BadcheckStatus(status.rawValue)GoodcheckStatus(status)そもそもenumにコード値を持たせるべきではない?「コード値はenumにする」の項と矛盾するが、そもそもenumがコード値を持っていなければ、このような間違いは生まれない。レイヤーでenumに変換してやりenumにはコード値をもたせない方が綺麗なプログラム設計になる。1】静的コードチェックツールを活用するLintなどの静的コードチェックを積極的に活用する。静的コードチェックは人の手を使ずローコストでコードをチェックできるので、やっておいた方がお得である。問題を検知するだけでなく、どのようなコードに問題があるかを知る勉強にもなる。静的コードチェックにもデメリットはあり、大量のワーニングが出たとき真面目に全てをチェックすると非常に時間がかかる場合がある。ワーニングが出たからといって直ちに問題があるわけではないので、時間を使ってワーニングを潰してもアプリケーションのクオリティはさほど変わらないということもある。静的コードチェックはあくまで問題を見つける手助け程度に考えるのが良いかもしれない。0】その他雑多なプラクティス詳細な説明は省くが、その他雑多なプラクティスを列挙する。関数の引数で渡す情報は必要最小限にするパフォーマンスの最適化を早期にしすぎない大小比較には<を使い>を使わない関数の引数を出力に使わないコードのインデントを揃える求人情報いかがでしたでしょうか?この記事は私が代表を務める株式会社アルトノーツのコーディングガイドラインです。弊社は代表含め2名の会社ですが、現在iOS・Androidのエンジニアを募集中です。requestStockLike3012山本@alt_yamamoto株式会社アルトノーツ代表。エンジニア募集中です。upLoginユーザーは見つかりませんでした。