Jon Kruger -
  • About Me
  • Blog
  • Resume
  • Values
  • Presentations
About Me
Blog
Resume
Values
Presentations
  • About Me
  • Blog
  • Resume
  • Values
  • Presentations
Jon Kruger
Agile

Challenging assumptions

There are many ideas and principles in software development that we believe to be true and often are non-negotiable for us.

Here’s a challenge for you – challenge the assumptions that you have. What if they’re not true?

For example (not that I believe any of this, just throwing it out there):

  • What if TDD is a waste of time?
  • What if estimating in hours is better than estimating in story points?
  • What if pair programming is an inefficient use of your development team?
  • What if pair programming is the most efficient use of your development team?
  • What if a relational database is not the best way to store data?
  • What would happen if you developed a given feature and put it into production without QA testing it at all?
  • What if sitting in a co-located environment is less valuable than being able to sit in a cube with less distractions?

Like I said, I don’t necessarily believe anything I just said. I’m just trying to make your blood pressure rise a little bit when you think about some of your core principles being false.

The reason I think that this is a valuable exercise is that it forces you to think outside the box and honestly evaluate the way you do things. Most of our core principles depend on the situation. That’s why I get frustrated when people take a prescriptive process like Scrum and say that you have to follow the Scrum rules exactly as they’re laid out or you’re introducing “scrum-buts” into the process. If you haven’t adapted your process to fit your team and your environment, that would be a red flag to me that you might not understand your process or that your not trying hard enough to find ways to improve.

I don’t want to ever stop improving. I’m not going to be naive and think that I have everything figured out. At one point I thought that Windows Forms
data binding was awesome, and after that project was over, I realized that that was the totally wrong approach.

I really took to heart a quote that someone said at CodeMash a couple years ago, “If you don’t ever fail, you’re not trying hard enough.” It’s OK to fail, and when you do, you’ll learn something from it and come out a better person. But if you’re never willing to fail or too scared to consider that maybe your way is not the best way, you’re not going to take that next important step.

May 7, 2012by Jon Kruger
Uncategorized

My new marketing material… er, resume

I’ve talked about it for a long time, but I finally refactored my resume. I read a lot of resumes, and most of the time they annoy me because I get annoyed by the way that it’s written, even if the candidate is qualified. Yet my resume was more or less the same thing, so I figured I needed to take my own advice and do something about it. Here’s the thought process that led me to the end result (which you can see here).

Selling services

Go to any tech conference and you get the big bag of vendor pamphlets trying to sell you their product or consulting services. These papers are very colorful and attractive and professional looking. What you don’t find is a black and white piece of paper with a list of 50 bullet points that enumerates their achievements.

We really are no different from those companies. We are trying to sell our services to potential employers or clients. So why aren’t we making our resumes look more like marketing material?

When I read a resume, I pretty much know whether I want to hire someone or not. The interview is just there to confirm my assumptions and potentially break the tie between two candidates. So if your resume is poorly done, you’re already behind the 8-ball before I even get to talk to you.

Answer the right question

Most resumes are answering the wrong question. The question to answer is not, “What did you do?”, the question is, “What sets you apart from the other candidates?”, or, “What experience that you have that can help our team/company improve?”

If you’re a QA person, don’t put “Entered bugs into bug tracking system” on your resume. That is something you did, true, but (a) I assume that a QA person uses a bug tracking system and (b) it doesn’t tell me anything about how you can help my team.

More is less

The way I see it, there are two kinds of people reading your resume. There are those who are briefly glancing at it to decide if they want to learn more. There are those who want to learn more and/or interview you and they will read more of it. No one ever reads it all.

With that in mind, only put things on there that you want someone to read. I know that sounds obvious, but apparently people are not good at it. You want to make it easy for the people glancing over your resume to want to read more, and you want to make it easy for the people doing the interview to find what’s important.

Everything on your resume has a value — but that value can be negative. When I read a resume before an interview, I read through the last couple work assignments and cross out everything I read that doesn’t add value. Then I’m left with the statements that have value. I would’ve much rather just read the good stuff without having the black out all of the cruft.

Also, I don’t really care what you did in 2003. Chances are you were using a technology that is not the technology being used in the job you’re applying for. Just tell me the things that have relevance, either because it’s a similar skill to what the team needs or because it’s something that you did relatively recently.

No more than 2 pages

I’ve never found anything meaningful on page 3 of a resume, so don’t have one. You don’t have to list every place you’ve worked and you don’t have to list every single thing that you did there. This is particularly challenging for consultants because we tend to move from project to project. Remember, you just have to give me enough information to make me want to work with you, you don’t have to tell me your life story.

Write it so someone would want to hire you for the job you want

If I think about my ideal project, it would probably involve Agile, TDD, either .NET or Ruby on Rails, and working in a team environment with people who care about their craft. I tried to make my resume reflect that. On the first page, I highlight how I’ve led Agile projects, I do TDD training and like unit testing and acceptance testing, and how I’ve used Ruby on Rails and ASP.NET MVC, which is my .NET tool of choice. I put a link to my GitHub account because people who tend to think like me like to see that developers hack on stuff and like to be able to look at actual code they’ve written. I also have a link to my blog so that people can learn more about the things I like (and don’t like). While I don’t claim to be great at design, I’ve tried to add some flair so that people can see that I am creative and am capable of thinking outside the box, which I think is an important quality for a software developer.

I actually went through this process when I created the first page of my resume. I made sure I highlighted all of the important stuff that I mentioned and left off everything that was not on that list. There’s room on page 2 for the other less important details.

Things I don’t want to do are nowhere to be found on either page. I’ve done C++, WebForms, and TFS build server administration. I really don’t want to do those things again if I can help it, so I’m not going to list those things anywhere. The people hiring someone for my ideal job wouldn’t care about those things.

Recap

You are selling yourself. There is nothing that mandates that your resume be a sea of bullet points or that you must list everything you’ve ever done. You are much smarter than that, so be creative and come up with your own marketing material. Then walk into the interview knowing that they have the important information they need to want to give you the job.

March 26, 2012by Jon Kruger
Agile

Writing requirements to match your code

I’ve always said that software development is a series of translations — that we need to incrementally translate business processes to business requirements to acceptance criteria to test plans to tests to code to working software. This is why we write acceptance criteria in the Given/When/Then syntax — it’s a common language that developers, BAs, testers, and business people can use to make sure that we’re all speaking the same language. These kinds of requirements define what the system is supposed to do for the business.

All this is good, but there still are problems. Let’s say that your BA writes some requirements and you implement a feature. Several months later, you get a new requirement to change that code, or someone asks you what the code does for a certain feature. How do you find the code for that feature?

Or maybe you have some common validations that happen many times throughout the application. Are your BAs copying and pasting the rules for that validation over and over in the requirements documents?

What seems to be missing here is another layer of translation. We have too big of a jump from our typical business requirements to our code, and no way to map the two to each other. The acceptance criteria tell us what the code should do, but nothing tells us how to do it.

On my current project, they’ve come up with an ingenious way to solve this problem. (I have to preface all of this by saying that none of this was my idea and I can take zero credit for it. They were doing it long before I joined the team.)

Our system does transaction processing with incredibly complicated business rules. All operations are written as command classes and workflow classes (which are a series of commands).

Our requirements are structured the exact same way. In the requirements we have commands and workflows that are named the same as the classes in the code.

Example

Let’s say I’m building an order processing system. Here’s how we might break it all down.

High-level business requirements

When an order is processed, the order total is sum of the cost of the products + tax + shipping. Save the order information and the total price to the database.

Tax depends on where the order is being shipped:
Ohio – 7%
Michigan – 6.5%
Any other state – 0%

Shipping:
If sum of the cost of the products >= 25, shipping is free, otherwise $5.

