views:

158

answers:

3

I am trying to grasp the entire TDD methodology and as such, I don’t really know how to present this as a nice concise question so here is the long drawn out version. I seem to be experiencing a gap between the bowling (Martin), money (Feathers), and other similar game/simple examples and a fully functioning Enterprise app.

I am trying to figure out if I'm missing something like the concept of feature which as I understand it is something that adds business value or how to properly separate concerns when doing TDD and how each will then apply to the other. If that definition of what a feature is is a hard rule then things like logging and error reporting are not features. Does that mean TDD does not provide a means for logging and notifying?

Not trying to start any wars, I am pretty sure that is not the case so I then tell myself that the 'business value' must switch mid app from the customers business value to the businesses(the creator of the app) business value.

So I then try to switch it up like this common example From: As a math idiot When I enter 2, press add, enter 2, then press = I want 4 returned.

To: As an systems analyst monitoring the system When a user enters a function that results in an unhandled error I want the current state of the application, the exception thrown and stack trace entered into the log and send an email to the systems analyst distribution list.

And then to: As a business analyst ensuring all customers orders get processed When a user submits an electronic order and routing or accounting information does not validate I want the invalid accounting and routing information entered into the log and emailed along with the order file attached to the business analyst user group. unless the issue is because the database could not be reached to lookup the customer info due to network issues enter "database could not be reached to lookup the customer info due to network issues" into the log and send an email with the error message to the systems analyst distribution list.

Then that starts getting expanded into something that I think would be totally unacceptable: As a electronic order completion check When an order is received I want to check the x12 file is translated into a flat file and if it fails validation or translation log and email the error the order information and status is extracted and loaded to the database the flat file is sent to the queue to the as400 and the status is updated to the database the as400 sends an acknowledgement that they received the order and the status is updated to the database the as400 sends a flatfile confirmation and the status is updated to the database the confirmation is translated to an x12 and the status is updated to the database the x12 confirmation is routed appropriately and the status is updated to the database the confirmation is sent to the customer and the status is updated to the database if the x12 contains invalid data log the error, send an email and if the flat file is not pulled of the queue in 2 minutes log the error, send an email etc with n to the x power of possible error scenarios.

Even if you broke each into its own 'feature' you still have issues of logging, notifying systems analyst that an application threw an exception or a network error occurred or database not found etc. or business group that an order with an unrecognized account number was encountered etc. Adding any one of these into the class, as a method, attribute etc seems to violate the Single Responsibility principle. About that time things start spinning, I get dizzy, shortness of breath and heart palpitations

So, since it is so confusing to me that I am at a loss as to how to even pose this as an articulate question, I will try to sum it up like this.

How do you determine when/where and how to break these things down and separate them? It's easy to say break them down into the smallest piece that offers business value but when you can't have one piece without a number of other pieces what is the 'real' answer? All of that doesn't fit on one sticky.

I am open to answers that include more books, tutorials, video but I think if there were perhaps some real world applications that account for these types of things that adhere to the agile & TDD principles that would probably provide the most value? Admittedly I am relatively new to this but I've gone through the Martin/Feathers/Osherove books, I've seen a number of katas on tic-tac-toe, bowling, prime numbers etc but there’s no logging, no error reporting none of that kind of 'real world' stuff.


Let me try something else.

I get a file from the mainframe via ftp listing the orders to be placed with our suppliers, this file is called the summary file. I check for this file every 5 minutes. When there is a file I parse it then check to ensure that we received every order listed in this summaryfile via MQ. As a double check I also check for the existence of orders because if a summary file fails to be received we cannot ensure we received all the orders. With that being said does the following seem like I'm headed in the right direction?

Feature: Check for the presence of a summary file
  In order to verify all orders were sent through MQ from the mainframe
  a summary file must be found to determine the expected orders.

  Scenario: A summary file has not been sent
    Given a summary file does not exist
    When I check for the existence of a file
    Then I should sleep for 5 minutes

  Scenario: A summary file has been sent
    Given a summary file does exist
    When I check for the existence of a file
    Then I should validate the summary file

Feature: Validate the summary file
  In order to process a summary file
  summary file must be valid

  Scenario: A valid summary file exists
    Given a valid summary file
    When I validate the summary file
    Then I should upload the order details to the order details DB.

  Scenario: An invalid summary file exists
    Given a invalid summary file
    When I validate the summary file
    Then I should log the errors encountered
    And email the erroneous file to the analyst email group

Repeat that again replacing summary with order. That is what I came up with.

+3  A: 

You definitely can't jump straight to your most advanced story (x12 file translation, yikes) - when you're dealing with an immature system, you have to decompose huge complicated features into comprehensible stories that you can estimate and deliver within an iteration.

I'll start with your second user story, which I hope will be sufficient:

As an systems analyst monitoring the system When a user enters a function that results in an unhandled error I want the current state of the application, the exception thrown and stack trace entered into the log and send an email to the systems analyst distribution list.

