Verwenden von Try…... außer zur Behandlung von Fehlern


Erfahren Sie mehr über Ausnahmen und zum Schreiben von Code für die bessere Fehlerbehandlung. Lernen Sie, wie Castalia uns schreiben robuster und tolerant Fehlercodes.

(Ursprünglich veröffentlicht auf Delphi-Expert.de am 23. März 2004)


Wie versprochen, ist heute Teil zwei unserer Diskussion der Delphi versuchen Konstrukte. Letzte Woche haben wir uns versuchen... Schließlich, gelernt, was es ist gedacht für die Verwendung und wie Castalia uns es effizienter nutzen kann. Diese Woche werden wir untersuchen die andere Hälfte der Familie versuchen , Versuch... außer und erfahren Sie, wie Castalia unserer versuchen machen kann... außer Nutzung effektiver. Wir werden auch über Java lustig machen.

Try... außer ist ein Konstrukt für den Umgang mit 'Ausnahmesituationen' in einem Programm. Ein Programm hat eine typische Strömung, die einen Satz von Anweisungen, die in Reihenfolge Vorgehen. Manchmal beinhaltet diese Reihenfolge Zweige, aber gibt es immer einen logischer Fluss und Entscheidungen diesen Fluss Verzweigung basieren auf einen Zustand des Programms, wie ob X kleiner als 5 ist.

Manchmal kann jedoch dieses Staates nicht korrekt gerendert werden. Nehmen wir ein Beispiel, das wir sehen, könnte in der realen Welt:

AssignFile (F, 'SomeFile.Txt');
ResetFile(F);
S: = ReadLn(F);
CloseFile(F);

Dieser einfache Code wird eine Datei öffnen, eine Zeile daraus gelesen und schließen Sie es wieder. Dies ist der normale Programmablauf. Allerdings sind eine Reihe von Annahmen über diese Strömung machte. Zunächst gehen wir davon aus, dass die Datei vorhanden ist. Wir gehen davon aus, dass wir zum Lesen geöffnet werden kann. Wir davon ausgehen, dass es eine Zeile gelesen werden. Etc....

Wenn alle diese Annahmen entpuppt sich als falsch, dann haben wir eine Ausnahmesituation! Der Programmablauf wird durch die Tatsache Durcheinander sein, dass einige Zustand nicht der Staat ist, was, den wir erwartet hatten.

Es gibt mehrere Möglichkeiten, diesen außergewöhnlichen Situationen behandeln. Wir können sie ignorieren, und tritt einer von ihnen, das Programm abstürzt oder tun Sie etwas anderes ebenso unberechenbar. Wir konnten für diese Ausnahmen überprüfen Sie Code wie folgt hinzufügen:

Wenn nicht dann FileExists('SomeFile.txt')
beginnen
WriteLn ('Datei existiert nicht');
Ausfahrt;
Ende;

Das ist besser. Einerseits haben Sie tatsächlich der Benutzer erklärt, warum das Programm nicht funktionieren. Für einfache Programme das funktioniert gut, aber da das Programm immer komplexer wird, der Zustand des Programms wird exponentiell komplexer geworden, und bald werden Sie nicht in der Lage, alle die Annahmen zu überprüfen. Überprüfen Ihre Annahmen ist eine gute Sache. Wir kommen wieder, dies später.

Wir können auch Checkafter jeder Vorgang, um sicherzustellen, dass was wir erwartet haben. Dies ist der traditionelle C-Ansatz und der Ansatz von der Windows-API (und den meisten anderen Betriebssystem-APIs mit BeOS als eine erwähnenswerte Ausnahme). In diesem Modell hat jede Funktion ein Fehlercode zurückgegeben. Es obliegt Ihnen, überprüfen den Fehlercode und sehen, ob es 'OK' oder etwas anderes wie FILE_NOT_FOUND. Dann noch einmal, würde Sie den Benutzer informieren und beenden.

Dies ist letztlich eine Abwandlung der gleiche Ansatz, nur diesmal wir die Annahmen überprüfen sind, nachdem wir etwas tun, anstatt vor. Der Vorteil ist, dass die einzelnen Funktionen eigene Annahmen überprüfen kann und im Falle der Windows-API, alle möglichen Rückgabewerte recht gut dokumentiert sind, so mit disziplinierten schreiben, es tatsächlich möglich ist, behandeln jede Bedingung, unter der Annahme, dass, wer die API schrieb alle seine Annahmen zu berücksichtigen hat. Code mit dieser Ansatz würde etwa so aussehen (Nein, dies ist keine gültige Pascal, ich entschuldige mich bei den Puristen):

