Want to work on a green field ASP.NET MVC project?

Posted by Joe Wilson on Thursday, June 2, 2011 6:18 PM

I'm assembling a team to work with me on a green field ASP.NET MVC project.  We will be using ASP.NET MVC 3, an ORM (NHibernate or EF Code First), SQL Server 2008, dependency injection (Ninject or Castle Windsor), and ATDD and TDD (Specflow, Watin, NUnit, and Moq).  If you've done some but not all of these things, I'll teach you the rest to fill in the gaps.

This project will be run using lean methods, so we'll pull in work only when the current task is completely done, meaning the product owner has accepted it and it's ready to go live.  We'll spend a lot of time getting the acceptance criteria just right before we build anything, so there will be lots of small, just-in-time conversations with the product owner.

We'll have flexible hours and do a lot of remote work, but we'll get together for designing and pair programming several days a week, also.  This will be done face-to-face, ideally, but remote web-cam/desktop-sharing pairing is an option, too.  We'll have to tweak this as we go to be sure communication isn't slipping and the work is getting done to the customer's expectations.

For more details or to apply, please check out the careers section.

Tags: ASP.Net, MVC, NHibernate, Castle Windsor, ATDD, TDD, SpecFlow, Watin, NUnit, Moq, ELMAH, Git, AppHarbor
Categories: Business

Push your logic to the core

Posted by Joe Wilson on Tuesday, December 28, 2010 10:31 PM

Creeping logic

Developers struggle with where to put their business logic.  We all know at an intellectual level that we should be keeping business rules and logic in some kind of a business layer, but I don't see it in practice that often.  I do see a lot of business layers that turn around and call data layers.  There's often nothing business-y about them.

Instead, the logic is sprinkled throughout the other layers, sometimes to take advantage of a technology, sometimes because of the strengths of the developer who wrote the code.

Validation controls in ASP.NET Web Forms are an example of business logic in the UI layer.  Another is an ASP.NET Web Forms code behind event that calculate discounts for preferred customers on Page_Load. 

ASP.NET MVC isn't immune from this either, although the validation logic story is better with Data Annotations letting validation rules flow up to the UI.  Controller actions can be mistreated just like code-behind and often contain more business logic than they should. 

And putting more logic in stored procs doesn't make your app dev teams more agile.  It makes the data team the bottleneck for logic changes.

Journey to the Center of the App

A better approach is to lift that logic out of those layers and put it in your business/domain/core layer in C# POCOs.  In many apps, this logic is what makes the app worthwhile.  Sometimes, it's what gives the company a competitive advantage.  It should be clear, expressive, and long lived code.  It should not be coupled to any particular technology.

These can be tricky changes to make once an app is partly finished or already up and working in production.  There can be a lot of refactoring.  But the effort can pay off in making the code more clear to anyone working on it and letting you make complex changes much faster because the logic is centralized and expressive.

How do you do this?

One test I like to use for where the logic goes is, "What if the technology changed?"  What if I wasn't able to use Web Forms or MVC, but had to use Silverlight or any other future technology?  What if SQL Server went away?  What if we switched from stored procs to NHibernate and then again to Entity Framework?  If we've got business logic wrapped up in our tools, no matter what the tools are, we can be sure the logic will need to be rewritten when the technology changes. 

It's great to take advantage of new tools, but your code needs to keep it's distance where possible.  Wrap the tool with an interface or something so the tool is decoupled from your logic, and you can replace the technology if you need to. I've written about this interface wrapping technique before.

Another great technique is using TDD or other test-first approaches because your code will be written with an eye toward how it will be consumed.  You'll end up with lots of small classes and methods with expressive names.  This outside-in approach to coding really guides you toward creating a clean API for the app's first customer - your test code.

Tags: Patterns, POCOs, TDD
Categories: Technical

Stop making hay

Posted by Joe Wilson on Thursday, December 23, 2010 10:31 PM

Straw men

When test-driven development (TDD) or other test-first methods are first introduced, many people object with different variations of the same argument "if you can't test everything, it's flawed".  People seem to get mentally stuck when they can't automate all test cases.  Sometimes, the point gets really stretched, like, "What if the user enters a negative salary lower than int.MinValue?  We don't' have a test for that, do we?" or "What if the database or web server goes down?  How do we do TDD for that?"

Darren Cauthon made this observation on Twitter a few months ago:

DarrenCauthonQuote

All these arguments are straw men, where an exaggeration or misrepresentation of the point is used to discount the entire thing.

Getting started

