一個輸入框你要做一周?

10 評論 12598 瀏覽 76 收藏 19 分鐘

對于產(chǎn)品和開發(fā)來說,這兩者可能會因為需求開發(fā)的難度與耗費工時發(fā)生一些爭議與不同看法。那這背后隱藏的是什么原因呢?我們又該如何解決這類問題呢?

如果PO說這是個很小的改動,你不要信他。

01 一次有爭議的估點

在某次迭代會議上,PO希望交付這樣一個“簡單”功能:在應(yīng)用中,用戶可以輸入自己的地址,這樣我們可以定期郵寄一些宣傳冊給用戶。

按照PO的描述,這只是一個很簡單的文本輸入框,用戶填寫地址之后,地址信息隨著其他個人信息一起存到數(shù)據(jù)庫即可。

PO甚至在白板上畫了一個不太規(guī)則的長方形作為示意,然后滿懷期望的將目光投向了你—— 一個做事情還算靠譜的開發(fā),友善的問道:

“你覺得實現(xiàn)這樣一個輸入框,需要多長時間?如果你覺得太小的話,我們是不是可以在做其他卡的時候順手做了?”。

你定了定神,在腦海里大致驗算了一遍,說:“嗯,我覺得在理想情況下,大概需要五、六天。如果算上開會……”。

“什么?這樣一個輸入框你要用一周?!”,PO敲著白板上那個不規(guī)則的長方形問道。

“呃……,我說的是理想情況,實際上應(yīng)該會比這個時間更長……”

“……”

如果你有過和非技術(shù)出身的PO(或者站得太高而忘記地面是什么樣子的架構(gòu)師)一起工作過,大約很大程度上有過類似的經(jīng)歷。

通常來說,預(yù)期有這么大的偏差,很可能是大家說的并不是同一件事兒:要么是PO想的過于簡單,要么是開發(fā)想的過于復雜。

02 遺漏掉的細節(jié)

由于專業(yè)知識的屏障,以及對細節(jié)的過度簡化,使得非專業(yè)人士往往會低估完成某項工作所需要的工作量。另一方面,對于專業(yè)人士自身,如果忽略了外部環(huán)境中客觀存在的阻力,同樣會對實際工作量產(chǎn)生錯誤的判斷。

1. “簡單”的輸入框

在PO眼中,一個普通的文本輸入框大約長這個樣子:

輸入之后,傳到后端保存一下就完事兒了。當然,可能還需要一些必要的校驗,比如長度不能太短或者太長,地址遵循一定的格式之類。

2. 不那么簡單的輸入框

不過在一個有經(jīng)驗的開發(fā)眼里,一個“普通”的文本輸入框是這樣的:

顯然它擁有更多的狀態(tài),也更加復雜:

  • 禁用狀態(tài)
  • 內(nèi)容為空的時候
  • 設(shè)置焦點之后的狀態(tài)
  • 非法輸入狀態(tài)
  • 提示信息(helperText)
  • 可用性(Accessibility)
  • 其他狀態(tài)

通常來說,在初始狀態(tài)下,輸入框會顯示一個占位符。當用戶開始輸入時,需要有各種各樣的反饋:拼寫錯誤、太短或者超長等。此外,系統(tǒng)的其他部分的狀態(tài)還可能影響輸入框的狀態(tài),比如一個未授權(quán)的用戶不能輸入,這時我們需要將輸入框禁用。

通常這些狀態(tài)對應(yīng)的樣式會有差異,比如字體、字號、顏色和間距等等。這些細小的,但是需要和UX頻繁溝通和改進的細節(jié)無疑會耗掉很多時間。

除了眾多的狀態(tài)之外,另一個會花費很多時間的地方是校驗(以及限制)。

3. 校驗

事實上,校驗作為一個Cross Functional的點在實際中占用的開發(fā)時間(包括測試時間)往往被嚴重低估。除了基本的校驗規(guī)則如:長度限制(最長10位,最短3位),格式限制(郵件)等之外,往往會有更為復雜的校驗規(guī)則,這些規(guī)則有時候?qū)πr炦壿媽崿F(xiàn)的結(jié)構(gòu)有一定的“破壞性”。

比如,開發(fā)可能定義了一系列的validations

const validations = {
    minLength: 1,
    maxLength: 16,
}

<AddressSearch validations={validations} value={value} />

