ЁЯЧВя╕П рдзрдбрд╛ 05 тАФ Domain-driven design: рд╕реНрд╡рддрдГрдЪреЗ рд╢рдмреНрдж рдЕрд╕рд▓реЗрд▓реЗ рд╡рд┐рднрд╛рдЧ
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 05 ┬╖ рдорд╛рдЧреЗ: lesson-04-hexagonal ┬╖ рдкреБрдвреЗ: lesson-06-styles
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ04, рдЖрдгрд┐ рд╡рд┐рднрд╛рдЧ. рд╢рд╛рд│рд╛ рдореНрд╣рдгрдЬреЗ рдПрдХ рдореЛрдареА рдирд┐рдпрдордкреБрд╕реНрддрд┐рдХрд╛ рдирд╡реНрд╣реЗ тАФ рддреА рдЖрд╣реЗ рдПрдХ рдкреНрд░рд╡реЗрд╢
рдХрд╛рд░реНрдпрд╛рд▓рдп, рдПрдХ рдкрд░реАрдХреНрд╖рд╛ рд╡рд┐рднрд╛рдЧ, рдПрдХ рд▓реЗрдЦрд╛ рдХрд╛рд░реНрдпрд╛рд▓рдп рдЖрдгрд┐ рдПрдХ рд╡реЗрд│рд╛рдкрддреНрд░рдХ рдХрд╛рд░реНрдпрд╛рд▓рдп,
рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ рдЬрдг рддреЗрдЪ рд╢рдмреНрдж рд╡реЗрдЧрд│реНрдпрд╛ рдЕрд░реНрдерд╛рдиреЗ рд╡рд╛рдкрд░рддреЛ. Domain-driven design (DDD) рдкреНрд░рддреНрдпреЗрдХрд╛рднреЛрд╡рддреА
рдПрдХ bounded context рдЖрдЦрддреЗ, рддреНрдпрд╛рдЪреНрдпрд╛ рдЖрдд рдПрдХ ubiquitous language рдмреЛрд▓рддреЗ, рдЖрдгрд┐ рддреЗ рдПрдХрдореЗрдХрд╛рдВрд╢реА
рдХрд╕реЗ рдЬреЛрдбрд▓реЗрд▓реЗ рдЖрд╣реЗрдд рдпрд╛рдЪрд╛ context map рдХрд╛рдврддреЗ. Lab рд╣рд╛ context map code рдордзреВрди рд╡рд╛рдЪрддреЛ:
arch/analyze.py рдордзреАрд▓ CONTEXTS рдЖрдгрд┐ context_edges(),
arch/demo.py рдордзреАрд▓ ddd().
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рддреАрди offices рдирд╛ рд╡рд┐рдЪрд╛рд░рд╛ "student рдореНрд╣рдгрдЬреЗ рдХрд╛рдп?" ЁЯдФ
- рдкреНрд░рд╡реЗрд╢ рдХрд╛рд░реНрдпрд╛рд▓рдп рдореНрд╣рдгрддреЗ: "рдПрдХ form рдХреНрд░рдорд╛рдВрдХ, рдПрдХ рдирд╛рд╡, рдЖрдгрд┐ рдЖрдореНрд╣реА рдкреНрд░рд╡реЗрд╢ рджрд┐рд▓рд╛ рдХреА рдирд╛рд╣реА."
- рдкрд░реАрдХреНрд╖рд╛ рд╡рд┐рднрд╛рдЧ рдореНрд╣рдгрддреЛ: "maths рдЖрдгрд┐ science рдордзрд▓реЗ marks рдЕрд╕рд▓реЗрд▓рд╛ рдПрдХ roll рдХреНрд░рдорд╛рдВрдХ."
- рд▓реЗрдЦрд╛ рдХрд╛рд░реНрдпрд╛рд▓рдп рдореНрд╣рдгрддреЗ: "fees рджреЗрдгреЗ рдмрд╛рдХреА рдЕрд╕рд▓реЗрд▓реЗ рдПрдХ рдЦрд╛рддреЗ."
рддрд┐рдШреЗрд╣реА рдмрд░реЛрдмрд░ рдЖрд╣реЗрдд тАФ рдЖрдкрд╛рдкрд▓реНрдпрд╛ office рдЪреНрдпрд╛ рдЖрдд. рдЧрдбрдмрдб рддреЗрд╡реНрд╣рд╛ рд╕реБрд░реВ рд╣реЛрддреЗ рдЬреЗрд╡реНрд╣рд╛ рдкрд░реАрдХреНрд╖рд╛ рд╡рд┐рднрд╛рдЧ рдкреНрд░рд╡реЗрд╢ рдХрд╛рд░реНрдпрд╛рд▓рдпрд╛рдЪреА student рдЪреА рдХрд▓реНрдкрдирд╛ рдЙрд╕рдиреА рдШреЗрддреЛ. рдЖрддрд╛ рдкреНрд░рд╡реЗрд╢ рдХрд╛рд░реНрдпрд╛рд▓рдпрд╛рдиреЗ рдЖрдкрд▓реНрдпрд╛ form рдордзреНрдпреЗ рдПрдХ рдирд╡рд╛ рд░рдХрд╛рдирд╛ рдЬреЛрдбрд▓рд╛ рдХреА рдкрд░реАрдХреНрд╖рд╛ рд╡рд┐рднрд╛рдЧрд╛рдЪреЗ report cards рдмрд┐рдШрдбреВ рд╢рдХрддрд╛рдд, рдЖрдгрд┐ рдкрд░реАрдХреНрд╖рд╛ рд╡рд┐рднрд╛рдЧрд╛рдд рдХреЛрдгреАрд╣реА рдХрд╛рд╣реАрдЪ рдмрджрд▓рд▓реЗрд▓реЗ рдирд╕рддреЗ.
рдореНрд╣рдгреВрди рдкреНрд░рддреНрдпреЗрдХ office student рдЪреА рд╕реНрд╡рддрдГрдЪреА рдХрд▓реНрдкрдирд╛ рд╕реНрд╡рддрдГрдЪреНрдпрд╛ рд╢рдмреНрджрд╛рдВрдд рдареЗрд╡рддреЗ. рдкрд░реАрдХреНрд╖рд╛ рд╡рд┐рднрд╛рдЧрд╛рд▓рд╛ рдкреНрд░рд╡реЗрд╢ рдХрд╛рд░реНрдпрд╛рд▓рдпрд╛рдХрдбреВрди рдирд╛рд╡ рд╣рд╡реЗ рдЕрд╕реЗрд▓, рддреЗрд╡реНрд╣рд╛ рджрд╛рд░рд╛рд╡рд░ рдХреЛрдгреАрддрд░реА рдЕрдиреБрд╡рд╛рдж рдХрд░рддреЗ: "рддреБрдордЪрд╛ рдЕрд░реНрдЬрджрд╛рд░ рдХреНрд░рдорд╛рдВрдХ 1042 рдореНрд╣рдгрдЬреЗ рдЖрдордЪрд╛ roll рдХреНрд░рдорд╛рдВрдХ 7." рддреЛ рдЕрдиреБрд╡рд╛рджрдХ рдореНрд╣рдгрдЬреЗ anti-corruption layer.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
adm["ЁЯЧВя╕П admissions<br/>Student = form no, name, status"]
gr["ЁЯУЭ grades (exam cell)<br/>student = roll no + marks"]
fee["ЁЯТ░ fees (accounts)<br/>student = an account"]
tt["ЁЯЧУя╕П timetable<br/>periods and rooms"]
gr -->|"imports Student ┬╖ conformist today<br/>тЖТ anti-corruption layer"| adm
fee -->|"imports Student ┬╖ customerтАУsupplier"| adm
ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрд╡реГрддреНрддреА + рдПрдХ lab: https://school-edh.pages.dev/software-architecture/lesson-diagrams.html#l05
тЭУ рдХрд╛рдп
- Domain-driven design (DDD) тАФ Eric Evans рдпрд╛рдВрдЪрд╛ рджреГрд╖реНрдЯрд┐рдХреЛрди (Domain-Driven Design, 2003): software рдЪрд╛ model рд╡реНрдпрд╡рд╕рд╛рдпрд╛рд╡рд░, рд╡реНрдпрд╡рд╕рд╛рдпрд╛рдЪреНрдпрд╛рдЪ рд╢рдмреНрджрд╛рдВрдд рдмрд╛рдВрдзрд╛, рдЖрдгрд┐ рдореЛрдареЗ models рд▓рд╣рд╛рди, рд╕реБрд╕рдВрдЧрдд models рдордзреНрдпреЗ рд╡рд┐рднрд╛рдЧрд╛.
- Domain / subdomain тАФ рд╡реНрдпрд╡рд╕рд╛рдпрд╛рдЪреЗ рдХреНрд╖реЗрддреНрд░ (рд╢рд╛рд│рд╛ рдЪрд╛рд▓рд╡рдгреЗ) рдЖрдгрд┐ рддреНрдпрд╛рдЪреЗ рднрд╛рдЧ (admissions, рдкрд░реАрдХреНрд╖рд╛, fees, рд╡реЗрд│рд╛рдкрддреНрд░рдХ). Core subdomains рддреБрдореНрд╣рд╛рд▓рд╛ рд╡реЗрдЧрд│реЗ рдард░рд╡рддрд╛рдд; supporting рдЖрдгрд┐ generic subdomains (payments, email) рддреБрдореНрд╣реА рдХрджрд╛рдЪрд┐рдд рд╡рд┐рдХрдд рдШреНрдпрд╛рд▓.
- Bounded context тАФ рдЕрд╢реА рд╕реАрдорд╛ рдЬрд┐рдЪреНрдпрд╛ рдЖрдд рдПрдХ model рдЖрдгрд┐ рдПрдХрдЪ рд╢рдмреНрджрд╕рдВрдЪ рд╕реБрд╕рдВрдЧрддрдкрдгреЗ рд▓рд╛рдЧреВ рд╣реЛрддреЛ. рддрд┐рдЪреНрдпрд╛ рдмрд╛рд╣реЗрд░ рддреЛрдЪ рд╢рдмреНрдж рд╡реЗрдЧрд│реЗ рдХрд╛рд╣реАрддрд░реА рдореНрд╣рдгреВ рд╢рдХрддреЛ тАФ рдЖрдгрд┐ рддреЗ рдареАрдХ рдЖрд╣реЗ.
- Ubiquitous language тАФ рдПрдХрд╛ bounded context рдЪрд╛ рд╕рд╛рдорд╛рдпрд┐рдХ рд╢рдмреНрджрд╕рдВрдЧреНрд░рд╣, рдЬреЛ рддрдЬреНрдЬреНрдЮ рдЖрдгрд┐ code (class рдЪреА рдирд╛рд╡реЗ, method рдЪреА рдирд╛рд╡реЗ, events) рджреЛрдШреЗрд╣реА рд╡рд╛рдкрд░рддрд╛рдд.
- Context map тАФ bounded contexts рдЖрдгрд┐ рддреЗ рдПрдХрдореЗрдХрд╛рдВрд╢реА рдХрд╕реЗ рдЬреЛрдбрд▓реЗрд▓реЗ рдЖрд╣реЗрдд рдпрд╛рдЪреЗ рдЪрд┐рддреНрд░. Evans рдпрд╛рдВрдиреА
рдпрд╛ рдирд╛рддреНрдпрд╛рдВрдирд╛ рдирд╛рд╡реЗ рджрд┐рд▓реА; рддреНрдпрд╛рддрд▓реА рдХрд╛рд╣реА:
- customerтАУsupplier тАФ downstream рдЯреАрдордЪреНрдпрд╛ рдЧрд░рдЬрд╛ upstream рдЪреНрдпрд╛ рдирд┐рдпреЛрдЬрдирд╛рдд рд╡рд┐рдЪрд╛рд░рд╛рдд рдШреЗрддрд▓реНрдпрд╛ рдЬрд╛рддрд╛рдд
- conformist тАФ downstream upstream рдЪрд╛ model рдЬрд╕рд╛рдЪреНрдпрд╛ рддрд╕рд╛ рд╡рд╛рдкрд░рддреЛ
- anti-corruption layer (ACL) тАФ downstream рд╕реАрдореЗрд╡рд░ upstream рдЪреНрдпрд╛ model рдЪрд╛ рд╕реНрд╡рддрдГрдЪреНрдпрд╛ model рдордзреНрдпреЗ рдЕрдиреБрд╡рд╛рдж рдХрд░рддреЛ
- shared kernel тАФ рджреЛрди рдЯреАрдо рд╡рд╛рдЯреВрди рдШреЗрддрд╛рдд рдЖрдгрд┐ рдлрдХреНрдд рдПрдХрддреНрд░рдЪ рдмрджрд▓рддрд╛рдд рдЕрд╕рд╛ рдЫреЛрдЯрд╛ model
- open host service / published language тАФ upstream рд╕рдЧрд│реНрдпрд╛рдВрд╕рд╛рдареА рдПрдХ рд╕реНрдерд┐рд░, рджрд╕реНрддрдРрд╡рдЬреАрдХрд░рдг рдХреЗрд▓реЗрд▓рд╛ interface рджреЗрддреЛ
- separate ways тАФ рдХреЛрдгрддреЗрд╣реА integration рдирд╛рд╣реА
- Upstream / downstream тАФ рдХреЛрдг рдХреЛрдгрд╛рд▓рд╛ рдореЛрдбреВ рд╢рдХрддреЛ: downstream upstream рд╡рд░ рдЕрд╡рд▓рдВрдмреВрди рдЕрд╕рддреЛ.
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг рд╕рдВрдкреВрд░реНрдг рд╢рд╛рд│реЗрд╕рд╛рдареА рдПрдХрдЪ model рдореНрд╣рдгрдЬреЗ рдЪрд╛рд│реАрд╕ fields рдЕрд╕рд▓реЗрд▓рд╛ Student class, рдЬреЛ рдкреНрд░рддреНрдпреЗрдХ office
edit рдХрд░рддреЗ рдЖрдгрд┐ рдХреЛрдгрд╛рдЪреАрдЪ рдорд╛рд▓рдХреА рдирд╕рддреЗ. Bounded contexts рдореБрд│реЗ рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рднрд╛рдЧ рд╕рдВрдкреВрд░реНрдг рд╢рд╛рд│реЗрдЪреНрдпрд╛ meeting
рд╢рд┐рд╡рд╛рдп рдЖрдкрд▓реЗ рдирд┐рдпрдо рдмрджрд▓реВ рд╢рдХрддреЛ тАФ рдореНрд╣рдгрдЬреЗ рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рднрд╛рдЧрд╛рд╕рд╛рдареА modifiability. рдирдВрддрд░ code рддреЛрдбрдгреНрдпрд╛рд╕рд╛рдареАрдЪреЗ
(рдзрдбрд╛ 06) рддреЗ рдиреИрд╕рд░реНрдЧрд┐рдХ рд╕рд╛рдВрдзреЗрд╣реА рдЖрд╣реЗрдд: рд╡рд┐рднрд╛рдЧрд╛рдВрдиреБрд╕рд╛рд░ рддреЛрдбрд╛, рдордЬрд▓реНрдпрд╛рдВрдиреБрд╕рд╛рд░ рдирд╡реНрд╣реЗ.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
arch/analyze.py рдордзреАрд▓ CONTEXTS рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рднрд╛рдЧрд╛рд▓рд╛ рддреНрдпрд╛рдЪреНрдпрд╛ рдЦреЛрд▓реНрдпрд╛рдВрд╢реА
рдЬреЛрдбрддреЛ (grades рдХрдбреЗ domain.grades, app.report_card рдЖрдгрд┐ infra.db рдЪреА рдорд╛рд▓рдХреА). context_edges(g, names) рдПрдХрд╛ рд╡рд┐рднрд╛рдЧрд╛рддреВрди рджреБрд╕рд▒реНрдпрд╛ рд╡рд┐рднрд╛рдЧрд╛рдд рдЬрд╛рдгрд╛рд░реА рдкреНрд░рддреНрдпреЗрдХ рдорд╛рд░реНрдЧрд┐рдХрд╛, import рдХреЗрд▓реЗрд▓реНрдпрд╛ рдирд╛рд╡рд╛рдВрд╕рд╣,
рд╕реВрдЪреАрдмрджреНрдз рдХрд░рддреЛ тАФ scan() рддреА рдкреНрд░рддреНрдпреЗрдХ from тАж import тАж рдордзреВрди рдиреЛрдВрджрд╡рддреЛ. Demo рдордзреАрд▓ "student" рдЪреЗ
рдЕрд░реНрде рд╣рд╛рддрд╛рдиреЗ рд▓рд┐рд╣рд┐рд▓реЗрд▓реЗ рдЖрд╣реЗрдд (рднрд╛рд╖рд╛ рдорд╛рдгреВрд╕ рдард░рд╡рддреЛ, scanner рдирд╡реНрд╣реЗ); edges рдорд╛рддреНрд░ code рдордзреВрди рд╡рд╛рдЪрд▓реЗ
рдЬрд╛рддрд╛рдд.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 arch/demo.py ddd
python3 - <<'EOF'
import sys; sys.path.insert(0, "arch"); from analyze import scan, CONTEXTS, context_edges, apply
cb = scan(); g = cb.imports
for c, rooms in CONTEXTS.items():
print(f"{c:<10} rooms {rooms} ┬╖ classes {[k for r in rooms for k, _ in cb.classes[r]]}")
print("cross-department corridors:", len(context_edges(g, cb.names)))
acl = apply(g, remove=[("domain.grades", "domain.admissions"), ("domain.fees", "domain.admissions")])
print("after each department keeps its own Student:", len(context_edges(acl)))
EOF
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
ddd рд╣реЗ рдЫрд╛рдкрддреЛ:
тФАтФА the context map, read from the code: 2 cross-department corridors
fees тЖТ admissions: domain.fees imports Student from domain.admissions
grades тЖТ admissions: domain.grades imports Student from domain.admissions
рддреБрдордЪрд╛ snippet рд╣реЗ рдЫрд╛рдкрддреЛ:
admissions rooms ['domain.admissions', 'app.enrol'] ┬╖ classes ['Student', 'Application', 'EnrolService']
grades rooms ['domain.grades', 'app.report_card', 'infra.db'] ┬╖ classes ['Mark', 'ReportCard', 'ReportCardService', 'SqlGradeStore', 'SqlLedger']
fees rooms ['domain.fees', 'app.fees_service'] ┬╖ classes ['Account', 'FeesService']
timetable rooms ['domain.timetable'] ┬╖ classes ['Period']
cross-department corridors: 2
after each department keeps its own Student: 0
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
Context map рдореНрд╣рдгрдЬреЗ whiteboard рд╡рд░рдЪреА рдЗрдЪреНрдЫрд╛ рдирд╡реНрд╣реЗ тАФ рддреЛ imports рдордзреВрди рд╡рд╛рдЪрддрд╛ рдпреЗрддреЛ. рджреЛрди рд╡рд┐рднрд╛рдЧ
рдПрдХрд╛рдЪ class рд╕рд╛рдареА, Student, admissions рдордзреНрдпреЗ рд╣рд╛рдд рдШрд╛рд▓рддрд╛рдд. рджреЛрдШрд╛рдВрдирд╛рд╣реА рдлрдХреНрдд рдирд╛рд╡ рд╣рд╡реЗ рдЖрд╣реЗ, рдкрдг рдЖрддрд╛
admissions рдиреЗ рдЖрдкрд▓рд╛ model рдмрджрд▓рд▓рд╛ рдХреА рджреЛрдШреЗрд╣реА рдмрджрд▓рддрд╛рдд. рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рднрд╛рдЧрд╛рд▓рд╛ student рдЪреА рд╕реНрд╡рддрдГрдЪреА рдЫреЛрдЯреА
рдХрд▓реНрдкрдирд╛ рджреНрдпрд╛ (рдЖрдгрд┐ рджрд╛рд░рд╛рд╡рд░ рдЕрдиреБрд╡рд╛рдж рдХрд░рд╛) рдЖрдгрд┐ рд╡рд┐рднрд╛рдЧ-рдУрд▓рд╛рдВрдбрдгрд╛рд▒реНрдпрд╛ рдорд╛рд░реНрдЧрд┐рдХрд╛ 2 рд╡рд░реВрди 0 рд╡рд░ рдпреЗрддрд╛рдд.
рдпрд╛рджреАрдд рджрд┐рд╕рдгрд╛рд░реА рдПрдХ рд╡рд┐рдЪрд┐рддреНрд░ рдЧреЛрд╖реНрдЯ рд▓рдХреНрд╖рд╛рдд рдШреНрдпрд╛: SqlLedger grades рд╡рд┐рднрд╛рдЧрд╛рдЪреНрдпрд╛ infra.db рдордзреНрдпреЗ
рд░рд╛рд╣рддреЛ, рдкрдг рддреЛ fees рдЪреА рд╕реЗрд╡рд╛ рдХрд░рддреЛ. File technology рдиреБрд╕рд╛рд░ рдорд╛рдВрдбрд▓реЗрд▓реА рдЖрд╣реЗ, рд╡рд┐рднрд╛рдЧрд╛рдиреБрд╕рд╛рд░ рдирд╡реНрд╣реЗ.
рддреБрдореНрд╣реА рд╡рд┐рднрд╛рдЧрд╛рдВрдиреБрд╕рд╛рд░ рддреЛрдбрддрд╛, рддреЗрд╡реНрд╣рд╛ рддреА file рд╣реА рддреБрдЯрддреЗ.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- рд╕рдВрдкреВрд░реНрдг рдХрдВрдкрдиреАрд╕рд╛рдареА рдПрдХрдЪ рд╕рд╛рдорд╛рдпрд┐рдХ
Student(рдХрд┐рдВрд╡рд╛User,Order) model - bounded contexts рд╡реНрдпрд╡рд╕рд╛рдпрд╛рдЪреНрдпрд╛ рд░реЗрд╖рд╛рдВрдРрд╡рдЬреА рддрд╛рдВрддреНрд░рд┐рдХ рд░реЗрд╖рд╛рдВрд╡рд░ (рдПрдХ "database context") рдЖрдЦрдгреЗ
- рд╕рдВрдкреВрд░реНрдг model рд╣реЛрдИрдкрд░реНрдпрдВрдд рд╡рд╛рдврдд рдЬрд╛рдгрд╛рд░рд╛ "shared kernel"
- "рдЖрдЬ fields рд╕рд╛рд░рдЦреЗрдЪ рджрд┐рд╕рддрд╛рдд" рдореНрд╣рдгреВрди рдЕрдиреБрд╡рд╛рдж рд╡рдЧрд│рдгреЗ
- рдХрд╛рдо рдХрд░рдгрд╛рд▒реНрдпрд╛ рд▓реЛрдХрд╛рдВрдХрдбреВрди рднрд╛рд╖рд╛ рд╢рд┐рдХрдгреНрдпрд╛рдРрд╡рдЬреА рддреА code рдордзреНрдпреЗ рд╢реЛрдзреВрди рдХрд╛рдврдгреЗ
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
On a real project тАФ anti-corruption layer рдореНрд╣рдгрдЬреЗ рдмрд╣реБрддреЗрдХрджрд╛ downstream рд╡рд┐рднрд╛рдЧрд╛рдЪреНрдпрд╛ рдорд╛рд▓рдХреАрдЪреЗ рдлрдХреНрдд рдПрдХ рдЫреЛрдЯреЗ рдЕрдиреБрд╡рд╛рджрдХ module:
# grades/acl/admissions.py тАФ the only file in grades that knows admissions' model
from dataclasses import dataclass
from admissions.api import get_student # the upstream's published interface
@dataclass(frozen=True)
class Learner: # grades' own word
roll_no: int
display_name: str
def learner_for(roll_no: int) -> Learner:
s = get_student(roll_no) # upstream shape: form_no, full_name, statusтАж
return Learner(roll_no=roll_no, display_name=s["full_name"])
рд╡рд┐рднрд╛рдЧрд╛рдВрдирд╛ top-level packages рдмрдирд╡рд╛ (schoolapp/admissions/, schoolapp/grades/ тАж) рдЖрдгрд┐
import-linter рд▓рд╛ рддреНрдпрд╛рдВрдирд╛ рд╡реЗрдЧрд│реЗ рдареЗрд╡реВ рджреНрдпрд╛, рдлрдХреНрдд рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рднрд╛рдЧрд╛рдЪреНрдпрд╛ api module рд▓рд╛ рдкрд░рд╡рд╛рдирдЧреА рджреЗрдКрди:
[importlinter:contract:departments]
name = Departments talk only through their api
type = independence
modules =
schoolapp.admissions
schoolapp.grades
schoolapp.fees
schoolapp.timetable
ignore_imports =
schoolapp.grades.acl.admissions -> schoolapp.admissions.api
Contexts рд╢реЛрдзрдгреЗ рд╣реА workshop рдЖрд╣реЗ, script рдирд╡реНрд╣реЗ: Event Storming (Alberto Brandolini) domain рддрдЬреНрдЬреНрдЮ рдЖрдгрд┐ developers рдирд╛ sticky notes рдЪреНрдпрд╛ рдПрдХрд╛ рд▓рд╛рдВрдм рднрд┐рдВрддреАрд╕рдореЛрд░ рдЙрднреЗ рдХрд░рддреЗ, рдкреНрд░рддреНрдпреЗрдХ business event рд╕рд╛рдареА рдПрдХ note, рдЖрдгрд┐ рдЬрд┐рдереЗ рд╢рдмреНрдж рдмрджрд▓рддрд╛рдд рддрд┐рдереЗ рд╕реАрдорд╛ рджрд┐рд╕реВ рд▓рд╛рдЧрддрд╛рдд.
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рддреБрдордЪреЗ рд╕рдЧрд│реНрдпрд╛рдд рдЬрд╛рд╕реНрдд import рд╣реЛрдгрд╛рд░реЗ рдкрд╛рдЪ classes рд▓рд┐рд╣рд╛. рдкреНрд░рддреНрдпреЗрдХрд╛рд╕рд╛рдареА рддреАрди рд╡рд┐рднрд╛рдЧрд╛рдВрдирд╛ рд╡рд┐рдЪрд╛рд░рд╛ рдХреА рддреНрдпрд╛ рд╢рдмреНрджрд╛рдЪрд╛ рдЕрд░реНрде рдХрд╛рдп. рджреЛрди рд╡реЗрдЧрд│реА рдЙрддреНрддрд░реЗ рдореНрд╣рдгрдЬреЗ рджреЛрди models.
тПня╕П рдкреБрдвреЗ
рд╡рд┐рднрд╛рдЧ рдореНрд╣рдгрдЬреЗ рд╕рд╛рдВрдзреЗ. рддреЗ рдПрдХрд╛рдЪ рдЗрдорд╛рд░рддреАрдд рд░рд╛рд╣рддрд╛рдд, рдХреА campus рднрд░ рд╡реЗрдЧрд╡реЗрдЧрд│реНрдпрд╛ рдЗрдорд╛рд░рддреАрдВрдд? Monolith, modular monolith, microservices тАФ рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХрд╛рдЪреА рдХрд┐рдВрдордд.
git checkout lesson-06-styles