Разработка класса Bot, способного возвращать объекты ответа для всех типов объектов вопросов - PullRequest
2 голосов
/ 17 февраля 2010

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

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

Так что-то вроде этого:

public class GraphBot {
    private Graph graph;

    public GraphBot(Graph graph) {
        this.graph = graph;
    }

    public Answer ask(Question question) {
        // delegate somehow to answer the question, providing the graph
        // return an Answer object encapsulating the answer
    }
}

public interface Answer {
    public toPrintableOutput();
}

public interface Question {
    // question methods go here... this is what I'm having trouble with
}

Проблема в том, что у вопросов есть связанные условия или параметры. Например, вопрос «длина пути» между «A» и «B» имеет тип вопроса («длина пути»), который задают все вопросы, а также параметры «A» и «B». Для сравнения, вопрос «пути, проходящие через вершину» будет иметь только параметр «C», представляющий вершину.

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

Каков наиболее расширяемый способ внедрения этой системы, чтобы новые вопросы не требовали тонны изменений в нагрузках различных классов? На самом деле я хочу иметь возможность создать класс, реализующий Вопрос, и, возможно, создать класс, который может решить этот вопрос, а затем автоматически установить GraphBot для обработки этого вопроса.

1 Ответ

1 голос
/ 17 февраля 2010

То, что вы можете сделать, это просто включить метод ask() в интерфейс Question и принять Graph. Таким образом, каждый Question должен знать, как ответить самому себе, и вам не нужно разрабатывать Question API, который можно расширять в будущем.

РЕДАКТИРОВАТЬ: Почему это лучший дизайн, чем GraphBot быть в состоянии ответить на Question?

  • Простота. Как вы выяснили, очень сложно разработать Question API, который будет учитывать все возможные данные, необходимые для любого вопроса, а также придумывать, как скомпилировать его в динамический алгоритм вопросов. Намного проще иметь собственный код для Question, который будет знать, что делать с общеизвестными данными Graph.
  • Depndencies: ваш первоначальный подход делает относительно стабильным GraphBot зависимым от явно нестабильного Question. Мой подход обращает вспять эту зависимость, делая все намного проще, что приводит к последнему пункту.
  • Техническое обслуживание: я гарантирую, что вы не сможете предсказать все, что класс Question должен сделать доступным. Когда (не если) вы сталкиваетесь с изменением, которое необходимо внести в интерфейс Question, должен быть изменен каждый исполнитель. Это заставит ваше будущее вы (или другого разработчика) ненавидеть ваше настоящее с огненной страстью в тысячу солнц, если существует более чем несколько Question исполнителей.

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

Так что теперь это будет так:

public class GraphBot {
    private Graph graph;

    public GraphBot(Graph graph) {
        this.graph = graph;
    }

    public Answer ask(Question question) {
        return question.ask(graph);
    }
}

public interface Answer {
    public toPrintableOutput();
}

public interface Question {
    public Answer ask(Graph graph);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...