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

引入Option優(yōu)雅地保證健壯性

開發(fā) 開發(fā)工具
通過引入Option,既規(guī)避了可能出現(xiàn)的一些錯(cuò)誤,又能避免編寫繁瑣的if判斷。

[[182563]]

REA的Ken Scambler在其演講《2 Year of Real World FP at REA》中,總結(jié)了選擇函數(shù)式編程的三個(gè)原因:Modularity, Abstraction和Composability。

函數(shù)式編程強(qiáng)調(diào)純函數(shù)(Pure Function),這是模塊化的一個(gè)重要基礎(chǔ),因?yàn)閷?duì)于純函數(shù)而言,可以不用考慮調(diào)用的上下文,就可以根據(jù)函數(shù)的輸入推斷函數(shù)的執(zhí)行結(jié)果。這也就是Ken所謂的:

 You can tell what it does without Looking at surrounding context.

Ken在演講中給出了一個(gè)案例:

  1. def parseLocation(str: String): Location = { 
  2.   val parts = str.split(",") 
  3.   val secondStr = parts(1) 
  4.   val parts2 = secondStr.split(" ") 
  5.   Location(parts(0), parts2(0), parts(1).toInt)} 

仔細(xì)閱讀這段代碼,你會(huì)發(fā)現(xiàn)這段代碼是不健壯的,可能存在如下錯(cuò)誤:

  • 作為input的str可能為null
  • parts(0)和parts(1)可能導(dǎo)致索引越界
  • parts2(0)可能導(dǎo)致索引越界
  • parts(1)未必是整數(shù),調(diào)用toInt可能導(dǎo)致類型轉(zhuǎn)換異常

這段代碼隱含的錯(cuò)誤還可能被廣泛地蔓延到系統(tǒng)的其他地方,只要該函數(shù)被調(diào)用。這種蔓延可能會(huì)因?yàn)楦嗲短椎恼{(diào)用而產(chǎn)生級(jí)聯(lián)的錯(cuò)誤效應(yīng)。例如:

  1. def doSomethingElse(): Unit = { 
  2.   // ...Do other stuff 
  3.   parseLocation("Melbourne, VIC 3000")} 

而doSomethingElse()函數(shù)又被其他函數(shù)調(diào)用,這些潛在的缺陷會(huì)分布到各個(gè)直接或間接的調(diào)用點(diǎn)。這意味著代碼會(huì)繼承它所調(diào)用代碼的錯(cuò)誤以及副作用,使得對(duì)代碼功能的推理(reasoning)變得近乎不可能,更不用說代碼的模塊化(modularity)了。

我們當(dāng)然可以通過對(duì)null進(jìn)行檢測來避免出現(xiàn)這些錯(cuò)誤。然而看看各種出現(xiàn)null值的可能分支,需要我們做各種條件判斷,想象這樣的代碼都讓人不寒而栗。引入Option類型就可以很好地封裝這種可能性。按照Ken的說法就是:

 All possibilities have been elevated into the type system.
  1. def parseLocation(str: String): Option[Location] = { 
  2.  val parts = str.split(",") 
  3.  for { 
  4.    locality <- parts.optGet(0) 
  5.    theRestStr <- parts.optGet(1) 
  6.    theRest = theRestStr.split(" ") 
  7.    subdivision <- theRest.optGet(0) 
  8.    postcodeStr <- theRest.optGet(1) 
  9.    postcode <- postcodeStr.optToInt 
  10.  } yield Location(locality, subdivision, postcode)} 

以上代碼中,split()函數(shù)返回的類型為Array[String],該類型自身是沒有optGet()函數(shù)的。但是我們可以為Array[String]定義隱式轉(zhuǎn)換:

  1. implicit class StringArrayWrapper(array: Array[String]) { 
  2.     def optGet(index:Int): Option[String] = { 
  3.         if (array.length > index) Some(array(index)) else None 
  4.     }} 

optToInt方法可以如法炮制。

Ken的解決方案并沒有考慮到parseLocation函數(shù)入?yún)tr存在null值的可能,故而在對(duì)str調(diào)用split方法時(shí)仍然有可能導(dǎo)致拋出空指針異常。因此進(jìn)一步,我們還可以修改parseLocation函數(shù)的定義:

  1. def parseLocation(optStr: Option[String]): Option[Location] 

顯然,通過引入Option,既規(guī)避了前面分析可能出現(xiàn)的錯(cuò)誤,又能避免編寫繁瑣的if判斷。這里的關(guān)鍵點(diǎn)是Option對(duì)兩種可能性(None與Some)的封裝。它由兩個(gè)代數(shù)類型Some與None構(gòu)成,前者包含了一個(gè)值,而后者則包含了一個(gè)不存在的值。事實(shí)上,Option是一個(gè)Maybe Monad,實(shí)現(xiàn)了flatMap與filter,因而在Scala中可以用for comprehension來訪問。

【本文為51CTO專欄作者“張逸”原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)聯(lián)系原作者】

戳這里,看該作者更多好文

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2018-06-29 14:51:41

Java健壯性實(shí)踐

2023-11-17 11:55:54

Pythonretrying庫

2021-05-27 08:15:05

CSS CSS prefer技巧

2021-02-26 20:07:54

安全性健壯性代碼

2025-02-13 00:28:26

2024-01-08 09:38:51

Java數(shù)據(jù)

2011-12-07 10:22:11

美信云網(wǎng)管閥值

2025-02-27 09:35:22

2021-10-11 08:08:02

Python異常程序

2022-02-15 08:38:04

錯(cuò)誤邏輯異常編程程序

2021-09-01 12:03:49

Spring單元測試

2024-05-07 07:58:47

C#程序類型

2024-07-04 08:02:59

2021-12-09 17:21:48

TypeScript TS 前端

2012-12-05 09:42:09

2024-04-12 12:14:39

Rust字符串代碼

2024-11-07 12:20:31

LinuxC語言數(shù)據(jù)類型

2022-03-01 21:25:30

對(duì)象代碼Proxy

2010-09-25 15:19:01

2021-04-14 17:18:27

冪等性數(shù)據(jù)源MySQL
點(diǎn)贊
收藏

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