Best structure to prevent a given cycle import

I have structure doubt about a complex package named repositories, there reside all my data access and the structs that i return after i run my queries (pagination, facets, results, etc…).

But, my inner packages, the ones that actualy do the query depends on the structs on the root level repositories, but this gives me a cycle import.

What is the best approach for this situation?

  • Move all structs to a new package, so everyone can access
  • Don’t know why, but this seems weird for me, but it is the easiest
  • Duplicate the struct in the packages and then copy the data from struct to struct
  • I like this approach, but involves too much programming and copy of data
  • Use a more flat structure like https://github.com/olivere/elastic
  • Messy, no? But works

Structure:

 repositories
 β”œβ”€β”€ config.go
 β”œβ”€β”€ dataaccess
 β”‚   └── item
 β”‚       β”œβ”€β”€ elasticsearch
 β”‚       β”‚   β”œβ”€β”€ config.go
 β”‚       β”‚   β”œβ”€β”€ elasticsearch.go
 β”‚       β”‚   β”œβ”€β”€ error.go
 β”‚       β”‚   β”œβ”€β”€ mapping.go
 β”‚       β”‚   └── transform.go
 β”‚       └── solr
 β”‚       β”‚   β”œβ”€β”€ config.go
 β”‚       β”‚   β”œβ”€β”€ solr.go
 β”‚       β”‚   β”œβ”€β”€ error.go
 β”‚       β”‚   β”œβ”€β”€ mapping.go
 β”‚       β”‚   └── transform.go
 β”œβ”€β”€ databases
 β”‚   β”œβ”€β”€ elasticsearch
 β”‚   β”‚   β”œβ”€β”€ config.go
 β”‚   β”‚   β”œβ”€β”€ elasticsearch.go
 β”‚   β”‚   └── errors.go
 β”‚   └── solr
 β”‚       β”œβ”€β”€ config.go
 β”‚       β”œβ”€β”€ errors.go
 β”‚       └── solr.go
 β”œβ”€β”€ entities.go
 β”œβ”€β”€ errors.go
 β”œβ”€β”€ item.go
 β”œβ”€β”€ provider.go
 └── repositories.go

I would just move the shared structs into their own package. Those data structures probably do not need to know anything about how they are used, they just need to be defined and shared.

2 Likes

The go way is to package based on what the code does first. I would decide which package is the origin or main user of these structs, then move them in to a subpackage.
An example:

root/
|--- busines_logic
|    |---shared_structs
|
|--- backend
|--- frontend
1 Like

This means you’ve already made a bad decision :smile:. PS. I’ll try to be quick here, hence no pleasantries.

Folder (and all other) structures should follow what you value. The higher the value, the more prominent it should be. Does anyone, except programmers, care whether you have a repository in your code or not?

For example:

A PageRepository is not valuable, however a Page is. A UserDAO is not valuable, but a User is.

This suggests your main folder structure should contain user and page… Then… what’s important about a user…? Obviously, all the ID-s, names, information. And also, they must be stored β€œsomewhere”, hence you should have an interface user.Repo. Something needs to implement it β†’ user/userrepo-solr…

Let’s now assume that you’ve also need a page/pagerepo-solr. To reduce duplication you can put the solr implementations into package db/solr. e.g. solr.Users, solr.Pages …

Of course depending on what you value and what you are building. user and page might not be that important. In a issue tracker, you could have tracker.User, and not a separate user package.

This approach will make sure that you have things organized by what is important – and not by form.

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.