Montag, 26. Dezember 2005, 13:41 Uhr

Effiziente Web-Projekte anhand von Partyguide, Teil 1

Bereits in mehreren Blog-Beiträgen (anschliessend hier) habe ich mich über die Amateurhaftigkeit von Partyguide aufgeregt. Da Kritik aber selten etwas bringt, möchte ich in dieser neu gestarteten Serie in unregelmässigen Abständen anhand der Architektur von Partyguide die gröbsten Schnitzer aufzeigen, die Internet-Frickler begehen, wenn man ihnen die nötigen Werkzeuge in die Hand drückt.

Heute ziehe ich hierzu die Seite ‚Personen suchen‘ unter ‚FlirtCity‘ heran. FlirtCity ist die kostenlose Variante von Partnerwinner, auf jüngeres Publikum gemünzt.

Notabene: Hinter gutaussehenden Frauen, die dort nach „Abenteuer“ suchen, stecken mit allergrösster Wahrscheinlichkeit pubertierende Jünglinge, die sich mit Model-Fotos aus dem Internet einen Spass erlauben. Gemäss dem Motto: „On the Internet, nobody knows you’re a dog.“

Standards, Standards, Standards

Kaum hat man den HTML-Quelltext geöffnet, sträuben sich bei mir bereits die Haare:

<script language="JavaScript">
...
</script>

<html>
...
</html>

NEIN! Web-Sites eröffnet man mit dem <html>-Tag. Dass JavaScript-Elemente vor <html> eingebunden werden, zeugt von Stümperhaftigkeit und Unkenntnis geltender Standards. Vor dem <html>-Tag steht höchstens ein

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

Transfervolumen schonen

Aufrufe auf Partyguide zeigen, dass die „Macher“ Probleme haben, die Infrastruktur (Hardware: Server) resp. den Traffic (Software: Datenfluss) zu finanzieren. Dies ist nicht verwunderlich, denn der Hauptbestandteil von Partyguide sind die unzähligen Bilder, die an Parties in der ganzen Schweiz geschossen wurden und nun dem Publikum zur Schau gestellt werden. Das Problem ist hier einfach, dass Bilder ein Vielfaches grösser sind als normale Text-Seiten. Und leider kostet im Internet heute – vereinfacht gesagt – nur noch die übertragene Datenmenge. Während Partyguide ein Bild überträgt, kann bspw. eine News-Site ihre Artikel für dieselben Kosten – sagen wir – zehnmal übertragen. Ziel müsste es also für das Team hinter Partyguide sein, den Datenfluss so effizient wie möglich zu auszunutzen – und klein zu halten. Kein Byte sollte zuviel übertragen werden, denn bei Tausenden von täglichen Besuchern summieren sich solche „Kleinigkeiten“ zu vielen Megabytes an verschwendetem Traffic an.

Zwei Beispiele, wieso Partyguide hier noch viel zu lernen hat:

Von Benutzern hochgeladene Bilder

Benutzer von Partyguide haben ein eigenes Profil. Dort kann man Angaben über die eigene Person publizieren (Alter, Wohnort, Lieblings-Clubs etc.) und unter anderem auch persönliche Bilder hochladen.

Desöfteren fallen mir bei der Anzeige der persönlichen Bilder aber lange Verzögerungen auf. Ein Blick auf die übertragenen Grafikdateien zeigt dann meistens dieselbe Ursache: Anstatt platzsparende JPEG-Dateien zu übertragen, kommen dann und wann BMPs daher. Notabene mit der Endung .jpg, was eine aktive Täuschung jedes Browsers darstellt – die meisten Browser stören sich aber an der falschen Endung nicht – anscheinend ist die falsche Erweiterung immer noch ein weit grassierendes Problem im Netz. Jeder halbwegs Sachverständige weiss aber, dass BMP keine Komprimierung aufweist und verlustfreie Bilder beinhaltet. Deshalb sind die Bilder teilweise um den Faktor 10 grösser als dasselbe, komprimierte Sujet im JPEG-Format.

Wer ist der Schuldige? Zuerst einmal die unzähligen unbedarften Windows-User, die BMP-Dateien auf Partyguide hochladen. Doch ihnen kann man nicht viel vorhalten – die wenigsten Benutzer kennen Unterschiede der einzelnen Grafik-Formate. Sie sind Endanwender, die sich um solchen „Käse“ nicht kümmern möchten.

Würden bei Partyguide fähige PHP-Entwickler arbeiten, würden spätestens aber diese solchen Unfug abfangen und die empfangenen Bilddateien nach dem Upload in das JPEG-Format umkodieren. Machen sie aber nicht. Und „bezahlen“ bei jedem Aufruf einer BMP-Bilddatei mit verschwendetem Transfervolumen.

Nachtrag: Am 29. September habe ich die Entwickler von Partyguide auf das Problem aufmerksam gemacht. Die läppische Antwort:

werden sie auch [Umkonvertierung von BMP-Dateien]. es kommt jedoch vereinzelt vor, dass die bilder nicht konvertiert werden können, oft wenn die datei zu gross ist…

Ein Kommentar erübrigt sich wohl …

Sich wiederholenden HTML-Code vereinfachen

Auch HTML-Code kann in den Händen von unbedarften, amoklaufenden Entwicklern zu Bloatware verkommen. Ein gutes Beispiel stellt die Seite dar, die Suchresultate nach FlirtCity-Inserenten darstellt. Dort werden alle Benutzer aufgelistet, die den Suchkriterien entsprechen. Eine Tabellenzeile sieht folgendermassen aus:

<tr bordercolor="#000000" valign="middle">
  <td bgcolor="#D5EAF4" height="25" class="text_klein" width="180"><A HREF="../user_details.php?my_pic_member_id=157382" onClick="NewWindow(this.href,'name','775','650','yes');return false">Croatia_Lady                        </td>
  <td bgcolor="#D5EAF4" height="25" class="text_klein" width="25"><IMG onmouseover="return overlib('<center><img src=http://images.partyguide.ch//memberfotos_thumbs/157382.jpg></center>', CAPTION, 'Foto');" onmouseout="return nd();" SRC="http://partyguide.ch/img/foto.gif" BORDER=0>  </td>
  <td bgcolor="#D5EAF4" height="25" class="text_klein" width="25">18 </td>
  <td bgcolor="#D5EAF4" height="25" class="text_klein" width="160">Steffisburg </td>
  <td bgcolor="#D5EAF4" height="25" align="left" class="text_klein" width="25"><IMG SRC="../img/wappen_be.gif"> </td>
  <td bgcolor="#D5EAF4" height="25" align="left" class="text_klein" width="30"><IMG SRC="../img/ch.gif"> </td>
  <td bgcolor="#D5EAF4" height="25" align="right" class="text_klein" width="130">25.12.2005 21:48:00 </td>
  <td bgcolor="#D5EAF4" height="25" align="right" class="text_klein" width="30"><A HREF="../user_details.php?my_pic_member_id=157382" onClick="NewWindow(this.href,'name','775','650','yes');return false"><IMG SRC="../img/info.gif"  BORDER=0></A> </td>
</tr>
<tr bordercolor="#000000" valign="middle">
  <td bgcolor="#FFFFFF" height="25" class="text_klein" width="180"><A HREF="../user_details.php?my_pic_member_id=52676" onClick="NewWindow(this.href,'name','775','650','yes');return false">Nini86                        </td>
  <td bgcolor="#FFFFFF" height="25" class="text_klein" width="25"><IMG onmouseover="return overlib('<center><img src=http://images.partyguide.ch//memberfotos_thumbs/52676.jpg></center>', CAPTION, 'Foto');" onmouseout="return nd();" SRC="http://partyguide.ch/img/foto.gif" BORDER=0>  </td>
  <td bgcolor="#FFFFFF" height="25" class="text_klein" width="25">19 </td>
  <td bgcolor="#FFFFFF" height="25" class="text_klein" width="160">Schliern </td>
  <td bgcolor="#FFFFFF" height="25" align="left" class="text_klein" width="25"><IMG SRC="../img/wappen_be.gif"> </td>
  <td bgcolor="#FFFFFF" height="25" align="left" class="text_klein" width="30"><IMG SRC="../img/ch.gif"> </td>
  <td bgcolor="#FFFFFF" height="25" align="right" class="text_klein" width="130">25.12.2005 20:00:00 </td>
  <td bgcolor="#FFFFFF" height="25" align="right" class="text_klein" width="30"><A HREF="../user_details.php?my_pic_member_id=52676" onClick="NewWindow(this.href,'name','775','650','yes');return false"><IMG SRC="../img/info.gif"  BORDER=0></A> </td>
</tr>

Je nach zurückgelieferten Resultaten wiederholt sich dieser HTML-Block dutzende, ja manchmal hunderte Male.

Schlichtwegs eine Katastrophe! Vielleicht mag man in den späten Neunzigern solchen Code als vorbildlich eingestuft haben – im 2005 ist er es garantiert nicht mehr.

