Wann ein Singleton oder Borg?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

In welchen Fällen ist es denn ratsam diese Pattern zu nutzen?

Welche Alternativen bieten sich und wie sieht es in anderen Sprachen aus?

Das was ich bisher gelesen habe, besonders auf kritischen Seiten fasse ich mal so zusammen:
  • Abhängigkeiten werden verschleiert
  • eine Singletonklasse hat verschiedene Zuständigkeiten (Verstoß gegen das " Single Responsibility Principle").
  • es Enstehen die gleichhen Probleme wie mt globals
  • Tests schlagen fehl, je nachdem wie die Tests ausgeführt werden
gut, das ist jetzt nur von hier


Wenn ich mich nicht irre sind ``None`` und Module Singletons. Bei ``None`` ist es nicht weiter schlimm, weil man keine weitere Instanzen erstellen kann, aber bei Modulen kann das zu unerwünschten Nebeneffekten führen.

Wenn man Singletons einsetzt, möchte man sich ja das rumreichen von Argumenten ersparen. Wie erreiche ich dies denn in Sprachen wie Java, ohne ein Singleton zu nutzen?

Irgendwo habe ich gelesen, dass man eine Klasse mit einer default-Instanz verwenden sollte. So kann man immernoch weitere Instanzen erzeugen, hat aber auch die vorzüge des Singleton.

Auf einer anderen Seite las ich, dass Singletons kein OOP sei, sonderen eher globale Variablen erzeugt.

In einem anderen Blog fand ich:
Me: So! Have you ever heard of a book called Design Patterns?

Them: Oh, yeah, um, we had to, uh, study that back in my software engineering class. I use them all the time.

Me: Can you name any of the patterns they covered?

Them: I loved the Singleton pattern!

Me: OK. Were there any others?

Them: Uh, I think there was one called the Visitater.

Me: Oooh, that's right! The one that visits potatoes. I use it all the time. Next!!!

Nun habe ich auf solchen Seiten kein Beispiel gefunden, wo sie sagen: "Aber in dem Fall XYZ macht es ausnahmsweise einmal Sinn sie zu nutzen".
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Auf diese Frage gibt es 4 einfache Antworten:
  • Verwende sowieso nur Singletons
  • Verwende sowieso nur Borg
  • Singleton/Borg Pattern ist ein Verbrechen
  • Du musst eine eigene Entscheidung suchen
lunar

@jbs: Ich denke, man sollte soweit wie nur irgend möglich auf diese Muster verzichten. Letztlich sind beides nur andere Ansätze für globale Variablen.

Wenn man nun in die Verlegenheit kommt, viele Objekte wild herumreichen zu müssen, liegt das imho weniger am Verzicht auf den Einsatz dieses Entwurfsmusters, sondern eher an Fehlern im Entwurf, die zu wilden Abhängigkeiten führen.
BlackJack

@jbs: Das Muster sollte man verwenden, wenn es passt. ;-)

Die Frage ist auch ein wenig, was denn dieses Muster überhaupt ist. Wenn man von einer Klasse nur ein Exemplar erzeugt und kein weiteres, dann hat man de fakto ja auch ein Singleton. Module sind in Python im Regelfall Singletons.

IMHO ein wenig unpythonisch ist das Erzwingen von so etwas. Wenn man in einem Modul eine Klasse hat, die nicht zur öffentlichen API gehört und davon beim laden des Moduls oder über eine Funktion *ein* Exemplar erstellt und das öffentlich macht, dann reicht das IMHO.

Das mit der Testbarkeit hängt auch von der Sprache und der Bibliothek ab, die man für Mock-Objekte verwendet. Python ist da zum Beispiel deutlich flexibler als Java, weil man alles mögliche aus der Standardbibliothek kurzzeitig und dynamisch durch etwas anderes ersetzen kann. Mocker kann das zum Beispiel.

Ein Weg "echte" Singletons in Java zu umgehen, sind "dependency injection"-Rahmenwerke. Als kleines, leichtgewichtiges wäre da zum Beispiel Picocontainer zu erwähnen. Da reicht man die "globalen Singletons" nicht überall herum oder greift über statische Methoden darauf zu, sondern macht sie alle einem Container bekannt, der dann über die Typinformationen dafür sorgt, dass alles passend "zusammengesteckt" wird.

Solche Rahmenwerke machen bei dynamisch typisierten Programmiersprachen allerdings anscheinend nicht so viel Sinn. Über die nicht vorhandenen statischen Typinformationen kann man nicht gehen. Und das Verbinden über Konfigurationsdateien ist genau so lang und aufwändig, wenn nicht gar länger, als wenn man das gleich in der Sprache selbst formuliert. Es bleibt also nur eine Indirektion, die alles verkompliziert.
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

BlackJack hat geschrieben:IMHO ein wenig unpythonisch ist das Erzwingen von so etwas.
...das ist sowieso für mich äußerst fragwürdig. Wahrscheinlich bin ich zu dumm um zu verstehen, warum man den Programmierer ZWINGEN soll etwas zu tun, anstatt ordentlich die Abhängigkeiten und Schnittstellen zu dokumentieren.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

BlackVivi hat geschrieben:
BlackJack hat geschrieben:IMHO ein wenig unpythonisch ist das Erzwingen von so etwas.
...das ist sowieso für mich äußerst fragwürdig. Wahrscheinlich bin ich zu dumm um zu verstehen, warum man den Programmierer ZWINGEN soll etwas zu tun, anstatt ordentlich die Abhängigkeiten und Schnittstellen zu dokumentieren.
Ich glaube, das hat rein gar nichts mit Dummheit zu tun. Das ist halt auch eine Einstellungssache und ein Thema, bei der jeder seine eigene Meinung haben darf.

Ich persönlich halte auch einige Paradigmen der OO für viel zu strikt (und damit unflexibel). Z.B. wenn in C# ein Property eingesetzt wird, das nur simple Setter-und Getter-Methoden beinhaltet (return this.x; this.x = value). Verstehe auch nicht warum man hier nicht einfach ein public Attribut verwenden kann. Man will ja den Zugriff auf diese Daten der Klasse gar nicht einschränken. Trotzdem muss man ein Property erstellen, damit es mit Windows-Forms richtig funktioniert. Meiner Meinung nach sind das einfach einige Zeilen von unnötigem Code, was letztendlich die Fehleranfälligkeit erhöht und den Programmierer ausbremst.
Bin bei deinem Beispiel außerdem auch auf deiner Seite ;)

Um zum Thema zurückzukommen:
Statt einem Singleton erstelle ich eine Instanz auf Modulebene und dokumentiere, dass gefälligst diese Instanz verwendet werden soll und keine neue erstellt werden. Das muss meiner Meinung nach reichen.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ice2k3 hat geschrieben:Meiner Meinung nach sind das einfach einige Zeilen von unnötigem Code, was letztendlich die Fehleranfälligkeit erhöht und den Programmierer ausbremst.
Manche Sprachen bieten daher syntaktische Abstraktion durch... *trommelwirbel* Makros.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Leonidas hat geschrieben:Manche Sprachen bieten daher syntaktische Abstraktion durch... *trommelwirbel* Makros.
Wenn ich die Wahl der Programmiersprache nicht beeinflussen kann und mit C# arbeiten muss, bringt mir das irgendwie wenig ;)
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ach gibt doch bestimmt Lisp-C#-Compiler :twisted:
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Singleton eigentlich nur, wenn die Identität eine Rolle spielt, also wenn zB. folgendes funktionieren soll:

Code: Alles auswählen

class Highlander(object):
    def __new__(cls):
        try:
            return cls.__inst
        except AttributeError:
            cls.__inst = super(Highlander, cls).__new__(cls)
            return cls.__inst

Highlander = Highlander()
...
MacLeod = Highlander.__class__()
...
if MacLeod is Highlander:
    ...
In specifications, Murphy's Law supersedes Ohm's.
Antworten