Umstieg von Java zu Python

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.
deamon
User
Beiträge: 63
Registriert: Mittwoch 8. Oktober 2008, 11:14

Beitragvon deamon » Mittwoch 26. November 2008, 15:08

Ich möchte diese interessante Diskussion noch mal um zwei Punkte erweitern, nämlich Depency Injection (DI) und aspekt-orientierte Programmierung (AOP).

Mir scheint es so, als wäre in der Python-Welt der Bedarf nach einem Framework für DI nicht so vorhanden, obwohl es dort auch welche gibt. Warum ist das so?

Ähnlich ist es mit AOP. Ich habe sogar mal die Aussage gelesen, dass AOP eine Erfingung aus dem Reich der statisch typisierten Sprachen wäre und man sowas bei Python mit seinen Möglichkeiten zur Metaprogrammierung gar nicht bräuchte. Wie seht ihr das? Ich halte AOP auch bei Python für sehr interessant!
DasIch
User
Beiträge: 2405
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Beitragvon DasIch » Mittwoch 26. November 2008, 15:42

Zum Thema Typprüfung sind eventuell Abstract Base Classes interessant.
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

Beitragvon keppla » Mittwoch 26. November 2008, 18:40

deamon hat geschrieben:Ich möchte diese interessante Diskussion noch mal um zwei Punkte erweitern, nämlich Depency Injection (DI) und aspekt-orientierte Programmierung (AOP).


Zu DI kann ich gerade nichts sagen, weil ich es glaube ich gerade mit ein paar anderen Konzepten verwechsele.

Zur AOP mal als Beispiel logging:

Code: Alles auswählen

def log(func):
  def wrapper(*args, **kwargs):
    print 'called %s' % func
    return func(*args, **kwargs)
  return wrapper

@log
def greet(name):
   print "hello, %s" % name


Weil man jede Funktion und jede Methode "wrappen" kann, werden viele der Aufgaben, um die sich in anderen Sprachen AOP-Frameworks kümmern würden, überflüssig.[/code]
BlackJack

Beitragvon BlackJack » Mittwoch 26. November 2008, 20:01

@Leonidas: Javaianer greifen nicht auf Bibliotheken zu, die es nur in C gibt. Sie sind viel schlauer: Sie programmieren das lieber alles noch einmal in Java nach. :-)

@daemon: Diese Angst, dass unter seltenen Umständen etwas kracht weil ein falscher Typ übergeben wurde, wird IMHO überbewertet. Für ein grösseres, robustes Projekt muss man sowieso Unit-Tests schreiben, die möglichst den gesamten Code abdecken, da fallen solche Missgeschicke in der Regel auf, und die Unit-Tests lassen einen auch über Fehler stolpern, die eine statische Typprüfung auch nicht gefunden hätte.

Was meinst Du mit "regelmässiger Prüfung zur Laufzeit"? Zur Laufzeit wird regelmässig zumindest der "duck type" geprüft. Ist ja nicht so, dass Python untypisiert wäre.

Habe mal kurz nachgelesen was DI ist. So im kleinen kann man das Java-Beispiel auf Wikipedia ja problemlos in Python umsetzen. Nach dem Beispiel habe ich mich gefragt wozu man dafür wohl ein Rahmenwerk braucht und habe entsprechend nach Python-Rahmenwerken gesucht. Die zwei die ich gefunden habe, hatten in der Beschreibung was von XML-Konfigurationsdateien stehen. Da habe ich nicht weiter gelesen und entschieden, dass ich das in Python nicht brauche. :-)

@sma: Gtk, GooCanvas, und Gstreamer würde ich nicht als betriebssystemspezifisch bezeichnen.
lunar

Beitragvon lunar » Mittwoch 26. November 2008, 20:16

BlackJack hat geschrieben:@Leonidas: Javaianer greifen nicht auf Bibliotheken zu, die es nur in C gibt. Sie sind viel schlauer: Sie programmieren das lieber alles noch einmal in Java nach. :-)

Klar, ist doch logisch ... die existierenden Bibliotheken wurden ja alle in so veralteten Sprachen wie C geschrieben. Das will doch kein Mensch nutzen ;)

Habe mal kurz nachgelesen was DI ist. So im kleinen kann man das Java-Beispiel auf Wikipedia ja problemlos in Python umsetzen.

Also ich finde an diesem Beispiel zwei Dinge toll: Zum einen ist das für eine so simple Sache erstaunlich viel Code, zum anderen finde ich den Sarkasmus in diesem Beispiel lustig: "EnterpriseFactoryObserverFactoryCreator" ist ein passender Name für Java und seine Entwurfsmusteritis ;)
deamon
User
Beiträge: 63
Registriert: Mittwoch 8. Oktober 2008, 11:14

Beitragvon deamon » Mittwoch 26. November 2008, 21:07

BlackJack hat geschrieben:@Leonidas: Javaianer greifen nicht auf Bibliotheken zu, die es nur in C gibt. Sie sind viel schlauer: Sie programmieren das lieber alles noch einmal in Java nach. :-)


Ich weiß schon, wie du es gemeint hast, aber es ist wirklich schlau. C ist keine tolle Sprache und wir haben ihr und C++ etwa die Hälfte aller Sicherheitslücken zu verdanken! In Java kann man keine Pufferüberläufe programmieren (es können höchstens welche in der Laufzeitumgebung vorkommen, die nicht in Java geschrieben ist, aber das ist vergleichsweise selten). Der große Vorteil von Java-Bibliotheken ist, dass man wirklich nur eine JVM als Basis braucht. Ich schätze das sehr.

BlackJack hat geschrieben:Was meinst Du mit "regelmässiger Prüfung zur Laufzeit"? Zur Laufzeit wird regelmässig zumindest der "duck type" geprüft. Ist ja nicht so, dass Python untypisiert wäre.

Ich meinte eine explizite Prüfung im Programm, aber vermutlich war ich da gedanklich falsch, weil ich Ducktyping nicht bedacht hatte.

BlackJack hat geschrieben:Habe mal kurz nachgelesen was DI ist. So im kleinen kann man das Java-Beispiel auf Wikipedia ja problemlos in Python umsetzen. Nach dem Beispiel habe ich mich gefragt wozu man dafür wohl ein Rahmenwerk braucht [...]


In der Tat ist es eigentlich ganz einfach. Aber es gibt dann eben doch viele Details, an die die Macher eines Frameworks schon gedacht haben und die man bestenfalls mit der Zeit nach und nach neu erfinden würde. Bei Spring ist z. B. die Reihenfolge der Deklaration der zu verschaltenden Objekte egal. Oder man kann anhand von Typinformationen optional autoamtisch verschalten lassen, man kann definieren, ob ein Objekt ein Singleton sein soll, oder ob es für jede Anfrage neu erzeugt wird ...

Aber vom Prinzip ist es einfach und man könnte das auch ohne Framework hinbekommen.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Beitragvon sma » Mittwoch 26. November 2008, 21:27

Das CommonLisp-Object-System (CLOS) kannte bereits Anfang der 90er :before, :after und :around-Methoden. Wahrscheinlich kannten die Vorgänger Flavors und Loops das auch schon, ich habe das nicht recherchiert.

Diese Methoden und mehr wurden in dem (für Lisp-Fans lesenswerten) Buch "The Art of the Metaobject Protocol" von genau dem Gregor Kiczales beschrieben, der Jahre später dann AspectJ gebaut hat und einem komplexen Formalismus mit Pointcuts, Jointpoints, Advices und Aspekten entwickelt hat. Somit ist das nichts grundsätzlich Neues.

Die Idee eines Aspekts ist naheliegend und kann z.B. durch Mixins (AFAIK eine Erfindung von Flavors) realisiert werden, die dank dynamischer mehrfacher Vererbung in Python trivial ist. Eine ähnliche, modernere Idee sind Traits. Die anderen Methoden lassen sich mit decorators auf einfache Weise realisieren. Decorators systematisch an bestimmte Funktionen (pointcuts) zu hängen, müsste man in Python allerdings mittels Metaprogrammierung realisieren und kann das nicht deklarativ erledigen.

Allgemein ist aber IMHO die Aussage richtig, das Python bereits ausdrucksstark genug ist, um keine spezielle Syntax oder Sprachvariante für AOP zu benötigen. In Lisp wäre es dank besserer Metaprogrammierung (Stichwort Makros) noch einfacher.

Dependency-Injection ist eigentlich nur die Idee, einzelne Klassen mit möglichst wenig gegenseitigen Abhängigkeiten zu entwerfen, um sie so getrennt voneinander möglichst gut testbar zu gestalten. Die Aufgabe, das Objektnetz zusammenzustecken, überlässt man jemand anderem. Statt sich hier jedoch eine komplizierte XML-Syntax (so wie es Spring macht) auszudenken, kann man das Zusammenstecken bei Python auch einfach in Python machen.

Eine Aufteilung in Interfaces und Implementierung ist bei python unnötig. Getter und Setter in der Regel auch.

Schaut man sich ein Beispiel von Fowlers an:

Code: Alles auswählen

<beans>
    <bean id="MovieLister" class="spring.MovieLister">
        <property name="finder">
            <ref local="MovieFinder"/>
        </property>
    </bean>
    <bean id="MovieFinder" class="spring.ColonMovieFinder">
        <property name="filename">
            <value>movies1.txt</value>
        </property>
    </bean>
</beans>

entspricht dies

Code: Alles auswählen

movieLister = MovieLister()
movieFinder = MovieFinder()

movieLister.finder = movieFinder
movieFinder.filename = "movies1.txt"

Um näher am Original zu sein, muss man allerdings ein bisschen tricksen. Allgemein muss man Instantiierung und Initialisierung trennen, sondern kann man keine sich gegenseitig referenzierenden Strukturen bauen. Ich glaube, Spring nutzt hier Proxy-Objekte. Könnte man in Python auch.

Oder vielleicht so:

Code: Alles auswählen

class Ref:
    def __init__(self, name): self.name = name

def bind(dct):
    for o in dct.values():
        for k, v in o.__dict__.items():
            if isinstance(v, Ref):
                setattr(o, k, dct[v.name])

movieLister = MovieLister(Ref('movieFinder'))
movieFinder = MovieFinder("movies1.xt")

bind(locals())

Das vergleiche man mit dem Aufwand, den Spring für den selben Effekt treibt :)

Stefan
deamon
User
Beiträge: 63
Registriert: Mittwoch 8. Oktober 2008, 11:14

Beitragvon deamon » Freitag 28. November 2008, 11:10

Für eine einfache Verschaltung bräuchte man in Java auch kein Framework. Das wäre auch dort ähnlich einfach wie in dem Python-Beispiel möglich.

Code: Alles auswählen

MovieLister movieLister = new MovieLister();
MovieFinder movieFinder = new MovieFinder();

movieLister.setFinder(movieFinder);
movieFinder.setFilename("movies1.txt");


Aber das ist es ja nicht, was ein DI-Framework ausmacht. Ein DI-Framework wie Spring nimmt einem die Auflösung der (auch zyklischen) Abhängigkeiten ab und kann teilweise automatisch Objekte konfigurieren.

Meine Frage ziele aber darauf ab, warum DI im Python-Lager scheinbar nicht so gefragt ist. Welche andere Programmierphilosophie wird verfolgt, dass DI keinen so hohen Stellenwert hat. Meine These ist, dass Abhängigkeiten eher in Kauf genommen werden, weil man ja (fast) immer den Quelltext vorliegen hat und dort bei Bedarf direkt ändern kann.

Das ist vielleicht weniger Elegant als die Objekte an einer Stelle außerhalb exlizit zu konfigurieren, aber ich glaube, dass bei Skriptprogrammierung zu Gunsten der Einfachheit vieles nicht so elegant ist, dafür ist es aber einfacher und das ist ja auch ein Wert für sich.
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

Beitragvon veers » Freitag 28. November 2008, 11:42

Also ich finde das ehrlich gesagt eleganter als ein gigantisches XML.
Ich habe oft ein application.py Modul o.ä. was dann die einzelnen Komponenten zu einer Applikation zusammen steckt. Finde ich einfacher und mächtiger als gigantische XML Dateien.
My Website - 29a.ch
"If privacy is outlawed, only outlaws will have privacy." - Phil Zimmermann
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Beitragvon Darii » Freitag 28. November 2008, 14:22

Das würde ich auch sagen, Python ist elegant genug, dass man keine XML-Datei braucht, damit es nicht noch hässlicher wird(und XML ist imo verdammt hässlich). Ruby ist da ja noch viel extremer als Python, da die Sprache viel flexibler ist.
deamon
User
Beiträge: 63
Registriert: Mittwoch 8. Oktober 2008, 11:14

Beitragvon deamon » Freitag 28. November 2008, 16:20

Darii hat geschrieben:Das würde ich auch sagen, Python ist elegant genug, dass man keine XML-Datei braucht, damit es nicht noch hässlicher wird(und XML ist imo verdammt hässlich).


Es geht nicht darum, ob die Konfiguration von Objekten in XML stattfindet oder nicht. Man kann Spring auch mit Java (oder Groovy) konfigurieren. Es geht darum, dass diese Form der externen Konfiguration von Objekten (mit Hilfe eines Frameworks) in Python scheinbar nicht so beliebt ist.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Beitragvon Darii » Freitag 28. November 2008, 17:24

deamon hat geschrieben:Es geht darum, dass diese Form der externen Konfiguration von Objekten (mit Hilfe eines Frameworks) in Python scheinbar nicht so beliebt ist.
Und das war meine Vermutung/Meinung warum das so ist.
lunar

Beitragvon lunar » Freitag 28. November 2008, 19:09

Darii hat geschrieben:
deamon hat geschrieben:Es geht darum, dass diese Form der externen Konfiguration von Objekten (mit Hilfe eines Frameworks) in Python scheinbar nicht so beliebt ist.
Und das war meine Vermutung/Meinung warum das so ist.

Warum sollte es das sein?

In Java mit seiner statischen Typisierung ist eine Aufteilung in Schnittstelle und Implementierung erzwungen. Auch ist dynamischer Java-Code viel schwerer zu schreiben, weil man mit Reflection arbeiten muss. Python dagegen hat ein dynamisches Objektmodell, dass Objekte nicht über Typ, sondern Verhalten identifiziert. Außerdem ist Metaprogrammierung in Python straigt-forward, während sie in Java einfach furchtbar ist. Da ist also nichts, für das man groß ein Framework bräuchte, weil Python viel einfacher ist als jedes Framework, das man dafür bauen könnte ...
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Beitragvon Darii » Freitag 28. November 2008, 19:18

lunar hat geschrieben:Warum sollte es das sein?
Ist die Frage an mich gerichtet? Denn was du da schreibst, ist das was ich meine, nur ausführlicher.
lunar

Beitragvon lunar » Freitag 28. November 2008, 19:40

Darii hat geschrieben:
lunar hat geschrieben:Warum sollte es das sein?
Ist die Frage an mich gerichtet? Denn was du da schreibst, ist das was ich meine, nur ausführlicher.[/quote
Nein, an deinen Vorposter deamon. Hab das falsche Posting zitiert.

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder