Developing a Team for Re-engineering
For six months now, I’ve been building a team to take on the re-engineering of a legacy code base for scalability, performance, and to provide flexibility in the core processing components to accommodate differences in global regulatory requirements. To take on this project, I have a smart, but largely inexperienced team. I am finding my usual strategy for training, and professionalizing new developers insufficient, so I’ve decided to try something new. This is the beginning of my experiment.
Here’s what I’ve tried so far: TDD katas running the standard exercises, String Calculator, Bowling Game, etc. I’ve recommended reading Working Effectively with Legacy Code, Clean Code, and The Pragmatic Programmer. I promote stewardship of the code. Even my most junior team member is expected to take responsibility for tasks, review the code of other team members, and make decisions about how to implement and test features. It’s a safe team to make decisions, and to make mistakes.
In a lot of ways, this approach is working. The team is increasingly effective and independent. We’re delivering code, and testing thoroughly in sprint. But, in many ways, we’re falling short of our goals. Overall confidence on the team is low. The quantity and severity of changes required following code reviews, or as a result of defects discovered during test is driving an impulse to seek approval before committing to low-level design decisions. Knowledge silos build up extremely quickly as an individual (or pair) learn how to interact with the legacy code or framework, then take all similar subsequent tasks to accelerate completion of a story, or sprint. We’re also failing sprints due to a combination of poor estimation, and defects discovered during testing.
I believe that the root of our problem lies in our attempt to work both on a new type of problem, and on that problem in an extremely complex code base. For example, the team recently introduced MyBatis to handle new database interactions instead of continuing the use of a custom DAO framework oriented around stored procedures. For everyone on the team, MyBatis is a new tool, but they’re also trying to integrate this with the WebLogic data sources, to replicate behavior in code, such as transactional updates and audit trails, which have typically been provided by the stored procedures, and to do all of this with complex objects.
There’s too much newness here. As a result, the team has struggled to break big problems down into smaller components. They’re not sure if the failure of their MyBatis DAO is related to the MyBatis configuration, the JNDI lookup of the data source, and since both tools are new, they didn’t know how to configure one at a time and test.
I need experience that I don’t have, so I’ve decided to try and produce it artificially. Starting next sprint, I’m replacing my TDD katas with targeted exercises to practice simplified versions of problems that we’ll be facing in the future. I’m going to take my real code, pare it down, and then present a piece of the upcoming problem as a TDD exercise. I might ask the team to replace a stored procedure with a MyBatis DAO, but the procedure itself will be simple and clear, the objects small, and I’ll provide explicit connection details rather than a JNDI lookup on a WebLogic server. We’ll still test first, but we may need to first refactor for testability, and we’ll still throw away our code at the end of the exercise.
The result, I hope, will be that when we encounter the problem in our code, the team will have experience with at least some part of the solution. We’ll reduce our unknowns, and we’ll know how to break the problem into smaller pieces because we will have experienced a small piece already. We will address our complexity as complexity, and avoid getting stuck on simple problems concealed by complex code and interactions.