6 months. . . to become a better developer

Ok.  I’ll jump on this bandwagon since it is forcing me to reflect on how I can make myself a better developer.  Justice Gray started this whole thing, and I was ‘tagged’ by Bil Simser.  It’s a pretty hard question since this is the first time I’m trying to reflect on how to be a better developer.  I don’t consider myself a great developer right now, but I hope to be one some day.  What the definition of that is, I’m not sure.  Will I know it when I see it?  I have, however, progressed enough that I’m pleased with my progress so far, and I believe I’m at least keeping pace with my peers.  I can attribute my current position to voracious reading and listening.  I began this when I was deployed to Iraq with the Army in 2003.  I spent every free minute reading.  I read programming books and other material related to software, and I read all the scriptures in the Old Testament as well. 

When I returned from Iraq, I was a different developer.  I approached problems from a different angle.  By reading, I realized how much I did not know, and the more I learn, the more I learn how much I don’t know.  Since then, I’ve learned to listen to others (quite selfishly) in order to learn from them.

So here are the things I’ll do in the next 6 months to become a better developer:

  • Finish my stack-o-books.  I have a stack of software books in my office that is my “to read” stack.  My “read” stack is every bigger, but I’m not nearly finished, so I need to finish those.  They mostly consist of older software books.  I feel that if I’m to have a balance view of software, I have to have a good foundation of past research.  I approach it as engineering.  I need to understand past successes and failures so that I can apply it to today.  Perhaps some could be considered software history books, but I don’t know all the history at this point, and I certainly don’t want to be doomed to repeat it.
  • Teach more than do.  Up to this point, I’ve written a lot of code.  I’ve been a code monkey, developer, senior developer, manager, executive, and now consultant, and I’ve realized that my programming skills don’t scale.  I can only create software so fast, and then there is a limit.  In management, I started this line of thinking, but moving to consulting has brought it more to the fore-front.  As the saying goes, teach the men to fish, don’t fish for them.  I will teach more and “do” less.  By that I hope to learn more by teaching and deliver more value to my clients by enabling their staff.
  • Educate myself on other ways of developing.  At this point, I have a “default architecture” in my head that has been fine-tuned from every project I’ve worked.  It’s based in part on Domain-driven design and encompasses a lot of other OOP principles.  I prefer to use NHibernate for relation database interaction and MVC for UI whether it be web or windows programming.  But even so, I realize that I will never reach a “default architecture” and that this only represents my knowledge as of today.  There is so much working software that I haven’t studied.  I intend to acquire source code to other successful applications and study it for patterns and other knowledge that has escaped me up to this point.  Of course, some open-source applications come to mind since the source is freely available. 
  • Focus on trust.  Product owners often don’t trust the developers and developers don’t trust the product owners.  In many places, the testers don’t trust either and there is a triangle of distrust.  Each group believes they are doing a good job and the other isn’t.  This just isn’t true.  Everyone wants to do a good job, but the lack of trust sabotages productivity of the whole.  Working to form trust can save so much time and keep a project from running over budget.  If ideas can flow without everyone involved finding it necessary to “cover their butts”, we remove a whole category of “work”.  I have began this, but I have a long way to go with it.  At my clients, I will focus on the trust factor first and software second.  I believe the software will come easier when the people involved trust each other.

I’ll keep this going.  For the following 4 people, what are you going to do in the next 6 months to become a better developer?

Levels of automated testing within a single application

We need a common language for the different types of automated testing.  We’re partially there, but the term “unit test” is still very confusing.  Here, I’ll lay out the different types of automated tests I find helpful with a single application:

  • Unit testing – testing a single class or possible a small group of collaborating classes (absolutely does not call out of process and is the fastest-running of all automated tests).  Running 1000 unit tests in 3 or 4 seconds is common.
  • Full system tests – through the UI integrated with the full application including the database.  May or may not use real system dependencies such as external web services.  (These are the slowest of all tests)
  • Integration testing.  Here, there are some categories.
    • Data access tests.  Used to test repositories, data access classes, etc.  These tests validate the translation from entities to data.  These tests run all SQL and test the structure of the database schema as well.  A real database must be involved.
    • General scenario testing.  Any time it’s appropriate to pull a section of the application in and run a lot of classes together, this is an integration test.  It involves several parts of the system, not just one.  It can run fast if completely in process, or it can be slow if it requires an out-of-process call such as leveraging the file system.

This is not an exhaustive list, but it includes most of the automated testing on a typical enterprise application.  Feel free to comment with any type I may have left out.

Scott Bellware reasoned that the database needs to be left out for unit testing.  I completely agree.  Unit testing, by common definition, excludes external dependencies.  It’s not a unit test if we reach out and touch things.  When you have the right number of unit tests (for example, I’ve worked on a smart client system with 80,000 lines of code and 1300 unit tests and another 700 integration tests), you can’t afford to take more than a few milliseconds to run each one.  You need your unit tests to run very quickly.  Otherwise, you won’t run them very often.

Conversely, this doesn’t mean that the database should be ignored when testing a system.  There are plenty of reasons why a database, SQL, or stored procedures, triggers (shudder), views, etc can cause a bug in the system.  I insist writing an automated integration test for every database operation.  How else can we verify that the database operation works correctly?  We can’t.  It is important, however, for communication’s sake, to understand that these database-inclusive tests are integration tests, as are any tests that exercise an external dependency.

Automated testing with the database REQUIRES the following:

  1. Every developer has a dedicated instance of the database that can be dropped and created at will.
  2. Tests must be responsible for their own data setup.  An empty database should be all that is required to run the test.  The test must be responsible for adding data for the appropriate scenario before testing the scenario.
  3. You will want to generalize test data setup because it isn’t feasible to expect EVERY test to set up all the data.  A general data set that sets a base line of data is very useful and can be invoked with a data helper class.  Then each test can just add specific data necessary for it’s test case.
  4. Data setup, database creation, etc should be automated.  If it’s manual, it cost more, and you won’t run the tests as often.
  5. Database schema must be in source control with the code.  Without that, you never know what the correct version of the schema is.

Another of Scott’s points: “As a side effect of doing the necessary dependency injection, you often get a cleaner and more explicit separation of concerns – which makes software easier to change and maintain.”

He’s right.  If you can’t unit test your domain classes because everything you do with them requires a real database to be online, you have an indication that you aren’t separating concerns.  Data access should be independent of domain object behavior in most cases.  I should be able to verify that a Customer object can Sort() itself without invoking a database query, but if constructing a Customer initiates a database call, my domain model is then materially coupled to the database and needs to be separated.

Jeremy Miller is of the same mind in his comment: “Referential integrity, non null checks, and sundry other data constraints.  All good things.  All a pain in the ass when you’re unit test only needs a single property set on the InvoiceItem class.”

To help clear up some confusion with the term “unit test”, I propose a simple constraint in our dialog:  If the test calls out-of-process, it is then disqualified from “unit test” status and falls into “integration test”.  Feel free to argue in the comments. 🙂

Speaking at AlamoCoders user group in July

If you are in the area, come on over to the AlamoCoders group in San Antonio, TX.  AlamoCoders is a relatively new .Net User Group in San Antonio.  Several founding members attended the Austin Code Camp in May.

I’ll be speaking on July 9th on the following (same session that got great reviews at the Austin Code Camp):

Fundamentals of modern programming – Join Jeffrey Palermo for a talk that gets back to the basics of programming with .Net in the 21st century. This talk will not venture into Test-Driven Development, Domain-Driven Design, O/R Mapping or other recent advances in programming. Instead, I’ll focus on fundamentals that few colleges or training courses are equipped to cover. Some fundamentals include the actual differences between procedural programs, object-oriented programs. Code presented herein will be basic and geared toward illustrating specific fundamentals. An example presented will be what a class should look like and how to decide when to create a class. If you feel a bit rusty on your fundamentals or if you’d just like a refresher course, this talk is for you.

Modify and restore Firefox extensions that fail to load

Recently, my Firefox browser started loading without the extensions I’ve installed.  I run my Firefox browser off of my 4GB Cruzer using the PortableApps suite.

When Firefox loaded, it would load without a single extension, but when I opened the “add-ins” box, it listed all of my extensions.

Here is the thread where I found my particular solution.  I was able to get Firefox to load my extensions again by modifying the files within my Firefox profile (find it in you user account appdata folder).  I deleted extensions.cache, extensions.ini and extensions.rdf.  When I started Firefox the next time, it regenerated these files using the extensions that were in my profile (folders like {2fa4ed95-0317-4c6a-a74c-5f3e3912c1f9}).

Problem solved for me.  I did take notice that Firefox is blazing fast on start-up. . . until I load a ton of extensions.  With the number of extensions I have, it’s more like Visual Studio since I’m loading up a whole suite of web development tools.  Firefox is just as much a web IDE as Visual Studio – including the RAM usage.

Xml is the code of the future – so long C# – say it isn’t so.

Ok, so the title is a bit sarcastic.  I remember the debut of Xml.  We used it for data.  It was a way to improve on comma-delimited strings.  We converted from flat files to xml files for data.

It wasn’t long before scripting could be expressed in Xml, and now I see teams with large libraries of executable Xml in the form of build scripts with NAnt.

I think it’s going to far, however.  I’m beginning to hear that all software can now be expressed in Xml if you have the right tools.  The implications of that is just shifting from C# programming to Xml programming.  Whatever the language of execution is – that’s the programming language.

I share Ayende’s concern for Xml programming.  Xml is not a 5th generation language.  Just because designers can generate Xml instead of C# doesn’t mean code is going away.  It just means that the chosen syntax is different for the generated code.

My stance on code generation has always been:

  • Machine generates code, human maintains (bad)
  • Machine generates code, machine runs code, human never has to see code (good). i.e. C# to MSIL
  • Machine generates code exactly how human would have written it anyway (good – just saves typing).
  • Machine generates code, human has to modify code and then maintain (worst)

Designers fall into the category that WANTS to be the 2nd bullet point, but that never happens.  WinForms tried to do this with the .designer file, but that code still needed to be understood and tweaked from time to time.  Designers don’t have good track records because they always constrain flexibility.  When you hit a wall, you always have to fall back and change the generated code.  That’s the problem.  Good intentions, but it won’t happen that way.  For it to work, the designer has to be the language. 

Designers come and designers go.  Languages stay and evolve.

Resharper (R#) 3.0 has been released!

Version 3.0 of my favorite IDE add-in has been released.  If you purchased v2.5 recently, you get a free upgrade**

If you are unfamiliar with the tool, check out my previous posts on it:

** All those who have bought ReSharper 2.5 since April 15, 2007 qualify for a free upgrade!