For now, stick with refactoring strategies that are in the category of proper naming, functions doing only one thing, and the avoidance of mutation; don’t immediately start making extensible or reusable classes and factories until you have identified a repeating pattern.
At this point, it makes sense to use any refactoring that can stand on its own merit.
This means refactoring with the purpose of the code being understood, or the code being reliable.
Consider postponing refactoring with patterns that are only useful in certain scenarios.
You’ll want to save those until you have a reason.
Have A ReasonHaving SOLID code is not a reason.
Having functional or pure code is not a reason.
Why do we make our code extensible?.So that similar, but not exactly the same, functionality can branch off of base logic.
Why do we invert dependencies?.So that the business logic can be used by multiple implementations.
Hopefully, you see where I am going with this.
Some refactoring stands on its own.
For example, refactoring the name of a variable to become more accurate will always make sense.
Its merit is inherent.
Refactoring a function to be pure usually makes sense because side-effects can cause unforeseen issues.
Those are reasons.
“It’s best practice to use dependency inversion” is not a reason.
“Good code is extensible” is not a reason.
What if I only have a couple of never-changing dependencies?.Do I still need dependency inversion?.Not yet.
What if nothing needs to extend my code and I have no plans for anything to do so?.Should my code increase its complexity just to check off this box?.No!Take a look at the following example.
Which do you prefer?.Which do you naturally tend to write first?.Of course, the User class is far more extensible because it can handle more than just name and email.
It can also be extended by a child class, maybe a SuperUser, that will have many more methods but still uses the classic get() and set() methods.
Still, that User class may be complete overkill, and now your code is more complicated than it will ever need to be.
My advice is to stick with the simplest possible pattern.
Order Of ComplexityAnd now, if you’ll allow it, I’m going to make something up!.I call it the order of complexity and it helps me when I make refactoring decisions.
It looks like this:Constant VariableMutable VariableCollection (Object, Array)FunctionFunction with ClosureFactory (A function that returns a collection)ClassWhenever I decide how to organize functionality, I refer to the list.
I choose the highest possible choice that will suffice for my implementation.
I don’t choose again until it simply will not work.
Sometimes performance will affect this choice, but not often.
Usually, I find that I’ll put something in an object instead of a simpler constant variable.
Or I created a factory when I only require a function.
This list keeps me grounded.
It prevents me from prematurely refactoring.
BalanceI recently heard that if you say in a meeting, “it’s really all just about finding the right balance,” everyone will nod their head at your meaningless comment, like you’ve said something profound.
I’ve got to give it a try soon.
Here, though, I think balance is important.
As programmers we have to balance code quality, performance, maintainability, with the good old-fashioned need to get things done.
We have to be vigilant and make sure both needs stay in their correct place.
Our code can’t be maintainable if it doesn’t work correctly.
On the other hand, it’s hard to make bad code work correctly.
Still, code may be refactored, but what if it’s been refactored past the point of what is useful?.These are important questions to keep in mind.
Next time you write your code, please, refactor!.But also, maybe… don’t?Hi, I’m Justin Fuller.
I’m so glad you read my post!. More details