ErrCode: = AssignFile (F, 'SomeFile.Txt');
Wenn ErrCode = FILE_NOT_FOUND then
beginnen
WriteLn ('Datei nicht gefunden');
Ausfahrt;
Ende;
ErrCode: = ResetFile(F);
Wenn ErrCode = FILE_NO_ACCESS then
beginnen
WriteLn (' Sie don'' t haben Zugang zu tun.');
Ausfahrt;
anderes Ende
Wenn ErrCode = FILE_ALREADY_OPEN then
beginnen
WriteLn ('jemand anders ist die Datei lesen');
Ausfahrt;
Ende;
ErrCode: = ReadLn (F, S); Nehmen wir an, das bedeutet von F in S lesen
Wenn ErrCode = NOT_ENOUGH_TEXT then
beginnen
WriteLn ('nicht genügend Text');
Ausfahrt;
Ende;
CloseFile(F);

Sie erhalten die Idee. Es könnte viel schlimmer sein, aber unser Programm ist wirklich komplex wirklich schnell geworden und alle Dinge unterzubringen, die normalerweise geschehen nicht.

Also musste jemand in den letzten paar Jahrzehnten eine neue Idee. Warum nicht erstellen eine Kontrollstruktur speziell für Ausnahmesituationen zu? Diese neue kann Kontrollstruktur ermöglichen würde, uns zu definieren, was normalerweise geschehen sollte, und dann zu definieren, was geschehen soll, wenn etwas schief geht. Dies bezeichnet man als 'Ausnahmebehandlung.'

Die Grundidee hinter eine Ausnahme ist, dass wir davon ausgehen, dass die normale Flusssteuerung stattfinden wird. Wenn nicht, hören wir sofort Ausführung, wo immer wir sind, und die aktuelle Funktion beenden. Wir beenden Sie dann die Funktion, die diese Funktion aufgerufen, und so weiter, bis wir einen Ausnahmehandler erreichen die einen Codeblock, der ausgeführt wird, nur dann, wenn ein außergewöhnlicher Zustand oder Ereignis stattfindet. Wenn der normale Ablauf bei der Ausführung folgt, werden Ausnahmehandler ignoriert.

In Delphi, der normale Ablauf der Ausführung ist in einem Try-Block und des Ausnahmehandlers einer ausser Block. Hier ist ein einfaches Beispiel:

versuchen Sie
AssignFIle (F, 'SomeFile.txt');
ResetFile(F);
S: = Readln(F);
CloseFile(F);
mit Ausnahme von
WriteLn ('Fehler');
Ende;

Dies ist sauberer, und es erlaubt uns, welcher Code deutlich zu sehen, wir erwarten normalerweise ausgeführt werden soll, und welcher Code ausgeführt werden soll, wenn etwas sonderbares passiert (nicht wie das letzte Beispiel... Schaudern).

Natürlich wäre es schön, dass man dem Benutzer mitteilen, welcher Fehler genau aufgetreten. Ausnahmebehandlung ist dies ein Kinderspiel zu. Seit Ausnahmebehandlung entwickelten Hand in Hand mit der objektorientierten Programmierung wurden Dinge genannt Ausnahmeobjekte konzipiert. Das Exception-Objekt wird automatisch erstellt, wenn eine Ausnahme ausgelöst wird. Wenn wir das Exception-Objekt verwenden möchten, erweitern wir die Try... außer die Syntax wie folgt:

versuchen Sie
AssignFile (F, 'SomeFile.txt');
ResetFile(F);
S: = Readln(F);
CloseFile(F);
mit Ausnahme von
auf E: Ausnahme do
WriteLn(E.Message);
Ende;

Sie sehen, jede Ausnahme hat eine Eigenschaft, die einige wenige nützliche Informationen über die spezifische Ausnahme gibt. Er enthält möglicherweise die Zeichenfolge 'Datei nicht gefunden' oder 'File already in Use', oder etwas, was wir dem Benutzer mitteilen möchten.