經(jīng)過一些時間的調(diào)試和代碼的重構(gòu)之后,假設(shè)這個校驗機制可以良好的運行了。

const builtIns = {
    minLength: (value, criteria) => value && value.length > criteria,
    maxLength: (value, criteria) => value && value.length < criteria
}

const isValid = (validations) => (value) => {
    return _.every(validations, (k, v) => builtIns[k](value, v))
}

const AddressSearch = ({validations, value}) => (<Input error={isValid(validations)(value)} ... />);

很快,下一個需求是將這個AddressSearch的合法性和頁面上的另外一個輸入框關(guān)聯(lián)起來:當另一個選擇國家的Dropdown的值發(fā)生變化之后,AddressSearch組件的校驗規(guī)則會隨之變化。

這種情況下,之前的很多邏輯被打破,開發(fā)需要更多的時間來修改代碼,以及代碼對應(yīng)的測試,比如上面代碼片段中的builtIns中的規(guī)則都需要重寫。

4. 輸入值的限制

另一個與校驗相關(guān)的功能是限制某些值的輸入,對于某些字段,需要禁止用戶輸入特定的字符。它可以認為是對校驗的進一步擴展,不過有時候在實現(xiàn)上會將其獨立起來。一些常見的例子如下:

  • 不允許輸入特殊字符
  • 只允許輸入數(shù)字
  • 只允許輸入alphabet
  • 只允許輸入1-12的月份或者1-31的年份
  • 允許輸入數(shù)字的小數(shù)點,其余則為非法

等等,有時候這些限制是正交的,互不干涉。有時候則不然。比如在允許輸入數(shù)字(初衷是允許輸入手機號碼)的場景下,如果使用

<input type="number" />

作為實現(xiàn),則當輸入值實際需要0作為前綴的場景就會出現(xiàn)問題:瀏覽器往往會很智能的將前綴0刪掉。

你可以通過:

<input type="tel" pattern="[0-9]*">

修復這個問題,不過很有可能你又會遇到跨瀏覽器等其他問題。總之,每一個潛在的問題,以及對應(yīng)的解決方案都隱藏在表面之下,我們通常很難在開始前就能預(yù)料到這些細節(jié)。即使對有經(jīng)驗的開發(fā)者也是如此,更不用說遠離這些細節(jié)的業(yè)務(wù)人員了。

5. 通過網(wǎng)絡(luò)獲取數(shù)據(jù)

現(xiàn)在,我相信PO已經(jīng)能對“一個簡單的輸入框”所需要的工作量有一個初步的了解了。這些還只是對于純前端的工作量。

現(xiàn)在假設(shè)有這樣的一個增強:當用戶輸入地址時,我們需要搜索地址并智能地自動補全(auto-suggestion):

當引入網(wǎng)絡(luò)數(shù)據(jù)獲取之后,情況會變得更加復雜。

一方面,異步數(shù)據(jù)本身就比本地數(shù)據(jù)復雜,它需要額外的庫(如果你想要屏蔽各個瀏覽器對異步請求的差異的話)。

另一方面,網(wǎng)絡(luò)中很多變量會超出開發(fā)者的控制:比如網(wǎng)速,網(wǎng)絡(luò)異常(路由配置,防火墻等)。

另外,當有了前端和后端的分別之后,協(xié)議/契約就會變成另一個障礙 — 如何保證協(xié)議雙方對契約的消費的同步。比如,當前端發(fā)現(xiàn)需要展現(xiàn)一個額外字段在界面上,而發(fā)現(xiàn)后端并沒有提供的時候;或者后端將日期存成了更加方便存儲的long,而前端消費時發(fā)現(xiàn)沒有timezone信息等等。

有了前后端雙方的交互之后,校驗規(guī)則同樣需要在后端的模型對象和持久化層中都有所體現(xiàn)。

一種做法是前后端使用同構(gòu)的架構(gòu)(JavaScript全棧),這樣有一部分代碼可以在全后端復用(我們在上一個項目就中采用了React+AWS Lambda+Node.js的模式,整體體驗還算不錯)。

如果是異構(gòu)架構(gòu),則需要將類似的代碼用不同的語言寫兩遍,而且另外一個潛在的問題是:如何使得兩者保持同步?

