ありがちな処理で構造化プログラミングについて考えてみる
要件
データベースから何かのデータを取得し、加工したうえでファイルに出力する
要件を分解する
まず要件を分解して処理の概要を決める
- データベースから処理対象セットを取得する
- 処理対象セットを何か加工してリストを作る
- 出力用リストをファイルに出力する
これをフローチャートにすると以下
処理概要を実装可能なレベルに分解する
実装するためには処理内容をもう少し細かく分解して適当な粒度にまとめる必要がある
- データベースから処理対象セットを取得する
- 処理対象セットを取得するためのクエリーを構築する
- クエリーを実行する
- クエリー実行結果から処理対象セットを構築する
- 処理対象セットを何か加工して出力用リストを作る
- 処理対象セットの全件に対して以下の処理を実行する
- 合計を計算する
- etc,...
- 処理対象セットの全件に対して以下の処理を実行する
- 出力用リストをファイルに出力する
- 出力用リストの全件に大して以下の処理を実行する
- リスト要素をファイルに出力する
- 出力用リストの全件に大して以下の処理を実行する
フローチャートはこうなる
実装
良くないパターン 1
全てを1メソッドに書く
class DataExport{
public void Export(){
// データベースから処理対象セットを取得する
// 処理対象セットを取得するためのクエリーを構築する
var query = "select * from Table1 -- ,...";
// クエリーを実行する
// クエリー実行結果から処理対象セットを構築する
var resultset = database.ExecuteQuery(query);
// 処理対象セットを何か加工して出力用リストを作る
// 処理対象セットの全件に対して以下の処理を実行する
var total = 0M;
var reportItemList = new List<ReportItem>();
foreach(var item in resultset){
var reportItem = new ReportItem(item);
// 合計を計算する
total += item.Amount;
// etc,...
reportItemList.Add(reportItem);
}
// 出力用リストをファイルに出力する
// 出力用リストの全件に大して以下の処理を実行する
using(var writer = new StreamWriter("report.txt")){
foreach(reportItem in reportItemList){
// リスト要素をファイルに出力する
writer.Write(reportItem);
}
}
}
}
これだと上で処理内容を分割して粒度によって分割した意味がなくなる
ましなパターン
まとめた処理内容の粒度に従って適切にメソッドを分割する
class DataExport{
public void Export(){
GetResultSet();
CreateReportItemList();
WriteReportItemList()l
}
///<summary>データベースから処理対象セットを取得する</summary>
private void GetResultSet(){
// 処理対象セットを取得するためのクエリーを構築する
var query = "select * from Table1 -- ,...";
// クエリーを実行する
// クエリー実行結果から処理対象セットを構築する
var resultset = database.ExecuteQuery(query);
}
///<summary>処理対象セットを何か加工して出力用リストを作る</summary>
private void CreateReportItemList(){
var total = 0M;
var reportItemList = new List<ReportItem>();
foreach(var item in resultset){
var reportItem = new ReportItem(item);
// 合計を計算する
total += item.Amount;
// etc,...
reportItemList.Add(reportItem);
}
}
///<summary>出力用リストをファイルに出力する</summary>
private void WriteReportItemList(){
using(var writer = new StreamWriter("report.txt")){
foreach(reportItem in reportItemList){
// リスト要素をファイルに出力する
writer.Write(reportItem);
}
}
}
}
こうすると、要件に記述した内容が明確になり、処理内容を分割、まとめた内容とも比較し易い。