Statyczne metody wytwórcze vs konstruktory vs Factory

Odpowiedz Nowy wątek
2018-03-12 21:13
0

Tak mnie naszło po dzisiejszej dyskusji. Kiedy korzystacie, co preferujecie do tworzenia obiektów?

U mnie to wygląda tak:

public class Pojo {
    private static final int DEFAULT_INT_VALUE = -1;
 
    private final String someString; 
    private final int intValue;
 
    // Podstawowy konstruktor - warto pamiętać, 
    // żeby liczba wstrzykiwanych pól nie była 
    // za długa
    public Pojo(String someString, int intValue){
        // opcjonalnie guard-block
        this.someString = someString;
        this.intValue = intValue;
    }
 
    public Pojo(String someString){
        super(someString, DEFAULT_INT_VALUE);
    }
 
    // gettery, equals, hashCode i inna magia
 
    public static Pojo fromCSV(String line) throws IllegalArgumentException {
        Pojo result = ... // parsowanie i guard-block
 
        return result;
    }
 
    public static Pojo fromOtherPojo(OtherPojo otherPojo){
        return ... // mapowanie do Pojo etc. 
    }
 
    public static class Factory {
        private final int defaultIntValue; 
 
        public Factory(int defaultIntValue){
            this.defaultIntValue = defaultIntValue;
        }
 
        public Pojo get(String someString){
            return new Pojo(someString, defaultIntValue); 
        }
    }
}

Oczywiście jeśli klasa puchnie to rozdzielam je na mniejsze klasy w stylu PojoCSVParser, PojoFactory itd. Jeśli jest potrzeba to dorzucam Buildera.

Mutacje wyżej wymienionego, z którymi się spotkałem:

  • konstruktory tylko prywatne, jak chcesz jakiś upublicznić to przez static
  • odwrotnie do powyższego - "static Pojo" tylko w oddzielnych klasach
  • Factory.get powinno być zawsze bezargumentowe
  • w konstruktorach guard-block na nulle

Jak to jest u was? Macie lepsze patenty? Czy też po prostu nie zawracacie sobie tym głowy i jedziecie wszystko Lombokiem?

w drugim konstruktorze nie powinno być this zamiast super ? :) - Pablitto77 2018-03-13 22:19

Pozostało 580 znaków

2018-03-12 22:22
0

Kodzę na co dzień w Scali, ale dorzucę swoje trzy grosze.

konstruktory tylko prywatne, jak chcesz jakiś upublicznić to przez static

Nie widzę sensu jako ogólnej reguły.

w konstruktorach guard-block na nulle

Preferuję konstruktory, które nie mają żadnych efektów ubocznych (a więc nie mogą się sypnąć), nawet null-checków. Zwiększa to mocno testowalność i możliwości rozszerzania klasy. W testach mogę wstawić nulle tam gdzie wiem, że parametr nie będzie używany. Jeśli trzeba wykonać coś co powoduje efekty uboczne to zamykam taką logikę w statycznej metodzie wytwórczej.

Gdybym chciał np zabronić tworzenia klasy bez odpalania null-checków to mogę wystawić publiczną statyczną metodę wytwórczą oraz konstruktor o dostępie protected.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 1x, ostatnio: Wibowit, 2018-03-12 22:24

Pozostało 580 znaków

2018-03-12 22:37
0

to mogę wystawić publiczną statyczną metodę wytwórczą

No ale jak to będziesz mockował, w sytuacji gdy ten obiekt zostanie wyprodukowany statyczną metodą we wnętrzu innego obiektu? W tym innym obiekcie nie będziesz mógł podstawić mocka. Podobny problem jak tworzenie obiektów przez new.

Myślałem, że obiekty nie powinny być tworzone ani przez new ani przez statiki. Tylko przekazywanie przez konstruktor (przekazywanie obiektu albo przekazywanie fabryki).


Przeważnie ignoruję niezarejestrowanych użytkowników.
Jak utworzyć obiekt bez new? - Wibowit 2018-03-12 23:10
Obiekty tworzy się za pomocą new tylko w funkcji main. Potem trzeba sobie radzić bez new i bez staticów, za wyjątkiem pewnych klas podobnych do Int. - jarekczek 2018-03-13 17:47

Pozostało 580 znaków

2018-03-12 22:59
0

