这几天,红警1的开源代码重现江湖,这个20年前,甚至25年前的代码,被我们所有的后来者所惊叹,这才是一个艺术品(art)一般的存在。其优秀的代码才是一款RTS游戏能够风靡全球的最根本保障。
其开源链接为:https://github.com/electronicarts/CnC_Remastered_Collection
如果你想重温这款童年记忆,那么花费140人民币,你就可以在Steam上体验到这款游戏。
但是,我们的重点,主要在其代码上,因此不放出其游戏截图了,而是专注代码。下面是我随便点开的一个文件内容。大家可以欣赏一下什么是赏心悦目的代码。
通过上图,我们能够看到什么?我们惊叹的是它的什么?
先看看小伙伴们的评价(只摘取了部分评价):
我们可以看到非常工整的文档头注释(图1),还有详细的方法注释(图2),以及代码的字里行间里的逻辑注释(图3)。这些注释不仅仅是简单的重复代码,更把代码背后的业务逻辑详细的呈现了出来,使得我们不用猜测这个的用途,只读代码就可以知道它应该在哪里使用。最为夸张的是第三张,在具体实现中,注释竟然比代码所占篇幅还要大。
我们可以看到它明显的语义化编码,也就是在逻辑实现部分,尽可能的能够少考虑具体的实现,如if判断条件中,使用一个函数来实现具体的判断,而不是直接把判断细节暴露出来。这有助于我们思维的连续性,从而从更高的层面对于代码有一个整体的把握。
一般的,尽可能的要让一个函数的实现少,大概一个屏幕可以放得下即可,真正做到一个函数只做1件事,这样既可以避免逻辑混乱,而且也易于维护。对于其中的复杂的逻辑的细节实现,完全可以放到另一个函数中,从而避免一个函数包含了若干个层次的逻辑。
那么在我们感叹之余,我们能不能做些什么向大佬看齐?在我的Blink发出以后,收到了上百个点赞评论,一致认为都想像20多年前的前辈一样优雅的编程。那么,我们就从最简单的、最明显改观的代码注释开始。
在Python中,代码注释其实就两种,单行代码注释(#)和多行代码注释("""""")。但是我们需要用到的地方则有4个部分:文档级、类级、方法级和行级别。下面我们分别讲解一下这些部分的组成。
我们可以看到红警文件开头的那个非常醒目的注释,它展示了整个文件的简要信息,如属于什么项目,谁在什么时候创建的,什么时候更新的,而且以一种非常规范的格式呈现在我们面前。我们能不能拥有这样酷炫的文档开头呢?答案是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新建文件时头部的模板》。
当添加完文件注释以后,我们就需要添加更加细致的注释,首先来看对于类的注释。下面的例子给出了类注释的两个部分,一个部分是直接处于类下的简要介绍,另一个则是在__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+"" # Special operation to avoid there is no root. node in original file.
self.soup = BeautifulSoup(file, 'xml')
self.document_list=[]
self._set_documents()
更加细致的注释是在方法级的注释,如下面代码所示,它注释在方法上,一个好处是可以直接指导这个函数的功能,另一个好处就是当你在查看方法时,不需要点击方法里面查看源代码,也知道它的用途、参数和返回值,这个操作我们下面会介绍。
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
最细致的是行级注释,只注释在每一个行上,例如刚才出现过的例子。它可以用来解释一些不是很容易知道操作的目的的代码。
file="" +file+"" # Special operation to avoid there is no root.
经过以上4级的注释,我们让代码更加的丰满了,从而能够达到红警里注释的效果。但是我们这东西可不是绣花枕,中看不中用,它是可以实实在在帮助我们提高编程效率的。下面我们介绍一些小技巧来帮助我们更好的利用我们/其他人的注释。
当我们费了千辛万苦注释完毕后,该怎么查看呢?一个方法就是将鼠标放置在我们想要查看的方法上,按住ctrl
,就可以查看到其注释了。
另一个方法则是ctrl+Q
,它用来查看说明文档呈现的注释,两者的不同大家可以通过下面的图和上面的图对比可得。
就像刚才讲的,这些都是在代码里查看的,如果我们想生成一个工业级的软件说明文档该如何呢?这么多注释不能白写了呀。这时候我们就可以使用Sphinx来帮助我们实现自动化的说明文档生成,详情可以看《Sphinx入门——快速生成Python文档》。
当我们代码也准备好了,说明文档也准备好了,距离交付别人就只差一个依赖包了。我们的项目可能会依赖很多第三方的包,如果不给别人一个依赖清单,那么别人也没有办法非常容易的复现你的程序,因为总会报各种各样的错误。这时候,我们又需要另一个神器了pipreqs
。
首先使用命令行执行pip install pipreqs
。
然后进入项目的文件夹里,执行下面的命令:
pipreqs ./ # 报错就执行下面这条
pipreqs ./ --encoding=utf-8
这样就会生成一个requirement.txt
文件,里面就是我们的依赖包了,等到再复现的时候,只需要执行pip install -r requirement.txt
即可重装这些依赖了。
至此,我们基本上讲述了如何实现教科书级的红警开源代码需要注意的事项,为以后我们更好的编码打下了基础。在将来,我们将会磨砺自己的编程技巧,终有一天做出一流的艺术品,为整个虚拟世界真真正正的贡献自己的一份力量!