Thursday, May 7, 2009

Technical Debt is like a steep hill, not a brick wall

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

Overtime, bad software decisions (design, coding, process) get compounded, like interest on a loan, and effectively presents the team with a "technical debt" that yearns to be repaid. This debt weighs down the system, making it harder and harder to make changes or add new features. One way to measure technical debt is by lines of code that require maintenance. Therefore you can reduce debt by reducing lines of code (codeGen, refactor, automate, buy instead of build, etc...).

For example, a developer may copy and paste duplicate code a hundred times (like in HTML or SQL), or create thousands of lines of tedious plumbing code, or create an army of brittle JavaScript files, or write an entire app with no code coverage. Many of the best practices out there are designed to explicitly reduce technical debt.

One thing to note is that technical debt is like a steep hill that can go infinitely high. You can go fast bicycling on a flat road, but as that road turns into a steep hill that gets gradually steeper, you slow down. In software terms, because code may have been copied to 10 different places, making a single change requires 10 separate updates - so it takes longer.

I don't think technical debt is like a brick wall - where suddenly at a specific point you're blocked and you simply cannot go further. And that's part of the problem. As long as you're moving, albeit slower and slower, it's seductive to think that you can still keep making "enough" progress so you don't need to change yet. The stubborn leader can just keep pushing on: "longer hours, more developers..." There are two choices to make: keep going forward, or turn around. However, if you were to hit that brick wall, then it forces you to stop and reevaluate. It's easier in the sense that you now only have one choice - you must "turn around".

Monday, May 4, 2009

Cool Tool - NDepend for automated code metrics

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

Given human nature, and all the tedious things that go into coding, the coding standards that survive are usually the ones that you can automate with some external tool.

Code Metrics is one such type of governance. Two of the most popular metrics are line count and cyclomatic complexity. Perhaps the best tool on the market to assist with these (and much more) is NDepend.

For example, say you want to prevent developers from writing huge methods, or huge files. You could use the command line for NDepend to check for method-line-count, and then fail any check-in that doesn't meet this policy - just like you could fail a check-in that doesn't compile or breaks a unit test.

Cyclomatic code complexity is another one - this (to simplify it) measures the number of dependencies. The more dependencies, the harder to instantiate something in a test harness, so this is actually a big deal. You could reduce dependencies by leveraging interfaces and abstract classes, using injections, or the like (whole books are written about this).

This is just the tip of the iceberg. NDepend has dozens of these types of metrics.

Initially I tried to use Visual Studio's "code metrics" feature, but for some reason I cannot fathom, you cannot run it from the command line - which of course makes it useless for an automated build (which is the whole point). At least VS code coverage had undocumented techniques to work around this.

I realize there are open-source options for basic file line count, but I personally haven't come across any that can effectively do the other metrics like method line count and cyclomatic complexity.

Bottom line - if you're trying to enforce automated governance through your build, consider checking out NDepend. Yes, there's a license fee, but if it saves you even 10 hours by preventing issues and bad design, then it's paid for itself. Also, being aware of these types of metrics is the kind of thing that helps take a developer to the next level.

[Disclaimer - I haven't fully implemented this myself yet, it's still in a research phase, and I'm just sharing my findings]

Sunday, May 3, 2009

Chicago Code Camp sessions and agenda are up

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

The Chicago Code Camp (at CLC in Grays Lake, IL), which will be May 30 (Saturday), has the speakers, sessions, and agenda up.

It's all all-star cast, including several MVPs.

There's a huge variety, including TDD everything (even TDD for JavaScript and the iPhone!), UI, backend, many non-.Net platforms, and much more!

Wednesday, April 29, 2009

Management decisions for good developer cost-benefit ratios

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

I've often seen development groups (or their managers) dismiss a good idea with "we can't afford it." The irony is that the group is already "affording" other expenses - developer salaries, MSDN licenses, hardware, and office space - so the question really becomes not "are there funds", but rather "what is the best way to spend our funds". There are at least three common examples where, for some reason, many managers shun the best cost-benefit ratio.

Problem 1: "We cannot afford a star developer - let's get two average developers instead."

The irony is that one star developer is far more profitable than two average developers. The star will build complex things that a dozen average developers will never be able to dream of. The star will write more solid code that spares you costly production errors. The star will solve the same problems faster by leveraging advanced techniques (like code generation, refactoring, or just elegant solutions). So, if you're creating a team of more than 10 developers, exchanging the bottom two spots for 1 star is a good investment. ThoughtWorks, a world-class consulting firm, does a good job of demonstrating the profitability of this business model.

Problem 2: "We cannot afford that tool - just do it another way instead."

Say you spend somewhere between $70K-$120K on an average developer (not just salary, but benefits, payroll taxes, etc...).  Let's use $100K for easy numbers. At 50 work-weeks (assume 2 weeks of vacation), that's $2000 a week to pay for a developer - i.e. $50 an hour. So, a $50 tool that saves your developer one hour a year is a break-even investment.

Now about the "power tools" out there - like CodeSmith (for code generation), or ReSharper (for refactoring), or Simian (for detecting code duplication), or NDepend (for code metrics) - say it's a few hundred per tool (i.e. less than 0.5% of your developer labor cost). However, a tool like CodeSmith fundamentally changes the rules of the game, and can save a development team hundreds of hours. Sure, you can try to find open-source alternatives to each of these, and if you find something that fills the niche you need - great. A similar problem applies to hardware (where's there's not an open-source alternative)- for example when management "saves" $200 by not providing sufficient memory on a laptop, such that every hour of coding is sluggish due to a slow machine.

For many groups, a manager refusing to fund this kind of software engineering "equipment" (sounds classier than just "tools"), is like telling a construction worker to dig a trench - but we can't afford a $20 shovel, so use this spoon instead. Again, if a company is creating a 5 person development team, better to have only four people, but funded with the right equipment, then five developers who need to dig with spoons.

Problem 3: "We cannot afford that book - just see if you can figure it out from free, online tutorials."

Of course everyone knows that continuing education is vital in software engineering. In the manager's perfect world, they have a team of self-motivated developers who study on their own time, paying for their own materials, and learning at their own expense. And then, the manager (who has contributed nothing) gets to benefit from having all these learned developers. While yes, a developer is ultimately responsible for their own learning and career, a wise manager would realize that the company has a huge vested interest in the developer's learning, and would hence do things to encourage that learning.

Perhaps the most basic thing a manager could do is to have the company pay for a book that the developer is motivated to read. A book costs between $30 and $50 dollars. If a developer spends 20 of their own hours (on nights and weekends) over a month reading and absorbing that book, such that they can now profit the company with a new skill, this is a no-brainer. It could cost management thousands to send a developer to training (plus the days off work). It could cost management additional thousands to fix mistakes resulting from the developer not knowing that profitable technology. A book is cheaper, can be re-read by other developers, and is often read off the clock. Money speaks, so if management can't even encourage a motivated developer's learning with a $30 every other month, they're effectively telling developers that management doesn't value learning.

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.