自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

ZOMBIES:為什么簡潔性是交付健壯軟件的關(guān)鍵(五)

開發(fā)
當(dāng)你堅(jiān)持最簡場景時(shí),你最終會得到最簡單的解決方案。

在前面的文章中,我已經(jīng)解釋了為什么將編程問題看作一整群喪尸來處理是錯(cuò)誤的。我用 ZOMBIES 方法來解釋為什么循序漸進(jìn)地處理問題更好。

ZOMBIES 表示以下首字母縮寫:

  • Z – 最簡場景(Zero)
  • O – 單元素場景(One)
  • M – 多元素場景(Many or more complex)
  • B – 邊界行為(Boundary behaviors)
  • I – 接口定義(Interface definition)
  • E – 處理特殊行為(Exercise exceptional behavior)
  • S – 簡單場景用簡單的解決方案(Simple scenarios, simple solutions)

在系列的前四篇文章中,我展示了 ZOMBIES 方法的前六個(gè)原則(LCTT譯注:原文為前五個(gè),應(yīng)為筆誤)。

第一篇中 實(shí)現(xiàn)了最簡場景,它為代碼提供了最簡可行路徑。第二篇文章中執(zhí)行了 單元素場景和多元素場景上的測試。第三篇中介紹了 邊界和接口。 第四篇中處理 特殊行為。在本文中,我將介紹最后一項(xiàng):簡單場景用簡單的解決方案。

簡單場景用簡單的解決方案

回顧這個(gè)網(wǎng)購 API 的實(shí)現(xiàn)過程,你會發(fā)現(xiàn)總是有目的性地堅(jiān)持考慮最簡單的場景。在這個(gè)過程中,最終你會得到最簡單的解決方案。

ZOMBIES 方法通過堅(jiān)持簡潔性來幫助你交付健壯優(yōu)雅的解決方案。

勝利了嗎?

似乎一切工作都結(jié)束了,一個(gè)不那么認(rèn)真負(fù)責(zé)的工程師很可能會宣布勝利。但開明的工程師總是會探索得更深一點(diǎn)。

我一直推薦做 變異測試mutation testing。在圓滿結(jié)束這個(gè)練習(xí)項(xiàng)目,開始新的征程之前,用變異測試來敲打敲打你的解決方案是明智的。況且你也不得不承認(rèn),變異很適合對付喪尸的。

你可以在開源網(wǎng)站 Stryker.NET 上進(jìn)行變異測試。

Mutation testing

Mutation testing

看起來有一個(gè)存活的變異體。這可不是好兆頭。

這意味著什么呢?當(dāng)你自認(rèn)為解決方案無懈可擊的時(shí)候,Stryker.NET 卻表示在你的地盤上并非一切安好。

讓我們來看看這個(gè)存活下來的煩人變異體:

Surviving mutant

Surviving mutant

變異測試工具將

if(total > 500.00) {

變異為:

if(total >= 500.00) {

然后運(yùn)行測試,結(jié)果對于這個(gè)變化沒有一個(gè)測試失敗。如果業(yè)務(wù)處理代碼中發(fā)生了一處變動卻沒有任何一個(gè)測試失敗,這就意味著你遇到一個(gè)存活的變異體。

為什么要在意變異體

為什么存活的變異體是麻煩的征兆呢?因?yàn)槟銓懙臉I(yè)務(wù)處理邏輯代碼控制著整個(gè)系統(tǒng)的行為。如果業(yè)務(wù)處理邏輯改變,系統(tǒng)的行為也應(yīng)該隨之改變。而系統(tǒng)行為的改變應(yīng)該會導(dǎo)致測試表示的期望被違反。如果沒有期望被違反,那就說明這些期望對系統(tǒng)行為的描述還不夠準(zhǔn)確。這也意味著你的業(yè)務(wù)處理邏輯中存在漏洞。

要解決這個(gè)問題,你需要干掉這個(gè)存活下來的變異體。要怎么做呢?一般來說,有存活的變異體意味著有期望被遺漏了。

仔細(xì)檢查代碼,梳理已定義的期望,看看漏掉了什么:

  • 期望 0:新建購物框里有零個(gè)商品(這隱含了總價(jià)為 ¥0)。
  • 期望 1:向購物框添加一件商品的結(jié)果是購物框里有一件商品,如果這件商品的價(jià)格是 ¥10,那么總價(jià)為 ¥10。
  • 期望 2:向購物框添里加入一件價(jià)值 ¥10 的商品,再加入一件價(jià)值 ¥20 的商品,總價(jià)是 ¥30 。
  • 期望 3:關(guān)于從購物框移除商品的期望。
  • 期望 4:總價(jià)大于 ¥500 時(shí)打,享受九折優(yōu)惠。

缺了什么呢?根據(jù)變異測試報(bào)告,你沒有定義訂單總價(jià)剛好為 ¥500 的銷售策略。你已經(jīng)定義訂單總額大于 ¥500 和小于 ¥500 時(shí)的情況。

定義邊界情況的期望:

[Fact]
public void Add2ItemsTotal500GrandTotal500() {
	var expectedGrandTotal = 500.00;
	var actualGrandTotal = 450;
	Assert.Equal(expectedGrandTotal, actualGrandTotal);
}

第一步先寫一個(gè)假的實(shí)現(xiàn)讓測試失敗?,F(xiàn)在共有 9 個(gè)微測試。其中 8 個(gè)通過,第 9 個(gè)失敗了:

[xUnit.net 00:00:00.57] tests.UnitTest1.Add2ItemsTotal500GrandTotal500 [FAIL]
  X tests.UnitTest1.Add2ItemsTotal500GrandTotal500 [2ms]
  Error Message:
   Assert.Equal() Failure
Expected: 500
Actual: 450
[...]
Test Run Failed.
Total tests: 9
     Passed: 8
     Failed: 1
 Total time: 1.5920 Seconds

將硬編碼值替換成正樣例的預(yù)期代碼:

[Fact]
public void Add2ItemsTotal500GrandTotal500() {
	var expectedGrandTotal = 500.00;
	Hashtable item1 = new Hashtable();
	item1.Add("0001", 400.00);
	shoppingAPI.AddItem(item1);
	Hashtable item2 = new Hashtable();
	item2.Add("0002", 100.00);
	shoppingAPI.AddItem(item2);
	var actualGrandTotal = shoppingAPI.CalculateGrandTotal(); }

共添加了兩件商品,一件價(jià)值 ¥400,另一件價(jià)值 ¥100,總價(jià)是 ¥500。調(diào)用計(jì)算總價(jià)的函數(shù),期望的總價(jià)是 ¥500。

運(yùn)行,9 個(gè)測試全部通過!

Total tests: 9
     Passed: 9
     Failed: 0
 Total time: 1.0440 Seconds

現(xiàn)在是揭曉真相的時(shí)刻。這個(gè)新增的期望能夠清理掉所有的變異體嗎?運(yùn)行變異測試來看看結(jié)果:

Mutation testing success

Mutation testing success

成功了!10 個(gè)變異體全都被干掉了。太棒了!現(xiàn)在你可以放心地發(fā)布這個(gè) API 了。

結(jié)語

如果從這次練習(xí)中有什么收獲的話,那就是 技術(shù)性拖延skillful procrastination

主動拖延

拖延對于軟件工程師來說并不是一件容易的事情。我們總是急于動手寫代碼。我們熟悉各種設(shè)計(jì)模式、反模式、編程原則和現(xiàn)成的解決方案。我們總是迫不及待想將它們應(yīng)用到可執(zhí)行的代碼中,并且傾向于一次性做大量的工作。所以在行動之前仔細(xì)考慮每個(gè)步驟是一種美德。

這個(gè)練習(xí)說明 ZOMBIES 方法能夠通過一系列深思熟慮的小步驟來幫你實(shí)現(xiàn)解決方案。但是有一點(diǎn)需要特別注意,根據(jù) Yagni 原則,這些深思熟慮常常會飛得太遠(yuǎn),以至于最終形成一個(gè)大而全的系統(tǒng)。這會產(chǎn)生臃腫、緊密耦合的系統(tǒng)。

迭代式開發(fā)與增量式開發(fā)

在這次練習(xí)給我們的另一個(gè)重要收獲是讓我們意識到保持系統(tǒng)持續(xù)可用的唯一方法是采用迭代式的開發(fā)方法。你通過改造已有代碼開發(fā)出整個(gè)購物 API。這種改造工作是在迭代優(yōu)化解決方案的過程中不可避免的。

很多團(tuán)隊(duì)混淆了迭代和增量。這是兩個(gè)完全不同的概念。

增量式方法是假設(shè)是你有完整清晰的需求,然后通過增量累加的方式來構(gòu)建解方案。大體上來說,你一點(diǎn)點(diǎn)地構(gòu)建各個(gè)部分,然后將所有的部分組裝在一起。大功告成!解決方案已經(jīng)準(zhǔn)備好交付了!

相比之下,迭代式方法中,你并不很確定自己需要交付給客戶的是什么。因?yàn)檫@個(gè)原因,你更加小心謹(jǐn)慎。你會小心翼翼地避免破壞能夠運(yùn)行的系統(tǒng)(也就是說系統(tǒng)處于穩(wěn)態(tài))。如果不得不擾動已有的平衡,你也會采取最小侵入性的方式。你專注于用盡可能小的工作量來快速完成每次得改動工作。你傾向于讓系統(tǒng)盡快回到穩(wěn)態(tài)。

