From: Robert C. Martin on 17 Jun 2005 15:44 On 17 Jun 2005 10:52:37 -0700, "topmind" <topmind(a)technologist.com> wrote: >> >> >> >> > TREES ARE A CRUTCH >> >> >> >> Trees are a red herring. They aren't the issue. There was a time in >> >> the late '80s when OO enthusiasts were very hopeful about inheritance >> >> hierarchies. That feeling passed in the early '90s. The last nail >> >> was driven into it's coffin by the Design Patterns book. >> >> >> > >> >But as I mentioned and described, non-tree OO is really messy. >> >> No, it's really clean. >> >> >It is like Goto's reborn. >> >> No, it's like having a tool that allows me to strongly decouple. > > >Coupling is not always bad. True. And coupling sometimes is bad. When it is, it's nice to have a set of tools that can manage it. >Polymorphism couples one to mutual exclusitivity, so there! As the CompositeAccount example showed, this is not exactly true. > >Relational is discipline on tables, OO is a 60's style navigational >mess that lacks discipline. Tsk, tsk. OO is not equivalent to network databases. You have to get your head out of that silly idea. OO is not about data at all. OO is about the partitioning of behavior. >> No, I rather like the Visitor. I think it's an elegant solution to a >> very tricky problem. > >You have a strange notion of "elegant". Hmmm. The visitor is one polymorphic method to determine type, and another to dispatch function. Clean, simple, fast. Elegant. >> Some people are democrats, and others are republicans. Who can >> explain why? People who don't like Visitor are just wrong, IMHO. > >Can you objectively prove this? I can't prove that they are wrong to dislike it; since dislike is not a rational emotion. I can certainly prove that visitor is the best tool to use for certain situations. Indeed, I have walked through such proofs in a number of books and articles. See: http://www.objectmentor.com/resources/articles/visitor >Beam Visitor and navigational messes the hell off my planet! What a nice, rational, objective, remark. ----- Robert C. Martin (Uncle Bob) | email: unclebob(a)objectmentor.com Object Mentor Inc. | blog: www.butunclebob.com The Agile Transition Experts | web: www.objectmentor.com 800-338-6716 "The aim of science is not to open the door to infinite wisdom, but to set a limit to infinite error." -- Bertolt Brecht, Life of Galileo
From: topmind on 17 Jun 2005 18:16 > > >If there are only a few factors, then either approach (case or classes) > >is simple, so that is not what we are discussing. > > Actually, since it was your example, we *were* discussing it. But if > you'd like to change the rules right now, that's fine. > > >It is bigger more complex things. > > Fine, let's discuss the bigger, more complex, things. > > > Here's the polymorphic solution for the more complex case: > > public class CompositeAccount { > public ArrayList<Account> components; > public decimal calcFee() { > decimal fee = 0; > foreach Account a in components > fee += a.calcFee; > return fee; > } > } > > Notice the lack of the exponential explosion? > > What does the procedural version look like? > > decimal fee = 0; > if (isTypeA(account)) > fee += calcFeeForTypeA(account); > if (isTypeB(account)) > fee += calcFeeForTypeB(account); > if (isTypeC(account)) > fee += calcFeeForTypeC(account); > . > . > . > > Hmmm. An array of function pointers. That has been around long before OOP. (One could argue that OOP languages have more ability to verify such at compile-time. I don't necessarily disagree with such a claim because I don't really care because I prefer dynamic languages anyhow.) Or, how about: qr = query("select * from employees") while (row = getNext(qr)) { executue(row.strategyName & '()'); } But generally things don't wind up that clean in the real world (as described in the new "change patterns" topic). What I find is that factors usually *interweave* such that a strategy pattern is insufficient. For more on this see: http://www.geocities.com/tablizer/struc.htm#if If factors didn't interweave, then software develepment could much easier almost to the point of being formulaic. The biggest problem I find with custom business software is that any factor can affect potentially any other factor. There is no inharent guarentee of separation of concerns in the domain. If you picture business logic as a big graph, then any node can potentially be required to touch any other node in the graph. The best we can do is make predictions about what is more or least likely. Logic is just plain not added or subtracted in clean, isolated chunks much of the time. -T-
From: Robert C. Martin on 17 Jun 2005 21:14 On 17 Jun 2005 15:16:19 -0700, "topmind" <topmind(a)technologist.com> wrote: >> >> >If there are only a few factors, then either approach (case or classes) >> >is simple, so that is not what we are discussing. >> >> Actually, since it was your example, we *were* discussing it. But if >> you'd like to change the rules right now, that's fine. >> >> >It is bigger more complex things. >> >> Fine, let's discuss the bigger, more complex, things. >> >> >> Here's the polymorphic solution for the more complex case: >> >> public class CompositeAccount { >> public ArrayList<Account> components; >> public decimal calcFee() { >> decimal fee = 0; >> foreach Account a in components >> fee += a.calcFee; >> return fee; >> } >> } >> >> Notice the lack of the exponential explosion? >> >> What does the procedural version look like? >> >> decimal fee = 0; >> if (isTypeA(account)) >> fee += calcFeeForTypeA(account); >> if (isTypeB(account)) >> fee += calcFeeForTypeB(account); >> if (isTypeC(account)) >> fee += calcFeeForTypeC(account); >> . >> . >> . >> >> Hmmm. > > >An array of function pointers. That has been around long before OOP. An array of function pointers *is* OOP. Or rather OOP is discipline imposed upon tables of pointers. > >Or, how about: > > qr = query("select * from employees") > while (row = getNext(qr)) { > executue(row.strategyName & '()'); > } Same differences, that's just a manual implementation of something an OOPL will do for you automatically. >But generally things don't wind up that clean in the real world (as >described in the new "change patterns" topic). What I find is that >factors usually *interweave* such that a strategy pattern is >insufficient. So you give up? Or do you try to find regularity within the chaos. In many cases that regularity really is there. ----- Robert C. Martin (Uncle Bob) | email: unclebob(a)objectmentor.com Object Mentor Inc. | blog: www.butunclebob.com The Agile Transition Experts | web: www.objectmentor.com 800-338-6716 "The aim of science is not to open the door to infinite wisdom, but to set a limit to infinite error." -- Bertolt Brecht, Life of Galileo
From: topmind on 17 Jun 2005 23:25 Jeff Brooks wrote: > topmind wrote: > >>You make claims all the time and have no proof. > > > > Like what? Even if I did, does that give you license to also be an > > idiot? > > You can't remember what you posted and your calling me an idiot?! It was figurative, like saying don't follow the lemmings off the cliff. That does not mean I am calling you a lemming. > > Jeff Brooks -T-
From: topmind on 17 Jun 2005 23:50
> >> > >> >If there are only a few factors, then either approach (case or classes) > >> >is simple, so that is not what we are discussing. > >> > >> Actually, since it was your example, we *were* discussing it. But if > >> you'd like to change the rules right now, that's fine. > >> > >> >It is bigger more complex things. > >> > >> Fine, let's discuss the bigger, more complex, things. > >> > >> > >> Here's the polymorphic solution for the more complex case: > >> > >> public class CompositeAccount { > >> public ArrayList<Account> components; > >> public decimal calcFee() { > >> decimal fee = 0; > >> foreach Account a in components > >> fee += a.calcFee; > >> return fee; > >> } > >> } > >> > >> Notice the lack of the exponential explosion? > >> > >> What does the procedural version look like? > >> > >> decimal fee = 0; > >> if (isTypeA(account)) > >> fee += calcFeeForTypeA(account); > >> if (isTypeB(account)) > >> fee += calcFeeForTypeB(account); > >> if (isTypeC(account)) > >> fee += calcFeeForTypeC(account); > >> . > >> . > >> . > >> > >> Hmmm. > > > > > >An array of function pointers. That has been around long before OOP. > > An array of function pointers *is* OOP. Or rather OOP is discipline > imposed upon tables of pointers. > > > >Or, how about: > > > > qr = query("select * from employees") > > while (row = getNext(qr)) { > > executue(row.strategyName & '()'); > > } > > Same differences, that's just a manual implementation of something an > OOPL will do for you automatically. What is "manual" about it? It can be simplified by making a generic/library function for such: executeStrategies(entityName, strategyColumn) .... function executeStrategies(entity, col) { qr = query("select * from " & entity); while (row = getNext(qr)) { executue(row[col] & '()'); } } It is hard to get more "automatic" than that. And Lispers do similar things with ess-expressions all the time. > > >But generally things don't wind up that clean in the real world (as > >described in the new "change patterns" topic). What I find is that > >factors usually *interweave* such that a strategy pattern is > >insufficient. > > So you give up? Or do you try to find regularity within the chaos. > In many cases that regularity really is there. > As described under the new "Change Patterns" sub-topic, I disagree. If there *is* lasting regularity, it is NOT subtyped shaped. Perhaps I am just missing the real patterns, but I already have seen hierarchies and sub-types crash and burn several times. People and things created by people are capricious and chaotic. That is the inherent nature of people and their products. If you model the laws of nature (math, chemistry, phyz., etc.), stable hierarchies (forced or real) may exist because God does not change those laws very often. However, people fart around every which way and every manager, law-maker, marketer etc. has a VERY DIFFERENT personality from each other such that their laws, rules, sales pitches, etc. are all different from the last and will be different from the future ones. And again squared, sets can be trees and other things that trees cannot easily be. Thus, they are a better bet. If I am wrong then sets cost only a little bit more than trees, but if I am right then trees are far costlier than the alternatives for handling the chaos. Thus, my hedge is rational. Ascii bar graph illustrations: (Cost of changes) TREES: Actual Tree-centric changes **** Chaos ************************************** SETS: Actual Tree-centric changes ******* Chaos ************** > > > ----- > Robert C. Martin (Uncle Bob) | email: unclebob(a)objectmentor.com -T- |