1 Agile has long shunned up-front design. When Agilists force themselves to do up-front work, it usually is limited to a symbolic use of User Stories for requirements and metaphor for architecture, with much of the rest left to refactoring. Experience and formal studies have shown that incremental approaches Lean Architecture for to architecture can possibly lead to poor structure in the long term. This talk shows how to use domain analysis in a Lean way to build an architecture of form that avoids the mass of structure that usually Agile accompanies big up-front design, using only judicious documentation. It will also show how Development architecture can accommodate incremental addition of features using Trygve Reenskaug's new DCI (Data, Context and Interaction) approach, and how it maps elegantly onto C++ implementations. The Taking Architecture into the talk is based on the forthcoming Wiley book of the same title. Agile World 7 Platform hours (9:00 - 16:00), 82 Slides. James O. Coplien Gertrud&Cope, Mørdrup, Denmark Copyright ©2010, ©2011, ©2012, ©2013, ©2014, ©2015 James O. Coplien. All rights reserved. No Scrum Foundation portions of this material may be reproduced or redistributed in any form without prior written permission from James O. Coplien. In general you will find that I am generous about giving permission for use of these materials at no charge as long as the source is acknowledged.

2 In this course you will learn Lean architecture — not just as a pop phrase, but in terms of the Seminar Objectives grounding of the term "Lean" in the principles of the Toyota Way. You will lean the importance of mental models in , particularly as the concept underlies the Model-View-Controller architecture that has been the foundation of most interactive programs since the 1980s. You will learn • To be able to apply Lean principles of the basics and several advanced concepts of the DCI (Data-Collaboration-Interaction) architecture. domain architecture • To learn about the place of mental models in architecture • NOTE: This is a seminar, not a tutorial

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 3 Here is an outline for the day. Outline

I. Definitions: Lean, Agile, Architecture... 4–7 II. The Agile Architecture Allergy 8–15 III. Mental Models & MVC 16–20 IV. More than that: Overall form 21–23 V. What the System Is, ABCs, Dictionary 24–36 VI. What-the-system-Does 37–38 VII. The OO Crisis and DCI 41–48 VIII. Roles and DCI Implementation 49–63 IX. DCI Advantages 65–66 X. The Process 67–73 XI. Advanced Topics (time permitting) 74–81 XII. Conclusion 82–84

4 Lean is a complicated framework of values and practices that has been proven in building complicated I. What is Lean? systems. It has been refined by Toyota in Japan and has spread to other companies like Canon and Honda in Japan. It is the main foundation of the Scrum production framework.

! A collection of principles and approaches A comprehensive treatment of Lean would be impossible here, and the concept is difficult for the – Value Stream Western world. Here, we list some of the popular trappings of Lean as understood in the West. – Reducing waste (time, material) – Reducing inconsistency (with communication) The goals are reduced waste and higher value. – Reducing unevenness (planning & process) – Up-front planning – Single-piece continuous flow – Reduce inventory – Kaizen ! Results in – Reduced inventory – Reduced waste – Higher Value

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 5 In this course, by the term "Agile" we mean it as defined by the Agile Manifesto, above. What is Agile?

We are uncovering better ways of developing software by doing it and helping others do it. Through this work we have come to value: – Individuals and interactions over processes and tools – Working software over comprehensive documentation – Customer collaboration over contract negotiation – Responding to change over following a plan That is, while there is value in the items on the right, we value the items on the left more.

• Kent Beck • James Grenning • Robert Cecil Martin • Mike Beedle • Jim Highsmith • Steve Mellor • Arie van Bennekun • Andrew Hunt • Ken Schwaber • Alistair Cockburn • Ron Jefries • Jef Sutherland • Ward Cunningham • Jon Kern • Dave Thomas • Martin Fowler • Brian Marick

© 2001, the above authors this declaration may be freely copied in any form,

but only in its entirety through this notice.

6 This is a seminar about Lean and Agile architecture. What is architecture? Throughout the ages and even in the field of building construction, architecture has always been about form. Form is the What is Architecture? essence of structure. The word in English for a piece of material, into which molten metal or plastic are poured or injected to make a new something, is called a form. We focus on form because if we look at ! Architecture is the essence of structure: form structure, it actually makes it difficult to understand the essence by adding a lot of detail which is – Structure obfuscates form! irrelevant early in design. ! Lean architecture: just-in-time delivery of functionality, just-in-time pouring material into What, then, is Lean Architecture? The principles of Lean include just-in-time delivery, careful the forms organization, up-front planning, avoiding waste, and overall consistency. Architecture is in principle – Reduces long-term cost – Increases harmony: remove muri about consistency. If we have a consistent system early on that is stable over time, it avoids rework ! Agile architecture: one that supports change, and waste. That takes up-front planning and careful organization. That in place, we have a guide — a end-user interaction, discovery, and ease of form — into which we can write code when the need comes along. comprehension (of functionality) – Rapid delivery A good architecture supports Agile development. A good architecture is Agile if it supports change and – Increased revenues has just enough documentation to do the job — the documentation that really makes a difference. Good architecture supports the Agile values: support for change, a good model that supports the end user’s mental model of the system and that helps the developer’s discovery process. Here, we will focus on helping the developer reason about functionality in the code — functionality that reflects the end user wishes.

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 7 There are very few fundamental activities in software development; here they are. Analysis is about Architecture in the understanding the system, and is rather independent of the problems we want to solve. Problem Development Process definition sets the direction for design in the context of the analysis. Design solves the problem, and testing evaluates the degree to which we have solved the problem. We build a product called software,

Analysis and most of that is code. The software has a form that we call its architecture. Understanding the System Architecture

Design Solving the Problem(s) Code

Problem Definition Articulating the Problem(s)

Testing Did we solve the problem?

8 In an XP world, the air is full of singing User Stories and there is a beautiful and simple landscape. All II. YAGNI...? is well and the future looks bright.

User Stories

Tacit

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 9 The problem is that most of the system mass comes not from the explicit knowledge of system II. YAGNI...? functionality, but from the tacit knowledge about the form of the implementation and of the assumptions behind its functioning. These are often the realm of architecture. We often call it domain knowledge.

Image by Ralph Clevenger, 1999. User Stories

Tacit Knowledge

10 Mads Thiessen of Nordija relates that his project failed to do an up-front architecture, and used YAGNI The Agile Allergy to techniques to create a set-top box architecture based on channel services. When the architecture had Architecture to be converted to accommodate video on demand, it required a major re-work of the interface code and business logic.

Marko Taipale of European Game and Entertainment Technology Ltd. Related (23 November, 2007, Helsinki, Finland) that they consciously started a project from scratch to use TDD to create an architecture — even though they thought they knew what the architecture would be. Six months later,

“Because we had no up- “We spent 6 months their effort proved their initial hunch to be correct. front architecture, we didn’t doing TDD and ended foresee the need for video- on-demand services and with the architecture we originally knew that

Long-term Cost Long-term incurred a great cost implementing it” — Mads we would get” — Thiessen, Nordija Marko Taipale, EGET

Architectural Effort

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 11 Test-driven development is a design technique, intended to replace big up-front design in XP. The Architecture driven by Tests? historic progression started with an article by Kent Beck [Bec1994] that described how had suffered because it lacked a testing culture, and the article proposed how to solve the problem with a test framework. That framework evolved into the form it took in an article joint with Eric Gamma in ! The XP approach: Test-Driven Design 1998, which today we know as jUnit. [BeGa1998] Test-first was part of XP in 1999 [Bec1999], and TDD – First, write the test; then run it; then write the techniques matured by 2002 [Bec2002]. code; then run the test again; “refactor” until it works The idea is that tests shape your architecture. That could be true in the days when function — which is – No code without a test first what tests are about — dominated system structure. That was true in the day of batch programming ! This worked fine in the days when the system shape followed the imperative flow and card readers. In today's Agile, interactive world, the system form is dominated by the data in the ! Today’s interactive systems are different, end user mental model. TDD is therefore unsuitable to Agile development. It is not helpful. It may even driven by user mental models / domain be harmful, as empirical studies suggest. knowledge . ! TDD is unsuitable for Agile development ! It is not helpful and is likely harmful

12 Even the strongest Agile advocates weigh in against TDD as the foundation of architecture. Uncle Bob weighs in

One of the more insidious and persistent myths of agile development is that up-front architecture and design are bad; that you should never spend time up front making architectural decisions. That instead you should evolve your architecture and design from nothing, one test-case at a time.

Pardon me, but that’s Horse Shit.

— The Scatology of Agile Architecture, http://blog.objectmentor.com/articles/2009/04/25/the-scatology-of-agile- architecture

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 13 We, instead, take a Lean approach to architecture. That means reducing waste—muda. Rework in A Lean approach production is waste (though some rework during planning adds value by reducing waste in production). We can count refactoring among such rework. Up-front planning can reduce this overall rework (see the upcoming slide from Barry Boehm). ! Reduce muda—waste Instead of deferring decisions (about form) we are going to embrace them early. Every time we defer a ! Rework in production is waste decision about form, it has repercussions. Planning reduces rework. The key is to find the balance. – Refactoring for architecture is rework – Instead, do up-front planning ! There is no time between the first responsible moment and the last responsible moment—it is just the responsible moment — Gertrud Bjørnvig ! Planning reduces rework

