Tuesday, April 28, 2009

Bad estimate trick - playing people off of each other

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/bad_estimate_trick__playing_people_off_of_each_other.htm]

One estimating technique I occasionally saw in consulting, which I thought was pathetic, is as follows:

The consultant faces a domain-specific problem that they're not familiar with (say writing reports, or doing some database optimization, or wiring up a backend service). So, they intend to sub-contract it out. They interview two separate contractors, and ask each for an estimate. The consultant, in their sneaky mind, figures that they'll play the two contractors off of each other to get the "real estimate", and whichever estimate is lower must be the honest and correct one.

The biggest mistake I see here is the bias that whatever is lower is more correct. Developers are notorious for low-balling estimates (especially if the manager demands a low estimate in order for the developer to continue), so this is historically a bad bias. It's just as likely, or more likely, that the higher estimate is actually closer to the truth.

I think a much better approach is to find a way to determine who the more reliable and experienced developer is, and go with their estimate, even if it's the higher one.

Monday, April 27, 2009

BOOK: Patterns of Enterprise Application Architecture

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/book_patterns_of_enterprise_application_architecture.htm]

I remember when Martin Fowler's Patterns of Enterprise Application Architecture came out back in 2002. I constantly heard good things, but never got around to reading it. Finally, I buckled down and went through it, and I'm glad I did.

Perhaps the biggest thing I liked about the book was the common vocabulary. Whenever I look at popular community projects (such as Enterprise Library, CLSA, or .NetTiers), or just read star bloggers, ones keeps hearing about all these pattern names (ActiveRecord, Gateway. Lazy Load, Repository, Registry, Service Layer, etc...). While gradually you pick them up, it's convenient just injecting them into your brain all at once.

I also thought his chapters on concurrency were excellent, especially how he explains the difference between an optimistic lock and pessimistic lock. (My simplified interpretation is that an optimistic lock is "optimistic" in that it assumes conflicts are either rare, or easy to resolve, and hence checks for conflicts at the end of a transaction. On the other hand, a pessimistic lock is "pessimistic" in that it assumes conflicts are either common, or very expensive to resolve, and hence prevents the conflict from ever occurring by locking at the beginning of a transaction).

He's also very "no-holds-barred" for doing things the best way. For example in the Metedata Mapping pattern he emphasizes using code generation or reflection - two concepts that for some reason many developers seem reluctant to use.

Lastly, reading a solid book like this just helps you think more about enterprise patterns as you go through your daily coding, and that's a valuable thing.

 

Sunday, April 26, 2009

Structs vs. Classes - seeing the functional difference

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/structs_vs_classes__seeing_the_functional_difference.htm]

There's a lot written about the difference between classes and structs, and comparing the two.

One thing I find helpful to really "get it" is to whip up a quick unit test, and functionally see the differences. While classes (being reference types) and structs (being value types) will have different memory and performance implications, it seems most devs are initially concerned with how they're functionally different, and they worry about performance "later".

Here's an example showing both a struct and a class object being passed into some method and having their property updated. The struct, being a value type, is copied when sent into the method, and hence the property doesn't "persist" outside of the method (the copy is discarded, the original left untouched). However, the class sends in a reference, and therefore the method is pointing to the same instance as the host caller, and hence the update "persists" for the class..

    [TestMethod]
    public void TestMethod1()
    {
      MyStruct s = new MyStruct();
      s.Name = "Struct1";
    
      MyClass c = new MyClass();
      c.Name = "Class1";

      UpdateStruct(s);
      UpdateClass(c);

      Assert.AreEqual("Struct1", s.Name);
      Assert.AreEqual("newClass", c.Name);
    }

    private void UpdateStruct(MyStruct s)
    {
      s.Name = "newStruct";
    }
    private void UpdateClass(MyClass c)
    {
      c.Name = "newClass";
    }

    public struct MyStruct
    {
      public string Name { get; set; }
    }
    public class MyClass
    {
      public string Name { get; set; }
    }

You could write tests for similar things - like showing how structs don't allow inheritance (which actually wouldn't even compile), but do allow interfaces. You can drill down even further by stepping through in the debugger, or checking Visual Studio's performance wizard.

Tuesday, April 14, 2009

Tips to incrementally check in code without breaking the build

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/tips_to_incrementally_check_in_code_without_breaking_the_bui.htm]

No one wants to break the build. However, every time you check in code, you risk breaking the build. This leads some developers to avoid checking in for days (or weeks!) until they have a dangerously-big component. That has its own problems. Integration is pay-me-now-or-pay-me-later. I'm a big fan of paying upfront with small, continuous check-ins. Here are some tips to do check-ins without breaking the build:

  • Try to do multiple smaller commits as opposed to one giant commit.
  • Where reasonable, try to keep a component split into multiple smaller files instead of one giant file, especially if these files are updated by many developers. This reduces contention, and hence likeliness of breaking the build.
  • Check in a file that won't hurt anything, like a class file that's not added to the project yet.
  • Make sure you understand how code-generation integrates into your build. It's easy to have the code "work on your machine", only to have a code-generated script on the build server overwrite your changes and break the build. Make sure all your local code is in sync with what will be actively code-generated.
  • Make sure you always check in all the needed files, especially files that get "registered" with a master file list. For example, C# files get registered with a csproj project file.
  • Use a source control that allows merging (SVN, not VSS)
  • Split your code into isolated components - i.e. reduce dependencies in your code.
  • If you're working on a unit test, and you "need" (?!) to check in a partially-completed test that currently breaks, then consider applying the "Ignore" attribute so the test doesn't run yet.
  • If you really need to check it in, perhaps comment out the breaking section.
  • If you're checking in to send code to another dev, consider not checking in, and sending them a patch instead
  • If you're checking in to the global trunk just to "back up" your work, consider checking into your own private branch.

