Learnings from “no failure”

Marc Villagrasa
Jun 14 · 8 min read

After a year of hard work if the goal hasn’t been achieved someone could say we have failed. But in this case and like the Norm Kerth said:

“Regardless of what we discover, we understand and truly believe that everyone did the best job they could, given what they knew at the time, their skills and abilities, the resources available, and the situation at hand.”

We have done the best work we can with our knowledge and our environment. Even though our product hasn’t produced the expected profit we need to have very proud of our work and learnings did in this project.
This article tries to explain the experiences and learnings during the last year working in Genioo.

How we play

Spring 2018. Two partners have reaped funds for starting a project. It is time to create a team.

They did a selection process that included a funny interview. The test was a role play: the candidate starts in a new job, his first day at work he needs to do paring with a colleague that has a hangover and they need to solve a problem requested by a business person.

They evaluated both the technical skills and how the candidate works with business people. I know that this type of test is most common in London than here, it’s worthy to another article itself.

Finally, in August 2018 the team was ready, it was composed by 1 product owner + 1 business analyst + 3 devs. But nothing was written,
the first tasks should serve to see how we would play it.

We put on the table our experience (our “cards”) and ideas in order to define How we going to play as a team. Always we had in mind that these decisions were a starting point and could be improved after retrospective sessions.

Kanban

We were going to use Kanban, the tasks would be defined as Github issues and a physical card would identify the issue in a physical board, where we will represent the task status.

Throughout the process, we have been very demanding in the definition of the tasks and we have improved it along the time.

Three Amigos. The PO and BA define the task with explicit acceptance criteria, before play the task we do a “Three Amigos”. A lot of things happen after “business, development and testing voices” talk together (we don’t have a specific QA role, but someone in the team takes this hat).

We invest the necessary time in every three amigos. We verify what the task need to do and why we need to do the task. The complicity between business and dev is total and sometimes the task is completed with new acceptance criteria, and sometimes is simplified in order to do the minimum necessary to achieve the task goal. But always it was improved after these talks.

Issue checklist. After iterations, we add a checklist in the task definition. This checklist was completed on the three amigos session and it reviews aspects like:

- Is the outcome of this story defined?
— [ ] Yes
— [ ] No

- Do we need to implement new metrics to measure the outcome?
— [ ] Yes, and they are included in the story
— [ ] No

- The implementation of this story affects the data in production?
— [ ] Yes -> How do we fix it? _[TBD]_
— [ ] No

- Do the ACs describe the behaviour without connectivity?
— [ ] Yes
— [ ] No

- How is the story gonna be tested?
— [ ] Manually
— [ ] Testlab for multiple devices
— [ ] Smoke test must be adapted
— [ ] Others _[TBD]_

- If the story needs remote configuration, are the default values described in the story?
— [ ] Yes
— [ ] No

- We need to test:
— [ ] User App
— [ ] Expert App

- We need to release:
— [ ] User App
— [ ] Expert App

- Do we need a force update?
— [ ] Yes
— [ ] No

- Do we need a feature toggle?
— [ ] Yes
— [ ] No

- The implementation of this story affects users/experts that do not upgrade the app?
— [ ] Yes -> How? _[TBD]_
— [ ] No

- Does this change have an impact on security?
— [ ] Yes -> What impact? _[TBD]_
— [ ] No

- Does it have an impact or relationship with other US?
— [ ] Yes -> What US? _[TBD]_
— [ ] No

WIP’s. We use Kanban with wip’s limits. In my previous experiences, I had not realised the importance of this measure. But in this context, a small team, it takes relevance, since it forces the team to focus on the tasks that are more to the right. If some dev had to do a QA task he did it, if someone needed to define a history he also did it. And the times that we skipped them, we surpassed the maximum “in dev” or “in qa” tasks, we had a bad impact in our flow.

Put WIP’s in your Kanban and experiment with them, it can improve your flow.

How to Manage code

Another thing that we needed to decide is how we organise our code and how we will deploy it to different environments.
In this context, we didn’t innovate anything, we use GitHub as a repository and Circle CI to automate our pipeline, but for me the following aspects were new:

Monorepo

Our project involved an Android application and a set of backend services, a part in AWS and another part in Firebase. We decided to organise our repo as a Monorepo, in that case, the code is placed in a single project, of course properly ordered in folders.

In the beginning, it seemed crazy to me and it smelled me to a monolith, but quickly I saw that one thing is the repo organisation and the other is how you deploy your artefacts.

After a year using this model, I don’t appreciate any big inconvenient, apart from the size of the project, instead I appreciated some advantages as that you have a single version of your application, including in our case the Android app and the rest of the services. One product one version.

Note that, at the beginning we tried to use BUCK as a build system because we expected it improves the building time. After a while, we realised that it limits some Android features not supported by the okbuck plugin, and we changed to Gradle.

Continuous deployment

We wanted to go fast to production in order to get feedback as soon as possible and to work in small steps.
We decided to try to use continuous deployment. To get this we did:

No branches. All commits in the master branch, and every push in master go to production. Two considerations:

  • For android application, a RollOut is required before customers have the new features available.
  • Using branches was not prohibited, and for a specific feature, we used it.

Test. To be confident with our code we need to create a battery test.

  • We used TDD when it was possible, I must admit that in this aspect Android makes it a bit difficult, but we did all possible unit test in Android despite its framework.
  • We designed an integration test for all our business critical paths, and we automated it in our pipeline. Using Firebase Test lab we executed this test for each of the most used Android APIs.

Feature toggle. If a new feature didn’t have a sense if it was not complete, we used feature toggle to activate it when it was finished.

Because we could go to production when we needed, we used hardcoded features toggles and using Android variants we could promote the feature for each of our environments (DEV, QA, PROD).

What language are we going to use?

In our case, we developed a project that includes an Android application and backend services. In this context, we decided to use Kotlin.

Only the Android developer had experience with Kotlin but we thought that if the backend guys needed to do some Android task will be fine that they had Kotlin knowledge, with this and our motivation to learn new things we decided use Kotlin as the principal language. Definitely, Kotlin is the new Java ;-)

Serverless

Backend guys, you need to implement your first service.

Without system guys in the team, we needed to decide on which infrastructure we were to deploy our backend services.

After a first attempt to use boots implemented with micronaut we realised of the complexity to deploy these services to production. Maybe due to our lack of experience.

We had decided to use AWS, and we could follow some of the available tutorials talking about to create a Kubernetes cluster in AWS, or even change and use another service.

Even though we had requirements that justified such a structure, in that moment it was a too complicated solution.

Using a Serverless framework allowed us, in a week, to deploy our first service in the different environments, using our pipeline.

And Yes, serverless with Kotlin why not? It works well.

After a year we can’t only say good things. No availability issues helped us to concentrate our efforts to solve domain problems instead fight with provisioning machines in production.

We have created some issues with some pending improvements referring to manage logs, monitoring or local execution.

There is a lot of information available about serverless, I have found especially useful:

Summary

This article is a little summary of the things I think are more relevant, and of course, each would be worth a separate article and I have others pending to review as:

  • Google Firebase (Real-time database, functions)
  • Some Android things (Testing with robolectric and test lab, architecture, …)
  • Why we ❤️ coroutines vs rx

It’s difficult for me to summarise all the learnings of this year. I hope someday Alex @_alexfdz make a talk about this project, perhaps in the Barcelona crafters conference, and he will explain it with more details. I will push for it.

This has been a challenging year. I’ve enjoyed a lot working with all the team. We are a good team and IMO we have done a very good job, with funny moments, good vibrations, beers and too much chocolate. We don’t fail, the only failure is not to try.

I hope the Genioo app get results in the next weeks or months and I wish it receives a new inversion. If you want to talk with the best experts at the best price, please use it:

The best words for Sebi Collell @sebicollell and Alex @_alexfdz . Thanks for allowing me to live this challenging adventure, for your transparency in the good and bad moments, for demonstrating that to build a company it is necessary to be a Genioo like you, but also have a great heart.