Tuesday, October 26, 2010

Never Found A Programming Language I Couldn't Love

Notice: this was originally posted to the CodeProject's Lounge in 2010-10-25, and featured in the Daily News the next day. Yay me! :P

Some say that "when the lady can't dance, she complains the band can't play". Generally that's my feeling towards complaints that such-and-such language is "bad", or that it produces "bad" code.

I do agree that some languages lend themselves more than others to certain good (or bad) practices, and that some languages are better/worse suited than others for some problems. However, in my experience the most crippling problems are the result of poor programming style: the respective programmer community either doesn't know, or seems to forget how to write clear code once they join in.

As way of example, this is my list of good practices for several widely-belittled languages. It's mostly about how you can use each language's specific features to uphold the principles of structured / OO programming:

Visual Basic
  • Always use Option Explicit for enforcing variable declaration;
  • Shun Variant variables – always use definite types;
  • Horribly misnamed as they are, embrace "Classes" as the way to go for behavior encapsulation;
  • Use the Object type sparingly, but learn to recognize where it can be leveraged for generalizing algorithms;
  • Well employed, the On Error machinery can make do as an effective Exception system;
  • Prefer Collections over Arrays, and learn to explore their associative features.
C
  • Just because the language doesn't enforce a type-oriented form of programming doesn't mean you shouldn't. Always think about problems in terms of data types and accompanying operation (function) sets;
  • Structure your code as a collection of header / source pairs, where the header defines (ideally) one data type and its API, and the source contains the implementations;
  • Create more complex types by composing simpler ones, and likewise implement their API's in terms of the lower types' interfaces;
  • When designing a type's API, remember to provide functions for dynamic instantiation, initialization of stack-defined instances, and deletion. Consider providing macros for access to struct fields, instead of conceding to direct dereference;
  • Preserve the global namespace by defining symbols as static whenever they don't have to be seen outside their compilation units;
  • Use function pointers for generalizing complex algorithms;
  • Though dreadful when used carelessly, macros have great potential for simplifying programming interfaces – know when and how to use them.
C++
  • Forget struct's, always use classes;
  • Forget memory buffers and pointer arithmetic, use the STL collections instead;
  • Prefer inline functions to macros;
  • Avoid using pointers whenever possible. Use references for function arguments, inline definitions for class members, STL collections for dynamic instantiation, and locally-defined variables for automatic memory management;
  • Leverage variable scope control for automating common operations, as logging function calls;
  • C++ exception support is poor, but it's better than nothing – learn to take advantage of it;
  • In general terms, do not stand with one foot on C and the other on C++ – jump in with both feet.
Scripting Languages (Perl, Javascript, PHP, etc)
  • Just because you're writing to a script language doesn't mean you should forget how to program – structure your code around data types and/or classes, concise functions and specialist modules, just as you'd do on a "proper" systems programming language;
  • Do not mingle your code to HTML. Write everything on separate modules; where inline code can't be avoided, provide as concise an interface as possible, ideally a single function call.
What about you? Do you think there are inherently "bad" languages, or is it essentially a matter of poor practice?