Slide 1

Slide 1 text

【連続講座】ソフトウェア設計原則 【 SOLID 】を学ぶ #4 開放閉鎖の原則(open/closed principle ) パーソルクロステクノロジー株式会社 第1 技術開発本部 第4 設計部 設計2 課 阿部耕二

Slide 2

Slide 2 text

目次 自己紹介 SOLID について 開放閉鎖の原則(open/closed principle )について 日常にある【開放閉鎖】 原則違反の例 原則に則った例 今回の設計所感 設計についてのディスカッション・質問 参考資料 2

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

開放閉鎖の原則( open/closed principle )について 拡張に開かれており(Open )、変更に閉じられていること (Closed )。 機能拡張(追加)の際にクライアントコード(機能追加したコードを 使う側)に変更が発生しないこと。 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 6

Slide 7

Slide 7 text

日常にある【開放閉鎖】 生活していると様々な製品・事象で開放閉鎖の原則を感じることがで きる。 開放閉鎖の原則はソフトウェア設計の領域のみでなく、ビジネスを大 きくするための考え方など幅広い事象に転用できる、と個人的に思っ ている。 いくつか私が日常生活で感じた開放閉鎖の原則について紹介したい。 これらの考え方、事象はより良いソフトウェアの構造にするためのヒ ントになりそうと感じている。 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 7

Slide 8

Slide 8 text

日常にある【開放閉鎖】の例 USB Apple AC アダプタ apt-get コマンド その他 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 8

Slide 9

Slide 9 text

日常にある【開放閉鎖】の例 USB 日常にある【開放閉鎖の原則】の考えたときに一番はじめにイメージ したのがUSB 。参考資料3 の説明がわかりやすかったので引用する。 参考資料3: テスト駆動開発による組み込みプログラミング―C 言語とオ ブジェクト指向で学ぶアジャイルな設計 11.1.2 オープン・クローズド の原則(OCP : Open Closed Principle ) 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 USB ポートは規格に準拠したデバイスなら何でも挿せるよう拡張 可能だが、新しいデバイスを受け付けるために変更する必要はな い。したがってUSB ポートのあるコンピュータは、デバイス追加 による機能の拡張に対して開いているが、デバイスがUSB に準拠 している限り機器構成の変更に対しては閉じていると言える。 “ “ 9

Slide 10

Slide 10 text

日常にある【開放閉鎖】の例 Apple AC アダプタ Apple のAC アダプタも開放閉 鎖かなと思った。 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ 10

Slide 11

Slide 11 text

アダプタは取り外し可能で海外でも使えるように考慮されていると予 想できる。調べてみたらApple ワールドトラベルアダプタキットなる 製品があり、7 種類のアダプタが付属していた。 プラグ部分が拡張でき、プラグ部分を変更しても本体部分に変更が及 ばない作りになっている。 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 11

Slide 12

Slide 12 text

日常にある【開放閉鎖】の例 apt-get コマンド Linux (Debian やUbuntu )のパッケージ追加コマンド。 パッケージを追加してもLinux カーネル本体には影響がない。 拡張に開かれていて、修正に閉じていると言えそう。 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 12

Slide 13

Slide 13 text

日常にある【開放閉鎖】の例 その他 家庭のコンセント マクドナルド ハッピーセット リカちゃん 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 13

Slide 14

Slide 14 text

家庭のコンセント コンセント側はコンセントに挿される機器を気にしない。 何がさされても変わらずAC100V を供給する。 機器側はコンセントから供給されるAC100V を機器側の仕様に従って 利用する。 例)ヘアドライヤーは交流で動作するものが多い印象 例)AC アダプタは交流→ 直流へ変換し所望の電圧にしている(12V, 5V, 3.3V, その他) 【AC100V が供給される】ことに従えば様々な機器を動作させること ができる。 様々な機器を動作させるためにコンセントの動作に変更は発生しな い。 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 14

Slide 15

Slide 15 text

マクドナルド ハッピーセッ ト リカちゃん こどもたちが大好きマクドナ ルド ハッピーセットの玩具 リ カちゃんに注目した。 全キャラの共通事項 ポージングが同じ メイクが同じ ヘアスタイルはパーツ化し てあり変更可能 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ 15

Slide 16

Slide 16 text

マクドナルド ハッピーセッ ト リカちゃん ラプンツェル風(左) ドレス着せ替えバージョン (中央) 髪色変化(右) 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ 16

Slide 17

Slide 17 text

マクドナルド ハッピーセッ ト リカちゃん 頭部のパーツはネジ止めされ ている。 頭部をパーツ化する設計でリ カちゃんのヘアスタイルのバ リエーションを増やすための 拡張が可能になっている。 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ 17

Slide 18

Slide 18 text

マクドナルド ハッピーセット リカちゃん リカちゃんは共通の特性を持ちながらもいろいろな特徴を持つ拡張が できている。 このような商品展開を続けられれば今後もハッピーセットはこどもた ちの収集癖と心とおなかを鷲掴みにすることでしょう。 このような製品を多く生産するには生産ラインにも工夫がありそう。 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 18

Slide 19

Slide 19 text

日常にある【開放閉鎖】の例 日常にある【開放閉鎖】はつぎのような特徴がある。 拡張しやすくするためのポイントが設計され、用意されている。 例)Apple AC アダプタはプラグの取り外しで様々な国のコンセント に対応可能 例)リカちゃんであればポージング・メイク・ヘアスタイルのパー ツ化の共通事項 拡張はそれ以外の本体部分に影響しないように設計されている 例)Apple AC アダプタはプラグがどの形状になっても本体は変化し ない 例)リカちゃんはどのバリエーションでもお人形のベースは変わら ない(と思う。製造者ではないので確証はない) 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 19

Slide 20

Slide 20 text

日常にある【開放閉鎖】の例 拡張しやすくするためのポイントが設計され、用意されている。 拡張はそれ以外の本体部分に影響しないように設計されている 上の特徴をソフトウェアに持ち込めば拡張に開かれており ( Open )、変更に閉じられている( Closed ) 構造になりそう。 具体的にどうすれば良いのか??? 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 20

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

説明のシナリオ: 現在はBoot クラスと SettingValueRAM クラスが 実装済みとする。 仕様変更(将来的にRAM が 生産中止になることがわか った)で次ロットからSPI の RAM に変更することになっ た、というストーリーとし ます。 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ 24

Slide 25

Slide 25 text

GitHub URL: no_ocp_principle // Boot.cpp #include "Boot.h" // コンストラクタの実装 Boot::Boot() { _settingValue = new SettingValueRam(); } Boot::~Boot() { delete _settingValue; } int Boot::readSettingValue() { return _settingValue->read(); } 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 25

Slide 26

Slide 26 text

// Boot.h #ifndef _H_BOOT_ #define _H_BOOT_ #include "SettingValueRam.h" class Boot { private: SettingValueRam* _settingValue; public: Boot(); ~Boot(); int readSettingValue(); }; #endif // _H_BOOT_ 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 26

Slide 27

Slide 27 text

// SettingValueRam.cpp #include "SettingValueRam.h" // コンストラクタの実装 SettingValueRam::SettingValueRam() { } void SettingValueRam::write() { } int SettingValueRam::read() { return 123; } 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 27

Slide 28

Slide 28 text

// SettingValueRam.h #ifndef _H_SETTINGVALUERAM_ #define _H_SETTINGVALUERAM_ class SettingValueRam { private: public: SettingValueRam(); void write(); int read(); }; #endif // _H_SETTINGVALUERAM_ 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 28

Slide 29

Slide 29 text

#include using namespace std; #include "Boot.h" int main() { Boot* boot = new Boot(); cout << "SettingValue = " << boot->readSettingValue() << endl; delete boot; return 0; } 実行結果 $ ./no_ocp_principle.app SettingValue = 123 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 29

Slide 30

Slide 30 text

変更の方針としてつぎが考えられる 既存の機能提供側のコードに新仕様を実装する 仕様変更のモジュールを追加し、機能を使う側でどちらの機能を使 うか選択する 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 30

Slide 31

Slide 31 text

既存の機能提供側のコード に新仕様を実装する場合 既存の機能提供側とは SettingValueRam のこと。 ここにSettingValueSpiRam の機能を追加する。 SettingValueRam 内部で SettingValueSpiRam の機能 を切り替えて使用する。 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ 31

Slide 32

Slide 32 text

既存の機能提供側のコードに新仕様を実装する場合 機能を使う側で選択する場合 no_ocp_principle_server_dirty //SettingValueRam.cpp #include "SettingValueRam.h" // コンストラクタの実装 SettingValueRam::SettingValueRam(eSettingValueRamType eSettingValueRamType) { _eSettingValueRamType = eSettingValueRamType; } void SettingValueRam::write() { if (_eSettingValueRamType == eSettingValueRamType::Ram) { // SettingValueRam のロジック } else { // SettingValueSpiRam のロジック } } int SettingValueRam::read() { if (_eSettingValueRamType == eSettingValueRamType::Ram) { // SettingValueRam のロジック return 123; } else { // SettingValueSpiRam のロジック return 456; } 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 32

Slide 33

Slide 33 text

// SettingValueRam.h #ifndef _H_SETTINGVALUERAM_ #define _H_SETTINGVALUERAM_ enum class eSettingValueRamType { Ram, SpiRam, }; class SettingValueRam { private: eSettingValueRamType _eSettingValueRamType; public: SettingValueRam(eSettingValueRamType eSettingValueRamType); void write(); int read(); }; #endif // _H_SETTINGVALUERAM_ 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 33

