Clean Architecture - Robert Martin - How to connect use cases - ios

I'm trying to implement the Clean Architecture described by Robert Martin.
More specifically I'm using VIPER which is an iOS version of Clean Architecture.
The problem I have is as follows:
The user starts looking at a map with places (pins) on it.
If he clicks a button, a pin is dropped and he is taken to another view to create (or edit if it was a click to an existent pin) the place (or cancel).
In this other view, the user can edit the place's information and then click "back" or "done" (or "edit").
If he clicks "done", the PlaceDetailsViewController sends a message to the PlaceDetailsPresenter with the place information and the PlaceDetailsPresenter uses the CreatePlaceInteractor to create the place. This interactor returns the GUID which is used to identify the place.
If the user clicks back before creating the place, he gets back to the map and the dropped pin goes up and away (since it has no GUID, it is a new place and goes away).
If he clicks back after creating, the pin stays there (because it should have a GUID).
How should I connect all that and where should the place information (including GUID) be stored?
To clarify a little bit more:
Who should inform the MapPresenter that the pin stays there or goes away?
Is it the PlaceDetailsPresenter or should I pass this information to the PlaceDetailsWireframe -> MapWireframe -> MapPresenter -> MapView ?
Before going back, where should this GUID be stored, in the PlaceDetailsPresenter or in the PlaceDetailsViewController?
Right now that's what I have:
EDIT:
Basically I think the problem is that VIPER came from Robert Martin's Clean Architecture and he comes from a Web (Rails) background, so he doesn't think much about state (or don't specify it in his talks).
Which is mainly my question, where should the state be stored, how should the different modules communicate, should it be through the Wireframe, or through the database, or through the interactors, or through the Presenters communicating with each other like here https://github.com/objcio/issue-13-viper-swift.

I don't know much about Viper, so I can't comment about that. However, the gross state of the system should be held in the entity objects and manipulated by the interactors. The detailed state of the GUI (selection rectangles, etc) should be managed by a special connection between the controller and the presenter.
In your case there are two screens. The map, and the place editor. Clicking on the map causes either the placePinController to be invoked. It gathers the location of the click, and any other contextual data, constructs a placePinRequest data structure and passes it to the PlacePinInteractor which checks the location of the pin, validates it if necessary, create a Place entity to record the pin, constructs a EditPlaceReponse object and passes it to the EditPlacePresenter which brings up the place editor screen.
If the Done button is clicked on the place editor screen it invokes the EditPlaceController which gathers up the edited data into an EditPlaceRequest data structure and passes it to the EditPlaceInteractor. etc..
You specifically asked about the GUID of the pin. That would be created by the Place entity and passed back to the editPlacePresenter PlacePinInteractor.

In pure VIPER Router should hold modules input in form of a protocol. And modules Presenter should conform to it. So when Router uses other modules Router to assemble new module it passes it's input to it.
The second Router then assigns the input to its Presenters output. So basically Presenter of the first module becomes a delegate for the second modules Presenter.
So in your case when a user selects a place MapPresenter asks MapInteractor for a GUID and tells MapRouter to navigate to details for this GUID.
MapRouter asks PlaceDetailsRouter to assemble PlaceDetailsModule for this GUID and passes MapModuleInput to it. PlaceDetailsRouter assigns MapModuleInput to PlaceDetailsPresenter. PlaceDetailsRouter puts GUID in the PlaceDetailsInteractor

Related

ASP.NET Core MVC - Complex Objects specific to a Controller

I'm sort of learning on the fly (coming from a desktop perspective), so forgive me if this seems dumb.
This would be a CRUD type of application, so imagine if you have two controllers for data entry:
SupervisorController
EmployeeController
Now, let's say the User goes to https://whatever/SupervisorController and before I do anything, I need to create some objects specific to the Supervisor screen (e.g. I create an Access object, which reads some data from a source, which tells me what they have access to on that specific Supervisor screen).
OK, in my Index method I construct that object and pass it to my view. But, that object won't persist when say, another method for that controller is called, or say Refresh on the browser is clicked (the constructor for the controller is called each time).
And let's say that the user goes to the browser and types https://whatever/SupervisorController/AnotherMethod themselves. Well, I only constructed that object in my Index Method. So now I have to construct that same object, again, there? And pass it to this view?
Where I'm getting at is that if someone goes to any method of the SupervisorController, if the object isn't there, I want to construct some "supervisor" specific objects, keep them available in my "private member variables", until I'm done with SupervisorController. Meaning, if they move on to say EmployeeController, those objects can now go away.
At EmployeeController, I'll want something similar. Complex objects created specifically for Employee CRUD, that I won't need once I'm done with Employees.
I mean, I really don't want to create these objects and store them in the Session for the lifetime of the session, as they are really only needed for their specific controllers. On top of that, how much data do I really want to be storing in session memory before it gets to be too much!
But if I don't store them somewhere, I would have to re-create these objects for every action/method. I don't want to create them in every method of a specific controller (I could be going to a database to get some specific information). For example, I'm playing around with a Grid Control on my Index page, and when you reach that page, there's the initial call to the Index method, and then the grid itself makes a call to this Read method I have. So I would be creating that object twice!? On one call to https://whatever/SupervisorController?
How do people handle what I'm trying to achieve? Or is there some way I need to look at it now, and implement it to those guidelines?

Nested data and BLoCs in Flutter

My Flutter app has the following general structure:
The initial screen shows a list of contact objects. The user can tap a contact, which brings up
a detail screen that lets the user see the whole contact info, and modify any details temporarily. The user can either
dismiss the screen without saving the changes, or
tap a save button, which updates the contact permanently, and upon completion leads back to the initial screen.
I'm using FireStore. The list is built with Stream<QuerySnapshots>, and when the user taps an item, the app's router parses the route name (e.g. /contacts/123), creates the respective DocumentReference and forwards it to the detail screen's initializer, which then uses DocumentReference.get to load the details, and DocumentReference.updateData to save changes. Works beautifully – but is only a proof of concept.
Now I would like to hide FireStore and the remaining business logic behind a BLoC. This leads to some questions:
Keeping business logic out of the UI, as far as I understand it, implies that I should stick to named routes, and have the detail screen somehow use the route details to retrieve the relevant contact data through the BLoC. Is that true, and what's the best solution for this?
How can I subscribe to nested data using the BLoC? I want the detail screen to observe data changes, so that I can warn the user if the data becomes stale. Using functions on BLoCs (something like streamOfContact(contact) -> Stream<Contact>) is forbidden, so how would I do that with Sinks? Or is there generally a different way to do this without breaking the BLoC pattern? I'm very new to all of this, so may very well be I'm overlooking something important.
Similar question: How would I update a particular contact?
The tutorials I've found online only deal with root data (e.g. adding cart items to a cart, handling user authentication, ...), but I haven't seen an example showcasing nested data yet. Any help is highly appreciated!
1) Routing and navigation is in the responsibility of the UI layer. That means the UI layer must call Navigator.push[Named](...).
If it makes sense, you can move the logic that decides if the app should navigate to the detail screen:
// in the BLoC:
Stream<int> showContactDetail;
// in the UI layer:
bloc.showContactDetail.listen(_showContactDetail);
How you transfer the parameters to the detail route is totally up to you. You can use named routes, but it would be easier to transfer data with a builder:
void _showContactDetail(int contactId) {
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) {
return ContactDetailPage(
contactId: contactId,
);
}));
}
2) One BLoC should be tied to a single screen, that means there should be a separate BLoC for the detail screen (or dialog/sidebar/...), and you would pass the id of your contact to the second BLoC as a constructor parameter, or using a StreamSink, or using a simple setter method.
I would recommend you to use plain old methods instead of StreamSinks for the BLoC inputs. Here is a recent discussion about the topic.
3) The question is not only how to update your contact from the detail screen, but also how the detail BLoC obtains the contact data (if you are only transferring the contact id).
The answer: Another application layer, what I would call the data layer, that is shared between all BLoCs. You can store the data in Firebase, a sqlite database or a simple Map<int, Contact>.
The data layer would also propagate changes to the backend, and notify all BLoCs when the data has changed, probably using a Stream.
The next question that would come up is where you put this data layer (e.g. a class called ContactService):
You can create the ContactService in your ContactListPage, then pass it to the ContactDetailPage in a constructor parameter (using a route builder, as explained above). No magic here. A side effect that you may not want is that the service will be discarded when the list page is popped.
InheritedWidget that is above the MaterialApp, or at least above the Navigator generated by the MaterialApp (You can use the builder of MaterialApp to wrap the navigator with your own widgets). Putting it that high up in the tree ensures that all pages of your app can access it.
Using scoped_model, which is basically the same. Must also be inserted above the navigator to be accessible from both routes
A static variable/singleton

VIPER architecture: how to obtain return info from a module

I have a problem dealing with the return of some info from a module that has been presented by another module. In my case I have two modules, Map and Search. The MapView notifies that it wants to search an address, so the MapPresenter begins the actions to show the Search module (its view is shown modally). Inside the Search module I make a text search, obtain the results, show it and select one. That selection has to be returned to the Map module. How can I achieve that without breaking boundaries?
Taking into account, and please correct me if I'm wrong, that the communication between modules has to be achieved only via routing (not "jumping" between modules with notifications, completion blocks and so on), I implemented this scenario:
(Sorry, maybe a sequence diagram would be better)
MapWireframe implements the regular interface but also another one I called MapModuleInput, so when I begin the search action (blue) I pass to the SearchWireframe the MapWireframe implementing that interface.
After that, in the red flow, in the SearchView I begin the search case, it obtains the results from the interactor, etc. After that the results are presented and the user selects one (green), so the selected result is returned to the map via the MapModuleInput interface.
So, is that correct?
Thank you!
If i understood correctly you have a "module" with the search, it searches with the search interactor, retrieves some POIs and the returns this result to the search presenter. You have a problem that you can avoid, instead of retrieving results in SearchPresenter, just communicate to the map and send the query, then use the SearchInteractor in MapView, now you don't have to send objects between modules.
If you need to do this in the way you painted in the diagram use a DataSource like Core Data to persist huge objets and retrieve it later in the other "module".

