Как мне структурировать наследование этого класса? - PullRequest
5 голосов
/ 18 мая 2011

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

Я буду писать псевдокод для моих примеров, поэтому, пожалуйста, не выделяйте синтаксис.

Когда я видел продемонстрированное наследование классов, обычно это что-то простое, например class Student extends Person() {},Очевидно, что ученик - более специализированный человек, так что это имеет смысл.

В моем приложении у меня есть класс Site(), который содержит соответствующую информацию, такую ​​как DSN, каталог загрузки файлов и т. Д. Я выполняю свойЭкспорт SQL в один класс и экспорт моего файла с загрузкой в ​​другой класс, оба из которых вызываются из класса сайта (псевдокод):

class Site {
    public function exportSql() {
        sqlExport = new sqlExport(this.dsn);
        sqlExport.createDumpAndZipItAndStuff();
    }
    public function exportUploads() {
        uploadsExport = new uploadsExport(this.uploadDirectory);
        uploadsExport.copyAndZipFilesAndStuff();
    }
}

Класс Site не делает ничего, кроме controlпоток трафика, который запрашивается из внешнего интерфейса приложения, все остальное передается одному из классов экспорта.

Это прекрасно работает для меня, но я хотел бы структурировать его правильно .Прямо сейчас я должен передать свойства Site конструктору классов экспорта, а затем установить свойства класса экспорта с этими аргументами.Это вызывает много дублирования.

Было бы целесообразно, чтобы мои классы экспорта наследовали класс Site, чтобы я мог получить прямой доступ к свойствам?Классы экспорта не являются более специализированным сайтом, как в примере Person / Student, который я приводил ранее.Скорее, они просто выполняют тяжелую работу для класса Site.

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

Ответы [ 2 ]

5 голосов
/ 18 мая 2011

Наследование следует использовать, когда что-то является видом другой вещи.

Подобно тому, как собака является видом животного, поэтому она должна наследоваться от животного.

Экспорт не является сайтом , поэтому он не должен наследоваться от него.

То, что вы ищете, это Композиция . Экспорт должен содержать ссылку на Сайт , который он экспортирует. Затем вы можете передать ему объект Site при его создании, и он может получать данные с сайта в любое время.

2 голосов
/ 19 мая 2011

Экспорт не должен расширять ваш класс Сайта, так как вещи, которые являются Экспортами, не являются членами подмножества вещей, которые являются Сайтами. Наследование чрезмерно используется, и в этом случае Composition имеет больше смысла, как и вы. Один из способов улучшить существующую объектную модель и улучшить тестируемость - использовать Dependency Injection.

Вызов «new» внутри экземпляра объекта делает вашу объектную модель более хрупкой и сложной для тестирования. Вы можете добавить экземпляры ваших экспортеров в класс Site.

Примечание: я назвал классы экспорта чуть более явно как существительные (SQLExporter, а не SQLExport). Это стилистическая вещь, но я думаю, что она лучше отражает роль класса: это объект, которому была делегирована роль экспорта данных.

public setSQLExporter( SQLExporter exporter )
{
   variables.sqlExporter = arguments.exporter;

   // set some properties on exporter here, like the DSN
   variables.sqlExporter.dsn = this.dsn;
}

public setUploadsExporter( UploadsExporter exporter )
{
   variables.uploadsExporter = arguments.exporter;

   // set some properties on exporter here, like the upload directory
   variables.uploadsExporter.uploadDirectory = this.uploadDirectory;
}

public function exportSql() {
    variables.sqlExporter.createDumpAndZipItAndStuff();

    // or maybe your generalize the interface to these exporters and do something like
    // variables.sqlExporter.export();
}

public function exportUploads() {
    variables.uploadsExporter.copyAndZipFilesAndStuff();

    // or maybe your generalize the interface to these exporters and do something like
    // variables.uploadsExporter.export();
}

Затем, в вашем главном приложении (или в другом месте, где создавался объект Site):

thisSite = new Site(...);

// Get some Exporters
thisSite.setSQLExporter( new SQLExporter() );
thisSite.setUploadsExporter( new UploadsExporter() );

// Trigger exports
thisSite.exportSql();
thisSite.exportUploads();

Это открывает двери для использования Mock Objects для непосредственного тестирования Site без необходимости иметь базу данных или файловую систему для общения. Если вы используете DI-фреймворк, такой как ColdSpring, фреймворк может сделать это за вас.

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