python軟件開發規范

軟件開發規范

什么是軟件開發規范?

好的設計項目目錄結構,就和編碼風格一樣,是每個程序員都有的風格,但是在流水化標準化作業過程中,個性和風格是

不被鼓勵的。如果你去維護一個非常不好讀的項目,雖然實現邏輯并不復雜,但是對后續的維護者來說就是災難。

 一個層次清晰的目錄結構,可以提高程序的可維護性:

  1. 可讀性高:

    后續維護人員可以一眼看懂目錄結構,不必為復雜混亂的層次耗費大量精力。測試文件在哪,配置文件在哪會被放置在規范操作的地方,可以讓后續人員快速的了解這個項目。

  2. 可維護性高:

    看清目錄架構之后,維護者可以將后續新增的文件和代碼按照規范放置在規定的地方,雖然后續代碼和文件增多,但是項目目錄并不會混亂,仍然能夠快速組織良好

按照分級目錄規范模擬博客園系統

一個py文件下的博客園系統:

import json,time,os
print('歡迎使用博客園系統')
flag = 1
msg = """1.請登錄
2.請注冊
3.進入文章頁面
4.進入評論頁面
5.進入日記頁面
6.進入收藏頁面
7.注銷賬號
8.退出整個程序
"""login_information = {"username": None, "status": False}
def login(func=False):"""登錄函數:param func: 函數名默認為False:return: 無返回值"""time.sleep(0.1)user_name = input('請輸入你要登錄的用戶名')pwd = input('請輸入登錄密碼')landing_info = {}global login_informationwith open("userinfo.txt", "r", encoding="utf-8")as f1:for line in f1:x = line.strip()[:-2]num = int(line.strip()[-1])name = x.split(':', 1)[0]password = x.split(':', 1)[1]landing_info[name] = [password, num]if user_name in landing_info:count = landing_info[user_name][1] + 1if count == 3:print('你的賬號已鎖定,請聯系管理員解鎖')else:while count < 3:if pwd == landing_info[user_name][0]:login_information["username"] = user_namelogin_information["status"] = Trueprint("登錄成功")if func:func()breakelse:print(f"你的密碼輸入錯誤,剩余次數為{3 - count},請重新鍵入")pwd = input('請重新輸入密碼:')landing_info[user_name][1] = count + 1count += 1else:print('你的賬戶已鎖定,請聯系管理員處理')with open('userinfo.txt', 'r', encoding='utf-8')as f1, open('user.txt', 'w', encoding='utf-8') as f2:f1.seek(0, 0)for i in f1:if i.strip().split(':', 1)[0] == user_name:i = i.strip()content = i[:-1] + "3"f2.write(content + '\n')else:f2.write(i)os.remove('userinfo.txt')os.rename('user.txt', 'userinfo.txt')else:print('你輸入的賬號不存在,請先去注冊')def wrapper(f):"""操作認證:param f: 操作函數:return:"""def inner():time.sleep(1)if login_information["status"]:f()else:login(f)return innerdef registration():"""注冊函數:return:"""user_info = {}num = 3while num:user_name = input('請輸入要注冊的用戶名:')pwd = input('請輸入要注冊的密碼:')num -= 1lst_name = list(range(65, 91)) + list(range(97, 123))for i in user_name:if (i.isdecimal()== True or ord(i) in lst_name) and 6 <= len(pwd) <= 14:passelse:print('用戶名或密碼無效,請重新輸入')if num == 0:print('注冊失敗')breakelse:with open('userinfo.txt', 'r+', encoding='utf-8')as f:for i in f:i = i.strip()[:-2]k, v = i.split(':')user_info[k] = vif user_name in user_info:print('用戶名已存在,請重新輸入用戶名')if num == 0:print('注冊失敗')continueelse:f.write(f"\n{user_name}:{pwd}:0")choose = input('你已經注冊成功,是否重新注冊(重新注冊鍵入1)')if choose == '1':num = 3else:print('注冊成功,你可以去嚯嚯了')time.sleep(1)num = 3break@wrapper
def article():"""文章頁面:return:"""global login_informationprint(f"歡迎{login_information['username']}進入文章頁面!")@wrapper
def comment():"""評論頁面:return:"""num = 1global login_informationprint(f"歡迎{login_information['username']}進入評論頁面!")with open('com','r',encoding="utf-8") as f:for i in f:s = i.strip()print(json.loads(s))num += 1choose = input("是否評論Y or N")if choose == "Y":com = input("請輸入評論:")with open('com','a',encoding="utf-8") as f2:com1 = f"{num}樓 - {login_information['username']}:{com}"f2.write(json.dumps(com1,ensure_ascii=False)+"\n")@wrapper
def diary():"""日記頁面:return:"""global login_informationprint(f"歡迎{login_information['username']}進入日記頁面!")@wrapper
def collect():"""收藏頁面:return:"""global login_informationprint(f"歡迎{login_information['username']}進入收藏頁面!")@wrapper
def off():global login_informationlogin_information["username"] = Nonelogin_information["status"] = Falselogin_information["count"] = 0print("賬戶注銷成功!")def drop():global flagflag = 0print("歡迎下次光臨")func_information = {'1': login, '2': registration, '3': article, '4': comment, '5': diary, '6': collect,'7': off, '8': drop}
while flag:print(msg)choose = input("請選擇數字使用對應功能選項:")if choose in func_information:ret = func_information[choose]ret()else:print("你的輸入有誤,請重新輸入")

