dedlfix: Vereinfachung meines Blättermechanismus

Beitrag lesen

Hi!

beispielsweise die konsequente Trennung von Steuerung, Datenbeschaffung und Datanaufbereitung, so wie es Tom angeschnitten hat.

Wenn man alle Programmbestandteile mischt, hat man es schwerer, die Übersicht zu behalten und vor allem Fehler zu suchen. Stattdessen ist es von Vorteil, seinen Anwendungsfall sorgfältig zu planen und Aufgaben in Teilaufgaben runterzubrechen. Diese Teilaufgaben sollten klar voneinander abgrenzbar sein, und das sollte sich auch im Code widerspiegeln. So hat man es später einfacher diese Teilaufgaben in Funktionen auszulagern, falls man solche nicht sowieso schon von Anfang an erstellt.

Ich vermute, er meint, dass Tom meint, anhand einer übergebenen Seite die entsprechenden Zeilen auslese, separat die Steuerung und wieder separat die Ausgabe aufbereite.

Die Ausgabe sollte nicht mehr entscheiden müssen, ob anhand der Daten bestimmte Elemente ausgeblendet werden sollen. Stattdessen kann man diese Information im Hauptteil berechnen und nur noch Flags an den Ausgabeteil reichen, am besten als Array (oder Objekt), damit nicht so viele einzelne Variablen herumliegen. Wobei hier nicht die Anzahl als solche ein Problem darstellt, sondern die Ordnung. In einem Array/Objekt sind sie alle schön beieinander.

Tobias meinte, dass kein <div>-Tag innerhalb eines <a>-Tags sein dürfe, was meine Systematik wiederum über den Haufen wirft.

Es gibt grob gesagt zwei Arten von HTML-Elementen: Block-Elemente und Inline-Elemente. Block-Elemente haben die Eigenschaft, eine neue Box auf neuer Zeile zu erstellen. Inline-Elemente setzen den Textfluss fort. Block-Elemente strukturieren im Groben, Inline-Elemente formatieren einzelne Textstücke - sag ich jetzt einfach mal so vereinfachend. Für die eigentliche Formatierung ist CSS zuständig, und man kann damit auch Blöcke zu Inlineren umformatieren und umgekehrt, aber tun wir mal so, als ob es CSS nicht gäbe. Jedes HTML-Element hat eine Grundformatierung gemäß seiner Aufgabe. Wenn nun ein Inline-Element mitten im Text steht und darin ein Block-Element notiert wird, so würde das Block-Element den Fluss, in dem sich der Inliner befindet, sprengen, weil es eine neue Zeile beginnt. Und in der Tat ist es so, dass Browser beim Auftreten von Blockelementen in Inlinern, letzteres einfach schließen und einen neuen Block anfangen - oder auch nicht. Bis HTML 4 war das Verhalten bei solchen Schachtlungsfehlern nicht definiert und die Browser konnten damit machen was sie wollen. In der HTML-Referenz steht zu jedem Element, worin es in welcher HTML-Version stehen und was es enthalten darf. Es steht allerdings nicht dabei, ob es ein Block- oder Inline-Element ist. Das ist nämlich nicht explizit festgelegt, sondern ergibt sich aus den HTML-DTDs. Eine DTD ist quasi ein technisch auswertbares Gesetz zur Strukturierung von HTML-Dokumenten (ist jetzt nicht exakt formuliert, aber das stört jetzt für das Verständnis nicht). Anhand der DTDs sind auch die Referenz-Seiten zu HTML entstanden. Deswegen lesen die sich auch ziemlich technisch. Wenn du dir jedoch mal das div anschaust, siehst du darin im Abschnitt Kindelemente eine ausklappbare Zusammenfassung von Block- und Inline-Elementen.

In deinem Fall brauchst du eigentlich nur das div um das a zu legen und nicht umgekehrt. Aber ... Dann kommt auch noch die Semantik ins Spiel, wenn man genau sein will. Deine Blätter-Elemente bilden eigentlich eine Liste. Du brauchst sie nicht mit dem Universalelement div auszuzeichnen, wenn du eine ungeordnete Liste nimmst, also ein ul um's Ganze und die einzelnen Elemente sind li. Wenn verlinkt steht darin noch ein a und darin der Linktext, ansonsten nur das nackige li mit Nicht-Link-Text. Fertig - zumindest der HTML-Teil. Formatiert wird das ganze mit CSS, indem die Anstriche und Abstände gegebenenfalls entfernt werden, und so weiter. Die Browser haben eingebaute oder nachrüstbare Werkzeuge, mit denen man sich die aktuelle Formatierung inklusive der Default-Werte anzeigen lassen kann, um so herauszufinden, was man alles ändern muss.

Und schließlich Deine Antwort bzgl. des "Vorbeiblättern" etc.

Du willst ja immer nur einen Teil anzeigen lassen. Dazu musst du eigentlich auch nur den anzuzeigenden Teil der Datei einlesen. Das geht bei einer Datenbankabfrage zum Beispiel mit LIMIT recht bequem. Zudem braucht man eine zweite Abfrage, die die Gesamtzahl Datensätze ermittelt. Textdateien bieten diesen Luxus nicht. Wenn du die Zeilenanzahl haben willst, musst du die Datei vollständig durchlaufen und die Zeilenenden zählen (oder zeilenweise einlesen und diese Zeilen zählen). Die Anzahl lässt sich nicht aus der Dateigröße berechnen, weil jede Zeile unterschiedlich lang sein kann. Ansonsten brauchst du jedoch nur den Teil der Zeilen aufzuheben, der wirklich angezeigt werden soll und nicht komplett alle Zeilen. Wenn du schon eine Blätterfunktion haben willst, dann doch sicher, weil die Daten einerseits zu umfangreich zum Anzeigen geworden sind und andererseits sie auch nur unnötig Speicher belegen, wenn du große Teile gar nicht haben willst.

Tom schlug daraufhin vor, die unnötigen Zeilen am Anfang zu überspringen und die x Zeilen der anzuzeigenden Seite zu lesen und zu merken und dann das Auslesen zu stoppen. Damit kommst du aber nicht zur Gesamtzahl der Zeilen. Du musst also weiter bis zum Ende lesen, brauchst aber diese Zeilen auch nicht abzuspeichern. Soweit erstmal so einfach, doch der Teufel steckt im Detail. Jemand übergibt als Parameter, dass er Seite n+m haben will, aber du hast nur Daten für maximal n Seiten. Die Gesamtzahl weißt du noch nicht, die ergibt sich erst beim Auslesen. Aber du musst vorher schon berechnen, von wo bis wo du die Zeilen aufheben willst. Erkennst du das Problem? Wir wollen effizient mit dem Speicher umgehen, müssen aber auch Fehlerfälle beachten, die wir nicht durch Vorabberechnungen erkennen können.

Das Problem besteht natürlich nicht, wenn du die Datei im Ganzen einliest und dann erst rechnest, wobei der Speicherverbrauch aber nicht optimal ist. Wenn du dir für den Anfang die genannten Schwierigkeiten ersparen willst, kannst du ja erstmal die ineffiziente Variante nehmen. Doch je mehr Daten du hast, desto mehr kostet dich das Ressourcen. Dass du immer die gesamte Datei durchlaufen musst, bleibt dir jedoch in keinem Fall erspart. Wenn das zunehmend zum Problem zu werden droht, solltest du dir über eine andere Datenhaltung Gedanken machen, beispielsweise eine Datenbank. Die bekommt die Gesamtzahlberechnung deutlich einfacher hin, und auch die Auswhl der Daten für die aktuelle Seite.

Lo!