Multiple gateways in the interactor's constructor

225 views
Skip to first unread message

Breno Sarkis

unread,
Mar 26, 2015, 7:26:04 PM3/26/15
to clean-code...@googlegroups.com
The largest interactor I have, validates and saves a bunch of data in a database. It communicates with almost every entity I currently have, this means it's constructor expects 10-15 different gateways. 

This bothers me a little bit, since I'm not using a container, I'm manually "newing" them up in a different layer, Dependency Injection is being applied, but the amount of gateways is starting to hurt my eyes. Have you been through a similar situation?

One strategy I've been thinking about is to have some sort of context, that knows about the gateways. But that means I'd allow my interactor to have more knowledge than its supposed to have in many cases. Though I'm not sure if theres a true risk involved.

Thoughts?

Łukasz Duda

unread,
Mar 27, 2015, 4:23:52 AM3/27/15
to clean-code...@googlegroups.com
Yep, I've seen this. Use case that has a lot of responsibility.
My factory uses reflection and property injection, so I don't have large constructor, but that doesn't change a lot. But still a lot of responsibility means a lot of properties :-P
But I didn't feel that it hurts readability, changeability or that the use case is too complex. If the use case really needs all it's stuff, is there any other way? Dividing into a lot of small sub use cases doesn't seem a good, readable solution to me.
I don't prefer hiding dependencies with context yet, I like having obvious place to see all dependencies without reading all the code.

Caio Fernando Bertoldi Paes de Andrade

unread,
Mar 27, 2015, 6:25:31 AM3/27/15
to clean-code...@googlegroups.com
I divide my giant usecase into many others, trying to improve readability, but it’s hard to not introduce temporal coupling between them.
To solve that I often create a “parent” usecase that calls the others, but this parent will have the same construction problem.
I like this approach because in the end every small rule has its place in a smaller usecase and I end up reusing a lot of code, but the construction problem is still there in the parent.
I suggest you experiment with this and other approaches and see what works best for your project and team.

Caio
> --
> The only way to go fast is to go well.
> ---
> You received this message because you are subscribed to the Google Groups "Clean Code Discussion" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discu...@googlegroups.com.
> To post to this group, send email to clean-code...@googlegroups.com.
> Visit this group at http://groups.google.com/group/clean-code-discussion.

Paolo Laurenti

unread,
Mar 27, 2015, 7:41:50 AM3/27/15
to clean-code...@googlegroups.com
From an OO point view, an object with too many dependencies could be a symptom of an object with too many responsibilities, so this could be true for interacors also.
Maybe the problem it's that the use case has not been correctly defined (is it hiding other smaller use cases?) or the dependencies are not well formed (dependencies that make sense to join or group in some sort of abstraction that fit better with the domain).

I don't know, maybe if you share your example, could help us too better understand the problem and make this discussion more effective for everybody.

Paolo

> To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discussion+unsub...@googlegroups.com.
> To post to this group, send email to clean-code-discussion@googlegroups.com.
--
The only way to go fast is to go well.
---
You received this message because you are subscribed to the Google Groups "Clean Code Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discussion+unsub...@googlegroups.com.
To post to this group, send email to clean-code-discussion@googlegroups.com.

Norbert Nemes

unread,
Mar 27, 2015, 7:57:23 PM3/27/15
to clean-code...@googlegroups.com
Hi,

Correct me if I'm wrong, but I have the feeling that you think of interactors as big classes with lots of methods and that do a lot of things.
I used to have the same problem until I read UB's "Agile Software Development" book and I realized that my comprehension of what interactors look like, was completely wrong.
The interactors are command objects that have a single method: execute.
Every controller in the system has access to an interactor factory, and whenever something happens, the controller asks the factory for an interactor and call execute on it.
The interactor factory passes the interactor the appropriate gateways and whatever it needs.
Interactors have very narrow responsibility (scope) as well. There is one for fetching data, there is one for validating, there is one for saving a particular type of data, etc.
As such, each interactor only needs to handle just a few entities / gateways at any time.
The controller fetches these interactors form the factory and call execute on them in the required order.

Regards,

Norbert

Sebastian Gozin

unread,
Mar 29, 2015, 7:19:53 AM3/29/15
to clean-code...@googlegroups.com
Big class with lot's of methods (facade?) is not exactly the vibe I got from the OP.
It sounded more like a dispatcher. Which I would solve as he already pointed out by using a context (registry?) from which I would retrieve the appropriate interactor to handle the current request.

But I could be wrong.

vivek poddar

unread,
Mar 29, 2015, 8:37:17 AM3/29/15
to clean-code...@googlegroups.com

