3

In GWT MVP my presenters typically have a lot of private members (event bus, rpc, message bundles created with GWT.create()...). We have been using a "ClientFactory" to generate views as singleton, so they won't be recreated each time we need them. That factory can also provides rpc, event bus, and other resources.

I can read in GWT doc that the main purpose of this factory is to gain access to object needed through your application. The second advantage of using a ClientFactory is that you can use it with GWT deferred binding to use different implementation classes based on user.agent or other properties.

My question is: if I don't and never will need different implementation of that factory with deferred binding, can't I just use a static classes & methods to retrieve my dependencies instead of a client factory or Gin ? I can't really grab the advantage of Gin over this solution, nor whether it could get me into trouble at some point / under some (not obvious) circumstances. I would usually avoid static classes in server-side code as it is multi-threaded but in client-side mono-threaded code I don't see where a problem could happen. Yet it seems most people use Gin or some other solution...

Olivier Tonglet
  • 3,312
  • 24
  • 40

1 Answers1

3

The problem with static is not about threading, it's about global state and singletons.

One of the main reason for using MVP in GWT is to be able to test your presenters without the need for GWTTestCase, because they wouldn't depend directly on GWT.create() or JSNI, both requiring a browser environment to run (note that GWT.create() is becoming usable in plain Java, and some projects such as gwt-mockito or gwt-test-utils use bytecode manipulation to make it run anyway). But even without MVP, that'd still be a problem:

Global states and singletons come in your way when testing:

  • your tests are not isolated (they depend on global state, so two tests running at the same time share the same state and they're therefore not running in a controlled environment)
  • you cannot use mocks/fakes/stubs or other test-doubles as the system-under-test directly uses singletons rather than depend on some objects passed by the environment (that one being different in tests and in production)

See http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/

Thomas Broyer
  • 64,353
  • 7
  • 91
  • 164
  • Thanks for your anwser. I get the point that we need to have testable presenters (that's why we have to write all those interfaces), and that having a global **state** is bad practice. But in our case I'd just need to check that the methods on my view, rpc, messages, ...'s **interfaces** are called in time. **I won't have to care about their state or whether their instance is a singleton or not**, as I'm testing the presenter and not the views, nor the rpc's or message bundles. Couldn't I just mock my static factory with PowerMock and avoid the problems you're talking about ? – Olivier Tonglet Aug 22 '13 at 10:59
  • Probably, I don't know PowerMock enough. AIUI, that's more or less equivalent to what gwt-test-util does; and just because you can doesn't mean you should… The basic idea is that your presenter depends on some things, and those things should be provided to it (law of Demeter) with whichever the implementation is needed for the environment (Liskov substitution principle). (technically, though less powerful, you could also put the factory in a separate JAR and switch JAR for tests; or use a boolean switch in your factory to switch to "test mode"; the factory violates the law of Demeter though) – Thomas Broyer Aug 22 '13 at 11:32
  • Thanks, I kind of see your point. I don't get what the Law of Demeter has to do about it though, since it's about "only talking to one's close friends" and that the factory (static or not) is a "close friend" of any presenter. The static factory is as well encapsulated has a non-static one. As for Liskov I will quote myself: 'if I don't and never will need different implementation of that factory'... I guess having a presenter knowing about something that won't vary doesn't affect that rule. Hence I won't need to switch JARs or (worse) use boolean (why suggest it, inheritance would be a better – Olivier Tonglet Aug 22 '13 at 12:52
  • option if I ever needed boolean-parametrized classes) since I don't need different implementations. Should I conclude using a client factory or Gin is way overkill in this case? If I feel the need to have different implementations at some point, I can always revert the few ressources/classes that need to be retrieved to Gin or a client factory. In order to avoid boilerplate code, the rule of thumb would be to control the number of classes handled that way, and **strongly go against blindly wiring everything up from the start**. Thanks again for your answers. – Olivier Tonglet Aug 22 '13 at 12:53
  • Passing the `ClientFactory` to the presenters is IMO the same anti-pattern than a static factory: the factory is a "close friend", but what you're dealing with are the _services_ returned by that factory. Re. the need for a different implementation, isn't changing the behavior for the tests equivalent to having a different implementation? That's one that you generate dynamically through bytecode-rewriting rather than a hand-coded one, but still. – Thomas Broyer Aug 22 '13 at 13:13
  • I generally try to "avoid the magic" (reflection, bytecode-rewriting, etc.), and I feel that using injected dependencies (either by hand or using something like GIN) makes the code cleaner and easier to understand (principle of least astonishment: "oh, yes, that class you're look at, in tests, we rewrite it to do something slightly different". It's more verbose and that what you could do with PowerMock and a static factory, but we have IDEs to help generate and maintain the boilerplate. YMMV. – Thomas Broyer Aug 22 '13 at 13:13
  • Do you mean using a client factory is an anti-pattern despite it being present int GWT official doc on the MVP page ? The factory provide accessors to views, the eventbus, etc, not to services. I agree, Gin could be useful to help me wire services but it is not the point of my question. I won't change the implementation of the factory. Instead I'll just mock it so that itself will return mocks of the views' interfaces (not the implementation) and verify such methods are called in time. So you can't say I'm switching implementations, right ? Maybe the mock library will have to manipulate – Olivier Tonglet Aug 22 '13 at 13:55
  • bytecode but it's the problem of the library, not ours. So I understand your advice is to use Gine (which you say is easier to use than mocks + a static factory, which looks close to deprecation). I also understand special IDE tools are required to handle all the boilerplate needed. It makes me afraid to use Gin but I'll have a better look at it though. Thanks again for your advice. – Olivier Tonglet Aug 22 '13 at 13:56
  • "Do you mean using a client factory is an anti-pattern despite it being present int GWT official doc on the MVP page ?" Yes, it should IMO provide the activities, with the apropriate views injected into them. BTW, I'm advocating using DI, not necessarily GIN or any other framework (Dagger?). DI _by hand_ (using a `ClientFactory`) works just as well, it only requires a bit more hand-written code (but not much more than your static factory). – Thomas Broyer Aug 22 '13 at 13:59