領域驅動模型


領域驅動模型

 

  要想了解領域驅動模型,首先你要先知道基於領域驅動的架構目錄,如下圖

  • 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層導入上述代碼類,並實例對象,調用服務層驗證方法就可以了

 

  我們看到,整個代碼設計都是由登陸這個業務邏輯驅動的

  不過你感覺這繞來繞去的,感覺沒什么好的,可以這么說小型項目,毫無疑問增加很多不必要的代碼,但是對於大型網站,協作與維護是非常方便的,只能因景而異啦

  再加個圖吧

 

 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM