Mat Ryer Profile picture
5 Oct, 19 tweets, 4 min read
I agree with @ScribblingOn

It's time to get rid of estimates in software engineering. They don't work, do more harm than good, and drive people to act in dishonest ways.

Buckle up people, it's a thread.
"How long is this going to take?" feels like a completely reasonable question, but how come "I don't know" isn't a
reasonable answer?

"We just need a ballpark figure, you won't be held to it," they lie.

Well how come we just had to work the weekend?
Estimates are an effort to try and predict _when_ something is going to be ready. This is necessary so the rest of the business (sales, other dev teams, cult leaders, etc.) can line up and coordinate their efforts.

The reason for estimates is entirely respectable.
The trouble is, we don't know how long something is going to take. We just don't know. It's a hard truth, but truth nonetheless.

In rare cases, work is repetitive enough to allow for accurate estimates - but most of software engineering is all about building something NEW.
The worst time to make decisions about how long something is going to take is at the beginning (or before) we've started, when we have the least amount of information.

Even after just a day of working on it, we're infinitely more qualified to guess. But it's still guessing.
So people started to build in a 'buffer'.

Some say, "have a guess and add a week" or even "double it".

I've ever heard of someone who multiplied the estimate by 4 before sharing them.

Does it sound like something is broken to anyone else?
The real trouble starts when we inevitably miss the targets.

All of a sudden, we're LATE. The team is BEHIND. We're FAILING. We're AMBER or even in the RED.

All of this avoidable negativity and blame is completely manufactured out of these "ballpark" estimates.
The self-esteem of team members and its impact on productivity is dismissed by some as irrelevant, "an emotional thing", or not professional.

Some people think it's some kind of weakness, rather than a simple undeniable objective reality.

A happy team is just more productive.
Telling a team that they're BEHIND does not magically make them work harder, it has a much darker, often hidden effect.

"Cut corners, add tech debt, skip tests, hack it in for now, just do whatever's easiest."

When you start to ignore the QUALITY, it's the beginning of the end.
Once there is one awful hack in the code, it's very easy to excuse another, and another, and so on.

The quality of our work needs to be non-negotiable.

medium.com/@matryer/broke…
So far I'm just complaining, so let me propose a solution that has worked, and continues to work for me.

I learned it when I was first studying Agile methodologies, and given it's such an old buzzword, is suspiciously missing from a lot of team's processes.
1. Pick a hard deadline for the work

Never mind estimating to guess when something is going to be finished. Fix the finish date.

This gives all interested parties something they can align with. They can even tell customers about it, depending on how brave* they are.
2. Fix the quality

No more cutting corners, or hacking things in. Only perform at the highest possible quality. No rushing. Test coverage should be perfect, all documentation correct and up to date, code a shining example of our best work.
3. Let the scope be the variable

Do less.

Commit to the deadline, but don't fix the tasks that need to be done in that time.

Focus on solving the problem, but allow the definition of that solution evolve.

medium.com/@matryer/halft…
This approach forces you to prioritise the important stuff.

You can't have everything, so what do you REALLY need by the deadline?

This is a very valuable exercise in understanding the real problem faced by users. It's a feature, not a bug.
Then trust the team to do their best, and to achieve as much as they can.

Devs are never happier than when they're delivering real value to the business, and solving real people's problems.
If you don't trust your team to do this, you have much bigger problems that will not be solved by holding your team to estimates that we're only supposed to be "ballpark" in the first place.
Pace.dev is a minimalist project management and team comms tool that admits these realities and others, and helps foster more positive working practices for teams.

So if you like this way of thinking, why not give it a go with your team for a couple of weeks?
(It won’t surprise you to learn that Pace doesn’t have estimations—we didn’t want to encourage teams to lie).

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with Mat Ryer

Mat Ryer Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @matryer

15 Sep
I always call into a run function from main in #golang passing in any system dependencies as arguments.

If I am going to parse flags, use arguments, and write to stdout, my run func looks like this:

func run(args []string, stdout io.Writer) error

pace.dev/blog/2020/02/1…

1/6
This means I can write normal Go tests that can call the run function, and there's no global state to mess around with.

func Test(t *testing.T) {
args := []string{"tool", "--debug=true", "./testdata"}
var stdout bytes.Buffer
err := run(args, stdout)
//...

2/6
This is nice because I can use any `io.Writer` as the `stdout`. In my tests, I use bytes.Buffer - which allows me to capture (and make assertions about) what the tool outputs.

I can also play around with any flags or arguments without having to do anything weird :)

3/6
Read 6 tweets
13 Sep
A bit more context on how we organise our #golang services at Pace.
Oto has a very simple definition format:

type Service interface {
Method(Request) Response
}

Which turns into:

func (s *Service) Method(context.Context, Request) (*Response, error) {
// todo: implementation
}
The pointer return is simply because I like returning nil in the error case:

return nil, errors.New("not today mate")
Read 8 tweets
30 Apr
This is the best PR I've ever opened. Someone has a PDF of my book in their GitHub repo. Image
UPDATE: the PR got merged 😂🥳

To celebrate I am going to BUY five copies of my own book (Go Programming Blueprints: Second Edition) for anyone who wants, it but can’t get it themselves.

Reply if interested and I’ll abuse a Go map to randomly pick five winners. Image
@goinggodotnet @ellenkorbes remember when we did this to pick lightning speakers? 😂
Read 4 tweets
20 Mar
#golang tip

You can use documented consts for simple values (like bools) to make code much easier to read and understand AT A GLANCE.

I wouldn't do this _all_ the time, but when I notice code is tricky to read, I do it.

Example follows... 1/4
Consider this:

Greet("Mat", true)

I'd have to look up the method signature to figure out what that 'true' was for.

2/4
If we had these consts:

const (
// AnimationOn will greet with a flourish.
AnimationOn = true

// AnimationOff will greet without animations.
AnimationOff = false
)

Glanceability goes up:

Greet("Mat", AnimationOn)

3/4
Read 5 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!

Follow Us on Twitter!