スポンサーリンク

コードが書ける!数式が書ける!AAが書ける!スタンプが貼れる!

無料の匿名掲示板型SNS「このはちゃんねる

新規会員募集中!

ソフトウェアの設計で大事なこと【そんな気がする】

101, 2019-08-12

目次

はじめに

経験則多めのそんな気がするだけのメモです(2017年に記述)。
今見るとまぁまぁ正しいことを書いてるような気もするので、原文のまま転載。

エラーとログ

エラーハンドリングとログの記録方法を最初に決定すべき。エラーハンドリングは言語の設計に従うのが良い気がする。Python3なら例外、Goなら戻り値。
ログはUNIX系ならsyslogなど。

アーキテクチャー

アーキテクチャーはプロジェクトの土台。最初に設計すべき。MVCなど実績のあるアーキテクチャーを選択する。
MVCの適用風景。

$ mkdir project
$ touch project/models.py
$ touch project/views.py
$ touch project/ctrls.py

インターフェースとコンポジション

インターフェースに依存し、継承よりもコンポジションを多用すると、設計に多少の柔軟性が生まれるらしい。使ってみると確かにそんな気はする。
フレームワークの利用者の視点で見ると、継承は拡張の手間が少なく、コンポジションの場合は継承より拡張の手間が多くなる気がする。

/**
 * インターフェ―ス。
 */
interface Book {
    public String getTitle();
    public String getAuthor();
}

/**
 * Bookインターフェースを実装したクラス。
 */
class RedBook implements Book {
    public String getTitle() {
        return "The Red Book";
    }

    public String getAuthor() {
        return "Taro Tanaka";
    }
}

/**
 * インターフェース。
 */
interface Printer {
    public void print();
}

/**
 * Bookをコンポジションするクラス。
 */
class BookConsolePrinter implements Printer {
    private Book _book; // インターフェースに対する依存

    BookConsolePrinter(Book book) {
        // Book をコンポジション
        _book = book;
    }

    public void print() {
        System.out.println(_book.getTitle() + " by " + _book.getAuthor());
    }
}

class Main {
    public static void main(String args[]) {
        /* コンポジションを多用するとこのレイヤー(Main)の処理が増える傾向がある。
        このレイヤーはファクトリーなどで代替される。 */
        Book book = new RedBook();
        Printer printer = new BookConsolePrinter(book); // Bookをコンポジション
        printer.print();
    }
}

テスト

実装がテスト可能かどうかを気にすると良い気がする。「テスト不可能≒設計が複雑」という指針は乱暴?関連にDIがある。

レイヤー

処理がレイヤー可されているかどうか、似た物同士がないか気にすると良い気がする。ファイル名はレイヤー名を表している。身近な例でMVCがある。

$ ls
models.py # モデル・レイヤー
views.py # ビュー・レイヤー
ctrls.py # コントロール・レイヤー

過去にマルチプロセスなアプリケーション(ChromeExtension)を作成したとき、バイト列とオブジェクトを相互変換するために変換レイヤーを設けたら上手く行ったことがある。

プロセス1から受け取ったバイト列を変換レイヤーでオブジェクトにする。  
process1 -> bytes -> conv -> object

オブジェクトを変換レイヤーでバイト列にしてプロセス2に渡す。  
process2 <- bytes <- conv <- object

その時もやはりファイル名はconv.jsでレイヤー名を表していた。変換処理がこのファイル内で完結するため管理がしやすく実装が捗った。
他にもSQLを使う場合、MVCを適用するとモデル・レイヤーにSQLが集約されたことがあった。モデル・レイヤーによってDBへのアクセスが集約され、管理がしやすくなった。
つまり似た物同士は同じ所に集めると管理がしやすい(レイヤー化)気がする。

共通化

似たような処理を共通化すると大体うまく行くが、たまに失敗する気がする。メソッドAとメソッドBで同じような処理をしているのでメソッドCに切り出して共通化すると、大体うまく行くが、失敗することもある。不思議。

汎用性のある抽象化

汎用性のある抽象化は正義。例えばcssなら、

my-nantoka-row {
  margin: 0 0 4px 0;
  font-size: 14px;
}

などのオートクチュールなパーツではなく、

small-row {
  margin: 0 0 4px 0;
}
normal-font {
  font-size: 14px;
}

のように汎用性のあるパーツにすると拡張性&保守性が上がる。

投稿者名です。64字以内で入力してください。

必要な場合はEメールアドレスを入力してください(全体に公開されます)。

投稿する内容です。

スポンサーリンク

スポンサーリンク

スポンサーリンク

スポンサーリンク