一、背景

软件开发是一个系统工程,当然编码实现是其中尤其重要的一个环节,关乎到功能需求的实现好坏。这个环节中除了编码这一硬功之外,与之相关的编码风格这一柔道,虽然没有直接决定功能的实现与否,但却在很大程度上决定了的项目代码整体的可读性、健壮性、移植性、可维护性等重要特性。编码风格不仅涉及到代码如何编写,也涉及到代码模块的分布组织,即项目代码目录的设计。

好的代码目录设计可以直观展现开发者的逻辑条理,提高代码的可读性、可维护性、移植性甚至是健壮性,不好的代码目录设计就不细说了,逻辑层次混乱不清,代码拷贝到其他环境不能运行等是最常见的问题了。

今天就来谈谈软件目录开发设计规范相关的事宜。

二、设计软件目录开发规范的重要性和必要性

在上文中略微提到软件项目代码目录设计规范对项目的一些影响,这里细化展开一下其重要性和必要性,大致为以下几点:

  • 可读性高:好的代码目录设计,可以让刚接触项目的人员通过目录即可大致了解开发者的逻辑条理,明确程序入口文件、测试样例、说明帮助文档、配置文件等的分布位置,从而可以最快的速度熟悉项目。
  • 可维护性强:当前的目录设计规范可以明确地提示维护者新增的代码文件、配置文件等该设计在哪个目录下,以便更好的维护项目。这样可确保随着时间的推移和人员的变更,项目本身的可维护性依然很强。
  • 可移植性:当项目上到一定规模或变得复杂时,通过不同的层级目录来分布不同用途的文件显得异常重要,这样可以确保代码包拷贝到其他环境后,尽可能地避免因模块依赖、配置文件缺少、目录调用失败等问题导致的运行失败问题。

三、软件开发目录组织方式

仅以Python为例,谈谈建议的软件开发目录组织结构:

Foo/
|-- bin/
| |-- foo
|
|-- foo/
| |-- tests/
| | |-- __init__.py
| | |-- test_main.py
| |
| |-- __init__.py
| |-- main.py
| |--conf/ | |-- __init__.py | |-- settings.py | |--logs/ |
|-- docs/
| |-- conf.py
| |-- abc.rst
|
|-- setup.py
|-- requirements.txt
|-- README
 
解释如下:
1. bin/: 存放项目的一些可执行文件,当然起名scripts/之类的也未尝不可
2. foo/: 存放项目的所有源代码。(1) 源代码中的所有模块、包都应该放在此目录。不要置于顶层目录。(2) 其子目录tests/存放单元测试代码; (3) 程序的入口最       好命名为main.py
3. conf/: 存放配置文件
4. logs/: 作为日志目录存放程序运行中生成的各种日志
5. docs/:存放项目的帮助文档
6. setup.py:安装、部署、打包的脚本,一般用于适配环境、解决依赖关系等
7. requirements.txt: 存放软件依赖的外部python包列表
8. README:存放项目说明文档,下文详述
除此之外,有一些方案给出了更加多的内容。比如LICENSE.txt,ChangeLog.txt文件等,其中LICENSE.txt主要是项目开源的时候需要用到。ChangeLog.txt可根据需要确定是否添加。

四、README相关

使用过开源软件的朋友们都知道README可以给软件的使用带来很大的帮助,包括软件介绍、功能定位、安装启动使用方法、有建议或bug怎么联系作者等,其必要性和重要性不言而喻。

因此每一个项目都应该有README说明,好的README应该至少包括以下几方面的内容:

  • 软件的简要介绍、功能定位、适用场景等
  • 软件的安装、环境依赖、启动方法、常见使用命令(使用说明)等
  • 代码的目录结构说明
  • 常见问题说明
  • 遇到建议或bug如何联系作者或项目组

如果再编写的更详细,可以考虑简述软件的基本原理。这方面最好的参考就是开源软件的README,如nginx,redis等。

五、requirements.txt和setup.py相关

1. requirements

requirements主要解决以下两个问题:

  1. 方便开发者维护软件包依赖 有新的依赖包产生时直接添加进该列表即可,然后通过setup.py自动解决该依赖,避免遗漏
  2. 方便用户明确依赖关系

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

2.setup.py

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

这个问题好比在linux通过yum来安装一个软件一样,我们不得不承认,在解决环境依赖关系方面,yum安装相对于源码编译安装更方便。

在python项目方面,对于初学者来讲,很多都经历过以下问题:

  1. 安装环境时忘了最近又添加了一个新的Python包,结果一到线上运行,程序就出错了。
  2. Python包的版本依赖问题,有时候我们程序中使用的是一个版本的Python包,但是官方的已经是最新的包了,通过手动安装就可能装错了。
  3. 如果依赖的包很多的话,一个一个安装这些依赖是很费时的事情。
  4. 新同学开始写项目的时候,将程序跑起来非常麻烦,因为可能经常忘了要怎么安装各种依赖。

setup.py的目的是将这些事情自动化起来,统一自动化管理,提高效率并减少出错的概率。"复杂的东西自动化,能自动化的东西一定要自动化。"是一个非常好的习惯。

setuptools的文档比较庞大,刚接触的话,可能不太好找到切入点。先从模仿开始吧,可以参考一下Python的一个Web框架,flask是如何写的: setup.py

如果开发的项目只是在Linux环境上运行,简单点自己写个安装脚本(deploy.sh)替代setup.py也未尝不可。

六、配置文件相关

注意,在上面的目录结构中,没有将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.py。或者你也可以使用其他格式的内容来编写配置文件,比如settings.yaml之类的。

-------------------------atm.py-------------------------------
print(__file__)#返回当前程序的相对路径 import os
import sys
print(os.path.abspath(__file__)) #返回绝对路径
print(os.path.dirname(os.path.abspath(__file__)))#返回上级路径
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append((BASE_DIR)) from conf import settings
from core import main main.login() ---------------------------main.py------------------------------------ def login():
print("Welcome to my atm")

python 软件管理规范的更多相关文章

  1. python软件开发规范&分文件对于后期代码的高效管理

    根据本人的学习,按照理解整理和补充了python模块的相关知识,希望对于一些需要了解的python爱好者有帮助! 一.软件开发规范--分文件 当代码存在一个py文件中时: 1.不便于管理 (修改,增加 ...

  2. 从入门到自闭之Python软件命名规范

    软件命名规范:分文件存储 当代码存放在一个py文件中时会存在一下缺点: 不便于管理 可读性差 加载速度慢 是Django的雏形 程序员预定俗称的一些东西 启动文件:也叫启动接口,通常文件夹名字使用bi ...

  3. python 软件目录规范

      软件目录结构规范 软件开发规范 一.为什么要设计好目录结构? 1.可读性高: 不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪儿,配置文件在哪儿等等.从而非常快 ...

  4. [ python ] 软件开发规范

    在python开发中,我们建议采用如下规范: soft/ ├── bin # 程序执行文件目录 │   ├── __init__.py │   └── start.py # 程序开始执行脚本文件 ├─ ...

  5. Python软件开发规范

    bin  整个程序的执行路口    start.py conf 配置文件     setting.py lib   库  模块与包    common.py    sql.py core  核心逻辑  ...

  6. Python模块的导入以及软件开发规范

    Python文件的两种用途 1 . 当脚本直接使用,直接当脚本运行调用即可 def func(): print("from func1") func() 2 . 当做模块被导入使用 ...

  7. Python 入门之 软件开发规范

    Python 入门之 软件开发规范 1.软件开发规范 -- 分文件 (1)为什么使用软件开发规范: 当几百行--大几万行代码存在于一个py文件中时存在的问题: 不便于管理 修改 可读性差 加载速度慢 ...

  8. python中软件开发规范,模块,序列化随笔

    1.软件开发规范 首先: 当代码都存放在一个py文件中时会导致 1.不便于管理,修改,增加 2.可读性差 3.加载速度慢 划分文件1.启动文件(启动接口)--starts文件放bin文件里2.公共文件 ...

  9. python 全栈开发,Day29(昨日作业讲解,模块搜索路径,编译python文件,包以及包的import和from,软件开发规范)

    一.昨日作业讲解 先来回顾一下昨日的内容 1.os模块 和操作系统交互 工作目录 文件夹 文件 操作系统命令 路径相关的 2.模块 最本质的区别 import会创建一个专属于模块的名字, 所有导入模块 ...

随机推荐

  1. 洛谷P4197 Peaks&&克鲁斯卡尔重构树学习笔记(克鲁斯卡尔重构树+主席树)

    传送门 据说离线做法是主席树上树+启发式合并(然而我并不会) 据说bzoj上有强制在线版本只能用克鲁斯卡尔重构树,那就好好讲一下好了 这里先感谢LadyLex大佬的博客->这里 克鲁斯卡尔重构树 ...

  2. jzoj5878

    tj:這道題可以想到排列組合 對於第一問,我們知道,左轉的次數比右轉次數多4,所以答案是c(n,n/2-2) 對於第二問,我們發現,不能出現下凹的情況,所以不能同時出現2個左拐,且路徑可以分為4段,且 ...

  3. 二叉堆的实现(数组)——c++

    二叉堆的介绍 二叉堆是完全二元树或者是近似完全二元树,按照数据的排列方式可以分为两种:最大堆和最小堆.最大堆:父结点的键值总是大于或等于任何一个子节点的键值:最小堆:父结点的键值总是小于或等于任何一个 ...

  4. Jmeter测试计划要素

    Jmeter中一个脚本就是一个测试计划,也是一个管理单元.Jmeter的请求模拟与并发数(设置线程数,一个线程即代表一个虚拟用户)设置都在脚本文件中一起设置. 测试计划要素如下: 1.脚本中测试计划只 ...

  5. cassandra用户名和密码的设置

    设置Cassandra使用用户名和密码验证的步骤如下: 1.修改${CASSANDRA_HOME}/conf/cassandra.yaml,把authenticator: AllowAllAuthen ...

  6. [JavaScript] 时间戳格式化为yyyy-MM-dd日期

    function formateDate(timestamp){ var date = new Date(timestamp); var y = 1900+date.getYear(); var m ...

  7. 《JAVA与模式》之适配器模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述适配器(Adapter)模式的: 适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能 ...

  8. python学习笔记08-字符串

    字符串是用单引号或者双引号引起来来的  单引号和双引号没有什么区别 1字符串支持乘法操作 >>> print('hello'*2) hellohello >>> 2 ...

  9. (转)Python 字符串

    原文:http://www.runoob.com/python/python-strings.html

  10. Linux awk命令详解[备份]

    简介 awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再 ...