-
Notifications
You must be signed in to change notification settings - Fork 2
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
NewService function has too many arguments #2
Comments
Supply it with an array of objects which implement an importable interface which has an import function. You can use reflection to find all your objects in repositories which implement it. You need to do the same thing on all of them, so they are not really distinct dependencies. Or have I missed something? :) |
@Phr0ztByte that would work, but if any of the "required" repositories were missing, I'd have to check that in runtime. This way it wont compile. That is what I would like. |
@lunemec Add them to the array manually. It would still save your constructor and if it does not implement importable it would throw a compile time error |
But how would you distinguish between the individual repositories within the service? Since you'd expect |
Why would you need to know? I might not have understood the purpose of the service. The import function on the repo would import the data itself. |
Well, the service uses the repositories to Get/Save data in the DB. If you'd pass them as EDIT: // Import uses jsonRepository to load data and save them in DB repositories.
func (i *ImportService) Import(id uint) error {
imported, err := i.jsonRepo.Get(id)
if err != nil {
return err
}
saved, err := i.orgRepo.Save(imported)
if err != nil {
return err
}
// Here would be more code handling recursive saving of locations, contacts, etc...
// Handling cases where you want to update existing records, delete stale etc...
fmt.Printf("Saved: %v\n", saved)
return nil
} |
@Phr0ztByte for some reason I got email with your comment, but can't see it here ... |
Ah. Your original solution is better than trying to tidy up the constructor. There are other solutions, but it depends on the context of which ImportService is used. It really is a special case, since it touches almost your entire DB. Hard to encapsulate responsibility. |
I realize this is an old thread but how about having a separate type ImportServiceOptions struct {
JSONRepository repository.Import,
...
} And either passing it to the constructor func NewImportService(o *ImportServiceOptions) (ImportService, error) or initialize from the options object itself. Although you still cannot validate "required" repositories at compile time, it's easier to write validator function that checks them at the earliest runtime possible. If you do need 50 or similar dependencies I don't see any other way around if not introducing another layer of abstraction. |
@sanggonlee yes I thought about this approach, some libraries use this pattern. But I dislike it because you can pass empty Options struct and it will compile just fine. But when you run it you get runtime errors. But with the other (ugly) approach you can't compile this. Anyway after some discussion, we came to the conclusion that having a separate interface The layer separation should be for the transport + logic, but if you use DB - that kinda is part of the logic (in SQL statements). |
Thanks for sharing what you came up with. Yeah if you do need the check at compile time that might be the only way to go about it... |
This is terrible.
Suppose having 50 DB tables, it is hidious and unreadable. But we can't use (repositories ...tableInterface) because we could not be certain all required repositories were provided.
Another issue here is when adding new repositories, the compiler message gets unreadable when missing one of 20 repositories.
The text was updated successfully, but these errors were encountered: