关于java:框架使用大量静态

Play! framework uses a <lot> of statics

哇,这出戏!框架有很多静态方法。在我上学的地方,我们被告知决不使用任何静力学,但玩!就像没有明天一样使用它。不知怎么的,可以吗?如果是,为什么?

我们(7个人和我)正计划使用这个游戏!包含Web应用程序的项目的框架。我们决定玩一玩!因为它看起来很有趣,所以我们都已经知道Java,而且分配很难,所以我们想把重点放在实际的作业上,而不是学习如何用不同的语言编程。

然而,我们一直被告知,在我们开发的任何Java程序中,永远不会使用"static",但当我看游戏的时候!…好。。。大约一半的方法是静态的。< /夸张>

我想,至少,我们可以使用singleton对象(通过使用scala,例如^^)来编程我们的项目,但是我非常关心框架本身中实际有多少静态。

那么,我应该担心这个吗?表演的方式!开发人员对它进行了编程,这样所有这些静态都不会造成问题?

(例如,这个线程有一个关于为什么应该不惜一切代价避免静态成员的咆哮。)


只有当游戏有意义时才使用静态方法:

  • 在控制器层中,因为控制器不是面向对象的。控制器充当HTTP世界(即无状态和基于请求/响应)和完全面向对象的模型层之间的映射器。
  • 在工厂方法的模型层中,如findall()、count()、create(),这当然不依赖于任何特定的实例。
  • 在某些play.libs.*类中提供纯实用函数


play框架不能很好地演示何时使用statics是合适的,也不能证明您的老师是错误的。玩是一种作弊,解决了Java语言之外的静力学问题。

关键问题是必须并行处理多个HTTP请求,静态字段是"全局"字段。因此,对于某些事情,每个线程需要一个实例(或者更好的做法是,每个HTTP请求一个实例),但是其中一些事情是由静态方法返回的。那是因为玩!使用EDCOX1,0,-s,S,因此它解决了Java语言之外的静力学问题。但这不是全部。有人说控制器方法是完全静态的。当然,但在普通Java中,这将是不方便的,因为在没有EDCOX1×1的EDCOX1(2)的情况下,如果没有某种前缀,就不能访问请求特定的数据,然后仍然需要从某个地方获取EDCOX1×3×,例如作为静态控制器方法的参数,这更麻烦。但是在游戏中,你可以直接写session,就像,它们只是静态字段。这是因为play使用字节码工具将所有静态字段引用更改为更智能的内容。同样,Java语言之外的解决方案。这些不是最后的静态字段。

所以,一般来说,避免非最终静力学。尽管游戏对你有魔力,但在这种情况下不要害怕它们。


从一个非常简单的角度来看,我认为这是有意义的:Web请求是无状态的,因此没有对象来接收请求(=方法)。因此,映射一个URI,如"/文章/存档"?日期=08/01/08&page=2"到一个名为EDOCX1[1]的静态方法,我想,您的应用程序类是有意义的。


编辑现在在2.4中,注射是自动完成的。因此,只需在文件routes中控制器路径的开头添加@

1
GET     /                  @controllers.Application.index()

对于旧版本(2.1到2.3),您必须重写全局类中的getControlInstance,如documention中所述。


就像编程中的任何事情一样,永远都不是正确的答案。一如既往。总是有例外,正确的答案总是"视情况而定"。

确实,在纯OO(我完全赞成)中,静态空间非常小。但也有一点是真的,那就是有时它们只是有意义的。

典型的例子是效用方法。当然,如果我们可以将abs()方法附加到integer中,那就更好了。但我们做不到,所以我们被Math.abs(int i)困住了。

我倾向于认为,当方法与实例本身无关时,将其设置为静态是正确的。例如,在一个类Person中,您可以有一个方法,它获取人员列表,并返回今天过生日的人数。也许只有当计算所需的数据是私有的(OO纯粹主义者会理解;)时,您才能在类本身中这样做,但是方法显然与单个人实例没有关系。

另一件事是内部类。如果不需要与包含类型的关系,则通常希望使它们成为静态的。

我从没看过比赛!但是如果你说超过50%是静态的,那么我猜它可能设计得不好。这也不例外,很多框架都是。别让它让你失望。绝对不要从中学习!但如果它起作用,你仍然可以使用它。


静态控制器方法无疑是一个值得关注的领域!框架,在做了一些测试之后,这是我不玩的主要原因!在项目中。你可以在FOSS项目中看到这一点!使用。控制器测试很少或没有。原因是,使用静态方法时,DI变得很困难。这就是他们应该花更多时间在ASP.NET MVC上的地方,从那里开始玩!已经需要一点灵感了。

通常,您有这样一个构造函数:

1
2
3
4
5
6
7
public HomeController( IService service ) {
   _service = service;
}
public Index() {
   var data = _service.getData();
   return View( data );
}

