Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Concrete Programming

Simon Pai
February 20, 2014

Concrete Programming

Simon Pai

February 20, 2014
Tweet

More Decks by Simon Pai

Other Decks in Programming

Transcript

  1. Concrete Programming A set of front-end architectural guidelines that focuses

    on defining solid-meaning modules. It was developed and used throughout the front-end section of our new product, Quire.
  2. Table of Contents Zone of Concern Data Flow Analysis Semantic

    Analysis Asynchrony Analysis Standard Sections
  3. Standalone Model onClick Update DOM Component Model onChange listen listen

    Model is standalone and doesn’t know Component plus() user call
  4. Component onClick Update DOM Component Model onChange listen listen Model

    is standalone and doesn’t know Component Actuators Receptors plus() user call
  5. Data Flow A onClick Update DOM Component Model onChange listen

    listen (Source) (Sink) plus() user call
  6. Data Flow B onClick Update DOM Component Model onChange listen

    listen (Source) (Sink) plus() user call
  7. Dependency onClick Update DOM Component Model onChange listen listen Component

    knows DOM and Model DOM and Model are standalone plus() user call
  8. Zone of Concern ZoC is all the relevant parts in

    your project when you fix a bug or add a new feature. The larger ZoC is, the more things you need to keep in mind, and the harder to maintain.
  9. Zone of Concern ZoC is not fixed throughout development. For

    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.
  10. Zone of Concern Maintanence cost = Cost of ZoC reduction

    + Cost to solve the problem under final ZoC.
  11. Zone of Concern The lower bound of total complexity of

    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.
  12. Zone of Concern DRY (Don’t Repeat Yourself), MV*, TDD (Test

    Driven Development), profiling, etc. Concrete Programming, like many architectural techniques, is about minimizing the size of final ZoC, and/or speeding up ZoC reduction.
  13. Data Flow Data flow refers to how threads travel in

    your software. (This idea is constantly mentioned in Reactive Programming.)
  14. The Example, Flow A onClick Update DOM Component Model onChange

    listen listen (Source) (Sink) plus() user call
  15. The Example, Flow B onClick Update DOM Component Model onChange

    listen listen (Source) (Sink) plus() user call
  16. Solution: Judge by Value (Only work when function A is

    idempotent.) Skip when new value is equal to old value. A B
  17. Solution: Judge by Source A B S1 S1 S1 Skip

    when source comes from itself. Attach a data flow source token and pass it around.
  18. Bad Smell: Diamond Pattern A B C D When A

    is called, should D be called twice? (The answer depends on your spec, but let’s discuss the ‘NO’ scenario.)
  19. Solution: Judge by Value A B C D (Only work

    when function D is idempotent.) Skip when new value is equal to old value.
  20. Solution: Judge by Event A B C D Attach an

    event token and pass it around. Skip calls with duplicated event token. E1 E1 E1 E1 E1
  21. Simple Data Flow When a data flow contains no echo

    or diamond pattern, we call it a simple data flow. Simple data flows are easy to maintain due to its DRY (Don’t Repeat Yourself) property.
  22. Upstream, Midstream, Downstream A simple data flow can usually be

    organized to 3 parts: upstream, midstream, downstream.
  23. Upstream, Midstream, Downstream Upstream Mostly receptors (user event listening) Midstream

    Business logic, talking to server, heavy algorithm Downstream Mostly actuators (UI update)
  24. Upstream, Midstream, Downstream onClick Update DOM Component Model onChange listen

    listen (Source) (Sink) Upstream Downstream Midstream plus() user call Actuators Receptors
  25. Module A module is an encapsulated unit in a project.

    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.
  26. Dependency Planning Design your module dependencies according to their semantics.

    Think about “who should know what.” A proper limitation on module knowledge and solid module semantics greatly reduce ZoC.
  27. Cyclic Dependency Cyclic dependencies are not necessarily bad. However, removing

    cycles in dependency graph often leads to a better architecture. Dependencies can be easily manipulated with the help of observer pattern.
  28. Cyclic Dependency A B When A has a problem, you

    need to concern A & B. When B has a problem, vice versa.
  29. Observer Pattern A B In the graph, we use dotted

    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.
  30. Non-cyclic Dependency A B When B has a problem, you

    only need to check B itself. When A has a problem, still need to check both, but you can divide and conquer more easily.
  31. Which Side to Go? A B How do I know

    which dependency I should invert? Doesn’t matter. It depends on their semantics, up to your call.
  32. A Reminder Design your module dependencies primarily according to their

    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.)
  33. Introducing... Introducer Question: suppose A holds a reference of B,

    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.
  34. Middleman Pattern Sometimes two modules A and B are loosely

    connected (in data flow) and they don’t really need to know each other (by semantics). Consider to turn their introducer C into a middleman.
  35. Middleman Pattern A B This removes the dependency of A

    on B. C C still knows A & B, but A doesn’t know B anymore.
  36. Discontinuous Data Flow In JS or Dart, data flow can

    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; });
  37. Segments & Gaps A data flow with asynchronous calls are

    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; });
  38. Segments & Gaps Of course, many things can happen across

    a gap. A B Δ this.x = 0; setTimeout(function () { this.y = this.x; }); still 0?
  39. Temporal State Your application is a giant state machine. It

    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.
  40. Temporal State However, in the middle of the flow, if

    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.
  41. Detect Threats Mark synchrony gaps on the data flow graph.

    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.”
  42. Guard against Them When you find a potential temporal state...

    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.
  43. Guard against Them When you find a potential temporal state...

    3. Pessimistically, lock relevant assets to block access by other units. 4. Or, optimistically, figure out a way to tolerate and recover from errors.
  44. Model Driven View Concrete Programming promotes Model Driven View (MDV).

    “View update is just a side effect of model change.” -- AngularJS
  45. Another Perspective: MVN M-V-Nothing (MVN), unlike other MV*, is not

    a paradigm. It’s just an universal way to define Model and View.
  46. M-V-Nothing Model is a module which doesn’t know native UI

    (DOM), even transitively. View is a module which is not a Model. No other crap! Browser native UI excludes local storage, ajax, file upload, etc.
  47. M-V-Nothing The set of all Models is the largest section

    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.
  48. Standard Sections Models should include entire business logic. (But it

    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.
  49. Reasons: Dependency Models don’t know views. One-way dependency greatly reduces

    ZoC. You have a chance to test your business logic separately, without UI testing tools.
  50. Reasons: Dependency You would change UI logic all the time,

    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.
  51. Reasons: Data Flow Using standard sections, you can achieve simple

    data flow more easily. In data flow graph, models will be at midstreams, while views are at upstreams/downstreams.
  52. Reasons: Asynchrony Models are views have different types of asynchrony

    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.
  53. Conclusion 1. Understand the idea of ZoC (Zone of Concern).

    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.
  54. Conclusion 4. Apply semantic analysis. Review module semantics & knowledge.

    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.
  55. Priorities of Aspects Often you would run into design choices

    among the previously mentioned aspects. It is your own call to determine which is more important. Anyway, in General, Semantics > Data Flow > Asynchrony > Dependency
  56. Priorities of Sections Code at hot spots should be treated

    much more carefully, compared to those at terminal places. As a result, priorities are: Model >> View Midstream >> Upstream/Downstream