此時我們所有文件都寫在一個py文件下,如果代碼量多且都在一個py文件中,那么對于代碼結構不清晰,不規范,運行起來效率也會非常低。所以我們接下來一步一步的修改:

1.軟件配置:

我們的博客園系統中出現了多處這樣的相對路徑,如果我們用戶注冊表位置發生改變,我們需要一處一處修改,那么我們是否可以統一相同的路徑,也就是統一相同的變量,在文件的最上面寫一個變量指向userinfo注冊表的路徑,代碼中如果需要這個路徑時,直接引用即可。

1729998-20190801174800511-1400295791.png

1729998-20190801174820641-780464943.png

1729998-20190801174827394-264747807.png

userinfo_path = r"E:\Python\week3大作業\userinfo.txt"
# 我們博客園系統中出現的相對路徑均用userinfo_path替換即可

2.劃分文件:

1729998-20190801174843880-487290551.png

一個小型的博客園系統已經這么多代碼了,如果我們開發一個項目,可以想象我們的py文件該有多亂了,我們可以將這些函數進行分類,分文件而治,我們將上述py文件依據功能劃分以下幾類:

settings.py: 配置文件,就是放置一些項目中需要的靜態參數,比如文件路徑,數據庫配置,軟件的默認設置等等(如我們上面提到的用戶注冊表表文件)

common.py:公共組件文件,這里面放置一些我們常用的公共組件函數,并不是我們核心邏輯的函數,而更像是服務于整個程序中的公用的插件,程序中需要即調用。比如我們程序中的裝飾器wrapper,有些函數是需要這個裝飾器認證的,但是有一些是不需要這個裝飾器認證的,它既是何處需要何處調用即可。比如還有密碼加密功能,序列化功能,日志功能等這些功能都可以放在這里。

1729998-20190801174903299-196290235.png

src.py:這個文件主要存放的就是核心邏輯功能,你看你需要進行選擇的這些核心功能函數,都應該放在這個文件中。

1729998-20190801174911304-1682250361.png

