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.

A Picture of Walt Howard

WALT HOWARD

Senior Software Developer Walt Howard is a Senior Software Developer on the CORE engineering team at MediaMath. He began his C++ career with version 1.0 of the Microsoft C++ compiler. In his own words, "I was a C programmer and was continually frustrated because C didn’t have certain automatic, housekeeping functions I thought were only sensible, like destructors, templates, and exceptions. When C++ came out it was all my programming dreams come true. I was an instant convert. It was like Bjarne Stroustrup was reading my diary." Walt finds himself in the peculiar position of being a right-brained programmer in a left-brained programmers' world. He values simplicity where most programmers strive for complexity. “I would rather augment a naive, overly simplistic solution than try to undo a tangled up mess caused by complexity.” As for experience, Walt has been involved in software development with evolving techniques and team sizes since before MS-DOS.
1 Comment.

One response to “Whattup With Walt: Whattup with blindly using the crippled APIs someone else provides you?”

  1. Hi Walt, great article!

    I don’t think standard Linux API calls lack mentioned functionality.
    Combining strace, strace-plus, ltrace, tcpdump tools and proc fs you can get any performance and trace information.

    To get the time spent in each call you can do “strace -T -tt”.
    strace also logs passed parameters and return value.
    strace-plus produces a trace of the system calls with calling context.
    ltrace produces a trace for all library calls including a calls to libc.so, libdl.so and so on.
    To control memory allocations there is malloc hook in libc.
    To get file name by descriptor one can use list from /proc/[pid]/fd/*.
    To get listening socket by descriptor get node id from /proc/[pid]/fd/*, then do netstat -aenp|grep [node_id].

    So i’d rather not say there is a lack of transparency.

    Regards,
    Serge

Leave a Reply

Your email address will not be published. Required fields are marked *