從Java開源項目中總結出的常見壞實踐(Bad Practice)

来源:https://www.cnblogs.com/valarchie/archive/2022/12/29/17011659.html
-Advertisement-
Play Games

一些開源項目包含了各種編程的最佳實踐供人參考學習和借鑒。但是也有一些開源項目雖然初衷是好的。但是包含了一些代碼的壞實踐。特別是對於一部分剛入行的大學生來說,可能會給到一些錯誤的示範。於是在此列舉一些項目中的壞實踐。 1.方法的用意判斷是與否卻返回字元串的“0”或者“1” 如果一個方法明確返回是與否這 ...


一些開源項目包含了各種編程的最佳實踐供人參考學習和借鑒。但是也有一些開源項目雖然初衷是好的。但是包含了一些代碼的壞實踐。特別是對於一部分剛入行的大學生來說,可能會給到一些錯誤的示範。於是在此列舉一些項目中的壞實踐。

1.方法的用意判斷是與否卻返回字元串的“0”或者“1”

圖片.png
如果一個方法明確返回是與否這兩種情況,那麼沒有必要返回字元串的0或者1。這樣會造成很多地方需要使用
字元串的形式來匹配結果判斷是與否。例如以下這種形式。
圖片.png
方法應該直接返回true或者false。 代碼會簡潔明瞭很多。

2.濫用三元運算符

圖片.png

圖片.png

3.濫用機翻英語

Poor有不好,差的意思。 例如My english is poor.
這裡的Poor是差的意思。
但是下圖這個方法getDatePoor。也用poor來表達獲取時間“差”的含義。
英語還是程式員應該要掌握學習的。不能光靠機翻英語,不然容易鬧笑話。
圖片.png

4.造不必要的大量輪子

很多方法或者功能我們應該儘可能的搜索是否已經有開源成熟的jar包或者框架實現。成熟的開源jar包或者框架,有大量完備的測試以及廣泛的用戶來確保質量。
如果實在需要自己造小輪子,請使用單元測試來確保質量

圖片.png

5.大量if else語句

大量的if-else語句,具體情況具體分析。但是大部分都可以用衛語句提前返回結果。避免大量嵌套。

例如左邊的寫法可以改為右邊的寫法

圖片.png

像下圖這種情況可以用Stream Lambda來進行簡化
圖片.png

優化後

圖片.png

6.多餘的代碼判斷

有些時候可能會寫出一些不必要的冗餘判斷

圖片.png

7.大量的代碼細節讓閱讀者增加心智負擔

圖片.png

我們應該封裝一部分代碼細節,暴露出代碼的主流程,優化後

圖片.png

8.繁瑣的代碼邏輯

圖片.png
像上圖這種情形,我們其實可以使用一句Stream 語句就可以描述出來。

9.資料庫中是與否可以直接用tinyInt映射,不要用字元串來映射

這樣會造成布爾欄位取出時,還需要跟字元串1或者0進行比對,這是很尷尬的設計。
圖片.png

10.異常捕獲之後不做任何處理

我們捕獲異常之後一般都需要使用log來記錄錯誤情形,如果什麼都不做,就很可能丟失錯誤信息,並且使代碼排查過程更加困難。

圖片.png

圖片.png

11.使用Map填充數據

使用Java是靜態語言,使用Map填充數據,反而失去了靜態語言帶來了代碼檢查以及IDEA識別欄位引用的功能。

圖片.png

12.混亂的常量

請不用將項目中所有的常量一股腦的放到一個類中。

圖片.png

可以使用像這種靜態類的方式,分門別類地放入不同的常量

圖片.png

13.請使用駝峰命名

圖片.png

14.變數的定義請在系統內保持一致,比如1在系統內表示是。 請勿有時表示是,有時表示否。

有時候用1表示肯定,有時候用0表示肯定,有時候用Y表示肯定。

圖片.png

圖片.png

圖片.png

15.奇葩的代碼腦迴路

在外層方法判斷一遍,在內層方法又進行一遍一樣的判斷

圖片.png

16.常量隨意的命名格式

常量的命名請使用大寫加下劃線的格式

圖片.png

17.嵌套的Switch語句

就一種case了 完全沒有必要使用switch語句
圖片.png

18.使用魔法值

圖片.png

例如項目中大量使用了“jpg”的字元串魔法值,使用魔法值使得我們無法統一找到代碼的引用處。在重構的時候難免會有疏漏。

圖片.png

19.單個方法代碼超過80行

如果單個方法的代碼行超過80行,意味你的代碼缺乏封裝和可讀性。例如這種一大坨的代碼。

public static void initColumnField(GenTableColumn column, GenTable table)
{
    String dataType = getDbType(column.getColumnType());
    String columnName = column.getColumnName();
    column.setTableId(table.getTableId());
    column.setCreateBy(table.getCreateBy());
    // 設置java欄位名
    column.setJavaField(StringUtils.toCamelCase(columnName));
    // 設置預設類型
    column.setJavaType(GenConstants.TYPE_STRING);
    column.setQueryType(GenConstants.QUERY_EQ);

    if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType))
    {
        // 字元串長度超過500設置為文本域
        Integer columnLength = getColumnLength(column.getColumnType());
        String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
        column.setHtmlType(htmlType);
    }
    else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType))
    {
        column.setJavaType(GenConstants.TYPE_DATE);
        column.setHtmlType(GenConstants.HTML_DATETIME);
    }
    else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType))
    {
        column.setHtmlType(GenConstants.HTML_INPUT);

        // 如果是浮點型 統一用BigDecimal
        String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
        if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0)
        {
            column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
        }
        // 如果是整形
        else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10)
        {
            column.setJavaType(GenConstants.TYPE_INTEGER);
        }
        // 長整形
        else
        {
            column.setJavaType(GenConstants.TYPE_LONG);
        }
    }

    // 插入欄位(預設所有欄位都需要插入)
    column.setIsInsert(GenConstants.REQUIRE);

    // 編輯欄位
    if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk())
    {
        column.setIsEdit(GenConstants.REQUIRE);
    }
    // 列表欄位
    if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk())
    {
        column.setIsList(GenConstants.REQUIRE);
    }
    // 查詢欄位
    if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk())
    {
        column.setIsQuery(GenConstants.REQUIRE);
    }

    // 查詢欄位類型
    if (StringUtils.endsWithIgnoreCase(columnName, "name"))
    {
        column.setQueryType(GenConstants.QUERY_LIKE);
    }
    // 狀態欄位設置單選框
    if (StringUtils.endsWithIgnoreCase(columnName, "status"))
    {
        column.setHtmlType(GenConstants.HTML_RADIO);
    }
    // 類型&性別欄位設置下拉框
    else if (StringUtils.endsWithIgnoreCase(columnName, "type")
            || StringUtils.endsWithIgnoreCase(columnName, "sex"))
    {
        column.setHtmlType(GenConstants.HTML_SELECT);
    }
    // 圖片欄位設置圖片上傳控制項
    else if (StringUtils.endsWithIgnoreCase(columnName, "image"))
    {
        column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD);
    }
    // 文件欄位設置文件上傳控制項
    else if (StringUtils.endsWithIgnoreCase(columnName, "file"))
    {
        column.setHtmlType(GenConstants.HTML_FILE_UPLOAD);
    }
    // 內容欄位設置富文本控制項
    else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
    {
        column.setHtmlType(GenConstants.HTML_EDITOR);
    }
}

20.避免使用反邏輯

圖片.png

像圖中!(x == 0) 可以直接改成x != 0 即可

還有以下這種冗餘代碼。

圖片.png

21.複雜的判斷使用有意義的變數來替代

圖片.png

比如上圖的判斷我們可以用一個變數 isLongField來替代 提高代碼的可讀性。

22.常量沒有使用final來修飾

如果沒有使用final來修飾的話,就有可能在代碼中被修改。

圖片.png

23.字元編碼直接用字元串表示

圖片.png

字元編碼,JDK中都有常量可以直接表示,我們可以直接使用

圖片.png

24.多餘的方法修飾符

Java中interface類,方法預設都是Public的,沒必要再加上public修飾符

圖片.png

25.不必要的ToString

圖片.png

圖片.png

26.多餘的變數聲明

