Advertisement
superguru

NDEPEND Namespace Dependency Cycles

Jul 28th, 2014
617
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 2.80 KB | None | 0 0
  1. // <Name>Avoid namespaces dependency cycles</Name>
  2. warnif count > 0
  3. // This query lists all application namespace dependency cycles.
  4. // Each row shows a different cycle, prefixed with a namespace entangled in the cycle.
  5. //
  6. // To browse a cycle on the dependency graph or the dependency matrix, right click
  7. // a cycle cell and export the matched namespaces to the dependency graph or matrix!
  8. //
  9. // In the matrix, dependency cycles are represented with red squares and black cells.
  10. // To easily browse dependency cycles, the Matrix comes with an option:
  11. //   --> Display Direct and Indirect Dependencies
  12. //
  13. // Read our white books relative to partitioning code,
  14. // to know more about namespaces dependency cycles, and why avoiding them
  15. // is a simple but efficient solution to architecture for your code base.
  16. // http://www.ndepend.com/WhiteBooks.aspx
  17.  
  18.  
  19. // Optimization: restraint application assemblies set
  20. // If some namespaces are mutually dependent
  21. //  - They must be declared in the same assembly
  22. //  - The parent assembly must ContainsNamespaceDependencyCycle
  23. from assembly in Application.Assemblies
  24.                  .Where(a => a.ContainsNamespaceDependencyCycle != null &&
  25.                              a.ContainsNamespaceDependencyCycle.Value)
  26.  
  27. // Optimization: restraint namespaces set
  28. // A namespace involved in a cycle necessarily have a null Level.
  29. let namespacesSuspect = assembly.ChildNamespaces.Where(n => n.Level == null)
  30.  
  31. // hashset is used to avoid iterating again on namespaces already caught in a cycle.
  32. let hashset = new HashSet<INamespace>()
  33.  
  34.  
  35. from suspect in namespacesSuspect
  36.    // By commenting in this line, the query matches all namespaces involved in a cycle.
  37.    where !hashset.Contains(suspect)
  38.  
  39.    // Define 2 code metrics
  40.    // - Namespaces depth of is using indirectly the suspect namespace.
  41.    // - Namespaces depth of is used by the suspect namespace indirectly.
  42.    // Note: for direct usage the depth is equal to 1.
  43.    let namespacesUserDepth = namespacesSuspect.DepthOfIsUsing(suspect)
  44.    let namespacesUsedDepth = namespacesSuspect.DepthOfIsUsedBy(suspect)
  45.  
  46.    // Select namespaces that are both using and used by namespaceSuspect
  47.    let usersAndUsed = from n in namespacesSuspect where
  48.                          namespacesUserDepth[n] > 0 &&
  49.                          namespacesUsedDepth[n] > 0
  50.                       select n
  51.  
  52.    where usersAndUsed.Count() > 0
  53.  
  54.    // Here we've found namespace(s) both using and used by the suspect namespace.
  55.    // A cycle involving the suspect namespace is found!
  56.    let cycle = usersAndUsed.Append(suspect)
  57.  
  58.    // Fill hashset with namespaces in the cycle.
  59.    // .ToArray() is needed to force the iterating process.
  60.    let unused1 = (from n in cycle let unused2 = hashset.Add(n) select n).ToArray()
  61.  
  62. select new { suspect, cycle }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement