Our approach to quality at Volkswagen Software Dev Center Lisbon
Assuring quality on the demanding software products we build at Volkswagen SDC:LX is not easy. Saying we’re agile is not enough, so I’ll present the soft and hard factors that ensure the required standards are met.
As a disclaimer, this is solely my point of view.
- Team members are part of the hiring evaluation stages, which greatly improves compatibility and ensures culture and methodology continuity.
- Critical thinking is highly appreciated and everyone is free to challenge what’s defined and the others (regardless of the role). This is supported by our non-judgmental environment.
- We rely on a scientific approach to problems by setting hypotheses and assumptions and seeking to confirm or disprove them.
- Team empowerment fosters ownership: since the team is responsible for the product (building and operating it), everyone is more dedicated to it. We have a flat structure and teams are balanced (PMs, designers, and developers) for autonomy reasons.
- Context switching is expensive, so the focus is essential to our way of working. For example, you only work on a single product at a time. Also, we try to reduce work in progress.
- Discussions of good practices are welcomed, valued, and common.
- We promote rotation amongst teams and even offices (we run programs for the interchange of people between offices). This allows the sharing of ideas and solutions, comparing and learning, and questioning the implemented habits.
- A feedback culture promotes individual/team improvement (team, product, and office retrospectives, individual feedback, etc.). Everyone reflects on it and gets continuously better.
- Transparency and happiness are kept so everyone feels part of the office. Weekly office syncs are held with everyone and social events are regularly organized by the happiness team.
- A culture of constant learning is held. It’s common to share interesting articles and other web resources. We have a book library and free access to online courses. We organize, attend, and host events. We have internal weekly meetups where anyone can present something.
- Every potential product starts with a scoping meeting to define the boundaries of the problem to be tackled; this is followed by a discovery/framing phase to better understand the problem and validate if we should move on. If so, we do inception to develop an MVP so we can quickly test it within a real environment. This ensures we do the minimum to validate it quickly and get feedback as soon as possible (lean development).
- A user-centric philosophy is followed. Every feature in the backlog is written in a clear way that brings value to the user; this explains you won’t find stories split by backend and frontend — we always split “vertically”.
- We do small experiments within the teams and the office, by trying new things that could improve our work (e.g. regarding our practices). Everyone is free to suggest improvements.
- Most documents are produced in a collaborative way and are quickly iterated. This is achieved by the use of collaborative tools like digital whiteboards, word processors, issue trackers, etc.
- By constantly pairing, we are running continuous live code reviews, as opposed to decoupled/async code reviews; the feedback is immediate and contextualized, thus more valuable.
- Pairing guarantees knowledge sharing because of its nature and also due to the daily pair rotations. As a consequence, all the team knows the codebase/architecture and it’s less dependent on individuals (‘no heroes’ culture). Pairing also happens with designers and product managers (PMs) which promotes know-how sharing amongst roles.
- Decisions are debated which improves their quality. By default, they are done as a pair but if they feel needed, they’ll reach out to the team or even other teams for discussion.
- Besides all the automatic quality checks, manual testing is done by the team, per feature: developers validate the stories and PMs/designers accept them in a near-production environment.
- Continuous improvement happens at a codebase level. Refactorings are usually done when working on a story. Other refactors and tech debts are tracked so they are not lost (any team member can add them to the backlog). Keeping the code maintainable is a core value.
- Voluntary facilitators improve the quality and outcome of meetings. They make sure the meeting is time-boxed and focused. We start by diverging and converge in the end.
- Test-Driven Development (TDD) ensures a better software design and code gets documented and tested as a consequence. Since we focus on the behavior (BDD), the implementation derives directly from the user requirements.
- The whole team (and possibly other people) is frequently invited to design sessions (e.g. to design a feature) organized by the designers. This feedback is taken into consideration and the designs are iterated.
- Developers are full-stack which promotes feature know-how/ownership from top to bottom, start to end, and a skill set across multiple technologies.
- There’s a general passion for technology (that’s almost a requirement) but we have methods to make sure it doesn’t bias our decisions so we keep our focus on the users.
- The team is free to choose the languages, runtimes, and frameworks and tries to make informed decisions when picking them.
- For each language and runtime, we choose and set up our IDEs, editors, utilities, and plugins so that we get code warnings, tips, validations, autocomplete, etc. These are kept always up-to-date.
- Attention to warnings: every warning in the code editor, logs, or others, is a symptom of something, so we always try to fix them.
- Static code analysis: the code is automatically analyzed regarding code conventions and other concerns.
- Versions checking: we make sure that the latest versions of the runtimes, frameworks, and libraries are used. This reduces the number of bugs such as security fixes.
- Unit testing, integration testing, and end-to-end (E2E) testing are done by default for all software components, testing multiple layers and combinations. Since those are developed in TDD, we feel really safe when refactoring or adding features. All the test suites are run per code push.
- Continuous Delivery/Integration (CD/CI): the features are pushed to the master branch (trunk-based development) and automatically deployed to pre-production. That way, we don’t have to keep track of lots of feature branches and releases. The CI pipeline is constantly visible on a TV.
- Different environments in the CI before reaching production: if any test fails, the code is not deployed. This also gives more opportunities to find problems before production since all team members, directors, and POs use them.