-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathmodularity.theory.txt
132 lines (109 loc) · 9 KB
/
modularity.theory.txt
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
┏━━━━━━━━━━━━━━━━┓
┃ MODULARITY ┃
┗━━━━━━━━━━━━━━━━┛
MODULARITY ==> #Dividing into different modules, aiming at orthogonality/separation of concern:
# - between modules: granularity, loose coupling
# - inside each module: high cohesion, single responsibility
#Goal is to improve maintainability by reducing incoherence inside each part:
# - move complexity from within each part to in-between
# - i.e. more maintainable inside each part, but less maintainable as a whole
#Need balance between:
# - providing isolation (i.e. simplicity to think of each module)
# - avoiding too high granularity (i.e. must think of several modules at once)
#Usually:
# - negative impact on flexibility (not extensibility) and efficiency (i.e. UX)
# - coupled with abstraction
MODULAR PROGRAMMING ==> #Features of a language allowing modularity, e.g. Python packages
┌─────────────────┐
│ GRANULARITY │
└─────────────────┘
GRANULARITY ==> #Dividing code into different pieces (modules|packages|components|units)
#Can be: blocks, functions, namespaces, files, directories
#Opposite is monolithic design.
FUNCTIONAL DECOMPOSITION ==> #Antipattern: too much granularity with OOP
#I.e. many too small classes (e.g. single-method)
THE BLOB / GOD CLASS / WINNEBAGO #Antipattern: piece of logic too big, i.e. lack of granularity
==> #Often also hints at high coupling
#"Bloaters" are code smells for it:
# - large method|class
# - long|complex parameters list
┌──────────────┐
│ COUPLING │
└──────────────┘
LOOSE|LOW COUPLING ==> #Also called "law of Demeter", "principle of least knowledge"
#Minimizing knowledge|contract between modules
#I.e. inheritance < composition < aggregation < association
HELPER/UTILITY ==> #Module that is not linked to the core business logic
#Helpers are stateful (e.g. object instances), utility are stateless|pure
CHAIN OF RESPONSABILITY PATTERN #Decoupling modules with different purpose but same input:
==> # - by defining shared interface to process that input, e.g. MODULE.process(INPUT)
#Sequence order can be maintained by (from simplest to most flexible):
# - container (e.g. array order)
# - items, i.e. each module point to:
# - 1 next module
# - 0-1 next module, i.e. can stop sequence
# - 0|1-n next modules ("dispatcher")
#Modules can be excluded from the sequence, according to input properties (e.g. its type)
MEDIATOR ==> #Abstracting away relations between items when they are too complex, e.g.:
# - n-n relationship with high n
# - many types of items
# - complex interaction
#I.e.:
# - instead of items referencing each other
# - let a shared "mediator" reference all
#Items can use mediator to either:
# - broadcast: no specific target
# - or reference target, with a key (not actual object)
#Mediator can:
# - do simple retrievals
# - or more complex, e.g. book-keeping
#Goal: promoting loose coupling
EVENTS/HOOKS ==> #Decoupling:
# - subject: [un]register callback for a specific event, and a specific observer
# - observer: notify subjects about an event (so callbacks are fired), optionally with parameters
#Alternative to waiting for return value, or providing callback as argument:
# - more abstract, less coupled
# - not coupled to a specific invokation
# - can abstract functional control (debounce, delay, once, etc.) into the event handling system
# - more flexible than callbacks, i.e. dynamic (add|remove)
#Can filter incoming events according to:
# - "topic-based": event name
# - "content-based": event parameters
#Must handle deregistering callbacks:
# - to avoid memory leaks ("lapsed listener problem")
# - can also hold weak references instead, allowing garbage collection
PUBLISH / SUBSCRIBE ==> #Also called "Pub/Sub"
#Like events, but using a mediator ("message broker") for event handling:
# - i.e. a single shared event emitter
# - might perform extra functions, e.g.: content|format transformation, aggregation|decomposition, logging, queuing, etc.
# - even more abstract and less coupled, but less flexible
MESSAGE ORIENTED MIDDLEWARE ==> #"MOM"
#Using message borkers in a Pub/Sub IPC system
#E.g. opposed to RPC where systems must directly interact with each other
MESSAGE QUEUE ==> #Using a queue between event emission and consumption
#Goal: abstract away sequencing between subject and observer
┌──────────────┐
│ COHESION │
└──────────────┘
COHESION ==> #How related are the parts of a module
#Cohesion reason is: technical < time < data < purpose, i.e. (from lowest to highest):
# - coincidental: none
# - logical: same technical nature (e.g. controllers, views)
# - temporal: happen together at a given time (e.g. init)
# - procedural: happen always after another
# - communicational/informational: same data
# - sequential: procedural + communicational, i.e. pipeline of input/output
# - functional: same purpose
OBJECT-ORIENTED PROGRAMMING ==> #See types doc
KITCHEN SINK ==> #Also called "swiss army knife"
#Antipattern: high flexibility of a module creating low cohesion
#I.e. trying to pack too many features/flexibility into one module
PRIMITIVE OBSESSION ==> #Adding information to a module that should instead be abstracted to its own module, because that information is very simple
#E.g. group of primitives
#Problem arise when more information is added
#A lot of constants in a module can be a code smell for this
┌────────────────┐
│ SIMPLICITY │
└────────────────┘
SINGLE RESPONSIBILITY ==> #A module must have a single responsibility (i.e. "reason to change")
#"S" of SOLID principles