システム開発入門です。経験の少ないエンジニアやプログラマの方を対象として,システム開発をする上で大切にしてほしいポイントをお伝えしていきます。よりよいプログラミング,よりよいシステム開発体験の一助にして頂けると幸いです。
モジュール
モジュールとは何でしょうか。簡単にいうと 「処理のまとまり」 です。1つ以上の関数または構造体を含みます。前回もお話した通り,処理はそれが何をするためのものなのかが端的に分かるように分割されているべきです。この分割された処理群をさらに意味のある単位でまとめたものがモジュールです。何かしらの意味のある単位でまとめることにより,集合としての責務・役割を表現できます。
システム全体から見たときのモジュールは部品や部分といった意味合いになります。1つ以上のモジュールを組み合わせることでシステムを構築していきます。モジュール自体も,より小さなモジュールを組み合わせて作られることがありますので,入れ子(フラクタル)構造になります。
小さな部品をつくり,小さな部品を組み合わせて大きな部品をつくり,大きな部品を組み合わせてシステム全体をつくる。というイメージです。小さな部品はテストがしやすく,品質が担保された部品を組み合わせてつくることでシステム全体の品質も向上させることができます。
とくに,店舗に関すること,商品に関すること,ユーザーに関することなどといった,ビジネス固有の領域を表したものを「ドメイン」といいます。「ユーザー」モジュール(パッケージ)の中には「ユーザー登録」や「ユーザー参照」といった処理が内包されることになります。
そのように区別して切り分けておくことで,システムが大きくなってきたときにも “どこで何をやっているのかわかりやすい” 状態にすることができます。
もう一つ重要なことは,モジュールの内側と外側を区別して,アクセスを制限する (公開 or 非公開)ということです。該当の関数やクラスは,外部から呼び出してよい(public
)のか,あるいは内部からしか使えない(private
, internal
)のか。関係者以外立ち入り禁止のところに部外者が入ってきたら安全ではありません。外の人(使う側)にとっても,アクセスできなくてよいものは隠されていた方がシンプルで分かりやすくなります。
言語機能として可能であるならばアクセス修飾子を適切に設定しましょう。もし,それができない言語であったとしても,この観点は意識することは大切です。
例えば,JavaScript にはアクセス修飾子はありませんが,クロージャを使って変数を封じ込めたり,module
の export
を使ったりすることでアクセスの制限をすることはできます。(後者はプログラム言語的な意味でのモジュールですね)
// クロージャを使ったカウンターのサンプル
const counter = (() => {
let _value = 0;
return () => ++_value;
})();
counter();
// > 1
counter();
// > 2
counter();
// > 3
処理フロー
続いて処理フローについて考えてみましょう。その処理がちゃんと要件を満たしているかどうかを確認するために処理フローを俯瞰してみることは大切なことです。とくに,初心者のうちは場当たり的にコードを書き進めていると段々何を書いているのかよく分からなくなってくることがあるかと思います。いったん,コードから離れて全体像を把握・調整する力を身に付けましょう。
処理フロー図は,主にプログラムの3つの基本制御構造を表現できます。
- 処理順序(逐次処理)
- 条件分岐
- ループ1
まずは,どんな処理が登場するのか確認しましょう。DB からデータを取得する,数値を計算する,文字列を処理する,ファイルに出力する,などといったものです。
次に,処理を実行する順番を確認しましょう。処理順序を考えるには,処理同士の依存関係を見ます。処理A の出力結果を 処理B が入力として必要としているのであれば,処理A は先に実行しなければなりません。条件分岐に関しても同様です。条件として参照しなければならないデータは,その判定よりも前に準備できていなければなりません。
I/F を意識した処理フロー
例として,記事データを登録する処理をみてみましょう。
渡されたデータの妥当性を検証して OK であれば保存します。
- まず,この処理の引数として未検証の記事データを受け取ります。
UnvalidatedArticle
は「未検証の記事」であることを型として表しています。 - バリデーション処理へ未検証の記事を渡して,検証済の記事を受け取ります。
ValidatedArticle
は「検証済の記事」であることを型として表しています。 - 「検証済の記事」では検証結果が OK か NG かが判断できます。
検証結果がOKの場合は次へ進みます。
そうでなければエラー内容を返して処理を終了します。 - 検証済の記事をDBへ保存します。
- 処理を終了します。
保存処理を行うには,記事データが検証済みである必要があります。ですので,保存処理よりも先にバリデーション処理を行う必要があることがわかります。また,このように型でデータの状態を表現することで未検証のデータが保存されてしまうのを防ぐこともできて安全性も高まります。
このように整理していくと
“I/F によって処理順序を明確にできる”
ようになります。
I/F(型)はプログラムの静的な側面を表現し,処理フローは動的な側面を表現していると捉えることもできます。処理フローを意識することで I/F(型)設計のレベルもアップすることができます。
まとめ
- モジュールとは,ある意味の単位で処理をまとめたもの
- システムは,モジュールを組み合わせて構成される
- I/F によって処理順序を明確にし,安全性も高めることができる
参考図書
-
このループは正規の記法ではありませんが,スッキリ書くためにこのようにしています。モデリングの肝は,記法の厳密さよりも理解の促進だと私は考えます。 ↩