驚豔於紅警開源代碼?賞心悅目的代碼註釋,我們也可以 !

1.前言

這幾天,紅警1的開源代碼重現江湖,這個20年前,甚至25年前的代碼,被我們所有的後來者所驚歎,這纔是一個藝術品(art)一般的存在。其優秀的代碼纔是一款RTS遊戲能夠風靡全球的最根本保障。
其開源鏈接爲:https://github.com/electronicarts/CnC_Remastered_Collection
如果你想重溫這款童年記憶,那麼花費140人民幣,你就可以在Steam上體驗到這款遊戲。

但是,我們的重點,主要在其代碼上,因此不放出其遊戲截圖了,而是專注代碼。下面是我隨便點開的一個文件內容。大家可以欣賞一下什麼是賞心悅目的代碼。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

2. 我們驚歎它的什麼?

通過上圖,我們能夠看到什麼?我們驚歎的是它的什麼?
先看看小夥伴們的評價(只摘取了部分評價):
在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在我看來,我們驚豔的部分至少包含三點:

  1. 清晰的代碼註釋
  2. 語義化的編碼規範
  3. 小而精的邏輯實現

2.1 清晰的代碼註釋

我們可以看到非常工整的文檔頭註釋(圖1),還有詳細的方法註釋(圖2),以及代碼的字裏行間裏的邏輯註釋(圖3)。這些註釋不僅僅是簡單的重複代碼,更把代碼背後的業務邏輯詳細的呈現了出來,使得我們不用猜測這個的用途,只讀代碼就可以知道它應該在哪裏使用。最爲誇張的是第三張,在具體實現中,註釋竟然比代碼所佔篇幅還要大。

2.2 語義化的編碼規範

我們可以看到它明顯的語義化編碼,也就是在邏輯實現部分,儘可能的能夠少考慮具體的實現,如if判斷條件中,使用一個函數來實現具體的判斷,而不是直接把判斷細節暴露出來。這有助於我們思維的連續性,從而從更高的層面對於代碼有一個整體的把握。

2.3 小而精的邏輯實現

一般的,儘可能的要讓一個函數的實現少,大概一個屏幕可以放得下即可,真正做到一個函數只做1件事,這樣既可以避免邏輯混亂,而且也易於維護。對於其中的複雜的邏輯的細節實現,完全可以放到另一個函數中,從而避免一個函數包含了若干個層次的邏輯。

3. 依葫蘆畫瓢

那麼在我們感嘆之餘,我們能不能做些什麼向大佬看齊?在我的Blink發出以後,收到了上百個點贊評論,一致認爲都想像20多年前的前輩一樣優雅的編程。那麼,我們就從最簡單的、最明顯改觀的代碼註釋開始。

在Python中,代碼註釋其實就兩種,單行代碼註釋(#)和多行代碼註釋("""""")。但是我們需要用到的地方則有4個部分:文檔級、類級、方法級和行級別。下面我們分別講解一下這些部分的組成。

3.1 添加文檔級註釋

我們可以看到紅警文件開頭的那個非常醒目的註釋,它展示了整個文件的簡要信息,如屬於什麼項目,誰在什麼時候創建的,什麼時候更新的,而且以一種非常規範的格式呈現在我們面前。我們能不能擁有這樣酷炫的文檔開頭呢?答案是Yes!
首先看一下我復現的效果:
在這裏插入圖片描述
儘管看起來可能沒有紅警原版霸氣,但是隻要學會了這個技術,我們都可以創建屬於自己的風格的文件頭。我們只需要利用pycharm中的文件模板設置即可。它總共分爲3個步驟:
首先,點擊File->Settings進入設置界面,選擇Editor下的File and Code Templates選項。
在這裏插入圖片描述
然後,點擊Python Script(你也可以爲其他類型文件設置文件頭),就可以看到最右側顯式的文件模板了。
最後,只需要將我們喜歡的文件頭複製粘貼進去即可,點擊OK即可。

下面是我仿照紅警風格自己設計的文件頭,大家可以隨意取用(CV一下):

#!/usr/bin/env python
# encoding: utf-8
'''
#-------------------------------------------------------------------#
#                   CONFIDENTIAL --- CUSTOM STUDIOS                 #     
#-------------------------------------------------------------------#
#                                                                   #
#                   @Project Name : ${PROJECT_NAME}                 #
#                                                                   #
#                   @File Name    : ${NAME}.py                      #
#                                                                   #
#                   @Programmer   : Adam                            #
#                                                                   #  
#                   @Start Date   : ${DATE} ${TIME}                 #
#                                                                   #
#                   @Last Update  : ${DATE} ${TIME}                 #
#                                                                   #
#-------------------------------------------------------------------#
# Classes:                                                          #
#                                                                   #
#-------------------------------------------------------------------#
'''

當然,更多其他的這種內置變量或者自定義變量的使用方法可以參見《詳解pycharm新建文件時頭部的模板》。

3.2 添加類級註釋

當添加完文件註釋以後,我們就需要添加更加細緻的註釋,首先來看對於類的註釋。下面的例子給出了類註釋的兩個部分,一個部分是直接處於類下的簡要介紹,另一個則是在__init__下的註釋。兩個部分都是使用"""進行標記的。圖上風格爲pycharm自帶的編碼風格,也有google和Numpy風格的註釋,詳情可以看《python常見的三種註釋風格

class CustomFile:
    """
    This is the main class, the file contains all documents.
    One document contains paragraphs that have several sentences.
    It loads the original file and converts the original file to new content.
    Then the new content will be saved by this class.
    """
    def __init__(self,src_file_name:str):
        """
        Initial the custom file by src file.
        :param src_file_name: string, the original filename.
        :return: None
        """
        file = open(src_file_name, encoding='utf-8').read()
        file="<File>"+file+"</File>"    # Special operation to avoid there is no root. node in original file.
        self.soup = BeautifulSoup(file, 'xml')
        self.document_list=[]
        self._set_documents()

3.3 添加方法級註釋

更加細緻的註釋是在方法級的註釋,如下面代碼所示,它註釋在方法上,一個好處是可以直接指導這個函數的功能,另一個好處就是當你在查看方法時,不需要點擊方法裏面查看源代碼,也知道它的用途、參數和返回值,這個操作我們下面會介紹。

def to_string(self):
        """
        Convert the document into string.
        :return: string, example: para\n\npara\n\npara
        """
        paragraph_string_list=[]
        for paragraph in self.paragraph_list:
            paragraph_string_list.append(paragraph.to_string())
        result="\n\n".join(paragraph_string_list)
        return result

3.4 添加行級註釋

最細緻的是行級註釋,只註釋在每一個行上,例如剛纔出現過的例子。它可以用來解釋一些不是很容易知道操作的目的的代碼。

file="<File>"+file+"</File>"    # Special operation to avoid there is no root.

3.5 其他小技巧

經過以上4級的註釋,我們讓代碼更加的豐滿了,從而能夠達到紅警裏註釋的效果。但是我們這東西可不是繡花枕,中看不中用,它是可以實實在在幫助我們提高編程效率的。下面我們介紹一些小技巧來幫助我們更好的利用我們/其他人的註釋。

3.5.1 查看方法註釋

當我們費了千辛萬苦註釋完畢後,該怎麼查看呢?一個方法就是將鼠標放置在我們想要查看的方法上,按住ctrl,就可以查看到其註釋了。
在這裏插入圖片描述
另一個方法則是ctrl+Q,它用來查看說明文檔呈現的註釋,兩者的不同大家可以通過下面的圖和上面的圖對比可得。
在這裏插入圖片描述

3.5.2 生成說明文檔

就像剛纔講的,這些都是在代碼裏查看的,如果我們想生成一個工業級的軟件說明文檔該如何呢?這麼多註釋不能白寫了呀。這時候我們就可以使用Sphinx來幫助我們實現自動化的說明文檔生成,詳情可以看《Sphinx入門——快速生成Python文檔》。

3.5.3 打包項目所需依賴包

當我們代碼也準備好了,說明文檔也準備好了,距離交付別人就只差一個依賴包了。我們的項目可能會依賴很多第三方的包,如果不給別人一個依賴清單,那麼別人也沒有辦法非常容易的復現你的程序,因爲總會報各種各樣的錯誤。這時候,我們又需要另一個神器了pipreqs
首先使用命令行執行pip install pipreqs
然後進入項目的文件夾裏,執行下面的命令:

pipreqs ./  # 報錯就執行下面這條
pipreqs ./ --encoding=utf-8

這樣就會生成一個requirement.txt文件,裏面就是我們的依賴包了,等到再復現的時候,只需要執行pip install -r requirement.txt即可重裝這些依賴了。

4 小結

至此,我們基本上講述瞭如何實現教科書級的紅警開源代碼需要注意的事項,爲以後我們更好的編碼打下了基礎。在將來,我們將會磨礪自己的編程技巧,終有一天做出一流的藝術品,爲整個虛擬世界真真正正的貢獻自己的一份力量!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章