#c# #.net #namespaces
#c# #.net #пространства имен
Вопрос:
Я нахожусь в процессе разработки библиотеки .NET и ищу некоторые отзывы относительно организации классов и пространств имен.
Предположим, что у меня есть абстрактный Message
класс, который находится в корневом пространстве имен Foo
. Message
имеет много конкретных реализаций для разных типов сообщений. Учитывая, что будет много конкретных реализаций (предположим, 20 или даже больше), ожидается ли, что эти конкретные типы будут находиться в отдельном пространстве имен, что-то вроде Foo.Messages
?
Я беспокоюсь о загромождении пространства имен слишком большим количеством конкретных Message
классов, которые пользователям моей библиотеки редко нужно будет использовать напрямую. Чего вы ожидаете при использовании библиотеки?
Редактировать:
Кроме того, если я сгруппирую конкретные классы в Foo.Messages
, должен ли абстрактный класс также находиться там или он должен остаться в Foo
?
Ответ №1:
Если пользователи вашей библиотеки не будут создавать ваши конкретные классы реализации (они проходят через фабричный шаблон для получения экземпляров и получают доступ к экземплярам только через абстрактный базовый тип), рассмотрите возможность создания ваших конкретных классов реализации внутренними. Это исключит их из пользовательских вариантов завершения кода.
Группировка всех конкретных классов реализации в пространстве имен Foo.Messages звучит неплохо. Вы также не хотите заходить слишком далеко другим путем — создание множества пространств имен для второстепенных вещей вызывает огромное раздражение у пользователя.
Комментарии:
1.
Message
Конкретные классы имеют внутренние конструкторы, поэтому они не могут быть созданы внеMessageFactory
. Однако сами классы являются общедоступными, потому что в настоящее время у меня есть шаблон, который позволяет пользователям добавлять «обработчики событий» по типу сообщения, которые выполняются при поступлении сообщения. Это казалось гораздо менее раздутым, чем объявление события вClient
классе для каждого конкретногоMessage
. Аналогично, у меня также есть аннотацияCommand
с несколькими конкретными реализациями. У них есть общедоступные конструкторы, обеспечивающие гибкость при взаимодействии с базовым протоколом.
Ответ №2:
Своего рода загруженный вопрос, но если проблема заключается в том, что слишком много классов затрудняют обнаружение, возможно ли частью решения сделать некоторые из этих классов internal
вместо public
? Если пользователи никогда не будут создавать их экземпляры напрямую, это может быть частью решения вашей проблемы беспорядка.
Это действительно во многом зависит от природы разрабатываемого вами API и в некоторой степени от вкуса. Часто существует один основной класс или набор классов, к которым ваши пользователи будут обращаться большую часть времени, например, к NLog Logger
, или AutoMapper Mapper
, или NoRM Mongo
, или фабрики классов в целом. Они должны быть в центре внимания и доступны для обнаружения, и вы могли бы привести веские доводы в пользу того, что лучше всего иметь это в вашем корневом пространстве имен.
Для других классов (тех, которые больше связаны с реализацией и меньше с API), очевидно, что вы хотите быть организованными, но вы можете играть довольно свободно и организовывать таким образом, который вам кажется естественным, при условии, что части API, которые пользователям нужно найти, наиболее заметны. Foo.Messages
кажется, что это вполне разумный способ начать. С другой стороны, если 90% ваших классов являются Message
подклассами, но существует важное различие между сообщениями сервера и сообщениями клиента, или фиолетовыми сообщениями и текстурными сообщениями, возможно, Foo.Server
или Foo.Plaid
являются подходящими типами пространств имен для вас.
Ответ №3:
Если вы создаете библиотеку и используете абстрактный класс Message со многими конкретными реализациями, часто может быть хорошей идеей скрыть все конкретные реализации от пользователя библиотеки и предоставить доступ к классу Factory, который вернет абстрактное сообщение (возвращаемый тип, фактический возвращаемый объект, конечно, будет конкретным), если это нормально для клиентов библиотеки, что часто бывает, он инкапсулирует 20 или даже больше классов и предоставляет доступ к требуемой функциональности отличным и удобным способом.