In the last few years, Async Labs has grown from 4 people to 25. It’s great to see such an enormous growth of our team, but this sudden expansion brought some problems with it:
#our processes weren’t scalable
#we didn’t have the developer’s documentation prepared
#our tasks and schedules were ad hoc organized and other similar issue
So we found ourselves in a situation where we had to introduce finite standards for our company (for the time being, at least).
My story as a developer
I come from an engineering background, having completed a Master of Science in Computing at the Faculty of Electrical Engineering and Computing. I also started working early on in my field, getting the much-needed experience in the real world.
During this time, I found that the developer’s process of defining and solving a task is pretty much the same as the engineering process.
The key difference is in the fact that engineers have to document each step of that process, resulting in a flow graph even before the actual tasks, while developers “just get it” and “feel [the process] in their guts”.
Here’s a graph of the engineering process:
So, having that experience, when we started talking about standardisation in development, I found myself (again) in this flow.
Standardisation in development
01. Define the Problem
The first thing we had to do was properly define what our major pain points were. As in development, this is the entry point to the task definition. We had had a couple of retrospectives previously, so most of the technical problems had already been written out: we had to define our GitFlow, backend, and frontend standards and guidelines, automate some things and clean up the legacy.
But this was just a part of the problem – the developer’s technical process only. We still had to talk about our internal processes around tasks, clocking, and delivering high-quality software.
A small digression…
In AsyncLabs, we share one key mindset – solve the problem and then pick the tool. Most of us have already worked at a couple of other companies and/or are very active in the community in our area.
This brought us a fair advantage of seeing what other companies are doing to be successful, not just from the external viewpoint, but from the actual gutters and real experiences.
Ok, back to the main topic.
So we got together one weekend and went through our process and the main problems we encountered in the last couple of months.
These are just some of them:
- lack of metrics (time-clocking, productive – non-productive hours, amount of time spent on educations, etc.)
- lacking QC/QA process
- Big feedback loop
- Poorly defined tasks
- Non-defined priorities
When we listed all of our problems, we prioritized them and sorted them in an Eisenhower Matrix on a piece of paper. This was later transferred to an actual timeline and action points that needed to be done.
02. Do Research
For each task, you have to do initial research to see if the thing you are building is, or rather, will make sense.
This phase for us was rapid: we knew that we need to organize our processes.
Keeping in mind our experience and mindset, we also knew how and what other companies do, so we recapped good processes we learned from them and talked about how we can apply for us.
03. Specify Requirements
In dev tasks, these represent your acceptance criteria. This is the bare minimum that you have to do when you start building your solution.
So we did exactly that: we have written ourselves a list of acceptance criteria. I, personally, am a major fan of The Golden Circle (the model, not the new Kingsman movie), so we have written our acceptances as to answer why we want to do this.
We also defined the flow of our tasks with the stages of defining a task, working on it, confirming it was appropriately done, and finally releasing it.
And for every stage, we defined our WHY:
We are flexible and adaptable to changes reflected through our time management and focus that arrived from good planning.WHY for Task stage
This phase is crucial because this is the entry point for the whole company. Stating why we are doing each stage is really important for the big picture, and it makes it easier to get people on board with large-scale changes.
04. Brainstorm, Evaluate and Choose a Solution
Now, finally, the juicy part, at least for me. 😄
After we defined our problem, we started working on solutions: choosing/abandoning tools, selecting processes, specifying how we communicate with clients, how we’re going to track employee satisfaction, etc.
We drew diagrams and expanded each stage from the previous phase. This gave us a bigger picture of what we are going to tackle as more minor problems. Finally, it looked like this:
And every single smaller problem was defined with its why. We then went on to how we are going to do every single element of our process.
Here are two examples:
We are doing Agile, specifically Scrum and Kanban, with all the included ceremonies.Task > Process
Meaning, we will organize our process with these approaches. Will this mean that we will never do Waterfall? No, it just means that we are going in this direction, and anything else besides this is an exception, not a rule.
We are applying Domain-Driven Design to our frontend and backend.Development > Architecture
This still doesn’t define what we are going to do, but it is a general overview. For example, when working with React: we can use either ContextAPI or Redux for the state management, but they will be organized cleanly, as it is described in Domain-Driven Design.
After this phase, we had a more detailed overview and definition for all the tasks we needed to do, along with our timeline.
Here are just some tasks we needed to do:
- Setup project boards in TeamWork (a tool that proved to be the best current solution for us, as opposed to using TeamWork, Trello, and Toggl in parallel)
- Define backend standards and architecture (create documentation)
- Specify frontend standards and architecture (create documentation)
- Define Git Flow
- Showcase time tracking in TeamWork
- Clean legacy code
- Organize education schedule
- Do SRMs with all employees
- Hold a quarterly company meeting
- Schedule a team-building, and many more.
With a clear picture of why and how we will do things, we went onto actual implementation.
05. Develop and Prototype Solution
We started with solutions that were quick and easy to implement. For me, this is the equivalent of how we approach our daily tasks to focus on the more difficult ones later in the day when we have a more specific type of focus.
Our first step was organizing our tasks and boards. This was pretty simple because we had to set up boards and columns on our projects, which is an effortless thing to do with TeamWork.
Then we created card templates to unify how we write cards—after that, transferring important things from Trello and setting everyone up with proper timing tools to clock their productive hours. With this, Trello and Toggl became obsolete for us.
That was actually writing out our Agile process documentation. In this phase, we organized an internal knowledge base to have all our documentation and processes described.
Alongside that, we created education schedules and several different schedules that will help us grow as a team.
The next step was defining our development process more thoroughly: the first thing was proper GitFlow, with exampled cases and potential problems we might encounter, thus expanding our knowledge base I mentioned before.
As a team, we didn’t just introduce official GitFlow or OneFlow or even Trunk Based Git. We took the best of all three and selected what will work the best for us. Also, we prepared git hooks for everyone and CI pipelines to decrease the feedback loop as much as possible.
Furthermore, we defined what Domain Driven Design means for us on the backend. The critical part here is our mindset: we choose a tool that is the best for a specific problem, not the other way around.
With this in mind, we had to communicate how we would do this cross-platform and cross-language. Luckily for us, we already worked on such a model, so we had many code examples in our projects and knew what will work for us.
So we took existing code and prepared a whole day workshop where we went through all of our examples and discussed everything. We named this DevPizzaDays, and we are hoping that we will hold these every month. 🍕😄
All of this we recorded with video or documentation. Documentation was sent to everybody to look at and discuss before we finally locked it in. We allocated time for that for each employee.
The following two days, we did SRMs with each employee where we gave and got feedback and talked about what we, as AsyncLabs, can do for our employees and explained their role in the company’s big picture. This brought us some additional pain points we immediately added to our task lists and prioritized for future iterations.
And much more, but I don’t want to bore you with other details. 😬
05. Test solution
For a developer’s task, you usually go through MergeRequest/PullRequest, where someone does quality control of delivered code. After that (or in parallel), you are doing quality assurance of the same code: testing that it does what it is supposed to do.
This phase was introduced in parallel with developing every single solution. We tested the clarity of documentations by having most of the people in our company reading it out. We also tested our architectures on projects we were working on, as well as our agile approach in day-to-day card lifecycles.
And then we went on to the next phase.
06. Solution Meets Requirements/Partially or Not at All
Luckily for us, all our solutions met our requirements. Does that mean we are super bright and brilliant? Not really. This just means we picked the excellent solutions in our current requirement space.
As time passes and the environment changes, so will our requirement space. But for now, we are doing a good job for ourselves.
07. Communicate Results
The last phase in every problem is actually showcasing the solution. For developers, that is releasing their code or reviewing it in front of the product owner.
We communicated our results during the quarterly company meeting and went over where we were and what we have done. We expressed that this is not the final form and that we still have some tasks to finish.
The whole team communicated how we are going to approach problems that will undoubtedly appear. We transparently shared our current position and the future of AsyncLabs. We got another excellent feedback and got everyone on the same page about the future.
We’re still not done with everything. We’re still adding things and solving them. But with the previously described process, we managed to explain why we are doing something and implement them in a standard flow most of us are familiar with.
By being reflective on how we solve things and what we need to do to find the solution, we had a reasonably simple solution space.
We managed to organize our company entirely in 2 weeks, following month of completely grasping every detail in our new standards.
So, I have a question for all of you out there: Now that you have the engineering terminology for your gut feelings, how will you start defining your problems? 😄