Repository navigation
Identify and name slices by their captures, like ArchUnit - #515
Draft
alexanderlinne wants to merge 1 commit into
Draft
alexanderlinne wants to merge 1 commit into
alexanderlinne wants to merge 1 commit into
Conversation
alexanderlinne
added this pull request to stack #514
October 24, 2026 19:47
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## nest-slices-in-packages-option #515 +/- ##
==================================================================
+ Coverage 86.56% 86.67% +0.10%
==================================================================
Files 261 261
Lines 12766 12801 +35
Branches 1245 1249 +4
==================================================================
+ Hits 11051 11095 +44
+ Misses 1368 1359 -9
Partials 347 347 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
A slice was identified by its name, a single string, and named after
what the pattern captured with nothing to mark it as a slice. A custom
SliceAssignment had no way to say what its slice consists of, and a
slice name read like a namespace.
Identify a slice by its parts, as ArchUnit's SliceIdentifier does: for
a slice pattern, the values its capture groups captured, in group order.
SliceIdentifier.Parts holds them, and equality, hash code, CompareTo and
therefore the grouping in SliceAssignment.Apply compare the parts (and
Ignored) alone. The matcher still captures a single value per type, so
every pattern slice has one part and groups exactly as before.
SliceIdentifier.Of(IEnumerable<string>) creates a slice with several
parts; Of(string) is the same slice as Of(new[] { part }).
Name every slice after its parts like ArchUnit's default: "Slice "
followed by the parts joined with " - ":
App.(*) App.Orders Slice Orders
App.(**) App.Orders.Web Slice Orders.Web
Of(new[] { "Orders", "Http" }) Slice Orders - Http
The prefix keeps a name from being mistaken for a namespace. It applies
to every slice, including SlicedBy and custom SliceAssignments, and it
is what failure messages and flat diagrams show. Nested diagrams draw
slices under their qualified names, so they don't change.
SliceIdentifier no longer derives from StringIdentifier: the parts are
all that identifies a slice. Violation stores need a string key, which
SlicesShould takes from the slice's name when it reports a violation, so
a store holds what failure messages show, e.g. "Slice Orders", as
ArchUnit's stores, which keep violation messages, do.
Hand-built parts that contain " - " can share a name, and thus a key,
with another slice: Of(new[] { "A - B" }) and Of(new[] { "A", "B" }) are
different slices, both named "Slice A - B". Parts captured by a pattern
never contain " - ", and ArchUnit has the same limitation. The exporter
rejects two such slices in one diagram, as they would be drawn under the
same name.
The guide's "Cycle Rule" section becomes "Slice Rules", with how slices
are named and frozen, and the NotDependOnEachOther rule.
Breaking changes:
- Slices are named "Slice ..." from their parts, which changes every
slice failure message and flat slice diagram label.
- Frozen slice violations are stored by the slice's name, so stores
written before no longer match and have to be regenerated.
- New are SliceIdentifier.Parts and SliceIdentifier.Of(IEnumerable).
- SliceIdentifier no longer derives from StringIdentifier, so its
Identifier field is gone, and ToString() returns the slice's name.
Signed-off-by: Alexander Linne <alexander.linne@tngtech.com>
alexanderlinne
force-pushed
the
identify-slices-by-captures
branch
from
October 24, 2026 20:10
5b1ca9a to
676c0b6
Compare
alexanderlinne
marked this pull request as draft
October 25, 2026 19:39
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A slice is identified by its name, a single string, and named after what the pattern captured, with nothing to mark it as a slice:
SliceAssignmenthas no way to say what its slice consists of.This PR settles identity and naming while
main's matcher still captures exactly one value per type, so the PR changes only names, not which types form a slice. PR 4 then only has to produce several values.What changes
Identity. A slice is identified by its parts, as
SliceIdentifieris in ArchUnit ("equal if and only if their parts are equal"). For a slice pattern, the parts are the values its capture groups captured, in group order.SliceIdentifier.Partsholds them, and the following compare the parts (andIgnored) alone:CompareTo,SliceAssignment.Apply.SliceIdentifier.Of(IEnumerable<string>)creates a slice with several parts;Of(string)is the same slice asOf(new[] { part }). Every pattern slice still has one part here, so every rule groups exactly as before.Names. Every slice is named after its parts like ArchUnit's default,
"Slice " + string.Join(" - ", Parts):App.(*)overApp.OrdersOrdersSlice OrdersApp.(**)overApp.Orders.WebOrders.WebSlice Orders.WebOf(new[] { "Orders", "Http" })Slice Orders - HttpThe
Sliceprefix keeps a name from being mistaken for a namespace. It is ArchUnit's default, so messages read the same in both libraries. A laterNamingSlices("$2 of $1")would replace the same thing ArchUnit'snamingSlicesreplaces. The name applies to every slice, includingSlicedByand customSliceAssignments, and it is what failure messages and flat diagrams show. Nested diagrams draw slices under their qualified names (PR 2), so they don't change:Every changed snapshot changes only labels and aliases; no slice and no arrow differs. Names with spaces aren't valid PlantUML ids, so these slices get an alias such as
Slice_Slice1. That, and bracketing component names in every arrow, comes from the fixes already merged in #507–#510.Freezing.
SliceIdentifierno longer derives fromStringIdentifier: the parts are all that identifies a slice. Violation stores need a string key, whichSlicesShouldtakes from the slice's name when it reports a violation, e.g.Slice Orders. A store thus holds what failure messages show, as ArchUnit's stores do, which keep violation messages.Until now, a slice was stored by its bare name, e.g.
Orders, so existing stores of slice rules no longer match and have to be regenerated. Since this PR changes every slice failure message anyway, and PR 4 changes which slices some rules produce, the stores are re-frozen once, together with the rest of the stack. The stores inFreezeTestsare updated accordingly.Hand-built parts that contain
-can share a name, and thus a key, with another slice:Of(new[] { "A - B" })andOf(new[] { "A", "B" })are different slices, both namedSlice A - B. Parts captured by a pattern never contain-, and ArchUnit has the same limitation. The exporter rejects two such slices in one diagram, as they would be drawn under the same name (PR 2).Guide. The "Cycle Rule" section becomes "Slice Rules": how slices are named, how they are frozen, and the
NotDependOnEachOtherrule next toBeFreeOfCycles. Like the code, the guide describes slices on their own terms and doesn't refer to ArchUnit.Breaking changes
Slice …after their parts, which changes every slice failure message and flat slice diagram label.SliceIdentifier.PartsandSliceIdentifier.Of(IEnumerable<string>).SliceIdentifierno longer derives fromStringIdentifier, so itsIdentifierfield is gone, andToString()returns the slice's name.Not in this PR
An ArchUnit-style
NamingSlices("$2 of $1"), so that users can choose slice names themselves. It would be a non-breaking addition: slices are identified by their parts, not their names, and the exporter already rejects two slices that would be drawn under the same name. As in ArchUnit, renaming the slices of a frozen rule would mean re-freezing it.How the image was made
It renders the
BuildUmlBySlices_SingleAsterisksnapshot at PR 2 and at this PR, with PlantUML 1.2025.4 and Graphviz, with the remote!includeof C4-PlantUML replaced by PlantUML's bundled copy (!include <C4/C4_Container>).