[almighty] Potential cyclic import issue in core.

Pranav Gore pgore at redhat.com
Wed Oct 12 02:36:12 UTC 2016


Thanks Konrad and Thomas for your time and inputs. I will create a Github
issue for tracking the changes made regarding layering.

@Thomas, thank you for elaborating the content with problem-solution. When
we say a system-layer., is it a bunch of related packages ? Or a layer is a
package.

>From the content above, what I understand is, we should have three main
system-related packages.
1. Interfaces (can import from infra)
2. Impl (Implementing interfaces from above package, should import from
interfaces)
3. Infra (All infrastructure related stuff e.g> Lifecycle,
GormTransactionSupport, must not import from interfaces/impl. In case, it
needs to import from interface, then we need to think is it really
infrastructure item)

4. Other business related packages e.g> remoteworkitem, account, login etc.

As a first step I will move Lifecycle to infra package (outside models).

@Thomas, is this (#110)
<https://github.com/almighty/almighty-core/issues/110> existing
architecture issue for the same ? If yes, I will update the same.



Thanks,
Pranav.


On Mon, Oct 10, 2016 at 3:03 PM, Thomas Mäder <tmader at redhat.com> wrote:

> Hi Pranav,
>
> I think your question touches upon an unresolved problem we have with our
> system layering. We have discussed this before when I wrote the first
> repository interfaces, but haven't really resolved the issue at the time.
> Let's look at what kinds of code we have:
>
>    - Repository interfaces
>    They define an interface for persistence in terms of application level
>    objects. The repository interfaces are not supposed to be gorm specific.
>    The idea is to be able to replace the implementation in tests and to avoid
>    coupling consumers to gorm.
>    - Repository implementations
>    They implement the repository implementations in a gorm-specific way.
>    They are free to convert app layer objects to a different form. For
>    example, we store work items as JSON in the db, which only has very few
>    data types (number, string, bool, etc.). The repository implementations
>    convert and validate the work item fields according to a given work item
>    type.
>    - Gorm support stuff
>    Stuff like models.Lifecycle, GormTransactionSupport, etc. This is
>    shared infrastructure for implementing repositories.
>
> Now that we have an overview, what problems can we run into and how do we
> solve them?
>
>    - Problem 1: shared repository infrastructure in models package
>    Solution: -> move infrastructure to a separate package
>    - Problem 2: false cycle
>    This problem can occur if we have multiple repositories in the same
>    package and have pairwise inverse dependencies: Think of two packages foo
>    and bar. We have repository foo.X depend on bar.Y and repository bar.M
>    depend on foo.N. Now we have a package cycle, but it is not a REAL cycle in
>    the code, we just co-located two independent repositories in the same
>    package
>    Solution: -> separate repositories into different packages
>    - Problem 3: real cycle
>    In real life, there ARE cases where cyclic dependencies make sense.
>    Imaging an event service and a logging service: the event service wants to
>    log things, and the logging service wants to send events. You usually need
>    some kind of setup protocol to get things going, but it's possible. The
>    problem in our case is that the compiler will complain if the two
>    repositories are in separate packages.
>    Solution: -> move the two repository interfaces to a common package
>    and only depend on the interface of the other repository in the
>    implementation.
>
> /Thomas
>
> On 10/08/2016 05:25 AM, Pranav Gore wrote:
>
> ​Hi Team Core,
>
> *Context/Background:-*
> I am working on #244
> <https://github.com/almighty/almighty-core/issues/244>. The task is to do
> `fields["system.creator"]=currentLoggedInUser`.
>
> There, I want to call a method Locate from package "Token" which returns
> current logged in user.
> While doing so I am facing cyclic import problem.
>
> *Reason:-* Work_item_repo is in package "models", it wants to call Locate
> method from package "token".
> But "token" pachakge imports "account" package and "account" package
> imports "models".
> Hence "models" package is unable to import "token" => cyclic dependency.
>
> *Debugging:-* When I was looking into "account" package, what exactly it
> needs from "models" package is ONLY "models.LifeCycle" and nothing else as
> of now.
>
> *Solutions:-* One quick possible/feasible solution is to put
> models.LifeCycle into different new package of its own, refactor and move
> on (IMO we should do this as first step).
>
> Another is to write a middleware(as mentioned in #244
> <https://github.com/almighty/almighty-core/issues/244>) for injecting
> loggedInUser which will be in package "middleware" and avoid cyclic import,
>
> Or redesigning to decouple models package into smaller chunks ?
>
> PFA- I have attached output of `go list -f` on account, models, token
> packages.
>
> Any input on this will be helpful :)
>
>
> Thanks,
> Pranav
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/almighty-public/attachments/20161012/d244ad6b/attachment.htm>


More information about the almighty-public mailing list