Scott Hanselman

Some Guiding Principles for Software Development

June 13, '07 Comments [22] Posted in Learning .NET | Musings | Programming
Sponsored By

Patrick Cauldwell is one of the architects on our Next Generation Banking System. A while back I asked him to write up our guiding principles for not only educating new developers but also for indoctrinating existing team members into our world view. He published it on his blog as This I Believe...The Developer Edition.

It's a great list. Here's a partial listing of the first two levels of his outline. Be sure to visit his post for the complete outline. It's bent towards .NET, because the stuff he's doing is .NET, but the general ideas are usable elsewhere.

  • Our "guiding principles"
    • Test Driven Development
    • Continuous Integration
  • Unit Tests
    • Two kinds of tests
    • Automation is equally possible for both sets of tests
    • All UI development should follow the MVP pattern for ease of testing
  • Test Coverage
    • 90%+ is the goal
    • NCover runs as part of the build, and reports are generated
  • Buy, Not Build
    • Take full advantage of the platform, even if it only solves the 80% case
    • Don't write a single line of code you don't have to
    • Take full advantage of .NET 3.0, SQL 2005, Windows 2003 Server, plan for- and test on Longhorn.
    • Don't invent new solutions to solved problems.
  • Limit compile time dependencies on code you don't own
    • Everything not owned by us should be behind an interface and a factory method
  • Define your data contracts in C# (think "active record")
    • All persistent storage should be abstracted using logical interfaces
  • Fewer assemblies is better
    • There should be a VERY good reason for creating a new assembly
    • The assembly is the smallest deployable unit, so it's only worth creating a new assembly if it means NOT shipping something else
    • Namespace != assembly name.  Roll up many namespaces into one physical assembly if they all must be deployed together.
  • Only the public interface should be public
    • Only make classes and interfaces public if absolutely necessary
    • Test code should take advantage of InternalsVisibleTo attributes
    • VS 2005 defaults to creating internal, not public classes for a reason
    • If it's public, you have to support it for ever
  • Windows authentication (good)
    • Just say no to connection strings
    • Windows authentication should be used to talk to SQL, ADAM, the file system, etc.
    • You can take advantage of impersonation without impersonating end users
  • Tracing
    • Think long and hard about trace levels
    • Use formatted resource strings everywhere for localization
    • For critical, error, or warning, your audience is not a developer
  • Error Handling
    • Method names are verbs
    • If anything breaks the contract, throw an exception
  • The definition of "done" (or, how do I know when a task is ready for QA?)
    • Any significant design decisions have been discussed and approved by the team
    • For each MyClass, there is a corresponding MyClassFixture in the corresponding test assembly
    • MyClassFixture exercises all of the functionality of MyClass (and nothing else)
    • Code coverage of MyClass is >=90%, excluding only lines you are confident are unreasonable to test
    • No compiler warnings are generated by the new code
    • Before committing anything to source control, update to get all recent changes, and make sure all unit and integration tests pass
    • FxCop should generate no new warnings for your new code
    • Compiling with warnings as errors will flush out any place you forgot documentation comments, which must be included for any new code

What guiding principles do you follow at your development shop?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Thursday, June 14, 2007 7:05:11 AM UTC
Hi Scott

They all generally sound pretty good, personally I've never found a good reason to use fx cop(but thats probably just me).

Could you confirm that the below doesn't refer to those horribly wizards or draggy drop tools in visual studio?

"Don't write a single line of code you don't have to"

Andy
Andy Stewart
Thursday, June 14, 2007 7:24:55 AM UTC
Hi Scott,

I really like the Done criteria.

Thanks for forwarding.

Gil

Thursday, June 14, 2007 7:47:27 AM UTC
"Windows authentication should be used to talk to SQL, ADAM, the file system, etc"

this is arguable I mean. There are good reason not to use Window authentication for sql database
Fred
Thursday, June 14, 2007 8:01:29 AM UTC
The "the complete outline" link is broken...
Robbie
Thursday, June 14, 2007 1:29:56 PM UTC
Hi Scott,

That is a great list! Each bullet is a principle worth serious consideration for any kind of programmer.

One thought about Fred's comment:
There are good reason not to use Window authentication...


In some circumstances, I think Fred is right. In an ASP.NET scenario, ASP.NET has no way of forwarding user credentials because of limitations to NTLM (Windows) Authentication. This can be problematic if your services span several machines, such as having a Microsoft Exchange Server on a separate machine than the website. Some services might simply be unavailable using only Windows Authentication.

