Przejdź do głównej zawartości

Practical Scrum Training (4) Discussion of Product Backlog

This post is a base for a discussion that could be held with a group of developers, facilitated by a trainer.

Let's look at our Product Backlog again and color the items that seem clear and straightforward green and those that require further discussion blue.
  • In order to add new people to the family tree efficienty as a family tree user, I want to be asked if I want to add another person right after I added the last one
  • In order for the family tree to be easier to read as a family tree user, I want the graphical representation of the tree to present each generation in a different color
  • In order to secure integrity of family tree data as a family tree user, I want to have checks for all data I enter so that entering invalid data is not possible
  • In order to correct the information about a person in the family tree as a family tree user, I want to be able to edit the data of a person I choose
  • In order to distinguish the gender of a person in the family tree as a family tree user, I want to be able to assign gender attribute to each person
  • In order to maintain the data about births and deaths in the family as a family tree user, I want to be able to assign birth and death dates to each person
This coloring does not mean that all the green items are absolutely clear about the details, for example, the last item does not say if birth date should be mandatory. Maybe yes, maybe no. Maybe the customer wants this to be mandatory and we will need to persuade them that optional is a better option for birth dates. That is all OK - it is not the point that all such details are known straight from item title. It is just first "C" in 3C: "Card, Conversation, Confirmation".

Let's talk about the second item from the list - tree coloring. Why is it blue? The basic idea is easy to get. The concept of what a generation is clear. Even if we do not have the algorithm to distinguish between generations, we would be able to manually color even a complex tree, were it printed on paper. I think the only thing that needs to be clarified is how many colors will do. Saying just "each in a different color" may be difficult or impossible to meet for very large trees. But maybe our program will never be used for trees larger than 4 or 5 generations. Or wait, maybe that's not good assumption. So if we may have a user that wants to maintain 12 generations, do we need 12 different colors? Will the user actually be able to distinguish between them then? Or maybe it will be all good if we just have 5 colors and use them one by one to color consecutive generations and simply switch from 5th to 1st color when we still have something to color? Yes, this last idea seems just fine, we may agree later if that's 5 or something else.

That much for clarification, but is there possibility to break this item into a couple of smaller ones? No, it is what it is, either we do coloring or not. Would it be easier though, if we started from just two colors? Well, yes, it could make things a little bit easier. If we were to use just two colors we could just say that whatever the color of parent nodes is, the color of all their children should be the other one. I think this would result in proper coloring of generations (that is, alternating between two colors) for any family tree. So, even for such seemingly undivisable product backlog item, we were able to break it into two that we can order one after another:
  • In order for the family tree to be easier to read as a family tree user, I want the graphical representation of the tree to alternately use one of two different colors for each generation
  • In order for the family tree to be easier to read as a family tree user, I want the graphical representation of the tree to rotate colors of generations from a predefined set of colors
In next post, we'll discuss the product backlog item that says about data checks.


Popularne posty z tego bloga

Unit Testing code with IO file operations (in Python)

We may often come across a piece of code that was written without Unit Tests at all. In addition, the piece of code may be dealing with IO like file writing and reading, which makes it more difficult to Unit Test it when we are trying to refactor and modify. Let's suppose the code in question looks like this:

def writeInitialsToFile(filename, name, surname):
    initials = name[0] + '.' + surname[0] + '.'
    with open(filename, 'w') as file:

def readInitials(filename):
    initials = None
    with open(filename, 'r') as file:
        initials = file.readline()
    return initials

A straightforward and bad idea would be to write a couple of Unit Tests that make use of a real file and simply test the reading and writing. Is therea a better way to test this code?

First of all, we need a way to replace the real file with something else. For both reading and writing we will now have a couple of functions, one that expects a stream fo…

Piotr's Less Obvious Advice on Google Mock: Returning new objects from a mock

Google Mock provides a way to return newly created objects from a mock method. Suppose we have a  Generator class that is supposed to generate new objects when createNewRecord method is called:

class Generator
    virtual ~Generator() {}
    virtual Record * createNewRecord() = 0;

...and suppose we want to mock this class:

class MockGenerator : public Generator
    MOCK_METHOD0(createNewRecord, Record * ());

Suppose the caller class Client has run method defined as follows:

void Client::run()
    for(int i = 0; i < 3; i++)
        rec_tab[i] = gen.createNewRecord();

We want the mock to return a pointer to a new object each time createNewRecord is called. This is how we can express this in the test code:

TEST(ClientTest, CanRun)
    MockGenerator gen;
    Client c(gen);

    EXPECT_CALL(gen, createNewRecord())
                 //this is equivalent of returning new Record(1,2,3)

Piotr's Less Obvious Advice on Google Mock: State maintenance

Google Mock provides several ways to maintain state inside mock objects. One way of implementing state maintenance is with SaveArg. Consider the following example.

We have a class Configurator, which allows a caller to set and get values of a parameter:

class Configurator

    virtual ~Configurator() {}

    virtual void setParamX(int n) = 0;
    virtual int getParamX() = 0;

And we have a class Client that calls Configurator's methods and it also has a method incParamXBy, that can be used to increase the current value of paramX by a certain value.

class Client

    Client(Configurator & cfg);
    virtual ~Client() {}

    void setParamX(int n);
    void incParamXBy(int n);
    int getParamX();


    Configurator & _cfg;

incParamXBy internally calls setParamX and getParamX on Configurator:

void Client::incParamXBy(int n)
    _cfg.setParamX(_cfg.getParamX() + n);

Let's assume that the initial value of paramX is A and that we want to increase paramX by…