14 Lean has a concept called poka-yoke. It is a device that helps assembly line workers align parts in a Other learnings from Lean way that they cannot assemble them the wrong way. Architectural form is a framework that is a poka- yoke that both guides developers in the right direction and limits and localizes the rework if they do head in the wrong direction. ! Poka-yoke – A manufacturing guide that makes Lean also has a concept called one-piece continuous flow. Instead of having stovepipes with handoffs assembly fool-proof between stages, all team members work at one U-shaped table. Kanban is a failure mode that is ! Single-piece continuous flow necessary when physical constraints make it impossible to do single-piece continuous flow. – Instead of handoffs ! Essential documentation only We limit the amount of documentation. Many architecture efforts of the past have been documentation- focused. Software development is an oral culture, and written documentation has limited effectiveness. ! Pull decisions forward: Decision structure matrix We still use it in those places where it makes a difference. We pull decisions forward, lining up the decisions we anticipate having to make, without actually making the decisions. We align dependencies between decisions, and then push decisions forward as far as we can at any time, executing rapidly. Architecture helps structure those decisions.

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 15 The answer to the question: “How much architecture should I do?” should vary from organization to Effect of Size on Sweet Spots organization based on need. What drives such a need? Boehm [Boe2009] argues that code mass and the degree of assurance about stability are two of the major drivers. Figure 16 shows Boehm’s model of project cost as a function of architectural investment; it is a more elaborate version of the graph in Figure 15. The coordinate axis shows how much time needs to be added to the schedule for a given investment in architecture, while the ordinate access corresponds to the amount of architectural effort. Barry Boehm Too little architecture leads to rework and added effort; too much architecture causes architecture work and Richard Turner, itself to dominate the schedule. Balancing Agility and Discipline, Appendix E

16 Agile is all about people. We write software to support an end user, and their mental models are one of III. This is about something the foremost considerations behind good software. In fact, that is the whole foundation of object- deeper… orientation. We take their mental model of the things in their world into a implemented as objects. ! This is all about people We also take their mental model of activities in their world into use cases, which can be expressed as ! User needs are in two dimensions; they should be supported in collaborations between roles. Those roles are associated with objects through a run-time query. harmony: – Thinking We want to build our software on these models to make things easier for the programmer and to ! ➞ mental model ➞ data model ➞ objects ensure a better fit from end-user needs to the software. – Doing ! ➞ use case ➞ collaboration ➞ role ➞ query ➞ objects ! Programmer needs are similar

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 17 Instead, we strive to make the program form represent the form in the heads of the end user. This The Direct Manipulation metaphor provides the fixed point, and the end user is in charge. The end user has the illusion of directly manipulating the objects in the program — objects that appear on the screen, and which reflect the model in their heads. The computer becomes an extension of self. ! Adhering to the rule of least surprise ! Directly manipulating the objects in the program ! Original view of MVC – Now, Trygve says that an interface should give the illusion of this – In simple interfaces, avoid the illusion part—illusions are hard to do!

18 Switching gears a bit, let’s turn to objects. Object orientation is a way of taking about form. It’s not the Architecture and OO only way, but let’s start there. What is object orientation anyhow? Instead of starting with the tired old coupling-and-cohesion ! OO is a paradigm — a way of talking definitions (which apply equally well to modules or procedures) or polymorphism (even overloading is a about form form of polymorphism), let’s go to the goals of its originators. Dahl and Nygaard were striving to capture the end user’s mental model in the code. Good OO captures the objects that users know ! OO’s foundations: to capture the end user’s mental models in the code about. Most object-oriented programming languages uses classes as a kit for building objects; that is largely an issue of history, and comes from the fact that Dahl and Nygaard chose to base their ! OO captures simulation language in Algol. (Well, they were paid to write an Algol compiler and were allowed to build – The entities (objects) that users know about Simula into the product.) But the goal is still focused on the user and the user mental model. – The classes that serve as sets of such objects What is that model? The traditional OO view is that it’s all about getting the objects right.

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 19 A quick side note: One of the other people in the wings in the early days of OO was Trygve MVC: The Embodiment of the Reenskaug. Trygve was disenchanted with Simula because of its lack of encapsulation (it was difficult OO Vision to send a message to a receiver that you didn’t create) and with Smalltalk because of the domination of classes in the programming environment — when it should have been about objects.

! User model -> into the code -> In 1978 Trygve brought the user into the picture with a four-part pattern called Model-View-Controller- presented back mental computer User. Its first goal is to let users interact directly with the code that itself was desigend as a reflection of model data to the user their own mental models: that’s what View is for.. Its second goal was to allow the user to coordinate Model ! The goal of several simultaneous views of the same model; that’s what Controller is for — to create and coordinate views is direct User manipulation those views.

The goal of the mental model Controller computer controller is to data This, again, is based on the simple model that it is sufficient to model the end user’s notion of the 1 * coordinate Model system objects. * * multiple views User View

20 This is Model-View-Controller-User in a nutshell. The user wants directly to interact with the data in the Tools and MVC-U extension of his or her memory that lives in computer memory. Technology makes that difficult to do directly. So we need an impedance matcher: a tool that allows the end user to view and manipulate Model: computer data as though it were in his or her own memory. Views provide multiple ways for end users Business Logic to view and interpret domain data, and the Controller creates and coordinates views. View: and State

1st Qtr 2nd Qtr 3rd Qtr Gives user access4th Qtr to remote data

90

80

70

60

50 East 40 View West North 30

20

10

0 1st Qtr 2nd Qtr 3rd Qtr 4th Qtr Controller: Creates and Tool: Presents and Coordinates Edits Business Data Views

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 21 However, there is a half that is missing. Even in his early work Trygve started using roles. Roles were IV. Overall Form collections of responsibilities on objects that corresponded to the end user’s view of those objects. An object could fill many roles; any given role could be filled by a number of different objects. Note that roles are themselves one kind of form. These roles captured a bit of what-the-system-does, rather than ! The form of the business domain just what it is. This is the model that the end user cares about. Except for Trygve’s roles, this notion of – What the system is object-oriented modeling escaped the computing community for years, and in particular the – Domain model (as in MVC) programming language folks. – What the programmer cares about – Deliver as abstract base classes – Eric Evans’ Domain-Driven Design, In the mean time, object orientation inspired further work on the what-the-system-is part of form. Multi-Paradigm Design for C++ Model-View-Controller-User was a way to bring the what-the-system-is picture out to the user. It provided the programmer tools for organizing and coordinating the interaction between the graphical ! The form of the system interactions interface and the objects inside the program, though it did nothing to enforce that the objects should – What the system does – Role models: OORAM reflect the end-user mental model. – What the end user cares about – Has long eluded the OO crowd Over time, this same idea would appear in the analysis and design space (instead of the programming space) as domain engineering. Domain engineering is somewhat more general than OO in some respects and somewhat less general in others.

Multi-paradigm design was another stab at domain engineering. Early forms of Agile architecture started to advocate the use of abstract base classes (form) rather than classes (structure) as the basis for architecture. The GOF book also strongly advocated programming to interfaces, rather to code.

22 This approach leads to a fundamental architectural pattern called four-layer architecture. This is one The Fundamental Architecture good structure for a system with a humane interface that is attentive to user needs and activities. The Pattern architecture is driven not just by convenience or concerns such as reuse, but rather derives from an understanding of usability and business needs. Business objects increase

View opportunities for revenues, and the project can reduce costs by organizing around domain Business Business Object Object components. This is the architecture that supports MVC-U notions. Business 1 2

Domain Domain Domain Component 1 Component 2 Component 3

Domain

Domain Domain Domain Component 4 Component 5 Component 6

Common Logic Infrastructure

G&C Coplien — Agile Architecture

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 23 Sometimes, the user vision of the work to be done does not map from the domain model. Instead, we Tools / Business Objects need tools that capture that model. We also call these business models: models of the user conceptualization of the work flow. These tools are the points of integration across domain. For example: when working with a cutting machine that makes molds, you may have a tool that defines the • Tools are the emacs vi points of paths the cutting tool will take through the material. While using that tool you may need access to integration several domains: knowledge about the material consistency, knowledge of how the resulting part fits across domains LineTextBuffer CharTextBuffer into the entire production plan, and others. Tools allow a many-to-many mapping from the domain to • Tools reflect the SourceLine AsciiFile user perspectives. Kay Dynabook BinaryFile Record Multipane metaphor: a SimpleWindow Window truly personal Linux / Android / Symbian Infrastructure Each tool is like a personal computer customize to a task. Ideally, you should be able to create these computer • Reflect the user model of the on the fly as you tailor workflows and adapt to changing needs in the environment; more practically, workflow these tools are instead created to be general enough to adeptly cover a wide range of situations. • Should be easy to build: you often Knowledge of the use cases and their frequency of use will suggest the main tools. need new ones quickly • Can access multiple applications

24 The first step of any design is partioning. Partitioning is not abstraction, nor generalization, but is just V. What the system is classification. In the Agile interest of supporting the stakeholder mental model we stick to concepts that come from the stakeholders, mainly the end users, but also customers and administrators. We call

Domain 1 these domains.

System being Application This is analysis. Using objects or modules prejudices the model to take on a certain shape, and that Domain 2 Analysed Domain might discard important details of the design. Analysis Domain 3 Because it is a disjoint partitioning it can never be perfect. Many of the techniques for dealing with this • We understand it by partitioning it into domains overlap are beyond the scope of this course; however, the DCI architecture addresses many of them. – Not objects — that prejudices the implementation – Not modules — that is a design concern When doing this analysis, involve all the stakeholders. Everything matters—not just end users, and • Partitioning follows: certainly not just customers. Analyze to the boundaries of the business, because that is the simplest – Business intuition and history – The need for software families within the product thing that could possibly work. • The partitioning can never be perfect—more about that later • Involve all stakeholders from marketing to developers! • Analyze to the boundaries of the business

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 25 Here we show trivial examples of some domain decompositions. Consumer banking can be said to Examples comprise the domains of the actuarial world, where the actual account data reside. CRM is where we track accountholders and accounts. Products include accounts and financial instruments.

