example, when you begin a bug fix, you may first identify the cause by narrowing down possible area of defect, which effectively reduces ZoC, from an initial ZoC.
your project is determined by the spec. There is little space to improve total complexity, unless your original implementation really suck. But you have chances to minimize the complexity of final ZoC.
Driven Development), profiling, etc. Concrete Programming, like many architectural techniques, is about minimizing the size of final ZoC, and/or speeding up ZoC reduction.
Each module has its own meaning, responsibility, assumption, and knowledge. Knowledge of a module refers to what it knows, usually in the form of dependencies.
lines to denote observer pattern. We keep the arrow head direction consistent with data flow. In the case of dotted lines, dependency direction is reverted.
semantics. Go easy with cycle removal. It is a tool to help you set up better semantics. (After all, dependency direction is not a syntactic property anyway.)
how does A get the reference in the first place? 1. A created B. 2. A learnt it from someone else it knows (or global). 3. Some C passed it to A. In the last case, we say C introduce B to A, and C is the introducer of B to A.
be discontinuous. setTimeout() or Promise/Future, in either form, the callback is executed in another event loop. A B Δ We can denote an asynchronous call like this. this.x = 0; setTimeout(function () { this.y = this.x; });
cut into synchronous segments, and the cuts are called (synchrony) gaps. A B Δ synchronous segments gap this.x = 0; setTimeout(function () { this.y = this.x; });
starts at a correct state. Then a user triggers a data flow; many functions are executed, and many variables are changed along the flow. At the end of the flow, the machine stops at another correct state.
an atomic operation is separated by a gap, there could exist a short period in runtime where the machine is at a wrong, temporal state. A B Δ operationA(); setTimeout(function () { operationB(); }); A & B should either both happen, or both not happen.
Whenever you see a gap, check the connection of the operations on the two sides to decide whether the gap introduces a temporal state. “This will help you capture bugs even before you start writing the code.”
1. You are lucky. Issues are natually avoided. (but may appear upon changes of assumptions) 2. Try to eliminate it by changing things around the gap, or just remove the gap if possible.
in the system which doesn’t involve native UI. In Concrete Programming, we recommend to make this section large enough to hold the whole business logic of your application.
doesn’t need to be 100% precise.) Views will be rather simple, mostly receptors, actuators, and delegations. Models are considered more important. Keep models as solid/maintainable as possible.
but business logic is rather stable. If you keep the models very solid, it will be very easy to overhaul views. You will have a chance to wire up different UI.
in general: in models there are ajax calls, file uploads; in views there are animations. Keeping models and views separated naturally reduces the amount of temporal states. With one-way dependency, it also means models are kept away from view-specific asynchrony.
2. Design in standard sections: Models & Views. Models should include entire business logic. Models should be solid, secure, maintainable. 3. Apply data flow analysis. Remove echo & diamond patterns if possible.
Remove cyclic dependency if necessary. Remove extra dependency with middleman. 5. Apply asynchrony analysis. Go through each synchrony gap, find out potential temporal states, and handle them.
among the previously mentioned aspects. It is your own call to determine which is more important. Anyway, in General, Semantics > Data Flow > Asynchrony > Dependency