教你如何做需求調(diào)研:忽略極端情況
寫accidental entities系列文章之初,我們跟著一個顧問公司為一個汽車租賃公司開發(fā)一套軟件。當(dāng)時他們已經(jīng)完成了新車注冊部分的功能。計(jì)劃中的下一步是讓顧客能在系統(tǒng)中預(yù)訂。
我們爭取到了租賃公司的CEO抽出一小時時間給我們介紹預(yù)訂系統(tǒng)流程。
CEO: 我想這個會議用不了一個小時。預(yù)訂流程非常簡單。你們對預(yù)訂流程有什么看法?”
Us: “是這樣,就我們的理解——也不是很復(fù)雜——客戶下了訂單,我們?yōu)檐嚪峙渥赓U期,用郵件通知客戶,這就完成了。”
CEO: “等一下,可不是這么簡單。我們收到訂單后,首先要確認(rèn)客戶的信用卡。”
Us: “我們?nèi)绾未_認(rèn)?”
CEO: “不是讓你們確認(rèn)。我們有一個第三方的電子認(rèn)證系統(tǒng),由它來做這些;這個系統(tǒng)會檢查信用卡是否有效,是否有能力支付。”
Us: “如果信用卡被系統(tǒng)拒絕,會發(fā)生什么?”
CEO: “這簡單,我們?nèi)∠唵?,通知客戶?rdquo;
Us: “如果信用卡通過審核,會怎樣?”
CEO: “那就預(yù)訂成功。”
Us: “這里有個問題。在客戶下訂單時我們要立即分配車輛嗎?”
CEO: “當(dāng)然不是!信用卡的驗(yàn)證需要時間;如果最終信用卡被系統(tǒng)拒絕,我們會因此造成業(yè)務(wù)損失。”
Us: “哦,如果這期間另外一個人也預(yù)訂了這輛車,怎么辦?”
CEO: “這是一個很好的問題。在過去,這種問題很少發(fā)生,但確實(shí)有過;我們也許要注意這種極端情況。”
Us: “那發(fā)生這種重復(fù)預(yù)訂情況后如何處理?我估計(jì)你們肯定不希望取消第二個訂單,放棄這個客戶,對吧?”
CEO: “當(dāng)然不想,我喜歡你的思考方式!有幾種做法;如果他們預(yù)訂使用車的期間只重疊30分鐘左右,我們什么都不做。當(dāng)客戶來取車時,我會向他抱歉,解釋有一點(diǎn) 點(diǎn)延遲,我們會用一些措施安撫他。如果重疊期再大,而且有更大更好的車在空閑,我們會給他提供免費(fèi)升級。當(dāng)我們沒有更好的車可用時,我們會讓最出色的銷售 員打電話給他,說服他。有時我們會給他打折,他們通常會很高興再等幾個小時,而不是去找另外的車。我們盡量避免訂單被取消,我們希望樹立一個有求必應(yīng)的好 口碑。”
Us: “哦,有趣。如果讓我自己琢磨估計(jì)會浪費(fèi)不少時間才明白這個過程。你說這事情很少發(fā)生??雌饋硪肽苷_的處理這種重復(fù)預(yù)訂的事情并不是很容易,是否可以 目前不處理這種極端情況,讓人工處理這種事情?我們可以把這輛車標(biāo)識為重復(fù)預(yù)訂,讓系統(tǒng)給出提醒,請求人工處理。Backoffice有這種工具,他們對 處理這種重復(fù)預(yù)訂的事很有經(jīng)驗(yàn)。把這個問題放一放,可以使系統(tǒng)提前幾個星期上線。”
CEO: “我很欣賞你的這個想法,讓我們的***個版本盡量精簡。真的沒有必要立即讓系統(tǒng)能夠自動處理這種事情。這并不是說系統(tǒng)功能不夠強(qiáng)大。系統(tǒng)還是要記錄每個重復(fù)預(yù)訂的情況,這是有用的信息。我們能做的這些吧?”
Us: “是的,這并不困難。”
跟CEO交談之后,我們開發(fā)一個代碼模型。
在我們的***次迭代中,一個訂單有多個顯示效果,每種效果表示一種訂單狀態(tài)。這樣做的好處是,可以手工的在各種狀態(tài)間切換,當(dāng)信用卡被拒絕時,你不能接受預(yù)訂….反之就是正常模式,或一些其他操作,這些不是我們這篇文章的重點(diǎn)。
- var booking = new Booking(
- bookingId, carId,
- new Customer(new CreditCard("343705171682875"), new CustomerName("Jef", "Claes")),
- new Period(DateTime.Now.AddDays(1), DateTime.Now.AddDays(4)));
- var bookingWithVerifiedCreditCard = booking.CreditcardVerified();
- var doubleBooking = bookingWithVerifiedCreditCard.Double();
每次狀態(tài)的改變都會觸發(fā)一個事件。如果我們輸出事件,運(yùn)行下面的代碼將會看到下面的信息。
- (EVENT) BookingCreditCardVerificiationPending
- (EVENT) BookingCreditCardVerified
- (EVENT) DoubleBooked
BookingCreditCardVerified 事件觸發(fā)我檢查重復(fù)預(yù)訂。
- public class BookingCreditCardVerifiedHandler : IHandle<BookingCreditCardVerified>
- {
- private readonly IBus _bus;
- public BookingCreditCardVerifiedHandler(IBus bus)
- {
- _bus = bus;
- }
- public void Handle(BookingCreditCardVerified @event)
- {
- _bus.Send(new DetectDoubleBooking(@event.BookingId));
- }
- }
如果發(fā)現(xiàn)重復(fù)預(yù)訂,我讓系統(tǒng)顯示提醒,通知我們??梢酝ㄟ^郵件,或Backoffice里的一個提醒,或其他的。
- public class DoubleBookedHandler : IHandle<DoubleBooked>
- {
- public void Handle(DoubleBooked @event)
- {
- NotifyHumans();
- }
- private void NotifyHumans() { }
- }
盡管技術(shù)上的實(shí)現(xiàn)并不是很特別,我想它已經(jīng)向我們展示了事件系統(tǒng)如何起作用,如何將責(zé)任分發(fā)到相應(yīng)的負(fù)責(zé)單位。
通常人們有個誤解,認(rèn)為我們有計(jì)算機(jī),它們應(yīng)該解決我們的所有問 題,甚至一些極端情況。極端情況——根據(jù)定義——只會發(fā)生在極端條件下,缺少一定的投入,用常規(guī)的方式很難處理。通過手工處理極端情況,用戶可以進(jìn)行人工 干預(yù),決定什么才是應(yīng)付這種問題的做好做法。這樣做我們可以快速的讓系統(tǒng)上線,減少了代碼編寫,最終能讓客戶更滿意。通過統(tǒng)計(jì)這種極端情況的發(fā)生頻率,我 們能夠按照實(shí)際情況來決定是否值得去投資處理這些極端情況。
原文鏈接:http://www.jefclaes.be/2013/06/not-handling-edge-cases-making-them.html
譯文鏈接:http://www.aqee.net/not-handling-edge-cases-making-them-explicit-instead/