Myself and 10 other developers in my company went through a day of BDD / TDD training, with Scott Bellware, yesterday. It was a lot of fun, very challenging at times, and covered a lot of topics including an overview of Agile and Behavior Driven Development, all the way down to writing Specification Tests, doing Test Driven Development and refactoring the model to improve readability, maintainability, flexibility, etc. I took notes via index cards (love that cool-aid) and wanted to share. I don't expect these notes to make sense to everyone. Hopefully it will spark some dialog in someone's mind and cause them to dig further. First off - the quote of the day. "Can I be honest with you and say that I've been wanting to touch your keyboard, all day?" Now for my notes.  User Stories [Role], [Goal], [Motiviation] - As a [role], I want to [goal], so that [motivation]
- Example: As a nurse, I want to record a patients vital signs, so that I can determine their medication and care needs
- Motivation is critical - it determines how the development team understands and implements the story. It determines the user experience, how things are integrated, how the software is designed, etc.
Acceptance Criteria - Acceptance Criteria is used to drive code, not the story, directly
- may change at any point, up to implementation
- is used to drive code design, test design, implementations, etc.
- should be spoken in domain language
- may include non-functional, technical details such as database tables, infrastructure, performance, etc
- All acceptance criteria must be met and tested / verified before a story is considered done
Specification Tests - Test Fixture per Class is an anti-pattern (on a personal note, this problem bothered me for months before I discovered BDD)
- Context Specification or Behavior Specification testing
- When [verb] then [verb]
- "When [verb]" is the context
- "Then [verb]" is an observation of the behavior
- Based on Acceptance Criteria, but not "code-gen'd" from acceptance criteria
Story Estimation - Agile Poker: uses generalized Fibonacci sequence as order of complexity
- "?", 0, 1/2, 1, 2, 3, 5, 8, 13, 20, 40, 100, infinite
- everyone throws their estimate at same time
- if estimates have significant outliers, discussion occurs to understand why, get more detail, etc. and re-throw may happen
Entity Data vs. Aggregate Data - Entities should never contain aggregate data
- Aggregate data is for reporting and other aggregate needs
- If you need aggregate data to process something, write an SQL query, stored proc, etc. - don't use an ORM like NHibernate
- We don't want a "Customer" entity to need 10,000 "Order" entities, to aggregate data for processing; write a query to aggregate instead
- We don't want to persist data that can be calculated / aggregated, generally (performance issues may override this)
Domain Services - Can have dependencies on external systems
- are part of domain logic, therefore are in domain model / assembly
- are "Doers" of process that don't fit into entity and entity logic, directly
- coordination of entity logic
- can include calls to data access, logging, etc.
Continuous Integration - Not just continuous compilation of code
- Full end to end integration of all code, components, databases, services, etc
- Full suite of integration testing including database testing
- Do not allow commits if build is currently broken
- do not allow defects to live - fix immediately, to fix build
- "Defect" is broken software, "Bug" is functional but wrong
Daily Scrum - 3 Questions everyone answers:
- What did I do yesterday?
- What am I doing today?
- What issues am I having?
- Each person should answer quickly - 1 or 2 minutes, max
- further discussion happens outside of the Scrum meeting
Productivity of Dev Team - RAD and other non-review, non-iterative based management causes problems and loss of productivity
- we need constant review of the design to ensure good design
- shorten the feedback loop and get constant review of the design, to always improve the design, via pair programming, work cells, retrospectives, etc.
- good design will cause productivity gains in the development team beyond the capabilities of any tools
Whiteboard Diagramming vs. Details Specs - White board diagramming and human interaction is always better than detailed documents and specs in UML
- Human interaction leads to knowledge crunching and learning, not just reading a repeating
- Take pictures, don't re-draw in UML; don't waste time with it
- Video the entire conversation is even better, so others can learn from the knowledge crunching that occurs; capture the human interaction, body language, etc.
The topic of Model-View-Presenter starter resources came up at work, today, and I like the list I pulled together. So, I thought I would share with the rest of the world. This is by no means a comprehensive list, or even "the best" list - it's only what I pulled together in 10 minutes. The original source of MVP : http://www.martinfowler.com/eaaDev/ModelViewPresenter.html My own best practices for MVP, following the Passive View mentality http://www.avocadosoftware.com/csblogs/dredge/archive/2008/02/20/787.aspx This article should solidify a lot of what I am talking about in my best practices http://msdn.microsoft.com/en-us/magazine/cc188690.aspx Jeremy Miller was one of the guys to originally start pushing MVP into the ASP.NET community. He’s got a lot of good articles on his blog http://codebetter.com/blogs/jeremy.miller/archive/2006/02/16/138382.aspx This was the article that really solidified my understanding of the basics of MVP, back when I first started learning it http://www.codeproject.com/KB/architecture/ModelViewPresenter.aspx Aside from those core MVP articles, there are several key concepts that you’ll want to understand in order to really be able to present / teach MVP, including: - Single Responsibility Principle
- Open/Closed Principle
- Dependency Inversion/Injection and Inversion of Control
- Liskov Substitution Principle
The key to these principles is really the subtlety that underlines them. For example, the Liskov Substitution Principle isn’t just a fancy name for polymorphism – it’s what makes polymorphism work. You certainly are not required to know these principles forward and backward to be able to implement MVP, but you’ll find that the question of “why?” is easier to answer to if you do know them. Honestly, when it comes down to it, these principles are what make object oriented development work – they are how you achieve the high cohesion, low coupling, and tight encapsulation that OOD wants. There are plenty of other principles (such as Orthogonality, the law of Demeter, and others) that will help you achieve this as well; but this is a starter-list, not the all encompassing list. One of the books I've been reading recently, that covers these topics and more, is "Agile Principles, Patterns, and Practices in C#" by Robert Martin and Martin Micah.  I highly recommend this book, not just for these topics. It's a great book, all around.
I hate the Try Catch syntax in C# - it's bulky, ugly, and makes my code hard to read. try { // do some stuff here } catch { //handle exceptions here } finally { //clean up here }
Although very functional and well documented, to the point where it can be effectively used, I don't see the elegance that I want in my language - especially if you actually have to catch a specific exception and deal with it in the middle of your functional code.
So, I'll create the elegance that I want.
public class TryCatch { public static Exception Do(Action action) { Exception caughtException = null; try { action(); } catch(Exception ex) { caughtException = ex; } return caughtException; } }
With this very basic implementation, using lambda expressions, I can create a much more friendly syntax to use:
Exception ex = TryCatch.Do(() => { //Do Stuff Here, with assurance that an exception will be caught, if thrown. }); //send the exception off to the exception processing / handling, if needed.
From there, you could add a "fluent" interface to catch specific exceptions, have a finally block, etc - but you end up with the same ugliness that I wanted to avoid.
//Blech. This just puts us right back in ugly-ville TryCatch.Do(() => { //throw exception here }).Catch<Exception>(() => { //handle exception here });
ugh - ugly, for that matter. That didn't help us at all. And we don't need it, anyway. You are guaranteed to have the before and after TryCatch.Do execute.
//setup IDBConnection conn = GetMyConnection(); TryCatch.Do(() => { //execute conn.Open(); }); //cleanup if (conn != null) conn.Dispose();
I like it.
I'm reading "Lean Software Development: An Agile Toolkit", and the first paragraph under "Tool 11: Queuing Theory" talks about the bottleneck that often occurs in the test lab - not enough testers, too much work for the number of testers, etc. "We have often heard the lament 'My biggest problem is the testing department.' Now, testing people are very nice people: dedicated, hard working, and very important to the development effort. But there never seems to be enough of them to go around. And although the developers might write their own unit tests, testers frequently do acceptance testing. So, without enough testers, the whole development process bogs down." The rest of the chapter talks about the queuing theory that can be applied to help alleviate the issue. It's a great chapter with lots of good information. I have a problem with the idea of applying this type of queuing theory to the the test lab, as a bottleneck, though. First, let me state some assumptions about the primary responsibility of the testers in the test lab: - Testers are writing automated acceptance tests, for automated regression testing and integration testing
- Testers are also doing human interaction testing, for the "human touch" of usability, etc.
If the testers are the bottleneck, and the two primary functions of the testers are as I have listed, then I think the there is a much more simple solution to the problem, from a lean perspective: let the developers write the automated acceptance tests. Assuming that the developers are already writing unit tests, and are therefore capable of writing code to test code, it makes a lot of sense in my mind that the developers should be writing the majority of the automated acceptance tests. It all goes back to the idea of flow - ensuring that the entire system (or process) has a smooth flow from beginning to end. This means that we may need to sub-optimize one area for the benefit of the whole, but the end result is that we will have a better system or process by making the entire flow as smooth as possible. Counteracting Mura - or "Let's make it smooooooth" If we are looking at the test lab as a bottleneck - a rough spot in the flow of our software development cycles - then let's take the most simple course of action possible, to reduce that rough spot as much as possible. Rather than spending so much time and effort on queuing theory and implementation, let's find a way to remove the bottleneck. Assume that the software developers are experts at writing code - and writing code to test their code. Doesn't it make sense, then, that the software developers should be writing the acceptance tests, even if the acceptance tests are being specified by the customer and test lab personnel? If we allow the developers to take a little more responsibility, we may be sub-optimizing the development department a little. But, by doing so we are freeing up the much more scarce resources of the test lab and we can then make adjustments to the test lab's queue and workload, if needed. The idea of leveling out the flow of the system like this can be traced back to the Japanese term, Mura. The Wikipedia entry says it all: "The fact that there is one operator will force a smoothness across the operations because the workpiece flows with the operator." In this case, we are calling the combination of production code, unit tests and acceptance tests, the "workpiece". I believe this is a fair assesment, since the code and tests are all going to be based on a feature, use case, or user story. In fact, I would say that the workpeice actually is the feature, use case or user story that is being worked on. The code, unit tests and acceptance tests could be considered the artifacts products by the workpeice flowing through the system. ... but that's just splitting hairs, really. It's all about Occam's razor, Parsimony, KISS, or whatever you want to call it - the simple solution is often the correct solution (simple, however, doesn't always mean easy). The Need for the Test Lab I'm certainly not saying we don't need a test lab. The testers are (supposed to be) experts in interaction testing, usability testing, and adding that "human touch". We absolutely need that perspective on those aspects of software testing that can't reasonably be automated. I am advocating that we find a better way to smooth the flow of the system - rather than apply complex theories and equations to the situation, find a solution that doesn't require anything complex. Conclusions In the end, the problem of the test lab bottleneck can be solved many different ways. You might level the system via Pair +1 Programming or some other form of involving the developers in writing the automated acceptance tests. Perhaps you make the testers part of the team and have them writing the automated tests at the same time as the developers writing code. You might still need to employ queuing theory. Either way, try to find the solution that works best to smooth out the process for your team.
There's a lot of talk about Spec# in the blogosphere, recently. I've read a few blog posts and reviewed some of the official web site, and it looks very promising. Essentially, it's a language extension to C# that adds Design By Contract as a 1st class part of the language - including non-nullable types, preconditions, post conditions, etc. Looks like my DBCUnit idea may have a short life.
A lot of people talk about software in terms of manufacturing and construction - laying the foundation, getting the architecture in place, building components, assembling the final product, make sure we have all the plumbing setup, wire it all together, etc, etc, etc. "The problem with the construction and manufacturing analogies, is that they fall apart as soon as you start talking about software as construction and manufacturing." - me Software developers are not construction or manufacturing workers. We don't sit on an assembly line, mechanically reproducing the same result over and over and over again. We don't (or at least, shouldn't) put all the plumbing and frames in place before anything else. We're not line workers, warehouse workers or laborers. The only parallel that exists between any manufacturing or construction positions, and software development is that we are research, design and development workers. Some manufacturing companies have R&D positions, some don't. Some construction companies do, too. Software development is ALL research, design, and development. When it comes down to it - source code is not a foundation, a structure, a component or any of the other parallels that people try to use. Source code is a specification for how an executable software package will be built and will behave. We don't build the executable software package - the compiler and build scripts do that for us (if you are manually building the software, go learn NAnt, Rake, Make files or some other automated build process for your environment). What we do when we write source code is R&D - research, design and development... hence the name, "Software Development". Therefore, "The only part of software development that even remotely resembles manufacturing or construction is the moment we click the 'build', or 'compile' button, or kick off whatever script or command, and the build process does the work for us." - me 
Based on the proposed information and syntax from My Previous Post, I've created a basic Design By Contract unit testing framework. The intent of the code so far, is to provide a quick-and-dirty proof of concept. With that in mind, I give you DBCUnit hosted on GoogleCode You can get the source code via Subversion: http://dbcunit.googlecode.com/svn/trunk/ Please note that the existing code only supports one assertion so far: Equals. Also, the execution engine is entirely made up of terrible code that assumes a lot of perfect-scenario input. I'm planning to flesh it out more and make the code more sustainable - actually adding Contract specifications for my execution engine, etc. Let me know what you think of the idea and the syntax. Also feel free to join the project and pitch in for syntax and implementation. The one Contract I have specified so far, just to get rolling, is that a [PreCondition] should be executed once. [Condition] public class WhenPreConditionIsPresentInContractCondition { private int preConditionExecutionCount = 0; [PreCondition] public void PreCondition() { preConditionExecutionCount += 1; } [PostCondition] public void ThePreConditionIsExecutedOnlyOnce() { Assert.That(preConditionExecutionCount).Equals(1); } }
To run the test, run build the solution and run the DBCUnit.Console pointing to the DBCUnit.Contracts.dll, like this:
C:\...\> DBCUnit.Console.exe DBCUnit.Contracts.dll
If the test succeeds, there is currently no message printed to the console window. If it fails, it will write out a message saying what value it expected and what the value was. It's all very simplistic at this point, just a proof of concept. I also set up the DBCUnit.Console project to automatically start with the "DBCUnit.Contracts.dll" as the startup parameter, so you can step into the code via debugger and see it in action.
Have fun, and don't laugh too much. This is my first attempt at hacking together a unit testing framework.
There's a lot of talk about Design By Contract (DBC) out there in the development world. Various development languages have varying support for it, but more importantly various processes have various levels of support for it. It seems, though, that the farther down the path of development we travel, the more important it is for us to consider DBC in the code that we write. Large projects with multiple developers are in great need of DBC. Projects that have publicly distributed API's are in even greater need of DBC. Even if you are working on a simple, one person project for yourself, and you are the only one that will ever use it's methods and objects, I'm willing to bet that you will forget about the assumptions that you are making when writing the methods and objects, at some point. So where does this distinct need for DBC leave us, in the world of .NET (C#, VB, and the other "common" .NET languages)? We still need a way to enforce DBC, but our language of choice doesn't support it, natively. So we have two real choices (excluding DSL writing, and/or switching languages) - documentation (via code comments or written / published documentation) or Unit Tests. Yes, that's right - Unit Tests are not just for testing, anymore. Or more correctly, the tests executed by unit testing are not just for the sake of testing. The intention is verify the pre and post conditions of a design-by-contract. Of course, I'm not the first one to suggest this. It's mentioned briefly in "Agile Principles, Patterns, and Practices in C#" by Robert C. Martin and countless other times as well. I am propose a new unit testing framework. I know, I know... "not ANOTHER xUnit framework... *sigh* ". In this case, I am proposing a semantic change along with the mechanical (syntax) change, specifically for the purpose of introducing unit testing to a group of developers that may not believe in "Unit Testing". As an example of my proposed syntax, in a file called "SomeContract.cs", this test code would exist: [Conditional] public class WhenSomeConditionIsMet { SomeValue someValue; [PreCondition] public void PreCondition() { Setup.My.Inputs inputs = Here; } [Execution] public void Execution() { someValue = Execute.TheContract.With(inputs); } [PostCondition] public void ThenSomeOutputIsSomeValue() { Assert.That(someValue).Equals("Some Known Value"); } [PostCondition] public void ThenSomeOutputIsSomeValue() { Assert.That(someValue).DoesNotEqual("Some Unknown Value"); } }
To make this proposed syntax easier to understand, I'm basing it on the NUnit style of using attributes, at the moment; but it doesn't have to be that way. There is almost a one to one translation between NUnit and this.
- The [Conditional] attribute is equivalent to [TestFixture]
- The [PreCondition] attribute is equivalent to [TestFixtureSetup]
- The [Execution] attribute is equivalent to [Setup]
- The [PostCondition] attribute is equivalent to [Test]
In this simple example, I don't have an equivalent to [Teardown] or [TestFixtureTearDown]. I'm sure I'll need those at some point, but until I see the need, I'm not going to worry about them. I also don't really care about the Assert syntax. I'm just putting that syntax in place to illustrate the point.
Where I differ from typical NUnit style of testing is that I want to see a single "PreCondition" and "Execution" per test fixture, and have multiple "PostConditions" that only contain the assert statements. This style of test code more closely resembles that of Scott Bellware's SpecUnit.NET and for good reason - I like it. I'm a fan of having as little as possible in the method that does the assert - keep it simple and explicit.
The biggest problem I have with my proposed syntax is a problem inherent to Design By Contract - the idea that you know the object (contract) being executed. A huge part of why I love Behavior/Specification Testing vs. Unit Testing is that Unit Tests and TestFixtures typically tell you that for class/file "XYZ.cs" you have "TestFixtureXYZ.cs". Whereas, Behavior/Specification Testing says that we have "BehaviorSpecification.cs" regardless of the classes used to implement it. I love this about Behavior Driven Development - it freed my mind from the horrible constraints that I saw in standard Unit Testing / TestFixtures. Unfortunately, Design By Contract basically takes us right back to the same place. We are specifying contract (class) "XYZ" so we have a "XYZContract.cs" file to hold all of our [Conditional]s.
...
Does anyone else see any value in this style of unit testing? I can certainly see scenarios where this would appeal to some developers more than the standard xUnit frameworks.
I saw "The Forbidden Kingdom" this weekend. Overall it was a great movie - lots of good action, a good storyline, etc. But there was one scene that stuck in my mind specifically. Jackie Chan is pouring some drink into a cup while the person holding it is talking. The cup quickly overflows and the person holding it notes that the cup is full and now overflowing. Jackie Chan's response was something to the effect of How can you fill your cup when it is already full? How can you learn anything when you 'know so much' already? The point of this, of course, is that the student thought he knew so much already and wanted to get right to the advanced stuff rather than letting the teacher guide him through the basics into the advanced stuff. As silly as it is for a pop-culture movie to have deep wisdom, I really thought that this scene's message was applicable to more than just martial arts. The same can be said of any situation where knowledge, learning and growth are present. One of my coworkers (Michael Adkins - who's blog is not publicly available, yet... *nudge nudge*) recently had a post that talked about the same thing, with a slightly different quote at the beginning. Rather than me re-hashing his post with my own interpretation, I'm re-posting his post in it's entirety (with his permission, of course). So, you think you know everything about development eh? A wise man once said, "He who knows everything, cannot be taught anything." This is such a profound statement. When it comes to learning, I attempt to look at the learning process as if I don't know any of the material (all things being equal of course). This allows me to see things I did not see in the past. It allows me to critically think about ways to solve problems with the new knowledge I have gained. Sometimes when a person asks questions, it is perceived that the person doesn't have a clue as to what is going on with the process. In my case, it is my acid or litmus test to locate a person; to see if they can articulate an answer that tells me if they are trying to help or build their ego. Nevertheless, whether a person is helping or building their ego, they are still helping with all types of insight. They just may not be aware of it. This is something we all may be guilty of in some form or another. But it just goes to show that we don't know everything. It also goes to show that we continue to teach and instruct when we think we know everything. This blog came about when I was going through a webcast that dealt with Delegates. I couldn't have said it better. ... I just hope that I'm not the guy who's cup is already full.
Recently, my development team has started up our Friday Lunch-n-Lean sessions where we all read a chapter of a given book and discuss that chapter amongst the group during lunch on Fridays. We're now on Chapter 2 of Domain Driven Design, by Eric Evans. When I first started reading DDD around a year and a half ago, I honestly thought the first 4 or 5 chapters were wordy, boring and repetitious. Going back to the beginning of the book with my experience and knowledge from the last year and a half, I can't believe that I thought this. The first two chapters alone have been completely mind-blowing for me, on my second read of the book. I don't know if it's the combination of other knowledge, the experience I've had trying to implement DDD's concepts, or what... At this point, I can hardly turn a page without having 10 or 15 highlighted phrases and sentences. Seriously - there's rarely a page in the first two chapters that does not have something highlighted. If your involved in any part of software development - management, analysis, development, documentation, or anything else - and you've never read this book; you need to read at least the first 3 chapters at least 3 times, if not the entire book.
|