ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則

2.8K Views

September 28, 23

スライド概要

2023/9/28(木)に実施する社内勉強会、X スペース 【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則の資料です。

profile-image

組込みソフトウェアエンジニア。 技術バックボーンはC言語・ベアメタル。 CQ EVカートのオーナーで、ハード・ソフトウェアの改造を通じて自身のスキルアップを日々考え中・・・。 LAPRASポートフォリオ: https://lapras.com/public/k-abe GitHub: http://github.com/grace2riku Qiita: https://qiita.com/juraruming Zenn: https://zenn.dev/k_abe よろしくね。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

【連続講座】ソフトウェア設計原則 【SOLID】を学ぶ #3 依存性逆転の原則(dependency inversion principle) パーソルクロステクノロジー株式会社 第1技術開発本部 第4設計部 設計2課 阿部耕二

2.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 目次 自己紹介 SOLID について 依存性逆転の原則(dependency inversion principle)について テーマについて 原則違反の例 原則に則った例 依存性注入 今回の設計所感 設計についてのディスカッション・質問 2

3.

参考資料 3

4.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 自己紹介 名前: 阿部 耕二(あべ こうじ) 所属: パーソルクロステクノロジー株式会社 第1技術開発本部 第4設計部 設計2課 医療機器の組込みソフトウェア開発。C言語。 趣味: 宇宙開発(リーマンサットプロジェクト広報メンバー) LAPRAS ポートフォリオ : https://lapras.com/public/k-abe Twitter: @juraruming 4

5.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 SOLID について 設計の5原則の頭文字をとったもの。 S 単一責務の原則( Single Respomsibility Principle ) O オープン・クローズドの原則( Open Closed Principle ) L リスコフの置換原則( Liskov Substitution Principle ) I インターフェイス分離の原則( Interface Segregation Principle ) D 依存関係逆転の原則( Dependency Inversion Principle ) 5

6.

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

7.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 依存性逆転の原則(dependency inversion principle)について 上位レベルのモジュールは下位レベルのモジュールに依存しないよ うにする。 上位も下位も抽象に依存すべきである。 まず、用語について認識合わせしましょう。 上位とは? 下位とは? 抽象とは? 7

8.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 上位レベル・下位レベルのモジュールとは? 上位レベルは目的を示す 下位レベルは上位の目的を達成する手段を実装する ■ 抽象とは ? 下位・上位に共通する概念 この後の章のテーマの説明で触れます。 ■ 8

9.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 テーマについて テーマ: 仮空の医療モニタ。患者の生体情報をモニタリングできる。 今回は設定値の書込み・読込み機能について注目する。 ■ テーマの要件: 画面から装置の設定ができる 設定値の例 表示エリア選択、表示テキストの名称・色、画面の輝度、音量、音 の種類、センサの校正値(ゲイン・オフセット)、その他いろいろ ■ 9

10.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 テーマの要件(続き): 起動時に前回設定値を装置に反映する。 設定値は持ち運べる(装置の設定状態をPCで見れる) ■ テーマを実現する要素技術: ● 前回設定値の反映 SRAM の設定値を電池でバックアップ ● 設定値の持ち運び SD カード書込み・読込み ■ 10

11.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 今後想定される要素技術の変更: 前回設定値の反映 (現状)SRAMを電池にてバックアップ ⇒SPI接続のシリアルRAMへ ⇒MRAMでバックアップ電池不要へ ● 設定値の持ち運び (現状)SDカード書込み・読込み ⇒USBメモリへの変更 ■ ● 11

12.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 前回設定値の反映 設定値の持ち運び この機能の抽象概念は何か? 共通する概念は何か? ⇒設定値を書く、読むこと 12

13.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 設定値読み・書きの上位・下位モジュールは? 【下位モジュール】 設定値を書く、読むを実現する具体的手段 ● 前回設定値の反映 (現状)SRAMへの書込み・読込み SPI 接続のシリアル RAM へ ■ MRAM ● 設定値の持ち運び (現状)SDカードへの書込み・読込み USB メモリへの書込み・読込み 13

14.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 設定値読み・書きの上位・下位モジュールは? 【上位モジュール】 抽象:設定値を書く・読むことを利用するモジュール ● 前回設定値の反映 上位モジュールは起動時に抽象を呼び出し、設定値を反映する 上位モジュールは設定値変更をSRAMに書き込む ● 設定値の持ち運び 上位モジュールはSDカード書込みの画面メニューを選択・実行でSD カード書込みを行なう 上位モジュールはSDカード読込みの画面メニューを選択・実行でSD カード読込みを行なう ■ 14

