Play! framework uses a <lot> of statics
Asked Answered
U

14

75

Waaah, the Play! framework has so many static methods. Where I go to school, we were told never ever to use any statics, yet Play! uses it like there's no tomorrow. Is that somehow okay? If so, why?

We (7 people and I) are planning to use the Play! framework for a project involving a web app. We decided to do it with Play! because it looks quite fun to do, all of us already know Java and the assignment is pretty hard so we wanted to focus on the actual assignment rather than also learning how to program in a different language.

We were always told, however, NEVER EVER to use 'static's in any Java program we developed, but when I look at Play! ... Well... about half the methods are static. </exaggeration>

I suppose, at the very least, we could use singleton objects (by using Scala, for example ^^) in order to program our project, but I'm quite concerned at how many statics there actually are in framework itself.

So, should I be concerned about this? Did the way the Play! developers programmed it make it so that all these statics don't pose a problem?

(For example, this thread has a rant about why static members should be avoided at all costs.)

Unction answered 4/3, 2011 at 11:6 Comment(4)
Uh ... You should probably ask your professor, or whoever. Also, it's natural for the rest of the world to not subscribe to the same ideas about what is good and bad programming practice as yourself, so get used to the idea. :)Kasher
@Saew though use of statics is discouraged, "NEVER EVER use statics" is an overstatementFiacre
the <exaggeration> tag is not visible. :)Chenee
That's the thing, our professor is an OO-purist. He always warns us of the dangers of using statics and he'll have our heads for using statics them unless we can provide a decent explanation why we still use them and are not afraid of there being consequences.Unction
B
95

Play uses static methods only when it makes sense:

  • in the controller layer, because controllers are not object oriented. Controllers act as mapper between the HTTP world (that is stateless, and request/response based) and the Model layer that is fully object oriented.
  • in the model layer for factory methods, like findAll(), count(), create() which of course don't depend of any particular instances
  • in some play.libs.* classes that provides purely utility functions
Budding answered 4/3, 2011 at 12:31 Comment(11)
As addition, the main problem are static members not static methods. In play the are only threadlocals as static members.Masterpiece
The use of the static validation member (see example) in combination with a ThreadLocal shows, that static is not appropriate in all cases.Encapsulate
Sorry deamon, I don't quite get what you mean, what's wrong with the sample you provide?Kp
I'm used to having controllers that have dependencies injected via a DI framework. How would you implement DI using static objects?Steffaniesteffen
@Steffaniesteffen : DI is just parameter passing, partial application of a collection of functions.Imp
yes, if you create a static DependencyInject class that has the Guice Injector, then you can call DependencyInject.create() to get any class from any of the static methods. In this method, you still have the DI you want ;) so if you interface with another system, that may be good to do so you can mock it.Redhanded
What if I needed something like a CRUD controller for different models. If the Actions were not static, i could have used generics and inheritance to achieve the same. But now theres an amount of code duplication.Festoon
Data access methods should be decoupled, how can we manage it? As I saw, Play! ecouraged developers to use finders and factories instead of DI.Illiteracy
@Guillaume I have to disagree with you heavily, Play shows the worst practices of writing Java and there should be no excuses for using statics in Java code, ever. Immutability is not indicated by statics, quite contrary static indicates shared state which is pretty much the opposite from what you are claiming. Then there's of course reflection fun stuff like calling static method on wrong instance since static methods aren't even paired to the class they're defined in. In short, static in Java is a huge code smell and should not be present at all if you're aim is to write modern Java.Hannon
@Hannon I definitely agree with you, Play may be valuable in scala, but in Java it sums a list of bad practices.Monocycle
I disagree--or at least don't understand. Ideally you'd have a UserMapperInterface and a UserMapperImpl (instead of User.find). The controller (or an action, however you group it) would then be passed a UserMapperInterface via the constructor (or curried into an action). If I wanted to switch the implementation of UserMapperInterface used throughout my code, I'd just how to change the DI configuration for the controller. Or replace the value returned by the "UserMapperInterface" key in a service locator. I can't see how to implement something like this with static controllers and models.Highoctane
P
34

Play framework is not a good demonstration of when using statics is appropriate, nor it proves that your teacher was wrong. Play is kind of cheating, solves the issues of statics outside the Java language.

The key problem is that you have to process multiple HTTP requests in parallel, and static fields are "global". So you will need one instance per thread (or even better, one instance per HTTP request) for certain things, yet some of those things are returned by static methods in Play. That works because Play! uses ThreadLocal-s heavily, and so it solves a problem of statics outside the Java language. But that's not everything. Some say that controller methods are rightfully static. Sure, but in plain Java it would be inconvenient, as then you can't access request-specific data without some kind of prefix, like req. in req.session, and then you still have to get req from somewhere, like as a parameter of the static controller method, which is even more hassle. Yet in Play you can you just directly write session and like, they are just static fields. That's because Play uses bytecode instrumentation to change all those static field references to something smarter. Again, a solution outside the Java language. Those are not static fields at the end.

So, in general, avoid non-final statics. Play does the magic for you though, so don't afraid of them in this case.

Persia answered 4/8, 2011 at 19:15 Comment(0)
K
15

From a very brief look, I'd say it kind of makes sense: web requests are stateless, so there is no object to receive the request (=the method). Thus, mapping an URI such as "/articles/archive?date=08/01/08&page=2" to a static method called archive() on, I guess, your application class makes sense.

Kasher answered 4/3, 2011 at 11:12 Comment(0)
J
8

EDIT Now in Play 2.4, the injection is done automatically. So just adding @ at the beginning of the controller path in the file routes will make the trick:

GET     /                  @controllers.Application.index()

For older versions (2.1 to 2.3) you will have to override getControllerInstance in the Global class, like explained in the Documentantion.

Joyless answered 14/12, 2013 at 1:59 Comment(0)
D
5

As with anything in programming, never ever is never the right answer. Just like always. There are always exceptions and the right answer is always 'it depends'.

It's true that in pure OO (which I'm all for) there is very little room for statics. But it's also true that sometimes they just make sense.

The classic example is utility methods. Sure, it would be better if we could just append our abs() method to Integer. But we can't; so we're stuck with Math.abs(int i).

I tend to think it's just correct to make a method static when it has nothing to do with the instance itself. For instance, in a class Person, you could have a method that takes a list of people, and returns the number of people that have a birthday today. Maybe you can only do this in the class itself if the data needed to do the calculation is private (something an OO purist would understand ;)) but still the method clearly has no relation to a single Person instance.

Another thing is internal classes. You often want to make them static if you don't need the relation with the containing type.

I've never seen Play! but if you say that over 50% of it is static, then I'm guessing it was probably badly designed. That's no exception; a lot of frameworks are. Don't let it get you down. Definately don't learn from it!
But if it works you can still use it.

Dorsal answered 4/3, 2011 at 12:11 Comment(1)
Play is not badly designed, but it is a departure from the way most Java libraries are designed.Streamy
F
4

The main problem is that static methods only have access to other static methods and fields, which results in 'static cling' whereby the static methods have to rendezvous with the rest of the application (which contains its collaborators) via common static field(s), which leads to inflexibility.

Disclaimer: I don't know much about 'play!'

Fleeting answered 4/3, 2011 at 11:41 Comment(0)
D
4

Static controller methods are certainly an area of concern with the Play! framework, and after having done some testing, it is the main reason for me not doing Play! in projects. You can actually see this where in FOSS projects where Play! is used. There is little or no Controller testing. The reason, with static methods, DI becomes difficult. This is where they should have spent even more time with ASP.NET MVC, from where Play! already takes a bit of inspiration.

Typically you have a constructor like this:

public HomeController( IService service ) {
   _service = service;
}
public Index() {
   var data = _service.getData();
   return View( data );
}

Then you use DI to inject the IService implementation into the Controller. The point being that in your tests, you can instantiate the IService just prior to running the Controller, and then test the result based on the IService you just produced.

In Play this becomes very hard. Thus Controller unit testing becomes hard. That is, to me, a significant problem. I would therefore tend to look for other frameworks than Play! in the Java world. Heck, why not go with the original and just use JRuby?

Discredit answered 29/10, 2012 at 12:36 Comment(0)
K
3

Statics method in play are mainly used in controllers action methods. These methods are meant to just fetch the necesary data from the model and expose it to views.

They correspond somehow to each possible http request, and, just like those http request are completely stateless.

On structural programming you have procedures on the one hand, and variables on the other, but on OOP paradigm you treat procedures and variables as a whole.

That is, you have and object with instance methods (procedures) and instance variables.

But controller actions are stateless, that is they get all there variables from the request (maybe also from the cache, but in that case you need some sort of session id that finally comes from the request). So controller actions are just like stateles procedures, and that's why they don't particularly fit in the OOP paradigm, as models do.

Kp answered 5/3, 2011 at 5:12 Comment(0)
C
2

I suppose, at the very least, we could use singleton objects

Singleton in Java does not makes much difference than using all static. There is not much to store as state as well. I think you should not worry about it.

So, should I be concerned about this? Did the way the Play! developers programmed it make it so that all these statics don't pose a problem?

It would not. In fact, it's alright.

Chenee answered 4/3, 2011 at 11:23 Comment(3)
Alright.. I guess. My conscience still nags at me for using statics, but I'll ignore it this time :)Unction
-1 because in singleton with non-static methods we CAN apply inheritance and polymorphism, but in statics world we can NOT use these benefits of OOP. So it not almost the same.Reporter
Having statics instead of good language support for singletons is arguably the biggest flaw in the Java language. Scala's companion-object system is a case study in how this small change can have tremendous benefits. Even if you would never swap the implementation in the real world, it's almost always useful to be able to swap an implementation in testing. I agree strongly with the professor, with a few exceptions. It's just not that hard to make a singleton.Stylet
K
1

Im also surprised by the number of static methods in play, but why not if it works fine...

Actually i don't agree with your teacher.

If an object has no state (ie global variables) but just contains methods for exemple, it doesn't give you any benefits to use an object rather than static methods. Except if you are planning to add a state later (state that should not be shared), or if you are using an interface and want to be able to switch easily the implementation, it's easier to use static methods...

JDK itself, apache commons or many frameworks are including static methods:

  • StringUtils
  • Pattern.matches(regex,input)

----------

Actually i guess you wonder what's about classes like JPA.java: https://github.com/playframework/play/blob/master/framework/src/play/db/jpa/JPA.java

They use only static methods and keep a static state. This could be strange, but actually for me it's a bit like using a singleton except the methods are used on a static context instead of an object. The main difference is that you don't have to call getInstance() everytime.

I think this was designed like that for usability, because it is not user friendly to call "getInstance" and it's cool to be able to get easily a session everywhere (linked to the thread) instead of injecting the sessionFactory everywhere with xml or autowiring...

Your professor perhaps tells you to avoid using statics because it can be dangerous for your design if you don't use them right. But notice in many cases, replacing static methods by a singleton doesn't make your design better. Even if you now call the methods on an instance method, objects will still be tightly coupled...

So perhaps a rule should be to avoid using statics except when you don't really care about a tight coupling.

  • On this case, when you call JPA.xxx() methods, your code is tightly coupled to play framework's JPA class. But i don't think play is designed so that you would be able to easily switch from one framework to another without at least some rework...

  • It's a big difference with EJB3 spec or stuff like that: if the EJB3 entity manager's methods where static, you would be forced to tightly couple your code to the implementation by calling HibernateEntityManager.xxx() or ToplinkEntityManager.xxx(). In this case, there is a common interface (and we can't add static methods on interfaces).

----------

  • That class is not part of a specification used on other frameworks.
  • The JPA class has just one implementation: the one done by play. And they probably are not planning to make a second one.
  • Thus a tight coupling to this Play class, while you are using Play framework, seems ok for me.
Kamal answered 25/5, 2011 at 13:33 Comment(0)
T
1

Play takes a functional approach, like node.js for example, and arguably makes 'more sense' in Scala than in Java, as the Typesafe Stack is pushing, for example. As other posters have pointed out, Java is being augmented using bytecode instrumentation (a la Aspect J) to behave in a more stateless/functional way; Scala does this by default.

Twelvemonth answered 17/5, 2012 at 10:33 Comment(0)
R
0

If you are an Object Orientated Programming purist, you shouldn't use static methods/fields, however they can be used safely, and don't have to be a cause for concern IMHO.

Rockafellow answered 4/3, 2011 at 11:11 Comment(2)
I'm not so sure. Gratuitous use of static fields can cause nasty classloader leaks in some environments.Advisory
See earlier comment :) According to my professor, statics are a cause of concern..Unction
S
0

One of the reasons to use static methods are the static imports which allow you to shorten the notation and make the code more readable. This is specially true when using utility libraries like Guava or Apache Commons in which you might have a lot of static calls.

Non-static controller methods are now supported in Play 2.1 via using controller injection, so it's not very clear why they were not there from start.

Shrewd answered 20/9, 2013 at 10:20 Comment(0)
J
0

You can now use Spring DI within Play, see https://mcmap.net/q/19815/-integrating-play-framework-2-0-and-spring-framework. I'm using it and it works fine so far.

Jobber answered 4/10, 2013 at 5:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.