$30 off During Our Annual Pro Sale. View Details »

ソフトウェア設計原則【SOLID】を学ぶ #2 インターフェイス分離の原則

k-abe
August 28, 2023

ソフトウェア設計原則【SOLID】を学ぶ #2 インターフェイス分離の原則

2023/8/28(月)に実施する社内勉強会、X スペース 【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2 インターフェイス分離の原則(Interface segregation principle)" の資料です。

※リンクが有効な資料はこちらを参照ください。
https://www.docswell.com/s/juraruming/KJLWEM-2023-08-28-005645

k-abe

August 28, 2023
Tweet

More Decks by k-abe

Other Decks in Technology

Transcript

  1. 【連続講座】ソフトウェア設計原則

    SOLID
    】を学ぶ
    #2
    インターフェイス分離の原則(Interface segregation principle

    パーソルクロステクノロジー株式会社
    第1
    技術開発本部 第4
    設計部 設計2
    課 阿部耕二

    View Slide

  2. 目次
    自己紹介
    SOLID
    について
    インターフェイス分離の原則(Interface segregation principle
    )に
    ついて
    インターフェイスについて
    例1.
    複合機
    例2.
    乗り物
    例3. read, write
    例4.
    リングバッファ
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    2

    View Slide

  3. 今回の設計所感
    設計についてのディスカッション・質問
    参考資料

    View Slide

  4. 自己紹介
    名前:
    阿部 耕二(あべ こうじ)
    所属:
    パーソルクロステクノロジー株式会社
    第1
    技術開発本部 第4
    設計部 設計2

    医療機器の組込みソフトウェア開発。C
    言語。
    趣味:
    宇宙開発(リーマンサットプロジェクト広報メンバー)
    LAPRAS
    ポートフォリオ: https://lapras.com/public/k-abe
    Twitter: @juraruming
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    4

    View Slide

  5. SOLID
    について
    設計の5
    原則の頭文字をとったもの。
    S
    単一責務の原則(Single Respomsibility Principle

    O
    オープン・クローズドの原則(Open Closed Principle

    L
    リスコフの置換原則(Liskov Substitution Principle

    I
    インターフェイス分離の原則(
    Interface Segregation Principle

    D
    依存関係逆転の原則(Dependency Inversion Principle

    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    5

    View Slide

  6. SOLID
    原則の重要性
    凝集度が高くなる
    他のモジュールと疎結合になる
    各モジュールの目的が明確に分けられると、コード変更の際の影響
    は局所化される。結果、テストしやすい設計になる。
    上記の特徴を持つと再利用しやすいコードになる。
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    参考資料2
    より引用


    6

    View Slide

  7. インターフェイス分離の原則

    Interface segregation principle
    )に
    ついて
    相手に必要なことだけを見せるようにする。必要ないことを見せる
    とよくないことがおきる。
    本来、関連が必要ないクラスと関連をもってしまったり(疎結合で
    はなく密結合になる)、
    変更の影響が大きくなってしまったりする。
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    参考資料1
    より引用


    7

    View Slide

  8. インターフェイスについて
    インターフェイスとは?
    機能の使い方のみを定義している。
    データ・処理を持たない。
    データ・処理をもたないのでそのまま使うことはできない。
    インターフェイスの使い方を実現したクラスをインスタンス化して使
    う。
    インターフェイスは参考資料3
    が個人的にわかりやすかった。
    Interface
    クラスの使い方ポイント解説【オブジェクト指向】
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    8

    View Slide

  9. C++
    でインターフェイス実現例
    #include
    #include
    class Shape {
    public:
    virtual void print_type() = 0;
    virtual float calc_area() = 0;
    };
    class Circle : public Shape {
    private:
    float r;
    public:
    Circle(float r) { this->r = r;}
    ~Circle() { }
    void print_type() {
    std::cout << "This is circle." << std::endl;
    }
    float calc_area() {
    return this->r * this->r * 3.14;
    }
    };
    class Triangle : public Shape {
    private:
    float base;
    float height;
    public:
    Triangle(float base, float height) {this->base = base; this->height = height;}
    ~Triangle() { }
    void print_type() {
    std::cout << "This is triangle." << std::endl;
    }
    float calc_area() {
    return (this->base * this->height) / 2.0;
    }
    };
    class Square : public Shape {
    private:
    float side;
    public:
    Square(float side) {this->side = side;}
    ~Square() { }
    void print_type() {
    std::cout << "This is square." << std::endl;
    }
    float calc_area() {
    return this->side * this->side;
    }
    };
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ
    9

    View Slide

  10. C++
    でインターフェイス実現例(インターフェイスを使う側)
    int main()
    {
    Shape* circle = new Circle(1.2);
    Shape* triangle = new Triangle(2.5, 2.0);
    Shape* square = new Square(1.3);
    circle->print_type();
    std::cout << "circle area = " << circle->calc_area() << std::endl;
    triangle->print_type();
    std::cout << "triangle area = " << triangle->calc_area() << std::endl;
    square->print_type();
    std::cout << "square area = " << square->calc_area() << std::endl;
    }
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    10

    View Slide


  11. 1.
    複合機
    参考資料4
    の複合機の例がわか
    りやすかったので説明に使わ
    せていただく。
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ
    11

    View Slide

  12. 複合機の例の学び
    異なる目的を持つ機能を組み合わせて製品にバリエーションを持た
    せる、などのときにインターフェイス分離の原則は効果を発揮しそ
    うだ。
    対象を自然な形で表現できる。
    インターフェイス分離の原則と単一責務の原則のエッセンスは似て
    いる。小さい目的の組み合わせでシステムが構成する。
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    12

    View Slide


  13. 2.
    乗り物
    参考資料5
    の乗り物のアクショ
    ンの例がわかりやすかったの
    で説明に使わせていただく。
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ
    13

    View Slide

  14. 乗り物の例の学び
    インターフェイスを分離しないことで例の車の飛ぶメソッドのよう
    に現実とはかけ離れた構造を実現できてしまうので注意が必要。
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    14

    View Slide


  15. 3. read, write
    インタフェース分離の原則で組込みソフトウェア向けのサンプルコー
    ドをChatGPT
    に提示してもらいました。
    原則違反の例、原則に則った例のコードを提示してもらいました。
    IoT
    の文脈でセンサーデータを読み込み、活用するシステムをイメージ
    してもらえればと思います。
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    15

    View Slide

  16. 原則違反の例
    class IDevice {
    public:
    virtual void readData() = 0;
    virtual void writeData() = 0;
    virtual void performAction() = 0;
    };
    class Sensor : public IDevice {
    public:
    void readData() override {
    //
    センサーデータを読み取る処理
    }
    void writeData() override {
    //
    センサーデータを保存する処理
    }
    void performAction() override {
    //
    センサーの動作を制御する処理
    }
    };
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    16

    View Slide

  17. 原則に則った例
    class IDataReader {
    public:
    virtual void readData() = 0;
    };
    class IDataWriter {
    public:
    virtual void writeData() = 0;
    };
    class IActionPerformer {
    public:
    virtual void performAction() = 0;
    };
    class Sensor : public IDataReader, public IDataWriter, public IActionPerformer {
    public:
    void readData() override {
    //
    センサーデータを読み取る処理
    }
    void writeData() override {
    //
    センサーデータを保存する処理
    }
    void performAction() override {
    //
    センサーの動作を制御する処理
    }
    };
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    17

    View Slide

  18. データの読み込み、書き込みを分けると組込みソフトウェアの現場で
    使いそうな汎用的なパターンになりそうです。
    class SensorDataDispley : public IDataReader, public IActionPerformer {
    public:
    void readData() override { //
    センサーデータを読み取る処理 }
    void performAction() override { //
    センサーの動作を制御する処理 }
    };
    class SensorDataStore : public IDataWriter {
    public:
    void writeData() override { //
    センサーデータを保存する処理 }
    };
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    18

    View Slide


  19. 4.
    リングバッファ
    インタフェース分離の原則で組込みソフトウェア向けのサンプルコー
    ドを考えた時にはじめに頭に浮かんだのがリングバッファでした。
    インタフェース分離とはリングバッファのライトとリードのインター
    フェースを分けるような実装かなぁと想像しました。
    こちらもChatGPT
    にコードを提示してもらいました。
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    19

    View Slide

  20. 原則違反の例
    class IRingBuffer {
    public:
    virtual void enqueue(int data) = 0;
    virtual int dequeue() = 0;
    virtual bool isEmpty() = 0;
    };
    class RingBuffer : public IRingBuffer {
    private:
    int buffer[100];
    int head;
    int tail;
    public:
    void enqueue(int data) override {
    //
    データをバッファに追加する処理
    }
    int dequeue() override {
    //
    バッファからデータを取り出す処理
    return 0;
    }
    bool isEmpty() override {
    //
    バッファが空かどうかを判定する処理
    return true;
    }
    };
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    20

    View Slide

  21. class Application {
    public:
    void processData(IRingBuffer* buffer) {
    if (!buffer->isEmpty()) {
    int data = buffer->dequeue();
    //
    データを処理する
    }
    }
    };
    int main() {
    RingBuffer buffer;
    Application app;
    //
    アプリケーションを実行
    app.processData(&buffer);
    return 0;
    }
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    21

    View Slide

  22. 原則に則った例
    class IEnqueuer {
    public:
    virtual void enqueue(int data) = 0;
    };
    class IDequeuer {
    public:
    virtual int dequeue() = 0;
    };
    class IBufferChecker {
    public:
    virtual bool isEmpty() = 0;
    };
    class RingBuffer : public IEnqueuer, public IDequeuer, public IBufferChecker {
    private:
    int buffer[100];
    int head;
    int tail;
    public:
    void enqueue(int data) override {
    //
    データをバッファに追加する処理
    }
    int dequeue() override {
    //
    バッファからデータを取り出す処理
    return 0;
    }
    bool isEmpty() override {
    //
    バッファが空かどうかを判定する処理
    return true;
    }
    };
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    22

    View Slide

  23. class Application {
    public:
    void processData(IDequeuer* dequeuer, IBufferChecker* checker) {
    if (!checker->isEmpty()) {
    int data = dequeuer->dequeue();
    //
    データを処理する
    }
    }
    };
    int main() {
    RingBuffer buffer;
    Application app;
    //
    アプリケーションを実行
    app.processData(&buffer, &buffer);
    return 0;
    }
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    23

    View Slide

  24. RingBuffer
    クラスが分離した3
    つのインタフェースを使っている。
    エンキュー、デキューでクラスを分けると責務が分かれたクラスが
    できると感じた。
    ただ機械的にインタフェースを分離すれば良いわけではなく、
    どんな目的を達成したいからインターフェイスをどのような粒度で分
    離しするのか、
    そしてどのような責務を持つクラスで目的を実現するのか?
    、の思考・
    検討が大事だと感じた。
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    24

    View Slide

  25. 今回の設計所感
    インターフェイスはどのくらいの粒度で分離すれば良いのか?
    ->
    ひとつヒントになりそうなのは単一責務の原則の視点だと思った。
    ->
    この問いに非常に参考になるのは参考資料6
    の動画。
    Forkwell
    エンジニア文化祭2023
    「分岐を低減するinterface
    設計と発
    想の転換」ミノ駆動
    目的に注目することがヒントになることを認識できた。
    インターフェイス自体の学習にもオススメです。
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    25

    View Slide

  26. 参考資料6
    の中で以下の意味合いの内容が印象に残った。
    このようなライブラリ・インターフェイスは会社・組織のソフトウェ
    ア資産となる考えられるのでこのような信頼性高いものを開発したい
    と思いました。
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    標準ライブラリFILE
    のopen, read, write
    などは信頼を持って、特
    に意識することなくつかっている。
    このような信頼性高いライブラリ・インターフェイスを生み出し
    たいものである。


    26

    View Slide

  27. 設計についてのディスカッション・質

    自分以外の設計の視点が学びになると個人的に考えています。
    ぜひぜひお気軽にフィードバックをよろしくお願いします
    こちらに学習の振り返りに使う目的でZenn
    のスクラップを用意しま
    した。
    活用ください。
    【SOLID
    原則】#2 "
    インターフェイス分離の原則(Interface
    segregation principle
    )"
    の勉強会後の振り返り
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    27

    View Slide

  28. 参考資料
    1.
    オブジェクト指向習得のための5ステップ【SOLID
    原則】
    2.
    テスト駆動開発による組み込みプログラミング―C
    言語とオブジェク
    ト指向で学ぶアジャイルな設計
    3. Interface
    クラスの使い方ポイント解説【オブジェクト指向】
    4.
    【オブジェクト指向】「インターフェース分離の原則」について
    5.
    インターフェース分離の原則とは何か
    6. Forkwell
    エンジニア文化祭2023
    「分岐を低減するinterface
    設計と
    発想の転換」ミノ駆動
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    28

    View Slide

  29. ご清聴ありがとうございました
    【連続講座】ソフトウェア設計原則【SOLID
    】を学ぶ #2
    インターフェイス分離の原則
    29

    View Slide