简体   繁体   中英

C# How to get the Circular Methods in a Project/Solution using ndepend in the latest version 2018.1.1

I tried this code in NDepend version 2018.1.1 with some changes made to the original code which was posted on stackoverflow. It is to get the Methods which have a circular dependencies (ie calling each other and forming a cyclic/circular code)

But this Code does not seem to work in the latest nDepend.

Note: the only difference from the other code on StackOverflow is that this one has this according to version 2018.1.1 requirement;

let cycle = ExtensionMethodsEnumerable.Append(usersAndUsed,suspect)

The Code.....

    // <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 }

The query provided works fine on my end to find cycles of methods inside a type.

For general cycle of methods (no matter their parent type) just modify the beginning of the query this way.

//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)

Also increase in the NDepend > Options > CQLinq query execution time-out to 60 seconds because the query can be slow on a large code base with all graph traversal.

Keep in mind that a cycle is not necessarily as simple as A calls B calls C calls A. A cycle is a set of methods where from any method, there is a path to any other method in the cycle. It can be quite complex like: 方法周期

To visualize a method cycle just export it to the code graph:

将循环方法导出到图形

Typically to break cycles, start by breaking mutual dependencies, like A calls B and B calls A.

A method cycle is not necessarily a code smell, many GoF design patterns for example rely on a method cycle.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM