软件开发规范
为什么要有开发规范?
软件开发,规范你的项目目录结构,代码规范,遵循PEP8规范等,使开发更合理,清晰.可读性高,可维护性高.
将代码分类后,加载速度快,可读性高,查询修改简单.
以博客园系统为例,将在一个py文件中的所有代码,整合成规范的开发.
status_dic = {
'username': None,
'status': False,
}
flag = True
def login():
i = 0
with open("register", encoding='utf-8') as f1:
dic = {i.strip().split('|')[0]: i.strip().split('|')[1] for i in f1}
while i < 3:
username = input('请输入用户名:').strip()
password = input('请输入密码:').strip()
if username in dic and dic[username] == password:
print('登录成功')
return True
else:
print('用户名密码错误,请重新登录')
i += 1
def register():
with open("register", encoding='utf-8') as f1:
dic = {i.strip().split('|')[0]: i.strip().split('|')[1] for i in f1}
while 1:
print('\033[1;45m 欢迎来到注册页面 \033[0m')
username = input('请输入用户名:').strip()
if not username.isalnum():
print('\033[1;31;0m 用户名有非法字符,请重新输入 \033[0m')
continue
if username in dic:
print('\033[1;31;0m 用户名已经存在,请重新输入 \033[0m')
continue
password = input('请输入密码:').strip()
if 6 <= len(password) <= 14:
with open("register", encoding='utf-8', mode='a') as f1:
f1.write(f'\n{username}|{password}')
status_dic['username'] = str(username)
status_dic['status'] = True
print('\033[1;32;0m 恭喜您,注册成功!已帮您成功登录~ \033[0m')
return True
else:
print('\033[1;31;0m 密码长度超出范围,请重新输入 \033[0m')
def auth(func):
def inner(*args, **kwargs):
if status_dic['status']:
ret = func(*args, **kwargs)
return ret
else:
print('\033[1;31;0m 请先进行登录 \033[0m')
if login():
ret = func(*args, **kwargs)
return ret
return inner
@auth
def article():
print(f'\033[1;32;0m 欢迎{status_dic["username"]}访问文章页面\033[0m')
@auth
def diary():
print(f'\033[1;32;0m 欢迎{status_dic["username"]}访问日记页面\033[0m')
@auth
def comment():
print(f'\033[1;32;0m 欢迎{status_dic["username"]}访问评论页面\033[0m')
@auth
def enshrine():
print(f'\033[1;32;0m 欢迎{status_dic["username"]}访问收藏页面\033[0m')
def login_out():
status_dic['username'] = None
status_dic['status'] = False
print('\033[1;32;0m 注销成功 \033[0m')
def exit_program():
global flag
flag = False
return flag
choice_dict = {
1: login,
2: register,
3: article,
4: diary,
5: comment,
6: enshrine,
7: login_out,
8: exit_program,
}
def run():
while flag:
print('''
欢迎来到博客园首页
1:请登录
2:请注册
3:文章页面
4:日记页面
5:评论页面
6:收藏页面
7:注销
8:退出程序''')
choice = input('请输入您选择的序号:').strip()
if choice.isdigit():
choice = int(choice)
if 0 < choice <= len(choice_dict):
choice_dict[choice]()
else:
print('\033[1;31;0m 您输入的超出范围,请重新输入 \033[0m')
else:
print('\033[1;31;0m 您您输入的选项有非法字符,请重新输入 \033[0m')
run()
每一个函数都是一个具体的功能,一个文件中功能越多,代码越冗余,应该将这些函数进行分类然后分文件而治.
具体划分如下:
1.划归固定路径
如代码中的"register"注册表文件,使相对路径,如果路径改变,则程序中用到的地方都需要一一更改,所以应该统一相同的变量,在文件的最上面写一个变量指向register注册表的路径,代码中如果需要这个路径时,直接引用即可.
REGISTER_PATH = r"C:\python\"register"
with open(REGISTER_PATH, encoding='utf-8') as f1:
#将register注册表的路径赋给变量,用到这个文件时直接引用这一变量.
2.划分文件
settings.py:
#配置文件,存放一些项目中需要的静态参数,比如路径,数据库的连接,配置等,一般在代码中只是引用不改变,基本上都是常量
比如博客园系统中的:
REGISTER_PATH = r"C:\python\"register"
common.py:
#公共组件文件,放置一些常用的公共组件函数,更像是服务于整个程序中的公用的插件,程序中需要即调用.
比如我们程序中的装饰器auth,有些函数是需要这个装饰器认证的,但是有一些是不需要的,何处需要何处调用即可,密码加密,序列化功能,日志功能等都可以存放在这里
比如博客园系统中的:
def auth(func):
def inner(*args, **kwargs):
if status_dic['status']:
ret = func(*args, **kwargs)
return ret
else:
print('\033[1;31;0m 请先进行登录 \033[0m')
if login():
ret = func(*args, **kwargs)
return ret
return inner
src.py:
#主要存放核心逻辑功能,即主逻辑函数,核心函数,是直接可以体现出来的,贯穿整个项目的主要功能.
比如博客园系统中的:
@auth
def article():...
@auth
def diary():...
@auth
def comment():...
@auth
def enshrine():...
def login_out():...
def exit_program():...
start.py:
#项目启动文件,将开启项目的功能单独放置到一个文件中,开启项目方便,醒目.
比如博客园系统中的:
run()
类似register文件:
#这种文件是存储数据的文件,类似于文本数据库,一些项目中的数据有的是从数据库中获取到,有些数据就是这种文本数据库中获取的,总之,会遇到将一些数据存储在文件中,与程序交互的情况,所以要单独设置这样的文件.
log文件:
#log文件就是存储log日志的文件,日志主要是供开发人员使用,可以记录用户的一些操作(停留时间,浏览信息等),,以及项目中的一些bug问题,以便开发者浏览查询.
形成以下目录:
|-- blog
| |-- settings.py
| |-- start.py
| |-- src.py
| |-- common.py
| |-- register.txt
| |-- access.log
|
划分具体目录
上面的博客园系统只是较为简单的程序,如果src主逻辑函数很多,则需要划分为src1.py,src2.py等,文本数据库register只是一个注册表,如果还有个人信息表,记录表等,则项目会比较凌乱,所以需要设计项目目录结构.
为什么要设计项目目录结构?
设计一个层次清晰的目录结构,是为了达到:
1.可读性高:不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪,配置文件在哪等等,从而非常快速的了解这个项目.
2.可维护性高:定义好组织规则后,维护者就能很明确的知道,新增的哪个文件和代码应该放在什么目录之下,好处是随着时间的推移,代码/配置的规模增加,项目结构不会混乱,仍然能够组织良好.
博客园的目录结构可以如下
blog
|-- bin
| |-- start.py
|-- conf
| |-- settings.py
|-- core
| |-- src.py
|-- db
| |-- register
|-- lib
| |-- common.py
|-- log
| |--access.log
|-- README
关于README:
每一个项目都应该有的文件,目的是能简要描述该项目的信息,让读者快速了解这个项目.
它需要说明以下几个事项:
1.软件定位,软件的基本功能
2.运行代码的方法:安装环境,启动命令等
3.简要的使用说明
4.代码目录结构说明,更详细点可以说明软件的基本原理
5.常见问题说明
实例演示:
博客园的目录结构可以如下
blog
|-- bin
| |-- start.py
|-- conf
| |-- settings.py
|-- core
| |-- src.py
|-- db
| |-- register
|-- lib
| |-- common.py
|-- log
| |--access.log
|-- README
-配置start.py文件,首先需要手动将整个项目的工作路径添加到sys.path中,即将blog项目的工作目录添加到sys.path中,这样无论项目下的任意一个文件引用项目中哪个文件,都可以找到.但是项目是共同开发的,所以文件路径还需要动态获取.即:
import sys
import os
BASE.DIR = os.path.dirname(os.path.dirname(__file__))
#获取到了本文件的父级的父级,也就是项目的根目录
sys.path.append(BASE.DIR)
from core.src import run
run()
if __name__ == '__main__':
run()
#__file__ 获取本文件的绝对路径
#os.path.dirname() 获取父级目录
#作为启动文件不可以被别人引用启动,所以要用到__name__
-配置settings.py文件,需要将项目中的静态路径,数据库的连接设置等等文件放置在settings文件中,settings文件也叫做配置静态文件,所以只需要把register_path放进去即可.
import os
BASE_PATH = os.path.dirname(os.path.dirname(__file__))
REGISTER_PATH = os.path.join(BASE_PATH,"db","register")
-配置common.py文件,在本项目中,装饰器就是公共组件的工具,除了将auth装饰器代码剪切到common.py文件中,还需要引入src.py文件中需要用到的变量,装饰器中的引用其他模块中的变量也需要前缀模块名
from core import src
-配置src.py文件,需要引用settings.py文件中register的路径和auth装饰器,src中的auth要变成common.auth,regis
ter的路径引用其他模块中的变量也需要前缀模块名
from conf import settings
from lib import common
这样的话,博客园项目按照规范化目录就合理的完善完成了.