Git Product home page Git Product logo

degraph's Introduction

Hi ๐Ÿ‘‹, I'm Rias A. Sherzad

Full-Stack Software Architect from Hamburg, Germany

riy

  • ๐Ÿ”ญ Iโ€™m currently working on customer projects

  • ๐ŸŒฑ Iโ€™m currently learning VueJS and more DevOps

  • ๐Ÿ“ I regulary write articles on https://www.theserverside.de

  • ๐Ÿ’ฌ Ask me about Java

  • ๐Ÿ“ซ How to reach me [email protected]

angularjs aws bash bootstrap csharp css3 docker dotnet git html5 java javascript jenkins kubernetes linux mongodb mysql nginx nodejs oracle photoshop rabbitMQ sass spring swift typescript vuejs webpack

riy

ย riy

riyadh rias 966973 rias.sherzad rias.sherzad

degraph's People

Contributors

kroneckerdelta avatar marcphilipp avatar meistermeier avatar riy avatar ruderphilipp avatar schauder avatar skyr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

degraph's Issues

Exception when analyzing class with type annotations

When analyzing a class with type annotations an exception is thrown like shown below.
This is due to problems that ASM has with the behavior of certain javac versions.

See the following for more details:

If you encounter the problem, you have the following options:

  • Use an older JDK Version for compiling your classes. 1.8.0_31-b13 is the latest one known to work.
  • Don't analyze such files. Note: an exclusing filter will not work
at org.objectweb.asm.ClassReader.readLabel(Unknown Source)
    at org.objectweb.asm.ClassReader.a(Unknown Source)
    at org.objectweb.asm.ClassReader.a(Unknown Source)
    at org.objectweb.asm.ClassReader.b(Unknown Source)
    at org.objectweb.asm.ClassReader.accept(Unknown Source)
    at org.objectweb.asm.ClassReader.accept(Unknown Source)
    at de.schauderhaft.degraph.analysis.asm.Analyzer$.readStream$1(Analyzer.scala:17)
    at de.schauderhaft.degraph.analysis.asm.Analyzer$.de$schauderhaft$degraph$analysis$asm$Analyzer$$analyze$1(Analyzer.scala:32)
    at de.schauderhaft.degraph.analysis.asm.Analyzer$$anonfun$analyze$1$$anonfun$apply$1.apply(Analyzer.scala:50)
    at de.schauderhaft.degraph.analysis.asm.Analyzer$$anonfun$analyze$1$$anonfun$apply$1.apply(Analyzer.scala:49)
    at scala.collection.immutable.HashSet$HashSet1.foreach(HashSet.scala:322)
    at scala.collection.immutable.HashSet$HashTrieSet.foreach(HashSet.scala:978)
    at de.schauderhaft.degraph.analysis.asm.Analyzer$$anonfun$analyze$1.apply(Analyzer.scala:49)
    at de.schauderhaft.degraph.analysis.asm.Analyzer$$anonfun$analyze$1.apply(Analyzer.scala:46)
    at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33)
    at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186)
    at de.schauderhaft.degraph.analysis.asm.Analyzer$.analyze(Analyzer.scala:46)

Filter node content

When collapsed two group nodes might have multiple (possibly hundreds of links between them. This is rather irritating.

It should be possible to collapse all these links into one link (possibly two, one in each direction) for nodes specified as a parameter.

As a side effect this should make handling of the graph much faster on all stages.

Scrolling and Zooming

There should be a way of easily scroll and zoom the display of nodes, so one can get a view of all the nodes one is interested in.

Comments in config file

The config files are a great way to share and document design aspects. I imagine pushing my config file with different predefined layers and comments within them to github. That is why comments in the config files would be neat. :)

question: filtering by regular expression

Greetings! I am trying out degraph and cannot get it to filter a graph by regular expression. For example if I use something like

-i Test
-i Name
-i Event

Then the resulting graph is empty. I know there are classes with those words in them. I'd really like to do by full name, including package, like this

-i com.acme.gui.events

Export information about found dependencies

