TNG / ArchUnit

A Java architecture test library, to specify and assert architecture rules in plain Java
http://archunit.org
Apache License 2.0
3.18k stars 288 forks source link

PlantUmlParser should allow for dependencies between nested components #1179

Open piterhub opened 11 months ago

piterhub commented 11 months ago

At the moment using syntax like

@startuml
component EventProcessing <<..eventprocessing..>> {
    component EventStore <<..eventstore..>> {
    }
    component Movements <<..movements..>> {
       component ProjectionCreator <<..projectioncreator..>>
    }
}

Movements -> EventStore
@enduml

will lead to

Caused by: com.tngtech.archunit.library.plantuml.rules.IllegalDiagramException: There is no Component with name or alias = 'Movements'. Components must be specified separately from dependencies.

We should make this possible, since it is valid syntax and can provide visual guidelines.

codecholeric commented 8 months ago

Hmm, I'm not sure about this 🤔 I've already stated in other cases that ArchUnit never set out to support the full set of PlantUML syntax. Because, doing so would be quite complex and effectively demand reimplementing a full parser. Right now the supported subset is quite limited, it uses simple regex parsing and that works okay for this little subset. If we'd set out to support all sorts of complex cases I'm not sure where we would end up at 🤔 In particular, I'm not sure the current implementation is sophisticated enough for that...

Besides, there is also the question of how this would really look like. Take your example, the stereotypes don't follow any hierarchy, i.e. if we would just support parsing components from nested places, then

// this class wouldn't be allowed to depend on anything
com.app.eventprocessing.EntryPoint

// this class would be detected as residing in component EventStore even though it's not in package eventprocessing
com.app.eventstore.EventStore

I think semantically nested components should inherit from their parent to make sense? But that can grow quite complex 🤔

@startuml
component EventProcessing <<..eventprocessing..>> {
    component EventStore <<..eventstore..>> {
    }
    component Movements <<..movements..>> {
       component ProjectionCreator <<..projectioncreator..>>
    }
}
component Messaging <<..messaging..>> {
  component Queue <<..queue..>>
}

Movements --> EventStore
ProjectionCreator --> EventStore
EventProcessing --> Queue
Movements --> Messaging
' now what may ProjectionCreator access? Messaging? Queue? Both?
@enduml

I'm not sure if that complexity in the end really helps in one diagram or if this shouldn't maybe be separate diagrams anyway 🤷

BTW: I think you can already do

package EventProcessing {
  [foo] <...>
  [bar] <...>
}