Local multiplayer in XNA

Is there any tutorial or sample on how to create a local multiplayer in an XNA game(Windows)?
I often see tutorials for networking game but never on how to enter a second player. How to ask the second player to sign in, to use the same object but with different controller...
Thanks.
I've not come across any tutorials, but I can outline some basic ideas for you.
If all of your players will be identical:
Modify your 'player' objects constructor to have a parameter for some playerIndex. When checking for input inside the player class, use this index. That way, you can create a bunch of 'players' without needing to write individual classes for each. You can then write general-purpose code like:
if (inputManager.IsMoveRight(playerIndex))
{
// do some stuff etc.
}
This will require some modifications to your input management structure. You should be aiming to generalise the code you already have.
If each player will have completely different implementations:
You'll need to take advantage of polymorphism in this case. If each player should select their character in a menu screen, you'll need to have some attribute in the player class that holds their chosen character (Note: If each player should be a preset default, i.e player 1 is always mario, player 2 is always sonic, it would probably be best to subclass your player class for each player). This attribute could be moved up a layer and stored in a 'controller' class if you wanted.
Menu logic:
Handling player sign-ins is really best done before any levels are loaded. I'm going to assume that you don't need players to drop in/out during the game. Basic outline:
When the game is in a character selection screen (or just the main menus) check for input from all controllers. If a controller presses 'start', sign them in. This could involve simply adding a playerIndex to an array for example. Then, when the game loads, check the array for active players and spawn any that are found.
Character selection can be implemented in very much the same way, although you'd probably want a specific menu sign-in screen. Check for input from active players during the sign in screen and allow them to scroll through and select a character. Store the result somewhere (player or controller class for example).
Other things to consider:
Are getting input from the keyboard as well as gamepads? If this is the case, it might be easier to default the keyboard to player one, and only allow sign in/out from gamepads.
I mentioned this before, but you will need to generalise your input management to prevent a major case of spaghetti code. In order for any of this to work, you should not be checking previous/current controller states from directly within your player class. The MSDN Game State Management sample is worth examining as it uses a similar system.
This isn't a very comprehensive guide, but hopefully I've raised some points for you to consider.

Delphi - Running code without showing form

What do you think about this programming practice:
- I need to execute one transaction at first form and after that to force some updates that are placed at another form (for each item that is shown at another form). I.e. it would be like show that form and click at some button. Because it is mandatory to execute these functionalities from second form, I thought to do it without showing second form. Is that good programming practice or you have some other recommendation?
Also, is it enough just to set property> Visible:=False before ShowModal for the second form or I need to do some other actions?
Well, it's unusual to have a form that you don't show. Normally you separate your business logic from the UI.
To answer your question, I don't think you need to call ShowModal at all. Just define a method on the form class and call that. Ultimately forms are just Delphi objects and you can use them as such. If you don't want to show them, don't call ShowModal or Show.
Second question first: Setting Visible := False is of no benefit because the point of all ShowXXX methods is to make the form visible. As David says, you could perform the actions without calling Show at all, provided of course your form doesn't rely on any OnActivate or OnShow code in order to do it's job properly.
As for whether this is a good idea, I say no!
As I've already pointed out there is a concern you have to watch out for. I.e. that currently (or even due to maintenance at some point in the future) your form relies on being visible to do its job properly.
Of course, you could work around that by letting the form flicker open, and be programatically closed. Clearly an aesthetically poor choice.
Not to mention the problems of getting it right. You'll end up writing a bunch of patch-work code to wrap the form so that it can do what you need to do, when you should rather do the following...
Correct Approach
Your form is currently doing at least 2 distinct things:
Visual UI control (call it A)
and "mandatory functionalities" (call it B)
It doesn't matter much whether B is doing validation rules, extra processing, or whatever.
B is a process that does not require user interaction.
Therefore, you need to:
Copy B into a non-UI location (either a simple unit with a custom object or a data module). Call it B*
Modify the form to call B* instead of using B.
Test that your form still behaves correctly.
Delete B
And now you can have your new form call B* instead.
The above approach will save you huge headaches in the future.

Resources