Actuarial The domains of text editing might include files, editing languages like emacs and vi, and different Consumer display technologies. CRM Banking Domains often characterize a family of products. The Products domain of Consumer Banking may include Savings Accounts, Checking Accounts, and others. Text editors may edit files in a number of Products different file formats or character sets, or support one or more of a family of editing languages. Files

Editing Text Editor Language

Displays

26 Exercise

! Discuss the main domains of your current product line

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 27 For each domain we want to find out how to reduce it to things we can build. We shape software using Structuring the domains paradigms, such as the object paradigm, procedural paradigm, and database paradigm. We analyze each domain to see what paradigm fits it best.

The most common paradigms for Agile programs are the object paradigm and the procedural System Domain paradigm. The object paradigm captures the domain structure (the Model of MVC) and the procedural being Analysed paradigm captures use cases.

• Do it for each domain • Domain Analysis versus Analysis – Analysis: understanding a system – Domain analysis: Understanding a topical area • Characterize the families of each domain using commonality analysis – Capture commonalities – Parameterize Variations

28 Exercise

! Enumerate the dominant design paradigms for each of your domains – object-orientation – database – rule-based – dataflow – procedural – state machine – generative programming

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 29 Often we’ll end up with an object (or, regrettably, a class) that has a mixture of domain behaviors and Old object-orientation, Part I end-user-work behaviors. The former we call domain behaviors, and the latter come from use cases. Domain behaviors change very slowly, while end user behaviors change rapidly.

In the naive object-oriented design of the 1980s we mixed both of these in the same interface. It caused some discomfort. However, if each use case behavior is encapsulated as an atomic operation, recolor • Domain methods and “use case” methods mixed in one then the object is the locus of everything that one needs to know to implement it well. rotate reSize interface • Different shear rates in one architectural unit The problem comes only if the interface has complex operations that cannot be understood locally, Shape • Can be O.K. — understanding an object locally is enough to because they in fact involve several objects. center understand a “use case” area method moveTo

30 So where do we start, if we want to do a Model-View-Controller-User architecture? The first step is at The First Deliverable: Abstract Base Classes the domain level. We divide the system into functions called domain services, sometimes called applications. In the above example of a milling system controller, these applications are project Business management, the design application, and numerical control data production. Objects / emacs vi Tools After dividing into these applications—which may be Use Case actors—the next step is to divide the system into objects. Objects should reflect the user’s mental model of the application. Resources, products and activities might be the objects of the above design for a milling system controller. CharTextBufferPointingDevice LineTextBufferKeyboard Domain Classes SourceLine Notice that the objects will indeed percolate into the user interface. But they are not the major facets BinaryFile AsciiFile Record either of the interface nor of the architecture: they are the atomic building blocks. Multipane Multipane SimpleWindow Window SimpleWindow Window

Linux / Android / Symbian Infrastructure

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 31 The first deliverable in Lean Architecture is in fact code. The code is very Lean: it compiles to zero Abstract Base Classes: Ruby bytes of object code. But it communicates the form of the system. This base class will be used for the domain classes like SavingsAccount and CheckingAccount.

class AccountWithPrintableBalance def initialize(balance); abort; end def availableBalance; abort; end def decreaseBalance(amount); abort; end def increaseBalance(amount); abort; end end

(dumb)

32 Here are the domain classes. We derive these accounts from the base that establishes the API to all Domain classes: Ruby accounts. Each one has a very simple interface and implementation. These implementations are very dumb. The intelligence will come later, injected from elsewhere. Those these classes are dumb, their objects will still be smart because of the injected intelligence. class SavingsAccount < class InvestmentAccount < AccountWithPrintableBalance AccountWithPrintableBalance def initialize(balance) . . . . end def initialize(balance) . . . . end def availableBalance . . . . end def availableBalance . . . . end def decreaseBalance(amount) .... end def increaseBalance(amount) . . . . def increaseBalance(amount) .... end end end def decreaseBalance(amount) . . . . end def dividend . . . . end end

(dumb)

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 33 Here is the base class that defines the type for the domain class role AccountWithPrintableBalance. Abstract base classes: C++ Using this abstract base class establishes an explicit architectural API for the domain class. We can create it even before creating the domain class, and then can provide the methods piecemeal in the domain class as needed.

class AccountWithPrintableBalance { public: AccountWithPrintableBalance(balance); virtual void printBalance(OutputDevice) const = 0; virtual Currency availableBalance(void) const = 0; virtual void decreaseBalance(Currency) = 0; virtual void increaseBalance(Currency) = 0; };

34 Here are the actual domain classes. We can have numerous kinds of accounts. Each one is a member Domain classes: C++ of the domain (the family) AccountWithPrintableBalance. This abstract base class helps de-couple the architecture, but also documents the family relationships between the domain classes. Capturing the design intent in the code is called intentionality. class SavingsAccount: class InvestmentAccount: public AccountWithPrintableBalance public AccountWithPrintableBalance SavingsAccount(Currency) { . . . . } InvestmentAccount(Currency c) void availableBalance const { . . . . } { . . . . } void decreaseBalance(amount) { .... } void availableBalance(void) const void increaseBalance(amount) { .... } { . . . . } }; void increaseBalance(Currency c) { . . . . } void decreaseBalance(Currency c) { . . . . } Currency dividend(void) const { . . . . } };

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 35 A domain dictionary is a simple dictionary of domain terms. Some of them may be domains, while The second deliverable: The Domain others may be more detailed definitions useful to the designer. If in doubt about whether a term Dictionary belongs in the domain dictionary, include it.

! Editing Language: the keystroke sequences and menus accessible to the user (vi, emacs…) ! Text Editing Buffer or Text Buffer: manages the text in between its residence in a file ! File: long-term storage for the text on a secondary storage device ! Window: medium for displaying the edited text to the user for interactive editing ! Input Device: keyboards, pointing devices, and other facilities for user input to the editor ! Command: a human/machine interface gesture

36 If we use these techniques, we reap some classic Lean benefits. Poka-yoke (means “fool-proof”) is a Lean Benefits result of the abstract base classes that serve like templates that we fill in later to meet behavioural requirements. With these base classes, it’s more difficult for engineers to do the wrong thing. These interfaces keep system parts consistent as well. ! Poka-yoke (interfaces provide constraints) Though we frame out the architecture, we don’t fill in its structures until a revenue-generating use case ! Just-in-time (fill in data and methods as needed) comes along. We deliver just in time. This also reduces waste and reduces inventory. – Reduce inventory costs ! Value Stream (gives domain experts a place) There is a place for domain expertise, which is often neglected in the value stream. ! Reducing waste (because of just-in-time) ! Reducing inconsistency; harmony (interfaces) Getting everyone involved in architectural planning means that there is not “bunching” of work. Work is – Reduces cost of rework: muda smoothed out because everyone is involved in every phase. The abstract base classes provide a ! Reducing unevenness (planning & process) concrete home for the results of this work. ! A home for results of up-front planning ! Reduce inventory (abstract base classes instead)

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 37 There are other forms in the user’s head beyond what-the-system-is. As described on the previous VI. Back to OO: Other forms slide, users care more about the responsibilities that are carried out inside the system: where the in the end-user’s head action is. Related responsibilities tend to group. Their grouping from the user perspective forms something called a role, which loosely corresponds to an interface in Java or C#. Think of a money ! Users think more about the roles played transfer at an ATM: you want to transfer money between two accounts. Your model of the program is by the objects than the objects that there is a source account and a destination account. You don’t think of “being source for a – What-the-system-does again! transfer” as being a property of a Savings Account, nor do you view this property as being duplicated in – Money transfer from a bank account: the roles are Source Account and Destination Account Checking Accounts. It may not be part of the Account hierarchy at all, but may extend to investments – Savings, checking, investment account objects and to a concept called your telephone bill or gas bill to which amounts are transferred monthly. This can all take on these roles — so can your phone bill role structure Is part of the end user mental model ! The association from roles to objects, for a given enactment of a use case, is also part But users know, in a given transaction, that these roles must bind to real objects. If I want to transfer of the end user model money from my savings account to my checking account, then I bind the role of “being source for a transfer) to my savings account and “being the destination for a transfer” to my checking account. These mappings are also part of the end user mental model.

This is getting a bit more rich than your grandfather’s architecture, which was just a bunch of objects!

38 Exercise

! Write a general user story for the business feature of transferring money between two financial accounts. Use revealing terminology.

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 39 Many of the problems with object orientation have arisen because complex methods appear in the Old object-orientation, Part II same interface as simple domain methods. In fact, their implementations become coupled in the same classes. Here we have a class TextBuffer from a text editor. The methods at the bottom are simple domain methods; those at the top come from user actions. While print and delChar might be atomic, how about spellCheck?

• Again, domain methods and spellCheck “use case” methods mixed in print delChar one interface • Different shear rates in one architectural unit — methods change more rapidly than the TextBuffer nature of the buffer nChars • We can’t understand spellCheck locally — it doesn’t topLine belong here! nLines

40 DCI is an architecture that addresses these problems. D is for Data: the rather unsophisticated, basic Proposed Solution: DCI building blocks of a program. It’s important that we view these as just barely smart data whose interpretation (as information) comes largely from the use cases.

! Data, Context and Interaction C is for context. Each use case takes place in a Context, so there is roughly one Context per use case. – Data: representation of basic domain Context includes the roles involved in the use case and their bindings to objects. information – Information != data !!! Last we have I for Interaction. This is how the roles work together to achieve a business goal. ! Context – The roles involved in a use case, and the way we choose objects to play those roles ! Interactions – How the roles work together to achieve a business goal

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 41 DCI is about object-oriented programming. Most methods focus on class-oriented programming. Yet Noteworthy DCI oddities programs have value only at run-time, so we need to think of their run-time architecture. At run time, objects become associated by their mutual invocations during a use case. These ! It’s mainly about thinking in objects relationships are very dynamic, so the program has a new architecture every microsecond or so. When – We must think of programs at run time we look at this architecture we are interested in only a very small fraction of an object interface at any – In a given use case we are interested in given time. Those methods of interest in a given use case define the role that the object is playing. only a fraction of an object’s interface – That interface is in no class We want to focus on the roles when we are implementing requirements — and on their relationship to – We can put it in a Java interface, but the objects that play the roles during enactment. Much of the hard work and enactment is in the roles. those are decoupled from the method That is where most of the traditional business value lies. bodies ! Classes don’t have responsibilities: In object-oriented programming, objects don’t have responsibilities — roles do. Think of yourself. We roles do can talk about your responsibilities as an employee, as a student, and as a son or daughter or husband or wife. We rarely talk about you as an instance of a class that has all of these. In fact, the class may not have these — husband and wife may be injected roles.

42 The way we have handled designs like this in the past is to tear down the global, procedural nature of VII. The usual solution... spellCheck and to redistribute its logic to individual objects. This is popularly called responsibility- based design: finding the right objects for different parts of the responsibility. However, there is nothing that suggests that objects provide a good partitioning of the algorithm with respect to the end user Dictionary Controller mental model. The algorithm partitioning becomes awkward the the result is unintelligible.

• We divide up spellCheck: spellCheck there is no locus of print delChar understanding it • The dividing up of spellCheck into methods must follow TextBuffer domain boundaries • Domain boundaries are nChars arbitrary with respect to how we conceptualize algorithm topLine steps nLines • It is therefore difficult to understand even the fragments!

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 43 When faced with the need for roles, computer scientists often respond that we have already tried to The usual retorts... solve this problem (or that we have in fact solved the problem). Here are common supposed remedies from the past, and why they fall short of the goals of DCI.

! Use multiple dispatch – That’s chooses one algorithm based on multiple types, rather than multiple algorithms based on multiple types ! Use aspects – The cutpoints are still dictated by the class structure ! Use mix-ins – Close, but how do they talk to each other? ! Just use objects (e.g., self) – A good start, but not enough ! Use multi-paradigm design – Undesired decoupling and lack of cohesion

44 Well, a few of the objects appear again and again, but there doesn’t seem to be any pattern. What is the form of function?

0145234427 0142366281 0283346255 0347212938 0324426292 0264274547 0374616737 0164571836 0173646282 Each class method 0324426292 0145234427 prints the object ID 0264274547

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 45 Again, and there’s a bit more of a pattern, but nothing we can use as a foundation for What is the form of design. function?

SavingsAccount CheckingAccount Euro SavingsAccount SavingsAccount Krone InvestAccount SavingsAccount Shekel Each class method CheckingAccount prints the class name PhoneBill Euro

46 Aha! Here we have a hard pattern. The patterns of events (we’ll come back to that phrase What is the form of later) is embodied in the roles — not in the classes or the objects. function? Why do object-oriented programming languages miss out on this?

SourceAccount DestinationAcct Amount SourceAccount DestinationAcct Amount SourceAccount DestinationAcct Amount Each class method SourceAccount prints its role name DestinationAcct Amount

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 47 Computers can: System Operations store and retrieve data Separation of Concern + transform data + communicate!!!

Communication becomes first class citizen in computing Show execution of the three tasks (on clicks) Class oriented programming: NOODLES

DCI: Separation of concern: Each task coded separately (animated on clicks)

48 A Context (an instance of a context class) System Operations receives a message Executed by Contexts is responsible for a use case/task/system operation triggers a method in the first role execution continues as specified in role methods

functional decomposition context responsibility/role responsibilities

50 years ago: Data store / applications / functional decomposition + Red circles: access routines DCI: Data objects / contexts / methodful roles + Context binds roles to objects: mobilize the objects that actually do the work

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 49 The pattern community sought metaphors of design and patterns for years. DCI is a portrayal of some A link to patterns? of the deepest structures behind , and usable software, that we know today. This quote from Timeless Way strikes a familiar chord with the DCI approach.

And finally, of course, I want to paint a picture which allows me to understand the patterns of events which keep on happening in the thing whose structure I seek. In other words, I hope to find a picture, or a structure, which will, in some rather obvious and simple sense, account for the outward properties, for the pattern of events of the thing which I am studying.

— Christopher Alexander, The Timeless Way of Building, Chapter 5, 1979

50 Object orientation is about objects interacting. However, in the mind of the user, the role played by an VIII. Roles object is more important than an object. You don’t look for a specific chair in the general case when you need a chair: you look for something that can play the role of chair. A role groups objects by purpose. ! The essence of OO is that objects interact to achieve a given goal A collaboration describes the structure of invocations between roles. ! A role is the name of an object according to its contribution to the goal An interaction specifies interactions between objects in terms of their roles. ! A role groups objects by purpose ! A collaboration describes the structure of roles ! An interaction specifies interactions between The objects are the data. Data, Collaboration, Interaction: DCI. objects in terms of their roles ! Classes are based on common characteristics; roles, on common purpose

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 51 What role does a tire play?

! Swing? ! Tire? ! Boat bumper?

52 This exercise helps you understand that you can think in roles — but that it is different than thinking in Exercise: What is a “role”? objects, in subtle ways that confound the way we usually do design.

! How many roles do you play? ! How many objects are you? ! How many classes are you? ! How many roles of people in this room? ! How many people objects in this room? ! How many classes of people in this room? ! As an instructor, which of these do I care about? ! As a course administrator, which of these do I care about?

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 53 Let’s get back to what objects are about. Users think about things in terms of roles (we can do an Back to the User Conceptual exercise about money transfer to illustrate this) and the interactions between them. They think about Model how those roles are played by objects during a specific enactment of a use case. The collaborations are the relationships between the objects that take place during that enactment. The end user model is more of a DCI model than a simple data (object) model! Objects

Collaborations

Roles

Interactions

54 Trygve Reenskaug has come up with a new architecture to support the end user’s view of Use Cases and These forms beg a new to localize algorithm in an encapsulated role. There are four major forms in this architecture. First is the architecture basic behavioural form, or architecture, that is defined just in terms of the protocols of the roles. Those are Methodful Roles at the right, and we call them methodless roles. We obviously have the objects; they capture the end user’s mental model of their world. Classes are an optimization for holding similar stuff that is common to many Use Case similar objects.

Role Identifiers Identifiers Role What Trygve adds are roles with methods. These roles are compliant with the method-less roles. Each one contains Use Case information in the form of methods. These methods can invoke methods of self or of another role. These roles are implemented as classes in most programming languages, though Scala can

Classes implement them as traits, and C++ as templates. They are pure, generic logic without state and with a fuzzy notion of the type of self or this. Each method-ful role is injected into each class whose objects play that

´ role at some time during their lifetime. Think of roles as a kind of class, and think of the domain classes (on the left) also as classes. This “injection” is a kind of gluing operation, or more like a smashing operation, where the logic of the method-ful roles is added to the logic of the classes. Each class will then behave as 54 though the methods of the method-ful roles had been copied into it. Of course, we retain one, single closed copy of each Use Case scenario in the methodful roles.

A Use Case scenario is implemented as an interaction of the algorithms between roles. It’s a kind of procedural decomposition, much as end users decompose complex tasks into subtasks. We divide up those subtasks on a per-role basis, consistent with the end user view. At run time we associate a method- less role (like an object identifier or object pointer in C++) with an object that can support the methods of

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 55 Here is a simple example with bank accounts. We have different operations like Withdraw, Deposit, An example: Bank Accounts and Transfer, that are in fact use cases with complex transactions — more than just simple atomic operations. Each one of these creates a Context that oversees the mapping from roles to objects, and that injects the role logic into the objects as needed before running the use case. Withdraw Algorithm AlgorithmAlgorithm Deposit

Transfer

Use Case Part Mapping from Objects Domain Part Context Use Case Part

Domain Part

56 This is a role contract type. The term “methodless role” usually refers to the identifier used by methods Role Contract Type of one role to access another role. That identifier has a type in statically typed languages, called the methodless role type. In any given context (scope) there is exactly one role of a given methodless role type. ! Used to declare the methodless role ! Includes role-binding helpers Think of this type as a Java or .Net interface, or as a C++ abstract base class used to describe the interface of a role (rather than of a class).

module MoneySourceAPI # Interface to a methodful object role def transferTo; end As an optimization of expression, this methodless role has simple support methods that publish the

# Role aliases for use by the methodful role methodless roles (identifiers) of the other roles that will participate in the use case that uses the def destination_account context.destination_account end def creditors; context.creditors end MoneySource role. def amount; context.amount end end

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 57 Here is the code. We have roles (method-ful roles) for a money sink and a money source, each one of Code for the which represents a role in a money transfer Use Case. We can read the transfer algorithm from the TransferMoneySink role TransferMoneySource perspective. It is readable. It is testable. One could stub it off and formally test it using system tests derived directly from Use Case requirements; if we did that, we might call it module TransferMoneySink include MoneySink, ContextAccessor Behavior-Driven Development.

# Object role behaviors (The code has been tested, and compiles and runs.) def transferFrom self.increaseBalance amount self.updateLog ‘Transfer in’, Time.now, amount end end

