tag:blogger.com,1999:blog-23912478.post991418519017976634..comments2024-01-03T12:45:39.815+00:00Comments on peripatetic axiom: TDD, Mocks and Designkeithbhttp://www.blogger.com/profile/14314542307822401015noreply@blogger.comBlogger53125tag:blogger.com,1999:blog-23912478.post-67097150307636399642008-11-13T20:36:00.000+00:002008-11-13T20:36:00.000+00:00This is an interesting read Keith. The comments ar...This is an interesting read Keith. The comments are very insightful as well. As somebody who recently learned and used Objective-C quite a bit, which uses many of the Smalltalk lingo, I've started to appreciate message passing quite a bit.<BR/><BR/>It helps a lot when doing TDD. I find myself setting up mocks quickly since there's very little to set up. With getters (setters not so much), more often than not we would have to setup not just the mock containing the getter, but also the object being returned by the getter. Without knowing the details on how the object being fetched by getter is used by the class under test, it becomes really hard to write test quickly.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-23912478.post-91295643524630527122008-09-04T20:54:00.000+01:002008-09-04T20:54:00.000+01:00You might want to check with Jerry Weinberg about ...You might want to check with Jerry Weinberg about TDD being "the first really new development technique to come along for a long time...".<BR/><BR/>Seems it was there at the start and was then lost for a time, to be rediscovered recently.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-23912478.post-83291738204245038942008-07-02T20:52:00.000+01:002008-07-02T20:52:00.000+01:00@KeithThanks for that...interesting to learn more ...@Keith<BR/><BR/>Thanks for that...interesting to learn more about Syntropy and how it relates to data and behaviour.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-23912478.post-3760888758056751542008-06-29T22:36:00.000+01:002008-06-29T22:36:00.000+01:00Please note there is a related discussion in a WIK...Please note there is a related discussion in a WIKI setup to discuss aspects of the Entity Framework functionality that MS are adding in the .NET space:<BR/><BR/>http://entities.pbwiki.com/Getters+and+Setters+Anti-Pattern<BR/><BR/>You need to sign up to comment but you might be interested in having your say.Colin Jackhttps://www.blogger.com/profile/01403166737046938219noreply@blogger.comtag:blogger.com,1999:blog-23912478.post-4749496459532813332008-06-29T11:11:00.000+01:002008-06-29T11:11:00.000+01:00@PhilipI'm not sure what sort of answer you're loo...@Philip<BR/>I'm not sure what sort of answer you're looking for.<BR/><BR/>Syntropy (presumably missing from West's survey?) puts equal emphasis of data and behaviour. And very different emphases on other things.<BR/><BR/>It's actually a three-pass model (which should be iterated, of course): one pass to understand (someone's view of a situation in) the problem domain, one to specify a system/components to deal with that, and one to design an implementation of a system that meets that specification to deal with that situation. <BR/><BR/>All three passes produce models that capture both data and behaviour together. Data in class diagrams, behaviour in statecharts (and other things). <BR/><BR/>A specification model is the closest to what folks seem to do with UML these days: objects send and respond to messages. As I understand it Cook and Daniels decided that these semantics were inappropriate for specification. In those kinds of model behaviour is captured using events, which objects respond to, maybe by causing other events to occur. And this was viewed as inappropriate for modelling the world, in essential/domain/business models objects change state when events occur, but do not themselves cause events to occur (almost a monadic view—Leibnitz monads, not Haskell ones). <BR/><BR/>In this way models speak throughout of what objects know, and how they respond, but only when appropriate do we say exactly how they work internally to achieve that. In particular, in an essential model object <EM>may not</EM> generate new events. This is what I meant by delaying allocation of responsibilities.<BR/><BR/>As you might imagine, candidates to come to interview with me and who have asserted an expertise in "object modelling" tend to have an interesting time.keithbhttps://www.blogger.com/profile/14314542307822401015noreply@blogger.comtag:blogger.com,1999:blog-23912478.post-78215624672695706082008-06-24T21:32:00.000+01:002008-06-24T21:32:00.000+01:00@KeithUse Case Driven Object Modeling with UML -Th...@Keith<BR/><BR/><I>Use Case Driven Object Modeling with UML -<BR/>Theory and Practice says: "(preliminary design) is driven by thinking about attributes while deliberately ignoring "who's doing what to whom". Then the second pass focuses all your attention on that exact question"</I> <BR/><BR/>You replied:<BR/><I>Well, in Syntropy we seek to delay describing a solution in terms of explicit message sends until as late as possible, so as to avoid premature allocation of responsibilities. But <B>that doesn't mean a first cut that ignores behaviour</B>. Instead, in Syntropy behaviour is first captured in terms of objects and (broadcast, instantaneous, asynchronous) events. A very different notion.</I><BR/><BR/>It seems that you too share my concern for the two pass approach advocated by the book:<BR/><I>We advocate a two-pass approach to design: The first pass (preliminary design) is driven by thinking about attributes while deliberately ignoring "who's doing what to whom". Then the second pass (detailed design) focuses all your attention on that exact question. </I>.<BR/><BR/>This approach is criticized by David West in his excellent book <A HREF="http://www.amazon.com/Object-Thinking-DV-Microsoft-Professional-David/dp/0735619654" REL="nofollow">Object Thinking</A>. On page 155 He groups the plethora of object development methods advanced in the nineties into three general categories: <B>data-driven (e.g. OMT), software-engineering, and behavioural (e.g. CRC)</B>. <BR/><BR/>Of the data driven group, he says (p124): <I>In a data-driven approach, the attributs of an object are discovered first, and then the responsibilities are meted out as a function of which object holds which data. A behavioural approach mandates the assignment of responsibilities first. Only when you are satisfied with the distribution of responsibilities among your objects are you ready to make a decision about what they need to know to fulfil their responsibilities and which parts of that knowledge they need to keep as part of their structure - in instance variables or attributes. This is the biggest difference in the definition between data-driven and behaviour-driven, or responsibility-driven approaches to objects.</I><BR/><BR/>Of Data-driven methods he also says (p156): <I>data-driven methods do not bring about the object paradigm shift...followers of this type of method "think like data", or "think like a relational database"...[the data-driven approach] isn't consistent with decomposition of the world in a natural way because the world isn't composed of computationally efficient data structures. There are no "natural joins" in the domain that map to <B>normalized entities</B>.<BR/>...<BR/>Data-driven methods tend to craete objects with more frequent and tighter coupling than do other object methods. </I><BR/><BR/>Keith: how does your following statement relate to these ideas: <I>in Syntropy we seek to delay describing a solution in terms of explicit message sends until as late as possible, so as to avoid premature allocation of responsibilities</I>Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-23912478.post-289163842526471902008-06-24T20:35:00.000+01:002008-06-24T20:35:00.000+01:00@Colin JackYou said:"Although I've started reading...@Colin Jack<BR/><BR/>You said:<BR/><BR/>"Although I've started reading Holubs book a couple of times I never stuck with it so it was good to read a summary, makes me want to follow through with it at some stage."<BR/><BR/>I must stress that it is not my summary, I reproduced it verbatim from the book (p34). I found it very useful because Holub's style (in my opinion) means that some ideas are repeatedly described, but sometimes only partially, over many pages. This means that when you look for something in his book, you sometime have to re-read large-ish sections of it: you can't zero-in on where he said this or that.<BR/><BR/>You said:<BR/><BR/>"instead of setting Customer.Name to be a new Name you pass in a message describing the name change and allow the Customer to process that as it sees fit. Seems sensible but you'll presmably end up with a lot of mesage classes"<BR/><BR/>No, when Holub says messaging systems he is using 'message' as the fundamental way of getting things done in an OO system. As Meilir Page-Jones says in <A HREF="http://www.amazon.com/Fundamentals-Object-Oriented-Design-Addison-Wesley-Technology/dp/020169946X" REL="nofollow">Fundamentals Of OO Design in UML</A>:<BR/><BR/>A message is the vehicle by which a sender object O1 conveys to a target object O2 a demand for object O2 to apply one of its methods.<BR/><BR/>And as Rebecca Wirfs-Brock says in <A HREF="http://www.amazon.com/Designing-Object-Oriented-Software-Rebecca-Wirfs-Brock/dp/0136298257" REL="nofollow">Designing Object-Oriented Software</A>:<BR/><BR/>A message consists of the name of an operation and any required arguments. When one object sends a message to another object, the sender is requesting that the receiver of the message perform the named operation and (possibly) return some information.<BR/>...When a receiver receives the message, it performs the requested operation in any manner it knows... by executing a method.<BR/><BR/>e.g.you can send the print message to a document and it will execute its print method.<BR/><BR/>I rarely hear developers talking about sending messages in their programs. At least not Java programmers. Smalltalk programmers probably actually <BR/><BR/>E.g. consider the following program: <B>Document d = getNextDocument(); d.print();</B> where Document is an abstract class with many concrete subclasses or an interface with many implementations.<BR/><BR/>Instead of saying that the program sends, to the object referenced by d, a message asking it to execute it no-args print method<BR/>we just say the program calls the document's print method.<BR/><BR/>The reason why some people still talk in terms of messages is that they want to stress the important difference between calling a routine, which is which is what procedural programs do, and which will simply result in the execution of a specific method that is known at compile-time, and making a polymorphic call, which is what OO programs do, and will result in the execution of a yet-unspecified method that can only be determined at run-time. <BR/><BR/>When I saw Kent Beck stressing this distinction in his <A HREF="http://www.amazon.com/Smalltalk-Best-Practice-Patterns-Kent/dp/013476904X" REL="nofollow">Smalltalk Best Practice Patterns</A>, I thought it might partly be due to the fact that the concept of message is key in Smalltalk, but he still makes this distinction in <A HREF="http://www.amazon.com/Implementation-Patterns-Addison-Wesley-Signature-Kent/dp/0321413091" REL="nofollow">Implementation Patterns</A>, which is aimed at Java developers.<BR/><BR/>You said:<BR/><BR/>"If I use the Customer class then it will have getters (and presumably setters) and Holub advises against that for domain classes (where possible). So would you instead use a different class and leave the Customer domain class to do just the domain logic (no CRUD or display maybe)?"<BR/><BR/>I have not yet seen domain objects that don't provide getters for fields that need to be displayed in a UI. Holub seems to be suggesting that the way we get away with domain objects without getters is either by either getting the domain objects to display themselves (in simple cases), or by using the Builder pattern to separate a business object from implementation-specific details such as how to display the business object on the screen. I am afraid I'll have to refer you to his book (p212) for more details, because I have yet to read that section. Basically, instead of ASKING the BO for its details so you can display them, you TELL (don't ask, tell - The Law of Demeter) it to build you a representation of itself that you can then pass to the UI.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-23912478.post-30737272970571022922008-06-21T18:19:00.000+01:002008-06-21T18:19:00.000+01:00@keithbI'm guessing you'll be blogging more about ...@keithb<BR/>I'm guessing you'll be blogging more about this so I'm definitely looking forward to reading about the specifics of the approach you guys use.Colin Jackhttps://www.blogger.com/profile/01403166737046938219noreply@blogger.comtag:blogger.com,1999:blog-23912478.post-57902195746621244882008-06-21T11:36:00.000+01:002008-06-21T11:36:00.000+01:00@Colin: The issue for me is that CRUD is a solutio...@Colin: The issue for me is that CRUD is a solution domain concept.<BR/><BR/>I want the business problem expressed in the business objects in the model of my application. It may be that some of these objects are long-lived, and it may be that therefore some data from them might be persisted to a database. Why should this be of concern to the user? And yet the idea permiates so many systems, all the way up to the UI.<BR/><BR/>The error seems to creep in even at the requirements level. I see too many users and analysts who've been trained by their IT folks into thinking in terms of data on forms as not merely one presentation aspect of one solution option, but as the only way of thinking about their problem. We, as an industry, have really screwed up on this one.<BR/><BR/>It we approach problems with the idea at the solution will have at the front end data in forms (maybe even with a "save" button!) and at the back end data in tables, it's not too hard to see why the bit in the middle ends up they way it so often does. <BR/><BR/>So no, I wouldn't have a business model and a CRUD model. I'd have a business model and treat the CRUDdiness as an implementation detail best well hidden from the user. And from most of the implementors.keithbhttps://www.blogger.com/profile/14314542307822401015noreply@blogger.comtag:blogger.com,1999:blog-23912478.post-16105890585206213172008-06-21T10:50:00.000+01:002008-06-21T10:50:00.000+01:00@keithbI may be going into too much detail, if so ...@keithb<BR/>I may be going into too much detail, if so I appologize but it is an interesting topic...<BR/><BR/>Oh and just to be clear upfront, although I use getters/setters on my domain classes we don't do direct databinding so we do have a lot of control. For example we can use patterns such as using value objects (in the DDD sense) which does help a lot.<BR/><BR/>Anyway can I add another option, would you even involve the domain classes in the CRUD work or would you just have two seperate models one customized for CRUD and other other for the more complex behavior (assuming your app doesn't just do CRUD and validation)? This splits your model in ways that could be un-natural and if you are totally against getters/setters then I guess its not an option, but I know some people do seem to go down this road.<BR/><BR/>On the higher level messaing approach, another advantage would be that they can be sent outside the system allowing you to get into the advanced design approaches that others use. So after a Customer object has processed a message relating to an address change that message (or a transformation of it) is sent out to other interested parties. Greg Young (and others) are driving forward this sort of thinking within the ALT.NET community and you might find his blog entries interesting (see DDDD posts):<BR/><BR/>http://codebetter.com/blogs/gregyoung/<BR/><BR/>Anyway all very interesting stuff and looking forward to reading more about it and how you personally use these practices in real systems.Colin Jackhttps://www.blogger.com/profile/01403166737046938219noreply@blogger.comtag:blogger.com,1999:blog-23912478.post-3820225331106320182008-06-20T13:44:00.000+01:002008-06-20T13:44:00.000+01:00@Colin: It does seem as if its awkward to do CRUD ...@Colin: It does seem as if its awkward to do CRUD operations on domain classes, doesn't it? One theoretical answer is indeed to have the domain object push a data transfer object through an interaction domain to the gui. Seems a bit clunky. We might also expect an MVP style of thing, with interactors coming inbound which record the user's intention rather than brute-force updates to the model.<BR/><BR/>The subtlety here (I think) is that in a world free of getters and setters we have to be more imaginative than merely providing the user with a long and convoluted path through a bunch of objects only to be running SELECTs and UPDATEs on an RDBMS. We really want to present rich objects that the user can interact with to augment their work.keithbhttps://www.blogger.com/profile/14314542307822401015noreply@blogger.comtag:blogger.com,1999:blog-23912478.post-33859962551902327212008-06-20T08:51:00.000+01:002008-06-20T08:51:00.000+01:00@Philip SchwarzAlthough I've started reading Holub...@Philip Schwarz<BR/>Although I've started reading Holubs book a couple of times I never stuck with it so it was good to read a summary, makes me want to follow through with it at some stage.<BR/><BR/>Anyway you say:<BR/><BR/>"you tend to design messaging systems that don't use getters and setters because statements such as "Get this" or "Set that" don't come up in the problem domain"<BR/><BR/>This is kida what I was expecting and it makes a lot of sense, so instead of setting Customer.Name to be a new Name you pass in a message describing the name change and allow the Customer to process that as it sees fit. Seems sensible but you'll presmably end up with a lot of mesage classes (I guess I could read the book to find out :)).<BR/><BR/>"The closer you get to the procedural boundary of an OO system (the database interface, the UI-construction classes, and so on), the harder it is to hide implementation. The judicious use of accessors and mutators has a place in the boundary layer."<BR/><BR/>OK so lets take a Customer domain class, I need to display it suitable in a GUI. If I use the Customer class then it will have getters (and presumably setters) and Holub advises against that for domain classes (where possible). So would you instead use a different class and leave the Customer domain class to do just the domain logic (no CRUD or display maybe)?Colin Jackhttps://www.blogger.com/profile/01403166737046938219noreply@blogger.comtag:blogger.com,1999:blog-23912478.post-90099990623770934912008-06-18T03:54:00.000+01:002008-06-18T03:54:00.000+01:00Nice post. Your post has been linked to in my post...Nice post. Your post has been linked to in my post about the same topic: http://moffdub.wordpress.com/2008/06/16/the-getter-setter-debate/Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-23912478.post-79160282020894312742008-06-18T00:04:00.000+01:002008-06-18T00:04:00.000+01:00In Holub on Patterns (great book), the author (als...In <A HREF="http://www.amazon.com/Holub-Patterns-Learning-Design-Looking/dp/159059388X" REL="nofollow">Holub on Patterns</A> (great book), the author (also the author of <A HREF="http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html" REL="nofollow">Why getter and setter methods are evil</A>) talks a lot about getters and setters. Here is how he describes the basic issues around setters and getters:<BR/><BR/>* The maintainability of a program is inversely proportional to the amount of data that flows between objects.<BR/><BR/>* Exposing implementation harms maintainability. Make sure that the accessor or mutator really is required before you add it.<BR/><BR/>* Classes that directly model the system at the domain level, sometimes called business objects, hardly ever need accessors or mutators. You can think of the program as partitioned broadly into generic libraries that have to relax the no-getter/no-setter rule and domain-specific classes that should fully encapsulate their implementation. Getters and setters at this level are an indication that you didn't do enough up-front design work. In particular, you probably didn't do enough dynamic modeling.<BR/><BR/>* By keeping the design process in the problem ("business") domain as long as possible, you tend to design messaging systems that don't use getters and setters because statements such as "Get this" or "Set that" don't come up in the problem domain.<BR/><BR/>* The closer you get to the procedural boundary of an OO system (the database interface, the UI-construction classes, and so on), the harder it is to hide implementation. The judicious use of accessors and mutators has a place in the boundary layer.<BR/><BR/>* Completely generic libraries and classes also can't hide implementation completely so will alwats have accessors and mutators.<BR/><BR/>* Sometimes it's not worth the trouble to fully encapsulate the implementation. Think of trivial classes such as Point and Dimension. ...<BR/><BR/>BTW, by dynamic modeling he means the kind of modeling that you do when you act out use cases with Class Responsibility Collaboration (CRC) cards.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-23912478.post-5208927106654861282008-06-17T23:18:00.000+01:002008-06-17T23:18:00.000+01:00It's seductively easy to bash in a controller for ...<I>It's seductively easy to bash in a controller for a use case and then bolt on a few passive entities that it can use without really considering the essence of the domain. What you end up with is the moral equivalent of stored procedures and tables.</I><BR/><BR/>That's right, if you use the <A HREF="http://martinfowler.com/eaaCatalog/transactionScript.html" REL="nofollow">Transaction Script</A> pattern, you end up with an <A HREF="http://www.martinfowler.com/bliki/AnemicDomainModel.html" REL="nofollow">Anemic Domain Model</A>.<BR/><BR/><I>That's not necessarily wrong, and it's not even necessarily bad depending on the circumstances.</I> <BR/><BR/>That's right, according to the <A HREF="http://martinfowler.com/bliki/DesignStaminaHypothesis.html" REL="nofollow">Design Stamina Hypothesis</A>, it is sometimes not worth investing in a rich <A>Domain Model</A>.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-23912478.post-45178878613849852942008-06-17T07:25:00.000+01:002008-06-17T07:25:00.000+01:00@winterstream: I think I do agree. After all, obje...@winterstream: I think I do agree. After all, objects want to be actors when they grow up. <BR/><BR/>I don't think that this is a co-incidence, either. There was a heavy Smalltalk influence at connextra, although they worked in Java, so a message-passing model was in their minds.<BR/><BR/>As error handling goes, yes I think that this approach does help because we spend more time with state on the stack (so we are also moving towards a functional approach).keithbhttps://www.blogger.com/profile/14314542307822401015noreply@blogger.comtag:blogger.com,1999:blog-23912478.post-19970896777443665052008-06-16T23:38:00.000+01:002008-06-16T23:38:00.000+01:00This is an interesting thought. It almost verges m...This is an interesting thought. It almost verges more towards an actor-based approach. When I write process-oriented code, my messages end up telling the receiver to do something and I can't think of times when I ask explicitly about a process's inner state (the equivalent of getters and setters).<BR/><BR/>I suspect (and I would like to know whether you agree) that writing code in this fashion also eases the drawing of error handling boundaries around various modules. I'm asking, because at least to me, process oriented programming makes this easy (and I see getter-free style programming as similar).Winterstreamhttps://www.blogger.com/profile/04982097826539673880noreply@blogger.comtag:blogger.com,1999:blog-23912478.post-35312797607132308352008-06-16T21:38:00.000+01:002008-06-16T21:38:00.000+01:00@Philip: Thanks for these pointers. I'm not famili...@Philip: Thanks for these pointers. I'm not familiar with ICONIX, nor have I read that book.<BR/><BR/>Pondering these quotes has lead me to a new realization of how much my ideas about discovering objects has changed over the years. What's described here looks as if it could well be a misinterpretation of what's in the Syntropy process, which i used extensively in my first programming job. It's enlightening to see more clearly how far and where I've come. Thanks.<BR/><BR/>What's described here is rather different from what I see in the wild, so I've amended the posting to suite. <BR/><BR/>Meanwhile, some thoughts on the quotes themselves.<BR/><BR/><I>"preliminary design (RA) is all about discovery of classes (aka object discovery), ... detailed design is, by contrast, about allocating behaviour"</I> — firstly, allocating behaviour is not a matter of "detail"<BR/><BR/><I>"[...] that is, allocating the software functions you've identified into the set of classes you discovered during preliminary design"</I> — but why would I introduce a class other than to support a "software function"?<BR/><BR/><I>"[...] there are no controller objects on the sequence diagram [...] because when you draw the sequence diagrams, the controllers (the verbs) are turned into messages on the boundary and entity objects (the nouns)."</I> — I really don't like this noun/verb thing. To start with, it's a bogus analogy: This sentence no verb. And further more, verbing weirds nouns. That said, it's good that they would recommend getting rid of the controllers. Why not not have them in the first place?<BR/><BR/><I>"sometimes a framework might tempt you to litter your design with dozens of tiny "controller classes""</I> — damn straight they sometimes. Again, good advice to avoid this.<BR/><BR/><I>" (preliminary design) is driven by thinking about attributes while deliberately ignoring "who's doing what to whom". Then the second pass focuses all your attention on that exact question"</I> — Well, in Syntropy we seek to delay describing a solution in terms of explicit message sends until as late as possible, so as to avoid premature allocation of responsibilities. <BR/><BR/>But that doesn't mean a first cut that ignores behaviour. Instead, in Syntropy behaviour is first captured in terms of objects and (broadcast, instantaneous, asynchronous) events. A very different notion.keithbhttps://www.blogger.com/profile/14314542307822401015noreply@blogger.comtag:blogger.com,1999:blog-23912478.post-49921256909599466982008-06-16T20:47:00.000+01:002008-06-16T20:47:00.000+01:00Hi Keith,great blog entry, full of meaty stuff; I ...Hi Keith,<BR/><BR/>great blog entry, full of meaty stuff; I agree with a lot of what you said.<BR/><BR/>I just wanted to clarify something about robustness analysis (RA). I am no expert on the subject but I have recently finished reading <A HREF="http://www.softwarereality.com/UseCaseDriven.jsp" REL="nofollow">Use Case Driven Object Modeling with UML -<BR/>Theory and Practice</A>, which promotes the use of the ICONIX process, in which Robustness Analysis (RA) plays several essential roles.<BR/><BR/>In essence, the authors say that robustness analysis (wich they call one of the industry's most useful and yet best kept secrets) is preliminary design, whereas detailed design (e.g. using sequence diagrams) is where you do responsibility allocation.<BR/><BR/>The best thing you can do is to read the book (unless of course you have already done that). I am just going to quote some of your statements and follow them with some excerpts from the book that seem to contradict your statements. <BR/><BR/>You said: <I>A design found by robustness analysis is built out of "controllers", big old lumps of logic, and "entities", bags of named values. (And a few other bits and bobs) Can you see where this is going? There are rules for robustness analysis and one of them is that entities are not allowed to interact directly, but a controller may have many entities that it uses together.</I> <BR/><BR/>Book says: preliminary design (RA) is all about discovery of classes (aka object discovery), ... detailed design is, by contrast, about allocating behaviour (aka behaviour allocation) - that is, allocating the software functions you've identified into the set of classes you discovered during preliminary design.<BR/><BR/><I>You said: It's seductively easy to bash in a controller for a use case and then bolt on a few passive entities that it can use without really considering the essence of the domain. </I><BR/><BR/>Book says: ...notice that there are no controller objects on the sequence diagram (although there could be). This is because when you draw the sequence diagrams, the controllers (the verbs) are turned into messages on the boundary and entity objects (the nouns). Sometimes you'll find real controller classes, such as a "manager", or a "dispatcher" class, and sometimes a framework (self: e.g. Spring MVC) might tempt you to litter your design with dozens of tiny "controller classes", but as a general rule of thumb, 80% or so fo the controllers from the RA diagrams can be implemented as one or more operations on the entity and boundary classes.<BR/><BR/><I> You said: In RA we assume that objects either know stuff or do stuff.</I><BR/><BR/>Book says: Having performed RA, you should by now have identified at least three quarters of the attributes (the data) on your classes, but very few, if any, operations (the behaviour). ...we advocate a two-pass approach to design: The first pass (preliminary design) is driven by thinking about attributes while deliberately ignoring "who's doing what to whom". Then the second pass (self: detailed design i.e. drawing sequence diagrams) focuses all your attention on that exact question.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-23912478.post-12147923453395770802008-06-16T19:00:00.000+01:002008-06-16T19:00:00.000+01:00If you have a domain/business class that you wante...<I>If you have a domain/business class that you wanted to do CRUD for but you also have more complex logic in it would you still avoid getters/setters?</I><BR/><BR/>Hmm... It would depend on the situation, really.<BR/>If exposing the object were a security risk, I'd go with a DTO, or maybe even put a DTO facade on the object itself if I could maintain integrity (I'd think long and hard before trying something like that, though!)<BR/><BR/>If the security risks were low enough not to warrant that level of paranoia when crossing boundaries, and if there was little chance of that part going distributed, I'd consider other, more OO-like designs.<BR/><BR/>Technically, I shouldn't really be considering distributed systems at the early design phase, but it happens so often, and can be so expensive to refactor for that I tend to err on the side of safety.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-23912478.post-27934846695911140102008-06-16T18:40:00.000+01:002008-06-16T18:40:00.000+01:00@Isaiah"Things like persisting an Account to DB, S...@Isaiah<BR/>"Things like persisting an Account to DB, Serialising it to some formatt, or displaying it on a GUI, dont make sense in the domain of Account so I wouldnt place all these responsibilities on to the Account."<BR/><BR/>So from this I'm thinking that you have multiple models. For example you'd have the one with the complex business object, one to handle CRUD and so on? <BR/><BR/>Personally I find that I can often have one class supporting both CRUD/display (though not databinding) and domain/business logic but that does mean getters/setters on those domain classes.<BR/><BR/><BR/>@Wolter<BR/>"You wouldn't put them in business objects, or the user interface, or even DAOs (excepting setters for IOC). You WOULD, however, put getters and setters in data transfer objects."<BR/><BR/>This bit interested me. If you have a domain/business class that you wanted to do CRUD for but you also have more complex logic in it would you still avoid getters/setters? If so how do you approach the situation, do you have multiple classes or would you perhaps send the domain/business classes in little DTO's (messages) explaining at a high level what changes you want them to make?Colin Jackhttps://www.blogger.com/profile/01403166737046938219noreply@blogger.comtag:blogger.com,1999:blog-23912478.post-16493757581910041572008-06-16T17:29:00.000+01:002008-06-16T17:29:00.000+01:00Actually, I should qualify that more:If this scena...Actually, I should qualify that more:<BR/><BR/>If this scenario happens entirely inside the business layer, and the object is never exposed outside, then there's no problem.<BR/>Once you pass through the business membrane, however, the rules of engagement change drastically.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-23912478.post-21095365930176216132008-06-16T17:10:00.000+01:002008-06-16T17:10:00.000+01:00all it does know is about the role of a Transactio...<I>all it does know is about the role of a TransactionReceiver, by Account.appendTransactionTo(TransactionReceiver), its simply sending it transactions information to this object. So any object can implement the TransactionReceiver interface and provide their own specific implementaion</I><BR/><BR/>Which is fine on paper, but once issues of distributed computing and security creep in, that solution won't look quite so elegant anymore.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-23912478.post-89884174311574591192008-06-16T17:02:00.000+01:002008-06-16T17:02:00.000+01:00"However I'd probably aim to keep my Account class..."However I'd probably aim to keep my Account class concentrated on the important domain/business logic ...."<BR/>I agree I would also keep Account concerned with key domain concepts. An Account has transactions, the role of TransactionReceiver is meaningful to an Account so Account.appendTransactionTo(TransactionReceiver)<BR/>makes sense, IMO it seems right to give the Account this responsiblity. Things like persisting an Account to DB, Serialising it to some formatt, or displaying it on a GUI, dont make sense in the domain of Account so I wouldnt place all these responsibilities on to the Account.<BR/><BR/>"If your account knows about the report, then a change to the report will likely require a change to account ...."<BR/>The Account doesnt know about reports or anything else, all it does know is about the role of a TransactionReceiver, by Account.appendTransactionTo(<B>TransactionReceiver</B>), its simply sending it transactions information to this object. So any object can implement the <B>TransactionReceiver</B> interface and provide their own specific implementaion of how the transactions information is processed, if the transaction information should be displayed as a summary or whatever..<BR/><BR/>"You wouldn't put them in business objects, or the user interface, or even DAOs (excepting setters for IOC). You WOULD, however, put getters and setters in data transfer objects." I agree, i dont think anyone is saying there should be no getter/setter at all, there are certianly cases where getter make a lot of sense even in a domain object. The whole point is that getters/setter in genral are overused.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-23912478.post-43580016085701254112008-06-16T16:41:00.000+01:002008-06-16T16:41:00.000+01:00Agreed.For the most part, this discussion comes do...Agreed.<BR/>For the most part, this discussion comes down to knowing the rules vs knowing the game.<BR/>You can teach someone poker in 5 minutes, but if they simply follow the rules, they'll get creamed.<BR/><BR/>The "avoid getters and setters" rule is in general a good rule to a point, but you'd hardly call them "evil". You wouldn't put them in business objects, or the user interface, or even DAOs (excepting setters for IOC). You WOULD, however, put getters and setters in data transfer objects.<BR/><BR/>When people start quoting rules-of-thumb as gospel, or harp on about purity, they betray their lack of experience. Most builders know how to use a circular saw. The seasoned builder knows not to use it to cut into a wall near a power outlet. If you're not thinking consequences, you're not thinking right.<BR/><BR/>That's why it is wisely written: You gotta know when to hold 'em, know when to fold 'em, know when to walk away, know when to run.Anonymousnoreply@blogger.com