Use cases and scenarios

178 views
Skip to first unread message

Trygve Reenskaug

unread,
Aug 13, 2017, 5:41:15 AM8/13/17
to DCI-object-composition
My DCI program is 3-dimensional. It is projected onto 2  two-dimensional orthogonal planes: A compile-time Context class and one or more run-time Interactions.



The responsibility of the class is (1) to declare methods for role/object binding; (2) to define how to handle an incoming system operation message by letting it create a CurrentContext,  then trigger an Interaction in this context. The responsibility of an Interaction is to establish the shared topology of its execution traces where the edges define role visibility and the nodes are roles declared in the class. The Interaction augments the nodes with the role scripts that define the execution. There can be many Interactions within a Context class that share the Roles but define different topologies and role scripts.

While waking up this morning, it occurred to me that a Context class can implement a use case, while different Interactions can implement different scenarios. The class establishes a 'vocabulary' naming all participating objects while the Interactions add behavior. (A role script can, of course, trigger another Interaction in the same context).

You all know how to deal with use cases and scenarios, of course. These are just some waking-up ideas of a very old man.

--

The essence of object orientation is that objects collaborate  to achieve a goal.
Trygve Reenskaug      
mailto: try...@ifi.uio.no
Morgedalsvn. 5A       
http://folk.uio.no/trygver/
N-0378 Oslo             
http://fullOO.info
Norway                     Tel: (+47) 22 49 57 27

Matthew Browne

unread,
Aug 13, 2017, 7:54:55 AM8/13/17
to object-co...@googlegroups.com

With this definition of "Interaction", it sounds like there would always be a one-to-one correspondence between System Operations and Interactions. A System Operation is triggered and the appropriate Interaction is executed in response. Is that correct?

If that's the case, then there won't always be only one Interaction per scenario. Think of booking a flight or train ticket - in one scenario there are multiple user actions / system operations and thus multiple interactions. But there still might be (and I would argue should be) an overarching Context for the whole use case, e.g. BookFlight (which can delegate to nested contexts as needed).

--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To post to this group, send email to object-co...@googlegroups.com.
Visit this group at https://groups.google.com/group/object-composition.
For more options, visit https://groups.google.com/d/optout.

Trygve Reenskaug

unread,
Aug 13, 2017, 9:49:42 AM8/13/17
to object-co...@googlegroups.com


On 13.08.2017 13:54, Matthew Browne wrote:

With this definition of "Interaction", it sounds like there would always be a one-to-one correspondence between System Operations and Interactions. A System Operation is triggered and the appropriate Interaction is executed in response. Is that correct?

Yes

If that's the case, then there won't always be only one Interaction per scenario. Think of booking a flight or train ticket - in one scenario there are multiple user actions / system operations and thus multiple interactions. But there still might be (and I would argue should be) an overarching Context for the whole use case, e.g. BookFlight (which can delegate to nested contexts as needed).

I'm no use case expert -- far from it. I now learn that there is a further breakdown of system behavior below the scenario. My point was to remind you of the second dimension in DCI that gives a capability of coding one context --> many behaviors (Interactions). (An Interaction can call another Interaction in the same Context)
I've never seen a proof that there MUST be one-to-one correspondence between use cases and Contexts. Cope?

The overarching Context could define all the roles needed for implementing the overall use case (if such a thing exists). They would be bound to objects together in one operation to ensure coherence. The Interactions could be organized in a kind of call tree that took care of all the details and variants you mention. The Contexts would not be nested, only the Interactions would be.

Just chattering while relaxing from my job of writing an article (46 pages by now)
--Trygve

James O Coplien

unread,
Aug 13, 2017, 10:09:48 AM8/13/17
to object-co...@googlegroups.com

Den 13. aug. 2017 kl. 15.49 skrev Trygve Reenskaug <try...@ifi.uio.no>:

I'm no use case expert -- far from it. I now learn that there is a further breakdown of system behavior below the scenario. My point was to remind you of the second dimension in DCI that gives a capability of coding one context --> many behaviors (Interactions). (An Interaction can call another Interaction in the same Context)
I've never seen a proof that there MUST be one-to-one correspondence between use cases and Contexts. Cope?

If object orientation is using a network of cooperating objects to attain some goal, and if DCI and Contexts are to support object orientation, then a Context supports the goal of a use case, and a Context is isomorphic to a use case.

For example, in the book checkout example (file:examples/borrow_library_panel5.k) the goal is to check out one or more books, and the use case is BorrowLibraryItems. There is therefore a context called BorrowLibraryItems. It enacts several interactions between the library and its client. A single interaction (like entering one’s PIN, or putting the book under the scanner) accomplishes no business goal. No one goes home from work and says, “Wow! It was a great day. I entered my PIN 40 times today!”

See Cockburn’s discussion of goal-driven use cases. A use cases almost always has a goal. In requirements-speak this is called the end user motivation.

Use cases and, to me, contexts, are there to help us reason about code in terms of the business. If we reason only about steps in isolation, we indeed have returned to procedural programming.

Quang

unread,
Aug 16, 2017, 2:05:59 AM8/16/17
to object-composition
I faced this situation many times too.

Indeed we might have multiple contexts that has same number of roles.
And it is tempted to merge them into one context, and support multiple related habit(s)/use case(s) in the same context since they have same number of roles and they might even share some edge(s).... 
So it is convenient sometimes.

But this defeats the purpose of using context to have separated, isolated, meaningful network of object communication.
It is the same as choosing the unit in unit test (method/class/scenario/use case).
(Btw, I am still using automation test for the sake of testing, but not 'driven design' blah blah :)
My choice of unit for testing is DCI context, and sometimes the standalone data objects if they are complex enough.
Testing DCI context with BDD is really good)

Choosing one context-one use case is a strong decision which comes with a cost and disciplines to stick with it.
That forces me to think hard about my use case: is it a use case or is it just a scenario ( we have seen this discussion before).

Eg. I have 3 related system operation(s): init, update, deinit from a controller, which will trigger my simulation context.
since I have 3 triggers, so my context has 3 public methods. Alternative I can choose to implement each of them as 3 separated contexts (init, update, deinit). 

But they are all related in the sense while I am working on update I need to change init, deinit...
That means they might be just different scenarios of a use case (eg. simualtion)
I think we have same situation with examples that have multiple user actions.
The problem with one-context solution is I need to have 3 public system operation and I just hate that.
It makes me feel un-safe.