start.py:項目啟動文件。你的項目需要有專門的文件啟動,而不是在你的核心邏輯部分進行啟動的,有人對這個可能不太理解,我為什么還要設置一個單獨的啟動文件呢?你看你生活中使用的所有電器基本都一個單獨的啟動按鈕,汽車,熱水器,電視,等等等等,那么為什么他們會單獨設置一個啟動按鈕,而不是在一堆線路板或者內部隨便找一個地方開啟呢? 目的就是放在顯眼的位置,方便開啟。你想想你的項目這么多py文件,如果src文件也有很多,那么到底哪個文件啟動整個項目,你還得一個一個去尋找,太麻煩了,這樣我把它單獨拿出來,就是方便開啟整個項目。

1729998-20190801174921860-213769830.png

除了上面提到的幾個py文件,還有幾個非常重要的文件,類似于userinfo用戶注冊表的數據庫文件,以及以后將拓展的logging日志文件,此外,隨著項目功能的擴展,還會多出許多的用戶數據表,個人信息表等等,因此,隨著項目的增多,單個文件夾下存放各種py文件看起來已經非常煩亂了,此處便可以引出標準版本的項目目錄結構了:

1729998-20190801174930995-186423559.png

按照標準項目目錄規范化博客園登錄系統:

  1. 配置啟動文件:

    import sys   # 導入sys模塊
    import os    # 導入os模塊
    BASE_DIR = os.path.dirname(os.path.dirname(__file__))   #__file__獲取當前文件絕對路徑,整體獲取blog系統絕對路徑
    sys.path.append(BASE_DIR)  # 將blog目錄添加到環境變量
    from core.src import run   # 從core文件夾src.py文件導入run函數if __name__ == '__main__':    # 程序啟動接口run()
  2. 配置settings.py文件:

    import os   # 導入os模塊
    BASE_DIR = os.path.dirname(os.path.dirname(__file__))  # blog系統絕對路徑
    userinfo_path = os.path.join(BASE_DIR,'db','userinfo.txt')  # 通過拼接獲取用戶注冊表絕對路徑
    com_path = os.path.join(BASE_DIR,'db','com.txt') # 獲取評論絕對路徑
    msg = """1.請登錄
    2.請注冊
    3.進入文章頁面
    4.進入評論頁面
    5.進入日記頁面
    6.進入收藏頁面
    7.注銷賬號
    8.退出整個程序
    """
  3. 配置common.py文件:

    from core import src   # 從core文件夾導入src主邏輯模塊
    import time # 導入時間模塊
    """
    操作認證
    :param f: 操作函數
    :return:
    """def wrapper(f):"""操作認證:param f: 操作函數:return:"""def inner():time.sleep(1)if src.login_information["status"]:   f()else:src.login(f)return inner

調整后新版博客園:

程序啟動模塊:

import sys
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
sys.path.append(BASE_DIR)
from core import srcif __name__ == '__main__':src.run()

配置模塊:

import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
userinfo_path = os.path.join(BASE_DIR,'db','userinfo.txt')
com_path = os.path.join(BASE_DIR,'db','com.txt')
msg = """1.請登錄
2.請注冊
3.進入文章頁面
4.進入評論頁面
5.進入日記頁面
6.進入收藏頁面
7.注銷賬號
8.退出整個程序
"""

公共組件模塊:

from core import src
import time
"""
操作認證
:param f: 操作函數
:return:
"""def wrapper(f):"""操作認證:param f: 操作函數:return:"""def inner():time.sleep(1)if src.login_information["status"]:f()else:src.login(f)return inner

主邏輯模塊:

