『設計』の基本中の基本その③:いよいよラスト!『段階的な詳細化』、そして伝説へ。。。♪
<アイデアが確定した日>
2022年04月03日。。。だな、うん(;´∀`)|||
<ざっくりとした環境情報>
OS:Windows11
言語:Java (azul-13.0.9)
追加ライブラリ:commons-lang3-3.12.0.jar(※commons-lang3-3.12.0-bin.zip)
『ソフトウェア設計における基礎の基礎』シリーズ!?もいよいよ大詰め!たぶんみなさま《無意識》にやってる『段階的な詳細化』について♪♪♪
ふぁい♡
みなさま
こんばんは!!
さいきん
すぅぃぃいー--っかり
スクラップの立ち上げる時の気軽さにハマってる
かがみんどぇす♪♪
さて、今回は
その決定は、
何十年にもわたって進化してきた
ヒューリスティックを用いて実現される基礎的な設計コンセプト
(関心事の分離、段階的な詳細化、機能の独立)や、
~
ロジャー・プレスマン; ブルース・マキシム. 実践ソフトウェアエンジニアリング (第9版) (p.212). Kindle 版.
などと超著名なソフトウェアエンジニアリング本に
書かれていたので、
かがみが勝手に『NY三部作』みたいにしちゃった(;´∀`)、
【『設計』の基本中の基本その③:段階的詳細化】
についてご投稿させて戴きま~す♪♪♪
あ、ちなみに関連記事は下記になりまぁす♪
その①:関心事の分離
その②:機能の独立
ではではさっそくサンプルコード♪♪
パターンその①:
→『親=メイン処理』中身の一部を、
『親=メイン処理』とは別のメソッドに分けて実装する。
package chapter02.section02.domain.model.organizationhierarchy;
import chapter02.section02.domain.model.organizationhierarchy.value_object.*;
//『組織名制約』クラス(の、つもり。。。)
class Judge_SoshikiMeiConstraint {
private final KaisouMei kaisouMei;
private final SoshikiMei soshikiMei;
//コンストラクタ
Judge_SoshikiMeiConstraint( KaisouMei kaisouMei , SoshikiMei soshikiMei ){
this.kaisouMei = kaisouMei;
this.soshikiMei = soshikiMei;
}
//////////////////////////////////////////////
//組織名チェック
//※段階的詳細化でめっちゃスッキリ♪♪♪
//////////////////////////////////////////////
Boolean isSoshikiMei() {
//内容チェック(偽)
if(this.isBadContents()) { return false; }
//二重登録チェック
if(this.isDouble()) { return false; }
//最終結果
return true;
}
//組織名チェック(偽)
Boolean isBadSoshikiMei() {
return !this.isSoshikiMei();
}
//内容チェック
private Boolean isContents() {
//『組織名内容チェック』クラスにマトリョーシカ♪
return new Check_SoshikiMeiContents(kaisouMei , soshikiMei)
.isContents();
}
//内容チェック(偽)
private Boolean isBadContents() {
return !this.isContents();
}
//二重登録チェック
private Boolean isDouble() {
//『組織名二重登録チェック』クラスにマトリョーシカ♪♪
return new Check_DoubleEntrySoshikiMei(kaisouMei, soshikiMei)
.isDouble();
}
}
→ほい、『組織名チェック処理( =isSoshikiMei() )』の具体的な
中身である、
『内容チェック』
と
『二重登録チェック』
について、
『組織名チェック処理( =isSoshikiMei() )』とは
別メソッドの
『内容チェック(偽)処理( =isBadContents() )』
と
『二重登録チェック処理( =isDouble() )』
に
分けておりますよね(^^
とまぁこんな風に、
処理内容が、
どーしても大きな粒度になる場合に、
「メインルーチン>サブルーチン」のように、
プログラムを分けて、
1つ1つの処理の流れを読みやすくする、
という設計手法が
『段階的詳細化』
というものになります(^^♪
パターンその②:
→パターン①と同じように『段階的詳細化』を実施し、その後進化した結果、
『親=メイン処理』クラスとは別クラスとして分けて実装する。
①『段階的詳細化』済み、かつ 『機能の独立』【前】
class 組織 implements 組織階層{
private List<組織階層> list = null;
private int level = 0;
private String 階層名 = null;
private String 組織名 = null;
public 組織(int level,String 階層名,String 組織名){
this.level = level;
this.階層名 = 階層名;
this.組織名 = 組織名;
list = new ArrayList<組織階層>();
}
public void add(組織階層 entry){
list.add(entry);
}
public void 組織一覧表(){
System.out.println(makeTree());
組織一覧表生成();
}
private void 組織一覧表生成(){
Iterator<組織階層> itr = list.iterator();
while(itr.hasNext()){
組織階層 entry = itr.next();
entry.組織一覧表();
}
}
private String makeTree(){
String Branch = null;
String leaf = 階層名 + ":" + 組織名;
String root = 組織名;
switch (level){
case 1:
Branch = root;
break;
case 2:
Branch = "\t" + leaf;
break;
case 3:
Branch = "\t" + "\t" + leaf;
break;
case 4:
Branch = "\t" + "\t" + "\t" + leaf;
break;
}
return Branch;
}
}
②『段階的詳細化』済み、そして 『機能の独立』【後】
class 組織 implements 組織階層{
private List<組織階層> list = null;
private int level = 0;
private String 階層名 = null;
private String 組織名 = null;
public 組織(int level,String 階層名,String 組織名){
this.level = level;
this.階層名 = 階層名;
this.組織名 = 組織名;
list = new ArrayList<組織階層>();
}
public void add(組織階層 entry){
list.add(entry);
}
public void 組織一覧表(){
System.out.println(
new 樹形図作成(this.level,this.階層名,this.組織名).実行()
);
new 組織一覧表作成(list).実行();
}
}
class 樹形図作成{
private int level = 0;
private String 階層名 = null;
private String 組織名 = null;
樹形図作成(int level,String 階層名,String 組織名){
this.level = level;
this.階層名 = 階層名;
this.組織名 = 組織名;
}
public String 実行(){
String Branch = null;
String leaf = 階層名 + ":" + 組織名;
String root = 組織名;
switch (level){
case 1:
Branch = root;
break;
case 2:
Branch = "\t" + leaf;
break;
case 3:
Branch = "\t" + "\t" + leaf;
break;
case 4:
Branch = "\t" + "\t" + "\t" + leaf;
break;
}
return Branch;
}
}
class 組織一覧表作成 {
private List<組織階層> list = null;
組織一覧表作成(List<組織階層> list){
this.list = list;
}
public void 実行(){
Iterator<組織階層> itr = list.iterator();
while(itr.hasNext()){
組織階層 entry = itr.next();
entry.組織一覧表();
}
}
}
→ほいほい分けちゃった(^^♪
てか①と②でメソッド順とクラス順の順番一部逆さまだな。。。(;´∀`)||
ところで、
クラス分けをすると、
単純に考えるとコード量が増えるだけなのに、
いったいこれの何が楽しいでしょうか?
はい、
みなさま
過去記事をお読みになっている場合は、
すでにお分かりですよね、
そうです、
『機能の独立』をすると、
後からいろんな処理で『再利用』ができるんです♪
♪♪♪It's DRY!(^-^)♪♪♪
例1)
テキスト出力でもHTML出力でも『同じ』計算BLを使用
例2)
異なるドメインモデルで『同じ』判定BLを使用
※boy’s L...ぢゃないっすよ ||(´Д`;)
結びに
はい、今日お伝えしたいことは
ここまでです(^-^)
みなさま
『段階的詳細化』を実践することの利点を
ご納得されましたでしょうか?
そうそう、
そーいえば
過去のあっしのZenn記事にも、
元々は『段階的詳細化』を実施し、
その後『機能の独立』を果たしたこんなクラスが。。。
public class 勤務状況サブステータス区分問合せサービス {
private String my勤務状況 = "";
private List<勤務状況サブステータス区分アダプター> my勤務状況サブステータス区分list
= new ArrayList<>();
~中略~
private List<勤務状況サブステータス区分アダプター> 出社設定() {
my勤務状況サブステータス区分list.add(new 勤務状況サブステータス区分アダプター(状態区分.稼働));
my勤務状況サブステータス区分list.add(new 勤務状況サブステータス区分アダプター(場所区分.社内));
return Collections.unmodifiableList(my勤務状況サブステータス区分list);
}
~中略~
}
んで、こんな仕様変更がきて、
そぉすると、
それまでふつーに『単一』だと思っていたクラスが、
仕様変更に対応するのが『困難に』なって。。。。
Before:
<出力イメージ>
『勤務状況』が出社の場合、該当する『勤務状況サブステータス区分』は
●稼働
●社内
です。
『勤務状況サブステータス区分』が稼働の場合、
⇒一日のうちなんらかの仕事をした状態を指します。テレワークも含みます
『勤務状況サブステータス区分』が社内の場合、
⇒一日のうちなんらかの仕事をした状態を指します。ただし、テレワークは含みません。
です。
Process finished with exit code 0
After:
<出力イメージ>
『勤務状況』が出社の場合、該当する『勤務状況サブステータス区分』は
●稼働
●社内
●内勤
●------------または-------------------
●稼働
●社外
●外勤
です。
『勤務状況サブステータス区分』が
●稼働の場合、
⇒一日のうちなんらかの仕事をした状態を指します。テレワークも含みます
●社内の場合、
⇒一日のうちなんらかの仕事をした状態を指します。ただし、テレワークは含みません。
●社外の場合、
⇒社内以外の場所での働き方を行い、一日のうちなんらかの仕事をした状態を指します。
●内勤の場合、
⇒主にデスクワークに該当する働き方を行い、建物内での仕事をする状態を指します。
●外勤の場合、
⇒外回りの営業など、勤務時間の大半が建物外での仕事をする状態を指します。そのため、テレワークは含みません。
です。
Process finished with exit code 0
だもんで、
『関心事の分離』
の設計手法に則り分けちゃった!!
ってのが
ございましたなぁ(´∀`)♪♪♪
改修後コード_①)勤務状況サブステータス区分サービス.java
~中略~
private List<勤務状況サブステータス区分インターフェース> 出社設定() {
my勤務状況サブステータス区分list.add(勤務状況サブステータス区分アダプター.稼働);
my勤務状況サブステータス区分list.add(勤務状況サブステータス区分アダプター.社内);
my勤務状況サブステータス区分list.add(勤務状況サブステータス区分アダプター.内勤);
my勤務状況サブステータス区分list.add(new 区分値区切り線());
my勤務状況サブステータス区分list.add(勤務状況サブステータス区分アダプター.稼働);
my勤務状況サブステータス区分list.add(勤務状況サブステータス区分アダプター.社外);
my勤務状況サブステータス区分list.add(勤務状況サブステータス区分アダプター.外勤);
return Collections.unmodifiableList(my勤務状況サブステータス区分list);
}
~中略~
改修後コード_②)勤務状況サブステータス区分補足説明サービス.java
~中略~
private List<勤務状況サブステータス区分インターフェース> 出社設定() {
my勤務状況サブステータス区分list.add( 勤務状況サブステータス区分アダプター.稼働 );
my勤務状況サブステータス区分list.add( 勤務状況サブステータス区分アダプター.社内 );
my勤務状況サブステータス区分list.add( 勤務状況サブステータス区分アダプター.社外 );
my勤務状況サブステータス区分list.add( 勤務状況サブステータス区分アダプター.内勤 );
my勤務状況サブステータス区分list.add( 勤務状況サブステータス区分アダプター.外勤 );
return Collections.unmodifiableList(my勤務状況サブステータス区分list);
}
~中略~
とまぁ、みなさま♪
いろいろと無理難題そうな
ごんぶと本とかオススメしちゃってる
かがみですが、
オブジェクト指向とか
デザインパターンとか
レイヤーアーキテクチャーとか
言う前に、
まずは
気軽に
『倣うより慣れろ』で、
そんな感じで良いんじゃないのかなぁ~っと、
ガチでそう思いますよ~♪♪♪(´∀`)♪♪♪ ♪
みなさま、『ソフトウェア開発』をぜひとも楽しみましょう♪
おべんきょよりもまずはそれから♪♪♪
それでは、
また~♪♪♪
まとめ♡
その①:関心事の分離
その②:機能の独立
その③:段階的詳細化(※当記事)
そしてDDDの道へ。。。
Author And Source
この問題について(『設計』の基本中の基本その③:いよいよラスト!『段階的な詳細化』、そして伝説へ。。。♪), 我々は、より多くの情報をここで見つけました https://zenn.dev/kagaminpower003/articles/2a7b1caa3c9aba著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Collection and Share based on the CC protocol