在GitConnected上发表的文章。
编写代码是任何人都可以获取的技能,但是达到最高标准的清洁代码需要纪律和奉献精神。在本文中,我们将探讨实用策略和工具,以帮助您将Python代码提升到无可挑剔的水平。通过逐渐将这些最佳实践纳入您的开发生命周期中,您可以确保经受时间考验的清洁,无漏洞的代码。
坚持最佳实践不仅保持代码清洁度,而且还可以最大程度地减少引入错误的风险。虽然可能需要最初的时间投资,但从这些实践开始,从长远来看,最终会减少开发工作。作为一名经验丰富的全栈软件工程师,我一直在与我合作的公司中保留编码标准的荣誉。
。为了说明这些最佳实践,我们将考虑一个称为Stack-Scraper的假设项目。该项目由一个单页网站刮刀组成,该网站从(假设)堆栈溢出中提取问题和答案。请注意,堆栈craper不是一个功能性的项目,而是作为演示此处讨论的想法的示例。该示例的源代码可以在GitHub。
上找到我个人使用VS Code作为我的首选IDE,因此此处提到的一些工具和插件也是如此。让我们研究我采用的最佳实践和工具,以确保我的Python代码遵守最高标准。
存储库结构
经过精心设计的存储库结构是清洁代码开发的基础。如果该结构无法满足项目的要求,则开发人员可能会在不同的位置散布代码,从而导致凌乱的结构并减少代码可重复使用性。精心制作的存储库结构在维护代码组织和促进开发人员之间的协作中起着至关重要的作用。
重要的是要注意,对于存储库结构,没有一个大小适中的解决方案。每个项目可能都有需要特定组织计划的独特要求。但是,研究一个实际的例子可以提供宝贵的见解。让我们考虑一下堆栈craper项目的存储库结构。以下是要注意的一些关键点:
-
堆栈craper存储库清楚地采用了不同组件的划分文件夹,例如API(
src/apis
)数据库模型(src/db_wrappers
),域级常数(src/constants
),Pydantic Models(src/domain_models
)和刮刀(src/external_sources/scrappers
)(src/external_sources/scrappers
)等等。此隔离确保代码的逻辑分离,使开发人员可以轻松地找到和修改特定功能。 -
堆栈craper存储库中的测试文件遵循与主存储库相同的层次结构。这种实践确保测试保持井井有条,并与相应的代码保持一致。一致的测试组织简化了测试管理并改善了代码可检验性。
预警
pre-commit是一个框架,可以在承诺之前执行可配置的检查或代码更改上的任务,从而提供了一种方法来执行代码质量,格式和其他特定于项目的特定要求,从而减少潜在问题并保持代码一致性。 /p>
您需要做的就是在存储库中创建一个pre-commit-config.yaml
文件。您可以通过运行以下命令来安装预密码。
pip install pre-commit
pre-commit install
让我们检查一下堆栈craper的koude5。
repos:
- repo: https://github.com/ambv/black
rev: 23.3.0
hooks:
- id: black
args: [--config=./pyproject.toml]
language_version: python3.11
- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
- id: flake8
args: [--config=./tox.ini]
language_version: python3.11
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
args: ["--profile", "black", "--filter-files"]
language_version: python3.11
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: requirements-txt-fixer
language_version: python3.11
- id: debug-statements
- id: detect-aws-credentials
- id: detect-private-key
在这里,我们配置了7个钩子。如果需要,可以添加more hooks,但是上述设置足以帮助您保持代码清洁。
类型的颗粒
python的动态键入允许在没有明确类型定义的情况下分配变量,这可能会导致便利。但是,这种灵活性可能在维持代码质量方面构成挑战,尤其是在可能发生类型错误和不一致的大型项目中。
请考虑以下示例,来自文件:堆栈craper中的src/apis/question_no.py
。您可以确定ques_no
是整数还是字符串?
@stackoverflow_blueprint.route("/stackoverflow/<ques_no>", methods=["GET"])
def get_question_answer(ques_no):
# code to do stuff
现在使用类型颗粒来检查同一示例。显然,它预计ques_no
是一个整数,而get_question_answer
返回响应对象。
@stackoverflow_blueprint.route("/stackoverflow/<ques_no>", methods=["GET"])
def get_question_answer(ques_no: int) -> Response:
# code to do stuff
文档
doc-strings是为每个功能添加的文档字符串,以提高代码可读性。他们提供有关函数目的,参数和返回值的其他信息,使开发人员更容易有效地理解和使用代码。
您还可以使用Doc-strings使用pdoc等库为您的代码生成自动文档。考虑从堆栈craper和使用PDOC库生成的相应文档的以下示例。
@stackoverflow_blueprint.route("/stackoverflow/<ques_no>", methods=["GET"])
def get_question_answer(ques_no: int) -> Response:
"""Function to fetch data for given question number
Args:
ques_no (int): Question number
Returns:
Response: Returns response object
"""
# code to do stuff
声音
SonarLint是一种代码分析工具,可与各种IDE集成(作为免费插件),并有助于识别和修复开发过程中的代码质量问题,安全漏洞和错误,使开发人员能够编写清洁器和更可靠的代码。多年来,这一直是我必须安装的插件。
pydantic
Pydantic是一个Python库,为数据模型提供运行时类型检查和验证。我们的目标不是使Python的行为为C/C ++,但是在某些用例中,它对执行类型检查至关重要。示例:API输入,数据库包装器中的方法可提供数据库中的数据和外部数据库等。
堆叠式造纸展示了相同的实现。通过利用Pydantic模型,StackOverflowQuestionAnswer
作为InMemoryDatabaseWrapper
类中get_question_answer_by_ques_no
方法的输出,我们基于其唯一的标识符建立了从数据库中检索问题的可靠手段。此设计选择可确保数据库的未来变化,包括对其模式的修改,只要该方法的输出遵守Pydantic定义的一致模型。
另一个演示正在验证与上面同一类中的方法upsert_question_answer
的输入,以确保仅允许的值进入数据库。
拼写检查器
最初可能看起来违反直觉,但将咒语检查器纳入您的代码是一种有价值的做法,与提供的其他建议保持一致。包含咒语检查器可确保代码质量和可读性,从而增强了对细节的关注在维护清洁和无错误的代码中的重要性。
首先,由于其不直觉的拼写,它将有助于避免使用upsert_qusetion_answer
之类的命名方法,因为它可能导致使用过程中的错误和混乱。注意qusetion
中的拼写错误。
其次,如果您使用自动文档生成器,则必须最大程度地减少拼写错误。保持准确且无错误的文档不仅可以提高代码可理解的能力,还提高了项目的整体专业素养和信誉。
测试
全面的测试对于维持无错误和强大的代码至关重要,确保其对未来变化和不同开发人员的适应性。虽然希望100%的覆盖范围是可取的,但重点应是彻底测试代码,而不仅仅是覆盖范围。
编写测试用例时,重要的是要考虑代码可能遇到的所有可能场景和边缘案例。这包括正面测试和负面测试,边界测试以及错误处理。 test/src/apis/test_question_no.py
文件中get_question_answer
功能的示例测试用例可以为设计有效的测试用例提供见解。
这就是本文的全部,以维护清洁代码实践和增强代码质量。希望您能在这里发现有价值的见解和策略。请记住,实施这些最佳实践并将它们纳入您的开发习惯中,一次可以对您的代码的可靠性和可维护性产生重大影响。
通过优先考虑代码清洁度并遵守这些做法,您将目睹代码飙升至新的高度。享受编写无可挑剔的代码的旅程,并获得强大的,无错误的软件开发的回报。愉快的编码!
其他提示
在这里,我列出了一些可以纳入编码习惯的通用提示/评论。
- 在您的代码中保证的任何地方都要添加评论。如果您在代码中做出假设,则最好在评论中突出显示相同的内容。示例:file
src/external_sources/scrappers/stack_overflow.py
中的line78
。 - 尽量不要在功能/类中定义常数,因为加班,您最终可能会散布在代码上的这些常数。在其各自的常数文件或各自的模块中定义它们。示例:
src/constants/api_constants.py
。 - 定义您自己的异常,而不是使用通用的例外。这有助于将代码中的异常区分为各个隔离。示例:file22中的
StackOverflowException
代表堆栈溢出刮刀提出的异常。 - 关注OOPs进行编码。示例:通过在文件
src/external_sources/external_source_base.py
中定义基类ExternalSource
的继承。 - 遵循REST API开发原则。
- 不要将秘密添加到您的存储库中。而是使用环境文件或诸如AWS Secrets Manager的秘密管理服务。
- 使您的代码环境不可知。因此,很容易维护单独的开发,测试,分期和/或生产环境。示例:
src/config.py
。 - 您在
requirements.txt
文件中安装的库的PEG版本。由于对库的升级,它有助于避免应用程序故障。