Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test Driven Design and Layered architecture [closed]

How to apply TDD over enterprise application that has layered architecture?

I want to know how to apply TDD to an application that has following

  1. WPF application (6-7 screens)
  2. 3-4 Modules (Prism modules)
  3. Some application services (Logging, Exception Handling, Security, Authorization, Core Business services library)
  4. Data Access Layer (using Entity Framework)
  5. A bunch of WCF services

As I understand, first thing is to get the architecture right. As a result, Components are identified. Next is to develop the components independently, where I stuck.

With TDD, design (of a component) evolves with time. For a component following is the way (I perceive) to go with TDD

  1. Identify all use cases
  2. Identify all test cases
  3. For each test case, write all scenario, and for each scenario, write a failing test case. Make little code, so that test case is passed. Add to list, if new scenario is found
  4. Follow Red-Green-Refactor until all the test cases (corresponding to all scenario) are passed
  5. In the refactoring, dont forget DRY, YAGNI, Mocking, DI, etc,etc.
  6. End result is well designed Component (how much well designed depends on experience and skills of developer).

Problem i face is, For a component, until i reach to Step 6 of TDD process, i donot know the interfaces. Since there are multiple components, multiple teams, No body is sure what they will come up with.

Now the summary Questions based on above scenario

  1. Is there some basics that I am missing? Please point me to appropriate resources if yes.
  2. How to apply TDD over layered architecture?
  3. How to do parallel development of multiple components
  4. Best practices for TDD with WPF UI (PRISM)
  5. Best practices for TDD with Database (using Entity Framework)
  6. How to decide WCF service contract, when using TDD?
like image 870
Tilak Avatar asked Dec 19 '12 13:12

Tilak


2 Answers

I think you have the order wrong. You're choosing the architecture, then trying to get there with TDD. The idea behind TDD is to start w/ nothing, and arrive at an layered architecture if it's needed.

Of course, that probably doesn't help when you're looking at a very large project, because there has to be some organization to it all. My usual approach is to try to divide the work into something that makes sense to real people (not programmers). And no, I'm not really talking full Domain Driven Design. I'm referring to just thinking of the different pieces as an outsider would.

For example, if I want to make a program that represents a cash register (something that can hold money and figure totals).

What's the first thing I want it to do? Hold and dispense money. So, I need a drawer (first component, give it to a team). I need a button to open it (second component, second team), etc... The key is to focus on what it should do, not how it should do it.

Yes, there's a lot of contract/protocol talks that have to happen. Those are things the teams involved will have to work out as they hit the problem. The key is to focus on what you want it to do. Solve the now problem. Don't pre-optimize. You'll probably find that not all of the components require all of the layers.

The short answer to the best practices questions is "it depends." (The cheesy, common, and overused IT answer.) The general rules are you want to focus on behavior, not implementation. Ensure you can trust the tests (they produces the correct results all the time). Make sure you test as much as is possible... Or, numbered...

  1. Start with tests, not design. Roy Osherove and others have a tons of writings on the subject. His book, along w/ Micheal Feathers are the best place to start.
  2. If you start w/ tests, and the layers evolve as you fulfill more tests, you wind up with TDD over a layered architecture.
  3. Divide them in a way that makes sense. My rule is to stick to what makes sense in the real world. Engine team gets the engine, tire team gets the tire. Make sure people communicate.
  4. I don't use PRISM.
  5. I don't use EF, but can say that database testing is a whole can of worms. Integration testing involves a lot of environmental configuration and such. Ayende has quite a few blog posts on this.
  6. Danger Will Robinson. What makes you so sure you need a WCF service contract?

Sorry if this was really vague. Google the names I dropped, they're good places to start. If you want a leg up on TDD, hire a couple experienced coders and use pair programming. If you can't afford that, hire someone to come in and do some training, then do pair programming. Can't do that? Get some books and use pair programming.

Then, beat the pairs to ensure they're writing tests first.

At the end of the day, it's about deciding what you want something to do, then letting the tests evolve the architecture. Not the other way around.

like image 157
cloggins Avatar answered Sep 27 '22 23:09

cloggins


I think that you are going in the right direction with all of your plans so far. What I advise is that you spend just enough time on upfront design so that you DO have the interfaces between each layer defined. It's simply impractical to start doing any development (let alone TDD) without it. Once the interfaces are agreed upon by all teams, you can then easily transition to TDD by using mock objects to implement the interfaces. There are many well established mocking frameworks available, such as Rhino Mocks. The idea of creating the interfaces upfront may be easier said than done, and you will undoubtedly end up having to make changes along the way. But you need to have a starting point. This is sort of challenge is exactly where a Component Model Diagram becomes useful. By having the teams work together to create this upfront, you won't be able to predict the final interfaces exactly, but you will get the high level details hammered out which will help avoid earth-shattering refactorings later in the project.

Also, I would give special consideration to your database layer. This is a debatable topic worthy of it's own separate discussion. Using EF you will find that you cannot simply "mock out" the entire layer. You would have to create a whole separate abstraction on TOP of EF to do so. Doing so may add unnecessary complexity to your application. You should consider very carefully if this is required - if you can just populate a test database with test data, there's no reason not to let your automated tests directly call the database.

like image 24
Dan Ling Avatar answered Sep 28 '22 00:09

Dan Ling