软件开发规范

软件开发规范

  1. 什么是软件开发规范?

    • 好的设计项目目录结构,就和编码风格一样,是每个程序员都有的风格,但是在流水化标准化作业过程中,个性和风格是不被鼓励的。如果你去维护一个非常不好读的项目,虽然实现逻辑并不复杂,但是对后续的维护者来说就是灾难。
  2. 为什么要有开发规范?

    • 一个层次清晰的目录结构,可以提高程序的可维护性:
      可读性高:
      后续维护人员可以一眼看懂目录结构,不必为复杂混乱的层次耗费大量精力。测试文件在哪,配置文件在哪会被放置在规范操作的地方,可以让后续人员快速的了解这个项目。
      可维护性高:
      看清目录架构之后,维护者可以将后续新增的文件和代码按照规范放置在规定的地方,虽然后续代码和文件增多,但是项目目录并不会混乱,仍然能够快速组织良好
  3. 按照分级目录规范模拟博客园系统:

    • 一个py文件下得博客园系统

      import json
      def award(choose):
          def func(f):
              def inner(*args,**kwargs):
                  if choose in ["Article","Comments","Diary","Collection","Cancellation"]:
                      if dic["flag"]:
                          return f()
                      else:
                          print("请先登陆")
                          return login()
                  else:
                      return f()
              return inner
          return func
      
      @award("login")
      def login(*args,**kwargs):
          global dic
          if dic["flag"]:
              return "已登陆,无需登陆"
          else:
              Account=input("请输入登陆账号").strip()
              Password = input("请输入登陆密码").strip()
              f=open("info.txt","r",encoding="utf-8")
              a=f.readlines()
              f.seek(0)
              for i in f:
                  x,y,z=i.split(":")
                  if Account==x:
                      if Password==y:
                          if z==3:
                              return "该账户已锁定"
                          else:
                              dic["user"]=Account
                              dic["flag"]=True
                              return "登陆成功"
                      else:
                          print(a)
                          for i in a:
                              x,y,z=i.strip("
      ").split(":")
                              print(x,y,z)
                              if int(z)==3:
                                  return "该账户已锁定"
                              else:
                                  z=int(z)+1
                                  f1=open("info.txt","w",encoding="utf-8")
                                  f1.write(x+":"+y+":"+str(z)+"
      ")
                          return "账号或密码错误"
              else:
                  return "账户不存在"
      
      
      
      
      
      
      @award("Registered")
      def Registered(*args,**kewargs):
          Account=input("请输入注册账号")
          Password=input("请输入注册密码")
          Count=0
          if Account.isalnum():
              if 6 <= len(Password) < 14:
                  f=open("info.txt","r+",encoding="utf-8")
                  for i  in f :
                      x,y,z=i.split(":")
                      if Account==x and Password==y:
                          return "用户已存在"
                      else:
                          f.write("
      "+Account+":"+Password+":"+str(Count))
                          f.seek(0)
                          return "注册成功"
                  f.close()
              else:
                  return "密码长度为6到14位"
          else:
              return "账号不能含有特殊字符"
      
      
      @award("Article")
      def Article(*args,**kwargs):
          return f"欢迎{dic['user']}进入文章界面"
      
      @award("Comments")
      def Comments(*args,**kwargs):
          f=open("Content","r+",encoding="utf-8")
          ContentNum=0
          for i in f:
              ContentNum+=1
              print(json.loads(i))
          choose=input("是否要评论")
          if choose=="是":
              info=input("请输入评论内容")
              ContentNum+=1
              f.write("
      "+json.dumps(str(ContentNum)+"楼"+" - "+info))
              return "评论成功,返回首页"
          else:
              return "返回首页"
      
      @award("Diary")
      def Diary(*args,**kwargs):
          return f"欢迎{dic['user']}进入日记界面"
      
      @award("Collection")
      def Collection(*args,**kwargs):
          return f"欢迎{dic['user']}进入收藏界面"
      
      @award("Cancellation")
      def Cancellation(*args,**kwargs):
          global dic
          dic["user"]=None
          dic["flag"]=False
          return "已注销"
      @award("ExitCode")
      def ExitCode(*args,**kwargs):
          exit()
      
      
      msg = """
      1.请登录
      2.请注册
      3.进入文章页面
      4.进入评论页面
      5.进入日记页面
      6.进入收藏页面
      7.注销账号
      8.退出整个程序
      ------------
      请输入选择
      """
      
      dic={"user":None,"flag":False}
      
      Menu={"1":login,"2":Registered,"3":Article,
      "4":Comments,"5":Diary,"6":Collection,"7":Cancellation,
      "8":ExitCode}
      
      def run():
          while True:
              choose = input(msg).strip()
              if choose in list(Menu.keys()):
                  ret=Menu[choose]
                  print(ret())
              else:
                  print("输入错误")
      run()
      
      

      此时我们所有文件都写在一个py文件下,如果代码最多且都在一个py文件中,那么对于代码解构不清晰,不规范,运行起来效率也非常低,所以我们要一步步修改

  4. 程序配置

    • 项目中所有得有关文件操作出现几处,都是直接写的文件操作路径发生改变,我们需要一处处修改,这时我们需要同一相同得路径,也就是同一相同得变量,在文件得最上面写一个变量指向文件得路径,代码中如果需要这个路径时,直接引用即可

  5. 划分文件

    • 每个函数都是一个具体得功能,一个文件中功能越多,代码越冗余,我们应该将这些功能分文件而治
  6. 一个项目得函数不止这些,所以我们应该将这些函数进行分类,然后分文件而治。在这里我们可以划分以下几个文件

    • settings.py:配置文件,就是放置一些项目中需要得静态参数,比如文件路径,数据库配置,软件得默认设置等等

    • common.py:公共组件文件,这里面放置一些我们常用得公共组件函数,并不是我们核心逻辑得含上诉,而更像是服务于整个程序得公用得插件程序中需要即调用。比如我们程序中的装饰器auth,有些函数是需要这个装饰器认证的,但是有一些是不需要这个装饰器认证的,它既是何处需要何处调用即可。比如还有密码加密功能,序列化功能,日志功能等这些功能都可以放在这里。

    • src.py:这个文件主要存放得就是核心逻辑功能,你看你需要进行选择得这些核心功能函数,都应该放在这个文件中

    • start.py:项目启动文件。你得项目需要专门得文件启动,而不是在你的核心逻辑部分进行启动的

      • 开启整个项目得代码就是下面这段
    • register.py:这个文件文件名不固定得,register只是我们项目中用到的注册表,但是这种文件就是存储数据的文件,类似于文本数据库

    • log文件:log文件顾名思义就是存储log日志得文件。日志我们一会就会讲到日志主要是供开发人员使用。比如你项目中出现一些bug问题,比如开发人员对服务器做的一些操作都会记录到日志中,以便开发者浏览,查询。

    • 划分具体工作目录

  7. 按照项目目录结果,规范博客园系统

    • 配置start.py文件,我们需要把run()函数引用过来但是你发现import run 或者 from src import run 都是报错的,模块在得三个地方:内存、内置、sys.path里面,,那么core在内存中肯定是没有的,也不是内置,而且sys.path也不可能有,因为sys.path只会将你当前的目录(bin)加载到内存

    • import sys#导入sys模块
      import os#导入os模块
      bash_path=os.path.dirname(os.path.dirname(__file__))#获取父级目录也就是blog的绝对路径
      sys.path.append(bash_path)#将该路径添加到环境变量中
      from core.src import run#导入core文件中src模块中得run函数
      if __name__ == '__main__':#主函数
          run()#运行run函数
      
    • 配置setting.py文件,我们就会将我们项目中的静态路径(一般不改变得路径),数据库的连接设置等等文件放置在settings文件中。

    • import os#导入os模块
      bash_path=os.path.dirname(os.path.dirname(__file__))#获取父级目录也就是blog的绝对路径
      register_path=os.path.join(bash_path,"db","register.txt")#获取register文件路径
      Content_path=os.path.join(bash_path,"db","Content")#获取content文件路径
      #此时run()启动函数已经将blog绝对路径已经添加到环境变量中,所以我们不需要再次添加
      
      #然后运行主函数,但还是有问题。因为主逻辑src中找不到register_path这个路径了,所以会报错,那么我们解决方式就是在src主逻辑中引用settings.py文件中的register_path就可以了。
      
    • 配置common.py文件(我们要配置我们的公共组件文件,在我们这个项目中,装饰器就是公共组件的工具,我们要把装饰器这个工具配置到common.py文件中。)

    • from core import src#导入核心函数
      def award(choose):
          def func(f):
              def inner(*args,**kwargs):
                  if choose in ["Article","Comments","Diary","Collection","Cancellation"]:
                      if src.dic["flag"]:
                          return f()
                      else:
                          print("请先登陆")
                          return src.login()
                  else:
                      return f()
              return inner
          return func
      
    • 可是你的src文件中使用了auth装饰器,此时你的auth装饰器已经移动位置了,所以你要在src文件中引用auth装饰器,这样才可以使用上。

    • import json
      from conf import settings#导入
      from lib import commom#公共函数导入
      @commom.award("login")
      def login(*args,**kwargs):
          global dic
          if dic["flag"]:
              return "已登陆,无需登陆"
          else:
              Account=input("请输入登陆账号").strip()
              Password = input("请输入登陆密码").strip()
              f=open(settings.register_path,"r",encoding="utf-8")
              a=f.readlines()
              f.seek(0)
              for i in f:
                  x,y,z=i.split(":")
                  if Account==x:
                      if Password==y:
                          if z==3:
                              return "该账户已锁定"
                          else:
                              dic["user"]=Account
                              dic["flag"]=True
                              return "登陆成功"
                      else:
                          print(a)
                          for i in a:
                              x,y,z=i.strip("
      ").split(":")
                              print(x,y,z)
                              if int(z)==3:
                                  return "该账户已锁定"
                              else:
                                  z=int(z)+1
                                  f1=open(settings.register_path,"w",encoding="utf-8")
                                  f1.write(x+":"+y+":"+str(z)+"
      ")
                          return "账号或密码错误"
              else:
                  return "账户不存在"
      
      
      @commom.award("Registered")
      def Registered(*args,**kewargs):
          Account=input("请输入注册账号")
          Password=input("请输入注册密码")
          Count=0
          if Account.isalnum():
              if 6 <= len(Password) < 14:
                  f=open(settings.register_path,"r+",encoding="utf-8")
                  for i  in f :
                      x,y,z=i.split(":")
                      if Account==x and Password==y:
                          return "用户已存在"
                      else:
                          f.write("
      "+Account+":"+Password+":"+str(Count))
                          f.seek(0)
                          return "注册成功"
                  f.close()
              else:
                  return "密码长度为6到14位"
          else:
              return "账号不能含有特殊字符"
      
    • OK,这样你就算是将你之前写的模拟博客园登录的作业按照规范化目录结构合理的完善完成了,最后还有一个关于README文档的书写

  8. 关于README得内容

    • 这个我觉得是每个项目都应该有的一个文件,目的是能简要描述该项目的信息,让读者快速了解这个项目。

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

      1. 软件定位,软件的基本功能。
      2. 运行代码的方法: 安装环境、启动命令等。
      3. 简要的使用说明。
      4. 代码目录结构说明,更详细点可以说明软件的基本原理。
      5. 常见问题说明。

      我觉得有以上几点是比较好的一个README。在软件开发初期,由于开发过程中以上内容可能不明确或者发生变化,并不是一定要在一开始就将所有信息都补全。但是在项目完结的时候,是需要撰写这样的一个文档的。

原文地址:https://www.cnblogs.com/zhangdadayou/p/11415322.html