Slide 34

Slide 34 text

// Boot.cpp #include "Boot.h" // コンストラクタの実装 Boot::Boot() { // _settingValue = new SettingValueRam(eSettingValueRamType::Ram); _settingValue = new SettingValueRam(eSettingValueRamType::SpiRam); } Boot::~Boot() { delete _settingValue; } int Boot::readSettingValue() { return _settingValue->read(); } 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 34

Slide 35

Slide 35 text

// Boot.h #ifndef _H_BOOT_ #define _H_BOOT_ #include "SettingValueRam.h" class Boot { private: SettingValueRam* _settingValue; public: Boot(); ~Boot(); int readSettingValue(); }; #endif // _H_BOOT_ // 実行結果 $ ./no_ocp_principle_server_dirty.app SettingValue = 456 // eSettingValueRamType::SpiRam 選択時 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 35

Slide 36

Slide 36 text

既存の機能提供側のコードに新仕様を実装してみた。 この実装はつぎの特徴がある。 既存機能と新機能が混在している。 単一責務の原則の観点からオススメしない。 既存機能と新機能が混在していることから機能切り替えの分岐が発 生する。 コードが汚くなる。機能のバリエーションが増えると複雑度が増 す。 → 修正に閉じれていない。 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 36

Slide 37

Slide 37 text

仕様変更のモジュールを追 加し、機能を使う側でどちら の機能を使うか選択する場合 仕様変更部分を実装するク ラスを追加する (SettingValueSpiRam ) 機能を使う側で機能を選択 する(Boot.cpp ) 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ 37

Slide 38

Slide 38 text

機能を使う側で選択する場合 no_ocp_principle_client_dirty // Boot.cpp #include "Boot.h" // コンストラクタの実装 Boot::Boot() { if (settingValueSelect) { _settingValue = new SettingValueRam(); } else { _settingValueSpiRam = new SettingValueSpiRam(); } } Boot::~Boot() { if (settingValueSelect) { delete _settingValue; } else { delete _settingValueSpiRam; } } int Boot::readSettingValue() { if (settingValueSelect) { return _settingValue->read(); } else { return _settingValueSpiRam->read(); } } 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 38

Slide 39

Slide 39 text

// Boot.h #ifndef _H_BOOT_ #define _H_BOOT_ #include "SettingValueRam.h" #include "SettingValueSpiRam.h" class Boot { private: SettingValueRam* _settingValue; SettingValueSpiRam* _settingValueSpiRam; public: int settingValueSelect = 0; Boot(); ~Boot(); int readSettingValue(); }; #endif // _H_BOOT_ 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 39

Slide 40

Slide 40 text

// SettingValueSpiRam.cpp #include "SettingValueSpiRam.h" // コンストラクタの実装 SettingValueSpiRam::SettingValueSpiRam() { } void SettingValueSpiRam::write() { } int SettingValueSpiRam::read() { return 456; } 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 40

Slide 41

Slide 41 text

// SettingValueSpiRam.h #ifndef _H_SETTINGVALUESPIRAM_ #define _H_SETTINGVALUESPIRAM_ class SettingValueSpiRam { private: public: SettingValueSpiRam(); void write(); int read(); }; #endif // _H_SETTINGVALUESPIRAM_ 実行結果 $ ./no_ocp_principle_client_dirty.app SettingValue = 456 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 41

Slide 42

Slide 42 text

仕様変更のモジュールを追加し、機能を使う側でどちらの機能を使う か選択するようにしてみた。 この実装はつぎの特徴がある。 既存機能と新機能は分離した。 → 拡張に開かれていそうだが・・・ 機能を使う側は既存機能と新機能を切り替えるための分岐が発生す る。 コードが汚くなる。機能のバリエーションが増えると複雑度が増 す。 → 修正に閉じれていない。 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 42

Slide 43

Slide 43 text

原則に則った例 開放閉鎖の原則に則るにはど うすれば良いのか? 原則に則れない理由を改めて 考えてみる。 既存のクラス (SettingValueRam )と追加 したクラス (SettingValueSpiRam )を同 一視できていないことが理由 として挙げられそう。 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ 43

Slide 44

Slide 44 text

同一視できていない(SettingValueRam とSettingValueSpiRam を同じ ように扱えない)ために機能を利用する側でどちらの機能を利用する かの分岐が必要になる。 結果、修正に閉じることができなくなり、開放閉鎖の原則に則ること ができない。 同一視するための技術として次がある(他にもあるかも・・・)。 C++: virtual でInterface のような動きを実現する。 C: 関数ポインタで動作する関数を動的に切り替える C#: Interface, abstrct (抽象クラス) 今回はC++ でvirttual を使い、Interface のような動きでクラスを同一視 する。 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 44

Slide 45

Slide 45 text

SettingValueRam と SettingValuSpiRam を同一視 するためにInterface を使 う。 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ 45

Slide 46

Slide 46 text

原則に則った例 ocp_principle_factories // ISettingValue.h #ifndef _H_ISETTINGVALUE_ #define _H_ISETTINGVALUE_ #include using namespace std; class ISettingValue { public: virtual void write() = 0; virtual int read() = 0; // 仮想デストラクタ virtual ~ISettingValue(){ cout << "ISettingValue destructor" << endl; } }; #endif // _H_ISETTINGVALUE_ 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 46

Slide 47

Slide 47 text

// 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_ 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 47

Slide 48

Slide 48 text

// SettingValueSpiRam.h #ifndef _H_SETTINGVALUESPIRAM_ #define _H_SETTINGVALUESPIRAM_ #include "ISettingValue.h" class SettingValueSpiRam : public ISettingValue { private: public: SettingValueSpiRam(); ~SettingValueSpiRam(); void write(); int read(); }; #endif // _H_SETTINGVALUESPIRAM_ 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 48

Slide 49

Slide 49 text

// Boot.h #ifndef _H_BOOT_ #define _H_BOOT_ #include "ISettingValue.h" class Boot { private: ISettingValue* _settingValue; public: Boot(); ~Boot(); int readSettingValue(); }; #endif // _H_BOOT_ 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 49

Slide 50

Slide 50 text

// Boot.cpp #include "Boot.h" #include "Factories.h" #include 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(); } 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 50

Slide 51

Slide 51 text

// Factories.cpp #include "Factories.h" #include "ISettingValue.h" #include "SettingValueRam.h" #include "SettingValueSpiRam.h" ISettingValue* Factories::CreateSettingValue() { // return new SettingValueRam(); return new SettingValueSpiRam(); } 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 51

Slide 52

Slide 52 text

#ifndef _H_FACTORIES_ #define _H_FACTORIES_ #include "ISettingValue.h" class Factories { public: static ISettingValue* CreateSettingValue(); }; #endif // _H_FACTORIES_ // 実行結果 $ ./ocp_principle_factories.app SettingValue = 456 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 52

Slide 53

Slide 53 text

Interface を使うことで2 つのクラスを同一視できた。結果、開放閉 鎖の原則に則ることができた。 クラスを生成する責務を持つFactory を導入した。 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 53

Slide 54

Slide 54 text

今回の設計所感 長く使われているもの・システムは開放閉鎖の原則に則っているこ とが多いことに気づいた。 例)USB 、AC アダプタ 開放閉鎖の原則はソフトウェア設計だけではなく、システムやもの を長く使うために広く使える考え方のフレームワークだと感じた。 覚えやすく、シンプルな原則でこの原則を言語化してくれた偉人に 感謝したい 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 54

Slide 55

Slide 55 text

設計原則の適用は課題解決に効果的だと思う。課題がないのに初め から原則を適用するとソフトウェアの構造を複雑にする可能性もあ ると感じた。技術駆動にならないよう気をつけたいと感じた。 ここでいう技術駆動はつぎのようなイメージ。 Interface の使い方を覚えたから特に課題はないけど、実際の開発現場 で適用してみよう、という感じ。 原則を適用する前の対象製品を分析することが重要ではないかと感 じた。製品のバリエーションが増えることがわかっていれば最初か ら原則を意識して拡張に開いて、修正に閉じる構造にしておくこと が効果的と感じた。 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 55

Slide 56

Slide 56 text

今回はC++ で開放閉鎖の原則の説明だった。参考資料3 ではC で開放 閉鎖の原則違反の課題、原則を適用する過程を紹介しているので共 有する。ライセンスの関係でコードを掲載、紹介できなかったが一 見の価値ありだと思っている。 テスト駆動開発による組み込みプログラミング―C 言語とオブジェクト 指向で学ぶアジャイルな設計 該当ページ: 11 章 SOLID で柔軟でテストしやすい設計 11.3 要求の進化と問題のある設計〜11.4.7 詳細を隠蔽する 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 56

Slide 57

Slide 57 text

著者の方がGitHub にコードをアップロードしている。 docker でテスト駆動開発の環境構築できるようです(有難い )。 tddec-code 書籍の該当ページと合わせてcode-t1 、code-t2 ディレクトリの差分を 見ていくと開放閉鎖の原則の観点でコードが改善されていく様子がわ かるのでオススメ 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 57

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

ご清聴ありがとうございました 【連続講座】ソフトウェア設計原則【SOLID 】を学ぶ #4 開放閉鎖の原則 60