TDD won't make all your problems go away or  all your dreams come true.  It's something that takes a lot of practice to get better at it.  I consider myself pretty mediocre at it.  You will be slower at coding when you start out, but you will get faster, and I believe it is worth the investment in terms of the cleaner design it yields.  The tests are nice, too. :>

The trick for me to getting started with TDD was to start small.  This has also been the only way I've been able to do TDD successfully - in very small steps.  Create one test for the happy path for the feature you are trying to implement. This usually has to be broken down into sub steps.  Write the least amount of code you can write to get the test to pass.  Once the test is passing, refactor the code to clean it up and add some polish.  Then run your test again to make sure it still passes. 

Unhappy paths

Occasionally test the unhappy paths, based on how likely they are and how important they are to the business.  If your product owner isn't worried about int.MinValue, you shouldn't be.  Move on to the next feature you're building.

You probably won't automate all your test cases, but that's OK.  Your code will be decoupled, easier to refactor, and easier to read.  Plus you will have automated tests for whatever percentage of tests cases you came up with.

There are far too many benefits to dismiss test-first approaches based on what it can't do well.  So let's stop with the straw man arguments against test-first and start reaping the benefits.

Tags: TDD
Categories: Technical

Generated unit tests are a net negative

Posted by Joe Wilson on Tuesday, October 12, 2010 6:30 AM

One of the most common misunderstandings for developers new to unit testing is the value of code coverage.  We intuitively know that if coverage is low, we don't have enough tests, and if coverage is high, we probably do.  Some IT shops even set minimum code coverage percentages, so if you check in code that drops the coverage metric below 80%, you fail the build.

One way to get higher code coverage is to generate the tests.  Visual Studio has versions that can do this for you.  Point the code at a class, click OK a few times, and all your code in the class under test can be covered.  In fact, the generated test usually check for things you might not bother to, like what if there is a negative value passed in to a method, what if a zero passed in, what about a null, etc.  How can this be bad?  We're exercising the API of our class more fully, right?

What not to test

I think the focus needs to be on testing the right code in the right way.  There is no point in testing the .NET framework.  If you have a auto property that is an int, you don't need to test -1, 0, 1, and null.  If int stops working, everyone using .NET has a bug.  But int isn't going to fail, and even if it does, it's not your code anyway (unless you work at Microsoft on the .NET framework team).

So the first rule is be sure you're testing your code.  That means testing your methods that do real stuff.  If you have a method in your class that just wraps a call to another class, there really isn't anything worth testing.  All you can test is that the class can be created and the method can be accessed and has those parameters and they are of that type.  But you can do that better by testing the underlying class instead of the pass-through method.

Go faster when refactoring

In fact, testing these properties and pass-through methods and no arg constructors increases your code coverage numbers without adding anything meaningful to the test suite.  The net negative comes into play when it's time to refactor, whether it's adding or removing properties, renaming, moving things to different classes, etc.  Generated tests can really slow you down here as the new code stops building and the generated tests have to be removed and regenerated.

A better way is to write the tests you need first, then add the code to implement that business rule or feature.  Whether you're using TDD, BDD or something else, you'll end up with tests that express the intent of the code rather than its implementation.  Tests should emphasize the features of the application, not the coding artifacts.  These are the kind of tests that add real value to your project.

Tags: Unit Testing, Refactoring, TDD, BDD
Categories: Technical

The case for TDD

Posted by Joe Wilson on Friday, July 17, 2009 7:39 PM

TDD is hard. It sounds like it wouldn't be hard.  It's just a little test.  The code is the hard part, right?  But it's really hard to do it well. I struggle with it plenty and I know my way around C# and OO pretty well.

There better be a payoff for this bass-ackwards way of coding.  It takes a while to get there, but I can see the light at the end of the tunnel in my own development.  Here's where I've seen my code improve as I've moved toward TDD:

Focusness

You focus on the behavior of your code instead of the implementation.  You don't start by thinking of tables, classes, and properties (or in my case, try hard not to).  You start off thinking of the business requirements and roles.  User stories are popular because they push you into restating the requirements in context: "As a (some role)...I want to (do something)...so that (some business value)".  The first two chunks of this can guide your test creation.  You can write methods that cover these scenarios.

TDD Logo If you're doing it the RED-GREEN-REFACTOR way, you'll write a test and just enough for the code to compile, get the test to pass with the minimum amount of code possible.  Finally, you can go back and clean up what you aren't proud of from your first effort, then run the test again.  You get to keep repeating that until you are happy with the code and that the requirement/story is met and the user accepts it.

Then you STOP.  That's the fourth step you don't see in the pretty RED-GREEN-REFACTOR icon.  If you don't stop, you loose your focus on the functionality and you start trying to gold-plate the code.  Which can lead to...

Dude, you know what would make this REALLY cool?

You're getting paid to write software to meet the requirements.  If you going beyond that, be careful who you're doing the coding for.  If it's the business, and you're glad to show them how much time you've spent on it, you might be justified in doing it.  But if you're coding it for yourself, do it on your own time.

Unfortunately, people who are drawn to programming are often tinkerers and bit-twiddlers.  I appreciate having a framework for my development that keeps me on task, because I am easily distracted by grand visions of what I might be able to code into the app.  There is no code we couldn't tweak a little and add this new cool pattern or just-learned technique to.  TDD forces you to go directly to the requirements, not the technology.

SOLID code

The more you move toward TDD, the more little classes you have with giant names.  Same thing with methods.  There are tons, they are very short (one screen or so max), and they have long names.  This is progress?

Yes, I think it is because of the SOLID principals.  SOLID is a horrible acronym of acronyms, but it can help you keep some object-oriented principals in mind.  I'll go over it and how I've tried to learn it in more depth in a future post, but the guys at Los Techies covered SOLID in depth already.  So the side effect of decoupled code is you have lots of little files that just do one little thing.  It took me a while to get over this and the file bloat in the project, but I'm at peace with it now. The payoff is that I am using more SOLID principals than I was before, and that's a good thing.

Oh yeah, you get some tests, too

It's been said before, but TDD is kind of misnamed.  Yes, you start with the test, but that's not the most important thing.  The most important thing is the requirement focus and the way it drives you toward a more loosely coupled design.  But it's pretty fun to see that screen light up with green checks or circles after you've made a change.

The real value of the tests themselves is that today's unit tests become tomorrow's regression tests.  You won't remember why you wrote the code last week, but you don't have to.  The tests can also serve as mini-documentation of the requirements if you write the test names in a consistent way.  There are BDD frameworks that let you spit out some HTML to do exactly this.

Ruthless Refactoring

All this adds up to something of a safety net for refactoring. Think of the confidence you can have changing the code, even if it's another team members code.  Or if (gasp!) they make changes to your code.  It's nice to know your code still works.

If you write the tests first, you know you've got the "happy path" covered on your code.  That's the one you started with.  You can write a few more tests to cover the likely deviations from that happy path, but when you get to the weird stuff (what if you order $999,999,999,999 in widgets?), call it good and move on.

Tags: TDD, SOLID, Refactoring
Categories: Technical

Why bother writing unit tests?

Posted by Joe Wilson on Friday, July 10, 2009 5:57 PM

More developers are coming around to the idea of writing unit tests for their code.  But not everyone is sold.  Let's take a look at the arguments for just writing code and either manually testing or handing the app over to QA:

  • It takes too long to write unit tests.
  • This is really simple code.  I could see maybe testing something complex, but this is just a CRUD app.
  • Write my tests before my code?  Are you kidding me?  I've always done it the other way and it's worked out just fine.

Let's take these one by one and see if they are still valid.

Time Argument

It doesn't take long to run the test.  I think there is consensus there.  But writing units tests and writing code is more lines of code than just writing the code.  More lines = more time, right?

Sure, as long as manual testing is less than the automated testing over time.  Not just the first time, but for the lifetime of that code.

If I'm using your old assembly from 2004 or web service from last month, I want some assurances it still works the way it was supposed to.  If you knew the secret way to manually test it, but have forgotten it, I don't fully trust your code.  I have to spend time going over that code and testing it out myself.

Code with a lifespan longer than your memory and availability to manually regression test it benefits from having a suite of unit tests that can be run in milliseconds.

Simplicity Argument

"If the code is really simple, there is no point in writing unit tests."

This is a good point.  Unit testing can help work through complex code, but what if the code is really easy?

I agree that there isn't a need to bother testing setting and getting properties and methods that just call other methods.  And please don't spend time testing code that is part of the .NET framework or an assembly you bought.  That's a waste of time.

But if you're using test-driven development, you start with the functionality, not the implementation.  So you write tests that cover the important/core stuff in your requirements.  You don't bother testing properties and call wrappers, which are just technical artifacts of the important stuff you are coding.  If it's the important stuff, shouldn't it be covered with unit tests?

TDD = My World Upside Down

Mad Hatter "Writing test before writing code is crazy talk." I also have had a great career without doing this, so what's the point?

I agree it is crazy.  I also agree it's a 180 on the conventional wisdom.  And I completely agree that it's harder than just writing the code.

