Dojos für Entwickler 2. Stefan Lieser

Чтение книги онлайн.

Читать онлайн книгу Dojos für Entwickler 2 - Stefan Lieser страница 2

Автор:
Серия:
Издательство:
Dojos für Entwickler 2 - Stefan Lieser

Скачать книгу

      Lösung 1

      Ein UserControl für Markdown-Textauszeichnungen

      Show up Mark down

      Texte mit Markdown-Auszeichnungen in einem Control darzustellen, das war die Aufgabe. Natürlich ist bei der Lösung wieder alles im Fluss. Und weil das im echten Leben auch so ist, muss wieder einmal eine Lösung her, die evolvierbar ist. So ist sichergestellt, dass spätere Anforderungen einfach umsetzbar sind.

      Mit Markdown steht eine Textauszeichnung zur Verfügung, die einfach anzuwenden ist [1] [2]. Das liegt daran, dass auf Schnickschnack verzichtet wurde. Es handelt sich nicht um eine weitere Variante des Themas „Viele Klammern werden das Problem schon lösen“. Statt also wie bei HTML auf spitze Klammern oder bei RTF auf geschweifte Klammern zu setzen, verwendet Markdown Zeichen wie etwa das Sternchen, um damit Passagen eines Textes auszuzeichnen. Das macht die Sache beim Schreiben eines Textes deutlich einfacher, weil weniger Formalismen erforderlich sind. Allerdings wird, damit einhergehend, das Parsen eines Textes nicht unbedingt einfacher. So wird in Markdown beispielsweise ein einzelnes Sternchen sowohl zur Markierung von kursivem Text verwendet als auch zur Kennzeichnung von Aufzählungen. Das zu erkennen ist die Herausforderung beim Parsen eines Markdown-Textes.

      Kleine Schritte

      Im ersten Schritt habe ich die Aufgabe wieder klein gehalten. Mir ist es wichtig, jeweils einen Teil der insgesamt gewünschten Funktionalität komplett fertig zu kriegen. Was nützt es mir, wenn ich zwar Markdown-Texte nach allen Regeln der Kunst zerlegen kann, davon jedoch noch nichts visualisiert wird? Folglich habe ich mich erst einmal darauf beschränkt, nur kursiv und fett zu erkennen und in einem UserControl zu visualisieren. Text, der in einfache Sternchen eingefasst ist, soll *kursiv* dargestellt werden, Text in doppelten Sternchen **fett**.

      Meine ersten Überlegungen drehten sich um die Frage, wie ich einen Text nach der Erkennung der Markdown-Auszeichnungen repräsentieren möchte. Wie sieht eine geeignete Datenstruktur aus? Um das Einfachste zu tun, habe ich mir überlegt, dass der Text nach der Zerlegung aus TextElementen bestehen könnte. Enthält ein Text keinerlei Markdown-Auszeichnungen, wäre der gesamte Text ein einzelnes TextElement.

      Enthält der Text jedoch ein Wort in Fettschrift, würde ich diesen Text in drei TextElemente zerlegen:

       ein TextElement in normaler Schrift,

       ein TextElement in fetter Schrift,

       T wieder ein TextElement in normaler Schrift.

      Der Text „Ein **fettes** Wort“ würde also in die drei TextElemente „Ein “, „fettes“, „Wort“ zerlegt. Beachten Sie die Leerzeichen: nach „Ein“ und vor „Wort“ ist jeweils ein Leerzeichen.

      Durch diese simple Datenstruktur kann die Zerlegung eines Markdown-Textes schrittweise erfolgen: Zuerst werden fett hervorgehobene TextElemente extrahiert. Anschließend werden aus den bereits gebildeten TextElementen weitere gebildet, um so kursive Texte darzustellen. Dazu muss die TextElement-Datenstruktur neben dem Text die Information mitführen, ob der Text fett und/oder kursiv dargestellt werden soll. Listing 1 zeigt die entsprechende Datenstruktur.

      Listing 1

      Grundlegende Datenstruktur.

      public class TextElement { public string Text { get; set; } public bool Fett { get; set; } public bool Kursiv { get; set; } }

      Aus diesen überlegungen hat sich der in Abbildung 1 gezeigte Flow ergeben.

      [Abb. 1]

       Fett und kursiv gesetzte Textteile extrahieren.

      Im ersten Schritt wird der eingehende String in ein TextElement-Objekt umgewandelt. Weil anschließend jeweils eine Aufzählung von TextElement-Objekten bearbeitet wird, liefert die Funktionseinheit Verpacke_in_TextElement gleich eine Aufzählung, die allerdings immer nur ein einzelnes Objekt enthält.

      Anschließend werden Texte extrahiert, die in Fettschrift ausgezeichnet sind. Es wäre denkbar, dass diese Funktionseinheit später auf mehr als einem TextElement arbeiten muss. Das könnte zum Beispiel der Fall sein, wenn vor der Fettschrift die Überschriften extrahiert werden. Somit ist es sinnvoll, als Eingang der Funktionseinheit gleich eine Aufzählung von TextElement-Objekten vorzusehen.

      Nach dem Extrahieren von Fettschrift folgt das Extrahieren der kursiv ausgezeichneten Texte. Wieder wird eine Aufzählung von TextElement-Objekten behandelt. Werden im eingehenden Datenstrom kursiv ausgezeichnete Texte gefunden, dann wird ein TextElement möglicherweise in mehrere TextElement-Objekte zerlegt. Die Anzahl der ausgehenden TextElement-Objekte kann also höher sein als auf der Eingangsseite.

      Nun mag dem einen oder anderen Leser durch den Kopf gehen, dass das gewählte Verfahren eventuell aus Laufzeitgründen ineffizient ist. Ja, das kann sein. Aber an dieser Stelle kümmert mich das nicht. Die Lösung ist dazu gedacht, Markdown-Texte in einem Label-Control zu visualisieren. Das heißt, es werden typischerweise wenige, noch dazu kurze Texte bearbeitet. Für die Verarbeitung von Massendaten ist dieser Ansatz möglicherweise nicht optimal.

      Aber das ist gerade nicht die Aufgabenstellung. Es genügt hier also, das Einfachstmögliche zu tun. Der gewählte Weg sieht mir bis hierhin in jedem Fall gut evolvierbar aus. Weitere Markdown-Elemente zu erkennen bedeutet nur, eine entsprechende Funktionseinheit zu implementieren, die für das Zerlegen zuständig ist. Diese kann dann leicht in den bestehenden Flow eingehängt werden. Spannend bleibt dabei die Frage, ob die Datenstruktur TextElement dann weiterhin ausreicht. Doch bevor ich das herausfinde, folgt nun die Implementation für das Erkennen von Fettschrift. Listing 2 zeigt einige Tests dazu.

      Listing 2

      Erst mal testen: Fett-Formatierungen erkennen.

      [TestFixture] public class Extrahiere_Fett_Tests { private Extrahiere_Fett sut; private IEnumerable<TextElement> result; [SetUp] public void Setup() { sut = new Extrahiere_Fett(); sut.Result += x => result = x; } [Test] public void Normaler_Text_ ohne_Fettschrift() { sut.Process(new[] {new TextElement{ Text = "x"}}); Assert.That(result.Select( x => x.Text), Is.EqualTo(new[]{"x"})); Assert.That(result.Select( x => x.Fett), Is.EqualTo(new[]{false})); Assert.That(result.Select( x => x.Kursiv), Is.EqualTo(new[]{false})); } [Test] public void Fettschrift_am_ Anfang_eines_TextElements() { sut.Process(new[] { new TextElement { Text = "**fett** x" } }); Assert.That(result.Select( x => x.Text).ToArray(), Is.EqualTo(new[] { "fett", " x" })); Assert.That(result.Select( x => x.Fett).ToArray(), Is.EqualTo(new[] { true, false })); Assert.That(result.Select( x => x.Kursiv).ToArray(), Is.EqualTo(new[] { false, false })); } [Test] public void Mehrfach_ Fettschrift() { sut.Process(new[] { new TextElement { Text = "**f1****f2** y**f3**" } }); Assert.That(result.Select( x => x.Text).ToArray(), Is.EqualTo(new[] { "f1", "f2", "y", "f3" })); Assert.That(result.Select( x => x.Fett).ToArray(), Is.EqualTo(new[] { true, true, false, true })); Assert.That(result.Select( x => x.Kursiv).ToArray(), Is.EqualTo(new[] { false, false, false, false })); } [...] }

      Die

Скачать книгу