System requirements

Workflow: Process Order
1. CalculatePriceOfProducts
2. CalculateTax
3. CalculateShipping
4. SaveProcessedOrder

Command: CalculatePriceOfProducts
Total Price = sum of price of each product on the order

Command: CalculateTax
Tax is calculated based on state the order is being shipped to. Can ship to US states only (including DC).
Ohio – 7%
Michigan – 6.5%
Any other state – 0%

Command: CalculateShipping
If total price of products in the order >= 25, shipping = $0
Otherwise, shipping = $5.

Command: SaveProcessedOrder
Save the following information to the database:
– Products in the order (save current price in case the price of a product changes after the order has been processed)
– Tax amount
– Shipping amount

Acceptance tests

We’ll write unit tests for each command. There are 153 different combinations of shipping (>25, =25, <25) and tax (51 states), so our unit tests will cover all of the permutations. We’ll write acceptance tests to cover some of the most likely scenarios.

Scenario: multiple products with total < 25, shipped to Ohio 
    Given an order with the following products:
        | Product  | Price | 
        | Mouse    | 4.00  |
        | Keyboard | 20.99 |
    And the order is being shipped to Ohio
    When I process the order
    Then the tax should be $1.75
    And the shipping should be $5.00
    And the total price should be $31.74

Scenario: one product with total = 25, shipped to Michigan 
    Given an order with the following products:
        | Product | Price | 
        | Mouse   | 25.00 |
    And the order is being shipped to Michigan
    When I process the order
    Then the tax should be $1.63
    And the shipping should be $0.00
    And the total price should be $26.63

Scenario: one product with total > 25, shipped to Indiana 
    Given an order with the following products:
        | Product | Price | 
        | Mouse   | 25.01 |
    And the order is being shipped to Indiana
    When I process the order
    Then the tax should be $0.00
    And the shipping should be $0.00
    And the total price should be $25.01

Why this is awesome

This has made everything so much easier for everyone. Developers and system analysts can easily communicate because we speak the same language. When we get new requirements that change existing code, the systems analysts even specify which commands and workflows we need to change. Now I know exactly where I need to go to change code without having to do any research!

Duplication is bad in code and it’s bad in requirements. When a new workflow needs to be created, they can reference existing commands without having to copy and paste requirements. The commands and workflows are in a big Word document with links so that I can easily navigate around the document.

Because all of the commands and workflows are outlined before we write the code, most of our design work is done for us. I know what classes I need to create. I know the specific things that each command needs to do, and I can easily unit test them. We have some older code in our application from before they switched to writing requirements in the command pattern. These classes tend to be too big and they’re much harder to decipher, partially because I can’t easily figure out how they map to the requirements. Every time we encounter one of these, we want to refactor it to match the requirements.

Estimation has become a lot easier. I can look at each command in a workflow and get a sense of how hard each one is (or which commands are existing commands that I can reuse), and I already know how I’m going to design my code for the most part.

Keeping requirements up to date is a challenge on any project, but this has helped us do a pretty good job of it. But when you have well structured requirements that don’t have stuff copied and pasted all over the place and you can easily compare a class and a section of the requirements with the same name, updating requirements becomes a lot easier.

The command pattern is a good fit for our application, but your app might not lend itself to the command pattern as well as ours. That’s fine, see if you can come up with another pattern if you want. But sit down as early as possible and see if you can come up with a way to structure your requirements and code using the same patterns.

As you can see in the example, we still have acceptance criteria in the Given/When/Then format. The acceptance criteria help define what the system is supposed to do and how we’re going to test it. The business requirements that we write in the command pattern define how the system is going to accomplish those goals. This method has filled that translation gap between business-focused requirements and code and has had a huge impact on our project.

February 28, 2012by Jon Kruger
Agile, QA

Writing requirements with acceptance criteria

