Beautiful Code?

I remember enjoying Jeff Atwood’s (aka Coding Horror) post about “code isn’t beautiful”. It took me a while explaining to myself why people are chasing after “beautiful code” so much. Why people are so passionate finding or forming beautiful code? Should great painters talk about beautiful colors or beautiful paintbrushes? I always thought they appreciate the entire painting, created and driven from emotions, dreams, ideas, styles and yes – colors & paintbrushes. They appreciate “the all” more then the exact technicalities. Why are we trying to figure out the best paintbrush to use or the best color? Why not trying to figure out the “best all”, the best experience, the best value, the best process?

I would define Beautiful Software as a surface to allow three magic abilities to emerge:

  1. It should be easy to add new Features.
  2. It should be easy to change existing Features.
  3. It should be easy for new teammate to become productive almost immediately.

If you’re able to have these abilities in your painting, your software, then you’re probably doing something beautiful; you probably figured out the correct paintbrushes, the right colors and most important – how to use them wisely to introduce true beauty.

I am not mentioning pseudo-code, language specific or whether or not testing is worthy. There are many ways to paint beautifully, it is up to you to figure out what makes software beautiful to you and figure out the right tools and process to achieve it. Don’t hang to tight to the “perfect algorithm” or “perfect Design Pattern”. There is nothing neither perfect nor beautiful about color or paintbrush by itself.

 

How to break Feature into Tasks: no leftovers!

Once you decide how to break a feature into tasks, it’s crucial to make sure you don’t leave any leftovers as part of the breakdown. Feature breakdown must include each and every task to make it a complete unit you can deploy as part of a version. Completeness means that not only a Feature is deployable and it can be monitored, it’s also with great external quality (no major bugs left behind) and great internal quality (design-review, QA test-cases review, code-review, UI review).

You want to price a Feature by the gross organization time; this is the only way to understand how much a Feature really costs. Knowing that, you can correctly price future roadmap without needing “Bugs Elimination Sprint” or “Big Refactoring Sprint” to introduce quality after things were delivered to your customers.

No leftovers:

1. Design review – may it be over emails or formal meeting, the design should be solid and well thought

2. QA test-cases review – making sure QA will test the right things or add more test cases for relevant edge-cases.

3. Testing time – writing tests (unit + integration) should be priced as part of the Feature, not after, not next sprint.

4. Code review – for knowledge sharing and internal quality validation.

5. UI review – making sure the UI look & feel just like Product team wanted it to be.

6. Bug fixing + validation buffer – fixing major bugs should be priced as well! if you’re not sure how much time to spend, start with 5-10% of the total estimated effort, and learn from your experience (by Feature size, complexity etc)

You can add more to this list, if the team/organization needs it. The idea is to make sure that once a Feature is complete, you’re feeling great about it and got confidence it won’t be fired back to the kitchen, to cook from scratch. You should have the same confidence about changing an existing feature; it should be easy, voodoo-less and highly testable to do so, with low chances of breaking other flows in the system.

 

Technical Features (in your) backlog

One of your responsibilities as a developer or team leader is to make sure you’ll be able to shine over time by constantly building confidence. This is why I strongly believe in maintaining a list of technical Features as part of your backlog. These are Features you believe will make the application more robust, provide better monitoring or make the team more productive (& happier) on their day-to-day work.

Have it to pass the message “we leave nothing as technical debt”

When someone in your team says “we really need to refactor this! it way too buggy and we cannot write tests for it”, don’t make it a technical debt that is written as a comment in the code or as a note on someone’s inbox. Make it a Feature, make it part of your backlog, pass the message that even though we cannot fix everything now, we will give it the right attention.

Have it to build confidence

Pick a few technical Features at each Sprint and make them a reality. This will make sure your team will be able to continue to produce fast and with great quality. Plan how much effort, from the entire Sprint, you would like to use to reduce waste – 1%? 5%? 10%? More? It’s really up to you. You need to balance it with thoughts of producing value to your customers while producing value to your team.

Have it for rough times

Having technical backlog is very useful when you need to re-plan the next few versions due to priority shift by the product teams, while your teammates are waiting for work. You can reduce pressure by letting them kill waste while you make certainty in the plans.

 

How to break Feature into Tasks

There are many ways to take a Feature and break it into workable unit of Tasks. Measuring “breakdown quality” is being ignored most of the time, as it’s very elusive to define “good breakdown”. The ability to break something into smaller pieces is one of the biggest signs of an experienced craftsman, so you should definitely challenge yourself by asking: am I known for predicting work effort well? detecting edge-cases early? Communicate progress to my boss clearly? being able to work with others on the same thing smoothly?

