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.
Misc musings about software development, agile, TDD, C++ and explorations in other programming languages.
2013-09-22
Clarify goals and objectives in 20 minutes
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
- "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.
- 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.
- 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.
- 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.
- 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.
- Collect loose papers and materials
- Process all inboxes, so they are empty
- Empty your head (on paper, for example)
- Review your Next Actions list
- Review the two previous weeks in your calendar
- Review the two next weeks in your calendar
- Review everything you are waiting for
- Review project lists
- Review any relevant checklists
- Review SomedayMaybe
- Be Creative and courageous
SomedayMaybe is a bad name
There are always too many projects
2013-04-06
12. Is Scrum "GTD for teams?"
2013-04-04
11. It's not the resources, it's the priorities.
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 paperthe 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.)
2013-04-02
10. If it works, fix it anyway
"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
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.
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
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
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:
- Next Actions
- Projects
- Areas of focus and responsibility
- Goals and intentions - things that should manifest in life in two to three years
- Vision - how should life be
- 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/
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
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
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 |
So - does this help in getting over the first crux while learning TDD? Please let me know!
2013-03-23
1. Blogging every day
2012-08-26
Why should you learn and use TDD in the first place?
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.
Footnotes:
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.

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.
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
QAbstractListModeland get the necessary data from it'sEquationModelreference. - We could create a concrete
EquationListModelthat inherit fromQAbstractListModeland which take anEquationModelpointer as a constructor argument and sendsgetDataandsetDatacalls to it (again representing our model by proxy.) - The
EquationModelit self could inherit fromQAbstractItemListModel, 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.


.jpg)