Es gibt verschiedene Arten von Ausnahmen, und wir profitieren davon zu. Vielleicht wollen wir etwas Besonderes zu machen, wenn eine bestimmte Ausnahme geschieht. Vielleicht wollen wir ein Signalton ertönt, wenn die Datei nicht gefunden wird:

versuchen Sie
AssignFile (F, 'SomeFile.txt');
ResetFile(F);
S: = REadln(F);
CloseFIle(F);
mit Ausnahme von
auf E: FileNotFound do
Signalton;
auf E: Ausnahme do
WriteLn(E.Message);
Ende;

Beachten Sie, dass wenn wir mehrere Ausnahmen behandeln, die spezifischste Ausnahme zuerst gehen muss. Dies liegt daran, Ausnahmen sind polymorph - d. h. Ausnahme ist jede Ausnahme, und EFileNotFound ist eine Ausnahme, so dass wenn Ausnahme zuerst behandelt wird, nie EFileNotFound behandelt werden.

Ein Problem mit diesem Mechanismus ist, dass wir noch nicht sicher welche Ausnahmen einer bestimmten Funktion oder Prozedur auslösen könnte. Einige Sprachen oder Entwicklungs-Tools haben einen Mechanismus, mit denen Sie wissen, was möglicherweise ausgelöst werden. Ein c#-IDE zum Beispiel geben Ihnen eine kleine Hinweisfenster, Ihnen zu sagen, welche Ausnahmen behandelt werden sollen, wenn Sie eine Funktion verwenden. Java ist berüchtigt (und von vielen gehasst) dafür, dass es erzwingt Ausnahmebehandlung mit terroristischen Eifer. Code wird nicht einmal kompilieren, wenn Sie nicht die Ausnahmen, denen es möchte, Sie, behandeln dass selbst wenn Sie wissen, dass diese Ausnahmen nicht gehen, um das geschehen, entweder weil Sie Kontrolle über die laufende Umgebung haben oder Code bereits prechecked die Bedingung und dafür gesorgt, dass die Ausnahme möglicherweise nicht möglich. Java wird seine Code-Stil, um den letzten deut und Tittle, durchsetzen, ob Sie oder nicht wollen.

Leider gibt es kein solches Tool für Delphi. Während ich dies schreibe, bin ich Anfang zu denken, es könnte eine gute Sache Castalia hinzu. Ich muss in diese suchen.

Puh!

Das war dreieinhalb Seiten von Microsoft Word, nur um zu verstehen, was eine Ausnahme ist. Jetzt zum lustigen Sachen:

Castalia helfen Ihnen Ihre normalen Code und Ihr Code zur Ausnahmebehandlung schreiben. Castalia des Code-Vorlagen definieren eine Trye -Vorlage, die erstellt automatisch einen Versuch... außer Block für Sie und Einstiegspunkte richtet, so dass Sie Ihren Code korrekt erstellen können. Dadurch sparen Sie weitere Anschläge und mehr Zeit als Sie denken!

Die Castalia Umgestaltung Tools bieten eine automatisierte umgeben mit... Umgestaltung, die einen Versuch setzt... außer Block um Ihren Code. Einfach markieren Sie den normalen Fluss Steuerelementcode, Rechtsklick auf den Editor (oder drücken Sie UMSCHALT + STRG + R) und wählen Sie das entsprechende Element aus dem Menü 'Umgestaltung'. Der Code wird automatisch geändert.

Diese Woche haben wir gelernt, was die Try... außer Block ist denn und woher es kam (und deshalb ist es die beste Fehlerbehandlung Mechanismus noch). Wir haben auch gelernt, wie Castalia Ihr diese leistungsstarke Kontrollstruktur mehr robuste und benutzerfreundliche Code schreiben nutzen kann.

Weitere Informationen über Castalias Code-Vorlagen klicken Sie hier.

Klicken Sie hier für weitere Informationen über Castalias automatisierte refactorings

Castalia jetzt zu kaufen, da dieser Artikel war das beste, das Sie je gelesen haben, klicken Sie hier, dann klicken Sie hier, um ein viel besseres Buch zu lesen.









Verwenden von Try…... außer zur Behandlung von Fehlern


Verwenden von Try…... außer zur Behandlung von Fehlern : Mehreren tausend Tipps, um Ihr Leben einfacher machen.


