程序员 rs编码_为什么声明性编码使您成为更好的程序员
程序員 rs編碼
在許多情況下,具有功能組成的聲明式解決方案提供了優(yōu)于傳統(tǒng)命令式代碼的出色代碼指標(biāo)。 閱讀本文并了解如何使用具有功能組成的聲明性代碼成為一名更好的程序員。
在本文中,我們將仔細(xì)研究三個(gè)問題示例,并研究用于解決這些問題的兩種不同技術(shù)(命令式和聲明式)。
本文中的所有源代碼都是開源的,可以在以下位置獲得
https://github.com/minborg/imperative-vs-declarative 。 最后,我們還將看到如何將本文的知識(shí)應(yīng)用于數(shù)據(jù)庫(kù)應(yīng)用程序領(lǐng)域。 我們將使用Speedment Stream作為ORM工具,因?yàn)樗峁┝伺c數(shù)據(jù)庫(kù)中的表,視圖和聯(lián)接相對(duì)應(yīng)的標(biāo)準(zhǔn)Java Streams,并支持聲明性構(gòu)造。
從字面上看,有無(wú)數(shù)個(gè)示例候選可用于代碼度量評(píng)估。
問題范例
在本文中,我選擇了開發(fā)人員在工作期間可能會(huì)遇到的三個(gè)常見問題:
SumArray
遍歷數(shù)組并執(zhí)行計(jì)算
分組
并行匯總值
休息
通過分頁(yè)實(shí)現(xiàn)REST接口
解決技術(shù)
正如本文開頭所暗示的,我們將使用以下兩種編碼技術(shù)來解決上述問題:
勢(shì)在必行
一種命令式解決方案,其中我們使用帶有for循環(huán)和顯式可變狀態(tài)的傳統(tǒng)代碼樣式。
陳述式
聲明性解決方案,其中我們組合了各種功能以形成解決該問題的高階復(fù)合功能,通常使用
java.util.stream.Stream或其變體。
代碼指標(biāo)
然后,我們的想法是使用適用于SonarQube(此處為SonarQube社區(qū)版,版本7.7)的不同解決方案的靜態(tài)代碼分析,以便我們可以為問題/解決方案組合得出有用的標(biāo)準(zhǔn)化代碼量度。 然后將這些指標(biāo)進(jìn)行比較。
在本文中,我們將使用以下代碼指標(biāo):
LOC
“ LOC”表示“代碼行”,是代碼中非空行的數(shù)量。
陳述
是代碼中語(yǔ)句的總數(shù)。 每條代碼行上可能有零到很多語(yǔ)句。
圈復(fù)雜度
指示代碼的復(fù)雜性,是對(duì)通過程序源代碼的線性獨(dú)立路徑數(shù)量的定量度量。 例如,單個(gè)“ if”子句在代碼中提供了兩條單獨(dú)的路徑。
了這里的維基百科。
認(rèn)知復(fù)雜性
SonarCube聲稱:“認(rèn)知復(fù)雜性不同于使用數(shù)學(xué)模型評(píng)估軟件可維護(hù)性的實(shí)踐。 它從Cyclomatic Complexity設(shè)定的先例開始,但是使用人工判斷來評(píng)估應(yīng)如何計(jì)算結(jié)構(gòu)并決定應(yīng)向模型整體添加哪些內(nèi)容。 結(jié)果,它得出的方法復(fù)雜性得分比以前的模型更能使程序員感到可維護(hù)性相對(duì)更公平。 這里 SonarCube自己的頁(yè)面上。
通常,最好構(gòu)想一個(gè)解決方案,其中這些指標(biāo)較小,而不是較大。
作為記錄,應(yīng)該注意的是,以下設(shè)計(jì)的任何解決方案只是解決任何給定問題的一種方法。 如果您知道更好的解決方案,請(qǐng)隨時(shí)告訴我,隨時(shí)通過https://github.com/minborg/imperative-vs-declarative提交拉取請(qǐng)求。
遍歷數(shù)組
我們從一個(gè)簡(jiǎn)單的開始。 該問題示例的對(duì)象是計(jì)算int數(shù)組中元素的總和,并將結(jié)果返回為
long 。 以下接口定義了問題:
當(dāng)務(wù)之急
以下解決方案使用命令式技術(shù)實(shí)現(xiàn)SumArray問題:
public class SumArrayImperative implements SumArray { @Override public long sum( int [] arr) { long sum = 0 ; for ( int i : arr) { sum += i; } return sum; } }聲明式解決方案
這是使用聲明性技術(shù)實(shí)現(xiàn)SumArray的解決方案:
public class SumArrayDeclarative implements SumArray { @Override public long sum( int [] arr) { return IntStream.of(arr) .mapToLong(i -> i) .sum(); } }請(qǐng)注意, IntStream::sum僅返回一個(gè)int,因此我們必須應(yīng)用中間操作mapToLong() 。
分析
SonarQube提供以下分析:
下表顯示了SumArray的代碼指標(biāo)(通常越低越好):
| 勢(shì)在必行 | 12 | 5 | 2 | 1個(gè) |
| 功能性 | 11 | 2 | 2 | 0 |
這是它在圖形中的外觀(通常越低越好):
并行匯總值
該問題示例的對(duì)象是將“ Person對(duì)象分組到不同的存儲(chǔ)桶中,其中每個(gè)存儲(chǔ)桶構(gòu)成一個(gè)人的出生年份和一個(gè)工作的國(guó)家/地區(qū)的唯一組合。對(duì)于每個(gè)組,應(yīng)計(jì)算平均工資。 聚合應(yīng)使用公共的ForkJoin池并行計(jì)算。
(不變的) Person類是這樣的:
勢(shì)在必行我們還定義了另一個(gè)稱為YearCountry不變類,該類將用作分組鍵:
勢(shì)在必行定義了這兩個(gè)類之后,我們現(xiàn)在可以通過以下接口定義此問題示例:
勢(shì)在必行當(dāng)務(wù)之急
實(shí)現(xiàn)對(duì)GroupingBy示例問題的命令性解決方案并GroupingBy 。 這是解決問題的一種解決方案:
勢(shì)在必行聲明式解決方案
這是一個(gè)使用聲明性構(gòu)造實(shí)現(xiàn)GroupingBy的解決方案:
勢(shì)在必行 在上面的代碼中,我使用了一些靜態(tài)導(dǎo)入
Collectors類(例如Collectors::groupingBy )。 這不會(huì)影響代碼指標(biāo)。
分析
SonarQube提供以下分析:
下表顯示了GroupingBy的代碼指標(biāo)(越低越好):
| 勢(shì)在必行 | 52 | 27 | 11 | 4 |
| 功能性 | 17 | 1個(gè) | 1個(gè) | 0 |
相應(yīng)的圖形如下所示(通常越低越好):
實(shí)施REST接口
在這個(gè)示例性問題中,我們將為Person對(duì)象提供分頁(yè)服務(wù)。 出現(xiàn)在頁(yè)面上的人員必須滿足某些(任意)條件,并且必須按照給定的順序進(jìn)行排序。 該頁(yè)面應(yīng)作為不可修改的Person對(duì)象列表返回。
這是捕獲問題的接口:
勢(shì)在必行頁(yè)面的大小在一個(gè)單獨(dú)的實(shí)用程序類RestUtil :
勢(shì)在必行當(dāng)務(wù)之急
這是Rest接口的命令性實(shí)現(xiàn):
勢(shì)在必行聲明式解決方案
下列類以聲明的方式實(shí)現(xiàn)Rest接口:
勢(shì)在必行分析
SonarQube提供以下分析:
下表顯示了Rest的代碼指標(biāo)(通常越低越好):
| 勢(shì)在必行 | 27 | 10 | 4 | 4 |
| 功能性 | 21 | 1個(gè) | 1個(gè) | 0 |
在這里,相同的數(shù)字顯示在圖表中(再次降低通常會(huì)更好):
Java 11的改進(jìn)
上面的示例是用Java 8編寫的。使用Java 11,我們可以使用LVTI(局部變量類型推斷)來縮短聲明性代碼。 這會(huì)使我們的代碼短一些,但不會(huì)影響代碼指標(biāo)。
勢(shì)在必行 與Java 8相比,Java 11包含一些新的收集器。 例如,
Collectors.toUnmodifiableList()可以使我們的聲明式Rest解決方案更短:
同樣,這不會(huì)影響代碼指標(biāo)。
摘要
對(duì)我們的三個(gè)示例性問題的代碼度量取平均會(huì)得到以下結(jié)果(通常越低越好):
考慮到本文的輸入要求,當(dāng)我們從命令式構(gòu)造到聲明式構(gòu)造時(shí),所有代碼度量都有顯著改進(jìn)。
在數(shù)據(jù)庫(kù)應(yīng)用程序中使用聲明性構(gòu)造
為了從數(shù)據(jù)庫(kù)應(yīng)用程序中獲得聲明式構(gòu)造的好處,我們使用了Speedment Stream 。 Speedment Stream是基于Stream的Java ORM工具,可以將任何數(shù)據(jù)庫(kù)表/視圖/聯(lián)接轉(zhuǎn)換為Java流,從而使您可以在數(shù)據(jù)庫(kù)應(yīng)用程序中運(yùn)用聲明性技能。
您的數(shù)據(jù)庫(kù)應(yīng)用程序代碼將變得更好。 實(shí)際上,針對(duì)數(shù)據(jù)庫(kù)的具有Speedment和Spring Boot的分頁(yè)REST解決方案可能表示為:
勢(shì)在必行Speedment提供了Manager<Person> persons ,并構(gòu)成數(shù)據(jù)庫(kù)表“ Person”的句柄,并且可以通過Spring @AutoWired進(jìn)行管理。
結(jié)論
選擇聲明式而不是命令式解決方案可以大大降低通用代碼的復(fù)雜性,并可以提供許多好處,包括更快的編碼,更好的代碼質(zhì)量,更高的可讀性,更少的測(cè)試,減少的維護(hù)成本等等。
為了從數(shù)據(jù)庫(kù)應(yīng)用程序中的聲明性構(gòu)造中受益,Speedment Stream是一種可以直接從數(shù)據(jù)庫(kù)提供標(biāo)準(zhǔn)Java Streams的工具。
如今,對(duì)于任何當(dāng)代的Java開發(fā)人員來說,必須掌握聲明性構(gòu)造和功能組成。
資源資源
文章源代碼: https : //github.com/minborg/imperative-vs-declarative
SonarQube: https ://www.sonarqube.org/ Speedment Stream: https ://speedment.com/stream/ Speedment初始化程序: https ://www.speedment.com/initializer/
翻譯自: https://www.javacodegeeks.com/2019/08/declarative-coding-makes-better-programmer.html
程序員 rs編碼
總結(jié)
以上是生活随笔為你收集整理的程序员 rs编码_为什么声明性编码使您成为更好的程序员的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 有什么办法关闭电脑弹窗电脑弹窗怎样关闭
- 下一篇: 如何设计高效测试用例_高效的企业测试-单