I'd begin by breaking this down further into two user stories:

1) As an systems analyst monitoring the system, when a user enters a function that results in an unhandled error I want the current state of the application, the exception thrown and stack trace entered into a log so that I can diagnose what happened and get a head start of correcting the problem.

2) As a system analyst monitoring the system, whenever there is an unhandled error, I want to be notified by email so that I'm more likely to address issues in a timely fashion.

You may not even need to articulate the first one as a user story in its own right, since modern development platforms (and their open-source communities) make logging trivial.

Say you get the business to sign off on user story number two. If you're not using a library to handle the emailing for you, you can immediately start practicing test-driven development just by considering what you want to do in your global error handler (which is already logging unhandled exceptions). It needs to:

  • Get one or more email address for the recipients list.
  • Get a subject line.
  • Get any additional content.
  • Send the mail via whatever mechanism you're using.

Start thinking about the classes that will do those things, stub out the interfaces, and write some tests.

Your further elaborations on the requirements are all additional features. Your next requirement will entail writing different kinds of information to the log. After that you need to be able to add attachments to the email. And on it goes. Each story may involve multiple classes, so the single responsibility principle shouldn't be an obstacle.

Jeff Sternal
+1 "you have to decompose huge complicated features into comprehensible stories" ...and that's a GOOD thing. That's design.
Carl Manaster
Carl-Thanks. I agree, I'm not questioning the validity of BDD. I understand it's value which is why I want to get a handle on it and it's relationship to TDD.
Phil Langeberg
Jeff-Re: "You may not even need to articulate the first one..." are you saying that you don't account for things if they are below a certain complexity threshold? Logging has to be incorporated. It doesn't just happen other then exceptions in EventViewr but that is not enough. So I am thinking that is a feature(bdd) and since *I* need to add it and log certain conditions I would think I need to also test for it. Am I off track there?
Phil Langeberg
@Phil, no you're not off-track at all. If it's going to take an observable amount of time to implement something or if it needs explicit testing, you ought to make it a feature. All I was trying to communicate is the sense that once you've successfully deployed several applications with log4j / log4net (for example), it *may* not be necessary to articulate it as an explicit feature - at some point it just becomes something you can take for granted, but certainly not the first time.
Jeff Sternal
Ok, gotcha, thanks Jeff!
Phil Langeberg
+6  A: 

You are getting off track by thinking that:"...you can't have one piece without a number of other pieces..."

Story splitting is a skill. It takes practice and it can be a difficult to become good at. This page explains the concept and gives links to resources about story splitting.

Here's one of your ideas that you were having trouble breaking up:

As a business analyst ensuring all customers orders get processed When a user submits an electronic order and routing or accounting information does not validate I want the invalid accounting and routing information entered into the log and emailed along with the order file attached to the business analyst user group. unless the issue is because the database could not be reached to lookup the customer info due to network issues enter "database could not be reached to lookup the customer info due to network issues" into the log and send an email with the error message to the systems analyst distribution list.

I see at least 4 stories in that paragraph:

  1. As a BA, during order entry failure due to invalid account and routing information, I want account and routing information to be emailed to the BA group with the order file so that someone knows to get correct information and re-enter the order.

  2. As a BA, during order entry failure due to invalid account and routing information, I want account and routing information entered into the log so that e have a permanent record of invalid information.

  3. As a BA, during order entry failure due to "can't reach database" , I want the error message "database could not be reached to lookup the customer info due to network issues" emailed to the SA list so that database/network issues can be analyzed and improved.

  4. As a BA, during order entry failure due to "can't reach database" , I want the error message "database could not be reached to lookup the customer info due to network issues" written to the log so that we have a permanent record of database/network issues.

And if your team is doing TDD well, it shouldn't be too difficult to implement each of those stories separately. Your code will be guarded with tests so that if someone working on card 4 breaks card 1's functionality, hopefully a test will catch it.

JeffH
+1  A: 

I've done a bit of work around this, so here are some things I wrote which might help:

Breaking down visions into features, stories, scenarios and code:

http://www.infoq.com/articles/pulling-power

Splitting stories:

http://lizkeogh.com/2008/09/11/splitting-up-stories/

Handling technical stories (logging, etc.):

http://lizkeogh.com/2008/09/10/feature-injection-and-handling-technical-stories/

All feedback welcome.

Lunivore
Now this seems to be what I was looking for.I think either my mindset really needs a hard reboot or maybe BDD just doesn't fit the enterprise developer that just builds apps and reports to support the processes as apposed to the one that creates the customer facing application.
Phil Langeberg
Well, there's always a customer-facing part of the application - it's just that sometimes another system is the customer. Sometimes it's an internal user. Sometimes it's the accounts department. Actually working out who the user of the system is, let alone the core stakeholder, can be half the work. Good luck!
Lunivore