Skip to content

Instantly share code, notes, and snippets.

@wataruoguchi
Created January 31, 2021 21:31
Show Gist options
  • Save wataruoguchi/fa527cf25ec41f48c7c335d6ccd7c2fa to your computer and use it in GitHub Desktop.
Save wataruoguchi/fa527cf25ec41f48c7c335d6ccd7c2fa to your computer and use it in GitHub Desktop.
Refactoring - Chapter 2: Principles in Refactoring

Refactoring

Chapter 2: Principles in Refactoring

The previous chapter explained what refactoring is. This chapter is about some of the principles.

Defining Refactoring

  • Refactoring (noun): a change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behaviour.
  • Refactoring (verb): to restructure software by applying a series of refactorings without changing its observable behaviour.

if someone says their code was broken for a couple of days while they are refactoring, you can be pretty sure they were not refactoring.

Takeaway: To go faster, do tiny refactorings as you don't need to spend any time debugging.

Any bugs that I notice during refactoring should still be present after refactoring.

Same goes for decaffeinating (CoffeeScript -> JavaScript). The bigger scope you work with, the more cognitive leaking you have.

Refactoring is very similar to performance optimization, as both involve carrying out code manipulations that don't change the overall functionality of the program. The difference is the purpose: Refactoring is always done to make the code "easier to understand and cheaper to modify." This might speed things up or slow things down. With performance optimization, I only care about speeding up the program, and am prepared to end up with code that is harder to work with if I really need that improved performance.

We should not try aiming for both refactoring and performance optimization. I think refactoring is required before optimizing performance, but it doesn't go the other way around.

The Two Hats

Two hats: Swapping hats while developing software. Be aware which hat you're wearing.

  1. Adding functionality - adding new capabilities and adding tests
  2. Refactoring - NOT adding functionality, only change tests when changing an interface.

Why Should We Refactor?

Refactoring is no "silver bullet" but a valuable tool what should be used for several purposes.

  • It improves the design of software
  • It makes software easier to understand
  • It helps me find bugs
  • It helps me program faster

Refactoring Improves the Design of Software

Without refactoring, the internal design - the architecture - of software tends to decay. As people change code to achieve short-term goals, often without a full comprehension of the architecture, the code loses its structure.

Software design is my personal hot topic. I'm studying about Domain Driven Design in my spare time. Software need architecture designed.

Refactoring Makes Software Easier to Understand

Your peers read the code, future yourself read the code. Code with empathy, reader friendly.

In time, I close the gap between what I want it to do and what I tell it to do.

Change code like gifting it to other developer. - Luke

Refactoring Helps Me Find Bugs

Refactoring make me understand what the code does.

"I'm not a great programmer; I'm just a good programmer with great habits." - Kent Beck

Refactoring Helps Me Program Faster

All the earlier points come down to this.

Doesn't the time I spend on refactoring reduce the speed of development? (...) Every new feature requires more and more time to understand how to fit it into the existing code base, and once it's added, bugs often crop up that take even longer to fix. (...) This burden slows down adding new features - to the point that developers wish they could start again from a blank state.

I can't more agree with this!

Software with a good internal design allows me to easily find how and where I need to make changes to add a new feature. Good modularity allows me to only have to understand a small subset of the code base to make a change.

What is the good design exactly? -> What is it for web development -> I ended up studying DDD.

(T)he Design Stamina Hypothesis: By putting our effort into a good internal design, we increase the stamina of the software effort, allowing us to go faster for longer.

When Should We Refactor?

The author does it every hour.

The Rule of Three Here's a guideline Don Roberts gave me: The first time you do something, you just do it. The second time you do something similar, you wince at the duplication, but you do the duplicate thing anyway. The third time you do something similar, you refactor.

Or for those who like baseball: Three strikes, then you refactor.

Preparatory Refactoring - Making It Easier to Add a Feature

The best time to refactor is just before I need to add a new feature to the code base. When fixing a bug.

  • Refactoring technique : Parameterize Function (310)

Comprehension Refactoring: Making Code Easier to Understand

By refactoring I move the understanding from my head into the code itself. - Ward Cunningham

When you understand what the code is doing, ask your self if you can refactor the code to make that understanding more immediately apparent.

Wiping the dirt off a window so you can see beyond. - Ralph Johnson

Litter-Pickup Refactoring

A version of comprehension refactoring. Pick the trash lying around. "Always leave the camp site cleaner than when you found it."

Planned and Opportunistic Refactoring

You have to refactor when you run into ugly code - but excellent code needs plenty of refactoring too.

Obviously, clean code is easier to change, easier to refactor. We would have a lot of chance to refactor. I hesitated to do this as I was not confident to know whether the result of my refactoring would be really clean. I wish we had patterns / software design to guide.

"for each desired change, make the change easy (warning: this may be hard), then make the easy change." - Kent Beck

