-
Notifications
You must be signed in to change notification settings - Fork 298
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
ArchCondition to ensure no upper package access incl. solution #151
Comments
This is an interesting idea, thanks for sharing 😃 I'm not sure if it should go into the core API though (since it feels more specific than the rest), or if it should be included as "library" (like the |
I think it's always kind of code smell to access parent packages as well as having cycles between packages. However looking forward to see it somewhere within your lib. Btw your lib is a great solution to ensure architecture. |
I don't know if it is always a code smell, for example what if my convention is to always have
Then Or did you actually mean real "access"? For real access this might be a different chapter, it's harder for me to imagine a valid use case there 😉. But then you need to check for I think your condition from above collects a little too many classes though, because for |
Both of you examples shouldn't lead to a violation, you are totally right.
It is a bug in my provided solution. I will adjust that next week.
…On Sat, 2 Mar 2019, 11:36 Peter Gafert, ***@***.***> wrote:
I don't know if it is always a code smell, for example what if my
convention is to always have
somebusiness
|-- InterfacePublicAPI
|-- internal
|-- PublicAPIImpl
Then PublicAPIImpl needs to depend on a parent package to implement the
public API InterfacePublicAPI. And I wouldn't call that convention code
smell, in the end it's often just a decision. So in my opinion it depends
😉 (which is why in many parts the only way is to provide a flexible tool
box that can be taylored to projects).
Or did you actually mean real "access"? For real access this might be a
different chapter, it's harder for me to imagine a valid use case there 😉.
But then you need to check for javaClass.getAccessesFromSelf() instead of
javaClass.getDirectDependenciesFromSelf().
I think your condition from above collects a little too many classes
though, because for com.Foo and com.Bar, it is true that
Foo.getPackageName().startsWith(Bar.getPackageName()) (equality must be
excluded).
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#151 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ADx6AjPOrAyMauZwWn42YRphwtPaWzQEks5vSlQ7gaJpZM4bYqUN>
.
|
In other words, what I want is to throw a validation only if a child
packages accesses any of its parent packages.
On Sat, 2 Mar 2019, 16:05 Bengt Brodersen, <bengt.brodersen@gmail.com>
wrote:
… Both of you examples shouldn't lead to a violation, you are totally right.
It is a big in my provided solution. I will adjust that next week.
On Sat, 2 Mar 2019, 11:36 Peter Gafert, ***@***.***> wrote:
> I don't know if it is always a code smell, for example what if my
> convention is to always have
>
> somebusiness
>
> |-- InterfacePublicAPI
>
> |-- internal
>
> |-- PublicAPIImpl
>
>
> Then PublicAPIImpl needs to depend on a parent package to implement the
> public API InterfacePublicAPI. And I wouldn't call that convention code
> smell, in the end it's often just a decision. So in my opinion it depends
> 😉 (which is why in many parts the only way is to provide a flexible
> tool box that can be taylored to projects).
>
> Or did you actually mean real "access"? For real access this might be a
> different chapter, it's harder for me to imagine a valid use case there
> 😉. But then you need to check for javaClass.getAccessesFromSelf()
> instead of javaClass.getDirectDependenciesFromSelf().
>
> I think your condition from above collects a little too many classes
> though, because for com.Foo and com.Bar, it is true that
> Foo.getPackageName().startsWith(Bar.getPackageName()) (equality must be
> excluded).
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <#151 (comment)>, or mute
> the thread
> <https://github.com/notifications/unsubscribe-auth/ADx6AjPOrAyMauZwWn42YRphwtPaWzQEks5vSlQ7gaJpZM4bYqUN>
> .
>
|
I've updated my initial solution. |
I think the line with
has to be changed to |
any progress on this? |
… this makes it impossible to extend an abstract class in an upper package due to the constructor call -> discussion Issue: #151 Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>
I've refactored the code to be compatible to Java 7 (sigh) and added an example so we can talk about it. The point I'm unsure about is that you can't extend abstract classes from a super package now either, since there is always a constructor call involved. |
Hi, actually that is a structure I want to avoid by this rule. From my perspective it is bad practice to have a structure where and implementation is part of the api package. |
@codecholeric I wonder if there is any blocker with this issue? |
@kkocel Sorry, there is no real blocker, I just lost track of it 😞 Consider for example
So However
would be allowed by the rule. So per se I don't see why case two is better than case one, maybe it is because it clearer identifies what is API and what is internal, but that also depends on my conventions. And what about a structure
I.e. my convention says I may only ever access the So all I'm saying is, that from my point of view it depends on your conventions. It might make sense to have such a rule, but it might also not make sense. I'm just saying an upper package access is not a code smell for me per se in all contexts. Also consider
That also would be forbidden even though Other than that, I still don't see any blocker to offer this as a library function 😉 The whole point of the library part is to offer rules that might be useful to a wider range of users, but they don't need to be useful in each and every project. Long story short, does this look good to you? (also you @qoomon) -> #352 |
Your second example shouldn't be allowed because the implementations access |
@codecholeric I agree that it's not the general rule. For my use case, it would be perfect though. |
@qoomon But I thought depending on an interface is fine? At least that's how I interpreted your comments #151 (comment) and #151 (comment) ? Thought it was okay to implement a top level interface in a sub-package? |
@codecholeric just to clarify - this rule will not be triggered on interfaces. However, it will fail in cases when inner classes are implementing a top-level abstract class |
@kkocel the rule as it is now, yes. But if the second example wouldn't be allowed, then interfaces in upper packages would not be allowed to be implemented, and I don't know if that is widely useful. Because that interfaces from higher packages are implemented in a lower one seems pretty common to me... |
@codecholeric sorry for my bad expression in #151 (comment) I meant no child should depend on any parrent |
@qoomon, but isn't this a super common use case and pattern? I think this would make the rule way less useful. In particular the example from my comment #151 (comment) |
@kkocel what is your take on this? Would you care about the distinction? Would it still match your use case if interfaces in parent packages could not be implemented anymore in sub-packages? |
@codecholeric I agree it is common, however it doesn't make it reasonable :-)
|
@codecholeric I use it in a slightly different context - in my Kotlin project I want to limit the scope of |
@qoomon Ah, now I get it, why didn't you explain in the beginning, that you had the splitting into archives in mind 🤣 But yes, then you need |
@codecholeric it works for me :) |
@codecholeric exactly, sorry for my bad description of my issue :-D. And thanks again for this great project |
Hie there,
would be great to have the following ArchCondition available out of the box like
noClasses().should().accessClassesThat().resideInAnUpperPackage().check(classes);
however I was not able to create a PR for this, so please feel free to just assimilate my solution below :-D
The text was updated successfully, but these errors were encountered: