Maksymalna ilość parametrów konstruktora w klasach danych.

0

Jak radzicie sobie z dość typową jak sądzę sytuacją kiedy mamy klasę reprezentującą jakąś strukturę danych o wielu atrybutach (niech będzie 20) i trzeba pogodzić konieczność zainicjowania wszystkich pól w konstruktorze z zaleceniami by nie przekraczać jakiejś tam liczby parametrów? Na siłę rozdzielacie klasę, rezygnujecie z immutability i używacie setterów, zaciskacie zęby i robicie konstruktor o 20 parametrach?

1

dość typową

No chyba nie aż taką typową, ale rozumiem że to jakieś wypychanie jsona do frontendu czy coś.
Anyway: wzorzec Builder

MyClass object = MyClass.builder()
    .withA(xxx)
    .withB(yyy)
    .withC(zzz)
    .build();
0

Takie obejścia czasem*:

Foo(Properties p) :P 
Foo(Map<Key,Object> m)
    • tam gdzie wydaje się mieć to sens w danej chwili, aczkolwiek może nie przetrwać próby upływu czasu
0

Zależy jaki język.
W JS użyłbym obiektu z opcjami, np. tak

class A { 
    constructor(params = {}) {
          Object.assign(this, params); // kopiuje wlasciwosci z params to this
    }
}

W innych językach pewnie użyłbym słownika, mapy, hashu czy czegokolwiek by dostarczał język, żeby zaimplementować koncept "zbioru różnych właściwości" (w C++ pewnie params byłoby dużą strukturą z wieloma polami)

nie przekraczać jakiejś tam liczby parametrów?

niektóre języki, np. Python, mają parametry nazwane, to pozwala podawać tylko te, które są potrzebne.

Aha, teraz dopiero spojrzałem, że to pytanie mimo, że wydające się ogólne, jest w kategorii Java, więc pewnie o Javę chodzi. W sumie ciekawe, czy w Javie można zrobić to w jakiś miarę zgrabny sposób.

0
Shalom napisał(a):

No chyba nie aż taką typową, ale rozumiem że to jakieś wypychanie jsona do frontendu czy coś.

Praktycznie większość obiektów biznesowych ma złożoność powodującą przekroczenie przez konstruktor granic dobrego smaku - jak sobie weźmiesz jakąś klasę typu Employee, Customer, to raczej mało prawdopodobne, żeby skończyło się na tych ~5 atrybutach.

Anyway: wzorzec Builder

MyClass object = MyClass.builder()
    .withA(xxx)
    .withB(yyy)
    .withC(zzz)
    .build();

Tylko wzorzec builder nie rozwiązuje za bardzo niczego, bo jeśli upieramy się, żeby klasy były immutable, z polami oznaczonymi final to pod spodem nadal siedzi wieloparametrowy prywatny konstruktor.

2

@piotrpo: to sobie zgrupuj te parametry w mniejsze obiekty jak Ci za dużo. Do buildera dalej możesz przekazywać gołe dane, a pod spodem z 20 argumentów robisz na przykład 5, czy 6. Jeżeli to nie rozwiązuje Twojego problemu, to znaczy, że istnieje spora szansa na to, że masz skopany design.

Na przykład:
Zamiast street, zip, city, country => Address(street, zip, city, country)
Zamiast first name, middle name, last name, maiden name => Name(first name, middle name, last name, maiden name)

I tak dalej.

3

na ta chwile nie robie ani wielkich konstruktorow ani builderow bo obydwa rozwiazania sa brzydkie i upierdliwe w czytaniu/uzywaniu, zamiast tego stosuje cos w rodzaju normalizacji, tzn dziele parametry na logiczne grupy i przekazuje ich 2-3 zamiast 20, na dodatek czesto okazuje sie ze mozna z powodzeniem takich grup uzyc w innych miejscach i tym samym zredukowac zaleznosci od zbyt ogolnej klasy, przykladowo zamiast miec taki wielki konstruktor:

User(id, username, firstName, lastName, email, street, city, country, phone1, phone2, phone3, fb, twitter, github, whatever,...

lepiej miec pare klas w stylu:

User(userIds, person)
UserIds(...)
Person(...)
Address(...)
itd...
2

Dokładnie jak wyżej. Zwykle te wielkie biznesowe obiekty mają kilka kluczowych pól, reszta da się hierarchicznie pogrupować i czasem mają też dodatkowe dane, które np. bezmyślnie przepychamy między różnymi systemami, ale nas nie interesują. (te ostatnie pakujemy w worki typu Properties, HashMap).

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