During the weekend, I found the following small JS function in a blog post:
const lineChecker = (line, isFirstLine) => {
let document = ``;
if (line !== "" && isFirstLine) {
document += `<h1>${line}</h1>`;
} else if (line !== "" && !isFirstLine) {
document += `<p>${line}</p>`;
} else if (line === "") {
document += "<br />";
}
return document;
};
I refactored it and was thinking that it could be an excellent beginner-level refactoring kata.
How would you refactor it?
Latest comments (93)
Personally I'd do..
Leaving out all further context, this might be one of the rare occasions where to make use
!!
(double ! operator)Note: After looking through some other solutions, I figured using
!!
introduces (or solves? I wouldn't know) a problem when passing unexpected falsy - values such asnull
,false
orundefined
.I'd still say it's a pretty good example for refactoring. Even though it seems fairly easy to overengineer if you adhere to the 'functions do a single thing' mantra.
I have refactored like below. Divided all conditions to Spec Units and Grouped Spec Units. Check my Github Link to see my code.
github.com/SenthilKumaranC/How-To-...
One-liner:
functional implementation with ramda
Here's my one-liner that includes a hilarious immediately-invoked arrow function:
const lineChecker = (Line,isFirstLine) =>
return line === « » ? «
» :
isFirsLine ? « H1 … » :
;
This is a simple as I could get it while retaining readability
I'd have to see the rest of the code to decide whether or not this would be the best case but for now
Note that I've used
!=
instead of!==
in order to check for undefined. If you were going the strict approach you'd have used!==
instead but because we're unaware of what will be coming inline
. We're using a non-strict check here. I think this is a fairly simple solution in this case"fat" version:
minimal:
Well there are certainly more problems with this than just this function. For example we don't know if the line data has been escaped properly.
So if we go a bit outside the box of the function, and we keep the logic we could generate the document like this:
However this smells from HTML / CSS perspective because we're generating HTML like this:
While it works it is "ugly", and giving users the power to do as many line breaks as possible isn't often really desired. So we could only separate paragraphs when we have multiple line breaks in the source text.
And now we get "nicer" HTML output:
But this isn't good either, because this is still a non-standard way of parsing text to HTML. To have confidence you should make extensive tests to cover possible edge cases, and you have to maintain it yourself. So what to do?
Just use Markdown.
It might be worth the pain to refactor to using some Markdown library. Don't write your own, by now there are plenty of options that fit about any use case imaginable.
I tend to prefer a balance between smaller and readable code:
But as many things, this is just a personal preference, and the team conventions should always supersede.
The most pressing concern here (imo) is the function name - I don't know what it is meant to do, and certainly doesn't just 'check' lines - it constructs lines of HTML based on the arguments passed in and returns a string.
To refactor I would first look at the function in context and rename it something appropriate based on its intended use - the next steps would likely be as much to do with preferred style as anything else after that point. (Personally I lean towards declarative so I liked the solutions I have seen in the comments where the code was DRYed up using clearly named, reusable functions, but this is just personal preference.)
you touching a good point about the function name.
But the case is refactor a peace of code.
Would you rename the function, or would you write a new function with the correct understandable name also for the param?
My version:
I like to leave the happy path as the default return, and early return for any
exceptions