A basic principle of layering is the dependencies between layers must exist in one direction, starting from the presentation layer downward. The domain layer contains most of the business logic and is mostly accessible to the other layers. Designing a behavior rich domain layer allows for
- UI to be free of business logic and available to concentrate on presentation logic
- Application layer to be thin, meaning it directs flow and delegates work to domain objects. It also addresses the concerns of transaction management, security and other enterprise services
- Infrastructure layer to focus of data related concerns such as connections to a database, CRUD operations that can be reused across various modules, and possibly ORM specific API calls such as a criteria query or abstracted SQL language (ejb-ql or hql).
Behavior-Driven Development (BDD) was first coined and introduced by Dan North, now of ThoughtWorks. BDD is an extension upon TDD and does not contest the fundamental values of TDD. Dave Astels, another strong proponent of BDD, explains that "Behavior-Driven Development is what you are doing already if you are doing Test-Driven Development very well." The core of BDD consists of focusing on the behavior of software and defining that behavior through executable specification. The motive behind BDD was that the users of Test-Driven Development tended to move away from focusing on behavior and a testing mentality would take over as tests were written.
An example of allowing a "testing mentality" to take over your test-Driven development process would be as follows:
- I create a test for class PersonService and its method findPersonByName, which is intended to retrieve a Person object whic has the name "bob" from a database. Note that I intend class to use a DAO of some sort to do data retrieval.
- I create the PersonService, Person, and PersonDAO class.
- Now I get back to my test and create my necessary mocks which may be for the Person and PersonDAO class. During this process I set up those mock objects to have dummy data or for them to expect invocation calls.
At this point I have entered the mindset of "testing" and not just the behavior of my PersonService class. If I was only worried about the behavior and abstracted myself away from implementation, the first test I create would only consider that the invocation of PersonService.findPersonByName returns a Person object named "bob", regardless of the implementation. What if we extended this example to a method that didn't return anything, i.e. it returned void? Thus, we may write a test that only verifies that a mock is called. What does this really accomplish other then satisfying code coverage and validating that you called what you intended to call. These are legitimate concerns but not "behavior-Driven" concerns. They are more unit testing and general "testing" concerns. In my experience, I have seen tests in projects that verify mocks and all the tests pass, but since no behavior was validated through tests the system behavior was not met. Thus we had a situation where unit tests passed, but the code had a bug. This is classic verification without validation. Essentially it is doing the right thing, but not doing the thing right.