然后使用DI将IService实现注入到控制器中。要点是,在测试中,您可以在运行控制器之前实例化IService,然后根据刚刚生成的IService测试结果。

在游戏中,这变得非常困难。因此控制器单元测试变得困难。对我来说,这是一个重大问题。因此,我倾向于寻找其他框架而不是游戏!在Java世界中。见鬼,为什么不使用原版JRuby呢?


主要问题是静态方法只能访问其他静态方法和字段,这会导致"静态粘附",静态方法必须通过公共静态字段与应用程序的其余部分(包含其合作者)会合,从而导致不灵活。

免责声明:我对"玩"不太了解。


静力学方法主要用于控制器的动作方法。这些方法只是从模型中获取必要的数据并将其公开给视图。

它们以某种方式对应于每个可能的HTTP请求,并且,就像那些HTTP请求一样,是完全无状态的。

在结构编程中,一方面有过程,另一方面有变量,但是在OOP范式中,您将过程和变量作为一个整体来对待。

也就是说,您拥有和对象实例方法(过程)和实例变量。

但是控制器操作是无状态的,也就是说,它们从请求中获取所有的变量(也可能从缓存中获得,但是在这种情况下,您需要一些最终来自请求的会话ID)。所以控制器操作就像Stateles过程,这就是为什么它们不像模型那样特别适合OOP范式的原因。


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

Java中的SuntLon与使用所有静态都没有多大区别。存储的状态也不多。我想你不应该担心。

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?

它不会。事实上,没关系。


例如,Soad采取一种功能性的方法,比如NoDE.js,并且可以在Scala中比Java中的"更有意义",因为Type SeaFe堆栈正在推动。正如其他海报所指出的,Java正在使用字节码测试(La Advices J)进行增强,以更无状态/功能的方式运行;斯卡拉默认情况下这样做。


我也对游戏中静态方法的数量感到惊讶,但如果它运行良好,为什么不呢?

实际上我不同意你的老师。

如果一个对象没有状态(即全局变量),但只包含用于示例的方法,那么使用对象而不是静态方法不会给您带来任何好处。除非您计划稍后添加状态(不应该共享的状态),或者如果您正在使用接口并希望能够轻松地切换实现,那么使用静态方法更容易……

JDK本身、ApacheCommons或许多框架都包含静态方法:

  • 斯特朗蒂斯
  • pattern.matches(regex,输入)

----------

实际上,我想你想知道jpa.java类有什么特点:https://github.com/play framework/play/blob/master/framework/src/play/db/jpa/jpa.java

它们只使用静态方法并保持静态状态。这可能很奇怪,但实际上对我来说,这有点像使用单例,只是方法用于静态上下文而不是对象。主要的区别是,您不必每次都调用getInstance()。

我认为这是为可用性而设计的,因为调用"getInstance"对用户不友好,并且能够轻松地在任何地方(链接到线程)获得会话,而不是用XML或自动连接在任何地方注入sessionFactory,这很酷…

你的教授也许会告诉你避免使用静力学,因为如果你不正确地使用静力学会对你的设计造成危险。但请注意,在许多情况下,用单例替换静态方法并不能使您的设计更好。即使现在调用实例方法上的方法,对象仍然是紧密耦合的…

所以,也许一个规则应该避免使用静态,除非您真的不关心紧密耦合。

  • 在这种情况下,当您调用jpa.xxx()方法时,您的代码与play框架的jpa类紧密耦合。但我不认为Play的设计是为了让您能够轻松地从一个框架切换到另一个框架,而不需要进行任何返工…

  • 这与EJB3规范或类似的东西有很大的区别:如果EJB3实体管理器的方法是静态的,那么通过调用HibernateEntityManager.xxx()或TopLinkEntityManager.xxx()将强制您的代码与实现紧密耦合。在这种情况下,有一个公共接口(我们不能在接口上添加静态方法)。

----------

  • 那个班不是用于其他方面的规范框架。
  • JPA类一个实现:由玩。他们可能不是计划再做一个。
  • 因此A与这个游戏类紧密耦合,使用play框架时,我觉得还行。


现在您可以在播放中使用SpringDI,请参阅https://stackoverflow.com/a/16552598/10433。我正在使用它,到目前为止它工作得很好。


使用静态方法的原因之一是静态导入,它允许您缩短表示法并使代码更可读。在使用像guava或apache commons这样的实用程序库时尤其如此,在这些库中可能会有很多静态调用。

现在,通过使用控制器注入,Play2.1中支持非静态控制器方法,因此从一开始就不存在这些方法的原因并不十分清楚。


如果您是面向对象编程的纯粹主义者,则不应使用static方法/字段,但是它们可以安全地使用,并且不必成为引起imho关注的原因。