I'm working on an Android piano "quiz" app - users tap on the piano keys and then click the yellow "check" button to submit the answer for evaluation and see the correct answer drawn on the piano. The main QuizActivity has this layout:
The upper part of the screen hosts a couple of controls (Text, submit buttons, etc.).
The lower part of the screen is occupied by a custom PianoView component, that handles drawing of the piano keyboard.
According to the MVVM principles, the PianoView should have its own PianoViewModel, that stores its state (i.e. currently pressed keys, highlighted keys, etc...) in a KeysStateRepository.
The enclosing QuizActivity should also have a QuizActivityViewModel, that handles the various controls (submitting an answer, skipping a question...).
The QuizActivityViewModel needs to be able to query the selected keys from the PianoView (or rather from its KeysStateRepository), submit them to the Domain layer for evaluation and then send the results back to the PianoView for visualization.
In other words, the QuizActivity's ViewModel should own/be a parent of the PianoView's ViewModel to facilitate communication and data sharing.
How can I model this parent-child relationship to communicate between the ViewModels?
AFAIK a ViewModel cannot depend on another ViewModel (What would I pass as the ViewModelStoreOwner to obtain a ViewModel in another Viewmodel?). I don't think it's possible to achieve with Dagger-Hilt at least.
Three solutions to work around this problem came to mind, all of them unusable:
1 - The official way of sharing data between Views
The Android dev docs recommend using a shared ViewModel to facilitate sharing of data between two Fragments / Views. However, this does not fit my use-case. The PianoView (or its ViewModel) should be the sole owner of its state with a Repository scoped to its ViewModel. Otherwise, the PianoView component would not be reusable. Consider for example another Activity, where I'd like to have two independent PianoView instances visible:
Reusing a Shared ViewModel from the quiz activity would be obviously wrong, because it contains irrelevant methods and logic (i.e. submitting quiz answers) and would not fit the two-keyboard scenario.
2 - Application-scoped repository
A similar problem was tackled on Reddit with a proposed solution of using a shared instance of the repository. However, using a #Singleton KeyStateRepository would once again prevent the two independent keyboards to display different data.
3(EDIT) - 2 duplicate repositories replicated by an Event Bus
I could in theory create 2 independent ViewModels and 2 KeyStateRepository instances. The ViewModels would subscribe to an event bus. Each time a ViewModel invokes a mutable operation on its repository, it would also fire an event and the operation would get replicated via the other ViewModel subscribed to the same event bus.
However, this feels like a fragile & complicated hack. I'd like to have a simple MVVM-compatible solution. I can't believe a simple parent-child relationship for two UI components is something unattainable in MVVM.
I think you got a decent answer from Pavlo up there, I'll just clarify what he meant with other words.
KeyStateRepository is a storage for the state of piano keys. There's nothing stopping you from making it to support N number of Pianos at the same time, this would solve the scenario where you have NNN Pianos on Screen, each with different keys pressed.
The PianoView should be contained in a Fragment, that should be your "unit". Why? Because you want a ViewModel to handle the state and events coming to/from the view. And a Fragment is the Android artifact provided for that regard. Think of it as an annoying piece of baggage you need. Android Devs used to call these things "Policy Delegates" because you delegate to these (a Fragment/Activity) some things you cannot do without "the framework" (the Android Framework, that is).
With this in mind, you have an Activity whose viewModel/State is handled independently. What State/Events do this viewModel handle? Things that are not in the PianoFragment/View(s). E.g. if you wanted to handle the back navigation, or a "record" button at the top, this is the activity's domain. What happens inside the "PianoView/Fragment" is not this activity's problem.
Now the Fragment that will contain the actual PianoView can be designed to contain "more than one" or just one. If you go for more than one, then the PianoContainerFragment will be designed with a ViewModel designed to handle more than one PianoView (so each view will have a "name/key") and the KeyStateRepo will be able to handle the "CRUD" operations of any Piano View you throw at. The ViewModel will sit in between, dispatching events for different "subscribed" views.
If you elect to go for "one fragment contains one piano view", then it's a similar architecture, but now handling the multiple "fragments" in one "activity" is now responsibility of the Activity (and its view model). But remember, the PianoViews (via a Fragment either shared or not) talk to a ViewModel that can be shared among piano views, that talks to a common KeyState Repo. The activity coordinates the views and other Android things (navigation, etc.) but the views operate independently, even of each other.
You don't really need a shared viewModel I think, in fact, I wouldn't do it until really needed, the more you separate things, the less the chances of "violating" one of the fancy patterns... but if you elect to use the PianoViewModel as a shared among all views, that's perfectly acceptable, you're going to have to include the Piano "Name" to differentiate whose events are for whom.
In other words (showing with ONE PianoViewModel for ASCII Simplicity),
// One QuizActivityViewModel, Multiple Fragments:
Activity -> PianoFragment (PianoView)|
| <-> PianoViewModel <-> KeyRepo
PianoFragment (PianoView)| /
-> QuizActivityViewModel <----------------------/
Here the QuizActivity creates N fragments (in a list maybe?). These fragments internally initialize their pianoView and connect to a PianoViewModel (can be shared like in the graph above) or each can have its own. They all talk to the same Repo. The repo is your "single source of truth about what each "piano". What keys are pressed, and anything else you can think of (including a name/key to make it unique).
When QuizActivity needs to evaluate the state of these, it will ask (via its own viewModel) for the state of NN pianos.
Or
// 1 Act. 1 Frag. N Views.
Activity -> PianoFragment (PianoView)|
(PianoView)| <-> PianoViewModel <-> KeyRepo
-> QuizActivityViewModel <---------------------------/
With these, the QuizActivity (which created the pianos to begin with as well), also knows the keys of the pianos that will/are displayed. It can talk to its viewModel that talks to the same KeysRepo (you only have one of these and that's fine). So it can still handle the "nav" buttons and it can ask (via its QuizActVM) what the current state of the Keys are (for all involved pianos). When a Piano key event is fired in a PianoView, the PianoViewModel will receive the event (what key was touched, in what piano); the KeyStateRepo will record this, and perhaps update a flow {} with the events coming from the pianos...
The Flow will be expressed in a sealed class which will contain enough information for both QuizActivity + VM (to perhaps perform a real-time validation), and to the PianoViewModel to update the state and push a new state to the PianoFragment (Which will update the state of its view(s)).
This is all common to either method. I hope this clarifies the sequence.
Does this make sense to you?
Edit
In a multiple architecture activity if you wan't PianoViews to have ViewModels and your ActivityViewModel to know about them - don't use Dagger injection with them but create PianoViewModels inside an ActivityViewModel and assign some callback to them on the stage of creation - thus you will have an access to them and will be able to listen to their events and influence their behaviour as well as save their state, from inside the ActivityViewModel. It is not an uncommon and in some cases even a correct approach. Dagger - is a mere instrument that is not intended to be used everywhere, but only there were it is needed. It is not needed to create PianoViewModels - you can inject all the needed stuff into the ActivityViewModel and pass all the needed elements to PianoViewModels constructors.
Also you don't need to wrap your Views into Fragments if you don't want to.
Edit end
You are making wrong assumptions based on a flawed architectural approach.
I am curious why do you need ActivityViewModel at all. View model should exist only for the elements that have some View. Current android development suggests that the Activity should not have a view representation and serve as a mere container of other views(Single activity principle). Depending on your architecture Activity may handle showing the loading state(progress bar) and some errors, but once again it should not contain anything that is being handled by other views. Thus PianoView should be a PianoFragment with its own ViewModel that handles access to its repository on the data layer via interactor on the domain layer.
The shared view model would work in case you would need one, and you would be using the Single activity principle with multiple fragments. Because Jetpack Navigation has the support of the shared view model out of the box. In the case of a shared view model - each fragment would have its own view model along with a shared one for communication. Each navigation graph could have a separate shared view model only for the fragments it contains.
Also regarding KeyStateRepository - you need only one of those(or a Dagger #Scoped multiple copies - but I do not recommend it). The only change should be - the addition of an extra key for each separate PianoView - to distinguish them inside a KeyStateRepository. To easily achieve that you may be using Room or some other file/memory/database cache mechanism.
Hence the initial problem of your app is not an inverted dependency of ActivityViewModel on a PianoViewModel, but a flawed architecture of the app and its inner interactions. If you want to continue work with your current architecture - there is no easy answer to your question, and almost every chosen solution would not be 'clean' enough to justify its usage.
I would do the following, if you don't want to tie the PianoViewModel to your ActivityViewModel, I'd just create an interface, which the ActivityViewModel implements, and the PianoVM could have a nullable reference to that interface. This way neither the implementation, nor the existence of the component would be required for the PianoViewModel to work.
How you get the ActivityViewModel is another question. Check out by activityViewModels() implementation for fragments, you probably can do the same with by viewModels() passing in the viewModelStore of the activity instead
I have few gwt mvp design related questions:
Can we use event bus to switch views from one presenter to other via controller using custom event?
If above is true, can the custom event (say changeViewEvent) contain name of next view, on the basis of which controller can take a decision, which presenter to show?
Is it a good design to make views reusable(as a widget) in an application, though i don't agree with this, but will be happy if someone has any thing to mention in favor of this.
PS: all my views make use of custom widgets and there is no gwt specific widgets(buttons, checkbox etc...) in views.
You can do anything you want, but you have to consider the consequences. For example, if you switch views without creating a history event, a user may be thrown out of your app when a user hits a back button expecting to see the previous view.
I very much like the Activities and Places design pattern. It takes care of all of the issues (history handling, bookmarks, tokens, etc.) You can also extend it to add animation effects when switching views on mobile devices - mgwt does that.
I have few gwt mvp design related questions :
Can we use event bus to switch views from one prsenter to other via controller using custom event ?
This is a bad practice, unless you have real good reasons to do that. Since you're changing the view without having an impact on the url, you won't know what is a the state of a view at a choosen moment, you cannot get back to a previous view in an easy way, and finally, people will have difficulties reading the code, since you're out of the "standard".
The only reference for you should be the url, you cannot assume data is loaded neither the applicatio is in a given state: each and any view may be the start of the navigation story for your users, so if you get information from any other source than the Place, you're probably doing wrong, especially if your source is an event. the only special case here is you don't want users to enter your app in a certain view state, so you 'impose' that another url is called before, and restrict the access to the view through an event starting from a given application state
If above is true, can the custom event (say changeViewEvent) contain name of next view, on the basis of which controller can
take a decission, which prsenter to show ?
as said before, you're reinventing the wheel. It's far better to adapt to the existing mechanism that is well thought and covers the majority of cases. You can put a json formatter to tokenize your url while developing so it's not a nightmare to put variables in. And when you're done, create a nicer regular url format
Is it a good design to make views reusable(as a widget) in an application, though i don't agree with this, but will be happy if
someone has any thing to mention in favor of this.
depends on what you call a View. if it's the activitie's view then youm might need that in very few cases, it's better to inherit a basic view and fork its children for each activity (even if the view does nothing, time will show it will evolve differently): this is better since the base view contains what is common without the specifics of each child activity.
Finally if you mean a composition of widgets when you say, a view, then you should definitely reuse them, it will make you obliged to improove your widgets and compositions to be in a constant improvement, this will heop you for the rest of the project, and maybe for other projects
Is there a Java utility class to help with data management in a desktop UI?
I am writing a UI to configure a network device that will be connected to the serial port of the computer while it is being configured. There is no web server for my application.
The UI has a large number of fields (50+) spread across 16 tabs.
I will write the UI in Java (Java FX?). It should run inside the browser when launched, and issue commands to the network device through the serial port. A UI has several input fields spread across tabs and one single Submit button. If a field is edited, and the submit button clicked, it issues a command and sends the new datum to the device, retrieves current value and any errors. so if input field has bad data, it is indicated for example, the field has a red border.
Is there a standard design pattern or Java utility class to accomplish the frequently encountered, 'generic' parts of this scenario? lazy loading, submitting only what fields changed, displaying what fields have errors etc.
(I dont want to reinvent the wheel if it is already there). Otherwise I can write such a class and share it back here if it is useful.
You need a data model : a set of classes with different kind of relationships (UML design may help).
You can learn more about MVC pattern.
Java encourages the Model Control View pattern for separating the levels of responsibility when it comes to the management of data.
Essentianlly the idea is to provide a model that a view can show to the user. The model doesn't care how its displayed nor does the view care about how the data is managed, they simply have an agree dead interface through which they can communicate
I think I understand the basic concepts of MVC - the Model contains the data and behaviour of the application, the View is responsible for displaying it to the user and the Controller deals with user input. What I'm uncertain about is exactly what goes in the Controller.
Lets say for example I have a fairly simple application (I'm specifically thinking Java, but I suppose the same principles apply elsewhere). I organise my code into 3 packages called app.model, app.view and app.controller.
Within the app.model package, I have a few classes that reflect the actual behaviour of the application. These extends Observable and use setChanged() and notifyObservers() to trigger the views to update when appropriate.
The app.view package has a class (or several classes for different types of display) that uses javax.swing components to handle the display. Some of these components need to feed back into the Model. If I understand correctly, the View shouldn't have anything to do with the feedback - that should be dealt with by the Controller.
So what do I actually put in the Controller? Do I put the public void actionPerformed(ActionEvent e) in the View with just a call to a method in the Controller? If so, should any validation etc be done in the Controller? If so, how do I feedback error messages back to the View - should that go through the Model again, or should the Controller just send it straight back to View?
If the validation is done in the View, what do I put in the Controller?
Sorry for the long question, I just wanted to document my understanding of the process and hopefully someone can clarify this issue for me!
In the example you suggested, you're right: "user clicked the 'delete this item' button" in the interface should basically just call the controller's "delete" function. The controller, however, has no idea what the view looks like, and so your view must collect some information such as, "which item was clicked?"
In a conversation form:
View: "Hey, controller, the user just told me he wants item 4 deleted."
Controller: "Hmm, having checked his credentials, he is allowed to do that... Hey, model, I want you to get item 4 and do whatever you do to delete it."
Model: "Item 4... got it. It's deleted. Back to you, Controller."
Controller: "Here, I'll collect the new set of data. Back to you, view."
View: "Cool, I'll show the new set to the user now."
In the end of that section, you have an option: either the view can make a separate request, "give me the most recent data set", and thus be more pure, or the controller implicitly returns the new data set with the "delete" operation.
The problem with MVC is that people think the view, the controller, and the model have to be as independent as possible from each other. They do not - a view and controller are often intertwined - think of it as M(VC).
The controller is the input mechanism of the user interface, which is often tangled up in the view, particularly with GUIs. Nevertheless, view is output and controller is input. A view can often work without a corresponding controller, but a controller is usually far less useful without a view. User-friendly controllers use the view to interpret the user's input in a more meaningful, intuitive fashion. This is what it makes it hard separate the controller concept from the view.
Think of an radio-controlled robot on a detection field in a sealed box as the model.
The model is all about state and state transitions with no concept of output (display) or what is triggering the state transitions. I can get the robot's position on the field and the robot knows how to transition position (take a step forward/back/left/right. Easy to envision without a view or a controller, but does nothing useful
Think of a view without a controller, e.g. someone in a another room on the network in another room watching the robot position as (x,y) coordinates streaming down a scrolling console. This view is just displaying the state of the model, but this guy has no controller. Again, easy to envision this view without a controller.
Think of a controller without a view, e.g. someone locked in a closet with the radio controller tuned to the robot's frequency. This controller is sending input and causing state transitions with no idea of what they are doing to the model (if anything). Easy to envision, but not really useful without some sort of feedback from the view.
Most user-friendly UI's coordinate the view with the controller to provide a more intuitive user interface. For example, imagine a view/controller with a touch-screen showing the robot's current position in 2-D and allows the user to touch the point on the screen that just happens to be in front of the robot. The controller needs details about the view, e.g. the position and scale of the viewport, and the pixel position of the spot touched relative to the pixel position of the robot on the screen) to interpret this correctly (unlike the guy locked in the closet with the radio controller).
Have I answered your question yet? :-)
The controller is anything that takes input from the user that is used to cause the model to transition state. Try to keep the view and controller a separated, but realize they are often interdependent on each other, so it is okay if the boundary between them is fuzzy, i.e. having the view and controller as separate packages may not be as cleanly separated as you would like, but that is okay. You may have to accept the controller won't be cleanly separated from the view as the view is from the model.
... should any validation etc be
done in the Controller? If so, how do
I feedback error messages back to the
View - should that go through the
Model again, or should the Controller
just send it straight back to View?
If the validation is done in the View,
what do I put in the Controller?
I say a linked view and controller should interact freely without going through the model. The controller take the user's input and should do the validation (perhaps using information from the model and/or the view), but if validation fails, the controller should be able to update its related view directly (e.g. error message).
The acid test for this is to ask yourself is whether an independent view (i.e. the guy in the other room watching the robot position via the network) should see anything or not as a result of someone else's validation error (e.g. the guy in the closet tried to tell the robot to step off the field). Generally, the answer is no - the validation error prevented the state transition. If there was no state tranistion (the robot did not move), there is no need to tell the other views. The guy in the closet just didn't get any feedback that he tried to cause an illegal transition (no view - bad user interface), and no one else needs to know that.
If the guy with the touchscreen tried to send the robot off the field, he got a nice user friendly message asking that he not kill the robot by sending it off the detection field, but again, no one else needs to know this.
If other views do need to know about these errors, then you are effectively saying that the inputs from the user and any resulting errors are part of the model and the whole thing is a little more complicated ...
The MVC pattern merely wants you to separate the presentation (= view) from the business logic (= model). The controller part is there only to cause confusion.
Here is a good article on the basics of MVC.
It states ...
Controller - The controller translates
interactions with the view into
actions to be performed by the model.
In other words, your business logic. The controller responds to actions by the user taken the in the view and responds. You put validation here and select the appropriate view if the validation fails or succeeds (error page, message box, whatever).
There is another good article at Fowler.
Practically speaking, I've never found the controller concept to be a particularly useful one. I use strict model/view separation in my code but there's no clearly-defined controller. It seems to be an unnecessary abstraction.
Personally, full-blown MVC seems like the factory design pattern in that it easily leads to confusing and over-complicated design. Don't be an architecture astronaut.
Controller is really part of the View. Its job is to figure out which service(s) are needed to fulfill the request, unmarshal values from the View into objects that the service interface requires, determine the next View, and marshal the response back into a form that the next View can use. It also handles any exceptions that are thrown and renders them into Views that users can understand.
The service layer is the thing that knows the use cases, units of work, and model objects. The controller will be different for each type of view - you won't have the same controller for desktop, browser-based, Flex, or mobile UIs. So I say it's really part of the UI.
Service-oriented: that's where the work is done.
Based on your question, I get the impression that you're a bit hazy on the role of the Model. The Model is fixated on the data associated with the application; if the app has a database, the Model's job will be to talk to it. It will also handle any simple logic associated with that data; if you have a rule that says that for all cases where TABLE.foo == "Hooray!" and TABLE.bar == "Huzzah!" then set TABLE.field="W00t!", then you want the Model to take care of it.
The Controller is what should be handling the bulk of the application's behavior. So to answer your questions:
Do I put the public void actionPerformed(ActionEvent e) in the View with just a call to a method in the Controller?
I'd say no. I'd say that should live in the Controller; the View should simply feed the data coming from the user interface into the Controller, and let the Controller decide which methods ought to be called in response.
If so, should any validation etc be done in the Controller?
The bulk of your validation really ought to be done by the Controller; it should answer the question of whether or not the data is valid, and if it isn't, feed the appropriate error messages to the View. In practice, you may incorporate some simple sanity checks into the View layer for the sake of improving the user experience. (I'm thinking primarily of web environments, where you might want to have an error message pop up the moment the user hits "Submit" rather than wait for the whole submit -> process -> load page cycle before telling them they screwed up.) Just be careful; you don't want to duplicate effort any more than you have to, and in a lot of environments (again, I'm thinking of the web) you often have to treat any data coming from the user interface as a pack of filthy filthy lies until you've confirmed it's actually legitimate.
If so, how do I feedback error messages back to the View - should that go through the Model again, or should the Controller just send it straight back to View?
You should have some protocol set up where the View doesn't necessarily know what happens next until the Controller tells it. What screen do you show them after the user whacks that button? The View might not know, and the Controller might not know either until it looks at the data it just got. It could be "Go to this other screen, as expected" or "Stay on this screen, and display this error message".
In my experience, direct communication between the Model and the View should be very, very limited, and the View should not directly alter any of the Model's data; that should be the Controller's job.
If the validation is done in the View, what do I put in the Controller?
See above; the real validation should be in the Controller. And hopefully you have some idea of what should be put in the Controller by now. :-)
It's worth noting that it can all get a little blurry around the edges; as with most anything as complex as software engineering, judgment calls will abound. Just use your best judgment, try to stay consistent within this app, and try to apply the lessons you learn to the next project.
Here is a rule of thumb that I use: if it is a procedure that I will be using specifically for an action on this page, it belongs in the controller, not the model. The model should provide only a coherent abstraction to the data storage.
I've come up with this after working with a large-ish webapp written by developers who thought they were understood MVC but really didn't. Their "controllers" are reduced to eight lines of calling static class methods that are usuall called nowhere else :-/ making their models little more than ways of creating namespaces. Refactoring this properly does three things: shifts all the SQL into the data access layer (aka model), makes the controller code a bit more verbose but a lot more understandable, and reduces the old "model" files to nothing. :-)
The controller is primarily for co-ordination between the view and the model.
Unfortunately, it sometimes ends up being mingled together with the view - in small apps though this isn't too bad.
I suggest you put the:
public void actionPerformed(ActionEvent e)
in the controller. Then your action listener in your view should delegate to the controller.
As for the validation part, you can put it in the view or the controller, I personally think it belongs in the controller.
I would definitely recommend taking a look at Passive View and Supervising Presenter (which is essentially what Model View Presenter is split into - at least by Fowler). See:
http://www.martinfowler.com/eaaDev/PassiveScreen.html
http://www.martinfowler.com/eaaDev/SupervisingPresenter.html
also note that each Swing widget is can be considered to contain the three MVC components: each has a Model (ie ButtonModel), a View (BasicButtonUI), and a Control (JButton itself).
You are essentially right about what you put in the controller. It is the only way the Model should interact with the View. The actionperformed can be placed in the View, but the actual functionality can be placed in another class which would act as the Controller. If you're going to do this, I recommend looking into the Command pattern, which is a way of abstracting all of the commands that have the same receiver. Sorry for the digression.
Anyway, a proper MVC implementation will have the following interactions only:
Model -> View
View -> Controller
Controller -> View
The only place where there may be another interaction is if you use an observer to update the View, then the View will need to ask the Controller for the information it needs.
As I understand it, the Controller translates from user-interface actions to application-level actions. For instance, in a video game the Controller might translate "moved the mouse so many pixels" into "wants to look in such and such a direction. In a CRUD app, the translation might be "clicked on such and such a button" to "print this thing", but the concept is the same.
We do it thusly, using Controllers mainly to handle and react to user-driven input/actions (and _Logic for everything else, except view, data and obvious _Model stuff):
(1) (response, reaction - what the webapp "does" in response to user)
Blog_Controller
->main()
->handleSubmit_AddNewCustomer()
->verifyUser_HasProperAuth()
(2) ("business" logic, what and how the webapp "thinks")
Blog_Logic
->sanityCheck_AddNewCustomer()
->handleUsernameChange()
->sendEmail_NotifyRequestedUpdate()
(3) (views, portals, how the webapp "appears")
Blog_View
->genWelcome()
->genForm_AddNewBlogEntry()
->genPage_DataEntryForm()
(4) (data object only, acquired in _construct() of each Blog* class, used to keep all webapp/inmemory data together as one object)
Blog_Meta
(5) (basic data layer, reads/writes to DBs)
Blog_Model
->saveDataToMemcache()
->saveDataToMongo()
->saveDataToSql()
->loadData()
Sometimes we get a little confused on where to put a method, in the C or the L. But the Model is rock solid, crystal clear, and since all in-memory data resides in the _Meta, it's a no-brainer there, too. Our biggest leap forward was adopting the _Meta use, by the way, as this cleared out all the crud from the various _C, _L and _Model objects, made it all mentally easy to manage, plus, in one swoop, it gave us what's being called "Dependency Injection", or a way to pass around an entire environment along with all data (whose bonus is easy creation of "test" environment).