@sprudel: Ich habe bis jetzt nur etwas mit dem Django-ORM und SQLAlchemy gemacht. Angeschaut hatte ich mir noch SQLObject. Für SQLAlchemy (SA) hatte ich mich entschieden, weil es um eine bereits bestehende Datenbank ging und ich den Eindruck hatte, das SA einem da am wenigsten Beschränkungen auferlegt, weil man beliebige Tabellen(teile) auf nahezu beliebige Klassen abbilden kann, wenn es sein muss. Selbst wenn man SQL hat, was nicht auf Klassen abgebildet wird, kann man das mit SA unabhängig von einem konkreten DBMS machen.
Das ist jetzt für Dein Projekt, wo Du die Datenbank selbst entwerfen kannst, natürlich nicht so wichtig. Und Elixir, was auf SA aufbaut, wurde ja auch schon erwähnt. Das macht das deklarieren von Klassen und Beziehungen etwas einfacher als es mit SA "zu Fuss" zu machen.
Deinen zweiten Punkt verstehe ich nicht ganz!? Und eine Datei pro Klasse ist nicht besonders "pythonisch". Eine Datei repräsentiert ein Modul und ein Modul sollte zusammengehörige "Dinge" enthalten. Wenn Du also eine Klasse hast, die eine Transaktion darstellt, und eine die eine einzelne Position auf so einer Transaktion darstellt, macht es durchaus Sinn, die im gleichen Modul zu haben. Ich persönlich stecke solche "Model-Klassen" in der Regel *alle* in ein Modul bis ich den Eindruck habe, dass es deutlich zu viele werden. Dann mach ich mich daran zu überlegen, wie man das sinnvoll in ein oder zwei Module zerlegen kann.
Der letzte Punkt erledigt sich wahrscheinlich von selbst, wenn Du Dir eine Einführung, ein Tutorial oder ein erklärendes Video zu einem der ORMs angeschaut hast.
Guter Programmierstil
Mal ne Frage: Würdet ihr eigentlich das Sqlalchemy direkt in die entsprechenden Klassen (Transaction, Product, usw.) einbauen, oder spezielle Klassen schreiben, die dann zu SQLALchemy gehören, und von dort aus dann die normalen Objekte generieren?
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Direkt in die Klassen einbauen. Proxy-Objekte führen schlussendlich dazu dass du Duplikation von Daten hast, wenn du dich nicht schlau anstellst und eine völlig nutzlose Zusatzebene.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Ich weiß, es ist eine blöde Frage, und hier so eigentlich nicht erwünscht.
Aber kann mir hier jemand mal ein grobes Beispiel (gerne auch schemenhaft) einer Beispielklasse (z.B. Transaction) machen, so wie ich das in SQLAlchemy lösen müsste?
Ich stelle mir das im groben (ohne SqlAlchemy) so vor:
Jetzt mal nur als Beispiel.
Aber kann mir hier jemand mal ein grobes Beispiel (gerne auch schemenhaft) einer Beispielklasse (z.B. Transaction) machen, so wie ich das in SQLAlchemy lösen müsste?
Ich stelle mir das im groben (ohne SqlAlchemy) so vor:
Code: Alles auswählen
class Transaction(object):
products = []
stornos = []
notes = []
payed = False
def addProduct(self,pobj):
self.products.append(pobj)
def getTotal(self):
total = 0.00
for pobj in self.products:
total += pobj.getPrice()
return total
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Ich sehe 4 Fehler. Oder 2 .. je nachdem wie man das betrachten will.
Willst du die Datenfelder nicht lieber in ein `__init__` schieben und an das Objekt binden?
Willst du die Datenfelder nicht lieber in ein `__init__` schieben und an das Objekt binden?
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Eben die 4 Attribute. Also nicht so dramatisch wie sich das evtl angehoert hat
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Dazu müßte man doch genau wissen, was diese Klasse leisten soll. Mir ist es im Moment nicht klar (und aus Deinem undokumentierten Ansatz geht das auch imho nicht hervor).sprudel hat geschrieben:Ich weiß, es ist eine blöde Frage, und hier so eigentlich nicht erwünscht.
Aber kann mir hier jemand mal ein grobes Beispiel (gerne auch schemenhaft) einer Beispielklasse (z.B. Transaction) machen, so wie ich das in SQLAlchemy lösen müsste?
Evtl. magst Du Dir doch zuerst mal Elixir angucken? Trotz der mittlerweile vorhandenen deklarativen Syntax bei SQLAlchemy halte ich Elixir immer noch für einfacher. Schau Dir doch da mal das Tutorial an - einfacher geht der Einstieg kaum (und er ähnelt Deinem Ansatz von der Komplexität hier ziemlich).
Zu Deinem Code fällt mir noch folgendes ein:
- beachte mehr PEP8, Einrückungen sollten 4 Spaces sein, Funktionen und Methoden werden klein_und_mit_underscore benannt. Zwischen Paramertern und dem abgrenzenden Komma immer ein Space
- "addProduct" kapselt letztlich direkt nur die append-Methode einer Liste. Daher kann man sich so etwas auch sparen.
- dieses "getPrice()" einer vermuteten Product-Klasse riecht auch zu sehr nach Java. Anstelle von Gettern und Settern nutzt man in Python eher Properties; sofern Du keine weiteren Tests oder Berechnungen in den Methoden vornimmst, kann man auch einfach direkt auf das Attribut zugreifen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Ich denke, dass diese zusätzliche Eben durchaus berechtigt ist: Möchte man zumeist nicht wissen, wenn ein - vermutlich als intern gedachtes, also mit _ prefixen (cooles Wort ) - Attribut verändert wird. Im jetzigen Zustand mag das noch nicht erforderlich sein, aber ich denke, dass er gewisse Aktionen ausführen will, sobald ein Produkt hinzugefügt oder entfernt wird, sodass die Daten untereinander konsistent sind. Nur solche Attribute, die ohne Komplikationen geändert werden dürfen, sollten als public markiert werden.Hyperion hat geschrieben:- "addProduct" kapselt letztlich direkt nur die append-Methode einer Liste. Daher kann man sich so etwas auch sparen.
In diesem Fall würde ich dir zustimmen. Besteht die Berechnung des Properties aus mehr als nur ein paar einfachen Statements, so würde ich doch eher zu einer explizizen getter-Methode greifen, um ersichtlich zu machen, dass es eben keine simple Operation ist.dieses "getPrice()" einer vermuteten Product-Klasse riecht auch zu sehr nach Java. Anstelle von Gettern und Settern nutzt man in Python eher Properties; sofern Du keine weiteren Tests oder Berechnungen in den Methoden vornimmst, kann man auch einfach direkt auf das Attribut zugreifen.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Ich bin ja auch vom jetzigen Zustand ausgegangen Wenn solche "Aktionen" tatsächlich notwendig sind, ist eine Methode natürlich erforderlich - aber dann kann ich sie ja immer noch einfügen. Vom Ausdruck "public" in Zusammenhang mit Attributen in Python würde ich übrigens absehen; das riecht zu sehr nach Zugriffskontrolle und weniger nach Konvention. Oben schreibst Du ja auch - wohl bewusst - intern.syntor hat geschrieben: Ich denke, dass diese zusätzliche Eben durchaus berechtigt ist: Möchte man zumeist nicht wissen, wenn ein - vermutlich als intern gedachtes, also mit _ prefixen (cooles Wort ) - Attribut verändert wird. Im jetzigen Zustand mag das noch nicht erforderlich sein, aber ich denke, dass er gewisse Aktionen ausführen will, sobald ein Produkt hinzugefügt oder entfernt wird, sodass die Daten untereinander konsistent sind. Nur solche Attribute, die ohne Komplikationen geändert werden dürfen, sollten als public markiert werden.
Hm... kommt imho drauf an. Bei komplexen und vor allem teuren Operationen handelt es sich ja zumeist auch nicht um das reine Setzen von Attributen, sondern um Funktionalität, die einem eine Klasse bietet. Da benennt man diese ja eh nach dieser. Ich war jedenfalls noch nie in so einer Situation, in der eine property zu komplex war.In diesem Fall würde ich dir zustimmen. Besteht die Berechnung des Properties aus mehr als nur ein paar einfachen Statements, so würde ich doch eher zu einer explizizen getter-Methode greifen, um ersichtlich zu machen, dass es eben keine simple Operation ist.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Guten Morgen, ihr Lieben.
Zuerst möchte ich mich mal für eure Hilfe Bedanken. Scheine ja wirklich ein ganz schönes Programmierchaos im Kopf zu haben. In der Arbeit wird ja auch eher Quick'n'Dirty verlangt, aber privat möchte ich es schon richtig machen.
So wie es aussieht, habe ich einen ruhigen Arbeitstag, die Computer tuen, und die Benutzer sind zufrieden. Ich werde aller Wahrscheinlichkeit eure Fragen heute also zeitnah beantworten können.
Aber fangen wir mal an:
Zu Deinem Code fällt mir noch folgendes ein:
Werde mir die Pythonstandard antrainieren.
Zuerst möchte ich mich mal für eure Hilfe Bedanken. Scheine ja wirklich ein ganz schönes Programmierchaos im Kopf zu haben. In der Arbeit wird ja auch eher Quick'n'Dirty verlangt, aber privat möchte ich es schon richtig machen.
So wie es aussieht, habe ich einen ruhigen Arbeitstag, die Computer tuen, und die Benutzer sind zufrieden. Ich werde aller Wahrscheinlichkeit eure Fragen heute also zeitnah beantworten können.
Aber fangen wir mal an:
Ich habe mir das so vorgestellt, dass ein gesamter Verkaufsprozess dort erfasst wird. Also die Produktobjekte, das Kundenkonto, eine Liste von Transaktionen (also z.B. Storno, oder Rabatt, reiner Text und Zeitangabe. Wird wohl wieder ein kleines Objekt werden.Dazu müßte man doch genau wissen, was diese Klasse leisten soll. Mir ist es im Moment nicht klar (und aus Deinem undokumentierten Ansatz geht das auch imho nicht hervor).
Habe mir beide schon etwas angeschaut, werde das aber nochmal gründlich wiederholen.Evtl. magst Du Dir doch zuerst mal Elixir angucken? Trotz der mittlerweile vorhandenen deklarativen Syntax bei SQLAlchemy halte ich Elixir immer noch für einfacher. Schau Dir doch da mal das Tutorial an - einfacher geht der Einstieg kaum (und er ähnelt Deinem Ansatz von der Komplexität hier ziemlich).
Zu Deinem Code fällt mir noch folgendes ein:
Das war jetzt nur kurz in Gedit geschrieben, normalerweise verwende ich Eclipse, und da ist das schon voreingestellt.- beachte mehr PEP8, Einrückungen sollten 4 Spaces sein, Funktionen und Methoden werden klein_und_mit_underscore benannt. Zwischen Paramertern und dem abgrenzenden Komma immer ein Space
Ich habe bereits an die Zukunft gedacht... und ich rechne damit, dass da nochmal was an Funktionalität dazu kommen wird.- "addProduct" kapselt letztlich direkt nur die append-Methode einer Liste. Daher kann man sich so etwas auch sparen.
Erwischt, wobei es bei mir eher C++ mit wxWidgets ist. und bei wxWidgets heißen die Methoden nunmal so... und das hat mir eben gefallen.- dieses "getPrice()" einer vermuteten Product-Klasse riecht auch zu sehr nach Java. Anstelle von Gettern und Settern nutzt man in Python eher Properties; sofern Du keine weiteren Tests oder Berechnungen in den Methoden vornimmst, kann man auch einfach direkt auf das Attribut zugreifen.
Werde mir die Pythonstandard antrainieren.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Das ist jetzt aber reine Datenhaltung und spiegelt keinerlei Funktionalität wieder. Also ich denke nicht, dass Dir hier jemand daraus etwas bastelt. Ich würde an Deiner Stelle eben einfach selber anfangen, das alles Schritt für Schritt zu implementieren. Du wirst eh das ein oder andere wegschmeißen und dank neuer Erkenntnisse nach implementieren müssen.sprudel hat geschrieben: Ich habe mir das so vorgestellt, dass ein gesamter Verkaufsprozess dort erfasst wird. Also die Produktobjekte, das Kundenkonto, eine Liste von Transaktionen (also z.B. Storno, oder Rabatt, reiner Text und Zeitangabe. Wird wohl wieder ein kleines Objekt werden.
Zudem kannst Du nicht mit dem "Integrations"-Objekt anfangen, sondern musst ja zuerst die "Rand"-Klassen implementieren. Ansonsten kannst Du keine (funktionierenden) Relationen definieren.
Auch schon mal camelot? Imho könnte das genau das richtige für Dich sein!Habe mir beide schon etwas angeschaut, werde das aber nochmal gründlich wiederholen.
Aber nicht die BenennungDas war jetzt nur kurz in Gedit geschrieben, normalerweise verwende ich Eclipse, und da ist das schon voreingestellt.- beachte mehr PEP8, Einrückungen sollten 4 Spaces sein, Funktionen und Methoden werden klein_und_mit_underscore benannt. Zwischen Paramertern und dem abgrenzenden Komma immer ein Space
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Wir haben bei unserer Warenwirtschaft mittlerweile 378 Tabellen. Ich hoffe nicht, dass es jemand in seiner Freizeit so weit treiben will.burli hat geschrieben:Es hängt davon ab, wie weit du das treiben willst. Um es einfach nur mal auszuprobieren reichen die vier Klassen für den Anfang
Kann es sein, dass es da einer mit der Normalisierung etwas übertrieben hat? Man muss nicht für jede Spalte eine eigene Tabelle anlegen. Man kann auch mehrere thematisch zusammengehörende Spalten zusammenfassenNoah hat geschrieben:Wir haben bei unserer Warenwirtschaft mittlerweile 378 Tabellen. Ich hoffe nicht, dass es jemand in seiner Freizeit so weit treiben will.
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
@Noah
Jetzt wäre es natürlich noch interessant wieviele Datenssätze auf die 378 Tabellen kommen. Einfach nur um sich auch so wie burli darüber zu amüsieren
Aber in meiner Freizeit, habe ich das bisher auch noch nicht so weit getrieben.
Jetzt wäre es natürlich noch interessant wieviele Datenssätze auf die 378 Tabellen kommen. Einfach nur um sich auch so wie burli darüber zu amüsieren
Aber in meiner Freizeit, habe ich das bisher auch noch nicht so weit getrieben.
Das kommt auf die Größe des Kunden an. Ich hab mal die Gesamtanzahl auf einer großen Kundendatenbank ermittelt:Xynon1 hat geschrieben:@Noah
Jetzt wäre es natürlich noch interessant wieviele Datenssätze auf die 378 Tabellen kommen. Einfach nur um sich auch so wie burli darüber zu amüsieren
33020205
33mio Datensätze, meine güte...
Die verkaufen auch viel kleinzeug, heißt Aufträge mit vielen Positionen. Umsätze ausrechenen dauert dort ein ganzes Wochenende
Es sind dort übrigens nur 314 Tabellen gefüllt, da ja nicht jeder Alle funktionen nutzt...
Nett, noch nicht die Welt, aber dennoch nett, für ein paar Rechnungen, Statistiken und andere kleinere Auswertungen wird es wohl reichen
Ja, wenn ich den bekloppten Rechnungsdruck wieder zum Laufen bekomme... Und von der Statistik will ich gar nicht reden. Ist alles Code der alle VB-Versionen ab 1.0 durchgemacht hat und jetzt auf VB.NET portiert wird.Xynon1 hat geschrieben:Nett, noch nicht die Welt, aber dennoch nett, für ein paar Rechnungen, Statistiken und andere kleinere Auswertungen wird es wohl reichen
Am liebsten würde ich ja alles in python neu schreiben, aber das geht verständlicherweise nicht...