Подтвердить что ты не робот

Что-то не так с классом со всеми статическими методами?

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

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

Что-то не так с этим шаблоном? Это только вопрос личного выбора, если состояние класса хранится в полях и свойствах или передается между статическими методами с использованием аргументов?

UPDATE: конкретное состояние, которое передается, представляет собой набор результатов из базы данных. Обязанностью класса является заполнение шаблона Excel Excel из набора результатов из БД. Я не знаю, имеет ли это значение.

4b9b3361

Ответ 1

Что-то не так с этим шаблон? Это только вопрос личный выбор, если состояние класс хранится в полях и свойствах или проходил между статическими методы с использованием аргументов?

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

Конечный результат: настоящая ООП-тастическая архитектура с таким количеством направлений, что требуется много часов, чтобы отлаживать что-либо. Недавно я начал работу с такой системой, где кривая обучения была описана мне как "кирпичная стена, а затем гора".

Иногда чрезмерно усложненный ООП приводит к таким гранулярным классам, что на самом деле это чистый вред.

В отличие от этого, многие языки функционального программирования, даже такие OO, как F # и OCaml (и С#!), способствуют плоской и мелкой атаке. Библиотеки на этих языках имеют следующие свойства:

  • Большинство объектов - это POCOs или имеют не более одного или двух уровней наследования, где объекты не намного больше, чем контейнеры для логически связанных данных.
  • Вместо того, чтобы классы вызывали друг в друга, у вас есть модули (эквивалентные статическим классам), управляющие взаимодействиями между объектами.
  • Модули имеют тенденцию действовать на очень ограниченное количество типов данных и поэтому имеют узкую область. Например, модуль списка OCaml представляет операции над списками, модули клиентов облегчают операции с клиентами. Хотя модули имеют более или менее ту же функциональность, что и методы экземпляров в классе, ключевое отличие от модулей-библиотек заключается в том, что модули гораздо более автономны, гораздо менее гранулированы и, как правило, имеют мало, если есть зависимости от других модулей.
  • Как правило, нет необходимости переопределять методы объектов подкласса, поскольку вы можете передавать функции как объекты первого класса для специализации.
  • Хотя С# не поддерживает эту функциональность, functors предоставляет средства для подкласса специализированных модулей.

Большинство крупных библиотек имеют тенденцию быть более широкими, чем глубокие, например, Win32 API, PHP-библиотеки, библиотеки Erlang BIF, OCaml и Haskell, хранимые процедуры в базе данных и т.д. Таким образом, этот стиль программирования - это тестирование на битву, хорошо работают в реальном мире.

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

Ответ 2

То, что вы описываете, - это просто структурированное программирование, как это можно сделать в C, Pascal или Algol. В этом нет ничего неправильного. Бывают ситуации, когда ООП более уместен, но ООП не является окончательным ответом, и если проблема под рукой лучше всего обеспечивается структурированным программированием, тогда класс, полный статических методов, - это путь.

Ответ 3

Помогает ли это перефразировать вопрос:

Можете ли вы описать данные, которые статические методы работают как объекты, имеющие:

  • понятное значение
  • Ответственность за поддержание внутреннего состояния.

В этом случае это должен быть экземпляр объекта, иначе он может быть просто связкой связанных функций, подобно математической библиотеке.

Ответ 4

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

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

Преимущество, которое я вижу в том, чтобы превратить эти статические методы в один или несколько классов, - это когда вы это делаете, часто становится легче понимать и поддерживать ваше программное обеспечение.

Ответ 5

Я чувствую, что если класс должен поддерживать некоторую форму состояния (например, свойства), то он должен быть инстанцирован (т.е. "нормальный" класс.)

Если должен быть только один экземпляр этого класса (следовательно, все статические методы), тогда должно существовать одноэлементное свойство/метод или метод factory, который создает экземпляр класса при первом вызове, а затем просто предоставляет этот экземпляр, когда кто-то еще просит его.

Сказав это, это только мое личное мнение и то, как я его реализую. Я уверен, что другие не согласятся со мной. Честно говоря, не зная ничего более сложного, чтобы объяснить причины/против каждого метода.

Ответ 6

Самая большая проблема IMO заключается в том, что если вы хотите unit test классы, которые вызывают упомянутый класс, не существует способа заменить эту зависимость. Таким образом, вы вынуждены одновременно тестировать как клиентский класс, так и статически называемый класс.

Если мы говорим о классе с такими полезными методами, как Math.floor(), это не проблема. Но если класс является реальной зависимостью, например объектом доступа к данным, то он связывает всех своих клиентов с его реализацией.

