Это плохой дизайн, чтобы класс использовался только одним другим классом? - PullRequest
1 голос
/ 05 августа 2010

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

Мой вопрос заключается в том, должен ли я создать отдельный класс с именем QueueProcessorSummaryEmail или он считается плохимдизайн, так как он чрезвычайно тесно связан с оригинальным классом?Если бы я сделал его собственным классом, мне пришлось бы передать ему тонну данных для генерации электронной почты, но было бы неплохо иметь такое разделение.Если я не делаю его классом, все данные доступны из класса QueueProcessor, но он просто странно смешивает логику обработки и логику генерации отчетов в одном классе.

И для справки: когда я говорю «логика генерации отчета», я не имею в виду, что я генерирую HTML-код в строке;Я использую представление для этого.Под форматированием я подразумеваю сбор данных и их объединение во что-то, что можно использовать в отчете по электронной почте.

Ответы [ 6 ]

4 голосов
/ 05 августа 2010

Ryeguy,

Мое предложение состояло бы в том, чтобы создать класс декоратора (например, SummarizedQueryProcessor), чтобы расширить функциональность QueueProcessor. Это позволит повысить степень разделения проблем и упростит модульное тестирование.

Ted

4 голосов
/ 05 августа 2010

считается ли это плохим дизайном, поскольку он чрезвычайно тесно связан с оригинальным классом?

Нет, это не проблема. Подкласс-суперкласс дизайн также тесно связан.

просто странно смешивать логику обработки и логику генерации отчетов в одном классе.

Делегирование отчетности / резюме часто имеет смысл. Отчет об изменениях и расширении быстрее, чем при обработке.

1 голос
/ 05 августа 2010

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

Затем ваш конструктор для QueueProcessorSummaryEmail может принять ISummaryDataProvider в качестве параметра. Таким образом, если вы когда-нибудь решите получить сводные данные от чего-то другого, чем QueueProcessor, вам просто нужно убедиться, что ваш новый источник данных реализует ISummaryDataProvider, чтобы он мог правильно использоваться QueueProcessorSummaryEmail.


Я рассмотрел похожие вопросы объектно-ориентированного проектирования в своем вопросе Как мне смоделировать код, чтобы максимизировать повторное использование кода в этой конкретной ситуации? . В одном из ответов предлагалось использовать Dependency Injection , чего я раньше не понимал. Внизу моего вопроса вы можете увидеть, как я реализовал это решение в слабосвязанной форме. Там может оказаться полезной информация для вашей ситуации.

0 голосов
/ 05 августа 2010

А как насчет этого?

public interface WorkProcessorI {
    public void process( WorkQueue queue ); // could also be something like "process( Task[] queue )"
}

public interface SummaryGeneratorI () {
    public String[][] generateSummary(); // returns subscripted string array of name/values or whatever
}

public class QueueProcessor implements WorkProcessorI, SummaryGeneratorI {
    public void process( WorkQueue queue ) {
        // process queue populating member values that will be used to generate the summary.
     }

     public String[][] generateSummary() {
        // read values that were populated by the process( WorkQueue ) method.
     }
}

public class SummaryMail {
    private String[][] summary = null;
    public void setSummary( String[][] argSummary ) {
        this.summary = argSummary;
    }
    // to, from, server, cc, bcc, subject, Additional body text, ...

    public void send() {
        // sends email via whatever api you want.
    }
}
0 голосов
/ 05 августа 2010

Структура имеет значение. Если есть набор логики, который на самом деле не принадлежит классу, то рефакторинг его в другом месте может реально помочь в обеспечении доступности в будущем.

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

0 голосов
/ 05 августа 2010

ryeguy,

Я бы хотел сделать класс QueueProcessor базовым абстрактным классом, а затем расширить его до класса QueueProcessorSummaryMail.

ok, базовый пример:

class QueueProcessor
{
     // all your methods and properties
}

class QueueProcessorSummaryMail extends QueueProcessor
{
     // add your custom properties and methods here
}

Надеюсь, это дает вам основную идею.

jim

[edit], что, конечно, для php.для c # вы все равно будете использовать либо абстрактные классы, либо интерфейс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...