Abstractions
Abstractions are when we stop thinking of code as the exact problem its solving, but the generalized class of problem it can solve.
Just as we might want to upgrade a part in your computer, we may want to upgrade (or modify) parts of a codebase. How can we do so with the least amount of obstruction, balanced with the upfront and maintenance costs of such a "generalized part"?
🔗 By example
My favorite example of abstraction is Data Abstraction, spelled out in Chapter 2 of
Structure and Interpretation of Computer Programs.
Consider two functions which add and multiply rational numbers .
How might we store our rational numbers? Let's use an array.
const oneHalf = [1, 2]; // 1 / 2
function add(a, b) {
const [p1, q1] = a;
const [p2, q2] = b;
return [p1 * q2 + p2 * q1, q1 * q2];
}
function multiply(a, b) {
const [p1, q1] = a;
const [p2, q2] = b;
return [p1 * p2, q1 * q2];
}
console.log(add([1, 2], [1, 3]));
// => [5, 6]
console.log(multiply([1, 2], [1, 3]));
// => [1, 6]
Maybe down the road we decide arrays are silly and we prefer objects.
const oneHalf = { numerator: 1, denominator: 2 }; // 1 / 2
Let's try our code:
console.log(
add({ numerator: 1, denominator: 2 }, { numerator: 1, denominator: 3 })
);
// data-abstraction.js:4
// const [p1, q1] = a;
// ^
// TypeError: a is not iterable
No worries, let's just change up
add
:
function add(a, b) {
- const [p1, q1] = a;
- const [p2, q2] = b;
+ const { numerator: p1, denominator: q1 } = a;
+ const { numerator: p2, denominator: q2 } = b;
- return [p1 * q2 + p2 * q1, q1 * q2];
+ return { numerator: p1 * q2 + p2 * q1, denominator: q1 * q2 };
}
And we run again:
data-abstraction.js:11
const [p1, q1] = a;
^
TypeError: a is not iterable
Not to worry, we just need to change
multiply
too.
function multiply(a, b) {
- const [p1, q1] = a;
- const [p2, q2] = b;
+ const { numerator: p1, denominator: q1 } = a;
+ const { numerator: p2, denominator: q2 } = b;
- return [p1 * p2, q1 * q2];
+ return { numerator: p1 * p2, denominator: q1 * q2 };
}
Now our code works
$ node script.js
{ numerator: 5, denominator: 6 }
{ numerator: 1, denominator: 6 }
🔗 Now do it all again
You push your change, get it reviewed, and merge it in. Now our fractions are represented as
{ numerator, denominator }
and we can move onto the next Jira ticket.
...until a