And if you think I'm on crack for saying such things, see this PDF file. Modula/Oberon programmers agree with my philosophies, it seems. The PDF file states that objects are not Holy Cows, and that sometimes we are better off using modules and procedures.
Five hundred and five object oriented programmers are asked to build a component or object or class. After arguing about 3 million ways the object could be created and what design schemes to use, a lot of algorithms are finally placed into the object and the object starts working. The algorithms are called by creating an instance of the object first.
The only problem is that some of the algorithms are welded into the object. Even the public algorithms are welded to the object instance.
Real World Example
When I was looking for a Source Code To Html converter system I thought of writing my own parser/tokenizer. Then I realized that the Synedit component for Delphi and Freepascal already had a tokenizer and source to html converter. I didn't need synedit for my program, I just needed to convert source to html (for example, if I wanted to convert C, Pascal, or PHP code into syntax highlighted HTML.)
Surely since objects are "reusable" and since you can "inherit" and since object orientation is supposed to discourage copy/paste coding.. I could "reuse" the source to html converter in Synedit, right?
Well, the problem with objects is that they can weld certain things together which you can't really unweld, without breaking the entire system.
Trying to pull the code to html converter out of Synedit was like trying to remove an engine from a car with the hood welded shut. First I had to try and melt some welding solder with a torch, which didn't work, and once I did that a few things caught on fire and the car wiring started melting so it wouldn't run any more.
Of course, after the fire and after all the time I wasted on trying to dissect the object, I wrote my own Source to Html converter from scratch in a separate unit of my own, and ended up wrapping the tokenizer up into a nice public function that was something like this:
SourceToHtml (returning a string)
SourceToHtmlFile (saving to a file)
SourceToHtmlCustom (output the html anywhere, flush to stdout, buffer, file, etc)
Instead of the above functions, you could create a "source to html object", and then try to weld the "source to html object" to the Synedit object somehow, and weld it to stringlists and memory streams - there are a million ways to do that and a million different ways to go about that. Pondering about it gives me shivers, as there are just too many options. Why didn't the Synedit team (an experienced OOP team) create the source to html converter so that it was reusable for me?
The problem is that objects can't predict every single use case for a function or method. Some things end up being welded together.. because humans don't always get the objects right from day 1. And after day 1 of creating the object, it becomes harder to unweld and decouple certain things from the object for other developers who didn't write the object originally.
Instead of considering all the object oriented options, and instead of pondering, sometimes its just better to create some ALGORITHMS that do something NOW.. a verb. JUST DO IT. Then you can reuse your verb inside your nouns.. those SourceToHtml converter functions can be reused inside a million different objects from five hundred and five different programmers who all have different opinions on what the correct object design pattern is to use.
Algorithms and useful functions need to be written (verbs) regardless. The noun that encloses the verb is a moot point, icing on the cake, or sometimes worse.
Wait a minute - is this guy telling us that algorithms are reusable if they are written down in a public unit? Since when is public without an instance good thing...?
Of course anyone could have written something like this:
property: ConvertToWhat(file, string, other)
But the loadfromfile and savefromfile methods.. aren't those something we've seen in some other object? Could we inherit those loadfromfile and savetofile methods from some other object inside the sourcetohtmlconverter? Could a TStringList be inherited? Not really since the TStringList was meant for stringlists and not for converting source to html... but if we had a FileToString or StringToFile function that was in a public reusable unit... maybe we could reuse some of the algorithms...
Hmm.. so the loadfromfile and savetofile functions are also welded to the TStringList object and I can't really pull those out without copy/pasting, can I? How am I going to weld the TStringList object to the SourceToHtml converter? Okay I could put a TStrings inside the SourceToHtml object as one of the objects fields or variables - now I've welded together two objects that have tons of methods which I will never want to use.. the stringlist is a stringlist, it isn't a loadfromfile function. All I needed was the loadfromfile function from the stringlist - I didn't want the entire stringlist stuff to be brought along too!
Errmmm... so, I could have just used the FileToString function I wrote in a public unit.. since that is all I needed. BUT THAT IS NOT OBJECT ORIENTED PROGRAMMING MR. SMARTIE AND YOU HAVE NOW DONE VERY WRONG. Or have I? Whatever works, whatever is reusable.. you know.
Heck I may even be able to make use of the ReadLn function with a text file if the string snippet is really large and I need to read it in chunks or line by line instead of all at once, instead of trying to Weld a Tstream object to the SourceToHtmlObject. After all, the only thing I wanted to effing do was convert some source code over to HTML.. hence the function, SOURCEtoHTML.
Of course there was this other time when I tried to unweld the FPDOC parser from the FPDOC objects and use the parser to parse pascal, without creating actual documentation. That didn't work either since fpdoc welded the parser to the documentation creation system in many ways. Not that someone couldn't have created separate objects and welded the objects together in a more reusable way - it was just that there were too many possibilities and someone didn't do that because of the possibilities. And there was this other time when I tried to modify the FPDOC tool to output an HTML snippet instead of outputting a full html page with html head tags.. I tried to inherit the fpdoc tool but it was too complicated for me to figure out. And I'm not a dumb guy, as you may have noticed (or not). So I posted a mail to the fpc list asking how I would inherit or modify the FPDOC tool, and all sorts of possibilities existed, but no one ended up showing a way it could be done. So of course I just blackboxed the FPDOC tool and trimmed the html using a separate program.
The problem with some object oriented thinking is that there are TOO MANY PRIVATE OPTIONS and inheriting doesn't usually work since it creates monolithic bloated objects that aren't specialized in doing one thing well. Sometimes a SIMPLER more ELEGANT PUBLIC option may exist which does something well - rather than trying to be everything in one instance. Yes I know you can make a method public in an object - but making it public still means it is welded to the object instance, something that is not so good in many cases (such as the IntToString function being welded to a system object... or should it be welded to a string object, or should it be welded to an integer object? Which is it? Or should it be decended from one MainObject and not be welded to any object specifically, except the main TObject? or should it just be generic? or should we just make it the IntToString function in a separate public unit, not welded to anything specifically, since it don't need no damn welding?)
Cookies that have nice packages
So tell me, in web pogramming.. should the GetCookie and SetCookie methods be placed into the main TWeb object, the TWebCookies object, the TCgi object, or the TSessionsAndCookies object.. or should I just create GetCookie and SetCookie functions in a public unit since setting and getting a cookie is fairly straighforward.. and since putting them in a public unit would allow anyone to wrap them and create there own objects with them? If I were to put it into an object after first figuring out (inconclusively) which object it should be in, should this SetCookie method and GetCookie method be protected, published, public? Should it allow one to get more than one cookie at once (i.e. an indexed object or other tricks to make it do cool things, instead of just using an array), and should I be able to inherit and override the GetCookie method with my own derived method? And should the GetCookie and SetCookie methods link to an object property, the Cookie property. And should this Cookie property of the object have indexed access to several cookies, or should it reference only one cookie at a time?
These are only the questions that I would start to ask myself - this doesn't include all the questions other programmers on the team would ask about and debate about. Meanwhile, we aren't getting any algorithms written - we are just objecting to each others objections.
My vote would first be to shut the hell up and stop Objecting to Objections, and just make the GetCookie and SetCookie functions into a public unit available for anyone to access, since a lot of people are going to be needing these GetCookie and SetCookie functions. Instead of methods.. put them in a public unit - and have people decide WHAT THEY WANT TO DO with the getcookie and setcookie functions in their own object wrappers, if they even decide that they need wrappers. They can privatize the hell or inherit the hell out of a public and open function in their wrapper, if they want to, if they need to.
There is no holy grail or purism to follow
A public function that can screw up a pointer to a pointer to a global variable isn't good, but sometimes a privately welded together object isn't so good either.