Holub on Patterns
If I can level any complaint against this book, it's probably that the title doesn't properly convey the goodness locked within. Holub on Patterns is short for Allen Holub on Design Patterns. Allen Holub is a long time expert on Design and Design Patterns, so he's the man you want to learn it from. Still, if I could name this book, it would be Object Oriented Design Voodoo. (Note: This is probably why I don't work for Apress or any other publisher.)
The book's subtitle is "Learning Design Patterns by Looking at Code." That probably conveys the work's focus a little better and it also gives away one of the book's best features: sensational examples. (These examples are in Java, another area where Holub is a well-known authority, but the concepts taught apply to Object Oriented Programming in any language.)
Titles aside, this book really is the best work I've read on design patterns. If you don't already know, design patterns are the recurring patterns of object-oriented software implementations. Luckily, you don't have to know anything about them to read this book. The author covers many patterns in rich detail from the beginning. Even if you do know your design patterns well, I'll wager Holub still has a trick or two to impress you with.
Holub discusses patterns in their ideal pure form, but much more importantly he shows them as they occur "in the wild," with multiple variations. He covers the downside of each pattern, weights the trade-offs of using them, and even gives a handful of cases where he felt they were impractical. He does all this right in the middle of complex real-world examples so you can see each point he's making. That's actual programming, folks. The good, the bad and the choices we programmers make are well presented, and that's rare in a programming text.
The book opens with two chapters that more or less cover why we need design patterns at all. Did you know getters/setters are bad? Did you know that subclassing is dangerous? If you said No to either question, you need this book and these two chapters in particular will get you up to speed on good OO practices. This section of the book is mostly theory, light on examples.
The next two chapters (covering over 250 pages) make up the heart of the book. Holub examines two examples in exhaustive detail. The first is his implementation of The Game of Life. You've probably implemented that on your TI calculator, but Holub sure didn't. He admits that his implementation is "Toy Code," but it's a robust example that involves eleven design patterns. The second example is production code, a mini database complete with SQL interpreter. This code is also swimming in pattern usage, and Holub gives you the guided tour.
I've already said these examples are great, but that claim begs some elaboration. First, we're talking about hundreds of lines of code in many of these listings. These aren't the usual contrived junk. What's more, one class may be participating in multiple patterns. Making any sense of these examples would be almost impossible if the author wasn't flawless in explaining the key points and always dropping hints about what you need to notice. This isn't light reading. It's work, but the rewards are there and it'll pay off if you really spend the effort to understand how the code works.
Finally, the book closes with an appendix that gives more typical recipe-card style listings of all the design patterns discussed throughout the text. This is a nice reference after you've finished the tricky stuff. If you're new to design patterns, you might start here, before the book throws you into the lion's den with its massive examples.
Just in case I haven't sold you on this title yet, I better mention the gorgeous hard back binding. Brilliant and sexy. How can you beat that?
Holub on Patterns is a very approachable way to learn a lot about design patterns. If you already know how much patterns can improve your object-oriented programming, you'll really enjoy Holub's presentation of the topic. If you don't yet grasp Design Patterns or haven't enjoyed other works on the subject, you'll just have to trust me: You want this book.
You can purchase Holub on Patterns: Learning Design Patterns by Looking at Code from bn.com. Slashdot welcomes readers' book reviews -- to see your own review here, read the book review guidelines, then visit the submission page.
Great, now we're getting book reviews by witch doctors!
The official site is located here.
The book opens with two chapters that more or less cover why we need design patterns at all. Did you know getters/setters are bad? Did you know that subclassing is dangerous? If you said No to either question, you need this book and these two chapters in particular will get you up to speed on good OO practices.
Can someone explain why accessor and mutator methods (I assume this is what he means by "getters/setters") are bad?
I am the maverick of Slashdot
In the interim before the appearance of such works, I've been trying to keep an informal list of patterns I've unearthed through practice, but my ability to codify patterns cannot match that of someone like Holub. :-)
Finally, the book closes with an appendix that gives more typical recipe-card style listings of all the design patterns discussed throughout the text.
What? Is that supposed to be some sort of witch's brew?
This sounds promising. I've been waiting for another book besides design patterns by the gang of four, and specifically looking for one with nice Java examples. The other design patterns books I've found are all geared towards J2EE or the enterprise market. Does anyone have a quick table of contents or a list of patterns he covers?
LMAO! Well, MISTER HACKER try typing gmail.google.com into your browser and see what happens.
huh? Actually, the 'real' gmail is gmail.google.com. Check out the ssl cert for https://gmail.com/ if you don't believe me. I imagine it's done that way so all the google domains share the same cookie base.
Shit dude did you just hack Google? I'm getting the Gmail page!
Design pattern fans should check out Pattern Hatching: Design Patterns Applied by John Vlissides, one of the Gang of Four. Short, but interesting reading.
EricHow to detect Internet Explorer
YHBT YHL HAND.
OOP fails and will always fail because it attempts to anticipate the future at design time, and that's just plain silly.
No, your OOP attempts fail. I can't see anything in your post that applies to OOP versus any other style/method of programming.
No Commodity Server for me. It's all a bunch of "if-then"s with nothing underneath.
lol, people like you are the reason why I keep trolling. you think I dont know that? the troll is in the fact that a whole bunch of you come in here to tell everyone the truth and then make a big rucas about it. its so LOL to watch 5 or 6 of you make a big fuss.
Google owns gmail and uses the google.com subdomain for gmail stuff.
You're an idiot.
I bet you don't have the balls to reply and admit that you are wrong.
Comment removed based on user account deletion
Before perusing this discussion, you may want to get some perspective by reading Unskilled and Unaware of It: How Difficulties in Recognizing One's Own Incompetence Lead to Inflated Self-Assessments by Justin Kruger and David Dunning (Journal of Personality and Social Psychology,
Well, I didn't know much about this guy. But anybody who defends his position by referring to this psychology paper doesn't score too high in my book. If you're not familiar with the paper, it basically asserts that stupid people don't realize how stupid they are. So referring to this paper is a subtle way of saying "you're stupid, and you don't know it".
But I'll give him the benefit of the doubt.. after all some other pompous experts have referred to that paper yet raise important points based on sound theory. I.e., there is not necessarily a correlation between being an assmunch and being *wrong*.
So now I read his papers on getters/setters and he claims this is "bad" because it assumes an implementation of the underlying value:
Excuse me but having to declare orderTotal to be any particular type is a *JAVA* thing, and not universal to OO programming. In Ruby for instance:
No types or assumptions here. Since Ruby is fully OO, this will work even if amount.value returns a Fixnum, a Float, or a SomethingElseEntirely.
He says a "better" way is:
But this is just syntax. In Ruby I would just write:
And it doesn't matter what the types (classes) are.
Poor guy is stuck in a statically typed Java hell, with distinctions between primitive types and objects, of course he's gonna think getters/setters are evil and he's gonna become obsessed with keeping his data hidden in a box or behind opaque methods! I can just imagine his code filled with thousands of builder objects with 2-3 levels of abstraction .. and it will just be a grotesque simulation of a true dynamic language in the end, with everything completely decoupled.
I don't know if I should bother reading any more of his writings since I don't use Java.... is the rest of his work "how to get around Java's shortcomings" or is there something a general purpose OO practitioner might find useful???
One common pattern with maintained code is the cancerous growth of special cases to deal with new requirements. Over time, the special cases dwarf the original code, and it becomes very hard to even figure out what it's supposed to be doing.
Yes, OO doesn't solve all problems, yet "procedural languages"* are also well-known to have many problems of its own. OO is also easy to get wrong, as evidenced by your "have to throw them away periodically" observation. However, I can't help but feel that you're making conclusions based on limited and anecdotal evidence of failures.
* Many OO languages are procedural.
Anyway, what I've noticed is that up until the past couple of years, not many people really had an idea of how to do Object Oriented programming all that well. Most programmers were faking it, mimicing the talk out of the various trade rags without really understanding the reasoning behind what they were doing. And you can make some pretty atrocious object oriented designs if you don't know what you're doing.
OOP doesn't need to be what you've seen any more than procedural code needs to be twisty mazes of GOTOs and global variables. It all boils down to the abilities of the guy writing the code.
I'm trying to teach myself to set people on fire with my mind... Is it hot in here?
OOP done badly is as you describe, but done well, can be amazing.
The same crew that uses OOP badly may also use any other methodology badly. I have wasted countless days reading through nested if-then statements trying to figure out how something works. And when you find out, the user tends to not want that to be the case, and you rewrite it anyway.
That is is the road to insanity.
No matter how subtle the wizard, a knife between the shoulder blades will seriously cramp his style.
OOP is a wonderful thing because it enforces tons of those wonderful principles that are taught in Computer Science classes 'round the globe: encapsulation, abstraction, data hiding, "black-box" programming, etc. OOP is NOT supposed to be the end-all, be-all of programming, just as the creation of C and other higher-level programming languages was not to be the death of assembly programming.
What, so often, people fail to realize is that software is designed to be built in layers. See the TCP/IP stack, for instance. This allows for one of those wonderful OOP principles to work - abstraction. If the nature of the OOP system/API/et. al. is causing you more problems than it's solving, then I say it's not OOP's fault, it's the designer's fault. I don't believe that OOP is the solution to all problems - some problems are square, and some programming paradigms are round. Problems arise not because of the evil nature of OOP, but because someone tried to pound a square peg into a round hole. OO languages and systems give you the ability to make things object-oriented, but none that I've seen prevent you from using procedural programming techniques when your square programming problem doesn't fit nicely into a round OO hole.
Generally, I've found that people who hate OOP were forced into using it without getting enough exposure to it to appreciate it. Nobody's gotten rid of procedural programming, just like nobody's gotten rid of assembly programming. We just have higher-level tools and paradigms for dealing with high-level programming tasks.
I pity the foo that isn't metasyntactic
The dirty unacknowledged secret of design patterns is that they're strongly coupled to a language. For example, switching from a statically typed language like Java to a dynamic one with forwarding substantially changes the approach to Factory, Proxy, Singleton, Observer and others. In fact, they're often rendered trivial. The claim that the approaches described in the book apply to any language is just not true. These patterns are for Java and Java-like languages.
Philip Crow wrote a very original piece on how to avoid OOP and still use patterns with Perl's special built-in features
http://www.perl.com/pub/a/2003/08/15/design3.htm l
In a similar manner object-oriented databases have no mathematical or logical model (wherein one can model any OO database ) and so the relational database model, which can be universally applied to any database and which has a strong mathematical foundation, dominates.
Someday OOP proponents will realize the futility of their efforts and move to logic programming systems. But such systems are somewhat difficult to master today (look at Prolog) and will need improvement before adoption becomes widespread. Today's "business rule" systems are a sort of hybrid OO-logical mixture that has significant market share.
If it wasn't for OOP, we probably couldn't have reached multi-tier approach to programming. Yes, I know, Java sux. But not OOP in itself.
I program in PHP, and without OOP, I wouldn't be able to use very nifty template classes which simplify my web job, not minutes or hours, but days.
The problem with OOP is that if you don't know best-use practices and think before writing (i.e. use UML), you're sure to make a bloody mess.
Think of OOP as 3D as procedural programming was 2D. A building in 3D is certainly more astounding than a 2D plane. But a maze in 3D is much scarier than a 2D maze.
It's not that OOP is "worse" than procedural programming. It just allows more powerful designs (either good or bad).
I mean, yea, "getters/setters are bad", in public APIs. Getters are bad- unless you need to vend an object and can't afford the overhead of creating entirely new instances when you do so. Setters are _definitely_ bad- unless they're private or are data that act as input for your object, which it recieves from controller-layer objects.
Sure, "inheritance is dangerous" as anyone who has ever written an object-oriented program from scratch and had to modify it can tell you. Inheritance is also the key to code reuse, and can be very powerful when done correctly- do you really want to re-write a section of logic that's shared by 5 other objects ?
These things have their place. They're good targets for "is evil"-type articles because they're often used when they should not be. But to call them "evil" and "bad" without proper qualification? It smacks of unprofessional behavior, at best.
I'm a bit puzzled by claims that use of getter/setter methods and, more puzzling, inheritance, are indications that you haven't solved your problem in an object-oriented manner, or that your problem isn't object-oriented... because, well... not all problems are best solved by object-oriented methods, even if you're using an object-oriented language to do so. Sometimes, you need a variable and a loop... what's wrong with that?
At some point, my model code is going to have to give my view code some objects to display... what, I'm not supposed to use getters there? At some point my view code is going to want to tell my model code about an object the user modified... I'm not supposed to use a setter there? I often think folks who write such blanket statements as "accessors are bad" are just trying to spark some flames.
I didn't find it in many programmers I worked with, but personally I find all of the advices in this book intuitive. What I did find in many programmers is the rigidness they assume when someone questions their position on some specifics. I remember a few conversations I had where I questioned the entire OO paradigm, the people look at you as if you are mad.
But the reason why I questioned the OO paradigm was not the paradigm in its purity, but the implementations that I so often saw in real life. Some of the architectural designs that I witnessed did not make any sense and were artificially created to be more complex than the problem at hand required. What is worse, I have seen 'architects' who got into those positions without any merit. I have witnessed architects who think their position is justified because they spend another 4 weeks in the beginning of every project 'rethinking' the ACLs. I have witnessed an 'architect' that was supposed to design a system, but who instead sat down with a programmer, did a bunch of handwaving, and left the programmer without any idea and without documentation on how things are supposed to be done, and it was not a simple thing for that guy who was still a beginner. I cannot count the number of times where I (as a contractor) in different companies was put into a position where I had to solve the problems created by these 'architects' as well as by 'managers' and the marketting people.
Yes, I remember having a conversation about getters, setters about 4 years ago, I was convinced that those things are a horrid idea as well as extends (for almost the same reasons given in the article). I was attacked on more than just the techno-level. It is hard, it is not easy at all to work around bad design decisions, where someone just does something because it is either a pattern they read, or the marketting says it has to be done that way because there was this meeting with an IBM guy, who bought all the managers year-long golf memberships.
What I appreciate in people is the ability to think for themselves and to make decisions on when something is appropriate. I am also a realist, I know that noone on this planet can be perfect 100% of the time. We get tired, we have schedules, we just want to do things fast and dirty, we resist structure because it is easier that way. But those of us who are good enjoy going through all of this nonsense and figuring out sensible ways to still deliver a good system.
You can't handle the truth.
Or save even more by using Bookpool...
3 88 X
http://www.bookpool.com/.x/7mg7fyzjlr/sm/159059
Nothing is perfect by the way.
In my last project I had a moment in between the deadlines, where I was able to actually do some OO design for a piece of functionality in the system. (a java GUI playing talking to C++ over JNI and playing videos.) The functionality I needed to add was an on screen display for video properties (you press up, and the current property is increased by 1, you press pgup, and you go to the next property, and all of this is overlaid on the video display.) So I had a choice. I could do it in the quick and dirty way, or create each property as an object extended from the base property, and then from one of the possible 2 property types: numeric and enumerated (strings). Each device listed which properties it has - some properties are common to some devices. These devices implemented interface that allowed to have a device factory to figure out which of the devices is playing right now. Once the factory retrieves the correct device manager, the device manager 'knows' the currently selected property. The property 'knows' it's min/max/default and the current value. The property 'knows' how to 'increase', 'decrease' its value by a step of 1 or whatever.
And what do you know, the system became so robast that once in place, adding a new property or a new manager even literally takes 2-3 minutes.
Now, implementing it through a bunch of if or switch statements would have created a maintenance mess.
So no, I do not agree that OO is a complete waste of money. I do agree that in most cases the projects written in languages that allow OO are not written in the OO way, but rather in a procedural manner that is easier to think about and to develop but harder to maintain.
You can't handle the truth.
There's some truth in what you say, but you're overstating it. Some patterns fit more easily in some langauges, and indeed some are unnecessary in more dynamic languages.
However, the original Gang of Four patterns book rather disproves your assertion:
" The dirty unacknowledged secret of design patterns is that they're strongly coupled to a language. "
The examples in that book are all given in C++ and Smalltalk, which are pretty much at opposite ends of the O-O spectrum, and yet the patterns are applicable to both languages and also to Java and C#.
There are probably patterns out there that only make sense in one language, and many are "better" or "easier" in lanague X or language Y, but I've seen little evidence that the majority of patterns are only useful in one language, and plently of evidence they're broadly applicable.
For some patterns I doubt you even need an OO langauge.
Lord Pixel - The cat who walks through walls
A little bigger on the inside than out
Object Oriented languates/programming wasn't invented for DoD. You're thinking of Ada, which, in it's original incarnation was an Object-based system but didn't support proper inheritance or polymorphism (Ada'82).
OO started with Simula and Smalltalk, with Simula67 being the object oriented base of C++.
And if you don't know what you're doing in a particular paradigm you usually end up with dreck nobody wants to maintain.
Slashdot's name? When my compiler sees
Timothy, you going to cover this book? I've like to see how the two compare. -TF
Every time I sit down to a piece of "bad" old code, I notice just how much easier it is to maintain. I add an "if-then", but the OOP guy is screaming factor-factor-factor so much that you have to shlep the whole thing off to india to because that's the only way you can afford the thousand programmers to sort out.
You are aware of the fact, that most OO languages have the (really usefull) if-then construct. If you only need to change that, it can also be done quite easy in those languages.
*Polite Golf Clap*
Ok, to summarize his point. If you are making a "thing" then the operations on that thing should be contained inside that thing. So if you make these little routines that do nothing more than let you peek into "thing" to see "the real thing" inside, your "thing" isn't your friend.
As a peice of mental oragmi (and to fold my own self in here, instead of _just_ trying to paraphrase this guy).
There is nothing wrong (IMHO) to exposing parts of your thing via accessors and setters AS LONG AS you think of these methods as "translation to the outside world".
That is, if you find yourself writing NewThing.setValue(OldThing.getValue() * 5) then you are no longer getting any useful work out of having "thing" in the first place, and this is bad. It's bad because you are requiring yourself/the world to reach behind a blined and operate on something that you hope will remain stable.
Accessors and Setters are "good", however, (my view, not his) when you lear to see them as moments-of-control that you wrap around the need to communicate "parts of thing" with the outside world. These moments of control may involve locking or provide you the opportunity for "lazy evalutation" of a "thingness" that might exist in any of several forms. For instance, in TCL all of the values exist as this mutable state of "string or whatever". If you are working with the value as a string then it is best represented internally as a string; if as an integer then as an integer; etc. So having a getValueAsString() and getValueAsInteger() accessors make sense as they have that opportunity to do things while communicating with the outside world.
Such an enlightened thing should, however, have a [+= int] operator, and that operator should be used in global preference to dong set(get()+X).
So it isnt "really bad" to offer the user the opportunity to communicate with your object, but if you find that the objects *prefer* to be tweaked via this communication, then you have made a mistake that will cost you a lot _eventually_.
In practice, you can avoid this trap by being liberal with the getters but stingy as heck with the setters.
For instance a network socket object should have a lot of getters for things like "local address" and "peer address" and "lcoal port" and "general health"; but you don't want to "set peer address then connect" you want to socket.connectTo(PeerAddress).
Anoter example is "const string & someImportnatValue()" where your object maintians some important string and you might want to let the world examine that important value. But you don't ever let the world "replace" that value whole-scale. You allow the world to opperate uppon the thing, which *may* change the string too.
So expose spesific items of interest through accessors, but only provide "operators" as a means of changing what must change.
After all, if someone can just set a value, then how do you maintian your invariants (requirements of state)?
If you have written a true operator that you have chosen to call "set", then your name is probably wrong at least.
It's a distinction between grays in many cases.
Rule of thumb: the code that changes a thing should be owned by the thing. If you are "borrowing out" some key value, operating on it in the wild, and then "putting it back in" you are probably making code that will cause you harm, because now everybody is "diddling" your state in their alien and undefined-to-you code.
It's bad to be everybody else's (deleted).
Innocent people shouldn't be forced to pay for inferior software development.
--"Code Complete" Microsoft Press
Yeah, this is a common pattern, and I've done it a lot myself, but do you see what you are really doing is just using your object hierarchy as -data-. If you put those relationships into a database of some sort, rather than in code, then adding a new thingy as you describe takes place in seconds and without a code redployment. Every good OOP design is just a bad use of a database.
This is my sig.
The voodoo title would hightlight the real reason we need design patterns -- we (those of us in the software business) don't really know what we're doing. Just like witch doctors, we do stuff that satisfies some inner aesthetic, built up over the years through experience. We learn from our experiences, but don't really understand the causes and effects.
Holub on Patters: Learning design Patterns by Looking at Code Surprised nobody has mentioned this...
maybe you should grab a book about reviewing books instead
Basically "patterns" are a formalisation of "writing the same code over and over again". Probably all programmers end up repeating themselves from time to time, but if you do it so much that you need to formalise the process, then either you're severely lacking as a programmer, or your tools are severely lacking in reusability.
I think the agglutination of people who talk about "patterns" around Java must necessarily indicate a fundamental problem with the language.
It's worth thinking of a "pattern" as a kind of template class, and when you write code using that "pattern", you're instantiating that class, in your head. The amount of repetitive typing we do directly reflects how much our tools suck.
To give a concrete example, I type a line like
in virtually every Perl program I write. This could be called an instantiation of the "robustly open a file pattern", if I was going to be a wanker about it.There are actually three different kinds of suckage going on here:
- Perl ignores the failure of open unless I tell it not to. But 9 times out of 10 I want that error check there. This is the suckage of inappropriate defaults.
- I could write a class to check the open by default, but then I'd need to install it everywhere my software runs. This is the suckage of software distribution.
- I could write a class to check the open by default, but then it would slow down every program I used it in. This is the suckage of manual optimisation.
That last suckage is probably my biggest peeve with Perl. You can have fast code, or you can have good code, but you can't have both.I propose an antidote to all this talk of "patterns", for those of us who still believe that "business logic" is a dirty word. We should start talking about "suckage". In particular the suckage of writing the same damn thing over and over again.
fish and pipes
lol
No, the video properties are not database data, especially not the current value. Also the functionality of switching between the properties as well as functionality increasing/decrease the current property value has nothing to do with a database. You are confused.
You can't handle the truth.
Poor guy is stuck in a statically typed Java hell, with distinctions between primitive types and objects, of course he's gonna think getters/setters are evil and he's gonna become obsessed with keeping his data hidden in a box or behind opaque methods! I can just imagine his code filled with thousands of builder objects with 2-3 levels of abstraction .. and it will just be a grotesque simulation of a true dynamic language in the end, with everything completely decoupled.
This is totally off base. You're missing the point. This isn't about typing, it's about Data Encapsulation.
Pop quiz, in Ruby no less. You have a class:
When your balance is off at the end of the day, you know where to look for errors. One of your methods, probably transfer_to(), is causing the problem. Change attr_reader to attr_accessor though, and then where do you check? Answer: The Whole Wide World! Good luck finding it, you'll need it.
lol, people like you are the reason why I keep trolling. you think I dont know that? the troll is in the fact that a whole bunch of you come in here to tell everyone the truth and then make a big rucas about it. its so LOL to watch 5 or 6 of you make a big fuss.
I once wondered what the reason was.. thanks for the info.
Actually it is a multilayered OOP design.
From bottom to top:
layer 0 is the server memory mapped file access layer
layer 1 is the memory mapped block allocation layer
layer 2 is the memory mapped skip list layer
layer 3 is the profile engine layer
layer 4 is the profile task layer. this is the vm implementation
layer 5 is the socket listening layer and multithreaded job scheduler.
then, on the client
layer 6 is the socket layer
layer 7 is the compiler parse thread
layer 8 is the compiler tokenizer thread - yes, virginia, I put the tokenizer and lexer into separate threads on the client
layer 9 is the data tier
layer 10 is lightweight browsing / chart control tier - internally the new release of commodity server u/i has a mini browser. this is actually separated into two layers, the block rendering / page engine, and its window container. I also wrote my own chart control which has several views and really sweet date zooming.
layer 11 is the user interface itself.
It's a long time in the making and I'm pushing out the next big release soon. The reason for my memo was because during the course of the development of commodity server as well as a fairly big project at work, I've discovered that oop dogma for dogma's sake gets in the way. you have to keep in mind that oop was designed by the military and funded by big corporation as a way to get repeatable coding results out of idiots so that labor costs could be reduced and projects managed more smoothly and outsourced more easily. the emphasis of oop is not on individual productivity, but team productivity, and, as a lone developer, during the development of c/s, I've been gathering cons of oop languages towards the end of solo development. like, design a language that is good for a small team of no more than three or four people, and excels at individuals.
This is my sig.
Good post. I enjoy programming in something like C# not necessarily because of some dogmatic OO ideology, but mostly because of the libraries. In any case, the problem with bad OO is the deep hierarchies. Composition and programming to interfaces are favored over subclassing in modern OO thinking.
Not confused at all. Table in your case could mean comma delimited file all the way up to some mini rdbms server.
The properties are in a table. The table consists of these fields:
property name, property type, property default value.
The functionality of switching between properties is the selection of a row on table. This is in code. Also, the behavior of each of the property widgets is in code. In Windows you could, in C world, say that property type specifies the Window class.
The user interface is initialized by loading data out of the table. Your message loop handles the obvious keystrokes.
If you are smart, you could put the widget code in the property type table as well. But that would mean that your widget u/i layer would have to be in an interpreted language. Code is just a way of expressing a tree of execution, and there's no reason you can't map an OOP to a relational model, and the relational model is can be more flexible if implemented by the right software.
This is my sig.
The problem that I have with OOP is that it is a religion to too many people that take each of its precepts as an excuse to not actually solve problems. I've seen a lot of developers balk at solving a problem, throwing out all of the precepts of OOP as complexities that make it harder to design. You hand someone a problem these days, and they will give you a beautiful class hierarchy of sorts that is beautifully polymorphic, data hidden, and doesn't do a damn thing that the customer wants and certainly took too long to do.
Yet it's difficult to make a good OOP design, and oftentimes, many developers are just good enough to make OOP designs of very simple systems, but can't actually connect the dots and make complex systems using OOP because they simply cannot do the designs. And, ask most OOP activists about real language shortcomings, like, how most OOP languages are crippled for lack of dynamic dispatch, and they will just draw blanks or worse, roll out with a design pattern that is merely a workaround for a language failure. A solution yes, but an intellectual refusal to admit something could be better.
We say OOP is good because it lets you implement good abstraction, but its become a cliche and I think that with all the CPU power we have, we might break up abstraction and reexamine the motivating problems that lead to its adoption, in light of modern hardware, widely available graph theory.
Why, for example, do we have polymorphism? I say that it is a convenient way of arranging code in graphs to reduce decision logic. You factor if-then into class hierarchies? But why not other branching logic as well? And why just branching logic? Why not let one dimension hierarchies of code based on any common language construct!
Why do we have strong data typing? Strong data typing makes for expensive designs and developers usually f--- this up. We have no automatic translation of types except by base class, or in some languages, by matching method syntax - C++ templates or C# generics. What if you could allow automatic conversions to take place? That's a run time check, but could you not avoid that by having iterate decision points in your code as part of a post-compilation but pre-execution step? It's just walking a tree.
Why data hiding? We want to hide complexity, but then, we also don't. I had a C# problem the other day that could only be resolved, ironically, by looking at the mono source for the framework. So much for data hiding and black box code! Why not some way to filter chunks of code and or data streams on demand or at least in various cases.
And finally, why are will still using imperative languages when everyone who ever fires up Excel to do a quick calculation rather than write a C# or Java program implicitly agrees that functional programs are easier to write!
Admittedly, OOP, properly employed, will help us get to that "next step", whatever it is. That new language / paradigm will no doubt be implemented in an OOP language. But those people that think OOP is "the shit", well, I think they are just stupid.
This is my sig.
Yes, and your point is? All data ends up stored someway, in our case we used XML, whatever. The design of a property object has a loose corelation to the data model behind it. You can also say that everything is just bits. You can also say it's electrones' movement. What is your point?
You can't handle the truth.
Porn on the first post! Bravo! This is indeed a pleasurable trend!
What "technique"? The OO-technique? Well, then I am glad to inform you that it was not invented by the DOD. Simula was the first OO-language ever, and it was invented by researchers at NR.
And therefore the title of the book is fine, although "Holub on OO design patterns" might be more accurate.
As you pointed out, if you used a different language, for example one with multi-methods, then you could design things differently. However, there is some debate about whether these other languages are OO or not. For example, is the notion of "self" essential in an OO language? If so, multi-methods abandon the notion of self and cannot be classified as OO. What about method pointers? If "object-oriented" means that the objects are the first class citizens, then method pointers go against the OO principle.
There is a lot of debate on these issues, and many people are not happy to call these features above as "OO". I think it is totally fine to use a language without these features as the tool to demonstrate design patterns in "pure" OO.
I studied programming with Allen Holub, and can truly say I became a 'real programmer' under his tutelage. He's a literate and broadly intelligent man, and if I can boil what I got from him down to one sentence it would be: programming is writing. You know, like writing an essay or a novel. It should be clearly structured and readable by human beings.
Beyond this, though, I think he's taken a bad turn. I haven't read the new book, but familiarity with any real-world programming is not Holub's strong suit. In fact, his dedication to strict OO procedures betray his lack of familiarity with the requirements of real jobs, where you're always forced, by changing requirements and time pressures, to make something of a mess.
The 'game of life' example sounds typical: take a simple problem, implement a solution in a long-winded language (java), making the whole thing even more long-winded by adherence to preconceived pattern methodology, and you end up with a big enough mess for it to look like a 'real-world' program. But the situation is as artificial as any bubble sort assignment in a beginning programming class.Examples like this have zero relevance for what most programmers face when they are on the job: here, modify this million-line program which no-one really understands to fix this bug or add that feature.
Let's realize what computer programming usually is: the creation, under great time pressure, of temporary solutions to problems which will go away or change soon. Worrying too much about purity of structure and reusability is not only unnecessary, it often paradoxically has the effect of creating programs too rigid to be modified over time as requirements change.
Except that increasingly people don't write IP stacks that way because it doesn't scale.
Then there was the "inheritance is bad" deal where everything is to be done with composition and you have to write gobs of forwarding methods between the object and the object it contains.
Now there is this "Get/Set is harmful" -- no, "Evil" I say because this is a matter of religion. So what are you supposed to do when you need to get some representation of state out of an object -- to display it? Can you do a getStateValue()? Oh, no! You have to hand that object an AWT graphics context object and have the object render itself. So much for reusing that object outside of Java.
Or in another Golub article referenced on this topic, you are not supposed to have set functions to initialize an object to a required state -- you are supposed to pass your object a "Visitor" or "Strategy" object that supplies the state -- through what? An interface with a whole raft of get functions?
Suppose the approach was, "Do you have a whole lot of get methods on an object? Why are they there? Is it because you need to retrieve the state of an object to print it out? Have you considered giving your object a Print() method and getting rid of all of the get methods? Are you concerned that your object is now hard-wired into a particular print driver? Have you considered implementing an abstract print interface and implementing void Print(IPrintInterface my_printer) as the Print method?"
But no. The approach is that get/set is "evil" or "smells bad" or some such thing. An object with get/set is a kind of shame and you have to go to extreme contortions in your code, spinning off bunches of classes you never needed before to avoid the embarrassment of having get/set.
I guess I'm just going to have to write the language to show you.
This is my sig.
hahahahaha, you are a funny-man. Tell me a joke, man.
You can't handle the truth.
When I first read that, I assumed you were joking, and had just made that up as an absurd example to exaggerate the author's point. Then I read TFA, and realised that Holub himself advocated exactly that. Talk about getting your priorities completely wrong!
Getters and setters are not "evil". They are a design choice, as Holub himself acknowledges. If you have a lot of these for a particular class, this is often symptomatic of a confused design, but the author missed the point here. The bits you're supposed to hide are the individual aspects of an object's state that must satisfy various invariant conditions. It doesn't make sense to change these independently, because you might violate that invariant. Hence, you only provide operations on the class that change them collectively such that they still satisfy the required invariant conditions.
However, if something can be changed in isolation without violating any invariants, there's no harm in providing a mutator method to do it. That applies up to and including classes with no invariants ("structs") where you can sensibly modify any aspect of the state in isolation. Moreover, if some aspect of state has a meaning in isolation, there is no harm in providing an accessor method to look up that state, even if you wouldn't allow it to be changed directly because of invariant constraints.
Confusing this with the idea that an object should be the only thing that can do anything with itself (such as drawing itself on a screen) demonstrates a spectacular failure to understand the underlying issues here. In fact, it's easy to show this: consider an operation where two or more user-defined types are involved, and you can't restrict all the knowledge about each object to that object and still perform the operation. Attempting to do so often results in exactly the problem with Holub's "draw thyself" example: it tightly binds two separate subsystems, forcing one class to live in both of them, with all the attendant spaghettiness that brings.
Now, Holub clearly realises that mixing UI code with business logic has unfortunate problems. He can protest about inner classes and facade patterns all he likes, but the fundamental design concern -- coupling the UI system to a data-handling system -- is still there. The only way to break the bad coupling is to separate out the facade code or whatever from the original class, and put it in a UI-based layer where it belongs. Of course, that probably requires using some form of accessor methods, which takes up back to where we started.
Who is this guy anyway, and why do some people here think he's good at this stuff? I honestly haven't heard of him before, and I'm fairly open-minded, but I'm not forming a good impression from reading a couple of his articles that people have cited in this thread.
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
The surprising thing here is that nobody seems to be considering that there are more than two concepts at work here: sure you've got the "total" and the "money to add", but you also have the operation of adding two monetary values together, and the operation of assigning that result to yield a new total.
It doesn't matter whether you call the summation operation "+=" or "addTo" or "funkyTypeConvertingSummationAlgorithm". The operation is dependent on both the total and the amount, or more precisely on how their values are represented. There could be complications, perhaps due to type conversion issues: not just the obvious double vs. float type of thing, but for example the possibility that the amounts are value-currency pairs and exchange rates need to be considered.
Until you've sorted out where responsibility for this sort of operation should lie within your design, messing around with whether the function that does it is a method of this class or that one (or a non-member function in a language that allows them) is running before you can walk.
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
Amen! The OO crowd is full of dogmatism but slight on evidence. The existing body of evidence that OOP is objectively better is slim or none[*]. That is the truth, whether you want to hear it or not.
* Assuming we ignore anecdotal evidence. But, anecdotal evidence can be used to prove flying saucers are goosing humans in the dead of night.
Rather than debate here, if you have solid OOP evidence, please place it here:
http://www.c2.com/cgi/wiki?OoEmpiricalEvidence
(I tentatively agree that OOP improves patterns that resemble device drivers, but that cannot be extrapolated into domains I am familar with.)
Table-ized A.I.
One common pattern with maintained code is the cancerous growth of special cases to deal with new requirements. Over time, the special cases dwarf the original code, and it becomes very hard to even figure out what it's supposed to be doing
I agree that this is a huge problem. But OO does not seem to be the answer. Subtyping for specialization assumes a few things that don't pan out in reality.
First is the granularity. Sometimes you need to override only 1/3 of an existing method. Either you have to make tiny methods up front (some propose this but I find it drandruff-like messy), or else reshuffle the code to get the newly needed granularity. If you have to reshuffle methods and classes, then it flunks the goal of being change-friendly.
Second, if you study change patterns, you will see that the differences are not really tree-shaped. Inheritance usually assumes a tree-shaped change pattern. But, the real world has no Tree Cop that forces actual changes to be tree-shaped.
Third, the differences often require different interfaces. OO is not designed to hide interface changes, only implementation changes.
But then again, no paradigm that I have seen has easy solutions to this. The most promising ideas are based on set theory in my opinion, but it is too early to say whether they are the Golden Hammer for the messy Nails of Variation.
Table-ized A.I.
I have wasted countless days reading through nested if-then statements trying to figure out how something works.
Is that the fault of the procedural paradigm or bad programmers?
Sometimes there are ways to fix/simplify messy nested IF statements and sometimes there does not seem to be much that can be done. This appears to be because dispatching is based on multiple independent or semi-independent factors. It is essentially a multi-dimensional problem that we are trying to project onto a one-dimensional surface known as "text". OOP is not a fix because it's built-in dispatching is also only one-dimensional and multiple dimensional OO solutions, such as the Visitor Pattern, are at least as ugly as nested IF's, especially if we have more than 2 independent factors that are intertwining in our dispatching.
Table-ized A.I.