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

工具類與函數(shù)編程毫不相干

開發(fā) 后端
最近,由于我把工具類看作反模式,所以被指責反對函數(shù)式編程。這是絕對錯誤的!我認為它們是很糟糕的反模式,因為他們與函數(shù)式編程無關。我認為其中有兩個基本原因。首先,函數(shù)式編程是可聲明的,然而工具類方法是命令式的。

最近,由于我把工具類看作反模式,所以被指責反對函數(shù)式編程。這是絕對錯誤的!我認為它們是很糟糕的反模式,因為他們與函數(shù)式編程無關。我認為其中有兩個基本原因。首先,函數(shù)式編程是可聲明的,然而工具類方法是命令式的。第二,函數(shù)式編程是基于lambda演算,即被傳遞參數(shù)的函數(shù)。從這個意義上來說,工具類方法不是函數(shù)。我會用一點時間來解釋一下。

在Java中,基本上有兩種被Guava、Apache Commons和其它開發(fā)庫推薦使用的拙劣的工具類。***種是使用傳統(tǒng)的類,第二種就是Java 8的lambda?,F(xiàn)在讓我們看看為什么工具類和函數(shù)式編程關系不大,以及錯誤觀念的來源。

[[131824]]

這就是來源于Java 1.0中Math工具類的一個典型示例:

  1. public class Math { 
  2.  
  3. public static double abs(double a); 
  4.  
  5. // a few dozens of other methods of the same style 
  6.  

 當你想要計算一個浮點型數(shù)字的絕對值,你可以使用如下方式:

  1. double x = Math.abs(3.1415926d); 

這里有什么問題呢?我們需要一個函數(shù),并且我們從 Math類中得到了結果。這個類有許多有用的內置函數(shù),可以用于許多典型的數(shù)學運算,比如計算***值、最小值、正弦、余弦等。這是一個非常流行的概念,許 多商業(yè)化或者開源產品也是如此。自從Java出現(xiàn)(Math類在Java***版本被引入),這些工具類就被廣泛使用。當然,在技術上沒有什么不妥。相反, 他們是命令式和過程式的。我們是否在意呢?這取決于你的選擇。讓我們來看看他們有什么區(qū)別。

基本上有兩種不同的選擇,聲明式和命令式。

就改變程序狀態(tài)的聲明來說,命令式編程的重點是描述一個程序是如何運作的。我們剛剛看到了上面一個命令式編程的例子。下面是另一個(這是一個和面向對象無關,純粹的命令式并且程序化的代碼):

  1. public class MyMath { 
  2.  
  3. public double f(double a, double b) { 
  4.  
  5. double max = Math.max(a, b); 
  6.  
  7. double x = Math.abs(max); 
  8.  
  9. return x; 
  10.  
  11.  

 就采取的一系列舉措來說,聲明式編程側重于在沒有規(guī)定如何做的情況下程序應該完成哪些事情。就像是Lisp中的代碼,一種函數(shù)式編程語言。

  1. (defun f (a b) (abs (max a b))) 

我們明白了什么?只是句法的不同?不是這樣的。

在命令式和聲明式之間有很多描述差異,但是我盡量給出自己的理解?;旧嫌腥N角色在使用f函數(shù)的場景下相互影響:買家、包裝者和消費者,讓我們談一談下面的調用:

  1. public void foo() { 
  2.  
  3. double x = this.calc(5, -7); 
  4.  
  5. System.out.println("max+abs equals to " + x); 
  6.  
  7.  
  8. private double calc(double a, double b) { 
  9.  
  10. double x = Math.f(a, b); 
  11.  
  12. return x; 
  13.  

 這個例子中,方法calc()是一個買家,方法Math.f()是結果的包裝者,方法foo()是消費者。無論使用哪種編程風格,總是有這三個參與其中,買家、包裝者,和消費者。

想象一下,你是一個買家并希望購買禮物給你的女朋友或男朋友。首先會想到進一家店鋪,消費50美元,讓別人噴上香水打包給你,然后寄給你的朋友(回報是一枚香吻),這是命令式的風格。

第二個選項是進一家店鋪,消費50美元,并得到一張禮品券,你將此券展示給你的朋友(回報是一枚香吻)。當他或者她想要得到這股芳香,他或她就會進這家店來得到它。這就是聲明式風格。

看到什么區(qū)別了么?

在***個場景中,這是命令式的風格,你要求包裝者(一家店鋪)使用庫存中的香水來打包,并作為準備好的禮品呈現(xiàn)給你。在第二個 場景中,這是聲明式的,你最終得到了店鋪的承諾,當必要的時候店鋪職員會找到香水來打包禮物,并提供給需要的人。如果你的朋友從來沒有進過有禮品券的這家 店,這股芳香將一直留在這家店中。

此外,你的朋友可以用這個禮品券當做這個禮品本身,就不用去這家店。他或她可能會將這張券作為禮物給其他人,或者用來交換其它禮券或者禮品。這個禮品券本身成為了一個禮品。

因此,區(qū)別就是消費者得到了什么,是用來當做禮品(命令式)還是之后可以轉換成真實禮品的禮券(聲明式)。

工具類,就像從JDK中的Math類或 者Apache Commons中的StringUtils類中立刻得到了準備好的禮品。然而,從Lisp中的函數(shù)和其它函數(shù)式編程中,卻得到了“禮券”。比如,如果你想 調用Lisp中的求***值的方法,但只有當你真正開始使用的時候才能計算出來。

  1. (let (x (max 1 5)) 
  2. (print "X equals to " x)) 

 直到輸出結果打印到屏幕上,求***值的函數(shù)才會調用。當你嘗試去“購買”1到5之間***值的時候,這個x就是一個返回給你的“禮券”。

但是請注意,嵌套的Java靜態(tài)函不會讓他們可聲明化,代碼仍然是命令式的,因為此時方法進行了傳值。 

  1. public class MyMath { 
  2.  
  3. public double f(double a, double b) { 
  4.  
  5. return Math.abs(Math.max(a, b)); 
  6.  
  7.  

 你可能會說,“好吧,我明白了。但是為什么聲明式的風格比命令式的更好呢?有什么大不了的呢?”我會慢慢解釋的。首先讓我來展示在面向對象中函數(shù)式編程中的函數(shù)和靜態(tài)方法的區(qū)別。正如上面所提到的,這是工具類和函數(shù)式編程之間第二大的區(qū)別。

在函數(shù)式變成語言中,你可以這么做: 

  1. (defun foo (x) (x 5)) 

然后,你可以調用這個x:

  1. (defun bar (x) (+ x 1)) // defining function bar 
  2. (print (foo bar)) // passing bar as an argument to foo 

 就函數(shù)式編程而 言,Java中的靜態(tài)方法不是函數(shù)。你不能用一個靜態(tài)方法做這樣的事。你不能將一個靜態(tài)方法當做參數(shù)傳遞給其他方法。基本上靜態(tài)方法是生產者,或者簡單地 說,Java由唯一的名字所聲明。唯一的方法就是調用一個程序并且傳遞所有必要的參數(shù)給它。這個程序將會計算出結果并立即返回給調用者。

現(xiàn)在,我們來到了最終的問題上,我能聽到你在問:“好吧,工具類不是函數(shù)式編程,但是他們看起來很像函數(shù)式編程,他們運行的很快,并且使用很方便。為什么不用他們?為什么當20年的Java歷史證明了工具類是每一個Java開發(fā)者的主要手段的時候,又要力求***?”

除了面向對象的,這點我經常受指責,這里有一些實際的原因(順便說一句,我推崇面向對象)。

可測試性。在工具類中調用靜態(tài)方法是硬編碼式的依賴,它不能因為測試的需要而被打斷。如果你的類正在調用FileUtils.readFile(),除非我的磁盤上有一個實際的文件,否則我無法測試。

效率。工具類,由于其命令式的性質,比可替代的聲明式更加低效。即使當他們不是必要使用 的時候,他們也盲目地進行所有的計算,處理資源。而不是返回一個期望值來分隔字符串chunks、StringUtils.split()可以立即打斷 它。同時,這也打破了所有可能的chunks,即使“買家”僅僅需要***個。

可讀性。工具類往往 是龐大的(嘗試從Apache Commons閱讀StringUtils或者FileUtils的源碼)。關注點分離可以使得面向對象如此優(yōu)雅,但這些想法在工具類中是沒有的。他們盡 量把所有可能的程序放進一個.java文件,這導致當它的大小超過了許多靜態(tài)方法的時候是極難維護的。

***,我要重申一下:工具類與函數(shù)編程無關。他們僅僅是靜態(tài)方法的包裝,是命令式的程序。無論你要聲明他們多少次,他們有多渺小,都要盡量遠離他們而去使用可靠、健壯的對象。

 

責任編輯:王雪燕 來源: ImportNew
相關推薦

2015-09-15 09:36:12

大數(shù)據企業(yè)

2021-07-12 09:52:10

物聯(lián)網農業(yè)應用IOT

2020-11-05 09:59:24

Linux內核信號量

2009-04-29 09:49:56

LookupshardingDBA

2015-06-18 15:35:52

SDN

2018-05-09 08:09:15

2011-07-13 16:52:44

2020-05-08 15:48:33

手機PCAndroid

2016-10-12 13:53:38

JavaByteBufferRandomAcces

2013-03-13 16:47:49

2013-09-24 10:58:00

編程生活方式

2009-12-11 14:24:09

路由表信息

2010-04-30 14:51:23

Unix系統(tǒng)

2021-08-10 10:48:39

拷貝代碼架構耦合

2021-08-26 16:55:26

耦合服務化架構

2017-06-08 14:25:46

Kotlin函數(shù)

2022-11-01 07:54:18

Python工具類計數(shù)器

2022-07-07 09:03:36

Python返回函數(shù)匿名函數(shù)

2022-10-12 07:53:46

并發(fā)編程同步工具

2012-03-07 11:03:13

Java設計模式
點贊
收藏

51CTO技術棧公眾號