... when I change the system, there is a human involved, and humans do care.
.
When you have to add a feature to a program but the code is not structured in a convenient way, first refactor the program to make it easy to add the feature, then add the feature.
Whenever I do refactoring, the first step is always the same. I need to ensure I have a solid sets of tests for the section of code.
Ask myself:
- Do you have tests?
- Do you have code that’s testable?
- Do you have skills to make our code testable?
- Refactoring technique : Extract Function
Refactoring changes the problems in small steps, so if you make a mistake, it is easy to find where the big is.
Push, merge, ship, and iterate with small changes. The author does commit after each successful refactoring. -> we should all learn git-squash
I take a look at what I’ve extracted to see if there are any quick and easy things I can do clarify the extracted function. The first thing I do is rename some of the variables...
Name convention. Generally in JavaScript, using camel case for variables and functions. Constants are in upper case, pascal case for class names. Also, it should describe what it is. It’s ok to be super long, if that help other developers read the code. To prevent making it long, use class so you can add context.
For example,
const authorizedUserFullName = “Luke Skywalker”
It can be:
class AuthorizedUser {
constructor(id, firstName, lastName) {
this.id = id;
this.fullName = `${firstName} ${lastName}`;
}
...
}
Even more:
class AuthorizedUser {
constructor(id, firstName, lastName) {
this.id = id;
this.fullName = new FullName(firstName, lastName);
}
}
// this is called "value object"
class FullName {
constructor(firstName, lastName) {
this.value = `${firstName} ${lastName}`;
}
}
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
We need empathy. Empathy to your coworkers. Craftsmanship and professionalism come together.
Removing / adding a parameter to a function is a big deal. Each parameter may need to interact with others. The number of combinations will be N * (N-1). (N is the number of parameters).
The great benefit of removing local variables is that it makes it much easier to do extractions, since there is less local scope to deal with.
The other benefit I can think of is it keeps the parameter “immutable”. With a variable, it’s possible that someone will rewrite, or update the variable anytime. This is not immutable (but “mutable”). Mutable variables are hard to track, thus hard to change its implementation.
- Refactoring technique : Inline Variable
It reminds me of this tweet.
https://twitter.com/stemmlerjs/status/1245785484233707523?s=21
Boring code:
- is consistent
- is not clever
- is easily understandable
- makes locating features easy
- adheres to Principle of Least Surprise (things do what I assume they would)
- takes a minimal amount of effort to change
- uses the right tool (paradigm, language) for the job
"It makes locating features easy."
- Refactoring technique : Change Function Declaration
In the book, he says “formatAsUSD would be a bit too long-winded” - remember, we’re coding for developers. If it describes great, that’s improving developer experience better. I’d use long names.
- Refactoring technique : Split Loop
- Refactoring technique : Slide Statements
- Refactoring technique : Replace Temp with Query
- Refactoring technique : Extract Function
- Refactoring technique : Inline Variable
Additionally, for loop is not a great pattern. It introduce a variable that you need to pay attention to. I would:
function totalVolumeCredits() {
return invoice.performances.reduce(function (acc, perf) {
return acc + volumeCreditsFor(perf);
}, 0);
}
“reduce” is more familiar for many developers. It has a context of “Making something out of an array.”
The problem: broken-out functions are nested.
- Refactoring technique : Split Phase
- Refactoring technique : Extract Function
When programming, follow the camping rule: leave the code base healthier than when you found it.
The amountFor function highlighted the central role the type of play has in the choice of calculations - but conditional logic like this tends to decay as further modifications are made unless it’s reinforced by more structural elements of the programming language.
- Refactoring technique : Replace Conditional with Polymorphism
- Refactoring technique : Change Function Declaration
- Refactoring technique : Move Function
- Refactoring technique : Inline Function
Note: class is handy, however, we can freely change class members. This will confuse people, because it’s so hard to tell the state of class members. When the class is huge, class members tend to be used like global variables. In my opinion, they should not be changed (immutable). There’s a good way to add the constraint.
Object.freeze();
For example,
class Person {
constructor(name) {
this.name = name;
Object.freeze(this);
}
updateName(newName) {
this.name = newName; // error
}
}
const person = new Person(“Wataru”);
person.name = “Watura”; // error
- Refactoring technique : Replace Type Code with Subclasses
- Refactoring technique : Replace Constructor with Factory Function
- Refactoring technique : Replace Conditional with Polymorphism
The true test of good code is how easy it is to change it.
.
A common sequence is: Read the code, gain some insight, and use refactoring to money that insight from your head back into the code.
.
Code should be obvious: When someone needs to make a change, they should be able to find the code to be changed easily and to make the change quickly without introducing any errors. A healthy code base maximizes our productivity,allowing us to build more features for our users both faster and more cheaply.