Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slices across different base packages #685

Open
whiskeysierra opened this issue Oct 1, 2021 · 4 comments
Open

Slices across different base packages #685

whiskeysierra opened this issue Oct 1, 2021 · 4 comments

Comments

@whiskeysierra
Copy link

I'd like to cut slices in the following package structure:

  • application
    • a
      • http
      • grpc
    • b
      • kafka
      • sns
  • domain
    • api
      • a
      • b
    • logic
      • a
      • b
    • spi
      • c
      • d
  • infrastructure
    • c
      • memory
      • postgres
    • d
      • file
      • s3

Slices that I'd like to have:

  1. application.a.http, application.a.grpc, domain.api.a and domain.logic.a
  2. application.b.kafka, application.b.sns, domain.api.b and domain.logic.b
  3. domain.spi.c, infrastructure.c.memory and infrastructure.c.postgres
  4. domain.spi.d, infrastructure.d.file and infrastructure.d.s3

If I could specify multiple package identifiers (when calling slices().matching(packageIdentifier)), then I would use (slice 1+2):

"..application.(*).*.."
"..domain.api.(*).."
"..domain.logic.(*).."

or respectively (slice 3+4):

"..domain.spi.(*).."
"..infrastructure.(*).*.."

Is there a readable way to express that with a single package identifier expression?

Alternatively I'm currently using this (Kotlin) implementation that supports multiple package identifiers:

private fun SlicesRuleDefinition.Creator.matching(vararg packageIdentifiers: String) =
    assignedFrom(MultiPackageMatchingSliceIdentifier(*packageIdentifiers))

private class MultiPackageMatchingSliceIdentifier(private vararg val packageIdentifiers: String) : SliceAssignment {
    override fun getIdentifierOf(javaClass: JavaClass): SliceIdentifier =
        packageIdentifiers
            .map {
                PackageMatcher.of(it)
                    .match(javaClass.packageName)
                    .map(TO_GROUPS)
                    .orElse(emptyList())
            }
            .filter { it.isNotEmpty() }
            .let { it.flatten() }
            .let { parts -> identifierOf(parts) }

    private fun identifierOf(parts: List<String>?) =
        if (parts.isNullOrEmpty()) ignore() else of(parts)

    override fun getDescription(): String {
        return packageIdentifiers.joinToString(", ") { "'$it'" }
    }
}
@codecholeric
Copy link
Collaborator

I don't know if I completely understand your example, because e.g. "..application.(*).*.." would not give you slices application.a.http and application.a.grpc but only application.a and application.b, no?

The packageIdentifier API at the moment works if a) all your relevant packages have the same level of nesting (e.g. relevant packages are always level 3 and 4) and b) you don't need to ignore any of the matched packages.

Then you could for example also do

com.myapp.(*).(*).(*)..

(given com.myapp is your root package) and match your example to derive pretty much exactly the slices you want. The first asterisk would match application, domain, infrastructure, the second the first subpackage, etc. A slice would be defined by exactly the same triple.
If your structure is not so homogeneous, then so far you actually have to do it the SliceAssignment way that you have already found. We could add an API for multiple patterns, but I'm not sure yet, if it is really useful for real life use cases. My fear would be that it is still too weak for most cases and users will have to fall back onto SliceAssignment anyway.

@whiskeysierra
Copy link
Author

because e.g. "..application.(*).*.." would not give you slices application.a.http and application.a.grpc but only application.a and application.b, no?

What I wanted to say there was:

Slices that I'd like to have:

  1. Slice a, containing packages: application.a.http, application.a.grpc, domain.api.a and domain.logic.a
  2. Slice b, containing packages: application.b.kafka, application.b.sns, domain.api.b and domain.logic.b
  3. Slice c, containing packages: domain.spi.c, infrastructure.c.memory and infrastructure.c.postgres
  4. Slice d, containing packages: domain.spi.d, infrastructure.d.file and infrastructure.d.s3

@codecholeric
Copy link
Collaborator

Ah, okay, I see. You're right, at the moment the simple API works best for the cases where the business cuts are toplevel and the technical cuts are subpackages. For the other way round, I think the only way at the moment is SliceAssignment, which you already found.
Maybe it would be good to support multiple patterns out of the box, because that would cover exactly the case where it is a consistent structure, but technical cuts toplevel 🤔

@Pfoerd
Copy link
Contributor

Pfoerd commented Oct 22, 2021

Hi. If I understand the question correctly this could benefit from the feature request I made some times ago: #662 . maybe it makes sense to look at both topics together.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants