싱글 톤 : 좋은 디자인인가 아니면 버팀목인가?
싱글 톤은 열띤 논쟁이 벌어지는 디자인 패턴이므로 Stack Overflow 커뮤니티가 이에 대해 어떻게 생각했는지에 관심이 있습니다.
"싱글턴은 게으른 프로그래머를위한 것입니다!"뿐만 아니라 귀하의 의견에 대한 이유를 제공하십시오.
Singletons : scienceninja.com : performant-singletons 사용에 반대하지만이 문제에 대한 상당히 좋은 기사가 있습니다 .
다른 좋은 기사가 있습니까? 싱글 톤을 지원할까요?
싱글 톤 방어 :
- 전역에는 표준 적용 초기화 순서가 없기 때문에 전역 만큼 나쁘지는 않으며 순진하거나 예상치 못한 종속성 순서로 인해 비 결정적 버그를 쉽게 볼 수 있습니다. 싱글 톤 (힙에 할당되었다고 가정)은 모든 전역 이후 코드에서 매우 예측 가능한 위치에 생성됩니다.
- 느린 I / O 장치에 대한 인터페이스와 같은 리소스 지연 / 캐싱 시스템에 매우 유용 합니다. 느린 장치에 대한 단일 인터페이스를 지능적으로 구축하고 아무도 호출하지 않으면 시간을 낭비하지 않을 것입니다. 다른 코드가 여러 위치에서이를 호출하는 경우 싱글 톤은 두 가지 모두에 대해 동시에 캐싱을 최적화하고 이중 조회를 방지 할 수 있습니다. 또한 싱글 톤으로 제어되는 리소스에서 교착 상태를 쉽게 피할 수 있습니다.
싱글 톤에 대해 :
- C ++에서는 싱글 톤 후에 자동 정리하는 좋은 방법이 없습니다. 해결 방법과 약간 엉뚱한 방법이 있지만 싱글 톤의 소멸자가 항상 호출되도록하는 간단하고 보편적 인 방법은 없습니다. 이것은 메모리 측면에서 그렇게 끔찍한 것은 아닙니다.이 목적을 위해 더 많은 전역 변수로 생각하십시오. 그러나 싱글 톤이 다른 리소스를 할당하고 (예 : 일부 파일을 잠근다) 해제하지 않으면 좋지 않을 수 있습니다.
내 의견 :
싱글 톤을 사용하지만 합리적인 대안이 있다면 피하십시오. 이것은 지금까지 나를 위해 잘 작동했으며 테스트 할 작업이 약간 더 많지만 테스트 할 수 있음을 발견했습니다.
Google에는 Google 에서 생성 된 모든 코드에서 실행되어야하는 도구로 시작된 Java 용 Singleton Detector 가 있습니다. 싱글 톤을 제거하는 간단한 이유 :
테스트를 어렵게 만들고 설계 문제를 숨길 수 있기 때문입니다.
보다 명확한 설명은 Google의 ' Why Singletons Are Controversial '을 참조하십시오 .
싱글 톤은 멋진 드레스의 전역 변수입니다.
전역 변수는 싱글 톤과 마찬가지로 용도가 있지만, 엉뚱한 전역 변수를 사용하는 대신 싱글 톤으로 멋지고 유용한 일을하고 있다고 생각하면 (전역이 좋지 않다는 것을 누구나 알고 있습니다) 불행히도 오해를받습니다.
Singleton의 목적은 클래스에 인스턴스가 하나만 있는지 확인하고 이에 대한 전역 액세스 지점을 제공하는 것입니다. 대부분의 경우 초점은 단일 인스턴스 지점에 있습니다. 그것이 Globalton이라고 불렸다 고 상상해보십시오. 이것은 전역 변수의 (보통) 부정적인 의미를 강조하기 때문에 덜 매력적으로 들릴 것입니다.
싱글 톤에 대한 좋은 주장의 대부분은 테스트 더블을 생성하는 것이 쉽지 않기 때문에 테스트에서 나타나는 어려움과 관련이 있습니다.
Google 테스팅 블로그에는 Miško Hevery의 Singletons에 대한 3 개의 꽤 좋은 블로그 게시물이 있습니다.
싱글 톤은 많이 오용 되지만 끔찍한 패턴 은 아닙니다 . 이 오용은 더 쉬운 패턴 중 하나이고 싱글 톤에 가장 새로운 것이 글로벌 부작용에 끌리기 때문이라고 생각합니다.
Erich Gamma 는 싱글 톤이 GOF 책에 포함되지 않았 으면하는 패턴이며 잘못된 디자인이라고 말했습니다. 나는 동의하지 않는 경향이 있습니다.
주어진 시간에 개체의 단일 인스턴스를 만들기 위해 패턴을 사용하는 경우 패턴이 올바르게 사용되고있는 것입니다. 전역 효과를주기 위해 싱글 톤을 사용하면 잘못 사용되고있는 것입니다.
단점 :
- 싱글 톤을 호출하는 코드 전체에서 하나의 클래스에 연결됩니다.
- 인스턴스를 모의 객체로 교체하기가 어려우므로 단위 테스트가 번거 롭습니다.
- 둘 이상의 인스턴스가 필요하기 때문에 나중에 코드를 리팩토링해야하는 경우 단일 클래스를 사용하는 객체 (인터페이스 사용)에 전달되는 것보다 더 고통 스럽습니다.
장점 :
- 클래스의 한 인스턴스는 특정 시점에 표시됩니다.
- 의도적으로 이것을 시행하고 있습니다.
- 필요할 때 인스턴스가 생성됩니다.
- 글로벌 액세스는 부작용입니다
나는 싱글 톤을 거의 사용하지 않기 때문에 병아리가 나를 파헤친다. 아니요, 진지하게 저는 싱글 톤 패턴을 좋아합니다. 왜 그런지 알아? 때문에:
- 내가 게으른.
- 아무것도 잘못 될 수 없습니다.
물론, "전문가들"은 "단위 테스트"와 "종속성 주입"에 대해 많은 이야기를 던질 것이지만 그것은 모두 딩고의 신장에 대한 부하입니다. 싱글 톤이 단위 테스트하기 어렵다고? 문제 없어요! 모든 것을 공개로 선언하고 수업을 글로벌 선의 재미있는 집으로 바꾸십시오. 1990 년대 하이랜더 쇼 기억 나? 싱글 톤은 그 이유는 다음과 같습니다. A. 절대 죽을 수 없습니다. B. 하나만있을 수 있습니다. 그러니 모든 DI 위니들을 듣지 말고 포기로 싱글 톤을 구현하십시오. 여기에 더 좋은 이유가 있습니다 ...
- 모두가하고 있습니다.
- 싱글 톤 패턴은 당신을 무적으로 만듭니다.
- 싱글 톤은 "승리"(또는 억양에 따라 "재미")와 운율을 나타냅니다.
싱글 톤 패턴의 사용에 대해 큰 오해가 있다고 생각합니다. 여기에있는 대부분의 의견은이를 글로벌 데이터에 액세스 할 수있는 장소라고합니다. 여기서 조심해야합니다. 패턴으로서의 싱글 톤은 전역에 접근하기위한 것이 아닙니다 .
Singleton은 주어진 클래스의 인스턴스 를 하나만 갖기 위해 사용해야합니다 . Pattern Repository 에는 Singleton에 대한 훌륭한 정보가 있습니다.
제가 함께 일한 동료 중 한 명은 매우 싱글 톤에 관심이 많았습니다. 매니저 나 상사와 같은 물건이있을 때마다 그는 그것을 싱글 톤으로 만들었습니다. 왜냐하면 그는 상사가 한 명만 있어야한다고 생각했기 때문입니다. 그리고 시스템이 몇 가지 새로운 요구 사항을 받아 들일 때마다 여러 인스턴스를 허용해야하는 완벽한 이유가 있다는 것이 밝혀졌습니다.
도메인 모델이 하나가 있다고 ( '제안'이 아니라) 지시하는 경우 싱글 톤을 사용해야한다고 말하고 싶습니다. 다른 모든 경우는 클래스의 단일 인스턴스입니다.
나는 여기서 가난한 싱 겔톤의 구출에 올 수있는 방법을 생각하고 있었지만 그것이 어렵다는 것을 인정해야한다. 나는 그것들의 합법적 인 사용을 거의 보지 못했고 현재의 의존성 주입 및 단위 테스트를 수행하기 위해 사용하기가 어렵습니다. 그것들은 분명히 "GoF"책을 읽어 본 적이없는 많은 프로그래머들과 함께 일한 많은 프로그래머들과 함께 일한 디자인 패턴을 가진 프로그래밍의 "화물 컬트"표현입니다.하지만 그들은 'Singelton'을 알고 그래서 그들은 'Patterns'를 알고 있습니다.
하지만 저는 Orion에 동의하지 않습니다. 대부분의 경우 singeltons가 드레스의 글로벌 변수가 아니라 드레스의 글로벌 서비스 (방법)와 비슷하다는 것을 과용하는 것을 보았습니다. CLR 인터페이스를 통해 안전 모드에서 SQL Server 2005의 Singeltons를 사용하려고하면 시스템이 코드에 플래그를 지정한다는 점이 흥미 롭습니다. 문제는 실행될 수있는 주어진 트랜잭션을 넘어서는 영구 데이터가 있다는 것입니다. 물론 인스턴스 변수를 읽기 전용으로 만들면 문제를 해결할 수 있습니다.
그 문제로 인해 1 년 동안 많은 재 작업이 필요했습니다.
거룩한 전쟁! 알겠습니다 .. 제가 마지막으로 디자인을 확인했을 때 경찰이 ..
싱글 톤은 자동 테스트를 방해하기 때문에 좋지 않습니다. 각 테스트 케이스에 대해 인스턴스를 새로 만들 수 없습니다. 대신 로직은 쉽게 인스턴스화하고 테스트 할 수있는 클래스 (A)에 있어야합니다. 다른 클래스 (B)는 생성 제한을 담당해야합니다. 전면에 단일 책임 원칙! A에 액세스하려면 B를 통해 이동해야한다는 팀 지식이어야합니다. 일종의 팀 컨벤션입니다.
대부분 동의합니다 ..
많은 응용 프로그램에서는 일부 클래스의 인스턴스가 하나만 있어야하므로 클래스의 인스턴스가 하나만있는 패턴이 유용합니다. 그러나 패턴이 구현 되는 방법에는 차이가 있습니다 .
이 정적 싱글 (자바 클래스 로더 당 실제로 하나) 클래스 힘은 프로세스 당 클래스의 인스턴스가있을 수있는가. 또 다른 옵션은 인스턴스를 하나만 만드는 것 입니다.
정적 싱글 톤은 악의적 이며 전역 변수의 한 종류입니다. 테스트를 완전히 격리 할 수 없기 때문에 테스트가 더 어려워집니다. 모든 테스트 사이에 시스템을 정리하기 위해 복잡한 설정과 해체 코드가 필요하며, 일부 전역 상태를 올바르게 정리하는 것을 잊기 매우 쉽습니다. 따라서 테스트에서 지정되지 않은 동작이 발생할 수 있습니다.
인스턴스를 하나만 만드는 것이 좋습니다 . 프로그램이 시작될 때 하나의 인스턴스를 만든 다음 해당 인스턴스에 대한 포인터를 필요한 다른 모든 개체에 전달하면됩니다. 의존성 주입 프레임 워크는이를 쉽게 만듭니다. 객체의 범위를 구성하기 만하면 DI 프레임 워크가 인스턴스를 생성하고 필요한 모든 사람에게 전달합니다. 예를 들어 Guice에서는 @Singleton으로 클래스에 주석을 달고 DI 프레임 워크는 클래스의 인스턴스를 하나만 만듭니다 (애플리케이션 당-동일한 JVM에서 여러 애플리케이션을 실행할 수 있음). 이렇게하면 각 테스트에 대해 클래스의 새 인스턴스를 만들고 더 이상 사용되지 않을 때 가비지 수집기가 인스턴스를 파괴하도록 할 수 있으므로 테스트가 쉬워집니다. 한 테스트에서 다른 테스트로 글로벌 상태가 누출되지 않습니다.
For more information: The Clean Code Talks - "Global State and Singletons"
Singleton as an implementation detail is fine. Singleton as an interface or as an access mechanism is a giant PITA.
A static method that takes no parameters returning an instance of an object is only slightly different from just using a global variable. If instead an object has a reference to the singleton object passed in, either via constructor or other method, then it doesn't matter how the singleton is actually created and the whole pattern turns out not to matter.
It was not just a bunch of variables in a fancy dress because this was had dozens of responsibilities, like communicating with persistence layer to save/retrieve data about the company, deal with employees and prices collections, etc.
I must say you're not really describing somthing that should be a single object and it's debatable that any of them, other than Data Serialization should have been a singelton.
I can see at least 3 sets of classes that I would normally design in, but I tend to favor smaller simpler objects that do a narrow set of tasks very well. I know that this is not the nature of most programmers. (Yes I work on 5000 line class monstrosities every day, and I have a special love for the 1200 line methods some people write.)
I think the point is that in most cases you don't need a singelton and often your just making your life harder.
The biggest problem with singletons is that they make unit testing hard, particularly when you want to run your tests in parallel but independently.
The second is that people often believe that lazy initialisation with double-checked locking is a good way to implement them.
Finally, unless your singletons are immutable, then they can easily become a performance problem when you try and scale your application up to run in multiple threads on multiple processors. Contended synchronization is expensive in most environments.
Singletons have their uses, but one must be careful in using and exposing them, because they are way too easy to abuse, difficult to truly unit test, and it is easy to create circular dependencies based on two singletons that accesses each other.
It is helpful however, for when you want to be sure that all your data is synchronized across multiple instances, e.g., configurations for a distributed application, for instance, may rely on singletons to make sure that all connections use the same up-to-date set of data.
I find you have to be very careful about why you're deciding to use a singleton. As others have mentioned, it's essentially the same issue as using global variables. You must be very cautious and consider what you could be doing by using one.
It's very rare to use them and usually there is a better way to do things. I've run into situations where I've done something with a singleton and then had to sift through my code to take it out after I discovered how much worse it made things (or after I came up with a much better, more sane solution)
I've used singletons a bunch of times in conjunction with Spring and didn't consider it a crutch or lazy.
What this pattern allowed me to do was create a single class for a bunch of configuration-type values and then share the single (non-mutable) instance of that specific configuration instance between several users of my web application.
In my case, the singleton contained client configuration criteria - css file location, db connection criteria, feature sets, etc. - specific for that client. These classes were instantiated and accessed through Spring and shared by users with the same configuration (i.e. 2 users from the same company). * **I know there's a name for this type of application but it's escaping me*
I feel it would've been wasteful to create (then garbage collect) new instances of these "constant" objects for each user of the app.
I'm reading a lot about "Singleton", its problems, when to use it, etc., and these are my conclusions until now:
Confusion between the classic implementation of Singleton and the real requirement: TO HAVE JUST ONE INSTANCE OF a CLASS!
It's generally bad implemented. If you want a unique instance, don't use the (anti)pattern of using a static GetInstance() method returning a static object. This makes a class to be responsible for instantiating a single instance of itself and also perform logic. This breaks the Single Responsibility Principle. Instead, this should be implemented by a factory class with the responsibility of ensuring that only one instance exists.
It's used in constructors, because it's easy to use and must not be passed as a parameter. This should be resolved using dependency injection, that is a great pattern to achieve a good and testable object model.
Not TDD. If you do TDD, dependencies are extracted from the implementation because you want your tests to be easy to write. This makes your object model to be better. If you use TDD, you won't write a static GetInstance =). BTW, if you think in objects with clear responsibilities instead classes, you'll get the same effect =).
I really disagree on the bunch of global variables in a fancy dress idea. Singletons are really useful when used to solve the right problem. Let me give you a real example.
I once developed a small piece of software to a place I worked, and some forms had to use some info about the company, its employees, services and prices. At its first version, the system kept loading that data from the database every time a form was opened. Of course, I soon realized this approach was not the best one.
Then I created a singleton class, named company, which encapsulated everything about the place, and it was completely filled with data by the time the system was opened.
It was not just a bunch of variables in a fancy dress because this was had dozens of responsibilities, like communicating with persistence layer to save/retrieve data about the company, deal with employees and prices collections, etc.
Plus, it was a fixed, system-wide, easily accessible point to have the company data.
Singletons are very useful, and using them is not in and of itself an anti-pattern. However, they've gotten a bad reputation largely because they force any consuming code to acknowledge that they are a singleton in order to interact with them. That means if you ever need to "un-Singletonize" them, the impact on your codebase can be very significant.
Instead, I'd suggest either hiding the Singleton behind a factory. That way, if you need to alter the service's instantiation behavior in the future, you can just change the factory rather than all types that consume the Singleton.
Even better, use an inversion of control container! Most of them allow you to separate instantiation behavior from the implementation of your classes.
One scary thing on singletons in for instance Java is that you can end up with multiple instances of the same singleton in some cases. The JVM uniquely identifies based on two elements: A class' fully qualified name, and the classloader responsible for loading it.
That means the same class can be loaded by two classloaders unaware of each other, and different parts of your application would have different instances of this singleton that they interact with.
Write normal, testable, injectable objects and let Guice/Spring/whatever handle the instantiation. Seriously.
This applies even in the case of caches or whatever the natural use cases for singletons are. There's no need to repeat the horror of writing code to try to enforce one instance. Let your dependency injection framework handle it. (I recommend Guice for a lightweight DI container if you're not already using one).
참고URL : https://stackoverflow.com/questions/11831/singletons-good-design-or-a-crutch
'development' 카테고리의 다른 글
Windows에서 프로세스를 일시 중단 / 재개하는 방법은 무엇입니까? (0) | 2020.11.09 |
---|---|
ng-click의 if 문 (0) | 2020.11.09 |
ExpandableListView의 groupIndicator를 완전히 숨기려면 어떻게해야합니까? (0) | 2020.11.09 |
SIGSEGV를 잡기 위해 신호 핸들러를 작성하는 방법은 무엇입니까? (0) | 2020.11.08 |
PC 브라우저에서 터치 이벤트 시뮬레이션 (0) | 2020.11.08 |