SlideShare a Scribd company logo
1 of 60
Download to read offline
【連続講座】ソフトウェア設計原則
【SOLID】を学ぶ
#4 開放閉鎖の原則(open/closed principle)
パーソルクロステクノロジー株式会社
第1技術開発本部 第4設計部 設計2課 阿部耕二
目次
自己紹介
SOLIDについて
開放閉鎖の原則(open/closed principle)について
日常にある【開放閉鎖】
原則違反の例
原則に則った例
今回の設計所感
設計についてのディスカッション・質問
参考資料 2
自己紹介
名前: 阿部 耕二(あべ こうじ)
所属: パーソルクロステクノロジー株式会社
第1技術開発本部第4設計部設計2課
医療機器の組込みソフトウェア開発。C言語。
趣味: 宇宙開発(リーマンサットプロジェクト広報メンバー)
LAPRASポートフォリオ: https://lapras.com/public/k-abe
Twitter: @juraruming
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
3
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
SOLID原則の重要性
凝集度が高くなる
他のモジュールと疎結合になる
各モジュールの目的が明確に分けられると、コード変更の際の影響
は局所化される。結果、テストしやすい設計になる。
上記の特徴を持つと再利用しやすいコードになる。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
参考資料3より引用
“
“
5
開放閉鎖の原則(open/closed
principle)について
拡張に開かれており(Open)、変更に閉じられていること
(Closed)。
機能拡張(追加)の際にクライアントコード(機能追加したコードを
使う側)に変更が発生しないこと。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
6
日常にある【開放閉鎖】
生活していると様々な製品・事象で開放閉鎖の原則を感じることがで
きる。
開放閉鎖の原則はソフトウェア設計の領域のみでなく、ビジネスを大
きくするための考え方など幅広い事象に転用できる、と個人的に思っ
ている。
いくつか私が日常生活で感じた開放閉鎖の原則について紹介したい。
これらの考え方、事象はより良いソフトウェアの構造にするためのヒ
ントになりそうと感じている。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
7
日常にある【開放閉鎖】の例
USB
Apple ACアダプタ
apt-getコマンド
その他
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
8
日常にある【開放閉鎖】の例
USB
日常にある【開放閉鎖の原則】の考えたときに一番はじめにイメージ
したのがUSB。参考資料3の説明がわかりやすかったので引用する。
参考資料3: テスト駆動開発による組み込みプログラミング―C言語とオ
ブジェクト指向で学ぶアジャイルな設計11.1.2 オープン・クローズド
の原則(OCP : Open Closed Principle)
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
USBポートは規格に準拠したデバイスなら何でも挿せるよう拡張
可能だが、新しいデバイスを受け付けるために変更する必要はな
い。したがってUSBポートのあるコンピュータは、デバイス追加
による機能の拡張に対して開いているが、デバイスがUSBに準拠
している限り機器構成の変更に対しては閉じていると言える。
“
“
9
日常にある【開放閉鎖】の例
Apple ACアダプタ
AppleのACアダプタも開放閉
鎖かなと思った。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ
10
アダプタは取り外し可能で海外でも使えるように考慮されていると予
想できる。調べてみたらApple ワールドトラベルアダプタキットなる
製品があり、7種類のアダプタが付属していた。
プラグ部分が拡張でき、プラグ部分を変更しても本体部分に変更が及
ばない作りになっている。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
11
日常にある【開放閉鎖】の例
apt-getコマンド
Linux(DebianやUbuntu)のパッケージ追加コマンド。
パッケージを追加してもLinuxカーネル本体には影響がない。
拡張に開かれていて、修正に閉じていると言えそう。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
12
日常にある【開放閉鎖】の例
その他
家庭のコンセント
マクドナルドハッピーセットリカちゃん
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
13
家庭のコンセント
コンセント側はコンセントに挿される機器を気にしない。
何がさされても変わらずAC100Vを供給する。
機器側はコンセントから供給されるAC100Vを機器側の仕様に従って
利用する。
例)ヘアドライヤーは交流で動作するものが多い印象
例)ACアダプタは交流→直流へ変換し所望の電圧にしている(12V,
5V, 3.3V, その他)
【AC100Vが供給される】ことに従えば様々な機器を動作させること
ができる。
様々な機器を動作させるためにコンセントの動作に変更は発生しな
い。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
14
マクドナルドハッピーセッ
トリカちゃん
こどもたちが大好きマクドナ
ルドハッピーセットの玩具リ
カちゃんに注目した。
全キャラの共通事項
ポージングが同じ
メイクが同じ
ヘアスタイルはパーツ化し
てあり変更可能
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ
15
マクドナルドハッピーセッ
トリカちゃん
ラプンツェル風(左)
ドレス着せ替えバージョン
(中央)
髪色変化(右)
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ
16
マクドナルドハッピーセッ
トリカちゃん
頭部のパーツはネジ止めされ
ている。
頭部をパーツ化する設計でリ
カちゃんのヘアスタイルのバ
リエーションを増やすための
拡張が可能になっている。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ
17
マクドナルドハッピーセットリカちゃん
リカちゃんは共通の特性を持ちながらもいろいろな特徴を持つ拡張が
できている。
このような商品展開を続けられれば今後もハッピーセットはこどもた
ちの収集癖と心とおなかを鷲掴みにすることでしょう。
このような製品を多く生産するには生産ラインにも工夫がありそう。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
18
日常にある【開放閉鎖】の例
日常にある【開放閉鎖】はつぎのような特徴がある。
拡張しやすくするためのポイントが設計され、用意されている。
例)Apple ACアダプタはプラグの取り外しで様々な国のコンセント
に対応可能
例)リカちゃんであればポージング・メイク・ヘアスタイルのパー
ツ化の共通事項
拡張はそれ以外の本体部分に影響しないように設計されている
例)Apple ACアダプタはプラグがどの形状になっても本体は変化し
ない
例)リカちゃんはどのバリエーションでもお人形のベースは変わら
ない(と思う。製造者ではないので確証はない)
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
19
日常にある【開放閉鎖】の例
拡張しやすくするためのポイントが設計され、用意されている。
拡張はそれ以外の本体部分に影響しないように設計されている
上の特徴をソフトウェアに持ち込めば拡張に開かれており
(Open)、変更に閉じられている(Closed)構造になりそう。
具体的にどうすれば良いのか???
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
20
原則違反の例
前回の#3 依存性逆転の原則と同じテーマで説明をしていきます。
■テーマ:
仮空の医療モニタ。患者の生体情報をモニタリングできる。
今回は設定値の書込み・読込み機能について注目する。
■テーマの要件:
画面から装置の設定ができる
設定値の例
表示エリア選択、表示テキストの名称・色、画面の輝度、音量、音
の種類、センサの校正値(ゲイン・オフセット)、その他いろいろ
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
21
■テーマの要件(続き):
今回は前回設定値の反映機能のみを対象とする。
起動時に前回設定値を装置に反映する。
設定値は持ち運べる(装置の設定状態をPCで見れる)
■テーマを実現する要素技術:
●前回設定値の反映
SRAMの設定値を電池でバックアップ
●設定値の持ち運び
SDカード書込み・読込み
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
22
■今後想定される要素技術の変更:
●前回設定値の反映
(現状)SRAMを電池にてバックアップ
⇒SPI接続のシリアルRAMへ
⇒MRAMでバックアップ電池不要へ
●設定値の持ち運び
(現状)SDカード書込み・読込み
⇒USBメモリへの変更
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
23
説明のシナリオ:
現在はBootクラスと
SettingValueRAMクラスが
実装済みとする。
仕様変更(将来的にRAMが
生産中止になることがわか
った)で次ロットからSPIの
RAMに変更することになっ
た、というストーリーとし
ます。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ
24
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
// 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
// SettingValueRam.cpp
#include "SettingValueRam.h"
// コンストラクタの実装
SettingValueRam::SettingValueRam() {
}
void SettingValueRam::write() {
}
int SettingValueRam::read() {
return 123;
}
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
27
// SettingValueRam.h
#ifndef _H_SETTINGVALUERAM_
#define _H_SETTINGVALUERAM_
class SettingValueRam {
private:
public:
SettingValueRam();
void write();
int read();
};
#endif // _H_SETTINGVALUERAM_
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
28
#include <iostream>
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
変更の方針としてつぎが考えられる
既存の機能提供側のコードに新仕様を実装する
仕様変更のモジュールを追加し、機能を使う側でどちらの機能を使
うか選択する
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
30
既存の機能提供側のコード
に新仕様を実装する場合
既存の機能提供側とは
SettingValueRamのこと。
ここにSettingValueSpiRam
の機能を追加する。
SettingValueRam内部で
SettingValueSpiRamの機能
を切り替えて使用する。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ
31
既存の機能提供側のコードに新仕様を実装する場合
機能を使う側で選択する場合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
// 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
// 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
// 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
既存の機能提供側のコードに新仕様を実装してみた。
この実装はつぎの特徴がある。
既存機能と新機能が混在している。
単一責務の原則の観点からオススメしない。
既存機能と新機能が混在していることから機能切り替えの分岐が発
生する。
コードが汚くなる。機能のバリエーションが増えると複雑度が増
す。
→修正に閉じれていない。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
36
仕様変更のモジュールを追
加し、機能を使う側でどちら
の機能を使うか選択する場合
仕様変更部分を実装するク
ラスを追加する
(SettingValueSpiRam)
機能を使う側で機能を選択
する(Boot.cpp)
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ
37
機能を使う側で選択する場合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
// 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
// SettingValueSpiRam.cpp
#include "SettingValueSpiRam.h"
// コンストラクタの実装
SettingValueSpiRam::SettingValueSpiRam() {
}
void SettingValueSpiRam::write() {
}
int SettingValueSpiRam::read() {
return 456;
}
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
40
// 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
仕様変更のモジュールを追加し、機能を使う側でどちらの機能を使う
か選択するようにしてみた。
この実装はつぎの特徴がある。
既存機能と新機能は分離した。
→拡張に開かれていそうだが・・・
機能を使う側は既存機能と新機能を切り替えるための分岐が発生す
る。
コードが汚くなる。機能のバリエーションが増えると複雑度が増
す。
→修正に閉じれていない。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
42
原則に則った例
開放閉鎖の原則に則るにはど
うすれば良いのか?
原則に則れない理由を改めて
考えてみる。
既存のクラス
(SettingValueRam)と追加
したクラス
(SettingValueSpiRam)を同
一視できていないことが理由
として挙げられそう。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ
43
同一視できていない(SettingValueRamとSettingValueSpiRamを同じ
ように扱えない)ために機能を利用する側でどちらの機能を利用する
かの分岐が必要になる。
結果、修正に閉じることができなくなり、開放閉鎖の原則に則ること
ができない。
同一視するための技術として次がある(他にもあるかも・・・)。
C++: virtualでInterfaceのような動きを実現する。
C: 関数ポインタで動作する関数を動的に切り替える
C#: Interface, abstrct(抽象クラス)
今回はC++でvirttualを使い、Interfaceのような動きでクラスを同一視
する。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
44
SettingValueRamと
SettingValuSpiRamを同一視
するためにInterfaceを使
う。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ
45
原則に則った例ocp_principle_factories
// 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_
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
46
// 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
// 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
// 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
// Boot.cpp
#include "Boot.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();
}
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
50
// 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
#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
Interfaceを使うことで2つのクラスを同一視できた。結果、開放閉
鎖の原則に則ることができた。
クラスを生成する責務を持つFactoryを導入した。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
53
今回の設計所感
長く使われているもの・システムは開放閉鎖の原則に則っているこ
とが多いことに気づいた。
例)USB、ACアダプタ
開放閉鎖の原則はソフトウェア設計だけではなく、システムやもの
を長く使うために広く使える考え方のフレームワークだと感じた。
覚えやすく、シンプルな原則でこの原則を言語化してくれた偉人に
感謝したい
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
54
設計原則の適用は課題解決に効果的だと思う。課題がないのに初め
から原則を適用するとソフトウェアの構造を複雑にする可能性もあ
ると感じた。技術駆動にならないよう気をつけたいと感じた。
ここでいう技術駆動はつぎのようなイメージ。
Interfaceの使い方を覚えたから特に課題はないけど、実際の開発現場
で適用してみよう、という感じ。
原則を適用する前の対象製品を分析することが重要ではないかと感
じた。製品のバリエーションが増えることがわかっていれば最初か
ら原則を意識して拡張に開いて、修正に閉じる構造にしておくこと
が効果的と感じた。
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
55
今回はC++で開放閉鎖の原則の説明だった。参考資料3ではCで開放
閉鎖の原則違反の課題、原則を適用する過程を紹介しているので共
有する。ライセンスの関係でコードを掲載、紹介できなかったが一
見の価値ありだと思っている。
テスト駆動開発による組み込みプログラミング―C言語とオブジェクト
指向で学ぶアジャイルな設計
該当ページ:
11章SOLIDで柔軟でテストしやすい設計
11.3 要求の進化と問題のある設計〜11.4.7 詳細を隠蔽する
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
56
著者の方がGitHubにコードをアップロードしている。
dockerでテスト駆動開発の環境構築できるようです(有難い )。
tddec-code
書籍の該当ページと合わせてcode-t1、code-t2ディレクトリの差分を
見ていくと開放閉鎖の原則の観点でコードが改善されていく様子がわ
かるのでオススメ
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
57
設計についてのディスカッション・質
問
自分以外の設計の視点が学びになると個人的に考えています。
ぜひぜひお気軽にフィードバックをよろしくお願いします
こちらに学習の振り返りに使う目的でZennのスクラップを用意しま
した。
活用ください。
【SOLID原則】#4 "開放閉鎖の原則(dependency inversion
principle)"の勉強会後の振り返り
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
58
参考資料
1. オブジェクト指向の原則1:単一責務の原則とオープンクローズド
の原則
Udemyの講座。作成者はピーコックアンダーソンさん。オープンク
ローズドの原則以外のSOLID原則の講座もあり。
2. オブジェクト指向習得のための5ステップ【SOLID原則】
3. テスト駆動開発による組み込みプログラミング―C言語とオブジェク
ト指向で学ぶアジャイルな設計
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
59
ご清聴ありがとうございました
【連続講座】ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則
60

More Related Content

Similar to ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則.pdf

テストからより良い組込みソフトウェア開発を考える.pdf
テストからより良い組込みソフトウェア開発を考える.pdfテストからより良い組込みソフトウェア開発を考える.pdf
テストからより良い組込みソフトウェア開発を考える.pdf耕二 阿部
 
Java仮想マシンの実装技術
Java仮想マシンの実装技術Java仮想マシンの実装技術
Java仮想マシンの実装技術Kiyokuni Kawachiya
 
メタな感じのプログラミング(プロ生 + わんくま 071118)
メタな感じのプログラミング(プロ生 + わんくま 071118)メタな感じのプログラミング(プロ生 + わんくま 071118)
メタな感じのプログラミング(プロ生 + わんくま 071118)Tatsuya Ishikawa
 
Lambda: A Peek Under The Hood [Java Day Tokyo 2015 6-3]
Lambda: A Peek Under The Hood [Java Day Tokyo 2015 6-3]Lambda: A Peek Under The Hood [Java Day Tokyo 2015 6-3]
Lambda: A Peek Under The Hood [Java Day Tokyo 2015 6-3]David Buck
 
第4回勉強会 単体テストのすすめ
第4回勉強会 単体テストのすすめ第4回勉強会 単体テストのすすめ
第4回勉強会 単体テストのすすめhakoika-itwg
 
はこだてIKA 第4回勉強会 単体テスト
はこだてIKA 第4回勉強会 単体テストはこだてIKA 第4回勉強会 単体テスト
はこだてIKA 第4回勉強会 単体テストSeiji KOMATSU
 
Introduction to JShell #JavaDayTokyo #jdt_jshell
Introduction to JShell #JavaDayTokyo #jdt_jshellIntroduction to JShell #JavaDayTokyo #jdt_jshell
Introduction to JShell #JavaDayTokyo #jdt_jshellbitter_fox
 
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行gree_tech
 
Pythonによる機械学習入門 ~Deep Learningに挑戦~
Pythonによる機械学習入門 ~Deep Learningに挑戦~Pythonによる機械学習入門 ~Deep Learningに挑戦~
Pythonによる機械学習入門 ~Deep Learningに挑戦~Yasutomo Kawanishi
 
C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?Shinichi Hirauchi
 
初めてのPadrino
初めてのPadrino初めてのPadrino
初めてのPadrinoTakeshi Yabe
 
ソフトウェアエンジニアのための「機械学習理論」入門・ハンズオン演習ガイド
 ソフトウェアエンジニアのための「機械学習理論」入門・ハンズオン演習ガイド ソフトウェアエンジニアのための「機械学習理論」入門・ハンズオン演習ガイド
ソフトウェアエンジニアのための「機械学習理論」入門・ハンズオン演習ガイドEtsuji Nakai
 
PF開発に使えるAOSPのツール達
PF開発に使えるAOSPのツール達PF開発に使えるAOSPのツール達
PF開発に使えるAOSPのツール達l_b__
 
OpenMDAOの最適化を試す(第23回オープンCAE勉強会@関西)
OpenMDAOの最適化を試す(第23回オープンCAE勉強会@関西)OpenMDAOの最適化を試す(第23回オープンCAE勉強会@関西)
OpenMDAOの最適化を試す(第23回オープンCAE勉強会@関西)TatsuyaKatayama
 
JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type Confusion)
JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type Confusion)JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type Confusion)
JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type Confusion)JPCERT Coordination Center
 
10分でわかるFuelPHP @ 2011/12
10分でわかるFuelPHP @ 2011/1210分でわかるFuelPHP @ 2011/12
10分でわかるFuelPHP @ 2011/12kenjis
 
はじめてのCodeIgniter
はじめてのCodeIgniterはじめてのCodeIgniter
はじめてのCodeIgniterYuya Matsushima
 
あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)Takuya Tsuchida
 

Similar to ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則.pdf (20)

Tokyo r30 beginner
Tokyo r30 beginnerTokyo r30 beginner
Tokyo r30 beginner
 