Plan refactoring before adding new feature. When you're adding a new feature, you will:

  • Take time to understand what the existing code is doing.
  • Make the code easy to understand (Refactoring).
  • Add a feature (incl. writing tests!).

Long-Term Refactoring

It's not great idea to have a team do dedicated refactoring for weeks. Refactoring should be done gradually.

To change from one library to another, start by introducing a new abstraction that can act as an interface to either library. Once the calling code uses this abstraction, it's much easier to switch one library for another. (This tactic is called Branch By Abstraction)

^ We can use this idea in frontend. Separate business logic and rendering, for adopting React.js or whatever we would want to use.

Refactoring in a Code Review

Code Reviews help more experienced developers pass knowledge to these less experienced.

Can other developers read my code? Do they think it's clean? Make other developer's life easier with code reviews.

One of senior developer's jobs is to make another senior developer. - Brandon

I believe code review is one of the best opportunity to share knowledge and improve team's skills.

What Do I Tell My Manager?

One of the most common questions I've been asked is, "How to tell a manager about refactoring?"

You don't need to tell managers who are not familiar with tech.

Software developers are professionals. Out job is to build effective software as rapidly as we can.

  • When you add a feature: Refactor -> Add the new feature.
  • When you fix a bug: Understand how it's working -> Move your understanding from your head into the code (Refactoring) -> Fix.

When Should I Not Refactor?

  • The part you don't need to understand
    • Even if the part you run across is a mess, if it's not related to what you're working on. Do refactor only when you need to understand how it works.
  • When it's easier to rewrite it than to refactor it.
    • This is tricky, because you need to know the difficulty and how it should work.

Problems with Refactoring

Slowing Down New Features

The whole purpose of refactoring is to make us program faster, producing more value with less effort.

If we don't have a healthy code base, you can't tell the difference iin productivity between a healthy code base and a sickly code base.

"Show team members that you value improving the health of code base." - I think asking a code review is one way. Pairing is another way.

One note here is that if you don't know what "clean code" is, what "good engineering practice" is, and if you don't share that with peers, your refactoring may not be effective. What is clean code? What about SOLID principles?

  • S Single-responsibility principle
  • O Open–closed principle
  • L Liskov substitution principle
  • I Interface segregation principle
  • D Dependency inversion principle

Code Ownership

Code ownership boundaries get in the way of refactoring.

For example, when you want to refactor a public API that could be used by someone else? You could make it deprecate.

Branches

The longer I work on an isolated branch, the harder the job of integrating my work with mainline is going to be when I'm done.

Run multiple tiny cycles. keep feature branches short (a couple of days).

Testing

We're concerned that refactoring carries too much risk of introducing bugs - because we don't have solid tests! Write test!

Legacy Code

If you have a big legacy system with no tests, you can't safely refactor it into clarity.

Add tests!

Databases

Refactoring, Architecture, and Yagni

Refactoring has profoundly changed how people think about software architecture. Early in my career, I was taught that software design and architecture was something to be worked on, and mostly completed, before anyone started writing code. Once the code was written, its architecture was fixed and could only decay due to carelessness.

The architecture most of orgs would have is MVC(Model, View, Controller) or MVP(Model, View, Presenter). The problem with MVC is that the responsibility of Model gets incredibly bigger. Not only data model but all the model/application logics live in Model.

However, it's not easy to determine whether the architecture is appropriate for your app before you build the app.

The real impact of refactoring on architecture is in how it can be used to form a well-designed code base that can respond gracefully to changing needs.

Build software that solves only the currently understood needs. - YAGNI (You are not going to need it)

Yagni doesn't imply that architectural thinking disappears, although it is sometimes naively applied that way. I think of yagni as a different style of incorporating architecture and design into the development process - a style that isn't credible without the foundation of refactoring.

Refactoring and the Wider Software Development Process

Agile = CI + self-testing code + refactoring

You can't be agile without solid tests. You can't refactor safely without solid tests. You can't write tests without testable code. My observation tells our immediate definition of "clean code" is to write testable code and write tests. How to write testable code can be a good topic to discuss.

Refactoring and Performance

To tune software performance, you need to write tunable software first. You may also need a clear understanding of what the bottleneck is.

It Takes Awhile to Create Nothing

Lesson: Before you discuss, observe, measure, and identify what is the real problem.

Where Did Refactoring Come From?

Good programmers know that they rarely write clean code the first time around.

Refactoring is a key element in the whole process of software development.

Automated Refactorings

Tools, IDEs. Use the right tool.

For JavaScript, VSCode is the best one. You can change a variable name within a file with a few clicks. Same for a file path. The editor tells what variable is unused.

You can't do with CoffeeScript...

Many refactorings are made much safer when applied in a language with static typing.

With VSCode and JSDoc's hint in JavaScript, it tells what variable is used wrongly.

Programming with powerful refactorings like this is a compelling reason to use an IDE rather than stick with a familiar text editor.

Going Further

.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment