awesome-everything EN
↑ Обратно к восхождению

Базовый CS с нуля

Абстракция: чтение кода

Суть Читай небольшие сниппеты — объект-счётчик, exports модуля, пробой через устаревшее состояние и протечку stack overflow — и выбирай, что abstraction реально открывает, прячет или не может спрятать.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на middle-высоте — в небе
◷ 14 min

Abstraction оценивают по коду, а не по определению. Читай каждый сниппет, реши, где кончается interface и начинается скрытая implementation, и замечай момент, когда граница держит — или ломается.

Цель

Потренируй чтение, которое работающий программист запускает постоянно: найди interface, от которого зависит вызывающий, найди implementation за ним и определи, держит ли сокрытие под кодом перед тобой.

Сниппет 1 — связка-счётчик

const counter = {
  count: 0,                       // data field — состояние
  increment() {                   // method field — операция
    this.count = this.count + 1;
  },
  value(): number {               // method field — ещё операция
    return this.count;
  },
};

counter.increment();
counter.increment();
let n = counter.value();          // n становится 2
Викторина

Какие строки — единственные, что называют поле данных, и что это говорит об interface связки?

Сниппет 2 — модуль

// module: text-format
const TABLE = { /* ... */ };               // таблица поиска
function pad(s: string): string { /* ... */ }
function trim(s: string): string { /* ... */ }
export function format(s: string): string {
  return pad(trim(s));                     // использует оба хелпера
}
// другой модуль, импортирующий тот, что выше
import { format } from "./text-format";
format("  hi  ");        // ок
pad("x");                // ??? — pad никогда не экспортировали
Викторина

Импортирующий модуль вызывает pad('x') напрямую. Что происходит и каков public interface модуля?

Сниппет 3 — пробой

// module: bank
let balance = 100;                  // приватно — без export
export function deposit(n: number) { balance = balance + n; }
export function getBalance() { return balance; }
// вызывающий — что он может и не может
import { deposit, getBalance } from "./bank";
deposit(50);                        // ок — через interface
balance = -999;                     // ??? — мимо interface
Викторина

Вызывающий присваивает balance = -999, чтобы сделать баланс отрицательным в обход deposit. Почему дизайн модуля не даёт этому стать реальным риском?

Сниппет 4 — протечка

function depth(n: number): number {
  return depth(n + 1);   // не останавливается — нет базового случая
}

depth(0);   // RangeError: Maximum call stack size exceeded
Викторина

Abstraction вызова функции обещает «вызови, она выполнится, вернёт». Этот код падает, называя стек вызовов. Как юнит это назвал и в чём урок?

Итог

Каждый сниппет — одно и то же чтение на разном масштабе. В счётчике interface — методы, а count скрыт за this. В модуле через границу проходит только экспортированный format, а pad, trim и TABLE остаются приватными. В банке приватный balance нельзя достать снаружи, поэтому модуль может гарантировать инвариант — граница превращает надежду в правило. А в безудержной рекурсии конечный стек вызовов протекает сквозь abstraction вызова в момент, когда нижний слой упирается в предел. Найди interface, найди скрытую implementation и проверь, держит ли сокрытие.

Продолжить восхождение ↑Абстракция: модуль, что держит и потом протекает
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.