歡迎光臨
每天分享高質量文章

如何編寫相對標準的後端專案 (一)組織與執行

(點選上方公眾號,可快速關註)


來源:koala bear,

wsfdl.com/architecture/2017/12/18/daemon_normalize_arch.html

本人接觸過數個 Open Source 專案,如 OpenStack/Kubernetes 等,深感這些優秀的開源專案存在著一些共性,如:美觀的程式碼,完整的測試,設計理念,框架和架構等等。一般來說,遵循這些優良原則的專案在易讀性,可維護性,特別是(功能和規模的)可擴充套件性會更強些。

本文探討性的梳理部分開源專案某些共同的優秀之處,但是軟體工程領域,不同業務/語言的專案千差萬別,故“標準”二字也是相對的,更適合於 golang/python 語言編寫的 LAM(Linux/Apache/Mysql)後端專案,爭議之處請多包涵。

目錄組織與命名

目錄組織

不同語言下的目錄組織可能會有很大的差異,但是都遵循以下共識:

  • 語意貼切:檔案/目錄的命名要盡可能表達其功能/用途

  • 集中原則:功能相近的檔案/目錄應集中存放

例如:

your_project /

|– contrib /        # 存放一些如 rpm.spec,指令碼等等

|– doc /            # 檔案相關

|– examples /       # 樣例說明

|– etc(or conf) /   # 配置檔案

|– src /

    |– api /               # api 相關程式碼

    |– cmd(or cli) /       # command 相關程式碼,

    |– db /                # database 相關程式碼

    |– rpc /               # rpc 相關程式碼

    |– tests /             # 測試檔案目錄

    |– utils(or common) /  # 一些公共的方法

    |– …                 # 其它目錄/檔案

|– README           # 專案說明

|– .gitigore        # 忽略的 git 檔案和目錄

|– …              # 其它目錄/檔案

  • api:存放 api 相關程式碼,比如 route,filter,middleware,serialize/de-serialize等。

  • contrib:存放一些編包的檔案,git 的 patch 檔案,systemd 的配置檔案,以及指令碼等等。

  • db:存放 database(如:sql/NoSQL) 相關程式碼,包括 model, connection, session,orm/sql。是程式碼層面訪問 db 的唯一入口,建議所有訪問 database 的操作都必須在程式碼層面經過 db 目錄下的程式碼。

  • utils:一般存放一些公共的方法,如 time/date,encoding/decoding,exec,regex,uuid,string/json 等等。

推薦閱讀:

  • What is the best project structure for a Python application?

    https://stackoverflow.com/questions/193161/what-is-the-best-project-structure-for-a-python-application

  • What is a sensible way to layout a Go project

    https://stackoverflow.com/questions/14867452/what-is-a-sensible-way-to-layout-a-go-project

命名

匈牙利命名法和 unix 命名法是常見的命名風格,一般來說,c 和 python 以 unix 命名法居多,golang 和 java 以匈牙利命名法居多。程式設計過程中,遵循一致的命名風格,會使得程式碼更為美觀,可讀性強。

程式設計中貼切的縮寫常見單詞,可使得程式碼更為簡潔美觀,但是縮寫最好應遵循某些約定成俗,避免產生歧義。

一般情況下不建議採用拼音命名和拼音縮寫。

推薦閱讀:

  • Google Python Style Guides

    https://google.github.io/styleguide/pyguide.html

  • Google Shell Style Guide

    https://google.github.io/styleguide/shell.xml

  • 一個查單詞縮寫的網站

    http://www.abbreviations.com/

釋出與執行

為什麼應用的釋出和執行也應該遵循一定的規則呢?首先,使用者體驗更好。比如,軟體工程師習慣性在 /etc 尋找配置檔案,/var/log 尋找日誌檔案。其次,遵循這些規則有利於被運維軟體管理,如 ansible,chef 等等。最後,linux 及相關軟體在設計時就已經遵循這些規則,如果你的應用不遵循,可能會產生某些衝突。

版本號

