2016-02-22 5 views
1

У меня есть класс с одной частной области:избежать сеттер, чтобы изменить значение свойства класса

class Person { 
    string name; 
    public void setName(string name); 
} 

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

Person somePerson; 
CommandLineView view; 
somePerson.setName(view.askUserForName()); 

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

Новая реализация выглядит следующим образом:

class Person 
{ 
    string name; 
    public void changeName(view) { name = view.askUserForName(); } 
} 

и:

Person somePerson; 
CommandLineView view; 
somePerson.changeName(view); 

Теперь Person не разоблачить своего члена. Кроме того, этот класс отвечает за логику, связанную с изменением имени (например, функция changeName также может обновлять базу данных, уведомлять заинтересованные стороны и т. Д.

Вопрос: Является ли такой рефакторинг хорошей практикой? Или, может быть, реализация с setter была лучше ?, даже если она нарушает инкапсуляцию

+0

не знаю, подходит ли этот вопрос здесь, но IMO так, как вы его используете, теперь пара 'Person' подходит к' CommandLineView' - лучше иметь установщик или просто метод changeName (принимая новое имя) - это нормально, чтобы представление зависело от модели (очевидно), но другое направление - большой знак * предупреждения *! – Carsten

+0

Почему вы не хотите выставлять имя? –

+0

@Carsten - так что вы думаете о вставке нового слоя между 'person' и' view', например, некоторым презентатором? –

ответ

1

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

Person somePerson(view.askUserForName()); 

Проблема с подхода заключается в том, что вы сначала создать объект который не полностью инициализирован, так это опасность ous для использования: Person somePerson. Что, если вы забудете setName? Будет ли ваш код работать с этим «пустым» человеком?

И тогда вы разрешаете напрямую изменять внутреннее состояние с помощью метода setName, что также не очень хорошо.

Используя параметр конструктора, вы избегаете обеих этих проблем.

Что касается исходного вопроса - я не думаю, что существует большая разница между этими двумя методами. Результат - это то же самое - вы вызываете метод и внутреннее состояние объекта. Вы можете назвать его setName или changeName, результат будет таким же.

Второй способ с changeName(view) на самом деле хуже, потому что вы также вводите зависимость Person на объекте View. Теперь, если вы хотите изменить имя, вам всегда нужно создать объект View.

+0

Конечно, человек без имени может существовать в программном обеспечении! Я могу представить, например, людей, которых я вижу через окно - я знаю много о их внешности, но я узнаю их имя только после того, как я открою окно и попрошу его;) Но дело не в этом. –

+0

Согласен, может быть, зависимость от 'View' плохая. Возможно, это должно зависеть от чего-то типа «NameChanger». Я прочитал статью Егора Бугаенко: http://www.yegor256.com/2014/09/16/getters-and-setters-are-evil.html, и я следую этому предложению: «Объект может быть разветвлен в отличие от других объектов, поскольку они могут вставлять в нее любые новые данные через сеттеры. Объект просто не может безопасно инкапсулировать свое собственное состояние, так как любой может его изменить ». Ключевое слово здесь «безопасно» - я считаю, что разрешить только указанные объекты изменять состояние «Личность» помогает избежать некоторых ошибок. –

+1

@PiotrAleksanderChmielowski Я думаю, вы пытаетесь обмануть себя и найти какой-нибудь причудливый способ иметь сеттер для имени, в то время как в статье говорится, что вам следует избегать создания сеттеров вообще. Вот цитата: «Собака - это неизменный живой организм, который не позволяет никому извне менять вес, размер, имя и т. Д.». В принципе, если у вас есть геттер и сеттер, в любой форме, это то же самое, что просто объявить 'name' поданным как' public': 'person-> name =" New name "'. Это выглядит не очень хорошо? Но на самом деле это то, что у вас есть сеттер. –

Смежные вопросы