Соглашения для неизменных объектов - PullRequest
1 голос
/ 01 апреля 2009

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

Layer.ColorCorrect ( layer )

или

layer.ColorCorrect ( )

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

Ответы [ 6 ]

8 голосов
/ 01 апреля 2009

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

layer.AfterColorCorrection()

или

layer.WithCorrectedColors()

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

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

5 голосов
/ 01 апреля 2009

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

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

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

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

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

3 голосов
/ 05 апреля 2009

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

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

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

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

1 голос
/ 01 апреля 2009

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

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

Это будет похоже на

mystring = mystring.Substring(1, 2);

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

0 голосов
/ 01 апреля 2009

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

0 голосов
/ 01 апреля 2009

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

...