Skip to content

Core Concepts

Concepts introduced in LAD may differ from your vision!

The truth is that there is no “correct definition”.

We try to make the concepts we introduce correlate with generally accepted ones. But our main task is to create a unified non-contradictory system.

For those who know DDD, we create ubiquitous language in the bounded context of LAD

Be aware that the concepts introduced by LAD are basically created only for use in LAD.

Abstraction


The most important term of all architecture. Everything we will do is create abstractions, move code between abstractions, build relationships between abstractions.

Sounds complicated but actually abstraction is any way to hide code, complexity any information, behind a name and public interface.

The essence of abstraction is that you can understand what’s inside even without reading the content

// Variable is an abstraction
const userList = [];
// The variable name is enough to guess what's there
userList.map((user) => user);
// Function is an abstraction
function createUser(name: string): Promise<User> {
// ... Many lines of complex code
}
// By calling this function we know it will create a user and return it, even without reading the source code
const user = await createUser("0xFrizen.eth");
// Class is an abstraction
class Board {
addCard(title: string) {
// ... Many lines of complex code
}
removeCard(id: string) {
// ... Many lines of complex code
}
renderHTML(): string {
// ... Many lines of complex code
}
}
// When we use this class, we understand that calling methods will add cards to the board.
// And calling renderHTML will return html of this board even without reading the source code
const board = new Board();
board.addCard("Card 1");
board.removeCard("Card 1");
document.body.innerHTML = board.renderHTML();
// File is an abstraction
// Just the file name is enough for us to assume what's there
import {} from "./use-user-list";
// Folder is an abstraction
// Thanks to the folder name we know,
// that UserCard is a component
import { UserCard } from "./components/user-card";

Important: not all abstractions are expressed in code

Concepts, terms, patterns - these are all abstractions

// By the name we understand that this is a component
// This means:
// - You can use hooks there
// - You need to return jsx from there
// - There should be no side effects in the body
function UserComponent() {}

With the help of abstractions we can get a lot of information from a small amount of code

You can read more about this here Abstraction

Miller’s Wallet


Okay, we figured out what abstraction is, but why do we need it?

The thing is that the human brain thinks in abstractions. Not symbols, not words, not lines of code, but abstractions.

More about this here Neurophysiology of code complexity

And this thinking has an important limitation, which is the basis of code complexity.

At the same time we can only think about 7+-2 abstractions. (Usually around 4x)

This rule is called Miller’s wallet

Try to understand 2 pieces of code:

const maxSubArray = (nums) => {
let maxSub = nums[0];
let curSum = 0;
for (let i = 0; i < nums.length; i++) {
if (curSum < 0) {
curSum = 0;
}
curSum += nums[i];
maxSub = Math.max(maxSub, curSum);
}
return maxSub;
};
const user = {
id: 1,
name: "Alex Johnson",
email: "alex@example.com",
avatar: "https://i.pravatar.cc/150?img=3",
role: "Software Engineer",
bio: "Full-stack developer specializing in React & Node",
location: "San Francisco, CA",
joined: "2022-03-15",
followers: 1243,
following: 562,
};

Why is the first one significantly more difficult to understand than the second one, although both have 11 lines of code?

In the first case, we work with a large number of abstractions simultaneously: loop, Math.max, conditions maxSub, curSum There’s little code but the wallet is overflowing.

And in the second case, there are few simultaneous abstractions - user, object declaration