テストからより良い組込みソフトウェア開発を考える.pdf
テストからより良い組込みソフトウェア開発を考える.pdfテストからより良い組込みソフトウェア開発を考える.pdf
テストからより良い組込みソフトウェア開発を考える.pdf
 
Java仮想マシンの実装技術
Java仮想マシンの実装技術Java仮想マシンの実装技術
Java仮想マシンの実装技術
 
メタな感じのプログラミング(プロ生 + わんくま 071118)
メタな感じのプログラミング(プロ生 + わんくま 071118)メタな感じのプログラミング(プロ生 + わんくま 071118)
メタな感じのプログラミング(プロ生 + わんくま 071118)
 
Lambda: A Peek Under The Hood [Java Day Tokyo 2015 6-3]
Lambda: A Peek Under The Hood [Java Day Tokyo 2015 6-3]Lambda: A Peek Under The Hood [Java Day Tokyo 2015 6-3]
Lambda: A Peek Under The Hood [Java Day Tokyo 2015 6-3]
 
第4回勉強会 単体テストのすすめ
第4回勉強会 単体テストのすすめ第4回勉強会 単体テストのすすめ
第4回勉強会 単体テストのすすめ
 
はこだてIKA 第4回勉強会 単体テスト
はこだてIKA 第4回勉強会 単体テストはこだてIKA 第4回勉強会 単体テスト
はこだてIKA 第4回勉強会 単体テスト
 
