衛星開発ゼミ
WEEK 7
ソフトウェア
エンジニアリング
良いソフトウェア設計とは、
変更を安全かつ高速に回せる構造を作ることである
軸①設計:責務を分け、依存先を実装からインターフェースへ移す
軸②検証:PC 上で動かし、Unit Test・TDD・SILS で確かめる
軸③統合:小さな変更に、自動チェックとレビューをフィードバック
アストロキャンプ2026 / 衛星開発ゼミ
0.1 前回の講義から
完成形を一度で設計せず、検証できる小さな単位から始める
前回の宿題(再掲)
模擬衛星の初回打ち上げに必要な機能を考える
- 完成形の設計は、一度では決まらない。要求から具体的な設計を一足飛びには導けない。作ってみて初めて分かることがある。
- まず、検証できる小さな範囲を切り出す。到達点まで全部を作るのではなく、今日作って結果を観測できる単位まで小さくする。
- 小さく作り、小さく確かめる。設計 → 実装 → 試験 → 観測を一周させる。
- 分かったことを、次の設計へ戻す。一周で得た知見を使って、次の一周を決める。
今日学ぶのは、ソフトウェア開発でこのサイクルを小さく・速く・安全に回すための技術。
Week 7|ソフトウェアエンジニアリング2
1
なぜソフトウェアエンジニアリングが必要か
ソフトウェア開発では、変更と学習を繰り返す。
衛星では打ち上げ前に、そのサイクルをできるだけ高速に回しておく必要がある。
1.1設計は一度では決まらない設計そのものが動き、変更コストも物理に縛られないので、改善し続けられる
1.2実機では何度も試せない確かめたいことのすべてを、実機で繰り返し試すことはできない
1.3–1.4何度でも試せる場所を作る実機より速く、何度でも試せる場所をソフトウェアの構造として用意する
1.1 ソフトウェアは変更され続ける
設計は一度では決まらない。そしてソフトウェアは、それを前提に作れる
システム開発一般
実装して初めて分かることがある
責務の切り方、依存の向き、必要な情報などは、書いて動かして初めて見える
ソフトウェア固有
設計そのものが動く
コードは設計書と製品が同一物。製造工程がないので、設計をそのまま実行して確かめられる
ソフトウェア固有
変更コストが物理に縛られない
複製・巻き戻し・やり直しが安い。同じ検証を何度でも繰り返せる
だから
重要なのは、最初から完璧に設計することではなく、設計を速く安全に改善できること
Week 7|ソフトウェアエンジニアリング4
1.2 実機で何度も試すことはできない
衛星では、確かめたいことのすべてを実機で何度も試すことはできない
開発中は自由回転させられない。Week 6 の運用ルール。ベアリングで自由回転させるのは打ち上げの中だけ
軌道上と同じ条件を地上で完全には再現できない。実衛星も同じで、打ち上げ前に作り込むしかない
実物での試行錯誤には制約がある。試せる回数・条件・機体への負荷が限られる
具体例:姿勢制御。開発中は機体を固定し、自由回転はさせない
設計を何度も改善するにはフィードバックが必要。しかし、そのフィードバックを毎回実機から得ることはできない。
Week 7|ソフトウェアエンジニアリング5
1.3 フィードバックは手前の段から返す
広く・現実に近いことを確かめるほど、1周は遅くなり試せる回数も限られる。だから、手前の段で確かめられることは手前の段で確かめる
確かめる場所1周にかかる時間要るもの
静的解析秒未満コードだけ
Unit Test秒PC だけ
SILS秒〜分PC + 機体モデル
HILS分〜時間実物の一部(マイコン・ホイール)
実機統合試験時間〜日機体一式と人の立ち会い
打ち上げ一度きり・やり直せない本番の機会そのもの
さらに、人間が毎回手で実行・目視していては高速には回らない。手前の段の検証は、繰り返し実行できる形にする。
実機依存と人手依存の両方を減らす。青い3段を自分で作るのが今日の目標
Week 7|ソフトウェアエンジニアリング6
1.4 今日学ぶことの全体像
どうすれば、変更の結果をもっと早く確かめられるか
実機では何度も試せない → 何度でも試せる検証環境を地上に作る必要がある → そのために、設計・テスト・SILS・CI・構成管理を学ぶ
設計
2章 変更に強い構造責務・凝集度・結合度・情報隠蔽・インターフェース
検証
3章 テスト可能性Unit Test
4章 小さく直すTDD・Refactoring
5章 全体を試すMBD・SILS
統合と再現
6–7章 小さく統合GitHub Flow・Review・CI
8章 再現できる構成管理・Release
AI と人間AI は設計・実装・検証環境まで作ってよい(設計案・実装・テスト・SILS・CI の設定まで)。
人間は Evidence の十分性・独立性と Risk を見て Accept / Revise / Reject を決め、最終的な mission acceptance の責任を持つ。
すべて、変更→実行→観測→修正のループを短くし、変更を安全にするために必要になる
Week 7|ソフトウェアエンジニアリング7
第1章 なぜソフトウェアエンジニアリングが必要か|1.5 この章のまとめ:ここは覚えて次へ
実機のフィードバックは遅く、試せる回数も限られる。だから、地上に速く何度でも確かめられる場所を作る。
①設計は一度では決まらない実装して初めて分かることがある。ソフトウェアは設計そのものが動き、変更コストも物理に縛られない
②実機では何度も試せない試せる回数と条件に制約があり、軌道上と同条件の地上試験もできない
③確かめる場所を手前の段へ移す静的解析は秒未満、Unit Test は秒、SILS は秒〜分、実機統合試験は時間〜日。手前で確かめられることは手前で確かめ、繰り返し実行できる形にする
次章へ手前の段で確かめるには、まずコードの構造がそれを許す形になっていなければならない
Week 7|ソフトウェアエンジニアリング8
2
変更に強いソフトウェアを設計する
一つの変更がどこまで波及するかは、設計で決まる。責務を分け、変わりやすい判断を隠し、依存先を実装からインターフェースへ移す。
2.1 困る具体例:センサ直書きのコード
メインループでベタ書きすると、役割の違うコードが同じ場所に混ざる
// 直書きの例:判断ロジックとハード操作は違う役割while (true) { double sun_angle = read_sun_angle(); // ← ここで実機の ADC に直接触っている if (sun_angle > kThreshold) { set_wheel_command_us(1600); // ← ここで実機のサーボに直接触っている }}
read_sun_angle() が実機の ADC を直に叩くため、ADC が無い PC では動かない
「太陽方向で回転を決める」という判断ロジックだけを取り出せない
Week 7|ソフトウェアエンジニアリング10
2.2 なぜ困るのか:依存と結合度
依存が多く深いほど、変更は広く波及する
依存
A が B に依存する=B の変更が A に波及しうる
必要な依存はある。減らしたいのは、相手の内部まで知っているという不要な依存
結合度
依存先が多く、相手の内部を深く知るほど高結合
直書きコードの場合(高結合)
判断が、センサの読み出し手順や生の値の形式まで知っている。センサ側の小さな変更が判断に波及し、判断だけを取り出して試せない
この章の方針
部品どうしは不要な依存を減らし(低結合)、部品の内側は同じ責務でまとめる(高凝集)
Week 7|ソフトウェアエンジニアリング11
2.3 情報隠蔽:変わりやすい判断を隠す
独立して変更されそうな設計判断を、モジュールの内側に隠す
独立して変更されそうな判断を隠す。ADC の分解能、配線、電圧から角度への変換式。他の部分と関係なく変わりうる判断
外に見せるのは約束だけ。太陽方向を返す、という一行だけを公開する
隠せた範囲が、変更で読み直さなくてよい範囲になる。漏れていれば、呼び出し側すべてが変更の対象になる
公開する約束read_sun_angle() : double
モジュールの内側に隠す判断
ADC のチャンネル割り当て分解能と基準電圧電圧→角度の変換式平滑化の方法校正値(calibration)
ここが変わっても、判断ロジック側は書き換えなくてよい
Week 7|ソフトウェアエンジニアリング12
2.4 分離の道具:依存の相手を実装からインターフェースへ
依存の相手を、具体的な「実装」から「インターフェース(守るべき取り決め)」に変えると、中身を差し替えられる
いま:実装に直接依存する
これから:インターフェースにだけ依存する
この間接化は言語を選ばない(C では関数ポインタでも作れる)。今回は C++ のクラスを道具に使う
Week 7|ソフトウェアエンジニアリング13
INFO 索引:Interface を C++ で実現する手段の一つ(必要になったときに引く)
C++ では、クラス+virtual が差し替えを実現する方法の一つ
クラス。データと操作を1つの部品にまとめる。窓口も実装もクラスで表す
仮想関数(virtual)。同じ呼び出しで、実機と模擬実装のどちらが動くかを実行時に切り替える
設計思想と実現手段は別。Interface は設計の考え方、virtual はその実現手段の一つ(テンプレートや関数ポインタなど他の手段もある)。文法の細部は必要になったときに引けばよい
Week 7|ソフトウェアエンジニアリング14
2.5 実機センサでも模擬センサでも、同じ判断ロジックが動く
判断を「太陽方向を返す何か」に依存させ、実機と模擬実装(Test Double)を差し替える
// 判断は「太陽方向を返す窓口」にだけ依存するclass ISunSensor { // 窓口(インターフェース)public: // 「太陽方向を返す」とだけ約束する virtual double read_sun_angle() = 0;}; // 実機:ADC を叩くclass RealSunSensor : public ISunSensor { double read_sun_angle() override;};// 模擬実装(Test Double):決めた値を返すclass MockSunSensor : public ISunSensor { double read_sun_angle() override;};
判断ロジック戻り値だけを見る(ADC の存在を知らない)
ISunSensor(窓口)
↑ どちらかを差し込む ↑
Real…実機:ADC を叩く
Mock…模擬実装:決めた値を返す
PC のテストでは模擬実装に決めた角度を入れて判断を確かめる
Week 7|ソフトウェアエンジニアリング15
第2章 変更に強いソフトウェアを設計する|2.6 この章のまとめ:ここは覚えて次へ
良い分離は、変更の影響範囲と試験の範囲を小さくする。
①部品の内側は高凝集、部品どうしは低結合責務で分け、変わりやすい判断は情報隠蔽でモジュールの内側に置いた
②依存の相手を実装からインターフェースへ変えたインターフェースに依存させたので、実機センサと模擬センサを差し替えられる
次章へPC 上でロジックを動かせるようになった → 次は入力と出力を与えて自動で確かめる
Week 7|ソフトウェアエンジニアリング16
3
テストできることは設計品質である
分離した結果、判断ロジックはPC上で動く。入力と出力を与えられるなら、その振る舞いは自動で確認できる。
3.1入力と出力を与える模擬実装で入力を決め、出力をコードで確かめる
3.2Testability は設計の性質テストしにくさは、書き方ではなく設計の問題
3.3–3.4何をどこまで試すか同値分割・境界値分析と、Coverage の読み方
3.1 Unit Test:確認する作業をコードにする
入力を決められて出力を読めるなら、その振る舞いは自動で確認できる
// 明るい側ではホイールを回す、という期待を書くTEST(SunPointing, TurnsWheelWhenBright) { MockSunSensor sun(30.0); // 入力を決める SunPointingLogic logic(&sun); auto cmd = logic.step(); // 出力を受け取る EXPECT_EQ(cmd.wheel_us, 1600);}
入力は模擬センサで決める。MockSunSensor に角度を持たせるだけで、実機の ADC は不要
出力は戻り値で読む。ホイールへの指示が値として返るので、期待と機械的に比べられる
Test Double(模擬実装)。決めた値を返すもの、簡易な実装を持つものなどの総称。配布テンプレートでは MockSunSensor という名前で用意している
確認が資産になる。一度書けば、変更のたびに同じ確認を同じ手順で繰り返せる
Week 7|ソフトウェアエンジニアリング18
3.2 Testability:テストしやすさは設計品質
Testability はテスト担当者の都合ではなく、ソフトウェア設計そのものの性質である
Testability の中心は3つ入力を決められる初期状態と入力を思いどおりに与えられる(Controllability)
結果を見られる必要な出力と状態を外から観測できる(Observability)
同じ条件を再現できる同じ条件なら同じ結果になる(Repeatability)
PC 上で動かせることは、この3つを手軽に実現する有力な手段。Testability = PC で動くこと ではない
テストしにくいコード
×ハードウェア入出力と判断が同じ関数に同居している
×時刻・乱数・通信の応答で結果が変わる
×結果が内部状態にしか現れず、外から読めない
×確かめるには実機を用意して人が見るしかない
テストしやすいコード
○ハードウェア入出力などの副作用を、境界の外へ追い出している
○同じ初期状態と入力列なら、同じ結果を再現できる
○入力は引数、結果は戻り値として外から読める
○模擬センサを差し込めば PC 上で完結する
テストが書きにくいときは、テストの書き方ではなく設計を疑う
Week 7|ソフトウェアエンジニアリング19
3.3 何をテストするか:同値分割と境界値分析
入力は、同値分割で代表を選び、境界値で誤りの出やすい点を突く
同値分割。同じ振る舞いになる入力のまとまりから、代表を1つずつ選ぶ
境界値分析。しきい値のちょうど・直前・直後を突く。比較の向きの誤りはここで出る
異常系も1つは書く。「30°なら1600を返す」だけでなく、センサ更新が止まったら(timeout・stale data)どう振る舞うか。範囲外値・NaN・アクチュエータ飽和も同じ形で期待を書ける
Week 7|ソフトウェアエンジニアリング20
3.4 Coverage の読み方と、テストが言えること
Coverage が高いだけでは正しさは言えない。見えるのは「どこまで試したか」
言えること試した範囲が見える実行された命令や分岐の割合が出る。命令網羅(C0)・分岐網羅(C1)という段階がある
言えないこと正しさは出てこない試していない入力には何も言えない。期待値そのものが間違っていれば緑になる
使い方薄い場所を探す道具数値を上げる目標ではなく、確認が届いていない箇所を見つけるために読む
テストが積み上げるもの。定義した期待動作を継続的に確認できること、そして変更で壊れたこと(Regression)を早く検出できること
テストが積み上げないもの。そのテストが対象にしていない性質、そしてシステム要求そのものの妥当性(→ Systems Engineering の回)
Week 7|ソフトウェアエンジニアリング21
INFO 発展:テストの感度を確かめる(Mutation Testing)
意図的に壊して赤になるかを見ると、何も見ていないテストを見つけられる
STEP 1テストが緑で通っているただし、これだけでは「甘くて何も見ていない」場合と区別できない
STEP 2対象をわざと1か所壊すWeek 3 の「わざと壊して壊れ方を観測する」のテスト版
STEP 3テストが赤くなるその壊し方には反応する、という確認
言えるのは「その壊し方には反応する」まで。それでも、何も見ていないテストは見つかる
Week 7|ソフトウェアエンジニアリング22
第3章 テストできることは設計品質である|3.5 この章のまとめ:ここは覚えて次へ
テストできること自体が、ソフトウェア設計の品質である。
①確認する作業をコードにした入力を決められて出力を読めるなら、その振る舞いは自動で確かめられる(Unit Test)
②テストしやすさは設計の性質入力を決められる(Controllability)結果を見られる(Observability)
同じ条件を再現できる(Repeatability)
③Coverage は物差しであって保証ではない分かるのはどこまで試したか。積み上がるのは継続的に確認できるという根拠
次章へ数秒で確認が返るなら、設計を小刻みに直しても壊さずに済む
Week 7|ソフトウェアエンジニアリング23
4
小さく設計し、小さく直す
テストが数秒で返るなら、設計・実装・検証を非常に小さな単位で往復できる。最初から完璧な設計は要らない。
4.1赤→緑→リファクタ期待を先に置き、1周を数分の単位で回す
4.2なぜ小さく往復するのか外した場所を直前の一歩に閉じ込める
4.3Refactoring振る舞いを変えずに内部設計を改善する
4.1 TDD:期待を先に置き、実装と設計を小さく往復する
次の一歩を、検証できる大きさまで小さくする
大きく作ってから確かめる進め方
まとめて実装する
まとめてテストする
問題が出たら広く切り分ける
・一度に足した分がまとまって効くので、外した場所の候補が広がる
・自動テストの有無ではなく、1回のフィードバックが受け持つ範囲の大きさが違う
TDD:小さく往復する
赤
次の期待を1つ書く。まだ満たされていないため、意図どおり失敗することを確認する
緑
最小限で通す。
リファ
クタ
確認してから Refactor し、次へ。次のテストへ戻り、1周を繰り返す。確認はコードとして残り続ける
Week 7|ソフトウェアエンジニアリング25
4.2 なぜ小さく往復するのか
設計と実装と検証を、非常に小さな単位で往復する開発の進め方
大きく作ってから確かめる外した場所の切り分けが広くなる変更がまとまっていると、どこが原因かを切り分ける範囲が広がり、手戻りも広がりやすい
小さく往復する原因の探索範囲を狭めやすい赤になった時点で、原因の探索範囲を直前の変更周辺に狭めやすい。手戻りも局所化しやすい
1周は数分、振る舞い1つ。大きく作ってから確かめるのではなく、確かめられる大きさに設計を刻む
先に書く理由は2つ。期待をコードで表してから実装に入り、その期待がまだ満たされていないことを Red で確認する
言い過ぎない。テストは要求仕様そのものではない。テスト対象となる振る舞いの一部を、実行できる例として表したもの
Week 7|ソフトウェアエンジニアリング26
4.3 Refactoring:振る舞いを変えずに内部を改善する
外部から見える振る舞いを変えずに、内部設計を改善する
意図は内部構造の改善。外部から見える振る舞いを変えずに内部を改善する。緑が崩れたら、それは Refactoring ではなく変更
Green は Evidence の一つ。Green なら、少なくともそのテストが観測している振る舞いについて Regression は見つかっていない。それを数秒で得ながら構造を変えられる
やることは小さい。名前を直す、重複を抜く、責務を分ける、窓口を切り出す
固定される外から見える振る舞いテストが表している入出力。ここは動かさない
自由に変えられる内部の構造責務の切り方、関数の分け方、名前、データの持ち方
最初から完璧なアーキテクチャを設計する必要はない。小さく作り、確かめ、学び、設計を改善する。
Week 7|ソフトウェアエンジニアリング27
第4章 小さく設計し、小さく直す|4.4 この章のまとめ:ここは覚えて次へ
小さく確かめられるから、設計は後から安全に改善できる。
①一歩を、確かめられる大きさまで小さくする期待を1つ書いて意図どおり赤になるのを見て、通す最小限で緑にし、緑のまま整えてから次へ進む(TDD)。赤が出た時点で、原因は直前の一歩の周辺に絞られる
②Refactoring は振る舞いを変えない改善Green は、テストが観測している範囲で Regression が見つかっていないという Evidence。変えるたびにテストを走らせ、その Evidence を確かめながら構造を良くする
次章へUnit Test で確かめたのは部品単体の入出力だけ。部品を全部つないで動かしたときの振る舞いはまだ分からない
Week 7|ソフトウェアエンジニアリング28
5
実機なしでシステム全体を試す
Unit Test で確かめたのは部品単体まで。次は、部品を全部つないで動かしたときの振る舞いを確かめる。実機の代わりに、実行できるモデルの中で制御ループを閉じる。
5.1検証の階層Unit / Integration → SILS → Target → HILS → 実機
5.2–5.4実行できるモデルと SILSモデルを実行し、その中に実際のフライトロジックを接続する。用語より、実機を使わず何度も回せることが本質
5.5–5.6モデルと実機のずれパラメータは実機で測り、残ったずれはテレメトリで直す
5.1 Unit Test だけでは、衛星全体の振る舞いは分からない
段を上げるほど範囲は広がる。段ごとに得られる Evidence の種類が違う
段その段で得られる Evidenceその段では得られないもの
静的解析動かさずに分かる危ない書き方実際の振る舞い
Unit TestHost(PC)上部品単体の入出力が期待どおりか局所化と再現性。数秒で返る部品どうしをつないだときの振る舞い
Integration TestHost(PC)上複数部品の接続が成立しているか例:SunSensor 実装と判断ロジックをつなぎ、値が正しく渡るか機体が実際にどう動くか
SILS制御ループ全体の振る舞い(姿勢が収まるか)モデルと実機のずれ・target 固有の性質
Target 試験On-target Test実 CPU・compiler / ABI・RTOS 上での timing / deadlineinterrupt・scheduling・CPU load・memory / stack・queue・bus 帯域。PC 上では再現しにくい実ハードとの interface・実環境
HILS実ハードとの interface、タイミングや応答軌道上・自由回転の環境
実機統合試験実ハード全体の統合挙動軌道環境・自由回転などは残る
打ち上げ・運用実際の環境での振る舞いやり直しが極めて困難
手前の段で確かめられる性質は、その中で最も信頼できる段で早く潰す。ただし、その段でしか得られない Evidence は省略しない
Week 7|ソフトウェアエンジニアリング30
5.2 実行できるモデルで設計を試す(この講義での MBD の扱い)
対象の振る舞いをモデルにすると、設計を実行して比べられる
モデルとは。機体の運動や機器の応答を、数式とコードで表したもの
実行できることの意味。設計案を回して結果を比べられる。紙の上の議論が観測に変わる
押さえるのはここ。実行できるモデルを使えば、変更→実行→観測→修正を実機を使わずに何度も回せる。覚えるのは用語ではなくこの効果
この講義での MBD実行可能なモデルを設計・検証に使う考え方として紹介するMBD の全体系はこの講義では扱わない
SILS(構成の一つ)モデル環境に実際のフライトロジックを接続して検証するPC 上の仮想的なセンサ・アクチュエータ・機体モデルへつなぐ。SILS は MBD を採用していなくても構築できる
Week 7|ソフトウェアエンジニアリング31
5.3 SILS の構造:Plant(物理モデル)と Controller(フライトロジック)
機体の物理を模す Plant と、判断を担う Controller を分け、PC 上でループさせる
Controller。センサ値を受けて、モータへの指示を決める(実機に載る頭脳)
Plant。モータ指示を受けて、機体の回転と次のセンサ値を計算する(実機の代わり)
2章の分離が効く。同じ Controller を、実機にも SILS にも差し替えるだけで載せられる
Week 7|ソフトウェアエンジニアリング32
5.4 SILS が成立するのは、分離してあるから
SILS が作れるのは、フライトロジックがハードウェアから分離されているからである
低結合・高凝集
インターフェースで依存を切る
ハードウェアを差し替えられる
ロジックが PC 上で実行できる
SILS が成立する
差し込む先は同じ窓口。Unit Test の模擬センサと、SILS の Plant は、同じインターフェースの向こうに入る
Controller は書き換えない。同じフライトロジック、可能なら同じ source を SILS でも使うことで、実機へ近いロジックを地上で検証できる
逆も真。ハードウェア依存が分離されているほど、Unit Test や SILS を小さく・局所的に構築しやすい。設計が検証環境の前提になっている
Week 7|ソフトウェアエンジニアリング33
5.5 モデルは現実そのものではない
測れる値は実測し、残った差を観測してモデルを更新する
実測値と仮定値を区別する
実測しないと決まらない値
機体とホイールの慣性
指令→トルクの換算
軸受の摩擦
正しい数は運営からは渡らない。各チームの機体の中にしかない
仮定として置く値
摩擦モデルの形、無視する外乱、時間の刻み方。置いた仮定はそのまま残差になる
残った差はテレメトリに現れる
SILS の予測:こう動くはず
↓
打ち上げのテレメトリ:実際はこう動いた
↓
差を見てモデルを直す
ずれは失敗ではなく前提。Week 6 の観測設計は、モデルを直す材料でもある
Week 7|ソフトウェアエンジニアリング34
第5章 実機なしでシステム全体を試す|5.6 この章のまとめ:ここは覚えて次へ
分離してあるから、同じフライトロジックを PC 上のモデルの中でも回せる。
①確かめたい性質に応じて、最も手前で信頼できる段を選ぶUnit / Integration → SILS → Target → HILS → 実機。段ごとに得られる Evidence の種類が違い、その段でしか得られない Evidence は省略しない
②Plant と Controller でループを閉じる同じフライトロジック(可能なら同じ source)を Host(PC)上で回して姿勢制御を作り込める。compiler・ABI・RTOS・timing の差は Target 試験で確かめる
③モデルは現実そのものではない実測しないと決まらない数(慣性・換算・摩擦)は測る。残ったずれは打ち上げのテレメトリで更新する
次章へ1人で変更→検証を速く回せるようになった。次は、その小さな変更をチームで壊さず合流させる
Week 7|ソフトウェアエンジニアリング35
6
変更を小さく統合する
1人で速く回せるようになった変更を、チームで壊さず合流させる。ここでの「小さく」は設計の話ではなく、一度に持ち込む変更量の話。
6.1GitHub Flow とはmain を動く状態に保ち、短命な枝と Pull Request で変更を戻す型
6.2小さく保つ短命なブランチと小さな commit。長く育てた枝は統合が難しくなる
6.3差分にフィードバックPull Request で単位を示し、Code Review で差分を読む
INFO 用語の整理:バージョン管理・Git・GitHub
バージョン管理は変更の履歴を残し、どの時点へも戻れるようにする仕組み
バージョン管理考え方。変更を履歴として記録し、いつでも過去の時点へ戻れるようにする
Git道具。履歴とブランチを扱う。Week 0 で「作業を戻せる場所を作る道具」と位置づけたもの
GitHub置き場。Git の履歴をチームで共有する場所。Pull Request などの共同作業の仕組みが載る
Week 7|ソフトウェアエンジニアリング37
6.1 GitHub Flow とは:一般的なチーム開発の型
main を常に動く状態に保ち、変更は短命な枝で作って Pull Request で戻す
1branch を切るmain から枝分かれ。何をする枝か分かる名前を付ける
→
2commit する変更を小さく刻んで、意図ごとに履歴へ残す
→
3Pull Request を開くこの差分を main に入れたい、という単位を示す
→
4Review と自動チェック人が差分を読み、機械がビルドとテストを走らせる
→
5merge して枝を消すmain へ入れたら枝は捨てる。次の変更はまた main から
枝は main からだけ生える。長期の develop や release ブランチを並走させない。履歴の中心は常に一本の main である
main は壊さない、が唯一の約束。main はいつ取り出しても動く状態に保つ。だから確認は merge の前、Pull Request の上で済ませる
Week 7|ソフトウェアエンジニアリング38
6.2 二つ目の「小さく」:一度に持ち込む変更量
長く育てた巨大なブランチは統合が難しくなる。変更は小さく刻んで持ち込む
ブランチは作業単位の器。main(最新の統合基準線)から枝分かれさせた独立の作業場。ここでの「小さく」は2章の影響範囲ではなく、一度に持ち込む変更量の話
短命に保つ。長く生きた枝は他の変更と衝突し、差分が大きすぎて読めない。統合そのものが難しくなる
commit も小さく。1コミット1つの意図。何をしたかが履歴で読めて、戻す単位にもなる
Week 7|ソフトウェアエンジニアリング39
6.3 Pull Request と Code Review
PR は単なる関所ではない。変更単位を明示し、差分へフィードバックを集める場所である
PR は提案である。この差分を main に入れたい、という単位の明示。何を変えたかが1画面に収まる
Review は別視点からの指摘である。変更に対して問題・懸念・改善案を出す活動。AI が実行してもよく、人間は挙がった論点を見て採否を決める
小さい PR ほどレビューが効く。大きすぎる差分は論点が埋もれ、形式的な承認しか生まない
小さな差分(短命な枝)
Pull Request変更の単位を示す場所
Review と採否の判断Review は AI も、採否は人間
自動チェック7章で自動化する
main へ統合
Week 7|ソフトウェアエンジニアリング40
第6章 変更を小さく統合する|6.4 この章のまとめ:ここは覚えて次へ
設計では影響範囲を小さくし、統合では一度に持ち込む変更量を小さくする。
①短命なブランチと小さな commit長く育てた巨大な枝は他の変更と衝突し、レビューも統合も難しくなる
②小さな差分を頻繁に main へ入れるPull Request で変更の単位を示し、Review で別視点のフィードバックを受けてから統合する。差分が小さいほどレビューが効く
次章へテストがあっても、人間が走らせるならそこが手作業として残る
Week 7|ソフトウェアエンジニアリング41
7
フィードバックを自動化する
テストがあっても人間が走らせるなら、そこが手作業として残る。変更した直後に、機械が品質のフィードバックを返す。
7.1–7.2CI とは何か共有の場所が、変更のたびに同じ手順で build・静的解析・テストを走らせる
7.3–7.4自動チェックと判断、二重のループ根拠を積むのは機械、採否を決めるのは人間。自動ループは数分で返る
7.51章の問いへの答え変更の結果を、もっと早く確かめられるようにする
7.1 CI とは何か(Continuous Integration・継続的インテグレーション)
人が思い出して自分の PC で確かめる代わりに、共有の場所が変更のたびに同じ手順で確かめる
名前の意味Integration は、自分の変更をチーム共有の main へ合流させること。Continuous は、それを小さく頻繁に繰り返すこと
1回の CI で起きること
1自分の変更を push する(または PR を出す)いつもの作業。ここから先に人の操作は要らない
2共有サーバが変更を検知し、自動で確かめるまっさらな環境を用意し、設定ファイルに書いた手順を上から実行する
3緑・赤とログが、その変更の画面に返るどこで失敗したかまで残る。赤ならその場で直してもう一周する
走るのは自分の PC ではない。GitHub などの共有サーバ上の自動実行(GitHub Actions など)。誰の変更でも、同じ場所で同じように確かめられる
毎回まっさらな環境で実行する。手元にだけ入っていたライブラリや設定に頼れないので、「自分の PC では動く」が起きにくくなる
手順は設定ファイルに書いて履歴に残す。どのテストを走らせるかを人が覚えておく必要がなくなる。手順そのものもレビューできる
目的は合流のたびの確認。テストを自動で走らせること自体が目的ではなく、頻繁な合流のたびに根拠を受け取ることが目的
Week 7|ソフトウェアエンジニアリング43
7.2 CI で何を走らせるか
変更をきっかけに走らせるものを決め、その結果を差分の上に返す
変更を小さくする→短命な枝 / small batch→統合基準線へ頻繁に統合→そのたびに自動 Feedback
Push / Pull Request をきっかけに走るもの
buildそもそも通るか
compiler warnings警告は消してから進む
formatter書式を自動で整える
lint / static analysis規約違反や怪しい記述を、動かさずに指摘する
unit test部品単体の期待動作
integration test部品どうしの接続
SILS scenario必要なら、制御ループごと回す
引き金は変更そのもの。人間がコマンドを打たなくても、push や PR が機械を走らせる
結果は差分の上に返る。required checks を満たしたかが出る。合流はレビューと判断のあと
覚えておく必要がなくなる。どのテストを走らせるべきかを人間が記憶する仕事が消える
統合のたびに返る。小さな差分を main(最新の統合基準線)へ頻繁に統合し、その統合ごとに Feedback を受ける
CI は「自動テストサービス」ではなく、Frequent Integration + Automated Feedback。変更を共有される統合基準線へ頻繁に入れ、そのたびに build / test / analysis が根拠を返す
Week 7|ソフトウェアエンジニアリング44
7.3 二種類の働き:自動チェックと意思決定
自動チェックは根拠を返し、判断はその根拠を採用するかを決める
CIで実行する自動チェック(静的解析・Unit Test・Integration Test・SILSなど)
決められた基準に対して、高速に・再現可能に結果を出す
変更直後に根拠を返す。何度でも同じ手順で繰り返せる
基準の外側には何も言わない
基準そのものが妥当かは判定できない
Review と Decision(差分レビューと採否の判断)
根拠と設計案を見て、基準・リスク・採否を決める
抜けた観点や設計の筋に気づける。Review は AI も支援・実行してよい
採否の判断は自動チェックの外側にあり、小さい差分でなければ働かない
AI はレビュー案や改善案を作ってよい。採否は人間が持つ
分けるのは AI か人間かではなく、根拠を積む自動チェックと、それを採用するかの判断である
Week 7|ソフトウェアエンジニアリング45
7.4 二重のループ:高速な自動ループと、統合のループ
自動チェックは数分で戻り、統合は判断を経て進む
内側:自動ループ(数分)
変更→Build→静的解析→Unit Test→SILS
→
根拠が返る
←赤ならその場で直して、もう一周する
外側:統合のループ(判断を含む)
Pull Request→自動チェックの結果→Code Review→人間の判断→Merge
Code Review は数分では返らない。だから自動ループを内側に置き、判断は差分の単位でまとめて受ける
1章の問いへの答え:手前の段に自動ループを作れば、変更の結果は数分で返る
Week 7|ソフトウェアエンジニアリング46
第7章 フィードバックを自動化する|7.5 この章のまとめ:ここは覚えて次へ
変更した直後に、数分で根拠が返る状態を作る。
①CI は自動テストサービスではないFrequent Integration + Automated Feedback。小さな差分を統合基準線へ頻繁に入れ、そのたびに build・静的解析・Unit Test・SILS が根拠を返す
②二重のループで受ける内側の自動ループは数分で返る。外側の統合ループは Review と人間の判断を経て進む
③返るのは保証ではなく継続的な確認自動チェックが根拠を積み、それを採用するかの意思決定は人間が持つ
次章へCI の Green は「この構成で確かめた」という Evidence。では、実際に飛ばした構成は何だったのか
Week 7|ソフトウェアエンジニアリング47
8
飛ばしたソフトウェアを再現できるようにする
テストが緑でも、軌道上で動いていたものが何だったかを言えなければ、原因は追えない。
8.1なぜ構成管理が必要か同じものを手元で動かせなければ、異常の切り分けが始まらない
8.2最低限やることRelease と Tag、依存の固定、build artifact の保存
帰結戻れることは副産物再現できる状態が保たれているから、外れても戻れる
8.1 なぜ構成管理が必要か
同じものを手元で動かせなければ、原因の切り分けは始まらない
前提
軌道上で異常が出る手元にあるのはテレメトリだけで、実機は取り戻せない
↓
必要
原因を絞るには、同じものを手元で動かす飛んだものと同じコード・同じ設定・同じ焼き方で再現して、初めて比べられる
↓
帰結
「何が載っていたか」が言えないと、そこで止まるどこが違うのか分からないので、切り分けも、直したことの確認もできない
だから、飛ばしたものを後から再現できる状態を、打ち上げ前から保っておく
Week 7|ソフトウェアエンジニアリング49
8.2 Release・Tag・依存固定・artifact 保存
時点を指せて、同じものを作り直せるなら、原因を追えて戻れる
STEP 1Release / Tagこの時点が飛んだ、と後から指せる名前を付ける
STEP 2Dependency 固定ライブラリとツールの版を書き残し、同じ環境を作り直せるようにする
STEP 3Configuration の版管理しきい値や校正値も、コードと同じように履歴へ載せる
STEP 4Build artifact の保存実際に焼いたバイナリそのものを残す
「外れたら戻せる」は、再現できる状態が保たれていることの副産物である
Week 7|ソフトウェアエンジニアリング50
第8章 飛ばしたソフトウェアを再現できるようにする|8.3 この章のまとめ:ここは覚えて次へ
「何を飛ばしたか」を再現できて、初めて原因を追える。
①構成管理の対象は commit だけではないtoolchain、依存のバージョン、設定と校正値、焼いたバイナリまで含む
②その時点を指して同じものを作り直せる外れたら戻せるというのは、この状態が保たれていることの副産物
次章へ変更を安全・高速に回すという一つの思想から、設計・検証・統合がどう出てきたかを一枚で見る
Week 7|ソフトウェアエンジニアリング51
9
まとめ:高速なフィードバックループを作る
今日の技法はバラバラのベストプラクティスではない。変更を小さく、安全に、高速に回すという一つの思想から出てくる。
9.1一つの思想から三つの仕組みへ設計・検証・統合が、並行してフィードバックループを支える
9.2結論完璧に作る技術ではなく、改善し続けるための技術
9.3–9.4次回予告と宿題Week 6 の宿題を、今日の道具で考え直す
9.1 一つの思想から、設計・検証・統合が出てくる
「変更を安全・高速に回す」を、設計・検証・統合の三つで支える
↓
設計|2–4章責務分離・情報隠蔽
Interface
Testability
Fast Unit Test → Refactoring
TDD は、高速な Feedback で設計と実装を小さく往復する有力な実践方法の一つ。必ず行う工程ではない 検証|3・5章Static Analysis
Unit / Integration(Host)
SILS / Target
HILS / 実機
Evidence を早く得る
段ごとに得られる Evidence の種類が違う。上位互換ではない 統合|6・7章Small batch
Short-lived branch
PR / Review
Frequent Integration
CI(自動 Feedback)
SILS の次に PR が必然的に発生するわけではない
横断基盤|8章Configuration Management / Reproducibility。設計・検証・統合すべての Evidence が、どの構成に対するものだったかを後から特定できる状態を支える。最後に追加する工程ではない
講義では左から順に学んだが、実際の開発ではこの三つを並行して使う。前段をやらなければ後段が成立しない一本道ではない。
Week 7|ソフトウェアエンジニアリング53
9.2 結論
ソフトウェアエンジニアリングとは、
最初から完璧なソフトウェアを作る技術ではない。
変更を小さくし、変更の結果を高速に検証し、学習しながら安全に設計を改善し続けるための技術である。
軌道上では回せない開発サイクルを、地上で可能な限り高速に回しておく。
そのために、ソフトウェアを分離し、試験可能にし、シミュレーション可能にし、自動化する。
9.3 次回予告:Week 8 プロジェクトマネジメント
今日までに作った検証と統合の道具を、チームの計画とインターフェース設計へ
WEEK 6|前回宇宙開発とシステムズエンジニアリング
WEEK 7|今日ソフトウェアエンジニアリング
WEEK 8|次回・講義最終回プロジェクトマネジメント依存を描く PERT 図とマージン。コードを書く前のインターフェース定義
以降作業期間・チーム開発、そして合宿へ
マネジメントの本質はタスクの依存関係をほどくこと。依存を描く PERT 図と、計画を守るマージンを学ぶ
インターフェースの二つ目の顔。Week 7 では変更を局所化し Testability を作る設計境界、Week 8 では複数人が並行開発するためのチーム間の契約として扱う
事前学習の講義は Week 8 で一区切り。以降は作業期間とチーム開発へ
Week 7|ソフトウェアエンジニアリング55
9.4 宿題:同じ宿題を、ソフトウェアエンジニアリングの考え方で考え直す
Week 6 で考えた「初回打ち上げに必要な機能」をSWE視点で考え直す
Week 6 の宿題模擬衛星の初回打ち上げに必要な機能を考える
同じ宿題を三つの回で考え直すお題は Week 6 と同じで、
今日はソフトウェアエンジニアリングの考え方から
Week 6 SE|初回に必要な機能は何か→Week 7 SWE|どう作り、どこで検証するか→Week 8 PM|誰といつ作るか
考える観点の例
その機能のうち、Unit Test に落とせる判断はどこか(入力と期待を書けるか)
SILS で確かめる範囲はどこか(制御ループとして回す必要があるか)
CI に載せるものは何か。そして、実機でしか分からないことは何か
Week 7|ソフトウェアエンジニアリング56