zoukankan      html  css  js  c++  java
  • Day 22: 软件开发目录设计规范

    软件开发目录设计

    对于提高项目可读性、可维护性的要求就很高了。”项目目录结构”其实也是属于”可读性和可维护性”的范畴,我们设计一个层次清晰的目录结构,就是为了达到以下两点:

    可读性高: 不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪儿,配置文件在哪儿等等。从而非常快速的了解这个项目。

    可维护性高: 定义好组织规则后,维护者就能很明确地知道,新增的哪个文件和代码应该放在什么目录之下。这个好处是,随着时间的推移,代码/配置的规模增加,项目结构不会混乱,仍然能够组织良好。

     

    Foo/
    |-- bin/
    |   |-- foo
    |
    |-- foo/
    |   |-- tests/
    |   |   |-- __init__.py
    |   |   |-- test_main.py
    |   |
    |   |-- __init__.py
    |   |-- main.py
    |
    |-- docs/
    |   |-- conf.py
    |   |-- abc.rst
    |
    |-- setup.py
    |-- requirements.txt
    |-- README

    1、bin/: 存放项目的一些可执行文件,当然你可以起名 script/之类得也行

    2、foo/: 存放项目的所有源代码。

    (1)源代码中的所有模块、包都应该放在此目录。不要置于顶层目录

    (2)其子目录tests/存放单元测试代码;

    (3)程序的入口最好命名为main.py

    3、docs/:存放一些文档

    setup.py:安装、部署、打包的脚本

    4、requirements.txt:存放软件依赖的外部python包列表

    README:项目的说明文件。

    除此之外,有一些方案给出了更加多的内容。比如LICENSE.txt,ChangeLog.txt 文件等,这些东西主要是项目开源的时候需要用到的。

    关于README[自述文件]的内容

    这个文件的目的是能够简要的描述项目的信息,让读者快速了解这个项目。

    它需要说明一下几个事项:

    1、软件的定位,软件的基本功能

    2、运行代码的方法:安装环境,启动命令等

    3、简要的使用说明

    4、代码目录结构说明,更详细点可以说明软件的基本原理

    5、常见问题说明。

    关于requirements.txt[要求]和setup.py

    setup.py

    一般来说用setup来管理代码的打包、安装、部署问题。业界标准的写法是用python刘雪的打包工具Setuptools来管理这些事情。这种方式普遍应用于开源项目中。不过这里的核销思想不是用标准化的工具来解决这些问题,而是说,一个项目一定要有一个安装部署的工具,能快速便捷的在一台新机器上讲环境安装好,代码部署好喝将程序运行起来 。

    如果手动完成 软件的 安装环境,部署代码,运行程序,经常会出现以下问题。

    1、安装环境时经常忘记最近添加了一个新的python 包,结果一到线上运行,程序就出错了。

    2、python包的版本依赖问题,有时候程序中使用的是一个版本的python包,但是官网的意见是最新的包了,通过手动安装可能会出错。

    3、如果依赖的包很多的话,一个一个安装这些依赖是很费事

    4、新手再开始写项目的时候,将程序跑起来非常麻烦,因为可能经常忘记这么安装各种依赖

    setup.py可以将这些事情自动化起来,提供效率,减少出错的概率“复杂的东西自动化,能自动化的东西一定要自动化”是一个非常好的习惯

    setuptools的文档比较庞大,刚接触的话,可能不好找到切入点,学习技术的方式就是看他人是怎么用得,可以参考python的一个web框架,flask是如何写得:setup.py

    当然,简单点自己写个安装脚本(deploy.sh【配置,展开】)替代setup.py也是可以的

    requirements.txt

    这个文件存在的目的是:

    1‘方便开发者维护软件的包一辆。将开发过程中新增的包添加进这个列表中,避免在Setup.py安装一辆时漏掉软件包。

    2、方便读者明确项目使用了哪些python包

    这个文件的格式是每一行包含一个包的依赖说明,通常是flask> = 0.10这种格式,要求是这个格式能被pip识别,这样可以简单的通过pip install -r requirements.txt 把所有python包依赖都装好了,具体格式说明:

    需求文件¶
    在安装软件,特别是Python软件包时,通常会安装很多库。你刚刚做了easy_install MyPackage ,你得到了十几个包。每个软件包都有自己的版本。
    
    也许你运行该安装,它的工作原理。大!它会继续工作吗?您是否必须提供特殊选项才能找到所有内容?你必须安装一堆其他可选件吗?最重要的是,你能再次做到吗?需求文件为您提供了创建环境的方法:一组协同工作的包。
    
    如果您曾尝试在新系统上设置应用程序,或者稍微更新一些应用程序,并且使其失败,那么pip要求就适合您。如果你没有遇到这个问题那么你最终会这样,所以pip要求也适合你 - 要求明确,可重复地安装包。
    
    那么什么是需求文件?它们非常简单:要安装的软件包列表。您可以创建一个需求文件,而不是运行像pip install MyApp这样的东西并获取任何库。
    
    MyApp的
    框架== 0.9.4
    库> = 0.2
    如果将其保存在requirements.txt中,则可以pip install -r requirements.txt。无论MyApp在setup.py中列出什么,您都将获得特定版本的Framework(0.9.4)和至少0.2版本的Library。(您可能认为可以在MyApp的setup.py中列出这些特定版本 - 但如果您这样做,则必须编辑MyApp,如果您想尝试新版本的Framework,或者如果您确定该版本,则需要发布新版本的MyApp库0.3不适用于您的应用程序。)您还可以添加MyApp不严格要求的可选库和支持工具,为人们提供一组推荐的库。
    
    您还可以包含“可编辑”包 - 从Subversion,Git,Mercurial和Bazaar签出的包。这些就像使用-e 选项来进行pip一样。他们看着像是:
    
    -e svn + http:// myrepo / svn / MyApp#egg = MyApp
    您必须使用svn +(git +,hg +或bzr +)启动URL ,并且必须包含#egg = Package,因此pip知道该URL的内容。您还可以在URL中包含@rev,例如@ 275以查看修订版275。
    
    需求文件大多是扁平的。也许MyApp需要 Framework,而Framework需要Library。我鼓励您仍然将所有这些列在一个需求文件中; Python程序的本质是 MyApp和Library之间直接存在隐式绑定。例如,Framework可能会暴露一个Library的对象,因此如果更新了Library,它可能会直接破坏MyApp。如果发生这种情况,您可以更新需求文件以强制使用早期版本的库,并且您可以执行此操作而无需重新发布MyApp。
    
    阅读需求文件格式以了解其他功能。
    
    冻结要求
    所以你有一套可用的软件包,你希望能够在其他地方安装它们。 需求文件允许您安装确切的版本,但它不会告诉您所有确切版本是什么。
    
    要从已知的工作环境创建新的需求文件,请使用:
    
    $ pip freeze> stable-req.txt
    这将为stable-req.txt编写所有已安装库的列表,其中 包含每个库的确切版本。您可能希望在生成后编辑文件(例如,消除不必要的库),但它将为构建需求文件提供稳定的起点。
    
    您还可以为其提供现有的需求文件,并将其用作新文件的一种模板。所以,如果你这样做:
    
    $ pip freeze -r devel-req.txt> stable-req.txt
    它将按顺序保留devel-req.txt中列出的包并保留注释。
    
    该要求的文件格式
    需求文件是一种获取pip以安装特定包以构成环境的方法。本文档描述了该格式。要了解何时应使用需求文件,请参阅需求文件。
    
    需求文件的每一行都表示要安装的内容。例如:
    
    MyPackage == 3.0
    告诉pip安装3.0版本的MyPackage。
    
    您还可以在需求文件中请求额外内容:
    
    MyPackage == 3.0  [ PDF ]
    包也可以以“可编辑”的形式安装。这将源代码放入src / distname(使名称小写)并在包上运行python setup.py develop。要表示可编辑,请使用-e,如:
    
    -e svn + http://svn.myproject.org/svn/MyProject/trunk#egg=MyProject
    该#蛋= MyProject的部分是很重要的,因为虽然你可以给出的SVN位置只需安装,项目名称是在其他地方有用。
    
    您还可以为不可编辑的网址指定鸡蛋名称。这对于指向本地文件系统上的HEAD位置很有用:
    
    文件:///路径/要/你的/ lib目录/项目#蛋= MyProject的
    或相对路径:
    
    文件:../../ LIB /项目#蛋= MyProject的
    如果你需要给pip(和关联easy_install)提示有关在哪里找到包,你可以使用-f (-- find-links)选项,如:
    
    $ pip -f http://someserver.org/index-of-packages MyPackage == 3.0
    然后皮普将寻找在链路http://someserver.org/index-of-packages 匹配版本3.0的MyPackage的 -链接应该像MyPackage的-3.0.tar.gz。
    
    如果你想从带有直接链接的tarball或zip文件安装,你不需要-f选项,你只需要传递绝对URL,如:
    
    $ pip install http://someserver.org/packages/MyPackage-3.0.tar.gz
    版本控制
    现在pip知道以下主要版本控制系统:
    
    颠覆
    Pip支持URL方案svn,svn + svn,svn + http,svn + https,svn + ssh。您还可以对SVN URL进行特定修订,例如:
    
    -e svn + svn://svn.myproject.org/svn/MyProject#egg=MyProject
    -e svn + http://svn.myproject.org/svn/MyProject/trunk@2019#egg=MyProject
    这将检查修订版 2019. @ {20080101}还将查看2008-01-01的修订版。您只能使用-e svn + ...查看特定的修订版本。
    
    Git的
    Pip目前支持通过git,git + http和git + ssh进行克隆:
    
    -e git://git.myproject.org/MyProject.git#egg=MyProject
    -e git + http://git.myproject.org/MyProject/#egg=MyProject
    -e git + ssh://git@myproject.org/MyProject/#egg=MyProject
    传递分支名称,提交哈希或标记名称也是可能的:
    
    -e git://git.myproject.org/MyProject.git@master#egg=MyProject
    -e git://git.myproject.org/MyProject.git@v1.0#egg=MyProject
    -e git:/ / / / / / / / / / / / / / / /
    水银
    支持的方案是:hg + http,hg + https, hg + static-http和hg + ssh:
    
    -e hg + http://hg.myproject.org/MyProject/#egg=MyProject
    -e hg + https://hg.myproject.org/MyProject/#egg=MyProject
    -e hg + ssh://hg@myproject.org/MyProject/#egg=MyProject
    您还可以指定修订号,修订哈希,标记名称或本地分支名称:
    
    -e hg + http://hg.myproject.org/MyProject/@da39a3ee5e6b#egg=MyProject
    -e hg + http://hg.myproject.org/MyProject/@2019#egg=MyProject
    -e hg + http://hg.myproject.org/MyProject/@v1.0#egg=MyProject
    -e hg + http://hg.myproject.org/MyProject/@special_feature#egg=MyProject
    义卖
    Pip使用bzr + http,bzr + https,bzr + ssh, bzr + sftp,bzr + ftp和bzr + lp方案支持Bazaar :
    
    -e bzr + http://bzr.myproject.org/MyProject/trunk/#egg=MyProject
    -e bzr + sftp://user@myproject.org/MyProject/trunk/#egg=MyProject
    -e bzr + ssh://user@myproject.org/MyProject/trunk/#egg=MyProject
    -e bzr + ftp://user@myproject.org/MyProject/trunk/#egg=MyProject
    -e bzr + lp:MyProject#egg = MyProject
    可以像这样安装标签或修订版:
    
    -e bzr + https://bzr.myproject.org/MyProject/trunk/@2019#egg=MyProject
    -e bzr + http://bzr.myproject.org/MyProject/trunk/@v1.0#egg=MyProject
    递归要求
    如果您愿意,还可以参考其他需求文件,例如:
    
    -r Pylons-requirements.txt
    这为您提供了一种抽象出各种要求的方法。但是,对于冻结的要求,这并不是非常友好,因为Pylons-requirements.txt中的所有内容都 将显示在冻结文件中。
    
    索引,查找链接
    您还可以 在需求文件中为--index-url和--find-links选项提供值,例如:
    
    --index-url http://example.com/private-pypi/
    请注意,使用--index-url会删除PyPI的使用,而使用--extra-index-url将添加其他索引。
    
    --find-links更加临时; 而不是一个完整的“索引”,你只需要一个指向可用包的链接的HTML页面。只需将所有私有软件包放在一个目录中并使用Apache自动索引,就可以发布软件包,以便pip可以找到它们。 --find-links总是添加剂; pip看着它能找到的一切。使用它像:
    
    --find-links http://example.com/private-packages/
    请注意,所有这些选项必须在他们自己的行上。
    格式说明

    关于配置文件的使用方法

    注意,再上面的目录结构中,没有将conf.py放在源码目录下,而是放在.docs/目录下。

    很多项目对配文件的使用做法是:

    1、配置文件写在一个或多个python文件中,比如此处的conf.py。

    2、项目中哪个模块用到这个配置文件就通过import conf 这种形式在代码中使用配置。

    这种做法不是很赞成:

    1、这让单元测试变得困难(因为模块内部依赖了外部配置)

    2、另外一方面配置文件作为用户控制程序的接口,应当可以由用户自由一指定文件的路径。

    3、程序组件可复用性太差,因为这种贯穿所有模块的代码硬编码方式,使得大部分模块都依赖conf.py这个文件。

    所有,配置的使用,更好的方式是:

    1、模块的配置都是可以灵活配置的,不受外部配置文件的影响。

    2、程序的配置也可以灵活控制。

    能够佐证这个思想的是,用过nginx和mysql的人都知道,nginx,mysql这些程序都可以自由的指定用户配置。

    所以,不应当再代码中直接import conf 来配置文件。上面的目录结构中conf.py是给出的一个配置样例,不是在写死程序直接引用的配置文件,可以通过 给main.py启动参数指定配置路径的方式来让程序读取配置内容。当然,这里的conf.py你可以换个类似的名字,或者你也可以使用其他格式的内容来编写配置文件,比如settings.yaml之类。

  • 相关阅读:
    函数模板的局限性级解决方法(第三代具体化)
    模板实现机制
    函数模板与普通函数的区别以及调用规则
    函数模板基本用法及泛型
    向上类型转换和向下类型转换
    虚析构和纯虚析构
    纯虚函数和抽象类
    多态原理
    静态联编和动态联编即多态的概念
    虚基类的内部工作原理
  • 原文地址:https://www.cnblogs.com/sunjinchao/p/11127916.html
Copyright © 2011-2022 走看看