This Blog has Moved

June 21, 2008

I’m moving this blog to blog.codedemora.com. I’ll be keeping this on up for historical reasons. Pleas update your bookmarks and RSS feeds

Thanks

There was quite a bit of uproar regarding my rant about C# regions. At the time, I was looking through a lot of really bad code, and I was pretty peeved at how all the pieces of complex code were hidden away by Visual Studio.  However, some of the comments seemed to imply that there is no such thing as “perfect” or “good” code when you refer to code written by someone other than yourself. And, to be honest, that is true: I like to think the code I write is better than most other developers. However, I want to qualify what better is:

Better code is:

  • Code that is tested
  • Code that is maintainable
  • Code that is understandable by someone other than me
  • Code that is changeable by someone other than me

Even with those guidelines, there is still some room to define more terms, but we have to stop at some point. Notice how none of these points really points to Lines of Code, the degree of algorithm obfuscation or how low the average cyclomatic complexity is for your codebase. These bullet points take a professional approach to the software development profession. That is, I and many others are professionals, and we should write our code as professionals. I hold myself to the same high standards as I hold others. Granted, I don’t meet those standards all the time either. I try not to beat myself up about it, because I would never win.

However, I wanted to be less emotional about why regions are really not that great. Just flat out, the main reason I see is that when you encapsulate code in region blocks, you miss an opportunity for one of many refactorings. In other words, you are knowingly violating principles of good software development by hiding the “bad” code under the rug.

Regions are simply comments preprocessor-style comments. As with normal comments, they are removed before the code is compiled, and are only there to help our non-digital brains cope with the mess we created in the first place.

I try my best to follow the TDD (and by extension, BDD) methodology, and so far, I have found no need for regions. Ever. I find that they clutter the code. I also find that TDD manages the mess I create much better than regions because they are like little pieces of thoughts that stick around to keep verifying my intentions several features back. TDD is by no means a do all methodology, but it has saved my butt several times, and does tend to make you write code that is neat, well tested, well organized and region free.

This is so last minute notice, but tomorrow is the Desert Code Camp in Tempe, AZ. I’ve attended the last few code camps, and they’ve been loads of help to me and my career in software development. This year, I decided that I should try to give something back, so I’m presenting on a couple of topics: Test Driven Development, and Behavior Driven Development. I’ve been practicing and evangelizing TDD for a couple of years now, and this is yet another outlet to try to convince others that this is the path toward code enlightenment.

Spoiler Alert: BDD on the other hand is somewhat new to me. However, as I’ve read many of the descriptions, and BDD testing frameworks, its really all about the way you look at tests, and the eventual evolution of what your firstly written unit tests eventually become: behavior specifications. I will be talking about the little I’ve learned about rspec, nspec, and nbehave tomorrow.

See you all tomorrow!

Just say No! to C# Regions

February 29, 2008

I’ve seen lots of C# code over the last few days, and 100% of it contains the #region construct. So far, I have see it used in only one way: to hide big code blocks. Some of you might be saying “Duh! That’s what they’re for!”.

Well, let’s think about that for a minute:

You need a language construct so that your IDE can help you hide your big messy code block from you (because it’s just so hideous, you don’t even want to look at it anymore)?

If your code is so bad, that you just want to shove it under the covers, then I would argue that your design and the solution to said design is too complex.

Most of the uses I’ve seen of regions are to group member fields, constructors (and related overloads), methods and properties together. This has to be the most retarded way to use a tool because you have other tools to perform this same function. Granted not everyone can buy Resharper, but the File Structure window provides all that same information. Heck, if you simply followed a simple code standard such as:

class <className>
{

  private members
  constructors
  properties
  methods

}

this would do the same job. Honestly, if you can’t LOOK at your code and tell a constructor apart from a property or field, then you should be looking for a different line of work. Please, stop commenting the obvious!

Now, you will eventually get classes that are thousands of lines long, however there are other constructs in the language that can help you keep things neat without using this lame excuse for a preprocessor tag. When you DO find your class encroaching on this large line number threshold, that is a prime time to look at your code for copy/paste refactoring tragedies and do it right. It might be a little painful now, but it could be the thing that saves your project in the long run.

Another lame way I’ve seen regions used is within a method. Usually there is a large block of setup code that is copy and pasted all over the place, with the same region tags. C’mon people, at that point, read about the Extract Method refactoring and actually REUSE that block of code intelligently!

I honestly can’t think of any reason to use #region tags because all the things they are hiding is just really bad code. When you start to just hide bad code, you are less inclined to go back and refactor it properly.

Let’s try this analogy: if you were looking to lose weight before the summer beach season, the best thing to do is get a mirror. This way, you will be re-motivated on a regular basis.

The mere act of having the bad code stare back at you will make sure that it is at least not forgotten. Nearly all codebases have some code that is not koesher. Let’s try to make that lump of code as small as possible. By then, you may even find a way to get rid of that eyesore (and system-sore) all together…after all, it was probably some hack anyway.

I’ve been a huge fan of Rhino Mocks since I heard about it on a way-back-episode of Dot Net Rocks HanselMinutes. One of the more awesome features of Rhino Mocks is that it utilizes a Record/Playback semantic so that you can set up your mocks with actual calls to the mock objects, then play them back in your tests. This is great if you rely on intellisense when calling your object instances, or if you use Resharper or another code refactoring tool.

