Чи можливо тримати код журналу повністю поза діловою логікою?


12

За допомогою AOP я можу вилучити код журналу зі своєї логіки бізнесу. Але я думаю, що його можна використовувати лише для реєстрації простих речей (тобто методів входу / виходу методу входу та виходу та параметрів).

Однак що робити, якщо мені потрібно щось записати у свою ділову логіку? напр

public void SomeDomainMethod(string id)
{
   //Get user by Id
   User user = Users.Get(id);
   if (user == null)
   {
      Log.Warn("user is not existed");        //<----------------- Log A
      throw new InvalidOperationException("user is not existed");
   }

   //Step 1 
   while(true)
   {
       //do something
   }
   Log.Info("Step 1 is completed");            //<----------------- Log B

   //Step 2
   while(true)
   {
       //do something
   }
   Log.Info("Step 2 is completed");            //<----------------- Log C

}

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

Чи можливо перемістити вище 3 коду входу з методу? Яка найкраща практика для такої ситуації?


Я впевнений, що ваші приклади журналів "Step1" та "Step2" мають бути частиною аудиту аудиту бізнес-логіки, а перший - технічного журналу. Я б спочатку
сортував

Відповіді:


1

Звичайно!

Але, на мій досвід, є два загальних типи корисних лісозаготівель:

Усі журнали: журнали, створені за допомогою API профілювання. Добре підходить для виявлення проблем ефективності та звітування про винятки. Дуже шумно.

Журнали ділових подій : журнали, на які посилається бізнес-логіка. Все, що може зацікавити бізнес. Мінімальний шум. Просто помітні, логічні, "ділові" події. Добре підходить для аудиту та KPI ...

Отже, я б дуже запропонував дві речі. По-перше, зробіть те, що роблять інші інструменти моніторингу, такі як New Relic, і використовуйте API для профілювання NET 1 . По-друге, запишіть логічні ділові події у вашій бізнес логіці . Ведення обліку певних подій є діловою логікою.

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


1. Але серйозно, заощаджуйте тисячі годин на зусиллях і просто використовуйте існуючий інструмент профілера ...

2. Звичайно, це передбачає, що ви поділяєте мою думку, що аспект не є чудовим місцем для приховування бізнес-правил!


Я цілком згоден з "Журналами ділових подій", і так само, як відповіді інших, я буду зберігати код журналу в бізнес-логіці. А для частини "Все журнали" я вважаю за краще використовувати рішення AOP, оскільки воно буде слідувати SRP і не забруднювати мою бізнес-логіку. У будь-якому випадку я спершу погляну на API профілювання.
Чарлі

10

Звичайно, ви можете легко використовувати AOP для цього. Просто переробляйте деталі

  • Отримати користувача Id
  • крок 1
  • крок 2

в окремі методи (як ви мали б зробити чи чистішим кодом). Тепер ви можете легко налаштувати рамку AOP для реєстрації викликів методів на ваш вибір ( як показано тут ). Виняток може бути зареєстрований безпосередньо абонентом, не потрібно використовувати AOP для виведення цього з бізнес-логіки.

До Вашої редакції:

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

Чому це не слід? Якщо в контексті "бізнес-логіки" ви хочете записати "щось", що варто реєструвати, і якщо цьому "чомусь" можна присвоїти розумне ім'я, в більшості випадків буде сенс переробити код на метод для своє. Якщо ви хочете використовувати AOP, це вимагатиме від вас структурувати свій код таким чином, який ви, ймовірно, повинні були структурувати, незалежно від вимоги до реєстрації. Ви можете інтерпретувати це як недолік AOP або ви можете трактувати це як користь, оскільки це дає вам зворотній зв'язок, де можна покращити вашу структуру коду.


Погано, що мій приклад недостатньо зрозумілий. Що я насправді хочу показати у прикладі, це те, що метод є найменшою одиницею з точки зору домену, яку не слід розділяти на менші шматки.
Чарлі

@Charlie: приклад ідеально зрозумілий. Ваше помилкове уявлення тут, напевно, ви думаєте, що може бути хорошою ідеєю мати більші методи, ніж кроки. І це IMHO неправильно, це не дуже гарна ідея. Ознайомлення з різними кроками, що вартують ведення журналу, є чіткою ознакою, щоб ці кроки мали абстракцію, назву самостійно, тому метод самостійно.
Док Браун

@Charlie ніщо не заважає тобі виконувати 3 приватні методи, викликані вашим підрозділом або роботою. Цей спосіб ззовні залишався незмінним, але тепер у вас є необхідна абстракція для вашої реєстрації.
Ремі

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

@JohnWu: структура коду повинна відображати різні проблеми / кроки, незалежно від вимоги реєстрації. Саме це і приводить сюди структуру коду. Після того, як ця проблема буде вирішена, реєстрація може бути виконана AOP, що є "побічним ефектом" надання коду кращої структури. Тож я думаю, що не проблема занесення журналів визначає структуру коду, а більше, що вимога використання AOP для ведення журналів робить її більш прозорою, що код пропускає якусь структуру, яку вона повинна мати.
Док Браун

3

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

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

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


Ось що я думав. Я не можу придумати розумного випадку для входу в систему POCO домена / бізнесу. Ведення журналів - це те, що природно вписується поза основними бізнес-моделями, IMO.
jleach

2

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

Наприклад, завдяки використанню слухача (ручного або за допомогою шини подій тощо) ваш код буде виглядати так

public void SomeDomainMethod(string id)
{
   //Get user by Id
   User user = Users.Get(id);
   if (user == null)
   {
      listener.OnUserNotFound(userId);
      throw new InvalidOperationException("user is not existed");
   }

   //Step 1 
   while(true)
   {
       //do something
   }
   listener.OnStep1Finished(......);

   ...

}

Реалізуючи ведення журналу в слухачі, логіка ведення журналу вже не входить у вашу бізнес-логіку.

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

Інший підхід - через такий механізм, як Dtrace в Solaris, який дозволяє вводити в запущені процеси (я вважаю, що є подібний спосіб зробити в C #?), Так що реєстрація та збір статистики можуть бути визначені під час виконання. Однак є й інші недоліки.


Однією з проблем, яку AOP намагається вирішити, є проблема того, що код стає нечитабельним для комерційного коду (наприклад, дзвінки з журналу), переплетеного з "бізнес-кодом". Заміна "реєстратора" на "слухача" цього не вирішує, читабельність коду не змінюється,
Doc Brown

2

Інший підхід полягає в тому, щоб розділити ведення бізнесу та технічний журнал. Тоді ми можемо назвати журнал ведення бізнесу "Аудит" і застосувати певний набір бізнес-правил, таких як термін зберігання та правила обробки, такі як Моніторинг ділової активності.

З іншого боку, технічний лісозаготівлі або просто "Ведення журналу" - це засіб останньої інстанції, щоб залишити слід технічної проблеми. Він повинен бути асинхронним, швидким, толерантним до невдалого зберігання повідомлення журналу. Крім того, повідомлення журналу повинні проходити через найменшу кількість проксі-серверів, щоб бути близько до джерела проблеми.

Логіка журналу досить мінлива і тісно поєднана з реалізацією, тож вам справді потрібно відокремлювати її від коду?

Логіку аудиту слід вважати доменною логікою та керувати нею відповідно.

Наприклад, у гексагональній архітектурі може бути порт аудиту разом з портами клієнтів, сховища та MQ (і, можливо, Метрики та управління). Це був би вторинний порт, тобто діяльність на цьому порту викликається бізнес-ядром, а не зовнішніми системами.


Я дуже погодився на вас, що є два види лісозаготівлі. Але я не вважаю, що Logic of The Logging є досить мінливою і тісно поєднана з реалізацією , ви маєте на увазі тут технічний журнал? Для технічного ведення журналу я думаю, що він використовується для реєстрації значень входу / виходу методу та параметрів, які краще сидіти поза методом.
Чарлі

@Charlie Так, під "The Logging" я маю на увазі технічний лісозаготівлю. Журнал значень введення / виходу / параметра достатній для чистих функцій. Тоді або, звичайно, ви можете використовувати аспект або монаду Logger. Але чисті функції чудові тим, що вони перевіряються. Отже, питання, за якими слід відслідковувати реєстратор, ймовірно, будуть вирішені під час dev / debug. Завдяки нечистим функціям, де технологія ведення журналу найбільше використовує, ви хочете записувати всі параметри / результат виклику побічних ефектів, кожен виняток.
iTollu

1

Способи уникнути реєстрації безпосередньо у класі чи методі:

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

  2. Здійснюйте дзвінки до методів, які вже використовуються для ведення журналу.


1
Чи є лісозаготівля там, де, як було показано, є проблемою, і її навіть варто «виправити»?
whatsisname

1

Чи дійсно потрібно відокремити вашу реєстрацію від вашої бізнес-логіки? Ведення журналу відповідає відповідно до написаної бізнес-логіки, і тому має сенс бути в одному класі / функції. Що ще важливіше, це сприяє легшій читабельності коду.

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


0

Ні, не в c #

ОП, відповідь на ваше конкретне питання - ні, не в c #. Можливо, існують інші, більш рідні мови AOP, але всі підходи до AOP в c #, які я бачив, можуть застосовувати лише аспекти поведінки в контексті точки з'єднання , тобто означає, що має здійснюватися потік контролю між одним кодовим блоком і інший. Очікувана поведінка не виконуватиметься в середині методу, за винятком, звичайно, виклику іншого методу.

Ви можете «апсектировать» певні біти журналу

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

Написання журналу не є аспектом

Я б додав, що написання журналу все одно не є наскрізною проблемою. Принаймні не налагоджувати журнал. Я підтверджую це тим, що ви не змогли написати наскрізну вимогу, яка повністю пояснює, що буде робити цей аспект - це специфічно для кожного конкретного випадку, тому що метою написання журналу є відображення того, що відбувається з логіка, і логіка в кожному методі повинна бути досить унікальною (див. DRY ).

Іншими словами, існує нерозривна логічна залежність між написанням журналу та матеріалами, про яку пишеться. Ви не можете його узагальнити.

Але аудит є

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.