POJO z finalnymi atrybutami

Odpowiedz Nowy wątek
2019-04-23 18:05
0

Jak mam 7 atrybutów klasy POJO, finalne inicjowane w konstruktorze to lepiej robić konsturktor z 7 parametrami obowiązkowymi czy buildera?

Pozostało 580 znaków

2019-04-23 18:25
2

Wg mnie wtedy lepiej

  • nauczyć się Kotlina
  • zdefiniować sobie POJO z domyślnymi parametrami w data classie
  • zapomnieć o builderach i tworzyć sobie obiekty jak człowiek, z tymi parametrami których akurat potrzebujesz
  • side note: data class daje Ci gotową metodę copy() z możliwością nadpisania wybranych parametrów w kopii obiektu

Nie znam się, ale się wypowiem
edytowany 3x, ostatnio: superdurszlak, 2019-04-23 18:27

Pozostało 580 znaków

2019-04-23 18:34
0

Napisanie buildera, który zapewnia ci parametry obowiązkowe (i to 7) nie jest takie proste :). Jak masz aż 7 parametrów to znak ze cos jest nie tak z twoim POJO, chyba ze to szpring :) Lombok może być pomocny ;)

edytowany 1x, ostatnio: Interpod, 2019-04-23 18:35
Co do Lomboka, odsyłam do mądrzejszych ode mnie :P https://twitter.com/jarek000000/status/919213069418496000 - superdurszlak 2019-04-23 18:36

Pozostało 580 znaków

2019-04-23 18:46
0

Jest 7 atrybutów, bo to końcowy produkt całej apki, który następnie jest konwertowany i w całości ładowany do Mongo.

Pozostało 580 znaków

2019-04-24 10:00
0

Najpierw sprawdź, czy nie możesz wyodrębnić innej klasy z tych parametrów. Np. klasa User dostaje firstName, secondName, surname. Te trzy pola można z powodzeniem przerzucić do klasy UserName i ją wstrzykiwać przez konstruktor do klasy User. Jeśli nadal to nie wystarcza to idź w buildera.


Pozostało 580 znaków

2019-04-24 10:07
0
superdurszlak napisał(a):

Wg mnie wtedy lepiej

  • nauczyć się Kotlina
  • zdefiniować sobie POJO z domyślnymi parametrami w data classie
  • zapomnieć o builderach i tworzyć sobie obiekty jak człowiek, z tymi parametrami których akurat potrzebujesz
  • side note: data class daje Ci gotową metodę copy() z możliwością nadpisania wybranych parametrów w kopii obiektu

W javie 12 jest coś podobnego - zamiast data class masz record. :) Chociaż nie wiem czy będzie odpowiednik copy
EDIT: miało być coś podobnego, jednak to nie prawda; @Wibowit dzięki za sprostowanie

edytowany 1x, ostatnio: orchowskia, 2019-04-25 09:40
A czy record będzie wspierał named parameters? Bez tego nawet z default parameters to będzie takie trochę połowiczne rozwiązanie, a po szybkim googlowanku nie znalazłem nic o tym - superdurszlak 2019-04-24 10:18
Nic mi na ten temat nie wiadomo. Też poszukałem i wydaje mi się że jest tam po prostu zwyczajny konstruktor. Chociaż może będzie można przekazać jakąś mapę czy cóś. - orchowskia 2019-04-24 10:26
W Javie 12 jedyną zmianą w języku są switch expressions: http://openjdk.java.net/projects/jdk/12/ W Javie 13 jeszcze nic nie jest zaplanowane: http://openjdk.java.net/projects/jdk/13/ - Wibowit 2019-04-24 19:33
@Wibowit: fakt nie doczytałem, to było planowane, ale może w 13 się uda, a w następnym LTS już będzie do użytku na produkcji :D - orchowskia 2019-04-25 09:39
Rzeczywiście, jest taki JEP draft zgłoszony przez Briana Goetze'a - JEP draft: Records and Sealed Types :) - catom 2019-04-25 13:50
Zgłoszonych JEPów jest sporo: http://openjdk.java.net/jeps/0 - Wibowit 2019-04-25 14:01

Pozostało 580 znaków

2019-04-24 19:14
0

Pokażę Wam na kodzie o co chodzi.

Było tak:

public interface Result {

    boolean isValid();

    ResultSalary getSalary();

    Optional<Integer> getWorkExpInMonths();

    Set<String> getTech();

    Optional<String> getArea(); 

    Optional<Integer> getAge();

    Optional<ContractType> getContractType();
}
final class ResultImpl implements Result {

    private final boolean isValid;
    private final MessageSalary salary;
    private final Optional<Integer> experience;
    private final Set<String> technologies;
    private final Optional<String> location;
    private final Optional<Integer> age;
    private final Optional<ContractType> contractType;

