Continued from AreOoAndRelationalOrthogonalDiscussion
Words are failing us it seems. Time to look at example toy code. It is possible to define a table to hold a hierarchical menu web-page structure:
parentRef // foreign key to menuItemID
And then have a function something like:
// Example: "Peacock"
displayMenu("select * from menu", 0)
The first parameter is a query, and the second is the "current" menu item. In this case, zero, for the root.
It is also possible to have an OOP API that works something like this:
// Example "Finch"
menu1 = new menu()
menu1_1 = new menu.menuItem("Sports", sportsScript)
menu1_1_1 = new menu.menuItem("Baseball", baseballScript)
menu1_1_2 = new menu.menuItem("Soccer", soccerScript)
Generally, either you would use one or the other, but not both. Yes, you can use both, but it is duplication where the OO structure mirrors the structure represented by the data table. Thus, assuming we stick with reasonable OnceAndOnlyOnce
, one precludes the other in practice.
In the OOP version, you create a network or tree of objects that reference one another and have attributes like "title". In the relational version, the "pointers" and attributes are in the table, not objects. I see no reason to do both unless you are forced by requirements or circumstances to use a certain OOP API, and thus have it copy that info into an OOP structure from the table.
CompositePattern addresses this use case very well. Implement an abstract base class with GetChildren?() and Insert() methods to be used by derived views, sub-views, and menu items. These methods in turn manage an objects relative position within a hierarchy. DecoratorPattern objects that derive from the composite base will certainly have their own unique member persistence requirements, requiring changes to the OO layer to be synchronized with the RDBMS.
You could also have an OO API that does something like:
// Example "Parrot"
menu1 = new Menu()
menu1.queryString = "select * from menu"
However, this is "less OO" than the first OO version. It is our displayMenu() procedure in OO clothing. It does less with OO and more with relational because it is trading an OO structure shaped like the menu for a relational one.
Why is it "less OO" to load the list of menu item names from a query? Would it be "less OO" to load them from a flat file? The Menu's "shape" is identical, regardless of the way it obtains its initial values. We must have very different views of what OO code is. -- EricHodges
It lacks multiple instantiation/cloning, polymorphism, inheritance, etc. I would definitely score it lower in OO-ness. Like I said, it is a mere function call in an OO dress.
Loading menu item names from a query doesn't reduce the use of polymorhpism or inheritance. "Multiple instantiation" and "cloning" are not measures of OO'ness. If the flat file version had polymorphism and inheritance then the RDBMS version does, too.
You make it sound like flat-files can easily replace all the stuff that databases can do. As for the rest, I think it depends on one's definition of OO. I showed above how OO parts of an example were moved to a table. The "shape" of the menu was then controlled by the table and not OO code. The database took away stuff from the OO code. If that is not your style of OO coding or what you call "proper OO", then so be it. The rest is probably an issue of the "true nature of OO", which is another topic. The first approach at least matches the "roots" of OO in simulation languages: self-handling representations of real-world nouns. "Self-handling" is now called "responsibility" in most circles. A class/object represents a "node" in the menu, a "menu item". It handles its relationship with other menu nodes by having object references (pointers) to them. Has the definition of OO changed that much since its Simula-67 birth? There are still many fans of the original approach more or less.
What "OO parts" were moved to a table? Are you saying that these initialization statements:
menu1_1 = new menu.menuItem("Sports", sportsScript)
menu1_1_1 = new menu.menuItem("Baseball", baseballScript)
menu1_1_2 = new menu.menuItem("Soccer", soccerScript)
make the code more object oriented? There's nothing OO about hard coding initialization. Regardless of where the names and tree structure of the menu items reside (source code, flat file, database), the code that presents them and responds to user interaction can be just as OO as you want it to be. And if you're inside the method that creates the menu items from the relational query, you'll still see new MenuItem? and addSubItem().
Perhaps the API can read directly from the table.
By API, I guess you mean the Menu class? Yes, that was my understanding of the original example. The Menu class can read menu item names and structure from the results of a query to an RDBMS.
Just because OO GUI API's are in style right now does not mean they are they only way to do it.
I didn't say they were.
Anyhow, without looking at specific example code, it is hard to say what is "OO" and what isn't. I do tend to view any method or routine with "database verbs" as being more OO though. Thus, methods or routines with addX, removeX, findX, etc. tilt toward an OO score. Excessive use of them is an antipattern in my opinion.
Methods with names like add, remove and find indicate the use of collections. You can use collections (and add to them, remove from them or find in them) with procedural programming, functional programming, etc. You will see those verbs or synonyms for them used in any program that manages collections.
We have a specific example to look at. The Menu and MenuItem? classes you've imagined form our OO example.
But you were talking about what is inside of Display or DisplayMenu?
method/routine. For the sake of argument, let's say we don't have that, that they are libraries supplied to us and we are not supposed to touch the source. This is common from an application developer's perspective. But remember, API's could read from the database to draw the actual menus.
You've shown that an OO program can load data from an RDBMS query, or it can store the same data in source code. Neither strategy makes the program more or less OO. It still has the same class structure, the same use of inheritance, polymorphism, encapsulation, etc.
I saw no polymorphism and encapsulation in the source above, and inheritance was used to simply emulate a function call. So far, the pattern fits this:
// Example "Robin"
// procedural (note that we could also have optional named parameters, not shown)
X(param1, param2, param3....)
// your translation
x = new X
x.attrib1 = param1
x.attrib2 = param2
x.attrib3 = param3
That is hardly majestic OO in my book. One could take an entire procedural program and translate it almost one-to-one using the above pattern. Why the heck would that rate high on the "being OO" scale? It is a side issue anyhow because the second OO version does less
than the first one, which is really the important point, not whether turning function calls into method calls makes for an OO design. Perhaps we need some 3rd opinions in here. It looks cut-and-dry to me. I suspect your view of what is OO is "unique".
Even if we can't see inside the display() method, the method exists. I'm working on the assumption that the OO code in your example is actually OO code and exhibits the generally accepted characteristics of OO code. I haven't seen anything in your examples that shows a reduction of those characteristics when menu item names and structure are loaded from the results of an RDBMS query. I don't understand what the example code for X means or what pattern you're talking about. Can you show some OO code that would become less OO if initial values were loaded from an RDBMS instead of literals in source code?
Rather than get deep into the definition of the nature of OO, you can clearly see that the first OO example is more code
than the second OO example because some stuff relating to menus was moved to the database. Thus, the database got more stuff and the code got less stuff (all else being equal). Therefore, they are not orthogonal. QED.
Ah, so a small OO program is less OO than a large OO program? We will never agree to that.
The issue is orthogonality, not really measuring OO-ness. By shifting some of the burden to relational tables, the code got smaller. I suppose you could argue that *any* paradigm's code would get smaller if it too tried to store menu metadata in code, but by my definition of OO, it tends to overlap with what databases tend to do. If that differs from your view of OO, then we will just have to AgreeToDisagree
until the time comes when the definition of OO is standardized.
I could and I have argued that this has nothing to do with OO. OO code doesn't overlap with databases any more than any other paradigm. Identical behavior can be expressed in any paradigm. That's what the Turing completeness phase of this discussion was about. Remember? If you don't measure OO-ness you'll never know if OO is orthogonal to anything else or not.
I am generally considering a higher level than mere emulation here. OO "design principles" overlap with databases. A lot of OO training materials encourage the practice of using objects to contain and manipulate data in database-like ways. Even the GOF patterns overlap with data modeling in many ways. Observer is simply a "list of things to notify" or a list of triggers. If the list got big or complex enough, then DB-tizing it might be a worthwhile option. OO code that did not do such OO stuff would be kind of silly, since you wouldn't be using OOP languages for what they were intended for. If a relational language allowed recursion, then it would be TuringComplete
also (if that would do any good), and could emulate OOP languages. However, that is meaningless at the level of design principles. We are discussing design principles, not how to emulate X with Y. If one defines OO as merely programming language conventions, then I could perhaps agree with your point of view. But a search of the OO literature will generally emphasize that OO is design principles.
It sounds like you're talking about collections. They aren't exclusive to OO. Collections are used in almost all programming paradigms.
Well, it would be interesting to see OOP code that left a vast majority of the collection handling to a RDBMS, and still be called "OO" or "good OO" by a majority of OO proponents.
[Could the above comment be clarified? I am not sure I understand it. Most OO systems I have seen do use the RDBMS to build collections for them. The record sets, however, that are returned are usually not in the most convenient form for program manipulation, so the data is copied over into a class based structure.]
I've seen many OO programs that used an RDBMS for all collection handling. It didn't make them less OO. Collections are not a unique property of OO. Collections are used just as frequently by procedural programs. Remember Data Structures 101?
When I finally was able to use some NimbleDatabase
tools, I tossed "101" structures and never missed them. It turned me into a RelationalWeenie
, or at least a TableWeenie
(since some of those were not pure relational). But, I do think that OO training and publications tend to emphasize using code-based "data structures" and code-based taxonomies (usually-hierarchical). Are these books and articles "wrong" about what OO is about in your opinion? If you don't subclass and don't have very many multiple instances or clones of objects/classes, I just could not rank it very high on the OO scale. We have been over this already above. Our working definitions of OO just seem to differ. The key I think is your question about the second OOP menu example where you ask, "why is this less OO?". Perhaps your code tends to look like that, and is thus rather procedural, at least in my eyes.
There's no correlation between OO and data structures. My data structure classes were taught in Pascal. I've never seen any definition of OO that claimed OO was "about" basic data structures. Most OO definitions rely on encapsulation, polymorhpism and inheritance. Those are techniques for organizing behavior. Collections (like lists, sets, maps, tables, etc.) are techniques for organizing data. You can mix and match the two. You can use procedural techniques to manage maps. You can use OO techniques to manage tables. Etc. They are orthogonal.
The 2nd OOP menu example didn't show less encapsulation, polymorphism or inheritance because the 1st example didn't show those characteristics at all. The OO parts would be in the class definitions, inside the display method, etc.
Assume as application developers we don't know what is inside that. For all we know, the Display method could simply call a DLL written in C.
If that's the case then neither example is an OO example. I assumed your OO example would at least reference OO code even if it didn't show it. If there's no OO code involved in those examples, they aren't OO examples.
I am not sure what you mean here. How about you present some sample OO code on what you envision is a typical and/or "good" way to manage such a menu from an application developer's perspective.
I mean if there's no object oriented code, the example isn't object oriented. For a typical OO implementation of a menu, see JMenu and JMenuItem in the J2SE source code available at www.java.sun.com. It doesn't matter if you hard code menu item creation in the source or write a method to create them based on a SQL result set. The program will be just as object oriented either way.
Implementation? We are talking about the perspective of the application developer
, not the GUI guts writers.
No we aren't. We're talking about object oriented code. The object oriented techniques are the same for applications as they are for GUI libraries. If you only want to talk about application developers, don't use menus as examples. Use classes the application developers would write.
All the examples showed were 2 ways different objects could be used by client code. Write the display method for the 2nd example and you'll see the same initialization of MenuItems? and the same calls to addSubItem, just generalized so that their driven by the result set of a SQL query. The code is just as OO either way.
So if somebody built a translator program to translate every function call into an OOP class using the above pattern (I labelled it "Example Robin"), and ran a procedural program through it and got OOP code as output, you would be comfortable calling it "full OO"?
No. It wouldn't use inheritance, encapsulation or polymorphism. "Example Robin" has nothing to do with object oriented programming. I don't understand what you're trying to say with "Example Robin".
I labelled the other examples also. Example Robin is pretty much what Example Parrot does based on Example Peacock. Yet, you say that Parrot is "just as OO".
I assumed that the classes used in Parrot and Peacock were object oriented classes. There's no object oriented code in any of the 3 examples you've shown, just labels on 2 of them that they are OO examples.
Your definition of what is OO escapes me.
As yours escapes me. I'm using the most popular definitions of OO I can find. Object oriented programming uses encapsulation, inheritance and polymorphism. It groups behavior and data into units called classes which serve as templates for instances known as objects. None of that is exhibited in your examples.
May I suggest reading the analysis of those 3 terms near the bottom of DataStructureCentricViewDiscussion
Yes you may. There's still no object oriented code in your object oriented code examples.
Well, it isn't procedural in my book, so it must be some new paradigm?
Perhaps they are a new paradigm in your book. In my book they are sequences of method calls. They show no evidence of polymorphism, encapsulation or inheritance. Further, there is no evidence that reading the menu item names and structure from a result set would change the methods in anyway. Instead of a hard coded list of method calls, there would be an iteration through the result set calling the same methods.
Databases can subsume inheritance by having the tree be in the database instead of in code or code-instantiated RAM objects. And polymorphism can be subsumed by having the "instances" that you polymorph over be database records instead of objects or classes. IOW, the "poly" is multiple records, not multiple objects. Polymorphism is little more than a look-up scheme on a "structure" to find an attribute or method of a given name. RobertMartin
calls them "jump tables". OOP is nothing but look-up mechanisms on implied structures.
First, databases can't "subsume" inheritance of behavior because you can't describe behavior in databases alone. The menu and menu items in your example presumably
do something. If there's inheritance in your OO examples it will be involved with behavior. But none of what you just said shows how your object oriented examples are object oriented, or if they are object oriented in the code that is not shown, how that would be reduced by loading the menu item names and structure from a result set.
- Is OOP only about behavior? If somebody uses inheritance for attributes only, is it not OOP until at least one method is added? Behaviorism also seems to contradict the UniformAccessPrinciple, which implies that behavior is more or less a lower-level detail rather than a primary principle of OOP. Another way of stating this is that OOP interfaces should hide the fact of whether behavior or attributes are used to satisfy an interface. (Using triggers and calculated views, databases also can have similar source-hiding features.)
- Yes, OOP is only about behavior. No, inheriting attributes isn't OOP by any widely accepted definition of OOP. At their core, all OOP definitions get down to objects asking other objects to perform tasks. OOP interfaces hide the details by exposing everything as behavior. Attributes are secret implementation details.
- [I agree in spirit, but to nitpick, it seems to me that actually it has been claimed that it's about inheritance; I think that's a simplistic claim, but still, we should try to be cautious about phraseology. I'd say that your strongest point is where you said "At their core, all OOP definitions get down to objects asking other objects to perform tasks". That covers a lot of territory quite nicely.]
- As long as we're picking nits, I'm not aware of any widely accepted definition of OOP that says it's about inheritance of attributes. Inheritance is often one of the requirements, but it usually applies to behavior as well as state. -- EH
It is a matter of how the behavior is "dispatched". OO generally uses inheritance, polymorphism, and objects pointers to dispatch (find) the appropriate behavioral thingy. This tends to be where it overlaps with databases. Whether the final behavior is stored in the database or not is immaterial. Relational does not rule it out, I would note. Whether doing such is a good thing or not is another discussion.
There seems to be a difference in the way OOers design systems than relationalists. The relationalist will use the schemas to model the attributes and states of the nouns of the domain (employees, paychecks, plane reservations, etc.). The DB then becomes kind of a public chalkboard
from the application perspective. The public chalkboard is the model of the state of the domain world. The various operations of the app read and change this chalkboard both to update the model (as a bag of facts about something) and to communicate with other potential operations.
OO on the other hand tends to assign responsibilities (ResponsibilityDrivenDesign
RDD) to the nouns/objects of the domain, and one must negotiate with the nouns to perform changes or get information. There is no public message chalkboard. (However, the RDD nouns/objects can be kind of public. Related: GateKeeper
These two approaches to modeling a system seem fairly mutually-exclusive to me. If you mix them, you have too much chaos. Either you require the app (by convention perhaps) to change a plane schedule through a public chalkboard (DB), or through a RDD object, such as a Schedule object. Technically a given app can do both, but I think most would agree it does not make sense. Why make a RDD interface if some or most operations will use the chalkboard interface?
Using the above menu example, one could communicate with the menu via a database, or via a RDD interface with operations such as addMenuItem, setMenuClickModule, etc. It does not make much sense to allow both in a given app. An architect will generally dictate one or the other approach.
Nope. We (object oriented programmers) use databases just like you do. We use OOP to define the behavior which is ignored by your chalkboard analogy. Modeling "the attributes and states of the nouns of the domain" is just one part of programming. Without behavior there's no software, just a bag of information.
Perhaps an example will help clarify my point. In the "chalkboard" approach, an application that can change menus would be permitted to change the menu with something like:
executeSql("UPDATE menuItem SET priority=7 WHERE itemID=?", itemID);
An OO design instead would do it through typical accessors and mutators. The menu class(es) are where is one is "supposed to" go to make such changes.
mi = myMenu.getMenuItem(itemID);
You don't need to clarify. I understand your point. I just disagree. We do the exact same thing in OOP. If we want "priority" to reside in a database, we keep it in a database. The menu classes are where one defines the behavior of the menu. Configuration can be stored anywhere.
Ignoring accessors and mutators for the momement, what does the location of behavior have to do with the topic?
It's the aspect of OO you choose to ignore. You are trying to make a straw man out of OO by pretending OOP is about hard-coding configuration in method arguments. You often say things like '[t]he menu class(es) are where is one is "supposed to" go to make such changes'. But classes aren't where one is supposed to define or change configuration. Classes are where one defines behavior.
For one, I am not sure that is a common view of OOP. Second, behavior and data are interchangable for the most part [insert topic link when found] such that one can be turned into the other, depending on what mix one wants. (However, some things are harder to work with as humans in declarative/data-structure form. Boolean expressions are an example.)
Above you argue that "relationalists" use RDBMSs as a "public chalkboard" to share state while "OOers" hide state inside source code. That's provably false. The OO source code I wrote today contained no state values. All state values resided in RDBMSs or Spring configuration files (which can transparently load values from RDBMSs if desired). The OO source code defined only the behaviors. I can't figure out what your last paragraph has to do with this discussion at all. You made a claim about "OOers" and this "OOer" told you you were wrong.
. Anyhow, how are classes full of only behavior significantly different from procedural modules then? True, procedural modules and relational may be orthogonal, but your definition appears to be an outlier.
We've done this before, Top. That's not an "outlier" definition. Look at any general purpose introduction to OOP and you'll see OO is defined by inheritance, encapsulation and polymorphism. And that's how OOP differs from procedural programming. You know all of this, or should by now.
Most OO uses I've ever seen does those 3 with attributes and
behavior (or at least with things that could be viewed as attributes in behavioral clothing). If one only
did those things with behavior, you may have a point. But, most don't. Further, there is often a non-OO way to do the same thing. For example, using a query to look up a routine instead of multi-dispatch via something like Visitor.
But none of that means OOP hides state values inside source code as you claim above. Attributes are inherited, but the values in those attributes can and do reside in RDBMSs. "OOers" use RDBMSs as "public chalkboards".
One can wrap anything with OOP classes/objects. But that is "doubling up" on interface layers as already described above. In fact, one can also wrap OOP in a relational interface, such as SQL (regardless of whether it is a good idea). Under that approach, anything that can be translated or wrapped to another paradigm is orthogonal. In otherwords, with enough indirection everything is orthogonal.
select * from wrappedObject where objectInstance="Shape37"
and method="rotate" and parameterDegrees="180"
(Note that to the user/querier this appears as if the table has a row for every degree parameter variation/combination. However, it may not necessarily be implemented as a data table, for it may calculate the rotation as needed. Relational does not dictate implementation; it is only conceptual interface. It is yet another manefestation of DataAndCodeAreTheSameThing
Thus, if one is not wrap-happy, they are not orthogonal.
You ignore the "wrapping" and local variables required to use RDBMSs from procedural code and act like they are unique OO sins. OO programmers use RDBMSs the same way you do, but you refuse to acknowledge it even when directly confronted.
I am not sure what you mean. Please clarify.
There's no "doubling-up" on interfaces. There's no more wrapping in OO than other paradigms. You make statements like this:
"Either you require the app (by convention perhaps) to change a plane schedule through a public chalkboard (DB), or through a RDD object, such as a Schedule object."
That's a false dichotomy. In procedural programming you'd still use a Schedule structure because you wouldn't hit the database for every variable reference.
Okay, sometimes one might have a map (associative array or C-like "struct") or whatnot as a temporary holding or staging area for record creation. But if you are only using objects as glorified staging maps then many would consider your OO code "weak OO".
You'd also have procedures that changed that state because you wouldn't force the user to type their own SQL queries for every interaction with the system.
I am not sure what you mean by this. There may indeed be routines that are used instead of SQL for commonly-used stuff.
You'd have the same number of interfaces and wrappers. Your presentation of "relational" programming totally ignores the code that changes the plane schedule. You present it as if there's nothing more than picking a database schema and the application is complete. All of the flaws you find with the OO approach are either imaginary or also present in a procedural solution.
Your portrayal of OO seems "OO lite". Some contractors will use OO just to jack up their line-count using combersome formal ways to do basic stuff. Your portrayal of OO almost sounds like that so far. One can use methods in place of subroutines, and objects in place of maps, but the resulting code would not be that much different. Your OO code is OO in name only.
You mean my OO code isn't the straw man you pretend OO code is. It isn't stupidly written and obviously flawed. What you call "OO lite" is what we call "OO" and what you call "OO" is what we call crap.
I still suspect your view of OO is a minority opinion. Anyhow, we probably cannot settle this without visiting live code, so how about AgreeToDisagree
I bet I see more OO code than you do during any given day. I'm speaking as a working OO programmer, not a minority fringe element.
Well until there is documentation on what your techniques are or are not, it is not much use to discuss such.
I just told you my techniques. I wrote it down, so now it's documented.
Using "schemas to model the attributes and states of the nouns of the domain" doesn't make OO any "lighter" or less object oriented. There is much more to programming than modeling state.
Again, I claim it is possible to convert behavior to state to a large extent in order to shift the problem into one of processing attributes, where relational techniques can be more readily used. But this just returns to the age-old battle of DataAndCodeAreTheSameThing
. How it is represented is largely a matter of human preference. EverythingIsRelative
. Live with it.
Your description of using the RDBMS as a public chalkboard doesn't convert behavior to state. You still have to describe that behavior for a compiler or interpreter in addition to modeling your nouns. You've never shown how you can do that better than popular OO languages, and that's why you can't win converts.
This topic is not about popularity, so I won't get into that here. But if you have a specific example of how your version of OO facilitates behavior management, I would like to see it, perhaps under another topic.
Already been there and done that: inheritance, encapsulation and polymorphism.
I am curious, why bother with sub-type polymorphism? If you get your attributes from the DB, then you will need a case statement to allocate objects based on a "type" (cough) obtained from the DB to get polymorphic dispatching. Why not just use the case statement since you already set it up? Otherwise you may have to visit two places to add a new subtype. Or, store the function name in the DB and use dynamic function calls.
We've been over this before as well. Case statements litter type information all over the code. Polymorphism enables collapsing all those case statements to a single decision point (object instantiation). I don't use a case statement to create objects, I use Spring, which in turn gets concrete class names from XML files, property files or databases.
How is that more evil than spreading similar methods all over the place?
I don't spread similar methods all over the place. OnceAndOnlyOnce.
Polymorphism duplictes similar method signatures. That is what it does by nature. For example, in the Shape examples, you can have multiple "Draw" methods.
Method signatures are not methods. The only time a method signature is duplicated is when the methods differ. When the methods are the same there is only one signature (and only one method). That's a perfect example of normalized source code. Are you saying you have a technique for writing multiple implementations of a method with only one signature? Are you advocating filling a single method with all possible implementations? Are you really suggesting we modify a perfectly good method every time we need a new implementation of it?
And, the case lists are often not the same per task over the longer run.
Again, I don't use case lists. I use polymorphism.
No. You implied that you use poly to avoid having duplicate case statements. I am saying that dup case lists are mostly OO fiction. OO literature unicorns. I don't find them common except in bad programming, which can happen in any paradigm.
Multiple examples have been provided to you. A quick glance through any reasonably complicated open source project will prove you wrong. You can call it whatever you like, but the world is full of variants.
If there is only one instance of the list, then poly will require it 2 places instead of one because you have to translate the type flag from the DB into objects.
No, Spring just needs the name of a class. No translation and no lists required.
How does it know which column value to translate to which class? I suppose you could put that info in the classes, but that is just a glorified (bloated) case statement.
I don't understand your question. If you mean how does Spring know where to find the class name in an RDBMS, the answer is "you give it a select statement."
You have not answered that. XML? Oh Gawd! KISS me not. Your shop must be a real buzzword hangout.
Nope. My shop uses XML where it is convenient. Spring configuration is definitely one of those places.
If they really were the same in multiple places, then a relational strategy-like pattern (RSLP) may be in order. In practice I don't see enough regularity to justify a RSLP very often. But you are right that we have been over this already in SwitchStatementsSmell
and don't need to revisit it in detail. But these three choices:
- Case/if statements
- Relational strategy-like pattern
are generally mutually-exclusive design decisions unless one wants to duplicate stuff and bloat up code just to translate back and forth between paradigms.
What paradigms? We use relational databases just like you do, but we program in object oriented paradigm. You haven't presented an alternative paradigm, you've just said we should use procedural instead of OO. We're convinced that OO makes our code easier to write and maintain and we don't have to give up any of the power of relational databases. Why? Because OO and relational are orthogonal.
You have not made a good case for that. Anecdotes are nearly useless as evidence. You seem to recreate relationships in OO rather than truly use OnceAndOnlyOnce
. Show me 3 cases of production polymorphism from biz apps and I will show you non-orthogonality.
I'll give you one example of production polymorphism: passing lightweight and heavyweight images through a workflow. Lightweight images are just references to images in a central image archive. Heavyweight images contain all of the image data. Some steps in a workflow have access to the central image archive. Some do not. Code used throughout those steps needs to be able to operate on images no matter which kind of step calls it. Polymorphism makes it trivial to define a single image interface and multiple implementations that can be used wherever appropriate. There is no "non-orthogonality" there.
Now it's your turn. Show me that "OOers" don't use RDBMSs to model "attributes and states of the nouns of the domain", or that they don't use RDMBSs as "public chalkboards". You'll have to somehow show that neither I nor my co-workers are doing that, since we are all "OOers". Good luck.
(Discussion continued on TheAdjunct
My summary conclusion on the orthog question after several weeks on the Adjunct is that "it depends
". Something is OO is not always going to correspond to something in a DB one-to-one. For example, if somebody turns every CASE/SWITCH statement into polymorphism, there may not be a corresponding (practical) relational equivalent. It will generally be with more complex sets of related classes that the overlap will appear. --top
So we can conclude that there no longer seems to be a difference in the way "OOers design systems than relationalists", since you've refused to defend that claim?
How did you conclude that from what I said?
I repeatedly asked you to substantiate that claim and you ignored every request. Each branch of our argument ends with me asking you to defend that claim (and others you made on TheAdjunct). What other conclusion can we make?
Like I said, it depends. My claim is that it depends. Your particular example does not appear to be case where it would overlap.
Overlap? What are you talking about? Your claim at the top of this section is not "it depends". You claim that "OOers" design systems in a silly way, while "relationalists" use databases as "public chalkboards". I am an object oriented programmer and I work with many other object oriented programmers. We use RDBMSs exactly as you describe "relationalists" (with the exception that we also use other technologies, like messaging systems, when they provide better performance), and we don't hide configuration in source code as you accuse us of. Back it up or retract it.
I've started to think that TopMind
has his enemies confused. It isn't OO that he dislikes; it's data structures. Somehow he's come to believe that lists and maps are part of object oriented programming and not programming in general. Am I right, Top?
I don't really know. I don't remember seeing any OO of any length that does not use or form some kind of code-based data-structure that is a candidate for table-izing. This discussion is about orthogonality anyhow, not likes and dislikes. Polymorphism implies more than one. As soon as you start instantiating or cloning objects/classes, you are creating a data structure of sorts, or at least generating multiple similar "state" things that must be managed like nodes in a data structure. And, inheritance forms a tree-shaped data structure. And encapsulation without polymorphism and inheritance is not much different from a procedural module. -- top
I don't understand how that last paragraph relates to my statement. Are you saying that you do believe that data structures are a characteristic of or more prevalent in object oriented programming than other programming techniques?
May I suggest http://www.geocities.com/tablizer/whypr.htm
OOP is the pinnacle of the "code-centric" approach in my opinion.
I'm aware of that. Will you answer my question?
For the domain I am familiar with, custom biz apps, I would generally say "yes". Shops tend to lean toward database-centric or OO centric. Those who tend to "reinvent the database in code" generally are OO fans. Well, there are a few "array maniacs" who make procedural messes, but they are usually newbies.
I've seen millions of lines of procedural code for custom business apps. Data structures are just as common there as they are in object oriented code.
Perhaps my preference for relational biases me toward being hired by RDBMS-centric shops, because I generally see less of it.
I suggest that you correctly name your opponent. It isn't object oriented programming. It's data structures. Most computer science degrees require at least 2 data structures classes. You'll have a hard time convincing the world we should replace them all with relational tables.
Worse things have happened :-)
Now that I understand your confusion between object oriented programming and data structures, I think I can see why you argue that OO and relational are not orthogonal. Data structures and relational are not orthogonal. Relational tables are data structures. Data can be arranged in relational tables, or it can be arranged in trees (or lists, or bags, etc.). If we go back and replace "OO" with "data structures" in your comments they make more sense.
A relationist will generally see "lists", "bags", "trees", etc. as a viewpoint, not as rigid structure. You "query" to see data in a tree or a bag or whatever. It is about virtual-ness. How data is used or viewed is based on situational needs, not some universal IS-A cattle branding. That is what differs relational thinking from traditional college data structures in my opinion. Anyhow, I don't think we could settle this without exploring more code samples and better defining OO.
An OO programmer will see lists, bags and trees as viewpoints as well. It's trivial to add references to the same data to each of these data structures. There's nothing rigid about them. The "universal IS-A cattle branding" you speak of is a straw man. The difference I see is that I'm free to use any data structure I wish, not just relational tables, based on situational needs.
I've provided my definition of OO. It's a commonly used definition. Yours equates object oriented programming with the use of data structures and appears to be unique to you. I've proposed that we use the source code for Java's JMenu, but you didn't like that for some reason.
It is your turn to present some sample code here. Please don't make readers dig around Sun's web-pages. And, please keep in mind that I am looking at this from an application developer's perspective, not from a GUI engine implementor's perspective.
I can't make readers dig. If you would like to see an example of object oriented code for menus, that's some of the most widely used code around. Please keep in mind that I am looking at this from a software developer's perspective. I've written GUIs, commercial off the shelf apps, network transports, messaging systems, databases, compilers, etc. The type of software we develop doesn't change the definition of object oriented programming.
Perhaps what is orthogonal in one domain is not in another. I can't really say because I have insufficient experience in the domain of systems software and packaged software. Database vendors tend not to target these domains as much for some reason.
Object oriented programming and the use of relational databases are orthogonal in all of the domains I've worked in. All of the commercial off the shelf applications I've worked on used RDBMSs, and all of them were written using object oriented programming languages and techniques. When we moved data storage from flat files to the RDBMS it did not decrease the object orientedness of the code in any way.
Note that I am looking at specific parts at a time, not an entire application. In other words, I am not saying that either you use RDBMS entirely or use OO entirely.
Flat files? Sounds like you use RDBMS only for storage. Relational algebra and schemas are powerful modeling and abstraction tools used to their full potential. If your RDBMS is only an expensive file folder system, then why bother? Might as well use a big diamond as a paper weight.
We used RDBMSs for storage, fast ad hoc queries and data sharing. That's what they're best at. They are lousy for messaging, distributed event handling, general purpose programming, visualization, lexical translation, and the myriad other responsibilities of the applications I've worked on. We used other tools for those. What does any of that have to do with the topic of this page?
I am suspect of your "lousy for" list. I agree that there are niches where existing RDBMS have proven slow with regard to processing speed. However, that is becoming less and less of an issue over time as organization power is more important a factor as chips get faster. Plus, relational does not dictate actual implementation. Perhaps it can be tuned to particular niches. What is an example of "distributed event handling", by the way? And, what is "general purpose programming"?
Before I answer, please answer my last question.
You answered it yourself by saying "RDBMS are good at A, B, C, but bad at X, Y, Z". This strongly implies that you agree it is an either-or choice.
No it doesn't. It means RDBMSs are good for somethings and not others. Their use is still orthogonal to object oriented programming. Now what does any of this have to do with the topic?
To you, nothing has to do with the topic because you are not getting my point of view. I don't think you will because your definition of OO is hard to pin down, and thus we need a code example from you so that we don't have to rely as much on text definitions.
I've given my definition of OO. I've provided code examples.
As far as examples, do you mean the internal Java GUI menu implementations? If you mean the "classic 3" definition, see dispatching comment above.
I mean JMenu.
Do any of the "conversions" below apply to JMenu?
What do you mean? Can OO techniques be implemented with tables? Certainly. Most OO languages use tables under the covers. That has nothing to do with the examples earlier on this page.
(Examples of distributed event handling can be seen in JINI, JMS, MQSeries and various workflow, notification and system management products. General purpose programming is exactly what it says. Try a google search for "GeneralPurposeProgrammingLanguage
" for examples.)
Data transfer is not necessarily the same as "distributed computing".
I didn't say data transfer was the same as distributed computing. I didn't mention either of those topics.
Okay, but I wonder what the hell "distributed event handling" is. E-mail that triggers pagers?
Try a google search for the phrase.
This signal has become noise.
That is why I wish to focus on specific examples instead of get lost in LaynesLaw battles.
The below is quite similar to the core concepts of KyleBrown
, especially the static patterns.
How to turn OO into a table-driven arrangment:
Note that this does not necessarily imply that such should always be done. It is only to illustrate some concepts. I agree that the conversions described here may be over-simplistic, for entirely different approaches may be taken in practice rather than one-to-one conversions.
- Polymorphism: Convert each "variation" into a record with one or more "type" codes, and subroutines use such to dispatch any behavior. (This is for "subtype polymorphism" more or less. "Utility polymorphism" is more situational.)
- Inheritance: Convert tree structure into table rows with a "parent" foreign key, or convert the various features of each node into attributes which become table columns (thus, de-tree-ing the structure).
- Objects referencing objects. See the menu example above. Generally, object references are turned into foreign keys of some sort.
I am curious. For those who think they are orthogonal, do you also think that procedural or functional are also orthogonal to OO? You don't see any decision points where you say have to decide between a Case statement and polymorphism?
No, procedural, functional and OO are all ways to organize code. They are not orthogonal. Relational is not a way to organize code.
(I did not originate that topic, BTW). To the compiler/interpreter, code is data. Some things are just easier for humans to represent as code and others as data. My threshold for when do make what into code and what into data is apparently at a different point in the continuum than yours. Many OO systems and designs have the GUI layout for an application as code, for example, whereas I would prefer it as data.
This was too good not to share with somebody, although I'm not sure what, if anything, it says about orthogonality: http://www.dbdebunk.com/page/page/754911.htm
In most applications we have a "state system" of some sort, or perhaps a bunch of state systems. The state system is generally a data-structure, at least. A state system is something non-trivial that "lasts" between method and function calls and often during the entire "run" of the application or longer. In the ClassicOoModelingApproach?
, this state system is the virtual "state machine" that tends to reflect some real-world entity such as Customer or Product. Relational is different in that it tends not to reflect physical boundaries and does not try to associate behavior with a single PrimaryNoun
because the associations can also be one-to-many or even many-to-many. Where relational and OO fight over territory is whether this state system is an OO network or a set of relational tables. It cannot be both unless we violate OnceAndOnlyOnce
, which many OO-R mapping tools do.
Relational is an example of CollectionOrientedProgramming
are used as a standard for manipulating collections. Either you use the standard, or you invent your own. OO tends to invent its own per use or per class. Thus they are not orthogonal. Either you use a standard or you don't. I suppose you could half-use the standard, but you are still separating things into pile A or pile B by choosing what parts of the standard you use and which you ignore.
I suppose you could wrap all the CollectionOrientedVerbs
usage inside of objects, but this produces a redundancy of sorts. This is simply using a custom behavior-oriented wrapper around a collection-oriented system. If you define OO as being behavior-oriented wrappers, then perhaps they are not orthogonal. But this all depends on your working definition of OO.
It's all getting a bit abstruse. 'Relational' is getting that all-encompassing definition feeling. It grows and shrinks according to circumstance (OO does this too). Just as a canard, can we not simply say that relational only adds a single abstraction, the "primary key"?
This is at a much lower level than OO and all that jazz. Type systems are merely implementation wrinkles. Table-driven versus hard-coded is a matter of design stability and location. Query by content is equivalent to get by parameter.
All the rest seems more sound than light i.e. I can interconvert between systems without adding or subtracting information, except for the concept of a 'key' over a 'location'. And even 'key' has problems in that it needs to be static, and yet sometimes needs to be dynamic i.e. a datum's identity may not remain the same forever. Relational theory does tend to get horribly tangled at the point where multiple identity or changing identity comes in. Similar issues occur elsewhere (including OO). It is a universal problem. --RichardHenderson
Can you provide examples or UseCase's?
Primary keys are also part of competent OO persistence. The difference is that they are globally unique vs unique to a table. Avoiding the "deep copy" problem or realizing a Composite Pattern is most easily done by passing gluons (Globally Unique Object Numbers) rather than whole objects as object attributes. Polymorphism comes to the rescue.
A lot of the "talking past each other" on this page is due, I think, to confusing objects with session beans (degenerate J2EE code-filled objects) and classes with collections.
In OOP, managing bunches of objects is done with collections. If persistence is needed, what you want is a persistent collection--an instance of the appropriate persistent collection class. How it arranges persistence is irrelevant to the clients of the class; a SQL database is fine. That adds up to two classes for each thing: one for the thing, the other for collections of the thing, e.g. Mouse and Mice where an instance of Mice is some collection of Mouse. (Btw, this is antithetical to the J2EE paradigm).
As RH suggests, identity is where OO and Relational seem to part company. Formally, a relational item's identity is the product of its attribute values. An object's identity (distinguished by its gluon) is independent of its attribute values. In OO, Fred has had only one axe; in Relational, he has had many (see FredsAxe
But that is mostly a technical issue. Even if we compromised to adjust the identity of rows to better fit OOP, the other issues still remain.
, but one is TooBigToEdit