Ah, requirements. Gathering requirements is really hard. I’m not a BA, but like most developers, we’ve had to gather requirements at some point. You have to meet with users who might not have enough time for you or might not be able to make up their mind. Then you have to take their ideas and understand the business problem enough so that you can write up requirements. You have to try and find the balance between giving the users what they’re asking for and giving the users what they really need but don’t know it yet. It’s a fine line for sure.

I’m not going to sit here and bash BAs for lousy requirements. I’ve been the one who wrote the requirements only to have a developer mock the requirements (they probably didn’t know that I wrote them or that I was listening, but that’s neither here nor there). I tried really hard and I thought I did a good job. But nevertheless, there were things that I didn’t really think of that the other developers thought of.

Since we know that requirements gathering is hard, what can we do to make sure that we don’t end up with ambiguous requirements, we make it easy to test, and we make sure that we actually give the users what they want?

The key is that we need to find common language that people in different roles can agree on so that we can all be on the same page. Users, BAs, QAs, and developers all think differently and speak different languages. So we need to find a better way to communicate and a better way to write requirements.

The way that we do this is using the Gherkin language, or Given/When/Then format. This goes something like this:

Feature: Transfer money between accounts
    As a user
    I want to be able to transfer money between active checking accounts
    So that I don't overdraw my account
    And I don't have to go to the bank to make the transfer

Scenario: Transfer positive amount
    Given a checking account "A" that has $100
    And a checking account "B" that has $50
    When I transfer $10 from account "A" to account "B"
    Then the transfer should be successful
    Then account "A" should have $90 
    And account "B" should have $60

At the top of the file we have background information about what the user wants to do and why they want to do it. Then we go step by step and identify all of the scenarios in the Given/When/Then syntax.

So what’s the big deal? Aren’t I just writing the same thing in another format? Yes, but the good thing about the Given/When/Then format is that it helps you find the holes in your requirements and think of all the details and edge cases. If you’re requirements are more in paragraph form with some bullet points, it’s really easy to miss things, even if you’re smart and trying to do a good job.

Essentially what we’re doing here is writing test scripts. As a developer, I want to know how QA is going to test my code. Not only that, I can take these scenarios and automate these tests with acceptance testing tools like SpecFlow or Cucumber or with plain old integration tests or unit tests.

What we did here was establish a common language between everyone involved. This will help BAs think in a detailed, logical way that ensures that they don’t miss things in the requirements. This will help developers because they won’t have to write code to hit a moving target or get stuck waiting for answers to requirements questions. This will help testers because all of their test plans get written up front before the development happens, so they don’t get stuck trying to figure everything out on their own after it’s been developed (and the BAs do a lot of their work because they write their test plans for them). Not only that, this gives the development team the chance to automate the tests. This will help users because once we get the Given/When/Thens done, we can take that to the user and ask them to confirm that we’re building the right thing. We’re still using their terminology, and the syntax will help them think of cases that maybe they hadn’t thought of initially.

If you write your requirements this way, if you get everyone involved up front, and if you write your code to make the tests pass, you should be completely done when you finish development. Because you wrote code against detailed requirements that were written without ambiguity in a manner that makes it easy to write tests for it, you should have no bugs (or at least very very few bugs). QA won’t have to spend lots of time afterwards trying to figure out how to test the feature. And hopefully the users are getting what they want.

February 27, 2012by Jon Kruger
TDD, unit testing

When unit tests are better than acceptance tests

In my last post, I talked about how acceptance tests can be more important than unit tests. But clearly there is another side of the coin.

The conventional wisdom is that you should have more unit tests than acceptance tests. This is how I’ve done it in the past (on pretty much every project other than my current one).

A common scenario is a web application that uses an ORM for data access with as few stored procedures as possible. Because I’m using an ORM, my data layer has very little code. I’ll probably write a few basic unit tests and integration tests to test what data layer I have, and I’ll write integration tests to test the stored procs that I have (usually only for queries that need custom SQL).

