0

The usual workflow for my team looks something like this: features are planned by product management and then collectively broken down to business requirements. Then the developers start working separately through those requirements one by one until the next feature comes around.

One issue I noticed is since the stories are implemented in an incremental way the associated code tends to be slapped on the existing code. Initially it is easy to make sure the new code somehow fits with the old code. But over time portions of the codebase begin to diverge and the whole thing turns into patchwork.

I have been thinking an initial design story to put down method and test stubs, discuss the development strategy to follow etc. for the rest of the stories can help with this although I am not sure how exactly it would work.

Alternatively or alongside this I want to propose switching our code review system from a single peer review by a tech lead to a consensus system, but not sure how the alternative would look like as far as what everyone would review for, how much effort would go into it, what kind of standards we would follow or how I would go about proving it would bring value.

4
  • 3
    See pretty much everything under technical-debt.
    – jonrsharpe
    Jan 5, 2020 at 18:40
  • I am simply looking for advice on two somewhat concrete ideas I came up with. Not sure why I am getting voted down and told to just search technical debt
    – user313675
    Jan 5, 2020 at 18:42
  • 1
    @Victor. I also get frustrated about uncommented downvotes. If I had to guess, I would say that the primary challenge in your question is that it doesn't ask a particularly specific question that can be clearly answered. My answers to your two points are that I think design stories are, at best a crutch, and I like your idea of expanding code reviews because it shares knowledge. Those are my opinions and therefor make for poor answers. If you had a specific question about architectural drift, a specific answer may be available.
    – Daniel
    Jan 5, 2020 at 20:06
  • It sounds to me like you need some sort of overall design/architecture goal in mind, and work your commits toward that. "Clean" or "hexagonal" or whatever, the specific choice is less important than having that clear design goal.
    – KarlM
    Jan 5, 2020 at 20:46

4 Answers 4

5

Building an application piece by piece using Agile Development means you do not build what you do not need, but you still need to design the architecture for the application.

When I see a code base become a patchwork of enhancements with little technical direction I see a number of issues that should be addressed:

  • A lack of technical leadership on the team (think "architect", "architecture" and/or "system design")
  • A code review process that could use some polishing up
  • A team more concerned with hitting today's deadline
  • A general lack of communication between team members

All of these are fixable. Someone needs to be given the authority by management to provide technical leadership. Given the high level requirements and the basic roadmap for the product, someone in this role should be capable of selecting the appropriate architecture. They need to work with the engineering team to ensure enhancements fit the architecture by utilizing UML diagrams for each enhancement, enforcing this during code review (which is a little late in the game) or by a quick design meeting prior to starting work on a new story.

The code review process can be used to spot architectural issues and provides a means for coaching the team on proper coding practices. You mention the code review process involves a single tech lead as the final approver. If you are still getting sub-par code, I would question whether that "tech lead" is really technical leadership (see the previous paragraph).

Finally, the demands of making a date can be the crack in the foundation that takes the whole building down. The "tech lead" might be passing code that should be refactored or redesigned, because management has the whole team running a marathon at a sprinter's pace, and they are just trying to keep their heads above water. This, again, is where technical leadership comes in to play. At some point the tech lead needs to stand up and communicate with management the cost of perpetually chasing a date without giving the engineering team the proper time to design the software system.

This should not result in one person leading a bunch of brainless monkeys with keyboards. It is a conversation and group effort to design the application that starts with one person coordinating the effort and pointing the team to the correct application architecture. From that point on the team needs to increasingly take charge of the application design while the tech lead guides them towards the correct architecture.

2

What you describe is what Martin Fowler calls Flaccid Scrum.

The only solution to this that I can agree with are eXtreme Programming practices:

  • Test Driven Development
  • Relentless Refactoring
  • Pair Programming
  • Trunk-based development
  • Continuous Integration
  • Evolutionary design

And in general, focus on discipline and technical excellence. You must simply accept that it will take some effort (I would guess around 30%-20% of your development effort) to keep the codebase up to standards.

1
  • I think the last paragraph is key. The team need to recognise the problems with the code being patchwork, as they work on it, and take steps to fix that, either as technical debt or when adding new functionality. Jan 6, 2020 at 14:14
0

You should apply the open/closed principle and the single responsibility principle

This addresses a problem where code increases in complexity and coupling when features were added.

In the old way, we would extend the appropriate function by just one more use case. Do this long enough, and you will have long functions containing many use cases which are increasingly hard to test and risky to change.

I found it useful to assess how suitable the existing code is for modification before implementation gets started. In SCRUM, that would be in your definition of ready and the cost to refactor the existing code would be factored in during estimation.

If the refactoring is nontrivial, I like to create a separate story (enabler story) and mark it blocking the actual story.

For example, I recently needed to make a change how we instantiate database connections. However, there were about a hundred instances of copy/paste code where database connections were created. This code had grown over time with no oversight and everyone who needed to add a class to the database layer make a copy of an existing class and added their own code. I concluded the code was unsuitable for modification, and created a ticket asking to create a database connection factory following SRP/DRY principles.

I also wanted to refactor from SqlConnection to IDbConnection to increase the testability, but that turned out to require a lot of churn. It's important to remember what counts is to move the needle, ever so slightly, in the right direction. We won't clean up code written over the course of 15 years overnight. As long as we keep moving in the right direction, conditions will continue to improve.

-1

It sounds like your team needs to do more planning and grooming of the user stories. If you have tasks such as:

  1. Write save method for Books
  2. Write save method for Authors
  3. Write save method for Customers

and each developer does it their own way, you've clearly missed the chance to write a generic method (or pick a framework that does it for you). By the time a task reaches a developer, it's too late.

However, even with perfect planning, you still have changes that build up the patchwork. Attempting to plan for every possible future change is impossible, and results in needless complexity. The answer is to refactor whenever it gets too messy.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.