Documenting my journey through the pratice of software development RSS 2.0
 Monday, July 21, 2008

Test Driven Development Is To Unit Testing As Interaction Design (IxD) Is To Accidental Design

One of the major problems with writing unit tests after the code is that it is very natural to write tests that prove the code works the way it was written, instead of the way it should work. Writing code test-first (via whatever flavor of Test Driven Development) flips that scenario right side up. TDD helps to ensure that code is written to work according to specifications and not the other way around.

Similarly, designing and/or implementing a UI after a behavior or process has been coded is a likely to result in a UI that fits the code model and not a model that fits the needed interaction and workflow. This situation must also be flipped right side up - interaction design should be done before, or at least in parallel, with coding. It cannot be left to accidental or incidental happenstance - interaction design must occur with proper interaction patterns and practices in mind.

Overlapping IxD and TDD

To overlap interaction design and test driven development, there are a few key words that need to be borrowed from interaction design. Fortunately, they easily fit within TDD development techniques and philosophies.

Epistemic work is exploratory in nature, or a process of trial and error through research. TDD and interaction design sketching are both epistemic. TDD explores API possibilities and allows easy trial and error to find the simplest implementation for what you need at the time. UI design sketches also allow you to quickly explore interaction designs - whether it's a white board, pencil and paper, graphics design software, or even quick-hack forms layout in IDEs. You can quickly and easily throw away a bad API in TDD and you can quickly and easily throw away a bad UI/Interaction design when you have nothing more than pencil sketches or white board drawings.

Pragmatic work is very structured and step-by-step in it's nature, implementing patterns and practices to fulfill what is needed at the moment. Implementing Code after writing unit test and implementing UI after designing around constraints are both pragmatic. TDD is pragmatic in that you only implement what is needed to properly pass the tests that have already been written. Similarly, with previously designed interactions and UI elements, implementation can be easily limited to what is needed for the UI.

With epistemic and pragmatic work covering both interaction design and test driven development, it seems that they are a natural pair. An analysis of a user story and it's acceptance criteria will create the unit tests that we need. At the same time, the same analysis can be applied to interaction designs. Additionally, a strong understanding of how a UI will look can have a profound impact on the code that is written, and vice-versa. Therefore, it is natural that interaction design and test driven development are done at just-in-time intervals - before the real work is implemented in the real code and UI platform.

IxD As Part of "Done"

Despite interaction design being a required part of UI development, not all user stories require a UI. Interaction design may not fit into a swim lane board or be part of every story's "done" criteria. However, interaction design will always be done for any story that does have a UI - it may simply be an accidental or incidental part of the software development process for a team, though. If it's safe to assume that the work will be done, then it is the team's responsibility to ensure that it is done correctly. Don't let interaction design happen accidentally or incidentally in the development process. Set a standard of always including interaction design in the development process, the same way Model View Presenter/Controller is a part of development.

Monday, July 21, 2008 8:47:04 AM (Central Standard Time, UTC-06:00)  #    Comments [3]. Trackback 
Tags: Agile | Analysis and Design | Behavior Driven Development | Interaction Design | Management | Model-View-Presenter | Principles and Patterns | Test Driven Development | Unit Testing | User Stories

 Friday, July 11, 2008

Earlier this week, I was doing a training session with my current team, building a sample Org Chart application. One of the user stories we were working with, talked about assigning managers to department and had the following acceptance criteria:

  • When assigning a manager to a department, ensure that they are an employee of that department, and remove them from their old department

The basic code that we came up with worked well and was encapsulated into a service object in the domain.

public class AssignmentService
{
    
    private IDepartmentRepository _repository;
 
    public AssignmentService(IDepartmentRepository repository)
    {
        _repository = repository;
    }
 
    public void AssignManagerToDepartment(Employee manager, Department assignedDepartment)
    {
        Department previouslyAssignedDepartment = _repository.GetDepartmentForEmployee(employee);
        if (previouslyAssignedDepartment != assignedDepartment)
        {
            previouslyAssignedDepartment.RemoveEmployee(manager);
            _repository.Save(previouslyAssignedDepartment);
        }
 
        assignedDepartment.AssignEmployee(manager);
        assignedDepartment.AssignManager(manager);
        _repository.Save(assignedDepartment);
    }
    
}

Problems

At first glance, this code seems simple enough, but we quickly ran into a problem when we started coding for another story and acceptance criteria.

  • When creating a department, allow a manager to be assigned

Off-hand, this seems like a very simple situation. We'll just call the AssignmentService object after we create the Department. However, there's a large potential problem with this - the AssignmentService handles the entity persistence for both of the departments that were changed, when the manager is assigned. With that in mind, the developer working on the new requirement would have to ensure that the department is created with all of it's required fields and information before calling this service object. If the developer allows the manager to be assigned before the department's info has been completely filled in, we may accidentally allow an invalid state for a department object when calling the AssignmentService. Since the AssignmentService tries to save the department being assigned, we may also have created an semantic coupling between the department creation process and the AssignmentService - the developer needs to know that the AssignmentService will save the department. If they don't know this, they may try to save the same entities more than once, may try to save an invalid state, etc, etc, etc.

Unfortunately, we didn't have time to fix the problem during the training session - we had to stop the training almost immediately after we discovered this issue. I've got a few ideas running around in my head, on how to fix this, but I'm not 100% sure that I like any of them.

Possible Solutions

First and foremost, though, it's becoming rather apparent to me that we want to avoid entity persistence calls from within the domain service objects. This essentially means that the AssignmentService object would have to return the assigned department, and the 'previously assigned department' objects, so that the coordinating presenter could save them both. That seems a little odd, if you ask me.

One of my coworkers suggested that we allow the service to save the previously assigned department, since that is an self-contained operation in the method (the method loads the department, modifies it, and saves it) and then return the assigned department so that the presenter can save it. This option seems a bit better off-hand, but I'm still worried about the possible side effects of the AssignmentService saving the previously assigned department.

Questions

What are your thoughts on this situation... How would you solve the dilemmas that I'm pointing out? Is there a better design for the model that would eliminate this problem and make the department persistence more obvious, without having to 'know' when it is persisted?

Is the idea of not allowing entity persistence from a domain service object valid? Should we go with allowing the self-contained operations to persist the entity in that operation?

Or ???

Friday, July 11, 2008 7:23:46 AM (Central Standard Time, UTC-06:00)  #    Comments [3]. Trackback 
Tags: .NET | Analysis and Design | Data Access | Domain Driven Design | Model-View-Presenter | Principles and Patterns | Refactoring | User Stories

 Monday, July 07, 2008

During a TDD/BDD training session with my team, today, we wrote the following code:

public void SaveRequested()
{
    Employee employee = Department.CreateEmployee(firstName, lastName, email);
 
    if (employee == null)
        repository.Save(Department);
}

I ignored this when we first wrote it, as it was "technically correct", but later returned to this code as a point of refactoring for greater insight and expressiveness. When we came back to it, though, I started off by asking a series of questions:

  • Why would that method return a null?
  • Why would it not return a null?
  • Why is it important to not call repository.Save if the employee is null?

The code is essentially a mystery to anyone that hasn't memorized the details of the Department.CreateEmployee method. Worse yet, I can make a lot of assumptions about this code - but every one of them is going to be wrong until I can prove that they are right by reading the code in Department.CreateEmployee.

So how do we refactor this code for better insight and more expressiveness? How do we change this code so that the assumptions a reader creates in their own mind are more likely to be correct - or better yet, are irrelevant because you don't need to even care about the details of the Department.CreateEmployee method? First and foremost, you need to understand what this code is supposed to be expressing - what it's supposed to be doing and why. If you don't know, you need to ask the person that wrote it. If they don't know (or aren't around), you need to find someone that can help you determine the intended behavior. Ultimately, you may need to dig into the Department.CreateEmployee method to figure it out for yourself.

In this situation, we were trying to express some business rules from a set of acceptance criteria on a user story:

  • When creating an employee, the employee must belong to a department
  • When creating an employee, require a first name, last name, and email address

This code is a factory method on the Department object that is used to ensure these rules are satisfied. In this case, if CreateEmployee returns a null, one of these rules was violated and we should not attempt to save the Department (with the associated employee, or lack there-of). If CreateEmployee returned an employee, we satisfied the rules and we can save the Department and it's associated employees.

The code that we have in place doesn't express any of that intent, though. What we really want is code that tells us that the employee creation failed - and probably why it failed. Fortunately, the changes can be extraordinarily simple.

public void SaveRequested()
{
    EmploymentResult employmentResult = Department.Employ(firstName, lastName, email);
 
    if (employmentResult.Success)
    {
        repository.Save(Department);
    }
    else
    {
        view.DisplayError(employmentResult.FailureReason);
    }
}

UPDATE: Thanks to Martin Linkhorst for the comments, and making this code even more expressive (changing from Department.CreateEmployee to Department.Employ)

By creating an AddEmployeeResult object and supplying a few additional bits of information in it, our code became much more expressive of it's intent. We can now read the SaveRequested method and have a much better chance of knowing what it is really doing - try to create an employee and if it successfully created, then save it. Otherwise, display the failure reason.

What assumptions does your code create in the minds of the readers? Are these assumptions correct, incorrect, or unintelligible? And finally, what can you do to make your code assumption-free and/or assumption-irrelevant?

Monday, July 07, 2008 7:05:17 PM (Central Standard Time, UTC-06:00)  #    Comments [2]. Trackback 
Tags: .NET | Analysis and Design | Domain Driven Design | Model-View-Presenter | Refactoring | User Stories

 Wednesday, May 14, 2008

There are a few examples in The Toyota Way, of American manufacturing companies that were thought to be world class Lean Manufacturers. When representatives from Toyota began working with these companies, though, the result was quite a shake-up. The companies that were thought to be lean, were merely implementing some of the surface level processes of lean manufacturing. They had not realized that there was a root cause of the process that they were implementing.

The Principles, Not The Process

A coworker recently asked me to help out with a presentation on Model-View-Presenter. He had some specific questions about why we would want to use MVP vs. MVC vs. any other UI pattern. Many of the questions centered around various benefits that have been promoted by myself and others out in the developer world via blogs and articles - items such as testability, changeability, flexibility, and other "ilities". My answers to some of these questions surprised me.

Model-View-Presenter is often thought of as a journey and an end in itself. When I first started learning MVP just over a year ago, this is exactly how I saw it. I started with the intention of learning how to separate my core process from the form implementation, with the intention of being able to unit test the core process. I was working under the impression that I could find a way to implement MVP that would truly allow me to swap out my UI - to the point of changing the workflow within the UI. I had the goal in the mind, of being able to write one presenter and have it support WinForms, WebForms, Web Services, and any other client-facing API.

One year and several projects later, I have some good lessons learned. I have implemented various forms of MVP - automagic view injection, manual everything, and a lot of ideas in between. My understanding of MVP is fairly solid, and I am capable of implementing it in WinForms, WebForms, Web Services, and other client-facing API's.

What I have realized recently, is that MVP is not (or, should not be) a journey and a goal in itself. MVP, MVC, and other UI related patterns are actually an effect of other underlying principles. The underlying principles of object oriented development - such as Separation of Concerns, Single Responsibility Principle, Dependency Inversion and others - are the real cause of MVP, MVC, etc. Testability, flexibility, and the other "ilities" are merely side-effects of good design and implementation. And while Testability is a valid goal in itself, seeking it as the primary or only goal will only lead you part way down the path. You will end up like the American manufacturers that thought they were world class lean companies, only to find out that they had barely scratched the surface of lean process.

The Journey, Not The Goal

Despite the success of Toyota as the creators of lean manufacturing, they believe that they are continuously learning about lean, so they can continuously improve. Similarly, despite my many years of software development experience, I now believe that I know little about software development. I have a good knowledge of .NET and general knowledge of Object Oriented Development, but I don't know much about other paradigms like Functional Languages or Duck-Typed languages such as Ruby.

In my professional growth as a developer, I have set goals for myself at various times. Most of these goals were set with the belief that they would make me a great developer. However, I've found that every time I have reached a goal, there is an entirely new world of possibilities ahead and what I thought was a great developer was merely the beginning of a journey. I've discovered that the journey itself is often far more important than what I believed the goal to be.

I'm not advocating that you forget about setting goals and let your career happen as it will - that's a great way to become burned-out, outdated, and irrelevant. What I am advocating is that when we have a goal in mind, we set out with the understanding that the goal itself may only be a small leg on a long journey. In this case, the journey is the process of learning. The journey itself should be viewed as the long term strategy, to the point where you allow the individual goals to come and go as needed. You may not accomplish a specific set goal - but the experience gained while working toward that goal may open up opportunity for other goals to be reached easily.

Learn The Principles Via The Process

All this talk about knowing the underlying principles is great - but how can we understand the principles and philosophies without knowing the process? Unfortunately, I don't know if that's possible for most of us. I'm sure that somewhere out there, someone has read SRP, DI, SoC, and other principles, and as a result began writing code that was modeled in a manner similar to MVP (Martin Fowler, for example). For the majority of us, though, learning the principles is done by first learning the process - study the implementation of the effect to learn the cause.

Conclusions

The journey itself is how we build our experience and understanding. For most of us, that journey begins with a goal of learning a new process. Find a goal or two that you believe will help you be a better developer and learn the processes. Along the journey of reaching for this goal, always keep in mind that there is an underlying principle or philosophy that enables the process. By learning the principles and philosophies behind the process, the process itself becomes a trivial matter - an implementation of the principles and philosophies, and not a goal in itself.

Wednesday, May 14, 2008 9:37:10 AM (Central Standard Time, UTC-06:00)  #    Comments [0]. Trackback 
Tags: .NET | Agile | Lean Systems | Model-View-Presenter | Philosophy of Software | Principles and Patterns

 Monday, May 05, 2008

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.

clip_image002

I highly recommend this book, not just for these topics. It's a great book, all around.

Monday, May 05, 2008 9:11:02 AM (Central Standard Time, UTC-06:00)  #    Comments [0]. Trackback 
Tags: .NET | Agile | Model-View-Presenter | Principles and Patterns

 Thursday, March 13, 2008

A lot of people ask these questions when they first start unit testing

  • How many unit tests is too many?
  • Do I need to cover every property, every individual method, ever object, every ???

The goal of unit testing is to provide 100% test coverage. The reality of unit testing is that you want 95% or more, test coverage. There are occasions when unit testing that one last line of code is horrendously repetitious or you miss something or accidentally couple something too tightly. But wait... there's more... and those seem like lousy excuses that lead to allowing bad design in your code.

Ultra-Fine Granularity is Horrible

If you are writing your unit tests after you write your production code, or if you are writing your unit tests first but are simply going through the mechanical process switch and it doesn't really matter if you write your tests first or not, then the answer is horrible. You'll end up unit testing way more than you need to. For example, I wrote a login screen last year. This login screen has three fields and two buttons on it: Username, Password, a drop list of locations assigned to the username, a Login button and a Cancel button. How many unit tests do you think should be written for this? ... I wrote 27 unit tests to cover every possible edge case in the presenter that controlled this view. What a giant horrible mess - changing anything in that login screen was almost as bad as not having it unit tested at all (well ok... nothing is that bad)

I ended up unit testing setting an individual property, and then checking to make sure that property was stored correctly. I unit tested individual method calls with only the username set, or only the password set, or only the location set, or only whatever combination of those set. I unit tested loading the list of locations for the username, and ensuring that the location selected is valid for the user. I unit tested what would happen is an invalid location was selected or a null location was selected... every possible edge case was unit tested and it drove bad design into the application because no one wanted to go through the pain of having to change all of those unit tests at that level of granularity.

Step Up To The API

Just unit testing your code is a great way to ensure that you are writing way more unit tests than you need. Chances are, the code you are writing is not very cohesive and you will end up unit testing the read and write of individual properties rather than just unit testing the business value (process) that actually reads / writes the individual properties. That is to say, your unit tests should be written at one or two steps above ultra-fine granularity. Don't test the individual properties, test that API that you want to call, that has business value.

So, how do you account for 100% code coverage if you are not unit testing the properties and all of the edge cases?

Never write code that you don't need, right now. If you are writing a unit test and the test or the implementation needs a property, then you create that property for that unit test at that time. This does not mean that you write a bunch of get / set property unit tests, just so you can unit test the properties. This means that you specify the business value API in your unit test, and by virtue of having business value, you will likely have various properties associated with the classes in that API. The same is true for edge cases - if the business value of the unit test does not handle the edge cases, then there are no edge cases. Only when you have business value specifying an edge case, do you need to write a unit test for the edge case and possibly modify code to handle the edge case.

Ok, then what happens if your code changes and you don't call that property in the original unit test, anymore?

Never leave dead code in your system. Ever. Period. End of discussion. If you change your unit tests because the design of the object(s) change, and you are no longer using a property - delete the property! If you delete it and you find that you can't compile the code any longer because other parts of the system need that property, then you need to evaluate whether or not that property is really providing value to those other places vs. changing those other places to match the new design.

Test First vs. Test After

A big part of figuring out how many unit tests you need is understanding the functionality of the system. You should be writing a unit test for every functional point of the code, achieving 100% code coverage. The problem with the original question of how many unit tests to write, though, is that there is a hidden assumption in that question:

"I wrote my code, now how many tests do I need, to cover it correctly?"

This question is an underlying problem in Unit Testing and simple Test First development. If you are just unit testing your existing code or only going through the mechanical process switch of writing a unit test first, but not really using the test to drive your design, then you are likely not going to see some of the major benefits of Test Driven DESIGN / Development: not writing code you don't need, and creating the API that you want to call instead of the API coming together haphazardly as a bi-product of writing code first.

When you take the step up to unit testing the API, it becomes more apparent that you really want to specify the API before you write it. If you specify the API before you write it, then you are one step closer to true Test Driven Development. Don't expect the test to design your code for you. Use the test to flesh out your design before you write any code.

Test Driven DESIGN / Development

Would you rather:

Write 50+ lines of code into your model, then write a unit test that shows an ugly API causing you to go back to the code and re-write it in the hopes that it will produce a better API, most likely repeating this process once or twice until you get frustrated with changing your code because it takes so long

or

Write 5 lines of unit test code, specifying the API that you want, realizing that it's not going to work and changing 2 or lines of that test, going through this cycle 5 or 6 times until you have the API that you really do want to call; then implementing the API in the 50+ lines of code and being done with it

I'll take #2. I don't like rewriting large chunks of code. Rewriting 2 or 3 lines of code is easy - I'll do that any minute of any day. Chances are, if you are willing to write the correct number of unit tests by specifying the higher level API in your unit tests, you will gravitate toward designing your API in your unit tests.

TDD Misconception:

TDD is NOT a design tool. It is not "the answer". Is will not design your application for you. It will not solve your problems for you. If you don't know how to design software, then you need to get some training on design patterns, loose coupling through single responsibility and separation of concerns, and various other core foundations of good Object Oriented Development.

In reality, Test Driven Development is just an easier way of saying this:

"Design your API in the context of a unit test, so that you have your API implementation covered by unit tests before you even write the implementation."

Conclusions:

In the end, we can answer the original questions from this post by re-stating Test Driven Development as a software development guideline:

"Design via code, unit testing 100% as you go."

Thursday, March 13, 2008 1:45:25 PM (Central Standard Time, UTC-06:00)  #    Comments [0]. Trackback 
Tags: .NET | Agile | Model-View-Presenter | Test Driven Development | Unit Testing

 Saturday, March 08, 2008

(reposting a few items from my previous blog to my new one)

...

I follow a lot of Agile Engineering Practices, at this point in my career: Test Driven Development, Domain Driven Design, Single Responsibility Principal, Separation of Concerns, Inversion of Control, Dependency Injection, etc. To get to this point, I've basically taught myself - I read blogs, books, example code, and work my butt off to make sure I know what I'm talking about so that I can stay a few steps ahead of my team(s). In all this effort, learning, failure, success and otherwise, I've learned a few key things about software development as it relates to the Agile world.

  1. Unit Testing is an absolute must, even if you don't do Agile
  2. Unit Testing is not Test Driven Development
  3. Test Driven Development is Agile Engineering, not Agile Process
  4. Agile Engineering alone, does not make Agile software development

1. Unit Testing is an Absolute Must

Whether or not you are trying to do any sort of agile software development, or even test driven development; if you do not unit test your code, you are opening your code up for breaking unexpectedly. In the worst case scenario, you are preventing your code base from being able to change with the needs of the business and causing crippling problems by not keeping your code separated appropriately.

Think about the goals of object oriented development: well encapsulated, highly cohesive and low coupled objects that can easily be re-used. These goals are very high, very lofty and they may be pie-in-the-sky dreams for some developers. So how do you achieve such goals? Single Responsibility Principle, Separation of Concerns, and Inversion of Control. All of these practices are much closer to the implementation level of code - they tell us to keep our code as small as possible; only write the code that needs to be written, in this class. When you see code that does not quite fit into the class you are currently writing, you look for a better place to put that code. This means that you need to split data access out of your business processing, user interface out of your business processing, and often times you will need to split your business process out into multiple classes.

The hard part is, single responsibility, separation of concerns, etc. are not one-time coding practices per class. They are processes that require a continuous series of design, redesign, and refactoring of your code. Don't assume that an object you write, now, will be the same 10 minutes or 10 days from now. If you find yourself in a situation where two objects are very similar, you may have an opportunity to create a better abstraction that can fit both scenarios - whether it becomes a single object, a template pattern, strategy pattern, or other solution.

If you are continuously redesigning your code to fit the business needs, and you are continuously separating your code into more and more classes, creating the high cohesion and loose coupling of true OOD; how do you manage the process and ensure that you are not breaking your application as you go? The answer is simple: Unit Testing. If you are not unit testing your application, then you do not know if the application works until you actually run it and try to use it. If your application is small - one or two classes, one or two screens - this may be reasonable and you may just run the application in it's entirety to see if it works. If your application is medium to large, though - one or two hundred or thousand classes and screens - you will quickly find yourself in a situation where you cannot expect to run the entire application in a reasonable amount of time and you are likely to miss some of the features and functionality if you do try to run it all. The only reasonable way to ensure that your code still works, is to have an automated test suite that can be executed on a regular basis. The easiest way to achieve this, at a very low level, is to do Unit Testing and ensure that your code is 100% covered with the unit tests. By unit testing every line of code in your system, you will have a rapid feedback tool that tells you when you break something. This rapid feedback will allow you to quickly fix anything that is broken, compared to the "run it and see" process.

With all that being said, it's very important to understand ...

2. Unit Testing is not Test Driven Development

Test Driven Development involves Unit Testing. In fact, Test Driven Development doesn't exist without Unit Tests. However, just because you are Unit Testing, that does not mean that you are doing Test Driven Development. When it comes down to it, Unit Testing is all about insurance - make sure your code is covered because change will happen, and change breaks things. Test Driven Development, on the other hand, is all about software design; writing your unit tests first, to drive the design of the software that you are really writing. TDD is not just Unit Testing; TDD is not just Test-First-Development, either. True TDD is the practice of designing the APIs in your code, by writing out the API that you want to see before you try and implement it.

To do any sort of software development, you need to have some basic functional requirements - what is this software going to do, and why? When you start breaking these requirements down into pieces that are small enough to implement, you can begin to see how the software will look - what classes will be there, what processes will run, and how it all fits together.

When you have good requirements it's easy for a developer to see some of the low level code implementation - using whatever design pattern to create these classes, with this code underneath so that this feature can call into them and do something... TDD, though, wants you to step back a few paces. Don't worry about the low level implementation details, yet. Let's focus on how you want to call into the implementation - what is the API that you want to call, in order to do these processes. Rather than looking at a requirement and saying that you don't know what the API will look like because they have not implemented any of the details, TDD forces you to think backwards - you don't know what the implementation is, but here is the API that you want to call.

3. TDD is Agile Engineering Only

There is a huge disconnect from Test Driven Development, to a true Agile software process. Agile Engineering is a great set of practices that every developer should adopt. This includes Test Driven Development, Domain Driven Design, even Pair Programming. However, these engineering practices can and do fit into any software development lifecycle: RUP, Waterfall, iterative waterfall, and everything else you can image, can all have Agile Engineering practices put in place. I would go so far as to say that we shouldn't even call it Agile Engineering - rather, we should just call these good software engineering practices.

To illustrate this - look at the projects that I work on. They are all standard waterfall type projects. We've implemented these engineering practices in every project that I have lead, for the last 2 years, though.

4. Agile Engineering is not Agile Software Development

Real Agile software development is more than just good engineering practices. It encompasses the entire software development lifecycle - from requirements gathering to requirements definition, continuous discussions with the customer to elaborate on those requirements, discussions with the customer to determine what requirements go into what release and iteration, and more discussions with the client to ensure that the software is heading down the path that they actually want. Have you noticed a trend, here? There's a lot of constant, continuous discussion with the customer in real Agile development. This is an absolute must, in Agile work. If you don't stay in regular communications - as in daily, if not more often - then you don't know if the customer is getting what they want.

I've worked on various projects that do some of these - short iterations, continuous integration for unit testing, regular releases to the customer, even pair programming; but I have never worked on a true agile project. It's just not possible to do true agile software development if you don't have complete buy-in and ownership from the entire team - from the customer down to the individual developer. I dream of the day that I'll have a chance to work in an environment like this.

The Future of Agile

Agile engineering, Agile process... how does this all tie together? Where is the knowledge moving and how do we get there? Personally, I'm on board with Behavior Driven Development group. Imagine taking every aspect of Agile, and wrapping it up into one very cohesive set of processes and practices. I get all kinds of excited just thinking about it.

Saturday, March 08, 2008 3:26:08 PM (Central Standard Time, UTC-06:00)  #    Comments [0]. Trackback 
Tags: .NET | Agile | Model-View-Presenter | Unit Testing

Navigation
About Me
View Derick Bailey's profile on LinkedIn

Send mail to the author(s) Contact Me
Archive
<August 2008>
SunMonTueWedThuFriSat
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2008
Derick Bailey
Sign In
Statistics
Total Posts: 65
This Year: 65
This Month: 4
This Week: 0
Comments: 25
Themes
Pick a theme:
All Content © 2008, Derick Bailey
DasBlog theme 'Business' created by Christoph De Baene (delarou)