這就是為什么迭代式方法在真正實(shí)現(xiàn)一個(gè)功能之前總是先提供一個(gè)假實(shí)現(xiàn)。你硬編碼一系列的期望,以驗(yàn)證小的修改不會導(dǎo)致系統(tǒng)無法運(yùn)行。然后進(jìn)行必要的修改,用實(shí)際處理代碼替換硬編碼的值。

作為經(jīng)驗(yàn)法則,在迭代方法中,你的目標(biāo)是通過設(shè)計(jì)期望(微測試),對代碼進(jìn)行不斷改進(jìn)。每進(jìn)行一次改進(jìn),你都要檢驗(yàn)系統(tǒng),以確保它處于工作狀態(tài)。以這種方式不斷前進(jìn),最終會達(dá)到滿足所有期望的程度,并且此時(shí)代碼已經(jīng)被重構(gòu),沒有任何存活的變異體了。

一旦達(dá)到了這種狀態(tài),你就可以相當(dāng)自信地交付解決方案了。

由衷感謝 Kent Beck、 Ron Jeffries 和GeePaw Hill 在我的軟件工程學(xué)習(xí)道路的啟發(fā)。

愿 ZOMBIES 方法在軟件開發(fā)的征程上幫助到你。

責(zé)任編輯:龐桂玉 來源: Linux中國
相關(guān)推薦

2022-03-11 10:31:49

Go語音

2022-02-17 16:44:19

函數(shù)Go 語言高階函數(shù)

2021-10-27 11:49:09

勒索軟件惡意軟件安全

2021-01-14 10:04:29

人工智能AI機(jī)器學(xué)習(xí)

2013-02-21 16:44:43

惠普云計(jì)算

2019-07-19 09:35:28

Linux發(fā)行版MX Linux

2020-09-22 12:38:18

軟件

2023-07-12 11:14:36

智能建筑數(shù)據(jù)建模

2020-05-29 14:10:23

軟件開發(fā) 開源

2022-12-29 10:16:12

觀察性系統(tǒng)監(jiān)視

2013-11-04 17:04:22

容錯(cuò)可靠

2017-07-18 09:02:05

磁盤克隆軟件

2023-08-03 11:06:46

5G工業(yè)4.0物聯(lián)網(wǎng)

2023-07-04 16:28:09

2019-09-26 18:30:03

2021-11-29 18:06:04

CIOCFO數(shù)字計(jì)劃

2019-01-02 08:02:08

物聯(lián)網(wǎng)可見性IOT

2020-06-18 07:16:22

聯(lián)網(wǎng)車隊(duì)物聯(lián)網(wǎng)IOT

2023-10-10 14:57:49

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號