C# Как получить Циркулярные методы в проекте / решении с помощью ndepend в последней версии 2018.1.1

Я попробовал этот код в версии 2018.1.1 NDepend с некоторыми изменениями, внесенными в исходный код, который был размещен в stackru. Это чтобы получить методы, которые имеют циклические зависимости (то есть вызывать друг друга и формировать циклический / циклический код)

Но этот Код, похоже, не работает в последней версии nDepend.

Примечание: единственное отличие от другого кода в Stackru заключается в том, что этот код соответствует требованиям версии 2018.1.1;

let cycle = ExtensionMethodsEnumerable.Append(usersAndUsed,suspect)

Код.....

    // <Name>Avoid methods of a type to be in cycles</Name>
warnif count > 0


from t in Application.Types
                 .Where(t => t.ContainsMethodDependencyCycle != null && 
                             t.ContainsMethodDependencyCycle.Value)

// Optimization: restreint methods set
// A method involved in a cycle necessarily have a null Level.
let methodsSuspect = t.Methods.Where(m => m.Level == null)

// hashset is used to avoid iterating again on methods already caught in a cycle.
let hashset = new HashSet<IMethod>()


from suspect in methodsSuspect
   // By commenting this line, the query matches all methods involved in a cycle.
   where !hashset.Contains(suspect)

   // Define 2 code metrics
   // - Methods depth of is using indirectly the suspect method.
   // - Methods depth of is used by the suspect method indirectly.
   // Note: for direct usage the depth is equal to 1.
   let methodsUserDepth = methodsSuspect.DepthOfIsUsing(suspect)
   let methodsUsedDepth = methodsSuspect.DepthOfIsUsedBy(suspect)

   // Select methods that are both using and used by methodSuspect
   let usersAndUsed = from n in methodsSuspect where
                         methodsUserDepth[n] > 0 && 
                         methodsUsedDepth[n] > 0 
                      select n

   where usersAndUsed.Count() > 0

   // Here we've found method(s) both using and used by the suspect method.
   // A cycle involving the suspect method is found!
   let cycle = ExtensionMethodsEnumerable.Append(usersAndUsed,suspect)

   // Fill hashset with methods in the cycle.
   // .ToArray() is needed to force the iterating process.
   let unused1 = (from n in cycle let unused2 = hashset.Add(n) select n).ToArray()

select new { suspect, cycle }

1 ответ

Предоставленный запрос отлично работает с моей стороны, чтобы найти циклы методов внутри типа.

Для общего цикла методов (независимо от их родительского типа) просто измените начало запроса таким образом.

//from t in Application.Types
//                 .Where(t => t.ContainsMethodDependencyCycle != null && 
//                             t.ContainsMethodDependencyCycle.Value)

// Optimization: restreint methods set
// A method involved in a cycle necessarily have a null Level.
let methodsSuspect = Application.Methods.Where(m => m.Level == null)

Также увеличьте время ожидания выполнения запроса NDepend > Options > CQLinq до 60 секунд, потому что запрос может быть медленным на большой базе кода со всем обходом графа.

Имейте в виду, что цикл не обязательно так прост, как вызовы A, вызовы B, вызовы C, вызовы A. Цикл - это набор методов, в котором из любого метода есть путь к любому другому методу в цикле. Это может быть довольно сложно, как: Метод цикла

Чтобы визуализировать цикл метода, просто экспортируйте его в граф кода:

Экспорт методов цикла на график

Как правило, чтобы разорвать циклы, начните с разрыва взаимозависимостей, как A вызывает B и B вызывает A.

Цикл метода не обязательно является запахом кода, многие шаблоны проектирования GoF, например, полагаются на цикл метода.

Другие вопросы по тегам