Design Pattern

Divo1984

Erfahrenes Mitglied
Hallo liebe Community,

heute habe ich mal keine "Frage" in diesem Sinne sondern eher ne Anmerkung zu machen, zu der ich gern eure Meinungen hören würde!

Ich beschäftige mich seit neuestem mit den PHP Design Pattern - sicherlich kennen sich einige von euch schon gut drain aus - ich halt weniger;)

Ich habe viel darüber gelesen und vorallem auch, dass es viel zur Performance einer Web-Applikation beiträgt, wenn man halt Design Pattern nutzt.

Also habe ich mich grad mal dran gemacht und einen Test geschrieben - nen einfaches Singleton siehe hier:

PHP:
<?php
class db{
	private static $instance=NULL;
	
	protected $db_name;
	
	protected $db_user;
	
	protected $db_pw;
	
	protected $db_host;
	
	public $dbh;
	
	
	
	private function __construct(){
	
		$this->db_name="****";
		$this->db_user="****";
		$this->db_pw="****";
		$this->db_host="localhost";
	
		$this->dbh=new mysqli($this->db_host, $this->db_user, $this->db_pw, $this->db_name);
	
		if(isset($this->dbh->connect_error)){
			echo $this->dbh->connect_error;
		}else{
			echo"Datenbankverbindung steht!<br>";
		}
	}
	
	public static function getInstance(){
		if(self::$instance==NULL){
			self::$instance = new DB();
		}
		return self::$instance;
	}
}
?>

gegen dieses Variante hier:

PHP:
<?php
class DBA{
	
	protected $db_name;
	
	protected $db_user;
	
	protected $db_pw;
	
	protected $db_host;
	
	public $dbh;
	

	
	public function __construct(){
		
		$this->db_name="****";
		$this->db_user="****";
		$this->db_pw="****";
		$this->db_host="localhost";
	
		$this->dbh=new mysqli($this->db_host, $this->db_user, $this->db_pw, $this->db_name);
	
		if(isset($this->dbh->connect_error)){
			echo $this->dbh->connect_error;
		}else{
			echo"Datenbankverbindung steht!<br>";
		}
	}
	
	public function __destruct(){	
		$this->dbh->close();
	}
}

Beides "Instanziiert" über folgende Datei:

PHP:
<?php
$a="Eva";
$b="MT";
$start=microtime(true);

include_once 'classes/class_DB.php';


$conn=db::getInstance();
$stmt=$conn->dbh->prepare("SELECT id FROM regger_scripts WHERE script_name=?");
$stmt->bind_param("s", $a);
$stmt->execute();
$stmt->store_result();
if($stmt->num_rows>0){
	$stmt->bind_result($id);
	while($stmt->fetch()){
		echo"ID: {$id}<br>";
	}
}


$conn2=db::getInstance();
$stmt=$conn2->dbh->prepare("SELECT id FROM regger_scripts WHERE script_name=?");
$stmt->bind_param("s", $b);
$stmt->execute();
$stmt->store_result();
if($stmt->num_rows>0){
	$stmt->bind_result($id);
	while($stmt->fetch()){
		echo"ID: {$id}<br>";
	}
}


if($conn === $conn2){
	echo"Das selbe Objekt!<br>";
}else{
	echo"Nicht das selbe Objekt!<br>";
}

$end=microtime(true);
$zeit=$end-$start;

echo"Laufzeit: {$zeit} Sekunden!<br>";
echo"<br><br><hr>";
$start2=microtime(true);
require_once 'classes2/class_DB.php';
#$c="Active4u";
$data=new DBA();
$stmt=$data->dbh->prepare("SELECT id FROM regger_scripts WHERE script_name=?");
$stmt->bind_param("s", $a);
$stmt->execute();
$stmt->store_result();
if($stmt->num_rows>0){
	$stmt->bind_result($id);
	while($stmt->fetch()){
		echo"ID: {$id}<br>";
	}
}

$data2=new DBA();
$stmt=$data2->dbh->prepare("SELECT id FROM regger_scripts WHERE script_name=?");
$stmt->bind_param("s", $b);
$stmt->execute();
$stmt->store_result();
if($stmt->num_rows>0){
	$stmt->bind_result($id);
	while($stmt->fetch()){
		echo"ID: {$id}<br>";
	}
}
if($data === $data2){
	echo"Das selbe Objekt!<br>";
}else{
	echo"Nicht das selbe Objekt!<br>";
}

$end2=microtime(true);
$zeit2=$end2-$start2;
echo"Laufzeit: {$zeit2} Sekunden!<br>";

?>

Wie gesagt, ich lerne hier erst und war daher mit den Messwerten ein wenig überfordert bzw. etwas verblüfft:

Datenbankverbindung steht!
ID: 10
ID: 15
Das selbe Objekt!
Laufzeit: 0.010672092437744 Sekunden!


Datenbankverbindung steht!
ID: 10
Datenbankverbindung steht!
ID: 15
Nicht das selbe Objekt!
Laufzeit: 0.021194934844971 Sekunden!

In einigen Messungen machte das sogar noch einen größeren Unterschied...

Nun die Frage - kann ich also davon ausgehen, dass mir die Design Pattern immer solche fantastischen Werte erbringen? Liegt das hier am Einzelfall?

Habt Ihr denn schon Erfahrungen mit den Design Pattern? Wenn ja, würde mich eure Meinung dazu sehr interessieren!


Liebe Grüße
 
Na das ist doch genau der erwartete Wert. Die Datenbankabfragen werden genau gleich schnell sein. Einziger Unterschied ist die Instanziierung des Objekts und damit der Verbindungsaufbau. Den gibts bei der zweiten variante halt zweimal, weshalb die Zeit auch ziehmlich genau doppelt so lang ist.
 
Allgemein sind die Design Patterns nicht dazu da, um schnellere Programme zu erreichen.
Das Ziel ist ein schöner, übersichtlicher, wiederverwendbarer,
leicht verständlicher und -änderbarer Code.

Wenn man alles nur auf Geschwindigkeit ausrichtet
wirds ab einem gewissen Maß unverhältnismäßig viel Programmieraufwand,
verwurschtelter Code, in dem sich keiner schnell zurechtfindet, usw.
 
Ich kann mich da sheel nur anschließen. Entwurfsmuster sind das Steckenpferd von Software-Architekten und können damit nichts mit Geschwindigkeit wohl aber Wartbarkeit zu tun haben. Mir ist auch grad kein Pattern außer dem Singleton bekannt, was Geschwindikeitsvorteile bringt. Dabei ist der Sinn und Zweck von Singleton noch nicht mal Geschwindigkeit sondern eben, das es von einer Klasse maximal ein Objekt pro Sitzung existieren kann.

Dass du da bei der Singleton-Variante nur halbsolang brauchst, ist ja auch völlig klar, wenn man darüber nachdenkt ;-)

Setze Entwurfsmuster dann ein, wenn du den Sinn dahinter verstanden hast. Geschwindigkeit ist jedenfalls kein Sinn ;-)

Design Pattern sind an die Verwendung von Klassen gebunden, denn dafür wurden sie erdacht. Es gibt ein ähnliches Verfahren in der prozeduralen Version dieses Anwendungsfalls: Globals.

Da Globals aber pfui sind ;-) nimmt man sinnigerweise ein Singleton und kapselt das eigentliche Objekt weg, um es vor Manipulation zur Laufzeit zu schützen. Um das zu erreichen, brauchst du in der prozeduralen Version wieder einen Trick:

PHP:
<?php
function db()
{
	static $db;
	
	if(!$db)
	{
		$db = mysql_connect('localhost', 'test', '', null, null);
	}
	
	return $db;
}

function mysql_fetch_all($resource, $fetchType = MYSQL_ASSOC, $free = true)
{
	if(!$resource)
		die(mysql_error());
	
	$results = array();
	$func = 'mysql_fetch_array';
	
	switch($fetchType)
	{
		case MYSQL_ASSOC:
			$func = 'mysql_fetch_assoc';
			break;

		case MYSQL_NUM:
			$func = 'mysql_fetch_row';
			
		case MYSQL_BOTH:
		default:
			$func = 'mysql_fetch_array'; 
			
	}
	
	while($r = $func($resource))
	{
		$result[] = $r;
	}
	
	if($free)
		mysql_free_result($resource);
	
	return $result;
}

$db = db();
var_dump (mysql_fetch_all(mysql_query("SELECT * FROM test.t", db())));
if($db === db())
	echo "Identisch";
else
	echo "Nicht identisch";
 
Zuletzt bearbeitet:
Vielen lieben Dank für eure Antworten. Okay, da hab ich halt bisschen vorschnell geschossen - aber dennoch finde ich die Design Pattern richtig genial.

Habe mir grad nen feinen Debugger geschrieben und bin echt begeistert, das macht nicht nur Spaß sondern funktioniert auch und erleichtert echt einiges - insofern man die Interpretationen der Pattern versteht!
 

Nur mal so nebenbei, ich kannte das Pattern bisher noch nicht, sieht aber ganz allgemein nach der korrekt Art und Weise aus, wie man Schnittstellen anwendet. Aber auch dieses Pattern hat nicht das Endziel, einen Performance-Gewinn zu erlangen, sondern schlicht, um Speicher-Ressourcen zu sparen. Gut, jetzt könnte man daher kommen und behaupten, das wenn mehr Speicher zur Verfügung steht, auch sinnigerweise mehr Geschwindigkeit im Rest ablaufen wird, weil nicht so viel Speicher angefordert werden muss. Ok, ist ein Nebeneffekt, aber nicht das Ziel ;-)

Hab das Pattern sogar schon ein oder zwei mal eingesetzt, ohne zu wissen, dass es als solches definiert ist.

Was es nicht alles gibt :)
 
Zurück