Ja generalnie korzystam tylko z 2 metod jak moge:
1)Konstruktor z argumentami
2)Statyczna metoda wytwórczaii
Zaletą te 2 jest to że ma nazwe inną niż kostruktor, co może się przydać w przypadku gdy chcesz stworzyć metode z tym samym zbiorem argumentów (czyli np. 2 metody które przyjmują Stringa ale inaczej sie nazywają) + możesz łatwiej kontrolować wytwarzanie obiektów (np. stworzyć tylko 1 obiekt i zawsze go zwracać). Wadą może być overkill czyli strzelanie z armaty do muchy, więc generalnie konstruktory z argumentami, jesli bardziej złożony projekt to jeszcze kontener IoC


Nie pomagam przez PM. Pytania zadaje się na forum.

Pozostało 580 znaków

2018-03-12 23:21
0
Wibowit napisał(a):

Kodzę na co dzień w Scali, ale dorzucę swoje trzy grosze.

konstruktory tylko prywatne, jak chcesz jakiś upublicznić to przez static

Nie widzę sensu jako ogólnej reguły.

w konstruktorach guard-block na nulle

Preferuję konstruktory, które nie mają żadnych efektów ubocznych (a więc nie mogą się sypnąć), nawet null-checków.

Niby ok, ale to wyciąga nam kontrakt klasy do metod statycznych. O ile to może się sprawdzać w momencie, kiedy wszystkie pola są final/efektywnie final o tyle w przypadku klas mutowalnych to idziemy w stronę:

  • "głupich" klas będących pojemnikami na wartości
  • serwisów operujących na obiektach wyżej wymienionych klas.

W sumie właśnie sobie uświadomiłem, że to zagadnienie trzeba różnicować ze względu na przeznaczenie obiektu. Klasy będące de facto serwisami rzeczywiście powinny być możliwie łatwo testowalne, przy czym klasy będące opakowaniami na dane takie być nie muszą.

jarekczek napisał(a):

to mogę wystawić publiczną statyczną metodę wytwórczą

No ale jak to będziesz mockował, w sytuacji gdy ten obiekt zostanie wyprodukowany statyczną metodą we wnętrzu innego obiektu? W tym innym obiekcie nie będziesz mógł podstawić mocka. Podobny problem jak tworzenie obiektów przez new.

A po co mockować?
Uważam, że takie statici nie powinny mieć dużych ilości kodu. Idąc dalej - powinny być też przetestowane. Tak samo jak nie mockujesz np. Integer.parseInt, tak samo nie ma potrzeby mockowania takich metod.

Myślałem, że obiekty nie powinny być tworzone ani przez new ani przez statiki. Tylko przekazywanie przez konstruktor (przekazywanie obiektu albo przekazywanie fabryki).

Co to znaczy "przez konstruktor"? Konstruktor wołasz ze słówkiem kluczowym "new" chyba?

edytowany 1x, ostatnio: wartek01, 2018-03-12 23:22

Pozostało 580 znaków

2018-03-12 23:28
0

Niby ok, ale to wyciąga nam kontrakt klasy do metod statycznych. O ile to może się sprawdzać w momencie, kiedy wszystkie pola są final/efektywnie final o tyle w przypadku klas mutowalnych to idziemy w stronę:

  • "głupich" klas będących pojemnikami na wartości
  • serwisów operujących na obiektach wyżej wymienionych klas.

Napisałem przecież, że możesz zrobić konstruktor protected oraz publiczną metodę wytwórczą. Wtedy dalej masz kontrakt w jednej klasie. Jaki jest konkretnie minus mojego podejścia?


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.

Pozostało 580 znaków

2018-03-13 17:52
0

A po co mockować?
Uważam, że takie statici nie powinny mieć dużych ilości kodu. Idąc dalej - powinny być też przetestowane. Tak samo jak nie mockujesz np. Integer.parseInt, tak samo nie ma potrzeby mockowania takich metod.

A kto powiedział, że mówimy tylko o tworzeniu małych klas? Ja mówię raczej o dużych.

Myślałem, że obiekty nie powinny być tworzone ani przez new ani przez statiki. Tylko przekazywanie przez konstruktor (przekazywanie obiektu albo przekazywanie fabryki).

Co to znaczy "przez konstruktor"? Konstruktor wołasz ze słówkiem kluczowym "new" chyba?

Przekazuję obiekt klasy B nowotworzonemu obiektowi klasy A przez konstruktor, więc klasa A nie używa już słówka new. A jeżeli klasa A potrzebuje wytworzyć więcej obiektów klasy B, dostanie w konstruktorze fabrykę. Myślałem, że to ogólnie obowiązujące i dobrze znane zasady, stąd ten skrót myślowy.


Przeważnie ignoruję niezarejestrowanych użytkowników.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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

Robot: CCBot