I think, though, that in nearly every circumstance, Windows authentication is the way to go. This is especially true if the application must live on someone's desktop instead of the server. Even if encrypted, giving clients physical access to a file containing a connection string is asking for trouble.

Never stop writing, Scott. You're well appreciated!
Thursday, June 14, 2007 1:31:20 PM UTC
"All UI development should follow the MVP pattern for ease of testing"

Many programmers talk up the MVP model, but every time I start trying to read up on it, I always think, "Am I the only one who doesn't get this?" I think "ease of testing" should be balanced against "ease of development" and "ease of future support by other developers."

Scott -- how about a podcast on MVP? I'd love to use it, but it just hasn't clicked yet -- and I think I'm not alone in this.
T A L
Thursday, June 14, 2007 2:52:49 PM UTC
I realize that on ASP.net applications that more assemblies cause a longer time, however if you were developing a desktop application would this really matter?

Besides wouldnt it be better to have your code seperated out more in different assemblies especially if multiple teams on it. At least during the development phase. Could you talk about that sometime in a podcast to?

Also

Lets assume that it would be cheaper to not buy code? For example a 2000 dollar printing suite for reports when you know one of your capable jr programmers could program the basic functionality I know. Don't you find a blanket statement like this to be not cost effective.

With the lack of good documentation from even major vendors, could this practice leave a development team very much delayed.

This new approach of all programming(coding) is bad. Does this lead to a lack of refactoring of existing code?

