Subj : Re: What the bleep is Coupling? (was: Polymorphism sucks) To : comp.programming,comp.object From : topmind Date : Sat Jul 09 2005 01:47 pm Chris Sonnack wrote: > topmind writes: > > >> * Coupling creates dependancies between separate parts of the system. > >> * Dependancies increase the difficulty of maintanence. > >> ~~~ > >> * Therefore, coupling is to be *avoided*, subject to other constraints. > >> > >> What part of that is problematic for you? > > > > 1. Precise definition of "coupling" > > Neither is there a precise definition of, say, "what a CEO does" or > "what is love". In fact, according to quantum physics, nothing in the > universe is precisely defined. You're just going to have to learn to > accept that. In that case, my fuzz can beat up your fuzz. > > > 2. That all dependencies are necessarily bad. > > We've said repeatedly they are not. It's situational and dependant on > other constraints. 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. Say it over and over until it sinks in. That is a perfectly logical conclusion. (Perhaps you can reject DB's for performance reasons in some cases, but not for org management ability for human developers.) > > > >> In general, the duplicate selects do require knowing about the new > >> type. Consider your bank account example. If the bank adds a new > >> account type, what are the odds that most--if not all--the rest of > >> the system needs to know about it? > > > > Case list A is blind to case list B in code. The code does not know or > > care how the bank changes before anything actually happens. They are > > *not* objectively coupled. The compiler/interpreter will never make a > > pointer or look-up between case list A and B (barring odd internal > > optimization tricks). > > Yeah, and? As repeatedly explained, 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. Case lists can and do drift apart over time. > > 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. Often, perhaps usually, they don't. How is duplicating lists of methods better? Dup is dup. If you penalize dup case lists, you must also penalize dup method lists for each sub-type. You cannot have it both ways. But the most important thing is that case lists "degenerate" more easily. Poly doesn't. It is more code rework to replace IS-A with HAS-A than to turn case lists into IF statements, often without existing code. 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} .... } 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... > > Whereas, if you know the code deals only with abstractions that you > haven't changed, your change is restricted to one easily tested area. > > >> The usual answer is: Very high. > > > > I disagree. > > 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 is usually poor business system modeling. Don't add "types", add features; and then use the database to manage which customer gets which feature. That is part of how you create flexible business systems. > > > The real world does not change in a tree-shaped way for the most > > part. > > This really isn't about trees. The model here is of an abstraction, > a "bank account" with a number of concrete realizations. No. It is only in the head of OO sub-type zealots (and a few managers who get duped in). Reality is different. Reality does not necessarily give a flying fluck about "types". > It's, IMO, > unlikely you'd have more than these two levels, although in some > cases you might derive a very specialized account from an existing > account type. Well, if it will stay small and simple (which I doubt for a bank), then it does not matter much whether poly or case lists are used. The penalty for being wrong WRT future change with either would then be small. Banks can have at least these features: * 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. > > All that's happening is that we've added a new concrete realization > of the "bank account" abstraction. "Concrete" because you have cement between your stubborn earns. Can't you see how lowsy sub-type modeling is as you scale up? It is so damned obvious that it behooves me how you miss it. I don't get it. You don't seem to grasp the enormity of combinatorial explosions WRT feature combinations. > > > > As I already illustrated with the "checkingAndSavings" example, > > polymorphism would result in more code rework, not less. You > > lost that one. > > This isn't about winning or losing. Whatever you call it, poly is harder to adjust. How about "reality challenged" instead of losing. Better? > > > >> Obviously. IME (and obviously in the E of others), adding a new > >> "thing" to the system *usually* implies that the system needs to > >> know about it (otherwise, why bother adding it?). > > > > Thing != Type > > Yeah, and? > > 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". But doing such does not necessarily make it the most change-friendly design decision. > > > It is you polymorphism zealots... > > Mischaracterization. Semi-zealot? > > > Sets can do the same thing, often in a more flexible way. Different > > instances/records will have a different set of features not bound to > > any tree. Sets allow one to "reference" dispatched behavior instead > > of hard-wire them into code via locations in the polymorphic tree. > > 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 effort and blow me over with your vast abilities and expose me for the dummy I am. In other words, it is more effective to SHOW how dumb somebody is rather than simply claim it. You game? If your change count is lower, it does not matter whether I "get OOD" or not. Lower is lower. I don't need to know how your car engine works to know that your hotrod reaches the finish line before mine. "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. The eastern mysticism approach to OO justification has gotta end. We have to get out of the software engineering dark ages to progress our discipline. Time to grow up. > > 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. The advantage to declar is that there are more known "maths" available for attribute-orientation than behav orientation, and this results in more consistent designs and consistent collection manipulation. 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. OO'ers claim this gives them flexability, but IMO it removes consistency from designs. OO has always had a consistency problem. 3. Polymorphism generally only works well with one poly "tree" at a time. If there are multiple orthogonal factors affecting dispatching, then poly gets ugly or has to arbitrarily favor one factor at the expense of others. > > 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. This is because the relationship between a record and behavior dispatching is rarely one-to-one. It is most only 1-to-1 in OO textbooks, not reality. I often use such "control tables" to compete with OO textbook examples for flexible dispatching contests. But reality doesn't favor them. (IMO OO is shaped by a bunch of falsehoods, or at least unproven claims, about the nature of real-world change. OO often assumes changes are tree-shaped and/or only the implementation changes and not the interface. In practice the interface is often just as volitile as the implementation, and that is where dynamic sets help.) > > IF changes were often, that could make it a win. IF the system is > relatively stable, it probably isn't. > > >> Don't see that thread here in comp.programming. > > > > 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 :-) > > -- > |_ CJSonnack _____________| How's my programming? | -T- .