33

I am on a team of ~20 people that is part of a very large organization. We have been using the same codebase for ~5 years and have released multiple derivative projects from it.

I've had some 1:1 conversations with team members and most of them are also aware of the various code smells and don't like them, but refactoring rarely happens because there is always something more important to do. I've also asked management if we could have some more deliberate planning or cleanup for the codebase, but I was basically told no. Everyone on the team programs in their own way and there isn't any coordination.

I am not asking for refactoring techniques here; I'm asking what are some ways I can help create a culture of writing for maintainability rather than pure functionality. Note: I am not a manager, so I can't just dictate things.

10
  • 4
    Apply rule 8 of the "eXtreme Go Horse" method.
    – Alexander
    Feb 20, 2019 at 20:08
  • 7
    Note: I am not a manager, so I can't just dictate things. Authority is bestowed, leadership is not. While you can't dictate anything, you can absolutely lead your team to consider best practices (refactoring, unit testing, CI/CD, coding standards, whatever). Demonstrate the value to your teammates, help them get setup with things, give talks about your approach. There are any number of ways you can be a leader without having the title, and in fact the best leaders would be such whether they had the title or not.
    – dlev
    Feb 20, 2019 at 22:42
  • 1
    Are you possibly mixing "management" (ie the guys worried about business) with the "engineering lead" (ie the buffer between you and management, responsible for the state of the codebase)?
    – Mars
    Feb 21, 2019 at 5:01
  • 2
    Don't be too idealistic. This might come as a surprise for many, but most people in the business don't care about code quality, either because they don't understand it or because they don't need it to reach their personal goals. The best you can do is gather more experience, more years and more authority, and thus gain more influence on the work of others. Feb 21, 2019 at 7:11
  • 1
    @Luaan: My experience must be completely different to yours, then. A typical manager question in my world would be: "How much money will it get us?" And it's hard to answer that question because refactoring naturally doesn't have so easily quantifiable benefits. Feb 21, 2019 at 11:44

10 Answers 10

113

Do not ask management for permission to refactor. It's none of their business. You might as well be asking permission to sharpen a pencil.

Management doesn't understand refactoring. It's not a business need. Management shouldn't need to understand it. It's not their job. It's yours.

Refactoring is a tool you use to satisfy managements needs. Don't ask management to think about this. I'd be very concerned if my mechanic asked me what brand of wrench to use on my car. Concerned, not about the tool, but about the mechanic.

What you need to do is to lead this team to good practices. Don't ask management to dictate that. Even if they try they'll just make a mess of it.

You need to build trust with the team, show them the benefits and the costs, and accept that change doesn't happen instantly.

Sometimes a cross cutting concern sweeps through many classes and needs refactoring. Sometimes you just can't justify doing it now because now you just need this one little thing changed.

It hurts. You have to live with working in crap code because you just don't have the time. So it keeps taking longer and longer.

Abe Lincoln is often quoted as saying, "Give me six hours to chop down a tree and I will spend the first four sharpening the ax."

When dealing with management don't argue for sharpening the ax. Argue for the six hours. Don't expect to get credit for sharpening the ax. Don't do it for management at all. Do it so you only have to spend two hours fighting the damn tree.

18
  • 19
    This is one of the best answers I've ever seen on this site, no joke.
    – Marc.2377
    Feb 20, 2019 at 17:58
  • 19
    "It's not a business need." ...until it boils over and becomes the biggest business need there could be. "Oh, our software somehow works, and we don't know how. We can't really implement any new changes, and oh, everyone is quitting because work is miserable"
    – Alexander
    Feb 20, 2019 at 20:05
  • 6
    In addition, any programmer who doesn't enjoy writing fully factored code more than cut-and-paste code probably shouldn't be a programmer. It's the difference between enjoying your job and being a grind. I tend to find that early programmers often feel they need "Permission" to do things that make their job easier... the first thing you can do might be to give them that permission and remind them regularly to take advantage of it.
    – Bill K
    Feb 20, 2019 at 20:53
  • 9
    @Alexander This is what it looks like when that exact process kills people and only then it becomes a business need: safetyresearch.net/blog/articles/… Feb 20, 2019 at 20:56
  • 10
    "You might as well be asking permission to sharpen a pencil." Except sharpening a pencil takes a few seconds, and a major refactor of a codebase often takes long enough that management starts to wonder what the hell you've been doing this whole time. Even if they don't understand how tech debt works, they should at least understand that refactoring is valuable and that time should be made for it when appropriate, and they should be comfortable with the fact that little work will appear to be done during those times. Feb 20, 2019 at 21:09
25

Understand the difference between a simple refactor and a rewrite. All too often people use the word "refactor" when the really mean a targeted rewrite. Think of the difference this way (in order of riskiness):

  • Refactoring is a small, easily reversed change that has no functional impact
  • Targeted rewrite is a focused rewrite of one aspect of an application that affects multiple parts of the code
  • Full scale rewrite is tossing out the old source code and starting over from scratch

The reason for the distinction here is that some code fixes have a real impact on schedule. Any time you want to do something that impacts schedule, you need buy-in. There is a way to get that buy-in, but you have to sell it as an opportunity.

Refactoring should be just something you do as good practice. Like a boy scout leaves his campsite in better condition than he found it (cleaning up other people's mess), it just happens. Many Java and C# IDEs come with refactoring tools built in, so little things like re-ordering parameter lists and renaming code is updated across the whole application. As long as what you are modifying is an internal API (not something that third parties interact with) there isn't any practical restriction.

I believe it is important to realize that a series of well targeted refactorings can add up to the same effect as a targeted rewrite, but without the same level of risk involved. I also believe that if you can't get any other work done within a sprint other than what you are calling a refactoring, what you are really talking about is a targeted rewrite. You can't commit project money (i.e. developer time doing one thing vs. something else) to something with that big of an impact without buy-in from the people who's jobs are on the line. A refactoring is the type of work that won't cause the product to slip deadlines.

Targeted rewrites need to be scoped and planned. It's like remodeling a kitchen where you have to take down a wall. There are things you need to do to support the existing infrastructure until the job is complete and new support is added. It's usually an acceptable amount of risk that brings with it some advantages you didn't have before. The code is messy during the process, but when it is complete, the application as a whole is better off.

The best way to sell the targeted rewrite is to cage it in terms of what new features the rewrite will enable your team to perform.

Whole scale rewrites should be avoided unless there really is no option. It's like demolishing a house before replacing it with something completely different. Unless you know very well how that house was used, you run the risk of the new house not meeting the client's needs.

There are times where a whole scale rewrite is indeed required, but it takes a lot of research to ensure you are addressing all the current needs of your client when you are done. There's a lot of detail that exists in the existing code that was written for some long forgotten feature that is still important. There are strategies for this type of work as well.

One concept for whole scale rewrites is to use the strangler pattern. Essentially you are building the new application alongside the old one, and using the new when you can. Less and less of the old application exists, until it is fully replaced. This allows the customer to provide feedback so that you don't miss any critical details.

8
  • "Refactoring is a small [...] change." -> Uhm, no? Not even "not necessarily", as many refactorings are not "small" at all. It's a common misconception that refactoring is just the stuff in the context-menu of your IDE - these are not even the tip of the refactoring catalog-iceberg. Book and catalog recommendation: refactoring.com
    – phresnel
    Feb 21, 2019 at 8:01
  • With your refactoring description, you seem to unintentionally omit what to do when other team members don't/refuse to refactor. More often than not, this is the situation you find yourself in when you start labeling refactoring as a necessity. In these cases, even if it's not a rewrite by any definition you provided, it can still be a bunch of pending refactorings which will still take a more-than-insignificant amount of time.
    – Flater
    Feb 21, 2019 at 8:23
  • 1
    @phresnel Refactoring can take you years of real time, and that's fine. That's not the point - the point is that no refactoring should mean that you can't write code for a month. Ideally, every refactoring you do should seamlessly integrate into the existing code base, and should only touch the things that need to be touched. It should heavily focus on not breaking things. It shouldn't do any functional changes. Sometimes it's not easy, but then again, it's not like software developers don't get paid for the hard work :)
    – Luaan
    Feb 21, 2019 at 9:31
  • 1
    @Luaan: All of that is mostly true (֍). Why not write that instead of defining refactorings as necessarily _small _? (֍: "mostly", e.g. because "It shouldn't do any functional changes" should be "It must not do any functional/observable changes" --> if the program's observable behavior is changed, it is not a refactoring)
    – phresnel
    Feb 21, 2019 at 10:50
  • If you are defining refactoring as something that takes long enough that it's all you are doing in a sprint is lying to themselves. What you are doing is a targeted rewrite. If you disagree with me, that's fine. If you get fired because you didn't deliver on required functionality time and again, that's on you. Feb 21, 2019 at 15:12
12

Refactoring should happen as part of development. When you change behavior or add a new feature, the affected code should, if necessary, be refactored to support the change cleanly. Follow the boy-scout rule: Always leave the code in better condition than you found it.

You should not refactor code which don't need changes to behavior. You should not perform refactoring which is not related to a bugfix or new development. Don't estimate or schedule refactoring as separate from development. Like writing unit tests and performing code review, it should be an naturally integrated part of all development, not a separate negotiable option.

You encourage refactoring as part of the code review. Just ask the simple question if the code after the change is at least as clean as the code before the change was. If not, improve before the code is comitted.

Don't be a perfectionist - at least not at first. As long as every commit improves the code a little bit, things will get much better over the long haul.

3
  • 1
    Extra emphasis on the last paragraph - "just" keeping the pressure to ensure every commit does at least a tiny bit better costs considerable energy, especially if you're still the only person on the team (especially a 20 person team!) who really cares. Choose your battles, and go in for the long haul. You're fixing issues that took years to build, so don't expect them to disappear overnight.
    – Luaan
    Feb 21, 2019 at 9:33
  • 1
    Yes, exactly this. And among other things, doing the refactoring as part of development helps ensure that you have a way to test your results, which is what separates refactoring from cowboy coding.
    – Kyralessa
    Feb 21, 2019 at 12:54
  • Indeed. And doing it as part of other development gives you a much better excuse — both to management, who won't see it as wasted time, and to the rest of your team, who'll have to pull your changes. As I always say, the important thing is to know where you want to get to; then you can ensure you're taking steps in the right direction.
    – gidds
    Feb 21, 2019 at 19:23
4

It's next to impossible to convince a business to refactor, because customers won't pay for refactoring but developers still want to be paid to do it.

I would throw the question back to you. Why do you want to refactor?

  • Improve the end product

    Refactoring by definition means no changes to the end product. So this is a non starter

  • Speed up development

    A popular choice, "If we refactor this it will make it easier to change in future!". Of course, a 10% improvement of speed will take 10 times as long before you start seeing a return. It's hard to show numbers that add up to a net win.

  • Allow devs to program in the latest fashion?

    This of course is the fear of management, that the devs just want new toys. But you can spin it. "We are a tech company! unless we use the latest stuff and do stuff right, no one will respect our products. We have to be seen to be on the leading edge"

What Business is your company in?

  • Bespoke apps/websites to order

    There just no justification of refactoring, unless the customer specifically requests it, or you need to switch techs do implement their requirement

  • In house core product eg. ecommerce website

    Key concerns are reliability and new features. 'Refactor' to improve reliability or perhaps to add a feature "If we switch to events on MQs then we can send out product suggestions based on machine learning, as well as decoupling our microservices"

  • IT Consultancy

    Here refactoring to the latest ideas and techniques could be a core part of your sales pitch. "Switch to distributed-cloud-agile! (now with added truck based dev)" But you are more likely doing greenfield or POC projects where you can have everything you want.

2

Mind the Economics of Refactoring

Refactoring

  • does not affect functional aspects (otherwise it's more than refactoring)
  • therefore affects non-function aspects only (also known as quality attributes).

There is an inherent cost associated with refactoring, and the benefits of refactoring must surpass that cost:

  • refactoring costs time, and therefore money (in commercial environments)
  • opportunity cost: this time could be spent for something better (adding functional value or delivering earlier, or improving quality aspects in another way)
  • risk: the outcome could be worse than what you had before, or it could take longer time than planned. Therefore a save margin has to be added to the refactoring costs.

The benefits have to be quanitified as well, in terms of expected improved quality aspects (https://en.wikipedia.org/wiki/Non-functional_requirement): the refactoring can

  • save you time (and thus: money) in the future (for maintenance and faster addition of new features)
  • have significant quality improvements that can be monetarized (payed by current or future clients)

So, for every refactoring, consider:

  • What are the expected benefits, and how and when will they will pay off
  • How much time/money you have to invest, plus risk uplift

Bad situation: The code could need a refactoring, but the benefits of doing so are marginal, and it is late in the project, and you're in a fix-priced, one-shot project that won't be continuted save for serious bug fixes.

For small refactorings: those decisions can be made by the developers themselves as by the boyscouts rule: leave the code/campground in a better condition than you found it.

For larger refactorings: management attention (project lead) and feedback (peer developers) are strongly adviced before wasting potentially precious time on a refactoring. Peer developers may get relevant input or advice for the refactoring (which usually can be done in more than one way), and lessons can be learned (both by you and others).

2

Something your question lacks, which is also likely the reason that you couldn't pass it by Management, is demonstration for the need for refactoring.

Refactoring is a risk, so you need to show that the "expected return" is a net positive and that the damage can be mitigated if things go south.

However, if you CAN demonstrate that the expected return is higher than the cost, then surely no one will disagree with you.

It's possible that refactoring is outside of management's power too--depending on your company/projects, your company may not actually own the codebase you are working on. Working on changes not requested by the client may be a breach of contract.


I'm asking what are some ways I can help create a culture of writing for maintainability rather than pure functionality

With a team of 20, I'm assuming you have meetings and (hopefully) code-reviews. These would be a good time to share your concerns about coding styles (ideally a coding-guideline would exist) and design patterns. Again, you will need to demonstrate an advantage to this! Changing coding styles requires effort by all members to change, maintain and enforce, but if people generally agree that you made a valid argument, it shouldn't be hard to continue.

If you need to convince your lead, somethings they may be considering (that you need to convince them will not be an issue):
・Depending on the complexity of your code, free reign for refactors will likely lead to a lot of "Why did this break??" "Oooh! I didn't know that was weird like that for a reason!" (In other words, it's not ideal, but sometimes things are how they are for a reason, a reason which the lead will likely know and have under control and not want people poking at)
・Tasks may start taking longer than the lead expected, so the lead needs to be prepared for that (ie budget more time)

PS, this sounds like it should be in stackexchange WorkPlace rather than software engineering

PPS, I think many of these answers seem to reflect one's own work environment rather than software engineering in general. Whether or not you own the code-base matters. Whether or not your product is in production matters. Your situation may invalidate many of these answers.

2

You have to include refactoring in your designs. I understand the need to "fix" something that doesn't seem appropriate, but you need to be honest in terms of what the refactoring of finished, tested, certified and working (in production) code will provide to you and your company. You shouldn't change something that has been working, doesn't have major bugs or performance issues, and is providing value to your stakeholders. This is very visible to them, and it is why they'll (most likely) never allow time for unnecessary changes.

You have to be smart about it. You are (I think) providing maintenance to this software. New functionality will require some design, so whenever you need to change the code, don't do a surgical, pragmatic change and commit to building the correct solution for the problem. This will likely involve refactoring of the existing classes.

2
  • Re "don't do a surgical, pragmatic change": What should be done instead? Feb 21, 2019 at 2:21
  • Design the correct solution for the whole problem. It will most likely result in refactorimg. Feb 21, 2019 at 2:46
1

I see more problems than just a refactoring here.

I've also asked management if we could have some more deliberate planning or cleanup for the codebase but I was basically told no.

Did you talk to your direct team lead? Management is a very broad term, and can include anything from team lead of your 20+ people up to a a CEO of the entire company as well as other company pillars' management (aka Operations or Business management; note that any level CEO is usually more of Ops/Bus as well).

Essentially the person you have to persuade is your direct (line) manager. The one responsible for the team. If you manage to convince them, you're on the right way. It'll be then their decision if they want to apply changes without notifying anyone or seek further approvals. They are also responsible for building the culture of coding.

I've had some 1:1 conversations with team members and most of them are also aware of the various code smells and don't like them

This means you actually have a very strong basis. In most companies there are team meetings and there you can bring up the point of improving your coding practices in general. Talk upfront to 2-3 colleagues that you think might be most interested in it as well so that they can back you up at the meeting. That will strengthen your discussion position.

Prepare your arguments. Look for the analysis of impact to the code, programming efficiency etc when it is not written properly. The term "technical debt" has been already mentioned in other answers. This is what you need to look for in general.

Think also about actual problems that you or your colleagues/a whole team experienced due to those problems. Will you be able to spend less time if the code was uniform? Will there be less errors during code integrations?

Everyone on the team programs in their own way and there isn't any coordination.

This, rather than the refactoring itself is the main and first thing to address. What's the point of refactoring if you will be back to the same (lack of) code quality in another 2-3 years (at best). In reality your refactoring will be slower than introducing the new code, so it will be simply a waste of efforts. Focus on discussing how to improve new code quality in the first row, agree on the practices to follow, add code reviews as a mandatory part of your coding to ensure the practices are followed.

In other words - stop doing more mess (aka acquiring more technical debt). Of course, you'll always have challenges with that and sometimes you might end up with some deviations from the standard but each deviation should be immediately fixed before moving on to the next project.

but refactoring rarely happens because there is always something more important to do.

Once the previous point is achieved you can move on to the refactoring, In reality make it a part of your coding practices immediately but only once the standards are settled.

Refactoring is not about making a huge single change (again - as already pointed out in other answers). It's about continuous improvement of parts of the code neighbouring what you currently write. Make it a custom that you're fixing a line of code or function that you're about to use. Just one at a time. Make sure to have unit test (if you don't writing them one is also a part of your refactoring).

With this approach it'll be easier to blend the refactoring into everyday work. You need to account that when assessing the workload for the actual coding. Only if you give yourself the required time, you'll be able to do that. And no-one will most probably object, since they have no idea what you are really doing. Of course as long as you have your managers consent.

0

This is not a team problem, because it is never a team problem. This is a management problem, and the question you need to answer is this: Does management understand what technical debt is, and why it's important to service it - and more importantly, do they care?

In the majority of businesses where software is not the core focus, management doesn't understand or want to understand software, because they don't see it as important. If this is your scenario, then you need to put a presentation together explaining why you need to refactor software (i.e. risks of not refactoring) and pitch it to the relevant managers. Either they will get on board with you, in which case you can start introducing it gradually, or they won't - in which case you either have to continue dealing with a rotting codebase forever, or find employment elsewhere.

If, however, you're working at a software-focused business where refactoring isn't a core focus, you need to get the hell out, pronto. There is no other option, because such businesses (and yes, I have worked at one) will never change their practices, regardless of what they may claim, because they literally cannot afford to spend their time in any other way than pitching the lowest bid to the next client, and lowest bids don't include refactoring time.

1
  • 1
    I disagree. Unless the management routinely micro-manages the development team, it's none of their business. The responsibility for the code base and productivity is on the development team. And it's really the team that's the problem here - because refactoring shouldn't really be a "separate step" or a three-month-long-issue-on-the-JIRA-board. It's part of the original task, and it should be within the scope of the original task (if possible). Do you prevent the mechanic from closing the hood, just because the engine runs fine already? Of course not - finishing up is part of the process.
    – Luaan
    Feb 21, 2019 at 9:39
0

You need to make it a fun and exciting thing to do. We call it "The Quality Offensive". A code analyser runs overnight and generates lists of things which could be done better. These tasks hang around in Jira, it's a good Friday afternoon job to pick one up and do your stuff. Newbies do this full time for a week, till they get the feel of stuff. There is actually a table in Jira for how many buglets someone vaporised in a task before checking back in. And if you get that little blob to turn from red to yellow to green you are a hero, deep inside.

After you've done this a while - combine these if statements, comment this function, remove this unused code - you find you do it anyway while coding, just to save someone else the trouble later. And there's always the little nagging thought "I don't want Lint to find things to complain about in my code".

It is very important that no-one gets blamed for the not-quite-bugs. They are just there, like rats in sewers, you are trying to reduce their number for the common good.

It doesn't matter which of the many excellent tools you use, just get one - maybe a 30-day trial installation - and let it rip. You have to adjust its parameters till it gives you useful output. Try different ones. We actually have two different ones running.

1
  • Now there's a funny thing. Where did the up-votes disappear to? If you don't like my answer, tell me how I can improve it.
    – RedSonja
    Feb 25, 2019 at 7:26

Not the answer you're looking for? Browse other questions tagged or ask your own question.