TGViewer
ТОП - Тёма о программировани ТОП - Тёма о программировани @temaprog · 2.81K subscribers
Post #101 2.7K
Cohesion и Coupling 🧩🔗

Здарова, работяги!

Если очень коротко: хорошая архитектура — это высокая связность внутри модулей (cohesion) и низкая связанность между ними (coupling). Эти два термина отлично объясняют, почему код либо живёт годами, либо рассыпается от каждого чиха.

В оригинале различить их достаточно просто, но вот в переводе… связанность и связность… Если у вас есть дефекты речи или вы просто устали к концу дня, то готовьтесь к сумбуру. Поэтому я обычно использую другой перевод:
— Cohesion — Связность
— Coupling — Сцепленность

Связность (Cohesion) 🧲
— Насколько сильно и «по делу» связаны части внутри модуля/компонента.
— Высокая связность = модуль делает одну понятную вещь.
— Сигнал проблемы: описываете модуль через «и-и-и» — «карточка товара грузит, форматирует цену, читает локаль и отправляет аналитику».

Сцепленность (Coupling) 🔗
— Насколько сильно модуль зависит от других.
— Низкая сцепленность = модуль знает только минимально необходимое о внешнем мире.
— Сигнал проблемы: изменение структуры store/API ломает полприложения.

Пример 🍿

Плохо: низкая связность + высокая сцепленность

function ProductCard({ id }: { id: string }) {
const [product, setProduct] = React.useState<any>(null);

React.useEffect(() => {
fetch(`/api/products/${id}`)
.then(r => r.json())
.then(setProduct);

window.analytics.track('view_product', { id });
}, [id]);

if (!product) return <>Loading...</>;

const currency = localStorage.getItem('currency') || 'USD';
const priceText = new Intl.NumberFormat('en', { style: 'currency', currency })
.format(product.price);

return (
<div>
<img src={product.image} />
<div>{product.name}</div>
<div>{priceText}</div>
</div>
);
}

— Компонент делает всё: загрузка, форматирование, аналитика, работа со storage, UI.
— Жёсткая привязка к fetch, analytics, localStorage, Intl и структуре product.
— Любое внешнее изменение тянет правки сюда.

Хорошо: высокая связность + низкая сцепленность

type Product = { id: string; name: string; image: string; price: number };
type ProductApi = { getById(id: string): Promise<Product> };
type CurrencyFormatter = (currency: string, amount: number) => string;

function ProductCardView({ product, priceText }: { product: Product; priceText: string }) {
return (
<div>
<img src={product.image} />
<div>{product.name}</div>
<div>{priceText}</div>
</div>
);
}

type Props = {
id: string; api: ProductApi; currency: string; formatPrice: CurrencyFormatter;
}

function ProductCard({ id, api, currency, formatPrice }: Props) {
const product = useProduct(id, api);

if (!product) return <>Loading...</>;

const priceText = formatPrice(currency, product.price);

return <ProductCardView product={product} priceText={priceText} />;
}

— ProductCard оркестрирует UI конкретной карточки (высокая связность).
— Зависимости приходят снаружи: api, formatPrice, currency (низкая сцепленность).
— Легко подменять реализации.

Опасные виды сцепленности на фронте 🛑
— Компонент знает «внутренности» ответа бэкенда и лезет в deeply.nested.a.b.c.
— Временная: функция/эффект B должна вызываться строго после функции/эффекта A (завязка на порядок эффектов).
— Прямое использование window, document, localStorage прямо в компоненте.
— Зависимость от окружения: компонент «знает», что он в проде/тесте.

Как снижать coupling и повышать cohesion 🛠
— Интерфейсы и адаптеры: компоненту нужен api.getById, а не fetch/axios.
— DI через props/context: прокидывайте зависимости сверху.
— Разделяйте UI и данные: View без побочек, отдельные сервисы для данных и бизнес-логики.
— Избегайте «utils.ts на 1000 строк»: маленькие тематические модули (price/strings/date).
  • 🔥 33
  • ❤ 17
  • ❤‍🔥 2
  • 👍 2
More from @temaprog
  1. Sep 15, 2026Здарова, работяги! Кто собирается на Avito.Tech.Conf 26 сентября? Я уже рассказывал про ко…
  2. Sep 14, 2026Зачем ты пишешь? Здарова, работяги! Помню, как все только начинали активно использовать аг…
  3. Sep 4, 2026Здарова, работяги! Приезжает коробка. Внутри бейдж на Avito.Tech.Conf и часы «Ракета».😳 И…
  4. Sep 3, 2026Здарова, работяги! Потихоньку продолжаю дописывать посты из заметок. В прошлый раз — элеме…
  5. Aug 26, 2026Здарова, работяги! Совсем скоро осень, а значит, начинается сезон конференций. Про Avito.T…
  6. Aug 18, 2026Здарова, работяги! Сейчас я много думаю про AI-native команды и внедрение ИИ в разработку.…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →