Конструктор со всеми свойствами класса или конструктор по умолчанию с установщиками? - PullRequest
24 голосов
/ 06 мая 2009

Ниже приведены два подхода:

  • конструктор со всеми свойствами класса

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

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

  • сеттеры и пустой конструктор по умолчанию

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

Минусы: создание объекта с множеством свойств может занять несколько строк (не знаю, действительно ли это кон), и если я забуду установить свойство, компилятор ничего не скажет.

Что вы будете делать и почему? Знаете ли вы о каком-либо шаблоне освещения (подумайте, что его следует использовать каждый раз, когда создается экземпляр объекта со свойствами 7+), чтобы предложить? Я спрашиваю об этом, потому что мне не нравятся большие конструкторы, где я не могу быстро понять, где находится переменная, которую я ищу, с другой стороны, я нахожу «установить все свойства» уязвимыми для пропуска некоторых свойств.

Не стесняйтесь аргументировать мои предположения о плюсах и минусах, поскольку они являются только моими мыслями:)

Обновление - вопрос, который я нашел, который связан с этим: Создание больших неизменяемых объектов без использования конструкторов, имеющих длинные списки параметров

Ответы [ 9 ]

26 голосов
/ 06 мая 2009

Вы пропустили самое большое про наличие конструктора с множеством параметров: он позволяет создавать неизменяемые типы.

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

20 голосов
/ 06 мая 2009

Вы можете взглянуть на шаблон Builder, поддерживаемый Джошуа Блохом и описанный в Effective Java . Есть презентация с основными пунктами на http://developers.sun.com/learning/javaoneonline/2007/pdf/TS-2689.pdf;, без сомнения, вы могли бы найти лучший справочник.

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

Например, предположим, у меня есть простой Message с несколькими свойствами. Клиентский код, создающий это, может использовать конструктор для подготовки Message следующим образом:

Message message = new Message.Builder()
    .sender( new User( ... ) )
    .recipient( new User( ... ) )
    .subject( "Hello, world!" )
    .text( messageText )
    .build();

Фрагмент Message.Builder может выглядеть примерно так:

public class Builder {

    private User sender = null;
    // Other properties

    public Builder sender( User sender ) {
        this.sender = sender;
        return this;
    }
    // Methods for other properties

    public Message build() {
        Message message = new Message();
        message.setSender( sender );
        // Set the other properties
        return message;
    }

}
6 голосов
/ 06 мая 2009

Недавние научные исследования (CMU и Microsoft) по юзабилити API позволяют предположить, что конструкторы по умолчанию с установщиками были бы подходящими с точки зрения удобства использования. Это из «Дейффа Стилоса и Стивена Кларка» «Последствия использования удобства требования параметров в конструкторах объектов» и было представлено на Международной конференции по разработке программного обеспечения:

Аннотация : Удобство использования API становится все более важным для производительности программистов. Основываясь на опыте изучения юзабилити конкретных API, были изучены методы изучения юзабилити вариантов проектирования, общих для многих API. Было проведено сравнительное исследование для оценки того, как профессиональные программисты используют API-интерфейсы с необходимыми параметрами в конструкторах объектов, в отличие от безпараметрических конструкторов «по умолчанию». Высказывалось предположение, что требуемые параметры позволят создать более удобные и самодокументируемые API, помогая программистам правильно использовать объекты и предотвращая ошибки. Однако в ходе исследования было установлено, что, вопреки ожиданиям, программисты предпочитали и были более эффективными с API, которые не требовали параметров конструктора. Поведение участников анализировалось с использованием структуры когнитивных измерений и выявляло, что требуемые параметры конструктора мешают распространенным стратегиям обучения, вызывая нежелательные преждевременные обязательства.

3 голосов
/ 06 мая 2009

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

Геттеры и сеттеры намного легче отлаживать, особенно если вы устанавливаете меры безопасности, которые выдают исключение времени выполнения, если объект не заполнен должным образом. И я большой поклонник "легко отлаживать".

До этой темы я никогда не слышал о паттерне Билдера, который упоминает Роберт. Никогда не использовал его сам (очевидно), но это чертовски интригующе.

2 голосов
/ 07 мая 2009

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

Например, если у вас есть что-то вроде этого:

class Contact
{
    public Contact(string firstName, string lastName, string phoneNumber,
        string street, string city, string state, int zipCode) { ... }
}

Я бы реорганизовал его на:

class Contact
{
    public Contact(Person person, PhoneNumber number, Address address) { ... }
}

class Person
{
    public Person(string firstName, string lastName) { ... }
}

class PhoneNumber
{
    public PhoneNumber(string digits) { ... }
}

class Address
{
    public Address(string street, string city, string state, int zipCode) { ... }
}

Слишком большие классы - действительно распространенная проблема проектирования в базах кода ООП.

0 голосов
/ 07 мая 2009

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

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

0 голосов
/ 06 мая 2009

сеттеры и пустой конструктор по умолчанию

JRL косвенно коснулся его , но одной из причин, чтобы рассмотреть возможность использования сеттеров, является соответствие объекта спецификации JavaBean . Это делает экземпляры пригодными для редактирования с помощью инструментов самоанализа и настойчивости с использованием определенных методов сериализации .

0 голосов
/ 06 мая 2009

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

0 голосов
/ 06 мая 2009

Есть и другие аспекты. Если вы хотите иметь возможность делать определенные вещи с вашим классом во время разработки, а не только во время выполнения, например, добавляя свой класс как объект в палитре объектов (это Java с использованием Netbeans), вам нужно предоставить конструктор без аргументов в чтобы иметь возможность сделать это.

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