Соглашения для неизменяемых объектов

Когда вы создаете неизменяемые классы, предпочитаете ли вы:

Layer.ColorCorrect ( layer )

or

layer.ColorCorrect ( )

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


person Joan Venge    schedule 01.04.2009    source источник


Ответы (6)


Я бы предпочел использовать метод экземпляра, но выберите имя, чтобы отразить тот факт, что он не меняет существующий экземпляр. Например:

layer.AfterColorCorrection()

or

layer.WithCorrectedColors()

Использование статических методов довольно быстро утомляет. Кроме того, если вы дадите понять своим пользователям, что тип неизменяемый, они должны быстро это освоить. Всех сбивает с толку, что String.Replace на самом деле ничего не заменяет в мишени - но они не повторяют ту же ошибку. С лучшими именами тоже все будет в порядке.

Я спросил связанных вопрос о «добавлении» к неизменяемому списку - лучшее решение IMO - использовать «Плюс», а не «Добавить»; опять же, это не означает, что исходное значение было изменено. Вы можете найти другие ответы на этот вопрос полезными.

person Jon Skeet    schedule 01.04.2009
comment
Спасибо, Джон. Ваш вопрос очень полезен. Похоже, вы тоже очень обеспокоены лучшими возможными практиками :) - person Joan Venge; 01.04.2009
comment
Я, конечно, люблю думать о лучших практиках. Вы должны спросить моих коллег, в какой степени мой производственный код отражает их ... - person Jon Skeet; 01.04.2009
comment
ржу не могу. Лично я стараюсь использовать все, что узнаю, как можно скорее, поэтому я не забываю об интеграции их в свою работу :) Просто из любопытства, вы используете C # для большинства вещей, которые вы делаете на работе? - person Joan Venge; 01.04.2009
comment
Нет, к сожалению, мы мало используем C # - мой основной проект находится на Java. Мой проект на 20% портирует буферы протоколов на C #, так что это весело :) - person Jon Skeet; 01.04.2009
comment
Звучит весело :) Спасибо, Джон. - person Joan Venge; 02.04.2009
comment
Голосующие против: оставьте, пожалуйста, комментарий. Это делает его гораздо более полезным. - person Jon Skeet; 05.04.2009
comment
@Jon: Кто бы сказал, что это вне меня. Но не волнуйся, чувак, я рядом с тобой :) - person Joan Venge; 05.04.2009

Лично я предпочитаю сосредоточиться на том, чтобы было видно, что тип неизменяем. Например, я бы назвал это ImmutableLayer vs. Layer. Или, если по какой-то причине «Неизменяемый» не подходит для префикса имени, я добавлю к классу атрибут, указывающий на его «Неизменяемость» (атрибут добавляется в обоих случаях).

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

var col = GetTheCollection();
col.Add(42);

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

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

person JaredPar    schedule 01.04.2009

У @JaredPar есть лучший ответ, IMO, но ни один из ответов не является отличным, потому что сегодня для этого нет "отличных" решений. Нам нужны лучшие инструменты и рекомендации по проектированию, которые развиваются вместе с инструментами, чтобы лучше справляться с растущей популярностью неизменяемых объектов.

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

«Лучшее» имя зависит от контекста кода, которым вы окружены. Единственная стратегия, которая, на мой взгляд, жизнеспособна в диапазоне контекстов от «в основном изменчивого» до «в основном неизменяемого», - это та, о которой упоминает Джаред, где инструменты делают очевидным, является ли данный объект неизменным, а затем каждый метод имеет «императив». name (egoAdd), которое либо оказывает побочное действие на объект-получатель (если он изменяемый), либо возвращает новый объект (если он неизменяемый).

(Кроме того: к сожалению, «беглые» эффективные API, такие как StringBuilder, означают, что вы не можете просто посмотреть на сигнатуру метода, чтобы решить, является ли объект-получатель неизменным, поскольку такие примеры «возвращают это», чтобы быть беглым, давая ту же сигнатуру как «вернуть копию».)

person Brian    schedule 04.04.2009

Обычно у вас будет что-то вроде:

layer = layer.ColorCorrect([required parameters here]);

Это было бы похоже на

mystring = mystring.Substring(1, 2);

Где создается новая строка, это подстрока первой.

person Neil Barnwell    schedule 01.04.2009
comment
Спасибо, вы имеете в виду params как ключевое слово params для передачи других значений? - person Joan Venge; 01.04.2009
comment
Нет, просто как заполнитель, чтобы указать, что могут быть параметры. - person Neil Barnwell; 01.04.2009

Это абсолютно противоречит принципам OOPS - писать статический метод, передавать экземпляр и делать его почти похожим на процедурное программирование, такое как "C". Также в 1-м методе вы дважды набираете Layer, что делает его неоднозначным для читателя.

person Akash Kava    schedule 01.04.2009
comment
Спасибо. Что OOPS? Также не могли бы вы рассказать, почему это не лучшая практика. Также слой var был просто примером. Что, если бы это было что-то вроде normalMap, а затем передали бы Layer.ColorCorrect, который сообщал бы программисту, что это слой. - person Joan Venge; 01.04.2009
comment
OOPS означает объектно-ориентированную систему программирования. Обычно, если необходимо изменить члены класса, вы создаете свойства, создавая средства доступа и мутаторы. Большинство функций никогда ничего не могут изменить, тем не менее, они кодируются как методы экземпляра. - person Akash Kava; 02.04.2009

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

person Ken    schedule 01.04.2009