Fehler 1 – Sich wiederholender Code

Jede Tabellenzelle erhält eine Hintergrundfarbe zugewiesen. Jede Zeile soll alternierende Farben aufweisen, um die Lesbarkeit der Resultate zu verbessern. Die Idee dahinter ist löblich – die Umsetzung unter aller Sau. Jeder Tabellenzelle wird auch explizit eine Höhe zugewiesen (height). Manchmal findet man auch das Attribut align, das die Ausrichtung des Textes innerhalb einer Zelle steuer. Und zu guter letzt wird auch fast jeder Zelle noch eine CSS-Klasse zugewiesen.

Die von mir vorgeschlagene Lösung sieht viel einfacher aus – gemäss meinem Credo „Keep it simpleTM„:

Zuerst einmal kreiert man ein CSS-File und bindet dieses per Include in jede Seite ein. Deren Inhalt (auszugsweise):

table.tblListing              {}
table.tblListing tr td        {background-color:#FFFFFF;height:25px;font-size:10px;padding:4px;}
table.tblListing tr.trOdd td  {background-color:#D5EAF4;}

Der korrespondierende HTML-Code für die Tabelle sähe folgendermassen aus:

<table>
<colgroup>
 <col width="180" />
 <col width="25" />
 <col width="25" />
 <col width="160" />
 <col width="25" />
 <col width="30" />
 <col width="130" />
 <col width="30" />
</colgroup>
<tr class="trOdd">
 <td>...</td>
 <td>...</td>
 <td>...</td>
 <td>...</td>
 <td align="right">...</td>
 <td>...</td>
 <td>...</td>
 <td align="right">...</td>
</tr>
<tr>
 <td>...</td>
 <td>...</td>
 <td>...</td>
 <td>...</td>
 <td align="right">...</td>
 <td>...</td>
 <td>...</td>
 <td align="right">...</td>
</tr>
</table>

Fazit: Unmengen an unnötigen Zeichen werden durch einfachste Hilfsmittel wie intelligenteren HTML-Formulierungen und Cascading Stylesheets (CSS) eingespart. Man beachte auch den colgroup-Block zu Beginn der Tabelle. Heutzutage ist es wirklich nicht mehr nötig, die Spaltenbreite in jeder Zeile neu zu definieren. A propos: Wieso hat die Tabelle eine fixe Breite?

Fehler 2 – URIs

Der Inhalt der Zellen weist auch einige Links und Verweise auf Grafikdateien auf. Auch hier könnte man mit intelligenter Strukturierung der Datenablage Doppelläufigkeiten vermeiden. Wieso Bilder mit

<IMG SRC="../img/wappen_be.gif">

eingebunden werden, ist mir schleierhaft. Ich würde immer absolut addressieren und nur dort, wo dies definitiv nicht möglich ist, davon abweichen. So könnte man sich die .. sparen. Hochgerechnet mit Anzahl Zeilen mal Anzahl Besuche mal 8 (ergibt Bytes) sollte für einen Tag dann doch eine stattliche Summe an eingesparter Datenmenge ergeben.

Fehler 3 – JavaScript-Funktionsnamen

Programmierer sollten wenn möglich aussagekräftige Namen für ihre Funktionen verwenden. Auf den ersten Blick ist dies bei

<A HREF="../user_details.php?my_pic_member_id=52676" onClick="NewWindow(this.href,'name','775','650','yes');return false"><IMG SRC="../img/info.gif"  BORDER=0></A>

gut gelöst. Ich sehe auf den ersten Blick, dass hier also ein neues Fenster geöffnet werden soll. Doch vergegenwärtigt man sich, dass diese Funktion in jeder Zeile der Resultate auftaucht, wird es mir übel. Ich würde in einem solchen Fall dann doch auf die Lesbarkeit verzichten und die Funktion zusammenschmelzen:

<a href="#" onclick="win(52676)">...</a>

Die JavaScript-Funktion würde also die redundanten Angaben in der Funktion selber beeinhalten, anstatt all die identischen Angaben in jeder Zeile zu wiederholen:

function win(intUserId) {
 var intWinWidth = 775;
 var intWinHeight = 650;
 var strURL = '/user_details.php?my_pic_member_id=' + intUserId;
 
 window.open(strURL,intWinWidth,intWinHeight,...);
 return false;
}

Fazit

Da ist noch viel zu tun! Ich bleibe dran und bin mir ganz sicher, auch in den nächsten Folgen dieser Serie viele weitere Leckerbissen präsentiert werden können.

Tags:
Labels: Allgemein

Kommentar erfassen