Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eliminating GWT ActivityMapper boilerplate

I am using the GWT Activities and Places framework to structure my application and it is turning out nicely. One thing that annoys me though is that the ActivityMapper implementation is (1) receiving all the views in the application (2) contains a giant if/else block for instantiating activities based on the received place. It will only get worse as the number of views increases.

ActivityMapper screenshot

I am already using Gin but I don't see how I can use it here.

How can I reduce or eliminate the boilerplate from my ActivityMapper?

like image 614
Robert Munteanu Avatar asked Apr 27 '11 10:04

Robert Munteanu


2 Answers

There isn't a great answer yet. I have code generation schemes in mind, but it's all scribbles on white boards at the moment. For Gin users it seems like a Place Scope might be handy.

Re: the if / else cascade, one common approach is to make your Place objects implement the visitor pattern. E.g. let's assume you have AssistedInject set up for your activities (and forgive the sloppy field injection, it's just a sketch).

class BasePlace extends Place {
    <T> T acceptFilter(PlaceFilter filter);
}

interface PlaceFilter<T> {
  T filter(FooPlace place);
  T filter(BarPlace place);
  T filter(BazPlace place);
}

public class MainActivities implements ActivityMapper {
  @Inject FooFactory fooMaker;
  @Inject BarFactory barMaker;
  @Inject BazFactory bazMaker;

  public Activity getActivity(PlaceChangeEvent e) {
     return ((BasePlace)e.getPlace()).acceptFilter(
       new PlaceFilter<Activity>() {
         Activity filter(FooPlace place) {
           return fooMaker.create(place);
         }
         Activity filter(BarPlace place) {
           return barMaker.create(place);
         }
         Activity filter(BazPlace place) {
           return bazMaker.create(place);
         }
       })         
   }
}
like image 127
rjrjr Avatar answered Nov 07 '22 13:11

rjrjr


One possibility is to have the root of your Place class hierarchy define a createActivity() method, and Place subclasses can return a new instance of the Activity they're associated with.

@Override
public Activity getActivity(Place place) {
    return ((BaseAppPlace)place).createActivity();
}

This has the advantage of having eliminated that if/else block, and having one less place to modify when you add a new Place/Activity. The downside of this is that it kindof pollutes your Place class with Activity creation behavior, even if you're just delegating to a Ginjector.

like image 43
Jason Avatar answered Nov 07 '22 11:11

Jason