From: James Coplien Date: 2010-02-20T02:20:15+09:00 Subject: Re: "Code must be Chunkable" Let me respond to bits of Marnen's excellent post at a time. Marnen Laibow-Koser wrote: > Thanks for replying! I've probably injected myself into a debate that's > a bit over my head, but that's how learning happens. For all of us > James Coplien wrote: >> Marnen Laibow-Koser wrote: >>> James Coplien wrote: >>> [...] >> >>> I cannot imagine *not* representing a bank account as an object in a >>> bank software system. The balance is part of such an object's state. >> >> No. In every example I've seen, financial records are kept as audit >> trails that track deposits, withdrawals, interest accruals, etc. There >> is no "balance" sitting on a disk nor sitting in memory. The balance is >> computed as the sum of accruals, less the sum of decreases, against some >> baseline. All these data are in a database — but no balance. > > That's implementation. It is irrelevant to interface, no? It affects the internal form of the system. That form is called its architecture: the parts and their relationships. Those parts have interfaces, and the way we think about them affects the way they are implemented in the code. For example, if we implement a bank system in terms of incremental audit trails and dynamic association between those elements and roles that appear in dynamically created account Contexts, it's a much different design than if an Account is a data object. It shows through. Kent Beck has long argued that you can't hide a bad design behind a good interface. Brenda Laurel emphasizes the importance of the direct manipulation metaphor. Alan Kay talks about these objects as extensions of the images of your own mind. That is what DCI is trying to do. More to the point, the way that the market thinks about them (the stakeholders) affects their rates of change. Much of design is about eliciting change points so that frequently changing stuff is easy to change, is localized, and is separated from the stuff that doesn't change so much. That isn't all in the interface, unfortunately. In fact, it is often just the opposite. Most of the interface of a Prius car is the same as that for an ordinary gasoline-powered automobile, but the internal architecture is radically different. >> Let me reiterate my question, which yet goes unanswered here: Can you >> name me one, real, concrete system in real use, in a real financial >> institution, where the account is an object, and its field is a balance, >> within a system that manages the account itself? > > First, your question probably goes unanswered because the only people > who could answer it are people who've worked on the proprietary systems > in question. I have the impression that not much financial software is > open source. O.K., well, I can speak for what I have seen in Saxo Bank, in Swiss Bank Chicago, in Swiss Bank London, in Allianz, in a large Danish pension company and in many other discussions with financial people at conferences. Even Ron Jeffries' XP book features a user story that describes an account balance in these terms. If you have done your domain analysis, these things are obvious to someone in the business. Another obvious failure is that people designing a telecom system thinking that a phone call is an object. It isn't an object in any phone system I've seen. I've seen many inside AT&T and Western Electric, and publications from Bell Northern Research / Nortel indicate that also avoid this failure mode. The same was true at Avaya, AGCS, ... shall I go on? The problem is that objects became really popular in the industry in about 1990 and now everything that is a Thing has to be an object. The naivté was fueled by early methodologists who told us a number of silly things: everything is an object; objects should be created in isolation; objects are the nouns in your requirements document; and so forth. And so we have a claim here about accounts being objects, unsubstantiated in reality, but based in such an overwhelmingly strong mythology that it prompts multiple denials about the claim of how real systems implement this. It is a matter of maturity. It is easy to stumble into a great tool like Ruby and to look for ways to apply its class facilities to everything in site. But there are much more subtle structures at work here. What's really cool about Ruby is that rises even to this challenge. (Most languages can express DCI concepts in some degree. There's only one popular language that can't, and I'll let you figure that out. Class, that's your homework assignment for tomorrow.) The popular, naive claim doesn't work in practice — which is why you don't see it in practice. Let's contemplate your account example with a balance as a member. What is the object's scope? Its lifetime? How many of these objects exist in a banking system? How is concurrency handled (that's the killer): when the actuaries and account holder and the bank want to access it at the same time? What is the scope and duration of a transaction in terms of the object? If you have transaction semantics (and all banks do, to avoid losing money under concurrency) what is the mapping from the object model to the transactional model and the relational model that usually supports it? Remember: Ontos and its cousins were largely failures, because they tried to stay in the paradigm of your grandfather's object-oriented architecture. The complexity just got out of hand. DCI actually offers reasonable answers to all of these questions, because it's rooted in structures that can capture and express higher levels of complexity, both static and dynamic, than a POJO approach can. I think that's what got this thread started: I described a solution to a problem that is more complex than people can conceptualize using their grandfather's object-oriented programming, and understanding broke down. I think that people fail to understand it's a paradigm shift — but that's maybe a liability of taking one's understanding from a few hours of videotapes. > Second, it's irrelevant whether balance is a field or a calculation, at > least if the uniform access principle is still to hold. That claim holds only within a single contextual thread. Another set of immature foundations can be found in the Agile world where we are supposed to be focused on the customer. And most of the naive claims about accounts here come from that perspective. I can just read the user stories and use those to drive my design, using TDD or something else. Just find all the elements of all the interfaces and just organize them. The fact is that most of the computation in a bank has nothing to do with someone who has an account, but who is in the back office managing investments or doing analyses. They're called actuaries in English. Actuaries care little about the status of your bank account. They care about the transactions. There are many other sets of users who are looking at these data: auditors, tellers, ATM machines, other banks, the national bank, investors, loan officers, bank executives. All you need to do is to take all the responsibilities of all those stakeholders and divide them up into nice interfaces that give you nice objects that have nice coupling and cohesion. It's intractably complex. DDD has recently drawn attention to the importance of unearthing domain concepts that are stable over time. They have little to do with the requirements of the stakeholders. Very few people understand that. The "dumb" data objects of DCI come from this domain analysis; they are often the model objects one finds in MVC. The intelligence that serves the actuaries, the accountants, the loan officers and everyone else play out in use cases that are defined in terms of roles — roles that are mapped onto the right domain objects at the right time by the right context. The essence of an object-oriented system is that the mappings from roles to objects changes thousands or millions of times a second. Your grandfather's OO simulated a very weak version of that called inclusion polymorphism. The DCI mapping brings these dynamics to the surface. > As a > hypothetical user of class Account, I want to be able to call > Account#balance and get a balance. I don't care in the least what has > to go on to get me that balance. So you don't care about its data. It is essentially a service, a computation. We collect those services together in DCI and call them Contexts. You instead are trying to convince me that they should be objects. O.K., a Context is an object by some definition, and if that's enough for us to agree, then we agree. But it is not a domain object — that creates an architecture where the pressure points of change are all in the wrong place. A simple domain analysis of a financial application will bear that out quickly. More to the point, it is useful to distinguish between objects (as Dahl or Nygaard would recognize them) and the roles that they play. If programming language is to be about intentionality (communicating the design intent of the programmer) then we want the programming formalisms to carry this distinction forward. That's what DCI is: a set of formalisms that carry archetypical elements of human cognition and machine computation forward into the code. Calling it an object is a little like calling it a thing. I want a little more insight from these labels. > I think of an account as being an object. Doesn't that make it the > proper mental model for me? No, you're a programmer. And that's O.K.: programmers are people, too, and we need to support ehir model. But, again, object orientation is all about capturing mental models in code, and we need to be attentive to stakeholders other than the programmer. Like Raskin said: The interface is the program. A user experience person would pursue this issue using the kind of question I posed in an earlier post, leading to the description (e.g., for a money transfer) that I think about things in terms of source accounts and destination accounts. Unfortunately, my bank doesn't have source accounts. I can conceptualize a source account, but can't create one, can't open one, can't find one. They're not *objects*. They're protocols, or interfaces to objects. They're roles. Those, too, are part of our mental models. And they should be part of the code as well. If you look at where Rebecca Wirfs-Brock has taken responsibility-driven design, it is into this realm of roles. Objects don't have responsibilities; their roles do. That was the conversation that Trygve and I recall from his discussion with Rebecca on the deck of the Hurtigruten all those years ago. There are some additional concepts that we should be attentive to as well, including algorithms and the associations from roles to objects. DCI packages most of these in roles and Contexts. If all you have learned is objects, then everything to you is an object. That is whey I said you might make a good student of Kant. A good exploration of end-user mental models shows that they are much more subtle. Introducing roles provides a much better match for this model and provides a much better foundation for good software structure than the pure object approach does. Trygve published some preliminary metrics about this on object-composition, and you might have a look at them and at the surrounding discussion. > Uh, what? You can't transfer money to your phone bill. You can > transfer money to your account at the phone company -- and you can do so > precisely because it is (or behaves like) an account. No, the entity I manipulate on my web page is exactly my phone bill. (Denmark has an advanced banking system, so maybe those of you in other countries still do this with checks to the phone company and so forth — but even for one of my accounts outside Europe, I can treat the phone bill as an entity.) That's my mental model. It's not that I'm paying the phone company; I pay my phone bill. No one says at the end of the month "I need to pay my phone company." They say "I need to pay my phone bill." >> My point is that >> it doesn't have to be, and that in fact, very few accounts are. They >> rather are Contexts than Data objects. > > And I really don't see where you come to that conclusion. > >> >> This facet of the underpinnings of DCI is not about language expression, >> but of about how we think. That's the paradigm shift part. > > Yes, but I so far do not agree with your premises here, which means I > can't agree with the paradigm that develops from them. I'm certainly > willing to be convinced, though. I'm still awaiting concrete examples that are different than those banking examples that provide much of the background for my premises. In any case, it shouldn't matter if you are trying to understand. Adopt my assumptions arbitrarily if it helps you see the ideas more clearly and I can provide the documentation later. I think that if you explore the real world you'll see that my assumptions hold. I hope this helps. I really appreciate your specific and forceful questions — I think it helps me communicate my ideas more concretely. -- Posted via http://www.ruby-forum.com/.