When working with MVP in GWT how would you work with a table? For example if you had a table of users does your view look like this?
public interface MyDisplay{
HasValue<User> users();
}
or would it be more like this?
public interface MyDisplay{
HasValue<TableRow> rows();
}
MVP makes a ton of sense until you start dealing with widgets that need to display lists of non-primitive data. Can anybody shed some light?
This mailing list archive appears to ask the same question but never reaches a solid resolution...
http://www.mail-archive.com/google-web-toolkit#googlegroups.com/msg24546.html
HasValue<User> or HasValue<TableRow> would not work in this case, because this would only permit handling a single row.
You could maybe use a HasValue<List<User>> but that would mean, that your view has to render the entire table on each change.
I might be wrong, but I think for tables its best to use a Supervising Presenter instead of the Passive View.
Have a look at the PagingScrollTable widget in the GWT Incubator:
public class PagingScrollTable<RowType> extends AbstractScrollTable implements
HasTableDefinition<RowType>, ... {
...
TableModel<RowType> getTableModel()
...
}
For a PagingScrollTable, a MutableTableModel<RowType> is used as implementation of TableModel<RowType>.
MutableTableModel<RowType> in turn implements the following interfaces:
HasRowCountChangeHandlers, HasRowInsertionHandlers, HasRowRemovalHandlers, HasRowValueChangeHandlers<RowType>
The PagingScrollTable registers itself as listener on the MutableTableModel and therefore gets very fine-grained notifications of updates. The resulting implementation should be very performant.
this discussion does reach a resolution for similar question:
http://groups.google.com/group/google-web-toolkit/browse_thread/thread/4887a7565d05f349?tvc=2
This might be a very interesting blog post:
http://www.draconianoverlord.com/2010/03/31/gwt-mvp-tables.html
Related
Most of the gwt mvp tutorials show the view interface declared as an inline interface in the presenter class. Is there a good reason for doing that or is creating a separate file for the View interface a better choice or does it just not matter (I know it doesn't matter for the compiler).
public ItemPresenter {
...
public interface MyView<> {
public void setName(..);
}
...
}
Thanks.
There's no technical need to use an inner interface. It will definitely work with separate compilation units.
I personally prefer inner interfaces as the presenter together with the view interface define the contract how these two communicate with each other.
Another reason for me is naming. Think about ItemPresenter & ItemView vs ItemPresenter & ItemPresenter.View. For me the latter is more intuitive as the View is defined by the presenter itself.
And the last reason is copy&past. Yes, that's right :)
For presenters/views as well as Events with inner handler interface, I have empty copy&paste templates in my workspace. With the inner interface you won't have trouble with imports when copying the template.
It doesn't matter what you do. It is just to bring things closer together.
i learned how to implement my own SuggestionOracle("AuSuggestOracle") and own
Suggestions("AuMultiWordSuggestion"). In my case the suggestion object
is constructed with a DTO. On a selection event i need this dto (or
some fields of it) to react appropriate.
I implemented a widget containing 3 suggest boxes with this special
oracle and some logic between them. Now i want to apply MVP pattern -
split this widget in presenter and view.
At the moment the presenters display interface look like that:
public interface Display {
HasSelectionHandlers<Suggestion> getFedLand();
HasSelectionHandlers<Suggestion> getCounty();
HasSelectionHandlers<Suggestion> getCommunity();
AuSuggestOracle getFedLandOracle();
AuSuggestOracle getCountyOracle();
AuSuggestOracle getCommunityOracle();
void clearCounty();
void clearCommunity();
void activateForm();
Widget asWidget();
}
the problem is the implicit knowledge about my model in methods
returning "AuSuggestOracle". so my question is how to get the view/
interface "humble". in my case the displayed suggestion-strings are
ambiguous and i need at least the "id" of a selected item to know what
DTObject is selected.
The way I got around this is by leaving out the getters for the Oracle since once my presenter sets it my view doesn't need any information about it. So, my interface looked like this:
public interface Display {
...
void setSuggestionOracle(SuggestOracle oracle);
HasSelectionHandlers<SuggestOracle.Suggestion> getSelectionListener();
}
The problem I encountered was being able to add the suggestion to the SuggestBox after it was instantiated. To get around this, I initialized with a blank SuggestBox and then removed it from the view, updated in, and inserted it back into position.
After that, you can write your handler (in the presenter) to check if the suggestion is an instance of your custom suggestion and your presenter can handle the selection and push the relevant information back down to your view.
By doing this, all your view knows is that it will be taking generic suggestions for something, and that at some later time it will be updating with information (which will be as a result of the suggestion, but the view is to 'humble' to know that).
I'm trying to familiarize myself with the "Places & Activities" design pattern for GWT development, and so far I think it has a lot of potential. I especially like the way how once you start thinking about your application in terms of "Places", browser history virtually just lands in your lap with almost no extra effort.
However, one thing just bothers me: All the articles and code examples I've seen so far gloss over one (as far as I am concerned, major) aspect: the 'M' part of the 'MVP', i.e. the Model!
In normal MVP architecture, as far as I understand it, the Presenter holds a reference to the Model, and is responsible for updating it according to UI events or, respectivly, updating the UI according to Model changes.
Now, in all the articles/samples for "P&A" the Activities seem to be taking the place of the Presenter, but unlike 'normal' Presenters, they get discarded and (re-)created whenever a new Place arrives, so they can't be the ones to store the client state, or it would be lost every time. Activities are cheap to create, so it's not much of a hassle, but I wouldn't want to create the model of a complex application over and over again.
All the samples are fairly simple and don't have much of a state and therefore just ignore the Model aspect, but where would an actual, complex application store its state?
I think I found my own answer. The main problem seems to be that all of the simple code examples make the Activities be the Presenters, as in:
public class NavigationActivity extends AbstractActivity implements NavigationView.Presenter {
private final ClientFactory clientFactory;
private final NavigationPlace place;
public NavigationActivity(ClientFactory clientFactory, NavigationPlace place) {
this.clientFactory = clientFactory;
this.place = place;
}
#Override
public void start(AcceptsOneWidget panel, EventBus eventBus) {
NavigationView navView = clientFactory.getNavigationView();
navView.setSearchTerm(place.getSearchTerm());
navView.setPresenter(this);
panel.setWidget(navView);
}
#Override
public void goTo(Place place) {
clientFactory.getPlaceController().goTo(place);
}
}
Now Activities are fairly short-lived, whereas a typical Presenter in the 'classical' sense has a much longer lifespan in order to maintain the binding between the model and the UI. So what I did was to implement a separate Presenter using the standard MVP design pattern, and all the Activity does is something like this:
public class NavigationActivity extends AbstractActivity {
private final ClientFactory clientFactory;
private final NavigationPlace place;
public NavigationActivity(ClientFactory clientFactory, NavigationPlace place) {
this.clientFactory = clientFactory;
this.place = place;
}
#Override
public void start(AcceptsOneWidget panel, EventBus eventBus) {
NavigationPresenter presenter = clientFactory.getNavigationPresenter();
presenter.setSearchTerm(place.getSearchTerm());
presenter.go(panel);
}
}
So, instead of the Activity fetching the View, and acting like a Presenter on it, it fetches the actual Presenter, just informs it of the client state change induced by the Place, and tells it where to display its information (i.e. the view). And the Presenter is then free to manage the view and the model any way it likes - this way works a lot better (at least with what I have in mind for the application I'm working on) than the code examples I have found so far.
You're right, almost always the presenter is the only guy holding the model and managing its lifetime. Model from previous GWT versions has simply been a DTO, (and continues to be) a POJO which are created by the GWT deserializer when RPC methods return, or created by Presenters and filled with UI data by UIHandlers, and sent to the server.
I have taken efforts, to keep the Models lifetime encapsulated within the Activities lifetime, and avoided storing state outside of activities. (I do however have a singleton Global State maintained for use from anywhere in the application.) This I think is what GWT MVP engineers assumed will happen - It makes sense when, say the user has navigated away from a Place, for the models associated with that place also to get disposed (& collected). Create models, fill them up inside the activities, and make service calls to update the server before navigating away (or triggered by some control on the page), and let them go along with the activity - is what I have been doing till date.
A bigger project I have been involved in faced quite a few browser memory footprint issues, and all of them were due to objects which are associated with another (not currently viewed) Place being in memory. It was hard to track and remove references to these objects, and since the user has navigated away from the screen - the "why are my old screen objects still in memory?" question cropped up frequently and subsequently got fixed. This is why, upfront, I chose to keep the Model's lifetime encapsulated within the Activities lifetime in my current pet project.
If you have models that span across (that are filled/accessed by) several activities (as is the case if you have sidebars & master/container widgets), some redesigning of models maybe in order, if you have examples I will try and help.
I have inherited a project that has an awkwardly big interface declared (lets call it IDataProvider). There are methods for all aspects of the application bunched up inside the file. Not that it's a huge problem but i'd rather have them split into smaller files with descriptive name. To refactor the interface and break it up in multiple interfaces (let's say IVehicleProvider, IDriverProvider etc...) will require massive code refactoring, because there are a lot of classes that implement the interface. I'm thinking of two other ways of sorting things out: 1) Create multiple files for each individual aspect of the application and make the interface partial or 2) Create multiple interfaces like IVehicleProvider, IDriverProvider and have IDataProvider interface inhertit from them.
Which of the above would you rather do and why? Or if you can think of better way, please tell.
Thanks
This book suggests that interfaces belong, not to the provider, but rather to the client of the interface. That is, that you should define them based on their users rather than the classes that implement them. Applied to your situation, users of IDataProvider each use (probably) only a small subset of the functionality of that big interface. Pick one of those clients. Extract the subset of functionality that it uses into a new interface, and remove that functionality from IDataProvider (but if you want to let IDataProvider extend your new interface to preserve existing behavior, feel free). Repeat until done - and then get rid of IDataProvider.
This is difficult to answer without any tags or information telling us the technology or technologies in which you are working.
Assuming .NET, the initial refactoring should be very minimal.
The classes that implement the original interface already implement it in its entirety.
Once you create the smaller interfaces, you just change:
public class SomeProvider : IAmAHugeInterface { … }
with:
public class SomeProvider : IProvideA, IProvideB, IProvideC, IProvideD { … }
…and your code runs exactly the way it did before, as long as you haven't added or removed any members from what was there to begin with.
From there, you can whittle down the classes on an as-needed or as-encountered basis and remove the extra methods and interfaces from the declaration.
Is it correct that most if not all of the classes which implement this single big interface have lots of methods which either don't do anything or throw exceptions?
If that isn't the case, and you have great big classes with lots of different concerns bundled into it then you will be in for a painful refactoring, but I think handling this refactoring now is the best approach - the alternatives you suggest simply push you into different bad situations, deferring the pain for little gain.
One thing to can do is apply multiple interfaces to a single class (in most languages) so you can just create your new interfaces and replace the single big interface with the multiple smaller ones:
public class BigNastyClass : IBigNastyInterface
{
}
Goes to:
public class BigNastyClass : ISmallerInferface1, ISmallerInterface2 ...
{
}
If you don't have huge classes which implement the entire interface, I would tackle the problem on a class by class basis. For each class which implements this big interface introduce a new specific interface for just that class.
This way you only need to refactor your code base one class at a time.
DriverProvider for example will go from:
public class DriverProvider : IBigNastyInterface
{
}
To:
public class DriverProvider : IDriverProvider
{
}
Now you simply remove all the unused methods that weren't doing anything beyond simply satisfying the big interface, and fix up any methods where DriverProvider's need to be passed in.
I would do the latter. Make the individual, smaller interfaces, and then make the 'big' interface an aggregation of them.
After that, you can refactor the big interface away in the consumers of it as applicable.
I'm working with the MVVM pattern + a simple ServiceLocator implementation, now to my problem how am I supposed to setup the services when the views are running in design time?
Iv tried this but it does not seem to work in VS 2010 or some thing, I know it worked on my old computer but on my new it does not. so does any one know a good alternative?
Edit: (On behalf of Merlyn Morgan-Graham)
Well what I'm trying to do is this, I have my view, ViewModel and services now the difference here is that I have 2 implementations of each service one for design time and one for run time.
for a better explanation look here.
If you want to decouple your view from your viewmodel, and your viewmodel from your model/dal (basically, if you want to use MVVM), then your view model and data model shouldn't know anything about design time. Design time only applies to the view.
This article shows a way to define your design time data via XML/XAML, so your code underneath doesn't have to know anything about it:
http://karlshifflett.wordpress.com/2009/10/21/visual-studio-2010-beta2-sample-data-project-templates/
After Edit: It turns out that you'll still have to use your view model for your existing XAML bindings to work. This will just populate the view model rather than having to create a new data model. I'm not sure, but there might be classes that allow you to use the WPF binding mechanism to take care of this... Views?
Resume Before Edit...:
As far as the solution in the article you linked first, the designer doesn't instantiate anything but your class, and the code it references. That means that assembly attributes won't be instantiated unless your view code somehow directly references them.
If you really want to couple your view models to your views during design time, and make it so that design time services are registered, then you have to place the service registration code in your view class, or a class the view class directly references.
To do that, you could use static constructors of your views to register your design time services. You could also write a static method on some other class (application?) to (conditionally) register the design time services. Then, call that method in the constructor of your views.
Or you could simply register them in the constructor for each of your views.
Basically, what you want to do is possible, but that method linked in the first article isn't. If you read farther in the comments, you'll see that his method is broken.
You may also want to question the idea of hooking your view model to your view during design time, because the MVVM pattern was made to avoid that sort of thing.
You usually don't need to access services at design-time... Typically, you don't even use your real ViewModels at design-time, you use dummy design data, as explained here. If you really need to use your real ViewModels, you can implement dummy versions of your services, and use them instead of the real services :
if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
{
// Design time
ServiceLocator.Instance.Register<IService1>(new DummyService1());
ServiceLocator.Instance.Register<IService2>(new DummyService2());
}
else
{
// Run time
ServiceLocator.Instance.Register<IService1>(new RealService1());
ServiceLocator.Instance.Register<IService2>(new RealService2());
}
Also I do agree to all who have concerns regarding the use of the service locator at design time, I do believe that this is a valid scenario in some use cases.
This is not a discussion on why/why not, this is simple the way it (almost) worked for me.
There is still a problem which I did not solve yet: this only works for one view at a time.
Create a simple bootstrapper for setting up your IoC of choice. Notice the ISupportInitialize interface.
public class Bootstrapper: ISupportInitialize
{
#region ISupportInitialize Members
public void BeginInit() { }
public void EndInit()
{
if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
Setup();
}
#endregion
public static void Setup() { SetupServiceLocator(); }
static void SetupServiceLocator()
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<ConfigService>().As<IConfigService>().ExternallyOwned().SingleInstance();
IContainer container = builder.Build();
ServiceLocator.SetLocatorProvider(() => new AutofacServiceLocator(container));
}
}
Use the Bootstrapper as before for runtime mode, e.g.:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Bootstrapper.Setup();
}
}
Additionally you need to add it to the application resources for design mode support:
<Application x:Class="MonitoringConfigurator.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyBootstrapperNamespace"
StartupUri="MainWindow.xaml">
<Application.Resources>
<local:Bootstrapper x:Key="Bootstrapper" />
</Application.Resources>
</Application>