ããå®å šãªãã¬ãŒã³ããŒã·ã§ã³ã®ããã«ãæ¢æã®ã³ãŒããã¬ã¬ã·ãŒã³ãŒãã«æœè±¡åãé©çšããåŽããæœè±¡åã®åé¡ã«æ³šç®ããŸããã ãã®å Žåããªããžããªã¯ãé«å質ã§å®å šãªã³ãŒããå®çŸããããã®ããŒã«ãšããŠã®ã¿ç§ãã¡ã«èå³ãæã£ãŠããŸãã ãã¡ãããTDDãã©ã¯ãã£ã¹ãé©çšããããã«å¿ èŠãªã®ã¯ãã®ãã¿ãŒã³ã ãã§ã¯ãããŸããã ããã€ãã®å€§ããªãããžã§ã¯ãã§ãå³ã®ãªãé£ã¹ç©ããé£ã¹ãŠãäœãæ©èœããŠäœãæ©èœããªãã®ããèŠãŠãTDDãã©ã¯ãã£ã¹ã«åŸãã®ã«åœ¹ç«ã€ããã€ãã®ã«ãŒã«ãæãã€ããŸããã TDDã®å®è£ ã«é¢ãã建èšçãªæ¹å€ããã®ä»ã®ããªãã¯ãèããŠããããæããŸãã
ãŸããã
å€ããããžã§ã¯ãã§ã¯TDDãäžå¯èœã§ããããšã«æ°ä»ã人ããããããããŸããã ããŸããŸãªã¿ã€ãã®çµ±åãã¹ãïŒUIãã¹ãããšã³ãããŒãšã³ãïŒãããé©ããŠãããšããæèŠããããŸãã å€ãã³ãŒããç解ããã®ã¯é£ããããŸãã ãŸãããšã³ã³ãŒãèªäœã®åã«ãã¹ããæžããšæéã®æ倱ã«ã€ãªããããšãããããŸãã ã³ãŒããã©ã®ããã«æ©èœãããããããªãå ŽåããããŸãã åäœãã¹ãã¯ææšã§ã¯ãªãããšãèæ ®ããŠãçµ±åãã¹ãã®ã¿ã«å¶éãããããã€ãã®ãããžã§ã¯ãã§äœæ¥ããå¿ èŠããããŸããã åæã«ãå€ãã®ãã¹ããäœæãããå€æ°ã®ãµãŒãã¹ãªã©ãéå§ãããŸããããã®çµæãå®éã«ããããäœæããã®ã¯1人ã ãã§ããã
ç·Žç¿äžãå€ãã®ã¬ã¬ã·ãŒã³ãŒãããã£ãããã€ãã®éåžžã«å€§ããªãããžã§ã¯ãã§åãããšãã§ããŸããã ãããã®ã«ã¯ãã¹ããããããããã®ã§ã¯åã«å°å ¥ããã ãã§ããã ç§èªèº«ã2ã€ã®å€§ããªãããžã§ã¯ããéããããšãã§ããŸããã ãããŠã©ãã§ããã©ããããããTDDã¢ãããŒããé©çšããããšããŸããã TDDãç解ããæåã®æ®µéã§ã¯ããã¹ããã¡ãŒã¹ãéçºãšããŠèªèãããŠããŸããã ããããé ããªãã»ã©ããã®åçŽåãããç解ãšãBDDãšåŒã°ããçŸåšã®èŠè§£ãšã®éããããæ確ã«æããã«ãªããŸããã 䜿çšããèšèªãäœã§ãããç§ãã«ãŒã«ãšåŒãã äž»èŠãªãã€ã³ãã¯åããŸãŸã§ãã 誰ããè¯ãã³ãŒããæžãããã®ã«ãŒã«ãšä»ã®ååã®éã«é¡äŒŒç¹ãèŠã€ãããããããŸããã
ã«ãŒã«1ïŒããã ã¢ããïŒã€ã³ãµã€ãã¢ãŠãïŒã䜿çšãã
ãã®ã«ãŒã«ã¯ããã§ã«åäœããŠãããããžã§ã¯ãã«æ°ããã³ãŒããåã蟌ãéã®åæããã³ãœãããŠã§ã¢èšèšã®æ¹æ³ã«ããé¢é£ããŠããŸãã
æ°ãããããžã§ã¯ããèšèšãããšããã·ã¹ãã å šäœãæ瀺ããã®ã¯åœç¶ã®ããšã§ãã ãã®æç¹ã§ãã³ã³ããŒãã³ãã®ã»ãããšã¢ãŒããã¯ãã£ã®å°æ¥ã®æè»æ§ã®äž¡æ¹ãå¶åŸ¡ããŸãã ãããã£ãŠã䟿å©ã§æé©ãªæ¹æ³ã§çžäºã«çµ±åããã¢ãžã¥ãŒã«ãäœæã§ããŸãã ãã®ãããªãããããŠã³ã¢ãããŒãã«ãããå°æ¥ã®ã¢ãŒããã¯ãã£ã®åªããå è¡èšèšãå®è¡ããå¿ èŠãªã¬ã€ããèšè¿°ããæçµçã«å¿ èŠãªãã®ã®å šäœåãææ¡ã§ããŸãã ãã°ãããããšããããžã§ã¯ãã¯ã¬ã¬ã·ãŒã³ãŒããšåŒã°ãããã®ã«å€ãããŸãã ãããŠããããã楜ãã¿ãå§ãŸããŸãã
å€æ°ã®ã¢ãžã¥ãŒã«ãšãããã®éã®äŸåé¢ä¿ãæã€æ¢åã®ãããžã§ã¯ãã«æ°ããæ©èœãçµã¿èŸŒãå¿ èŠããã段éã§ã¯ãèšèšãæ£ããããããã«ãããããã¹ãŠé ã«å ¥ããããšã¯éåžžã«å°é£ã§ãã ãã®åé¡ã®ãã1ã€ã®åŽé¢ã¯ããã®ãããªã¿ã¹ã¯ãå®äºããããã«å¿ èŠãªäœæ¥éã§ãã ãããã£ãŠããã®å Žåãäžããã®ã¢ãããŒããããå¹æçã§ãã ã€ãŸããæåã«å¿ èŠãªã¿ã¹ã¯ã解決ããå®å šãªã¢ãžã¥ãŒã«ãäœæããŠãããæ¢åã®ã·ã¹ãã ã«åã蟌ã¿ãå¿ èŠãªå€æŽã®ã¿ãè¡ããŸãã ãã®å Žåã次ã®ããã«ããã®ã¢ãžã¥ãŒã«ã®å質ãä¿èšŒã§ããŸãã æ©èœã®å®å šãªãŠããããè¡šããŸãã
ã¢ãããŒãã§ã¯ããã¹ãŠãããã»ã©åçŽã§ã¯ãªãããšã«æ³šæããŠãã ããã ããšãã°ãå€ãã·ã¹ãã ã§æ°ããæ©èœãèšèšããå Žåãwillã䜿çšãããäž¡æ¹ã®ã¢ãããŒãã䜿çšããŸãã æåã®åæã§ã¯ãã·ã¹ãã ãè©äŸ¡ããŠãããã¢ãžã¥ãŒã«ã¬ãã«ãŸã§äžããŠããå®è£ ããã·ã¹ãã å šäœã®ã¬ãã«ã«æ»ãå¿ èŠããããŸãã ç§ã®æèŠã§ã¯ãããã§ã®äž»ãªããšã¯ãç¹å®ã®ããŒã«ãšããŠãæ°ããã¢ãžã¥ãŒã«ãå®å šã«æ©èœããç¬ç«ããŠããããšãå¿ããªãããšã§ãã ãã®ã¢ãããŒãã«åºå·ããã°ããã»ã©ãå€ãã³ãŒãã«å ããããå€æŽã¯å°ãªããªããŸãã
ã«ãŒã«2ïŒå€æŽãããã³ãŒãã®ã¿ããã¹ããã
å€ããããžã§ã¯ãã§äœæ¥ããå Žåãã¡ãœãã/ã¯ã©ã¹ã®èãããããã¹ãŠã®ã·ããªãªã®ãã¹ããèšè¿°ããå¿ èŠã¯ãŸã£ãããããŸããã ããã«ãããã€ãã®ã·ããªãªããŸã£ããç¥ããªããããããŸããã ãããã®å€ãããããŸãã ãããžã§ã¯ãã¯ãã§ã«å®çšŒåäžã§ããã¯ã©ã€ã¢ã³ãã¯æºè¶³ããŠããã®ã§ããªã©ãã¯ã¹ã§ããŸãã äžè¬çãªå Žåããã®ãããªã·ã¹ãã ã§ã¯ãå€æŽã®ã¿ãåé¡ãåŒãèµ·ãããŸãã ãããã£ãŠããããã®ã¿ããã¹ãããå¿ èŠããããŸãã
äŸ
éžæããã¢ã€ãã ã®ãã¹ã±ãããäœæããŠããŒã¿ããŒã¹ã«ä¿åãããªã³ã©ã€ã³ã¹ãã¢ã¢ãžã¥ãŒã«ããããŸãã ç¹å®ã®å®è£ ã¯æ°ã«ããŸããã å®è¡æ¹æ³ãå®è¡æ¹æ³-ããã¯ã¬ã¬ã·ãŒã³ãŒãã§ãã 次ã«ãããã§æ°ããåäœãå°å ¥ããå¿ èŠããããŸãããã¹ã±ããã®ã³ã¹ãã1000ãã«ãè¶ ããå Žåã«äŒèšéšéã«éç¥ãéä¿¡ããŸãã ãããç§ãã¡ãèŠãã³ãŒãã§ãã å€æŽãå®è£ ããæ¹æ³ã¯ïŒ
public class EuropeShop : Shop { public override void CreateSale() { var items = LoadSelectedItemsFromDb(); var taxes = new EuropeTaxes(); var saleItems = items.Select(item => taxes.ApplyTaxes(item)).ToList(); var cart = new Cart(); cart.Add(saleItems); taxes.ApplyTaxes(cart); SaveToDb(cart); } }
æåã®ã«ãŒã«ã«ããã°ãå€æŽã¯æå°éãšååã§ãªããã°ãªããŸããã ããŒã¿ã®ããŠã³ããŒãããçšéã®èšç®ãããŒã¿ããŒã¹ãžã®ä¿åã«ã¯èå³ããããŸããã ãããããã§ã«èšç®ããããã¹ã±ããã«èå³ããããŸãã å¿ èŠãªããšãè¡ãã¢ãžã¥ãŒã«ãããã°ãå¿ èŠãªã¿ã¹ã¯ãå®è¡ããŸãã ãããã£ãŠãããããŸãã
public class EuropeShop : Shop { public override void CreateSale() { var items = LoadSelectedItemsFromDb(); var taxes = new EuropeTaxes(); var saleItems = items.Select(item => taxes.ApplyTaxes(item)).ToList(); var cart = new Cart(); cart.Add(saleItems); taxes.ApplyTaxes(cart); // NEW FEATURE new EuropeShopNotifier().Send(cart); SaveToDb(cart); } }
ãã®ãããªéç¥æ©èœã¯ããèªäœã§åäœãããã¹ãããããšãã§ããå€ãã³ãŒãã«å ããããå€æŽã¯æå°éã§ãã ããã¯ãŸãã«ã2çªç®ã®ã«ãŒã«ãèšãããšã§ãã
ã«ãŒã«3ïŒèŠä»¶ã®ã¿ã®ãã¹ã
ãŠããããã¹ããå¿ èŠãšããã·ããªãªã®æ°ãæãäžããªãããã«ãå®éã«ã¯ã¢ãžã¥ãŒã«ããäœãå¿ èŠããèããŠãã ããã ã¢ãžã¥ãŒã«èŠä»¶ãšããŠè¡šãããšãã§ããæå°éã®æ¡ä»¶ã»ããã«ã€ããŠæåã«èšè¿°ããŠãã ããã æ°ããã»ãããè¿œå ãããšãã®æå°ã»ããã¯1ã€ã§ãã¢ãžã¥ãŒã«ã®åäœã¯ã»ãšãã©å€æŽããããåé€ãããšã¢ãžã¥ãŒã«ã¯åäœããªããªããŸãã BDDã¢ãããŒãã¯ãè³ãæ£ããè»éã«ä¹ããã®ã«éåžžã«åªããŠããŸãã
ãŸããã¢ãžã¥ãŒã«ã®ã¯ã©ã€ã¢ã³ãã§ããä»ã®ã¯ã©ã¹ãã¢ãžã¥ãŒã«ãšå¯Ÿè©±ããæ¹æ³ãæ³åããŠãã ããã 圌ãã¯ããªãã®ãŠããããã«ã¹ã¿ãã€ãºããã«ã¯ãã³ãŒãã®10è¡ãèšè¿°ããå¿ èŠããããŸããïŒ ç°¡åã«ã¯ãã·ã¹ãã ã®éšåéã®éä¿¡ãè¯ããªããŸãã ãããã£ãŠãç¹å®ã®åå ãšãªã£ãŠããã¢ãžã¥ãŒã«ãå€ãã³ãŒãããåé¢ããããšããå§ãããŸãã ãã®åŸãSOLIDã®å©ãã«æ¥ãŸãã
äŸ
ä»åºŠã¯ããããã¹ãŠã®ããã«ã³ãŒããå©ããç§ãã¡ã®äžã«æžãããæ¹æ³ãèŠãŠã¿ãŸãããã ãŸãããã¹ã±ããã®äœæã«éæ¥çã«ã®ã¿é¢é£ãããã¹ãŠã®ã¢ãžã¥ãŒã«ãéžæããŸãã ããã¯ãã¢ãžã¥ãŒã«ã®è²¬ä»»ãå²ãåœãŠãæ¹æ³ã§ãã
public class EuropeShop : Shop { public override void CreateSale() { // 1) load from DB var items = LoadSelectedItemsFromDb(); // 2) Tax-object creates SaleItem and // 4) goes through items and apply taxes var taxes = new EuropeTaxes(); var saleItems = items.Select(item => taxes.ApplyTaxes(item)).ToList(); // 3) creates a cart and 4) applies taxes var cart = new Cart(); cart.Add(saleItems); taxes.ApplyTaxes(cart); new EuropeShopNotifier().Send(cart); // 4) store to DB SaveToDb(cart); } }
ãããŠãããããåºå¥ããããšãã§ããŸãã ãã¡ãããäžåºŠã«ãã®ãããªå€æŽãè¡ãããšã¯ã倧èŠæš¡ãªã·ã¹ãã ã§ã¯äžå¯èœã§ãããåŸã ã«è¡ãããšãã§ããŸãã ããšãã°ãå€æŽãçšã¢ãžã¥ãŒã«ã«é¢ä¿ããå Žåãã·ã¹ãã ã®ä»ã®éšåããã®äŸåé¢ä¿ãç°¡çŽ åã§ããŸãã ããã¯ã圌ãžã®åŒ·ãäŸåé¢ä¿ãåãé€ããå°æ¥çã«ã¯èªçµŠèªè¶³ã®ããŒã«ãšããŠäœ¿çšããã®ã«åœ¹ç«ã¡ãŸãã
public class EuropeShop : Shop { public override void CreateSale() { // 1) extracted to a repository var itemsRepository = new ItemsRepository(); var items = itemsRepository.LoadSelectedItems(); // 2) extracted to a mapper var saleItems = items.ConvertToSaleItems(); // 3) still creates a cart var cart = new Cart(); cart.Add(saleItems); // 4) all routines to apply taxes are extracted to the Tax-object new EuropeTaxes().ApplyTaxes(cart); new EuropeShopNotifier().Send(cart); // 5) extracted to a repository itemsRepository.Save(cart); } }
ãã¹ãã«é¢ããŠã¯ããããã®ã·ããªãªã§ããŸãããããšãã§ããŸãã ãããŸã§ã®ãšããããããã®å®è£ ã«ã¯èå³ããããŸããã
public class EuropeTaxesTests { public void Should_not_fail_for_null() { } public void Should_apply_taxes_to_items() { } public void Should_apply_taxes_to_whole_cart() { } public void Should_apply_taxes_to_whole_cart_and_change_items() { } } public class EuropeShopNotifierTests { public void Should_not_send_when_less_or_equals_to_1000() { } public void Should_send_when_greater_than_1000() { } public void Should_raise_exception_when_cannot_send() { } }
ã«ãŒã«4ïŒãã¹ãæžã¿ã³ãŒãã®ã¿ãè¿œå
äžèšã§æžããããã«ãå€ãã³ãŒããžã®å€æŽãæå°éã«æããå¿ èŠããããŸãã ãããè¡ãã«ã¯ãå€ãã³ãŒããšæ°ãã/å€æŽãããã³ãŒããåé¢ã§ããŸãã æ°ããã³ãŒãã¯ãåäœãã¹ãã§åäœã確èªã§ããã¡ãœããã«åºå¥ã§ããŸãã ãã®ã¢ãããŒãã¯ãé¢é£ãããªã¹ã¯ã軜æžããã®ã«åœ¹ç«ã¡ãŸãã ãã¬ã¬ã·ãŒã³ãŒããå¹æçã«äœ¿çšãããã§èª¬æãããŠãã2ã€ã®ææ³ããããŸãïŒä»¥äžã®æ¬ãžã®ãªã³ã¯ïŒã
ã¹ãã©ãŠãã¡ãœãã/ã¯ã©ã¹-ãã®ææ³ã«ãããå€ãã³ãŒãã«æ°ããã³ãŒããéåžžã«å®å šã«åã蟌ãããšãã§ããŸãã éç¥æ©èœãè¿œå ããæ¹æ³ã¯ããã®ã¢ãããŒãã®äŸã§ãã
ã©ããæ¹æ³-ããå°ãè€éã§ãããæ¬è³ªã¯åãã§ãã åžžã«é©åã§ãããšã¯éããŸããããæ°ããã³ãŒããå€ãã³ãŒãã®å/åŸã«åŒã³åºãããå Žåã®ã¿ã§ãã 責任ãå²ãåœãŠãéã«ãApplyTaxesã¡ãœãããžã®2ã€ã®åŒã³åºãã1ã€ã®åŒã³åºãã«çœ®ãæããããŸããã ãããè¡ãã«ã¯ãäœæ¥ã®ããžãã¯ãããŸãå£ããã«ç¢ºèªã§ããããã«ã2çªç®ã®ã¡ãœãããå€æŽããå¿ èŠããããŸããã ã¯ã©ã¹ãå€æŽã«èŠããŸããã
public class EuropeTaxes : Taxes { internal override SaleItem ApplyTaxes(Item item) { var saleItem = new SaleItem(item) { SalePrice = item.Price*1.2m }; return saleItem; } internal override void ApplyTaxes(Cart cart) { if (cart.TotalSalePrice <= 300m) return; var exclusion = 30m/cart.SaleItems.Count; foreach (var item in cart.SaleItems) if (item.SalePrice - exclusion > 100m) item.SalePrice -= exclusion; } }
ãããŠãããã¯åŸã§ãã ãã¹ã±ããã®èŠçŽ ãæäœããããžãã¯ã¯å°ãå€æŽãããŸããããäžè¬çã«ã¯ãã¹ãŠãåããŸãŸã§ãã ãã®å Žåãå€ãã¡ãœããã¯æåã«æ°ããApplyToItemsãåŒã³åºãã次ã«ä»¥åã®ããŒãžã§ã³ãåŒã³åºããŸãã ããããã®ãã¯ããã¯ã®æ¬è³ªã§ãã
public class EuropeTaxes : Taxes { internal override void ApplyTaxes(Cart cart) { ApplyToItems(cart); ApplyToCart(cart); } private void ApplyToItems(Cart cart) { foreach (var item in cart.SaleItems) item.SalePrice = item.Price*1.2m; } private void ApplyToCart(Cart cart) { if (cart.TotalSalePrice <= 300m) return; var exclusion = 30m / cart.SaleItems.Count; foreach (var item in cart.SaleItems) if (item.SalePrice - exclusion > 100m) item.SalePrice -= exclusion; } }
ã«ãŒã«5ïŒé ãããäŸåé¢ä¿ã®ãç Žå£ã
ãã®ã«ãŒã«ã¯ãå€ãã³ãŒãã®æ倧ã®æªã«é¢ãããã®ã§ããããBOã®ã¡ãœããå ã§newæŒç®åã䜿çšããŠãä»ã®BOããªããžããªããŸãã¯ä»ã®è€éãªãªããžã§ã¯ããäœæããããšã§ãã ãªããããæªãã®ã§ããïŒ æãç°¡åãªèª¬æïŒããã«ãããã·ã¹ãã ã®åéšåãé«åºŠã«æ¥ç¶ãããäžè²«æ§ãäœäžããŸãã ããã«çãïŒãäœçµåãé«åéãã®ååã«éåããŸãã å察åŽããèŠããšããã®ãããªã³ãŒãã¯éåžžã«é£ãããç¬ç«ããç¬ç«ããããŒã«ã«åé¢ã§ããŸããã ãã®ãããªé ããäŸåé¢ä¿ãäžåºŠã«åãé€ãããšã¯éåžžã«æéãããããŸãã ããããããã¯åŸã ã«è¡ãããšãã§ããŸãã
æåã«ããã¹ãŠã®äŸåé¢ä¿ã®åæåãã³ã³ã¹ãã©ã¯ã¿ãŒã«è»¢éããå¿ èŠããããŸãã ç¹ã«ãããã¯æ°ããæŒç®åãšã¯ã©ã¹ã®äœæã«é©çšãããŸãã ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãåãåãããã®ServiceLocatorãããå Žåã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒããåé€ããŠãå¿ èŠãªãã¹ãŠã®ã€ã³ã¿ãŒãã§ã€ã¹ãååŸã§ããããã«ããå¿ èŠããããŸãã
第äºã«ãå€éšBO /ãªããžããªã®ã€ã³ã¹ã¿ã³ã¹ãæ ŒçŽããå€æ°ã«ã¯ãæœè±¡åãã§ããã°ã€ã³ã¿ãŒãã§ãŒã¹ãå¿ èŠã§ãã ããè¯ãã€ã³ã¿ãŒãã§ãŒã¹ããªã© éçºè ã®æããã£ãšè§£ããŸãã æçµçã«ãããã«ããã¢ãžã¥ãŒã«ããã¢ãããã¯ãªã€ã³ã¹ãã¥ã«ã¡ã³ããäœæã§ããããã«ãªããŸãã
第äžã«ã¯ãå倧ãªæ¹æ³ã§ãã·ãŒããæŸçœ®ããªãã§ãã ããã ããã¯ãã¡ãœããããã®ååã§ç€ºãããŠãã以äžã®ããšãè¡ã£ãŠããããšãæ確ã«ç€ºããŠããŸãã ãããŠããã¯ããã¡ãã«ã®æ³åã§ãããœãªããã®éåã®å¯èœæ§ã瀺ããŠããŸãã
äŸ
äžèšã®ãã¹ã±ãããå€æŽãããåŸããã¹ã±ãããäœæããã³ãŒããèŠãŠã¿ãŸãããã ãã¹ã±ãããäœæããã³ãŒããããã¯ã®ã¿ãå€æŽãããŸããã æ®ãã¯å€éšã¯ã©ã¹ã«å²ãåœãŠãããä»»æã®å®è£ ã§çœ®ãæããããšãã§ããŸãã EuropeShopã¯ã©ã¹ã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒã§æ瀺çã«è¡šãããç¹å®ã®ãã®ãå¿ èŠãšããã¢ãããã¯ããŒã«ã®åœ¢åŒãåããŸãã ã³ãŒããç解ãããããªããŸãã
public class EuropeShop : Shop { private readonly IItemsRepository _itemsRepository; private readonly Taxes.Taxes _europeTaxes; private readonly INotifier _europeShopNotifier; public EuropeShop() { _itemsRepository = new ItemsRepository(); _europeTaxes = new EuropeTaxes(); _europeShopNotifier = new EuropeShopNotifier(); } public override void CreateSale() { var items = _itemsRepository.LoadSelectedItems(); var saleItems = items.ConvertToSaleItems(); var cart = new Cart(); cart.Add(saleItems); _europeTaxes.ApplyTaxes(cart); _europeShopNotifier.Send(cart); _itemsRepository.Save(cart); } }
ã«ãŒã«6ïŒå°ããªå€§ããªãã¹ããããè¯ãã§ã
倧èŠæš¡ãªãã¹ãã¯ããŠãŒã¶ãŒã¹ã¯ãªããããã¹ãããããšããããŸããŸãªçµ±åãã¹ãã§ãã 確ãã«ããããã¯éèŠã§ãããã³ãŒãã®åŸãã«ããIFã®ããžãã¯ããã§ãã¯ããã®ã¯éåžžã«é«äŸ¡ã§ãã ãã®çµæãã¢ãã¥ã¬ããã§èŠãããç¹å¥ãªã¹ãŒããçã1人ã®éçºè ã®ã¿ãããã§äœããå€æŽã§ããŸãã ãã®ãããªãã¹ããäœæããã«ã¯ãæ©èœèªäœãäœæããã®ãšåããããã®æéãå¿ èŠã§ãã ãããããµããŒãããããšã¯ãå€æŽããã®ãæãã ãã®å¥ã®ã¬ã¬ã·ãŒã³ãŒãã§ãã ãã ãããããã¯åãªããã¹ãã§ãïŒ
ãªãããã«ãããªãã®ç©Žãšã圌ãã¯ãã¹ããå¿ èŠãšãããŠããã©ã®ãããªãã®ãå ±æããªããã°ãªããªãå¯èœfakapeã«ã€ããŠã®ãããã«èŠåããæ確ã«ãã®éšéã«ä»çãããšããåžæããã¹ãããããã«ãçµ±åãã¹ããããŠã¿ãŠãã ããããŠã³ããã¶ã€ããŒã¬ãŒãäžã®ã¹ããããžã çµ±åãã¹ããå¿ èŠãªå Žåã¯ãè¯å®çããã³åŠå®çãªçžäºäœçšã·ããªãªãå«ããæå°éã®ãã¹ãã»ãããäœæããŸãã ã¢ã«ãŽãªãºã ã確èªããå¿ èŠãããå Žåã¯ãåäœãã¹ããäœæããæå°éã®ã»ããã«å¶éããŠãã ããã
ã«ãŒã«7ïŒãã©ã€ããŒãã¡ãœããããã¹ãããªã
çªç¶ãã©ã€ããŒãã¡ãœããããã¹ããããå Žåãã©ãããæŸèæã«æ§ããããã§ãã äžéšã®äººã¯ããã§äœã®åé¡ãèŠãŠããŸããã ããããããŠã£ãã·ã¥ãªã¹ããã®çç±ãèŠãŠã¿ãŸãããã ãã©ã€ããŒãã¡ãœãããè€éããããããããªãã¯ã¡ãœããããåŒã³åºãããªãã³ãŒããå«ãŸããŠããå¯èœæ§ããããŸãã ããªããèããããšãã§ããä»ã®çç±ã¯ããæªããã³ãŒãããã¶ã€ã³ã®ç¹åŸŽã§ãããšå€æããã§ãããã ã»ãšãã©ã®å Žåããã©ã€ããŒãã¡ãœããã®ã³ãŒãã®äžéšãå¥ã®ã¡ãœãã/ã¯ã©ã¹ã«å²ãåœãŠãå¿ èŠããããŸãã æåã®SOLIDååã«éåããŠããªãã確èªããŸããïŒ ãããããããè¡ã䟡å€ããªãæåã®çç±ã§ãã 2çªç®ã¯ããã®æ¹æ³ã§ãã¢ãžã¥ãŒã«å šäœã®åäœã§ã¯ãªãããããã©ã®ããã«è¡ããããã確èªããããšã§ãã å éšå®è£ ã¯ãã¢ãžã¥ãŒã«ã®åäœã«é¢ä¿ãªãç°ãªãå ŽåããããŸãã ãããã£ãŠããã®å Žåãè匱ãªãã¹ããè¡ââãããå¿ èŠä»¥äžã«ãµããŒãã«æéãããããŸãã
ãã©ã€ããŒãã¡ãœããããã¹ãããå¿ èŠãé¿ããããã«ãã¯ã©ã¹ããäœãç¥ããªãã¢ãããã¯ããŒã«ã®ã»ãããšèããŠãã ããã ãã¹ãããŠããåäœãæåŸ ããŸãã ãã®ãã¥ãŒã¯ãã¢ã»ã³ããªã¯ã©ã¹ã«ãæå¹ã§ãã ã¯ã©ã€ã¢ã³ããïŒä»ã®ã¢ã»ã³ããªããïŒå©çšã§ããã¯ã©ã¹ã¯ãããªãã¯ã«ãªããå éšäœæ¥ãå®è¡ããã¯ã©ã¹ã¯ãã©ã€ããŒãã«ãªããŸãã ãã ããã¡ãœãããšã¯ç°ãªããŸãã å éšã¯ã©ã¹ã¯è€éã«ãªãå¯èœæ§ããããããå éšã¯ã©ã¹ãäœæããŠãã¹ãããããšãã§ããŸãã
äŸ
ããšãã°ãEuropeTaxesã¯ã©ã¹ã®ãã©ã€ããŒãã¡ãœããã§1ã€ã®æ¡ä»¶ããã¹ãããããã«ããã®ã¡ãœããã®ãã¹ããäœæããŸããã ç§ã¯çšéãç¹å®ã®æ¹æ³ã§é©çšãããããšãæåŸ ããã®ã§ããã¹ãã«ã¯ãããåæ ãããŸãã ãã¹ãèªäœã§ã¯ãçµæãã©ããªããããã³ã§æ°ãããããæšæºãšããŠåããã¯ã©ã¹ããåãçµæãæåŸ ããŸããã
public class EuropeTaxes : Taxes { // code skipped private void ApplyToCart(Cart cart) { if (cart.TotalSalePrice <= 300m) return; // <<< I WANT TO TEST THIS CONDIFTION var exclusion = 30m / cart.SaleItems.Count; foreach (var item in cart.SaleItems) if (item.SalePrice - exclusion > 100m) item.SalePrice -= exclusion; } } // test suite public class EuropeTaxesTests { // code skipped [Fact] public void Should_apply_taxes_to_cart_greater_300() { #region arrange // list of items which will create a cart greater 300 var saleItems = new List<Item>(new[]{new Item {Price = 83.34m}, new Item {Price = 83.34m},new Item {Price = 83.34m}}) .ConvertToSaleItems(); var cart = new Cart(); cart.Add(saleItems); const decimal expected = 83.34m*3*1.2m; #endregion // act new EuropeTaxes().ApplyTaxes(cart); // assert Assert.Equal(expected, cart.TotalSalePrice); } }
8ã«ãŒã«ïŒã¢ã«ãŽãªãºã æè¡ããã¹ãããªãã§ãã ããã
ããã§ã¯ãã«ãŒã«ã®ååã®éžæã«å€±æããŸããããããè¯ãååã¯ãŸã åºãŠããŸããã ãMoquistsãïŒãã¹ãã«æ¿¡ãã人ïŒã®äžã«ã¯ãç¹å®ã®ã¡ãœãããžã®åŒã³åºãåæ°ããã§ãã¯ããããåŒã³åºãèªäœãæ€èšŒããããã人ãããŸããã€ãŸããã¡ãœããã®å éšåäœããã§ãã¯ããŸãã ããã¯ãã©ã€ããŒããã¹ããšåããããæªãã§ãã å¯äžã®éãã¯ããã®ãããªãã§ãã¯ã®é©çšã¬ãã«ã§ãã ãã®ã¢ãããŒãã§ããå€ãã®è匱ãªãã¹ããè¡ââããããããTDDãéåžžã®ããã«èªèãããªãå ŽåããããŸãã
ã«ãŒã«9ïŒãã¹ããªãã§ã¬ã¬ã·ãŒã³ãŒããå€æŽããªãã§ãã ãã
ãããæãéèŠãªã«ãŒã«ã§ãããªããªã ããŒã ããã®ãããªéããã©ããšããé¡æãåæ ããŠããŸãã ãã®æ¹åã«ç§»åããããšãã欲æ±ããªããã°ãäžèšã§è¿°ã¹ããã¹ãŠã®ããšã¯ç¹å¥ãªæå³ãæã¡ãŸããã ãªããªã éçºè ãTDDã®äœ¿çšãæãŸãªãå ŽåïŒãã®æå³ãç解ããŠããªããå©ç¹ãåãããªããªã©ïŒãçã®å©ç¹ã¯ããããã©ãã»ã©å°é£ã§å¹æããªããã絶ããè°è«ããããšã«ãã£ãŠæãªãããŸãã
TDDãé©çšããå Žåã¯ãããŒã ã§è©±ãåãã[å®äºã®å®çŸ©]ã«è¿œå ããŠé©çšããŠãã ããã æ°ãããã®ãã¹ãŠãšåæ§ã«ãæåã¯é£ããã§ãããã ä»ã®ã¢ãŒããšåæ§ã«ãTDDã«ã¯çµ¶ãéãªãç·Žç¿ãå¿ èŠã§ãããåŠã¶ã«ã€ããŠåã³ãããããããŸãã åŸã ã«ãæžãããåäœãã¹ããå€ããªããã·ã¹ãã ã®å¥å šæ§ãæãå§ããæåã®æ®µéã§èŠä»¶ã説æããã³ãŒãã®æžãããããè©äŸ¡ãå§ããŸãã MicrosoftãšIBMã§å®éã®å€§èŠæš¡ãããžã§ã¯ãã§å®æœãããTDDç 究ããããå®çšŒåã·ã¹ãã ã®ãã°ã40ïŒ ãã80ïŒ ã«æžå°ããããšã瀺ãããŠããŸãã ïŒä»¥äžã®ãªã³ã¯ãåç §ïŒã
ãªãã·ã§ãã«
- ãã€ã±ã«ãã§ã¶ãŒãºèãã¬ã¬ã·ãŒã³ãŒããå¹æçã«äœ¿çšããã
- ã¬ã¬ã·ã³ãŒãã§éŠãŸã§ã®TDD
- ç Žæé ãããäŸåé¢ä¿
- ã¬ã¬ã·ãŒã³ãŒãã®ã©ã€ããµã€ã¯ã«
- ã¯ã©ã¹ã§ãã©ã€ããŒãã¡ãœãããåäœãã¹ãããå¿ èŠããããŸããïŒ
- ãŠããããã¹ãã®å éš
- 5 TDDããã³ãŠããããã¹ãã«é¢ããäžè¬çãªèª€è§£
- åäœãã¹ãã®æŠèŠ5ïŒãã¹ã容ææ§ã®åã®ããšã§ã®ã¬ã¬ã·ãŒã³ãŒãã®äŸµå ¥
- ãã¡ãã«ã®æ³å