58 Here is the code. We have roles (method-ful roles) for a money sink and a money source, each one of Code for the which represents a role in a money transfer Use Case. We can read the transfer algorithm from the TransferMoneySource role TransferMoneySource perspective. It is readable. It is testable. One could stub it off and formally test it using system tests derived directly from Use Case requirements; if we did that, we might call it module TransferMoneySource Behavior-Driven Development. include MoneySourceAPI, ContextAccessor # Object role behavior (The code has been tested, and compiles and runs.) def transferTo beginTransaction raise "Insufficient funds" if self.balance < amount self.decreaseBalance amount destination_account.transferFrom self.updateLog "Transfer Out", Time.now, amount gui.displayScreen SUCCESS_DEPOSIT_SCREEN endTransaction end end

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 59 The Context is the administrative wrapper where the roles live. The Context also implements The Context ties it together the mechanics of assigning Role-players to Roles. From a design perspective the Context represents a system operation: a use case, or what Kay called an operational model. To Kay,

class MoneyTransferContext all objects should support this notion of an “operational model” in a child’s mind. module TransferMoneySource include MoneySourceAPI, ContextAccessor . . . . end

module TransferMoneySink . . . . end

def initialize . . . . end end

! A system operation ! A use case ! An operational model

60 Here is the injection: adding the roles into the domain classes like SavingsAccount and Injection: Contexts InvestmentAccount. Of course, we also could have injected the role TransferMoneySource into either or both of these accounts, too (in practice, we probably would). The classes re relatively dumb: they are little more than smart data. All of the action — the Use Case logic — is in the method-ful roles. The method-ful roles call on these rather dumb data operations to make the system fly. class MoneyTransferContext module TransferMoneySource . . . . end module TransferMoneySink . . . . end def initialize . . . . destinationAccount... sourceAccountForTransfer = SavingsAccount.new(account) sourceAccountForTransfer.extend TransferMoneySource destinationAccount.extend TransferMoneySink . . . . sourceAccountForTransfer.transferTo . . . . end

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 61 Here is the code. We have roles (method-ful roles) for a money sink and a money source, each one of The Code: C++ which represents a role in a money transfer Use Case. We can read the transfer algorithm from the TransferMoneySource perspective. It is readable. It is testable. One could stub it off and formally test it using system tests derived directly from Use Case requirements; if we did that, we might call it #define SELF static_cast(this) template class TransferMoneySource: public MoneySource Behavior-Driven Development. #define RECIPIENT \ { ((static_cast \ public: // Role behaviors (Context::currentContext_)-> \ void transferTo(Currency amount) { destinationAccount())) // This code is reviewable and (The code has been tested, and compiles and runs.) // meaningfully testable with stubs! beginTransaction(); if (SELF–>availableBalance() < amount) { template endTransaction(); class TransferMoneySink: public MoneySink throw InsufficientFunds(); { } else { public: SELF–>decreaseBalance(amount); void transferFrom(double amount) { RECIPIENT–>transferFrom(amount); SELF->incrementBalance(amount); SELF–>updateLog("Transfer Out", SELF->updateLog("Transfer in", DateTime(), amount); DateTime(), amount); } } }; gui–>displayScreen( SUCCESS_DEPOSIT_SCREEN); endTransaction(); } public: TransferMoneySource(void) { } };

62 Here is the injection: adding the roles into the domain classes like SavingsAccount and Injecting the roles into InvestmentAccount. Of course, we also could have injected the role TransferMoneySource into either classes or both of these accounts, too (in practice, we probably would). The classes re relatively dumb: they are little more than smart data. All of the action -- the Use Case logic -- is in the method-ful roles. The class SavingsAccount: class InvestmentAccount: method-ful roles call on these rather dumb data operations to make the system fly. public Account, public Account, public TransferMoneySink< public TransferMoneySource< InvestmentAccount> { SavingsAccount> { public: public: Currency availableBalance(void); Currency availableBalance(void); void decreaseBalance(Currency); void decreaseBalance(Currency); void increaseBalance(Currency); void increaseBalance(Currency); void updateLog( string, DateTime, Currency); void updateLog( Currency dividend(void) const; string, DateTime, Currency); }; Currency interest(void) const; };

(dumb)

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 63 How do we glue classes together? Schärli has pioneered a use of traits in Smalltalk (in Squeak) to Tricks with Traits change the way method lookups work, so that two classes can be made to appear as though they are one. He uses an extra field in each Smalltalk class to hold a descriptor of the classes that are injected with it. This gives the illusion of composing classes, and we can use it to compose the generic ! Need to compose the generic algorithms algorithms of the role classes (method-ful roles) with the domain classes. In C++, we can do the same of roles with the classes whose objects thing with templates. In Scala, we can use the traits language feature. play those roles ! This is a simple class composition ! Can use Traits (à la Schärli) to glue classes together – Current Squeak implementation maps the method name into every class using it – Trivial application of templates in C++ – In more dynamic languages, the composition is temporary and on a per-object basis

64 The Context object provides the context for the execution of the use case. It is a kind of scope. All the The Context object roles for the use case are within this scope. A given Context may have multiple methods that run the use case. Each one is called a trigger ! “Scopes” the roles for a use case method. Different trigger methods may elicit specific use case deviations. – Each context supports all deviations – A context may have multiple triggers The Context is also responsible for injecting roles into the objects that need them. This can be done at compile time or at run time. Further, at the beginning of each use case enactment the Context ! For each use case, injects the role methods into the objects that need associates the methodless role (identifiers) with the objects that play the roles. The Context can find or them create these objects in any way. – The objects may be anywhere in the A Context represents a fixed set of role collaborations, but these roles can be injected into objects of program any type. The objects need only support the methods that the roles apply to the role SELF. The – Contexts know how to find these objects mappings are dynamic and can change with every use case. This is an advanced and far more general – Many forms of objects can take on a form of polymorphism than we find with method dispatch — and what’s more, by avoiding method role... dispatch, it makes it easier to statically reason about the code.

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 65 What do I get with this? IX. What do I get? In general, you can make virtual functions disappear at the level of the Use Case scenarios. When reading the interactions between the roles there is no dynamic dispatch: what you see is what you get. ! Polymorphism is gone You can read the algorithm as though it were a FORTRAN algorithm. The algorithms read like ! All objects that play the same role process algorithms; you don’t have to track down their fragments all over the system. the same messages with the same methods Furthermore, the more rapidly evolving business logic (in the method-ful roles) is separated from the ! Algorithms read like algorithms rather than fragments more slowly moving domain logic (in the domain classes). This gives good coupling and cohesion that ! Rapidly evolving functionality is separated supports change. from stable domain logic ! Can reason about system state and We have also embraced the end user and his or her mental model, and captured it in the program. behavior, not just object state and behavior That is likely to enhance usability. It also makes it easier to review functionality with end users more directly, or at least through a more direct comparison with Use Cases.

Last, we have risen to the system level. This paradigm -- called the DCI paradigm -- is about system state and behavior. Simple OO is about simple object or class state or behavior. That’s inadquate to reason about system properties or even about what-the-*system*-does.

66 Because it allows me to connect with the end user mental model, it supports the user/interaction Agile Or, from an Agile perspective: objective. Because it builds on shared customer vocabulary of Use Case scenarios, it allows me to work better in terms of customer collaboration. Because I can reason about task sequencing from the code, I am more likely to deliver working software. And because it exposes the changing part for ready ! Allows me to connect with the user mental update it is all about embracing change. model – Users & interactions instead of processes and tools ! Can employ shared customer vocabulary – Customer collaboration, not contracts ! Can reason about form of task sequencing – More likely to deliver working software ! Exposes the changing part for ready update – Embracing change

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 67 A radically new design technique might beg a radically different method. DCI looks a lot like OOD, except it is OOD X. The Process as it should have been. As in OOD, we start by analyzing both the domain and the behavior. For the domain we can use DDD or multi-

Use paradigm design or commonality analysis or some other domain analysis technique. The goal is to arrive at a list of Cases classes for the stable domains. Habit Algorithms Behavior Analysis Then we do behavior analysis. Complex sequences of exchanges between users and code become use cases. Other actions (simple button pushes, state machines, etc.) use other formalisms. In the latter case, old-fashioned Event- Roles object-oriented design works well. In the case of sequences of steps between a user and the code, use cases are Based better.

A use case should not constrain the ordering of steps unless the business depends on it. You want to give the Domain Analysis Classes programmer as much freedom as possible — but no more. If you don’t specify it in the use case, assume that the developer has freedom to implement it as she wishes.

Use cases may contain recurring blocks of sequences. We want the redundancy at the use case level for review with customers. The coders do not want that redundancy. We can factor low-level redundancy at the programmer level into habits. These are more specific than use case scenarios but more general than code. Ultimately, the scenarios have to be combined into an algorithm that can be coded up. The steps unfold as role methods, and we split them along role boundaries that naturally fit the end-user mental model. Objects of the domain classes play these roles at run time.

68 In Scrum, the Product Owner is responsible for analysis. Good architecture starts with extensive Architecture in the Scrum analysis. This often takes the form of wire frames, use cases, navigation trees, and other ways to Process document the ongoing dialog between the market, the Product Owner, and the Developers.

Architecture is a product of the high-level design that takes place during Sprint Planning. Its products include APIs (usually as class interfaces) and an understanding of the work plan to build the artefacts

New screens Contextualized use cases to express the architecture in the code and, if necessary, in supplementary documentation. A good Updated domain logic team pulls as much of this into the first Sprint as they can so that, in accordance with Lean, they avoid

High-level design later rework.

During the Sprint the Developers fill in the architecture scenario by scenario and they develop the new screens, do interaction design, create the algorithms and methods to support the use cases, and

Use cases update the domain logic as necessary. Wire frames Navigation trees

and Domain Analysis

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 69 How do you put together the architecture? The usual approach is to let the architect write a document, Defer decisions? which takes a month, and to send it to a reviewer where it ages a month in their in-box, after which the reviewer (optionally?) reviews it. Then we find a spot on the calendar that is free for all the reviewers,

