問題的分類
最初在1999年被Dave Snowden開發(fā)出來的Cynefin框架嘗試把世界上的問題劃分到了5個域中(大類):
簡單(Simple)問題,該域中的因果關(guān)系非常明顯,解決這些問題的方法是 感知-分類-響應(yīng)(Sense-Categorise-Respond),有對應(yīng)的最佳實(shí)踐
復(fù)合(Complicated)問題,該域中的因果關(guān)系需要分析,或者需要一些其他形式的調(diào)查和/或?qū)I(yè)知識的應(yīng)用,解決這些問題的方法是感知-分析-響應(yīng)(Sense-Analyze-Respond),有對應(yīng)的好的實(shí)踐
復(fù)雜(Complex)問題,該域中的因果關(guān)系僅能夠從回顧中發(fā)現(xiàn),解決這些問題的方法是探索-感知-響應(yīng)(Probe-Sense-Respond),我們能夠感知涌現(xiàn)實(shí)踐(emergent practice)
混亂(Chaotic)問題,該域中沒有系統(tǒng)級別的因果關(guān)系,方法是行動-感知-響應(yīng)(Act-Sense-Respond),我們能夠發(fā)現(xiàn)新穎實(shí)踐(novel practice)
失序(Disorder)問題,該域中沒有因果關(guān)系,不可感知,其中的問題也無法被解決
顯然,軟件開發(fā)過程更多地是一個復(fù)雜(Complex)問題。在一個產(chǎn)品被開發(fā)出來之前,不確定性非常高,團(tuán)隊(duì)(包括業(yè)務(wù)人員和技術(shù)人員)對產(chǎn)品的知識也是最少的,而且需要大量的學(xué)習(xí)和嘗試才可以明確下一步可能的方向。不幸的是,很多時候我們需要在一開始(不確定性最高的時候)就為項(xiàng)目做計(jì)劃。這種從傳統(tǒng)行業(yè)中非常適合的方法在軟件開發(fā)領(lǐng)域不再適用,這也是敏捷開發(fā)、精益等方法論在軟件開發(fā)中更加適合的原因。
正因?yàn)檐浖_發(fā)事實(shí)上是一個學(xué)習(xí)的過程,我們學(xué)習(xí)到的新知識反過來會幫助我們對問題的定義,從而帶來變化。這里的變化可能來自兩個方向:功能性非功能性。
功能性的變化指隨著對業(yè)務(wù)的深入理解、或者已有業(yè)務(wù)規(guī)則為了匹配市場而產(chǎn)生的變化。比如支付方式由傳統(tǒng)的貨到付款變成了網(wǎng)銀付款,又變成了微信支付、支付寶掃碼等等。一個原始的電商平臺僅僅提供基本的購物服務(wù),但是后來可以根據(jù)已有數(shù)據(jù)產(chǎn)生推薦商品,從來帶來更大的流量。這些變化需要體現(xiàn)在已有的代碼中,而對代碼的修改往往是牽一發(fā)而動全身。
非功能性的變化是指隨著業(yè)務(wù)的發(fā)展,用戶規(guī)模的增加,數(shù)據(jù)量的變化,安全認(rèn)知的變化等產(chǎn)生的新的需求。比如100個用戶的時候無需考慮性能問題,但是100萬用戶的時候,性能就變成了必須重視的問題。天氣預(yù)報(bào)應(yīng)用的數(shù)據(jù)安全性和網(wǎng)絡(luò)銀行的數(shù)據(jù)安全性要求也大不相同。
而在業(yè)務(wù)提出一個需求的時候,往往只是一個簡化過的版本。
非功能性復(fù)雜性
這是一個經(jīng)過設(shè)計(jì)師精確設(shè)計(jì)的界面,在它被設(shè)計(jì)出來之前,用戶事實(shí)上無法準(zhǔn)確的描述出它。設(shè)計(jì)過程中經(jīng)歷了很多的諸如:
-
線框圖
-
顏色的確定
-
交互的動畫
-
信息層次
往復(fù)多次之后,界面確定了。在沒有仔細(xì)思考使用場景的時候,開發(fā)會誤以為這個功能非常簡單。但是如果你是一個有經(jīng)驗(yàn)的開發(fā)者,很快會想到的一些問題是:
-
在寬屏下如何展示
-
在平板上如何展示
-
在手機(jī)上如何展示
-
即使僅僅支持桌面版,跨瀏覽器要考慮嗎?支持哪些版本?
-
有些UI效果在低版本的瀏覽器上不工作,需要Shim技術(shù)
除此之外,依然有大量的其他細(xì)節(jié)需要考慮:
-
性能要求是什么樣的?
-
安全性要考慮嗎?
-
在網(wǎng)絡(luò)環(huán)境不好的時候,要不要fallback到基礎(chǔ)視圖?
-
既然涉及發(fā)送邀請函,送達(dá)率如何保證
-
與外部郵件服務(wù)提供商集成時的工作量
等等。這些隱含的信息需要被充分挖掘出來,然后開發(fā)者才能做一個合理的評估,而且這還只是開始。一旦進(jìn)入開發(fā)階段,很多之前沒有考慮到的細(xì)節(jié)開始涌現(xiàn):字體的選用,字號,字體顏色,元素間的間距等等,如何測試郵件是否發(fā)送成功,多個角色之間的conversation又會消耗很多時間。
需求的變化方向
作為程序員,有一天你被要求寫一段代碼,這段代碼需要完成一件很簡單的事:
-
打印”Hello, world”5次
很容易嘛,你想,然后順手就寫下了下面這幾行代碼:
print("Hello, world") print("Hello, world") print("Hello, world") print("Hello, world") print("Hello, world")
不過,拷貝粘貼看起來有點(diǎn)低端,你做了一個微小的改動:
for(var i = 0; i < 5; i++) { print("Hello, world") }
看起來還不錯,老板的需求又變成了打印”Goodbye, world”5次。既然是打印不同
的消息,那何不把消息作為參數(shù)呢?
function printMessage(message) { for(i = 0; i < 5; i++) { print(message); } } printMessage("Hello, world") printMessage("Goodbye, world")
有了這個函數(shù),你可以打印任意消息
5次了。老板又一次改變了需求:打印”Hello, world”13次(沒人知道為什么是13)。既然次數(shù)也變化了,那么一個可能是將次數(shù)
作為參數(shù)傳入:
function printMessage(count, message) { for(i = 0; i < count; i++) { print(message); } } printMessage(13, "Hello, world"); printMessage(5, "Goodbye, world");
完美,這就是抽象的魅力。有了這個函數(shù),你可以將任意消息打印任意次數(shù)。不過老板是永遠(yuǎn)無法滿足的,就在這次需求變化之后的第二天,他的需求又變了:不但要將”Hello, world”打印到控制臺,還要將其計(jì)入日志。
沒辦法,通過搜索JavaScript
的文檔,你發(fā)現(xiàn)了一個叫做高階函數(shù)的東東:函數(shù)可以作為參數(shù)傳入另一個參數(shù)!
function log(message) { system.log(message); } function doMessage(count, message, action) { for(i = 0; i < count; i++) { action(message); } } doMessage(5, "Hello, world", print); doMessage(5, "Hello, world", log);
這下厲害了,我們可以對任意消息,做任意次的任意動作!再回過頭來看看那個最開始的需求:
-
打印”Hello, world”5次
稍微分割一下這句話:打印,”Hello, world”,5次,可以看到,這三個元素最后都變成了可以變化的點(diǎn),軟件開發(fā)很多時候正是如此,需求可能在任意可能變化的方向上變化。這也是各種軟件開發(fā)原則嘗試解決的問題:如何寫出更容易擴(kuò)展,更容易響應(yīng)變化的代碼來。
小結(jié)
軟件的復(fù)雜性來自于大量的不確定性,而這個不確定性事實(shí)上是無法避免的,而且每個軟件都是獨(dú)一無二的。另一方面,軟件的需求會以各種方式來變化,而且往往會以開發(fā)者沒有預(yù)料到的方向。比如上面這個小例子中看到的,最后的需求可能會變成將消息以短信的方式發(fā)送給手機(jī)號以185開頭的用戶手機(jī)上。
-
算法
+關(guān)注
關(guān)注
23文章
4615瀏覽量
92977 -
軟件工程師
+關(guān)注
關(guān)注
8文章
218瀏覽量
21142 -
智能硬件
+關(guān)注
關(guān)注
205文章
2347瀏覽量
107631
原文標(biāo)題:軟件開發(fā)為什么很難?
文章出處:【微信號:mcuworld,微信公眾號:嵌入式資訊精選】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論