Проблемы с избеганием классов Smurf Naming с пространствами имен

39

Я вытащил отсюда термин «смурф» (номер 21). Чтобы избавить кого-то, кто не знаком с проблемой, именование Smurf - это префикс префикса группы связанных классов, переменных и т. Д. С общим префиксом, так что в итоге вы получаете «a SmurfAccountViewpass a SmurfAccountDTOto SmurfAccountController» и т. Д.

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

  1. Я работаю с библиотекой с Configurationклассом. Его можно было бы назвать, WartmongerConfigurationно он находится в пространстве имен Wartmonger, поэтому он просто называется Configuration. У меня также есть Configurationкласс, который можно вызывать SmurfConfiguration, но он находится в пространстве имен Smurf, поэтому он будет избыточным. В моем коде есть места, где Smurf.Configurationпоявляется рядом, Wartmonger.Configurationи ввод полностью определенных имен неуклюж и делает код менее читабельным. Было бы лучше иметь дело с a SmurfConfigurationи (если бы это был мой код, а не библиотека) WartmongerConfiguration.

  2. В Serviceмоем пространстве имен Smurf есть класс, который можно было бы вызвать SmurfService. Serviceэто фасад на вершине сложной библиотеки Smurf, которая выполняет задания Smurf. SmurfServiceкажется лучшим именем, потому что Serviceбез префикса Smurf это невероятно универсально. Я могу признать, что это SmurfServiceбыло уже общее, бесполезное имя, и удаление смарфа просто сделало это более очевидным. Но его можно было бы назвать Runnerи Launcherт. Д., И мне все равно было бы «легче», SmurfLauncherпотому что я не знаю, что он Launcherделает, но я знаю, что он SmurfLauncherделает. Вы можете утверждать, что то, что Smurf.Launcherделает, должно быть столь же очевидно, какSmurf.SmurfLauncher, но я мог видеть, что Smurf.Launcher - это некий класс, связанный с настройкой, а не класс, запускающий smurfs.

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

Даниэль Коверман
источник
3
Есть ли Smurf.Launcherзапуск Smurfs, или это запустить SmurfJobS? Возможно, это можно назвать Smurf.JobLauncher?
Blorgbeard
2
Назвать класс XService, XManager и т. Д. - это запах кода. Это ничего не значит. Это как Util. Если вы просматриваете имена файлов, все может быть там или отсутствовать. Там нет никакого способа узнать, если вы не загляните внутрь. Я бы переименовал его из SmurfService в другое.
Даниэль Каплан
1
Он на самом деле запускает SmurfJobs или технически запускает их в соответствии с языком документации Smurf. В свете этого и других ответов я собираюсь переименовать SmurfServiceв SmurfJobRunner. Кажется, номер 1 не имеет лучшего разрешения, как я ожидал. Я могу видеть случаи, когда подход SmurfConfigurationбыл бы правильным решением, но в моем случае я думаю, что Configurationэто лучше, даже несмотря на трудности Wartmonger.Configuration.
Даниэль Коверман,
6
Я пытаюсь понять, почему у вас есть один класс, который заботится о настройке как Wartmongers, так и Smurfs вообще.
Донал Феллоуз
Почему Smurf.Configurationи SmurfConfigurationчувствуешь себя иначе? Конечно, это не дополнительный символ, не так ли? (Сократите до, Configесли проблема в длине.) Есть ли Smurf.Configurationпроблемы, которых SmurfConfigurationнет?
Пабло Х

Ответы:

16

Вы поднимаете некоторые хорошие моменты.

  1. Что касается дублирующих классов, вы можете использовать псевдонимы классов в C #. Используйте, например, using ColorScheme = The.Fully.Qualified.Namespace.Outlook2007ColorScheme;см. Этот пост на StackOverflow . Вы не указали свой язык программирования, но я понял из того, что вы написали. Итак , где вы имеете дело с двумя разными проектами, вы можете алиас их SmurfConfigurationи WartmongerConfigurationчто позволило бы неоднозначность при употреблении обоих классов.

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

Я чувствую, что пространства имен следует использовать, чтобы избежать такого стиля именования. Это усложняет получение кода и проверку по номиналу, что такое класс, не читая MyCompanyMyProductMyAreaClassName. Использование метода псевдонимов позволяет уменьшить неоднозначность, где это необходимо. Я думаю, что единственное время, когда вы должны вносить сложность в свое наименование, это, как я указывал в # 2, когда люди будут потреблять услугу. Именно здесь имеет смысл использовать этот стиль именования, потому что, если у потребителя есть множество услуг, он потребляет неоднозначность.