My data layer primarily contains a really simple repository class that lets me do CRUD operations and get sort of IQueryable so that I can write LINQ queries. (If you’re using Rails, you don’t have to build any of that because it’s all there for you out of the box.) I don’t want my repository methods to have any concept of business logic or specific LINQ queries. Those belong in the business layer. The exception would be any stored procs that I have to have. I’m want to have a really thin data access layer and a fat business layer (yet another reason to use an ORM instead of having lots of SQL code in stored procs).

The business layer is going to contain the meat of the code. This is where I’m going to have a lot of unit tests. Because I kept my data layer so simple, I’m not going to have as many classes to stub out, and when I do, I’m stubbing out simple methods like Save() and Get(), which have no business logic in them.

I also have controllers, which take information from the business layer and return some sort of view model. I’ll write unit tests that verify that that translation happens correctly.

If I have some hardcore JavaScript, I’ll write unit tests for that. If it’s really simple stuff like, “when this radio button is clicked, disable this text box”, I don’t write tests for that. But when you build something that has more logic, you’ll want to test it.

At this point, I’ve tested pretty much everything very extensively. I could add some acceptance tests, which could help me communicate with the business and automate some QA testing. But at the same time, I’ve been on projects where I had excellent unit test coverage and no acceptance tests and it came out just fine. Now, that project was a two-person project with no QA team, so we just trusted our coding abilities and accepted the risk and things came out just fine. The point of saying this is not to say that you should fire your QA team, it just an example of how you can structure your code in a way that will allow you to unit test the code and get it right pretty much all the time.

This is just one example of one project. Your project might be different, with a different architecture, a different team, and a different business. You need to figure out what works best for you.

February 21, 2012by Jon Kruger
Agile, TDD, unit testing

When acceptance tests are better than unit tests

The conventional wisdom on TDD and testing is that unit tests are the preferred kind of tests to write. They help you design your code, and they run fast. Integration tests and acceptance tests are important too, but you should have far fewer of these. They exist so that you can have some end to end tests and to help test things that you can’t easily test with a unit test.

The Automated Testing TriangleYou may have also seen the automated testing triangle diagram, which illustrates how you should have more unit tests than the other kinds of tests and how the unit tests are the foundation of your test suite.

The implication of all of these diagrams and ideas is that this is the best way to do it on every project. But is that true?

I would argue that there are situations where integration tests and acceptance tests are more important than unit tests.

But wait, you say, aren’t you the guy who is always speaking about TDD and the value of unit tests?!? Was that all a lie?

Once again, the correct answer is… it depends!

Take my current project for example. We are writing web services that do back end transaction processing. Our system is very configurable, so we can make the system work very differently based on some configuration tables in the database, and different configurations are used for different types of transactions.

We have a very well defined framework. Even before I start coding a feature, I know what classes I need to create because they were defined up front with a systems analyst. So I’m not really going to get any benefit from TDD designing my code because the design work is already done.

Because the system is so configurable, we can handle new kinds of transactions by inserting new configurations into the database. There is very little coding involved. Sure, I could write unit tests for the configurable components of the application, but unit tests can’t tell me if the system works correctly for my new configuration. The best way to do that is with acceptance tests.

Not only is our framework well defined, we follow the SOLID principles and have lots of small classes that work together. I could write unit tests for all of the small classes, and in some cases I do, but in
most cases I find that the unit tests aren’t testing very much. Not only that, they tend to have lots of stubs and mocks, which makes the unit tests very brittle. Usually the integration tests and acceptance tests are more brittle, in our case, it seems to be the other way around. Nothing seems like a waste of time more than updating an existing unit test that broke because you refactored a seemingly unrelated class, especially when you have a nice acceptance test that is working just fine.

I’ve just shot down many of the positive arguments for unit tests on our project. Because it’s very important for us to test that our system is configured correctly, acceptance tests become very
important.

