Недавно я рассматривал несколько статических классов «вспомогательных пакетов» в стиле Хелпера, плавающих вокруг больших кодовых баз C #, с которыми я работаю, в основном, как следующий очень сжатый фрагмент:
// Helpers.cs
public static class Helpers
{
public static void DoSomething() {}
public static void DoSomethingElse() {}
}
Конкретные методы, которые я рассмотрел,
- в основном не связаны друг с другом,
- без явного состояния сохраняется через вызовы,
- маленький и
- каждый потребляется различными не связанными типами.
Изменить: выше не предназначен, чтобы быть списком предполагаемых проблем. Это список общих характеристик конкретных методов, которые я рассматриваю. Это контекст, чтобы помочь ответам предоставить более актуальные решения.
Только для этого вопроса я буду называть этот тип метода GLUM (общий легкий метод утилит). Негативный оттенок "мрачность" отчасти предназначен. Я извиняюсь, если это выглядит как тупой каламбур.
Даже если оставить в стороне мой собственный скептицизм по умолчанию в отношении GLUM, мне не нравятся следующие вещи по этому поводу:
- Статический класс используется исключительно как пространство имен.
- Статический идентификатор класса в принципе не имеет смысла.
- Когда добавляется новый GLUM, либо (a) к этому классу «bag» прикасаются без веской причины, либо (b) создается новый класс «bag» (который сам по себе обычно не является проблемой; что плохо, так это то, что новый статические классы часто просто повторяют проблему несвязанности, но с меньшим количеством методов).
- Мета-именование неотвратимо ужасно, нестандартное, и , как правило , внутренне противоречива, будь то
Helpers
,Utilities
или что угодно.
Каков достаточно хороший и простой способ для рефакторинга этого, предпочтительно для решения вышеупомянутых проблем, и, предпочтительно, с как можно более легким прикосновением?
Я, наверное, должен подчеркнуть: все методы, с которыми я имею дело, попарно не связаны друг с другом. Кажется, не существует разумного способа разбить их на более мелкозернистые, но все же многосоставные пакеты методов класса.
источник
Ответы:
Я думаю, что у вас есть две проблемы, тесно связанные друг с другом.
Эти проблемы могут быть исправлены путем объединения только логически связанных методов в один статический класс и перемещения других в их собственный статический класс. На основе вашей проблемной области вы и ваша команда должны решить, какие критерии вы будете использовать для разделения методов на связанные статические классы.
Проблемы и возможные решения
Методы в основном не связаны друг с другом - проблема. Объедините связанные методы в одном статическом классе и переместите несвязанные методы в их собственные статические классы.
Методы без явного состояния сохраняются через вызовы - не проблема. Методы без сохранения состояния - это функция, а не ошибка. В любом случае, статическое состояние сложно проверить, и его следует использовать только в том случае, если вам нужно поддерживать состояние между вызовами методов, но есть более эффективные способы сделать это, например, конечные автоматы и
yield
ключевое слово.Методы маленькие - не проблема. - Методы должны быть небольшими.
Каждый из методов используется различными не связанными типами - это не проблема. Вы создали общий метод, который можно использовать повторно во многих несвязанных местах.
Статический класс используется исключительно как пространство имен - не проблема. Вот как используются статические методы. Если этот стиль вызова методов вас беспокоит, попробуйте использовать методы расширения или
using static
объявление.Статический идентификатор класса в принципе не имеет смысла - проблема . Это бессмысленно, потому что разработчики вкладывают в него несвязанные методы. Поместите несвязанные методы в их собственные статические классы и дайте им конкретные и понятные имена.
Когда добавляется новый GLUM, либо (a) этот класс «bag» затрагивается (грусть SRP) - не проблема, если вы придерживаетесь идеи, что в одном статическом классе должны быть только логически связанные методы.
SRP
здесь не нарушается, потому что принцип должен применяться для классов или методов. Единственная ответственность статических классов означает содержать разные методы для одной общей «идеи». Эта идея может быть функцией или преобразованием, или итерациями (LINQ), или нормализацией данных, или проверкой ...или реже (б) создается новый класс «сумок» (больше сумок) - не проблема. Классы / статические классы / функции - это наши (разработчики) инструменты, которые мы используем для разработки программного обеспечения. Есть ли в вашей команде ограничения на использование классов? Каковы максимальные ограничения для «больше сумок»? Программирование - все о контексте, если для решения в вашем конкретном контексте вы в конечном итоге получите 200 статических классов с понятным именем, логически размещенных в пространствах имен / папках с логической иерархией - это не проблема.
Мета-наименование неизбежно ужасно, нестандартно и, как правило, внутренне несовместимо, будь то хелперы, утилиты или что-то еще - проблема. Укажите лучшие имена, которые описывают ожидаемое поведение. Храните только связанные методы в одном классе, которые помогают лучше именовать.
источник
A
со 100 статическими классами с одним методом (в 100 файлах), чем статический классA
со 100 методами в одном файле.Math
статический класс.Просто примите соглашение, что статические классы используются как пространства имен в таких ситуациях, как в C #. Пространства имен получают хорошие имена, как и эти классы.
using static
Особенность C # 6 делает жизнь немного легче.Вонючие имена классов, такие как
Helpers
сигнал о том, что методы должны быть разделены на статические классы с более подходящими именами, если это вообще возможно, но одно из ваших подчеркнутых предположений заключается в том, что методы, с которыми вы имеете дело, «попарно не связаны», что подразумевает разделение на один новый статический класс для каждого существующего метода. Это, наверное, хорошо, еслиКак надуманный пример,
Helpers.LoadImage
может стать что-то вродеFileSystemInteractions.LoadImage
.Тем не менее, вы можете получить статические классные методики. Вот как это может произойти:
Важно помнить, что эти методические пакеты статического класса не являются необычными в реальных кодовых базах C #. Вероятно, не патологично иметь несколько маленьких .
Если вы действительно видите преимущество в том, что каждый метод, похожий на «свободную функцию», находится в своем собственном файле (что хорошо и целесообразно, если вы честно осознаете, что это на самом деле повышает удобство сопровождения вашего проекта), вы можете рассмотреть возможность сделать такой статический класс вместо статическим частичный класс, использующий статическое имя класса аналогично тому, как вы бы использовали пространство имен, и затем использующий его через
using static
. Например:Program.cs
Foo / Bar.cs
Foo / Baz.cs
Flob / Wibble.cs
Flob / Wobble.cs
источник
Как правило, вы не должны иметь или требовать каких-либо «общих служебных методов». В вашей бизнес-логике. Посмотрите еще раз и поместите их в подходящее место.
Если вы пишете математическую библиотеку или что-то в этом роде, я бы предложил, хотя я обычно ненавижу их, Методы расширения.
Вы можете использовать методы расширения для добавления функций в стандартные типы данных.
Например, допустим, у меня есть общая функция MySort () вместо Helpers.MySort или добавление нового ListOfMyThings.MySort. Я могу добавить его в IEnumerable.
источник