2023/8/28(月)に実施する社内勉強会、X スペース 【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2 インターフェイス分離の原則(Interface segregation principle)" の資料です。
※リンクが有効な資料はこちらを参照ください。 https://www.docswell.com/s/juraruming/KJLWEM-2023-08-28-005645
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ#2インターフェイス分離の原則(Interface segregation principle)パーソルクロステクノロジー株式会社第1技術開発本部 第4設計部 設計2課 阿部耕二
View Slide
目次自己紹介SOLIDについてインターフェイス分離の原則(Interface segregation principle)についてインターフェイスについて例1.複合機例2.乗り物例3. read, write例4.リングバッファ【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2インターフェイス分離の原則2
今回の設計所感設計についてのディスカッション・質問参考資料
自己紹介名前:阿部 耕二(あべ こうじ)所属:パーソルクロステクノロジー株式会社第1技術開発本部 第4設計部 設計2課医療機器の組込みソフトウェア開発。C言語。趣味:宇宙開発(リーマンサットプロジェクト広報メンバー)LAPRASポートフォリオ: https://lapras.com/public/k-abeTwitter: @juraruming【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2インターフェイス分離の原則4
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
SOLID原則の重要性凝集度が高くなる他のモジュールと疎結合になる各モジュールの目的が明確に分けられると、コード変更の際の影響は局所化される。結果、テストしやすい設計になる。上記の特徴を持つと再利用しやすいコードになる。【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2インターフェイス分離の原則参考資料2より引用““6
インターフェイス分離の原則(Interface segregation principle)について相手に必要なことだけを見せるようにする。必要ないことを見せるとよくないことがおきる。本来、関連が必要ないクラスと関連をもってしまったり(疎結合ではなく密結合になる)、変更の影響が大きくなってしまったりする。【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2インターフェイス分離の原則参考資料1より引用““7
インターフェイスについてインターフェイスとは?機能の使い方のみを定義している。データ・処理を持たない。データ・処理をもたないのでそのまま使うことはできない。インターフェイスの使い方を実現したクラスをインスタンス化して使う。インターフェイスは参考資料3が個人的にわかりやすかった。Interfaceクラスの使い方ポイント解説【オブジェクト指向】【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2インターフェイス分離の原則8
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
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
例1.複合機参考資料4の複合機の例がわかりやすかったので説明に使わせていただく。【連続講座】ソフトウェア設計原則【SOLID】を学ぶ11
複合機の例の学び異なる目的を持つ機能を組み合わせて製品にバリエーションを持たせる、などのときにインターフェイス分離の原則は効果を発揮しそうだ。対象を自然な形で表現できる。インターフェイス分離の原則と単一責務の原則のエッセンスは似ている。小さい目的の組み合わせでシステムが構成する。【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2インターフェイス分離の原則12
例2.乗り物参考資料5の乗り物のアクションの例がわかりやすかったので説明に使わせていただく。【連続講座】ソフトウェア設計原則【SOLID】を学ぶ13
乗り物の例の学びインターフェイスを分離しないことで例の車の飛ぶメソッドのように現実とはかけ離れた構造を実現できてしまうので注意が必要。【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2インターフェイス分離の原則14
例3. read, writeインタフェース分離の原則で組込みソフトウェア向けのサンプルコードをChatGPTに提示してもらいました。原則違反の例、原則に則った例のコードを提示してもらいました。IoTの文脈でセンサーデータを読み込み、活用するシステムをイメージしてもらえればと思います。【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2インターフェイス分離の原則15
原則違反の例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
原則に則った例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
データの読み込み、書き込みを分けると組込みソフトウェアの現場で使いそうな汎用的なパターンになりそうです。class SensorDataDispley : public IDataReader, public IActionPerformer {public:void readData() override { //センサーデータを読み取る処理 }void performAction() override { //センサーの動作を制御する処理 }};class SensorDataStore : public IDataWriter {public:void writeData() override { //センサーデータを保存する処理 }};【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2インターフェイス分離の原則18
例4.リングバッファインタフェース分離の原則で組込みソフトウェア向けのサンプルコードを考えた時にはじめに頭に浮かんだのがリングバッファでした。インタフェース分離とはリングバッファのライトとリードのインターフェースを分けるような実装かなぁと想像しました。こちらもChatGPTにコードを提示してもらいました。【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2インターフェイス分離の原則19
原則違反の例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
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
原則に則った例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
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
RingBufferクラスが分離した3つのインタフェースを使っている。エンキュー、デキューでクラスを分けると責務が分かれたクラスができると感じた。ただ機械的にインタフェースを分離すれば良いわけではなく、どんな目的を達成したいからインターフェイスをどのような粒度で分離しするのか、そしてどのような責務を持つクラスで目的を実現するのか?、の思考・検討が大事だと感じた。【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2インターフェイス分離の原則24
今回の設計所感インターフェイスはどのくらいの粒度で分離すれば良いのか?->ひとつヒントになりそうなのは単一責務の原則の視点だと思った。->この問いに非常に参考になるのは参考資料6の動画。Forkwellエンジニア文化祭2023「分岐を低減するinterface設計と発想の転換」ミノ駆動目的に注目することがヒントになることを認識できた。インターフェイス自体の学習にもオススメです。【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2インターフェイス分離の原則25
参考資料6の中で以下の意味合いの内容が印象に残った。このようなライブラリ・インターフェイスは会社・組織のソフトウェア資産となる考えられるのでこのような信頼性高いものを開発したいと思いました。【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2インターフェイス分離の原則標準ライブラリFILEのopen, read, writeなどは信頼を持って、特に意識することなくつかっている。このような信頼性高いライブラリ・インターフェイスを生み出したいものである。““26
設計についてのディスカッション・質問自分以外の設計の視点が学びになると個人的に考えています。ぜひぜひお気軽にフィードバックをよろしくお願いしますこちらに学習の振り返りに使う目的でZennのスクラップを用意しました。活用ください。【SOLID原則】#2 "インターフェイス分離の原則(Interfacesegregation principle)"の勉強会後の振り返り【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2インターフェイス分離の原則27
参考資料1.オブジェクト指向習得のための5ステップ【SOLID原則】2.テスト駆動開発による組み込みプログラミング―C言語とオブジェクト指向で学ぶアジャイルな設計3. Interfaceクラスの使い方ポイント解説【オブジェクト指向】4.【オブジェクト指向】「インターフェース分離の原則」について5.インターフェース分離の原則とは何か6. Forkwellエンジニア文化祭2023「分岐を低減するinterface設計と発想の転換」ミノ駆動【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2インターフェイス分離の原則28
ご清聴ありがとうございました【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #2インターフェイス分離の原則29