Являются ли частичные classы C # плохой конструкцией?

Мне интересно, почему концепция «частичного classа» существует даже в C # / VB.NET. Я работаю над приложением, и мы читаем (на самом деле очень хорошую) книгу, относящуюся к платформе разработки, которую мы реализуем на работе. В книге автор предоставляет большую базу / оболочку кода вокруг API платформы и объясняет, как он ее развил, изучая разные темы о развитии платформы.

Во всяком случае, длинный рассказ короткий – он использует частичные classы, повсюду, как способ подделать множественное наследование в C # (IMO). Почему он не просто разделил classы на несколько, а использование композиции вне меня. Он будет иметь 3 ‘частичных classных файла, чтобы составить свой базовый class, каждый с 3-500 строк кода … И делает это несколько раз в своем API.

Вы считаете это оправданным? Если бы это был я, я бы следовал за SRP и создал несколько classов для обработки различных требуемых действий, а затем создал базовый class, который имеет экземпляры этих classов в качестве членов (например, состав). Почему MS даже включила частичный class в frameworks? Они удалили возможность развернуть / свернуть весь код на каждом уровне уровня в C # (это было разрешено на C ++), потому что это, очевидно, просто позволяло использовать вредные привычки – частичный class, IMO, то же самое. Я думаю, мой вопрос: вы можете объяснить мне, когда будет законная причина использования частичного classа?

EDIT: Я знаю, что для Web / WinForms нет другого выбора. Но вне этого? Почему MS не просто добавил несколько ключевых слов для склеивания кода? Или действительно ли есть законный сценарий дизайна, который заслуживает этого?

Я не имею в виду, что это была болтовня / война. Я честно хочу узнать что-то здесь. Когда в разработке кода должны использоваться частичные classы? Простой вопрос, нет необходимости закрывать

Спасибо

Можете ли вы объяснить мне, когда будет законная причина когда-либо использовать частичный class?

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

Тем не менее, вполне возможно иметь слишком много хорошего. Некоторые советы:

  • Не делайте свои classы partial чтобы быть partial .

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

  • Не используйте partial метод, чтобы затенять размер classа. Если вы разбиваете свои classы с partial потому что они слишком велики, вы должны пересмотреть принцип единой ответственности .

  • Если у вас есть три или более partial fragmentа для одного и того же classа, это почти гарантия, что вы злоупотребляете частичным. Вторая – типичная верхняя граница разумности, и она обычно используется для сегментации автоматически генерируемого кода из рукописного кода.

Во всяком случае, длинный рассказ короткий – он использует частичные classы, повсюду, как способ подделать множественное наследование в C # (IMO). Почему он просто не разбил classы на несколько, и использование композиции вне меня. Он будет иметь 3 ‘частичных classных файла, чтобы составить свой базовый class, каждый с 3-500 строк кода … И делает это несколько раз в своем API.

Да, это определенно явное злоупотребление partial !

Есть две причины, по которым я (и делаю) использовал бы частичные classы.

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

Обновить
Я вижу, что некоторые не убеждены в моем втором моменте, поэтому позвольте мне привести пример; ListViewItemCollection в рамках. Он вполне правильно вложен в ListView потому что он предназначен только для использования ListView , но для упрощения обслуживания я бы дал ему собственный файл, используя частичные classы. Я не вижу в этом плохой дизайн или неправильное использование partial ключевого слова.

Для более подробного обсуждения проверьте, что этот дубликат: Частичные classы в C #

Другое законное использование частичных classов – помочь уменьшить беспорядок «monoлитного веб-сервиса» в WCF. Вы хотите разбить его на логические группы функциональности, но не хотите создавать множество отдельных экземпляров / конечных точек службы (по-видимому, потому, что они разделяют состояние, ресурсы и т. Д.).

Решение? Попросите сервис реализовать несколько интерфейсов и реализовать каждый интерфейс в своем собственном частичном classе. Затем сопоставьте разные конечные точки в конфигурации с той же физической реализацией. Это делает проект намного более удобным, но у вас все еще есть только одна физическая конечная точка.

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

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

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

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

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

Помимо автоматического сгенерированного кода, я не могу думать о хорошем использовании частичных classов. Даже если вы используете EF и нуждаетесь в разных метаданных, они даже не рекомендуют использовать частичные метаданные. Фактически, если вы попытаетесь дублировать какие-либо свойства в другом частичном (просто добавить метаданные), вы получите ошибку компилятора.

Чем больше мы узнаем о рефакторинге и SOC (Разделение проблем), тем меньше становятся все более и более сосредоточенными наши classы. Они по умолчанию используются повторно, что со временем делает их пуленепробиваемыми и легко проверенными. Просто скажите «НЕТ» для гигантских программ. Генри Форд узнал эту концепцию в начале 1900-х годов, когда программисты начали изучать ее через 100 лет.