If there's a way to put out information about a scan of a project, for example

  • number of dependencies throughout the projects
  • number of cyclic dependencies (I know that may be a hard problem, but sure there are metrics to estimate that)
  • some derived metric of the health of the project

degraph could be used in a CI-server to monitor the dependency-health over time.

ArrayIndexOutOfBoundsException when categorising classes

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0 at de.schauderhaft.degraph.slicer.InternalClassCategorizer$.apply(InternalClassCategorizer.scala:13) at de.schauderhaft.degraph.slicer.InternalClassCategorizer$.apply(InternalClassCategorizer.scala:9) at de.schauderhaft.degraph.slicer.MultiCategorizer$.de$schauderhaft$degraph$slicer$MultiCategorizer$$next(MultiCategorizer.scala:18) at de.schauderhaft.degraph.slicer.MultiCategorizer$$anonfun$combine$1.apply(MultiCategorizer.scala:11) at de.schauderhaft.degraph.slicer.MultiCategorizer$$anonfun$combine$1.apply(MultiCategorizer.scala:10) at de.schauderhaft.degraph.graph.Graph.unfilteredAdd(Graph.scala:62) at de.schauderhaft.degraph.graph.Graph.add(Graph.scala:59) at de.schauderhaft.degraph.graph.Graph.connect(Graph.scala:74) at de.schauderhaft.degraph.analysis.asm.GraphBuildingClassVisitor$$anonfun$visit$1.apply(GraphBuildingClassVisitor.scala:71) at de.schauderhaft.degraph.analysis.asm.GraphBuildingClassVisitor$$anonfun$visit$1.apply(GraphBuildingClassVisitor.scala:71) at scala.collection.immutable.HashSet$HashSet1.foreach(HashSet.scala:322) at scala.collection.immutable.HashSet$HashTrieSet.foreach(HashSet.scala:978) at de.schauderhaft.degraph.analysis.asm.GraphBuildingClassVisitor.visit(GraphBuildingClassVisitor.scala:71) at org.objectweb.asm.ClassReader.accept(Unknown Source) at org.objectweb.asm.ClassReader.accept(Unknown Source) at de.schauderhaft.degraph.analysis.asm.Analyzer$.de$schauderhaft$degraph$analysis$asm$Analyzer$$analyze$1(Analyzer.scala:26) at de.schauderhaft.degraph.analysis.asm.Analyzer$$anonfun$analyze$1$$anonfun$apply$1.apply(Analyzer.scala:36) at de.schauderhaft.degraph.analysis.asm.Analyzer$$anonfun$analyze$1$$anonfun$apply$1.apply(Analyzer.scala:35) at scala.collection.immutable.Set$Set1.foreach(Set.scala:79) at de.schauderhaft.degraph.analysis.asm.Analyzer$$anonfun$analyze$1.apply(Analyzer.scala:35) at de.schauderhaft.degraph.analysis.asm.Analyzer$$anonfun$analyze$1.apply(Analyzer.scala:32) at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33) at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186) at de.schauderhaft.degraph.analysis.asm.Analyzer$.analyze(Analyzer.scala:32) at de.schauderhaft.degraph.configuration.Configuration.createGraph(Configuration.scala:31) at de.schauderhaft.degraph.app.Degraph$.main(Degraph.scala:23) at de.schauderhaft.degraph.app.Degraph.main(Degraph.scala)

Aggregation of contained nodes

If a closed node contains other nodes, the dependencies of those contained node are handled like dependencies of the containing node.

Performance is not satisfactory

When forgetting to filter out java_.* or scala._* degraph runs for ever.

a Quick glance in jvisualvm suggests that it is using up lots of it's CPU time in

scalax.collection.GraphBase$InnerNodeLike$class.equals()

This makes me think, it should be possible to increase performance a lot.

Things to do:

  • setup a project with some libs to analyse for performance measurements
  • further analysis of the hotspot mentioned above: Why does this get called so often/ takes so long?
  • make it faster. Possibly by dumping ScalaGraph

Layouting of nodes

