Poprawne zaprojektowanie klasy

0

Cześć.
Chciałem zapytać o sposób poprawnego projektowania klasy w przypadku gdy wiemy, że do klasy będzie dodawanych wiele nowych pól podczas pisania całego systemu.
Czy jest jakieś inne, lepsze podejście niż klasa z n-ilością ...{get; set;}? Chodzi mi o projektowanie zgodne z podejściem obiektowym. I w sumie, to czy i gdzie, może mieć sens podejście z klasą z samymi właściwościami? Zastanawiam się czy taka opcja nie wpływa na dużo większą podatność na błędy?. Dodam jeszcze, że klasa jest mapowana na tabele w DB przy użyciu EF. Z góry dzięki za odpowiedzi.

3

Klasa z samymi propertisami nadaje się jako DTO właśnie np. jako encja bazodanowa, model danych w API Restowym czy message z Kafki.
Nie ma to za dużo wspólnego z OOP ale miałem na obowiązku żeby system informatyczny był w 100% OOP.

0

Czyli dobrą praktyką jest, że gdy klasa ma być encją DB to nie ładować do niej żadnej logiki?

2
corthell napisał(a):

Czyli dobrą praktyką jest, że gdy klasa ma być encją DB to nie ładować do niej żadnej logiki?

Bardzo dobrą. Niech ta klasa służy jako mapowanie do bazy i nic więcej. Jeśli ma dużo kolumn, to po co do logiki pchać je wszystkie, jeśli ze wszystkich się nie korzysta? Lepiej zrobić projekcję na klasę domenową z takimi danymi, jakie są potrzebne dla obsługi przypadku użycia.

0

@SkrzydlatyWąż: I po utworzeniu takiej klasy po projekcji można używać w sposób zgodny z OOP, czy prywatne , walidowane pola, uniemożliwiać budowanie obiektu z jakimiś polami bez wartości itp? Zdaje sobie sprawę, że opcji rozwiązań może być wiele bo zakładam, że nie ma tego nigdzie ścisłe tego opisanego, jednak zdaje sie na Wasze doświadczenie.

1
corthell napisał(a):

Czy jest jakieś inne, lepsze podejście niż klasa z n-ilością ...{get; set;}?

No np. dużo klas z małą liczbą właściwości. Albo słownik. To, czy coś jest lepsze zależy od kontekstu, a tego nie znamy.

Zastanawiam się czy taka opcja nie wpływa na dużo większą podatność na błędy?

Jeśli pchasz tę klasę z warstwy data access na frontend, to owszem, może wpłynąć negatywnie.

corthell napisał(a):

@SkrzydlatyWąż: I po utworzeniu takiej klasy po projekcji można używać w sposób zgodny z OOP, czy prywatne , walidowane pola, uniemożliwiać budowanie obiektu z jakimiś polami bez wartości itp?

Ale jeśli to ma być używana przez ORMa (wolę nazwę persistence model niż encja DB), to czemu chciałbyś to wszystko w niej robić?
Logikę biznesową zaimplementuj w innych klasach.

1

Jako zwolennik niemutowalności tworzyłbym niemutowalny obiekt przez konstruktor, a właściwości tylko jako { get; }.Jeśli są potrzebne na zewnątrz, też mogą być niemutowalne. Są w C# System.Collections.Immutable. I zamiast tworzyć mnóstwo właściwości, w klasach domenowych według mnie lepiej skupić się kompozycji, czyli składać je z innych obiektów. Prosty przykład: Order zawiera właściwość OrderDetails. Zamiast wielu właściwości - te są zebrane w jednym OrderDetails. Ale to też zależy, czy robisz np. w XAMLu i potrzebujesz { set; }? Bo jeśli framework tego nie wymusza, to po co setter? Wydzielenie oddzielnej klasy walidatora może być sensowniejsze niż walidowanie w konstruktorze czy setterach (czego osobiście nie lubię).

Tworzenie obiektu bez wartości nie brzmi dobrze, chyba że z pustą kolekcją. Czy nie lepiej zrobić oddzielną klasę CanceledOrder z wypełnioną właściwością CancellationReason niż Order z CancellationReason = null? Trywialny przykład, ale sens chyba widoczny.

0
SkrzydlatyWąż napisał(a):

Jako zwolennik niemutowalności tworzyłbym niemutowalny obiekt przez konstruktor, a właściwości tylko jako { get; }.Jeśli są potrzebne na zewnątrz, też mogą być niemutowalne. Są w C# System.Collections.Immutable.

Entity Framework ogarnia takie rzeczy? Bo jeśli nie, to za wiele autor nie poszaleje.

1

@somekind: Entity Framework Core ogarnia wywoływanie konstruktora, co do kolekcji - raczej nie. Co to niemutowania - miałem na myśli niemutowanie klas z domeny. Klasy mapujące bazę niech się mutują, ale ja bym na nich nie robił domenowej logiki :)

0

@SkrzydlatyWąż:

SkrzydlatyWąż napisał(a):
corthell napisał(a):

Czyli dobrą praktyką jest, że gdy klasa ma być encją DB to nie ładować do niej żadnej logiki?

Bardzo dobrą. Niech ta klasa służy jako mapowanie do bazy i nic więcej. Jeśli ma dużo kolumn, to po co do logiki pchać je wszystkie, jeśli ze wszystkich się nie korzysta? Lepiej zrobić projekcję na klasę domenową z takimi danymi, jakie są potrzebne dla obsługi przypadku użycia.

Nie mogę się całkowicie z tym zgodzić. O ile zasadniczo wydaje się to być ok podejściem, to trzeba to przemyśleć. Może się okazać, że przez to kod w pewnym momencie będzie bardzo mocno zduplikowany.

2

No i? Co w związku z tym że będzie duzo duplikacji? Unikanie duplikacji jest wazne w logice a nie strukturach danych.

0

Może dojść do tego sporo niepotrzebnej roboty przy zmianach. Dodanie jakiegoś pola, czy usunięcie. Dlatego piszę o przemyśleniu tego.

1 użytkowników online, w tym zalogowanych: 0, gości: 1