Являются ли частичные классы C#плохим дизайном?
Мне интересно, почему концепция "частичного класса" даже существует в C#/VB.NET. я работаю над приложением, и мы читаем (на самом деле очень хорошую) книгу, относящуюся к платформе разработки, которую мы реализуем на работе. В книге автор предоставляет большую базу кода / оболочку вокруг API платформы и объясняет, как он ее разработал, поскольку он преподает различные темы о разработке платформы.
Короче говоря, он использует частичные классы, повсюду, как способ подделки множественного наследования в C# (IMO). Почему он просто не разделил классы на несколько и не использовал композицию, вне меня. У него будет 3 файла "частичного класса", чтобы составить его базовый класс, каждый с 3-500 строками кода... И делает это несколько раз в своем API.
вы считаете это правомерным? если бы это был я, я бы последовал за S. R. P. И создал несколько классов для обработки различных требуемых поведений, а затем создал базовый класс, который имеет экземпляры этих классов в качестве членов (например, композиция). Почему MS даже поместила частичный класс в фреймворк? Они удалили возможность расширения / свертывания всего кода на каждом уровне области в C# (это было разрешено в C++), потому что это, очевидно, просто позволяло плохие привычки - частичный класс, IMO, то же самое. Я думаю, мой вопрос: Можете ли вы объяснить мне, когда будет законная причина когда-либо использовать частичный класс?
изменить: Я знаю, что для Web/WinForms нет другого выбора. Но за пределами этого? Почему MS просто не поместила какое-то другое ключевое слово для склеивания классов code-genn'Ed вместе? Или есть действительно законный сценарий дизайна, который заслуживает этого?
Я не имею в виду, что это будет поток rant / war. Я честно ищу, чтобы узнать что-то здесь. Когда следует использовать разделяемые классы в разработке кода? Простой вопрос, не нужно закрыть
спасибо
15 ответов:
можете ли вы объяснить мне, когда будет законная причина когда-либо использовать частичный класс?
одной из наиболее законных и полезных причин является поощрение разделения автоматически генерируемого кода и ваших собственных пользовательских расширений к нему. Например, обычно автоматически генерируется код формы из какого-либо конструктора, но обычно вы хотите добавить к нему свое собственное конкретное поведение. Таким образом, если вы регенерируете автоматический код часть, вы не касаетесь части, которая имеет Ваши конкретные расширения.
тем не менее, вполне возможно иметь слишком много хорошего. Некоторые советы:
Не делайте ваши классы
partialрадиpartial.Не ставьте частичные классы нигде, кроме друг друга. Если вам нужно перейти к совершенно несвязанному разделу проекта, чтобы увидеть другую половину класса, вы, вероятно, делаете это неправильный.
Не используйте
partialкак метод, чтобы скрыть размер класса. Если вы разрываете свои занятия сpartialпотому что они слишком велики, вы должны пересмотреть Принцип Единой Ответственности.если у вас есть три или больше
partialфрагменты для одного и того же класса, это почти гарантия того, что вы злоупотребляете частичным. Два-это типичная верхняя граница разумности, и это вообще используется для сегментации автоматически сгенерированного кода из рукописного кода.Короче говоря, он использует частичные классы, повсюду, как способ подделать множественное наследование в C# (IMO). Почему он просто не разделил классы на несколько и не использовал композицию, выше моего понимания. У него будет 3 файла "частичного класса", чтобы составить его базовый класс, каждый с 3-500 строками кода... И делает это несколько раз в своем API.
да, это определенно явное злоупотребление
partial!
есть две причины, по которым я бы (и делаю) использовал частичные классы.
- для разделения автоматически генерируемых частей кода (например, кода конструктора WinForms или вывода T4).
- разрешить вложенным типам их собственный файл, сохраняя при этом инкапсуляцию, требуемую вашим дизайном.
обновление
Я вижу, что некоторые не уверены в моем втором пункте, поэтому позвольте мне привести пример;ListViewItemCollectionв рамках. Это вполне справедливо вложенные подListViewпотому что это только для использованияListView, но чтобы сделать обслуживание намного проще, я бы дал ему свой собственный файл с помощью частичных классов. Я не вижу в этом плохого или неправильного использованияpartialключевое слово.для более подробного обсуждения, проверьте вопрос, который этот дублирует:частичные классы в C#
другое законное использование разделяемых классов - это помочь уменьшить беспорядок "монолитной веб-службы" в WCF. Вы хотите разбить его на логические группы функций, но не хотите создавать множество отдельных экземпляров службы/конечных точек (предположительно, потому что они совместно используют состояние, ресурсы и т. д.).
решение? Пусть служба реализует несколько интерфейсов и реализует каждый интерфейс в своем собственном разделяемом классе. Затем сопоставьте различные конечные точки в конфигурация к такой же физической реализации. Это делает проект намного более ремонтопригодным, но у вас все еще есть только одна физическая конечная точка.
в некоторых случаях я бы указал на этот тип подхода как на плохую практику из-за SRP, но когда вы работаете со службами WCF или веб-службами в целом, это не так просто. Вы должны сбалансировать внутренние требования к конструкции с внешними требованиями к потребления.
менее распространенным использованием может быть разделение огромного класса на отдельные физические файлы, чтобы облегчить жизнь с точки зрения управления версиями. Я только что присоединился к проекту, содержащему некоторые чрезвычайно раздутые классы веб-сервисов, работающие с тысячами строк кода и с методами, связанными с несколькими различными бизнес-функциями.
слияние из различных ветвей функций-это кошмар из-за разных команд, вносящих одновременные несвязанные изменения в один и тот же файл. Я не могу разделите веб-службу без внесения серьезных изменений, но разбиение класса на частичные классы точно сохраняет поведение и удаляет целую кучу проблем слияния.
Я определенно не поощряю вышеизложенное как выбор дизайна, но это была хорошая быстрая победа для нас, и это показывает, что partials не злые все время...
Я использовал частичные классы по-разному в прошлом. По мере того, как я узнаю больше о программировании и, в частности, о концепции "предпочтения композиции над наследованием", я легко вижу, что необходимость уменьшается как для вертикального наследования, так и для чрезмерного использования частичных классов.
кроме автоматически сгенерированного кода, я не могу думать о хорошем использовании частичных классов. Даже если вы используете EF и вам нужны разные метаданные, они даже не рекомендуют использовать частичные данные для метаданных. На самом деле, если вы попробуйте дублировать какие-либо свойства в другой части(просто для добавления метаданных), вы получите ошибку компилятора.
чем больше мы узнаем о рефакторинге и SOC (разделение проблем), тем меньше и более сфокусированными становятся наши классы. Они по умолчанию используются повторно, что со временем делает их пуленепробиваемыми и легко проверяемыми. Просто скажите " нет " гигантским программам. Генри Форд изучил эту концепцию в начале 1900-х годов программисты начали изучать ее 100 лет спустя.
использовать композицию когда сможешь...
Я полностью согласен с Джон ответ. Но я бы сделал еще один шаг вперед.
- не делайте ваши классы частичным.
единственное использование частичных классов, о которых я могу думать, что я бы рассмотрел "хороший дизайн", - это автоматически сгенерированный код. Любое другое использование почти наверняка излишне разбивает ваш класс. (На самом деле, я вижу, что Джефф!--2--> второй пункт о вложенных классах, возможно, является допустимым использовать)
лично я думаю, что эта книга, которую вы читаете, звучит как плохой дизайн, однако считаете, что он может просто использовать частичные классы, чтобы он мог просто демонстрировать часть кода маленькими битами за раз, а не просто представлять весь класс за один раз.
можете ли вы объяснить мне, когда будет законная причина когда-либо использовать частичный класс?
в последних версиях Visual Studio частичные классы используются для отделения автоматически сгенерированного кода конструктора от собственного кода..
An ASP.NET пример:
- страница.aspx
- страница.aspx.cs
- страница.aspx.Дизайнер.cs
A Приложения WinForms пример:
- форма form1.resx
- форма form1.cs
- форма form1.Дизайнер.cs
Я использовал разделяемые классы для "физического" отделения статических методов доступа к данным от свойств и методов бизнес-класса в архитектуре активных записей. Например, у нас были частичные классы Company и CompanyData бок о бок. Преимущество состояло в том, что один файл был POCO, а другой содержал только методы доступа к данным. Это был шаг к удалению доступа к данным классов репозитория в устаревшем приложении. Я думаю, что это было законное использование, это, безусловно, сделало процесс повторного факторинга более здравый.
еще одно хорошее использование для частичных классов было бы при реализации абстрактный узор завод. Сделайте корневой объект фабрики частичным, а затем поместите фактические методы фабрики в тот же файл, что и класс, экземпляр которого создает фабрика.
EDIT: частичные классы также хорошо работают для классов, которые взаимодействуют с файлом конфигурации. Поместите код, содержащий параметры конфигурации, рядом с кодом, который фактически использует конфигурацию параметр.
просто наткнулся на этот поток, когда искал преимущества частичного класса. Я нахожусь в процессе преобразования приложения Java EE в приложение .NET на основе silverlight. Я наткнулся на следующий код в слое представления:
//------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. // Runtime Version:4.0.30319.225 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ ... public partial class Wwcusts04d : System.Windows.Controls.Page {теперь, если сама частичная страница генерируется автоматически, какой смысл ее поддерживать ? Кроме того, код внутри просто связывает различные элементы управления с их именами. Я не признаюсь, что знаю silverlight, но разве эта вещь не лучше подходит в XAML?
частичный класс существует в .Net framework исключительно чтобы позволить дизайнерам Visual Studio (например Asp.Net конструктор и конструктор Windows Forms) для создания кода / беспорядка с вашими классами, сохраняя этот сгенерированный код в отдельном файле.
(см. .Чистая разделяемые классы и наследование)
Если вы делаете что-то подобное (генерировать код, который должен сосуществовать с пользовательским кодом), то вы также можете найти частичные классы полезны, но Я не верю, что Microsoft когда-либо намеревалась использовать частичные классы в качестве языковой концепции для кого-либо, кроме команды Visual Studio.
Это не так много, что использование частичных классов-плохой дизайн - просто вы, вероятно, не найдете для них применения.
Я использовал частичный класс дважды в VB.Net и оба раза это был тот редкий случай, когда я нуждался в поздней привязке. Просто создать частичный класс и превратить строгий вариант в верхней части.
просто чтобы добавить к предыдущим ответам, которые упоминали разделение сгенерированного кода от пользовательского кода, я нашел частичные классы полезными для расширения строго типизированных наборов данных.
есть много дискуссий по этой теме, и многие люди говорят, что 1) это плохой дизайн для использования частичных классов, 2) что он используется для автогенерированного кода и 3) что он не должен занимать место наследования.
однако у меня есть ситуация, в которой частичные классы выглядят так, как будто они очень пригодятся: Я создаю серию приложений, которые в конечном итоге будут интегрированы в набор. Все они будут иметь основную форму, которая обеспечит некоторые функциональность и несколько общих компонентов (например, форма для отображения отчета). Пока Я может определить базовый класс и наследовать от него, что будет означать много переделок, когда придет время объединить все приложения в "корпоративную" версию продукта.
таким образом, частичные классы весьма полезны, потому что я могу довольно просто включить различные частичные классы в комбинированную версию, все еще позволяя мне создавать отдельные, автономные версии продукта. Если бы я попытался выполнить это с помощью наследования, я бы закончил тем, что каждый компонент вызывал свою собственную версию общих компонентов (например, InvoiceReportViewer, PurchasingReportsViewer и т. д.) вместо того, чтобы просто вызывать ReportsViewer и знать, что Visual Studio интегрирует все биты для меня.
еще одна вещь, чтобы рассмотреть,частичные классы заставляет вас создавать разные имена файлов, которые содержат одно и то же имя класса. Например, у вас есть FactoryClass, и вы создаете его частичные версии, такие как; Factory.дизайнер.КС, Фабрика.данные.cs и все эти файлы имеют класс с именем FactoryClass.
Если вы выберите этой вопрос; есть лучшие практики определено как:
лучшие практики, является определите один класс для каждого файла и дайте файлу то же имя, что и класс (или структура и т. д.) быть определенными.
Comments