    public ResultImpl (String content) {
        Scrapper<Integer> scrapperExp = new ScrapperExpFactory().produceDefault();
        Scrapper<String> scrapperTech = new ScrapperTechFactory().produceDefault();
        Scrapper<String> scrapperLocation = new ScrapperLocationFactory().produceDefault();
        Scrapper<Integer> scrapperAge = new ScrapperAgeFactory().produceDefault();
        Scrapper<ContractType> scrapperContractType = new ScrapperContractTypeFactory().produceDefault();

        this.salary = new MessageSalary4programmers(content);
        this.experience = scrapperExp.scrapeFrom(content).stream().min(Comparator.naturalOrder());
        this.technologies = new HashSet<String>(scrapperTech.scrapeFrom(content));
        this.location = scrapperLocation.scrapeFrom(content).stream().findFirst();
        this.age = scrapperAge.scrapeFrom(content).stream().findFirst();
        this.contractType = scrapperContractType.scrapeFrom(content).stream().findFirst();
        this.isValid = salary.getValueMonth().isPresent() && experience.isPresent() && technologies.size() > 0;
    }

    @Override
    public boolean isValid() {
        return this.isValid;
    }

    @Override
    public MessageSalary getSalary() {
        return this.salary;
    }

    @Override
    public Optional<Integer> getWorkExpInMonths() {
        return this.experience;
    }

    @Override
    public Set<String> getTech() {
        return technologies;
    }

    @Override
    public Optional<String> getArea() {
        return location;
    }

    @Override
    public Optional<Integer> getAge() {
        return age;
    }

    @Override
    public Optional<ContractType> getContractType() {
        return contractType;
    }
}
interface ResultSalary {

    Optional<Integer> getValueMonth();

    Optional<NettoBruttoSalary> getNettoBrutto();

    Optional<CurrencySalary> getCurrency();

    double getExchangeRate();
}
final class ResultSalaryImpl implements ResultSalary {

    private final Optional<Integer> value;
    private final Optional<NettoBruttoSalary> netGross;
    private final Optional<CurrencySalary> currency;
    private final double exchangeRate;

    public ResultSalaryImpl (String content) {
        Scrapper<Integer> scrapperSalaryValue = new ScrapperSalaryValueFactory().produceDefault();
        Scrapper<NettoBruttoSalary> scrapperNetGross = new ScrapperNetGrossFactory().produceDefault();
        Scrapper<CurrencySalary> scrapperCurrency = new ScrapperCurrencyFactory().produceDefault();

        this.value = scrapperSalaryValue.scrapeFrom(content).stream().findFirst();
        this.netGross = scrapperNetGross.scrapeFrom(content).stream().findFirst();
        this.currency = scrapperCurrency.scrapeFrom(content).stream().findFirst();
        this.exchangeRate = currency.isPresent() ? 
                (GlobalDataHolder.CURRENCIES.getMap().get(currency.get().toString())) : 1.0;
    }

    @Override
    public Optional<Integer> getValueMonth() {
        return value;
    }

    @Override
    public Optional<NettoBruttoSalary> getNettoBrutto() {
        return netGross;
    }

    @Override
    public Optional<CurrencySalary> getCurrency() {
        return currency;
    }

    @Override
    public double getExchangeRate() {
        return exchangeRate;
    }
}

zamieniłem na:

public final class Result {

    public final boolean isValid;
    public final MessageSalary salary;
    public final Optional<Integer> experience;
    public final Set<String> technologies = new HashSet<>();
    public final Optional<String> location;
    public final Optional<Integer> age;
    public final Optional<ContractType> contractType;

    public Result(Builder builder) {
        this.isValid = builder.isValid;
        this.salary = builder.salary;
        this.experience = builder.experience;
        this.technologies.addAll(builder.technologies);
        this.location = builder.location;
        this.age = builder.age;
        this.contractType = builder.contractType;
    }

    public static class Builder {
        boolean isValid;
        MessageSalary salary;
        Optional<Integer> experience;
        Set<String> technologies;
        Optional<String> location;
        Optional<Integer> age;
        Optional<ContractType> contractType;

        public Builder setValid(boolean isValid) {
            this.isValid = isValid;
            return this;
        }

        public Builder setMessageSalary(MessageSalary salary) {
            this.salary = salary;
            return this;
        }

        public Builder setExperience(Optional<Integer> experience) {
            this.experience = experience;
            return this;
        }

        public Builder setTechnologies(Set<String> technologies) {
            this.technologies = technologies;
            return this;
        }

        public Builder setLocation(Optional<String> location) {
            this.location = location;
            return this;
        }

        public Builder setAge(Optional<Integer> age) {
            this.age = age;
            return this;
        }

        public Builder setContractType(Optional<ContractType> contractType) {
            this.contractType = contractType;
            return this;
        }