如果變數聲明之後沒有做任何處理,請直接通過return返回,不要多聲明一個變數

圖片.png

27.使用語義不清晰的方法

例如String的indexOf方法 我們完全可以使用contains方法來替代,使代碼的語義更一目瞭然。

圖片.png

28.毫無必要的包裝語句unboxing和boxing

Integer.valueOf

返回的本身就是int, 沒有必要再調用intValue方法
圖片.png

29.使用+=進行在迴圈中字元串拼接

圖片.png

+=會造出臨時的字元串,我們應該使用StringBuilder在迴圈中拼接字元串

以上就是總結的關於項目中的一些壞實踐,請大家務必使用。有其他壞實踐,懇請大家繼續補充。


鄙人在業餘時間弄了一個全棧項目Agileboot,初衷是想做一個代碼規範,項目結構良好,可供大學生或者入門3年內的開發者參考使用的項目。

後端地址:
https://github.com/valarchie/AgileBoot-Back-End
鄙人能力水平有限,如果項目中發現不足或者錯誤,懇請指正。歡迎PR。一起構建一個規範完善的後端項目。

前端地址:
https://github.com/valarchie/AgileBoot-Front-End

鄙人前端小白,關於前端項目的規範以及優化僅作了力所能及的部分,還有很多優化空間。哪位前端大佬有興趣一起幫忙規範和優化嗎?

演示地址
www.agileboot.vip

歡迎加入全棧技術交流群:1398880

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • JZ67 把字元串轉換成整數(atoi) 題目 寫一個函數 StrToInt,實現把字元串轉換成整數這個功能。不能使用 atoi 或者其他類似的庫函數。傳入的字元串可能有以下部分組成: 1.若幹空格 2.(可選)一個符號字元('+' 或 '-') 3. 數字,字母,符號,空格組成的字元串表達式 4. ...
  • 1、阻塞 阻塞模式下,相關方法都會導致線程暫停 ServerSocketChannel.accept 會在沒有連接建立時讓線程暫停 SocketChannel.read 會在通道中沒有數據可讀時讓線程暫停 阻塞的表現其實就是線程暫停了,暫停期間不會占用 cpu,但線程相當於閑置 單線程下,阻塞方法之 ...
  • 用python爬取並分析《2021胡潤百富榜》的榜單數據! 1、python爬蟲講解(requests向介面請求)。 2、python數據分析講解(pandas數據分析及可視化畫圖)含:直方圖、柱形圖、餅圖、詞雲圖等。 ...
  • 安裝anaconda,進行數據標註 1.安裝前準備:下好安裝包和所需文件 https://www.aliyundrive.com/s/XyH2JQ5TjCz 提取碼: 3c2w 2.運行anaconda安裝包,解壓labelimg-master文件 3.把resources.py文件放到/label ...
  • 這篇文章更進一步,會結合電商前後臺API系統,把Go語言的知識點應用到商業項目中,讓大家結合實際的場景去理解,這樣應該對大家更有幫助! ...
  • 摘要:本文主要講解ACE去霧演算法、暗通道先驗去霧演算法以及霧化生成演算法。 本文分享自華為雲社區《[Python圖像處理] 三十.圖像預處理之圖像去霧詳解(ACE演算法和暗通道先驗去霧演算法)丨【拜托了,物聯網!】》,作者:eastmount 。 一.圖像去霧 隨著社會的發展,環境污染逐漸加劇,越來越多的城 ...
  • 前言 今天給大家介紹的是Python爬取Top100電影榜單數據保存csv文件,在這裡給需要的小伙伴們代碼,並且給出一點小心得。 首先是爬取之前應該儘可能偽裝成瀏覽器而不被識別出來是爬蟲,基本的是加請求頭,但是這樣的純文本數據爬取的人會很多,所以我們需要考慮更換代理IP和隨機更換請求頭的方式來對To ...
  • Git 分散式版本控制工具 Git最常用命令 | 命令名稱 | 作用 | | | | |git init|初始化本地庫| |git add ./文件名|把代碼添加到暫存區| |git commit -m '日誌'|把暫存區的文件添加到本地庫| |git push 鏈接 分支名|把本地庫的代碼載入到遠 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...