0% прочитано

Коли новій функції не потрібна нова таблиця

Нова функція не завжди означає нову таблицю. Якщо в системі вже є модель гілки обговорення та повідомлень, публічна дискусія може бути окремим сценарієм використання тієї самої моделі. Але спільне зберігання не повинно змішувати правила доступу, доменні події та поведінку різних частин системи.

26 жовтня 2026 р. 9 хв читанняЛаравель

Коли з’являється нова функція, дуже легко одразу перейти до нової міграції: нова сутність - нова таблиця.

Наприклад, для публічного обговорення першою ідеєю може бути таблиця comments.

Але якщо система вже має гілки обговорень і повідомлення, варто спочатку поставити інше запитання: чи справді з’явилася нова модель даних, чи лише новий сценарій використання вже наявної?

Повторно використовувати наявну модель варто не заради економії однієї міграції, а тоді, коли нова функція справді має ту саму сутність, життєвий цикл і правила зберігання.

Починати варто не зі схеми таблиць, а зі змісту даних

Дві функції можуть мати однакові поля і все одно бути різними моделями. І навпаки: дві функції з різним інтерфейсом можуть зберігати одну й ту саму сутність.

Тому я спочатку порівнюю не колонки, а зміст:

  • що саме є основною сутністю;
  • хто її створює;
  • як вона змінюється з часом;
  • що означає видалення;
  • як упорядковуються дочірні записи;
  • які правила цілісності мають виконуватися.

Гілка обговорення та повідомлення вже можуть покривати новий сценарій

Узагальнена наявна модель
Thread  id  context_type  context_id  ... Message  id  thread_id  author_id  body  created_at  ...

Якщо наявна модель уже представляє послідовність повідомлень усередині певного контексту, публічне обговорення може бути ще одним контекстом для тієї самої структури.

У такому випадку нова таблиця comments може лише продублювати те, що система вже вміє зберігати: автора, текст, час створення, порядок повідомлень і зв’язок із батьківською сутністю.

Але це правильне рішення лише тоді, коли збігається не форма даних, а їхній сенс.

Спільне зберігання не означає спільні правила поведінки

Найважливіша межа тут проходить між зберіганням і поведінкою.

Одна й та сама таблиця може використовуватися для кількох сценаріїв, але правила доступу до них можуть бути зовсім різними.

Наприклад, публічне обговорення може бути доступним усім читачам, а приватна гілка підтримки - лише її учасникам.

Спільна модель даних не дає права об’єднати ці правила в одну нечітку перевірку.

Правила доступу мають залишатися окремими

Одна модель не вимагає однієї політики доступу
final class PublicDiscussionPolicy{    public function view(User $user, Thread $thread): bool    {        // Rules for public discussions.    }} final class PrivateConversationPolicy{    public function view(User $user, Thread $thread): bool    {        // Rules for private conversations.    }}

Навіть якщо обидва сценарії працюють із Thread, їм не обов’язково мати одну політику, один сервіс або один набір перевірок.

Навпаки, окремі правила роблять межу явною: повторно використовується спосіб зберігання, але не змішується право на доступ.

Доменні події теж не варто змішувати лише через спільну таблицю

Різні події можуть спиратися на одну модель повідомлення
PublicDiscussionMessageCreated PrivateConversationMessageCreated

Створення повідомлення в публічному обговоренні може мати зовсім інші наслідки, ніж повідомлення в приватній розмові.

Наприклад, одна дія може запускати публічні сповіщення, а інша - приватні. Одна може бути доступною для модерації, інша - ні.

Тому спільна таблиця не означає, що вся система повинна реагувати на одну універсальну подію MessageCreated без контексту.

Про сам вибір подій я детальніше писала в окремій статті про випадки, коли подія справді доречна.

Повторне використання теж має межу

Не кожну нову функцію потрібно будь-якою ціною втиснути в наявну таблицю.

Тривожний сигнал з’являється, коли для нового сценарію доводиться додавати багато полів, які не мають сенсу для старих сценаріїв, або майже кожен запит починається з великого набору умов за типом.

Тоді спільна таблиця вже не спрощує систему, а приховує дві різні моделі під однією назвою.

Коли спільна таблиця починає втрачати єдиний сенс
threads  support_ticket_id nullable  post_id nullable  order_id nullable  moderation_state nullable  private_recipient_id nullable  public_sort_weight nullable  ...

Велика кількість взаємовиключних полів із null часто означає, що модель уже обслуговує занадто різні поняття.

Це не автоматичний доказ, що потрібні окремі таблиці, але хороший привід зупинитися й ще раз перевірити межу моделі.

Відсутність нової міграції не є метою сама по собі

Нова таблиця не є проблемою. Якщо нова функція справді вводить окрему сутність із власними правилами, таблицю потрібно створити.

Проблема виникає в іншому випадку: коли ми створюємо дубль уже наявної моделі лише тому, що нова функція має іншу назву в інтерфейсі.

Тоді з часом доводиться двічі вирішувати однакові задачі: пагінацію, порядок повідомлень, видалення, авторство, пошук, модерацію та цілісність даних.

Питання, які допомагають прийняти рішення

Коротка перевірка перед новою міграцією
1. Чи з'явилася справді нова сутність?2. Чи збігається життєвий цикл даних?3. Чи однаково працюють авторство, порядок і видалення?4. Чи можна відокремити правила доступу без дублювання зберігання?5. Чи можна залишити доменні події окремими?6. Чи не з'являється багато полів, потрібних лише одному сценарію?7. Чи не перетворюються запити на постійні перевірки типу?8. Що буде простіше підтримувати через рік?

Повторне використання моделі потрібно перевіряти на межах

Якщо одна модель використовується в кількох сценаріях, найважливіші тести перевіряють не саме збереження запису, а межі між сценаріями.

  • публічне обговорення не відкриває приватну розмову;
  • правила одного сценарію не впливають на інший;
  • створюються правильні доменні події;
  • видалення або модерація працюють лише там, де мають працювати;
  • запити повертають лише записи потрібного контексту.

Нова функція не завжди означає нову модель даних

Якщо система вже має модель гілки обговорення та повідомлень, нова публічна дискусія може бути ще одним сценарієм використання цієї самої моделі.

Це дозволяє не дублювати зберігання та вже вирішені технічні задачі.

Але повторне використання працює лише тоді, коли межі залишаються чіткими: правила доступу, доменні події та поведінка кожного сценарію не повинні випадково змішуватися.

Питання не в тому, чи можна обійтися без нової таблиці. Питання в тому, чи справді нова функція представляє ті самі дані з іншим способом використання.

Повторно використовувати варто модель даних, а не змішувати правила різних сценаріїв.