Introducing a Feature

Before we can play with breaking Feature into tasks, we need to have an example of a Feature in front of us. Let’s pretend that our desired Feature is “Signup and Sign-in” where to goal is to allow users to register and sign-in to the system. Next, here are the flows:
1. User can enter the signup page, if she’s not currently signed-in (else – redirect to homepage).
2. User can enter his details and signup.
3. User details will be validated, by [rules]. If failed – user will be asked to fix and re-send.
4. User will need to confirm her signup via email, before signing-in.
5. User can sign-in only after confirming her signup, if pending – show message.
6. User can sign-in in case she’s not signed-in already, using her credentials.
7. User can sign-out, only if she’s currently signed-in.
8. Page header needs to show relevant links, according to whether or not the user is currently signed-in.
9. If user fails to login multiple times (configurable), deny login for X minutes

[a few mockups here, a few technical/business notes there regarding URL structure, SEO to have in mind, analytics requirements, etc]

Breaking by Layers, the common way

A very common way is to break Feature by “application layers”:
1. Adjust database schema.
2. Create Data Access code to allow persistence of user (details, credentials encrypted etc) and retrieval of information.
3. Create Business Layer logic to validate credentials, confirm signup, perform sign-in.
4. Add signup and sign-in pages, alter header according to user state.
5. Add relevant validation on client side via javascript.

You can imagine that each task here will be a priced as 10-15 hours or even more, according to the implementer and the exact details. If the implementer founds an edge-case, it might mean that the every one of the layers here will be affected by it, making the estimation even less reliable.

Breaking by Verticals

A different approach will be using the flows above to form the tasks:
* create readConfiguration helper method
* create validateUserDetails method for server side
* create generateConfirmationNumber(userDetails) method
* create(/use) email sender provider
* create validateUserDetails for client-side
* create signup(userDetails) – schema to store user details, Data Access and Business to validate information and activate generateConfirmationNumber for sending confirmation email.
* create signup page (using validateUserDetails, signup method)
* create signin(credentials) method – schema to store number of login attempts, Data Access and Business to validate information, blocking user due to multiple attempts.
* create confirmUser method – Data Access and Bussiness to validate confirmation
* create signup confirmation page.
* create signin page
* create isLoggedIn method
* change header links according to status (via isLoggedIn)
* redirect user on entering signup page when currently signed-in (via isLoggedIn)

It’s not a 1:1 match between Task and flow, sometimes one flow will require multiple Tasks, but the flows drive the breakdown. No doubt, all of the tasks here are much smaller, each will take around 1-4 hours and very self-explanatory.

Why should you prefer Verticals breaking?

Confidence in achieving progress: if you strive for small tasks (up to 3-4 hours), it means that you’ll need to understand exactly what is needed to be done before committing to it. Every time you’ll finish a task, you’ll feel better that you’re moving on the right path. Because tasks are small, you will enjoy this feeling a few times during a day, which is important. You need to run away from “I wrote some code today, but I’m not sure if I’m on track”, poor planning will make you feel unproductive for long time.

Provide complete context to allow sharing workload: what happens if you need someone else to assist you? If you work by layers, it’s hard to understand “what is done”. The context is the entire Feature, which is too big to share easily. By working on vertical tasks, the context is much smaller as flows are smaller unit of execution. If you’re stuck, you can raise the flag and ask someone to assist you by taking a few vertical tasks and make them happen. They’ll have no trouble understanding what needs to be done.

 

Confidence building: make it part of your Sprint

One of the responsibilities of a great execution team is to make sure they will deliver in great speed and great quality, over time. “It’s a marathon, not a sprint” might be a confusing statement if you’re actually using Sprints in your development process ;)

What do I mean by “confidence building” and how does it affect you? Well, I believe that you need to earn others confidence over time, making sure your customers, internal and external, are happy with your results. For that you’ll need to make sure you understand what’s expected from you, to reach deadlines on time, to raise the Red Flag early and offer alternatives, to deliver product with great quality and to produce estimation that prove themselves as meaningful. Your job is to keep the execution machine at full speed and building the confidence as you go.

My recommendation is to make sure your Sprints will contain some internal maintainability time so you could stay on track rather than “have a good Sprint once in a while”. Here are a few thoughts:

  1. Bugs elimination – making sure the backlog is not overwhelming. Pick wisely, based on ROI given by product and technical teams.
  2. Provide rough estimation on the Features in the roadmap, review previous estimations and see if you were close.
  3. Push small POC for risky features to come.
  4. Create technical design for big/risky features you plan to address next sprint.
  5. Eliminating technical waste – small refactoring to enhance team productivity.

You can either treat them as features, or simply buffer some availability of the team to handle this.

No matter what, do not abuse the trust people have in you. Your boss hired you because s/he trusted you to do well, it doesn’t mean you don’t have to work hard and continue to earn her/his confidence in you.

It is a marathon, after all.

p.s. check out my latest side-project, SoftwareLeadWeekly – A free weekly email, for busy people who care about people, culture and leadership.

 

User Stories do not replace Features

User Stories became very trendy when Scrum became popular due to its smaller abstraction level; this made it possible to break big Feature and adjust its pieces into a single Sprint. I think this was taken too far, where User Stories sometimes completely replace Features. Not only I believe that Sprint should not be a release unit, I also believe that User Stories are not the correct work unit in a release or a Sprint:

1. Losing the why –User Stories by themselves are incomplete: they are missing the *why* – why do we think it is wise to develop this all experience? User Story describes only a small portion of a full experience. If we want to have real discussion on the value of a new capability, we must understand the full picture. The value always lies in the forest, not in the trees.

2. User Stories are usually not valuable to the customers by themselves – If you break a Feature into 20 User Stories, how many completed User Stories are enough to release the Feature? You cannot give your customer the Story of “A user can enter his password, the system will validate it by [rules]” without actually letting him register to the system. Your customer might enjoy tracking the Feature as you develop it this way, but you probably cannot release a version with 2 User Stories out of the 20 needed.

3. Maintaining another abstraction is expensive – what happens if a Feature changes? If you’re holding your User Stories separately, you’ll need to update them. Sometimes, as mistakes being made and it’s hard to sync papers, you’ll update one and not the other. So your business team, as an example, will work with the Feature paper but your QA team with the User Stories. Abstraction is smart only if it is beneficial over time.

I believe that User Stories are too pricey to be used as planning and execution units; they abstract a lot of the significant value Feature has to offer and introduce fragility in the process.

What User Stories are good for?

I would use User Stories only as a lingo between developers and business/marketing teams. They are small enough to be discussed without thorough background and big enough to explain behavior and expected outcome. I would not use User Stories to plan my sprints or my releases; I would aim to work in units I can deliver to my customers and discuss value of complete experiences.

How to adjust a big Feature into a Sprint?

More on it to follow…

 

Why Feature should detail full experience

Sometimes, multiple Features offer multiple experiences to the same motivation/goal/pain.

This is why it’s so crucial to document the why, the motivation, the pains, the reasoning behind a Feature. Although “The why” is crucial, it is not enough by itself. A great Feature must also detail the experience our users will enjoy, may it be capabilities, flows and look & feel. Only then, we can understand the purposed reality, before it is a reality – before we develop it and spend money to bring users to play with it.

With that, a real discussion on whether this Feature will be the best way to achieve this goal can take place. If you let your team be part of your vision building, by sharing the pains and goals, you can get invaluable internal feedback during “thinking time”. Fixing the Feature flows, improving usability or look & feel, before it’s developed, is always cheaper than doing it after it after the fact.

 

Feature, User Story and Task

Many confuse the terms Feature, User Story and Task. I believe it’s important to grasp the difference between them as each one serves different purpose and sometimes even different audience.

Feature

Feature is a detailed experience of how your users will do something with your application. In order to make “something” meaningful, a Feature must include (1) the reasoning behind it, the motivation, “the goal”, “the pain to solve” – without it, it’s simply impossible to judge Feature’s ROI in terms of value versus effort and money. Once this is in place, Feature should include (2) user flows. A user flow might be “User can click on the delete button to delete his record, this will popup [a message] for him to verify first”. Usually, a Feature will be built from multiple flows, edge-cases and wording to make sure the grand experience is fully complete. To help relating flow with look & feel, a Feature should (3) include mockups and other accessories. Lastly, (4) business (and even technical) notes should be added to wrap up the experience: URL structure, SEO considerations, user messages user, analytics requirements etc.

Language: customer’s lingo.
Estimation Size: Ideal Days / Story Points / T-Shirt sizes
Clients: Internal and external: development/marketing/business/analytics teams and also your customers (to share with them on feedback forums, blogs).
To Include: (1) reasoning (2) flows (3) mockups and (4) business/technical notes.

User Story

User Story is a single “user flow” from a Feature I described above. “User can enter his password and re-enter it for password verification. If the passwords are not matched, the system will show a message”. Another example: “User can enter his password; the system will check the password’s strength by [rules] and notify the user if the password is not strong enough”. By itself, from User Story is hard to understand the entire picture, but it’s a smaller unit of work to plan and execute by.

Language: customer’s lingo.
Estimation Size: Ideal Days / Story Points
Clients: mostly internal, sometimes external – some User Stories just don’t make sense on their own, without the Feature as complete background.
To Include: (1) flow (2) mockup and (3) business/technical notes.

Task

A task is a specific “todo” with a given work estimation. A Feature can be broken into multiple tasks and so does a User Story. A task will be something like “Add new column to database called Rate and model it in the application – 1 hour of effort”, or “create javascript function to validate input on price field – 1.5 hours of effort” or “create landing page for our campaign with Nike and connect it to our analytics system – 3 hours”. Task resolution will always be much smaller and much more technical than Feature or User Story. It will explain what to do rather than why.

Language: development/marketing/business lingo.
Estimation Size: Hours
Clients: internal only!
To Include: technical information needed.

 

Great Sprint Demo: the recipe

As I mentioned, you should not tie sprints and releases together. I thought to add a few notes about what will make a Sprint Demo really great. Luckily Moran Haviv, our legendary Project Manager at Delver, wrote a great recap I thought to share with you:

Why Sprint Demo?

· The primary purpose of the Demo is to communicate, share and celebrate what everyone managed to do in the last sprint and what is the value of it for the user/Organization; In other words: what are we doing here and Why are we doing it?.

· Collect valuable feedback to make sure our users will love our product as much as we do!

· Teams gets to show off with their output/artifact to everyone; (even if the software has no UI it might yet deserve to be presented by a good story).

A few guidelines for preparing great demo

  • Tell a story. Center your demo around a realistic user solving a real problem. The point is not just to show that the software works, but to show that it’s valuable.
  • What is a good Story? Or How can you tell it :
    • Use a meaningful relevant theme;
    • Demonstrate sequence of events as the user would experience them (tell the story);
    • Use realistic data and characters—use examples and names from your user community or members of the development team;
    • Make it Exciting and Entertaining
  • Keep it short. focus on what’s interesting and what’s valuable about your feature (you don’t need to exhaustively cover all your acceptance criteria).
  • Prepare. Create any necessary test data.
 

Version: extract releases from sprints

Separation of Concerns

Working by the “scrum book”, sprint is also a release unit, in which you want to complete all the effort you committed to your clients and demonstrate it at the end of the sprint. Well, not in my book. Sprint should be remained an internal unit of time. Sprint is used for planning, for doing and for reflection, to make the team work better over time. It doesn’t mean that your customers will enjoy adjusting to your schedule.

I prefer to leave release cycles outside, as they are external unit of time. You need to adjust them to your customers, not the other way around.

Let’s say that you picked 3 weeks as a sprint size after considering “big enough, small enough” values. If you tie sprint and release together, that means that your clients will see things every 3 weeks. That might be fine, but it won’t allow you to challenge yourself to reduce release cycles. Even worst, the customers might demand a shorter release cycle to earn confidence in your delivery. A dangerous move, in my opinion, is to reduce the sprint size to match desired release cycle. This move might violate the “sprint should be big enough to avoid unacceptable overhead of planning/reflection” principle. Yes, your customers will be happy but your developers won’t. It won’t last. You want both internal team and external customers to be happy and enjoy a process that pushes them forward rather than pushes them around.

What is a Version?

Version is just a bunch of capabilities with a specific target date attached to it. Version is easy to communicate out: “we plan to allow a user to upload image, crop it and update his profile image in version 1.1, which is targeted to July 20th”. Basically, for each targeted date you specify a list of features, enhancements, reports etc. The customers gets to say when the versions should be aimed for, according to their needs.

What does it mean about Sprint Demo then?

Well, if the release cycles are shorter than sprint cycles then the Sprint Demo will become a show off by the team to each other rather to your customers. Obviously, you may want to add another “Release Demo” meeting for your customers (and maybe include the team in it). By doing Sprint Demo internally, the teams will get the chance to see what’s going on “on the other side of the corridor”. Oh, did I mention that this is also fun? It allows the organization to collect valuable internal feedback to make sure our users will love our product as much people who wrote it!