15.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ 前回設定値の反映 上位:Boot 起動時に前回設定値を反映し たい 抽象:設定値 設定値の読み・書きの抽象 下位:RAM, MRAM, SpiRAM 実際に設定値を読み・書きす る手段を提供する ● 15

16.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ 設定値の持ち運び 上位:Boot 画面操作されたら設定値の読 み・書きをする 抽象:設定値 設定値の読み・書きの抽象 下位:USBMemory, SDCard 実際に設定値を読み・書きす る手段を提供する ● 16

17.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ 原則違反の例 【前回設定値の反映】機能の クラス図 上位が下位モジュールに依存 する場合 17

18.
[beta]
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則

前ページのクラス図のコード

GitHub URL: no_dip_principle
// Boot.cpp
#include "Boot.h"

コンストラクタの実装

//
Boot::Boot() {
_settingValue = new SettingValueRam();
}
Boot::~Boot() {
delete _settingValue;
}
int Boot::readSettingValue() {
return _settingValue->read();
}

18

19.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 // Boot.h #ifndef _H_BOOT_ #define _H_BOOT_ #include "SettingValueRam.h" class Boot { private: SettingValueRam* _settingValue; public: Boot(); ~Boot(); int readSettingValue(); }; #endif // _H_BOOT_ 19

20.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 // SettingValueRam.cpp #include "SettingValueRam.h" コンストラクタの実装 // SettingValueRam::SettingValueRam() { } void SettingValueRam::write() { } int SettingValueRam::read() { return 123; } 20

21.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 // SettingValueRam.h #ifndef _H_SETTINGVALUERAM_ #define _H_SETTINGVALUERAM_ class SettingValueRam { private: public: SettingValueRam(); void write(); int read(); }; #endif // _H_SETTINGVALUERAM_ 21

22.
[beta]
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則
#include <iostream>
using namespace std;
#include "Boot.h"
int main() {
Boot* boot = new Boot();
cout << "SettingValue = " << boot->readSettingValue() << endl;
delete boot;
return 0;
}

実行結果

$ ./no_dip_principle.app
SettingValue = 123

22

23.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 原則違反のクラス図・ソースコード 何が課題になるでしょう??? 23

24.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 課題の一例 関心の分離ができていない 目的と目的を達成する手段が混在する。結果、低凝集になる。 目的:起動時に設定値を読む 目的達成手段:RAMに書き込まれている設定値を読む 上位モジュールは下位モジュールがないと動かない 組込みソフトウェア開発では下位モジュールがないことの方が多い (ハードウェアができていない、機材が開発メンバー分がないなど の理由)。 下位モジュールの完成を待っていては開発スケジュールに影響がで る。 24

25.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 コードが汚れる 上位モジュールは下位モジュールがないと動かないから下位モジュ ールの動作を差し替えるテストコードを用意した、とする。 上位モジュールに本番用コードとテスト用コードを切り替える本番 コードには不要な分岐のロジックが実装されソースコードが汚れ る。 25

26.
[beta]
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則

コードが汚れる例 GitHub URL: no_dip_principle_dirty
// Boot.cpp
#include "Boot.h"

コンストラクタの実装

//
Boot::Boot() {
if (settingValueSelect) {
_settingValue = new SettingValueRam();
} else {
_settingValueRamFake = new SettingValueRamFake();
}
}
Boot::~Boot() {
if (settingValueSelect) {
delete _settingValue;
} else {
delete _settingValueRamFake;
}
}
int Boot::readSettingValue() {
if (settingValueSelect) {
return _settingValue->read();
} else {
return _settingValueRamFake->read();
}
}

26

27.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 // Boot.h #ifndef _H_BOOT_ #define _H_BOOT_ #include "SettingValueRam.h" #include "SettingValueRamFake.h" class Boot { private: SettingValueRam* _settingValue; SettingValueRamFake* _settingValueRamFake; public: int settingValueSelect = 0; Boot(); ~Boot(); int readSettingValue(); }; #endif // _H_BOOT_ 27

28.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 // SettingValueRamFake.cpp #include "SettingValueRamFake.h" コンストラクタの実装 // SettingValueRamFake::SettingValueRamFake() { } void SettingValueRamFake::write() { } int SettingValueRamFake::read() { return 456; } 28

29.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 // SettingValueRamFake.h #ifndef _H_SETTINGVALUERAMFAKE_ #define _H_SETTINGVALUERAMFAKE_ class SettingValueRamFake { private: public: SettingValueRamFake(); void write(); int read(); }; #endif // _H_SETTINGVALUERAMFAKE_ 実行結果 $ ./no_dip_principle_dirty.app SettingValue = 456 29

30.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 の実装を見ると下位モジュール(SettingValueRam)か下位モジ ュールのテストモジュール(SettingValueRamFake)を使うかで分岐が 増えている。 この分岐は本番コードには不要なコードである。 上位モジュールが下位モジュールに依存している場合で、下位モジュ ールをテストしようとするとこんなことがおきる。 コードも汚くなるし、テストしにくい構造になっている。 Boot.cpp 30

31.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ 原則に則った例 【前回設定値の反映】機能の クラス図 原則に則り、上位・下位も抽 象に依存する場合 31

32.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 上位・下位も抽象に依存する 前ページのクラス図を実装する。 GitHub URL: dip_principle ポイント: 抽象はC++の仮想関数でInterfaceのように使う(ISettingValue.h) 下位モジュールはISettingValueを使う(SettingValueRam.h) 上位モジュールは下位モジュールではなく、ISettingValueをメンバ 変数として持つ 32

33.
[beta]
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則
// ISettingValue.h
#ifndef _H_ISETTINGVALUE_
#define _H_ISETTINGVALUE_
#include <iostream>
using namespace std;
class ISettingValue {
public:
virtual void write() = 0;
virtual int read() = 0;

仮想デストラクタ

//
virtual ~ISettingValue(){
cout << "ISettingValue destructor" << endl;
}
};
#endif

// _H_ISETTINGVALUE_

33

34.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 // SettingValueRam.h #ifndef _H_SETTINGVALUERAM_ #define _H_SETTINGVALUERAM_ #include "ISettingValue.h" class SettingValueRam : public ISettingValue { private: public: SettingValueRam(); ~SettingValueRam(); void write(); int read(); }; #endif // _H_SETTINGVALUERAM_ 34

35.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 // Boot.h #ifndef _H_BOOT_ #define _H_BOOT_ #include "ISettingValue.h" class Boot { private: ISettingValue* _settingValue; public: Boot(); ~Boot(); int readSettingValue(); }; #endif // _H_BOOT_ 35

36.
[beta]
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則
// Boot.cpp
#include "Boot.h"
#include "SettingValueRam.h"
#include <iostream>
using namespace std;

コンストラクタの実装

//
Boot::Boot() {
cout << "Boot constructor" << endl;
_settingValue = new SettingValueRam();
}
Boot::~Boot() {
cout << "Boot destructor" << endl;
delete _settingValue;
}
int Boot::readSettingValue() {
return _settingValue->read();
}

36

37.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 実行結果 $ ./dip_principle.app Boot constructor SettingValueRam constructor SettingValue = 123 Boot destructor SettingValueRam decstructor ISettingValue destructor 余計なプリント文が出力されているが、実行結果は原則違反コードの 時と同じ。 37

38.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 Factory でインスタンスを生成する GitHub URL: dip_principle_factories 前回のコードは課題がある。 さて、どこでしょう??? 38

39.
[beta]
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則
// Boot.h
#include "Boot.h"
#include "SettingValueRam.h"
#include <iostream>
using namespace std;

コンストラクタの実装

//
Boot::Boot() {
cout << "Boot constructor" << endl;
_settingValue = new SettingValueRam();
}

// ★

ここで下位モジュールに依存している

Boot::~Boot() {
cout << "Boot destructor" << endl;
delete _settingValue;
}
int Boot::readSettingValue() {
return _settingValue->read();
}

39

40.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 上位モジュールは下位モジュールに依存しないようにするのが依存性 逆転の原則だが、上位モジュールは下位モジュールの依存を断ち切れ ていなかった これを改善していく。 使うテクニックはデザインパターンでお馴染みのFactory。 Factory クラスのメソッドでインスタンス生成を行う。 こうすることで上位メソッドは下位メソッドとの依存をなくすことが できる。 40