My best solution for now (inspired by Cope's pong game's example):

- If we look at the use case definition, it has a trigger (one and only one), so the trigger must come from outside of the context.
In this case it might be a controller that handles an event then create the context and trigger its system operation method to start the context.

- After that everything else must happen within the context including multiple user actions (or trigger events)
We can do this by consider the controller as a role in the context, and explicit connect multiple user actions into one of the roles to handle them. 

This could generate extra work for wiring/un-wiring beside the role binding.

I found this solution is not bad at all, it is required more work, but it makes everything much clearer, even more readable.
While working with context with multiple entry points I always have un-safe feeling.

And I found explicit wiring/un-wiring is much better than register and forget event bus nightmare. (events fired everywhere)

But that exactly how I used MVC-DCI in my game.
My controller is doing all the dirty work of wiring, storing, loading stuff to deal with the legacy system.
I spend extra time to keep my context code as clean as possible.

Thanks to DCI, separating logic into context already helps to keep the controller less messy.

But that is also the hard part for selling DCI to other people if they don't see the benefit but the cost of extra wiring, binding....

/quang

James O Coplien

unread,
Aug 16, 2017, 4:38:42 AM8/16/17
to object-co...@googlegroups.com
Another experience paper to write.

Quang

unread,
Aug 16, 2017, 4:52:48 AM8/16/17
to object-composition
I am working on my own prototype now as I am learning new game engine (unity3d). 
Along the way, I will write down the experiment.

/quang
To unsubscribe from this group and stop receiving emails from it, send an email to object-composition+unsub...@googlegroups.com.

James O Coplien

unread,
Aug 16, 2017, 5:26:55 AM8/16/17
to object-co...@googlegroups.com
;-)

Matthew Browne

unread,
Aug 16, 2017, 7:43:16 AM8/16/17
to object-co...@googlegroups.com
On 8/16/17 2:05 AM, Quang wrote:
Indeed we might have multiple contexts that has same number of roles.
And it is tempted to merge them into one context, and support multiple related habit(s)/use case(s) in the same context since they have same number of roles and they might even share some edge(s).... 
So it is convenient sometimes.
I'm not sure what kinds of use cases you're talking about here...I thought we were talking about use cases at the business / user goal level, rather than lower-level algorithms. There are two questions: (1) what should be the top-level Context, and
(2) how to structure that Context.

The top-level Context should represent the use case at the user goal level...or, if it's a use case without a user (e.g. a system task triggered automatically on a schedule) then it would still be at a higher level than a single algorithm if that use case includes multiple algorithms. I can't think of too many cases where it would be "convenient" to write a Context that includes more than one business use case, but maybe it's different in game programming.

I think the more likely mistake would pertain to #2: failing to realize that a use case represented multiple levels of mental models, like how in the money transfer example we have the perspective of the bank customer and also the perspective of the accountant, which can be represented in a nested Account context. Or in the shopping cart example, I would say that the details of processing payment including communicating with payment gateways is the programmer's perspective, so a nested Context would make sense there too (and without a separate context for payment processing, the PlaceOrder context would get huge and messy).

My best solution for now (inspired by Cope's pong game's example):

- If we look at the use case definition, it has a trigger (one and only one), so the trigger must come from outside of the context.
In this case it might be a controller that handles an event then create the context and trigger its system operation method to start the context.

- After that everything else must happen within the context including multiple user actions (or trigger events)
We can do this by consider the controller as a role in the context, and explicit connect multiple user actions into one of the roles to handle them.
I experimented with this approach with Andreas's library borrowing use case and didn't really like the result:

https://gist.github.com/mbrowne/97bcb11fbc56993ac337

...or did you mean something different?

The code in Cope's pong example feels cleaner, but the downside is that the UI is tightly coupled to the Context (same with Andreas's implementation of the library borrowing use case). That may be fine for many apps, but there are certainly a lot of apps these days that need to support multiple UIs (e.g. web, desktop, mobile), and I have yet to see a complete example of a DCI Context with a UI where the UI is decoupled, except for Trygve's Prokon example...and in that example there's no use case that involves more than one interaction with the user.

So I think this is an area of DCI that still needs more research and experimentation. I'm still not convinced that having multiple public trigger methods on a Context is really that "unsafe" - or at least not more so than much of our other code, since so much of the correct functioning of an app already depends on things being called in the right order (at least in my experience...perhaps in a fully FP environment it's different).

But if we did want to prevent trigger methods from being called in the wrong order, e.g. in the PlaceOrder context, we could add a validation method that would be called at the beginning of each trigger method to ensure that the steps were called in the right order. (The validation could be implemented in a number of different ways; perhaps a simple state machine.) I've thought about other solutions, but so far, manually validating the order in which trigger methods are called is the clearest and simplest option I've found.

Quang

unread,
Aug 17, 2017, 6:22:06 AM8/17/17
to object-composition
I am still testing different ideas, so far this is what I am thinking:

- Having multiple entry points to the context makes me feel that there are outsider ROLEs that interact with the ROLEs in the Context. And that makes me feel 'un-safe'.

- So I don't see the problem with mixing all the View-Role, Controller-Role, Model-Role in the same context.
If the UI need to support different platform, then it is just different UI objects playing same View-Role in the context.
Of course, there is extra work for abstraction, wiring....but I feel it is worthy to me :)

- The 'order' issue is always there, but placing ALL the ROLEs that are involved in the interaction allow me to consciously think and check that 'order' correctness.

/quang

Trygve Reenskaug

unread,
Aug 17, 2017, 8:37:34 AM8/17/17
to object-co...@googlegroups.com
I'm sure there is something here that I would like to understand.  An example might make your ideas clear to me. Outsider roles? There are no roles outside their context and no roles participating in an interaction outside this Interaction. DCI is separation of concerns in 3 dimensions!
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To post to this group, send email to object-co...@googlegroups.com.
Visit this group at https://groups.google.com/group/object-composition.
For more options, visit https://groups.google.com/d/optout.

Matthew Browne

unread,
Aug 17, 2017, 8:53:32 AM8/17/17
to object-co...@googlegroups.com
I think Quang was saying that it *feels* like outsider roles (even though roles are actually always private to the context) when there are multiple trigger methods called (at different times) as part of the same scenario. But I'm not sure if I understood him correctly. Quang, why does it feel that way to you? And can you describe an example of what you have in mind? I'm thinking of something like the shopping cart example, but you may be thinking of something different...
--
Sent from my Android device with K-9 Mail.

Quang

unread,
Aug 18, 2017, 6:25:19 AM8/18/17
to object-composition
I am talking about long running use case with multiple user's input actions.
In that case, I like to see 

this context:

Controller
{
    Context ctx;
    void onEvent() {
       ctx.AssignRoles(controller, view, model)
       ctx.Start();
    }
}

// all roles are inside.
Context {
    trigger Start() {} // single trigger

    role Controller {
           void onUserAction1() { View.display() }
           void onUserAction2() { Model.getABC() }
   }

   role View {
         void display() {}
   }

   role Model() {
       void getABC() {}
   }
}

not this Context:

// feel that the Controller should be a role in the context
Controller {        
    Context ctx;

    void onEvent()
    {
         ctx.AssignRoles(view, model)
         ctx.Start()
    }

    void onEvent1()
    {
         ctx.userAction1()
    }

    void onEvent2()
    {
         ctx.userAction2()
    }

}

Context {
    trigger Start() {} // multiple trigger
    public userAction1() {} // multiple trigger
    public userAction2() {} // multiple trigger

   role View {
         void display() {}
   }

   role Model() {
       void getABC() {}
   }
}

/quang
To unsubscribe from this group and stop receiving emails from it, send an email to object-composition+unsub...@googlegroups.com.

To post to this group, send email to object-co...@googlegroups.com.
Visit this group at https://groups.google.com/group/object-composition.
For more options, visit https://groups.google.com/d/optout.

--

The essence of object orientation is that objects collaborate  to achieve a goal.
Trygve Reenskaug      
mailto: try...@ifi.uio.no
Morgedalsvn. 5A       
http://folk.uio.no/trygver/
N-0378 Oslo             
http://fullOO.info
Norway                     Tel: (+47) 22 49 57 27

Matthew Browne

unread,
Aug 18, 2017, 6:59:56 AM8/18/17
to object-co...@googlegroups.com

I don't like either code example. I don't think there should ever be a public method called AssignRoles. Code outside a Context should only pass in whatever data it needs (via the constructor and/or a trigger method, as appropriate) without being concerned about how the roles will be bound. Role-binding is an internal concern of the Context and a programmer should be able to change the way roles are bound at any time without affecting any code outside the Context.

Also, it looks like it would be possible to call AssignRoles() more than once during the same use case execution, which makes the Context even more leaky / unsafe.

To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.

Trygve Reenskaug

unread,
Aug 18, 2017, 11:23:58 AM8/18/17
to object-co...@googlegroups.com
In DCI, separation of concerns means that the code is clearly separated into Data, Context, Interaction partitions.
The following example lacks an environment that starts it all. Also: it's hard to code in an undefined language.

Data d  {}
Context ctx {
   void AssignRoles() {
        // assign roles CONTROLLER = this, VIEW, and MODEL to objects
    }
    ctx.role("CONTROLLER").start();
}
Interaction intr {
     role CONTROLLER {
        void start() {
            repeatForever {
                void onEvent() {
                     void onUserAction3() { EXIT}   
                     CONTEXT.AssignRoles().

                    
void onUserAction1() { VIEW.display() }
                     void onUserAction2() { MODEL.doABC() }
                }
            }
       }
     Role VIEW { void display() {} }
     Role MODEL { void doABC() {} }
     }
}

Matthew Browne

unread,
Aug 18, 2017, 5:11:54 PM8/18/17
to object-co...@googlegroups.com
On Fri, Aug 18, 2017 at 11:23 AM, Trygve Reenskaug <try...@ifi.uio.no> wrote:

In DCI, separation of concerns means that the code is clearly separated into Data, Context, Interaction partitions.

Maybe I'm being overly literal here, but...the interaction happens between the roles, so I think having role declarations with 'role' keywords or something to designate "this is the area for roles" is sufficient to demarcate the Interaction partition. As far as I'm aware there's no "interaction" keyword in the trygve language but it's still clear where the interactions are.

Trygve Reenskaug

unread,
Aug 19, 2017, 5:32:06 AM8/19/17
to object-co...@googlegroups.com
--
True. I use the Interaction keyword to isolate the context object from the role scripts. The compiler enforces this bifurcation of the Context so that the programmer can't 'smart' and cross the  barrier in his/her head or code. The AssignRoles method is invisible in the CONTROLLER role script so the indirect access is required: CONTEXT.AssignRoles().
BTW: There were bugs in my code. Here's an improved version, hopefully with fewer bugs: (blue = plan views, red = elevation views).

