One of the alleged advantages of ObjectOrientedProgramming is that it allegedly can hide every detail behind an object interface. However, links between 2 or more objects are not truly encapsulated. A developer has to deal with the link(s) between them in a more or less "raw" form. Maybe one object has an interface to access or manage the partner link, but the developer is still dealing with links in a rather crude pointer-like way. And, I feel that relational has a more organized, abstract, and consistent approach to managing links in general. - top ---------------------------- Counterpoint: One is perfectly free to reify links between objects and encapsulate them. This happens often enough that it has a name: ProxyPattern. And if an object O wishes to manage links between two objects, simply reify the link as a ProxyPattern and allow a object O the capability to manipulate that link. More complex 'link management' can also be reified and performed via systems like MultiCaster. And, in a well-factored OO system, link-management outside of systems explicitly designed for it is usually a CodeSmell. I don't believe failure to encapsulate links is 'the problem' for OO. Rather, it's the need to do so explicitly, every damn time, and the ease with which "sweeping changes" can become necessary to interject a useful indirection. DesignPatternsAreMissingLanguageFeatures, or at least exhibit MissingFeatureSmell, and OO seems to be ''all'' about DesignPatterns. ---------------------------- Sorry, you'll never convince me there's a more natural way to deal with orders and items than the following anOrder.add(anItem); //includes rules throws exceptions when violated anOrder.total(); //totals items and includes all rules/discounts/taxes etc. anOrder.remove(anItem); anOrder.items; //for displaying to screen and such aCustomer.add(anOrder); //same easy place to enforce rules Both because it's an actual model of the Domain problem, and because it provides a natural place to put business rules for these entities that can't be bypassed or forgotten. Flexible SQL queries are just accessing a global database and provides no way to cleanly encapsulate rules nor model. Relational is great when little business rules are involved, but the more complex the rules become the more important actually modelling it become. I want my relations hard wired into the code, because logically they are hard wired in the Domain. I don't want someone to be able to simple select all from items and sum them without going through the order object, because there may be all kinds of rules involved in summing. I don't want a developer to be able to do flexible querying via sql, because he'll forget to include business rules that are included in the model, guaranteed. To put it simply, the model is the only access to the data I want exposed, period, ever. Once a model is in place, raw access to sql is forbidden, the model is the only data you ever need. As for any objections about other applications needing the data... too bad, each app gets its own database and the apps are integrated at the application level, not at the database level. Each app needs its own model, I don't want shared global data via a database between multiple applications, that's just asking for trouble and bugs imho. A database is just storage for my object model. Don't need flexible querying for reports, because if your app needs a bunch of reports, then your application is missing some functionality (ReportsSmell). Find out why they need those reports and just do that work for them with a screen in the app. An app should need few reports, the app itself should be able to provide you with the data without resorting to butchering the data with a sql query. * Response to most items found at DatabaseNotMoreGlobalThanClasses. * Please clarify "if your app needs a bunch of reports, then your application is missing some functionality". Managers always want reports. They want to see everything grouped and sorted by every which way, and the more complex the business the more variations they want. I suppose on-line techniques such as QueryByExample may reduce the desire for paper, but that may be a while. Query ability is also useful for debugging because it allows you to study the "state" in a flexible way. OO encapsulation will limit the different ways one can sift, sort, filter, cross-reference, etc. to study it, unless explicitly supplied. * {You appear to be conflating the capability (or lack thereof) of your debugger with the language paradigm. OO encapsulation does not limit the ways a debugger can sift, sort, filter, or even cross-reference run-time information. A good debugger can view private elements, so encapsulation is not an issue. However, the original poster (starting with "Sorry, you'll never convince me ..." is almost laughably naive; probably a student or hobbyist programmer, or someone who's never worked in a business IT.} * If the "good debugger" is viewing private elements, then it is indeed breaking encapsulation. Your "object" is then merely acting as a "record", not an object. Further, as "good debuggers" take on more and more database-like features the more "good" they become and more DB-like they become. A language and/or debugger can indeed get DB-like features, but then it is growing toward ''being'' a DB, or at least taking on DB-like characteristics to compete with DB features. GreencoddsTenthRuleOfProgramming. It's like saying, "I still don't need an SUV, for I put big tires, advanced suspension, running lights, a powered mud-trap hook, and metal-grid light protectors on my Toyota Corolla." * {Do know what a debugger is?} * Yeah, something that allows you to break encapsulation, and "browse" your static and/or dynamic object tree/graph as if it were a NavigationalDatabase of sorts. * {That's an unusual description. A debugger is software that typically allows you to pause a running program, single-step through its code, and examine (and sometimes manipulate) its run-time state. It's primarily used during development to visualise a program's internal workings during execution -- often for debugging purposes, hence the name. It allows you to "break encapsulation" in the same manner that opening the hood on a car allows you to break the "encapsulation" represented by the dashboard and controls so you can examine and fix the engine. As for browsing "your static and/or dynamic object tree/graph as if it were a NavigationalDatabase", I've never heard it described that way before and would never have thought of it myself, despite years of using debuggers. It doesn't appear to be a significant characteristic, and I don't recall ever treating an object graph like a NavigationalDatabase in a debugging context, or feeling the need to do so. I find it typical to single-step through (say) a function for searching a data structure in order to investigate a problem with the search function's implementation. It's very rare to have to search for an item -- in the usual run-time fashion -- in a data structure at debug-time, though many debuggers provide an "immediate" mode to permit evaluating arbitrary expressions or invoking functions and methods whilst debugging.} * That's if you are viewing "debugging" as merely trying to figure out what the computer/interpreter/compiler is doing to a specific thing at a specific time. I'm also considering a somewhat bigger picture where one is studying more general logic or flow to find or spot issues. For example, what happens when coupon X is applied to frequent-usage-discount Y in county Z if product categories A, B, and F are all in the i-shopping cart at the same time. Perhaps this also relates to CompilingVersusMetaDataAid. * {The same debugging approach applies. It often requires injecting the system with test data, but a good design should facilitate that -- ideally having been produced via a test-driven approach in the first place.} * Perhaps a distinction can be made between "structural" debugging and "temporal" debugging. I try to shift most of the complexity of an app to attribute-driven data-structures (tables in particular) such that analyzing the "structure" is a bigger part of debugging time than watching bit-buckets being filled and emptied during run-time with a byte X-rayer. And as I already mentioned, these attribute structures allow me to transform my view of things to study them at different "angles" looking for patterns or lack of. A lot of problem prevention also happens this way also because I can spot odd patterns by bad or ill-trained users, or mistakes by myself even as I fill "decision tables". This reduces Sunday-morning phone-calls. It's '''pre-bugging''' actually :-) Now I admit that perhaps somebody with sufficiently FastEyes doesn't need such transformation assistance and can spot patterns in textual code as-is. However, you are probably the minority, and you cannot hand off textual programming to the middle-level "power users" described in CompilingVersusMetaDataAid. One can teach them to fill in rule tables but not Java in a reasonable amount of time. -t * {What do you mean by '"structural" debugging and "temporal" debugging'? After that, I'm afraid I don't understand a word of what you wrote, despite designing, building, and maintaining business applications for 25 years. Sorry.} ''If each app has its own database, how do you ensure that the data is kept in sync between applications? A package sent to the wrong address or an order billed to the wrong credit card number ''is'' a problem. -- JonathanTang'' * ''You still store data OnceAndOnlyOnce, but you expose a query interface when you need out-of-DB data. For example, you might have a lightweight application managing your credit card number DB and exposing (say) a REST service to the other apps. At least, this is one practical approach; I'm sure there are others. --MarnenLaibowKoser 2011 Mar 21'' If they have that much dependency between the data, I wouldn't make them separate apps. Seems they'd be using the same model, so they'd share the same model. Forgive me if I'm a little incoherent; I'm sick and a bit drugged up. ''A bit more drugs and aches and you just might start to dig relational. :-)'' ---- How does a relational database "encapsulate links" in a way that is less "crude" or "pointer-like" than OO (or procedural) code? ''Responses generally found in TablesAndObjectsAreTooDifferent''. I see nothing on that page that provides a response to my question. Why is a value in a tuple less "crude" or "pointer-like" than a key value in a map? ''A table is a more powerful building block than a map. Further, inter-map "pointers" usually don't have externally-representable (printable) "keys". And, maps usually don't have referential integrity systems. It is hard to define usable referential integrity with maps because they are too primitive. BTW, I don't think I claimed that relational better "encapsulated links". I am not sure what you are quoting.'' Read the page title and this statement again: "And, I feel that relational has a more organized, abstract, and consistent approach to managing links in general." I didn't ask about the "power" of "building blocks". I didn't ask about "inter-map 'pointers'" (whatever that is). I asked how a relational database better encapsulates links. ''But interesting that you brought up maps versus tables. I am writing an article that essentially claims the OO versus relational debate is all about maps versus relational tables when you strip away language syntax and hardware issues. It is essentially the long version of ObjectsAreDictionaries, and then goes on to complain that dictionaries have no known larger-scale guidance principles, except maybe perhaps the pattern movement, which is similar to trying to classify GoTo patterns IMO.'' OK, but how does a relational database better encapsulate links than OO? ''Again, I did not claim such to my knowledge. I still don't know what you are quoting. If I did, then the title itself would contradict it. '''I never claimed that "relational better encapsulates links" up there'''. '' Then what are you claiming? The page is called "Can't Encapsulate Links" and begins by saying that links between objects are not encapsulated. Then it says that the developer has to deal with links in a "crude pointer-like way". Then it says that "relational has a more organized, abstract, and consistent approach to managing links in general." If you aren't saying that relational better encapsulates links, why mention it? ''I am basically saying that OO encapsulation cannot encapsulate links between objects. If it makes you feel better, I will remove mention of relational.'' Or you could explain why you mention it if you don't believe it better encapsulates links... The top of this page is written as if all objects must be linked by pointers and nothing else. It ignores the fact that we use pointers when all we need are pointers, but have an infinite number of other ways to link objects. Perhaps if you explained what you mean by "encapsulate" it would shed some light on your position. ''What is an example of linking objects without using pointers or inheritance?'' * Maps. ''huh? Maps are not native to OO.'' * Having a string containing a URL. ''Same here.'' * By name. * By inclusion. So, with those answers out of the way, what do you mean by encapsulate? Did you create the title of this page? If so, why, and what does it mean? -- AdamBerger Okay, I will try to work on rewording it. Sorry for not being clear enough. -- top ---- * Maps. ''huh? Maps are not native to OO.'' What does that have to do with anything? We still use them to link objects. ''Yes, but that is not encapsulation'' Why isn't it? ''A map is like a micro-table. Is sticking stuff in tables "encapsulation"?'' No, but sticking stuff in tables can be part of encapsulation. We use maps to link objects. We encapsulate the maps. Thus the links are encapsulated without using memory address style pointers. ---- How about we turn this into a question. Can links be encapsulated? ''Sure.'' Can all links be encapsulated? ''No.'' ---- I think this subject is very important and cuts to the core of where OO still fails at collection management. "How does relational better encapsulate links than OO?" In short: Because the relational model defines an *algebra*. OO does not define an algebra, it merely defines behaviour at the per-object level and then tries to generalise and constrain this behaviour via vaguely-defined heuristic approaches such as inheritance. (Vaguely-defined because there still is no unifying mathematical model to describe why we should have single vs multiple inheritance, interface vs implementation inheritance, message sending semantics such as synchronous vs asynchronous, scoping and privacy rules, etc.) * ''Mathematical models never describe why we '''should''' have anything. Your only question ought to be whether these mechanisms (a) are composable, and (b) allow useful and provable predictions in a mathematical model in the face of composition. Those are the properties that make an 'algebra' useful.'' An algebra - such as the definition of 'relation' - defines a set of constraints and invariants which go above and beyond the simple association of two items as a map. Because of this queries can be optimised and the definition of data is decoupled from its storage and access strategies. OO via polymorphism and encapsulation provides a way for individual methods to be decoupled from their implementation; but does not provide a way for *relationships* to be defined declaratively. The problem with the relational model is that it is not a Turing-complete model of computation while OO is. To extend the relational model to a full declarative computation model, we'd need to take it to something like LogicProgramming such as PrologLanguage. This is an area of research which ground to a halt at the end of the 80s and I think still needs further work on sets and logic to make it pleasant. Prolog 'sort of' works but ain't pretty and doesn't have anything like the widespread platform bindings we expect from modern languages, and there are major warts in the low-level semantics itself - negation by failure, cuts, assert/retract etc. These really need to be fixed to go forward, I think. -- NateCull The root source of problems you describe is that '''some''' (by which I mean '''most''') OO languages lack an object configuration layer. In the absence of such a layer, '''OO provides the primitives (objects) but not the means of composition''' (see PrimitivesAndMeansOfComposition). DataflowProgramming or boxes-and-ports based composition of objects works far more effectively. With a good ObjectConfigurationLayer, encapsulation of links is trivial. They're encapsulated by the configuration. Of course, building a good ObjectConfigurationLayer is crippled by SideEffect''''''s in constructors. (ConstructorsAreEvil.) And interesting composition with external services is also hurt by 'new'. (NewConsideredHarmful). And not being TuringComplete shouldn't ever be considered a 'problem'. Them be some backwards values. Being TuringComplete is usually a problem. Relational does benefit from LogicProgramming, though... such as DataLog or variations (see DeclarativeGui for a set of extensions on that path). Still no need for TuringComplete, at least not at that layer! ---- MarchEleven See also: OoHasLimitedAssociationModeling