ЁЯз▒ рдзрдбрд╛ 02 тАФ Modularity: рдХрдореА рдорд╛рд░реНрдЧрд┐рдХрд╛ рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдЦреЛрд▓реНрдпрд╛, рдореЛрдЬреВрди
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 02 ┬╖ рдорд╛рдЧреЗ: lesson-01-what-is-architecture ┬╖ рдкреБрдвреЗ: lesson-03-layers
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбрд╛ 01, рдЖрдгрд┐ рдореЛрдЬрдорд╛рдк. Cohesion (рдПрдХрд╛ рдЦреЛрд▓реАрддрд▓реНрдпрд╛ рдЧреЛрд╖реНрдЯреА рдПрдХрддреНрд░ рдЕрд╕рд╛рдпрд▓рд╛ рд╣рд╡реНрдпрд╛рдд рдХрд╛?)
рдЖрдгрд┐ coupling (рдХрд┐рддреА рдорд╛рд░реНрдЧрд┐рдХрд╛ рдЖрдд рдпреЗрддрд╛рдд рдЖрдгрд┐ рдмрд╛рд╣реЗрд░ рдЬрд╛рддрд╛рдд?), рдпрд╛рдВрдЪреЗ рддреБрдореНрд╣реА рд▓рдХреНрд╖ рдареЗрд╡реВ рд╢рдХрд╛рд▓
рдЕрд╢рд╛ рдЖрдХрдбреНрдпрд╛рдВрдд рд░реВрдкрд╛рдВрддрд░: afferent coupling Ca, efferent coupling Ce, instability I,
abstractness A рдЖрдгрд┐ main sequence рдкрд╛рд╕реВрдирдЪреЗ рдЕрдВрддрд░ D тАФ Robert C. Martin рдпрд╛рдВрдЪреЗ package
metrics тАФ рдЖрдгрд┐ рддреНрдпрд╛рд╕реЛрдмрдд рдПрдХ рд╕реЛрдкрд╛ relational-cohesion рдЖрдХрдбрд╛ H. arch/analyze.py
рдордзреАрд▓ coupling() рдЖрдгрд┐ arch/demo.py рдордзреАрд▓ modularity().
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рд╢рд╛рд│реЗрдЪреНрдпрд╛ рдЪрд╛рдВрдЧрд▓реНрдпрд╛ рдЗрдорд╛рд░рддреАрдд рдкреНрд░рддреНрдпреЗрдХ рдЦреЛрд▓реАрдЪреЗ рдПрдХрдЪ рдХрд╛рдо рдЕрд╕рддреЗ. Science lab рдордзреНрдпреЗ test tubes рдЕрд╕рддрд╛рдд. рдЧреНрд░рдВрдерд╛рд▓рдпрд╛рдд рдкреБрд╕реНрддрдХреЗ рдЕрд╕рддрд╛рдд. рдЕрд░реНрдзреНрдпрд╛ test tubes рдЧреНрд░рдВрдерд╛рд▓рдпрд╛рдд рдареЗрд╡рдд рдирд╛рд╣реАрдд. рд╣реЗрдЪ cohesion: рдПрдХрддреНрд░ рд╡рд╛рдкрд░рд▓реНрдпрд╛ рдЬрд╛рдгрд╛рд▒реНрдпрд╛ рдЧреЛрд╖реНрдЯреА рдПрдХрддреНрд░ рд░рд╛рд╣рддрд╛рдд.
рдЖрдгрд┐ рдЪрд╛рдВрдЧрд▓реНрдпрд╛ рдЦреЛрд▓реАрд▓рд╛ рджрд╣рд╛ рджрд╛рд░реЗ рдирд╕рддрд╛рдд. Science lab рд▓рд╛ рдЗрддрд░ рдкреНрд░рддреНрдпреЗрдХ рдЦреЛрд▓реАрдХрдбреЗ рджрд╛рд░ рдЕрд╕рддреЗ, рддрд░ рдореБрд▓реЗ рджрд┐рд╡рд╕рднрд░ рддрд┐рдЪреНрдпрд╛рддреВрди рдпреЗ-рдЬрд╛ рдХрд░рдд рд░рд╛рд╣рд┐рд▓реА рдЕрд╕рддреА, рдЖрдгрд┐ рдХреЛрдгрд╛рд▓рд╛рд╣реА рдзрдХреНрдХрд╛ рди рд▓рд╛рд╡рддрд╛ рдЖрдд рдХрд╛рд╣реАрдЪ рдмрджрд▓рддрд╛ рдЖрд▓реЗ рдирд╕рддреЗ. рд╣реЗрдЪ coupling: рдЦреЛрд▓реАрд▓рд╛ рдЬрд┐рддрдХреНрдпрд╛ рдХрдореА рдорд╛рд░реНрдЧрд┐рдХрд╛ рд▓рд╛рдЧрддрд╛рдд, рддрд┐рддрдХреА рддреА рдмрджрд▓рд╛рдпрд▓рд╛ рд╕реЛрдкреА.
рджреАрдкрд┐рдХрд╛ рдкреНрд░рддреНрдпреЗрдХ рдордЬрд▓реНрдпрд╛рдЪреА рджрд╛рд░реЗ рдореЛрдЬрддреЗ. рдЖрдд рдпреЗрдгрд╛рд░реА рджрд╛рд░реЗ (рдЬреНрдпрд╛рдВрдирд╛ рдпрд╛ рдордЬрд▓реНрдпрд╛рдЪреА рдЧрд░рдЬ рдЖрд╣реЗ рдЕрд╕реЗ рд▓реЛрдХ) рдордЬрд▓рд╛ рдмрджрд▓рд╛рдпрд▓рд╛ рдЕрд╡рдШрдб рдХрд░рддрд╛рдд тАФ рдЕрдиреЗрдХ рдЬрдг рддреНрдпрд╛рд╡рд░ рдЕрд╡рд▓рдВрдмреВрди рдЕрд╕рддрд╛рдд. рдмрд╛рд╣реЗрд░ рдЬрд╛рдгрд╛рд░реА рджрд╛рд░реЗ (рдпрд╛ рдордЬрд▓реНрдпрд╛рд▓рд╛ рд▓рд╛рдЧрдгрд╛рд▒реНрдпрд╛ рдЧреЛрд╖реНрдЯреА) рддреНрдпрд╛рд▓рд╛ рд╕рд╣рдЬ рдбрд│рдорд│реАрдд рдХрд░рддрд╛рдд тАФ рджреБрд╕рд░рд╛ рдордЬрд▓рд╛ рдмрджрд▓рд▓рд╛ рдХреА рдпрд╛рд▓рд╛ рдЬрд╛рдгрд╡рддреЗ.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
app["ЁЯзСтАНЁЯПл app floor<br/>Ca 2 ┬╖ Ce 3 ┬╖ I 0.60"]
domain["ЁЯУЪ domain floor<br/>Ca 5 ┬╖ Ce 2 ┬╖ I 0.29 ┬╖ A 0.33"]
infra["ЁЯФМ infra floor<br/>Ca 3 ┬╖ Ce 2 ┬╖ I 0.40"]
web["ЁЯЦея╕П web floor<br/>Ca 2 ┬╖ Ce 1 ┬╖ I 0.33"]
main["ЁЯФС main<br/>Ca 0 ┬╖ Ce 1 ┬╖ I 1.00"]
main --> app
main --> web
main --> infra
web --> app
app --> domain
app --> infra
domain --> infra
domain --> web
infra --> domain
ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрд╡реГрддреНрддреА + рдПрдХ lab: https://school-edh.pages.dev/software-architecture/lesson-diagrams.html#l02
тЭУ рдХрд╛рдп
- Cohesion тАФ рдПрдХрд╛ module рдЪреЗ рднрд╛рдЧ рдПрдХрдореЗрдХрд╛рдВрд╢реА рдХрд┐рддреА рдШрдЯреНрдЯ рдЬреБрд│рд▓реЗрд▓реЗ рдЖрд╣реЗрдд. Larry Constantine
рдЖрдгрд┐ Edward Yourdon рдпрд╛рдВрдиреА Structured Design (1979) рдордзреНрдпреЗ рддреНрдпрд╛рдЪреЗ рдкреНрд░рдХрд╛рд░ рд╡рд░реНрдгрди рдХреЗрд▓реЗ;
functional cohesion (рд╕рдЧрд│реЗ рдПрдХрд╛рдЪ рдХрд╛рдорд╛рд╕рд╛рдареА) рд╕рдЧрд│реНрдпрд╛рдд рдЪрд╛рдВрдЧрд▓реЗ, coincidental (рдПрдХ
utils.pyрд╕рд╛рд░рдЦреА рдЦрд┐рдЪрдбреА) рд╕рдЧрд│реНрдпрд╛рдд рд╡рд╛рдИрдЯ. - Coupling тАФ рдПрдХ module рдЗрддрд░рд╛рдВрд╡рд░ рдХрд┐рддреА рдЕрд╡рд▓рдВрдмреВрди рдЖрд╣реЗ. рдХрдореА рдореНрд╣рдгрдЬреЗ рдиреЗрд╣рдореАрдЪ рдЪрд╛рдВрдЧрд▓реЗ рдирд╛рд╣реА тАФ рд╢реВрдиреНрдп coupling рдореНрд╣рдгрдЬреЗ рднрд╛рдЧ рдПрдХрддреНрд░ рдХрд╛рдордЪ рдХрд░рдд рдирд╛рд╣реАрдд тАФ рдкрдг рдкреНрд░рддреНрдпреЗрдХ coupling рдЧрд░рдЬреЗрдЪреЗ рдЖрдгрд┐ рдпреЛрдЧреНрдп рджрд┐рд╢реЗрдиреЗ рдЕрд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ.
- Component тАФ рдПрдХрддреНрд░ release рд╣реЛрдгрд╛рд▒реНрдпрд╛ рдЖрдгрд┐ рдПрдХрддреНрд░ рд╡рд┐рдЪрд╛рд░ рдХреЗрд▓реНрдпрд╛ рдЬрд╛рдгрд╛рд▒реНрдпрд╛ modules рдЪрд╛ рдЧрдЯ (рдПрдХ
Python package, рдПрдХ Java JAR). рдЗрдереЗ: рдПрдХ рдордЬрд▓рд╛ (
web,app,domain,infra, рдЖрдгрд┐main). Martin рдпрд╛рдВрдЪреЗ metrics classes рдореЛрдЬрддрд╛рдд; lab рддреНрдпрд╛рдВрдЪреНрдпрд╛ рдЬрд╛рдЧреА modules рдореЛрдЬрддреЛ. - Ca, afferent coupling (fan-in) тАФ component рдЪреНрдпрд╛ рдмрд╛рд╣реЗрд░рдЪреЗ рдХрд┐рддреА modules рддреНрдпрд╛рдЪреНрдпрд╛ рдЖрддрд▓реЗ рдПрдЦрд╛рджреЗ module import рдХрд░рддрд╛рдд. рдЬрд╛рд╕реНрдд Ca = рдЕрдиреЗрдХ рдЬрдг рддреНрдпрд╛рд╡рд░ рдЕрд╡рд▓рдВрдмреВрди = рдЬрдмрд╛рдмрджрд╛рд░, рдмрджрд▓рд╛рдпрд▓рд╛ рдЕрд╡рдШрдб.
- Ce, efferent coupling (fan-out) тАФ component рдЪреНрдпрд╛ рдЖрддрд▓реЗ рдХрд┐рддреА modules рдмрд╛рд╣реЗрд░рдЪреЗ рдХрд╛рд╣реАрддрд░реА import рдХрд░рддрд╛рдд. рдЬрд╛рд╕реНрдд Ce = рддреЗ рдЦреВрдк рдЧреЛрд╖реНрдЯреАрдВрд╡рд░ рдЕрд╡рд▓рдВрдмреВрди = рд╕рд╣рдЬ рдбрд│рдорд│реАрдд.
- Instability I = Ce / (Ca + Ce) тАФ 0 рдореНрд╣рдгрдЬреЗ рдЬрд╛рд╕реНрддреАрдд рдЬрд╛рд╕реНрдд рд╕реНрдерд┐рд░ (рдлрдХреНрдд рдЗрддрд░ рддреНрдпрд╛рд╡рд░ рдЕрд╡рд▓рдВрдмреВрди), 1 рдореНрд╣рдгрдЬреЗ рдЬрд╛рд╕реНрддреАрдд рдЬрд╛рд╕реНрдд рдЕрд╕реНрдерд┐рд░ (рдлрдХреНрдд рддреЗрдЪ рдЗрддрд░рд╛рдВрд╡рд░ рдЕрд╡рд▓рдВрдмреВрди). Stable Dependencies Principle: рд╕реНрдерд┐рд░рддреЗрдЪреНрдпрд╛ рджрд┐рд╢реЗрдиреЗ (рдХрдореА I рдХрдбреЗ) рдЕрд╡рд▓рдВрдмреВрди рд░рд╛рд╣рд╛.
- Abstractness A тАФ component рдордзреАрд▓ abstract classes ├╖ рд╕рдЧрд│реЗ classes. Lab рдПрдЦрд╛рджрд╛ class
abstract рдорд╛рдирддреЛ рдЬрд░ рддреЛ
ABCрдХрд┐рдВрд╡рд╛ProtocolрдЪрд╛ subclass рдЕрд╕реЗрд▓ рдХрд┐рдВрд╡рд╛ рддреНрдпрд╛рдд@abstractmethodрдЕрд╕реЗрд▓. - Distance D = |A + I тИТ 1| тАФ component "main sequence" рдкрд╛рд╕реВрди рдХрд┐рддреА рджреВрд░ рдЖрд╣реЗ, рдЬрд┐рдереЗ рд╕реНрдерд┐рд░ components abstract рдЖрдгрд┐ рдЕрд╕реНрдерд┐рд░ components concrete рдЕрд╕рддрд╛рдд. A=0, I=0 рд▓рд╛ D рдЬрд╡рд│рдкрд╛рд╕ 1 рдореНрд╣рдгрдЬреЗ "zone of pain" (рд╕реНрдерд┐рд░ рдЖрдгрд┐ concrete: рдХрдбрдХ). D рд╣рд╛ рдЗрд╢рд╛рд░рд╛ рдЖрд╣реЗ, рдЧреБрдг рдирд╡реНрд╣реЗ: рдХреНрд╡рдЪрд┐рддрдЪ рдмрджрд▓рдгрд╛рд░рд╛ рд╕реНрдерд┐рд░ concrete code (рдПрдЦрд╛рджрд╛ date helper) рддрд┐рдереЗ рдЕрд╕рд▓рд╛ рддрд░реА рдЪрд╛рд▓рддреЛ.
- Relational cohesion H = (R + 1) / N тАФ component рдЪреНрдпрд╛ рдЖрддрд▓реНрдпрд╛ R рдорд╛рд░реНрдЧрд┐рдХрд╛, N modules (NDepend рд╡рд╛рдкрд░рддреЗ рддреЗ рд╕реВрддреНрд░). рдХрдореА H рдореНрд╣рдгрдЬреЗ component рдордзрд▓реЗ modules рдПрдХрдореЗрдХрд╛рдВрдирд╛ рдЬрд╡рд│рдкрд╛рд╕ рд╡рд╛рдкрд░рддрдЪ рдирд╛рд╣реАрдд тАФ рддреЗ рдХрджрд╛рдЪрд┐рдд рджреБрд╕рд░реАрдХрдбреЗ рдЕрд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗрдд.
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг "coupling рдХрдореА, cohesion рдЬрд╛рд╕реНрдд рдареЗрд╡рд╛" рд╣рд╛ рд╕рд▓реНрд▓рд╛ рд╕рдЧрд│реНрдпрд╛рдВрдирд╛ рдорд╛рдиреНрдп рдЕрд╕рддреЛ рдЖрдгрд┐ рдХреЛрдгреАрдЪ рддрдкрд╛рд╕реВ рд╢рдХрдд рдирд╛рд╣реА. рдЖрдХрдбреЗ рддреЛ рддрдкрд╛рд╕рдгреНрдпрд╛рдЬреЛрдЧрд╛ рдХрд░рддрд╛рдд. рдПрдЦрд╛рджрд╛ рд╕реНрдерд┐рд░ component (рдХрдореА I) рдЕрд╕реНрдерд┐рд░ component import рдХрд░рдд рдЕрд╕реЗрд▓ рддрд░ рддреЛ Stable Dependencies Principle рдореЛрдбрддреЛ: рдЬреНрдпрд╛ рдЧреЛрд╖реНрдЯреАрд╡рд░ рд╕рдЧрд│реЗ рдЯреЗрдХрддрд╛рдд, рддреА рдЖрддрд╛ рд╡рд╛рд░рдВрд╡рд╛рд░ рдмрджрд▓рдгрд╛рд▒реНрдпрд╛ рдЧреЛрд╖реНрдЯреАрд╡рд░ рдЯреЗрдХрддреЗ. рддреБрдореНрд╣реА рддреЗ рдкрд╛рд╣реВ рд╢рдХрддрд╛, рддреНрдпрд╛рдЪрд╛ рдХрд▓ рдкрд╛рд╣реВ рд╢рдХрддрд╛, рдЖрдгрд┐ тАФ рдзрдбрд╛ 09 рдордзреНрдпреЗ тАФ рддреНрдпрд╛рд╡рд░ build fail рдХрд░реВ рд╢рдХрддрд╛.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
arch/analyze.py рдордзреАрд▓ coupling(g, classes) рдЦреЛрд▓реНрдпрд╛рдВрдирд╛ floor(m)
(рдирд╛рд╡рд╛рдЪрд╛ рдкрд╣рд┐рд▓рд╛ рднрд╛рдЧ) рдиреБрд╕рд╛рд░ рдЧрдЯрд╛рдд рдЯрд╛рдХрддреЛ рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ рдордЬрд▓реНрдпрд╛рд╕рд╛рдареА рдореЛрдЬрддреЛ: N, R, H, Ca, Ce, I,
A рдЖрдгрд┐ D. scan() рдкреНрд░рддреНрдпреЗрдХ module рдЪреЗ classes рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ class abstract рдЖрд╣реЗ рдХрд╛ (рддреНрдпрд╛рдЪреЗ bases
рдЖрдгрд┐ decorators, ast рдиреЗ рд╡рд╛рдЪреВрди) рдиреЛрдВрджрд╡рддреЛ. apply(g, remove=тАж) рдХрд╛рд╣реА рдорд╛рд░реНрдЧрд┐рдХрд╛ рдХрд╛рдвреВрди graph рдЪреА
copy рдмрдирд╡рддреЛ, рдореНрд╣рдгрдЬреЗ files рд▓рд╛ рд╣рд╛рдд рди рд▓рд╛рд╡рддрд╛ рддреБрдореНрд╣реА рдПрдЦрд╛рджрд╛ fix рдХрд░реВрди рдкрд╛рд╣реВ рд╢рдХрддрд╛.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 arch/demo.py modularity
python3 - <<'EOF'
import sys; sys.path.insert(0, "arch"); from analyze import scan, edges, floor, coupling, apply
cb = scan(); g = cb.imports
ca = sorted({a for a, b in edges(g) if floor(a) != "domain" and floor(b) == "domain"})
ce = sorted({a for a, b in edges(g) if floor(a) == "domain" and floor(b) != "domain"})
print("Ca (outside rooms that import domain):", ca)
print("Ce (domain rooms that import outside):", ce)
print(f"I = {len(ce)} / ({len(ca)} + {len(ce)}) = {len(ce) / (len(ca) + len(ce)):.2f}")
clean = apply(g, remove=[("domain.grades", "infra.db"), ("domain.timetable", "web.format")])
m = coupling(clean, cb.classes)["domain"]
print(f"without the 2 outward corridors: Ce={m['ce']} I={m['i']:.2f} A={m['a']:.2f} D={m['d']:.2f}")
EOF
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
modularity рд╣реЗ рдЫрд╛рдкрддреЛ:
тФАтФА per floor (component): N rooms, R corridors inside, H = (R+1)/N, Ca in, Ce out, I = Ce/(Ca+Ce), A abstract, D = |A+I-1|
app N=3 R=0 H=0.33 ┬╖ Ca=2 Ce=3 I=0.60 ┬╖ A=0.00 D=0.40
domain N=5 R=2 H=0.60 ┬╖ Ca=5 Ce=2 I=0.29 ┬╖ A=0.33 D=0.38
infra N=2 R=0 H=0.50 ┬╖ Ca=3 Ce=2 I=0.40 ┬╖ A=0.00 D=0.60
main N=1 R=0 H=1.00 ┬╖ Ca=0 Ce=1 I=1.00 ┬╖ A=0.00 D=0.00
web N=2 R=1 H=1.00 ┬╖ Ca=2 Ce=1 I=0.33 ┬╖ A=0.00 D=0.67
рддреБрдордЪрд╛ snippet рд╣реЗ рдЫрд╛рдкрддреЛ:
Ca (outside rooms that import domain): ['app.enrol', 'app.fees_service', 'app.report_card', 'infra.db', 'infra.email']
Ce (domain rooms that import outside): ['domain.grades', 'domain.timetable']
I = 2 / (5 + 2) = 0.29
without the 2 outward corridors: Ce=0 I=0.00 A=0.33 D=0.67
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
Domain рдордЬрд▓реНрдпрд╛рд╡рд░ рд╕рдЧрд│реЗ рдЯреЗрдХрддрд╛рдд (Ca = 5) тАФ рдореНрд╣рдгреВрди рддреЛ рд╕рдЧрд│реНрдпрд╛рдд рд╕реНрдерд┐рд░ рдЕрд╕рд╛рдпрд▓рд╛ рд╣рд╡рд╛. рджреЛрди
рдорд╛рд░реНрдЧрд┐рдХрд╛ рд╣реЗ рдмрд┐рдШрдбрд╡рддрд╛рдд: domain.grades тЖТ infra.db рдЖрдгрд┐ domain.timetable тЖТ web.format. рддреНрдпрд╛
рдХрд╛рдврд▓реНрдпрд╛ рдХреА domain рдЪреА instability 0.29 рд╡рд░реВрди 0.00 рд╡рд░ рдпреЗрддреЗ. D рдЪреЗ рдХрд╛рдп рдЭрд╛рд▓реЗ рддреЗ рдкрд╛рд╣рд╛: рддреЛ
0.38 рд╡рд░реВрди 0.67 рд╡рд░, рд╡рд░ рдЧреЗрд▓рд╛, рдХрд╛рд░рдг domain рдЖрддрд╛ рдкреВрд░реНрдг рд╕реНрдерд┐рд░ рдЖрд╣реЗ рдкрдг рдлрдХреНрдд рдПрдХ рддреГрддреАрдпрд╛рдВрд╢ abstract.
рдореНрд╣рдгреВрдирдЪ D рд╣рд╛ рдЗрд╢рд╛рд░рд╛ рдЖрд╣реЗ: рдЗрдереЗ fix рдмрд░реЛрдмрд░ рдЖрд╣реЗ, рдЖрдгрд┐ D "рд╕реНрдерд┐рд░ рдЖрдгрд┐ concrete" рдореНрд╣рдгрддреЛ тАФ рдЬреЗ рдлрдХреНрдд
рд╢рд╛рд│реЗрдЪреЗ рдирд┐рдпрдо рдмрджрд▓рд▓реЗ рддрд░рдЪ рдмрджрд▓рдгрд╛рд▒реНрдпрд╛ business rules рд╕рд╛рдареА рд╕рд╛рдорд╛рдиреНрдп рдЖрд╣реЗ. app рдордЬрд▓реНрдпрд╛рдЪрд╛ H = 0.33 рдЖрд╣реЗ:
рддреНрдпрд╛рдЪреНрдпрд╛ рддреАрди рдЦреЛрд▓реНрдпрд╛ рдПрдХрдореЗрдХрд╛рдВрдирд╛ рдХрдзреАрдЪ import рдХрд░рдд рдирд╛рд╣реАрдд. рдордЬрд▓рд╛ рдЦреЛрд▓реНрдпрд╛рдВрдирд╛ рдкреНрд░рдХрд╛рд░рд╛рдиреБрд╕рд╛рд░ рдЧрдЯрд╛рдд
рдЯрд╛рдХрддреЛ, рдХрд╛рдорд╛рдиреБрд╕рд╛рд░ рдирд╡реНрд╣реЗ тАФ рдзрдбрд╛ 05 рддреНрдпрд╛рдВрдирд╛ рддреНрдпрд╛рдРрд╡рдЬреА рд╡рд┐рднрд╛рдЧрд╛рдиреБрд╕рд╛рд░ рдЧрдЯрд╛рдд рдЯрд╛рдХрддреЛ.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- рд╕рдЧрд│реЗ import рдХрд░рддрд╛рдд рдЕрд╕реЗ
utilsрдХрд┐рдВрд╡рд╛commonmodule тАФ рдкреНрд░рдЪрдВрдб Ca рдЕрд╕рд▓реЗрд▓реЗ coincidental cohesion - metric рд╡рд╛рдЪрдгреНрдпрд╛рдРрд╡рдЬреА рддреЛ optimise рдХрд░рдгреЗ (рдлрдХреНрдд Ce рдХрдореА рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА module рддреЛрдбрдгреЗ)
- рд╕реНрдерд┐рд░, рдЦреВрдк рд╡рд╛рдкрд░рд▓рд╛ рдЬрд╛рдгрд╛рд░рд╛ component рдПрдЦрд╛рджрд╛ рдЕрд╕реНрдерд┐рд░ component import рдХрд░рддреЛ ("рд╕реНрдерд┐рд░рддреЗрдЪреНрдпрд╛ рджрд┐рд╢реЗрдиреЗ рдЕрд╡рд▓рдВрдмреВрди рд░рд╛рд╣рд╛" рдореЛрдбрддреЛ)
- рдлрдХреНрдд рдереЗрдЯ imports рдореЛрдЬрдгреЗ рдЖрдгрд┐ рд▓рд╛рдВрдм рд╕рд╛рдЦрд│реНрдпрд╛ рдЪреБрдХрд╡рдгреЗ (рдзрдбрд╛ 01 рдЪрд╛ blast radius)
- tools classes, modules рдХреА packages рдореЛрдЬрддрд╛рдд рд╣реЗ рди рддрдкрд╛рд╕рддрд╛ рддреНрдпрд╛рдВрдЪреЗ рдЖрдХрдбреЗ рдПрдХрдореЗрдХрд╛рдВрд╢реА рддреБрд▓рдирд╛ рдХрд░рдгреЗ
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
On a real project тАФ рд╣реЗ рдЖрдХрдбреЗ рдХрд╛рдврдгрд╛рд░реА tools:
- JDepend (Java) рдкреНрд░рддреНрдпреЗрдХ package рд╕рд╛рдареА Ca, Ce, A, I рдЖрдгрд┐ D рджреЗрддреЛ тАФ рд╣реЗрдЪ metrics.
- NDepend (.NET) рддреЗ рдкреНрд░рддреНрдпреЗрдХ assembly рд╕рд╛рдареА рджреЗрддреЛ, рдЖрдгрд┐ relational cohesion рд╣реА.
- pydeps (Python) import graph рдХрд╛рдврддреЛ:
pip install pydeps && pydeps yourapp --max-bacon 2. - import-linter (Python) metrics рдореЛрдЬрдд рдирд╛рд╣реА, рдкрдг рддреНрдпрд╛рдВрдЪреНрдпрд╛рд╡рд░реВрди рддреБрдореНрд╣реА рдард░рд╡рд▓реЗрд▓реЗ рдирд┐рдпрдо рд▓рд╛рдЧреВ рдХрд░рддреЛ (рдзрдбреЗ 03, 04 рдЖрдгрд┐ 09).
рдлрдХреНрдд standard library рд╡рд╛рдкрд░реВрди рдХреЛрдгрддреНрдпрд╛рд╣реА Python package рдЪрд╛ рдЭрдЯрдкрдЯ fan-in / fan-out count тАФ
arch/analyze.py рдиреЗрдордХреЗ рд╣реЗрдЪ рдХрд░рддреЛ тАФ scan() рддреБрдордЪреНрдпрд╛ рд╕реНрд╡рддрдГрдЪреНрдпрд╛ code рдХрдбреЗ рд╡рд│рд╡рд╛:
python3 -c 'import sys; sys.path.insert(0, "arch"); from analyze import scan, coupling
cb = scan("src", "yourapp"); print(coupling(cb.imports, cb.classes))'
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рдкреНрд░рддреНрдпреЗрдХ component рдЪреЗ I рдЖрдгрд┐ D CI рдордзреНрдпреЗ рдиреЛрдВрджрд╡рд╛ рдЖрдгрд┐ рддреНрдпрд╛рдВрдЪрд╛ рдЖрд▓реЗрдЦ рдХрд╛рдврд╛. рдЬреНрдпрд╛ component рдЪрд╛ fan-in рд╡рд╛рдврдд рдЕрд╕рддрд╛рдирд╛ instability рд╣рд│реВрд╣рд│реВ рд╡рд░ рдЪрдврддреЗ, рддреЛ рддреБрдордЪреНрдпрд╛ codebase рдЪрд╛ рдкреБрдврдЪрд╛ "рдХреЛрдгреА рд╣рд╛рдд рд▓рд╛рд╡рд╛рдпрдЪреА рд╣рд┐рдВрдордд рдХрд░рдд рдирд╛рд╣реА" рдЕрд╕рд╛ рднрд╛рдЧ рдЖрд╣реЗ.
тПня╕П рдкреБрдвреЗ
рдкреНрд░рддреНрдпреЗрдХ рдордЬрд▓реНрдпрд╛рдЪреЗ рдЖрдХрдбреЗ рдЙрдкрдпреЛрдЧреА рдЖрд╣реЗрдд. рдордЬрд▓реНрдпрд╛рдВрдмрджреНрджрд▓рдЪрд╛ рдирд┐рдпрдо рдЕрдзрд┐рдХ рдЪрд╛рдВрдЧрд▓рд╛: рдХреЛрдгрддрд╛ рдордЬрд▓рд╛ рдХреЛрдгрд╛рд▓рд╛ call рдХрд░реВ рд╢рдХрддреЛ? Layers рдЖрдгрд┐ dependency rule.
git checkout lesson-03-layers