Skip to content

Slices don't differentiate between (*) and (**) making top-level cycle checks impossible #468

Description

@enolive

if I understand the original docs of ArchUnit correctly, there should be a difference between (*) and (**).

  • (*) should target the package
  • (**) should target the package and its sub packages

See also https://www.archunit.org/userguide/html/000_Index.html#_slices

this is however not how the dotnet port of ArchUnit behaves.

If I specify sth. like CycleDemo.(*) I'd expect it to only check cycles on the top-level

so

  • Domain -> Db -> Domain should be detected
  • Domain.Beers -> Domain.Wine -> Domain.Beers should not be detected

it will detect however both cycles effectively behaving like (**)

"Slices matching "CycleDemo.(*)" should be free of cycles" failed:
	Cycle found:
Db -> Domain
	CycleDemo.Db.ViolatingRepository -> CycleDemo.Domain.Service
Domain -> Db
	CycleDemo.Domain.Service -> CycleDemo.Db.Repository

	Cycle found:
Domain.Beers -> Domain.Wines
	CycleDemo.Domain.Beers.Beer -> CycleDemo.Domain.Wines.Wine
Domain.Wines -> Domain.Beers
	CycleDemo.Domain.Wines.Wine -> CycleDemo.Domain.Beers.Beer

I compared it with the behavior of the Java implementation and it works as documented.

Architecture Violation [Priority: MEDIUM] - Rule 'slices matching 'demo.(*)' should be free of cycles' was violated (1 times):
Cycle detected: Slice db -> 
                Slice domain -> 
                Slice db
  1. Dependencies of Slice db
    - Field <demo.db.ViolatingRepository.service> has type <demo.domain.Service> in (ViolatingRepository.java:0)
    - Constructor <demo.db.ViolatingRepository.<init>()> calls constructor <demo.domain.Service.<init>()> in (ViolatingRepository.java:6)
  2. Dependencies of Slice domain
    - Field <demo.domain.Service.repository> has type <demo.db.Repository> in (Service.java:0)
    - Constructor <demo.domain.Service.<init>()> calls constructor <demo.db.Repository.<init>()> in (Service.java:6)

If I look inside the SliceRuleInitializer.cs it confirms my suspicion. A single asterisk will be replaced with a double asterisk (line 81):

var countOfSingleAsterisk =
pattern.Split(new[] { "(*)" }, StringSplitOptions.None).Length - 1;
pattern = pattern.Remove(indexOfAsteriskInPattern) + "(**).";

Am I missing something?

ping me if I should upload my reproduction projects to GitHub!

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/bugCategorizes issue or PR as related to a bug.triage/acceptedIndicates an issue or PR is ready to be actively worked on.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions