23
don’t demo facts. demo stories! @girba I help developers not read code @girba I help developers not read code @girba

Don't demo facts. Demo stories! (handouts)

Embed Size (px)

Citation preview

Page 1: Don't demo facts. Demo stories! (handouts)

don’t demo facts. demo stories!

@girba

I help developers not read code

@girba

I help developers not read code

@girba

Page 2: Don't demo facts. Demo stories! (handouts)

designing value

designing value?

Everyone wants to get value. But, what is value?

designing value?something someone is willing to pay something for

Value denotes something someone is willing to pay something for. 1. Directly measurable: It can be that value comes from being able to do more; to do more reliably; to do faster; to do cheaper.

This is the kind of value that can be captured in an Excel file.2. Indirectly measurable: It can be that value comes from less tangible things such as how the thing makes you feel. User

experience is an example. This kind of value is non-linear and difficult to measure and even if some measurement happens, it is always approximate.

3. Even more vague: It can be that value comes from values. These are not even about the thing itself but about something that you are not even interacting with. It can be the manufacturing philosophy, it can be environmentalism, it can be equal employment rights.

Most often we only focus on the 1st set. For example, this is measured as throughput.

Page 3: Don't demo facts. Demo stories! (handouts)

designing value?

Before going further, let’s look at what design means.

designing value?choosing beautiful tradeoffs within given constraints

What is design? Design is all about choosing trade offs within given constraints. If there are no constraints, there is no design.

There is no single best way to embody value, and choosing the right one is a matter of taste, culture, experience, ethics, values.

designing value?

Do not restrain the design to only directly or easily measurable value. The other kinds of value are often more important. Yet, designing for this kind of value is usually more difficult.

In the end, we have the task of finding a balance between what is desired and what is possible. There is no perfect solution. There is only endless choice.

So, how do we design?

Page 4: Don't demo facts. Demo stories! (handouts)

Impact Mapping, by Gojko Adzic, comes with an interesting proposal.http://www.impactmapping.org

In many cases, the backlog is not a roadmap. It’s a tunnel: we go from one end, and after a long time we come out on the other one. We just split the work in small chunks to appear more flexible, but the backlog rarely changes.

A different proposition is to see a product roadmap as a roadmap that offers alternative routes to navigate a space.

Page 5: Don't demo facts. Demo stories! (handouts)

In this situations, the road is full of decision points that can affect radically the journey. Each of these decisions can be affected by customer reaction and empirical experiments.

designing value?

Impact mapping sounds great. Still how do you know it works? How do you know everyone is on board?

track value?

But, how do you test the presence of value throughout the team and company?You need feedback.

Page 6: Don't demo facts. Demo stories! (handouts)

usability habitability

https://www.dreamsongs.com/Files/PatternsOfSoftware.pdf

Let’s think of a system as a set of layers, such as the intended use, the actual user interface and the implementation (in reality, there are many more). If the value that should be shown to the user cannot be found in the implementation, how will we keep track of this value 2 years later? We likely won’t.

Now, let’s look at it from yet another point of view. When we talk about the experience of a user we use there term of usability. This is great as it allows us to focus on the user needs. But, the engineer lives in the software system for about half of his active life. It should follow that this system should be suitable for human inhabitance. It should be habitable (Richard Gabriel - Patterns of Software - https://www.dreamsongs.com/Files/PatternsOfSoftware.pdf). it should be meaningful. Unhappy, unmotivated people are unlikely to build value.

Btw, when was the last time you threw a perfectly reasonable implementation away only to redo it again in a different, more appropriate way? This is a hard proposition for Excel-based decision making, and it typically never gets to happen. That is why, the picture above shows a typical reality that needs to change.

track value?let developers show the value

Solution: let the engineers show the value.Why the engineers and not the marketing people? Or the POs?Because engineers are those that have to embody this value in the system.

feedback is key

The essence of agility is feedback. Quality of the feedback regulates the quality of the outcome.

Page 7: Don't demo facts. Demo stories! (handouts)

expose your assumptions

present your assumptions

present

Page 8: Don't demo facts. Demo stories! (handouts)

For example, in Scrum, the review is supposed to offer the space for obtaining feedback from stakeholders. But, does it happen in practice?

2 hours 20 people

1 man week every iteration

First, let’s look at the costs. Suppose you have a team of about 8 people. If the project is important enough, it is likely to attract an audience of some twenty people. If the review takes 2 hours, you have in your hands 1 man week worth of effort spent on the actual review.

a review is an investment

One way of looking at this situation is to view it as costs, and conclude that the amount of people that participate in the review should be reduced.

But, the review is an investment in feedback. You just need to ensure that you get its worth.

Page 9: Don't demo facts. Demo stories! (handouts)

if there is no feedback, it’s useless

The goal is to make feedback happen. If there is no feedback, it was for nothing. If at the end of the presentation, there is not even a single question, it was for nothing. This is a factor that can be observed.

if it does not affect product decisions, it’s useless

Talk without action is not particularly useful either. Effective feedback leads to a change in decisions, in behavior. That is something that can be measured.

present

Page 10: Don't demo facts. Demo stories! (handouts)

• presenting • is not • bullet • pointing

The act of presenting became synonym with shooting bullet points at people. This fails to animate the imagination, because everyone is busy dodging the bullets.

presenting is not even slide showing

To best way to get people on board is through stories. Presenting is storytelling.

presenting is story telling

To best way to get people on board is through stories. Presenting is storytelling.

Page 11: Don't demo facts. Demo stories! (handouts)

demoing is story showing

To demo is to show the story live. A good demo materializes your story and puts energies in motion.

as a

I want to

so that

This is a famous user story template.

as a user

I want to be able to search in any folder

so that I can find files and folders of interest

All you have to do is fill it in. It’s easy. But, this is no story. It’s just a set of facts. And facts do not necessarily make for interesting stories.

In fact the opposite is typically true: that is why iteration reviews are typically unexciting events that are dominated by technical details:http://www.tudorgirba.com/blog/you-click-here-you-get-that-considered-harmful

Page 12: Don't demo facts. Demo stories! (handouts)

I navigate to a folder where I think I have some folders and files of interest.

I just do not know exactly their names.

Would it not be cool to search in place and then continue the navigation?

This is a story about the same user story. It’s not a master piece, but it is more intriguing.

context I navigate to a folder where I think I have some folders and files of interest.

conflict I just do not know exactly their names.

resolution Would it not be cool to search in place and then continue the navigation?

It does not follow a template. It follows a pattern. A story pattern.The difference to the original user story is not dramatic, but it can make a difference in terms of how the audience responds to it.

This is how the search interface looks like in Eclipse:- Top-left: Searching for a type- Top-right: Searching for a method inside a file- Bottom-left: Searching for annotations is not directly supported- Bottom-right: Searching for declarations is clunky

Engineering-wise, these all work. But, it’s hard to get excited about them. And, it’s hard to tell a story about them, too.

Page 13: Don't demo facts. Demo stories! (handouts)

How could it look different? Here is an example from the Spotter interface that comes with Pharo (pharo.org / gt.moosetechnology.org):- Top-left: Searching for a class- Top-right: Searching for a method inside a class- Bottom-left: Searching for annotations- Bottom-right: Searching for files is as smooth

This interface is uniform, it’s simple and lends itself to a better story. This is not a coincidence either, as during the development, several versions were thrown away, precisely because the story was not smooth enough. How many versions do you usually throw away?

demoing is story showing

(the story behind the user story)

Not the user story. The story behind the user story.

content form

Demoing is adding living form to content. When do you build the demo?

Designing and building the form is typically perceived as an effort that comes after the main effort of designing and building the content. That is not an optimal process, because we cannot reason about content in the absence of form.

Page 14: Don't demo facts. Demo stories! (handouts)

content form

Content and form must co-exist, because neither has value without the other.

yesterday’s weather

Let me tell you a story about the very first scientific paper I ever wrote. It was about predicting changes in a software system using a Yesterday’s Weather metaphor.

http://www.tudorgirba.com/blog/yesterday-s-weather

30% 90%

In Switzerland, using yesterday’s weather as a predictor for today’s weather is a poor prediction model.

However, in Sahara, it is a great way to predict weather, given that most days look like the previous one.

This prediction model is contextual to the place, or system, in which it is to be applied. So, before applying this technique on a software system, we first have to see if it proved to be reasonable in the past.

Page 15: Don't demo facts. Demo stories! (handouts)

yesterdayWeatherProbabilityWithTopPreviousWENM: topPreviousWENM andTopCurrentENM: topCurrentENM | currentVersions previousClassHistoriesSortedByWENM yesterdayWeatherHits last2VersionsTopHistories last2Versions last2HistoriesSortedByENM x valuesCount previousVersionsTopHistories previousVersionsTopHistoriesNames over | currentVersions := OrderedCollection new. currentVersions addLast: (self allVersionNames at: 1).

yesterdayWeatherHits := 0.

(2 to: self allVersionNames size) do: [: i | self smelly: 'this algorithm is too big and complex'.

previousClassHistoriesSortedByWENM := (self classHistories selectFromReferenceVersionCollection: currentVersions) sortBy: [:a :b | a value getWENM >= b value getWENM]. currentVersions addLast: (self allVersionNames at: i).

previousVersionsTopHistories := OrderedCollection new.

x := previousClassHistoriesSortedByWENM first value getWENM. valuesCount := 0.

previousClassHistoriesSortedByWENM do: [ :each | (each value getWENM ~= x) ifTrue: [ valuesCount := valuesCount + 1. x:= each value getWENM]. (valuesCount < topPreviousWENM) ifTrue: [ previousVersionsTopHistories addLast: each] ].

last2VersionsTopHistories := OrderedCollection new.

last2Versions := OrderedCollection new. last2Versions addLast: (self allVersionNames at: (i-1)). last2Versions addLast: (self allVersionNames at: i). last2HistoriesSortedByENM := (self classHistories selectFromReferenceVersionCollection: last2Versions)

Once I had the basic idea, I just implemented it. And indeed, it turned out that my assumption was right. On some systems it makes sense, on others it does not.

I was happy, but I had a problem: I could not explain my approach to people.

(valuesCount < topPreviousWENM) ifTrue: [ previousVersionsTopHistories addLast: each] ].

last2VersionsTopHistories := OrderedCollection new.

last2Versions := OrderedCollection new. last2Versions addLast: (self allVersionNames at: (i-1)). last2Versions addLast: (self allVersionNames at: i). last2HistoriesSortedByENM := (self classHistories selectFromReferenceVersionCollection: last2Versions) sortBy: [:a :b | a value getWENM >= b value getWENM].

x := last2HistoriesSortedByENM first value getENM. valuesCount := 0. last2HistoriesSortedByENM do: [ :each | (each value getENM ~= x) ifTrue: [ valuesCount := valuesCount + 1. x:= each value getENM]. (valuesCount < topCurrentENM) ifTrue: [ last2VersionsTopHistories addLast: each] ]. previousVersionsTopHistoriesNames := previousVersionsTopHistories collect: [ :each | each value name]. over := false.

last2VersionsTopHistories do: [:each | ((previousVersionsTopHistoriesNames includes: (each value name)) and: [over not]) ifTrue: [ yesterdayWeatherHits := yesterdayWeatherHits + 1. over := true]. ]. ].

^yesterdayWeatherHits/(self size - 1) asFloat.

Even if Smalltalk is a beautiful language, my code was plain ugly.

yesterdayWeatherProbabilityWithTopPreviousWENM: topPreviousWENM andTopCurrentENM: topCurrentENM | currentVersions previousClassHistoriesSortedByWENM yesterdayWeatherHits last2VersionsTopHistories last2Versions last2HistoriesSortedByENM x valuesCount previousVersionsTopHistories previousVersionsTopHistoriesNames over | currentVersions := OrderedCollection new. currentVersions addLast: (self allVersionNames at: 1).

yesterdayWeatherHits := 0.

(2 to: self allVersionNames size) do: [: i | self smelly: 'this algorithm is too big and complex'.

previousClassHistoriesSortedByWENM := (self classHistories selectFromReferenceVersionCollection: currentVersions) sortBy: [:a :b | a value getWENM >= b value getWENM]. currentVersions addLast: (self allVersionNames at: i).

previousVersionsTopHistories := OrderedCollection new.

x := previousClassHistoriesSortedByWENM first value getWENM. valuesCount := 0.

previousClassHistoriesSortedByWENM do: [ :each | (each value getWENM ~= x) ifTrue: [ valuesCount := valuesCount + 1. x:= each value getWENM]. (valuesCount < topPreviousWENM) ifTrue: [ previousVersionsTopHistories addLast: each] ].

last2VersionsTopHistories := OrderedCollection new.

last2Versions := OrderedCollection new. last2Versions addLast: (self allVersionNames at: (i-1)). last2Versions addLast: (self allVersionNames at: i). last2HistoriesSortedByENM := (self classHistories selectFromReferenceVersionCollection: last2Versions)

Page 16: Don't demo facts. Demo stories! (handouts)

yesterdayWeatherProbabilityWithTopPreviousWENM: topPreviousWENM andTopCurrentENM: topCurrentENM | currentVersions previousClassHistoriesSortedByWENM yesterdayWeatherHits last2VersionsTopHistories last2Versions last2HistoriesSortedByENM x valuesCount previousVersionsTopHistories previousVersionsTopHistoriesNames over | currentVersions := OrderedCollection new. currentVersions addLast: (self allVersionNames at: 1).

yesterdayWeatherHits := 0.

(2 to: self allVersionNames size) do: [: i | self smelly: 'this algorithm is too big and complex'.

previousClassHistoriesSortedByWENM := (self classHistories selectFromReferenceVersionCollection: currentVersions) sortBy: [:a :b | a value getWENM >= b value getWENM]. currentVersions addLast: (self allVersionNames at: i).

previousVersionsTopHistories := OrderedCollection new.

x := previousClassHistoriesSortedByWENM first value getWENM. valuesCount := 0.

previousClassHistoriesSortedByWENM do: [ :each | (each value getWENM ~= x) ifTrue: [ valuesCount := valuesCount + 1. x:= each value getWENM]. (valuesCount < topPreviousWENM) ifTrue: [ previousVersionsTopHistories addLast: each] ].

last2VersionsTopHistories := OrderedCollection new.

last2Versions := OrderedCollection new. last2Versions addLast: (self allVersionNames at: (i-1)). last2Versions addLast: (self allVersionNames at: i). last2HistoriesSortedByENM := (self classHistories selectFromReferenceVersionCollection: last2Versions)

And I knew it was ugly and that I should do something about it. I just did not know what.

present

past future

YesterdayWeatherHit(present):

past:=all.topChanged(beginning, present) future:=all.topChanged(present, end)

past.intersect(future).notEmpty()

prediction hit

So, I stepped back and rethought the model behind. What exactly was I doing?

I eventually created a small picture and based on that I rethought the model. It turned out that the algorithm to check the assumption for each day was three lines long.

And I could explain it to people in 3 minutes. And they got it.

hit hit hit

YW = 3 / 8 = 37%

hit hit hit hit hit hit hit

YW = 7 / 8 = 87%

And obtaining the overall value was just an average.

Page 17: Don't demo facts. Demo stories! (handouts)

yWFor: yesterdayCheck for: tomorrowCheck | hits | hits := (self detailedYWFor: yesterdayCheck for: tomorrowCheck) sum: [ :each | each isEmpty ifTrue: [0] ifFalse: [1]]. ^ hits / (self versions size - 2)

yWFor: yesterdayCheck for: tomorrowCheck ^ ( 3 to: self versions size ) collect: [ :i | | yesterday tomorrow | yesterday := self selectByExpression: yesterdayCheck appliedFromVersionIndex: 1 toVersionIndexAndPresentInIt: i - 1. tomorrow := self selectByExpression: tomorrowCheck appliedFromVersionIndexAndPresentInIt: i - 1 toVersionIndex: self versions size. yesterday intersectWith: tomorrow ]

And, in the end, even the actual implementation became similarly simple (and even more generic).

All in all, it was because I could not present the idea, that I had to rethink the approach altogether. Of course, I could have just accepted that the problem is just too complex and cannot be made simpler, but that is never a good enough point.

http://www.tudorgirba.com/blog/yesterday-s-weather

content form

Content and form must co-exist, because neither has value without the other.

V. S. Ramachandran is a neurologist. Among other things, he invented a simple cure for the phantom pain.

The idea is that people with phantom limbs can still feel pain in the non-existent part of the member. The problem is that this pain cannot be treated directly because it is actually not real. But, it is a serious problem, with people that constantly feel deep pain for decades.

Page 18: Don't demo facts. Demo stories! (handouts)

The treatment turned out to be extremely simple and cheap. A mirror is placed on a table, and typically the phantom limb is placed in a box behind the mirror, and the healthy limb is placed in front of the mirror. The patient is then asked to look into the mirror and do exercises with the healthy limb. As the patient looks in the mirror, it appears that the phantom limb is actually moving. Through these kind of exercises, the pain goes away.

You can find more information in his very interesting TED presentation:http://www.ted.com/talks/vilayanur_ramachandran_on_your_mind.html

content form

Form plays an important role in the way we perceive and think of the world. It is time to stop ignoring it and embrace it during the design process.

Have you ever wonder why is it that Apple allocates such a prominent place for showcasing the interior of their machines? This is particularly odd given that you will likely never get to see that interior.

Page 19: Don't demo facts. Demo stories! (handouts)

It’s not just on the webpage, but also the keynotes show the interior prominently.

And it touches all devices.

And most hardware features.

Page 20: Don't demo facts. Demo stories! (handouts)

Even the cooler.

The cooler! This is odd. Why?

And it seems that Google does the same, too.

Page 21: Don't demo facts. Demo stories! (handouts)

Richard Seymour: How beauty feelshttps://www.ted.com/talks/richard_seymour_how_beauty_feels

But, do you notice how none of the advertisements show the internal of software systems? Why? There is immense beauty in software systems, too.

content form

Form and content are equally important. One has no value without the other.

It is for this reason that you do not want to build the user interface at the end of the project. And it is because of this reason that you should not want to prepare the demo at the end of the work either. The idea of the demo should be a prominent artifact of the planning game. The team should work with the PO to identify an interesting demo before the main work starts.

Simply talking about what could an exciting demo be makes the team discover implicit specifications and forces the PO to distill the important parts. That is because in a demo you cannot show everything, and this puts pressure to everyone to focus on the most valuable parts.

Page 22: Don't demo facts. Demo stories! (handouts)

Demoing a system engages people. Engaged people give feedback. Feedback exposes assumptions.

And the system changes.

And at that moment, when all assumptions are out in the open, we can find new shapes and an equilibrium that better fits technical reality.

Page 23: Don't demo facts. Demo stories! (handouts)

content form

It is time to stop ignoring form and to embrace it during the design process.

Demoing is not an afterthought. It has to become an integral part of development.

don’t demo facts. demo stories!

@girba