CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeffrey Palermo (.com)

Blog moved to www.jeffreypalermo.com

January 2007 - Posts

  • Cropper 1.9 release - screen capture utility - level 200

    Since I discovered Cropper, I've used it to create all of my screenshots.  I place and resize the translucent overlay onto my screen and capture exactly what I want to capture.  If you do screenshots, I'd recommend giving it a try.

     

    http://blogs.geekdojo.net/brian/archive/2007/01/29/108748.aspx

  • TeamCity 1.2 from JetBrains just released - level 200

    From the name's similarity with Microsoft's TeamSystem, I thought JetBrains might be trying to compete with Microsoft in the team collaboration arena.  They might be still, but TeamCity 1.2 is definitely a continuous integration server. 

    JetBrains is well-known from their excellent IntelliJ Idea Java IDE as well as their Resharper add-in for Visual Studio 2005.  In fact yesterday at the local AgileATX lunch, Scott Bellware and I spoke about how much we actually develop in Resharper more so than in Visual Studio.  Resharper replaces the Visual Studio experience with a better developer experience. 

    JebBrains originally targeted TeamCity to Java developers, but that was because they only had plugins for Java IDEs.  With TeamCity 1.2, they have completed an integration plugin for Visual Studio that allows integration with the TeamCity server from the workstation. 

    For those of you who use Team System (or wish you could afford it), note that TeamCity is a continuous integration server at this point, not a project management server or work item tracking server.  TeamCity is competing directly with Thoughtworks open-source project CruiseControl and CruiseControl.Net.  You can see a comparison they have done between the three.  In the comparison, they appear to have many more features, but none of the "missing" features from my CCNet are compelling enough to make me want to switch at the point.  Most of the features are really provided by the NAnt script anyway, not the CI server.  You can watch an online demo on their website.

    TeamCity is a new product, and I intend on following it as it grows more mature.  JetBrains is known for quality software, so there will be some interesting things to come, that's for sure.

  • Having a baby and an integration testing tip - level 400

    I found out today that my wife is with child, and we're having a baby!  Now, on with the post. . .

     

    Integration testing isn't your basic 200-level topic at an MSDN event.  It can be very involved.  I believe that a good integration test has to depend on targeted unit tests being present.  Consider the scenario without unit tests:

    Bob has a use case that spans 15 classes.  He sets up the environment to get this slice of the system under test.  He then proceeds to write the test with asserts.  He quickly becomes frustrated because for each of the 15 classes along the way, there are different scenarios that are possible.  If each class has just 2 possible uses, his number of scenarios to test are 2^15.  Each scenario requires many assert statements.  Faced with 32,768 test combinations, Bob is disgruntled and concludes that automated integration testing is too much overhead.

    What did Bob do wrong?  First, Bob attempted to start his automated testing at the integration level.  Second, he assumed unit test responsibilities inside the integration test.  Third, he tried to test every possible combination of integration.  Fourth, he hadn't surrounded himself with a quality team that could help guide the testing strategy.

    Here's the success scenario:
    Bob has written unit tests for each of his 15 classes.  He marvels at how simple they looks since each unit test only has to cover 2 usage scenarios for each class.  With confidence that each individual class will do its job correctly, Bob writes an integration test for the use case choosing one of the many combinations that could occur.  Bob sets up the test, executes it, and then asserts on the resulting state of the system.  Bob finds an integration issues caused by how two of the classes interact with each other.  He fixes that bug, and the test passes.  Bob now has confidence that the 15 classes are interacting properly in his use case.

     

    If you haven't already read the following from my friend, Jeremy Miller, take a minute to do so:

    Qualities of a Good Unit Test: http://jeremydmiller.blogspot.com/2005/05/qualities-of-good-unit-test.html
    Achieve Better Results by following Jeremy's Third Law of TDD: Test Small Before Testing Big: http://codebetter.com/blogs/jeremy.miller/archive/2006/05/30/145752.aspx
  • The first task of a new software project is to build trust - level 300

    Please read this post by Brad Appleton (and some links off the post) about building trust in a software team.  The notion is very profound, and we don't talk about much in professional circles.  I, for one, can easily be drawn into only thinking about the technical aspects of software development.  It's easy because it's something at which I excel.  Years ago I went so far as to scoff at a previous employers attempted evaluation of "soft skills", but I know see the importance of it.  Technical skills are necessary, but the greatest techy on earth can be rendered ineffective if no one will trust him.

  • Importance of developer data - level 200

    Most of my experience has been with systems that require a relational database to house most of the data.  Some systems have used a combination of relational databases, files, and external sources.  Regardless of the data store, there are different ways to set up the data stores in a developer environment that affect the ease and speed of development.  For clarity, I am talking about the database that is used by every developer on the development workstation (not a development team staging server)  I'll start with the worst way.

    Use last month's production backup (BAD)
    Assume for a moment that there is not a single corrupt field in your production data.  Even so, the data set can be so large that it is tough to see clearly what is going on while developing locally.  While working out problems in the program's behavior, it's necessary to peek into tables to see what data is there, and with a full production set, the developer has to formulate queries merely for narrowing the scope of the data to view.  Using a full production set bogs down development with unnecessary overhead.  Finally, it will be very hard to create repeatable tests since the developer is constantly changing the data.

    Create a development database with fake data and put it on a shared server(BAD)
    The "shared server" part of this one is the killer.  Imagine running a scenario using this database, and the data changes.  With a shared database, this is what happens.  Multiple users changes the data in many different ways.  A high degree of communication overhead and waiting is required to make this work.  The fake data will need to be refreshed periodically, so it becomes necessary to stop the team from using the database during the data reload.

    Use a local database with nothing in it(BAD)
    This is probably an obvious one since the system probably won't function without a proper data set.  If it will, security or configuration problems might lurk in the shadows (if you have security or configuration tables). 

    Use a local database created with the local build and populated with representative data that is enough to support every use case in the application(GOOD)
    In your local build script, have a target that creates the database locally from scratch.  Have a routine that pumps data into this local database.  In this data set, include enough data so that every use case in the application can be exercised.  As functionality grows, add to this data set proportionally.  Structure your automated build in such a way that it is easy to:

    1. Blow away the database and recreate it from scratch.
    2. Blow away the database and refresh it at any time.
    3. Create multiple local databases in the same way with different names.

    Your automated database tests are going to be blowing away and reading data in the normal course of execution, so it's important to be able to refresh the database at any time.  Using this technique, you will be able to run the system locally at any time and use it in a representative manner (and debug if necessary).

    WHAT ABOUT A TESTING DATABASE?
    That's a different animal.  You want the testing database to make bugs obvious.  Another tricky thing is that there isn't just one testing database, so that's a topic for another time.

  • I've been tagged. . . and enumerated classes - level 200

    After being tagged my numerous people, here's my 5.  My long-time readers might know some of these if they've been reading closely over the past few years, but here are 5 things about me that aren't widely known:
    • In college, I was a member of the Texas A&M country & western dance team:  www.aggiewranglers.com - I got to travel the country and world performing c&w dance.  I married a girl who was also on the team. (all partner dancing, people, no line dancing).  Think "girl being thrown in the air".
    • In 2003 I was called up for Army service to Iraq - was there 1 year and 3 days.  I'm 1.5 months from separation, so I'm hoping the nothing BIG happens between now and March 3rd.
    • I was using Yahoo before it had e-mail service, and my account is one of those that is really jacked up because my id I originally registered had to be an e-mail address.
    • I started writing database web applications before the dawn of ASP 1.0 - Anybody remember .idc and .htx files? - My CGI work was configuring WODA for a few clients.
    • When I was a kid, I read every book on motorcycles/dirtbikes/ATVs in the public library, and I'd moved on to the adult section.  I was the only young kid who knew the difference between a two-stroke and four-stroke engine.  I now have a motorcycle, love to ride dirtbikes, and I'm lobbying my wife for a Harley.
    Now, I'm going to tag Scott Bellware 5 times.

    So that this post is now void of technical content, here is a tip for using enumerations in your applications:

    Consider the following class: 

        1     public class WorkOrder

        2     {

        3         private Status _status;

        4         private string _description;

        5 

        6         public Status Status

        7         {

        8             get { return _status; }

        9             set { _status = value; }

       10         }

       11         public string Description

       12         {

       13             get { return _description; }

       14             set { _description = value; }

       15         }

       16     }

    Notice that we are using a Status class (enum):

        public enum Status

        {

            Pending,

            InProcess,

            CompleteNApproved,

        }

    My system manages work orders.  Realize that this is an over-simplified example, but what happens when you need to list our many WorkOrder(s) in a grid or for a printable report?  Easy, right?  No.  You have this Status property that is very ugly when displayed.  "InProcess", "CompleteNApproved".  Your users don't want to see that.  In business speak, it needs to be displayed as "In-Process", and "Complete & Approved".  How do we do this easily in code?  On possible way is to create a Facade class that is used in reports.  This facade class could translate the enum to our required Status titles.  This is undesirable because we then have to wrap each WorkOrder instance in a new class just for display purposes.  I would prefer that our WorkOrder could be displayed on its own, but we have to do something about that enum.  Let's turn our enum into an enumerated class:

    First, I'll rename the enum like so:

        public enum StatusValue

        {

            Pending,

            InProcess,

            CompleteNApproved,

        }

    Then I'll make Status a class with 3 static instances: 

        public class Status

        {

            private static Status _pending = new Status(StatusValue.Pending, "Pending");

            private static Status _inProcess = new Status(StatusValue.InProcess, "In-Process");

            private static Status _complete = new Status(StatusValue.CompleteNApproved, "Complete & Approved");

     

            private StatusValue _statusValue;

            private string _displayTitle;

     

            private Status(StatusValue statusValue, string displayTitle)

            {

                _statusValue = statusValue;

                _displayTitle = displayTitle;

            }

     

            public StatusValue StatusValue

            {

                get { return _statusValue; }

            }

     

            public string DisplayTitle

            {

                get { return _displayTitle; }

            }

     

            public override string ToString()

            {

                return _displayTitle;

            }

     

            public static Status Pending

            {

                get { return _pending; }

            }

     

            public static Status InProcess

            {

                get { return _inProcess; }

            }

     

            public static Status Complete

            {

                get { return _complete; }

            }

        }

    Notice that I've overridden the ToString() method so that my _displayTitle field is returned.  Now, when I throw my WorkOrder class (or List<T> of instances) into a grid or some other binding container, I'll see the proper display title for my Status.  Now my users are happy, and I can move a WorkOrder class around anywhere in my application.  For persisting to the database, I use the StatusValue (which can be Int32, Int16, or byte) in my database table.  It's easy to do that whether I'm using a hand-crafted SQL statement or (my favorite) NHibernate for my ORM solution.

    Our lack of built-in enumerated classes is something I plan to gripe about at the up-coming MVP Summit.  Our enum construct is very weak and is no more than glorified primitives.  Consider what Java has as of version 5 (taken from http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html):

    public enum Planet {
    MERCURY (3.303e+23, 2.4397e6),
    VENUS (4.869e+24, 6.0518e6),
    EARTH (5.976e+24, 6.37814e6),
    MARS (6.421e+23, 3.3972e6),
    JUPITER (1.9e+27, 7.1492e7),
    SATURN (5.688e+26, 6.0268e7),
    URANUS (8.686e+25, 2.5559e7),
    NEPTUNE (1.024e+26, 2.4746e7),
    PLUTO (1.27e+22, 1.137e6);

    private final double mass; // in kilograms
    private final double radius; // in meters
    Planet(double mass, double radius) {
    this.mass = mass;
    this.radius = radius;
    }
    public double mass() { return mass; }
    public double radius() { return radius; }

    // universal gravitational constant (m3 kg-1 s-2)
    public static final double G = 6.67300E-11;

    public double surfaceGravity() {
    return G * mass / (radius * radius);
    }
    public double surfaceWeight(double otherMass) {
    return otherMass * surfaceGravity();
    }
    }

    Now we need to play catch-up again.  If in C# I was able to declare my Status enum like this, I could give it a friendly display title and even some methods right there in the enum definition.  I would have less code to maintain, and I would get the build in enum behavior for free.



  • MVP Summit - Party with Palermo - level 000

    For all you MVPs out there, I'll be at the MVP summit in March, so count on a "Party with Palermo" the night before everything starts up.  I'll post more details (time/place) as it gets closer, but since tomorrow many people will be making travel plans, plan on arriving the day before the summit so you can Party with Palermo.

    Past Party with Palermo(s) posts:

     

More Posts

Our Sponsors

Free Tech Publications

This Blog

Syndication

News

Headspring Systems

View Jeffrey Palermo's profile on LinkedIn

See my new blog at .jeffreypalermo.com