import json,time,os
from conf import settings
from lib import common
print('歡迎使用博客園系統')
flag = 1login_information = {"username": None, "status": False}
def login(func=False):"""登錄函數:param func: 函數名默認為False:return: 無返回值"""time.sleep(0.1)user_name = input('請輸入你要登錄的用戶名')pwd = input('請輸入登錄密碼')landing_info = {}global login_informationwith open(settings.userinfo_path, "r", encoding="utf-8")as f1:for line in f1:x = line.strip()[:-2]num = int(line.strip()[-1])name = x.split(':', 1)[0]password = x.split(':', 1)[1]landing_info[name] = [password, num]if user_name in landing_info:count = landing_info[user_name][1] + 1if count == 3:print('你的賬號已鎖定,請聯系管理員解鎖')else:while count < 3:if pwd == landing_info[user_name][0]:login_information["username"] = user_namelogin_information["status"] = Trueprint("登錄成功")if func:func()breakelse:print(f"你的密碼輸入錯誤,剩余次數為{3 - count},請重新鍵入")pwd = input('請重新輸入密碼:')landing_info[user_name][1] = count + 1count += 1else:print('你的賬戶已鎖定,請聯系管理員處理')with open(settings.userinfo_path, 'r', encoding='utf-8')as f1, open('user.txt', 'w', encoding='utf-8') as f2:f1.seek(0, 0)for i in f1:if i.strip().split(':', 1)[0] == user_name:i = i.strip()content = i[:-1] + "3"f2.write(content + '\n')else:f2.write(i)os.remove('userinfo.txt')os.rename('user.txt', 'userinfo.txt')else:print('你輸入的賬號不存在,請先去注冊')def registration():"""注冊函數:return:"""user_info = {}num = 3while num:user_name = input('請輸入要注冊的用戶名:')pwd = input('請輸入要注冊的密碼:')num -= 1lst_name = list(range(65, 91)) + list(range(97, 123))for i in user_name:if (i.isdecimal()== True or ord(i) in lst_name) and 6 <= len(pwd) <= 14:passelse:print('用戶名或密碼無效,請重新輸入')if num == 0:print('注冊失敗')breakelse:with open(settings.userinfo_path, 'r+', encoding='utf-8')as f:for i in f:i = i.strip()[:-2]k, v = i.split(':')user_info[k] = vif user_name in user_info:print('用戶名已存在,請重新輸入用戶名')if num == 0:print('注冊失敗')continueelse:f.write(f"\n{user_name}:{pwd}:0")choose = input('你已經注冊成功,是否重新注冊(重新注冊鍵入1)')if choose == '1':num = 3else:print('注冊成功,你可以去嚯嚯了')time.sleep(1)num = 3break@common.wrapper
def article():"""文章頁面:return:"""global login_informationprint(f"歡迎{login_information['username']}進入文章頁面!")@common.wrapper
def comment():"""評論頁面:return:"""num = 1global login_informationprint(f"歡迎{login_information['username']}進入評論頁面!")with open(settings.com_path,'r',encoding="utf-8") as f:for i in f:s = i.strip()print(json.loads(s))num += 1choose = input("是否評論Y or N")if choose == "Y":com = input("請輸入評論:")with open('com','a',encoding="utf-8") as f2:com1 = f"{num}樓 - {login_information['username']}:{com}"f2.write(json.dumps(settings.com_path,ensure_ascii=False)+"\n")@common.wrapper
def diary():"""日記頁面:return:"""global login_informationprint(f"歡迎{login_information['username']}進入日記頁面!")@common.wrapper
def collect():"""收藏頁面:return:"""global login_informationprint(f"歡迎{login_information['username']}進入收藏頁面!")@common.wrapper
def off():global login_informationlogin_information["username"] = Nonelogin_information["status"] = Falselogin_information["count"] = 0print("賬戶注銷成功!")def drop():global flagflag = 0print("歡迎下次光臨")func_information = {'1': login, '2': registration, '3': article, '4': comment, '5': diary, '6': collect,'7': off, '8': drop}
def run():while flag:print(settings.msg)choose = input("請選擇數字使用對應功能選項:")if choose in func_information:ret = func_information[choose]ret()else:print("你的輸入有誤,請重新輸入")
run()

README的相關內容

這個我覺得是每個項目都應該有的一個文件,目的是能簡要描述該項目的信息,讓讀者快速了解這個項目。

它需要說明以下幾個事項:

  1. 軟件定位,軟件的基本功能。
  2. 運行代碼的方法: 安裝環境、啟動命令等。
  3. 簡要的使用說明。
  4. 代碼目錄結構說明,更詳細點可以說明軟件的基本原理。
  5. 常見問題說明。