41.
[beta]
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則
// Boot.cpp
#include "Boot.h"
//#include "SettingValueRam.h"
#include "Factories.h"
#include <iostream>
using namespace std;

コンストラクタの実装

//
Boot::Boot() {
cout << "Boot constructor" << endl;
_settingValue = Factories::CreateSettingValue();
}
Boot::~Boot() {
cout << "Boot destructor" << endl;
delete _settingValue;
}
int Boot::readSettingValue() {
return _settingValue->read();
}

41

42.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 // Factories.h #ifndef _H_FACTORIES_ #define _H_FACTORIES_ #include "ISettingValue.h" #include "SettingValueRam.h" class Factories { public: static ISettingValue* CreateSettingValue(); }; #endif // _H_FACTORIES_ 42

43.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 // Factories.cpp #include "Factories.h" #include "ISettingValue.h" #include "SettingValueRam.h" #include "SettingValueRamFake.h" ISettingValue* Factories::CreateSettingValue() { return new SettingValueRam(); // return new SettingValueRamFake(); } 43

44.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 実行結果 $ ./dip_principle_factories.app SettingValue = 123 ファクトリで生成する下位モジュールをSettingValueRamFakeに切り 替えた場合 実行結果 $ ./dip_principle_factories.app SettingValue = 456 44

45.
[beta]
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則

下位モジュールSettingValueRamFakeの実装
// SettingValueRamFake.cpp
#include "SettingValueRamFake.h"
#include <iostream>
using namespace std;

コンストラクタの実装

//
SettingValueRamFake::SettingValueRamFake() {
cout << "SettingValueRamFake constructor" << endl;
}
SettingValueRamFake::~SettingValueRamFake() {
cout << "SettingValueRamFake decstructor" << endl;
}
void SettingValueRamFake::write() {
}
int SettingValueRamFake::read() {
return 456;
}

45

46.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 依存性注入 前回の【Factoryでインスタンスを生成する】で上位モジュールは下位 モジュールとの依存をなくすことができた。 前回のコードを依存性注入のテクニックを使い、よりオブジェクト指 向っぽくする。 オブジェクト指向っぽいとはどういうことか?後で書きます。 46

47.
[beta]
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則
// Boot.h
#ifndef _H_BOOT_
#define _H_BOOT_
#include "ISettingValue.h"
class Boot {
private:
ISettingValue* _settingValue;
public:
Boot(ISettingValue* settingValue);
~Boot();
int readSettingValue();

// ★

ここに注目!!!

};
#endif

// _H_BOOT_

47

48.
[beta]
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則
// Boot.cpp
#include "Boot.h"
//#include "SettingValueRam.h"
//#include "Factories.h"
#include "ISettingValue.h"
#include <iostream>
using namespace std;

コンストラクタの実装

//
Boot::Boot(ISettingValue* settingValue) {
cout << "Boot constructor" << endl;
//

_settingValue = Factories::CreateSettingValue();
_settingValue = settingValue;

}
Boot::~Boot() {
cout << "Boot destructor" << endl;
delete _settingValue;
}
int Boot::readSettingValue() {
return _settingValue->read();
}

48

49.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 前回のコードを依存性注入のテクニックを使い、よりオブジェク ト指向っぽくする。 ↑ の【オブジェクト指向っぽい】とはどういうことか ? システムの中でクラスは自分の責務・責任を果たすために動く。 システムの中の要求で自分の責務だけで目的を達成できないときは、 他のクラスと協調して動く(私にはこれがオブジェクト指向っぽいと感 じた訳です)。 依存性注入はクラスが自分の責務を果たすために必要な情報を与えて いる。依存性の注入というワードに惑わされるかもしれないが、至極 当然というか自然なテクニック。 “ “ 49

50.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 依存性注入とテスト 依存性注入でテストをやってみる。 テストのシナリオ: 下位モジュールが読み出した設定値が正しいかテストしたい 設定値の確認を行うクラス, メソッド:SettingValueValidation, validate 読み出した設定値は100以上であれば正しいとする 下位モジュールの設定値はモック・SettingValueMockでテストに適 した値にする 50

51.
[beta]
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則
GitHub: dip_and_di_test_easy_env
下位モジュールが読み出した値の検証

// SettingValueValidation.cpp
#include "SettingValueValidation.h"
#include "ISettingValue.h"
#include <iostream>
using namespace std;