Im also curious to how much of the day writing unit tests take up for a developer on your team?
Noah Moerbeek
Thursday, June 14, 2007 4:05:47 PM UTC
I'd have to agree with TAL on not quite getting the MVP pattern. The high level view of it I understand, but it's the useful/semi-realistic examples that really come in handy for being able to reach that point where it finally clicks.
Steve
Thursday, June 14, 2007 4:55:35 PM UTC
I agree that the MVP pattern isn't obvious. It does take some time and some playing with it to really grok. Even then, I go back and forth about the best way to separate View and Presenter. For example, should your view implement events that represent user actions, which the presenter subscribes to, or should the view directly call methods on the presenter informing it of user actions. Personally I like the former, but one of our other team members favors the latter. Either way, it leads to extra code, but it's worth the time to put in place since you'll get so much better test coverage without having to worry about how to push buttons on forms.
If I have time I'll try and post an example that doesn't suck. :)
Thursday, June 14, 2007 4:59:52 PM UTC
On the "never write code you don't have to" principle, no, I don't mean wizards. I mean taking advantage of the platform or other stable 3rd party software rather than writing it yourself. I had several people at last week's ADAM/AzMan BOF at TechEd say stuff like "why should I use AzMan? I can just write my own role based security subsystem and back it with SQL." True, buy why would you? Even if AzMan (as an example) doesn't solve 100% of your problem, it probably solves enough of it to justify not writing (and more importantly maintaining) it yourself.
Thursday, June 14, 2007 9:37:29 PM UTC
There are good reasons not to use 3rd party controls. Where I work, we write very complex and full-featured insurance software (ASP.NET / C# / Heavy Windows//WebServices). We have used some 3rd parties and what we've learned, in a business where you need to be lighting fast in delivering enhancements or features, and quality matters, you can only move as fast as your slowest dependancy. Many 3rd party components we've used in the past have caused lots of grief. Either they don't fix critical defects quick enough, they eventually don't supports the features you need as your business evolves or the clients expectation changes, or they don't update their technology from COM --> .NET or from 32-bit to 64-bit or they are simply just too complex to get right and in many cases we've learned, some will not scale easily to millions of transactions per day so we have to throttle their throughput so we can remain reliable and stable as a service provider (or throw more CPU boxes at it which costs even more money simply because of a 3rd party limitation/problem). Our home-grown counterparts have none of these problems.

In other cases, to generate PDF's a component may work great for many years, for example, but then you need one property to set to generate the PDF with signed and protected, then all of the sudden, you need to shell out $1,800 each for 20 servers and again for 10 more developers, but when you finally do so and apply the updated version to all of your servers, existing functionality breaks and you must spend days correcting the differences in versions.

For us, it has served our company well in minimize 3rd party dependancies and we must provide a strong justification for actually using them. Our developers are talented enough that it isn't a drain on finance to create it ourselves, which is what we've done, and almost every problem we had with previous 3rd party vendors has dissappeared, in exchange for having a slightly longer target release date, but the quality of our deliverables is also acceptable.

Personally, my belief is that whether you stake the existance of your business on whether or not 3rd parties can keep pace with your requirements proportionately depends on how critical your product is to your company's survival. The part of about placing 3rd party dependencies behind a factory or proxy interface is sound. One which we haven't even considered but I will put some thought into that as it might help to keep a familiar interface but allow a switch to new toolkits in the future if necessary.


Thanks,
Shawn
Shawn B.
Friday, June 15, 2007 12:04:11 AM UTC
You forgot the most important one. Keep it simple.
Joe Chung
Friday, June 15, 2007 1:20:32 AM UTC
If you'd only included patrick's 'grassy knoll' item you could've claimed "13 Guiding Principles..." (which is a prime number, see) and thus guaranteed (2^101 - 1) links from reddit/digg et al.

re unit testing and 90% coverage: do you kids recommend unit tests for private methods? I've seen some great discussions of this recently -- and wondered what the hanselstance was on this one?

lb
Friday, June 15, 2007 1:35:01 AM UTC
Keith said:
>> ASP.NET has no way of forwarding user credentials because of limitations to NTLM (Windows) Authentication.

This is partly correct. ASP.NET has no way of forwarding credentials if you are using NTLM, but ASP.NET can pass credentials when you use Kerberos and delegation, allowing you to still use integrated authentication in multi-hop scenarios.
Friday, June 15, 2007 11:27:32 AM UTC
Re: Leon

Could you link to those discussions, here or on your blog? I'd be very interested.

To give my own unsolicited answer: I'm in the "test public interface period" camp. The rationale is that the existence of private methods is an implementation detail you don't want to couple your tests to, because it leads to severe test osteoporosis. Broken encapsulation will lead to a broken hip every time.
Friday, June 15, 2007 12:19:17 PM UTC
This podcast/demo by Craig Shoemaker on MVP was recommended to me in a Joel On Software thread, and it helped me:

http://polymorphicpodcast.com/shows/mv-patterns/

It is really good because it is a simple, short demo that for the most part focuses solely on the MVP issue, and doesn't complicate things with data access or other pieces you would find in a real project. Just following the walkthrough and typing in the code myself helped me figure it out pretty easily. In a larger "real world type" project you can lose the pattern in everything else that is going on. For someone like me lacking experience with MVP, better to start with the simplest possible example like this one.

I have to say I'm not yet convinced that MVP is the way to do +all+ UI's, but I do see its value.
Paul Reynolds
Friday, June 15, 2007 10:52:07 PM UTC
Simplicity.
Monday, June 18, 2007 3:06:19 PM UTC
I second Paul Reynolds' comment on the Polymorphic Podcasts show about the MVP pattern. The longest one is 15 minutes, so they're easy to watch but they really help you see the overall picture.

I still don't fully grok the pattern because I haven't yet had enough hands on experience with it, but I understand the concepts and see the benefits the pattern provides.
Tuesday, June 19, 2007 9:03:23 PM UTC
I'd actually contest the point about fewer assemblies - check out Are fewer assemblies really better?. For example:


In the end, you should see bunches of projects/dlls which go together, while between the bunches there is almost no dependence whatsoever. The boundaries between bunches will almost always be an interface project/dll.

This will have the pleasant side-effect of enabling concurrent development of bunches with developers hardly ever stepping on each other’s toes. Actually, the number of projects in a given developer’s solution will probably decrease, since they no longer have to deal with all parts of the system.
Tuesday, June 19, 2007 10:02:06 PM UTC
I'd have to disagree. I think that if you are creating more assemblies so that developers don't "step on each other's toes" then you have a management or communication problem. If two developers are working in the same part of the same file at the same time, they really should be in better communication. We found during our transition from pessimistic to optimistic source control (VSS -> SVN) that the fears everyone had about developers working on the same code and causing merge problems turned out to be largely unfounded if people just talked regularly. More assemblies just means more files to manage.
Wednesday, June 20, 2007 3:35:53 PM UTC
Patrick,

You're absolutely right.

Unless the developers sit on different floors of the same building, or different building, cities, time zones, etc.

I've scaled up and down the "many assemblies" approach and have found it doesn't create much overhead even at the single team level compared to code-and-merge techniques.
Saturday, June 23, 2007 6:11:53 AM UTC
I use this definition of done:

- The code should compile
- Have a simple design with fewest classes
- Be well factored - have no duplication
- Structured in accordance with coding standards
- Well documented
- Communicate the developer’s intentions
- Checked into the version control repository
- Integrated and build successfully.
- Unit tests must pass
- Code coverage >85%

Some of points are fuzzy and can’t be measured, but the force the developers thing about it.
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.