        public Result build() {
            return new Result(this);
        }
    }
}
interface ResultFactory {

    Result createResult(String content);
}
final class ResultFactoryImpl implements ResultFactory {

    @Override
    public ResultFactoryImpl createResult(String content) {
        Scrapper<Integer> scrapperExp = new ScrapperExpFactory().produceDefault();
        Scrapper<String> scrapperTech = new ScrapperTechFactory().produceDefault();
        Scrapper<String> scrapperLocation = new ScrapperLocationFactory().produceDefault();
        Scrapper<Integer> scrapperAge = new ScrapperAgeFactory().produceDefault();
        Scrapper<ContractType> scrapperContractType = new ScrapperContractTypeFactory().produceDefault();

        MessageSalary salary = new MessageSalary4programmersFactory().createMessageSalary(content);
        Optional<Integer> experience = scrapperExp.scrapeFrom(content).stream().min(Comparator.naturalOrder());
        Set<String> technologies = new HashSet<String>(scrapperTech.scrapeFrom(content));
        Optional<String> location = scrapperLocation.scrapeFrom(content).stream().findFirst();
        Optional<Integer> age = scrapperAge.scrapeFrom(content).stream().findFirst();
        Optional<ContractType> contractType = scrapperContractType.scrapeFrom(content).stream().findFirst();
        boolean isValid = salary.value.isPresent() && experience.isPresent() && technologies.size() > 0;

        return new Result.Builder()
                .setMessageSalary(salary)
                .setExperience(experience)
                .setTechnologies(technologies)
                .setLocation(location)
                .setAge(age)
                .setContractType(contractType)
                .setValid(isValid)
                .build();
    }
}
final class ResultSalary {

    public final Optional<Integer> value;
    public final Optional<NetGrossSalary> nettoBrutto;
    public final Optional<CurrencySalary> currency;
    public final double exchangeRate;

    public ResultSalary (Builder builder) {
        this.value = builder.value;
        this.nettoBrutto = builder.nettoBrutto;
        this.currency = builder.currency;
        this.exchangeRate = builder.exchangeRate;
    }

    public static class Builder {
        Optional<Integer> value;
        Optional<NetGrossSalary> nettoBrutto;
        Optional<CurrencySalary> currency;
        double exchangeRate;

        public Builder setValue(Optional<Integer> value) {
            this.value = value;
            return this;
        }

        public Builder setNettoBrutto(Optional<NetGrossSalary> nettoBrutto) {
            this.nettoBrutto = nettoBrutto;
            return this;
        }

        public Builder setCurrency(Optional<CurrencySalary> currency) {
            this.currency = currency;
            return this;
        }

        public Builder setExchangeRate(double exchangeRate) {
            this.exchangeRate = exchangeRate;
            return this;
        }

        public ResultSalary build() {
            return new ResultSalary(this);
        }
    }
}
interface MessageSalaryFactory {

    MessageSalary createResultSalary(String content);
}
final class ResultSalaryFactoryImpl implements ResultSalaryFactory {

    @Override
    public ResultSalaryFactoryImpl createResultSalary(String content) {
        Scrapper<Integer> scrapperSalaryValue = new ScrapperSalaryValueFactory().produceDefault();
        Scrapper<NetGrossSalary> scrapperNetGross = new ScrapperNetGrossFactory().produceDefault();
        Scrapper<CurrencySalary> scrapperCurrency = new ScrapperCurrencyFactory().produceDefault();

        Optional<Integer> value = scrapperSalaryValue.scrapeFrom(content).stream().findFirst();
        Optional<NetGrossSalary> netGross = scrapperNetGross.scrapeFrom(content).stream().findFirst();
        Optional<CurrencySalary> currency = scrapperCurrency.scrapeFrom(content).stream().findFirst();
        double exchangeRate = currency.isPresent() ? 
                (GlobalDataHolder.CURRENCIES.getMap().get(currency.get().toString())) : 1.0;

        return new ResultSalaryFactory.Builder()
                .setValue(value)
                .setNettoBrutto(netGross)
                .setCurrency(currency)
                .setExchangeRate(exchangeRate)
                .build();

    }
}

Chyba źle zrobiłęm, bo 120 linijek zaminiłem na 180

edytowany 2x, ostatnio: Julian_, 2019-04-24 19:16

Pozostało 580 znaków

2019-04-24 21:56
1

W przykładzie z interfejsem możesz użyć biblioteki Immutables, która generuje automatycznie implementację i builder. Ewentualnie możesz użyć lomboka. Najlepiej jednak jest wybrać np. Kotlina zamiast pluginów do kompilatora. Kotlin w sumie też jest pluginem do kompilatora, tylko stabilniejszym i lepiej udokumentowanym

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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