Erfahren Sie mehr über Ausnahmen und zum Schreiben von Code für die bessere Fehlerbehandlung. Lernen Sie, wie Castalia uns schreiben robuster und tolerant Fehlercodes.

(Ursprünglich veröffentlicht auf Delphi-Expert.de am 23. März 2004)


Wie versprochen, ist heute Teil zwei unserer Diskussion der Delphi versuchen Konstrukte. Letzte Woche haben wir uns versuchen... Schließlich, gelernt, was es ist gedacht für die Verwendung und wie Castalia uns es effizienter nutzen kann. Diese Woche werden wir untersuchen die andere Hälfte der Familie versuchen , Versuch... außer und erfahren Sie, wie Castalia unserer versuchen machen kann... außer Nutzung effektiver. Wir werden auch über Java lustig machen.

Try... außer ist ein Konstrukt für den Umgang mit 'Ausnahmesituationen' in einem Programm. Ein Programm hat eine typische Strömung, die einen Satz von Anweisungen, die in Reihenfolge Vorgehen. Manchmal beinhaltet diese Reihenfolge Zweige, aber gibt es immer einen logischer Fluss und Entscheidungen diesen Fluss Verzweigung basieren auf einen Zustand des Programms, wie ob X kleiner als 5 ist.

Manchmal kann jedoch dieses Staates nicht korrekt gerendert werden. Nehmen wir ein Beispiel, das wir sehen, könnte in der realen Welt:

AssignFile (F, 'SomeFile.Txt');
ResetFile(F);
S: = ReadLn(F);
CloseFile(F);

Dieser einfache Code wird eine Datei öffnen, eine Zeile daraus gelesen und schließen Sie es wieder. Dies ist der normale Programmablauf. Allerdings sind eine Reihe von Annahmen über diese Strömung machte. Zunächst gehen wir davon aus, dass die Datei vorhanden ist. Wir gehen davon aus, dass wir zum Lesen geöffnet werden kann. Wir davon ausgehen, dass es eine Zeile gelesen werden. Etc....

Wenn alle diese Annahmen entpuppt sich als falsch, dann haben wir eine Ausnahmesituation! Der Programmablauf wird durch die Tatsache Durcheinander sein, dass einige Zustand nicht der Staat ist, was, den wir erwartet hatten.

Es gibt mehrere Möglichkeiten, diesen außergewöhnlichen Situationen behandeln. Wir können sie ignorieren, und tritt einer von ihnen, das Programm abstürzt oder tun Sie etwas anderes ebenso unberechenbar. Wir konnten für diese Ausnahmen überprüfen Sie Code wie folgt hinzufügen:

Wenn nicht dann FileExists('SomeFile.txt')
beginnen
WriteLn ('Datei existiert nicht');
Ausfahrt;
Ende;

Das ist besser. Einerseits haben Sie tatsächlich der Benutzer erklärt, warum das Programm nicht funktionieren. Für einfache Programme das funktioniert gut, aber da das Programm immer komplexer wird, der Zustand des Programms wird exponentiell komplexer geworden, und bald werden Sie nicht in der Lage, alle die Annahmen zu überprüfen. Überprüfen Ihre Annahmen ist eine gute Sache. Wir kommen wieder, dies später.

Wir können auch Checkafter jeder Vorgang, um sicherzustellen, dass was wir erwartet haben. Dies ist der traditionelle C-Ansatz und der Ansatz von der Windows-API (und den meisten anderen Betriebssystem-APIs mit BeOS als eine erwähnenswerte Ausnahme). In diesem Modell hat jede Funktion ein Fehlercode zurückgegeben. Es obliegt Ihnen, überprüfen den Fehlercode und sehen, ob es 'OK' oder etwas anderes wie FILE_NOT_FOUND. Dann noch einmal, würde Sie den Benutzer informieren und beenden.

Dies ist letztlich eine Abwandlung der gleiche Ansatz, nur diesmal wir die Annahmen überprüfen sind, nachdem wir etwas tun, anstatt vor. Der Vorteil ist, dass die einzelnen Funktionen eigene Annahmen überprüfen kann und im Falle der Windows-API, alle möglichen Rückgabewerte recht gut dokumentiert sind, so mit disziplinierten schreiben, es tatsächlich möglich ist, behandeln jede Bedingung, unter der Annahme, dass, wer die API schrieb alle seine Annahmen zu berücksichtigen hat. Code mit dieser Ansatz würde etwa so aussehen (Nein, dies ist keine gültige Pascal, ich entschuldige mich bei den Puristen):

ErrCode: = AssignFile (F, 'SomeFile.Txt');
Wenn ErrCode = FILE_NOT_FOUND then
beginnen
WriteLn ('Datei nicht gefunden');
Ausfahrt;
Ende;
ErrCode: = ResetFile(F);
Wenn ErrCode = FILE_NO_ACCESS then
beginnen
WriteLn (' Sie don'' t haben Zugang zu tun.');
Ausfahrt;
anderes Ende
Wenn ErrCode = FILE_ALREADY_OPEN then
beginnen
WriteLn ('jemand anders ist die Datei lesen');
Ausfahrt;
Ende;
ErrCode: = ReadLn (F, S); Nehmen wir an, das bedeutet von F in S lesen
Wenn ErrCode = NOT_ENOUGH_TEXT then
beginnen
WriteLn ('nicht genügend Text');
Ausfahrt;
Ende;
CloseFile(F);

Sie erhalten die Idee. Es könnte viel schlimmer sein, aber unser Programm ist wirklich komplex wirklich schnell geworden und alle Dinge unterzubringen, die normalerweise geschehen nicht.

Also musste jemand in den letzten paar Jahrzehnten eine neue Idee. Warum nicht erstellen eine Kontrollstruktur speziell für Ausnahmesituationen zu? Diese neue kann Kontrollstruktur ermöglichen würde, uns zu definieren, was normalerweise geschehen sollte, und dann zu definieren, was geschehen soll, wenn etwas schief geht. Dies bezeichnet man als 'Ausnahmebehandlung.'

Die Grundidee hinter eine Ausnahme ist, dass wir davon ausgehen, dass die normale Flusssteuerung stattfinden wird. Wenn nicht, hören wir sofort Ausführung, wo immer wir sind, und die aktuelle Funktion beenden. Wir beenden Sie dann die Funktion, die diese Funktion aufgerufen, und so weiter, bis wir einen Ausnahmehandler erreichen die einen Codeblock, der ausgeführt wird, nur dann, wenn ein außergewöhnlicher Zustand oder Ereignis stattfindet. Wenn der normale Ablauf bei der Ausführung folgt, werden Ausnahmehandler ignoriert.

In Delphi, der normale Ablauf der Ausführung ist in einem Try-Block und des Ausnahmehandlers einer ausser Block. Hier ist ein einfaches Beispiel:

versuchen Sie
AssignFIle (F, 'SomeFile.txt');
ResetFile(F);
S: = Readln(F);
CloseFile(F);
mit Ausnahme von
WriteLn ('Fehler');
Ende;

Dies ist sauberer, und es erlaubt uns, welcher Code deutlich zu sehen, wir erwarten normalerweise ausgeführt werden soll, und welcher Code ausgeführt werden soll, wenn etwas sonderbares passiert (nicht wie das letzte Beispiel... Schaudern).

Natürlich wäre es schön, dass man dem Benutzer mitteilen, welcher Fehler genau aufgetreten. Ausnahmebehandlung ist dies ein Kinderspiel zu. Seit Ausnahmebehandlung entwickelten Hand in Hand mit der objektorientierten Programmierung wurden Dinge genannt Ausnahmeobjekte konzipiert. Das Exception-Objekt wird automatisch erstellt, wenn eine Ausnahme ausgelöst wird. Wenn wir das Exception-Objekt verwenden möchten, erweitern wir die Try... außer die Syntax wie folgt:

versuchen Sie
AssignFile (F, 'SomeFile.txt');
ResetFile(F);
S: = Readln(F);
CloseFile(F);
mit Ausnahme von
auf E: Ausnahme do
WriteLn(E.Message);
Ende;

Sie sehen, jede Ausnahme hat eine Eigenschaft, die einige wenige nützliche Informationen über die spezifische Ausnahme gibt. Er enthält möglicherweise die Zeichenfolge 'Datei nicht gefunden' oder 'File already in Use', oder etwas, was wir dem Benutzer mitteilen möchten.

Es gibt verschiedene Arten von Ausnahmen, und wir profitieren davon zu. Vielleicht wollen wir etwas Besonderes zu machen, wenn eine bestimmte Ausnahme geschieht. Vielleicht wollen wir ein Signalton ertönt, wenn die Datei nicht gefunden wird:

versuchen Sie
AssignFile (F, 'SomeFile.txt');
ResetFile(F);
S: = REadln(F);
CloseFIle(F);
mit Ausnahme von
auf E: FileNotFound do
Signalton;
auf E: Ausnahme do
WriteLn(E.Message);
Ende;

Beachten Sie, dass wenn wir mehrere Ausnahmen behandeln, die spezifischste Ausnahme zuerst gehen muss. Dies liegt daran, Ausnahmen sind polymorph - d. h. Ausnahme ist jede Ausnahme, und EFileNotFound ist eine Ausnahme, so dass wenn Ausnahme zuerst behandelt wird, nie EFileNotFound behandelt werden.

Ein Problem mit diesem Mechanismus ist, dass wir noch nicht sicher welche Ausnahmen einer bestimmten Funktion oder Prozedur auslösen könnte. Einige Sprachen oder Entwicklungs-Tools haben einen Mechanismus, mit denen Sie wissen, was möglicherweise ausgelöst werden. Ein c#-IDE zum Beispiel geben Ihnen eine kleine Hinweisfenster, Ihnen zu sagen, welche Ausnahmen behandelt werden sollen, wenn Sie eine Funktion verwenden. Java ist berüchtigt (und von vielen gehasst) dafür, dass es erzwingt Ausnahmebehandlung mit terroristischen Eifer. Code wird nicht einmal kompilieren, wenn Sie nicht die Ausnahmen, denen es möchte, Sie, behandeln dass selbst wenn Sie wissen, dass diese Ausnahmen nicht gehen, um das geschehen, entweder weil Sie Kontrolle über die laufende Umgebung haben oder Code bereits prechecked die Bedingung und dafür gesorgt, dass die Ausnahme möglicherweise nicht möglich. Java wird seine Code-Stil, um den letzten deut und Tittle, durchsetzen, ob Sie oder nicht wollen.

Leider gibt es kein solches Tool für Delphi. Während ich dies schreibe, bin ich Anfang zu denken, es könnte eine gute Sache Castalia hinzu. Ich muss in diese suchen.

Puh!

Das war dreieinhalb Seiten von Microsoft Word, nur um zu verstehen, was eine Ausnahme ist. Jetzt zum lustigen Sachen:

Castalia helfen Ihnen Ihre normalen Code und Ihr Code zur Ausnahmebehandlung schreiben. Castalia des Code-Vorlagen definieren eine Trye -Vorlage, die erstellt automatisch einen Versuch... außer Block für Sie und Einstiegspunkte richtet, so dass Sie Ihren Code korrekt erstellen können. Dadurch sparen Sie weitere Anschläge und mehr Zeit als Sie denken!

Die Castalia Umgestaltung Tools bieten eine automatisierte umgeben mit... Umgestaltung, die einen Versuch setzt... außer Block um Ihren Code. Einfach markieren Sie den normalen Fluss Steuerelementcode, Rechtsklick auf den Editor (oder drücken Sie UMSCHALT + STRG + R) und wählen Sie das entsprechende Element aus dem Menü 'Umgestaltung'. Der Code wird automatisch geändert.

Diese Woche haben wir gelernt, was die Try... außer Block ist denn und woher es kam (und deshalb ist es die beste Fehlerbehandlung Mechanismus noch). Wir haben auch gelernt, wie Castalia Ihr diese leistungsstarke Kontrollstruktur mehr robuste und benutzerfreundliche Code schreiben nutzen kann.

Weitere Informationen über Castalias Code-Vorlagen klicken Sie hier.

Klicken Sie hier für weitere Informationen über Castalias automatisierte refactorings

Castalia jetzt zu kaufen, da dieser Artikel war das beste, das Sie je gelesen haben, klicken Sie hier, dann klicken Sie hier, um ein viel besseres Buch zu lesen.


Verwenden von Try…... außer zur Behandlung von Fehlern

Verwenden von Try…... außer zur Behandlung von Fehlern : Mehreren tausend Tipps, um Ihr Leben einfacher machen.
Verwenden von Try…... außer zur Behandlung von Fehlern
Wiezutun
Freunden empfehlen
  • gplus
  • pinterest

Kommentar

Einen Kommentar hinterlassen

Wertung