Дозвольте спочатку попросити вибачення за тривалість публікації, але я дуже хотів передати якомога більше деталей, щоб я не витрачав час на коментарі.
Я розробляю програму за підходом DDD, і мені цікаво, до яких вказівок я можу керуватися, щоб визначити, чи повинен Кореневий корінь містити інший АР або якщо їх слід залишити як окремі, "стоячі" АР.
Візьміть до уваги просту програму Time Clock, яка дозволяє працівникам прилаштовуватися або виходити протягом дня. Користувацький інтерфейс дозволяє їм вводити ідентифікаційний номер і PIN-код свого працівника, який потім перевіряється та отримується поточний стан працівника. Якщо працівник наразі працює на інтерфейсі, в інтерфейсі відображається кнопка «Годинник»; і, навпаки, якщо вони не зафіксовані, кнопка пише "Clock In". Дія, здійснене кнопкою, відповідає і стану працівника.
Додаток - це веб-клієнт, який викликає бек-сервер, відкритий через інтерфейс служби RESTful. Мій перший пропуск щодо створення інтуїтивно зрозумілих, читаних URL-адрес призвів до наступних двох кінцевих точок:
http://myhost/employees/{id}/clockin
http://myhost/employees/{id}/clockout
ПРИМІТКА. Вони використовуються після підтвердження посвідчення особи та PIN-коду працівника і в заголовку передається "маркер", що представляє "користувача". Це пояснюється тим, що існує "режим менеджера", який дозволяє керівнику чи керівникові залучати до роботи іншого співробітника. Але заради цієї дискусії я намагаюся зробити це просто.
На сервері у мене є ApplicationService, який надає API. Моя початкова ідея методу ClockIn - це щось на зразок:
public void ClockIn(String id)
{
var employee = EmployeeRepository.FindById(id);
if (employee == null) throw SomeException();
employee.ClockIn();
EmployeeRepository.Save();
}
Це виглядає досить прямо, поки ми не усвідомили, що інформація про карту працівника, що насправді, зберігається як перелік операцій. Це означає, що кожного разу, коли я телефоную на ClockIn або ClockOut, я не змінюю безпосередньо стан працівника, а натомість додаю новий запис у часовий лист працівника. Поточний стан працівника (увійшов чи ні) походить від останнього запису у часовій таблиці.
Отже, якщо я перейду з наведеним вище кодом, моє сховище повинне визнати, що стійкі властивості Співробітника не змінилися, а що додано новий запис у часовий лист працівника та виконати вставку у сховище даних.
З іншого боку (і ось головне питання посади), TimeSheet здається, що це сукупний корінь, а також він має ідентифікацію (ідентифікатор співробітника та період), і я міг би так само легко реалізувати ту саму логіку, що і TimeSheet.ClockIn (ідентифікатор співробітника).
Мені здається, що я обговорюю переваги двох підходів, і, як сказано у вступному пункті, цікаво, які критерії я повинен оцінювати, щоб визначити, який підхід більше підходить для проблеми.