
æè¿ãç§ãã¡ã®ãã¥ãŒã¹ãã£ãŒãã«2人ã®ããŒããŒãããã°ã©ããŒãšãã³å±ãç»å ŽããŸãããããªã¹ãšããŒã«ã¹ã§ãã ããªã¹ã¯è¯ã人ã§å®ç§äž»çŸ©è
ã§ãããããŒã«ã¹ã¯ç®ç«ããªãéåžžã«è¬èã§ç°è²ã®ããã°ã©ããŒã§ãã ã©ã¡ããæåãå°œãããŠåªåããå¥ä»ããããšèããŠããŸãã ããããããŒã«ã¹ã¯äžçæžåœåªåããªãã£ãããã§ãã
ããã¯æ°ãããã©ã³ãã§ã-ç¶ãã ä»æ¥ãã¹ããŒãªãŒã¯ããŒã«ã¹ã«ã®ã¿è§ŠããŠããŸãã 圌ã¯äž»äººå
¬ã§ãã
ã ãããç©èªã¯åãæšãŠãããŠããŸãã
å
ã®æçš¿ïŒ
2人ã®ããã°ã©ãããã³ãçŒããæ¹æ³ãšã³ããªãŒæåã®æçš¿ã§ã¯ãããªã¹ã«å€ãã®æ³šæãæãããããŒã«ã¹ã«ã¯ã»ãšãã©æ³šæãæãããŠããªãã£ããšæããŸããã ãããã圌ã®è¬èãã®ããã§ãã æçš¿ã¯æ¥œããã£ãã§ããç§ãšå€ãã®äººã¯ãã³ã¡ã³ãããå€æããŠãæ°ã«å
¥ã£ãŠããŸãã ãããŠãç§ã¯åœŒã
ã建ç¯ã®
å®å®é£è¡å£«ãæã£ãããšãéåžžã«ããããæããŸãã ãããŠãããŒã«ã¹ã¯åå©ã®å°äœã«ãããŸããã ããããããã¯æåã®äžæã«éãããã¹ã³ãŒããèšå®ããæã§ããã å
ã®æçš¿ã«ã¯ããªãã¯ããããŸãã-ããªã¹ãããããšã¯å®å
šã«æããã«ãããããŒã«ã¹ãããããšã¯å€éšã€ã³ã¿ãŒãã§ã€ã¹ã®èåŸã«æ®ã£ãŠããŸããã ã²ã©ãã¹ãã²ããã£ã³ãŒãããããšæé»ã®ãã¡ã«æ³å®ãããŠããŸããã
ä»æ¥ã¯ãããŒã«ã¹ã®äœçœ®ã修埩ããããšããŸãã æçš¿ã¯YAGNIã®ååã«å°å¿µããŸãã ããã¯YAGNIã®äœ¿çšäŸã§ãããå人çãªçµéšã«åºã¥ããŠããŸãã æ®å¿µãªããããã®ååãé©çšããæ¹æ³ãäŸã§ç€ºãæ¬ã¯å€ããããŸããã ãããŠãã»ãšãã©ã®ããã°ã©ããŒã¯ãæ¬ãèªãããšã«å ããŠãçµéšãšä»äºãéããŠãããã®ã¹ãã«ãçã¿ãŸãã ãããã¯åãªãçè«ã§ã¯ãªããã³ãŒãã¹ãã«ã ãšæããŸãã ãããŠããã®ãããªçµéšã¯å
±æããã®ãããã§ãããã ããªãããäœãæ°ããããšãåŠã¹ããå¬ããã§ãã ãã®æçš¿ã¯ç·Žç¿å°çšã§ãããã¿ã¹ã¯ã¯CïŒã§æ€èšãããŸãã æ®å¿µãªãããæœåšçãªèŠèŽè
ãæžããããšãã§ããŸãã ããããçè«èªäœã¯æ¬åœã®å¯èœæ§ãèŠããŸã§æµã«åãå
¥ããããªãã®ã§ãä»ã®æ¹æ³ã¯ãããŸããã æ°ã«å
¥ããªãUMLã¯ã©ã¹å³ã ãããŠãããŒã«ã¹ã«ãšã£ãŠã¯ãæããã«ããããã¯å¿
èŠãããŸããã§ããã
ãŸããCïŒã®ã¹ã¿ã€ã«ãšã³ãŒãã®èŠèœãšãã«ããŸã泚æãæããªããããé¡ãããŸãã ç§ã¯ç解ããŠããããã«ãã¢ãããŒãã®æ¬è³ªã瀺ãããã ãã§ãã ãããŠãããããªããšã«æ³šæãåããªãã§ãã ããã ãŸããTDDã¢ãããŒãã¯ç€ºããŸãããåäœãã¹ãã®æžãæ¹ã瀺ããŸãããããããªããšããã®ãããªåçŽãªã¿ã¹ã¯ã§ãã£ãŠããæçš¿ã¯éåžžã«èšå€§ã«ãªããŸãã ãã¡ãããTDDã¯ã³ãŒãã«å¯ŸããŠç¬èªã®èª¿æŽãè¡ã£ãŠããŸããã ããããå
ã®æçš¿ããèŠãããã«ãMarkusãYAGNIã䜿çšããŠããå ŽåãMarkusãããã»ã©ã²ã©ããªã£ãŠãããã©ããã«ã®ã¿èå³ããããŸãã
ãããŠãã¡ãããç§ã¯ããããªããšãæžããŸãã ã³ã¡ã³ãã§å€æãããšãå€ãã®äººãç§ãšåãããã«èããŠããã圌ãã¯ãã®ãããªæçš¿ãæªåãããããšã¯ãããŸããã ãŸããããã€ãã¯ããã«åªããŠããŸãïŒæ©èœçãªã¢ãããŒãã䜿çšïŒã
å§ããŸãããã èŠä»¶ã®ãã§ãŒã³å
šäœãèŠãŠãããŸãããã ç§ã¯ããŒã«ã¹ã§ãã 確ãã«ãç§ã¯å°ãç°ãªãããŒã«ã¹ã§ããã以åã®ãã®ãšãŸã£ããåãããã«åäœããŸããã
èŠä»¶1-ã¿ããªããã³ãäœãå¿
èŠããããŸãåæãã³ãäœãã«ã¯ãã¡ãœãããå¿
èŠã§ãã ãã³ãšã¯ïŒ ããã¯ç¹å®ã®ãšã³ãã£ãã£ã§ãã ããã¯ãªããžã§ã¯ãã§ã¯ãããŸãããããã§ãªããã°ãä»ã®ãªããžã§ã¯ããšæ··åãããå¯èœæ§ããããŸãã ããã¯ãintåãŸãã¯ãã®ä»ã®çµã¿èŸŒã¿åãŸãã¯äœææžã¿ã®åã§ã¯ãããŸããã ãã³ã§ããããã¯æ°ããå¥åã®ã¯ã©ã¹ã§ãã 圌ã«ã¯çç¶ãè¡åããããŸããïŒ å人çã«ã¯ãçå°ïŒå°éºŠç²ãå°éºŠãã©ã€éºŠãªã©ïŒã§æ§æãããŠããããšãåºèã§è³Œå
¥ã§ããããšãé£ã¹ãããããšãç¥ã£ãŠããŸãã ããããããã¯ç§ã®å人çãªç¥èã§ãã 顧客ã¯ãè¡åãç¶æ
ã«ã€ããŠèšèãçºèšããŠããŸããã ãããŠä»¥æ¥ ç§ã¯æ ãè
ã§ããããå°ãç¥ã£ãŠããŠãã顧客ãäœãæãã§ããããçŽæ¥ç€ºãããšãªãããã¿ã³ãåã³æŒãããšã¯ãããŸããã
èŠä»¶ããã®ã¿é²ã¿ãŸãããã³ã«ã¯ç¶æ
ãšåäœããªãããã³ãååŸããæ¹æ³ãå¿
èŠã§ãã æ®å¿µãªãããŸãã¯å¹žããªããšã«ãCïŒèšèªèªäœã«ã¯ãããå°ã倧éšããå¿
èŠã§ããã€ãŸããä»»æã®ã¯ã©ã¹ã§ã¡ãœãããå®çŸ©ããããã§ãã ããããä»¥æ¥ é¡§å®¢ã¯ããã«ã€ããŠäžèšãèšããªãã£ãã®ã§ãååãæ°ã«ããŸãããã€ã³ã¹ã¿ã³ã¹ãæ°ã«ããŸãããä»ã®ãšããéçã¡ãœãããäœæããããšã«ããŸããã ã©ã¡ãããšããã°ããã€ã§ãããçŽãæéãããã§ãããã èŠä»¶ã®æãå¹³åçãªç解ã«äžèŽããååãéžæããŸãã ãããã£ãŠãæåã®ã³ãŒãã¯æ¬¡ã®ãšããã§ãã
class Bread { } class BreadMaker { public static Bread MakeBread() { return new Bread(); } }
èŠä»¶2-ãã³ãäœãã ãã§ãªãããªãŒãã³ã§çŒãå¿
èŠããããŸãåæ顧客ã¯ãèªåãæããã®ãèšãã®ã§ã¯ãªããäœããå®è£
ããæ¹æ³ã瀺ããããšããããšããããŸãã ã客æ§ã®å®è£
ã®åžæã¯ã身äœçãŸãã¯å¿ççã«ç§ã«åœ±é¿ãäžããŸããã ãã®å Žåãããã¯èŠä»¶ã§ã¯ãããŸããã 顧客ã¯ç§ããã³ãã©ãã§æã«å
¥ãããã確èªããæ¹æ³ããããŸããã ãããŠã圌ããã®ãããªé¡æããè¡šæãããŸã§-ãã§ãã¯ããã ãããã£ãŠããã³ãåãåã£ãŠåœŒã«æž¡ãæ¹æ³ã¯ã圌ã®é¡§å®¢ããžãã¹ã§ã¯ãããŸããã ããããç§ã¯éèŠã«äžå¯§ã«åæãã圌ããæ idleã®ããã«ããã«ãéãæã£ãŠããããã§ãã
ãŸã äœãããŠããŸããã ãããã念ã®ãããã¹ããŒããèŠããŠããŸãã 顧客ã¯ãªãŒãã³ãããã®éããããã³ãžã®ç°ãªã圱é¿ã瀺ããªãã£ãã åŸè
ãéèŠã§ãã 顧客ããªãŒãã³ã®ããã€ãã®ã¿ã€ãã瀺ãããšããŠãããšã«ããæ¥ãå Žæã¯ãããŸãã-ãã³ã¯åãã§ãã
ããããããã§ããç§ãã¡ã¯ãã¹ã®ããã«æ¥œãããã®ãäœããæå³ã«åãããã«ã³ãŒããå°ãä¿®æ£ããŸãã ã€ãŸãããã³ã¯ãªãŒãã³ã§çŒããåºã§ã¯è²·ããªãããšããã§ã«ç¥ã£ãŠããŸãã breadã¡ãœããã®ååãå€æŽããã ãã§ãïŒ
class BreadMaker { public static Bread BakeBread() { return new Bread(); } }
èŠä»¶3-ã¬ã¹ãªãã§ã¯çŒããªãããã«ããã«ã¯ã¬ã¹ã¹ããŒããå¿
èŠã§ãåæããïŒ æ°ããæ
å ±ãå°çããŸããã ã¬ã¹çãããããã®åäœã¯ä»ã®çãšã¯ç°ãªãããšãå€æããŠããŸãã 確ãã«ãä»ã®çã®ããŒãã¯åã³é瀺ãããŠããŸããã ããã§ããã ããããç°ãªããã®ã«ããŸãã
ããã€ãã®å®è£
ãæ¯èŒããŠã¿ãŸãããã
å®è£
1ã
enum Oven { GasOven, OtherOven } class BreadMaker { public static double GasLevel { get; set; } public static Bread BakeBread(Oven oven) { return oven == Oven.GasOven && GasLevel == 0 ? null : new Bread(); } }
å¯äœçšã¯ããã«æããã«ãªããŸãã ã¬ã¹ã¬ãã«ã¯ãBakeBreadïŒïŒã®åŒã³åºããšã¯å¥ã«èšå®ãããŸãã ã®ã£ãããçãããšããã°ãåºçŸããå¯èœæ§ã®åºãåéãéããŸãã ãããã®ãã°ïŒãã°ïŒã®åºçŸã¯ãçã«æ害ãäžããå¯èœæ§ããããŸããããããã°ãå°éºŠããã³ããªããªããŸãã
ãã®ããã«ãã©ã¡ãŒã¿ãŒãåå¥ã«ã€ã³ã¹ããŒã«ãããšãã³ãŒãã®ãŠãŒã¶ãŒïŒããã³ãã®ç ç²ãŠãŒã¶ãŒã«ãªãå¯èœæ§ããããŸãïŒã¯ãã¬ã¹çãéå§ããåã«ã¬ã¹ã¬ãã«ãèšå®ããããšãå¿ããŠããŸãå¯èœæ§ããããŸãã ãããŠã以åã«ãã³ãçŒãããšããã¬ã¹ã¬ãã«ã¯ãªãŒãã³ã®åã®èšå®ã®ãŸãŸã«ãªãå ŽåããããŸãã æ¬åœã«å¿ããŠããŸããšãäºæž¬äžå¯èœãªåäœã«ã€ãªãããŸãã
ãŸããããããã£ãéçã§ããããšãããããŸãã ãããéåžžã«æªãããšã§ããã¬ã¹ã¬ãã«ã¯1ã€ãããããŸããã ãã ããéçã¡ãœãããšéçããããã£ãåé€ããŠãäžèšã®åé¡ã¯è§£æ±ºãããªãããããã®ãªãã·ã§ã³ã¯èæ
®ããŸããã
å®è£
2ã
enum Oven { GasOven, OtherOven } class BreadMaker { public static Bread BakeBread(Oven oven, double gasLevel) { return oven == Oven.GasOven && gasLevel == 0 ? null : new Bread(); } }
ãšãŠãç°¡åã§ãã ãããŠã以åã®å®è£
ãããå°ãè¯ãã§ãã ãã ããäžè²«ãããã©ã¡ãŒã¿ãŒãåžžã«BakeBreadïŒïŒã¡ãœããã«æž¡ããããšã¯éããŸããã éã¬ã¹çã®å ŽåãgasLevelã¯æå³ããªããŸããã ã¡ãœããã¯æ©èœããŸãããéã¬ã¹çã®gasLevelã®ã¿ã¹ã¯ã¯ãã³ãŒãã®ãŠãŒã¶ãŒãæ··ä¹±ãããŸãã ãŸããã³ã³ãã€ã«æ®µéã§ã¯ãã©ã¡ãŒã¿ãŒã®æ£ç¢ºæ§ã¯ãã§ãã¯ãããŸããã
å®è£
3.ãã©ã¡ãŒã¿ã«åæããããã«ã¯ãçãã¯ã©ã¹ã®ããã«èŠããªããã°ãªããŸããã
ããã«ãéåžžã®ãã³ã¯åžžã«ãã³ãçŒããŸãããã¬ã¹ã¯åžžã«ããã§ã¯ãããŸããã ã€ãŸã 2ã€ã®ã¯ã©ã¹ãä»®æ³ã¡ãœããããªãŒããŒããŒãã ãã ãããªãŒãã³ãç¬èªã«äœæãããªãããã«ããããã®ä¿®é£Ÿåã«ã¢ã¯ã»ã¹ããæ¹æ³ãèããå¿
èŠããããŸãããç§ã®BakeBreadïŒïŒã¡ãœããã䜿çšããŸããããããªããšãå¯äœçšãçºçããŸãã
ãããŠãããã¯ç§ïŒããŒã«ã¹ïŒã§å€æãããŸãïŒ ãã®æ®µéã§ããããè¡ãã ãã§ãïŒ
class BreadMaker { public static Bread BakeBreadByGasOven(double gasLevel) { return gasLevel == 0 ? null : new Bread(); } public static Bread BakeBreadByOtherOven() { return new Bread(); } }
確ãã«ã顧客ã¯ãŸã ã©ã®ããã«ã¹ããŒãã䜿çšããããšããèšèãèšã£ãŠããŸããã ãã®æ®µéã§ã®ãã®ãããªã³ãŒãã¯éåžžã«æºè¶³ã®ãããã®ã§ãã
èŠä»¶4-ãªãŒãã³ã§ãã€ïŒå¥ã
ã«-èãå¥ã
ã«-ãã£ããïŒãããã³ã±ãŒããçŒãããšãã§ããããã«ããå¿
èŠããããŸããåæã¯ãã質åã¯ãããŸããïŒ ãªãŒãã³ã§æž©åºŠã¬ãã«ãèšå®ãããšãã¢ã€ã¹ã¯ãªãŒã ãçŒãããšãã§ããŸãã åè«ã ããŒã«ã¹ãç§ã¯çå£ã«ãªããŸããã-枩床ã«ã€ããŠã®èšèã§ã¯ãããŸããã 誰ãããªããç¥ã£ãŠãããã顧客ïŒïŒ
ã ããããã€ãšã±ãŒãã ããã ãã§ãªãã2çš®é¡ã®ãã€ã ããããããã¯ãèã®ãã€ãšãã£ããã®ãã€ã«ã¯ã±ãŒããããå€ãã®å
±éç¹ãããããšã人çããç¥ã£ãŠããŸãã ããããã¿ã¹ã¯ã®ã³ã³ããã¹ãã§ã¯ã顧客ã¯ããã«ã€ããŠè©±ããŸããã§ããã 圌ã¯ãã©ãã«ãããŠãã€ãå¥ã
ã«ãã±ãŒããå¥ã
ã«ã°ã«ãŒãåãããšã¯èšããªãã£ãã ãããã£ãŠããããŸã§ã®ãšãããèŠä»¶ã«åºã¥ããŠ-ã±ãŒãã¯ã»ãšãã©ãã§ãªãŒã®ãã€ã®ããã«æ¯ãèããŸã-ãããã¯ãã¹ãŠåãã§ãã 圌ãã¯äœãè¡åããããŸããïŒ ãã æ¡ä»¶ã¯ãããŸããïŒ ãã ãããã£ãŠãããããäºãã«åºå¥ããã«ã¯ãåæãäœæããã ãã§ååã§ãã ãããŠãææ¥çºçãã顧客ã®åžæãæšæž¬ããŠå
ã«é²ãããã«ãç§ãã¡ã¯åºæ¬çã«æãã§ããŸããã ã ãã-ãªã¹ããæãæ£ããã§ãã æãå¯èœæ§ãé«ãã ããããªãã ããããããªãã§ãã ããã ãã®å Žåã¯ããã€ã§ãæžãæããå¯èœã§ãã
䞊è¡ããŠãååãå€æŽããŸãããä»ã¯ãã³ã§ã¯ãªãããŒã«ãªãŒè£œåãçŒããŠããŸãã
public enum BakeryProductType { Bread, MeatPasty, CabbagePasty, Cake } public class BakeryProduct { public BakeryProduct(BakeryProductType bakeryProductType) { this.BakeryProductType = bakeryProductType; } public BakeryProductType BakeryProductType { get; private set; } } class BakeryProductMaker { public static BakeryProduct BakeByGasOven(BakeryProductType bakeryProductType, double gasLevel) { return gasLevel == 0 ? null : new BakeryProduct(bakeryProductType); } public static BakeryProduct BakeByOtherOven(BakeryProductType breadType) { return new BakeryProduct(breadType); } }
èŠä»¶5-ããŸããŸãªã¬ã·ãã«åŸã£ãŠãã³ããã€ãã±ãŒããçŒãå¿
èŠããããŸãåæã³ãŒãããã£ãšèŠãŠã¿ããšãBakeryProductTypeã®ãã°ããããªã¹ããããããšãããããŸãã ãµããžã§ã¯ããšãªã¢ã®è¿ãã§ã¯ãªãããªããšãªãäžåšçšã«ãäœããã®æ¹æ³ã§ããã°ã©ã çã«åŒã³åºãããŸãã ããããããã¯ã¬ã·ãã®ããã«æ¯ãèããŸãã äœãèµ·ãããïŒ ãã³ãšããŒã«ã¯ãã¿ã€ãã§ã¯ãªããã¬ã·ãã«åŸã£ãŠçŒããŸãã ãããŠããããããã¬ã·ãã¯ããŒã«ãã¶ã€ããŒã«äŒãããŸãã ååãå€æŽããã®ã«ååã å¯äžã®é害ã¯ãå£å財ç£ã§ãã ããããç§ã¯èªåèªèº«ãèŸä»»ããã§ãããã ã³ãŒããæ©æ¢°çã«èŠãŠããµããžã§ã¯ãé åãããã€ãã®ã»ãããšããŠæ³åãããšãã¬ã·ããšã¿ã€ãã®éã«å€§ããªéãã¯èŠãããŸããã ã€ãŸã ã¬ã·ãã¯ãåŸã§èµ·ããããšã®çŽæ¥ã®çç±ã§ãã ãã¡ãããç掻ã®äžã§ãç§ãã¡ã¯ã¬ã·ãã«ã€ããŠããå°ãç¥ã£ãŠããŸã-圌ãã¯äœãèµ·ããããèšè¿°ããã ãã§ã¯ãããŸããã ãŸããååŸã¢ã«ãŽãªãºã ãå«ãŸããŠããŸãã ãããã誰ãæ°ã«ããŸããïŒ é¡§å®¢ã¯ããã«ã€ããŠè©±ããŸãããïŒ ãã ããã¯ãã¿ã¹ã¯ã®ã³ã³ããã¹ãã§ã¯ãããçºçããªãã£ãããšãæå³ããŸãã ã¢ã«ãŽãªãºã ãå¿
èŠã§ã-åŸã§ãã€ã³ãããäœããèãåºããŸãã
ãããã£ãŠãããããã£ã¯åã®ãŸãŸã§ãããåæã¯ã¬ã·ãã®ãŸãŸã§ãããšããäºå®ã«ææ
¢ããŸãã 話ãèšèã®ç¹æ§ã®ãããçžç¶äººãå¥ã®ãªã¹ããäœæããªãã§ãã ããã ã¿ã¹ã¯ã®ã³ã³ããã¹ãã§ã¯ããã¹ãŠãæ£ç¢ºã§ãã ããŸãçŸãããããŸãããã 劥åïŒ
public enum Recipe { Bread, MeatPasty, CabbagePasty, Cake } public class BakeryProduct { public BakeryProduct(Recipe recipe) { this.BakeryProductType = recipe; } public Recipe BakeryProductType { get; private set; } } class BakeryProductMaker { public static BakeryProduct BakeByGasOven(Recipe recipe, double gasLevel) { return gasLevel == 0 ? null : new BakeryProduct(recipe); } public static BakeryProduct BakeByOtherOven(Recipe recipe) { return new BakeryProduct(recipe); } }
èŠä»¶6ãã¬ã³ã¬ããªãŒãã³ã§çŒãå¿
èŠããããŸãããåæãã®èŠä»¶ãšãã¹ãŠã®æžé¢ã«ããèŠä»¶ãæåéãå®ãã°ãã¬ã³ã¬ã¯ã±ãŒãããã³ãšå€ãããŸããã ãããããããšã«ãç§ãã¡ã®ã¬ã³ã¬ã¯ãžã£ã ãã€ãšã¯ã¯ããã«ç°ãªããŸããèŠä»¶ã«ãããå«ãŸããŠããªãããã§ãã ãã³ã®ããã«ã ãããã£ãŠãYAGNIã«ãããã®èŠä»¶ã¯å€§å¹
ã«èªåŒµãããŠããããã¹ãŠã®ã¯ã©ã¹ã®ååãå€æŽããŠã¬ã·ãã®åæãæ¡åŒµããããšã«ãã£ãŠã®ã¿å®çŸãããŸããããã¯ãã¬ã³ã¬ãªã©ã®ããªãŒãã³è£œåãã®ããŒã«ã§ãã ã¯ã©ã¹ã¢ãŒããã¯ãã£ãäœæããæ¹æ³ã®å
šäœçãªãã€ã³ãã¯ããã®äœ¿çšæ¹æ³ã§ãã ããã¯ãäžè¬çãšèŠãªããããã®ïŒã€ãŸããåºæ¬ã¯ã©ã¹ã®ç¶æ
ãšåäœïŒããã³ãã©ã€ããŒãïŒç¶æ¿è
ã®ç¶æ
ãšåäœïŒããã®ãã®ã§ãã ã©ã¡ããååšããªãå Žåãåæãå¯èœã§ãã æšæž¬ããªãããšã¯æããªãã ã¯ã©ã¹ãšçžç¶äººãžã®åæã¯ç°¡åã«å€æãããŸãã
ã³ãŒãã«ææããããŸãããïŒ ãã®ã³ãŒãããã¹ãããã®ã¯é£ãããããããŸãããïŒ ã¯ããããªã¹ã®ã³ãŒãã¯ãã¹ãããã®ãã¯ããã«é£ããããã§ãã ããªã¥ãŒã ã¯ãããå€ãã®ãã¹ãã§ãã å¿
èŠä»¥äžã®æ©èœããããŸããïŒ ããå€ãã®ãã¹ãã
ãã¡ãããæããã«ãå
ã®æçš¿ã¯ãèŠä»¶ããã詳现ã§ãããåãã¬ãŒãºã詳现ãªèª¬æã§æ確ã«ãããããšãæ瀺ããŠããŸããã ããããYAGNIãžã£ã³ã«ã¯èããªãããšãèŠæ±ããŸãã
èŠä»¶ãããã«è©ŠããŸãããã
èŠä»¶7ãã©ãããŠèŠãªãã£ãã®ïŒã ãã¹ãŠã®ã¹ããŒããã¬ã³ã¬ãçããããšãã§ããããã§ã¯ãããŸããã ãããè¡ãã«ã¯ãç¹å¥ãªãªãŒãã³ãå¿
èŠã§ããåæããã§ããã åæããããªãã¯ãåé€ãïŒã¬ã·ãïŒïŒãååãè¿ããŸãã å¥ã®ç©ºã®Brickã¯ã©ã¹ãäœæããŸãã ãããŠæ°ããæ¹æ³ïŒ
public static Brick MakeBrickByFurnace() { return new Brick(); }
ãšããã§ãæè»æ§ãä»å¿
èŠãªãå Žåã¯ã誰ããäœããã®çš®é¡ã®ãªããžã§ã¯ããæ£ç¢ºã«çæããè±å¯ãªã¡ãœãããããªããžã§ã¯ããäœæããæè»ãªæ¹æ³ãããåªããŠããŸãã æè»æ§ãå¿
èŠã§ãªãå Žåãããã°ã©ã ã¯èš±å¯ãå°ãªãããå¶éãå¢ããå¿
èŠããããŸãã ç¹å®ã®ã¿ã€ãã®ãªããžã§ã¯ããã€ã³ã¿ãŒãã§ã€ã¹ã«çœ®ãæããããšããã°ãã°äŸ¿å©ãªãŠããããã¹ãã¯èæ
®ããŸããã ãã®ã³ãŒãã¯ãã¹ãŠãå Žåã«ãã£ãŠã¯ç°¡åã«ã€ã³ã¿ãŒãã§ã€ã¹ã«å€æãããŸãã ã¯ãããŸããCïŒãåæ ãããã®ã¯ãããçš®ã®ãã«ãããªã³ã°ã®ãã¹ãã§ã¯ããã»ã©èŠæ±ãããŸããã
ããã«ã顧客ã¯ããŒã«ã¹ãšå¯ŸæŠããããšã«ããŸããã
èŠä»¶8-åã¬ã·ãã«ã¯ã補åãšãã®éïŒééïŒãå«ããå¿
èŠããããŸãã éèŠã®ã¬ã·ããæ·»ä»ãããŠããŸããåæããªã¹ãåŸ
ã£ãŠããæåã®è¡ã
ã²ã©ãã¹ãã²ããã£ã³ãŒãã«å¯ŸåŠããŠã¿ãŸããããããã¯ãããã§é·ãé圢æãããŠããã¯ãã§ããããªãã¡ã¯ã¿ãªã³ã°ããæ©äŒãäžããŠãããŸããã ããã§ããïŒ
ã¬ã·ãã®è£œåã¯æããã«ãªã¹ããããŠããŸãã ã¬ã·ãèªäœã«ã¯ãäœæãããã®ã®åââåïŒãŸãã¯åããã®ãããèªäœã®ååïŒã ãã§ãªããæ°éãšè£œåã®ã»ãããæ¢ã«å«ãŸããŠããŸãã ããããåæã«ã補åã®å³å¯ãªã»ãããç¹å®ã®ã¬ã·ãã«é¢é£ä»ããããŠãããå€æŽãããŠããªãããšã«æ°ä»ããŸãã ïŒããäžåºŠãYAGNIã«ã€ããŠã®æçš¿ãæãåºããŸã-ãäºåéãå€æŽãããå Žåã¯ã©ãã§ãããïŒãããããçªç¶-ä»æ¥-ããã¯ä»æ¥ããããŠææ¥-ããã¯ææ¥ã§ãïŒã
ã€ãŸã 顧客ã¯ãã¬ã·ãã®è£œåãšééãç°ãªãå¯èœæ§ããããšã¯èšããªãã£ãã ãã¡ããã圌ã¯ããããä¿®æ£ãã¹ãã ãšã¯èšããªãã£ãã ããããåºå®ãããã±ãŒã¹ã¯ããéå®çã§å³å¯ã§ãã ãããŠãããéãããã±ãŒã¹ãåžžã«éžæããŸãã ç§ãã¡ã«ãšã£ãŠã¯ãæè»æ§ãé«ããã®ã§ã¯ãªããããã·ã³ãã«ã§å³æ Œãªæ¹ãè¯ãã®ã§ãã
ãããŠãå³å¯ãªè£œåã»ãããåããã¬ã·ãã¯ãå人çãªäœéšã«ããè¯ã察å¿ããŠããŸãã ãã®å Žåãç¶æ¿ã䜿çšããŠåã¬ã·ãã®ã¯ã©ã¹ãèšè¿°ããããšã¯å®çšçã§ã¯ãããŸããã ãã®åŸãåã¯ã©ã¹ã¯å®æ°ã®ã¿ãä¿åããŸãã
ãããŠããã«ããã€ãã®èãã ãªããªã çŸæç¹ã§ã¯ãã³ãŒãå
ã®ã¬ã·ãã¯æå®ãããåæã«ããããã³ã³ãã€ã«åã«èšå®ãããŠããŸããä»ã«èŠä»¶ããªãå Žåã¯ãæããã«ãã®åäœãæ®ã£ãŠããã¯ãã§ãã ããããããã¹ãŠã®ã¬ã·ããå©çšå¯èœã«ãªããã³ãŒãã§çŽæ¥èšå®ãããããšã«ãªããŸãã åæåæ¡åŒµæ©èœãªãã§æ°ãããã®ãäœæããããšã¯ã§ããŸããã ãããããRecipeNameã§åãååã®åæã®ååãå€æŽããåŸãRecipeã¯ã©ã¹ãäœæããå¿
èŠãããããã§ãã äžçã¯éåžžã«äžå®å®ã§ãã çŸåšããªã¹ãã«ã¯ã¬ã·ãã®ã¿ã瀺ãããŠãããã¬ã·ããéžæããããšã¯ã§ããŸãããå®å
šã«ã¯ç¹åŸŽä»ããããŠããŸããã
äžèšã®æ¡ä»¶ãæºããã«ã¯ã次ã®ããã«ããŸãã
public enum RecipeName { Bread, MeatPasty, CabbagePasty, Cake } public enum RecipeProduct { Salt, Sugar, Egg, Flour } public class Recipe { private Recipe() { } public RecipeName Name { get; private set; } public IEnumerable<KeyValuePair<RecipeProduct, double>> Products { get; private set; } private static Dictionary<RecipeName, Dictionary<RecipeProduct, double>> predefinedRecipes; static Recipe() { predefinedRecipes = new Dictionary<RecipeName, Dictionary<RecipeProduct, double>> { { RecipeName.Bread, new Dictionary<RecipeProduct, double> { {RecipeProduct.Salt, 0.2}, {RecipeProduct.Sugar, 0.4}, {RecipeProduct.Egg, 2.0}, {RecipeProduct.Flour, 50.0} } } .................. }; } public static Recipe GetRecipe(RecipeName recipeName) { Recipe recipe = new Recipe(); recipe.Name = recipeName; recipe.Products = predefinedRecipes[recipeName]; return recipe; } }
äœãå£ãå¿
èŠã¯ãããŸããã 補åãäœæããã«ã¯ãä»ã®ãšããã¬ã·ãã®ååã§ååã§ãã ããã§ã¯äœãå€æŽããŸããã ãããå¿
èŠã«ãªããŸããæã
ã¯ã¬ã·ãèªäœãæž¡ããŸãã
ãã®ã³ãŒãã§ã¯ãã¬ã·ãäžèŠ§ããã¯ã©ã¹ãäœæããã¬ã·ãã®ååãšãããæ§æãã補åãé¢é£ä»ããŸããã ããã蟌ã¿ãã§ããããã«ãã¬ã·ãã§ã¢ã¯ã·ã§ã³ã®ã·ãŒã±ã³ã¹ãè¡šçŸããå¿
èŠããããŸãã ãããæ確ã§ãã¹ãã²ããã£ã³ãŒãããªãããšãé¡ã£ãŠããŸãã ã¯ã©ã¹ããšã«å¥ã®åäœã衚瀺ãããŸããRecipeã¯ã©ã¹ãç°¡åã«åºæ¬ã¯ã©ã¹ã«ãªããçžç¶äººã衚瀺ãããŸãã ããããç§ãã¡ã¯ããã«ã€ããŠèããŸããã YAGNIããããŸããããããè¡ãããã«èšãããŠããŸããã ããããç§ãã¡ã¯ãããæããŠããŸããã
èŠä»¶9èšç»å€ã®ã¢ãããŒããç¥ã£ãäžåãªé¡§å®¢ã¯ãããããã£ããããããšã«ããŸããã
ãã¬ã·ããå€ããŠã»ãããã ã¹ããŒãã¯ãæç人ãäœæããã¬ã·ãã«åŸã£ãŠèª¿çãããŸãããè«äºã«å
¥ãïŒ
-å€æŽæ¹æ³
-æç人ã¯ã¬ã·ããç¥ãããå®éšã§ãããšä¿¡ããŠããŸãã ã¬ã·ããä¿®æ£ããŸãããïŒ ãããŠã圌ã¯ç°ãªãéã®åµãç ç³ãªã©ãè¿œå ããããšèããŠããŸãã
-ãããŠããã®å Žåãã©ã®ãããªãã³ãæã«å
¥ããŸããïŒ äœãæã«å
¥ããã¹ãïŒ ãã³ãã±ãŒãããŸãã¯ã±ãŒãïŒ æããã«ãã¬ã·ããç°ãªãå Žåãæç人ã¯äœãä»ã®ãã®ãçŒããŸãã
-ã±ãŒãã¯å³ãç°ãªããçããçããªããšæããŸãã ãã³ãã ãã®ãããã¬ã·ãã¯ããçšåºŠç°ãªãå ŽåããããŸããããªã¹ããã補åãå
¥æããŸãã
-ã€ãŸã äœãåŸãããã®ããç¥ãã«ã¯ãæç人ã®ã¬ã·ãã®è£œåãªã¹ãã«æãè¿ãã¬ã·ããæ¢ãå¿
èŠããããŸããïŒ
-ã¯ããåæã¬ã·ããä¿®æ£ããŸããã çŸåšãã¬ã·ãã¯ä¿®æ£ãããŠããªãå¯èœæ§ããããŸãã ããããç§ãã¡ãæã£ãŠãããã®ã¯ãã³ãããŒã¯ã§ãã ã³ãŒãã®ãŠãŒã¶ãŒãç¬èªã®ã¬ã·ããäœæã§ããããã«ããã«ã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒãéããŠãã ããã ãããã補åãå°ããæ©äŒãäžããããšãå¿
èŠã§ãã ããããã£ããŠãŒã¶ãŒã«å²ãåœãŠãããç¹å®ã®ã¿ã€ããæå®ãããããæ©äŒãäžããããããŸããã ããã§ãªããã°ã圌ã¯ç§ãã¡ã®åºæºãæãªãããšãã§ããŸãã ãããã£ãŠãæãç°¡åãªæ¹æ³ã¯ããã¶ã€ããŒã«è£œåã転éããæ©äŒãäžããããšã§ãã ãŸããäœæãšåæåã®éã®ã®ã£ããããªããããã°ã®å¯èœæ§ãæžãããŸãã
ããã§2ã€ã®ã³ã³ã¹ãã©ã¯ã¿ãŒãã§ããŸããã
private Recipe() { } public Recipe(IEnumerable<KeyValuePair<RecipeProduct, double>> products) { Dictionary<RecipeProduct, double> copiedProducts = new Dictionary<RecipeProduct, double>(); foreach (KeyValuePair<RecipeProduct, double> pair in products) { copiedProducts.Add(pair.Key, pair.Value); } this.Products = copiedProducts; }
2çªç®ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã¯ã³ããŒãäœæããŸãã ããã¯ãCïŒããããã£-ããã©ã«ãã®ãªã³ã¯ãæž¡ãããã§ãã ã¯ã©ã¹ã®ãŠãŒã¶ãŒã«ã¯ãªã³ã¯ããããã³ããŒãäœæããªãå Žåã¯ãåŸã§ã¬ã·ãã®ææãå€æŽã§ããŸãã èšç»ã«å«ãŸããŠããªããã®ã
ãŸãããã®æçš¿ã§ã¯ãæšæºOOPã®ãã¬ãŒã ã¯ãŒã¯å
ã«çãŸããã©ã ããšzheneriksã䜿çšããªãããã«ããŠããŸãã ããå€ãã®èŽè¡ãç§ãããŠããããšãç解ã§ããããã«ã ã³ãŒãã¯ç°ãªãæ¹æ³ã§ç°¡åã«èšè¿°ã§ããŸãã ããããç§ã®ç®æšã¯ãYAGNIã®åçèªäœãšã³ãŒããè©äŸ¡ããããã€ãã®æ¹æ³ã説æããããšã§ãããã·ã£ãŒãã®ããŸããŸãªå¯èœæ§ã瀺ãããšã§ã¯ãããŸããã ãã¡ãããè©äŸ¡æ¹æ³ã¯èšèªãšãã®æ©èœã«äŸåããŸãã
ãŠãŒã¶ãŒçšã®2çªç®ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã¯ãããããã£ã®å€ïŒã¬ã·ãã®ååïŒãèšå®ããŸããã ãªããªã ç§ãã¡ã®è£œåã¯ãã¶ã€ããŒã«æž¡ãããå€æŽããããšã¯ã§ããŸãããããã§ãããããäœããã®æ¹æ³ã§è¿æ¥åºŠãèšç®ããŸãã ããæ£ç¢ºã«ã¯ãç¹ã«ãã¹ããŒããã¯å€åããå¯èœæ§ããããŸããããã©ãã€ã¢ã«æ©ãããšã¯ãããŸããã éçºè
ã¯é©åã§ãããç Žå£ã§ã¯ãªãåµé ã®ç«å Žã«ãããšä¿¡ããŠããŸãã
äœããã®è¿æ¥ã¡ãœãããæžãå¿
èŠããããŸãã 顧客ã¯æå®ããªãã£ãã®ã§ãæå°äºä¹æ³ã§æãåçŽãªãã®ãèšè¿°ããŸãã åæåã«ç°ãªããééããããããšãèãããšã ä»ã®ãšãããåŸã§èª¿æŽã§ããéã¿ãæžãçããŠãããŸãã
ã³ãŒãã¯ã»ãŒæ¬¡ã®ããã«ãªããŸãã
private double GetDistance(Recipe recipe) { Dictionary<RecipeProduct, double> weights = new Dictionary<RecipeProduct, double>(); weights[RecipeProduct.Salt] = 50; weights[RecipeProduct.Sugar] = 20; weights[RecipeProduct.Egg] = 5; weights[RecipeProduct.Flour] = 0.1; double sum = 0.0; foreach(KeyValuePair<RecipeProduct, double> otherProductAmount in recipe.Products) { var productAmounts = this.Products.Where(p => p.Key == otherProductAmount.Key); if (productAmounts.Count() == 1) { sum += Math.Pow(productAmounts.First().Value - otherProductAmount.Value, 2) * weights[otherProductAmount.Key]; } else { return double.MaxValue; } } return sum; } private RecipeName GetRecipeName() { IEnumerable<Recipe> etalons = ((RecipeName[])Enum.GetValues(typeof(RecipeName))) .Select(recipeName => Recipe.GetReceipt(recipeName)); IEnumerable<KeyValuePair<RecipeName, double>> recipeNamesWithDistances = etalons .Select(e => new KeyValuePair<RecipeName, double>(e.Name, GetDistance(e))); double minDistance = recipeNamesWithDistances.Min(rd => rd.Value); if (minDistance == double.MaxValue) { throw new Exception(" "); } return recipeNamesWithDistances.First(rd => rd.Value == minDistance).Key; }
ãããŠãããããã³ã³ã¹ãã©ã¯ã¿ãŒåŒã³åºãã§ãåœåãè¿œå ãããŸãïŒ
public Recipe(IEnumerable<KeyValuePair<RecipeProduct, double>> products) { Dictionary<RecipeProduct, double> copiedProducts = new Dictionary<RecipeProduct, double>(); foreach (KeyValuePair<RecipeProduct, double> pair in products) { copiedProducts.Add(pair.Key, pair.Value); } this.Products = copiedProducts; this.Name = GetRecipeName(); }
åžžã«ãªã³ã¶ãã©ã€ã§èšç®ããæ¹ãä¿¡é Œæ§ãé«ããªããŸãã ãããããã®å Žåã¯ãåç
§çšãšéåºå®ã¬ã·ãçšã®åœåã®åé¢ãèãåºãå¿
èŠããããŸãã ä»ã®ãšããããã§ååã§ãã
ã芧ã®ãšããããã®ãããªçŸåšã®èŠä»¶ãæºããããã«ã³ãŒããããçŽãããšã¯ãŸã£ããæãããšã§ã¯ãããŸããã äœãå£ããŸããã§ãã ãããŠã¡ããã©æ¡å€§ããŸããã äºåã«äºæž¬ããŠããå Žåããããå®äºããæéã¯ãããŸããã ããããæšæž¬ã§ã¯ãªãäºæž¬ããããšã¯æ¬åœã«æãã§ãã ãã®èŠä»¶ã«åŸã£ãŠãäžèŠã·ã³ãã«ã«èŠãããã®ã³ãŒããæ³åããŠã¿ãŠãã ããã ããã¯ãè¿œå ãã¹ããå¿
èŠãªåãªãã¢ã³ã¹ã¿ãŒã§ãã ãããŠä»ãããã¯åççã«æžãããŠããŸãã
ã³ãŒãã¯å®ç§ã§ã¯ãããŸãããç§ã¯å©ããããšãã§ããŸããã§ããããzhenerikiãšlambdaã«çªå
¥ããŸãã ãã®ãããã³ãŒãã¯ããå°ããããããããã«ãªããŸãã ããã«ãããCïŒãã©ã ãã«æ
£ããŠããªãèªè
ã®ç解ãæãªãããªãããšãé¡ã£ãŠããŸãã ãã¡ãããããã«æžããããšãã§ããŸãã ããããç§ã¯ããå€ãã®äººã
ã«ç解ãããããšããŠããŸãã
ããã§ã¯ãç¹å®ã®ã¢ã«ãŽãªãºã ã«æ¢ã«é¢é£ä»ããããŠããŸããããã®é¡§å®¢ã¯ãããå¿
èŠãšããŸããã§ããã ã€ã°ããã©ããïŒ ããã§ç¶æ³ãç解ããŸãã ããããã顧客ã¯ããã«ç®ã«èŠããçµæãå¿
èŠãšããŸãã ããã¯ããèµ·ãããŸãã ãããã£ãŠãå°ãªããšãããã€ãã®ã¢ã«ãŽãªãºã ãå¿
èŠã§ãã ããããåŸã§å¥ã®ã¢ã«ãŽãªãºã ãå¿
èŠã«ãªã£ãå Žåããã®ã¢ã«ãŽãªãºã ãå¥ã®ã¢ã«ãŽãªãºã ã«çœ®ãæããã®ã«è²»çšã¯ããããŸããã ãŸãã¯ãããã€ããæžããŠéžæããããšãã§ããŸãã ãŸãã¯ãã³ãŒãã®ãŠãŒã¶ãŒããã§ããè¿æ¥æ§ãæ¯èŒããããªã²ãŒããååŸããŸãã
æ確ãªããžãã¹ãä»ã§ã¯è£œé æ¹æ³ã«ã¬ã·ãã®ååã§ã¯ãªããã¬ã·ãèªäœã転éããå¿
èŠããããŸãã ã€ãŸã ãã®ããã«ïŒ
public class BakeryProduct { public BakeryProduct(Recipe recipe) { this.BakeryProductType = recipe.Name; } public RecipeName BakeryProductType { get; private set; } }
ãããŠïŒ
public static BakeryProduct BakeByGasOven(Recipe recipe, double gasLevel) { return gasLevel == 0 ? null : new BakeryProduct(recipe); } public static BakeryProduct BakeByOtherOven(Recipe recipe) { return new BakeryProduct(recipe); }
ããã§ããªãã¡ã¯ã¿ãªã³ã°ã¯éå°ãªã¹ãã¬ã¹ããã¯ã»ã©é ãã
èŠä»¶10æ²¹æãªããªã顧客ã¯ã©ããããããç§ãã¡ã®ã³ãŒããç 究ããç§ãã¡ã®ã³ãŒããå®å
šã«æºåãããŠããªãæãèŠããå Žæãæ¢ããŠããŸãã 9 . . .
â , , , . , . , , , , . ( ))), , .. , .åæ, . , . . , , ? , , . , . , , . , . ? . ãã¹ãã§ã¯ãªãã
, â . . , , â , . , , . . Product. Product? . . , , . , , . . ã€ãŸã , , . , . , â . ? .
. , . ã€ãŸã . , , , , ..
ã€ãŸã â , .
-.
, , : « , . , ( ). . , .»
. â .
public abstract class Article { public double Price { get; private set; } public Article(double price) { this.Price = price; } }
:
public class BakeryProduct : Article { public BakeryProduct(Recipe recipe, double price): base(price) { this.BakeryProductType = recipe.Name; } public RecipeName BakeryProductType { get; private set; } } public class Brick: Article { public Brick(double price) : base(price) { } }
, , .
ãã®ãããªãã®ïŒ
public static BakeryProduct BakeByOtherOven(Recipe recipe, double price) { return new BakeryProduct(recipe, price); }
. . , . , . , â . , , . , .. ( , ..) , . , â .
switch , , , , . . . . , . , .
, , . . . , , . . . . . , . YAGNI , . , , . - YAGNI . .
, . . , , , YAGNI . . . , â .