要想了解領域驅動模型,首先你要先知道基於領域驅動的架構目錄,以下圖前端
-
Repository 數據倉庫,用於數據訪問和持久化(功能是基於業務來作,並在業務裏定義接口來約束數據庫的操做功能)
-
Model 業務處理
-
建模(模型封裝業務須要的數據)
-
接口(約束數據庫的訪問功能)
-
協調 領域模型 和 數據訪問處理業務(調用數據庫訪問的xx方法,並把處理的數據封裝到模型中),把模型返回給服務層
-
service 服務層(請求有規則,響應有規則)---調用業務處理的協調者的協調方法
-
UI層 負責請求對應的類
領域驅動設計,用本身的話說就是業務邏輯場景驅動整個程序代碼的設計python
仍是不懂?那看個例子吧,這個例子再尋常不過了mysql
登錄場景sql
場景分析:數據庫
- 常見的兩種登錄方法--用戶名+密碼 或 郵箱+密碼,這就是前端提交後臺要處理的數據,三個一塊兒交過去,沒有的就等於None
- 登錄失敗,要顯示錯誤信息,登錄成功,就要顯示我的信息,因此後臺處理完後要返回這些數據
領域模型,固然是從模型入手了,模型怎麼建了,模型是要封裝全部須要的數據,那咱們須要哪些數據---登錄狀態,錯誤信息,以及我的信息,其中涉及數據庫訪問的就是我的信息了,那麼模型就要封裝我的信息架構
- 模型---我的信息:id,用戶名,郵箱,最近登錄時間,用戶類型,會員類型(其中用戶類型和會員類型又能夠分出小模型)
因此在Model裏建一個User.pypost
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
|
除了建模型,還在這裏定義接口(接口主要限制數據庫的訪問功能),分析認證的過程是郵箱或用戶名,能夠分開定義成兩個方法,一個用用戶名驗證的方法,一個就是用郵箱驗證的方法,最後還要有更新用戶登錄時間的方法fetch
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,專門用鏈接數據庫的spa
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層導入上述代碼類,並實例對象,調用服務層驗證方法就能夠了
咱們看到,整個代碼設計都是由登錄這個業務邏輯驅動的
不過你感受這繞來繞去的,感受沒什麼好的,能夠這麼說小型項目,毫無疑問增長不少沒必要要的代碼,可是對於大型網站,協做與維護是很是方便的,只能因景而異啦
再加個圖吧