• 领域驱动模型


    领域驱动模型

     

      要想了解领域驱动模型,首先你要先知道基于领域驱动的架构目录,如下图

    • Repository  数据仓库,用于数据访问和持久化(功能是基于业务来做,并在业务里定义接口来约束数据库的操作功能)

    • Model  业务处理

    1. 建模(模型封装业务需要的数据)

    2. 接口(约束数据库的访问功能)

    3. 协调 领域模型  和  数据访问处理业务(调用数据库访问的xx方法,并把处理的数据封装到模型中),把模型返回给服务层

    • service 服务层(请求有规则,响应有规则)---调用业务处理的协调者的协调方法

    • UI层  负责请求对应的类

      领域驱动设计,用自己的话说就是业务逻辑场景驱动整个程序代码的设计

      还是不懂?那看个例子吧,这个例子再寻常不过了

      登陆场景

    场景分析:

    • 常见的两种登陆方法--用户名+密码  或  邮箱+密码,这就是前端提交后台要处理的数据,三个一起交过去,没有的就等于None
    • 登陆失败,要显示错误信息,登陆成功,就要显示个人信息,所以后台处理完后要返回这些数据

      领域模型,当然是从模型入手了,模型怎么建了,模型是要封装所有需要的数据,那我们需要哪些数据---登陆状态,错误信息,以及个人信息,其中涉及数据库访问的就是个人信息了,那么模型就要封装个人信息

    • 模型---个人信息:id,用户名,邮箱,最近登陆时间,用户类型,会员类型(其中用户类型和会员类型又可以分出小模型)

    所以在Model里建一个User.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    #建立模型
     
    class VipType:
     
        dic = {
            1:'金牌',
            2:'银牌',
            3:'铜牌'
        }
     
        def __init__(self,nid):
            self.nid = nid
     
        @property
        def caption(self):
            for i in VipType.dic:
                if i == self.nid:
                    return VipType.dic[i]
     
     
    class UserType:
     
        dic = {
            1:'普通用户',
            2:'商户',
            3:'管理员'
        }
     
        def __init__(self,nid):
            self.nid = nid
     
        @property
        def caption(self):
            for j in UserType.dic:
                if self.nid == j:
                    return UserType.dic[j]
     
    class User:
     
        def __init__(self,nid,username,email,last_login,vip_type_obj,user_type_obj):
            self.nid = self.nid
            self.username = username
            self.email = email
            self.last_login = last_login
            self.vip_type = vip_type_obj
            self.user_type = user_type_obj

       除了建模型,还在这里定义接口(接口主要限制数据库的访问功能),分析认证的过程是邮箱或用户名,可以分开定义成两个方法,一个用用户名验证的方法,一个就是用邮箱验证的方法,最后还要有更新用户登陆时间的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    #定义接口
     
    class IUserRepository:
     
        def fetch_one_by_username(self,username,password):
            '''
            通过密码到数据库进行验证
            :param username: 用户名
            :param password: 密码
            :return:
            '''
     
        def fetch_one_by_email(self,email,password):
            '''
            通过邮箱到数据库进行验证
            :param email:
            :param password:
            :return:
            '''
     
        def update_last_login_by_nid(self,nid,cur_date):
            '''
            通过nid更新数据库的登陆时间
            :param nid: id
            :param cur_date: 最新时间
            :return:
            '''

       好!接口和模型定义好后,就可以去Repository把接口里方法实现了

    • 数据访问,数据访问,肯定要要连接上数据库才能访问

      在Repository创建了一个DbConnection.py,专门用连接数据库的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import pymysql
    import Config
     
     
    class DbConnection:
     
        def __init__(self):
            #数据库的信息写在配置文件里
            self.__conn_dict = Config.PY_MYSQL_CONN_DICT
            self.conn = None
            self.cursor = None
     
        #连接数据库,创建游标
        def connect(self,cursor=pymysql.cursors.DictCursor):
            self.conn = pymysql.connect(**self.__conn_dict)
            self.cursor = self.conn.cursor(cursor=cursor)
            return self.cursor
     
        #关闭游标以及数据库
        def close(self):
            self.conn.commit()
            self.cursor.close()
            self.conn.close()

       做好了这一步,访问数据库时只要实例化这样一个对象就可以了

      针对业务层User建立一个UserRepository.py专门实现User文件接口的方法,并处理得到的数据封装到模型里

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    from Model.User import VipType,User,UserType,IUserRepository
    #进行数据库连接的另成立模块
    from .DbConnection import DbConnection
     
     
    class UserDb(IUserRepository):
     
        def __init__(self):
            self.conn = DbConnection()
     
        def fetch_one_by_email(self,email,password):
            ret = None
            cursor = self.conn.connect()
            sql = '''select nid,username,email,last_login,vip_type,user_type
             from UserInfo where email=% and password=%'''
            cursor.execute(sql,(email,password))
            #db_result是一个字典
            db_result = cursor.fetchone()
            self.conn.close()
            if db_result:
                #调用模型进行封装
                ret = User(nid=db_result['nid'],
                           username=db_result['username'],
                           email=db_result['email'],
                           last_login=db_result['last_login'],
                           user_type=UserType(nid=db_result['user_type']),
                           vip_type=VipType(nid=db_result['vip_type']))
                return ret
     
     
     
        def fetch_one_by_username(self,username,password):
            ret = None
            cursor = self.conn.connect()
            sql = '''select nid,username,email,last_login,vip_type,user_type
             from UserInfo where username=% and password=%'''
            cursor.execute(sql,(username,password))
            #db_result是一个字典
            db_result = cursor.fetchone()
            self.conn.close()
            if db_result:
                #调用模型进行封装
                ret = User(nid=db_result['nid'],
                           username=db_result['username'],
                           email=db_result['email'],
                           last_login=db_result['last_login'],
                           user_type=UserType(nid=db_result['user_type']),
                           vip_type=VipType(nid=db_result['vip_type']))
                return ret
     
        def update_last_login_by_nid(self,nid,cur_date):
            cursor = self.conn.connect()
            sql = '''update UserInfo set last_login=%s where nid=%s'''
            cursor.execute(sql,(cur_date,nid))
            self.conn.close()

       定义好接口方法后我们需要再次来到业务层,在Model的User.py写入协调类,用于调用数据仓库的方法,并把封装好的模型对象返回给服务层,在调用方法前,需要需要先实例UserRepository对象,这里可以用依赖注入

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #协调者,进行认证
     
    class UserService:
     
        def __init__(self,user_repostiory):
            self.db = user_repostiory
     
        def check_login(self,user,pwd,ema):
            if user:
                user_model = self.db.fetch_one_by_username(username=user,password=pwd)
            else:
                user_model = self.db.fetch_one_by_email(email=ema,password=pwd)
            if user_model:
                current_date = datetime.datetime.now()
                self.db.update_last_login_by_nid(user_model.nid,current_date)
            return user_model

      那么对于协调者来说,验证的数据哪里来,没错就是服务层,不仅接收处理数据还是传递客户输入的数据进行验证,并且在服务层里协调类里调用业务层的协调方法

       在开始写服务层时,你必须理解这句话,就是请求有规则,响应有规则---请求就是传客户数据,响应就是收业务处理数据,到了服务层就要按服务层的规则,按照服务层定义进行封装数据

      在服务层下建个User的文件夹专门服务业务层的User

      我们先定义‘请求规则’--Request.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    '''
    对于request类的建立规则就是,前端发来多少项数据就对应建立几个字段
    '''
     
    class UserRequest:
     
        def __init__(self,usr,pwd,ema):
            self.username = usr
            self.password = pwd
            self.email = ema

       然后我们定义一下响应规则,在这里我们必须清楚,返回给客户看的是字符串,业务层返回模型里的字段带有对象的就到这里细化

    Response.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    '''
    需要返回的信息无非就是执行状态,错误信息,以及用户信息
    其中用户信息又封装到ModelView对象里
    '''
     
    class UserResponse:
     
        def __init__(self,status=True,message='',model_view=None):
            self.status = status
            self.message = message
            self.modelView = model_view

     ModelView.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    '''
    在服务层,模型数据的接收者,并且细化,在这里是封装客户信息
    '''
    class UserModelView:
     
        def __init__(self,nid,username,email,
                     last_login,user_type_id,user_type_caption,
                     vip_type_id,vip_type_caption):
            self.nid = nid
            self.username = username
            self.email = email
            self.last_login = last_login
            self.user_type = user_type_id
            self.user_type_caption = user_type_caption
            self.vip_type = vip_type_id
            self.vip_type_caption = vip_type_caption

       最后剩下就是调用业务层协调者和把数据返回给UI层的服务层协调者了,这里要调用业务层的协调者就必须实例一个业务层的UserService对象,这个通过参数的形式传入到服务层协调类的构造方法里,就又要用到依赖注入了,并且最终的信息要封装到服务层的规则里(Response),所以在定义验证方法里实例Response对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    '''
    在Service里,接收request对象里封装信息
    调用model业务层的方法做验证,先要实例业务层service对象(写在构造方法里)
    把验证的结果信息封装到response对象里
    '''
     
    from Services.User.Response import UserResponse
    from Services.User.ModelView import UserModelView
     
    class service:
     
        def __init__(self,model_user_service):
            self.modelUserService = model_user_service  #业务层协调者
     
        def check_login(self,user_request):
            response = UserResponse()
     
            try:
                model = self.modelUserService.check_login(user=user_request.usr,pwd=user_request.pwd,ema=user_request.ema)
                if model:
                   UserModelView(nid=model.nid,
                                 username=model.username,
                                 email=model.email,
                                 last_login=model.last_login,
                                 user_type_id=model.user_type.nid,
                                 user_type_caption=model.user_type.caption,
                                 vip_type_id=model.vip_type.nid,
                                 vip_type_caption=model.vip_type.caption)
                   response.modelView = UserModelView
                else:
                    raise Exception('密码错误!')
     
            except Exception as e:
                response.status = False
                response.message = str(e)
     
            return response

       最后在UI层导入上述代码类,并实例对象,调用服务层验证方法就可以了

      我们看到,整个代码设计都是由登陆这个业务逻辑驱动的

      不过你感觉这绕来绕去的,感觉没什么好的,可以这么说小型项目,毫无疑问增加很多不必要的代码,但是对于大型网站,协作与维护是非常方便的,只能因景而异啦

      再加个图吧

     
     
  • 相关阅读:
    js插件zClip实现复制到剪贴板功能
    基于jQuery的滚动条插件-jquery.jscrollbar
    jquery mobile 开启开关
    html5 中audio 在safari上不支持自动播放
    开发人员常用的10个Sublime Text插件
    通过padding-bottom或者padding-top实现等比缩放响应式图片
    get请求下载json文件正常,但是不弹出status
    JSON错误
    对象与类
    数组(二)
  • 原文地址:https://www.cnblogs.com/zcok168/p/10063654.html
Copyright © 2020-2023  润新知