Monday, April 13, 2009

The non-financial resources at a manager's disposal

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/the_nonfinancial_resources_at_a_managers_disposal.htm]

A good manager knows what resources they have at their disposal, and how they can exchange those resources for other things. The most basic resources are budget and headcount. But a creative manager can find a lot more:

  • Offering interesting projects and opportunities
  • Letting developers work from home (less driving is good for the environment too!)
  • Offering your time to hear out the devs.
  • Opportunity - If a dev is interested in a certain new technology, consider offering that if they research this task on their own, then potentially the team can leverage it - which means they can learn a ton more about it.
  • Work hours - to avoid rush-hour, or coordinate with work-life balance, let the devs come in an irregular hours (like 6am-3pm).
  • Offer encouragement - some developers are motivated knowing that their boss supports them and publicly appreciates the good job they've done.
  • Permit devs to install safe games on their laptop.
  • Give them a "free" PTO day to go to an in-town conference (Yes, time is money, but for some reason, mgrs and bureaucracies are more apt to give you time than money).

Even a little money can be stretched a long ways:

  • If they're working overtime at the office, consider at least buying them lunch or dinner. I remember on a death-march consulting gig when my manager kept bringing us lunch. He explained that if we're working 4 hours of overtime (say $400 billable dollars), he could at least help by getting us a $10 lunch. I thought he was a really good manager. Sure, he got the better end of the deal, but it was still a nice gesture.
  • Buy a book to encourage them to learn. Yes, it's ultimately the developer's responsibility to learn, but if they're going to spend 20 hours pouring over a book to learn a technology that helps the company, a $30 investment is a no-brainer.

Thursday, April 9, 2009

We need to get this done

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/we_need_to_get_this_done.htm]

Anyone can say “we gotta get this done ”. Sometimes this is just a broken record - everything is top priority and needs to be done now - but sometimes a specific task is truly on the critical path and is blocking other people.

Telling a developer to essentially "hurry up" won't get things done faster, it will just annoy the developer, or perhaps make them hurry and write sloppy code which will cost you more in the long run.

While I'm certainly no management expert, I'd expect at least a few questions you could ask any developer are:

  1. Everything considered (other tasks, meetings, misc distractions, research time, expected delays, possible overtime) - what date and time can the developer have this done by? Note that you want a date, not "how many hours do you think this will take". An 8-hour task may spread across 3 days if there are other distractions. Get an honest, unrushed date based on the developer's estimate. Note that you also want a time. Does "Wednesday" mean 8:00am, or midnight? This also gives the developer a concrete goal to shoot for, as opposed to "get it done real fast".
  2. Is there anything that can help the developer get this done faster (delegate sub-tasks, better hardware/software, tools, a technical roadblock holding you up, pair programming with another dev)? The goal is for the manager to offer practical help by shifting around resources. If this task is really so important, then it is important enough to provide extra resources too.
  3. Acknowledging that surprises do come up, so you understand if the date cannot be met, but the developer should at least alert you as soon as they reasonably think they can no longer meet the date - and provide an updated estimate. The goal is to not get suddenly surprised on the target date with a late feature.

Of course, it also helps to work in smaller increments with verifiable milestones along the way. It can be easier to manager 5 small 1-week "milestones" than a single big 1-month project.

All of these involve give and take. Yes you can have it be a certain date, but the developer determines what that date is. Yes you can have it earlier, but you need to provide the developer more resources. Yes you won't be surprised on the target date with bad news, but that's because the developer is encouraged to tell you the bad news up front.

Wednesday, April 8, 2009

Consider nixing the projector for quick demos

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/consider_nixing_the_projector_for_quick_demos.htm]

Say you want to do continuous development, with quick demos to management (or business sponsors) every week. One thing I've found useful is to nix the projector. I've been in places where in meetings, you can't show something on a computer unless it's on a projector. And of course for large meetings and official presentations I can see the benefit. However, if you want just a small and quick sanity-check meeting, there are several benefits to nix the projector:

  • Faster setup - I've seen endless problems trying to hook developer machines up to a seemingly innocent projector (can't turn on the projector, need to install special sofware, your laptop won't register, the screen doesn't show, different resolution sizes, adjust the font size, bad glare from the windows, etc...). If you only want a 10-minute "spot-check" demo, you don't want to waste even 5 minutes setting up a projector.
  • Smaller crowd - Something about human nature seems to be drawn to a presentation on the big screen (Maybe people think the bigger the screen, the more important, and they don't want to miss out on important things). However, by having just a laptop screen, it forces you to have a smaller crowd - maybe 5 or 6 people at the most.
  • Easier for multiple machines - Switching a projector between multiple laptops can also be risky (see "faster setup"). If for some reason you have multiple laptops (say you haven't integrated all the pieces for the demo onto a single machine yet, or you're showing very different scenarios that don't "fit" on one laptop), not having to worry about switching the projector can just make it more convenient.
  • Easier room requirements - A lot of offices only have a few "special" rooms that contain projectors - and these rooms are usually already booked. Not needing a projector means you aren't limited to these special rooms, and therefore have far more room options available.

I realize it's trivial in the scheme of things, but not needing to worry about the projector can eliminate some of the red tape and setup that distracts you from the things that aren't trivial.