Subj : Re: What the bleep is Coupling? (was: Polymorphism sucks) To : comp.programming,comp.object From : topmind Date : Wed Jul 13 2005 12:18 am Chris Sonnack wrote: > topmind writes: > > >> Dependencies are *unavoidable*. The trick is to manage them. > > > > Exactly. That is why one should manage relationships via > > database INSTEAD OF STATIC CODE if possible. > > If possible and sensible, I agree. In many of the situations > we've discussed it's neither. In most situations, it not one > or not the other. If it is simple, then the diff between case statements and poly is minor. If not, a DB usually does a better job over the longer run. > > > >> ...the coupling between case statements is *invisible* to > >> the compiler, which is *exactly* why it's bad. It > >> requires *external* means (documentation, programmer memory) > >> to manage. > > > > And often invisible to REALITY. > > In the cases we're considering, this simply isn't so. (I can't > believe I'm actually arguing with someone who thinks lots of > case statements to dispatch types are a win--I'd have thought it > was blatently obvious they are quite the opposite.) It is only "blatently obvious" in OO textbooks. The real world does not change in a sub-type-wise shape. Real world ain't fit the poly books, got it?! Make a polymorphic hierarchy of people, and you will eventually see it. Pretend you are modeling a game such as the SIMs. > > > Case lists can and do drift apart over time. > > Even so, if they are dispatching on the same sort of thing (like > a bank account) you still need to examine each and every one of > them when you make a change regarding bank accounts. One could say similar things about polymorphic trees. If you add a new method, you have to check the whole poly tree to see if it needs to be added to others or already exists. And, you may have to visit multiple nodes to add the same-named method. Can you say with certainty that adding new sub-types is more common than adding new behavior (with potential case/if statements)? Or, you may duplicate code that already exists and thus could be shared somehow. Poly places such behavior further apart, taking longer to see if there is duplication. How do you know a new method you add is not *already* on another tree node? You don't unless you check the entire tree. I almost guarentee a study of simulated random changes to variations would favor IF statements over poly WRT to change effort. I would bet money on it. If you bet enough, I will even build a similation. > > The problem is simply that the necessary changes are "out there" > in the main code rather than being contained in one place. And > in any real production system, there's LOTS of "out there"! Poly spreads related behavior all over the place. Using the worn-out shape example, the "draw" methods are further apart than they would be in a case list. Thus, what is it with your "contained in one place" statement? You should have anticipated my complaint if you truly understood the limits of poly. > > >> More to the point here, the need to locate and diagnose all > >> those case statements when you DO make a change is expensive. > > > > ONLY if they keep changing in lock-step with each. > > No, always. You still have to check them to see if they need to > be modified (and you have to find them all first). Poly has a different set of possible non-local change impacts, as described above. > > > How is duplicating lists of methods better? Dup is dup. > > The duplication isn't the problem (and there is *considerably* less, > because there are always many more points in the code where you need > to dispatch something than there are dispatch destinations). Looks pretty even to me: http://www.geocities.com/tablizer/inher.htm > > The problem is lots of changes spread though the code as opposed to > (even lots of) changes in one place. Why do you only think of changes that favor poly? Why can't you see beyond poly's sweet spots? If you were a basket-ball coach, you would keep trying to win your games with only 3-point shots. > > > But the most important thing is that case lists "degenerate" more > > easily. Poly doesn't. > > "Degenerate"? Do you know what you're talking about, or are you > just repeating words you heard somewhere? Please explain--I know > all those words, but there's no sense to me in what you just said. Random changes in variations. One way to think about it is a hypergrid: http://www.geocities.com/tablizer/struc.htm > > > It is more code rework to replace IS-A with HAS-A than to turn > > case lists into IF statements,... > > ?!?! I don't consider these even comparable. I'm still not at all > following what you're saying. You don't know how to change is-a to has-a? I thought that is a corner-stone of OO knowledge. Hint: "strategy". > > > I count moving code as more expensive than changing stuff in place, > > such as the IF criteria. If you count differently, then please > > justify it. > > > > function stuff(...) { > > if (criteria_1) {feature_1} > > if (criteria_2) {feature_2} > > if (criteria_3) {feature_3} > > .... > > } > > Lunacy. If you add criteria_4 and feature_4, now you need to find > each and every one of these constructs and see if it needs to be > modified. What if we add new functions instead? It is mathematically impossible to isolate every factor into one spot in 1D code, BTW. You are only focusing on your favored dimension. > > Worse, it requires that each occurance of this construct needs to > *know* about all criteria and all features. This is the worst kind > of software design. Like I said, they usually drift apart over time. Multiple factors interweave. The change is random, not tree-shaped. If you don't know what the means, I don't have time to explain it right now. Study the hyper-grid example as a start. > > > > I am mostly just changing the criteria expressions to change which > > instance gets which feature. You are shuffling your poly tree up down > > and all around to get the sharing of features at the right level, and > > adding new "combo" classes such as > > featureOneButNotFeatureTwoUnlessItsThursdayAndTheMoonIsFull... > > As has been explained **repeatedly** that's simply not how it works. > (That might be how someone who doesn't understand OOD could go about > it, but that doesn't make it right.) Didn't you want to make a checkingAndSavings class? Are you backing out of that now? > > >> You disagree that, if the bank adds a new type of account, most of > >> the system needs to know about it? How will it process those new > >> accounts? > > > > I disagree that a bank SHOULD add a new "type". > > That's not the question I asked. I've dropped out of software entirely > and am posing a basic business-requirements question: > > If the bank adds a new sort of account (e.g. an account that combines > checking and savings), does the rest of the system need to know about > it? > > Put another way, how does the system at large know a given account is > checking, savings or checking+savings. How does it know? Attributes in a database that tells what a given account is. And, more then likely it is (or should be) a "feature" attribute, not a "type" attribute (although the difference can be vague). > > > > Reality does not necessarily give a flying fluck about "types". > > Of course it does. I have any number of typed values. Height, gender, > weight, hair color, eye color, job title, home location, etc. Each > of these has a restricted domain of values. That's a Type. Whatever you call it, it is not best modeled with polymorphism. > > > * Checks > > * Interest (savings) > > * CD's > > * Credit cards > > * Overdraft insurance > > * Online banking > > > > If my math is right, that is 35 potential combinations if we use > > "types". If you add a new service, it could instantly double. > > You're assuming it requires a combinatorial design. It does not. > (This has been explained a number of times.) > Ding ding ding! Most REAL THINGS DO!!! Poly over-couples features together, more so than they are in real life. > > >> I've been using "thing" deliberately to get away from OOD. When I > >> say "thing" I mean just that, a "thing". A new feature is a thing. > >> > >> A newly permitted combination of existing things is a thing. > > > > Only if you package it together and call it a "thing". > > No, no, no. A car is a thing. A blade of grass is a thing. A tv > show is a thing. A song is a thing. An atom is a thing. > Okay, like an "entity". Entities have attributes. We might call some of these "features". > Find a dictionary. Look up "thing". That's ALL I mean by "thing". > > > >>> It is you polymorphism zealots... > >> > >> Mischaracterization. > > > > Semi-zealot? > > For the umpteenth time. I use whichever tool is appropriate for the > job and don't love or hate any of them. Then you should know that often sets are more appropriate than polymorphism. > > You love databases, tables & sets and hate trees, OO & polymorphism. > > Who's the zealot? It's always "the other guy" who is excessive, isn't it? If so, I am not an objectively wrong zealot. > > (And FWIW, in my experience, anyone--literally anyone--with that sort > of love/hate perspective is almost always wrong. Just plain wrong. > It's possible you're the first exception I've encountered in my 50 > years on earth, but I rather doubt it. To be honest, at this point, > I'm kind of thinking you're a deliberate troll.) > Well, you seem to be dead set on polymorphism. And, I don't "hate" polymorphism. I am only complaining that it is way over-hyped, especially outside of systems software. > > >> Your opinion seems ill-informed to me. You don't appear to me to > >> understand OOD principles very well. > > > > Good. Then show me how OOD objectively reduces typical code change > > I have. You waved your hands, stuck your fingers in your ears and > went "Nah, nah, nah, nah, I can't hear you." No, you didn't show "typical". If you disagree with my probability of change path assessment just say so. Instead you say thing such as: [requote] > (I can't > believe I'm actually arguing with someone who thinks lots of > case statements to dispatch types are a win--I'd have thought it > was blatently obvious they are quite the opposite.) That comes across as a zealot when I read it. Maybe you don't realize it, but it does to non-yous. > > > > "Getting it" needs to be proven on the street, NOT in your > > head. Nobody cares if OOD makes your head happier. We want a > > real tool, not an opiate. > > I've been a programmer for 30 years. I've been using OOD for about > half that time. It HAS proven itself over and over again. If it > hadn't, I wouldn't use it. Period. Maybe you were just a crappy procedural programmer. I cannot say for sure without inspecting your code. I've met some, so I know they exist. And, experience didn't make them better because they were set on bad patterns. > > Let me put it this way. I'm a suspicious cynic (a big part of why I'm > not buying your line at all so far). When I first started reading about > this new-fangled C++ language and OOP, I figured it was just another > fad and who needs that crap. > > It was *learning* it and *using* it that changed my mind. I was convinced > by my personal (and now long-time) experience with it--nothing else. It > made my life as a programmer better and easier time and time again. > Well, it didn't help you articulate clear evidence for it. "It just feels good" is not scientific. Learn how to articulate better. > > >> In reality, once you get down to cases, both techniques are similar. > >> Late-binding in polymorphism is usually implemented against some sort > >> of table of methods (in some languages a "method" is just an offset > >> into that table, so no lookup required). And using a table with a > >> list of features is sort of a form of polymorphism. > > > > To some extent you are right. But the difference between the two is > > generally: > > > > 1. Relational tends to use declarative (attribute-driven) > > interfaces while OO leans toward behavioral interfaces. > > I think you're parrotting something you read. Give me an example of > what you mean. Show me two cases, one declarative and one behavioral. Let's stick with trees for now. The message is already too long. > > > 2. Relational requires that each record/object belong to > > one and only one entity while object "records" can belong > > to zero or many other class groupings. > > ?!?! What about 1:M relationships in RDBs? They are still built with tables. > And I frequently use a > single table for multiple purposes. For example, I might have a table > of "communications links" which contain email addresses, phone numbers > and web URLs. > > Object "records"? What are those? Do you mean what are often called > the classes (design) or the instances (objects themselves)? May I suggest: http://www.geocities.com/tablizer/beyondhw.htm > > > OO has always had a consistency problem. > > News to me. Give me an example. How is one example going to prove consistency? Anyhow, that too is another topic. Let's stick with poly for now. > Not something you plucked off the net. > Something you create from whole cloth. Show me you have a clue what > you're talking about--I'd really like to believe you. Who knows, maybe > you'll teach me a new trick. > > > 3. Polymorphism generally only works well with one > > poly "tree" at a time. > > Utter nonsense. Many designs do very well by interface inheritance, > which allows classes to "wear many cloaks". Only if you have a complex layering of classes. Again, see the "hypergrid" article. > > Consider the MS COM design. There's no implementation inheritance, > no "root" class, per se, but all COM objects implement the IUnknown > interface. They implement others as needed. > > It's, IMO, a *very* slick design. That is a "device driver" kind of example. I have already agreed OO probably does well there. But such does not scale to "business objects". > > > >> The only major differences are that adding a record to a table is > >> probably faster than adding a new class, but needs to be balanced > >> against the additional overhead of the table-based solution. > >> > >> In most cases, dispatching against a formal table is a non-ideal > >> solution for production software, so it needs a big win in some > >> other regard to compete with native solutions. > > > > In practice I find that putting code in tables is not necessary and > > not helpful, even it it was easy. > > Code in tables? Where did that come from? Perhaps you can clarify this line: > >> In most cases, dispatching against a formal table is a non-ideal > >> solution for production software, so it needs a big win in some > >> other regard to compete with native solutions. > > I become increasingly curious as to just exactly how you'd implement > something like this bank account thing. I'd like to see some db > schema and some pseudo-code showing how you handle various sorts of > accounts and dispatch against your table data. On a larger scale, I expect it would more or less resemble the hyper-grid example. Just replace the payroll-oriented factors with the likes of these guys: > > * Checks > > * Interest (savings) > > * CD's > > * Credit cards > > * Overdraft insurance > > * Online banking And remember that the "dispatch tree" would tend to differ for each different operation. OO fans seem to think they would be almost the same. In my experience, they are not. They may share some similarities, but not near enough to do simple polymorphism. > > Or, bluntly, less hand waving and more examples, because I begin to > wonder if you're not just another amUSENET troll lonely to keep a > conversation going. > I have not seen your larger-scale polymorphism version either. > > >>> Try comp.object (which this topic has been cloned to.) > >> > >> Not interested. After many years of amUSENET, it's gotten very old, > >> so I only hang out here in comp.programming these days. > > > > You'll miss all the fireworks :-) > > Works for me. I've had decades of "fireworks". Shakespeare was right: > Sound and Fury signifying nothing. Or at least very little. Hmmm. Were's my Shakespeare sets quotes when I need them? > > -- > |_ CJSonnack _____________| How's my programming? | -T- .