EDIT: Я не согласен с людьми, говорящими, что "нет ничего плохого" в этом типе "структурированного программирования". Я бы сказал, что такой класс, по крайней мере, является запахом кода, когда встречается в рамках обычного Java-проекта и, вероятно, указывает на непонимание объектно-ориентированного дизайна со стороны создателя.

Ответ 7

В этом шаблоне нет ничего плохого. С# на самом деле имеет конструкцию, называемую статическими классами, которая используется для поддержки этого понятия, применяя требование о том, чтобы все методы были статическими. Кроме того, в структуре есть много классов, которые имеют эту функцию: Enumerable, Math и т.д.

Ответ 8

В этом нет ничего плохого. Это более "функциональный" способ кодирования. Это может быть проще протестировать (потому что нет внутреннего состояния) и более высокая производительность во время выполнения (потому что нет лишних затрат для экземпляра иначе бесполезного объекта).

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

Ответ 9

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

В С# следует учитывать, что многие классы, ранее написанные полностью статично, теперь могут рассматриваться как классы расширения .net, которые также находятся в их сердце неподвижных статических классах. На этом основаны многие расширения Linq.

Пример:

namespace Utils {
    public static class IntUtils        {
            public static bool IsLessThanZero(this int source)
            {
                return (source < 0);
            }
    }
}

Который позволяет вам просто сделать следующее:

var intTest = 0;
var blNegative = intTest.IsLessThanZero();

Ответ 10

Одним из недостатков использования статического класса является то, что его клиенты не могут заменить его двойным тестовым тестированием.

Точно так же сложнее unit test статический класс, потому что его соавторы не могут быть заменены тестовыми двойниками (на самом деле это происходит со всеми классами, которые не вложены в зависимость).

Ответ 11

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

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

public static File loadConfiguration(String name, Enum type) {
    String fileName = (form file name based on name and type);
    return loadFile(fileName); // static method in the same class
}

Ответ 12

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

Однако есть несколько исключений:

  • методы, которые обрабатывают строки (например, верхние буквы первых букв или такую ​​функцию)
  • которые являются апатридами и просто собирают некоторые вещи для создания нового, без какого-либо внутреннего состояния. Они, очевидно, редки, но обычно полезно сделать их статическими.

Фактически, я считаю ключевое слово static таким, каким оно есть: вариант, который следует использовать с осторожностью, поскольку он нарушает некоторые принципы ООП.

Ответ 13

Передача всего состояния в качестве параметров метода может быть полезным шаблоном проектирования. Он гарантирует, что не существует общего измененного состояния, и поэтому класс является неотъемлемо потокобезопасным. Сервисы обычно реализуются с использованием этого шаблона.

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

Ответ 14

"состояние класса... передается среди статических методов с использованием аргументов?" Вот как работает процедурное программирование.

Класс со всеми статическими методами и переменными экземпляра (кроме статических конечных констант) обычно является класс утилиты, например Math. Нет ничего плохого в том, чтобы сделать класс унижения (не само по себе) BTW: Если вы используете класс утилиты, вы можете предотвратить использование класса aver для создания объекта. в java вы сделаете это, явно определяя конструктор, но сделав конструктор закрытым. Хотя, как я сказал, нет ничего плохого в создании класса утилиты, Если основная часть работы выполняется классом utiulity (поскольку esc не является классом в обычном смысле - это скорее набор функций) то это проблема как знак, проблема не была решена с использованием ориентированного на объект парадизма. это может или не может быть хорошей вещью.

Метод входа принимает несколько аргументов и затем вызывает вызовы других статических методов, проходящих по всем или некоторым аргументам, полученным методом входа. из всего этого звука весь класс является просто эффектно одним методом (это, безусловно, будет иметь место, так как другие статические методы являются частными (и являются только вспомогательными функциями), и нет переменных экземпляра (константы baring)), Это может быть и хорошо, Это esc. структурированные/процедурные прогамминга, довольно аккуратные, имеющие их (функцию и ее помощник), все в одном классе. (в C вы просто поместили их все в один файл и объявили вспомогательный статический (значение не может быть доступно из стороннего файла))

Ответ 15

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

Ответ 16

Я не совсем уверен, что вы имели в виду при входе, но если вы говорите о чем-то вроде этого:

 MyMethod myMethod = new MyMethod();
 myMethod.doSomething(1);

 public class MyMethod {
      public String doSomething(int a) {
          String p1 = MyMethod.functionA(a);
          String p2 = MyMethod.functionB(p1);
          return p1 + P2;
      }
      public static String functionA(...) {...}
      public static String functionB(...) {...}
 }

Это нецелесообразно.

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

 MyClass.myStaticMethod(....);

в отличие от:

 MyClass.getInstance().mySingletonMethod(...);

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