目录
作者的吐槽
介绍流程
UBD的结构
UBD的流程图(也称不上流程图吧)
UBD的优缺点
优点
缺点
系统
设计结构
UI
UI的一些图片
UI的代码
Business
数据库的连接(json)
Data
总结
作者的吐槽
当知道UBD分层结构之后,我的大脑一阵疯狂运转,不过只是大概了解了流程,当我尝试去修改我的上一版系统之后,我已经不想说什么了,我自己写的都是什么玩意,我真**,让我把一堆抽象个什么,然后就是倔强的尝试;最终,成功的实现了,只去复用了数据库连接的一部分代码,然后非常“高兴”的重构了几次项目,这是我第一次重构这么多次,足足有着5次,一个小小的学生信息管理系统因为一个分层结构,让我重构了这么多次,最后写出来的东西和上一版几乎是完全不一样。
介绍流程
先介绍UBD结构再介绍相关的代码
UBD的结构
“U”指的是页面层,也叫做UI层,用来写展示给用户的内容(如登录界面,菜单界面等)
“B”指的是业务逻辑层,即BLL,用来写实现登录等功能的逻辑
“D”指的是数据访问层,即DAL,用来访问数据库/数据容器中的数据
层次 | 共同点 | 不同点 |
---|---|---|
UI(用户界面层) | 都是软件系统架构的一部分,共同协作来实现整个软件系统的功能。 | 主要负责与用户进行交互,将用户的操作转化为对系统的请求,并将系统的响应结果以合适的形式展示给用户。通常使用图形界面、命令行界面等形式呈现,关注用户体验和界面友好性。比如网页界面、桌面应用程序界面等。 |
BLL(业务逻辑层) | 处于 UI 层和 DAL 层之间,对业务逻辑进行封装和处理。包含各种业务规则、流程控制、数据验证等操作,将用户的请求进行业务层面的处理和协调,决定数据如何在系统中流动和处理,不直接涉及数据的存储和读取细节。例如订单处理中的折扣计算、库存检查等业务规则的实现。 | |
DAL(数据访问层) | 专注于与数据存储进行交互,负责数据的读取、写入、更新、删除等操作。具体实现与数据库(如关系型数据库、非关系型数据库等)或其他数据存储介质的交互,提供数据访问的接口和方法供上层调用,对上层隐藏数据存储的具体细节和实现方式。比如使用 SQL 语句或者特定的数据访问框架来操作数据库。 |
UBD的流程图(也称不上流程图吧)
说他是流程图的话太高看了,说不是的话也走了一个流程,徒手画的,虽丑但是“我”画的
UBD的优缺点
优点
1.高内聚低耦合。很明显,在使用这种结构的时候,可以体现出来面向对象的强大之处,要用这个就直接调用就完了,耦合程度低是因为把结构划分为这三层,那代码之间互不影响,其他人来用也可以很轻松就可以用了。
2.可复用性强。我在重构的时候,重构的后面几次就可以把我的页面和数据访问层直接拿过去,不断的梳理逻辑。虽然我的主观性在这里体现的比较强,但是确实可以直接拿过去用。
3.可扩展性比较好。这个我有点体会,但是不多,就是在设计的时候,设计了注册老师的方法,虽然最后没用,但是这个时候,如果我去把校长这个类创建出来,之后我就可以直接去设计逻辑然后直接就可以去数据访问层,虽然我没有去接着写,但是我体会到了这个感觉,有机会还是会不断完善我的第一个UBD结构的管理系统。
缺点
1.很明显,它以前的两层结构,页面直接到数据访问,现在穿插了一个业务逻辑,对性能极大可能的存在更多的消耗
2.设计的明显有点过度了,很多都可以两层直接完成,UBD结构的数据访问通过用户类去访问,每次都要去get、set明显会更麻烦,但是查了查资料,知道当数据量大就出问题了。
也就是小型的项目设计很可能会有些过度了。
系统
设计结构
前前后后一共使用到了12个py文件,一个json文件(用来存储mysql环境)
UI
这一层我是这样设计的,每一个界面设计为一个py文件,这些页面的py文件就放到Userface这个包里,然后一个页面对应一个业务逻辑。
UI的一些图片
第一个图片有没有种相似的感觉,哈哈哈哈哈哈,日常....蓝、浅蓝、红
UI的代码
实现这个玩意简单的很,虽然我做的很丑,真想不明白为什么其他人就做的那么好看,可以了,代码写出来简单的很,都用不了几个控件
layout = [
[sg.T('学号', font=('宋体', 18)),
sg.InputText('', tooltip='请输入学号, 在增加功能的时候学号无用', font=('宋体', 18), size=(10, 8),
key='id'),
sg.T('姓名', font=('宋体', 18)),
sg.InputText('', tooltip='请输入姓名(不要输的太长)', key='name', font=('宋体', 18), size=(10, 8)),
sg.T('年龄', font=('宋体', 18)),
sg.InputText('', tooltip='请输入年龄', key='age', font=('宋体', 18), size=(10, 8))],
[sg.T('性别', font=('宋体', 18)), sg.Combo(['男', '女'], key='gender', size=(10, 8)),
sg.T('班级', font=('宋体', 18)),
sg.Combo(['1班', '2班'], key='classroom', size=(10, 8)), sg.T('专业', font=('宋体', 18)),
sg.Combo(['软件工程', '物联网工程', '网络工程', '大数据'], key='major', font=('宋体', 18), size=(10, 8))],
[sg.B('增加', key='add', size=(5, 5)), sg.B('删除', key='delete', size=(5, 5)),
sg.B('修改', key='update', size=(5, 5)), sg.B('查询', key='find', size=(5, 5)),
sg.B('刷新', key='furnish', size=(5, 5))],
[sg.Table(result_all,
list_Text,
def_col_width=10,
num_rows=20,
row_height=40,
max_col_width=200,
justification='c',
auto_size_columns=False,
font=('宋体', 13),
key='table',
enable_events=True
# enable_click_events=True
)]
]
window = sg.Window('菜单', layout, size=(800, 800), element_justification='c')
Business
业务逻辑能说的就相对UI多了
首先要满足登录的逻辑,先连接一下数据库,然后去读取出来user表的全部数据,因为fetchall方法取出来的是元组嵌套元组,所以我直接用for循环然后遍历出来每个元组,然后因为在user表中,我只设计了username和password两个column,所以我使用了他的下标,然后判断是不是和用户输入的信息相同,相同则进入菜单,不同就显示弹窗告知它错误。
代码如下:
result = query.login_get_query()
# 取出来的值是元组嵌套元组,然后每个元组有两个数据,第一个是username第二个是password
for i in result:
if values['username'] == i[0] and values['password'] == i[1]:
window.close()
menu.welcome()
menu.menuGui()
break
# 因为for循环else的缩进很关键就直接把它放好
else:
menu_click.Error_message()
然后就是菜单的逻辑了,增删改查没什么好说的,比较有意思的就是回显功能了,点击表格内容会实现回显数据到输入框,通过的是pysimplgui的Table控件,然后其他的一些业务就没必要了 , 主要就是通过取出来这一行的全部数据,然后一次针对下标添加到输入框之中,虽然下标比较多,但是,这些代码摁这里就不懂了,能跑出来就行了。。
def table(self, result_all, values, window):
# self.furnish(window)
if values['table']:
select_row = values['table'][0]
select_item = result_all[select_row][0]
window['id'].update(select_item)
select_row = values['table'][0]
select_item = result_all[select_row][1]
window['name'].update(select_item)
select_row = values['table'][0]
select_item = result_all[select_row][2]
window['gender'].update(select_item)
select_row = values['table'][0]
select_item = result_all[select_row][3]
window['classroom'].update(select_item)
select_row = values['table'][0]
select_item = result_all[select_row][4]
window['age'].update(select_item)
select_row = values['table'][0]
select_item = result_all[select_row][5]
window['major'].update(select_item)
# 后续代码
else:
# 处理表格为空或者没有选中行的情况
print('现在的表格为空')
数据库的连接(json)
设计一个json文件用来存储MySQL的环境,然后通过静态方法把他读出去,然后其他类中创建对象,然后调用连接数据库的函数去创建游标,然后写sql语句
import json
import pymysql
class DatabaseConnect:
_json_config = None
@classmethod
def load(cls, json_path=r'E:\UBD_3\database_login.json'):
if not cls._json_config:
with open(json_path, 'r') as f:
cls._json_config = json.load(f)
# print(_json_config)
def __init__(self):
try:
self.load()
# self.connect_database()
except Exception as e:
print('初始化过程错误' + str(e))
def connect_database(self):
try:
db = pymysql.connect(
host=self._json_config['host'],
port=self._json_config['port'],
user=self._json_config['username'],
password=self._json_config['password'],
charset=self._json_config['charset'],
database=self._json_config['database']
)
print('数据库连接成功')
return db
except pymysql.Error as e:
print(f"数据库连接异常: {type(e).__name__}: {e}")
Data
嗯,很快就到数据访问层了,这一层的存在,用来调用数据的访问的方法,然后实现对数据库的增删改查,针对业务中的增删改等功能,使用了student类的get、set方法,然后传递参数。
想了想还是觉得该有一点代码:如下分别为定义类和调用类的方法
class Student(User):
def __init__(self):
self._student_classroom = None
self._student_major = None
def get_classroom(self):
return self._student_classroom
def set_classroom(self, value):
if isinstance(value, str):
self._student_classroom = value
return value
else:
raise ValueError('异常,不是str')
总结
这一周的时间基本都是在紧迫的催着完成,但是我也知道为什么要花这么久时间在这里,我还是很幸运的呢,自己慢慢的还是把这个写出来了,如有错误,随时指教,我掌握的还不是很好,如果有错误,请您动一动尊贵的手指评个论,指点一下小弟,感激不尽。