Я склонен объявлять статическими все методы в классе, когда этому классу не требуется отслеживать внутренние состояния. Например, если мне нужно преобразовать A в B и не полагаться на какое-то внутреннее состояние C, которое может отличаться, я создаю статическое преобразование. Если есть внутреннее состояние C, которое я хочу настроить, я добавляю конструктор для установки C и не использую статическое преобразование.
Я читал различные рекомендации (в том числе о StackOverflow) НЕ злоупотреблять статическими методами, но я все еще не понимаю, что не так с приведенным выше эмпирическим правилом.
Это разумный подход или нет?
Объект без внутреннего состояния - вещь подозрительная.
Обычно объекты инкапсулируют состояние и поведение. Странный объект, который только инкапсулирует поведение. Иногда это пример Легкого или Наилегчайшего веса .
В других случаях это процедурный дизайн, выполненный на объектном языке.
источник
На самом деле это только продолжение великого ответа Джона Милликина.
Хотя можно безопасно сделать статические методы без сохранения состояния (которые в значительной степени являются функциями), иногда это может привести к связыванию, которое трудно изменить. Предположим, у вас есть статический метод как таковой:
Что вы называете:
Это хорошо, хорошо и очень удобно, пока вы не столкнетесь со случаем, когда вам нужно изменить поведение статического метода, и обнаружите, что вы жестко привязаны к
StaticClassVersionOne
. Возможно, вы могли бы изменить код, и это было бы хорошо, но если бы были другие вызывающие объекты, зависящие от старого поведения, их нужно будет учитывать в теле метода. В некоторых случаях это тело метода может стать довольно некрасивым или неподдерживаемым, если оно пытается сбалансировать все эти поведения. Если вы разделите методы, вам, возможно, придется изменить код в нескольких местах, чтобы учесть это, или выполнить вызовы новых классов.Но подумайте, если бы вы создали интерфейс для предоставления метода и передали его вызывающим абонентам, теперь, когда поведение должно измениться, можно создать новый класс для реализации интерфейса, который будет более чистым, более легким для тестирования и более удобным в обслуживании, и это вместо этого предоставляется вызывающим абонентам. В этом сценарии вызывающие классы не нужно изменять или даже перекомпилировать, и изменения локализованы.
Это может быть, а может и нет, но я думаю, что стоит подумать.
источник
Другой вариант - добавить их как нестатические методы к исходному объекту:
т.е. изменение:
в
однако во многих ситуациях это невозможно (например, генерация кода обычного класса из XSD / WSDL / и т. д.), или это сделает класс очень длинным, а методы преобразования часто могут быть настоящей проблемой для сложных объектов, и вы просто хотите, чтобы они в своем отдельном классе. Так что да, у меня есть статические методы в служебных классах.
источник
Статические классы хороши, если они используются в нужных местах.
А именно: методы, которые являются «листовыми» методами (они не изменяют состояние, они просто каким-то образом преобразуют ввод). Хорошим примером этого являются такие вещи, как Path.Combine. Подобные вещи полезны и позволяют сократить синтаксис.
У меня много проблем со статикой:
Во-первых, если у вас есть статические классы, зависимости скрыты. Учтите следующее:
Глядя на TextureManager, вы не можете сказать, какие шаги инициализации должны быть выполнены, глядя на конструктор. Вы должны углубиться в класс, чтобы найти его зависимости и инициализировать вещи в правильном порядке. В этом случае перед запуском необходимо инициализировать ResourceLoader. Теперь увеличьте масштаб этого кошмара зависимостей, и вы, вероятно, сможете догадаться, что произойдет. Представьте, что вы пытаетесь поддерживать код без явного порядка инициализации. Сравните это с внедрением зависимостей с экземплярами - в этом случае код даже не будет компилироваться, если зависимости не выполняются!
Более того, если вы используете статику, изменяющую состояние, это похоже на карточный домик. Никогда не знаешь, у кого к чему есть доступ, а дизайн имеет тенденцию напоминать монстра-спагетти.
Наконец, что не менее важно, использование статики связывает программу с конкретной реализацией. Статический код - это полная противоположность тестируемости. Тестирование кода, пронизанного статикой, - это кошмар. Статический вызов никогда не может быть заменен тестовым двойником (если вы не используете тестовые фреймворки, специально разработанные для имитации статических типов), поэтому статическая система заставляет все, что ее использует, быть тестом мгновенной интеграции.
Короче говоря, статика подходит для некоторых вещей, а для небольших инструментов или одноразового кода я бы не стал препятствовать их использованию. Однако, помимо этого, они представляют собой кровавый кошмар для ремонтопригодности, хорошего дизайна и простоты тестирования.
Вот хорошая статья о проблемах: http://gamearchitect.net/2008/09/13/an-anatomy-of-despair-managers-and-contexts/
источник
Причина, по которой вас предостерегают от статических методов, заключается в том, что их использование лишает одного из преимуществ объектов. Объекты предназначены для инкапсуляции данных. Это предотвращает возникновение неожиданных побочных эффектов, что позволяет избежать ошибок. Статические методы не имеют инкапсулированных данных * и поэтому не получают этого преимущества.
Тем не менее, если вы не используете внутренние данные, их можно использовать и выполнять немного быстрее. Убедитесь, что вы не касаетесь глобальных данных в них.
источник
Это кажется разумным подходом. Причина, по которой вы не хотите использовать слишком много статических классов / методов, заключается в том, что вы в конечном итоге уходите от объектно-ориентированного программирования и переходите к сфере структурного программирования.
В вашем случае, когда вы просто преобразуете A в B, скажем, все, что мы делаем, это преобразовываем текст, чтобы он
Тогда имел бы смысл статический метод.
Однако, если вы часто вызываете эти статические методы для объекта, и он имеет тенденцию быть уникальным для многих вызовов (например, способ его использования зависит от ввода) или является частью неотъемлемого поведения объекта, это будет Будьте мудры, сделав его частью объекта и поддерживая его состояние. Один из способов сделать это - реализовать его как интерфейс.
Изменить: одним из хороших примеров использования статических методов являются вспомогательные методы html в Asp.Net MVC или Ruby. Они создают элементы HTML, которые не привязаны к поведению объекта и поэтому являются статическими.
Изменить 2: изменено функциональное программирование на структурированное программирование (по какой-то причине я запутался), спасибо Торстену за указание на это.
источник
Недавно я провел рефакторинг приложения, чтобы удалить / изменить некоторые классы, которые изначально были реализованы как статические классы. Со временем эти классы приобрели так много, и люди просто продолжали отмечать новые функции как статические, поскольку никогда не было экземпляра, плавающего вокруг.
Итак, мой ответ заключается в том, что статические классы не являются плохими по своей сути, но, возможно, будет проще начать создавать экземпляры сейчас, а потом придется провести рефакторинг.
источник
Я бы счел это запахом дизайна. Если вы обнаружите, что используете в основном статические методы, у вас, вероятно, не очень хороший объектно-ориентированный дизайн. Это не обязательно плохо, но, как и все запахи, я бы остановился и переоценил. Это намекает на то, что вы могли бы улучшить объектно-ориентированный дизайн или что, возможно, вам следует пойти в другом направлении и полностью избегать объектно-ориентированного проектирования для этой проблемы.
источник
Раньше я переключался между классом с кучей статических методов и синглтоном. Оба решают проблему, но синглтон гораздо проще заменить на несколько. (Программисты всегда кажутся настолько уверенными, что будет только 1 из чего-то, и я достаточно часто ошибался, чтобы полностью отказаться от статических методов, за исключением некоторых очень ограниченных случаев).
В любом случае синглтон дает вам возможность позже передать что-то в фабрику, чтобы получить другой экземпляр, и это изменяет поведение всей вашей программы без рефакторинга. Изменение глобального класса статических методов на что-то с другими «вспомогательными» данными или немного другим поведением (дочерний класс) является серьезной проблемой.
И статические методы не имеют подобного преимущества.
Так что да, они плохие.
источник
Пока не вступает в игру внутреннее состояние, это нормально. Обратите внимание, что обычно статические методы должны быть поточно-ориентированными, поэтому, если вы используете вспомогательные структуры данных, используйте их поточно-ориентированным способом.
источник
Если вы знаете, что вам никогда не понадобится использовать внутреннее состояние C, ничего страшного. Однако, если это когда-нибудь изменится в будущем, вам нужно будет сделать метод нестатическим. Если он изначально нестатичен, вы можете просто игнорировать внутреннее состояние, если оно вам не нужно.
источник
Если это служебный метод, неплохо сделать его статическим. Guava и Apache Commons построены на этом принципе.
Мое мнение по этому поводу чисто прагматическое. Если это код вашего приложения, статические методы, как правило, не лучшее решение. Статические методы имеют серьезные ограничения модульного тестирования - их нелегко смоделировать: вы не можете внедрить фиктивную статическую функциональность в какой-либо другой тест. Вы также обычно не можете внедрить функциональность в статический метод.
Поэтому в логике моего приложения обычно используются небольшие статические вызовы методов, подобных служебным. Т.е.
одно из преимуществ - я не тестирую такие методы :-)
источник
Ну, серебряной пули, конечно, нет. Статические классы подходят для небольших утилит / помощников. Но использование статических методов для программирования бизнес-логики - определенно зло. Рассмотрим следующий код
Вы видите статический вызов метода, вызывающего
ItemsProcessor.SplitItem(newItem);
запах, причинаBusinessService
изолировав егоItemsProcessor
(большинство инструментов тестирования не имитируют статические классы), и это делает невозможным модульное тестирование. Нет модульных тестов == низкое качествоисточник
Статические методы обычно плохой выбор даже для кода без состояния. Вместо этого создайте одноэлементный класс с этими методами, который создается один раз и внедряется в те классы, которые хотят использовать эти методы. Такие классы легче смоделировать и протестировать. Они гораздо более объектно-ориентированы. При необходимости вы можете обернуть их прокси. Статика значительно усложняет ОО, и я не вижу смысла использовать их почти во всех случаях. Не 100%, но почти все.
источник