These discussions arises my curiosity of how interactor should be defined, can someone put some more light on it?

--
The only way to go fast is to go well.
---
You received this message because you are subscribed to the Google Groups "Clean Code Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discu...@googlegroups.com.
To post to this group, send email to clean-code...@googlegroups.com.

Sebastian Gozin

unread,
Mar 29, 2015, 9:21:34 AM3/29/15
to clean-code...@googlegroups.com
Well what is an interactor?

Recently I have been thinking about things in terms of functions. And what purpose those functions serve.
And of course using the command pattern doesn't change anything because commands are just functions in my mind.

For example, there are functions which do something specific and need to be composed into something that makes more sense on a business level.
The former would be general functions and the latter could be considered interactors?

To move on from there. I've been thinking I only really want UI/transport connectors to access functions from the latter category.
So the subset of addresses to functions you can use to cross an architectural boundary would depend on that.

How to manage this list of addresses?
I guess I could make a registry for each architectural boundary.
Or perhaps I could make a facade by composing functions or commands into a service object and use that instead?

The facade idea has got me thinking lately.
You see, languages like Groovy allow you to obtain method references which then act like closures do.
So I could forego making a ton of individual factories and just make a big class with vaguely familiar methods and then use those method references to turn them into functions/commands and inject those into a controller without it having to depend on the facade abstraction.

I think I like the sound of such an approach. It feels a bit more familiar. Less factories for creating individual commands. It still avoids ISP issues.
I think I'd just have to be careful not to have interactors on a facade call interactors on the same facade as that would make for awkward TDD.
To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discussion+unsub...@googlegroups.com.

Breno Sarkis

unread,
Mar 29, 2015, 10:03:29 AM3/29/15
to clean-code...@googlegroups.com
I think I haven't explained myself enough.

The interactor I'm talking about, saves a car sale contract. The data comes from a huge page in the UI, and there are a lot of validations I have to perform in order to allow the contract to be saved. I have a Sub/Side interactor to do the validation, but the SaveContractInteractor expects all the gateways it needs in the constructor, so it can query data and allow the validator to perform the validations. 

The problem is that most of the business rules and validations are replicated from the legacy system, just as an example: I have to insert into 4 different tables and sometimes even duplicated fields. 
The interactor itself has only an execute method, which calls the validator object and then calls the gateway to insert the contract entity.

Since the request/response objects are simple data structures, I can't expect the UI to give me a Car entity, for an example, so it only gives me the Car plate, I have call the gateway and tell it to find me this car by plate number and then fill it in the Contract Entity.

It all comes down to the fact that the entity contract has a bunch of other entities inside of it.

Łukasz Duda

unread,
Mar 29, 2015, 2:14:20 PM3/29/15
to clean-code...@googlegroups.com
I would say that interactor represents use case from business requirements analysis. Going further, I'm not sure if it has to be implemented using command pattern. Ivar Jacobson mentions use cases that are bigger and longer, than one interaction or execution.

Sebastian Gozin

unread,
Mar 30, 2015, 6:38:41 AM3/30/15
to clean-code...@googlegroups.com
Let's stay on topic though.
Breno explained his situation better in the previous post.
I'll have to ponder a bit tho and am at a customers so can't spend too much time here now.

Sebastian Gozin

unread,
Mar 30, 2015, 6:38:50 AM3/30/15
to clean-code...@googlegroups.com
Let's stay on topic though.
Breno explained his situation better in the previous post.
I'll have to ponder a bit tho and am at a customers so can't spend too much time here now.

On Sunday, March 29, 2015 at 8:14:20 PM UTC+2, Łukasz Duda wrote:

Caio Fernando Paes de Andrade

unread,
Mar 30, 2015, 7:15:33 AM3/30/15
to clean-code...@googlegroups.com
Breno,

Are you letting your legacy system leak into your architecture? You mentioned that part of the problem was that you have to write to many database tables, and I wonder if you aren't suffering from the Grand Redesign Syndrome.

Maybe what you REALLY want is only one gateway injected into your use case: a gateway for saving Contracts that knows how to call other gateways to save the sub entities properly. Are you too biased by your old system to think about that possibility?

This has happened to me before, and it's quite common, so give it a thought. :-)

Caio
--
The only way to go fast is to go well.
---
You received this message because you are subscribed to the Google Groups "Clean Code Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discu...@googlegroups.com.

Norbert Nemes

unread,
Mar 30, 2015, 8:16:56 AM3/30/15
to clean-code...@googlegroups.com
Thanks for the details.
This morning when I saw your post, I was going to say that you're letting the "bad" architecture of the legacy system infect your new one, but I had to go to work and Caio beat me to it :).
And as he said, unless you're talking to several different databases, you probably only need one gateway.
Message has been deleted