But here's where I depart from the TDD crowd.  If you're new to unit testing, I just want you to write unit tests to cover the critical code for now.  It might lead you to TDD at some point, it might not.  But it's not an all or nothing thing.  Let's just try to work in as many tests as we can and leave it there for now. How many tests do you need?  What code coverage levels are you shooting for?  That's up to you.  If you feel good showing the code to your peers and are happy to be held accountable for the quality of your code, you're probably done.

I'll make the case for TDD another time.  Just baby steps for now.

Tags: Unit Testing, TDD
Categories: Technical

Blog links

  • Subscribe to this blogRSS feed
  • Archive of old posts

Popular posts

  • Autocomplete dropdown with jQuery UI and MVC
  • Handling Exceptions in ASP.NET MVC
  • Don't mock HttpContext
  • Review of Sharp Architecture
  • Evolution of a View in ASP.NET MVC
  • Comparison of Typemock Isolator and Rhino Mocks
  • Building a Windows 8 Live Tile with JavaScript
  • Setting Default Values for Multiple Value Parameters in Reporting Services
  • Buy, Build, or Both?
  • Why bother writing unit tests?

Tag cloud

  • AppHarbor
  • Areas
  • ASP.NET
  • ATDD
  • BDD
  • Castle Windsor
  • Coding Standards
  • Common Service Locator
  • continuous integration
  • Cookies
  • CRM
  • CSS
  • Custom Software
  • Data Annotations
  • DataTables
  • DDD
  • Dell
  • Dependency Injection
  • DTOs
  • ELMAH
  • git
  • GitHub
  • Html Helpers
  • HttpContext
  • IOC
  • iPad
  • iPhone
  • JavaScript
  • jQuery
  • jQuery Mobile
  • JSON
  • Kendo UI
  • Knockout
  • Microsoft Accounting
  • Moq
  • MVC
  • NHibernate
  • NuGet
  • NUnit
  • OData
  • optimizations
  • Patterns
  • POCOs
  • QuickBooks
  • Rails
  • Refactoring
  • Reporting Services
  • REST
  • Rhino Mocks
  • Session
  • Sharp Architecture
  • SOLID
  • SpecFlow
  • SQL Server
  • SSRS
  • TDD
  • TeamCity
  • TempData
  • Typemock
  • unit testing
  • Validation
  • Visual Studio
  • VMWare
  • WatiN
  • WCF
  • Web API
  • Web Essentials
  • Web Forms
  • Windows 7
  • Windows 8
  • WinJS

Archive

  • 2013
    • May (1)
    • April (1)
    • March (1)
    • February (3)
    • January (1)
  • 2012
    • December (1)
    • October (6)
    • September (3)
    • March (1)
  • 2011
    • October (1)
    • August (1)
    • June (3)
    • March (2)
    • February (2)
    • January (4)
  • 2010
    • December (2)
    • October (3)
    • September (1)
    • August (2)
    • July (1)
    • May (1)
    • April (2)
    • March (2)
    • February (3)
    • January (2)
  • 2009
    • November (3)
    • October (2)
    • September (5)
    • August (2)
    • July (3)

Blogroll

  • RSS feed for Dan WahlinDan Wahlin
  • RSS feed for Jimmy BogardJimmy Bogard
  • RSS feed for John PapaJohn Papa
  • RSS feed for Josh TwistJosh Twist
  • RSS feed for Los TechiesLos Techies
  • RSS feed for Phil HaackPhil Haack
  • RSS feed for Scott GuthrieScott Guthrie
  • RSS feed for Scott HanselmanScott Hanselman
  • RSS feed for Steve SandersonSteve Sanderson

Twitter

  • Twitter May 15, 7:20 PM

    At Denver .NET meetup to hear @rlacovara talk about SpecFlow

  • Twitter May 15, 9:26 AM

    @eriklane @extofer @greeleygeek That sounds weird to me, too. Values on the query string, sure, but not JSON.

  • Twitter May 15, 9:24 AM

    @kevinkrueger otherwise, people will not be as forthcoming about areas they hope the team can improve

  • Twitter May 15, 9:24 AM

    @kevinkrueger I think retros are best if they are for the team only, so they can have a frank discussion of how to get better.

  • Twitter May 14, 10:49 AM

    Terrific talk from @zekeli @html5denver last night "Cross domain Pong with window.postMessage" http://t.co/iO0AAlbJ7l http://t.co/5mnf2fZL0p

  • Follow me on TwitterFollow me on Twitter

Recognition

  • INETA Community Champions

Blog license

  • Creative Commons License
    Blog by Volare Systems is licensed under a Creative Commons Attribution 3.0 Unported License.
    Based on a work at http://volaresystems.com/blog/.