플레이! 프레임 워크는 통계
와아, 플레이! 프레임 워크에는 많은 정적 메서드가 있습니다. 내가 학교에 다니는 곳에서 우리는 정적을 절대로 사용하지 말라고 들었지만 Play! 내일이없는 것처럼 사용합니다. 어떻게 든 괜찮습니까? 그렇다면 그 이유는 무엇입니까?
우리 (7 명과 나)는 Play! 웹 앱과 관련된 프로젝트의 프레임 워크입니다. 우리는 Play로하기로 결정했습니다! 재미있어 보였기 때문에 우리 모두는 이미 Java를 알고 있고 할당이 매우 어렵 기 때문에 다른 언어로 프로그래밍하는 방법을 배우기보다는 실제 할당에 집중하고 싶었습니다.
그러나 우리는 항상 우리가 개발 한 자바 프로그램에서 '정적'을 절대 사용 하지 말라고 들었습니다 . ... 음 ... 방법의 절반 정도는 정적입니다. </ 과장>
최소한 우리 프로젝트를 프로그래밍하기 위해 싱글 톤 객체 (예 : 스칼라를 사용하여 ^^)를 사용할 수 있다고 생각하지만, 프레임 워크 자체에 실제로 얼마나 많은 정적이 있는지에 대해 상당히 걱정됩니다.
그래서 이것에 대해 걱정해야합니까? 플레이 방식을 했어요! 개발자가 프로그래밍하여 이러한 모든 정적이 문제를 일으키지 않도록 만들었습니까?
(예를 들어, 이 스레드 는 왜 정적 멤버를 피해야하는지에 대한 호언을합니다.)
Play는 다음과 같은 경우에만 정적 메서드를 사용합니다.
- 컨트롤러는 객체 지향적이지 않기 때문입니다. 컨트롤러는 HTTP 세계 (즉, 상태 비 저장 및 요청 / 응답 기반)와 완전히 객체 지향적 인 모델 계층 사이에서 매퍼 역할을합니다.
- 물론 특정 인스턴스에 의존하지 않는 findAll (), count (), create ()와 같은 팩토리 메소드의 모델 레이어에서
- 순수하게 유틸리티 함수를 제공하는 일부 play.libs. * 클래스
플레이 프레임 워크는 정적을 사용하는 것이 적절할 때 좋은 시연이 아니며 선생님이 틀렸다는 것을 증명하지도 않습니다. Play는 일종의 속임수이며 Java 언어 외부의 정적 문제를 해결합니다.
주요 문제는 여러 HTTP 요청을 병렬로 처리해야하고 정적 필드가 "전역"이라는 것입니다. 따라서 특정 항목에 대해서는 스레드 당 하나의 인스턴스 (또는 HTTP 요청 당 하나의 인스턴스)가 필요하지만 이러한 항목 중 일부는 Play의 정적 메서드에 의해 반환됩니다. 그것은 Play! ThreadLocal-s를 많이 사용 하므로 Java 언어 외부의 정적 문제를 해결합니다. 그러나 그것이 전부는 아닙니다. 어떤 사람들은 컨트롤러 메서드가 정당하게 정적이라고 말합니다. 물론입니다.하지만 일반 Java에서는 req.in req.session과 같은 어떤 종류의 접두어 없이는 요청 별 데이터에 액세스 할 수없고 req정적 컨트롤러 메서드의 매개 변수와 같이 어딘가에서 가져와야 하므로 불편할 것 입니다. , 이는 훨씬 더 번거 롭습니다. 하지만 Play에서는 직접 쓸 수 있습니다.session마치 정적 필드 일뿐입니다. Play는 바이트 코드 계측을 사용하여 모든 정적 필드 참조를 더 스마트 한 것으로 변경하기 때문입니다. 다시 말하지만 Java 언어 이외의 솔루션입니다. 그것들은 마지막에 정적 필드가 아닙니다.
따라서 일반적으로 최종이 아닌 정적을 피하십시오. 하지만 플레이는 당신을 위해 마법을 제공하므로이 경우에 그들을 두려워하지 마십시오.
매우 간략하게 살펴보면 말이됩니다. 웹 요청은 상태 비 저장이므로 요청을받을 개체 가 없습니다 (= the method). 따라서 "/ articles / archive? date = 08 / 01 / 08 & page = 2"와 같은 URI를 archive()on 호출 된 정적 메서드에 매핑하면 응용 프로그램 클래스가 의미가있는 것 같습니다.
편집 이제 Play 2.4 에서 주입 이 자동으로 수행됩니다. 따라서 파일의 컨트롤러 경로 시작 부분에 @를 추가 routes하면 트릭이됩니다.
GET / @controllers.Application.index()
이전 버전 (2.1 ~ 2.3)의 경우 Documentantion에 설명 된 것처럼 Global 클래스에서 getControllerInstance를 재정의해야합니다 .
프로그램에서 아무것도와 마찬가지로, 결코 지금까지 정답 적이 없다. 언제나 처럼 . 항상 예외가 있으며 정답은 항상 '의존적'입니다.
순수한 OO (내가 전부인)에서는 정적을위한 공간이 거의 없다는 것이 사실입니다. 그러나 때로는 그들이 이해하기 쉬운 것도 사실입니다.
고전적인 예는 유틸리티 방법입니다. 물론 abs()Integer에 메서드를 추가 할 수 있다면 더 좋을 것 입니다. 그러나 우리는 할 수 없습니다. 그래서 우리는 Math.abs(int i).
인스턴스 자체와 관련이없는 경우 메서드를 정적으로 만드는 것이 옳다고 생각하는 경향이 있습니다. 예를 들어, 클래스 Person에서 사람 목록을 가져와 오늘 생일이있는 사람 수를 반환하는 메서드를 가질 수 있습니다. 계산을 수행하는 데 필요한 데이터가 비공개 (OO 순수 주의자가 이해할 수있는 것) 인 경우에만 클래스 자체에서이 작업을 수행 할 수 있지만 여전히 메서드는 단일 Person 인스턴스와 관련이 없습니다.
또 다른 것은 내부 클래스입니다. 포함하는 유형과의 관계가 필요하지 않은 경우 정적으로 만들고 싶을 때가 있습니다.
나는 플레이를 본 적이 없다 ! 하지만 그 중 50 % 이상이 정적이라고 말하면 아마도 잘못 설계되었을 것입니다. 예외는 아닙니다. 많은 프레임 워크가 있습니다. 당신을 실망시키지 마십시오. 확실히 그것으로부터 배우지 마십시오!
그러나 작동한다면 여전히 사용할 수 있습니다.
주요 문제는 정적 메소드가 다른 정적 메소드 및 필드에만 액세스 할 수 있다는 것입니다. 이로 인해 정적 메소드가 공통 정적 필드를 통해 애플리케이션의 나머지 (공동 작업자를 포함)와 랑데뷰해야하는 '정적 집착'이 발생합니다. , 이는 비 유연성으로 이어집니다.
면책 조항 : '플레이!'에 대해 잘 모릅니다.
정적 컨트롤러 메서드는 확실히 Play! 몇 가지 테스트를 마친 후 Play!를하지 않는 주된 이유입니다. 프로젝트에서. FOSS 프로젝트에서 Play! 사용. 컨트롤러 테스트가 거의 또는 전혀 없습니다. 그 이유는 정적 방법을 사용하면 DI가 어려워집니다. 여기에서 Play! 이미 약간의 영감이 필요합니다.
일반적으로 다음과 같은 생성자가 있습니다.
public HomeController( IService service ) {
_service = service;
}
public Index() {
var data = _service.getData();
return View( data );
}
그런 다음 DI를 사용하여 IService 구현을 컨트롤러에 삽입합니다. 요점은 테스트에서 컨트롤러를 실행하기 직전에 IService를 인스턴스화 한 다음 방금 생성 한 IService를 기반으로 결과를 테스트 할 수 있다는 것입니다.
Play에서 이것은 매우 어려워집니다. 따라서 컨트롤러 유닛 테스트가 어려워집니다. 그것은 나에게 중요한 문제입니다. 따라서 저는 Play! 이외의 다른 프레임 워크를 찾는 경향이 있습니다! 자바 세계에서. 도대체 원본을 사용하고 JRuby를 사용하는 것은 어떻습니까?
플레이중인 정적 방법은 주로 컨트롤러의 작업 방법에서 사용됩니다. 이 메소드는 모델에서 필요한 데이터를 가져 와서 뷰에 노출하기위한 것입니다.
그들은 어떻게 든 각 가능한 http 요청에 대응하며, 이러한 http 요청이 완전히 상태 비 저장 인 것처럼.
구조적 프로그래밍에서는 프로 시저가 다른 한편으로는 변수가 있지만 OOP 패러다임에서는 프로 시저와 변수를 전체적으로 취급합니다.
즉, 인스턴스 메서드 (프로 시저)와 인스턴스 변수가있는 개체가 있습니다.
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.
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.
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.
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.
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.
정적 메서드를 사용하는 이유 중 하나는 표기법을 줄이고 코드를 더 읽기 쉽게 만들 수있는 정적 가져 오기입니다. 이것은 많은 정적 호출이있을 수있는 Guava 또는 Apache Commons와 같은 유틸리티 라이브러리를 사용할 때 특히 그렇습니다.
비 정적 컨트롤러 메서드는 이제 컨트롤러 주입을 사용하여 Play 2.1에서 지원 되므로 처음부터 없었던 이유가 명확하지 않습니다.
이제 Play 내에서 Spring DI를 사용할 수 있습니다 . https://stackoverflow.com/a/16552598/10433을 참조 하십시오 . 나는 그것을 사용하고 있으며 지금까지 잘 작동합니다.
참고 URL : https://stackoverflow.com/questions/5192904/play-framework-uses-a-lot-of-statics
'program story' 카테고리의 다른 글
| Entity Framework-잘못된 열 이름 '* _ID' (0) | 2020.10.16 |
|---|---|
| 존재하는 경우 ffmpeg 대체 출력 파일 (0) | 2020.10.16 |
| 분기를 전환 할 수없는 이유는 무엇입니까? (0) | 2020.10.16 |
| Android NDK (Native Development Kit) 란 무엇입니까? (0) | 2020.10.16 |
| tslint는 console.log에 대한 호출이 허용되지 않는다고 말합니다. 어떻게 허용합니까? (0) | 2020.10.16 |