Skip to content

Instantly share code, notes, and snippets.

@fnbk
Last active February 15, 2021 22:17
Show Gist options
  • Save fnbk/a41b28ca894cbe95c0b1b08670486c94 to your computer and use it in GitHub Desktop.
Save fnbk/a41b28ca894cbe95c0b1b08670486c94 to your computer and use it in GitHub Desktop.
#
# SLA - Single Level of Abstraction
#
Within a certain method we look to keep all the code at the same level of abstraction to help us read it more easily. - Robert C. Martin
A helpful analogy is a newspaper article:
1) First comes is the most important thing – the heading. From this you should roughly know what the article is about.
2) The first sentence of the article describes it on a high level of abstraction.
3) The further you get in the article the more details emerge.
We can structure our code in a similar way:
1) Class name is the heading.
2) Next are public methods on a high level of abstraction.
3) These may call lower level methods until we are finally at “fiddle-with-bits” level.
With this structure at hand we can easily decide which detail level we want to see when looking at a class. If we are only roughly interested in how a class works, we just need to inspect the public methods which reflect functionality on a high level of abstraction. If we want to know further details, we will drill down to private methods.
Switching between levels of abstraction makes code harder to read:
It is really confusing as our brain tries to make the mental shift between thinking about higher level concepts and low level implementation details in the code. We have to mentally construct the missing abstractions by trying to find groups of statements which belong together (mental grouping).
The whole point of using the same abstraction is to keep less context in our head about the code so that we can just read through the code and quickly understand what's going on.
Code that is easy to read, is also easy to maintain.
#
# bad example
#
function dailyMessages() {
let dailyMessages = [];
let start = moment()
.subtract(moment().startOf("day").fromNow())
.startOf("day")
.toString();
const messagesSnapshot = db
.collection("users")
.doc(userId)
.collection("messages")
.orderBy("timestamp", "desc")
.where("timestamp", ">", start)
.get();
messagesSnapshot.forEach((snap) => {
const data = snap.data();
dailyMessages.push(data);
});
let dailyData = createMarketData(dailyMessages);
let dailySalesData = createSalesData(dailyMessages);
setMarketData(dailyData);
setSalesData(dailySalesData);
}
#
# good example
#
function dailyMessages() {
let dailyMessages = getDailyMessages();
let dailyData = createMarketData(dailyMessages);
let dailySalesData = createSalesData(dailyMessages);
setMarketData(dailyData);
setSalesData(dailySalesData);
}
#
# exception to the rule
#
function dailyMessages() {
let start = moment()
.subtract(moment().startOf("day").fromNow())
.startOf("day");
let end = moment.now();
let dailyMessages = getDailyMessages(start, end);
let dailyData = createMarketData(dailyMessages);
let dailySalesData = createSalesData(dailyMessages);
setMarketData(dailyData);
setSalesData(dailySalesData);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment