Monday, May 30, 2011

OO in Language Design

If you were to create a new programming language, and you wanted to support object oriented programming with it, what would it look like? An object is a set of instance data and various functions that work with it. In Java, they're specified by first grouping the variables and functions together in a class, and then creating an instance from the class definition. In JavaScript, functions are dynamically attached to the instance data (or it's prototype). This is an intentional over-simplification but does highlight the fact that different programming languages approach working with objects differently. I've been thinking about objects and working with structured code in relation to Kiwi and it depresses me how much the object oriented school of thought that started with C++ and came to fruition in Java has influenced our industry.

Of course there are the so-called five concepts of object oriented design, which says a design that meets the following criteria is considered object-oriented (OO):
  • Object/Class
  • Information Hiding
  • Inheritance
  • Interface
  • Polymorphism

But I'm not so sure I'm convinced. A coworker accused me of trying to re-define it:

Coworker: So now we're redefining what OO is too... care to define common words as well?

Me: I'm not redefining it per se... just calling bullshit where I see bullshit.

Coworker: Excuse while I go outside and laugh loudly.

Me: Sorry my name isn't Martin Fowler so my opinion probably doesn't matter much, but I still smell bullshit.

If we think about programming in C for a moment, a language that isn't considered to support OO practices, we can still encapsulate our code and provide an interface for data manipulation. Member variables are placed in a struct, public methods are functions listed in a header file, and private methods exist only in the code file. Encapsulating in this case depends on an understanding of variable and file scoping rules of the language, not the existence of some class, public, protected, and private keywords.

We have to pass a pointer to the instance class into the functions, but that still happens in languages that are considered to be OO languages too; it's just syntactic sugar that automatically passes it and assigns it to this. It's difficult to ignore the similarity between foo.doSomething() and doSomething(foo).

Java has developers define the method functions in the same code unit as the member variables. Others allow defining them separately, and then associate them in some way later. C++ does this through file and namespacing, and Go does this with interfaces.

If we were to think of instances of objects in terms as payload structs, then is inheritance really necessary? We don't extend a class for example because we have a protected integer member we want to reuse, we do it for the functionality provided by method functions. Inheritance supposedly helps with code-organization and promotes re-use, but I'd argue not essential for OO. In fact, the proliferation of OO far exceeds the amount of code we actually end up reusing.

Polymorphism probably isn't really needed either for OO. Data typing is all about the underlying semantic meaning of data and what operations are allowed to be performed on it. What it means to "add" two strings together and what it means to "add" two integers together are different even though both are aggregate operations. Typing is less relevant in dynamic languages like PHP and Ruby. We don't care what type an object is so long as we can call a method on it. The concept of polymorphism is only important in statically-typed languages, and promoting it as a core OO concept means a true dynamically typed language could never be object oriented.

The way I see it, encapsulation begets abstraction. Inheritance is about reusability, not objects. Interface is a design pattern that attempts to overcome difficulty for reusing code from different objects. Pure object oriented programming seems really to be about encapsulation and message passing, while the concepts above seem more concerned about structure.

It can be argued that the software industry is in the mess it's in right now because of the over-definition and application of intolerant ideas about OO, and a refusal to acknowledge other schools of thought on the subject. But if I'm taking on the responsibility to create a new language, then I'm going to take the time to think about such things and not just follow the herd. I want to create something better, not just a better Java.

Sunday, May 15, 2011

Spaghetti Code Considered Harmful

To chefs and epicureans, spaghetti is a good thing-- it's inexpensive, easy to make, and very versatile. But spaghetti isn't so appetizing to a programmer. The phrase "spaghetti code" is an all-too-common pejorative we programmers use to describe horrible code, whether it's difficult to understand, poorly organized, or just plain long-winded. And there-in lays the problem. What really constitutes spaghetti code is subjective; I've yet to hear a concrete definition or standard metric that measures it.

I've seen PHP code that amounts to nothing more than a giant switch construct... a hundred lines here to handle this condition over here, another hundred or so lines in the branch for that condition over there, maybe a dozen conditions... you get the idea. But such code isn't necessarily spaghetti. What's wrong with it is not that it's unreadable, I would argue, but rather there is a lack of encapsulation. There's a greater chance of inadvertently modifying the wrong variable 800 lines down in some unknown branch, but scoping isn't spaghetti. The code may otherwise be beautifully formatted with the coding standard du jour, and the logic might be crystal clear.

I've also seen OOP code that has been so meticulously refactored that it would bring a tear of joy to just about any DRY-advocate's eye, but that doesn't always mean the code is well organized or easy to follow. It can be frustrating to trace through deep inheritance chains without the help of a modern IDE with project support. IDEs are tools that should help make working with code easier, not be a requirement to navigate what is essentially a set of text files. New professionals coming out of college now with an OOP perspective would be comfortable with such code. They view the same procedural code an old-time C programmer would be comfortable with as messy, unorganized, sloppy spaghetti.

An informal poll I took asked a handful of developers to try to explain what is spaghetti code. They all agreed that it was a term used to describe bad code, but everyone has his or her own opinion as to what aspects would make them label it spaghetti:
  • Spaghetti code is code that is written quickly and doesn't follow the accepted standard.
  • Spaghetti code is any code that uses goto.
  • Spaghetti code is code written by a beginner who's learning to program in Basic.
  • Spaghetti code is like spaghetti in that after you've digested it you are fatigued.
It's trivial to find code samples that relegate such metrics as mere preference, because each one relies on a subjective perception of quality.

The best response I received was from a friend and former co-worker, Sean H. "Spaghetti code is what we call other people's code when we think it's a pile of blackened shit that's baked in the sun and has flies swarming about it but we still want to be polite." Spaghetti code really has nothing to do with code, but rather how we choose to interact with one another. Lacking a proper definition but carrying a negative connotation, spaghetti is just complaining about other people's work which is not beneficial to ourselves or to the quality of the code we produce/maintain.

Some programmers are very protective of the code they write and they can react in a variety of ways to people who call their work spaghetti. Depending on their personality, in an extreme case they may view such comments as a personal attack and become overtly confrontational. Few people like to be challenged on their way of doing something. In a more subtle case, the programmer may begin to resent others. He feels misunderstood and begins to draw inward, subconsciously severing communication channels.

But besides negatively affecting others, our complaining about spaghetti code hurts ourselves too. It's easier to motivate ourselves when tasked with fixing a bug when we're not dreading having to trudge through spaghetti. When we label code as spaghetti code, we are actually creating roadblocks that hamper ourselves and artificially increase the difficulty of the task at hand. A better perspective to have is that we have been given the opportunity to use our skills to fix something and to make it better. Constant complaining only reinforces the wrong attitude and makes it easier to become disillusion with our craft; negativity "sucks the life out of you" and doesn't serve to create a better work environment.

It's almost always easier to complain and set oneself up for failure rather than success. Should I stop harping on Java? Probably. Should I not let my skin crawl every time I run into Zend Framework? Maybe. Though I consider myself successful, how much more successful could I be if I didn't put up mental blocks for myself over what amounts to other people's preference? I have no idea. Old habits die hard, but it's a worthy goal to strive for to stop alienating others and making life difficult for myself by complaining about spaghetti code. Feel free to join me in doing so.