2013-09-22

Clarify goals and objectives in 20 minutes

I've found that having a clear picture of my overall goals and objectives, makes it easier to make decisions about items in my inbox. It makes it easy to answer the question of "is this really something I should act on". Unclarity of goals, makes my lists of things I believe I have to do in this world long, unfocused and hard to navigate. But even though I experience real value from having the clarity of mind a concrete set of goals gives, I've found it really hard at times to formulate them for my self. Leading of course to a total breakdown in any productivity system I've been using at any time.

A solution came to me in a book called "Smart Choices: A Practical Guide to Making Better Decisions" by Hammond, Keeney and Raiffa. A part of their (somewhat elaborate) decision procedure for making a choice, also provides a very good crutch in order to get the clarity of mind I need in order to form a bunch of good objectives for my self.

The process is very simple. Bring out a sheet of paper (I use a two-page spread in my journal) and write down what area, project or problem you'd like to get a clarity of mind around as a headline - be it a high-level thing such as "career" or a lower level item such as "the car." Then list all concerns you have with respect to this area. For this phase, I like to use a timer. I set it to four minutes, and pour everything that enters my mind until the timer tells me times up. That usually fill 70% of an A5 page (which is the size of my journal) and leaves a little bit of room should I think of anything else during the rest of the process.

Next I transform all those concerns to objectives - which I write down on the right-side spread in my journal. The transformation goes from "concern" - say "clunky sound from rear when left turns" - to a positive objective such as "Decide whether I'm going to keep fixing the old car, or buy a new one." I try not to fuzz to much about it, but I regularly try to stop and think a little bit bigger than my first inclination (which would be to take the car to the repair-shop.)

The final step then, is to separate the means from the ends - some of the objectives tends to be a way to accomplish other objectives. I then turn the page in my journal, and give the page an informative heading such as "What I want from my Car". From the previous page, I pick the most important objective that is an end in itself, and write it down. Then I take any objectives that support that objective as a means, and write those down as well as sub-points for the main objective. Then I take the next 'ends' objective from the previous page, and so on until all objectives from the previous page have been transferred to my overview.

And voila, I have a nice overview of clearly stated goals that meets any concerns I have, that I can re-visit for clarity and focus and measure progress against in the future.





2013-07-06

Five questions on Velocity

What is Velocity, really, in software jargon?
  • "Velocity" is a measure on how fast something moves. In, say, Scrum, it translates to how many Story Points we can expect to produce during a fixed time-period. A Story Point is a relative estimate of the effort required to realise a well described User Story, or a user episode, if you like. I have used the term "Gummy Bears" instead of StoryPoints though. The name doesn't really matter.
Why do we want to measure Velocity, in this sense ?
  • In order to allow us to optimise our development speed, as our Velocity should be tightly correlated to our ability to construct software. Getting better at what we do should translate to a higher Velocity, and higher Velocity should reflect overall higher production speed.
Why do you think Velocity is correlated to development speed?
  • We estimate the size of a UserStory in Story Points. We believe we are able to estimate user-stories good enough to establish such a correlation. Sure enough, some times we are overly optimistic, and at times we are to pessimistic. But we believe we are equally wrong all the time, on average.
You only talk about User Stories in relation to Velocity. But I do other tasks as well, such as fixing bugs or upgrading my OS. Shouldn't they count positively against the Velocity as well - it is necessary work that needs to be done, right?
  • Ideally, no - fixing a bug doesn't count positively on the Velocity. You see, spending time fixing a bug, is time not spent building a new valuable User Story. So if you spend much time on fixing bugs, your Velocity should really be expected to go down.
But that's madness - I need to fix my bugs! Why do you say not to fix the bugs?
  • Please fix the bugs! But Velocity is feedback on how fast we are creating new valuable stuff. If you have to spend time fixing bugs, you've done something in the past that prevents you from creating new valuable stuff now. Velocity going down because you need to spend your time fixing bugs, is just an indication that you'r team need to get better at, say, quality assurance, in order to squash those bugs at an early state when they are easy to fix!





2013-04-08

13. On Getting Things Done - Keeping the weekly review under an hour.

After comparing Getting Things Done (GTD) with Scrum the other day, I got sort of inspired to write more about GTD. I'd like to share two revelations I've made about my personal GTD implementation. As I mentioned, I'm (making an attempt at) following David Allens productivity system GTD. My goal state is to follow it "to the book", and I do so to a large degree. And I have to admit. The most difficult habit to form and follow have been to perform the weekly review consistently.

The problems I've been facing, is that doing a review have, to me, been a very costly endeavor.  According to The Book, it should not take more than an hour. I've often found mine to take three. Spending three hours on a sunday afternoon reviewing my work-in-progress is a lot of work - both for me and my family. Even when it leaves me feeling totally in control of my destiny for an hour or five afterwards.

Your basic weekly review checklist looks like this:
  1. Collect loose papers and materials
  2. Process all inboxes, so they are empty
  3. Empty your head (on paper, for example)
  4. Review your Next Actions list
  5. Review the two previous weeks in your calendar
  6. Review the two next weeks in your calendar
  7. Review everything you are waiting for
  8. Review project lists
  9. Review any relevant checklists
  10. Review SomedayMaybe
  11. Be Creative and courageous
To me, those 10 actions + primer usually added up to much more than one hour of work! Even though, in the periods when I actually did this (without the optimizations I will describe in a second) on a regular basis, it felt like keeping it below an hour and thirty minutes was entirely possible. But still then, dropping the last point - reviewing the contents of the SomedayMaybe list, happened more often than not.

So what did I do then, to fix this?

SomedayMaybe is a bad name

My first observation was over time that I used my SomedayMaybe folder more like a trashcan. I placed things there, and never looked at them again. It grew huge! And for my own part, it was a problem of semantics. SomedayMaybe is, at least to my brain, to similar to the category of things that it would be nice to be able to do, should the universe put it in to my lap - but not otherwise. The intention of SomedayMaybe however is for things that you intend to do, but can't give top priority as of yet. For SomedayMaybe to work, it must be revisited on a regular basis! I needed a name for the category that was closer to "put it of for now, but make sure to read it again later."

I renamed my SomedayMaybe category to Incubate.

After renaming the list, I was more inclined to actually intervene with it. It was half the battle - my Incubate system was working!

There are always too many projects

Reviewing my projects list was another pain-point. It took a very long time during the review. And many of the projects was things I didn't really have intentions to execute on as of just now. They didn't really have a place on the project list at all! Of course, keeping the project list clean is one of the tings one do during the weekly review. And all of those projects should have been moved to the someday-maybe category. But I really had intentions to do them some time - and my someday maybe wasn't working so they stayed on my project list. A Catch 22 of sorts.

I ended up fixing this by adapting a concept from the Kanban process for agile software development: capping Work In Progress(WIP). I arbitrarily set the amount of projects I allowed to have open at any time to 15, and moved one by one over to my Incubate folder to that limit was reached. Reviewing 15 projects I could do in a couple of minutes. In addition, limiting the content of my active projects-list to only 15 projects at a time, really forced me to get my priorities in order. It became a driver to sort out especially what was happening on 30 thousand feet (the short-to-medium-term goals and intentions level.) And then, having my priorities in order enabled me to think clearly and more critical when I reviewed my Incubation lists. So in a sense, limiting the content of my active projects created a positive feedback-loop that made me clean up everything I put off - contributing to even more efficient weekly reviews.

Those two things - Limiting WIP and renaming SomedayMaybe to Incubate, essentially fixed it for me. There are some more details to adress here around review-optimization, but these two items turned out to be the gist of the matter for me. I'm now able to do a meaningful review within an hour, and I actually look through my Incubate-files when doing it.

2013-04-06

12. Is Scrum "GTD for teams?"

I've been using GTD for ten years plus, after a then colleague of mine sold me on the idea. He was very exited about David Allens book. I've been doing Agile in some way or another from before that after going all in on eXtreme Programming with a startup, and Scrum have been the go-to-process of choice for the last six years or so. A couple of weeks ago, I heard a pod-cast (I think it was with Daniel Pink) where a part of the show touched upon the similarity between Scrum and GTD. One of the statements made in that podcast was that "Scrum is GTD for teams." When listening, I agreed that this comparison was not entirely without merit. I've come to appreciate the similarities between them, and I pondered a similar idea my self a couple of years ago. This is a short stab at what's similar and what's different. Is Scrum really GTD for teams?

Scrum (as do other agile processes, such as eXtreme Programming) split the problem space of software development in to Stories, and device a plan for how to prioritize and track the translation of the Stories to actual software artefacts. GTD focuses on translating "stuff" that's coming your way in to Projects and next actions, and the efficient management of these through usage of contexts.

A Story maps almost directly to a Project. A story is a tiny description of a user interaction of the system, with a clear definition of the What and Why, and a description of the goal state through a recipe for how to demonstrate the complete story. A simplified example may be "User press the Stroke button in order to draw lines with strokes", where this should be demonstrated by performing a drawing action that does not cause strokes unless the Strokes-button is indeed pressed. In a similar way, GTD encourage you to think first about "Whats the Outcome, and what does doing look like" and then define your actions in terms of things you need to do in order to reach done. A Project in GTD-jargon is any goal-state that needs more than one physical action. In this regard, you may say that "Research BitCoin" may be an ill formed project. "Research what economists in general thinks about BitCoin" however, is better. "Research ten renowned economists opinions of BitCoin" however, clearly states what needs to be done much in the same way what a Scrum Story does. In some sense, Scrum and GTD have converged to very similar formats  for the actionable items. At least ideally, if not in form.

Both GTD and Scrum defines a kind of "morning ritual". Both asks you to figure out and state somewhat clearly what your goals for the day is. The GTD morning ritual is to look over the calendar for today, find the next actions you need to complete and perhaps group them in a "today" list. The Scrum morning ritual is to gather around the Scrum-board, state for each other what goals one have for the day and perhaps grab new work if one's done with the previous task.

But this is where the similarities ends. Scrum defines, in addition, a process, where you first plan a "sprint" lasting one, two, three or four weeks. The goal is to first plan the sprint, by building a "Sprint backlog". The sprint backlog contains all stories to complete with estimates. The stories are perhaps broken down in more details - tasks needed to build the stories. Progress is measured relatively to the sprint backlog. One goal is to be able to fill the sprint with exactly the amount of work one can complete within the Sprint. The Sprint Backlog is considered "holy", and should not be touched during the sprint. The items on the Sprint Backlog is then tracked and "burned down" towards completion during the execution of the sprint. Then there is an end-of-sprint ritual to evaluate its execution. Lather, rince, repeat.

GTD do not come with such a process attached. However, GTD advocates a weekly review, where one clear the deck, look over all open loops, check the calendar for the last two weeks and the next two weeks. This is done in order to be able to see if there are any required actions that one have failed to record any where. something crops up. It may look like a planning and retrospect meeting, but it lacks the concept of estimation and "locking in" any target scope of work. GTD recognized that all your priorities may change during a two minutes chat beside the water-cooler, or when your spouse call you and tell you she have crashed the car. Reacting on such priroity-changing events in Scrum, requires an act of "terminating the sprint" and starting over with a new planning session.

With the last paragraph in mind, the GTD process looks more like a personal Kanban process. It is a more lightweight process than Scrum. Kanban focuses on continuous evolutionary change and how work items flow through the organization from concept to finished feature. The concept of a sprint is gone, so is the concept of a Sprint Backlog. There is only the product backlog, in addition to issues that crop up while one move forward together. The center of a Kanban process is of course the Kanban, maintaining a living representation of what work is actually being done at any time. Spending some time every week reflecting over the work being done is still a good idea. So is standups.

Another thing that distinguishes GTD from Scrum, is that GTD moves beyond the mere execution of a plan. GTD defines some useful thinking tools, the different levels of focus, to guide how projects and actions are prioritized. Areas of focus and responsibility, short term goals, visions and intentions, and finally purpose and principles - all these levels of thinking unite in a constructive way to reflect around you and your life's direction. A team working towards delivering a product need to do the same, and Scrum provides very little guidance besides giving the key stakeholder a name.

In conclusion then. I'd say that the execution-part of GTD bares more resemblance to Kanban, than it does to Scrum. So one may say Kanban is GTD for teams. Or GTD is a one-man-Kanban. But this comparison on the execution-level only leave out the deeper more life-encompassing aspects of GTD. GTD is a different beast all together.


2013-04-04

11. It's not the resources, it's the priorities.

"We don't have enough resources" - if I had an euro for every time I heard that statement, I would be rich. I've heard the sentence used everywhere, from the mouth of a one-man-team, and from leading developers in a seemingly "unlimited resources" situation. And every time, it kind of strikes me how... wrong... the statement is.

I remember participating in a project meeting once with our then most important customer. From the customer side, it included the main stakeholder - our key sponsor - and two of his colleagues, who participated in QA and follow up activities. From our part, it included the Project Manager for the project, who was a new hire, the CEO of our company, a developer who had participated in meeting this customer before, and me. It was the first time I visited, and I was quite new on the team. Due to several factors, such as key people moving on, lack of communication and a couple of very buggy binaries sent to the client, trust was suboptimal to say the least.

The meeting spanned three days. The first day was "get to know each other day". The second day was more of a feature discussion day, which turned out to be the day where the customer spent most of their time piling on new stuff they wanted to have delivered within the scope of the contract.

Ah - the contract. I need to talk about the contract. From the start, it was almost the agilists dream contract. It was fixed price, with a list of perhaps 20 or so vaguely described features they wanted, delivered over four increments. The contract had fixed seemingly non negotiable delivery-dates for each phase. We had delivered phase three, and the customer was still not happy with what we had delivered for phase two. So some place along the line we had failed to match - or control - the expectations of the customer. Fair enough. We were sitting there, we had not closed phase 2, we wanted to close phase 3 and we wanted to get started on the last phase. To add insult to injury, we had spent more time than scheduled on phase 3 - we didn't have the budget to complete phase 4 without taking a monetary loss (not to mention finishing it on time.) And still, the customer was piling on changes and fixes on features delivered for phase 1, 2 and 3.

I can rant on about what went wrong with that project, but I don't think that would be the interesting part. The interesting part is how we got out of it. We simply did a variation on the planning game. New and exiting for everybody but me.

On the evening of the second day, me and the PM sat down, wrote all requirements we had gathered during those two first days on A4-sized printer paper (For you purists: sorry - no index-cards in the grocery-store on the corner of our hotel.) One requirement on one piece of paper. There was even room for drawings. I committed a grave sin that day, by singlehandedly giving StoryPoint estimates on every item in the list (the PM was not able to participate.) And voila, we had a backlog.

The next day then turned out to be the planning and prioritization day. We started by presenting the key sponsor and his entourage with the following:

  • Acknowledged that we had a fixed deadline
  • Put forward the pile of paper the backlog
  • Stated the sum of the StoryPoints (we called them apples) and how they came about
  • That given the current velocity of the team, we could complete a third of the backlog within the deadline for the project (our team had an established velocity, and we used this to extrapolate under the assumption that my estimates was ballpark-ish.)
I must admit, that the first part of that meeting was difficult. But to cut the story short - when presented with what he asked for this way, the sponsor was able to agree to participate in prioritization of the backlog, remove two thirds of it's content, and negotiate a realistic scope for the deadline. On which we delivered successfully. Trust was reestablished, and we got a new contract with them.

Lack of resources was not an issue in the discussion. Priorities, on the other hand, was. Priorities, and clearly communicating what priorities the stakeholders have to make. What to keep, and what to remove. When this is communicated clearly, the resource-question solves it self. Either the project get's the amount of resources it needs, or the project gets shaffed. Both are wins, in some sense. In our case, it turned out to be more resources (the next contract.)

2013-04-02

10. If it works, fix it anyway

I remember a day where I'd spent a couple of hours understanding a piece of code. There was no tests for this code, and it was hard to read. When I finally understood it, I thought of a way to change the design of these parts so that it would be easier both to test and to read for the next maintainer coming along. I aired my opinion to one of the teammates, and you have probably already guessed what he said.
"Why change that? It works. Don't fix it if it works."
And in some sense, that's a good advice. It's a good strategy for risk-mitigation, and my hunch is that it's correct 80% of the time. But in this particular case, I disagreed. We had touched upon that piece of code several times the last sprints, we had fixed several bugs in it, and chances were we would have to dig in to it again in the next sprints.

What definition of "work" do you follow, when it comes to your code? In our discussion above, my colleague was of the opinion that if the user experienced the feature as working, we should not risk breaking that state of "working". I think that's a bad definition for "work".

Any definition of "work" must include maintainability to some degree. Of course, the required level of maintainability may vary, but for most cases readability and testability not to mention the existence of adequate tests must come first. If the code isn't easy to understand, it doesn't work. If the code is difficult to test, it doesn't work. If the code is difficult to exclude from a test that don't need it, it doesn't work. If it isn't covered by a test, it definitely doesn't work. If it doesn't work, it needs to be fixed.

The code must stand the test of change in order to be flexible. Maybe the feature works, but the code doesn't. So go and fix it anyway.

2013-03-30

8. A New War on Waterfall

"I'm concerned, because that looks very much like a waterfall!" a coworker of mine quipped. "We need to communicate across disciplines, and some times things discovered while implementing the solution might affect the final design of the product" he continued. The product manager had just finished outlining a sketch of a process he wanted us to follow when bringing new products or new versions of products to the market. My colleague (a very competent one, I might add) commented on what he perceived to be communicated as a linear step by step process. As he spoke, I felt an agonizing pain somewhere in my soul. As I've come to do ever so often lately.

The plan our product manager had outlined, contained steps of a data-driven process for product development. Where we every step of the way, from first concepts, then minimum value products (MVPs) and prototypes, could validate the product at different stages by interacting with the audience even before implementation and deployment. What my colleague failed to see was that the PM was picturing a "main-flow" - not a prescriptive "do this, then that, then finnish with this" type of plan. Colleague reacted as if saying that we want to do user studies and prototypes before we start working on the real thing, implies that lessons learned while implementing the product, or data from the live product, can not affect the direction the product takes. Which was obviously not what the PM had in mind. My colleague is not alone in making this mistake, though. An entire industry have made the same error for decades.

Even the person defining the waterfall process was clearly aware that any ventures in to software development would require feedback from parts lower "down" to various parts higher "up". The "waterfall process" is usually credited Winston W. Royce, although he did not use the term in the original paper. The figure he used to outline his basic process, or workflow, however, does indeed resemble a waterfall, hence the name. The waterfall is a flow of "steps" from System Requirements through analysis, design, coding and testing to deployment. The term Waterfall then, have come to mean a process where every activity in that list is performed to completion in isolation, where the result is handed over to the next box for processing. Below is the original canonical picture of the waterflow process.


From reading the paper of Dr. Royce, however, it becomes quite clear that this inflexible process is definitely not what he intended to communicate in his paper. On the general overview of the process he states, and I quote: "I believe in this concept, but the implementation described above is risky and invites failure." The paper is full of examples showing how, if applied blindly, such a "step-by-step" process might fail. He also state quite clearly, translated to more modern terminology, that it is usual to have iterations spanning multiple phases. And there is also modern sounding gold in the paper, like "Involve the customer - the involvement should be formal, in-depth, and continuing" - still a hallmark of good software development if you ask me! So the first paper that defined the Waterfall process, is actually the first loud critic of it. It actually talks about something that to a high degree resembles something closer to a modern agile iterative methodology. Unfortunately after Royce's paper, and contrary to his intentions, the term waterfall is cemented in to our minds to mean an inflexible step-by-step process that are doomed to fail due to lack of feedback loops. It is wrongfully used as a contrast by whoever have some new snake-oil a new process to sell. But that inflexible step-by-step process never existed.

This is the core of my pain: Most, if not all, people I meet in the software industry are (somewhat) grownup persons who are well aware that succeeding in software development require communication and feedback, and that things we learn underway almost invariably change what we end up building. Heck, it's those who are fresh out of school who tend to yell out the loudest about the need for feedback and communication. Do we forget this when we get older or something?

Could we please then, even if somebody for the sake of communication paints a simplified picture of a bunch of boxes with arrows between them take for granted that there are feedback-loops? And do that even if, taken literally, it resembles a waterfall? I'm not saying I believe that those feedback-loops will be popping up all by them selves. They must be nurtured and cared for as any other important aspect of the development process. But sketching a general flow from idea to finished product does not exclude it's existence!

It seems to me like yelling "waterfall!" has become the favorite guilt-by-association argument. Some feat, for a process that never really existed anyway! So then. Hereby, I declare war on the term waterfall it self. 

2013-03-29

7. Test behavior, not methods

I recently revieved some code from one of my colleagues. A birds-eye view of his class looked like the following. There was nothing wrong with it - it looked perfectly fine to me.

// Foo.java
class Foo {
  public void Foo(Bar bar) {...}
  public void methodOne(String str){...}
  public String methodTwo(){...}
  public Integer methodFour(Boolean b){...}
}

However, I read the test for this class first, FooTest. Even though it looked like it tested what it should test, I had some immediate comments after just a quick glance in the file.

class FooTest {
  @Test public void testMethodOne(){
    ...code...
    assert...
    ..reusing and modifying state..
    assert...
    ...more code...
    assert..
  }
  @Test public void testMethodTwo(){..more of the same..}
  @Test public void testMethodThree(){..more of the same..}

As many others, he had written one test for every method in the system under test (SUT). The methods was long. State bled through from the start of the test-method to the end of it. Variables were reused and their state modified as the test went along. I usually prefer to test behaviors, not methods, and I felt being on safe grounds when I suggested for him to rearrange his test so that he had one test per behavior.

He thought what I said was a ridiculous idea. As an example he pointed out one of my own tests that follows this pattern and looked something like the following.

class FooTest {
  @Test public void methodOne_leaves_foo_with_clothes_on(){...}
  @Test public void methodTwo_calls_mom(){...}
  @Test public void methodTwo_writes_result_in_book(){...}
  @Test public void methodOne_after_methodTwo_lights_the_firecrackers(){...}
  ...more tests...

"I hear what you say, but I think it is ridiculous. What do you need all those damned tests for? You have twice the amount of code in your tests than what you have in the classes you write. Plus. You are violating our coding standard with those underscores! Think about maintainability, man! And after all, this is just the test-code. It doesn't need that much focus." Awh the pain! I managed to resist the temptation to slap the offending party in the face with a fresh cod I usually carry around for that exact purpose. Instead I resorted to a reasoned debate and conversation.

In some respects he's right. It becomes more code. Much more code. But I've come to realize that organizing tests by methods does not tell me anything about the behavior of the SUT. In order to understand the behavior of Foo from above, I need to read all the code in the tests. I probably need to read all code in Foo as well. And from that I might be able to deduce what it does or what it's supposed to do. But even if I get thus far, it's still very difficult for me to understand what aspects of that behavior actually have a test and which one have not.

One test per behavior, allows a quick glance of the behavior of the class or subsystem just by collapsing the body of the test-methods. The naming of the tests can read as a story. IMO the layout and cleanlyness of the test-code is more important than the production code it self. If we need more words to communicate, write more words - communicating the intents clearly is more valuable than writing less code.

As Einstein said, paraphrased, make it as simple as possible, but no simpler.


2013-03-28

6. Efficient TDD: Start closer to the end user



Nobody gets it right every time. Especially not software design, where... well... everybody gets it wrong most of the time. Even when doing Test Driven Development (TDD). I remember a series of blogposts by Ron Jeffries where he tried to implement a Sudoku-solver using TDD and absolutely failed to solve the problem. If you read the posts from Ron Jeffries, notice how he jumps straight in and attack an internal design detail before even understanding the problem. He basically gets stuck there and end up without a solution.

I remember having had design-sessions that looks eerily similar. After listening to the product owner for two minutes outlining what's needed, we went on to discuss lots of internal design details. "We would need a Frobinizer." "Also, we need a FlexiPlug" "The Frobinizer and FlexiPlug cant talk to eachother directly - they need to post and read messages via the PlancCampfer." "But the semantics of a Planc dictates that it should not share component with the Camfer, they should be separated." At more than one situation, I've found my self preoccupied with the software components to a very high degree, and to a lesser degree about how it actually implements the features we wanted. And I do believe that the times I've ended up with a huge outburst of frustration and then scrapping everything and starting over, is strongly correlated with the times I've become to preoccupied with the internals of what I'm making.

The topic for this post is a strategy to approach design and implementation in a way that I experience steer me away from the problems Mr. Jeffries experienced. The key is to start with a test that is as close to the user as possible.

All applications originates with some user or some agent that interact with the application (not to much of a generalization, I presume.) If I write a GUI application (I've blogged about something slightly relevant previously)  I'm probably using a GUI framework, such as Qt, wxWidgets, GTK or Swing, so the actual view I'm putting together is composed of components from the framework. I'd like to avoid testing these framework-provided components. But the user clicks a button with the mouse, or he type some text in a text view, or he exercise a key-combo. I'd like to start as close to the user as possible, and for a GUI application this is where the user action leave the framework code - usually this involves implementing some kind of event handler. So the first test is for the event-handler that originates with the user interacting (and it's immediate surroundings.)

For another example, we can look at a web-service. When adding something new I like to start with writing a test for the network access-point. The test basically checks that the web-endpoint manages to get responses, and react appropriately to them. The endpoint is tested by relaying representations to an interface. The diagram below illustrates the  basic design of such a test.

I start by writing the WebServiceEndPointTest and the WebServiceEndPoint, create a interface that represent the real behavior, and translates calls to WebServiceEndPoint to something ServiceInterface can relate to (e.g. method calls and values.) The test then sets up the mock for the ServiceInterface, exercises the WebServiceEndPoint and validates that the interactions with the mock was correct. There is nothing revolutionary with this idea of course - the main point of this blogpost is that this is the right end to start working in. Get the user interactions defined first, before the design of the rest of the application get so set in stone that it can dictate how the user interaction can be.

You may view this as performing top-down design, as opposed to doing things bottom up. And you would be right in pointing out that this leads to a design that pretty much follows the Dependency Inversion Principle (DIP.) By following DIP, we get a design where "lover level" components and packages depend on abstractions exposed by "higher level" components, and that everything relates to each other via those abstractions. This in turn leads to a nicely decoupled and inherently testable codebase. The figure below is a caricature of the dependency inversion principle. If you let Foo in the picture below play the same role as WebServiceEndPoint above, notice how higher level components don't depend on lower level components, but that lower level components depends on abstractions from higher level components (higher translates to closer to the end user.)



It also turns out that the result of following this advice, becomes very similar to behavior driven development (BDD), without the domain language for specifying the tests. At the beginning I get an outer loop, where I write tests that closely capture the behavior and the interactions of the end user. These tests are also suitable for testing the overall behavior of the system, and can be 'wired' as integration tests (in addition to working as unit-tests for the outermost units.) I also get an inner loop, where I can refine and refactor the designs and tests of individual units that build the application. So from following a very simple advice - starting as close to the user as possible - we've discovered the dependency inversion principle and we've been doing BDD. Not bad for an afternoons work!

So, how would I do the sudoku thing then? When I solved sudoku by means of TDD, I started with a textual representation of a completed sudoku-board and wrote a test that verified that my solver recognized it as complete and valid. After that I progressed with leaving one, then two, then more fields blank. After a handful of tests, I had a solution that was not to dissimilar from this solution, based on search and constraint propagation. I felt satisfied with the solution, and I never needed any tests for the internal data structures. Starting closer to the user guided me in a good direction.

2013-03-27

5. Ruthless with email

I'm using David Allens system for personal productivity called Getting Things Done. The system states some overarching principles, such as Inbox Zero - reduce the content in all inboxes to zero elements at least once every day, and a process in order to reach that state.

Roughly stated, the process for emptying all inboxes is as follows: For each item in the box, ask the question "Is it Actionable?" If yes, formulate a next action and place this in a system to keep track of it. If no, figure out if it's trash, if it's something you need for later, or something you want to keep for reference. Sounds like simplicity itself, right? See the picture below for details. There is one big problem with the application of this procedure. The first question - "Is it Actionable?" - generate too many false positives, and there are too many effing emails in this world.  If you open an email, and ask your self "Is this Actionable?" your brain will happily translate that to "Is there something I could possibly do with this thing?" and then happily continue to answer "Well, dude! Yeah, sure! Here's some random thing you could do!" "This commercial from the electronics store... You know, you should investigate a new stereo!" Bam. New useless project.



In the email-account I use for work, I get ~70 mails I need to relate to in some way or another pr. week. That's... 14 mails a day. There are spikes of perhaps 30 mails in one day. The actual number of mails that hits my mailbox is higher - maybe three times that number - but two thirds get sorted to designated folders I seldomly need to look at. I'm not on any mailing lists except those relevant at work. So 70 - that's the number of mails I need to open, read, and figure out if and how to act on. In addition I get ~30 mails a week for my private account. I don't know if 100 emails a week is a lot. It feels like a lot at times. And some times I get a bit on my heels, and they pile up. So how do I cope?

The solution to this email-problem is found in the parts of GTD that have not gained the same amount of attention as the mechanics around processing. Allen talk about six different horizons of focus:

  1. Next Actions
  2. Projects
  3. Areas of focus and responsibility
  4. Goals and intentions - things that should manifest in life in two to three years
  5. Vision - how should life be
  6. Purpose - principles, ideals and why I ultimately are here.

Most tools only handle 1, 2 and perhaps they pay lip-service to level 3. These are the high throughput artefacts. The things that should have turnaround-times in at most a few weeks. They pose interesting engineering challenges. They are easier to talk about. "Hey, what system do you use to track your next actions?" But in order to fix that mail problem, I find I need to play on more levels.

A more representational thought-procedure for my part might be something like the following - if I really spell it out.
Is it somewhat probable that this item does not relate to my current projects, my defined areas of focus or my goals?
If the answer is yes, I chuck it in the bin right away. This is not revolutionary, by the way. Judging how meaningful a piece of "stuff" is to you by aligning it with your areas, goals and vision is exactly the point of the GTD-system. This fact just seems to drown in the tool-mayhem.

I can intuitively answer that question quite fast. Often even without opening the mail. If I hesitate a little bit with deciding yes or no, I archive it instead of deleting it. Minor safety valve. Sure, I loose stuff. I quite possibly miss opportunities. I feel a bit like a ruthless bully when I munch through 20 mails in five minutes, and only two of them survived the ordeal. But I empty my inbox and feel good about it.

Didn't I get back to you on the email you sent? I guess you didn't align with my grand plan in life. I'm sorry. But my inbox is clean!

2013-03-26

4. Group by function, not kind


Today I'd like to write a little bit about physical design. Physical design is all about placing the needed behavior in the right place, and not so much about objects and how they interact - a concept I first read about in "Large Scale C++ Software Design" by John Lakos. The functionality needed must reside somewhere, but it's not irrelevant where it ends up. Good physical design guidelines can be crucial for the long term success of a project.

Here's a very simplified abstract representation of the source-layout in a project I worked with a couple of years back:

myapp/dialogues 
myapp/shapes 
myapp/views 
myapp/caches 
myapp/preferences

For each new feature we added to the system, we wanted to add one or more shapes, one or more views, one or more caches, one or more preferences relating to the feature, and perhaps a handful of dialogues as well. So what was wrong with this?

It doesn't scale well with the size of the codebase. As long as we had a handful of features, this was ok. But the application grew fast - we were adding new features, and every new feature sliced through most if not all of the directories. In addition the team grew, and we collided with each others works more often. Build-times increased to an uncomfortable level (this was C++). At a point we wanted to separate things in libraries and we realized that we had a huge problem. Shapes depended on preferences, preferences depended on views, and views depended on shapes - all directories had dependencies to most of the other directories. Circular dependency galore. An entangled mess we spent a fair amount of time to try to tease apart.

The solution that materialized, was to group our files according to new features. So over time the directory structure morphed in to something that looked more like this:

myapp/jump/dialogues 
myapp/jump/shapes 
myapp/jump/views 
myapp/jump/caches 
myapp/jump/preferences 
myapp/slide/[dialogues, shapes, views, caches, preferences]
myapp/talk/[dialogues, shapes, views, caches, preferences] 
myapp/common/

...where the actions - verbs - represents different features or groups of somewhat tightly related functionality - features. When we started organizing the physical design of the application this way - by the feature rather than the type of the different software entities - we experienced several immediate benefits. If I worked with the jump-feature, for example, I would be pretty certain that my changes did not break anything relating to the slide-feature. This organization also made it easier to remove duplications by discovering and salvaging common functionality, and add that to separate utility libraries. In short, this physical design inspired loosely coupled designs. On the other hand, the original (and maybe more intuitive) physical design led us to make tightly coupled logical designs.

I use this as a rule of thumb. It's obviously not always true, but true often enough to make notice. If I fail to follow it, I notice that the natural evolution of general utilities that helps me continue to keep speed up while I'm adding new features, fails to manifest. I also experience that circular dependencies between packages is more prone to pop up. If I manage to group by function first, I find that keeping the codebase decoupled, clean and non-cyclic is much easier.

2013-03-25

3. Talk about execution speed, not quality

I remember sitting in an all-day company meeting once. Everybody was there, and it was supposed to be sort of a pep-talk thing to get all of us back on track. It was important, as we had grown by aquicition a couple of years, business was not the best and there were some bad moods here and there (to put it mildly). We had a newly appointed CTO, a jolly nice fellow I liked a lot on a personal level. He was not from a software background, but had more of a domain background (this was in the oil and gas industry.) He stood up to hold sort of a speech, and he opened with a phrase that didn't sound to different from "Quality costs more, we must tone down our quality focus."

First of all - I'm a fan of W. Edwards Deming, and I believe that with a quality mindset, you produce better "stuff" for cheaper - whatever "stuff" happens to be. So how could this new CTO fellow stand up and say something that seemed to contradict that? I was furious. Who hired this idiot? Of course, nothing else from what he said stuck to my mind that day.

When I left the meeting, however, I remembered a lecture (or was it blog-post) by Kent Beck, where he discussed the notion of external and internal quality. I realized that what our CTO had talked about and what I reacted to was those two somewhat different and orthogonal entities.

If you have not heard about this before: External quality is relating to the end user observables. What features do we have, how complete are they, how do these features feel and how many bugs are there. Internal quality is almost entirely orthogonal to this (of course - they aren't entirely orthogonal, bugs are external quality observables that obviously relate to the internal quality of the software but humor me,) and is all about how the software behaves and feels when the software developers work on it. A low internal quality is often referred to as "Technical Debt" - a phrase coined by Ward Cunningham. Examples includes bad design choices, duplicated code and low test coverage. The theory goes, that if the internal quality is raised, new features can be added faster.

The next time I met said CTO, we had a chat about this and he concurred. He had talked about the size and scope of our deliverables and the amount of time we spent on polishing them. He meant we delivered more than what the customer payed for, or what the customer wanted to pay for. And he could absolutely understand the need to do some house cleaning in order to be able to deliver efficiently.

All in all this is boils down to a variant of a challenge we often experience as software developers. The stakeholders want more features they can see. The software developers want to clean up the bit-rot they're creating, caused by miscellaneous pressures to deliver features the stakeholders can see as fast as possible. I somewhat learned a lesson, and I've stopped talking about quality when communicating to stakeholders about needed cleanups. Instead I try to frame any discussion about when to do that cleanup in terms of how fast we can add other visible features. Further I try very hard to talk about all end-user observable external quality as scope stakeholders can rationally triage against estimates, established velocity and the calendar.

This perspective have made my life somewhat easier at least once. :)

2013-03-24

2. A TDD Crux: Talking to others

I've been a fan of test-driven development (TDD) since I first learned how to do it my self, and at various times during the last ten or so years I've been asked questions that pretty much sounds like "How do you test THAT?" while the asker points to some source-code. The source-code being pointed to has almost always been a tightly coupled mess without tests. And of course it's nigh impossible to test THAT without investing a significant amount of work in both refactoring and a huge scaffolding.

The Bowling kata, for example, is a well known exercise everybody who learn TDD run in to. It is simplicity itself: An internal datamodel, with simple and well defined behavior. It's "Perfekt for TDD" (If you haven't done the bowling kata yet, check it out here.) It crosses over to the "How do you test THAT?"-realm in the second it sends a signal to an external system in order to play a video of a dancing turtle every time you roll a strike. If not doing TDD, some might probably just pass the "PlayAnimation" subsystem to the BowlingGame class, and call the "celebrateStrike" method every time the player roll a strike. And voila, it is evolving in to a tightly coupled unmaintainable mess. I'm thinking of this as the first stumbling-block, the first mental challenge, when learning TDD: How to test behavior that relates to other behavior not contained in the object being implemented.

I won't dive in to mocks, stubs, fakes and the lot - there's been plenty written about that already and this is by and large a well understood problem. Still, in order to hopefully make a condensate of how to get over that hump, I do want to describe a general pattern of thought that I often apply in such scenarios, outlined in the figure below:
A less direct path
The object we are aiming to develop with TDD is Foo, and it needs to call methods on some object Bar that is not under our direct control. Instead of interacting directly with Bar, Foo interacts with it's surroundings through FooActions. Foo gets a reference to FooActions via the constructor during application setup. FooActionsBridge is a very simple implementation of something that interact directly with the Bar system, preferably only relaying method calls without actually containing any other behavior so it can be checked for correctness through quick inspection. Notice also that Foo and FooActions is bundled together in the same package. FooActionsBridge is a part of the setup of the application - so quite possibly in a third package. There is of course one obvious simplification here. If Bar is under our control,  Bar can implement FooActions directly, eliminating the need for the FooActionsBridge. In this case I sometimes like to add the FooActionsBridge first while getting Foo sorted out, then change Bar afterwards. That might be overly cautious on my part though.

So - does this help in getting over the first crux while learning TDD? Please let me know!







2013-03-23

1. Blogging every day

I want to form a habit of writing about software development and personal productivity. It's on my list of long term intentions, and I have blogged sporadically in the past. Small blips every now and then, and I hate to admit that publishing a blog-post have been much work to some extent. I've been baking on them, reading, rereading, re-rereading and moving paragraphs and - Egad! They're still not perfect! I do the same thing with emails btw. I'm fretting over the content way longer than I should. I think the proof is in the pudding, that's an unproductive approach. 

During the last week I've repeatedly thought to my self that if I, at some point in time, set out to blog something about what I'd like to write about, every day for, say, a month, that would be an attainable well formed goal that would help me form that habit.

I'm not one for new year resolutions. I don't believe they work. Never did. I believe, at least, that I have well thought ought reasons not to do so. The main reason is that it, in some way, represent postponing important things to some day in the future on the cost of more urgent matters. "Yes, I'd make it a new year resolution to quit smoking." - but not right now. I tried to put the idea in my Incubate-folder first. But the third time it showed up I decided that now was the time to do it. So - this is number one. Thirty to go. And I haven't even figured out what tomorrows topic will be yet. Kind of scary.

And this is the main topic of this exact post: I want to establish a new behavior. So I set out to exercise the habit I want to establish in a somewhat extreme manner. In a month, I'm changed. If I follow through with it. I've read about this somewhere. Not sure from where, but it's not my idea. I still think it's good. So I'm doing it anyway. Let's see if I manage to follow through, all the way.

Let me know if you manage to find a positive adjective to describe my writing. Until tomorrow, then.

2012-08-26

Why should you learn and use TDD in the first place?

I've been a preacher of test-driven development (TDD) since my initiation to test-first development some time around 2001. And as far as programming goes, I feel crippled if I can't plug a feature in by means of TDD. Sorry. Wrong. Correction follows. I am crippled if I can't plug a feature in by means of TDD. For me TDD is primarily a design aid - a way to be able to think about the solution at hand. If I don't have that tool available, due to e.g. too tightly coupled legacy code, my ability to be productive is reduced. If I work with you, I want you to do TDD, because then I know you'll make the same design considerations I am making. And that is the main reason for me to advocate TDD. It's a hygiene factor, where the absence of it feels like if I'm typing on a keyboard that lies beneath a mattress.

But what should be your motivation for doing TDD? I dont believe that me saying cheese pretty please on my knees is very convincing in that regard. I remember some debacle from 2007 and onward when Robert C. Martin stated that in his opinion a software developer cannot consider him self a "professional" if he did not do TDD. I'm not really sure that it convinced anyone to do TDD, maybe even the exact opposite. So why do I think you should do TDD? Maybe because it provide better quality products? Or maybe it yield better designs? Because it improves communication? Should you do it to avoid being slapped in the face with a cod from your other team-mates that are doing TDD? Does it come out on top after doing a cost-benefit analysis? What should be the important motivational factor here? I might give an answer before I'm done with this blogpost, but first some good old-fashioned arguing.

I'm writing this, because recently I read this blogpost by Jacob Proffitt (it trickled up on the frontpage of Hacker News) and it ripped open some old battle-scars on the topic. The blogpost is somewhat old, but still a good read. The topic of the post is a criticism of another blogpost written by Paul Haack and the article "On the Effectiveness of Test-first Approach to Programming" by Erdogmus et al. Proffitt points out several problems with both the conclusions of Haack's blog post and the article he criticizes. And he allows me to highlight yet another problem that can show up in discussions about TDD. Let me quote the following section from Proffitt's blogpost:

More interesting still would be the correlation between "Testing First" and unit test quality. Ask yourself this, which unit tests are going to be better, the ones created before you've implemented the functionality or those created after? Or, considered another way, at which point do you have a better understanding of the problem domain, before implementing it or after? If you're like me, you understand the problem better after implementing it and can thus create more relevant tests after the fact than before. I know better where the important edge-cases are and how to expose them and that could mean that my tests are more robust.
He concludes that your tests will be better, if they are written after implementing an artefact. Sounds like a reasonable argument, right? Well. I'm so sorry, and I hate to say this so bluntly, but the argument is baloney. The first question in the paragraph should rather be the following: "Ask yourself this, which unit tests are going to be better, the ones created after writing a lot of tests while implementing the functionality, or those bolted on after just implementing the functionality?" I guess it's obvious what my answer to that question is. The point being - I'm not entirely convinced that the author really get TDD, and that is a big obstacle in these kinds of discussions. Anyhow. Bad form by me - as mentioned, it is somewhat old, and the paragraph is taken out of context.

I have been looking for academically published empirical results regarding the merits of TDD for quite some time, and I've managed to dig up some publications around this topic (including the previously mentioned article by Erdogmus et al.) Maximillien and Williams report that, measuring a team in IBM using TDD, the defect rate was reduced by 50% with minimal extra effort, compared to using ad-hoc testing. Later George and Williams reported higher quality with slightly higher cost (The TDD'ers being 18% more expensive than the control-group, and the authors speculate that the cost-difference was because the developers in the control-group did not write automated tests that they were required to do.) Nagapan, Maximilien, Bhat and Williams studied several teams working at Microsoft, and the core finding was that development cost increased 15-35% (measured in a subjective fashion, details omitted) whilst the pre-release bug density decreased with 40-90% (yes, one of the teams had a pre-release bug-density at 90% lower). There are some more studies, involving e.g. using student groups (with lacking experience) implementing the same features using either TDD or… that other approach - I don't know what to call it really - plain-old-hacking? But I think studies involving software professionals are more relevant. This is not a survey or meta-study, but the trend seems to be that if developers use TDD, quality is improved, with a small increase in pre-release cost.

As far as I'm concerned, the academic results places the choice between TDD and plain-old-hacking, squarely in the management camp. The development cost might be slightly higher,1 but an increase in quality that reduces both uncertainty and time spent in the "stabilization" period between feature-ready and actual release-time, should tilt the decision in favor of TDD. Plus, I'm quite confident that we can extrapolate the evidence to mean lower cost during maintenance and future development as well. Therefore, from a managerial and economical perspective, the only time you don't use TDD, is if you know you are building a short lived (e.g. development and maintenance totaling to less than a man-year) prototype that you know you are going to throw away (but damnit, the prototype was so successful, that you couldn't afford to chuck it… So there you are then, doing plain-old-hacking again writing legacy code from the start.) But this is opinion, based on others and my own anecdotical experience. And of course I want TDD to be "better" in some way, so I am definitely susceptible to confirmation bias.

Any such studies are, by their very nature, anecdotes. And the weaknesses with anekdotes are easy to point out by nay-sayers. E.g. we don't know the differences in skill-sets, perhaps the team who did TDD was rockstar programmers and still used more time, whilst the other team was mediocre hackers who could barely run the compiler and still delivered their product quicker than the rockstars. Who knows. Stupid rockstars who used TDD then. TDD-nay-sayers will latch on to any such weakness that can be found and never let go. Any (positive) academic result on TDD is bound to fall dead on the ground (I guess confirmation bias works both ways.)

On the other side, empirical evidence about TDD (or any other fab engineering tactics, like for example pair-programming) are also bound to be short sighted. Of practical reasons, they don't shed any light on the long term effects on a codebase evolving over the full lifetime of a library or a product. This puts us back to plain old rhetoric and creation of hot-air, breathing out what-if scenario argumentation, where the better and most convincing lawyer win the truth. We can not know how TDD influences productivity, quality and costs in a truly positivistic sense. That is, until we can simulate a skilled team of programmers, and then start two simulations at exactly the same time in their lives - in one which they use TDD and the other where they use plain-old-hacking - run the experiments a gazillion times (I don't have the time to brush up on the maths required to figure out how many experiments we need to run before we get a statistically significant result) and compare which one come out top cost-wise.

So what am I getting at really? After reading Proffitts blog-post, I realized that the academics is pretty much a straw-man when it comes to any one persons motivation for doing TDD. The real motivation should be the sentiment that as a software developer is a crafts-man. TDD, BDD, Design patterns, SOLID, Pair Programming or what ever technique or practice cannot be dismissed, without having put enough effort in to learning it, and practicing it long enough to do it well, and then choose to do it or not. After putting in the effort, I can make up my own mind. It's an important part of evolving and growing. That's why you should learn how to do TDD. Not because the quality of code becomes better (subjective and hard to measure, but it does, trust me on this), not because it make you work faster (you probably don't, especially not at the beginning), not because it makes the release-phase more predictive (it does that to), not because it makes you sexy (try "I do test-driven development" as a pick-up line) but - because in the end it expands your skill-set and the way you think about code.

If you don't do TDD, I don't think it says anything about your professionalism or skills as a developer. I do on the other hand believe that it might say something about you as a person. If you are not doing TDD, you are not doing TDD because you don't know how to do it. Because it's a skill, and learning this skill takes effort. Learning TDD takes a lot more effort than just doing the bowling kata a couple of times. Applying it in all kinds of different situations takes practice practice practice. And some have a bias towards not making that effort, unless the payoff in the other end is known. That's okay. I can understand that. Others yet have a bias towards not wanting to feel incompetent while learning the new skill, as plain-old-hacking have always worked in the past. I understand that as well. And then I think you are either one or both of those kinds of persons, or you just havent heard about TDD yet (unlikely, if you read this… )

So it boils down to these two kids swimming in a lake, where one say "Come over here, the water is warmer." The other kid can't know if that's the case. The only way to find out is to swim over and find out if the other kid was telling the truth. You can't understand the feeling you get, when you can do a totally safe large refactoring of your codebase, unless you have done it. Or the joy of plugging together the components you wrote using TDD and then have everything just working, without having experienced it. You can't understand how the unittests guides your design choices, without having the experience to understand how the unittests guides your design choices. When you start to get that, you are sucked in. You are test infected. And now, real quick, why isn't this a circular argument! Come over here, the water is warmer, and you'll understand it all so much better when you view it from this angle. I promise.

Footnotes:

1 I'm not convinced there is any added cost if you use TDD with, say, dynamically typed languages like Ruby, Python or Lisp.

2012-08-12

Presenter First with Qt

Somewhat recently a friend of mine sent me an article on the Presenter First pattern - a 'recipe' to build applications using the Model-View-Presenter (MVP) pattern with Test Driven Development (TDD). The article seemed to be tuned against C# and Java, so I wondered how I would apply Presenter First with Qt and C++. This is a short experiment with implementing a UI with Qt, using the Presenter First pattern.

The idea with the 'Presenter First' pattern, is to implement the Presenter first in a test-driven fashion. In the MVP-pattern, the presenter only see an abstract representation of the view and the model, listens to events from them and glue their behaviors together. In the PresenterFirst formulation from the aforementioned article, model and view are interfaces. Since we are using Qt, we want to utilize the signal and slot mechanism so both classes would be abstract classes that somehow inherits from QObject. For starters the Model can inherit QObject, and the View can inherit QWidget. Both will be abstract with only pure virtual functions and slots. While going through this blog-post I will put emphasis on the test-code and the Presenter code, and for the most part regard the View and Model code as 'given'. As you will see, the tests we implement turns out to correspond very closely to the usecases we are implementing and we are able to test all aspects of the behaviour of the application under user interaction.

The working example will be a simple "editor" with two controls: a list-view to list available entities by name on the left, and a text edit-view for editing the content associated with the name on the right. Lets imagine that the content are equations, so we call it an equation editor. When writing this, I wanted to try using a component from the Qt itemviews, because they are intentionally written in a way that merges the View and Controller components of a MVC-design. 1 This makes them a less-than-perfect fit with the MVP and PresenterFirst, but we'll see if we can make due never the less.

https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj71IdBwxZNY7GK4Mc8eM1Y_NsAyHkf1kqmk2WtYBqPFtKncyoxvNGq08XSXDXJzvd8lQnEK6WAfuyf0lrnrt_C020ctKHjKeil5hsYD1-hdAvaU_mf8IK_Yo6YFgvWPCJNO8MJkfob-YEL/s1600/presenterfirst_ui.jpg

The ui should look something like this. Equation names in the left listview, the actual equation in the textedit on the right.

When interacting with the editor, we would like to implement the following user-stories:

  • When I select equation named E in the dropbox, the equation should show in the equation editor
  • When I click 'new equation', a dialogue should show for me to select a name for the new equation, and the new equation should afterwards show in the item-view on the left
  • When the user edit the equation-text for an equation X, then select a different equation Y, and then again select the recently edited equation X, the originally written text for equation X should be displayed in the editor
  • When I click on a selected equationname, I should be able to edit it, and only the new name should be used to reference the equation

It won't be an equation editor yet after implementing them, but we'll be off with a good start! It doesn't matter which of these stories we implement first, even though the last story could benefit somewhat from doing the first one in the list first.

Let's dive right in. We start with the add-new-equation story. The first tests for the presenter could thus look something like this:

void
PresenterTest::test_addNewEquation(){
  MockEquationView * v = new MockEquationView;
  MockEquationModel * m = new MockEquationModel;

  Presenter p( v, m );
  QString equationName("new equation");
  v->user_createNewEquation( equationName );

  m->verify_newEquationCreated( equationName );
  v->verify_modelChangedRecieved( 1 );
}

This reveals the basic MVP design. The Presenter have references to an abstract Model and an abstract View, and listens for updates via some sort of event-model to glue their behaviours together.

http://www.gliffy.com/pubdoc/3791985/L.png

The overall design of Model View Presenter, and presenter first. The presenter only knows about the abstract representations of view and model, and listens to events.

During the development we will implement the abstract classes EquationView and EquationModel, with their mock-objects MockEquationView and MockEquationModel. The 'View' here represents the target UI form, while the 'Model' stores equation-names and equations and ties them together. After we are done, we add ConcreteEquationView and ConcreteEquationModel - the latter developed with the help of TDD.

We drive the test by telling our fake view that the user want to "create a new equation", and afterwards we verify that there was a new equation created in the model and that the view got an update about changes in the model.

To see what's going on better, I'll prefix all the functions on the fake version of the view used to "simulate" user interactions in order to drive the presenter and the model with "user_" - so we don't confuse the method-names from the test-double with the methods of the "real" view. Also - I'll roll my own mocks, I will not use a mocking library in these examples (even though I could have benefited from using something like Google Mock.)

How should we implement this behavior? If the presenter listen to a signal from the view that asks for creation of a new equation we would be in good shape!

Presenter::Presenter(EquationView* v, EquationModel* m)
 : view_(v),
   model_(m)
{
  connect(view_, SIGNAL(createNewEquation()), this, SLOT(addNewEquation()));
}

This makes it obvious where the events come from. It also clarifies a presenter-first idiom: We 'drive' the Presenter through simulated user behavior, created by programmatically interacting with a fake view-class.

Note that the createNewEquation and addNewEquation signal-slot pair have no arguments, but from the user story we are expecting a specific name for the equation to be created - the story even specify that a dialog should pop up. We can't have dialogues popping up in our automated unittests - there's no user on the other end - so I want to stub out that behavior. There are many ways to achieve this. In the example article that inspired this blog post, they fired an event to show the dialogbox. Instead in this example I just ask the view to create a new equation name for me through createNewEquationName, and let ConcreteEquationView pop up the dialogue, get the name, and return this from an interface function. For the test-view, I implement createNewEquationName so it returns the name passed with user_createNewEquation().

void
Presenter::addNewEquation()
{
  QString eqname = view_->createNewEquationName(); 
  model_->addNewEquation(eqname);
  view_->modelChanged();
}

The code above should be sufficient to make our test pass. The modelChanged() function can be a pure virtual function or slot on the View object, and in our MockView we just register that it has been called - we don't need to introspect the view in order to know that this test passes.

Below is the state of EquationView, MockEquationView and EquationModel at this point. The verification code in MockEquationModel is similar to that of MockEquationView.

class EquationView : public QObject
{
public:
  Q_OBJECT;
  EquationView(QObject * parent = NULL);
  virtual ~EquationView();

  virtual void modelChanged() = 0;
  virtual QString createNewEquationName() const = 0;
signals:
  void createNewEquation();
};

class MockEquationView : public EquationView
{
public:
  Q_OBJECT;
  MockEquationView(QWidget * parent = NULL)
    : modelchanged(0)
  { 
  }

  virtual ~TestEquationView()
  {}

  void user_createNewEquation(QString equationname) 
  {
    createNewEquationName_ = equationname;
    emit createNewEquation();
  }

  virtual QString createNewEquationName() const 
  {
    return createNewEquationName_;
  }

  virtual void modelChanged() 
  {
    modelchanged++;
  }

  void verify_modelChangedReceived( int correctupdatecount ){
    QVERIFY(modelchanged == correctupdatedcount);
  }

private:
  QString createNewEquationName_;
  int modelchanged;
};

class EquationModel : public QObject
{
public:
  Q_OBJECT;
  EquationModel(QObject * parent = NULL);
  virtual ~EquationModel();
  virtual void addNewEquation(QString equationname) = 0;
};

This completes the first story. Next we enable selection of different equations in the listview. To be certain that this story is complete, we need a model with several items, and we need to verify that the correct equation text is set in the text-edit after changing the index.

void
PresenterTest::test_indexChanged()
{
  MockEquationView * v = createView();
  EquationModel * m = new MockEquationModel;
  populateModel(m); // adds three equations. 

  Presenter p ( v, m );

  int indexnr = 1; // indexnr < number of equations defined in Model.
  v->user_changeIndexTo(indexnr);
  v->verify_currentEquationIs(m->getEquation(indexnr));
}

This drives a little bit of design. We expect that, when we change equation in the listview, the view must be told what equation to put in the equation text-box. So it seems that the Presenter must listen to some change-of-index event, be able to fetch the equation for this index from the model, and then pass the correct text from the model, to the view. The presenter needs a slot like this:

void
Presenter::changeEquationIndex(int equationidx)
{
  v->setEquationText(m->getEquation(equationidx));
}

The view class need a corresponding signal that we can emit from MockEquationView::user_changeIndexTo(int indexnr) (or from the concrete view when we implement that.) This signal-slot pair needs to be connected in the Presenter constructor.

Presenter::Presenter(EquationView* v, EquationModel* m)
{
  connect(v, SIGNAL(createNewEquation()), this,  SLOT(addNewEquation()));
  connect(v, SIGNAL(equationIndexChanged(int)), this, SLOT(changeEquationIndex(int x)));
}

Our fake view can then verify that it got the correct equation text. Our test passes. Now we know that the View have been told to display the correct data both in the listview and the equation editor. The story is complete.

The third story, and the third test, is for the edit equation story. When we edit the equation text in the text-editor on the right in the view, the text should be sent to the model.

void
PresenterTest::test_editedTextIsSetInModel()
{
  MockEquationView * v = new MockEquationView;
  MockEquationModel * m = new MockEquationModel;
  populateModel(m); // adds a couple of name-text pairs

  QString newText = "My new Equation.";
  int activeIndex = 1;
  v->user_changeIndexTo(activeIndex);
  v->user_editEquationText(newText);

  m->verify_equationText(activeIndex, newText);
}

In the test we simulate that the user chooses an equation through user_changeIndexTo, and then simulate that the user_editEquationText to something. Then, in order to verify that our Presenter works as we want it to we check that the equation-text sent to the model is correct.

In order to make this test pass, we need two things: A signal from the view that tells the presenter that text have changed, and a corresponding slot on the presenter that updates the equation-text associated with the current active equation. That means we would need to keep track of what the current equation is. The tracking of current state belongs in the presenter.

Presenter::Presenter(EquationModel * m, EquationView * v, QObject * parent) :
  QObject(parent),
  model_(m),
  view_(v),
  currentEquationIndex(0)
{
  connect(v, SIGNAL(createNewEquation()), this,  SLOT(addNewEquation()));
  connect(v, SIGNAL(equationIndexChanged(int)), this, SLOT(changeEquationIndex(int x)));
  connect(v, SIGNAL(equationChanged(QString)), this, SLOT(currentEquationTextChanged(QString)));
}

void
Presenter::changeEquationIndex(int equationidx)
{
  currentEquationIndex = equationidx;
  v->setEquationText(m->getEquation(currentequation));
}

void
Presenter::currentEquationTextChanged(QString equation)
{
  m->setEquation(currentEquationIndex, equation);
}

We added the connection in the constructor, added currentEquationIndex as state in the presenter, and implemented setActiveEquation. A handful of lines of code, and our test is passing.

No for the final test: Editing the name of an already added equation. So far we've only used signals and slots from Qt, and we have talked about how new equations come to be (and that this requires the View to receive a modelChanged signal) and how the text in the equationview is updated. But we have not talked about how the listview with equation-names to edit is populated - this have been a detail we could just gloss over so far. Now that we should be allowed to change the name of the equation in the listview, we need to supply an editable model from Qt's modelview components to the view and then test that the data stored in it is updated. Granted, we could make this work without using an QAbstractItemModel - we could somehow have kept the names in our model in synch with what's in the view by setting a QStringList of equation-names every time the model changes or adding and removing names by some other means. This would increase the amount of logic we would have to add to the concrete View-implementation - the code we are trying to keep as minimal as possible. By using an QAbstractItemModel on the itemview and simulate the interaction from the MockView, everything is more or less automated from the ConcreteEquationView's viewpoint.

For our next test then, the view must change the name for an item, and we need to check that the name is updated in the model.

void
PresenterTest::test_equationNameIsChanged()
{
    MockEquationView * v = new MockEquationView;
    MockEquationModel * m = new MockEquationModel;
    QString originalname = "Name0";
    int idx = m->addNewEquation( originalname, "Some text");
    Presenter p(m, v);
    QString newname = "Name1";
    v->user_changeEquationName(idx, newname);

    QCOMPARE( m->getEquationName(idx), newname );
}

The key driving function of the test - user_changeEquationName - simulates the behavior of the listview by first creating a correct QModelIndex for the name and then call abstractlistmodel->setData(index,data) to update the name stored in the model.

There are several valid alternatives for how to get an QAbstractListModel from our EquationModel:

  • The Presenter can act as a proxy and inherit from QAbstractListModel and get the necessary data from it's EquationModel reference.
  • We could create a concrete EquationListModel that inherit from QAbstractListModel and which take an EquationModel pointer as a constructor argument and sends getData and setData calls to it (again representing our model by proxy.)
  • The EquationModel it self could inherit from QAbstractItemListModel, and be both.

What matters most at this point, is that these are the options. There are three. Not four or five. A getter or factory-method on EquationModel that returns an QAbstractItemModel is a jolly bad idea. 2

In order to quickly make the test pass, I chose the last option - the EquationModel inherit from QAbstractItemListModel - then I only need to add a setData function to it, and use it to update the equation-name.

The constructor of Presenter now only need to be updated so that it passes the EquationModel (as a QAbstractListModel) to the EquationView, and after a correct implementation of setData my test passes.

Presenter::Presenter(EquationView* v, EquationModel* m)
{
  connect(v, SIGNAL(createNewEquation()), this,  SLOT(addNewEquation()));
  connect(v, SIGNAL(equationIndexChanged(int)), this, SLOT(changeEquationIndex(int x)));
  connect(v, SIGNAL(equationChanged(QString)), this, SLOT(currentEquationTextChanged(QString)));
  v->setModel( (QAbstractListModel*) m ); // cast for emphasis
}

Voila, all user stories implemented test first, without ever having to open an application with a Widget. So far so good.

There are several observations we can make while wrapping up here. Notice first how all the tests "simulate" the user interaction. The driving functions get names that are very simmilar to the user stories: user_editsEquationText is a good example. Also, notice how none of the tests actually calls functions on the Presenter, save from the constructor. The tests only calls functions on the mocks, and the behavior of the Presenter is then implicitly verified. All Presenter slots and functions can in other word be private. Both of these observations are in line with the experiences reported in the previously mentioned article.

I also want to emphasis how the tests are agnostic to many of our design decisions. Notice for example how test_changeEquationName is totally ignorant to our actual design choice - we can choose any one of the three alternatives proposed for getting a QAbstractItemModel, and the test still stays the same. Presenter First drives you to implement your tests on a comfortable distance from your design, where they support your design decisions without geting into the way when refactoring.

When using Presenter First with Qt, all UI-classes in most cases only need to relay signals from the relevant ui-components to the Presenter via it's own signals, and implement the slots to set the data to display in the correct ui components. A test of the GUI simply need to verify that it is hooked up - e.g. that pressing a button makes the view emit the correct signal - as the test-driver for the presenter tests the actual functionality behind.

There is a full example with a view implementation in addition to the tests at bitbucket. It's not an equation editor yet, but as far as being an example of Presenter First with Qt, it suffice. Thank you for reading!

Footnotes:

1 This is, btw, the design choice in Qt I have the biggest beef with as it lures the unwary developer to add tons of behavior in view classes. The result is often classes that mix responsibilities and are difficult to test.

2 I also might mention here that I usually just avoid the QTreeWidget by default. In order to avoid the duplication of data and the efforts needed to keep the QTreeWidgetItems in synch with the underlying datamodel I like to implement a QAbstractItemModel around my data instead.