Normal Sequential Processing: after another month, and we get together to find that there are many problems. Then the architect tries again and we do another iteration, and the exchanges play out again with the programmer. System Design New Design Most of the time, most people are doing nothing. That is waste, and it isn’t lean. It leads to months-long architecture schedules.

Architect Customer Programmer

Mismatch!

Mismatch again!

70 Instead, you create the architecture with one-piece continuous flow. Get everyone together in one Domain Structure Matrix room. Use verbal communication instead of written communication, supplemented with a whiteboard and Post-It® notes. You can do a broad architecture, delivered as code, in about a week — certainly in Cross-Functional Team: a Scrum sprint — with much better fidelity than the months-long process takes.

If you’re doing Scrum, remember to put in some kind of demonstrable business functionality, too. Make it simple on the first sprint. You want to show, with confidence, that the build tools and processes for Customer delivering code all work — they’re an extended part of your architecture. Fast Design! Architect

Programmer

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 Filling out the code, one Scenario at a time 71 So where do we start, if we want to do a Model-View-Controller-User architecture? The first step is at Name: Insert Character Precondition: Buffer exists Postcondition: buffer updated the domain level. We divide the system into functions called domain services, sometimes called with the character Scenario: 1. User types character 2. Buffer updated with content 3. Screen updated applications. In the above example of a milling system controller, these applications are project Business management, the design application, and numerical control data production. Objects / emacs vi Tools After dividing into these applications—which may be Use Case actors—the next step is to divide the system into objects. Objects should reflect the user’s mental model of the application. Resources, products and activities might be the objects of the above design for a milling system controller. CharTextBuffer LineTextBufferKeyboard Domain

Classes SourceLine AsciiFile SourceLine BinaryFile Record Notice that the objects will indeed percolate into the user interface. But they are not the major facets

Multipane either of the interface nor of the architecture: they are the atomic building blocks. Multipane SimpleWindow Window SimpleWindow Window

Linux / Symbian / Android / Next Infrastructure

For those who like process 72 Here is a representation of the process activities with a rough idea of the dependencies between them. In Scrum, most analysis tasks take place under the Product Owner process as part of up-front diagrams planning; that includes user experience analysis, user stories, and use cases. The tester and

User Experience developer are deeply involved in that process as well! The steps from domain analysis to abstract base Analysis User Stories Use Cases CRC Cards Roles classes also involve the whole team and form a process of their own — but, again, one that involves

Usability Screen people who are instrumental in other processes. These two parts in hand, one can go through the Agile Test Design iteration cycle of creating tools: View-Controller combinations that use the existing Models (from the Abstract Domain Domain Select Base domain analysis), tying them together into an application. Analysis Division Paradigms Classes

Create Tools Code up the Domain Logic Test

Write Tests

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 73 In Lean Architecture, we focus more on domain experts, including the knowledge that everyone brings A system perspective to the team, instead of a limited number of architects. It’s O.K. to still have an architect, particularly in the role of coordinator, but they shouldn’t throw UML over the wall. Architecture is a participatory activity. Architects should also write code to stay current with the actual artifact. ! New role taxonomy – Architect Domain Instead of waterfall steps or Kanban stovepipes, we use one-piece continuous flow. Get everyone Expert involved in all the steps. Exactly how you do this depends on your history and domain — inspect and ! New process adapt. – Kanban Single-piece Instead of your old professor’s architecture, we use DCI. It more fully fulfills the vision of the original continuous flow creators of object orientation. ! New paradigm – Objects DCI Instead of user stories — which often have no user and no story — we want to focus on use cases for sequences of exchanges between the end user and the system. Use simpler techniques for simpler ! New formalisms – User Stories Use requirements, of course. And remember that the form doesn’t matter as much as the process that gets Cases & Habits you there. In particular, support good communication so you eliminate muri in your organization. Use habits for replicated use case fragments that coders can capture in one closed copy.

74 Time permitting we will go into some advanced DCI topics. XI. Advanced DCI Topics

! Contexts as Domain Objects ! Habits

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 75 We’ve been telling you that SavingsAccount is an object. We lied — kind of. In a real bank, your Contexts as Domain Objects account isn’t an object (a bag of money sitting in a safe somewhere). Instead, it is a computation across an audit trail, adding up deposits and subtracting withdrawals. However, to the end user it is still an object. On the other hand, actuaries who deal with savings account data may not even care about ! Is SavingsAccount an object? the accounts. – It is in the end user mental model – It isn’t in the Actuary mental model! What a SavingsAccount is, is a collection of use cases. That’s what a Context is. If we have a special – The implementation should support kind of object that is a Context but that can act like a domain object, we have the best of both worlds. both Let’s take that into code. ! A SavingsAccount is a collection of scenarios between an end user and a system under construction... a use case! ! We use Contexts for use cases!

76 An Environment object such as the Controller will receive an end user gesture that it interprets as Special contexts starting a Money Transfer. It instantiates a MoneyTransfer context object, providing context parameters it knows from previous inputs. The MoneyTransfer context knows the use case for transferring money. It also knows how to take the inputs from the Controller and use them to create (or find) Account Controlle Algorithm r context objects suitable to the environmental parameters. Those objects are also Contexts, and each Savings one knows algorithms for accessing the database objects to achieve the transfer. The domain objects Account Algorithm (audit trails, transaction logs, database tables) remain relatively dumb. They are injected with the

Use Case Parts context logic at the appropriate time.

Money Domain Part Transfer Checking Domain Account Objects

Algorithm Use Case Parts Domain Part Algorithm

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 77 Here is some code for a couple of the methods of the SavingsAccount class. It has no data except for SavingsAccount as a Context the DCI housekeeping parts (e.g., the ContextAccessor — see the appendix). It accesses database objects — the real domain objects — to do the jobs of withdrawal, funds transfer, and so forth.

class SavingsAccount attr_reader :account_id A more ambitious version might use roles to access the database objects, but this is enough for now. include ContextAccessor def initialize(account_id, credentialsA, credentialsB) @account_id = account_id @dbh = DBI.connect( "DBI:Mysql:retail:accounthost", credentialsA, credentialsB) end

def withdraw(amount) execute_in_context do raise "Bad argument to withdraw" if amount < 0 @dbh['AutoCommit'] = false begin raise "Inadequate funds" if balance < amount @dbh.do("INSERT INTO debits (amount, time) \ VALUES(?, ?)", amount, Time.now) @dbh.commit rescue raise "Withdrawal transaction failed" @dbh.rollback end end

78 Now a Context is an ordinary data object, and we can choose to forget that it is a Context and treat is Interesting questions as data. Any data object can play a role — even if it is a Context object. So an Account object can play the role of, say, Source Acccount. Can any data object be a domain object? We need to be a bit careful here because we don’t want to create domain objects from objects whose class interfaces are ! A Context is now an ordinary data cluttered with use case semantics. But in general the answer is yes. An Account object can behave like object a domain object, as viewed from a higher level. – Can it play a role? Yes: SourceAccount – Can it be a domain object? Yes, at a high level, it is the domain object for high-level use cases on accounts

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 79 Sometimes a given scenario, such as logging in, appears again and again in requirements. Such Habits redundancy is in fact good in requirements. End users tend not to think in terms of encapsulated subroutines and aren’t terribly interested in factoring out these commonalities. But programmers are.

! Actions can recur across many use We introduce the concept of habit as a way to capture a recurring sequence that might apply in many cases contexts or with many different pre- and post-conditions. It is the programmer’s job to seek a single closed copy of code for that habit that can work in all of those pre- and post-conditions, goals, and ! The actions are the same, but the goals and contexts are different — contexts. hence, they are not more refined use cases ! These matter to the DCI developer, who wants one closed copy of the code ! We capture them as habits

80 This is an example habit for the commonly recurring sequence that moves money between accounts, Example habit and does the concomittant accounting. Note that it is NOT a use case: it has no pre- or post- conditions, no context, and no goal. Those come from the context in which the habit is used.

Habit Name: Move Money and Do Accounting Preconditions: A valid Source Account and Destination Account have been identified, and the amount to be transferred is known Sequence: 1. Greenland Net Bank veriies funds available 2. Greenland Net Bank updates the accounts 3. Greenland Net Bank updates statement info Post-conditions: The periodic statements reflect the exact intent of the transaction (a transfer is a transfer — not a pair of a withdrawal and a deposit)

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 81 Because this is a design course rather than an analysis course, we don’t do much exploration of how Note: we capture requirements. Scenarios are a way to capture the business imperatives of the ordering of steps between an end user and a system. Use cases gather related scenarios and their deviations together into one package, such that all the scenarios strive toward the same goal. Algorithms reflect ! The general design flow is ... the engineering and implementation choices made by the programmer when the business does not – from use cases to scenarios constrain the ordering or dependencies of tasks. – from scenarios to habits – from habits to algorithms User stories are usually just a prelude to a scenario. They are inadequate for writing tests or, for that matter, for writing code. ! Most naive design methods confuse these See Cockburn’s “Why I still use use cases,” http://alistair.cockburn.us/Why+I+still+use+use+cases ! User stories miss this completely

82 Thanks for listening! Conclusion

! Lean architecture reduces rework and cost ! Agile software production meets end user expectations ! MVC brings the human side of Agile beyond the team to the code ! DCI separates the shear layers to ease maintenance ! New processes and organizations amplify the benefits

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 83 Learn more at:

! Full OO: – http://fulloo.info ! The Article: – http://www.artima.com/articles/dci_vision.html ! Agile Architecture, the book: – http://www.leansoftwarearchitecture.com ! Two Grumpy Old Men: – ROOTS 2008 – ROOTS 2009

84 More home reading to do! References