當然,我相信在工程上,這些問題最終都可以被解決,但是每個問題及其解決方案都不是免費的。即使團隊中的開發(fā)有足夠的經(jīng)驗和快速的學習能力,很多問題依然是無法預(yù)見的,而你永遠無法解決一個你不知道的問題。

6. 異常情況

大部分情況下,人們傾向于從正常流程去考慮工作量。

而事實上在開發(fā)過程中,所謂的“正常流程”才是不正常的?,F(xiàn)實世界中有太多的不確定的因素可以讓我們的應(yīng)用崩潰或者停止工作——網(wǎng)絡(luò)請求超時,地址服務(wù)器宕機,后端版本升級,瀏覽器的不兼容,操作系統(tǒng)的不兼容,不同的硬件環(huán)境,特定的瀏覽器版本(我最近工作的項目上,由于客戶使用的kerberos鑒權(quán)機制導致只有Firefox的特定版本才可以正常訪問應(yīng)用)等等。

與之對應(yīng)的正常流程反而如同在走鋼絲。

既然異常無可避免,我們需要為其設(shè)計很精巧的保護機制,一方面需要讓系統(tǒng)可以在錯誤中恢復(不至于白屏,或者禁用所有功能),另一方面還需要展示以及記錄可靠且準確的信息以供修復(日志,前端的Modal,截圖等等)。

7. 用戶體驗

功能之外,還有很多其他因素需要考慮。比如可用性(Accessibility)以及易用性(包括頁面上字詞的選擇和用戶體驗),以及兼容性的考慮。一些常見的會影響開發(fā)工作量的因素包括:

  • 跨瀏覽器支持
  • 老舊的瀏覽器兼容
  • 多設(shè)備支持

如果涉及響應(yīng)式設(shè)計,則需要和UX進一步合作來確定實際方案。很多時候,多個設(shè)備上的交互模式都不盡相同,比如iPad上的hover效果,小尺寸屏幕上的字體等等。

03 技術(shù)之外的因素

除了技術(shù)上很難預(yù)見的延遲和障礙之外,實際項目中還有很多會消耗掉大量時間的事件,它們無處不在,細微而瑣碎,但是累積起來產(chǎn)生的影響則相當可觀。

1. 混亂才是常態(tài)

比如項目上有若干名同事:

const roster = [

'吳榮華',

'侯曉成',

'賈彥軍',

'邱俊濤'

]

從概率上來說,每個人都或多或少有些工作之外的事情要處理,比如偶爾休假,不太舒服在家休息,通勤路上堵車,或者在買咖啡排時迷路等等。

const excuses = [

'堵車了',

'遲到了',

'要接小孩',

'不舒服,請半天假',

'休假了'

]

生活就像是這樣一行代碼:

${_.shuffle(roster)[0]} ${_.shuffle(excuses)[0]}

所以,我們眼中的世界就是這個樣子的:

當然這些異常不會每天都發(fā)生,但是如果項目足夠長,這些事情則幾乎必然會發(fā)生。隨著人員的增加,參與方的增加,不確定性隨之提高,不是一切都正常的概率則會變得非常大。畢竟,混亂才是這個世界的常態(tài)。

而這些混亂可以讓我們之前的估算失效,耗時增長。而這些混亂在估算之初則很難被我們看到,從而導致估算往往偏小。

2. 一個小故事

在幾年前的一個項目上,我估計理想情況下大概需要三天來實現(xiàn)一個對某個資源的RESTful API,客戶的技術(shù)負責人當時就怒了,說他自己寫半天就可以寫完,不就幾個CURD嘛。

我?guī)退詾榱辛艘恍┳尤蝿?wù)之后,他陷入了沉思:

  • Database migration腳本
  • 實體類
  • 實體類之間的關(guān)聯(lián)
  • Service/Controller類
  • 異常處理
  • 單元測試
  • 與下游系統(tǒng)的契約
  • 集成測試

我印象中這個任務(wù)花費的時間應(yīng)該是多于三天的,因為光找其他團隊的接口人要契約就花了一天半。

04 應(yīng)對策略

通過上述的例子,相信大家已經(jīng)看出評估失誤的一些原因了,而要應(yīng)對這些錯誤,大的原則當然是反其道而行之。

在具體的實踐上,除了經(jīng)驗之外,一個可行的應(yīng)對策略是足夠程度的細化。通過細化事實上可以在一定程度上降低不確定性,使得很多原先沒有看清楚的點被重新發(fā)現(xiàn)。

