Hi,
ich bin bei meinem Projekt fast mit der Basis fertig. Problem ist, ich weiß nicht genau, wie es sich Performancemäßig entwickeln wird, da es komplett Objektorientiert ist und sehr Abstrakte Klassen hat (daher viele kleine Klassen, die leicht erweiterbar sind und immer nur eine konkrete Aufgabe erfüllen).
Hat jemand Erfahrungen mit PHP Projekten bei denen sehr viele Klassen im Einsatz sind und größere Anzahlen von Vererbungen? (> 100 Klassen)
Zu den Fakten der Größenordnung:
Ich hab derzeit 75 Klassen, die im Durchschnitt 50 Zeilen PHP Code enthalten (und ca. 80-100 Zeilen Kommentare dazu). Vererbung spielt bei mehr als der Hälfte aller Klassen eine Rolle, daher Sie sind selbst nur abgeleitet. Außerdem hat jede Klasse eine eigene Datei bei mir und wird nur bei Bedarf geladen (derzeit 140 "require_once" enthalten). Mit allen Einstellungsdateien und bisherigen Sprachdateien hab ich 120 Dateien.
Bisher läuft alles noch recht flüssig. Problem ist halt, das ist bisher fast alles nur die rohe Basis, die kaum etwas mit einem Browsergame zu tun hat (alles allgemeine Sachen, die man in jedem Projekt verwenden könnte). Dazu kommen nochmal um die 60 Klassen für das Browsergame, die zwar nicht alle bei jedem Aufruf, aber doch des öfteren geladen werden müssen.
Wollte halt nur mal wissen, ob ich es übertreibe mit der Anzahl meiner Klassen und nicht doch lieber wieder mehr Funktionalitäten zusammenfasse, auch wenn darunter die Wartbarkeit und Flexibilität leiden würde.
Objektorientiert = Langsam in der Performance?
gepostet vor 17 Jahre, 3 Monate von DrakeL
gepostet vor 17 Jahre, 3 Monate von Fornax
Original von DrakeL
Außerdem hat jede Klasse eine eigene Datei bei mir und wird nur bei Bedarf geladen (derzeit 140 "require_once" enthalten). Mit allen Einstellungsdateien und bisherigen Sprachdateien hab ich 120 Dateien.
bzgl. require_once: Schau dir mal __autoload an, das ist sehr praktisch
Bei mir sieht die so aus:
function __autoload($class) {
$file = PATH_CLASS.'/'.strtolower($class).'.php';
if(!file_exists($file)){
return false;
}
include_once($file);
return true;
}
Das muss dann sehr weit an den Anfang des Scripts (bei mir in einer header-Datei die Konstanten definiert, Datenbankverbindung aufbaut etc.).
Wegen der Anzahl der Klassen: Mir erscheint das recht viel, da ich bei mir eher wenige - aber dafür größere - Klassen verwende. Aber ich denke, damit sollte PHP klarkommen.
gepostet vor 17 Jahre, 3 Monate von DrakeL
Autoload geht sehr schlecht, da meine Klassennamen nicht direkt auf den Pfad schliessen lassen, zum Beispiel ein paar Klassen und Pfade:
Klasse um Tabellenbeschreibungen anzulegen:
"Helpclass/Database/Description.php"
Klasse zum Validieren von E-Mails:
"Helpclass/Validator/EmailValidator.php"
Klasse zum Bearbeiten von einzelnen Benutzern:
"Database/MemberDatabase.php"
Hab halt die Klassen Thematisch in Ordnern hinterlegt. Da kann ich sehr schlecht über Autoload etwas machen. Außerdem finde ich Autoload eher hässlich, da ich im Moment am Anfang jeder Datei die Sachen lade, die in der Datei gebraucht werden und ich (vor allem im Eclipse im Dateibaum) sehr schön sehe wer von wem abhängig ist.
Bei PHP machts mir halt Sorgen, da er ja wirklich bei jedem Seitenaufruf alle Klassen laden und parsen muss (hab kein Compilercache verfügbar solang ich auf einem Webspace arbeite). Und bei so vielen Klassen kann ich mir schon vorstellen, dass das Parsen dann doch etwas länger dauert.
PS: Höchstens ich definiere mir ein Array, in welchem die Klassen und Ihre Pfade definiert sind und greife damit dann drauf zu.
function __autoload($class) {
global $classpaths;
include_once $classpaths[$class];
}
Braucht Autoload Funktion überhaupt ne Rückgabe? eigentlich ja nicht.
Klasse um Tabellenbeschreibungen anzulegen:
"Helpclass/Database/Description.php"
Klasse zum Validieren von E-Mails:
"Helpclass/Validator/EmailValidator.php"
Klasse zum Bearbeiten von einzelnen Benutzern:
"Database/MemberDatabase.php"
Hab halt die Klassen Thematisch in Ordnern hinterlegt. Da kann ich sehr schlecht über Autoload etwas machen. Außerdem finde ich Autoload eher hässlich, da ich im Moment am Anfang jeder Datei die Sachen lade, die in der Datei gebraucht werden und ich (vor allem im Eclipse im Dateibaum) sehr schön sehe wer von wem abhängig ist.
Bei PHP machts mir halt Sorgen, da er ja wirklich bei jedem Seitenaufruf alle Klassen laden und parsen muss (hab kein Compilercache verfügbar solang ich auf einem Webspace arbeite). Und bei so vielen Klassen kann ich mir schon vorstellen, dass das Parsen dann doch etwas länger dauert.
PS: Höchstens ich definiere mir ein Array, in welchem die Klassen und Ihre Pfade definiert sind und greife damit dann drauf zu.
$classpaths = array('MemberDatabase' => 'Database/MemberDatabase.php');
function __autoload($class) {
global $classpaths;
include_once $classpaths[$class];
}
Braucht Autoload Funktion überhaupt ne Rückgabe? eigentlich ja nicht.
gepostet vor 17 Jahre, 3 Monate von Fornax
Das mit dem Array ist denke ich das sinnvollste. Alle 100 Klassen zu laden ist ja recht.. unnötig
Nein, braucht es nicht, aber ich habe mir angewöhnt, dass ich Funktionen einen Rückgabewert gebe (ist immer mal nützlich).
Nein, braucht es nicht, aber ich habe mir angewöhnt, dass ich Funktionen einen Rückgabewert gebe (ist immer mal nützlich).
gepostet vor 17 Jahre, 3 Monate von Nuky
Die Anzahl kommt mir auch hoch vor - schon davon gehört das OO ein Werkzeug, nicht ein Allheilmittel ist?
Sofern du nicht auf jeder Seite 30-40 Includes hast (oder mindestens einen Cache!) sollte es damit wenig Probleme geben. Habe das ExV2 für einen Auftrag umgeschrieben - das braucht pro Seite ernsthaft um die 30 Includes, die sich tlw. rekursiv inkludieren. Ist nicht ganz der Sinn der Sache denk ich mal, aber auf unserem Server lauft das nebenher ohne Probleme - mit EAccelerator an.
Sofern du nicht auf jeder Seite 30-40 Includes hast (oder mindestens einen Cache!) sollte es damit wenig Probleme geben. Habe das ExV2 für einen Auftrag umgeschrieben - das braucht pro Seite ernsthaft um die 30 Includes, die sich tlw. rekursiv inkludieren. Ist nicht ganz der Sinn der Sache denk ich mal, aber auf unserem Server lauft das nebenher ohne Probleme - mit EAccelerator an.
gepostet vor 17 Jahre, 3 Monate von DrakeL
Bisher hab ich einen Webspace für meine Sachen, darauf bekomme ich auf jeden Fall keine Compilercache. Ob ich mir für den laufenden Betrieb später einen Server leisten kann ist ungewiss bzw. unwahrscheinlich.
Bisher beschränken sich die includes auf maximal 5 Stück pro Datei, die meisten haben nur 1-2 enthalten.
Das OO nur ein Werkzeug ist ist mir schon klar. Nur wenn man es konsequent einsetzt, sodass man sehr flexible bleibt wird es halt etwas krass mit der Zeit.
Ich hab 11 Systemkerne (Connection, Configfile, Session, Plugins z.b.) die bei jedem Seitenaufbau gebraucht werden. dann nen großer Batzen sind meine Validator Klassen zum validieren von Daten aus Formularen (String, Numeric, EMail usw.) und das ganze nochmal pro Validator eine Display Klasse für die Anzeige. Dann hab ich für jede Tabelle in der Datenbank eine Klasse die den Zugriff darauf regelt, sind auch nochmal 13 Stück. Macht allein für die paar Sachen um die 45 Klassen. und und und... halt
Sind eigentlich nur so 5-6 größere Dinge, die die Klassen übernehmen. Klar könnt ich daraus 5-6 Klassen machen, aber die werden gross unübersichtlich und schlecht erweiterbar. So wie ich es bisher hab kann ich für einen neuen Datentyp zum validieren einfach ne neue Klasse rein schieben und fertig. Oder einzelne Klassen austauschen oder weitergeben.
Aber um die 50 includes werdens auf jeden Fall pro Seitenaufruf. Vor allem wenn auf der Seite Formulare (Validator und Formularelemente) oder tabellarischen Daten (Display Klassen) sind.
Bisher beschränken sich die includes auf maximal 5 Stück pro Datei, die meisten haben nur 1-2 enthalten.
Das OO nur ein Werkzeug ist ist mir schon klar. Nur wenn man es konsequent einsetzt, sodass man sehr flexible bleibt wird es halt etwas krass mit der Zeit.
Ich hab 11 Systemkerne (Connection, Configfile, Session, Plugins z.b.) die bei jedem Seitenaufbau gebraucht werden. dann nen großer Batzen sind meine Validator Klassen zum validieren von Daten aus Formularen (String, Numeric, EMail usw.) und das ganze nochmal pro Validator eine Display Klasse für die Anzeige. Dann hab ich für jede Tabelle in der Datenbank eine Klasse die den Zugriff darauf regelt, sind auch nochmal 13 Stück. Macht allein für die paar Sachen um die 45 Klassen. und und und... halt
Sind eigentlich nur so 5-6 größere Dinge, die die Klassen übernehmen. Klar könnt ich daraus 5-6 Klassen machen, aber die werden gross unübersichtlich und schlecht erweiterbar. So wie ich es bisher hab kann ich für einen neuen Datentyp zum validieren einfach ne neue Klasse rein schieben und fertig. Oder einzelne Klassen austauschen oder weitergeben.
Aber um die 50 includes werdens auf jeden Fall pro Seitenaufruf. Vor allem wenn auf der Seite Formulare (Validator und Formularelemente) oder tabellarischen Daten (Display Klassen) sind.
gepostet vor 17 Jahre, 3 Monate von Nuky
Bist du sicher, dass du nicht eine FormValidation Klasse machen sollest, die alle Validierungen enthält?
Weiß nicht ob die so sehr wachsen wird..
Weiß nicht ob die so sehr wachsen wird..
gepostet vor 17 Jahre, 3 Monate von DrakeL
Ja bin ich mir sicher, es sind bei mir 7 Validator a um die 150 Zeilen, daher wäre es zusammen in eine Klasse gepackt um die 600 Zeilen (fällt ja auch einiges weg, wie Konstruktoren) und das ist mir echt zu unübersichtlich ^^.
Hier mal ein Beispiel:
* Ueberpruefung, ob das Script von der "index.php" aufgerufen wurde. Ist
* dies nicht der Fall, wird der Scriptaufruf mit "die()" abgebrochen
*/
if(defined('DEVELOPMENT') == false)
{
die('no intern access');
}
/**
* @include Basisklasse aller Validator fuer Benutzereingaben
*/
require_once 'Helpclass/Validator/AbstractValidator.php';
/**
* @include Exceptionklasse fuer Ausnahmen beim Validieren von Daten
*/
require_once 'Exception/ValidateException.php';
/**
* Validiert eine Variable auf einem numerischen Wert
*
* Der Validator ueberprueft die uebergebene Variable, ob diese eine Zahl
* oder ein numerischer String ist. Danach werden die verschiedenen
* Parameter abgefragt, ob sie eine Dezimalzahl ist und sein darf und ob sie
* sich im erlaubten Wertebereich befindet. Danach kann sie abgefragt werden
*
* @author Christoph Herrmann (DrakeL)
* @copyright 2007 DragonUniverse
* @version 29.06.2007
*
* @package Helpclass
*/
class NumericValidator extends AbstractValidator
{
/**
* @var bool $decimal "true", falls es eine Dezimalzahl sein darf
*/
protected $decimal;
/**
* @var mixed $minimal Minimalwert den die Zahl haben darf
*/
protected $minimal;
/**
* @var mixed $maximal Maximalwert den die Zahl haben darf
*/
protected $maximal;
/**
* Konstruktor der Klasse "NumericValidator"
*
* @return NumericValidator
*/
public function __construct()
{
parent::__construct(0);
$this->decimal = false;
$this->minimal = false;
$this->maximal = false;
}
/**
* Bestimmt, ob die uebergebene Zahl eine Dezimalzahl sein darf
*
* @param bool $decimal "true", falls es eine Dezimalzahl sein darf
*/
public function setDecimal($decimal)
{
$this->decimal = $decimal;
}
/**
* Bestimmt den Minimalwert, den die uebergebene Zahl haben darf
*
* @param mixed $minimal Minimalwert den die Zahl haben darf
*/
public function setMinimal($minimal)
{
$this->minimal = $minimal;
}
/**
* Bestimmt den Maximalwert, den die uebergebene Zahl haben darf
*
* @param mixed $maximal Maximalwert den die Zahl haben darf
*/
public function setMaximal($maximal)
{
$this->maximal = $maximal;
}
/**
* Ueberprueft, ob eine uebergebene Variable gueltig ist
*
* @param mixed $value Variable, die validiert werden soll
*/
protected function isValid($value)
{
/*
* Eventuell eingegebene Kommas werden mit Punkten ausgetauscht, falls
* eine Dezimalzahl mit Kommas statt mit einem Punkt eingegeben wurde
*/
$value = str_replace(',', '.', $value);
/*
* Es wird geschaut, ob die Variable eine Zahl oder ein numerischer
* ist. Wenn nicht, befinden sich ungueltige Zeichen in der Variable
*/
if(is_numeric($value))
{
if($this->decimal == false and ((integer) $value != $value))
{
/*
* Die uebergebene Zahl besitzt Nachkommastellen. Es wird jedoch
* eine natuerliche Zahl ohne Nachkommastellen erwartet
*/
throw new ValidateException();
}
if($this->minimal)
{
if($this->minimal > $this->value)
{
/*
* Die uebergebene Zahl ist kleiner als das erlaubte Minimum.
* Der Benutzer muss eine groessere Zahl eingeben
*/
throw new ValidateException();
}
}
if($this->maximal)
{
if($this->maximal < $this->value)
{
/*
* Die uebergebene Zahl ist groesser als das erlaubte
* Maximum. Der Benutzer muss eine kleinere Zahl eingeben
*/
throw new ValidateException();
}
}
} else
{
/*
* Die uebergebene Variable ist weder eine Zahl, noch ein
* numerischer String, daher sie beinhaltet ungueltige Zeichen
*/
throw new ValidateException();
}
return true;
}
}
?>
Außerdem enthält eigentlich keiner meiner Klassen (abgesehen von den Konstruktoren) Code, den man weglassen könnte, wenn man Sie zusammen führen würde. Von daher würde man keinen Code einsparen, sondern wirklich nur die Zahl der Klassen minimieren und dafür größere unübersichtlichere Klassen erhalten, die man bei jeder Erweiterung anpassen müsste.
Hier mal ein Beispiel:
/*
* Ueberpruefung, ob das Script von der "index.php" aufgerufen wurde. Ist
* dies nicht der Fall, wird der Scriptaufruf mit "die()" abgebrochen
*/
if(defined('DEVELOPMENT') == false)
{
die('no intern access');
}
/**
* @include Basisklasse aller Validator fuer Benutzereingaben
*/
require_once 'Helpclass/Validator/AbstractValidator.php';
/**
* @include Exceptionklasse fuer Ausnahmen beim Validieren von Daten
*/
require_once 'Exception/ValidateException.php';
/**
* Validiert eine Variable auf einem numerischen Wert
*
* Der Validator ueberprueft die uebergebene Variable, ob diese eine Zahl
* oder ein numerischer String ist. Danach werden die verschiedenen
* Parameter abgefragt, ob sie eine Dezimalzahl ist und sein darf und ob sie
* sich im erlaubten Wertebereich befindet. Danach kann sie abgefragt werden
*
* @author Christoph Herrmann (DrakeL)
* @copyright 2007 DragonUniverse
* @version 29.06.2007
*
* @package Helpclass
*/
class NumericValidator extends AbstractValidator
{
/**
* @var bool $decimal "true", falls es eine Dezimalzahl sein darf
*/
protected $decimal;
/**
* @var mixed $minimal Minimalwert den die Zahl haben darf
*/
protected $minimal;
/**
* @var mixed $maximal Maximalwert den die Zahl haben darf
*/
protected $maximal;
/**
* Konstruktor der Klasse "NumericValidator"
*
* @return NumericValidator
*/
public function __construct()
{
parent::__construct(0);
$this->decimal = false;
$this->minimal = false;
$this->maximal = false;
}
/**
* Bestimmt, ob die uebergebene Zahl eine Dezimalzahl sein darf
*
* @param bool $decimal "true", falls es eine Dezimalzahl sein darf
*/
public function setDecimal($decimal)
{
$this->decimal = $decimal;
}
/**
* Bestimmt den Minimalwert, den die uebergebene Zahl haben darf
*
* @param mixed $minimal Minimalwert den die Zahl haben darf
*/
public function setMinimal($minimal)
{
$this->minimal = $minimal;
}
/**
* Bestimmt den Maximalwert, den die uebergebene Zahl haben darf
*
* @param mixed $maximal Maximalwert den die Zahl haben darf
*/
public function setMaximal($maximal)
{
$this->maximal = $maximal;
}
/**
* Ueberprueft, ob eine uebergebene Variable gueltig ist
*
* @param mixed $value Variable, die validiert werden soll
*/
protected function isValid($value)
{
/*
* Eventuell eingegebene Kommas werden mit Punkten ausgetauscht, falls
* eine Dezimalzahl mit Kommas statt mit einem Punkt eingegeben wurde
*/
$value = str_replace(',', '.', $value);
/*
* Es wird geschaut, ob die Variable eine Zahl oder ein numerischer
* ist. Wenn nicht, befinden sich ungueltige Zeichen in der Variable
*/
if(is_numeric($value))
{
if($this->decimal == false and ((integer) $value != $value))
{
/*
* Die uebergebene Zahl besitzt Nachkommastellen. Es wird jedoch
* eine natuerliche Zahl ohne Nachkommastellen erwartet
*/
throw new ValidateException();
}
if($this->minimal)
{
if($this->minimal > $this->value)
{
/*
* Die uebergebene Zahl ist kleiner als das erlaubte Minimum.
* Der Benutzer muss eine groessere Zahl eingeben
*/
throw new ValidateException();
}
}
if($this->maximal)
{
if($this->maximal < $this->value)
{
/*
* Die uebergebene Zahl ist groesser als das erlaubte
* Maximum. Der Benutzer muss eine kleinere Zahl eingeben
*/
throw new ValidateException();
}
}
} else
{
/*
* Die uebergebene Variable ist weder eine Zahl, noch ein
* numerischer String, daher sie beinhaltet ungueltige Zeichen
*/
throw new ValidateException();
}
return true;
}
}
?>
Außerdem enthält eigentlich keiner meiner Klassen (abgesehen von den Konstruktoren) Code, den man weglassen könnte, wenn man Sie zusammen führen würde. Von daher würde man keinen Code einsparen, sondern wirklich nur die Zahl der Klassen minimieren und dafür größere unübersichtlichere Klassen erhalten, die man bei jeder Erweiterung anpassen müsste.
gepostet vor 17 Jahre, 3 Monate von TheUndeadable
Dein Code gefällt mir, richtig schön OOP, gut ausdokumentiert und der Validator sieht zumindest sehr sauber aus.
Ich persönlich hatte auch mal ein größeres Projekt in PHP 4 mit OOP gemacht (altes BG) und hatte keine Probleme mit dem regelmäßigen Einbinden von vielen Klassen.
Ich persönlich hatte auch mal ein größeres Projekt in PHP 4 mit OOP gemacht (altes BG) und hatte keine Probleme mit dem regelmäßigen Einbinden von vielen Klassen.
gepostet vor 17 Jahre, 3 Monate von DrakeL
Thx
Ich versuche alle Klassen so sauber zu implementieren und vor allem so gut zu dokumentieren, dass ich auch in einem Jahr, wenn ich Bugs beheben muss nicht nur weiß was ich gemacht hab, sondern vor allem auch warum.
Bisher sehen alle meine 75 Klassen in der Struktur und Dokumentation so aus, was zwar auch massig Zeit kostet alles zu standardisieren (zum Beispiel haben heute alle abstrakte Klassen einen protected Konstruktor bekommen, weil es an einer Stelle gebraucht wurde und es keine Nachteile bringt es generell zu machen, daher alles wieder angepasst und eingecheckt). Deswegen geht die Entwicklung nicht so schnell voran, als wenn ich alles hinklatschen würde, aber ich will ja nicht schnell fertig werden sondern spätestens nach meiner Aubsildung (in nem Jahr) ne saubere Referenz zum bewerben haben, falls ich mal in die Versuchung komme die Branche zu wechseln. Und ich denke bei der späteren Weiterentwicklung und Bugfixen wird es mir zugute kommen. ^^
Aber zum Thema:
Es scheint also kein Problem zu sein mit vielen Klassen zu arbeiten. Und vor allem ist noch genug Luft in der Performance durch den Compilercache, der bei meinem komplett OO Aufbau wohl ziehmlich viel bringen würde.
Thx für die Kommentare.
Ich versuche alle Klassen so sauber zu implementieren und vor allem so gut zu dokumentieren, dass ich auch in einem Jahr, wenn ich Bugs beheben muss nicht nur weiß was ich gemacht hab, sondern vor allem auch warum.
Bisher sehen alle meine 75 Klassen in der Struktur und Dokumentation so aus, was zwar auch massig Zeit kostet alles zu standardisieren (zum Beispiel haben heute alle abstrakte Klassen einen protected Konstruktor bekommen, weil es an einer Stelle gebraucht wurde und es keine Nachteile bringt es generell zu machen, daher alles wieder angepasst und eingecheckt). Deswegen geht die Entwicklung nicht so schnell voran, als wenn ich alles hinklatschen würde, aber ich will ja nicht schnell fertig werden sondern spätestens nach meiner Aubsildung (in nem Jahr) ne saubere Referenz zum bewerben haben, falls ich mal in die Versuchung komme die Branche zu wechseln. Und ich denke bei der späteren Weiterentwicklung und Bugfixen wird es mir zugute kommen. ^^
Aber zum Thema:
Es scheint also kein Problem zu sein mit vielen Klassen zu arbeiten. Und vor allem ist noch genug Luft in der Performance durch den Compilercache, der bei meinem komplett OO Aufbau wohl ziehmlich viel bringen würde.
Thx für die Kommentare.