Introduction to JShell #JavaDayTokyo #jdt_jshell
Introduction to JShell #JavaDayTokyo #jdt_jshellIntroduction to JShell #JavaDayTokyo #jdt_jshell
Introduction to JShell #JavaDayTokyo #jdt_jshell
 
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
 
Pythonによる機械学習入門 ~Deep Learningに挑戦~
Pythonによる機械学習入門 ~Deep Learningに挑戦~Pythonによる機械学習入門 ~Deep Learningに挑戦~
Pythonによる機械学習入門 ~Deep Learningに挑戦~
 
C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?
 
Introduction of Python
Introduction of PythonIntroduction of Python
Introduction of Python
 
初めてのPadrino
初めてのPadrino初めてのPadrino
初めてのPadrino
 
ソフトウェアエンジニアのための「機械学習理論」入門・ハンズオン演習ガイド
 ソフトウェアエンジニアのための「機械学習理論」入門・ハンズオン演習ガイド ソフトウェアエンジニアのための「機械学習理論」入門・ハンズオン演習ガイド
ソフトウェアエンジニアのための「機械学習理論」入門・ハンズオン演習ガイド
 
PF開発に使えるAOSPのツール達
PF開発に使えるAOSPのツール達PF開発に使えるAOSPのツール達
PF開発に使えるAOSPのツール達
 
OpenMDAOの最適化を試す(第23回オープンCAE勉強会@関西)
OpenMDAOの最適化を試す(第23回オープンCAE勉強会@関西)OpenMDAOの最適化を試す(第23回オープンCAE勉強会@関西)
OpenMDAOの最適化を試す(第23回オープンCAE勉強会@関西)
 
JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type Confusion)
JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type Confusion)JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type Confusion)
JRE標準ライブラリの脆弱性事例を理解する (AtomicReferenceArrayクラス と Type Confusion)
 
10分でわかるFuelPHP @ 2011/12
10分でわかるFuelPHP @ 2011/1210分でわかるFuelPHP @ 2011/12
10分でわかるFuelPHP @ 2011/12
 
はじめてのCodeIgniter
はじめてのCodeIgniterはじめてのCodeIgniter
はじめてのCodeIgniter
 
あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)
 

More from 耕二 阿部

猫の日開催!ねこIoTLT vol.9(Spresense猫モーラー🐈)_20240222
猫の日開催!ねこIoTLT vol.9(Spresense猫モーラー🐈)_20240222猫の日開催!ねこIoTLT vol.9(Spresense猫モーラー🐈)_20240222
猫の日開催!ねこIoTLT vol.9(Spresense猫モーラー🐈)_20240222耕二 阿部
 
SWEST25_EmbLT_NervesとSpresenseをHostIFで通信してみた.pdf
SWEST25_EmbLT_NervesとSpresenseをHostIFで通信してみた.pdfSWEST25_EmbLT_NervesとSpresenseをHostIFで通信してみた.pdf
SWEST25_EmbLT_NervesとSpresenseをHostIFで通信してみた.pdf耕二 阿部
 
20210830 rust入学式
20210830 rust入学式20210830 rust入学式
20210830 rust入学式耕二 阿部
 
Arduinoでモーター制御ロジックを実装した話
Arduinoでモーター制御ロジックを実装した話Arduinoでモーター制御ロジックを実装した話
Arduinoでモーター制御ロジックを実装した話耕二 阿部
 
