UBD分层结构的学生信息管理系统(python+pysimplegui+mysql)

目录

作者的吐槽

介绍流程

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')

总结

这一周的时间基本都是在紧迫的催着完成,但是我也知道为什么要花这么久时间在这里,我还是很幸运的呢,自己慢慢的还是把这个写出来了,如有错误,随时指教,我掌握的还不是很好,如果有错误,请您动一动尊贵的手指评个论,指点一下小弟,感激不尽。

  • 26
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FX3UBD板是一种用于工业自动化控制系统的主站设备。ADP则是从站设备。主站设备负责控制整个系统的操作和监控,它通过ADP从站设备与各个外设相连接。ADP从站设备通过与主站进行通信,将主站下达的指令传递给各个外设,并将外设的状态信息反馈给主站。 FX3UBD板作为主站设备,具有多个通信接口,包括以太网接口、串行接口等,用于与其他设备进行通信。它采用高速处理器和先进的控制算法,能够快速响应主站的指令,实现对各个外设的精确控制。主站设备还具备数据存储功能,可以保存历史数据以及系统配置信息,方便系统运行和维护。 ADP作为从站设备,通常连接着各种外设,例如传感器、执行器、输入输出模块等。它接收主站的指令,并将其转发给外设,同时收集和整理外设的状态信息,通过与主站进行通信,将这些信息传递给主站。ADP从站设备可以支持多种通信协议,如Modbus、Profibus等,以适应不同设备之间的通信需求。 FX3UBD主站和ADP从站通过特定的通信协议进行数据传输和交互,实现系统的自动化控制和监测。主站设备可以将外设的信息传送至上位计算机,实现对整个系统的集中控制和管理。 总之,FX3UBD板作为主站设备,ADP作为从站设备,共同组成了工业自动化控制系统中的核心部分,实现了对各个外设的精确控制和信息交互。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值