← Назад к вопросам

Что такое Cohesion?

2.0 Middle🔥 131 комментариев
#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое Cohesion?

Cohesion (Связность) - это принцип проектирования кода, который показывает, насколько функции, методы и переменные в модуле, классе или компоненте связаны между собой и сосредоточены на одной цели.

Просто говоря: высокая связность (High Cohesion) означает, что все элементы в блоке кода работают вместе для достижения одной цели. Низкая связность (Low Cohesion) означает, что элементы не связаны и делают разные вещи.

Определение высокой связности (High Cohesion)

Модуль с высокой связностью:

  • Все функции и переменные решают одну задачу
  • Элементы используют друг друга
  • Легко понять назначение модуля
  • Легко переиспользовать
  • Легко тестировать

Определение низкой связности (Low Cohesion)

Модуль с низкой связностью:

  • Содержит несвязанные функции
  • Элементы не используют друг друга
  • Непонятно, что делает модуль
  • Сложно переиспользовать
  • Сложно тестировать
  • Часто нужно изменять при разных причинах

Примеры: React компоненты

Пример 1: НИЗКАЯ связность (плохо)

// UserProfileBadly.tsx - делает слишком много разного
function UserProfileBadly() {
  // Управление профилем
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  
  // Управление постами
  const [posts, setPosts] = useState([]);
  
  // Управление комментариями
  const [comments, setComments] = useState([]);
  
  // Управление авторизацией
  const [token, setToken] = useState('');
  
  // Управление уведомлениями
  const [notifications, setNotifications] = useState([]);
  
  // Функции для разных целей
  const updateProfile = () => { /* ... */ };
  const deletePost = () => { /* ... */ };
  const approveComment = () => { /* ... */ };
  const logout = () => { /* ... */ };
  const sendNotification = () => { /* ... */ };
  
  return (
    <div>
      {/* управление профилем */}
      {/* управление постами */}
      {/* управление комментариями */}
      {/* управление авторизацией */}
      {/* управление уведомлениями */}
    </div>
  );
}

// ПРОБЛЕМЫ:
// - Компонент делает 5 разных вещей
// - Сложно тестировать
// - Сложно переиспользовать (нужно весь этот код)
// - Часто нужно изменять (по разным причинам)

Пример 2: ВЫСОКАЯ связность (хорошо)

// UserProfile.tsx - только управление профилем
interface UserProfileProps {
  userId: string;
  onUpdate: (user: User) => void;
}

function UserProfile({ userId, onUpdate }: UserProfileProps) {
  const [user, setUser] = useState<User | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  
  useEffect(() => {
    fetchUser(userId);
  }, [userId]);
  
  const fetchUser = async (id: string) => {
    setIsLoading(true);
    const data = await apiClient.getUser(id);
    setUser(data);
    setIsLoading(false);
  };
  
  const handleSave = async (updatedUser: User) => {
    await apiClient.updateUser(updatedUser);
    setUser(updatedUser);
    onUpdate(updatedUser);
  };
  
  if (isLoading) return <div>Loading...</div>;
  if (!user) return <div>User not found</div>;
  
  return (
    <form onSubmit={(e) => {
      e.preventDefault();
      handleSave(user);
    }}>
      <input 
        value={user.name}
        onChange={(e) => setUser({...user, name: e.target.value})}
      />
      <input 
        value={user.email}
        onChange={(e) => setUser({...user, email: e.target.value})}
      />
      <button type="submit">Save</button>
    </form>
  );
}

// ПРЕИМУЩЕСТВА:
// - Компонент делает ОДНО: управляет профилем
// - Всё что здесь - нужно для профиля
// - Легко тестировать
// - Легко переиспользовать
// - Легко поддерживать

Другие примеры низкой и высокой связности

Низкая связность: функция с разными целями

// processUserData - делает слишком много
function processUserData(user: User) {
  // Валидирует юзера
  if (!user.email.includes('@')) {
    throw new Error('Invalid email');
  }
  
  // Логирует в файл
  fs.writeFileSync('/logs/user.log', user.name);
  
  // Отправляет на сервер
  fetch('/api/users', { body: JSON.stringify(user) });
  
  // Обновляет UI
  document.getElementById('user-info').textContent = user.name;
  
  // Отправляет аналитику
  analytics.track('user_processed');
  
  return user;
}

// ПРОБЛЕМЫ:
// - Функция делает валидацию, логирование, запросы, обновление UI, аналитику
// - Сложно тестировать
// - Сложно переиспользовать

Высокая связность: функции с одной целью