Используйте композицию, когда можете …

Я полностью согласен с ответом Джона . Но я бы сделал еще один шаг вперед.

  • Не делайте свои classы неполными.

Единственное использование частичных classов, о которых я могу думать, что я считаю «хорошим дизайном», – это автоматически сгенерированный код. Любое другое использование почти наверняка не обязательно разделяет ваш class. (На самом деле, я вижу, что второй пункт Джеффа на вложенных classах, возможно, является допустимым использованием)

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

Можете ли вы объяснить мне, когда будет законная причина когда-либо использовать частичный class?

В последних версиях Visual Studio используются частичные classы, чтобы отделить созданный автогенерируемый код разработчика от вашего собственного кода.

Пример ASP.NET:

  • Page.aspx
  • Page.aspx.cs < - Ваш код
  • Page.aspx.Designer.cs < - частичный класс, содержащий автоматически сгенерированный код.

Пример WinForms:

  • Form1.resx
  • Form1.cs < - Ваш код
  • Form1.Designer.cs < - частичный класс, содержащий автоматически сгенерированный код

Я использовал частичные classы для «физического» разделения методов статического доступа к данным из свойств и методов бизнес-classа в активной архитектуре записи. Например, у нас были частичные classы Company и CompanyData бок о бок. Преимущество заключалось в том, что один файл был POCO, а другой – только методы доступа к данным. Это стало шагом к удалению доступа к данным к classам репозитория в устаревшем приложении. Я думаю, что это было законное использование, это, безусловно, сделало процесс повторного факторинга более ясным.

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

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

Просто наткнулся на эту нить, в то время как придумывал преимущества частичного classа. Я в процессе преобразования приложения Java EE в .NET на основе Silverlight. Я натолкнулся на следующий код на уровне представления:

 //------------------------------------------------------------------------------ //  // 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. //  //------------------------------------------------------------------------------ ... public partial class Wwcusts04d : System.Windows.Controls.Page { 

Теперь, если сама частичная страница автогенерируется, зачем ее поддерживать? Кроме того, код внутри просто связывает различные элементы управления с их именами. Я не признаюсь, что имею знания о Silverlight, но разве эта вещь больше не подходит для xaml?

Частичный class существует в среде .NET, чтобы позволить разработчикам Visual Studio (например, дизайнеру Asp.Net и конструктору Windows Forms) генерировать код / ​​беспорядок с вашими classами, сохраняя этот сгенерированный код в отдельном файле.

(См. Раздел .NET Partial Classes and Inheritance )

Если вы сделаете нечто подобное (сгенерируйте код, который должен сосуществовать с написанным пользователем кодом), вы также можете найти частичные classы полезными, но я не верю, что Microsoft когда-либо предлагала частичные classы в качестве языковой концепции, чтобы быть полезной для кого-либо, кроме команда Visual Studio.

Его не так много, что использование Partial classes – плохой дизайн – его просто вы, вероятно, не найдете для них использования.

Я дважды использовал частичный class в VB.Net, и оба раза были для того редкого случая, что мне нужно было последнее связывание. Просто создайте частичный class и включите опцию Strict Off сверху.

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

Там много дискуссий по этой теме, и многие люди говорят, что 1) плохой дизайн использует частичные classы, 2) что он используется для автогенерированного кода и 3) что он не должен заменять наследование.

Однако у меня есть ситуация, в которой частичные classы выглядят так, как будто они пригодится: я создаю серию приложений, которые в конечном итоге будут интегрированы в набор. Все они будут иметь основную форму, которая обеспечит некоторые функции и несколько общих компонентов (например, форму для отображения отчетов). Хотя я мог бы определить базовый class и наследовать его, это означало бы большую переделку, когда придет время объединить все приложения в «корпоративную» версию продукта.

Таким образом, частичные classы весьма полезны, потому что я могу просто включить различные частичные classы в комбинированную версию, сохраняя при этом возможность создавать отдельные автономные версии продукта. Если бы я попытался выполнить это с помощью наследования, я бы включил каждый компонент, который вызывал свою собственную версию общих компонентов (например, InvoiceReportViewer, PurchasingReportsViewer и т. Д.), А не просто вызывал ReportViewer и знал, что Visual Studio будет интегрирован все биты для меня.

Другое дело, что частичные classы заставляют вас создавать разные имена файлов, которые содержат одно и то же имя classа . Например, у вас есть FactoryClass, и вы создаете частичные версии этого типа; Factory.designer.cs, Factory.data.cs и все эти файлы имеют class с именем FactoryClass.

Если вы перейдете к этому вопросу; существует наилучшая практика, определяемая как:

Лучшей практикой, однако, является определение одного classа для каждого файла и предоставление файлу того же имени, что и определение classа (или структуры и т. Д.).