! Bjørnvig, Gertrud, “Patterns for the Role of Use Cases.” Proceedings of EuroPLoP ’03, p. 890. ! Coplien, James. Multi-Paradigm Design for C++. Addison-Wesley, 1998. ! Knauber et al, “Quantifying Product Line Benefits”, F. van der Linden, Editor, Lecture Notes on 2290, PFE-4 2001, p. 16.1 Springer-Verlag, 2002. ! Laurel, Brenda. Computers as Theatre. Addison-Wesley: 1993. ! Raskin, Jef. The Humane Interface: New Directions for Designing Interactive Systems. Addison-Wesley: 2000. ! Reenskaug, Trygve. Working with objects: the OORAM software development method. Manning Publications: 1995. ! Siniaalto and Abrahamsson, Comparative Case Study on the Effect of Test-Driven Development on Program Design and Test Coverage, ESEM 2007. ! Siniaalto and Abrahamsson, Does Test-Driven Development Improve the Program Code? Alarming results from a Comparative Case Study. Proceedings of Cee-Set 2007, 10 - 12 October, 2007, Poznan, Poland. ! “Data, Context and Interaction.” Wikipedia.

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 85 Contact...

! [email protected]

86 Dijkstra’s Algorithm

#!/usr/bin/env ruby # Example in Ruby – Dijkstra's algorithm in DCI #Modified and simplified for a Manhattan geometry with 8 roles # #TODO: #1. Nice chunking with headers. Data first. #2. Use terms from glossary only. #3. Get rid of two coordinate systems (street / avenue; west / south) #4. Change the single Neighbor into an EastNeighbor and SouthNeighbor again # # #Document on web has a model of the data (domain model), the use case, and #the algorithm that implements the use case. Put this document in a directory. #It also has the URLs for the implementations in different implementations # #Harmonize the code. I take first step. # # # # # Demonstrates an example where: #- objects of class Node play several roles simultaneously # (albeit spread across Contexts: a Node can # play the CurrentIntersection in one Context and an Eastern or # Southern Neighbor in another) #- stacked Contexts (to implement recursion) #- mixed access of objects of Node through different # paths of role elaboration (the root is just a node, # whereas others play roles) #- there is a significant pre-existing data structure called # a Geometry (plays the Map role) which contains the objects # of instance. Where DCI comes in is to ascribe roles to those # objects and let them interact with each other to evaluate the # minimal path through the network

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 87 Dijkstra’s Algorithm

#- true to core DCI we are almost always concerned about # what happens between the objects (paths and distance) # rather than in the objects themselves (which have # relatively uninteresting properties like "name") #- equality of nodes is not identity, and several # nodes compare equal with each other by standard # equality (eql?) #- returns references to the original data objects # in a vector, to describe the resulting path # #There are some curiosities #- east_neighbor and south_neighbor were typographically equivalent, # so I folded them into a single role: Neighbor. That type still # serves the two original roles #- Roles are truly scoped to the use case context #- The Map and Distance_labeled_graph_node roles have to be # duplicated in two Contexts. blah blah blah #- Node inheritance is replaced by injecting two roles # into the object #- Injecting roles no longer adds new fields to existing # data objects. #- There is an intentional call to distance_between while the # Context is still extant, but outside the scope of the # Context itself. Should that be legal? #- I have added a tentative_distance_values array to the Context # to support the algorithm. Its data are shared across the # roles of the CalculateShortestPath Context #- nearest_unvisited_node_to_target is now a feature of Map, # which seems to reflect better coupling than in the old # design

def infinity; return (2**(0.size * 8 -2) -1) end

88 Dijkstra’s Algorithm

def infinity; return (2**(0.size * 8 -2) -1) end

module ContextAccessor def context Thread.current[:context] end

def context=(ctx) Thread.current[:context] = ctx end

def execute_in_context old_context = self.context self.context = self yield self.context = old_context end end

# # Consider street corners on a Manhattan grid. We want to find the # minimal path from the most northeast city to the most # southeast city. Use Dijstra's algorithm #

# Data classes

Edge = Struct.new(:from, :to)

class Node attr_reader :name def initialize(n); @name = n end

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 89 Dijkstra’s Algorithm

def eql? (another_node) # Nodes are == equal if they have the same name. This is explicitly # defined here to call out the importance of the differnce between # object equality and identity return name == another_node.name end def == (another_node) # Equality used in the Map algorithms is object identity super end end

# #--- Geometry is the interface to the data class that has all #--- the information about the map. This is kind of silly in Ruby #

class ManhattanGeometry def initialize; end

# In the domain model we have a general model of streets and avenues. The notions of # an east and south neighbor are not part of the domain model, but are germane to # the Dijkstra problem. Though they evaluate to the same thing we use different # names to reflect these two different (mental) models of Manhattan streets.

def east_neighbor_of(a); return nil end def south_neighbor_of(a); return nil end

def root; return nil end def destination; return nil end def nodes; return @nodes end end

90 Dijkstra’s Algorithm

# #------Contexts: the home of the use cases for the example #

# #------This is the main Context for shortest path calculation #

class CalculateShortestPath # Housekeeping crap

include ContextAccessor

# These are handles to to the roles

def pathTo; @pathTo end def east_neighbor; @east_neighbor end def south_neighbor; @south_neighbor end def path; @path end def map; @map end def current; @current end def destination; @destination end def tentative_distance_values; @tentative_distance_values end

# This is a shortcut to information that really belongs in the Map. # To keep roles stateless, we hold the Map's unvisited structure in the # Context object. We access it as though it were in the map

def unvisited; @unvisited end

# Initialization

def rebind(origin_node, geometries)

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 91 Dijkstra’s Algorithm

@current = origin_node @map = geometries @map.extend Map @current.extend CurrentIntersection

geometries.nodes.each { # All nodes play the role of Distance_labeled_graph_node. This is not a # canonical DCI role, since a proper DCI role designates a unique object # in any context. This is a role in the sense of Child being a role, and # in a given Context I want to address all the children in the room at once. # It works fine as a methodful role, less obviously fine as a methodless # role.

|node| node.extend Distance_labeled_graph_node }

@east_neighbor = map.east_neighbor_of(origin_node) if east_neighbor != nil east_neighbor.extend EastNeighbor end

@south_neighbor = map.south_neighbor_of(origin_node) if south_neighbor != nil south_neighbor.extend SouthNeighbor end

end

92 Dijkstra’s Algorithm

# public initialize. It's overloaded so that the public version doesn't # have to pass a lot of crap; the initialize method takes care of # setting up internal data structures on the first invocation. On # recursion we override the defaults

def initialize(origin_node, target_node, geometries, path_vector = nil, unvisited_hash = nil, pathto_hash = nil, tentative_distance_values_hash = nil) @destination = target_node

rebind(origin_node, geometries)

execute(path_vector, unvisited_hash, pathto_hash, tentative_distance_values_hash) end

# There are eight roles in the algorithm: # #pathTo, which is the interface to whatever accumulates the path #current, which is the current intersection in the recursive algorithm #east_neighbor, which lies DIRECTLY to the east of current #south_neighbor, which is DIRECTLy to its south #destination, the target node #map, which is the oracle for the geometry #tentative_distance_values, which supports the algorithm, and is #owned by the CalculateShortestPath context (it is context data) # # # The algorithm is straight from Wikipedia: # #http://en.wikipedia.org/wiki/Dijkstra's_algorithm # # and reads directly from the distance method, below

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 93 Dijkstra’s Algorithm

module Distance_labeled_graph_node

# Access to roles and other Context data

include ContextAccessor

def tentative_distance_values; context.tentative_distance_values end

# Role Methods

def tentative_distance; tentative_distance_values[self] end def set_tentative_distance_to(x); tentative_distance_values[self] = x end end

module CurrentIntersection

# Access to roles and other Context data

include ContextAccessor def unvisited; context.map.unvisited end def south_neighbor; context.south_neighbor end def east_neighbor; context.east_neighbor end

# Role Methods

def unvisited_neighbors retval = Array.new if south_neighbor != nil if unvisited[south_neighbor] == true; retval << south_neighbor end end if east_neighbor != nil if unvisited[east_neighbor] == true; retval << east_neighbor end end return retval

94 Dijkstra’s Algorithm

end end

# This module serves to provide the methods both for the east_neighbor # and south_neighbor roles

module EastNeighbor include ContextAccessor

def relable_node_as(x) if x < self.tentative_distance; self.set_tentative_distance_to(x) return :distance_was_udated else return :distance_was_not_udated end end end

module SouthNeighbor include ContextAccessor

def relable_node_as(x) if x < self.tentative_distance; self.set_tentative_distance_to(x) return :distance_was_udated else return :distance_was_not_udated end end end

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 95 Dijkstra’s Algorithm

# "Map" as in cartography rather than Computer Science... # # Map is a DCI role. The role in this example is played by an # object representing a particular Manhattan geometry

module Map

# Access to roles and other Context data

include ContextAccessor

# These data are physically in the Context. There used to be a bit # affixed to each node used in the Dijkstra algorithm, but that violated # the encapsulation of the node. Data classes should be able to be used # unmodified by the DCI framework — except for the addition of roles, # and it's important that roles be stateless. So we put the data in # the Context. However, it is logically associated with the Mpa: think # of putting a check mark on the map next to each node, as it is # visited. So we put the accessor for the univisted vector here def unvisited; context.unvisited end

# Role Methods

def distance_between(a, b) return @distances[Edge.new(a, b)] end

def origin; return root end

# These two functions presume always traveling # in a southern or easterly direction

def next_down_the_street_from(x); east_neighbor_of(x) end

96 Dijkstra’s Algorithm

def next_along_the_avenue_from(x); south_neighbor_of(x) end

def nearest_unvisited_node_to_target min = infinity selection = nil unvisited.each_key { |intersection| if unvisited[intersection] if intersection.tentative_distance < min min = intersection.tentative_distance selection = intersection end end } return selection end end

def do_inits(path_vector, unvisited_hash, pathto_hash, tentative_distance_values_hash)

# The conditional switches between the first and subsequent instances of the # recursion (the algorithm is recursive in graph contexts)

if path_vector.nil?

# blah @tentative_distance_values = Hash.new

# This is the fundamental data structure for Dijkstra's algorithm, called # "Q" in the Wikipedia description. It is a boolean hash that maps a # node onto false or true according to whether it has been visited @unvisited = Hash.new

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 97 Dijkstra’s Algorithm

# These initializations are directly from the description of the algorithm map.nodes.each { |node| @unvisited[node] = true } unvisited.delete(map.origin) map.nodes.each { |node| node.set_tentative_distance_to(infinity) } map.origin.set_tentative_distance_to(0)

# The path array is kept in the outermost context and serves to store the # return path. Each recurring context may add something to the array along # the way. However, because of the nature of the algorithm, individual # Context instances don't deliver "partial paths" as partial answers. @path = Array.new

# The pathTo map is a local associative array that remembers the # arrows between nodes through the array and erases them if we # re-label a node with a shorter distance @pathTo = Hash.new

else @tentative_distance_values = tentative_distance_values_hash @unvisited = unvisited_hash @path = path_vector @pathTo = pathto_hash end end

98 Dijkstra’s Algorithm

# This is the method that does the work. Called from initialize. def execute(path_vector, unvisited_hash, pathto_hash tentative_distance_values_hash) execute_in_context do do_inits(path_vector, unvisited_hash, pathto_hash, tentative_distance_values_hash)

# Calculate tentative distances of unvisited neighbors

unvisited_neighbors = current.unvisited_neighbors

if unvisited_neighbors != nil unvisited_neighbors.each { |neighbor| net_distance = current.tentative_distance + map.distance_between(current, neighbor) if neighbor.relable_node_as(net_distance) == :distance_was_udated pathTo[neighbor] = current end } end unvisited.delete(current)

# Are we done?

if map.unvisited.size == 0; save_path(@path) else

# The next current node is the one with the least distance in the # unvisited set selection = map.nearest_unvisited_node_to_target

# Recur CalculateShortestPath.new(selection, destination, map, path, unvisited, pathTo, tentative_distance_values) end end end

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 99 Dijkstra’s Algorithm

def each path.each { |node| yield node } end

# This method does a simple traversal of the data structures (following pathTo) # to build the directed traversal vector for the minimum path

def save_path(pathVector) node = destination begin pathVector << node node = pathTo[node] end while node != nil end

end

# This is the main Context for shortest distance calculation

class CalculateShortestDistance include ContextAccessor

def tentative_distance_values; @tentative_distance_values end def path; @path end def map; @map end def current; @current end def destination; @destination end

module Map include ContextAccessor

def distance_between(a, b); @distances[Edge.new(a, b)] end

100 Dijkstra’s Algorithm

# These two functions presume always traveling # in a southern or easterly direction

def next_down_the_street_from(x); east_neighbor_of(x) end

def next_along_the_avenue_from(x); south_neighbor_of(x) end end

module Distance_labeled_graph_node

# Access to roles and other Context data

include ContextAccessor

def tentative_distance_values; context.tentative_distance_values end def tentative_distance; tentative_distance_values[self] end def set_tentative_distance_to(x); tentative_distance_values[self] = x end end

def rebind(origin_node, geometries) @current = origin_node @destination = geometries.destination @map = geometries map.extend Map map.nodes.each { |node| node.extend Distance_labeled_graph_node } end

def initialize(origin_node, target_node, geometries) rebind(origin_node, geometries) @tentative_distance_values = Hash.new

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 101 Dijkstra’s Algorithm

3.times { |i| 3.times { |j| @nodes << Node.new(names[(i*3)+j]) } }

# Aliases to help set up the grid. Grid is of Manhattan form: # #a - 2 - b - 3 -c # | | | # 1 2 1 # | | | #d - 1 -e - 1 -f # | | #2 4 # | | #g - 1 -h - 2 -i # @a = @nodes[0] @b = @nodes[1] @c = @nodes[2] @d = @nodes[3] @e = @nodes[4] @f = @nodes[5] @g = @nodes[6] @h = @nodes[7] @i = @nodes[8]

9.times { |i| 9.times { |j| @distances[Edge.new(@nodes[i], @nodes[j])] = infinity } }

@distances[Edge.new(@a, @b)] = 2

102 Dijkstra’s Algorithm

@distances[Edge.new(@b, @c)] = 3 @distances[Edge.new(@c, @f)] = 1 @distances[Edge.new(@f, @i)] = 4 @distances[Edge.new(@b, @e)] = 2 @distances[Edge.new(@e, @f)] = 1 @distances[Edge.new(@a, @d)] = 1 @distances[Edge.new(@d, @g)] = 2 @distances[Edge.new(@g, @h)] = 1 @distances[Edge.new(@h, @i)] = 2 @distances[Edge.new(@d, @e)] = 1 @distances.freeze

@next_down_the_street_from = Hash.new @next_down_the_street_from[@a] = @b @next_down_the_street_from[@b] = @c @next_down_the_street_from[@d] = @e @next_down_the_street_from[@e] = @f @next_down_the_street_from[@g] = @h @next_down_the_street_from[@h] = @i @next_down_the_street_from.freeze

@next_along_the_avenue_from = Hash.new @next_along_the_avenue_from[@a] = @d @next_along_the_avenue_from[@b] = @e @next_along_the_avenue_from[@c] = @f @next_along_the_avenue_from[@d] = @g @next_along_the_avenue_from[@f] = @i @next_along_the_avenue_from.freeze end

def east_neighbor_of(a); @next_down_the_street_from[a] end def south_neighbor_of(a); @next_along_the_avenue_from[a] end

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 103 Dijkstra’s Algorithm

def root; return @a end def destination; return @i end end

class ManhattanGeometry2 < ManhattanGeometry def initialize super() @nodes = Array.new @distances = Hash.new

names = [ "a", "b", "c", "d", "a", "b", "g", "h", "i", "j", "k"]

11.times { |j| @nodes << Node.new(names[j]) }

# Aliases to help set up the grid. Grid is of Manhattan form: # #a - 2 - b - 3 -c - 1 - j # | | | | # 1 2 1 | # | | | | #d - 1 -e - 1 -f 1 # | | | #2 4 | # | | | #g - 1 -h - 2 -i - 2 -k # @a = @nodes[0] @b = @nodes[1] @c = @nodes[2] @d = @nodes[3] @e = @nodes[4] @f = @nodes[5] @g = @nodes[6]

104 Dijkstra’s Algorithm

@h = @nodes[7] @i = @nodes[8] @j = @nodes[9] @k = @nodes[10]

11.times { |i| 11.times { |j| @distances[Edge.new(@nodes[i], @nodes[j])] = infinity } }

@distances[Edge.new(@a, @b)] = 2 @distances[Edge.new(@b, @c)] = 3 @distances[Edge.new(@c, @f)] = 1 @distances[Edge.new(@f, @i)] = 4 @distances[Edge.new(@b, @e)] = 2 @distances[Edge.new(@e, @f)] = 1 @distances[Edge.new(@a, @d)] = 1 @distances[Edge.new(@d, @g)] = 2 @distances[Edge.new(@g, @h)] = 1 @distances[Edge.new(@h, @i)] = 2 @distances[Edge.new(@d, @e)] = 1 @distances[Edge.new(@c, @j)] = 1 @distances[Edge.new(@j, @k)] = 1 @distances[Edge.new(@i, @k)] = 2 @distances.freeze

@next_down_the_street_from = Hash.new @next_down_the_street_from[@a] = @b @next_down_the_street_from[@b] = @c @next_down_the_street_from[@c] = @j @next_down_the_street_from[@d] = @e @next_down_the_street_from[@e] = @f

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015 105 Dijkstra’s Algorithm

@next_down_the_street_from[@g] = @h @next_down_the_street_from[@h] = @i @next_down_the_street_from[@i] = @k @next_down_the_street_from.freeze

@next_along_the_avenue_from = Hash.new @next_along_the_avenue_from[@a] = @d @next_along_the_avenue_from[@b] = @e @next_along_the_avenue_from[@c] = @f @next_along_the_avenue_from[@d] = @g @next_along_the_avenue_from[@f] = @i @next_along_the_avenue_from[@j] = @k @next_along_the_avenue_from.freeze end

def east_neighbor_of(a); @next_down_the_street_from[a] end def south_neighbor_of(a); @next_along_the_avenue_from[a] end

def root; return @a end def destination; return @k end end

# #--- Main Program: test driver #

geometries = ManhattanGeometry1.new path = CalculateShortestPath.new(geometries.root, geometries.destination, geometries) print "Path is: " path.each { |node| print "#{node.name} " }; print "\n"

106 Dijkstra’s Algorithm

puts "distance is #{CalculateShortestDistance.new(geometries.root, geometries.destination, geometries).distance}"

puts("")

geometries = ManhattanGeometry2.new path = CalculateShortestPath.new(geometries.root, geometries.destination, geometries) print "Path is: " last_node = nil path.each { |node| if last_node != nil; print " - #{geometries.distance_between(node, last_node)} - " end print "#{node.name}" last_node = node }; print "\n" puts "distance is #{CalculateShortestDistance.new(geometries.root, geometries.destination, geometries).distance}"

LeanArchitecture-DCI-OneDay-Master.key - 15 Sep 2015