All nodes get properly arranged, so it is easy to understand the dependency structure.

  • When the displayed dependencies build an acyclic directed graph all dependencies are directed from left to right.
  • nodes inside an opened node get arranged so that they are as close together as possible, so that the enclosing opened node, becomes as small as possible, without violating a rule above.
  • all nodes, especially opened nodes don't overlap each other (with the obvious exception that nodes contained in other nodes are displayed in/on top of those nodes.

Provide a Gradle plugin

Continuing the discussion from junit-team/junit5#483:

It would be cool if Degraph came with a Gradle plugin that allowed users to check their Java code for violations. I did a very rough sketch of a Degraph task in the JUnit repository.

Ideally the plugin should have the following characteristics:

  • Users have a simple way to define slicings and constraints (doesn't need to be a Groovy DSL. Gradle's checkstyle plugin uses checkstyle.xml config for instance)
  • for each Java sourceSet, a Degraph check task is automatically created
  • the Degraph check tasks are hooked into the Java plugin's check task
  • the plugin works with future version of Degraph without needing to be upgraded itself
  • The plugin does not depend on Degraph directly. Instead it resolves it at runtime and invokes it in a forked process. This way it does not pollute the plugin classpath (ASM is especially problematic, as so many tools depend on so many different versions of it)
  • (If Degraph is extensible?) users can write custom extensions in the project being checked

The DSL could be as simple as this, assuming the configuration is written in an XML file. The rest is wired up automatically.

degraph {
  version = '1.0.0' //use some hardcoded default if the user doesn't specify
  configuration = "$rootDir/gradle/config/degraph.xml"
}

The plugin and task should be pretty straightforward. The only thing I'm not sure about is: Is there already a configuration file format that allows users to specify slicings and constraints? Is there a class with a main method that fails if violations are found?

Show all circles

Degraph shows currently a single circular dependency per slice type. This should be fixed.

The original plan was to implement the 110% solution which only marks an almost minimal set of edges neccessary to break for breaking all circles, but this will take some time.

As an intermediate solution the following approach should be used:

  • find a circle and mark it.
  • remove the dependencies making up that circle from the graph representation
  • continue at the beginning until no further circle is found.

source as category

It should be possible to distinguish nodes, i.e. to group and filter them by the source they come from (jar-file or classpath entry)

Include / Exclude Filters should use the same Ant Like Syntax

include/exclude filters in a configuration currently use a different semantic (simple 'in') than the slice configurations, which use a Ant like pattern matching language (using * and **) this should be unified to both using the Ant like syntax.

Analyze Spring Context Files

Dependencies in a Spring Context files should be included in the dependency analysis.

Tasks

  • Spring beans should appear as Nodes in diagrams, similar to classes
  • Spring beans should be contained inside nodes representing the context files similar how packages contain classes
  • Spring beans should have a dependency to the class they are implemented by
  • Spring beans should have a dependency to other beans referenced as setter injection parameter
  • Spring beans should have a dependency to other beans referenced as constructor injection parameter
  • Spring beans with the same name or id from different files should be rendered as separate nodes
  • If a Spring bean is dependend on a bean that is not unique a dependency should be considered to all beans with the same name or id
  • add an configuration option to disable Spring context file analysis as a command line parameter
  • add an configuration option to disable Spring context file analysis in the configuration file
  • all Spring context files should get considered that are in directories, subdirectories or jar files of the 'classpath'

printTo should always print

Following the documentation I expected that PrintTo always prints a graph. However if there was no error I didn't get a grapml-file.

Display all toplevel node

This is the first of a group of tasks that will result in a gui that is suitable to replace yed for 95% of all use cases for Degraph

