Яка користь мати чисті моделі POCO?


16

Яка головна перевага мати чисті моделі POCO? Я розумію, що Моделі повинні бути чистими та простими, але я, як правило, люблю тримати утримання дочірніх об'єктів у межах модельних класів. Наприклад, якщо у мене є ClassAта ClassBвизначено наступним чином:

public class ClassA
{
    public string MyProp { get; set; }
    public IEnumerable<ClassB> Children { get; }

    public void AddChild(ClassB newChild) { /*... */ }
    public void RemoveChild(ClassB child) { /* ... */ }
}

public class ClassB
{
    public string SomeProp { get; set; }
} 

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

Будь-яка допомога вдячна. Дякую.


Я б видалив методи Add / Remove, якщо вони не додадуть значення, як-от переклад нульового аргументу ClassB у версію об’єкта NullObject-шаблона:AddChild(ClassB newChild) => Children.Add(newChild ?? new NullClassB())
Graham

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

Основна причина уникати саме цього дизайну полягає в тому, що це суперечить правилам дизайну .net. Це абсолютно довільно, але люди очікують, що колекція має в ньому мутаційні методи.
Френк Хілеман

@Casey Я не використовую шаблон "Активні записи", метод "додавання" просто робить незначну перевірку даних. Метод видалення існує, оскільки колекція не піддається впливу, вони просто додають та видаляють із внутрішнього списку. Я змінив його, хоча використовував інший тип колекції, який дозволяє мені перевірити, використовуючи вбудовані методи додавання та видалення.
Джессі

Відповіді:


43

Ваші два питання не пов'язані між собою.

Яка користь мати чисті моделі POCO?

Чистий POCO не залежить від якихось підприємницьких рамок, конвенцій, [] речей або тісно пов'язаних з якимось об'єктом, який так само залежить. Іншими словами, світ може повністю змінитися навколо POCO, і він просто продовжує робити те, що робить, не піклуючись. Ви не можете зламати його, оновивши рамку, перемістивши її в нову систему або дивлячись на це смішно. Це просто продовжує працювати. Єдині залежності - це речі, про які явно просять.

POCO - це не що інше, як ідея POJO. J було змінено на C, тому що люди дивляться на вас смішно, коли ви пояснюєте концепцію, яка має назву Java, якщо ці люди використовують C #. Ідея не залежить від мови. Вони могли просто називати це звичайними старими предметами. Але хто хоче похвалитися використанням POO?

Я дозволю Фоулеру пояснити походження:

Цей термін був введений, поки Ребекка Парсонс, Джош Макензі і я готувалися до бесіди на конференції у вересні 2000 року. У бесіді ми вказували на багато переваг кодування ділової логіки в звичайні об'єкти Java, а не на використання Entity Beans. Ми поцікавились, чому люди настільки проти використання звичайних об’єктів у своїх системах і зробили висновок, що це тому, що простим об’єктам не вистачає фантазійної назви. Тож ми дали їм один, і це дуже приємно.

martinfowler.com: POJO

Щодо вашого іншого питання:

Чи є щось по суті не в тому, щоб мати методи додавання та видалення?

Мені не подобається Aбезпосередньо знати про це B. Але це DIP річ, а не POJO .


Я мав пряму залежність від Bпростоти, в ідеалі вони обидва реалізували б інтерфейси. Але Aвсе ще є список IInterfaceB. Чи щось не так з AddChildметодом, якщо діти слабко поєднуються через посилання на інтерфейс?
Джессі

6
Я можу зробити безліч дурних речей заради простоти. Що мені не подобається - це знання про B. A не використовує B, тому не потрібно визначати належний інтерфейс, що належить, щоб спілкуватися з B через. Наскільки я можу сказати, A - це колекція. Таким чином, A повинен мати справу з B через <T>, тому він не повинен знати про нього нічого.
candied_orange

2
Я також бачив "PODO" для "простого старого об'єкта даних", щоб уникнути будь-якого мовного специфікатора в абревіатурі. PODO звучить трохи нерозумно (якось звучить як епітет, який ви почуєте на Tatooine, як мені здається), тим більше ніж POJO або POCO, я думаю, але набагато менш глупо, ніж POO.
KRyan

2
Цікаво, як добре пройшла б презентація Фоулера, якби він назвав їх POO?
Олівер

3

За допомогою функції "Додати та видалити" ви реалізуєте Collection<T>функції. Запитайте себе, чому ви використовуєте IEnumerable<T>замість цього List<T>чи іншого змінного класу? Мабуть, це не тому, що ваша колекція повинна бути прочитана щойно.

Єдина причина, про яку я можу подумати - це те, що ви хочете контролювати, які методи доступу ви хочете опублікувати. У такому випадку було б приємніше створити власний клас колекції, скласти список, реалізувати вибрані способи Додати та видалити та реалізувати IEnumerable<T>. Потім використовуйте це замість IEnumerable<T>типу дитячої колекції.

Але мені здається List<ClassB>, мабуть, просто добре послужив би вам.


0

Що AddChildдодає та RemoveChildвилучає? Якщо це з бази даних (або зберігання будь-якого виду), у вас є активні записи. Не обов'язково завжди погана річ, але це, безумовно, змушує вас турбуватися про рамки, конвенції, залежності тощо, як згадує @CandiedOrange.

У той же час, який би був сенс уникнути залежності від ClassA до ClassB (або принаймні InterfaceB), якщо вони всі в одній програмі? У реальному світі, що моделює ваша програма, речі залежать один від одного. У реальному світі об'єкти робити є колекції інших об'єктів , які «належать» до них. Ці відносини цілком доречно представляти у своєму коді.

Єдина причина, що стає навіть трохи складною, це тому, що, здається, у вас є потреба точно керувати тим, як ClassB стає асоційованим та відмежованим від ClassA. Отже, у вас є трохи поведінки для реалізації. Ви можете або реалізувати його в класі (що є абсолютно "законним"; див. Https://stackoverflow.com/a/725365/44586 ), або у вас може бути якийсь окремий клас, який містить таку поведінку. Робіть те, що має найбільше значення для ваших індивідуальних обставин.

У будь-якому випадку, POJO / POCO - це справді лише OOP, як це було призначено, неприховане та безрезультатне. Дотримуйтесь принципів OOP, і ви будете в безпеці.


Дійсно, AddChild просто перевіряє наявність дублювання та null та не дозволяє. RemoveChild є, тому що для запобігання доданню бекдорда колекція виставляється як IEnumerable. Хоча це виконуватиме лише стандартне видалення з колекції.
Джессі

1
Дякуємо за пояснення. Так, це виглядає як саме тип поведінки, який повинен бути в POCO, і, безумовно, краще, ніж просто виставляти ваш базовий IEnumerable для абонентів, щоб змінити або замінити за бажанням.
Джон М Гант

Я думаю, що Active Record - це лише погана модель.
Кейсі

1
@Casey, ти не отримаєш від мене жодного аргументу з цього приводу. Але я б не заперечував, якби хтось теж хотів ним скористатися. Основна суть полягала в тому, що якби Джессі мав намір використовувати такий зразок, як Active Record, який інтегрує стійкість із визначенням моделі, у нього виникнуть усі проблеми, що виділяються CandiedOrange, і він би не справді кваліфікувався як POCO, для чого це варто. Але це все одно не робиться.
Джон М Гант
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.