Сэм
источник
5
псевдонимы просто запутывают вещи. Вместо Smurf.Service у вас теперь есть SmurfService = Smurf.Service. Таким образом, вы могли бы просто иметь SmurfService в качестве названия вещи в первую очередь. У них есть место, но не для этого конкретного вопроса. Тем не менее, это, вероятно, лучший ответ на проблему, на которую нет ответа :)
gbjbaanb
C # во мне вышел в моем вопросе, но на самом деле я сейчас имею дело с Java и org.apache.smurfville.wartmonger.configuration. Это, к сожалению, исключает псевдонимы. 2 - это сплошная точка, поэтому я собираюсь сохранить Smurf для брендинга Сервиса.
Даниэль Коверман
25

Смысл пространств имен в том, что вы можете иметь классы с одинаковыми именами из разных библиотек без их коллизии. Когда вам нужно использовать один и тот же именованный класс из обоих, вам нужно убрать неоднозначность, добавив один или оба префикса к области его пространства имен.

Тем не менее, неплохо иметь кучу классов Smurf, если Smurf расскажет вам что-то конкретное о классе. Имена классов должны быть достаточно наглядными, чтобы дать вам некоторую информацию о том, что делает класс.

      Session
       ^   ^
      /     \
DBSession   HttpSession

Точно так же DBSessionможет взять DBRequestобъект, который возвращает DBResponseобъект. HttpSessionТакже может работать на HttpRequestи HttpResponseобъекты.

Это классы Smurf с целью.

Они могут жить в MyCompanyпространстве имен , но MyCompanyHttpSessionи MyCompanyDBSessionне дает вам никакой больше информации , чем было раньше. В этом случае бросьте Smurf и сделайте его пространством имен.

MyCompany.HttpSession
Дэйв Рейгер
источник
3

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

Вы упоминаете SmurfConfigurationи в WartmongerConfigurationкачестве потенциальных видов конфигураций. Вы указываете, что вы удалили прилагательное (его вид) в его пространство имен, так что осталось только ваниль Configuration. Я бы избегал этого.

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

Давайте представим, что в вашем приложении вы импортируете Strawberry.IceCreamкласс, а затем начинаете создание экземпляра непосредственно из IceCream.

var ic = new IceCream(); //actually I'm strawberry ice cream

Это может показаться неплохим, до того момента, пока вы не импортируете другой IceCreamкласс. Теперь вы вернулись к первоначальной проблеме необходимости как-то различать их, что проблематично. Все, что вы хотели, было:

var sic = new StrawberryIceCream();
var cic = new ChocolateIceCream();

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

Марио Т. Ланца
источник
2

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

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

using Sm = Smurf;
using W = Wartmonger;

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

Sm::Configuration smConf; 
W::Configuration wConf;

2) Псевдоним класса, как предлагается в другом ответе.

using SmConf = Smurf.Configuration;

3) Любую библиотеку, которой вы управляете, не используйте термин «Конфигурация». Используйте тезаурус: например, «Настройки», «Модель», «Параметры». В любом случае, это может быть более значимым для контекста: например, если бы Smurf был своего рода модулем численного анализа, вы бы написали, что «Параметры» были бы лучше для его конфигурации. Используйте конкретный словарь, связанный с контекстом модуля, в ваших интересах, чтобы придумать уникальные имена, которые обладают уникальностью, даже когда они смешаны с другими пространствами имен. Я чувствую, что это может быть своего рода ответом на OP-вопрос 2.

4) Рефакторинг кода, чтобы вам не приходилось смешивать использование конфигурации из двух разных мест. Детали этого до вас.

5) Объедините две конфигурации в одну, прежде чем передать ее в свой класс. Используйте комбинированный класс conf для представления:

struct Conf {
    SmurfConfiguration smurf;
    WartmongerConfiguation wart;
}

Короткие имена переменных-членов теперь как бы достигают того же, что и псевдоним класса / пространства имен.

Бенедикт
источник
0

Кажется странным, что добавление одной точки к названию беспокоит вас.

Wartmonger.Configuration configuration = Wartmonger.Configuration .new();

// vs

WartmongerConfiguration configuration = WartmongerConfiguration.new();

Если обе конфигурации Smurfи Wartmongerконфигурации используются вместе в одном месте, но по отдельности они используются в нескольких местах - тогда пространство имен, безусловно, является хорошим подходом.

Имея пространство имен даст возможность использовать «чистые» имена во внутреннем коде, где с префиксами вы в конечном итоге с помощью SmurfConfigurationвнутри SmurfService«s внутренний код, который может стать раздражает каждый раз, когда вы откроете этот код.

Fabio
источник