釋出版本時,版本號的命名需要遵循某種規則,其中 Semantic Versioning 2.0.0 定義了一套簡單的規則。重點如下: 版本號的格式為 X.Y.Z(又稱 Major.Minor.Patch),遞增的規則為:

  • X 表示主版本號,當 API 的相容性變化時,X 需遞增。

  • Y 表示次版本號,當增加功能時(不影響 API 的相容性),Y 需遞增。

  • Z 表示修訂號,當做 Bug 修複時(不影響 API 的相容性),Z 需遞增。

  1. X, Y, Z 必須為非負整數,且不得包含前導零,必須按數值遞增,如 1.9.0 -> 1.10.0 -> 1.11.0

  2. 當 API 的相容性變化時,X 必須遞增,Y 和 Z 同時設定為 0;當新增功能(不影響 API 的相容性)或者 API 被標記為 Deprecated 時,Y 必須遞增,同時 Z 設定為 0;當進行 bug fix 時,Z 必須遞增。

  3. 版本一經釋出,不得修改其內容,任何修改必須在新版本釋出!

推薦閱讀:

  • Semantic Versioning 2.0.0

    https://fedoraproject.org/wikiHow_to_create_an_RPM_package/zh-cn

打包

不同語言的應用可能有不同的打包和釋出規範,如 java 的 jar 包,python 的 wheel 包,它們極大的簡化了應用的安裝/升級/管理等等,非常方便的解決了版本和依賴問題。但是上述的打包方式在通用性上有所欠缺,只能被特定語言的工具管理,比如 jar 包需要被 maven 等管理,wheel 包需要 pip 等管理。為此 Redhat 定義了 redhat package management(即 rpm 包),所有語言的應用都可以製作成 rpm 包,然後用 rpm 和 yum 等常用工具進行管理。與此類似,ubuntu 也定義了 debian 包。

個人認為,應用最好以軟體包的形式釋出,避免直接複製原始碼或者二進位制檔案到線上。

推薦閱讀:

  • How to create an RPM package

    https://fedoraproject.org/wikiHow_to_create_an_RPM_package/zh-cn

  • Python application 的打包和釋出

    http://wsfdl.com/python/2015/09/06/Python應用的打包和釋出上.html

執行

一個應用可能包涵配置檔案,程式碼庫,可執行檔案等等,這些檔案的存放也所講究,一般來說:

  • 可執行檔案應存放於 /usr/bin 或者 /usr/local/bin 目錄下

  • 程式碼或者庫應放於 /usr/lib 或者 /var/lib 目錄下

  • 配置檔案應存放於 /etc/your_project/ 目錄下

  • 日誌檔案應存放於 /var/log/your_project 目錄下

  • systemd 相關指令碼應該放置於 /usr/lib/systemd/system/ 目錄下

  • logrotate 相關指令碼應該放置於 /etc/logrotate.d/ 目錄下

個人不建議把應用放在 /home 目錄下。

測試

測試可分為單元測試/整合測試/效能測試。需不需要測試,需要哪些測試,測試改寫率為多少和很多因素有關,個人認為:

  • 程式碼越多,測試越重要

  • 動態語言,測試越重要

  • 開發人員越多,測試越重要

從經驗上看,很多專案一般都會有整合測試,但是很少有單元測試。這裡想談談單元測試的重要性,它很大程度上保證了新加的程式碼不會影響原有的邏輯。首先這種程式碼級別首先更為精細,能夠針對性的改寫重要功能程式碼。其次,單元測試的執行一般不依賴具體環境,能夠隨時編寫隨時測試。再次,單元測試能夠在一定程度上維護程式碼的結構。最後,都說動態一時爽,重構火葬場,而完整的單元測試是避免火葬場的重要手段。

很多語言都有測試框架和工具,這些工具功能強大,如:執行測試,生成測試報告,程式碼風格規範檢查,整合 jenkins 等等。建議根據需要選擇合適的測試框架。

推薦閱讀:

  • tox vision: standardize testing in Python

    https://tox.readthedocs.io/en/latest/

  • 談談開發中單元測試的重要性

    http://ufdouble.com/2016/07/談談開發中單元測試的重要性/

看完本文有收穫?請轉發分享給更多人

關註「ImportNew」,提升Java技能

贊(0)

分享創造快樂