🍣

「システム設計の原則」覚え書き - チャプター1, 2

2021/06/04に公開

はじめに

現場で役立つシステム設計の原則を読んだ。
(リンク先は技術評論社のHP)

この記事は、読んだ本について書き残すことを目的としている。つまり・・

  • 覚えておきたい要点を書き残す
  • 周辺知識へのリンクも貼っておく
  • 本書はJavaで書かれているので、C#で書いたときの文法メモ

書いているうちに長くなったので、チャプター2までを対象とする

※ あくまで自分なりの解釈であり、著者の意図を完全トレースしているわけではない。

要点だけ知りたい

著者のスライドがアップされているので、右矢印連打するとよいです。

ドメインオブジェクトの見つけ方・作り方・育て方

チャプター1

キーワードは★閉じ込める★

要点

  • 名前を省略してはいけない
  • 段落を使って、コードに意味を持たせる
  • 変数を使いまわすな(再代入するな)
  • 関心ごとをクラスに閉じ込める
  • 単位を扱うクラスをつくる
    • intをそのまま使わずに、Priceなど独自の型をつくる
    • 型にはロジックも閉じ込める(×データだけのクラス ×インスタンス変数を使わないメソッド)
  • コレクションを扱うクラスをつくる;ファーストクラスコレクション

最後のファーストクラスコレクションについては、奥が深く理解しきれていない。

不変な性質

「この変数はもう変わらないんだな」とわかるとうれしい。
いわゆる脳内メモリの消費が少なくて済む。

せっかくなら用意されている修飾子(finalreadonly)を余すところなく使いたい

Qiita記事->読みやすいコードを書くためのTips

// java
class A
{
    static final int MIN = 1;
}
// c#
class A
{
    static readonly int MIN = 1;
}

プライベート変数はアンダースコア派?それともthis派?

C#はアンダースコア_を変数の頭につけることが多い。
本書ではプライベート変数にthisをつけている。
それがJavaの決まりなのか慣例なのかは知らない。

言いたいことは、自分はアンスコ派だったけど、thisもいいなあ、と。
thisのほうが、インテリセンスが的を射ている気がする。

Case1: アンダースコアを使った場合...Not good enough

ifやregionとかプリプロセッサが示唆される

Case2: thisを使った場合...Good!!

関係ありそうなメソッドあるいは変数が表示される

破壊的代入の例

変数の値はなるべく変わらないほうがいい。
変えたくなったら別の変数を用意してみるといいかも。

javascriptなんかでは、なるべくconstで値を宣言しましょう、と言われる。
最近流行りのRustも用意されているのはイミュータブルな変数が基本。

最近みつけたマイクロソフトさんのサンプルコードに、破壊的代入とも呼べるコードがあったので、リンクする。
このくらいの規模感だと、下手に変数たくさん用意されるほうが何か深い意図を勘ぐってしまうので、
マイクロソフトさんはこのくらいラフにやってくれたほうがこちらも安心する。

破壊的代入の例?→TcpListener クラス
変数dataを使いまわしている。

値オブジェクト

またの名をバリューオブジェクト

クソコード爆殺隊のミノ駆動様の記事にすべて書かれている

Qiita記事->設計要件をギッチギチに詰めたValueObjectで低凝集クラスを爆殺する

チャプター2

要点

  • elseは使わない
  • 早期リターン
  • インターフェイスと多態を使う
    • そのクラスを使う側が"知っておくべきこと"は少ないほうがいい
    • これもキーワード★閉じ込める★に通じるものがある
  • 列挙型を使い倒そう
    • Javaの強力な列挙型が紹介されている。C#では同じことができない・・(?)

列挙型

本書ではいろいろ便利なことが書かれているけど、残念ながらC#では真似できない
(ラッパーやら拡張メソッドやらで似せることはできるけど?)

Qiita記事->C# と Java の列挙型の違い

Qiita記事->【C#】Enumを使う際のTips

JavaMapは、C#Dictionaryでいいのだろうか。
細かい違いはあるようだけれども・・JavaプログラマーがC#でプログラムを書いて引っかかったところ その1

Enumを使った状態遷移

P65 状態Aから状態Bに遷移できるか判定するプログラムをC#で無理やり書いてみる

3つの状態をenumで定義する。待機と準備と動作中みたいなやつ。

internal enum State
{
    Wait,
    Move,
    Ready,
}

Enumの拡張メソッドクラスをつくる

internal static class EnumExtend
{
    // JavaのMapは、C#のDictionaryで代用する
    static Dictionary<State, HashSet<State>> allowd;

    static EnumExtend()
    {
        allowd = new();

        // ある状態をKeyとして、遷移先の状態をValueとする。Valueは複数あってもよい。
        allowd.Add(State.Wait, new() { State.Ready });
        allowd.Add(State.Ready, new() { State.Wait, State.Move });
        allowd.Add(State.Move, new() { State.Wait });
    }

    // 状態遷移可能であればTrue
    public static bool CanTransit(this State from, State to)
        => allowd[from].Contains(to);
}

使う側

var state = State.Move;
var b = state.CanTransit(State.Wait);
// b: True

おわり

気が向いたらチャプター3以降も書く

Discussion