コンストラクタの実装

//
SettingValueValidation::SettingValueValidation(ISettingValue* settingValue) {
cout << "SettingValueValidation constructor" << endl;
_settingValue = settingValue;
}
SettingValueValidation::~SettingValueValidation() {
cout << "SettingValueValidation destructor" << endl;
delete _settingValue;
}
bool SettingValueValidation::validate() {
int value = _settingValue->read();
if (value >= 100) return true;
return false;
}

51

52.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 // SettingValueValidation.h #ifndef _H_SETTINGVALUEVALIDATION_ #define _H_SETTINGVALUEVALIDATION_ #include "ISettingValue.h" class SettingValueValidation { private: ISettingValue* _settingValue; public: SettingValueValidation(ISettingValue* settingValue); ~SettingValueValidation(); bool validate(); }; #endif // _H_SETTINGVALUEVALIDATION_ 52

53.
[beta]
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則
下位モジュールの設定値読み・書きをモックする

// SettingValueMock.cpp
#include "SettingValueMock.h"
#include <iostream>
using namespace std;

コンストラクタの実装

//
SettingValueMock::SettingValueMock() {
cout << "SettingValueMock constructor" << endl;
}
SettingValueMock::~SettingValueMock() {
cout << "SettingValueMock decstructor" << endl;
}
void SettingValueMock::write() {
}
int SettingValueMock::read() {
return 100;
}

53

54.
[beta]
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則
テスト

// SettingValueExampleTest.cpp
#include "CppUTest/TestHarness.h"

#include <iostream>
using namespace std;
#include "SettingValueValidation.h"
#include "SettingValueMock.h"
#include "ISettingValue.h"
TEST_GROUP(SettingValueExampleTest)
{
SettingValueValidation* settingValueValidation;
void setup()
{
//
(SettingValueMock)
(SettingValueValidation)
settingValueValidation = new SettingValueValidation(new SettingValueMock());
}

モック

を設定値チェックのロジック

に依存性注入している

void teardown()
{
delete settingValueValidation;
}
};
TEST(SettingValueExampleTest, SettingValueValid)
{
CHECK(settingValueValidation->validate());
}

54

55.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 テストの結果表示 // $ ./bin/dip_and_di_test_easy_env -v TEST(SettingValueExampleTest, SettingValueValid) - 0 ms OK (1 tests, 1 ran, 1 checks, 0 ignored, 0 filtered out, 1 ms) 依存性注入を使うことでテストコード、本番コードの切り替えも簡 単に行える 下位モジュールはデバイス制御に特化したコードにする(今回の例で は設定値の読み出しのみ)。下位モジュールを使う上位モジュールの ロジックをテストしやすくなる。 55

56.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 今回の設計所感 未来のことは分からないけど、製品にバリエーションを持たせる必 要が開発開始時にわかっているなら(もしくは多品種にシリーズ展開 する目論みで開発をスタートさせるなど)依存性逆転の原則を使うと 幸せになれるかもしれないと思った。 開発しているソフトウェアはどういうビジネス戦略で、今後どうい った方針をとるのか、は把握しておいた方がよさそうと感じた。あ とは製品のトレンドとか。やはりビジネスの観点とソフトウェア設 計は関係している、と思った。 原則に則り、依存性注入を使うとテストしやすくなりそう。 原則に則ると製品、プロダクトの拡張にも対応しやすそう。 56

57.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 設計についてのディスカッション・質 問 自分以外の設計の視点が学びになると個人的に考えています。 ぜひぜひお気軽にフィードバックをよろしくお願いします こちらに学習の振り返りに使う目的でZennのスクラップを用意しま した。 活用ください。 【SOLID原則】#3 "依存性逆転の原則(dependency inversion principle ) " の勉強会後の振り返り 57

58.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 参考資料 オブジェクト指向の原則3:依存関係逆転の原則とインタフェース 分離の原則 Udemy の講座。作成者はピーコック アンダーソンさん。依存関係逆 転の原則以外のSOLID原則の講座もあり。 2. オブジェクト指向習得のための5ステップ【 SOLID 原則】 3. テスト駆動開発による組み込みプログラミング ―C 言語とオブジェク ト指向で学ぶアジャイルな設計 1. 58

59.

【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #3 依存性逆転の原則 ご清聴ありがとうございました 59