A couple of days ago I saw Daniel Moka's LinkedIn post about the DRY (i.e. "don't repeat yourself") principle and a common misunderstanding people have of it. He argued that we often consider the principle to be about code duplication in general and refactor our code to remove that duplication even when the duplicated code might serve two different logical purposes (or, "represent different business knowledge", as he puts it). His main point was that if the two instances of code had different reasons to change, we should keep them separate and not deduplicate them for the sake of deduplication.
I think this was a great reminder and I completely agree with him — and must confess that I've often been guilty of running around with my refactoring hammer seeing all duplicated code as nails. I hope I remember that post the next time I'm about to do that.
My perhaps unorthodox function names
Today I started thinking about how this all might be related to my way of naming small functions when writing functional code.
A person reading my code might bump into functions like this:
const activeOnly = (company: Company) => company.active;
const byName = (first: Company, second: Company) => first.name.localeCompare(second.name);
const toNameAndRegNumber = (company: Company) => `${company.name} (${company.registrationNumber})`
These may look weird by themselves, and I don't think I've ever seen any guide or person suggest using names like these.
But the reason I personally really like names like these is how it makes the code using them really easy to understand (in my opinion at least).
companies
.filter(activeOnly)
.sort(byName)
.map(toNameAndRegNumber);
I fully understand that the names are too short and vague for general use, and I wouldn't suggest using such convention to name some helper functions exposed widely. But relating to Moka's point about specific knowledge, I think such names can make sense and actually make code easier to read when they're close to the calling code and have the same context. If e.g. my examples above were to be some global helpers, they would definitely need to somehow communicate that they are for Company
objects only.
If I'd need a function comparing companies' names somewhere else, I'd probably duplicate that code there with a more fitting function name. After all, it would be serving a different purpose there.
I don't know if many developers would agree with this and use similar names. And if a team member pointed out in a code review that they found those names confusing, I'd of course use a more traditional naming convention. (And to be fair, I'd probably go with the common isActive
function name instead of that activeOnly
anyway. I used the latter as an example of an unconventional name but I don't think it really helps readability, so using it would just add unnecessary cognitive load for the reader.)
Perhaps my eagerness to use such names comes from a long history in Java and getting a bit fed up with its naming conventions. I'd take that sort(byName)
or sort(byCompanyName)
any day before sort(companyNameComparator)
, and I think the latter should never be used in functional code.