Data d  {}
Context ctx {
   void AssignRoles() {
        // assign objects to roles CONTEXT, CONTROLLER, VIEW, and MODEL
    }
    ctx.role("CONTROLLER").start();    // roles are invisible in the context so a method call is required to find it

Interaction intr {   // the context is invisible in the role scripts ro it has to play a role in the Interaction.

     role CONTROLLER {
        void start() {
            repeatForever {
                void onEvent() {
                     void onUserAction3() { EXIT}  
                     CONTEXT.AssignRoles().
                     void onUserAction1() { VIEW.display() }
                     void onUserAction2() { MODEL.doABC() }  // not MODEL.getABC() because I don't know what you want to do with the returned value.

}


Matthew Browne

unread,
Aug 21, 2017, 6:18:01 PM8/21/17
to object-co...@googlegroups.com
Hi Trygve,
What if MODEL is a use case context like PlaceOrder in the shopping cart example? With trigger methods like these:

    processProductSelection(desiredProductId: Int)
    getOrderDetails()
    processProductRemoval(productId: Int)
    processPayment()

(Side-note: I probably wouldn't call the role 'Model' in this case, but rather the name of the Context, so 'PlaceOrder').

The debate here is whether or not this is a good design...on the one hand, people are arguing that there shouldn't be multiple public entry-points to the Context, e.g. there would only be one public method like 'startOrder()' and all UI interaction from that point until the end of the use case would be handled within the PlaceOrder context. This requires mixing UI concerns into the use case context.

And on the other hand, I am arguing that multiple public trigger methods as above are a fine design as long as you do the appropriate validation to ensure that the methods aren't called in the wrong order. And it has the benefit of keeping the UI code decoupled from the use case.

We might need to go through this example from the very beginning in detail in order to get to the bottom of it, but since you weren't an active participant in the original discussion we had about it (last year I think), I figured I'd start with this quick summary.


--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composition+unsub...@googlegroups.com.
To post to this group, send email to object-composition@googlegroups.com.

Quang

unread,
Aug 22, 2017, 1:41:17 AM8/22/17
to object-composition
Time to look back at our canonical example:

http://folk.uio.no/trygver/Diverse/Draft/BB10Planning-listing/readableVersion.html#DependencyDisplayCtx

in the DependencyDisplayCtx, role binding method:

NameSortedActivities 
    ^(view model allActivities asSortedCollection: [:x :y | x name < y name])  <--- the context knows how to get objects out from the view, mode.....

For me I like to keep this outside of the context, so the context only know how to inject role to the object.
How to get the object is obligation of the external system (external controller object maybe).

In the programming language that uses interfaces for roles, I can inject any object that can play that role including fake or temp object for testing (especially UI object or network related object).

/quang

James O Coplien

unread,
Aug 22, 2017, 4:17:00 AM8/22/17
to object-co...@googlegroups.com

Den 22. aug. 2017 kl. 00.17 skrev Matthew Browne <mbro...@gmail.com>:

What if MODEL is a use case context like PlaceOrder in the shopping cart example? With trigger methods like these:

    processProductSelection(desiredProductId: Int)
    getOrderDetails()
    processProductRemoval(productId: Int)
    processPayment()

Who calls these?

Whether this entity contains the UI code is, to me, a separate question from whether these steps form part of the same flow. I do not see why it follows. Further, I do not understand why it is important. Too much such separation leads to a client / server architecture and is likely to force business intelligence into the GUI.

Matthew Browne

unread,
Aug 22, 2017, 5:35:22 PM8/22/17
to object-co...@googlegroups.com
On Tuesday, August 22, 2017 at 4:17:00 AM UTC-4, Cope wrote:

Den 22. aug. 2017 kl. 00.17 skrev Matthew Browne <mbro...@gmail.com>:

What if MODEL is a use case context like PlaceOrder in the shopping cart example? With trigger methods like these:

    processProductSelection(desiredProductId: Int)
    getOrderDetails()
    processProductRemoval(productId: Int)
    processPayment()

Who calls these?

I guess that's the question...I was thinking they would be called by the MVC Controller. Alternatively, if all of this were internal to the PlaceOrder Context, then I'm sure it would be organized differently.

Whether this entity contains the UI code is, to me, a separate question from whether these steps form part of the same flow. I do not see why it follows. Further, I do not understand why it is important. Too much such separation leads to a client / server architecture and is likely to force business intelligence into the GUI.

Let's take a step back...suppose you want to buy something on an online store, say Amazon.com. I would say two of the major use cases from the customer's perspective are "Browse Products" and "Place Order". Place Order would include choosing shipping options and paying for the order. The division between the two is where it perhaps gets a bit more subjective...I would say that as soon as you add a product to your shopping cart, you've started the Place Order use case. It's a little tricky because after adding one product to your cart, you might want to go browse more products and add more items to your cart. Even after reading Alistair Cockburn's book (Writing Effective Use Cases) this still seems like a bit of a gray area to me. I guess one could argue that the user's real goal is to purchase something, so Browse Products wouldn't be a (user goal-level) use case on its own...but what about "window shopping"? If we're talking about a super-simple store (nothing like Amazon.com), then a separate use case for Browse Products would probably be unnecessary. With the Place Order use case that Marc wrote, I can imagine a very simple UI in which the whole product inventory could perhaps be made available via just a couple drop-down menus. (I'm assuming that "Don's Auto Shop" doesn't have a huge inventory.)

In any case, I was thinking of Place Order as a guided step-by-step process including adding items to a shopping cart and checking out.

Trygve Reenskaug

unread,
Aug 23, 2017, 2:13:02 AM8/23/17
to object-co...@googlegroups.com
Googled online shopping. Found "Design and Implementation of E-Commerce Site
for Online Shopping" by Sidhartha Reddy Vatrapu; Governors State University.

I see View - Context(s) - Data - Database
http://opus.govst.edu/cgi/viewcontent.cgi?article=1079&context=capstones



On 22.08.2017 23:35, Matthew Browne wrote:
On Tuesday, August 22, 2017 at 4:17:00 AM UTC-4, Cope wrote:

Den 22. aug. 2017 kl. 00.17 skrev Matthew Browne <mbro...@gmail.com>:

What if MODEL is a use case context like PlaceOrder in the shopping cart example? With trigger methods like these:

    processProductSelection(desiredProductId: Int)
    getOrderDetails()
    processProductRemoval(productId: Int)
    processPayment()

Who calls these?

I guess that's the question...I was thinking they would be called by the MVC Controller. Alternatively, if all of this were internal to the PlaceOrder Context, then I'm sure it would be organized differently.
The MVC Controller manages Views, IMO. The above operations would then be implemented as Model Contexts.

Whether this entity contains the UI code is, to me, a separate question from whether these steps form part of the same flow. I do not see why it follows. Further, I do not understand why it is important. Too much such separation leads to a client / server architecture and is likely to force business intelligence into the GUI.

Let's take a step back...suppose you want to buy something on an online store, say Amazon.com. I would say two of the major use cases from the customer's perspective are "Browse Products" and "Place Order". Place Order would include choosing shipping options and paying for the order. The division between the two is where it perhaps gets a bit more subjective...I would say that as soon as you add a product to your shopping cart, you've started the Place Order use case. It's a little tricky because after adding one product to your cart, you might want to go browse more products and add more items to your cart. Even after reading Alistair Cockburn's book (Writing Effective Use Cases) this still seems like a bit of a gray area to me. I guess one could argue that the user's real goal is to purchase something, so Browse Products wouldn't be a (user goal-level) use case on its own...but what about "window shopping"? If we're talking about a super-simple store (nothing like Amazon.com), then a separate use case for Browse Products would probably be unnecessary. With the Place Order use case that Marc wrote, I can imagine a very simple UI in which the whole product inventory could perhaps be made available via just a couple drop-down menus. (I'm assuming that "Don's Auto Shop" doesn't have a huge inventory.)

In any case, I was thinking of Place Order as a guided step-by-step process including adding items to a shopping cart and checking out.

--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To post to this group, send email to object-co...@googlegroups.com.

James O Coplien

unread,
Aug 23, 2017, 3:49:18 AM8/23/17
to object-co...@googlegroups.com

Den 22. aug. 2017 kl. 23.35 skrev Matthew Browne <mbro...@gmail.com>:

I guess that's the question...I was thinking they would be called by the MVC Controller. 

This seems to hark back to an old myth that user input comes in through the Controller. For most of these I would envision it coming in through the View.

As has been said many times before on this list: do the *user*-level use case. How many machines does the end user interact with? Is it all in one device? In many systems the product selection will be at the point of selection, and payment at the till — a separate device. If so, it is multiple use cases. If it is a web purchase with everything being done from one interface, then the whole thing may be one use case. If you want to make the code general to work with either case, given the right selection of models and views — well, good luck.

My guess is that you could not build a humane interface (à la Rasking) for both of them on top of such a system, and the arguments are fairly compelling: the relate to the end user mental model of the process. For example, the timeout use cases are quite different for these two.

James O Coplien

unread,
Aug 23, 2017, 3:53:18 AM8/23/17
to object-co...@googlegroups.com
Den 23. aug. 2017 kl. 08.12 skrev Trygve Reenskaug <try...@ifi.uio.no>:

Googled online shopping. Found "Design and Implementation of E-Commerce Site
for Online Shopping" by Sidhartha Reddy Vatrapu; Governors State University.
<eibnmomgccmimobe.gif>

I see View - Context(s) - Data - Database

Well, except that I’m sure he doesn’t. I find that these architectures destroy usability because the view is never a presentation of anything in the database. The data access layer just implements the relational (or whatever) model, and transactions. The use case is in the business logic layer and the presentation is done by a separate team using a GUI-builder.

This picture was prominent in the 1980s and I would never use it in any presentation where I was trying to help people understand how objects work. It persists today because we learned how to make databases scale. I don’t know any attempt at mass storage of objects that hasn’t been a dismal failure. Spring tries, but I don’t think it scales very well.

Andreas Söderlund

unread,
Aug 23, 2017, 4:17:14 AM8/23/17
to object-co...@googlegroups.com
Here's my thinking about the trigger methods, after a couple of months of absence from programming, so be prepared for some fresh perspectives here. ;)

tis 22 aug. 2017 kl 00:18 skrev Matthew Browne <mbro...@gmail.com>:
Hi Trygve,
What if MODEL is a use case context like PlaceOrder in the shopping cart example? With trigger methods like these:

    processProductSelection(desiredProductId: Int)

Should another part of the program trigger that a single product should be "processed"? Processed how? It's not very obvious for someone calling the method what to expect here.
 
    getOrderDetails()

Details like customer name, address, etc? Sounds more like data.
 
    processProductRemoval(productId: Int)
    processPayment()

Lots of "process", that worries me...! Can the "process" methods be called in any order? What kind of process is that?

/Andreas

James O Coplien

unread,
Aug 23, 2017, 4:30:06 AM8/23/17
to object-co...@googlegroups.com

Den 23. aug. 2017 kl. 10.17 skrev Andreas Söderlund <cisc...@gmail.com>:

Lots of "process", that worries me...! Can the "process" methods be called in any order? What kind of process is that?

Exactly why I suggested that a good review of the business-level use case would be in order.

If they can be called in any order then, at this level, it’s what the Lean Arch book calls an “atomic event architecture.” It is characterized by many of the early, simple paint-program examples supposedly clarifying how OO worked. No use cases; just an object at a time doing one public method at a time.

If so, they are probably four use cases. But it all depends on context and, so far, the discussion hasn’t started to establish any. Maybe a user narrative is in order.

Trygve Reenskaug

unread,
Aug 23, 2017, 6:03:34 AM8/23/17
to object-co...@googlegroups.com
Inspired by this thread, I've updated the BabyIDE report generator that exports the code for an application in HTML form:
The good, old bank example
The big planning example
There is a long road from a running program in BabyIDE to a Webhuset internet page with links. I hope I've got it right. The interesting part is the navigation pane on the left that displays the program structure.
More comments inline below.


On 22.08.2017 00:17, Matthew Browne wrote:
Hi Trygve,
What if MODEL is a use case context like PlaceOrder in the shopping cart example? With trigger methods like these:

    processProductSelection(desiredProductId: Int)
    getOrderDetails()
    processProductRemoval(productId: Int)
    processPayment()
No problem. Any object can play a role in an Interaction, even objects with unavailable classes.


(Side-note: I probably wouldn't call the role 'Model' in this case, but rather the name of the Context, so 'PlaceOrder').
In my big planning example, there is the MVC Model (the plan) and the UI (MVC Controller and Views). Both are bifurcated into Data and Interaction parts: Model/frontloading, Model/resource allocation, etc. UI/Dependency diagram,  UI/Gantt chart, etc  I was very uncertain about the latter partitioning when I first did it since I hadn't done anything like it before.  I now believe it's sound since it leads to an orthogonal separation of concerns and thus readable code. See code listing above.


The debate here is whether or not this is a good design...on the one hand, people are arguing that there shouldn't be multiple public entry-points to the Context, e.g. there would only be one public method like 'startOrder()' and all UI interaction from that point until the end of the use case would be handled within the PlaceOrder context. This requires mixing UI concerns into the use case context.
I can't judge if a fragment is a good design. I don't see a fundamental problem with many entry points to a Context.  I'm itching to implement several Interactions with separate interaction diagrams to a Context, but I have to do other things first.  I can't see any fundamental or practical problems offhand. I would also need a use case with several scenarios as an example.
And on the other hand, I am arguing that multiple public trigger methods as above are a fine design as long as you do the appropriate validation to ensure that the methods aren't called in the wrong order. And it has the benefit of keeping the UI code decoupled from the use case.
Any design that reflects a mental model shared by end user and programmer is a good design?


We might need to go through this example from the very beginning in detail in order to get to the bottom of it, but since you weren't an active participant in the original discussion we had about it (last year I think), I figured I'd start with this quick summary.
Complete use case, please.  I don't believe in dogma. Cope says that good design evolves through "all the people, all together, all the time." May be some  dogma will emerge after 10 years' experience, not up front today. And then they may be in the form of patterns, not simple Rules (aka Laws). What we need is more complete examples and time to discuss the merits of their design.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To post to this group, send email to object-co...@googlegroups.com.

Trygve Reenskaug

unread,
Aug 23, 2017, 8:41:27 AM8/23/17
to object-co...@googlegroups.com
2. attempt.
Wrong URL for the bank!

Trygve Reenskaug

unread,
Aug 23, 2017, 12:47:05 PM8/23/17
to DCI-object-composition
3. attempt.
I should read input boxes carefully before I click. A check box was on while it has always been off before. It was Thunderbird that exhibited some very artificial intelligence. I understand why people only rarely make URLs clickable in e-mail.

If it fails this time too - please look for attachments.
Try separating the URLs with normal text

The big planning example

Matthew Browne

unread,
Aug 23, 2017, 9:03:51 PM8/23/17
to object-co...@googlegroups.com

Hi Trygve,
Thank you for continuing to clarify your big planning example (Prokon). It's certainly a very helpful example. Unfortunately it doesn't answer the question I'm asking here, because all the use cases in that example can be achieved with a single interaction between the user and the system. For example, the user requests to frontload the activities, and the system does it, and that's the end of the use case.

As to the online shopping example, I'm thinking it might be better to start with the use case of placing an order on Amazon.com rather than a fictional auto parts shop. It's a concrete example and we already have a shared understanding of how it works.

But since you asked about the use case for the existing example, first of all I'll reiterate that the use case is at the top of the code, in the comments. A while ago I started working on my own version of the use case description, which is very similar but uses a two-column format that you might find a bit easier to follow...(but I didn't write the deviations for it yet [which are in the original], so it currently only shows the main success scenario).

Matthew Browne

unread,
Aug 23, 2017, 9:07:28 PM8/23/17
to object-co...@googlegroups.com
On 8/23/17 4:17 AM, Andreas Söderlund wrote:
    processProductRemoval(productId: Int)
    processPayment()

Lots of "process", that worries me...!
The latest version of the shopping cart example that I contributed was a slight restructuring of Marc Grue's original example. If I recall correctly, his reason for prefixing these methods with 'process' was that the initial events for product selection, etc. would be handled by MVC, and the PlaceOrder context was responsible for doing the processing.

Personally I prefer more straightforward naming, even if that's the case. So I would do it like this:

void addToCart(int productId, int quantity)
void changeQuantity(int productId, int quantity)
void removeFromCart(int productId, int quantity)
Order getOrder()


But before deciding on these details, obviously we first need to establish how the use cases should be organized. Apparently we have a lot of different mental models of an online shopping cart.

Matthew Browne

unread,
Aug 23, 2017, 9:18:02 PM8/23/17
to object-co...@googlegroups.com
On 8/23/17 3:49 AM, James O Coplien wrote:
This seems to hark back to an old myth that user input comes in through the Controller. For most of these I would envision it coming in through the View.
Good point; the user input would probably be handled by the View here. But I would say it would depend on the UI details...here's a helpful quote from the MVC page on Trygve's website:
Also, in my later MVC implementations, a view accepts and handles user input relevant to itself. The Controller accepts and handles input relevant to the Controller/View assembly as a whole
Based on that and Trygve's responses to my MVC questions on this list, I interpret this to mean that for cases where something more needs to happen in response to a user input event than just calling a Context method (perhaps some other UI-related code needs to run before/after), then it would make sense to write a method in the Controller to respond to the event.

But these are all just guidelines; I try to keep this advice from Trygve in mind:
I don't see MVC as a straight jacket, but as an inspiration.  I let it guide my implementations, but not constrain me when other solutions are clearly more readable.

Matthew Browne

unread,
Aug 23, 2017, 10:45:37 PM8/23/17
to object-co...@googlegroups.com
On 8/23/17 4:17 AM, Andreas Söderlund wrote:
> Can the "process" methods be called in any order? What kind of process
> is that?
In the code example on github, the idea is that the UI would be
responsible for calling the methods in the right order. But it would be
easy enough to add some code to the PlaceOrder context to enforce that
its methods are called in a valid order. As to the best solution for
this particular example, we should probably continue with the higher
level discussion first and then return to this.

Trygve Reenskaug

unread,
Aug 24, 2017, 3:52:22 AM8/24/17
to object-co...@googlegroups.com
On 24.08.2017 03:03, Matthew Browne wrote:
Hi Trygve,

Thank you for continuing to clarify your big planning example (Prokon). It's certainly a very helpful example. Unfortunately it doesn't answer the question I'm asking here, because all the use cases in that example can be achieved with a single interaction between the user and the system. For example, the user requests to frontload the activities, and the system does it, and that's the end of the use case.
I believe there is only one use case: Create a Plan. The user model includes several operations: Create/remove a Plan and Edit the Plan. I doubt if Compute the Plan would be a separate command; it could be recomputed automatically at every change in the Plan Model.

The user starts the program through a global menu that triggers the BB9DBase class method open. (The big planning example)? This is the only global command that relates to planning. It invites the user to choose one of the existing Plans (the 'create new plan' command seems to be missing) and then opens an editor on the selected Plan:


The editor includes many user commands that can be given in any order; they are implemented in the UI-Context-Classes projection. Every class includes exactly one Interaction (an unnecessary limitation in the current BabyIDE). The details in the Model projections are not part of the use case but implements the 'magic' that melds the user's mental model with the computer-based model.

An aside: The 'magic' is an essential part of the program that is not specified by a use case, but could be specified by a database schema. The creation of a schema requires special expertise in user/programmer communication. The schema is implemented in the Model-Data-classes projection.

My question to our use case specialists: Is 'Planning' one use case? The whole is triggered by the user giving one command. If many: What are they and where is the user's perception of the whole?

Another aside: I think this example neatly illustrates the DCI separation of concerns in mental model as well as code.

Matthew Browne

unread,
Aug 24, 2017, 7:52:01 AM8/24/17
to object-co...@googlegroups.com

Sorry, Trygve, I misremembered how the interface for the planning app works. I have studied the organization of the code and run the application in the past, but I'm on a Mac and didn't have easy access to it...I didn't mean to make you explain the interface and send a screenshot, although of course it's good to be clear on it for this discussion.

Thanks,
Matt

--
You received this message because you are subscribed to the Google Groups "object-composition" group.

Matthew Browne

unread,
Aug 24, 2017, 8:10:57 AM8/24/17
to object-co...@googlegroups.com
On 8/24/17 3:52 AM, Trygve Reenskaug wrote:
My question to our use case specialists: Is 'Planning' one use case? The whole is triggered by the user giving one command. If many: What are they and where is the user's perception of the whole?
I look forward to comments from Cope and others who have a lot of experience with use cases. As a starting point, let me share some things from Alistair Cockburn's book that I think will be helpful...

An important concept in use cases is the level of the use case. There are 3 levels described in the book
  • Summary level
  • User goal level
  • Subfunction level
The level we are usually talking about on this list is the user goal level. To quote from the book:
The user goal is the goal of greatest interest. It is the goal the primary actor has in trying to get work done or the one the user has in using the system. It corresponds to "elementary business process" in business process engineering.

A user goal addresses the question "Can the primary actor go away happy after having done this?" For a clerk, it is "Does your job performance depend on how many of these you do today?," or the coffee break test: "After I get done with this, I can take a coffee break." In most circumstances, it passes the one person, one sitting test (2-20 minutes).

Neither "Complete an online auction purchase" nor "Log on" generally count as a user goal. Online auctions take several days and so fail the single-sitting test. Logging on 42 times in a row does not (usually) satisfy the person’s job responsibilities or purpose in using the system.

"Register a new customer" and "Buy a book" are likely to be user goals. Registering 42 new customers has some significance to a sales agent. A book purchase can be completed in a single sitting.

Trygve Reenskaug

unread,
Aug 24, 2017, 12:03:19 PM8/24/17
to object-co...@googlegroups.com
Thanks, this is helpful.  I'm learning all the time. 
A tool, such as a hammer, is not a use case. Editing the plan is not a use case. Editing the plan for a given purpose can be a use case. My planning interface is not a use case. In engineering, a CTR (Cost Time & Resource)  describes an activity. A user goal use case could be to enter a CTR into the system. My tool could be modified to fit this job. The use case sub-function level could be supported by commands and implemented as Contexts.  I have long suspected that there may be a many-to-many relationship between use cases  and Contexts. (A tool, e.g., a(hammer, can be used for many goals, and a job a goal can need many tools).  Excuse the clumsy language, I hope you see what I mean.
It would be interesting to see the shopping example in this light. (Not shopping cart, the cart is not a goal). We're getting there, I think.

James O Coplien

unread,
Aug 24, 2017, 12:11:01 PM8/24/17
to object-co...@googlegroups.com

Den 24. aug. 2017 kl. 09.52 skrev Trygve Reenskaug <try...@ifi.uio.no>:

My question to our use case specialists: Is 'Planning' one use case? The whole is triggered by the user giving one command. If many: What are they and where is the user's perception of the whole? 

“Planning” is just a word, and use cases are an informal tool to give such phrases meaning. Whatever it is, it could be expressed using the use case semi-formalism. It would be a good use case if it involves two to four actors that interact with each other in a network, for three or more interactions. I would use the use case formalism to capture it in development if, in addition to the above, it achieved some business goal: the lower level things are, to me, just pseudo code.

While “Planning” may be the name of the game, I wouldn’t find it profitable to make it a use case. That isn’t to say that it isn’t one. Maybe everything is, or can be, a use case. But that’s the wrong question.

My intuition says that the use cases are:

Add an activity
Variations: add an event at the end; between two events; as a new start event;
adding activity before START or after DONE; illegally name event; event
with only partial binding of predecessor / successor

Move an activity
Variations: forward; backward; ….

Add an actor
Variations: actor already exists; actor has an illegal name; balking once started

Delete an actor
Variations: actor does not exist; balking once started; actor is shared

Associate an actor with an activity
...

Dissociate an actor from an activity
...

Create new plan

Delete plan

I’ll leave it as an exercise for the reader to associate a user goal with each of these. Knowing that the user goal is “to get a plan” in response to one combination of a bunch of inputs really isn’t useful to anyone, most of the time. Again, I’m sure someone can come up with an exception — and then it’s a good use case.

But if you read the above, you get an idea not only of what the application does but of how it will be used. If I reduce this to one interaction, it’s almost uncontextualized. Understanding is all about context. The above use cases are much better contextualized.

With this view “Planning” may not be a use case at all: It is not a "case of use" (an advandningsfall). A use case is about networks of interactions. “Planning” is just what the program does once the interaction is done: there is no network. Drawing the pictures is a matter for the views, and while the topological sorting algorithm could be described as a use case, there is probably no reason to avoid just describing it in code. It’s design rather than analysis — and this has been the problems with several of Matt’s examples, is that they mix analysis and design. I’l stop short of saying “don’t do it” but it’s not how I use use cases. The interactions with the user are, to me, the use cases, and they are enumerated above.

Matthew Browne

unread,
Aug 25, 2017, 9:14:54 AM8/25/17
to object-co...@googlegroups.com

Here is a user narrative for Amazon.com, which I figure is a useful starting point since we're probably all familiar with it. I thought the idea of shopping being separate from payment was interesting, so I incorporated that.

~~~

Sam is a software developer and an Amazon customer who recently installed the Amazon app on his phone. He wants to buy two books: Working With Objects: The Ooram Software Engineering Method by Trygve Reenskaug, and Lean Architecture: for Agile Software Development by James Coplien. He is at his home computer, so he logs in to Amazon.com and adds the books to his shopping cart, but then he realizes that it's time to leave for work, so he decides to to complete the order on the train on his phone. Once on the train, he opens the (native) Amazon app on his phone and logs in, and taps the shopping cart icon in the top menu. He suddenly remembers about another book he wanted to buy, Perfect Software: And Other Illusions about Testing by Gerald Weinberg. So he adds that to his shopping cart as well and finally proceeds to checkout. For his payment method, he selects a credit card that was already saved in his Amazon account. He completes the order and Amazon emails him a receipt.

Matthew Browne

unread,
Aug 25, 2017, 8:17:34 PM8/25/17
to object-co...@googlegroups.com

So I suppose the next step would be to start drafting the use cases. I'm thinking that especially given the nature of shopping on Amazon, there should be two use cases for selecting and buying products - "Select Products to Purchase" and "Place Order". Select Products to Purchase would include adding and/or removing products to the shopping cart, and Place Order would comprise the whole checkout process.

James O Coplien

unread,
Aug 26, 2017, 6:10:30 AM8/26/17
to object-co...@googlegroups.com

Den 26. aug. 2017 kl. 02.17 skrev Matthew Browne <mbro...@gmail.com>:

So I suppose the next step would be to start drafting the use cases.

So far you have only one narrative. It gives texture to a single scenario of the use case for a single customer segment. One next step is to identify more alternatives for the scenario (credit card declined, book unavailable with an option to have it delivered when it becomes available, internet connection drops). Then identify more scenarios for this market segment (One-Click ordering, writing a product review, returning a product, etc).

Then you could move on to other market segments (B2B, analytics, etc.).

The first thing you want to codify in the use case is the typical / main success scenario. You may have to explore the market a bit (hence, the exploration of these scenarios) to discover what that is. Do most people use credit card or PayPal? Is OneClick the dominant ordering method, or the standard scenario? Also, the main success scenario will avoid the variation of interrupting in the middle, and will probably start with a single item. You will probably need to do more market research (and reflect it in narratives or at least user stories).

Then you can start implementing and delivering something, based on the main success scenario. Almost always develop and deliver it first.

One thing I find missing from the current narrative is the user motivation: try writing a user story to get to that. Without a motivation you leave the developers guessing about the details, or you have to compensate with a lot more detail. The point is that a user narrative doesn’t stand alone as a foundation for a use case: you may also need user profiles, user stories, market data, standards definitions, user facility analyses or assumptions (to some level), scaling and performance requirements, etc. (Things like acceptable response times belong in the use case.) And I would suggest starting a domain analysis in parallel, for what should be obvious reasons.

Over time you can implement more of the extensions and deviations, as well as add new extensions and deviations to the main scenario. 

Matthew Browne

unread,
Aug 26, 2017, 7:33:05 AM8/26/17
to object-co...@googlegroups.com

Thanks Cope. If I were building a new online store from scratch, then I should indeed do all of those things. But my only goal here is to establish enough context to discuss a realistic online shopping use case on this group. I chose Amazon.com because we already share at least a basic understanding of how it works and why people use it. Do you think it's necessary to do all of the analysis you suggested just to discuss the example here? If so then I'll need to pick a simpler example, because duplicating all the real analysis and design that went into building even the first version of Amazon would be a big job, and probably impractical for discussion on this group. I know there are details of Amazon's business that none of us know, so there will probably be gaps and mistakes in any use cases I write, but most of our other DCI examples aren't 100% realistic either and we're still able to discuss the merits of various implementations.

--
You received this message because you are subscribed to the Google Groups "object-composition" group.

James O Coplien

unread,
Aug 26, 2017, 7:53:15 AM8/26/17
to object-co...@googlegroups.com

Den 26. aug. 2017 kl. 13.33 skrev Matthew Browne <mbro...@gmail.com>:

Do you think it's necessary to do all of the analysis you suggested just to discuss the example here?

If you want to discuss a use case,
  • you will need several scenarios. A narrative covers a single scenario. One way to get several scenarios is to start with several narratives. You have only one narrative. You need more.
  • you need a user motivation. That’s what usually comes from a user story and, for me, is about all that user stories are good for
  • you will need some kind of NFRs to put into the user case and to guide preconditions and postconditions, so response time, error tolerance, and so forth are central. Again, not mandatory, but common.
  • you will need some kind of business rules to guide the articulation of invariants, if you want those in your use case (their part of the standard shtick)
If you avoid the parts that aren’t mandatory and just do something minimal, you have basically just a scenario. There are no formal criteria for what constitutes a use case. But to explore its power I think you need to get into the pre- and post-conditions, into extensions and deviations, and into exploring the end user motivation.

You don’t need to actually do all the analysis, but you at least have to pretend you have done enough analysis to have the above — and probably more. To tell you what else you would minimally need, I’d have to actually do it.

Matthew Browne

unread,
Aug 26, 2017, 7:58:30 AM8/26/17
to object-co...@googlegroups.com

Regarding the business rules, should those be listed in some separate document in advance of the use case writing?

Matthew Browne

unread,
Aug 26, 2017, 8:05:45 AM8/26/17
to object-co...@googlegroups.com
On 8/26/17 7:58 AM, Matthew Browne wrote:
>
> Regarding the business rules, should those be listed in some separate
> document in advance of the use case writing?
>
I'm guessing the answer is yes, but to provide a little more context, I
was thinking that the process of writing use cases is likely to help
think about what the business rules should be for certain questions that
might not have been answered yet. But of course many business rules are
already established at the time use cases are written.

Also, I just found this:
http://agilemodeling.com/artifacts/businessRule.htm

James O Coplien

unread,
Aug 26, 2017, 8:20:47 AM8/26/17
to object-co...@googlegroups.com

Den 26. aug. 2017 kl. 13.58 skrev Matthew Browne <mbro...@gmail.com>:

Regarding the business rules, should those be listed in some separate document in advance of the use case writing?

First, some broad context: My partner Gertrud can tell you the story of how she was once hired “to write use cases,” and then had to start all over again when they switched the vendor from some outsourced outfit in India to Maersk Data. That makes no sense.

We write for two reasons: to remember, and to communicate. Writing is O.K. for remembering. It is terrible for communicating. Communication should be face-to-face and should employ not only natural language but prototypes, plays, songs, formal models — whatever works. Use cases are just one communication tool that helps us document and structure what we have agreed about how the system under construction will behave externally.

In terms of a more vulgar answer, most business rules can directly be translated into use case invariants, precondtions and postconditions. Or you can just add a section called “business rules.” No use case police will stop you. 

James O Coplien

unread,
Aug 26, 2017, 8:21:34 AM8/26/17
to object-co...@googlegroups.com
Den 26. aug. 2017 kl. 14.05 skrev Matthew Browne <mbro...@gmail.com>:

. . . I was thinking that the process of writing use cases . . .

It’s about the discussion, not the writing.

Matthew Browne

unread,
Aug 26, 2017, 9:34:28 AM8/26/17
to object-co...@googlegroups.com
Good point. And of course the writing is a group activity too.
--
Sent from my Android device with K-9 Mail.

James O Coplien

unread,
Aug 26, 2017, 9:38:50 AM8/26/17
to object-co...@googlegroups.com

Den 26. aug. 2017 kl. 15.34 skrev Matthew Browne <mbro...@gmail.com>:

Good point. And of course the writing is a group activity too.

Right. Everyone sitting around a Jira keyboard. Not.

Matthew Browne

unread,
Aug 27, 2017, 1:29:51 AM8/27/17
to object-co...@googlegroups.com
Haha, that's obviously not what I meant. Anyway.

James O Coplien

unread,
Aug 27, 2017, 3:34:48 AM8/27/17
to object-co...@googlegroups.com

Den 27. aug. 2017 kl. 07.29 skrev Matthew Browne <mbro...@gmail.com>:

Haha, that's obviously not what I meant. Anyway.

Yeah, I should have added a smiley. But there are teams that more or less work this way instead of at a task board. An opportunity for improvement.
Reply all
Reply to author
Forward
0 new messages