Существуют ли какие-либо инструменты статического анализа, которые сообщают о том, насколько точно соблюдаются принципы SOLID?

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

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

SRP Принцип единой ответственности

У класса должна быть только одна причина для изменения.

OCP Принцип открытого-закрытого

Программные объекты (классы, модули, функции и т. Д.) Должны быть открыты для расширения, но закрыты для модификации.

LSP Принцип замещения Лискова

Подтипы должны быть заменяемыми на свои базовые типы.

Интернет-провайдер Принцип разделения интерфейса

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

DIP Принцип инверсии зависимостей

Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

-Из Agile Principles, Patterns and Practices Роберта К. Мартина.


person Kenneth Cochran    schedule 26.10.2009    source источник
comment
Обратной стороной к ним является то, что они иногда требуют глубокого анализа исходного кода для их применения. Если анализа кода (независимо от того, насколько глубоким) будет достаточно, такие инструменты будут возможны, однако изучение кода мало.   -  person Wolf    schedule 06.10.2014
comment
@Wolf В контексте этого конкретного предложения я имел в виду человеческий анализ, основанный на понимании, проницательности и интуиции.   -  person Kenneth Cochran    schedule 15.10.2014
comment
Вы имеете в виду шаблоны, извлеченные из анализа человеческого кода, наличие которых позже проверяется автоматически?   -  person Wolf    schedule 15.10.2014
comment
Нет. Я просто спрашивал, есть ли какие-нибудь инструменты, которые могли бы приблизиться к результатам, полученным при ручном анализе кода опытным разработчиком программного обеспечения. Я думаю, что главный ответ довольно хорошо резюмировал это. Таких инструментов не существует, потому что принципы SOLID слишком неформальны для автоматического анализа.   -  person Kenneth Cochran    schedule 15.10.2014


Ответы (2)


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

Тем не менее, у вас могут быть инструменты, которые помогут вам определить вероятность нарушения. Например, вы можете использовать метрики кода, такие как количество методов на класс, количество членов на класс, чтобы определить, является ли класс слишком большим и, следовательно, может нарушить SRP.

Исключением может быть принцип замены Лискова. ЕСЛИ вы определяете контракты для всех методов (предусловий, постусловий, инвариантов), тогда вы можете проверить, что метод, переопределяющий метод суперкласса, не усиливает предусловие, не ослабляет постусловие и соблюдать инварианты метода суперкласса. Я думаю, что инструмент ESC / Java выполняет эти проверки. При чтении страницы wikipedia о LSP потребуется выполнить дополнительные проверки.

person Monkeyget    schedule 26.10.2009

Мой ответ касается продукта, специфичного для .NET, заранее приношу извинения и, возможно, кто-то может предложить его аналоги, не относящиеся к .NET.

Я бы попробовал NDepend и посмотреть, может ли это привести меня к нарушениям SRP и Интернет-провайдер, используя такие показатели, как:

  • количество методов на типы типов с
  • аномально большое количество методов
  • афферентная / эфферентная связь на уровне сборки и типа
  • другие показатели, полный список показателей здесь

Нарушения DIP и LSP может быть труднее отследить, потому что они связаны с намерениями программиста. Инструмент анализа может идентифицировать отношения между типами, но как он может отличить ситуацию, когда один класс действительно расширяет другой, от неправильного производного класса Square от Rectangle? Или что в правильно спроектированной программе A должно зависеть от B, а не наоборот?

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

Однако, если мы считаем, что следование SOLID ведет к более удобному обслуживанию продукта (вопрос не в том, чтобы доказать это утверждение с научной точки зрения), тогда диаграмма абстрактности-нестабильности NDepend должна дать хороший агрегированный показатель того, насколько хорошо принципы были соблюдены для каждого программного модуля. Если бы это было так, то модуль должен был бы избегать нижнего левого угла диаграммы, получившего название «Зона боли». В этой зоне модуль стабилен (не в хорошем смысле - от него зависит слишком много других, поэтому его сложно изменить), но недостаточно абстрактно.

person azheglov    schedule 30.10.2009
comment
Теоретически, если бы программист провел набор идеальных тестов для каждого объекта, можно ли было бы автоматически обнаружить нарушение Лискова? Квадрат - это случай прямоугольника, где методы setWidth () и setHeight () квадрата имеют побочный эффект, заключающийся в установке не только объявленной переменной, но и другой. Например. setWidth обновляет не только ширину, но и высоту. setHeight обновляет ширину и высоту (продолжение в следующем комментарии) - person stk1234; 31.10.2020
comment
Это поведенческое нарушение Лисков, которое невозможно обнаружить без теста. Однако, если у класса Rectangle был тест, в котором setWidth () обновляет ширину и не меняет высоту, выполнение Square через модульные тесты Rectangle приведет к сбою. На таком языке, как Java, вы можете написать программу, которая будет брать все дочерние экземпляры родительского класса и запускать над ними родительские тесты. Это позволит зафиксировать нарушения побочных эффектов и возможные дополнительные ошибки. - person stk1234; 31.10.2020
comment
Разъяснение об идеальном в идеальных тестах выше: я не имею в виду, что для этого потребуются все наборы возможных входов и выходов, но достаточно (это очень мягкое слово). Возможно, это означает, что 1 пример setWidth () равен 100, который будет представлять все положительные целые числа. - person stk1234; 31.10.2020