Reed Law

unread,
Apr 7, 2015, 9:01:26 PM4/7/15
to clean-code...@googlegroups.com
Norbert,

I'm intrigued by your concept of an "interactor factory" that passes interactors to the controller in order of execution. Currently I'm calling interactors from within other interactors in order to reuse code. Or in some cases using inheritance for interactors with similar functions. Can you give me an example of how an interactor factory works? How is the response from multiple interactors composed into a single DTO for the view? How are errors handled?

Alexánder

unread,
Apr 9, 2015, 10:20:05 AM4/9/15
to clean-code...@googlegroups.com
I have just found a example with these problem. I think now is more clear:
https://github.com/cbergau/clean_arch_shop/blob/master/src/Bws/Interactor/SubmitOrder.php

Alexánder

unread,
Apr 9, 2015, 10:20:05 AM4/9/15
to clean-code...@googlegroups.com
I'm imagining this example like a blog system. An user can create a post but behind that entity are other entities like an author, a list of categories and a list of tags. We could have an interactor named like "PublishPostUseCase" but this would have in her constructor a validator object for each entity (PostValidator, AuthorValidator, TagsValidator, CategoryValidator) and gateways for each table (PostsRepository, PostsCategoriesRelationshipRepository (to link existing categories with posts), TagsRepository (to add tags if they don't exists) and PostsTagsRelationshipsRepository (to create relationships between posts and tags) ).

How do you group these dependencies in to reduce the number? In "PublishPostDataValidation" and "PublishPostGateway". Your interactor would have only 2 dependencies but each class would still having many dependencies in her constructor.


El viernes, 27 de marzo de 2015, 0:26:04 (UTC+1), Breno Sarkis escribió:

Norbert Nemes

unread,
Apr 9, 2015, 11:26:46 AM4/9/15
to clean-code...@googlegroups.com
Hi Reed

Sorry for the late response.
Here's how I'm using the factory:
 
Interactor Factory
          |
    Presenter
          |
ViewController

The ViewController simply sends signals to the Presenter.
For each signal (method), the presenter calls the factory with a method like 
[self.interactorFactory interactorWithId: interactorId forCaller:self andParameter: parameterObject]; (obj-C)
InteractorId is just an Enum that the factory uses to decide which interactor to instantiate.
ParamaterObject is, as the name says, an object containing one or more parameters needed by the interactor to perform its job.
Interactors hold no state and are very narrow in the scope of what they do. (Like get number of items in cart, selectItem, addItemToCart,etc.)
This way the same interactor can be instantiated any time and passed around the system.
The factory creates an interactor, wires it up with the necessary entities, sets the needed parameters, sets the caller as its delegate and returns it.
The presenter then calls execute on the interactor.
If multiple interactors are needed to do a job, the presenter calls the factory for them one after the other and executes them.
The DTO for the view is gradually built up as the interactors return, and the view model is finally sent to the view controller for presentation.
If your interactors are asynchronous, things get a bit more complicated, and the DTO will probably be a field on your presenter that the callback methods gradually build up.
All entities live in the Interactor factory and are wired up to the proper interactor on an as needed basis.

I'm currently doing error handling in the following way:
I have a single ErrorManager class that handles all the errors in the system.
Entities return errors as usual to the interactors, and the interactors feed those errors into the ErrorManager.
When interactors are created by the factory, it hooks up the interactor and the calling presenter to the ErrorManager.
Whenever the Error manager receives an error, it feeds it to the currently active presenter, which puts the error into a presentable form and sends it to the VC for presentation.
This way all the errors in the system pass through the ErrorManager making logging and what not a breeze. Errors are stored in a dictionary organized by domain and code. When an error is received, the ErrorManager asks the Presenter if it is interested in errors from the error's domain. If it is, the Error manager sends it the error and removes it from the dictionary. If it isn't, it does nothing and waits till a presenter that handles such errors gets hooked up to it. 

Hope this helps, but let me know if you have further questions.

Norbert Nemes

unread,
Apr 9, 2015, 11:34:03 AM4/9/15
to clean-code...@googlegroups.com

Yeah, pretty much.
2 interactors one validates and the other posts.
The validator has a validation gateway and the poster has a post gateway.
The validator validates everything about the post in one go. The poster posts everything to where it needs to be posted.
So 2 interactor and each interactor has 1 gateway in its constructor.

Just my 2 cents.
Reply all
Reply to author
Forward
0 new messages