However great a programmer you are, you can't beat one great team. Teamwork makes the dream work.
But it's also true that a tech team always comes with incompetent junior programmers.
What a mess!
Years ago, I joined this team, and I happened to be the most able programmer in the team (that's why they hired me for help). I don't think I was exceptionally good back then, but it was just that most of the others were inexperienced junior developers.
As you might have guessed, the code base was just a mess. Functions usually had millions of responsibilities and tangled with each other. There were no tests, literally. However, we still had a constantly growing list of feature requests from the business owners. The team kept implementing features anyway, somehow finding a "hack". But, as they kept working, the mess kept growing to the point where I found a significant loss of productivity.
That's when I spoke up. I suggested refactoring the code in one meeting. By then, I had already learned what was going wrong and was confident that refactoring would pay off.
Hoever, there were a few challenges with the refactoring:
- There were no tests in the code base. So it was a lot harder to make changes
- No one in the team knew how to write tests
- They didn't even seem to realize what exactly was wrong with their code
I considered how I would deal with the issues. What I ended up doing was as follows.
Work with one volunteer
I first asked for a volunteer to help me with testing and refactoring.
Because:
- There were still a few minor change requests to be implemented, so we couldn't assign all the guys to the refactoring.
- Even though I could work on the testing and refactoring myself, I thought another developer should know what was happening.
I picked up one developer. He had about 2-years of experience but had never written a single test. But I found him more hopeful than the others. He was a nice guy to work with as well.
Test-harness the code
I first explained to him why we would need tests before refactoring. We started by writing E2E tests because the code was too tangled to put unit-test harnesses on. I set up the environment and wrote some initial examples to follow. As he followed me, he gradually learned how testing works.
Refactor to test
After covering all the app use case scenarios, we gradually started refactoring the code so we could write integration tests on them. We salvaged React components and functions from the deeply nested muddy code pond while running the tests to ensure safety.
After separating the components, we set integration/unit tests on each component. After finishing the job, we discarded the sometimes-flaky e2e tests.
By the time we finished the job, he had already learned how to write tests. I found it much easier to teach just one person in a peer-to-peer way than the entire team.
Spread the practice and culture
I told the team we finished the task. I suggested having a one-hour Zoom session with the entire team to review what we had done.
I have slideshowd the issues with the legacy code base. To improve, you first need to know the issue. Improvement comes only after knowing the reality.
Then, I held a hands-on session of unit testing, which they appreciated. I told them to ask the other guy (the volunteer) questions. I thought he would learn better by explaining by himself. And who knows what happens to me the next day? I might be dead. You can't rely only on one person in the team.
After a while, I left the team to travel around the world. One year later, I met the team again. One of the team said the refactoring benefited the application. He also said the refactoring I conveyed kind of changed the team's coding culture after that. I succeeded in seeding a culture in the team. The seed was the volunteer guy.