// Каждая функция делает ОДНО
function validateUser(user: User): boolean {
  return user.email.includes('@');
}

function fetchUserToServer(user: User): Promise<Response> {
  return fetch('/api/users', { body: JSON.stringify(user) });
}

function updateUserInUI(user: User): void {
  document.getElementById('user-info').textContent = user.name;
}

function trackUserProcessed(): void {
  analytics.track('user_processed');
}

class UserLogger {
  log(user: User): void {
    fs.writeFileSync('/logs/user.log', user.name);
  }
}

// ПРЕИМУЩЕСТВА:
// - Каждая функция делает одно и делает его хорошо
// - Легко тестировать
// - Легко переиспользовать
// - Легко заменить реализацию (например, логирование в БД вместо файла)

Cohesion и Coupling (взаимное переплетение)

Cohesion и Coupling часто упоминаются вместе:

  • High Cohesion: элементы в модуле тесно связаны
  • Low Coupling: модули мало зависят друг от друга
// ПЛОХО: High Coupling + Low Cohesion
class UserManager {
  database: Database;
  logger: Logger;
  emailService: EmailService;
  paymentProcessor: PaymentProcessor;
  
  // Всё зависит от всего
  async createUser(data: any) {
    // нужна БД
    // нужен логгер
    // нужен email сервис
    // нужен платёжный процессор
  }
}

// ХОРОШО: High Cohesion + Low Coupling
class User {
  id: string;
  name: string;
  email: string;
}

class UserRepository {
  // Только работа с БД для юзеров
  async create(user: User) { }
  async findById(id: string) { }
  async update(user: User) { }
}

class UserService {
  constructor(private repository: UserRepository) {}
  
  // Только бизнес-логика
  async registerUser(data: UserData) {
    // валидирует
    // создаёт юзера
    // возвращает результат
  }
}

// Других сервисов не знает

Практические преимущества высокой связности

1. Легче понять код

// Высокая связность
function calculateDiscount(subtotal: number, code: string): number {
  // Ясно: функция считает скидку
  const discounts: { [key: string]: number } = { 'SAVE10': 0.1, 'SAVE20': 0.2 };
  return subtotal * (discounts[code] || 0);
}

// Низкая связность
function handleCheckout(subtotal: number, code: string) {
  // Считает скидку
  const discount = subtotal * (code === 'SAVE10' ? 0.1 : 0);
  // Отправляет на сервер
  fetch('/api/checkout', { body: JSON.stringify({ subtotal, discount, code }) });
  // Обновляет UI
  document.getElementById('total').textContent = (subtotal - discount).toString();
  // Логирует
  console.log('Checkout:', { subtotal, discount, code });
  // Отправляет аналитику
  analytics.track('checkout_processed');
}

2. Легче тестировать

// Высокая связность - легко тестировать
test('calculateDiscount returns 10% for SAVE10', () => {
  expect(calculateDiscount(100, 'SAVE10')).toBe(10);
});

// Низкая связность - сложно тестировать (нужно мокировать всё)
test('handleCheckout works', () => {
  jest.mock('fetch');
  jest.mock('document');
  jest.mock('analytics');
  // ... 20 линий мокирования ...
  handleCheckout(100, 'SAVE10');
  // ... проверять разные вещи ...
});

3. Легче переиспользовать

// Высокая связность - переиспользуемо
const discount = calculateDiscount(1000, 'SAVE20'); // Используй где угодно

// Низкая связность - нельзя переиспользовать
handleCheckout(1000, 'SAVE20'); // Работает только для чекаута, не для предпросмотра

Как достичь высокой связности

1. Single Responsibility Principle (SRP)

  • Каждый модуль должен иметь одну причину для изменения

2. Разделяй на модули по функциям

  • User Profile -> управление профилем
  • User Posts -> управление постами
  • User Comments -> управление комментариями

3. Используй dependency injection

  • Зависимости передавай через параметры, не создавай их внутри

4. Избегай god objects

  • Не создавай объекты/компоненты, которые делают слишком много

5. Группируй связанные данные

  • Переменные и функции, которые работают вместе, должны быть рядом

Вывод

Cohesion - это важный принцип чистого кода. Высокая связность означает:

  • Все элементы в модуле работают на одну цель
  • Легче понять
  • Легче тестировать
  • Легче переиспользовать
  • Легче поддерживать

Стремись к высокой связности (High Cohesion) и низкому связыванию (Low Coupling) - это основа качественной архитектуры.

Что такое Cohesion? | PrepBro