Sunday, December 23, 2007

The Admission That Every Developer Must Make...



...is that no matter how great you think your code is, it ultimately sucks. At some point in time, the "great" code that you think you're writing will ultimately cause pain on somebody else.

The Gift That Keeps on Giving

Code is a lot of fun to write, but the more code you write, the more suffering you inflict upon others. I can't begin to stress enough that the mere presence of code itself is a symptom of a problem. It means that you had to write something because whatever requirements that you had to meet couldn't be done using the existing code that you have at your disposal. In other words, you're writing code to solve a preexisting deficiency, whether it was a deficiency on someone else's part, or your own.

Isn't it i.Ronic()?

This has to be the greatest irony of software development: we (as developers) write code to solve other people's problems, but the more code we write, the more problems we inflict on other developers that eventually have to maintain our code. In the end, someone out there has to maintain that 'wonderful' solution that you thought you wrote in yesteryear. In the end, someone else has to write their own version of your library because you had some deficiency in it that was too complicated to fix. That new library, in turn, will eventually fail to solve another problem, causing another developer to write another application to solve the new problem that couldn't be fixed using any other means.

The Path of Suffering

It's a vicious cycle that never ends, and at some point, this pain of maintenance that we inflict on other developers must somehow end. A naive solution to this would be to stop writing code altogether, but it still doesn't solve the problems that we as developers ultimately need to solve. We still need to write code in our daily lives to pay the bills, and people will still need us to write software so that they don't have to do all their work by hand. In other words, it's a necessary evil that perpetuates itself. We cannot avoid the fact that our jobs (by definition) require us to write more and more code--and that's exactly the problem. Code begets even more code, causing the suffering to continue.

Code Nirvana, and the Path of Enlightenment

This cycle seems complicated and nearly impossible to fix, but the solution is ridiculously simple: write less code.

In general, there are a few ways to do write less code:

-Design Patterns.
-Refactoring.
-Keeping it simple.

Design Patterns - A Panacea?

Unfortunately, there are some people out there that think that implementing a particular design pattern automatically leads to less code. That's not always the case. The more patterns you add to your application, the more suffering you inflict on those who have to maintain it and those who use it, and that still doesn't solve the problem of ending the suffering altogether.

It means that if you need to use multiple design patterns in your applications, more often than not, your code is far too complicated to write using the simplest possible means. Design patterns exist to simplify code, and if you find yourself scrolling through thousands and thousands of lines of code in multiple source files to figure out how your 'cool' pattern works, then you're defeating the original purpose of having those design patterns altogether: simplicity.

if (complexity == null) { // Cool! }

For me, it's always a pleasure to see someone else write something so simple that I don't have to waste any more than five minutes trying to figure out how to use their code. Unfortunately, such moments rarely ever occur for me, and more often than not, I find myself having to wade through pages and pages of their code or documentation (or both) to do something that's supposedly 'simple' to do using their software--and that assumes that they even write documentation at all.

Yet again, it becomes even more ironic because it seems that the same developers who write documentation for their code are actually compensating for the fact that their code is so complicated that it needs documentation in the first place. Even I have to admit that I'm guilty of this myself, given that I wrote a series of articles that describes how to use LinFu. It's certainly not as simple as I would like it to be, and in my opinion, admitting that it can be made simpler (or more importantly, admitting that it sucks) is the first step in becoming a better developer. In any case, the same principle for having more and more code is also true for having more and more documentation: More documentation is a symptom of complexity. It's not a feature--it's a liability. So if design patterns themselves don't necessarily mean simplicity, what about Refactoring? Does that solve the problem?

I Code, You Fix It (Later)

Refactoring is certainly one of the best things you can do for your application(s), and it definitely can reduce the coding "footprint" that you impose on developers who will eventually maintain your code. However, at the risk of sparking some controversy, if you're the initial developer, refactoring is actually something that you should avoid, and I'll explain why.

Hold Your Pitchforks...

Before I become labeled as a madman, let's analyze the etymology of the word "refactoring". The Greek/Latin root of the prefix "Re" roughly translates to "again", and the word "factoring" (according to dictionary.com) means:


2. the act or process of separating an equation, formula, cryptogram, etc., into its component parts.


The meaning of the word "factoring" (in this context) is effectively the process of designing your application. In other words, when you combine those two small phrases together into the word "refactoring", it means that your design was faulty enough to warrant a redesign of your code. So my only criticism with refactoring is this--refactoring isn't a preventive measure. It's a reactive measure that everyone (including myself) undertakes when they slowly realize that their code really, really sucks.

So when I say that you should "avoid" refactoring, what I'm actually saying is that you should avoid having to make your code so complicated that it needs to be refactored in the first place. Refactoring, in practice, is an absolute necessity; however, you can avoid refactoring altogether by making your code so simple that it makes refactoring seem ridiculous. For example, when was the last time you had to debug a property getter/setter like:

public int SomeProperty
{
get { return _someProperty; }
set { _someProperty = value; }
}

Dubya-Tee-Eff?

The above example might seem too simplistic--and some people would even scoff at the concept of debugging something so simple--but that's the idea. It's so simple that you don't have to worry about how it works--it just works. You can criticize it all you want for being so simple, but it probably took you less than a second in your mind to make a judgment about it, and move on to something else more useful. In contrast, it naturally takes several hours (or even days, weeks, or months) to solve something more complex. The point here is that having simplicity precludes the need to refactor and (thus) redesign your application, and that something I'll talk about next.

The Best Code Ever Written

The best code that I have ever seen in my life is certainly not my own; however, it's really easy to remember, and you can find it in between the two comment lines below:

// ---begin best code ever written--


// ---end best code ever written--

No, I haven't gone crazy. You might be saying to yourself that there is no code between those two comment lines. You're right.
The best code ever written is code that doesn't have to be written at all. Ultimately, it's being able to solve a problem without having to resort to writing code in the first place. There's literally no code to maintain, meaning that no poor sap has to cleanup my code in the long run. No suffering, no pain, and no mess. It's simply beautiful.

For those short of this lofty goal of not having to write code (including myself), however, my only advice is this: Simplicity is the ultimate design pattern. If you write it simple the first time, you won't have to worry about refactoring it because you "fudged" it with several other not-so-simple design patterns. You'll be able to rest well knowing that your code won't cause someone else to curse your name at 4am (your local time), and in the end, that is truly sweet indeed.

Friday, December 14, 2007

Holiday Hiatus.

I'll be taking some time off for the holidays, so that means development for the LinFu framework is going to take a break for the holiday season, as well. When I come back after the new year, things will again go back to full speed. Happy Holidays!

Monday, December 10, 2007

My Love-Hate Relationship with Mono.Cecil

I managed to fix the bug from my previous rant about Mono.Cecil, and I've even managed to implement some jaw-dropping method interception capabilities using that library. I can now intercept any method from nearly any .NET assembly, regardless of whether or not that method is static, sealed, and even non-virtual. The only problem with this library is that the more I explore its capabilities, the more I find myself becoming too dependent on Mono.Cecil. It might take me another year of research just to get LinFu.Reflection.Emit up and running, so for now, I really don't have any other viable alternatives to use (other than Mono.Cecil, of course).

It's ultimately a 'marriage of convenience' of sorts, and until I can make an alternative of my own, a figurative divorce is not an option.

One of these days, my bouts of NIH (Not Invented Here) syndrome are either going to either going to make me rich, or just plain insane, and since the first option doesn't seem so possible, I think the 'insanity' option just might get the best of me.

Wednesday, December 5, 2007

A feature that I would love to see in future IDEs...

With all this talk of type inferencing on the horizon and with the coming of Dynamic Languages to the .NET platform, one feature that I would love to see in VS.NET is something I call it Intellisense, with "Type Prediction".

The concept is actually quite simple. Since dynamic languages themselves have the ability to dynamically modify their types at runtime, it would be nice if the compiler were smart enough to "predict" (at compile time) which methods and properties that a class might have at run time. So, for example, if I had a class called MyDynamicClass, and if at some point in the the class' lifetime, I wanted to add a method called DoSomething(), then the IDE should be able to effectively guess which parts of the code have a DoSomething() method available and give me an intellisense listing of all its signatures.

Then again, since we're only at the cusp of even beginning to use dynamic languages on the CLR, it'll be quite a while before anyone picks up on this idea. Oh well. :)

Ratings by outbrain