Как структурировать сложные объекты со связанными полями, которые должны быть инициализированы одновременно - PullRequest
2 голосов
/ 12 июля 2019

Я реализую API и продолжаю сталкиваться с этой проблемой, думаю, что-то не так с моим дизайном ядра, но я не уверен, что именно, и я чувствую себя подавленным принципами проектирования.

В основном у меня будет объект со связкой связанных полей. Заполнить поля правильной информацией нетривиально и полагаться на один или несколько внешних вызовов API с помощью клиента, который я передаю конструктору, эти вызовы API также предоставляют информацию, относящуюся к нескольким полям, поэтому желательно заполнить много полей одновременно. Я хочу, чтобы конструктор был простым / быстрым, и чтобы мой объект тестировался, чтобы я не помещал в него логику, а только присваивания. Однако в итоге я создаю один метод для заполнения всех полей и вызываю его во всех моих методах получения после нулевой проверки, т. Е. Лениво заполняет поля объекта.

Я думаю, что это плохо, потому что нарушает принцип «быстрого отказа», особенно потому, что я использую клиента для вызова внешней службы, которая может завершиться ошибкой, если, скажем, учетные данные клиента недействительны. Однако у меня возникают проблемы при реструктуризации моего кода.

Я думал об извлечении клиентской логики в сервис / коннектор, например, ClothingConnector, но я не уверен, что это решит мою проблему, так как я все еще не хотел бы вызывать это в конструкторе, и Было бы полезно заполнить сразу несколько полей.

class Person {
    ClientToGetClothing clothingClient;

    Pants pants;
    Shirt shirt;
    Fabric shirtFabric;
    Fabric pantsFabric;

    public Person(ClientToGetClothing clothingClient) {
         this.clothingClient = clothingClient;
    }

    private void populateClothing() {
         PantsResponse pantsInfo = clothingClient.retrievePantsInfo();
         this.pants = pantsInfo.getPants();

         ShirtResponse shirtInfo = clothingClient.retrieveShirtInfo();
         this.shirt = pantsInfo.getShirt();

         // do some more things with my pants + shirt and assign results to more fields, calculate the fabric in this example

    }

    public Shirt getShirt() {
        if (shirt == null) {
            populateClothing;
        }
        return this.shirt;
    }
    // ...
}

1 Ответ

1 голос
/ 12 июля 2019

Во-первых, я бы отделил объект ClothingClient от объекта Person. Попросите фабрику выполнить атрибутивную группу населения, а затем вернуть класс человека. https://en.wikipedia.org/wiki/Factory_method_pattern#Java

...