Well, if I already have a big suite of acceptance tests, do I really need unit tests to test things that are well covered by acceptance tests? Maybe if I have some class that has many different permutations, but if there’s only a couple paths through a class and I’ve covered it with acceptance tests, then I’m just going to skip the unit tests.

We also use stored procedures to do most of our data access. You can’t easily unit test a stored procedure, so we need more acceptance tests and integration tests to take care of that.

We still have about twice as many unit tests as acceptance tests, but that tide is turning. In a couple months, we will probably have twice as many acceptance tests as unit tests.

It honestly took us awhile to convince ourselves that we weren’t doing it wrong based on the conventional wisdom. But when we thought about it it just made sense to do it the way we’re doing it.

The moral of the story is that there are always exceptions to the so-called “best practices”.

February 20, 2012by Jon Kruger
Agile, BDD

Announcing the Columbus ATDD Developers Group

A few of us have been talking and have decided to start the Columbus ATDD Developers Group. If you’re in the Central Ohio area and you use tools like Cucumber and SpecFlow, believe that testing is not just for QA people, or if acceptance test driven development sounds interesting to you, then this group may be for you. This is a developer-focused group, so expect to learn things about how to write code using BDD testing tools, design patterns and practices, how acceptance tests mesh with your unit tests, and other developer topics. QA people are always welcome too, especially the technical-minded ones! Absolutely no experience is required, just come ready to learn.

Testing is not just for QA people, and BDD testing tools like Cucumber and SpecFlow have really helped me speak to business people, BAs, and testers with a common language and automate acceptance testing for my features. This hasn’t all been easy, and I’ve had to learn a new set of workflows, tools, and patterns. I found that I’ve asked a lot of questions about agile testing and BDD tools on Twitter and I’ve called people up when I’ve had questions on how to do things, and having those connections have really helped me out as I work through the learning process.

We are going to meet on the 1st Thursday of the month from 11:30-12:30 at various locations around Columbus. We’ll probably move the group around so that the same people don’t get stuck with the drive every month. This is an informal group so we’ll have open discussions as well as presentations and people showing their code. We want to hear everyone’s questions and ideas.

Our first meeting will be Thursday, March 1 from 11:30-12:30 at IGS Energy in Dublin. We will have an open space style discussion about Adopting ATDD in Your Organization. Some of us are far along down this path and some are just starting out, and we can all learn a lot from each other’s experiences. So come with your questions and ideas to share. And because IGS Energy is awesome, they will hook you up with free pizza and pop.

If you want to keep up with the group, we are in all the usual places:

  • Blog (we’ll post meeting announcements as well as guest posts about ATDD topics!) – http://columbusatdd.wordpress.com
  • Twitter – @ColumbusATDD
  • Google group

I probably won’t post meeting announcements on my blog, so go follow the RSS feed on the blog.

Hope to see some of you there!

February 7, 2012by Jon Kruger
.NET, TDD, unit testing

Changing how I structure unit tests

When I write unit tests, I use the BDD-style GIven/When/Then format so that the tests are descriptive and explain the business functionality that is being implemented. But I’ve recently changed the way that I do it.

Let’s say that I’m implementing bank account functionality and I am writing code to implement the following:

Given a bank account
When I deposit money into the account
Then the balance should increase by the amount of the deposit

The old way

I used to write them like this:

[TestFixture]
public class When_I_deposit_money_into_the_account : Specification
{
    private Account _account;

    public void Establish_context()
    {
        _account = Given_a_bank_account();
    }

    public void Because_of()
    {
        _account.Deposit(10m);
    }

    [Test]
    public void Then_the_balance_should_increase_by_the_amount_of_the_deposit()
    {
        _account.Balance.ShouldEqual(10m);
    }

    private Account Given_a_bank_account()
    {
        return new Account();
    }
}

This style is used by RSpec and many people in the .NET community. I’ve had a lot of success doing it this way, but I’ve always had some complaints.

  • The Given/When/Then phrases are spread out and aren’t in order.
  • We have the Specification base class, which isn’t bad but I think it might confuse new people who know NUnit but don’t know my special base class.
  • If you have a lot of “given” statements, you’re tempted to use inheritance or nested contexts, each with their own level of setup, virtual properties and methods, etc. This is very unreadable and gets unwieldy very quickly.

The new way

This isn’t really a new way, but it’s new to me. I’ve seen it before over the years but I didn’t really start doing it until I joined my current team where they did it this way and I’ve come to like it a lot better than the old way.

[TestFixture]
public class Bank_account_tests
{
    [Test]
    public void Deposit()
    {
        Given_a_bank_account();
        When_I_deposit_money_into_the_account();
        Then_the_balance_should_increase_by_the_amount_of_the_deposit();
    }

#region Helper methods  

    private void Given_a_bank_account()
    {
        _account = new Account();
    }

    private void When_I_deposit_money_into_the_account()
    {
        _account.Deposit(10m);
    }

    private void Then_the_balance_should_increase_by_the_amount_of_the_deposit()
    {
        _account.Balance.ShouldEqual(10m);
    }

#endregion
}

The best thing about doing it this way is that the business functionality is clearly specified at the top of the class and the Given/When/Then statements aren’t spread out all over the place. There are no crazy inheritance hierarchies, base classes, or big setup methods. When I write tests, I just write out the Given/When/Then scenarios in plain text and then use Specs2Tests to generate the test code for me. Then all I have to do is fill in the private helper methods. This is really easy, like filling in the blanks.

Also, I typically hate regions but in this case I find that they work quite well because they hide the helper methods that I typically don’t want to see when I open the class file.

It depends

Obviously there are situations where this is all overkill and you can just write simple tests without Given/When/Then methods all over the place. Just do whatever makes sense. I’ve found that this new-to-me way leads to very readable and easy to maintain tests.

January 18, 2012by Jon Kruger
Uncategorized

When good enough is (or isn’t) good enough

I came across this post the other day that went on and on railing on things that the author found unacceptable in today’s web frameworks, specifically Rails and ASP.NET MVC. It covered the whole gamut of issues, from abstract base classes in ASP.NET MVC to mega-controllers in MVC frameworks.

I’ve thought a lot of the same things too, to various extents. For example, I’ve never understood why controllers existed. Why can’t we just define routes that are handled by route handler classes that use conventions and REST and things like that? Yet I continue to use controllers in web apps. It made me think, at what point is something bad enough to do something about it and when do I just live with it?

This is the kind of question that makes software development so difficult, but at the same time a lot of fun. Today we were looking at a piece of code that needed to be refactored. We couldn’t figure out what the right way was to implement it, nor could we decide if it was worth the time to even do anything about it.

How do you decide what to do in this situation? The way I see it, you have to look at the return on investment on everything you do. In my controller example, I could invest the time to implement some non-controller solution. On a large enough project, I would probably get a good return on investment compared to using controllers.

But then again, you could argue that since controllers are towards the outer layers of the stack, maybe you can live with it. I care much more about the sanctity of the domain model because that’s the heart of my application. So is it really worth the time or not?

But it gets more complicated than that. Let’s say it takes me a week to implement the non-controller solution. During that time I’m not delivering any client facing features, and that might not sit too well with the people paying for your project. I was in this situation once, and the project almost got cancelled. Thankfully I pulled it out and was on the project for a year and a half and my framework investments more than paid off. But those first few weeks were nerve racking.

So what’s the answer to my original question? I guess it depends. As does pretty much everything else in software development. Which means that you don’t get an easy way out and you are going to have to use your head.

I still think I’m right about the return on investment thing. But at the same time you need to be shrewd about it.

January 16, 2012by Jon Kruger
Agile

The three amigos

Part of being a developer is taking requirements that are written by business analysts and understanding the business problem and the requirements enough to develop a working software solution to solve the problem. In most environments, BAs will work with the developers to help them understand the feature. Once the developers are done, the QA team has to try to understand all of the requirements that the BAs and developers already covered extensively.

You can run into multiple problems here. First, many business analysts write requirements in a format that are not detailed enough to outline all of the edge cases. This is not a knock on business analysts, but they often think in terms of use cases and how the business will use the functionality. But this is why we have a team. Business analysts are better at thinking about the needs of the business and how the app will solve business problems. Developers and testers are good at thinking about the details but sometimes don’t always see the big picture.

This is why it’s so important to bring all of the team members together so that we can take advantage of all of our strengths. We do this in a meeting we call the “three amigos”.

How It Works

A three amigos meeting consists of a business analyst, a QA tester, and a developer. If it’s a larger feature that might involve more than one developer or more than one tester, then you might have more people in the meeting. The BA has written up all of the requirements beforehand, and ideally everyone in the meeting will have read through them before the meeting so that people can have a basic understanding of the feature and can come with their questions.

Once we all have a basic understanding of what we need to develop, we read through the requirements together and someone starts writing all of the test scenarios on a whiteboard. We’re not writing out the complete test plans, we’re just covering the scenarios that need to be tested and maybe some of the things that each scenario will check for. The primary goal is here to figure out what needs to be tested and how we’re going to test each scenario (unit tests, acceptance tests, or manual tests).

Outcomes

The primary outcome of the three amigos are acceptance tests written in Given/When/Then format. Actually writing these out can take a little time, so we don’t do that with everyone sitting in a room. Typically a developer or a tester will work on it outside of the meeting, and once they have the scenarios all written out, then we do a quick review with everyone else that was involved in the original three amigos meeting to make sure that we all agree with what was produced.

Benefits

When you get everyone involved up front, you spread the understanding of what’s being developed across multiple team members. On most teams, BAs and developers have a good understanding of what’s being built, but QA people are left in the dark until you’re most of the way through the process. This way, QA people know what’s going on and they can add their valuable input before a line of code is written. As a developer, this will also help you because the QA people helped you agree on the acceptance criteria that you’ll need in order to complete the feature. No more guessing about what QA is going to test or whether you’ve built everything that needs to be built.

Automating acceptance tests becomes much easier when QA people have helped you come up with the tests and have agreed on them. This is also a good chance to talk to the QA team about what you’re going to automate so that they know that they don’t have to spend as much time manually testing scenarios that the developers have fully automated. Remember, we’re all on the same team, and we’re all responsible for quality. It shouldn’t matter who is testing something as long as it gets tested.

In the end, you end up with fewer bugs because developers know what they need to build and they have everything they need to build it with no coding errors. Certainly this works much better if you’re writing automated unit tests and acceptance tests, but even if you aren’t, at least you will know what you need to build and what it needs to be able to do in order to pass all of the QA tests.

Exceptions

As with everything in software development, it helps to use common sense. We typically don’t do three amigos meetings for really simple features. There’s no hard and fast rule about this, so you have to use your head. If it doesn’t make sense to have a meeting with a bunch of people to review something that you can handle with simple hallway conversations, then go with that.

We don’t always do three amigos on bugs either. If it’s a coding error, there isn’t much to discuss, it just doesn’t work correctly. If we missed something in the requirements, it might require a bigger discussion about the new requirement.

I think that it’s dangerous to make blanket policies that say that you must have a meeting or a certain amount of documentation before you start development on something. The goal is to develop working software that meets the needs of the business with a sufficient level of testing and documentation. You have to decide what that is and how you get there.

January 4, 2012by Jon Kruger
Page 10 of 23« First...«9101112»20...Last »

About Me

I am a technical leader and software developer in Columbus, OH, currently working as a Sr. Engineering Manager at Upstart. Find out more here...

I am a technical leader and software developer in Columbus, OH, currently working as a Senior Engineering Manager at Upstart. Find out more here...