Перспектива проектирования: статические методы против классов - PullRequest
1 голос
/ 08 января 2010

Хотя это довольно распространенная проблема, я борюсь с тем, как лучше всего к ней подойти (если в этом случае вообще нужно подходить).

Я унаследовал сайт (ASP.NET, C #), часть которого содержит класс, полный статических методов (честно говоря, это очень большой класс). Один из методов, в частности, для отправки электронной почты. У него есть все возможные параметры, которые я могу придумать, и он работает достаточно хорошо. Тем не менее, внутренности этого конкретного метода довольно громоздки для управления и понимания из-за того, что все запихано внутрь - особенно когда большинство параметров не используются. Кроме того, обрабатывать ошибки, опять же, довольно сложно из-за всех параметров этого одного метода.

Имеет ли смысл иметь класс EMail, который создается, когда вы хотите отправить электронное письмо? Мне это кажется более правильным, хотя я не могу полностью объяснить, почему. Что вы думаете о том, как поступить в этом конкретном случае? Как насчет вообще?

Спасибо.

Ответы [ 5 ]

5 голосов
/ 08 января 2010

То, что вы описываете, звучит как пример афоризма: «Вы можете писать на фортране на любом языке».

Массовый класс, полный статических методов, часто (не всегда) является признаком того, что кто-то просто не «получил» ООП, застрял в мышлении процедурного программирования и пытался изменить язык, чтобы сделать то, что он хотел.

Практическое правило. Если какой-либо метод, статический или экземпляр, принимает более 5 параметров, это часто является признаком того, что метод пытается сделать слишком много вещей одновременно, и является хорошим кандидатом для рефакторинга в один или больше классов.

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

Мне действительно интересно, почему у вас вообще есть метод «отправить электронную почту», учитывая, что пространство имен System.Net.Mail обрабатывает практически каждый случай и настраивается через файл app.config / web.config , так что вам не нужно передавать ему имя сервера или порт. Является ли этот случай «уведомительным» методом - чем-то, что отдельные страницы должны вызывать для отправки одного из нескольких «стандартных» сообщений на основе шаблонов с заполненными различными значениями и автоматически добавляемых определенных верхних и нижних колонтитулов? Если это так, то существует целый ряд проектов для этого типа взаимодействия, с которыми гораздо проще работать, чем те, которые вы, кажется, унаследовали. (т. е. MailDefinition )

Обновление: Теперь, увидев ваш комментарий о том, что это используется для обработки исключений, я думаю, что наиболее подходящим решением является фактический обработчик исключений . На это есть масса ресурсов. Для ASP.NET WebForms я фактически взял тот, что написал Джефф Этвуд несколько лет назад, перенес его на C # и внес несколько изменений (например, игнорирование ошибок 404). Есть несколько хороших ссылок в этом предыдущем вопросе .

В настоящее время я предпочитаю рассматривать обработку исключений (и последующую отправку отчетов об исключениях по электронной почте) как подмножество ведения журнала. log4net имеет SmtpAppender , который вполне способен, и вы можете настроить его так, чтобы он использовался только для "фатальных" ошибок (то есть необработанных исключений - в вашем обработчике вы просто делаете LogFatal звоните).

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

4 голосов
/ 08 января 2010

Вот рекомендации Microsoft по использованию статических типов , как правило.

Некоторые вещи, которые я бы добавил, лично:

  • Вы должны использовать статические типы для написания методов расширения.
  • Статические типы могут усложнить юнит-тестирование, поскольку их трудно / невозможно подделать.
  • Статические типы обеспечивают неизменяемость и ссылочно-прозрачные функции, что может быть хорошим дизайном. Поэтому используйте их для вещей, которые предназначены для того, чтобы быть неизменными и не иметь внешних зависимостей. Например, System.Math .
  • Некоторые утверждают ( например, ), что модель Синглтона - плохая идея. В любом случае было бы неправильно думать о статических типах как о синглетонах; они гораздо шире.

Этот конкретный случай имеет побочные эффекты (отправка электронной почты) и, по-видимому, не требует расширенных методов. Так что это не вписывается в то, что я считаю полезным для статических типов. С другой стороны, использование объекта позволило бы издеваться над электронной почтой, что было бы полезно для модульного теста. Поэтому я думаю, что вы правы, когда говорите, что статический тип здесь неуместен.

3 голосов
/ 08 января 2010

О, черт возьми, да.

Похоже, это было старое приложение Classic ASP, которое было портировано.

Это нарушает принцип единоличной ответственности . Если вы можете рефакторинг этого класса. Используйте перегрузку для этой функции.

2 голосов
/ 08 января 2010

Это пример анти-паттерна Utils .

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

0 голосов
/ 08 января 2010

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

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

...