在軟件開發初期,由于開發過程中以上內容可能不明確或者發生變化,并不是一定要在一開始就將所有信息都補全。但是在項目完結的時候,是需要撰寫這樣的一個文檔的。

轉載于:https://www.cnblogs.com/lifangzheng/p/11284247.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/247299.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/247299.shtml
英文地址,請注明出處:http://en.pswp.cn/news/247299.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

D3Vueecharts個人亂記

利用d3vue開發的一個網絡拓撲圖 https://copyfuture.com/blogs-details/20200710101052238h32wazjmcii49dr 一開始用的是echart畫的。 根據https://gallery.echartsjs.com/editor.html?cxH1Rkt3hkb&#xff0c;成功畫出簡單的節點關系。 如圖&#xff1a; 總結—— 【優…

vue中使用Vue-pdf在線預覽

下載 npm i vue-pdf 引入(在所需要預覽的頁面) <script>import axios from axiosimport pdf from vue-pdfimport CMapReaderFactory from vue-pdf/src/CMapReaderFactory.js // 加載中文的包export default {components: {pdf},data () {return {numPages:&#xff0c;…

oracle 自定義 聚合函數

Oracle自定義聚合函數實現字符串連接的聚合 create or replace type string_sum_obj as object ( --聚合函數的實質就是一個對象 sum_string varchar2(4000), static function ODCIAggregateInitialize(v_self in out string_sum_obj) return number, --對象初始化 member func…

Vue3里的setup中使用vuex

useStore 這里我們可以直接從vuex 4.X中解構出useStore方法&#xff0c;就可以在setup中使用vuex的相關函數 template 使用$store <template><div><h2>{{ $store.state.count }}</h2><button click"increaseCount">點擊</button…

JQ 取CHECKBOX選中項值

備忘錄 $("[namecheckbox]:checked").each(function(){ alert((this).val()); }) ;轉載于:https://www.cnblogs.com/showblog/archive/2010/09/13/1825099.html

vue3 echarts5 graph關系圖譜 點擊圖例節點消失線不消失重復生成問題

const myChart ref(null);const myCharts ref(null);onMounted(() > {// 這種會導致線仍然存在 重復生成myCharts.value echarts.init(myChart.value);myCharts.value.setOption(option);});return {myChart,myCharts,}; 現象&#xff1a;如下圖1 點擊圖例類目2&#xf…

非常完整的coco screator socketio

https://github.com/SeaPlanet/cocoscreator_chat 前端源碼 https://github.com/socketio/socket.io-client https://cdnjs.com/libraries/socket.io 轉載于:https://www.cnblogs.com/suneil/p/11288628.html

JavaScript 中 obj.hasOwnProperty(prop) 方法

語法 obj.hasOwnProperty(prop) 參數 prop 要檢測的屬性的 String 字符串形式表示的名稱&#xff0c;或者 Symbol。 返回值 用來判斷某個對象是否含有指定的屬性的布爾值 Boolean。 描述 所有繼承了 Object 的對象都會繼承到 hasOwnProperty 方法。這個方法可以用來檢測…

python面向對象初識

面向對象編程 1.面向對象初步了解 ? 面向過程編程與函數編程對比&#xff1a; s1 ajdsgkaffddha count 0 for i in s1:count 1 print(f字符串的長度為{count}) # 面向過程編程每計算一次便使用一次for循環def my_len(s): # 計算數據類型長度的函數&#xff0c;可重復使用…

Vue3 VSCode新建項目報錯The template root requires exactly one element.

1.首先我們點擊左側第四個圖標插件2.輸入框搜索vetur插件3.點擊設置圖標&#xff0c;再點擊擴展設置4.搜素vetur>validation>template&#xff0c;取消vetur>validation>template的勾選 然后就不會報錯了

計算機視覺概述

關于計算機視覺的介紹性文章&#xff0c;包括計算機視覺的定義&#xff0c;和人類視覺的區別以及涉及到的學科等等。 1. 什么是計算機視覺 計算機視覺既是工程領域&#xff0c;也是科學領域中的一個富有挑戰性重要研究領域。計算機視覺是一門綜合性的學科&#xff0c;它已經吸引…

Java生鮮電商平臺-電商支付流程架構實戰

Java生鮮電商平臺-電商支付流程架構實戰 說明&#xff1a;我一直秉承的就是接地氣的業務架構實戰。我的文章都有一個這樣的核心。 1. 業務場景 2. 解決問題。 3.代碼實現。 4.代碼重構。 5.總結與復盤。 6.缺點與防范 一、場景描述 想必大家都曾遇到過這個問題&#xff0c;在電…

vue3.0 AntDesignVue2.0 table的rowkey報錯問題解決方法

Warning: [antdv: Each record in table should have a unique key prop,or set rowKey to an unique primary key.] Warning: [antdv: Table] Each record in dataSource of table should have a unique key prop, or set rowKey of Table to an unique primary key 提示因為…

模式識別掃盲

模式識別是對表征事物或現象的各種形式的信息進行處理和分析&#xff0c;以對事物或現象進行描述、辨認、分類和解釋的過程&#xff0c;是信息科學和人工智能的重要組成部分。英文“Pattern”源于法文“Patron”&#xff0c;本來是指可作為大家典范的理想的人&#xff0c;或用以…

vue2項目使用codemirror插件實現代碼編輯器功能

1、使用npm安裝依賴 npm install --save codemirror 2、在頁面中放入如下代碼 <template><textarea ref"mycode" class"codesql" v-model"code" style"height:200px;width:600px;"></textarea> </template>…

CentOS 6.5系統安裝配置LAMP(Apache+PHP5+MySQL)服務器環境

安裝篇&#xff1a; 一、安裝Apache yum install httpd #根據提示&#xff0c;輸入Y安裝即可成功安裝 /etc/init.d/httpd start#啟動Apache 備注&#xff1a;Apache啟動之后會提示錯誤&#xff1a; 正在啟動 httpd:httpd: Could not reliably determine the servers fully qual…

前端有用的庫

HTML awesome-html5 精選的HTML5資源精選清單 CSS tailwindcss 與Tailwind CSS相關的很棒的事情awesome-css-frameworks 很棒的CSS框架列表awesome-css-cn CSS 資源大全中文版&#xff0c;內容包括&#xff1a;CSS預處理器、框架、CSS結構、代碼風格指南、命名習慣等等awesom…

計算機視覺牛人(轉載)(最早在自動化所論壇上發現的)

paper畢竟是死的, 寫paper的人才是活的. 那么我現在研究一下cv圈的格局, 按師承關系, 借鑒前人, 我總結a tree stucture of cv guys.David Marr----->Shimon Ullman (Weizmann) ----->Eric Grimson (MIT)----->Daniel Huttenlocher (Cornell)----->Pedro Felzenszw…

Java生鮮電商平臺-促銷系統的架構設計與源碼解析

Java生鮮電商平臺-促銷系統的架構設計與源碼解析 說明&#xff1a;本文重點講解現在流行的促銷方案以及源碼解析,讓大家對促銷&#xff0c;納新有一個深入的了解與學習過程. 促銷系統是電商系統另外一個比較大&#xff0c;也是比較復雜的系統&#xff0c;作為一個賣貨的&#x…

vue3中websocket用法

1.0 認識 websocket #1.0.1 什么是 websocket 和 http 協議類似&#xff0c;websocket 也是是一個網絡通信協議&#xff0c;是用來滿足前后端數據通信的。 #1.0.2 websocket 相比于 HTTP 的優勢 HTTP 協議&#xff1a;客戶端與服務器建立通信連接之后&#xff0c;服務器端只…