在鈦坦那邊花了蠻多時間把產品架構面的 error handling 機制弄好,不再是到處 try/catch 只寫 log return false.
不再是無謂的 try/catch re-throw exception.
不再是 catch(ex) throw ex; 的該死寫法。甚至吃掉 exception 不做事的情況。
該記 log 的只在邊界層,透過 decorator/action filter/middleware 來封裝與加載。也不再有那種 log 只記到表層的 call stack 而沒記錄到 inner exception 真正的問題發生點。
該做 error handling 或附加 run time 的資訊,handle 完 re-throw 自定義的 custom business exception, 再交給 error handling 底層來觸發對應的 error handler。
在發現問題(例外)的第一時間點 throw exception 通知整個 process 發生了什麼問題。
整個 call stack 與方法簽章都是乾乾淨淨的「正常流程」,沒有不必要的 return true/false 來通知是否有異常,也沒有不必要的 error code Enum 來一路傳遞回呼叫端。
發生怎樣的異常,該決定怎樣的 error code/status code 通知呼叫端,是最後要回傳結果那一層的 error handle 職責與行為。
Error handling 本身就是一整門學問,能在企業等級產品架構裡面打好這段基礎,可以指數性降低 application design 的複雜度。
鈦坦的產品工程師扛霸子之一的 Jrting ,開始把這門知識整理成系列文了,希望能給大家一些幫助。
https://medium.com/@neokn/exception-%E6%80%8E%E9%BA%BC%E4%B8%9F%E6%89%8D%E4%B8%9F%E5%BE%97%E6%BA%96-a385bd27ed15
error code定義 在 91 敏捷開發之路 Facebook 八卦
很多人以為,測試人員「只靠測試」,來測出 bug,但事實上他們負責的是「品質」,他們的價值不只是測試本身,更多的是:
☆ 找出哪一些東西需要測試
☆ 說明哪一些東西不測試可能會有什麼樣的風險
☆ 哪一些東西雖然在開發人員的定義不是 bug,卻影響到使用者用起來的感受與品質
☆ 甚至他們需要在短時間內快速探索、學習「新產品」或「新領域」的能力,了解這樣的產品提供了怎樣的功能,是為了解決使用者的什麼問題。
這是我覺得「真正專業的測試/品質工程師」所具備的專業價值與能力,而且這很吃天賦、個人特質,不是每個人都適合或做好的。
很多專業的 QA 才是真正的 domain expert,他們的天性是發散、建立關聯、探索、聚焦、學習。
然而,如果把一般功能的驗證,產品開發的邏輯 bug,也都交給 QA 來一概承擔,那我覺得這產品的極限可能是「沒有 bug」,但「品質」不一定是高水準的,因為 QA 的能力被用在低效的產出上。
▍開發人員怎麼跟測試人員相輔相成
開發上大部分的 bug,都是因為「寫的跟想的不一樣」,想的沒 bug,寫出來卻有 bug。
※ QA 是幫忙解決:「想錯」的 bug。
這問題適合用「#單元測試」來解決,夠多扎實、涵蓋程度夠廣的單元測試,可以避免這類「低級錯誤」。
當正式環境產品出錯的時候,透過單元測試可以快速定位出問題的位置與原因。
※ 如何在賺錢的 legacy code 上,優雅地加入【單元測試】,請參考:https://dotblogs.com.tw/…/201905-unit-testing-effectively-w…
另一種 bug 是每個人寫的都沒問題,但串起來的部份沒做好。這類就適合依靠「#驗收測試」來模擬,站在使用者的角度,用使用者的情境,自動化的去「走」這些情境,驗證功能、情境、資料是否如同預期。
該怎麼確認我們的「驗收測試」沒有想法上的問題,會不會我們覺得是對的,但跟需求單位想要的不一樣?
當然有可能,而且很常發生。這問題通常透過「#實例化需求」來避免。在實例化需求過程,有需求單位、有 BA、有 QA、有 Dev (當然,這只是指團隊有人可以 cover 該角色所具備的技能即可)
那有沒有可能, #實例化需求 仍然不夠?例如:開發團隊做出來的,既符合當初的驗收情境,也通過 QA 的品質要求,PO 也認為這是當初講的東西,但看完之後,PO 覺得當時想錯了,他有更好的想法,或是需要更好的想法呢?
當然有可能!而且這才是「正常」。在看不到實際的功能、使用的情境,只有空想、文字、圖片或雛型,事實上是很難出現「更好的想法」。
但一旦看到了產品功能,一旦試著使用,就更容易激發出更好的想法、更多改善的方式。
所以,Agile 的「#快速迭代交付產品增量」、「#MVP / #MMF」、ATDD/TDD 的「#可行走的骨架」、「#曳光彈式開發」,都是為了能用最小的付出,獲得最大的 outcome。(這個 outcome 不只是功能本身,也包含了發現我們的功能根本是無用的廢物,或是發生了不同的 event 而產出更棒的作法)
最後,有沒可能上面的理想狀況都做好了,但產品卻因為功能頻繁修改,而越來越慢、越來越肥、問題越來越多?
當然有可能!所以,從一開始的設計,就要 #即時重構,要重構前要有測試的保護,如果一樣都要寫測試,那 #TDD 會比候補測試來得更加「事半功倍」,用測試來描述情境、驅動開發、維持易用性,搭配重構來穩定設計、確保彈性、夯實品質,讓開發與維護的成本曲線是緩慢上升、斜率趨近於0的直線。
※ 想要用測試描述需求、探索需求、分析需求,並找到核心的情境,適當的開發順序,請參考【TDD與持續重構】:https://dotblogs.com.tw/…/201907-evolutionary-development-t…
※ 想要從軟體架構設計上達到「職責、關注點分離」,讓團隊能依循這樣的設計規範來達到「消除重複」,可以善用【DI與AOP】的設計,請參考:https://dotblogs.com.tw/…/201905-dependency-injection-and-a…
如果該具備的基礎建設都有,該了解的功能實踐基本也都能掌握,但你的產品開發的瓶頸,最後是卡在「時間不夠」、「時程太趕」,那其實問題有兩種。
第一種,需求沒照價值的優先順序排列,且不具備「捨棄」低價值功能的勇氣,想要的太多,需要的太少,當然快不起來。另外這一類問題常見的還有,無法把需求 end-to-end 的切細切小。
第二種,就是開發能量的不足。老話一句,加人是沒用的。在產品開發的領域,scale-up 遠比 scale-out 實際多了。三四個精英可以抵得上兩三個團的戰力。
如我最近最常講的一句話:「我認同沒有時間是個問題,那你做了什麼來改善這個問題呢?」
※ 很多人的開發方式、開發環境、開發工具,根本是原始人等級的,想要往【極速開發】的領域邁進,請參考:https://dotblogs.com.tw/…/2…/11/29/201905-extreme-developing
最後,有沒可能講了那麼多,都只有自己會,但團隊不買單、老闆不買單?
當然有可能,導入變革本來就是軟硬技能的綜合體,如何發揮影響力,如何幫助大家無感,如何找到對的 roadmap,如何讓大家嚐到甜頭,如何讓大家自己想要?
這是敏捷教練+技術教練的職能範圍。
※ 想要 train 出自己團隊的 internal coach? 請參考【工程實踐與流程規範導入實務】https://dotblogs.com.tw/…/engineering-practice-and-process-…
▍Road Map
上述雖然好像是打廣告,但我真心希望各位產品開發的朋友們想一想,整個產品開發事實上真的要具備很多專業的技能。
我在 2018 年、2019 年所開立的課程,就是希望把這條 road map 拉出來,幫助大家打通。
每一塊都是不可缺少的拼圖,一環扣一環,你能找到兩塊拼圖拼起來,就可以獲得 1+1 > 2 的綜效。
最後,還有幾門主題是這條 road map 上我正在準備的內容:
① 實例化需求
② 敏捷落地 (agile, scrum, lean, kanban, XP 揉在一起的綜合技)
③ Exception and Error handling
希望能在 2019 年下半年,幫助大家開地圖,帶著大家一起砍怪升級練技能。
error code定義 在 Taipei Ethereum Meetup Facebook 八卦
📜 [專欄新文章] 比較 require(), assert() 和 revert(),及其運作方式。
✍️ Hsieh Yung-chen
📥 歡迎投稿: https://medium.com/taipei-ethereum-meetup #徵技術分享文 #使用心得 #教學文 #medium
利用 solidity 來撰寫 ethereum 智能合約的時候,很常會需要做一些狀態檢查。比如很多dapp常用到的 ownable:
在 transferOwnership 的時候合約需要檢查交易發起人是否為 owner , 若不是則執行 throw。throw 會使整個交易終止,並讓合約狀態回到交易執行前的狀態,並取走“所有”交易手續費,及 msg.sender 會被抽走 gasLimit * gasPrice 這麼多 ether。
一筆失敗的交易,記上區塊鏈之後,gasUsed 直接等於 gasLimit。
補充:若是一筆沒有遇到 throw 的正常交易, 則會被抽走 gasUsed * gasPrice 這麼多 ether。
有參與過 ICO 的人應該會知道,ICO 很常會也一些奇怪的投標規則。像是會限制投標時間,或是 gasPrice,或是個人投標上限等等。你會發現如果你沒有遵守這些規則,那你發出去的交易會失敗,還會被抽走所有的交易手續費,而這通常都不少錢,因為很多投標需要大量的 gas,致使 gasLimit 不能設太低。像我只是搞錯了投標時間,提早發出了投標交易,就被抽走這麼多手續費,實在是叫我情何以堪。所以需要不同的狀態檢查機制,能夠分辨是簡單的錯誤,或是較嚴重的系統錯誤,兩者會顯示不同的錯誤,抽不同的手續費。
補充:在還沒更新前,還是可以透過 return 的寫法來避免抽取過多的手續費。不過這樣會合約會需要寫比較多東西。另外,因為智能合約為 ethereum 上所有節點所執行, return 如果不是由其他智能合約承接的話,無法直接從交易上看出回傳值,導致很難從交易本身直接看出交易成功或失敗。
用 return 的寫法。
在 0.4.10 版的 solidity,新增了 require(), assert(), revert() 想要解決上段提到的問題。預計 require() 用來檢查較不嚴重的錯誤,可以退回為使用到的 gas。而 assert() 用來檢查較嚴重的錯誤,會像以前一樣拿走所有 gasLimit 的手續費。寫法基本上都相同,只是處理方式不一樣。而 revert 跟 require 基本上相同,但是 revert 沒有包括狀態檢查。
11 行原為 throw 的寫法,改為 require,也可直接改成 assert。revert 寫法。
solidity 的智能合約完成後,會編譯成 ethereum byte code 在 ethereum virtual machine (EVM) 上執行。在 0.4.10 版之前,throw 這個關鍵字,會被編譯成 0xfe 開頭的 opcode ,如果你有把黃皮書背熟的話,就會知道這個 opcode 是沒有被定義的,所以當 evm 執行到這個 opcode 會回傳 invalid opcode error。
而在 0.4.10 版之後,新增了 require(), assert(), revert() 三個函式。編譯器會把 require() 以及 revert() 編譯成 0xfd。把 assert() 編譯成 0xfe。 throw 處理方式跟 require相同,會編譯成 0xfd。這些更新只在 solidity 跟 solidity compiler,與 ethereum protocol 無關。當然,新產生的 0xfd opcode, evm 也不認得。
要讓 evm 認得新的 opcode,以便執行相對應的動作,會要更改到 ethereum protocol, 需要硬分岔來更新。在還未更新之前,這些變更都還是會跟之前相同的結果。而這項更新會在 即將到來的 Byzantium 硬分叉裡。新增 REVERT opcode ,就是 0xfd 。
當 evm 執行到 REVERT 指令,會把這個交易更新到的合約狀態都回復到交易前,且會退還剩餘的手續費。另外允許回傳一些資訊,讓錯誤訊息不再只有 execution error。可能會像是這樣:
補充: solidity 目前還沒有 error message 的寫法,相關討論在 (連結)。
最後,關於 assert 以及 require 等如何選用並沒有硬性規定,在合約撰寫的時候可以自行決定。不過,建議像是狀態檢查,input 檢查這些不影響合約狀態的可以用 require()。而 revert() 跟 require 相同,但當合約較複雜的時候,你會發現用 revert 會比較好讀。assert ()用在較安全性上的檢查,像是 overflow 等等。
reference:
EIP 140: https://github.com/axic/EIPs/blob/revert/EIPS/eip-140.md
https://medium.com/…/the-use-of-revert-assert-and-require-i…
比較 require(), assert() 和 revert(),及其運作方式。 was originally published in Taipei Ethereum Meetup on Medium, where people are continuing the conversation by highlighting and responding to this story.
👏 歡迎轉載分享鼓掌
error code定義 在 錯誤碼如何設計才合理? 的相關結果
錯誤碼定義要有字母也要有數字 ... 錯誤碼即人性,感性認知+口口相傳,使用純數字來進行錯誤碼編排不利於感性記憶和分類。 說明:數字是一個整體,每位數字 ... ... <看更多>
error code定義 在 錯誤代碼編排(Error Code) · Java 開發規範 的相關結果
當系統發生無法向下運行的錯誤時,若User 並無要求需顯示對應訊息,則需依以下規定編排錯誤代碼. 依功能類別編排首碼英文; 依功能排序編排功能待碼; 依流程順序決定 ... ... <看更多>
error code定義 在 Error Code 錯誤碼該如何設計(上) - 為什麼你不該隨意定義 的相關結果
不廢話,先來講講常見令人頭疼的錯誤碼定義方法,可以大致分為以下: 大雜燴的流水編號法– 新手天賦技能; 一碼多解釋的通靈大法– 被程式耽誤的通靈王. ... <看更多>