Дизайн класса - вопрос объектно-ориентированного программирования - PullRequest
0 голосов
/ 18 января 2019

Об этом спрашивали во время интервью.

Существуют разные производители автобусов. У каждого автобуса есть разные модели, и у каждой модели только 2 варианта. Так что у разных производителей разные модели только с 2 вариантами. Интервьюер попросил меня разработать отдельную программу только с уроками. Она упомянула, что я не должен думать о базах данных, и мне не нужно было их кодировать. Например, это может быть консольная программа с входами и выходами.

Информация о производителях, моделях и вариантах должна храниться в памяти (жестко закодированные значения подходят для этой отдельной программы). Она хотела наблюдать за занятиями и моим подходом к решению проблем.

Она сказала мне сосредоточиться на реализации трех API или методов для этой системы.

Первым было получить информацию о конкретном автобусе. Введите имя производителя, название модели и название варианта. Учитывая эти три значения, информация о конкретном автобусе, такая как его цена, модель, год и т. Д., Должна быть показана клиенту.

Вторым API будет сравнение двух шин, а выводом будет перечисление функций рядом друг с другом, возможно, в табличном формате. Входные данные будут такими же, как и для первого API, т. Е. Название производителя, название модели и название варианта для обеих шин.

Третий - поиск автобусов по цене (> = цена) и получение списка автобусов, удовлетворяющих условию.

Она также добавила, что API должны быть масштабируемыми, и я должен разработать решение с этим условием.

Вот как я разработал классы:

class Manufacturer {
    private String name;
    private Set<Model> models;
    // some  more properties related to manufacturer
}

class Model {
    private String name;
    private Integer year;
    private Set<Variant> variants;
    // some more properties related to model
}

class Variant {
    private String name;
    private BigDecimal price;
    // some more properties related to variant
}

class Bus {
    private String manufacturerName;
    private String modelName;
    private String variantName;
    private Integer year;
    private BigDecimal price;
    // some more additional properties as required by client
}

class BusService {

    // The first method
    public Bus getBusInformation(String manufacturerName, String modelName, String variantName) throws Exception {
        Manufacturer manufacturer = findManufacturer(manufacturerName);
        //if(manufacturer == null) throw a valid exception
        Model model = findModel(manufacturer);
        // if(model == null) throw a valid exception
        Variant variant = findVariant(model);
        // if(variant == null) throw a valid exception
        return createBusInformation(manufacturer, model, variant);
    }

}

Она подчеркнула, что было только 2 варианта, и вариантов больше не будет, и они должны быть масштабируемыми. После прохождения классов она сказала, что понимает мой подход, и мне не нужно было реализовывать другие API / методы. Я понял, что она не была впечатлена тем, как я их спроектировал.

Было бы полезно понять допущенную мною ошибку, чтобы я мог извлечь из нее урок.

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Я интерпретировал ваши 3 требования немного по-другому (и я могу ошибаться). Но звучит так, будто общее желание - иметь возможность выполнять различные поиски по всем моделям, верно?

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

Во всяком случае, исходя из моих подозрений, я бы сделал Модель центром фокуса и пошел бы с:

(базовый класс)

abstract class Model {
    private Manufacturer manufacturer;
    private String name;
    private String variant;
    private Integer year;
    private BigDecimal price;
    // some more properties related to model
}

(варианты производителя)

abstract class AlphaModel {
    AlphaModel() {
        this.manufacturer = new Manufacturer() { name = "Alpha" }
    }

    // some more properties related to this manufacturer
}

abstract class BetaModel {
    BetaModel() {
        this.manufacturer = new Manufacturer() { name = "Beta" }
    }

    // some more properties related to this manufacturer
}

(варианты модели)

abstract class AlphaBus : AlphaModel {
    AlphaBus() {
        this.name = "Super Bus";
    }
    // some more properties related to this model
}

abstract class BetaTruck : BetaModel {
    BetaTruck() {
        this.name = "Big Truck";
    }
    // some more properties related to this model
}

(фактические случаи)

class AlphaBusX : AlphaBus {
    AlphaBusX() {
        this.variant = "X Edition";
    }
    // some more properties exclusive to this variant
}

class AlphaBusY : AlphaBus {
    AlphaBusY() {
        this.variant = "Y Edition";
    }
    // some more properties exclusive to this variant
}

class BetaTruckF1 : BetaTruck {
    BetaTruckF1() {
        this.variant = "Model F1";
    }
    // some more properties exclusive to this variant
}

class BetaTruckF2 : BetaTruck {
    BetaTruckF2() {
        this.variant = "Model F2";
    }
    // some more properties exclusive to this variant
}

Затем, наконец:

var data = new Set<Model> {
    new AlphaBusX(),
    new AlphaBusY(),
    new BetaTruckF1(),
    new BetaTruckF2()
}

API # 1:

var result = data.First(x => x.manufacturer.name = <manufactuer> 
                          && x.name = <model>
                          && x.variant = <variant>);

API # 2:

var result1 = API#1(<manufacturer1>, <model1>, <variant1>);
var result2 = API#1(<manufacturer2>, <model2>, <variant2>);

API # 3:

var result = data.Where(x => x.price >= <price>);
0 голосов
/ 18 января 2019

Я бы сказал, что ваше представление класса Bus строго ограничено. Вариант, Модель, Производитель должны быть жесткими ссылками на классы, а не строками. Затем получить имя каждого.

E.G с точки зрения Bus bus1 this.variant.GetName() или из внешнего мира. bus1.GetVariant().name

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

С точки зрения вашего API (хотя у меня нет примера), ваш единственный способ получить информацию об автобусе ограничен. Если состав шины изменяется (изменяются варианты, вводятся новые классы компонентов), это требует достойного переписывания этой функции, и если другие функции пишутся аналогично, то все эти два.

Это потребует некоторых размышлений, но общий подход к этому, который может динамически захватывать информацию на основе входных данных, облегчает добавление / удаление компонентов в дальнейшем. Это будет тем, на чем ваш интервьюер уделял основное внимание с точки зрения продвинутых технических и языковых навыков. Правильная реализация обобщений, делегатов и т. Д. Может значительно упростить дальнейшее обслуживание вашего API. (Извините, у меня нет примера)

Я бы не сказал, что ваш подход здесь обязательно плохой, хотя переменные-члены строки, вероятно, являются единственной серьезной проблемой.

...