All toplevel nodes shall be displayed

  • a method can be called which takes a Graph (actually an interface that will get extracted from Graph as a parameter and displays GUI.
  • all top level nodes are visible, and they don't overlap
  • each node displays it's name
  • there is a way of closing the GUI which actually ends the application (no threads keep running)

Multiple Configurations

It should be possible to have multiple configurations in one file, resulting in multiple output files.

This should allow for example to create an overview diagram + a set of detail diagrams in one go.

Check should write warnings when slicing or allow don't match

When writing checks it is easy to add typos to withSlicing() and allow().

It would be helpful for me

  • if degraph would issue a warning when pattern (either anonymous or named) doesn't match any class
  • if an allow references a name that doesn't exist

Thanks!

Is there any complex example of allowDirect

I'm trying at https://github.com/opensource21/sze/tree/degraph to make a dependency test for one of my projects. There following slices which should have DirectAccess job, frontend -> service -> dao.
Furthermore the are the slices config, security and model, constraints, util.
config and security are not a problem. However I have model -> constraints -> util and model ->util which is OK for me. Furthermore job, frontend, service and dao could be reference model and util. I have no idea how to configure this with allowDirect. My main concern is that job/frontend call dao directly without using a service.

Any suggestions?

Display dependencies between nodes

If A depends on node B there should be an arrow from node A to node B

The arrow can be rendered as a straight line, no fancy avoiding crossing other arrows or nodes.

Nodes not displayed, because they are inside other collapsed nodes get ignored for now.

Could we start yed directly after creating a graph

If one provides the installation path of yed, it should be possible to start yed directly after finishing degraph.

Just a simple instruction on how to do that by changing the bat/sh script would be an easy solution.

Create a basic DSL for configuration

configuration of groups with regular expressions (which have to use heavy escaping in the shell) is cumbersome, and useless for more then trivial cases.

There should be a little DSL that allows to configure the graph.

I know I have cycle and I want to include it in test.

Hi

I have 4 packages:

example.a, example.b, example.c, example.d

With cycle between a and c and that is ok.

My test:

assertThat(
classpath()
.noJars()
.including("example.**")
.allow(oneOf("example.a", "example.c"), oneOf("example.a", "example.c"))
, is(violationFree()))

fails with:

java.lang.AssertionError: 
Expected: is "de.schauderhaft.degraph.check.Check$$anon$1"
     but: Configuration{classpath = [snip]
includes = example.**
constraints = no cycles
} yields the following constraint violations: [Package](no cycles):
    example.a -> example.c
    example.c -> example.a

I've also tried adding .withSlicing("module", "example.(*).**") but I'm still getting assertion error.
Is there a way to configure degraph for that kind of situation?

Arranging of edges

Edges get arrange in a way that limits the amount of crossing of edges and nodes.

  • No edge crosses a nodes except when the edges goes from/to a node contained in that node
  • Reasonable effort should be made to avoid crossing of edges
  • Edges should be mainly horizontal. Vertical distance should be preferrable coverd at the start and end of an edge, as opposed to the middle.
  • Edges go diagonal up or down, but not vertical
  • A single edge should if possible not go up and down. Even if this means it has to cross more other edges.

It is OK to move nodes in order to obtain these goals.

I have no idea if all these goals can be achieved ... guess we need to dos some exploration.

Type annotations cause RuntimeException

Hi Jens,

I'm trying to get your tool running, because it looks very useful to me. However, a very simple test like

assertThat(classpath(), is(violationFree()));

results in the following exception

java.lang.RuntimeException
    at org.objectweb.asm.MethodVisitor.visitTypeAnnotation(Unknown Source)
    at org.objectweb.asm.ClassReader.b(Unknown Source)
    at org.objectweb.asm.ClassReader.accept(Unknown Source)
    at org.objectweb.asm.ClassReader.accept(Unknown Source)
    at de.schauderhaft.degraph.analysis.asm.Analyzer$.de$schauderhaft$degraph$analysis$asm$Analyzer$$analyze$1(Analyzer.scala:18)
    ...

It seems like asm has problems handing Java 8 type annotations that I'm using in my code.

Allow wildcards with allow

I have a setup where there are multiple adapters. The list of adapters is growing, and they shouldn't depend on each other.

It would be nice if degraph would allow wildcard with allow like this...

classpath
    .withSlicing("layer", "de.schauderhaft.app.(adapter.*).**")
        .allow(oneOf("adapter.*"))

... instead of listing all current adapters as inside of oneOf()

Thanks!

OutOfMemoryError when trying to generate a graph for a big project

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at scala.xml.Text$.apply(Text.scala:37)
at scala.xml.UnprefixedAttribute.(UnprefixedAttribute.scala:27)
at de.schauderhaft.degraph.writer.GroupNodeWriter$.apply(Writer.scala:77
)
at de.schauderhaft.degraph.writer.NodeWriter$.apply(Writer.scala:60)
at de.schauderhaft.degraph.writer.GroupNodeWriter$$anonfun$apply$2.apply
(Writer.scala:99)
at de.schauderhaft.degraph.writer.GroupNodeWriter$$anonfun$apply$2.apply
(Writer.scala:99)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike
.scala:245)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike
.scala:245)
at scala.collection.immutable.Set$Set1.foreach(Set.scala:79)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:245)

    at scala.collection.AbstractSet.scala$collection$SetLike$$super$map(Set.

scala:47)
at scala.collection.SetLike$class.map(SetLike.scala:92)
at scala.collection.AbstractSet.map(Set.scala:47)
at de.schauderhaft.degraph.writer.GroupNodeWriter$.apply(Writer.scala:99
)
at de.schauderhaft.degraph.writer.NodeWriter$.apply(Writer.scala:60)
at de.schauderhaft.degraph.writer.GroupNodeWriter$$anonfun$apply$2.apply
(Writer.scala:99)
at de.schauderhaft.degraph.writer.GroupNodeWriter$$anonfun$apply$2.apply
(Writer.scala:99)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike
.scala:245)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike
.scala:245)
at scala.collection.immutable.HashSet$HashSet1.foreach(HashSet.scala:322
)
at scala.collection.immutable.HashSet$HashTrieSet.foreach(HashSet.scala:
978)
at scala.collection.immutable.HashSet$HashTrieSet.foreach(HashSet.scala:
978)
at scala.collection.immutable.HashSet$HashTrieSet.foreach(HashSet.scala:
978)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:245)

    at scala.collection.AbstractSet.scala$collection$SetLike$$super$map(Set.

scala:47)
at scala.collection.SetLike$class.map(SetLike.scala:92)
at scala.collection.AbstractSet.map(Set.scala:47)
at de.schauderhaft.degraph.writer.GroupNodeWriter$.apply(Writer.scala:99
)
at de.schauderhaft.degraph.writer.NodeWriter$.apply(Writer.scala:60)
at de.schauderhaft.degraph.writer.NodeWriter$.apply(Writer.scala:55)
at de.schauderhaft.degraph.writer.NodeWriter$.apply(Writer.scala:50)
at de.schauderhaft.degraph.writer.Writer$$anonfun$toXml$1.apply(Writer.s
cala:37)

How to check for unidirectional dependency

I have three packages below coffee.synyx.autoconfigure for example and want to ensure that they do not use each other.

coffee.synyx.autoconfigure.discovery
coffee.synyx.autoconfigure.logging
coffee.synyx.autoconfigure.security

how do I write a unit test to test this? I only found documentation to say e.g. that logging is allowed to use security but not the other way. That would be done with allow() or allowDirect(). But how do I write a test that says nobody is allowed to use the other ones?

Show internal class structure

As support for refactoring large classes it might be interesting to visualize the internal structure of classes.

Dependency Finder should be able to provide the necessary information.

This would have to be pluggable / configurable, since when you look at hundreds of classes, you don't want a node for every single field/method/parameter.

Therefore it also relates to issues #14 and #15 which also would modify the thing thats appear in Degraph as a node.

Collapse / Uncollapse nodes

It should be possible to 'open' nodes that contain other nodes.

  • all nodes containing other nodes, can be opened
  • nodes not containing other nodes, can not be opened
  • open nodes automatically become large enough so all nodes inside that node get properly displayed.
  • all nodes get moved around so no node hides any part of any other node.
  • the dependencies of all visible nodes get properly displayed.

Ignore annotation

It would be helpful to be able to exlude Annotation-classes in checks such as the jaxb XmlSeeAlso.

@XmlSeeAlso({ A1.class, A2.class })
public abstract class A {}
public class A1 extends A {}
public class A2 extends A {}

Release with customClasspath change

There has been no release since the customClasspath method was introduced. This makes it pretty much impossible to use degraph in a Gradle build for instance. Could you please push a release with the latest changes? :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.