Классы именования - как избежать вызова всего "Менеджера <WhatEver>"?
=====================================================================

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

  Например, если бы мое приложение (как типичное бизнес-приложение) обрабатывало пользователей, компании и адреса, у меня был бы класс домена " `User`, " `Company` и " `Address` " - и, возможно, где-нибудь `UserManager` бы `UserManager`, `CompanyManager` и `AddressManager`, который обрабатывает эти вещи.

  Так что вы можете сказать, что `UserManager` эти `UserManager`, `CompanyManager` и `AddressManager`? Нет, потому что Менеджер - это очень очень общий термин, который подходит для всего, что вы можете делать с объектами вашего домена.

  В статье, которую я прочитал, рекомендуется использовать очень конкретные имена. Если бы это было приложение C++, а задание `UserManager` и освобождало пользователей из кучи, оно не управляло бы пользователями, а охраняло их рождение и смерть. Хм, может быть, мы могли бы назвать это `UserShepherd`.

  Или, возможно, задание `UserManager` заключается в `UserManager` данных каждого объекта пользователя и криптографической подписи данных. Тогда у нас будет `UserRecordsClerk`.

  Теперь, когда эта идея застряла у меня, я пытаюсь применить ее. И найти эту простую идею удивительно сложно.

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

  В конечном счете, я хотел бы иметь что-то вроде каталога шаблонов (часто шаблоны проектирования легко предоставляют имена объектов, например, фабрику)

 * Factory - создает другие объекты (наименования взяты из шаблона проектирования)
* Пастух - Пастух управляет временем жизни объектов, их созданием и отключением.
* Синхронизатор - копирует данные между двумя или более объектами (или иерархиями объектов)
* Няня - Помогает объектам достигать "пригодного для использования" состояния после создания - например, путем подключения к другим объектам
* и т.д.

 Итак, как вы решаете эту проблему? У вас есть постоянный словарный запас, вы придумываете новые имена на лету или считаете, что называть вещи не так важно или неправильно?

  PS: меня также интересуют ссылки на статьи и блоги, обсуждающие эту проблему. Для начала вот оригинальная статья, которая заставила меня задуматься об этом: [именование классов Java без "менеджера"](http://www.bright-green.com/blog/2003_02_25/naming_java_classes_without_a.html)

 

---

 Обновление: резюме ответов
---------------------------

  Вот небольшое резюме того, что я узнал из этого вопроса в то же время.

 * Старайтесь не создавать новые метафоры (няня)
* Посмотрите, что делают другие фреймворки

 Другие статьи/книги на эту тему:

 * [Какие имена вы регулярно посещаете/добавляете на занятия?](/questions/11784/what-names-do-you-find-yourself-prependingappending-to-classes-regularly)
* [Каков наилучший подход к именованию классов?](/questions/11786/whats-the-best-approach-to-naming-classes)
* Книга: [Шаблоны проектирования: элементы многоразового объектно-ориентированного программного обеспечения (в твердом переплете)](https://rads.stackoverflow.com/amzn/click/com/0201633612)
* Книга: [Шаблоны корпоративной архитектуры приложений (в твердом переплете)](https://rads.stackoverflow.com/amzn/click/com/0321127420)
* Книга: [Образцы реализации (Мягкая обложка)](https://rads.stackoverflow.com/amzn/click/com/0321413091)

 И текущий список префиксов/суффиксов имен, которые я собрал (субъективно!) Из ответов:

 * координатор
* строитель
* писатель
* читатель
* укротитель
* Контейнер
* протокол
* цель
* конвертер
* контроллер
* Посмотреть
* завод
* сущность
* ведро

 И хороший совет для дороги:

 
>   Не получайте именной паралич. Да, имена очень важны, но они не настолько важны, чтобы тратить на них огромное количество времени. Если вы не можете придумать хорошее имя за 10 минут, двигайтесь дальше.
> 
> 

 

 Я задал [похожий вопрос](/questions/11784/what-names-do-you-find-yourself-prependingappending-to-classes-regularly), но, где это возможно, я пытаюсь скопировать имена уже в .NET Framework и ищу идеи в Java и Android Framework.

  Кажется, что `Helper`, `Manager` и `Util` - это неизбежные существительные, которые вы присоединяете для координации классов, которые не содержат состояний и, как правило, являются процедурными и статическими. Альтернативой является `Coordinator`.

  Вы можете получить особенно пурпурные прозы с именами и пойти на такие вещи, как `Minder`, `Overseer`, `Supervisor`, `Administrator` и `Master`, но, как я уже сказал, я предпочитаю держать его как имена фреймворков, к которым вы привыкли.

 .i1a { width: 336px; height: 280px; }
 @media(min-width: 768px) { .i1a { width: 728px; height: 90px; } }
 @media(min-width: 992px) { .i1a { width: 360px; height: 300px; } }
 @media(min-width: 1083px) { .i1a { width: 728px; height: 90px; } }

 (adsbygoogle = window.adsbygoogle || []).push({});

 Некоторые другие общие суффиксы (если это правильный термин), которые вы также найдете в .NET Framework:

 * `Builder`
* `Writer`
* `Reader`
* `Handler`
* `Container`

 

Вы можете взглянуть на [source-code-wordle.de](http://source-code-wordle.de/), я проанализировал там наиболее часто используемые суффиксы имен классов платформы .NET и некоторых других библиотек.

Топ-20:

 .i2a { width: 336px; height: 280px; }
 @media(min-width: 768px) { .i2a { width: 728px; height: 90px; } }
 @media(min-width: 992px) { .i2a { width: 360px; height: 300px; } }
 @media(min-width: 1083px) { .i2a { width: 728px; height: 90px; } }

 (adsbygoogle = window.adsbygoogle || []).push({});

* атрибут
* типа
* помощник
* коллекция
* Преобразователь
* обработчиком
* Информация
* поставщик
* исключение
* услуги
* Элемент
* менеджер
* node
* опции
* factory
* Контекст
* элемент
* дизайнер
* база
* редактор

 

У меня все хорошие имена, и я часто пишу о важности заботы при выборе имен для вещей. По этой же причине я опасаюсь метафор, когда называет вещи. В исходном вопросе "factory" и "synchronizer" выглядят как хорошие имена для того, что они означают. Однако "пастух" и "няня" не являются, потому что они основаны на метафорах. Класс в вашем коде не может быть буквально няней; вы называете это няней, потому что она заботится о некоторых вещах, очень похожих на настоящую няню, которая заботится о детях или детях. Это нормально в неофициальной речи, но не в порядке (на мой взгляд) для обозначения классов в коде, который должен поддерживаться тем, кто знает, кто знает, когда.

Почему? Потому что метафоры зависят от культуры и часто зависят от личности. Для вас, назвав класс "нянькой", может быть очень ясным, но, возможно, это не так понятно кому-то другому. Мы не должны полагаться на это, если вы не пишете код, который предназначен только для личного использования.

В любом случае соглашение может сделать или сломать метафору. Использование "factory" само по себе основано на метафоре, но в течение довольно долгого времени и в настоящее время довольно хорошо известно в мире программирования, поэтому я бы сказал, что он безопасен в использовании. Однако "няня" и "пастух" неприемлемы.

 

Мы могли бы обойтись без классов `xxxFactory`, `xxxManager` или `xxxRepository`, если бы мы правильно смоделировали реальный мир:

```
Universe.Instance.Galaxies["Milky Way"].SolarSystems["Sol"]
        .Planets["Earth"].Inhabitants.OfType<Human>().WorkingFor["Initech, USA"]
        .OfType<User>().CreateNew("John Doe");

```

; -)

 

Это звучит как скользкий склон к тому, что было бы размещено на thedailywtf.com, "ManagerOfPeopleWhoHaveMortgages" и т.д.

Я полагаю, что один монолитный класс Менеджера не очень хороший дизайн, но использование "Менеджера" неплохое. Вместо UserManager мы можем разбить его на UserAccountManager, UserProfileManager, UserSecurityManager и т.д.

 "Менеджер" - хорошее слово, потому что он ясно показывает, что класс не представляет реальную вещь "." AccountsClerk" - как я могу рассказать, является ли класс, который управляет данными пользователя, или представляет кого-то, кто является секретарем учетной записи для своей работы?

 

Поскольку вас интересуют статьи в этой области, вам может быть интересна статья Стивена Егге "Выполнение в Королевстве существительных":

 <http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html>

 

Когда я думаю об использовании `Manager` или `Helper` в имени класса, я считаю его запахом кода, что означает, что я еще не нашел правильную абстракцию и/или нарушаю [принцип единой ответственности](http://en.wikipedia.org/wiki/Single_responsibility_principle), поэтому рефакторинг и привлечение большего внимания к дизайну часто упрощают именование.

Но даже хорошо продуманные классы не всегда называют себя, и ваш выбор частично зависит от того, создаете ли вы классы бизнес-моделей или классы технической инфраструктуры.

Классы бизнес-моделей могут быть трудными, потому что они разные для каждого домена. Есть несколько терминов, которые я использую много, например `Policy` для классов стратегии внутри домена (например, `LateRentalPolicy`), но они обычно вытекают из попытки создать "[вездесущий язык](http://domaindrivendesign.org/node/132)", который вы можете поделиться с бизнес-пользователями, проектировать и именовать классы, чтобы они моделировали реальные идеи, объекты, действия и события в реальном мире.

Классы технической инфраструктуры немного проще, потому что они описывают домены, которые мы знаем очень хорошо. Я предпочитаю включать имена шаблонов дизайна в имена классов, например `InsertUserCommand,` `CustomerRepository,` или `SapAdapter.`. Я понимаю озабоченность по поводу передачи реализации вместо намерения, но шаблоны дизайна выходят за эти два аспекта дизайна классов - по крайней мере, работа с инфраструктурой, где вы хотите, чтобы дизайн реализации был прозрачным, даже когда вы скрываете детали.

 

Будучи аутистом с шаблонами, определенными (скажем) [GOF book](http://en.wikipedia.org/wiki/Design_Patterns_%28book%29), а имена объектов после этого дают мне длинный путь в классах именования, организовывать их и сообщать о намерениях. Большинство людей поймут эту номенклатуру (или, по крайней мере, большую ее часть).

 

Если я не могу придумать более конкретное имя для моего класса, чем XyzManager, мне было бы необходимо пересмотреть, действительно ли это функциональность, которая принадлежит вместе в классе, то есть архитектурный "запах кода".

 

Я думаю, что самое важное, о чем нужно помнить, - это достаточно описательное имя? Можете ли вы рассказать, глядя на имя, которое должен выполнять класс? Использование таких слов, как "Менеджер", "Сервис" или "Обработчик" в именах классов, может считаться слишком общим, но поскольку многие программисты используют их, он также помогает понять, для чего предназначен класс.

Я сам много использовал фасад-образ (по крайней мере, я думаю, что он называется). Я мог бы иметь класс `User`, который описывает только одного пользователя, и класс `Users`, который отслеживает мою "коллекцию пользователей". Я не называю класс a `UserManager`, потому что мне не нравятся менеджеры в реальной жизни, и я не хочу напоминать им:) Просто использование формы множественного числа помогает мне понять, что делает класс.

 

 Специально для С# я обнаружил, что в ["Руководстве по проектированию инфраструктуры: условные](https://rads.stackoverflow.com/amzn/click/com/0321545613) обозначения [, идиомы и шаблоны для многократно используемых библиотек .NET"](https://rads.stackoverflow.com/amzn/click/com/0321545613) содержится много полезной информации о логике именования.

  Что касается поиска более конкретных слов, я часто использую тезаурус и прыгаю через связанные слова, чтобы найти подходящий. Я стараюсь не тратить на это много времени, хотя по мере развития я придумываю более `SuchAndSuchManager` имена или иногда осознаю, что `SuchAndSuchManager` действительно должен быть разбит на несколько классов, и тогда имя этого устаревшего класса становится не вопрос.

 

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

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

 

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

Например, UserRecordsClerk может быть лучше объяснен как расширение общего интерфейса RecordsClerk, который реализуется как UserRecordsClerk, так и CompanyRecordsClerk, а затем специализируется на нем, то есть можно посмотреть на методы в интерфейсе, чтобы увидеть, что делают его подклассы в целом.

См. книгу, например [Design Patterns](http://www.amazon.co.uk/gp/reader/0201633612/ref=sib_dp_pt#reader-link) для информации, это отличная книга и может помочь вам разобраться, где вы собираетесь быть с вашим кодом - если вы еще не используете его!; o)

Я считаю, что если ваш шаблон хорошо выбран и используется насколько это уместно, тогда достаточно достаточно непроницательных простых имен классов!