views:

167

answers:

4

I want to find the best setup for ASP.Net MVC projects to get the quickest code-build-run process in Visual Studio.

How can you set up your solution to achieve near zero second build times for small incremental changes?

If you have a test project, with dependencies on other projects in your solution, a build of the test project will still process the other projects even if they have not changed.
I'm don't think it is entirely rebuilding these projects but it is certainly processing them. When doing TDD you want an near zero second build time for your small incremental changes, not a 20 - 30 second delay.

Currently my approach is to reference the dll of a dependent project instead of referencing the project itself, but this has the side effect of requiring me to build these projects independently should I need to make a change there, then build my test project.

One small tip, if you use PostSharp, you can add the Conditional Compilation symbol SKIPPOSTSHARP to avoid rebuilding the aspects in your projects during unit testing. This works best if you create a separate build configuration for unit testing.

+2  A: 

Here's how you could structure your projects in the solution:

  • YourApp.BusinessLogic : class library containing controllers and other logic (this could reference other assemblies)
  • YourApp : ASP.NET MVC web application referencing YourApp.BusinessLogic and containing only views and static resources such as images and javascript
  • YourApp.BusinessLogic.Tests : unit tests

Then in the configuration properties of the solution you may uncheck the Build action for the unit tests project. This will decrease the time between you press Ctrl+F5 and you see your application appearing in the web browser.

Darin Dimitrov
A: 

I don't think "code-build-run" is any way a tenet of TDD.

You don't need zero-second build times -- that is an unreasonable expectation -- 5 - 10 seconds is great.

You're not running tests after every tiny incremental change. Write a group of tests around the interface for a new class (a controller, say, or a library class that will implement business logic). Create a skeleton of the class -- the smallest compilable version of the class. Run tests -- all should fail. Implement the basic logic of the class. Run tests. Work on the failing code until all tests pass. Refactor the class. Run tests.

Here you've built the solution a few times, but you've only waited for the builds a total of 30 seconds. Your ratio of build time to coding time is completely negligible.

Jay
I disagree - you _should_ be running tests after every tiny incremental change; if you're not, it reflects problems with your environment, that it's putting too many barriers in your way to painless testing. @Paul is exactly right to be finding a way to make testing painlessly fast.
Carl Manaster
Per-line-of-code? I think we're getting into the semantics of "tiny incremental change." Run tests after implementing a getter and setter? Yes. After just the setter? I think you can hold off 2 minutes until the getter is passable, too. Is 5 seconds painfully slow? Too much emphasis on a difference of a few seconds (once you start getting into 10-20 second differences, I'm on board), because reading and analyzing test results is where most people/teams fall down on efficiency. I see people going through an elaborate 5-click process every few minutes to see their test results. Home row, baby!
Jay
Also looking now at the semantics of "change." I think testing at shorter intervals is more important at refactoring time than at initial implementation.
Jay
I've read comments by Jon Skeet saying how compile times of more than 10 seconds affect your developer workflow, see this long but informative post http://www.eggheadcafe.com/software/aspnet/29777292/why-doesnt-c-allow-incr.aspx
Paul
+4  A: 

I like Onion architecture.

Solution should have ~3 projects only =>

  • Core
  • Infrastructure
  • UI

Put 2 more projects (or 1 and use something like nUnit categories to separate tests) =>

  • UnitTests
  • IntegrationTests

It's hard to trim down more. <= 5 projects aren't bad. And yeah - avoid project references.

Unloading unnecessary projects through VS might help too.

And most importantly - make sure your pc is not clogged up. :)


Anyway - that's just another trade off. In contrast to strongly typed languages - dynamic languages are more dependent on tests but it's faster and easier to write them.


Small tip - instead of rebuilding whole solution, rebuild selection only (Tools=>Options=>Keyboard=>Build.RebuildSelection). Map it to ctrl+shift+b. Original map remap to ctrl+shift+alt+b.

Arnis L.
Very clean, but it does require a little discipline with respect to namespaces.
Jay
@Jay, it's not that hard. Just stick to rule => folder:namespace == 1:1.
Arnis L.
What happens when you have projects in multiple solutions, some of which have the onion arrangement and some of which don't, or where the project is logically nested 1 level down in solution A and subordinate to something else in solution B? No, you're right -- not a big deal at all.
Jay
@Arnis, could you please explain why should one avoid project references? How to reference then?
Anton
@Anton Setup proper build that outputs everything to build directory, then - reference dll`s directly from there. Main gain - studio won't rebuild whole project tree when you need to rebuild one project only. But it's a tradeoff as usual. Project references are easier and more suitable for small solutions in case build time don't get on your nerves.
Arnis L.
+1  A: 

One way you can cut down on build times is to create different build configurations that suit your needs and remove specific projects from being built.

For example, I have Debug, Staging, Production, and Unit Test as my configurations. The Debug build does not build my Web Deployment project or my Unit Test project. That cuts down on the build time.

Chris F
This is what I ended up doing, I created a unit test build configuration with only the test project selected. In my test project I include references to the dlls of dependent projects (not the projects themselves). This reduces the build time to only the files in the test project.The only down side is when I have to change a dependent project, I have to recompile that independently then rebuild my test project. But overall this is the approach that gives me the best developer work flow.
Paul