Rust初心者がArduinoをLチカしてみた
Rust初心者がArduinoをLチカしてみたRust初心者がArduinoをLチカしてみた
Rust初心者がArduinoをLチカしてみた耕二 阿部
 
はじめてのブラシレスモータ制御
はじめてのブラシレスモータ制御はじめてのブラシレスモータ制御
はじめてのブラシレスモータ制御耕二 阿部
 
20201029 モデルベース開発モーター制御編~C言語とSimulinkの文法記述を比較する~
20201029 モデルベース開発モーター制御編~C言語とSimulinkの文法記述を比較する~20201029 モデルベース開発モーター制御編~C言語とSimulinkの文法記述を比較する~
20201029 モデルベース開発モーター制御編~C言語とSimulinkの文法記述を比較する~耕二 阿部
 
モデルベース開発勉強会
モデルベース開発勉強会モデルベース開発勉強会
モデルベース開発勉強会耕二 阿部
 
EVミニカート、技術交流&ミニセミナ 発表資料
EVミニカート、技術交流&ミニセミナ 発表資料EVミニカート、技術交流&ミニセミナ 発表資料
EVミニカート、技術交流&ミニセミナ 発表資料耕二 阿部
 
AWSとEVカートで走行データを可視化
AWSとEVカートで走行データを可視化AWSとEVカートで走行データを可視化
AWSとEVカートで走行データを可視化耕二 阿部
 

More from 耕二 阿部 (10)

猫の日開催!ねこIoTLT vol.9(Spresense猫モーラー🐈)_20240222
猫の日開催!ねこIoTLT vol.9(Spresense猫モーラー🐈)_20240222猫の日開催!ねこIoTLT vol.9(Spresense猫モーラー🐈)_20240222
猫の日開催!ねこIoTLT vol.9(Spresense猫モーラー🐈)_20240222
 
SWEST25_EmbLT_NervesとSpresenseをHostIFで通信してみた.pdf
SWEST25_EmbLT_NervesとSpresenseをHostIFで通信してみた.pdfSWEST25_EmbLT_NervesとSpresenseをHostIFで通信してみた.pdf
SWEST25_EmbLT_NervesとSpresenseをHostIFで通信してみた.pdf
 
20210830 rust入学式
20210830 rust入学式20210830 rust入学式
20210830 rust入学式
 
Arduinoでモーター制御ロジックを実装した話
Arduinoでモーター制御ロジックを実装した話Arduinoでモーター制御ロジックを実装した話
Arduinoでモーター制御ロジックを実装した話
 
Rust初心者がArduinoをLチカしてみた
Rust初心者がArduinoをLチカしてみたRust初心者がArduinoをLチカしてみた
Rust初心者がArduinoをLチカしてみた
 
はじめてのブラシレスモータ制御
はじめてのブラシレスモータ制御はじめてのブラシレスモータ制御
はじめてのブラシレスモータ制御
 
20201029 モデルベース開発モーター制御編~C言語とSimulinkの文法記述を比較する~
20201029 モデルベース開発モーター制御編~C言語とSimulinkの文法記述を比較する~20201029 モデルベース開発モーター制御編~C言語とSimulinkの文法記述を比較する~
20201029 モデルベース開発モーター制御編~C言語とSimulinkの文法記述を比較する~
 
モデルベース開発勉強会
モデルベース開発勉強会モデルベース開発勉強会
モデルベース開発勉強会
 
EVミニカート、技術交流&ミニセミナ 発表資料
EVミニカート、技術交流&ミニセミナ 発表資料EVミニカート、技術交流&ミニセミナ 発表資料
EVミニカート、技術交流&ミニセミナ 発表資料
 
AWSとEVカートで走行データを可視化
AWSとEVカートで走行データを可視化AWSとEVカートで走行データを可視化
AWSとEVカートで走行データを可視化
 

ソフトウェア設計原則【SOLID】を学ぶ #4 開放閉鎖の原則.pdf