Whattup With Walt: Whattup with blindly using the crippled APIs someone else provides you?
Be ever willing and ready to enhance the APIs you are given by wrapping them in your own functions and classes.
At some point, you will discover the “standard” function or class will prove to be incomplete, cluttered, broken, lame, slow, bloated, byzantine, obtuse, and a host of other adjectives best summed up as “annoying.”
When I use the functions provided by a general-purpose library, I find they have been weighed, measured, and found wanting. They always have some deficiency that drives me nuts. Give me any function provided by standard Linux or Windows API libraries, and I’ll show you something that it lacks.
Here are several lacks I can give you right now:
No performance information! These functions cannot tell you how long they took to execute and that becomes very important later on when you are trying to make your code fast and sexy.
If you were to wrap them in your own function instead, you could request timing information.
No logging! These functions provide no logging so you cannot keep track of when they are called, parameter values, and performance.
No Collection Level Information! These functions and classes cannot relate themselves to other instances when you call them, or a complete list of the objects you created so you have an inventory of what objects exist in your program. For example it’s often very useful to know all the files you have open in a program so when you exit you can explicitly close those files, making sure the data is written as you intended.
Not thread safe! Many of the standard objects and functions are not thread safe. For example, all of the STL classes!
Not exception safe! Many programmers write libraries and refuse to make the jump to light speed and use exceptions. In fact one huge, rich and famous software company, has it as a policy.
Now here you will say, “That’s intentional. These things are not supposed to be universal solutions.”
And that, grasshopper, is exactly the point I’m making.
Those general purpose functions don’t do exactly what you require, so don’t use them directly.
Wrap the functions and classes you are given inside your own. It will make your life much easier.
Here’s a more detailed case.
Most functions provided by the operating system, or even standard classes, provide a file class of some kind. It’s usually a class that is used to “hold” the file handle, a number, or pointer of some kind.
That file class is useful, but it does not uniformly save the name of the file within the class. It also does not save the list of all the files you open, nor does it remove them when you close the files. Thus, when an error occurs on a file read or write, your error message cannot tell the user the name of the file involved in the error! When you exit the program, you cannot iterate through all the open files and close them intentionally.
Don’t use that class. Subclass from it and create your own. You may not know it at the time, but later on you will find a deficiency in the standard class. However, since you used your own class, you can actually fix the problem. If you are using C++, and you create a subclass that merely inherits from a base class without adding functions or members, there is no cost. You haven’t added any additional memory requirements and your execution time doesn’t change. But you have enabled this class to have additional functionality added later should you desire it.
When you do that, you protect yourself from deficiencies that are discovered later. Since your class (not the standard class) is being used throughout the program, you can very often tweak your class to add the required functionality you found out later that you needed.
A good example of the necessity for your class to know about all instances of itself is threading. My multithreaded programs always exit cleanly without crashing ever. Why? Because my Thread Class keeps track of all of its instances and when the program exits, it explicitly makes every thread created, finish processing and it can do this because it keeps track of them all. I’m not saying having your class keep track of all its instances as a static list is the only way to do this, but it is one good way. And remember, you don’t have to do this when you write the first usable version of your class. But if you later discover you need something like this, you can retrofit it in there, encapsulated in the class, without refactoring other parts of your program.
If you try to keep track of all the threads outside your Thread class, that requires discipline, maintenance and consistency which humans are not good at. Humans are good at creativity.
If you make the class itself do it, everything it needs to do its job is available right there. The code is easy to write and once written you don’t have continually remember to keep it in sync with the rest of the program. The threads all innately know to self terminate when the program exits.