Recently, I trying to use Rhino Mocks with DataTables like so:

DataTable a = new DataTable();
DataTable b = new DataTable(); 

MockObject mock = mockRepository.CreateMock<MockObject>();

using (mockRepository.Record())
{
   Expect.Call(mock.CreateRecord("TableName", a, b).Return(1);
}
using (mockRepository.Playback())
{
  MyObject obj = new MyObject(mock);
  obj.Save();
}

When I ran the test, Rhino Mocks says that a the DataTable created during the obj.Save() call wasn’t the same as the one expected. This was correct as there were now two instances, and it seems that the default check Rhino Mocks performs is an Object.Equals(). Since I needed to do some more deep comparisons of the Expected and Actual DataTables, a fellow developer and I started a very simple DataTableConstraint:

    class DataTableConstraint : AbstractConstraint
    {
        private readonly DataTable _expected;
        private string _errorMessage;

        public DataTableConstraint(DataTable expected)
        {
            _expected = expected;
        }

        public override bool Eval(object obj)
        {
            DataTable actual = obj as DataTable;
            if (actual == null)
                return false;

            if (!CheckColumns(actual))
            {
                return false;
            }
            if (!CheckData(actual))
            {
                return false;
            }
            return true;
        }

        private bool CheckData(DataTable actual)
        {
            if (actual.Rows.Count == 0)
            {
                _errorMessage = "Actual table has no data to compare";
                return false;
            }
            try
            {
                for (int i=0; i < _expected.Rows.Count; i++)
                {
                    foreach (DataColumn column in _expected.Columns)
                    {
                        object expectedCell = _expected.Rows[i][column];
                        object actualCell = actual.Rows[i][column];

                        if (expectedCell != actualCell)
                        {
                            _errorMessage = string.Format("Expected {0} in Row ({1}), Column ({2}), but was {3}", expectedCell, i, column.ColumnName, actualCell);
                            return false;
                        }
                    }
                }
                return true;
            }
            catch (System.Exception e)
            {
                _errorMessage = e.Message;
                return false;
            }
        }

        private bool CheckColumns(DataTable actual)
        {
            foreach (DataColumn column in _expected.Columns)
            {
                if (!actual.Columns.Contains(column.ColumnName))
                {
                    _errorMessage = string.Format("Could not find column {0} in {1}", column, actual);
                    return false;
                }
            }
            return true;
        }

        public override string Message
        {
            get { return _errorMessage; }
        }
    }

To use this using the above sample code, do

Expect.Call(mock.CreateRecord(null, null, null).Constraints
(
  Is.Anything(),
  new DataTableConstraint(a),
  new DataTableConstraint(b)
);

Now, this is just a start, and will probably evolve more as I start to get more into verifying the data in two tables. Perhaps Oren will create a new Syntax Helper along the lines of Data.Equals(expectedDataTable) since using a new Constraint() call is a little awkward.

As a student in the Engineering college, I thought all the computer science classes were a waste of time. I mean, who cares how to properly define a push down automata and prove that it is, in fact, deterministic? Can P = NP? How do you write a grammar that defines this language? This class was the engineering equivalent of the touchy-feely hippie course that was required to complete my Computer Engineering degree. I mean, we were engineers, we weren’t going to be doing proofs in our future careers. We were going to be paid to implement; and I am being paid to implement software now. 

In much of the code I have seen, there have been far too many examples where a background in computer science was not present in the developer’s mind (minds when pairing).  Not that you have to have a formal degree, or classes, but a fundamental understanding that there are good ways to do things, and bad ways. It goes back to the analogy of having all the tools in your toolbox to use so that every problem does not become the nail to your hammer. If you understand the concept and application of grammars and languages, then you can use the tools available to you to create one. 

I have learned in the time since I completed college and have become a full time software engineer is that you need that background in computer science in order to understand the tools available to you, and to implement them properly.  This is the difference between a software engineer with a college education and a hacker who just writes code.

So, to bring this post to something concrete, let’s look at what I’m working on now. I’ve been tasked with parsing some stuff for an application. I could have just as well created my own parser using my own TDD methods so that at least when I need to make changes to the parsing algorithm or the language changes, I can make changes easily and know where things break, FAST. But I thought to myself. “There is no way I am the first person to encounter this problem, someone else has to have some experience to share” So, poking around, I found an open-source project called ANTLR. Now, to be honest, I’m still trying to wrap my head around certain aspects of what is done by the tool, and how to use it effectively. But, by using this tool, I effectively get a high end custom language parser generated for me based on my language specification. This is also a section of the code I don’t have to directly maintain. I do have to fix language inaccuracies, however, I get a lot of functionality for free. Things like error-checking, multi-language compatibility, and efficient parsing algorithms are useful, and completely maintained by someone else!

This post has turned into an agile leaning example, but this is one of the many tips included in The Pragmatic Programmer. Be sure to learn the tools available to you because while it will be slower at first to grok something new, once you get over the hump, you will be able to use that tool at a moment’s notice, and move on to other problems that need solving.