比如輸入框的各種狀態(tài),狀態(tài)之間的遷移,每個不同狀態(tài)所涉及的樣式等,通過細化(比如通過可視化的方式畫出狀態(tài)機),則很多細節(jié)自然浮現(xiàn)。

更進一步,如果涉及到數(shù)據(jù)的獲取,那么對應(yīng)的加載中,加載失敗,無數(shù)據(jù)等等狀態(tài)又會進一步驅(qū)動出更多的細節(jié),從而潛在的可以產(chǎn)生更加客觀的評估。

實踐中,通過有限狀態(tài)機的方式來描述窮舉一個組件(或者一組互相關(guān)聯(lián)組件)的狀態(tài)是一個比較有效的方式,它可以更好的揭示組件的各種變體的形態(tài)和所需邏輯。

(圖片來自:http://dwz.date/gcS)

另一方面,在心理上需要充分認識到現(xiàn)實世界的復雜程度,特別是涉及組織,相關(guān)方很多的時候,不確定性會非線性的增加,從而導致評估的失誤。

這要求我們一方面要擁抱變化而不是對抗變化,另一方面驅(qū)使我們采用更簡單的設(shè)計,更堅固的基礎(chǔ)設(shè)施,質(zhì)量更高的構(gòu)建方法等等,從而更快速的響應(yīng)變化。

05 小結(jié)

至此,相比你已經(jīng)猜到,雖然開發(fā)在估算中以為自己已經(jīng)留有足夠buffer,事實上這個功能的實現(xiàn)必然超過一周。

在實際項目中,一方面由于知識壁壘和一些偏見,人們傾向于忽略必要的細節(jié),從而造成對實際所需工作量錯誤的評估。

另一方面,由于我們所處于的現(xiàn)實世界是一個高度復雜,不確定性很高的環(huán)境,很多因素往往會互相疊加,互相影響,從而導致即使我們從比較客觀的視角去評估,如果忽略了不確定性,同樣可能低估實際所需的工作量。

我們可以通過足夠細化的方式降低不確定性,從而提高估算的可靠性。

另一方面,還需要積極的擁抱混亂,通過更簡單可靠的方式來構(gòu)建軟件,從而提高響應(yīng)變化的能力。

P.S. 我本來計劃著寫這篇文章大概需要3天,結(jié)果畫圖就花了兩個晚上。然后又去檢查了之前的博客,確定相對于之前的類似觀點有了一些提升,才開始寫草稿(耗時兩個晚上),然后又花了兩個晚上來潤色。

 

來源:https://mp.weixin.qq.com/s/cjONOqFZoVbmLSROWde7RQ

作者:邱俊濤;公眾號: ThoughtWorks洞見

本文由@ThoughtWorks洞見 授權(quán)發(fā)布于人人都是產(chǎn)品經(jīng)理,未經(jīng)許可,禁止轉(zhuǎn)載

題圖來自 Unsplash,基于 CC0 協(xié)議

更多精彩內(nèi)容,請關(guān)注人人都是產(chǎn)品經(jīng)理微信公眾號或下載App
評論
評論請登錄
  1. 這篇文章想表達的應(yīng)該是產(chǎn)品經(jīng)理與開發(fā)之間的理解差異,并不是想說搜索框要這么久,這僅是一個例子而已

    回復
  2. 百度的搜索框嗎?

    回復
  3. 輸入限制和流程不是PO給的嗎

    來自廣東 回復
  4. 說的這些我都明白,但一個輸入框我也只會給一天時間去做

    來自廣東 回復
  5. 校驗這些都能有公共方法實現(xiàn),如果一個簡單的輸入框也要做一個禮拜,這個產(chǎn)品的執(zhí)行力太差

    回復
  6. 一個細小的功能要做到完美,需要投入超常識的時間,怎么辦?
    1、完成比完美重要
    2、理解核心需求與應(yīng)用場景,團隊協(xié)商,主動做減法
    3、長期的積累提升復用率,這也是珍視自己時間的意義。

    來自天津 回復
  7. 說的很有道理

    來自湖北 回復
  8. 說的很有道理,但是一周的時間做一個輸入框大概會被炒吧

    來自廣東 回復
  9. 看題目,還以為說的是搜索

    來自廣東 回復
    1. 我開始還以為是搜索

      回復