onli blogging - Informatik https://www.onli-blogging.de/ de Serendipity 2.5.0 - http://www.s9y.org/ Fri, 06 Sep 2024 10:48:55 GMT https://www.onli-blogging.de/templates/2k11/img/s9y_banner_small.png RSS: onli blogging - Informatik - https://www.onli-blogging.de/ 100 21 Acht Kriterien für Programmabhängigkeiten https://www.onli-blogging.de/2429/Acht-Kriterien-fuer-Programmabhaengigkeiten.html Informatik https://www.onli-blogging.de/2429/Acht-Kriterien-fuer-Programmabhaengigkeiten.html#comments https://www.onli-blogging.de/wfwcomment.php?cid=2429 6 https://www.onli-blogging.de/rss.php?version=2.0&type=comments&cid=2429 [email protected] (onli) <p>Ob im Tagesjob oder für eigene Projekte, welche Abhängigkeiten (Module, Gems, libs, …) für Projekte gewählt wurden hat einen massiven Einfluss auf die spätere Entwicklung und besonders die Instandhaltung der Software. Während ich mir zu Beginn dazu kaum Gedanken gemacht habe, ist mittlerweile fast schon ein Regelwerk im Kopf entstanden. Teils aus der Mischung der positiven und den schmerzhaft negativen Erfahrungen, teils aus offiziellen Regeln für Qualitätskriterien auf der Arbeit. </p> <p>So denke ich derzeit:</p> <h4>0. Ist die Abhängigkeit notwendig? </h4> <p>Die oberste Direktive für Notwendigkeit ist Aufwandsminimierung. Nur wenn sie insgesamt Aufwand minimiert kann eine Abhängigkeit positiv wirken. Also nur wenn sie etwas umsetzt, was mit eigenen Code nicht gegangen wäre oder viel Arbeit gekostet hätte. Entsprechend ist die erste Frage, ob die Abhängigkeit funktionell sinnvoll und wie notwendig sie ist.</p> <div class="serendipity_imageComment_img"><a class="serendipity_image_link" href='https://www.onli-blogging.de/uploads/project_and_dependencies_ki_cover.jpg'><!-- s9ymdb:2036 --><img class="serendipity_image_center" width="400" height="400" srcset="https://www.onli-blogging.de/uploads/project_and_dependencies_ki_cover.800W.serendipityThumb.jpg 1200w,https://www.onli-blogging.de/uploads/project_and_dependencies_ki_cover.400W.serendipityThumb.jpg 800w" src="https://www.onli-blogging.de/uploads/project_and_dependencies_ki_cover.serendipityThumb.jpg" loading="lazy" alt=""></a> </div> <figcaption class="serendipity_imageComment_txt">Abhängigkeiten stellen manchmal viele Anforderungen an das sie nutzende Projekt. KI-generiertes Symbolbild.</figcaption><p>Warum diese Aufwandsperspektive? Weil jede Abhängigkeit potentiell Folgearbeit bedeutet. Wann immer eine neue Version herauskommt, die Anpassungen am eigenen Code einfordert, muss nur wegen der Abhängigkeit Arbeit investiert werden. Und das ist dann praktisch immer verlorene Arbeitszeit, die das Projekt an sich nicht weiterbringt. Aber es kann auch andersherum sein: Wenn durch die Einbindung einer Abhängigkeit eine stete Folgearbeit ausgelagert werden kann, wie die Anpassung an eine sich immer wieder ändernde API, spricht viel für die Einbindung. Das Szenario ist aber selten. </p> <p>Ein Beispiel für diese Überlegungen ist der MF2-Parser, den wir für Webmentions in Serendipity <a href="https://github.com/s9y/Serendipity/pull/841">eingebunden haben</a>. Da war ich am Zögern, ob so viel fremder Code notwendig ist, könnte man das HTML doch auch auf anderem Wege parsen. Aber der offizielle MF2-Parser ist im Zweifel exakter und vermeidet dann Arbeit, wenn sonst der eigene Code für die verschiedenen Web&shy;men&shy;tion-For&shy;ma&shy;te immer wieder angepasst werden müsste. Er war auch der empfohlene Weg der Umsetzung, daher schlug ich seine Einbindung vor. </p> <p>Die Erwartungshaltung der benötigten Folgearbeit variiert hier stark je nach Entwicklungssprache und dann nochmal je nach Nische innerhalb der Sprache, ist sie groß genug. Um ein paar Erfahrungswerte zu teilen: Javascript samt Node ist berüchtigt für die kurze Halbwertszeit und den wahnsinnigen geforderten Aufwand; bei Flutter beziehungsweise Dart gab es da noch keine etablierte Kultur, sondern variierte es wohl je nach Entwicklerhintergrund; Module für Ruby und PHP (hier im Gegensatz zur Sprache selbst) sind normalerweise respektvoll.</p> <h4>1. Welche Abhängigkeiten hat die Abhängigkeit? </h4> <p>Es empfiehlt sich einen Blick auf die Abhängigkeiten der Abhängigkeit zu werfen. Je mehr das sind, desto eher können durch sie neue Probleme entstehen. Ob das Interaktionen mit dem eigenen Code sind oder, wahrscheinlicher, wegbrechende oder sich ändernde Projekte Probleme verursachen, die dann über die Abhängigkeit an das eigene Projekt weitergegeben werden.</p> <h4>2. Wie beliebt ist die Abhängigkeit? </h4> <p>Die Beliebtheit kann durch das jeweilige Empfehlungssystem transportiert werden, wie die Sterne bei Github, oder durch Artikel, die das Modul vorstellen und loben. Beliebtheit ist erstmal positiv, die Weisheit der Masse wird nicht völlig unberechtigt ein Projekt hervorheben. Und viel Aufmerksamkeit kann die Chance erhöhen, dass bei einem Einschlafen der Entwicklung sich ein Nachfolgeprojekt bildet. <br /> Gleichzeitig kann Beliebtheit negative Auswirkungen haben, wenn die Entwickler durch einen Nutzeransturm überfordert werden, die gefühlte Popularität ihnen zu Kopf steigt oder schlicht durch die Masse an Anforderungen der Projektfokus verlorengeht. </p> <p>Gleichzeitig gibt es immer wieder gute Module, die von der Masse ignoriert werden. Oder das technisch bessere Folgeprojekt, das zwar beliebt ist, aber weniger als das früher etablierte. Die Inertia der Masse ist hier eben auch ein Thema. Daher ist Beliebtheit ein Faktor, aber ein schwacher.</p> <h4>3. Ist die Dokumentation brauchbar? </h4> <p>Die Brauchbarkeit der Dokumentation würde ich sehr viel höher hängen. Brauchbarkeit ist hier bewusst gewählt, statt Umfang. Ich habe mehrfach sehr umfangreiche Dokumentation erlebt, die aber überhaupt nicht hilfreich war, weil sie die aufkommenden Nutzungsfragen einfach nicht beantwortete. </p> <div class="serendipity_imageComment_img"><a class="serendipity_image_link" href='https://www.onli-blogging.de/uploads/Screenshot_2024-08-09_at_15-17-17_Documentation_Pipes.png'><!-- s9ymdb:2035 --><img class="serendipity_image_center" width="800" height="448" srcset="https://www.onli-blogging.de/uploads/Screenshot_2024-08-09_at_15-17-17_Documentation_Pipes.1200W.serendipityThumb.png 2600w,https://www.onli-blogging.de/uploads/Screenshot_2024-08-09_at_15-17-17_Documentation_Pipes.800W.serendipityThumb.png 1200w,https://www.onli-blogging.de/uploads/Screenshot_2024-08-09_at_15-17-17_Documentation_Pipes.400W.serendipityThumb.png 800w" src="https://www.onli-blogging.de/uploads/Screenshot_2024-08-09_at_15-17-17_Documentation_Pipes.serendipityThumb.png" loading="lazy" alt=""></a> </div> <figcaption class="serendipity_imageComment_txt">Pipes ist nicht direkt eine Abhängigkeit, aber aus ganz ähnlichen Gründen war <a href="https://www.pipes.digital/docs">die Dokumentationsseite</a> meine erste Priorität nach der initialen Softwareentwicklung.</figcaption><p>Ein gutes Readme kann völlig ausreichen, solange es den Umgang mit der gebotenen API sauber erklärt. Wobei bei vielen Projekten eine ausführlichere Beschreibung der Optionen in einer dedizierten Dokumentation erstrebenswert ist.</p> <h4>4. Wann war das letzte Update? </h4> <p>Das Datum des letzten Updates bestimmt, ob ein Projekt wirklich aktiv ist oder nicht. </p> <p>Das darf wieder nicht überbewertet werden. Manche Projekte sind stabil und fertig, sie brauchen nur seltene Anpassungen und das lange vergangene Datum des letzten Updates bedeutet kein brach liegendes Projekt, sondern ein stabiles. Genauso kann ein kürzliches Update und ein hohes Updateinterval auf Instabilität und fehlende Entwicklerdisziplin hindeuten. Aber es gibt hier eine gesunde Balance, die das Ideal wäre. </p> <h4>5. Wie viele offene Bugreports und Pullrequests gibt es? </h4> <p>Hier kommt es wieder stark auf den Kontext an. </p> <p>Ein übervoller Bug- oder Issuetracker ist erstmal ein Alarmsignal. Blöd sind auch sich aufstauende Pullrequests. Beides zeichnet das Bild eines überforderten Projekts, bei dem Probleme der Nutzer nicht angegangen werden. </p> <p>Aber man darf diesen Faktor auch nicht überbewerten. Bei einem sehr beliebten Projekt beispielsweise werden fast zwangsläufig sehr viele Nutzerberichte zu Problemen zusammenkommen, die kein Entwicklerteam der Welt alle ordentlich bearbeiten kann. Wenn trotzdem auf wichtige Beiträge geachtet wird, die Entwicklung trotzdem läuft, dann ist der volle Bugtracker fast ein gutes Zeichen: Denn dann wurde kein Bot eingesetzt, der automatisch Bugreports schließt, was immer eine feindselige Haltung zur Nutzerschaft auslöst und wichtige Berichte ungesehen verschwinden lässt. </p> <p>Genauso können sich bei alten Projekten Berichte ansammeln, die nicht wirklich angegangen werden können, die aber auch nicht unpassend sind und daher lange aufbleiben. Wieder, solange die Software und die Entwicklung trotzdem läuft ist das völlig okay.</p> <h4>6. Wie redet der oder reden die Maintainer mit Nutzern? </h4> <p>Das ist fast das wichtigste: Wichtiger als der Zustand des Issuetrackers in absoluten Zahlen ist das Verhalten der Entwickler darin. Werden Nutzer für ihre Berichte abgekanzelt, oder werden sie ernstgenommen und angehört? Werden Nutzer beleidigt, ihre Bugreports ohne verständlichen Grund geschlossen, fehlt einfach Freundlichkeit und Respekt sollte man sich soweit Fernhalten wie möglich.</p> <div class="serendipity_imageComment_img"><a class="serendipity_image_link" href='https://www.onli-blogging.de/uploads/developer_god_ki_cover.jpg'><!-- s9ymdb:2034 --><img class="serendipity_image_center" width="400" height="400" srcset="https://www.onli-blogging.de/uploads/developer_god_ki_cover.800W.serendipityThumb.jpg 1200w,https://www.onli-blogging.de/uploads/developer_god_ki_cover.400W.serendipityThumb.jpg 800w" src="https://www.onli-blogging.de/uploads/developer_god_ki_cover.serendipityThumb.jpg" loading="lazy" alt=""></a> </div> <figcaption class="serendipity_imageComment_txt">Ist dies das vermutbare Selbstbild des Maintainers ist Abstand zu wahren. KI-generiertes Symbolbild.</figcaption><p>Dabei lohnt sich auch ein Blick darauf, wer antwortet. Eine häufige Projektkonfiguration ist der erfahrene und freundliche Originalentwickler, dem aber die Zeit fehlt, und dann gibt es eine Nummer 2, die im Bugtracker viele Anfragen beantwortet. Dem Originalentwickler gegenüber wird diese Person immer nett sein, aber es besteht dann leider die Tendenz, gegenüber Nutzern respektlos zu antworten. Wird das geduldet, und wie weit ist diese Entwicklung vorangeschritten? Das wird viel darüber verraten, ob vom Originalentwickler dem Projekt noch Aufmerksamkeit geschenkt wird. </p> <p>Auch wenn man selbst in diesen Projektkommunikationsmitteln nicht aktiv teilnehmen will ist das ein wichtiger Faktor, denn es wird darüber bestimmen wie gut und verständlich Antworten auf Nutzerfragen sind, ob das Projekt Nutzungsprobleme angeht und ob bei der Weiterentwicklung der Nutzer bedacht wird. Und ein vernünftiger, freundlicher Maintainer gleicht fast alle anderen möglichen Schwachpunkte eines Projektes wieder aus, denn seine Handlungen werden mittelfristig der Einstellung gleichen.</p> <h4>7. Wie wurde mit inkompatiblen Änderungen umgegangen? </h4> <p>Der Einfluss des Maintainers kumuliert im Umgang mit Breaking Changes. Also Änderungen der Abhängigkeit, die Änderungen am eigenen Code erfordern. </p> <p>Um die Wichtigkeit des Aufwandsmanagements nochmal klarzumachen hilft vielleicht diese Perspektive: Das eigene Team hat X Mann. Wieviele Leute entwickeln an all den Abhängigkeiten? Wieviele entwickeln an der Grundsprache, wenn z.B. wie bei Flutter Google hunderte oder tausende Entwickler beschäftigt? Jeweils sind es viel mehr, also kann das eigene Team die investierte Arbeit der anderen nicht kontern. Das Projekt kann nur erfolgreich sein, wenn das nicht notwendig ist, wenn eben inkompatible Änderungen vermieden werden. </p> <p>Daher sind sind sie immer ein großer Negativpunkt. Aber manchmal sind Anpassungen an der Schnittstelle eines Moduls schwer zu vermeiden. Sind sie selten genug, werden die nötigen Änderungen gut erklärt und verständlich gerechtfertigt sind sie natürlich akzeptierbar. Auch hilft es, wenn die Versionsnummer nach Semantic Versioning angehoben wird, zumindest in Ökosystemen, bei denen die Updatetools darauf ausgelegt sind. Dann werden wenigstens Aktualisierungszeitpunkte samt ihren Migrationen etwas besser wählbar. </p> <p>Aber alleine die Nummer korrekt anzuheben reicht eben nicht. Wenn Änderungen einfach so gemacht werden, ohne Rücksicht, ist es Zeit zu rennen. Wenn beispielsweise vorher eine Funktion auf zwei Arten aufgerufen werden konnte, und jetzt eine davon wegfällt nur weil der Maintainer das schöner findet, hat er die Bodenhaftung verloren. Klar, vereinfacht das wesentlich seinen eigenen Code und Aufwand und erklärt er es entsprechend kann auch sowas mal okay sein. Aber grundsätzlich sollte Abwärtskompatibilität eine große Priorität haben. Einfach, weil sonst Abhängigkeit um Abhängigkeit Änderungen einfordern und die verfügbare Arbeitsleistung des eigentlichen Projekts für diese Pflege aufgefressen wird. </p> <p>Besonders klares Zeichen sind Sprüche wie "Ich muss mich nicht rechtfertigen", wenn bei kaputtmachenden Änderungen der Grund erfragt wird, oder wenn beim Versuch die Problematik zu erklären mit emotionaler Manipulation dem Nutzer die Schuld für das Problem gegeben wird, ein Ansprechen der Problematik zu Aggressionen führt. Beides habe ich wirklich gesehen, kürzlich erst wieder. Von solchen Projekten kann man gar nicht genug Distanz wahren.</p> <hr /><p>Ein weiteres Beispiel, dass Arbeit als Entwickler auch eine soziale Komponente hat. </p> <p class="wl_nobottom">Man kann diese Regeln ignorieren und Glück haben, man kann ihnen folgen und trotzdem von unnötigen Änderungen gepiesackt werden. Aber ich glaube, grundsätzlich sind sie kein schlechter Ansatz und recht umfassend. <br /> Gibt es etwas, was ich übersehen habe oder was ihr anders seht?</p> <img src="https://ssl-vg03.met.vgwort.de/na/e99c8235a17e4d7d8e743444624d7d00" width="1" height="1" alt=""> Mon, 02 Sep 2024 08:09:00 +0200 https://www.onli-blogging.de/2429/guid.html Kühl - Schattenorganisation https://www.onli-blogging.de/2337/Kuehl-Schattenorganisation.html HCI Informatik Textformen https://www.onli-blogging.de/2337/Kuehl-Schattenorganisation.html#comments https://www.onli-blogging.de/wfwcomment.php?cid=2337 0 https://www.onli-blogging.de/rss.php?version=2.0&type=comments&cid=2337 [email protected] (onli) <p><a class="serendipity_image_link " href='https://www.onli-blogging.de/uploads/schattenorganisation.jpg'><!-- s9ymdb:1897 --><img class="serendipity_image_left lefticonnob" width="150" height="200" srcset="https://www.onli-blogging.de/uploads/schattenorganisation.1200W.serendipityThumb.jpg 2600w,https://www.onli-blogging.de/uploads/schattenorganisation.800W.serendipityThumb.jpg 1200w,https://www.onli-blogging.de/uploads/schattenorganisation.400W.serendipityThumb.jpg 800w" src="https://www.onli-blogging.de/uploads/schattenorganisation.serendipityThumb.jpg" loading="lazy" alt=""></a><em>Agiles Management und ungewollte Bürokratisierung</em> - mit diesem Untertitel hatte mich <a href="https://www.campus.de/buecher-campus-verlag/wissenschaft/soziologie/schattenorganisation-17584.html">Schattenorganisation</a> gepackt. Denn ich war entsetzt darüber und ziemlich ratlos, wie starr und insgesamt negativ Scrum im neuen Entwicklerteam der Käuferfirma umgesetzt wurde, während meine Firma die Methodik zuvor so positiv genutzt hatte. "Ungewollte Bürokratisierung" schien mir dabei genau das Problem zu beschreiben. </p> <p>Schattenorganisation aber spricht zu diesem Thema nur indirekt. Statt Scrum, Kanban oder anderen gängigen Praktiken in Entwicklerteams wird über die mir vorab völlig unbekannte Holokratie berichtet. Das ist eine Organisationsform für gesamte Organisationen, bei der softwareunterstützt haarklein aufgeschrieben wird welche Rollen es gibt und wie sie arbeiten, daraufhin Arbeiter gerne auch mehreren Rollen zugeordnet werden und das ganze in Kreisen von Rollen organisiert wird, bei denen es keinen klaren Chef gibt. Bilden sich Abweichungen zu den niedergeschrieben Arbeitswegen, sollen diese direkt formal aufgeschrieben werden, die Rollenbeschreibungen, welche Rollen es gibt und wer sie besetzt ändere sich dadurch ständig. Nie wirklich groß, war es wohl doch in entsprechenden Kreisen eine Mode und ein paar Firmen, die man kennt, hatten versucht sich so zu organisieren, <a href="https://medium.com/the-story/management-and-organization-at-medium-2228cc9d93e9">beispielsweise Medium</a>. </p> <p>Kühl zerlegt dieses Konzept in seine Einzelteile. Durch seine Einordnung in organisationswissenschaftliche Modelle und seine Aufarbeitung, wie diese Methode am Ende wirklich gelebt wird (nicht, die informelle Ebene bildet sich immer wieder), blieb von der Holokratie am Ende zumindest bei mir kein positives Bild über. Kühl selbst positioniert sich nicht klar zu dem Konzept, dass diese Wahrnehmung nicht unbeabsichtigt ist kann ich nur mutmaßen. </p> <p>Für Scrum etc gab mir Schattenorganisation keine klare Antworten, aber am Ende doch ein paar Ideen. Wenn Holokratie durch eine maßlose, detaillierte Bürokratisierung Agilität herstellen will, ist das bei Scrum mit seinen Ritualen und festen Rollen gar nicht sehr anders. Die vermeintliche agile Softwareentwicklung nach Scrum wäre also – so ausgestaltet, wie ich es erlebte – in Wirklichkeit eine stark formalisierte, eben bürokratische Methode; und eben nicht die Annäherung an die "natürliche" Entwicklungsform, die FOSS-Projekte und entwicklerbestimmte Teams ohne formalisierenden Manager im Rücken wählen würden. Und wie es dazu kommen konnte, wie auch dieser Gedankengang von Agilität durch Bürokratie bzw Formalisierung funktioniert, dafür gibt der Blick auf die Holokratie dann eben doch ein paar Einblicke. </p> <p class="wl_nobottom">Schattenorganisation zu lesen war also keine totale Zeitverschwendung. Angesichts meiner Fragen hätte ich aber zu einem anderen Buch greifen sollen. Ich finde es schade, dass Kühl nicht über die eine Erwähnung im Nebensatz hinaus im Buch selbst den Bogen geschlagen hat, war Holokratie doch auf dem Klappentext nichtmal erwähnt und sind Scrum sowie Kanban die Arbeitsweisen, an die das Stichwort agil direkt denken lässt. Aber vielleicht stimmt das außerhalb meiner Nische eben nicht, oder war das relevante Stichwort hier eben Management, nicht alleine agil.</p> <img src="https://ssl-vg03.met.vgwort.de/na/1e5ddb0982804583b1994cc3a046034a" width="1" height="1" alt=""> Mon, 15 Jan 2024 08:27:00 +0100 https://www.onli-blogging.de/2337/guid.html Mein Rückblick aufs Studium, Teil 1: Bachelor Informatik TU Darmstadt https://www.onli-blogging.de/2072/Mein-Rueckblick-aufs-Studium,-Teil-1-Bachelor-Informatik-TU-Darmstadt.html Informatik about https://www.onli-blogging.de/2072/Mein-Rueckblick-aufs-Studium,-Teil-1-Bachelor-Informatik-TU-Darmstadt.html#comments https://www.onli-blogging.de/wfwcomment.php?cid=2072 0 https://www.onli-blogging.de/rss.php?version=2.0&type=comments&cid=2072 [email protected] (onli) <p><!-- s9ymdb:1404 --><img class="serendipity_image_left lefticon" width="134" height="58" srcset="" src="https://www.onli-blogging.de/uploads/tud_logo.webp" alt=""> Ich habe viel Zeit an der Uni verbracht, darüber aber hier nur selten geschrieben. Mittlerweile arbeite ich seit ein paar Jahren und das Studium wird mehr und mehr eine ferne Erinnerung. Zeit, ein paar Erfahrungen festzuhalten. </p> <p>Der Start war ein Informatikstudium an der TU Darmstadt, das ich vor fast genau einer Dekade abgeschlossen habe. Es war nur ein Bachelorstudium, den Master machte ich anderswo. Die Rahmenbedingungen waren gut: Die TU galt als gute Uni. Auch wenn es noch Diplomstudenten gab – einer davon wurde unser D&D-Dungeonmaster – war der Umstieg vom Diplomsystem mittlerweile fertig, es gab auch keine Wahl mehr, das schuf Fakten und Klarheit. Unsicherheit kam von den asozialen Studiengebühren, doch die wurden mir im ersten Semester erlassen und im zweiten dank Ypsilanti ganz abgeschafft. Das Studium selbst war von Seiten der Universität ziemlich toll organisiert, aber es war viel Arbeit und die Zeit insgesamt für mich ziemlich chaotisch.</p> <h4>Der Ablauf des Studiums </h4> <p>Da es keine Zulassungsbeschränkung gab saß ich am Anfang des Studiums mit sehr vielen anderen neuen Studenten in völlig überfüllten Hörsälen. Am schlimmsten war da Mathe 1, da passten die Leute nichtmal mehr auf die Stufen neben den Stühlen. Das blieb natürlich nicht so: Es würde mich sehr wundern, wenn mehr als 50% das Studium abgeschlossen haben, zudem sparten sich bald selbst viele die weitermachten die Vorlesungen. </p> <p>Die Übungen waren sowieso wichtiger: In ihnen kam der Stoff vor, der dann in den Prüfungen getestet wurde. Geleitet wurden diese Übungen meist von Studenten, als Nebenjob. Alle meine Prüfungen waren schriftlich, mündliche Prüfungen gab es in anderen Kursen, aber sie waren selten und galten als schwierig. Bei allen regulären Vorlesungen gab es am Ende stattdessen eine schriftliche Prüfung. Ohne irgendeinen Tests an Scheine zu kommen war mit dem Diplomsystem so ziemlich abgeschafft worden, ging aber noch in Seminaren – da wurde dann eine Präsentation bewertet. Das war natürlich der große Stressfaktor: Dass man durch Prüfungen und nach dreimaligen Scheitern an einer Prüfung sogar durch das ganze Studium durchfallen konnte. Zum Glück blieb mir der Drittversuch erspart, aber nicht alle Prüfungen konnte ich auf Anhieb bestehen. Auch deswegen war es die oben erwähnte chaotische Zeit. </p> <p>Die Massenvorlesungen am Anfang deckten die Grundthemen ab. Grundlagen der Informatik (GDI), Formale Grundlagen der Informatik (FGDI), Technische Grundlagen der Informatik (TGDI), Mathe. Davon gab es jeweils drei Kurse, nur TGDI blieb bei zweien. Nach den ersten Semestern kamen dann Kanonikfächer hinzu, "Einführung in X" – Computational Engineering, Computer Microsystems, Foundations of Computing, Human Computer Systems, Data and Knowledge Engineering und Net Centric Systems. </p> <p>Gegen Ende gab es noch Wahlpflichtfächer, wo man sich aus einer Auswahl von Themen die seinen raussuchen konnte, das war die minimale Spezialisierungsmöglichkeit. Bei mir wurde das Kryptographie, Mensch-Computer-Interaktion (HCI) und Künstliche Intelligenz. Man musste ein Bachelorpraktikum abliefern, aber was da die Optionen waren krieg ich nicht mehr zusammen. War das mit <a href="https://www.onli-blogging.de/1108/Bachelorarbeit-Leute-erkennen.html">der Bachelorarbeit</a> kombiniert? Denn die galt es ganz zuletzt zu schreiben, wobei man dafür noch einen Kurs besuchen konnte und dann mit Kommilitonen den Fortschritt besprach, was sehr hilfreich war.</p> <h4>Studiumsinhalte </h4> <p>Worum ging es jeweils? Ich werde nicht alles durchgehen, will aber einen Eindruck der wichtigsten Inhalte geben. </p> <p>In <strong>GDI</strong> ging es ums Bauen von Software. Am Anfang schlicht ums Programmieren: Wir lernten erst <a href="https://racket-lang.org/">Scheme</a> (jetzt Racket, ein LISP), dann Java, programmierten zusammen ein Spiel und lernten über die Komplexität von Algorithmen (O-Notation). Und das war alles GDI 1. An spätere Inhalte erinnere ich mich weniger gut. Ein kurzer Abschnitt wurde in C programmiert. Aber wir müssen auch Stoff über Wasserfallmodelle, Pflichtenhefte, Designpatterns und UML gehört haben – das meiste davon war anders als die erste Vorlesung im Nachhinein irrelevant, aber gut zu wissen dass es das mal gab. Spezielle Algorithmen <a href="https://www.onli-blogging.de/335/UEberlegungen-zur-Quicksort-Optimierung.html">wie Quicksort</a> kamen später auch vor, das war schon hilfreicher, auch Datenstrukturen wie Bäume waren ein wichtiges und nützliches Thema. </p> <p><strong>FGDI</strong> war Logik. Meine Anleitungen um einen <a href="https://www.onli-blogging.de/423/DFA-minimieren.html">Zustandsautomaten zu mimieren</a> und <a href="https://www.onli-blogging.de/231/Hornklauseln-und-Minimalbelegung-Markierungsalgorithmus.html">zum Markierungsalgorithmus</a> stammen daher, ob das nun FGDI 1 oder 2 war ist mir unklar. Anfangs ging es um Grundlagen wie Prädikatenlogik. Ich habe es gehasst, die Artikel landeten im Blog um mir Inhalte ins Hirn zu prügeln und anderen zu helfen. Ich muss aber zugeben, dass es später hilfreich und notwendig war solche formalen Logikausdrücke lesen zu können. FGDI 3 war etwas anders: Da ging es um die Verifikation von Programmen. Die wurden dafür in einer Spezialsprache geschrieben und ihre Richtigkeit musste dann Annahme für Annahme bewiesen werden. Auf der einen Seite absurd komplett nicht praxistauglich, auf der anderen konnte man sich vorstellen, wie das irgendwann doch praxistauglich werden könnte, es hieß sogar Prozessorhersteller würden das bereits machen (und später las ich, sie hätten das größtenteils aufgegeben). </p> <p><strong>TGDI</strong> hasste ich nicht, aber diese technischen Grundlagen hatte ich nie gehabt. Und-, Oder-, XOR-Schaltungen, Verilog und damit irgendwas anfangen – ich schnappte ein paar Grundlagen auf und kam durch die Prüfung. Im zweiten Kurs ging es dann mehr um Prozessorarchitekturen. Ob wir hier oder in GDI in Assembler programmiert haben krieg ich nicht mehr zusammen, aber das war auf jeden Fall spaßig. </p> <p>Bei <strong>Mathe</strong> kann ich kaum noch auch nur die Inhalt benennen. Mathe 1 und 2 war ein wilder Mischmasch von irgendwelchen Mathematikkenntnissen – irgendwas mit Reihen, Ableitungen, Beweisen. Mathe 3 war Computation (und Statistik?), also Mathematik vom Computer lösen lassen, was oft andere Ansätze braucht. Das hatte etwas Berechtigung. Aber Mathematik wie es dort zuvor gemacht wurde war ein pures Aussiebefach und vermittelte wenig, was irgendwie hängenblieb oder ich bisher nochmal gebraucht hätte. Teilweise wiederholten sich Inhalte in den spezialisierteren Fächern, die waren dann relevant und gut sie schonmal gehört zu haben, Gruppen beispielsweise. Aber hätte es kein Siebfach gebraucht hätte man Mathe schlicht weglassen und die Inhalte dort lehren können wo sie benutzt wurden. </p> <p>Bei den "Einführung in X"-Fächern ging es um ganz verschiedene Themen. Bis jetzt lernten wir ja nur allgemeine Grundlagen. <em>Net Centric Systems</em> z.B. konnte dann über Netzwerke und über das Internet reden. Es ging auch darum grob die Forschungsbereiche der Informatik abbilden. Die Wahlpflichtfächer gingen da dann später etwas tiefer, für die, die Interesse an einem bestimmten Thema hatten.</p> <h4>Besondere Inhalte und Lektionen </h4> <p><a class="serendipity_image_link" href='https://www.onli-blogging.de/uploads/kibuch.webp'><!-- s9ymdb:1405 --><img class="serendipity_image_center" width="800" height="450" srcset="https://www.onli-blogging.de/uploads/kibuch.1200W.serendipityThumb.webp 2600w,https://www.onli-blogging.de/uploads/kibuch.800W.serendipityThumb.webp 1200w,https://www.onli-blogging.de/uploads/kibuch.400W.serendipityThumb.webp 800w" src="https://www.onli-blogging.de/uploads/kibuch.serendipityThumb.webp" alt=""></a> </p> <p>Besonders prägend war Grundlagen der Informatik. Wegen dem Fach mit seinen Inhalten waren die meisten Studenten in dem Studiengang, mich eingeschlossen. Tatsächlich lernte man dort dann auch viele Konzepte, die für jeden Programmierer völlig relevant sind: Objektorientierte und funktionale Programmierung, Datentypen, Rekursion, Komplexität, aber auch generell das Entwerfen von und Arbeiten mit Algorithmen sowie das Planen von Programmen. </p> <p>Trotz diesem praktischen Aspekt des Studiums wurde gepredigt, dass ein Informatiker Konzepte lernt und die dann in jeder beliebigen Programmiersprache anwenden kann. Ich merkte später: Das stimmt nur so halb. Um abstrakte Konzepte wirklich anzuwenden muss man die Sprache beherrschen, das braucht Übung mit ihr. Bevor ich Ruby lernte – eigenständig im Master – konnte ich zum Beispiel faktisch kaum Serveranwendungen bauen, völlig egal ob ich die Konzepte drauf hatte. Aber es stimmt, dass sich viel übertragen lässt, und zwischen ähnlichen Sprachen zu wechseln ist kein großes Problem. Es stimmt aber auch der Vorwurf am Hochschulstudium, dass selbst das Bachelorstudium noch zu abstrakt ist um den Studenten wirklich das Programmieren beizubringen. Das müssen sie aus eigenem Antrieb zusätzlich oder später machen, selbst GDI mit seinem Praxisteil schafft nur wenige Grundlagen. Oder zumindest war das damals so. </p> <p>Was stimmte: Die Predigt vom Dekan ziemlich am Anfang des Studiums, dass er keinen von uns in gewöhnlichen Studentenjobs sehen will, wir seien alle jetzt schon als Programmierer beschäftigbar. Naja, vielleicht galt das nicht für alle, aber tatsächlich waren die Anfangsinhalte die wichtigsten und Firmen hätte mit den motivierteren Studenten definitiv arbeiten können. </p> <p>Wieviel weiteres nützliches man aus dem Studium ziehen konnte hing aber auch von den Wahlpflichtfächern ab. Meine Themenwahl sehe ich heute noch mit Wohlwollen. </p> <p>Künstliche Intelligenz war vor dem aktuellen Boom, neuronale Netze ein veraltetes Nischenthema. Trotzdem oder gerade deswegen war die Vorlesung super – denn KI hat im Kern das Thema, das mich an Informatik anfangs so faszinierte, nämlich wie man mit Algorithmen Probleme lösen kann. Der auf einem Infotag präsentierte Dijkstra-Algorithmus, der ein Wegfindeproblem lösen kann, hatte damals erst den Ausschlag gegeben dieses Studium zu wählen. Ich sehe KI als die komprimierte Essenz der Informatik, entsprechend spannend war die Vorlesung. Wobei ich wenig konkrete Inhalte aus ihr bisher anwenden konnte, wohl aber viele Ansätze. </p> <p>Kryptographie zu belegen war überraschend lohnenswert, weil IT-Sicherheit in jedem Projekt ein Thema ist und die Grundlagen von damals mich immer noch tragen. Zudem war der Professor <a href="https://de.wikipedia.org/wiki/Johannes_Buchmann">Johannes Buchmann</a>, der es einfach drauf hatte die Vorlesung interessant und verständlich zu halten. Ich glaube, das war auch die Vorlesung für die ich <a href="https://www.onli-blogging.de/1358/rsa.sh.html">RSA in Bash</a> implementierte, was ein bisschen zeigt wie locker man das Thema angehen konnte. </p> <p>Außerdem war HCI ein prägender Kurs zu <a href="https://www.onli-blogging.de/2011/Was-ist-Usability.html">Usability</a>. Als Informatiker fand ich das besonders toll, weil es einen Weg vorwärts versprach wie man alles andere anwenden konnte. Nicht nur viel wissen, sondern auch herausfinden können was man überhaupt bauen soll und womit Nutzer umgehen können. Damit wollte ich weitermachen, also wurde das Thema mein Masterstudium – was nicht ganz klappte, aber dazu später mal mehr. </p> <p>Und schließlich, etwas allgemeiner: Diese übliche Prophezeiung, dass im Studium viele gute Leute zusammenkommen und die dann auch oft besser sind als du, in Darmstadt stimmte das für mich. Auch eine Erfahrung.</p> <h4>Leben als Student in Darmstadt </h4> <p><a class="serendipity_image_link" href='https://www.onli-blogging.de/uploads/karoline-place-2573461_1920.jpg'><!-- s9ymdb:1403 --><img class="serendipity_image_center" width="800" height="536" srcset="https://www.onli-blogging.de/uploads/karoline-place-2573461_1920.1200W.serendipityThumb.jpg 2600w,https://www.onli-blogging.de/uploads/karoline-place-2573461_1920.800W.serendipityThumb.jpg 1200w,https://www.onli-blogging.de/uploads/karoline-place-2573461_1920.400W.serendipityThumb.jpg 800w" src="https://www.onli-blogging.de/uploads/karoline-place-2573461_1920.serendipityThumb.jpg" alt=""></a><br /> <em>Bild von <a href="https://pixabay.com/de/users/lapping-3464230/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=2573461">lapping</a> auf <a href="https://pixabay.com/de/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=2573461">Pixabay</a></em> </p> <p>Nach etwas Eingewöhnungszeit wurde das Studieren zum Alltag. Ich besuchte die Vorlesungen fast immer, nahm an den Übungen teil, und füllte die verbliebene Zeit mit anderen Dingen. </p> <p>Am Anfang hatte ich keine Zeit über, denn anfangs bin ich von meinem Heimatort nach Darmstadt gependelt, was großer Mist war. Dass ich seitdem mit einer kurzen Ausnahme nie wieder gependelt bin ist kein Zufall. Erstens kriegte ich anfangs vom Studentenleben wenig mit, zweitens fühlte ich mich wegen der unsicheren Heimreise in Darmstadt nicht wohl, drittens schadete es der Motivation an den Vorlesungen und Übungen teilzunehmen und damit dem Studium. Gerade kommt mir der Gedanke: Man konnte beides damals nicht von Zuhause machen, vielleicht ginge zumindest die fachliche Seite mittlerweile trotz der Distanz etwas besser? </p> <p>Später wohnte ich im Studentenheim, das half sehr. Es gab dort aber die absurde Situation, pfeilschnelles Internet zu haben, aber nur 10 oder 20 GB Traffic, danach wurde die Leitung für den Monat abgeschaltet. Ich hoffe, das ist heute Geschichte – ah, sie sind jetzt <a href="https://studierendenwerkdarmstadt.de/wohnservice/internetzugang/">bei 120GB</a>, das sind immer noch nur 2 AAA-Spiele. Peinlich. Und es half anfangs nicht gerade beim Sicherheitsgefühl in der neuen Heimat. </p> <p>Studentenjobs an der Uni dagegen waren eine gute Sache für mich. Eine Weile war ich Mentor für Erstsemester, ihr einer Pflichttermin. Diese Tätigkeit hatte abgesehen der üblichen Anliegen der Menties bezüglich mancher Studieninhalte so gar nichts mit Informatik zu tun, das war eine interessante Erfahrung. Später als Tutor in Übungen lernte ich immerhin noch, wie schwer diese Rolle ist und wieviel man von dem Stoff auch wieder vergessen hat. </p> <p>In meiner Freizeit verbrachte ich als Informatiker viel Zeit vor dem Rechner, klar. Von Darmstadt habe ich nicht viel mitbekommen, um in Cafes rumzusitzen zum Beispiel hätte mir auch schlicht das Geld gefehlt. Aber so ein bisschen Studentenleben nahm ich doch mit: Mit <a href="https://www.onli-blogging.de/292/Jugger.html">Jugger</a> eine ungewöhnliche Sportart; Serien bekamen durch das Studentennetzwerk eine neue Bedeutung, Filme ebenso durch den Mathefilmabend (mit schlechten Filmen) und dem Studentenkino im Audimax (mit besseren); auf Vorschlag einer Kommilitonin lernte ich mit ihr Salsa, ich war und bin darin untalentiert, aber es war aus Gründen später eine der wichtigsten Sachen die ich hätte lernen können. Die D&D-Gruppe erwähnte ich oben über den Spielemeister, eine Brettspielgruppe fand sich auch, meine erste. Ein paar Klischees erlebte ich zudem: Den sich nie als nützlich erweisenden Sprachkurs, krude Charaktere in WGs, sogar eine für mich gescheiterte WG, ein paar wenige Studentenfeiern. </p> <p>Man kann sich ja gerade bei Informatik auf den Standpunkt stellen, dass das Studium nicht lohnt. Einfach alles relevante online lernen, oder eine Ausbildung im Unternehmen machen und so früh wie möglich mit dem Arbeiten anfangen, beides bringe am Ende durch die gesparte Zeit mehr Gehalt. Stimmt monetär vielleicht. Aber wenn nicht gerade eine Pandemie alles sowieso blockiert, dann verpasst man so eben auch dieses Leben. Das zwar bei all der Arbeit, dem geringen Einkommen und dem dauernden Prüfungsstress auch nicht immer toll war, aber im Nachhinein echt keine schlechte Zeit.</p> <h4>Fazit </h4> <p>Man wurde im Informatikstudium mit Stoff bombardiert. Das schaffte viele Grundlagen, um Neues zu verstehen und auch anzuwenden. So brauchte ich beispielsweise diesen Schubs, um die praktische Funktion von Datenbanken zu verstehen und in meine Projekte einbauen zu können. Generell wurde alles was irgendwie praxisrelevant war besonders interessant: Beispielsweise auch der Bayes-Algorithmus wegen <a href="https://www.onli-blogging.de/753/Testaufruf-Bayes-Spamfilter-fuer-Serendipity.html">meinem Bayes-Spamblockplugin</a>. Aber das funktionierte auch andersrum: Praktisch alles, für das ich einen Zugang finden konnte – was mir nicht komplett unergründlich war – hatte in den Folgejahren nochmal irgendwie eine Relevanz. Selbst manche der Mathematikkenntnisse, sogar die Logikformeln aus den formalen Grundlagen erleichterten später mindestens das Lesen mancher Veröffentlichungen. </p> <p>Gut, manches war zu speziell oder ist mittlerweile veraltet. Das Wasserfallmodell als Entwicklungsmodell mit Lasten und Pflichtenheft zum Beispiel – klar gibt es das noch, aber es ist aus gutem Grund nicht der Standard. UML-Diagramme hätte man auch weniger machen können, damit Programme zu planen wurde sicher nicht die Zukunft der Programmierung. Wobei: No-Code-Programmierung baut ja irgendwo schon auf den gleichen Ideen auf, dafür gibt es derzeit verstärkt Aufmerksamkeit. Bei den Software-Designpatterns weiß ich nicht mehr, ob meine bis heute anhaltende kritische Haltung vom Dozent vermittelt wurde oder ob ich damals schon ihre Probleme wahrnahm. Aber das Thema zeigt die Gefahr, dass man an der Uni auch Dinge lernen kann, die einem Programmierer in der Praxis eher schaden – wie das übertriebene Anwenden von Designpatterns. </p> <p>Doch insgesamt: Für jemanden, der später Software bauen wollte, war das Informatikstudium in Darmstadt eine gute Wahl. Dass ich mir ein eigenes Bachelorarbeitsthema aussuchen konnte, direkt einen tollen Betreuer fand und daran dann auch noch bei der Telekom arbeiten konnte war dann noch ein guter Endpunkt eines guten Studiums. Rückblickend muss ich auch loben, wie gut die Uni ausgestattet war (schon der PC-Pool im Keller mit sauber funktionierenden Linux-Computern), wie fähig die Professoren Vorlesungen hielten und wie gut das Studium organisiert war, abgesehen nur vom damals fast unschaffbar überfrachteten dritten Semester. </p> <p class="wl_nobottom">Müsste ich nochmal von vorne anfangen, würde ich direkt wieder dieses Studium wählen und auch wieder nach Darmstadt gehen. Stattdessen ging es mit einem Master weiter, über den es auch einiges zu erzählen gibt.</p> <img src="https://ssl-vg03.met.vgwort.de/na/6ec91bcf356044318e498c1457dc8bd4" width="1" height="1" alt=""> Mon, 27 Sep 2021 08:39:00 +0200 https://www.onli-blogging.de/2072/guid.html studium Video: Cyberpunk 2077 und Softwareentwicklung https://www.onli-blogging.de/1998/Video-Cyberpunk-2077-und-Softwareentwicklung.html Informatik Spiele https://www.onli-blogging.de/1998/Video-Cyberpunk-2077-und-Softwareentwicklung.html#comments https://www.onli-blogging.de/wfwcomment.php?cid=1998 0 https://www.onli-blogging.de/rss.php?version=2.0&type=comments&cid=1998 [email protected] (onli) <p><iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/E-jGEtqB4wU" srcdoc="<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img,span{position:absolute;width:100%;top:0;bottom:0;margin:auto}span{height:1.5em;text-align:center;font:48px/1.5 sans-serif;color:white;text-shadow:0 0 0.5em black}</style><a href=https://www.youtube-nocookie.com/embed/E-jGEtqB4wU?autoplay=1><img width=560 height=420 loading=lazy src=https://img.youtube.com/vi/E-jGEtqB4wU/hqdefault.jpg><span>▶</span></a>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen ></iframe><br /> <a href="https://www.youtube.com/watch?v=E-jGEtqB4wU">direkt</a> </p> <p>Die Argumentation im Video ist nicht unbedingt neu, wenn man etwas im Thema ist. Aber gerade deswegen ist es ein anschauliches Beispiel für Planungsfehler, die möglicherweise dem Spiel geschadet haben. </p> <p>Vorab: Sie ist auch kritisierbar. Ein Spiel wie Cyberpunk kann man nicht von Anfang an in einem veröffentlichbaren Zustand halten. Auch die verlinkte <a href="https://www.youtube.com/watch?v=8hXRvvFDztg">Präsentation zu Sea of Thieves</a> ist da kein echtes Gegenargument, da wurde dieses Entwicklungsmodell nur teilweise adoptiert (immerhin!), und das Spiel ist viel kleiner und war am Ende wohl auch nicht besonders gut. Das geht mit Werkzeugen, bei denen schon ein kleiner Teil des geplanten nützlich wäre. Vielleicht bei Spielen mit einer sehr simplen Grafik, Mechanik und Frust-Spaß-Schleife (dass die bei Sea of Thieves zu simpel ist war <a href="https://www.pcgames.de/Sea-of-Thieves-Spiel-55701/Tests/Review-Wertung-MMO-1253079/">in Tests</a> der größte Kritikpunkt). Aber es geht nicht mit storygetriebenen echten AAA-Spielen, die bei ihrer Vollständigkeit eine hohe Messlatte erreichen müssen um auch nur ein bisschen spaßig zu sein. </p> <p>Außerdem hatte CD Projekt ja ursprünglich kein Releasedatum genannt, ist also anfangs der im Video vertretenen Theorie gefolgt. Das war sicher eben um flexibel sein zu können. Interessant wäre eher ein Blick auf die Dynamik, die das Entwicklerstudio trotz dieses Starts zum verfrühten und auf alten Konsolen wohl nahezu ungetesten Release verleiteten. Alternativen gab es nicht viele, die angesprochene, nur auf den alten oder neuen Konsolen zu veröffentlichen, war in dem Moment keine Option mehr als einmal etwas anderes angekündigt worden war, auch ohne die Ankündigung wäre es nach dem Release der neuen Konsolen nicht machbar gewesen. Denn: Zu wenige Leute haben die neuen Konsolen bereits, aber die neuen nicht zu beliefern wäre für jedes AAA-Spiel ein PR-Desaster. Tatsächlich war die veröffentlichte Version auch die, die auf die Last-Gen-Konsolen zugeschnitten sein sollte. Was wirklich schiefging werden erst später gute Reportagen <a href="https://kotaku.com/the-story-behind-mass-effect-andromedas-troubled-five-1795886428">wie der zu Andromeda</a> erklären können, bis jetzt gibt es nur Erklärungsansätze. </p> <p class="wl_nobottom">Die Argumentation des Youtubers ist also völlig daneben. Faszinierenderweise ist sie gleichzeitig völlig richtig. Denn die Grundargumentation im Video passt. Zumindest im letzten Jahr der Entwicklung sind die Entwickler nach allem was bekannt ist genau in die beschriebene Planungsfalle gelaufen. Gleichzeitig einen festen (fast, einmal wurde es ja nochmal verschoben) Termin treffen zu wollen ohne das Spiel nach all den Trailern deutlich verschlanken zu können war keine gewinnbare Situation. Entwicklerteams vergrößern ist, richtig, keine Hilfe. Da ging also etwas wie vom Youtuber beschrieben komplett schief. Das zeigt der Crunch: Scheinbar wurde wider besseren Wissens gehofft, Entwickler länger als 4 bis 5 Tage lange Stunden arbeiten zu lassen verkürze die Entwicklungszeit. Eine Verzweiflungsentscheidung, die offensichtlich verkehrt ist, denn ausgebrannte Entwickler werden höchstens grantig aber keinesfalls schneller. Das weiß eigentlich jeder, es trotzdem zu versuchen ist genau das kritisierte Wunschdenken.<br /> Wenn das anfängliche Scheitern Cyberpunks dazu führt, dass mehr Firmen die Unsinnigkeit von Crunchentwicklung erkennen, hätte das ganze nochmal was gutes.</p> <img src="https://ssl-vg03.met.vgwort.de/na/4d6b7ca599d44d9f8eaa018509b21d45" width="1" height="1" alt=""> Tue, 29 Dec 2020 07:52:00 +0100 https://www.onli-blogging.de/1998/guid.html Immutability und ein praktischer Einsatzzweck https://www.onli-blogging.de/1990/Immutability-und-ein-praktischer-Einsatzzweck.html Informatik https://www.onli-blogging.de/1990/Immutability-und-ein-praktischer-Einsatzzweck.html#comments https://www.onli-blogging.de/wfwcomment.php?cid=1990 0 https://www.onli-blogging.de/rss.php?version=2.0&type=comments&cid=1990 [email protected] (onli) <p>Objekte die immutable sind können in keiner Weise modifiziert werden. Doch was bringt das?</p> <h4>Das Konzept </h4> <p>Viele Sprachen – nicht alle natürlich – unterstützen das Konzept, mal für alle Datentypen, mal nur für spezielle. Aber grundsätzlich könnte es so aussehen:</p> <pre class="code"> class Car immutable doors = ['door1', 'door2'] end</pre> <p>Wenn der Entwickler sich dann später ein entsprechendes Objekt erstellt, dann kann er das <code>doors</code>-Attribut nicht ändern:</p> <pre class="code"> myCar = new Car(); myCar.doors.add('door3') #=&gt; Error!</pre> <p>Immutability ist ein Konzept, das man besonders oft bei funktionalen Programmiersprachen finden wird. Wer sich Gedanken über Seiteneffekte macht, der wird auch Immutability bedacht haben. Es kann auch massiv dem Compiler helfen, wenn Objekte entsprechend markiert sind und er so weiß, dass diese Objekte sich nie ändern können. Programme werden so schneller oder sicherer. </p> <p>Wobei, von wegen funktional, <code>const</code> geht ja in eine ganz ähnliche Richtung.</p> <h4>Ein Anwendungsfall </h4> <p>Doch hilft es dem Entwickler? Das allerwichtigste ist Entwicklerzeit, -effizienz und -komfort. Immutability schadet dabei oft. Wenn ich als Entwickler ein geschütztes Attribut ändern will, habe ich wahrscheinlich einen guten Grund. Wenn ich jetzt nur des Compilers wegen ein neues angepasste Objekt erstellen und am besten noch einige Attribute kopieren muss, dann stimmen die Prioritäten nicht. </p> <p>Aber jetzt lief ich in diesen Fall: Ich hatte eine Liste. Und irgendwas veränderte diese Liste. Und zwar wurde der letzte Eintrag in ihr länger. Doch nirgends in meinem Programm gab es eine solche Zuweisung, zumindest keine die eindeutig zu erkennen war. </p> <p>Was wohl passiert war: Es gab ein Fold.</p> <pre class="code">newList = originalList; targetMap = newList.fold({}, (prev, element) =&gt; prev..addAll(element));</pre> <p>Und dazu einige andere solcher Akkumulatoren, die meine Originalliste zusammenfassten (die in Wirklichkeit auch keine einfache Liste war, sondern eine Liste von Listen von Ojekten in einem Elternobjekt). Und irgendeiner davon hatte als Nebeneffekt, dass die Originalliste – denn in dieser Sprache werden meist Referenzen übergeben – ebenfalls verändert wurde. </p> <p>Die Lösung: <strong>Die Liste als immutable markieren.</strong> </p> <p>Die Akkumulatorfunktionen wie das <code>fold</code> funktionierten immer noch. Aber anstatt die Originalliste zu verändern, erstellten sie sich automatisch ihre eigene Kopie. Die Originalliste blieb unverändert, der Bug war gefixt. </p> <p>Es ist also keinesfalls so, dass Immutability nur den Code verkompliziert. Im Gegenteil, richtig eingesetzt kann es ein Programm wesentlich einfacher zu verstehen machen, dann dient das Konzept dem Entwickler. Besonders in Sprachen, die Referenzen einsetzen anstatt direkt Werte zu kopieren. </p> <img src="https://ssl-vg03.met.vgwort.de/na/0d9ef2e6ffdc4d97aede4389eaddbf5a" width="1" height="1" alt=""> Mon, 23 Nov 2020 16:49:00 +0100 https://www.onli-blogging.de/1990/guid.html Object-Oriented Programming is Bad https://www.onli-blogging.de/1982/Object-Oriented-Programming-is-Bad.html Informatik https://www.onli-blogging.de/1982/Object-Oriented-Programming-is-Bad.html#comments https://www.onli-blogging.de/wfwcomment.php?cid=1982 8 https://www.onli-blogging.de/rss.php?version=2.0&type=comments&cid=1982 [email protected] (onli) <p><iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/QM1iUe6IofM" srcdoc="<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img,span{position:absolute;width:100%;top:0;bottom:0;margin:auto}span{height:1.5em;text-align:center;font:48px/1.5 sans-serif;color:white;text-shadow:0 0 0.5em black}</style><a href=https://www.youtube-nocookie.com/embed/QM1iUe6IofM?autoplay=1><img width=560 height=420 loading=lazy src=https://img.youtube.com/vi/QM1iUe6IofM/hqdefault.jpg><span>▶</span></a>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen ></iframe> </p> <p>Ich mochte <a href="https://www.youtube.com/watch?v=QM1iUe6IofM">diesen Vortrag</a>. Man muss den Anfang mit seinem "das wichtigste Video ever" ignorieren, aber danach hat es ein paar gute Punkte (die sich nicht alle <a href="https://medium.com/@brianwill/object-oriented-programming-a-personal-disaster-1b044c2383ab">im zugehörigen Artikel</a> finden). Es wird ziemlich überzeugend erklärt, was die Schwachstellen der objektorierentierten Programmierung sind: Dass dessen Ideal nicht erreicht werden kann und gar kein Ideal ist, warum Objektarchitekturen gerne ausufern und wieso man oft an Fragen gelangt, die nicht entscheidbar sind. Es sind zudem ein paar gute praktische Tricks drin die man in seinen Code einbauen kann, auch wenn die meisten nicht gerade neu sind. Aber sie sind gut gebündelt und im Kontext des Hauptarguments angemessen, lange Funktionen zu rechtfertigen und gekapselte lokale Funktionen ins Spiel zu bringen ist erfrischend. </p> <p>Vor allem wird betont, dass Abstraktion nicht etwas positives ist, sondern automatisch Komplexität bedeutet, was sehr schlecht ist. Und das ist mindestens so richtig und wichtig wie es oft ignoriert wird. Es kollidiert mit vielem was gelehrt wird, aber ganz besonders mit den Paradigmen aus der Enterprise-Ecke. Man kann diesen Ansatz auch mit vielen gegenteiligen Entwicklungen im Javascriptuniversum vergleichen und wird ihn bestätigt finden. </p> <p class="wl_nobottom">Allerdings, was es für mich verdächtig komfortabel macht: Ich sehe einige Überschneidungen mit meiner angestrebten Programmarchitektur, die ich vor ein paar Jahren hier im Blog <a href="https://www.onli-blogging.de/1346/Schlanke-Controller-und-Fehlende-Manager.html">beschrieben habe</a> und die sich seitdem nicht groß geändert hat. Wobei ich meinen Code wesentlich objektorientierter halte als es Brian Will (von dem der Vortrag stammt) wahrscheinlich gut fände. Doch wo der Code letztens Endes lebt ist in der Argumentation nicht so wichtig, solange er nicht unnötig abstrakt und über das Programm verteilt ist, und das war so ziemlich mein Hauptziel. Dieser Aspekt und die funktionalen Anleihen, die ich mittlerweile gerne einbaue, passen gut zu den Ideen des Videos.</p> <img src="https://ssl-vg03.met.vgwort.de/na/6a6cfc1437d940b58246c87f6f384d30" width="1" height="1" alt=""> Mon, 02 Nov 2020 07:44:00 +0100 https://www.onli-blogging.de/1982/guid.html Effizienter CSV-Dateien verarbeiten, mit Ruby und generell https://www.onli-blogging.de/1926/Effizienter-CSV-Dateien-verarbeiten,-mit-Ruby-und-generell.html Code Informatik https://www.onli-blogging.de/1926/Effizienter-CSV-Dateien-verarbeiten,-mit-Ruby-und-generell.html#comments https://www.onli-blogging.de/wfwcomment.php?cid=1926 0 https://www.onli-blogging.de/rss.php?version=2.0&type=comments&cid=1926 [email protected] (onli) <p>Vor kurzem schrieb ich darüber, wie ich <a href="https://www.onli-blogging.de/1908/Mit-SAX-effizienter-XML-parsen.html">mit dem SAX-Parser</a> besser mit XML-Dateien umgehen konnte. Besser bedeutete, mit weniger Speicherbedarf schneller die gesuchten Informationen aus teils relativ großen XML-Dateien zu holen. Es half, aber der Server hatte immer noch spürbare Last durch die anderen Datenquellen: Den CSV-Dateien. Sie benutzen manche der Datenausgeber statt XML, und auch bei ihnen führte das naive Vorgehen zu extremen Speicher- und Prozessorbedarf. </p> <p>Das naive Vorgehen war grob so:</p> <pre class="code">hardwares = Database.instance.getHardwares hardwares.each do |hardware| csv = cache.getset('csvApi') do csvGz = open("https://url/zur/csv.gz") unzippedCsv = Zlib::GzipReader.new(csvGz).read csv = CSV.parse(unzippedCsv, :headers =&gt; true) csv end return csv.detect{|line| line['id'] == hardware.id } end </pre> <p>Es gab also ein Array mit den Bezugsobjekten, zu denen die Zeile mit ihrer ID aus der CSV-Datei gezogen werden soll. Optimiert ist da bereits, dass die CSV-Datei nicht mehrfach heruntergeladen wird. Dafür sorgt <a href="https://github.com/SamSaffron/lru_redux">der lru-cache</a>. </p> <p>Wie geht es besser?</p> <h4>1. Speichereffizienter parsen </h4> <p>Der erste Schritt ist das Parsen der CSV-Datei. Der bisherige Code macht das in einem Rutsch und baut – ähnlich wie bei XML-Dateien – ein CSV-Objekt. Wenn wir stattdessen Zeile für Zeile durchgehen entsteht eine Chance, den Speicherbedarf zu reduzieren. Dalibor Nasevic hat dazu <a href="https://dalibornasevic.com/posts/68-processing-large-csv-files-with-ruby">Codebeispiele und Benchmarkergebnisse</a>. Der Code ändert sich so:</p> <pre class="code"> unzippedCsv = Zlib::GzipReader.new(csvGz) csvFile = CSV.new(unzippedCsv, headers: true) while line = csvFile.shift # do something end </pre> <p>Der GzipReader liest nicht mehr die Datei auf einmal in den Speicher, mit diesem neuen Startpunkt geht der CSV-Parser zeilenweise durch die Datei. Wenn wir jetzt einfach das CSV-Objekt nachbauen bringt das nicht viel, aber es gibt uns die Möglichkeit etwas besseres zu bauen.</p> <h4>2. Mit fastcsv schneller parsen </h4> <p>Doch bleiben wir erstmal beim Parsen selbst. Derzeit benutzt der Code das in Ruby integrierte CSV-Modul. Doch es gibt Alternativen, insbesondere <a href="https://github.com/jpmckinney/fastcsv">fastcsv</a>. Das Gem kann in vielen Fällen das normale CSV-Modul direkt ersetzen und war in meinen Tests etwa doppelt so schnell.</p> <pre class="code">require 'fastcsv' csvFile = FastCSV.new(unzippedCsv, headers: true)</pre> <p>Nett, aber das Parsen der CSV-Datei war gar nicht das Problem. Das sparte ein paar Sekunden. Das eigentliche Problem war das spätere Durchsuchen des erstellten CSV-Objekts.</p> <h4>3. Mit Hash nicht suchen, sondern nachschlagen </h4> <p>Das ist eine Optimierung, die in jeder Sprache funktionieren wird. </p> <p>Wenn <code>CSV.parse</code> ein CSV-Objekt erstellt, ist das im Grunde ein großes Array mit Arrays (<code>headers: false</code>) oder Hashs (<code>headers: true</code>) in den Arrayeinträgen. Entsprechend durchsucht der Code von oben dieses Array mit dem üblichen <a href="https://ruby-doc.org/core-2.6.1/Enumerable.html#method-i-detect">Enumerable.detect</a>. Doch das bedeutet, dass für jedes Suchobjekt die CSV-Struktur durchgegangen werden muss, bis etwas gefunden wurde. Oder bis die Struktur durch ist und eben nichts gefunden wurde. Wenn es nur eine Datenstruktur gäbe, die für eine ID direkt die passende Zeile ausgeben könnte… </p> <p>Die gibt es natürlich, genau das ist in Ruby der Hash. Da wir jetzt zeilenweise durch die CSV-Datei durchgehen und die Struktur selbst bauen können wir sie nutzen:</p> <pre class="code"> csv = cache.getset('csvApi') do … csv = {} while line = csvFile.shift csv[line['id']] = line end csv end return csv[hardware.id] </pre> <p><strong>Das hier ist die große Optimierung</strong>. Anstatt mehrfach durch die riesige Datenmenge zu stöbern am Anfang mit etwas Mehraufwand die Hashstruktur zu erstellen spart danach so viel Zeit bei jedem Suchvorgang, dass minuten- bis stundenlange Prozesse in wenigen Sekunden fertig werden.</p> <h4>4. Ungenutzte Datenfelder rausschmeißen </h4> <p>Moment, da gibt es noch eine mögliche Optimierung, wieder völlig unabhängig von Ruby. Eventuell braucht es später gar nicht alle Felder, die in der CSV-Datei gespeichert sind. Vielleicht wird später nur nach <em>price</em> und <em>available</em> geschaut. Wenn dem so ist, dann ist genau hier der Moment die überflüssigen Felder zu entfernen und so den Speicherbedarf zu senken:</p> <pre class="code">while line = csvFile.shift csv[line['id']] = line.to_h.keep_if{|k, _| k == 'price' || k == 'available' } end</pre> <p>Die Kombination dieser vier Schritte ist sehr mächtig. Was vorher viele Minuten rödelte und Prozessorkerne voll auslastete ist in ein paar Sekunden erledigt. Aber es ist ja auch ein Idealfall. Es gab genau eine ID, wir in einer Hashmap als Key nutzen und dann nachschlagen konnten. Was, wenn es mehr als einen Key gibt?</p> <h4>5. SQLite für mehrere IDs </h4> <p>In meinem Anwendungsfall gab es manchmal neben der <em>id</em> noch die <em>sku</em>, also einen zweiten Key. Dann reicht ein Hash nicht, denn es gibt keine mir bekannte Möglichkeit, einen zweiten Key einzusetzen. Klar, wir könnten einen zweiten Hash erstellen. Aber würde das nicht den Speicherbedarf verdoppeln? Nein, es wäre besser einen zweiten Key als Index über die alte Hashmap zu legen. In Ruby wüsste ich nicht wie das geht (wenn du schon: Ein Kommentar wäre klasse!). Aber SQLite macht das mit links und ist in jeder Sprache verfügbar. </p> <p>Die Idee also ist: Statt einer Hashmap erstellen wir eine SQLite-Datenbank im Arbeitsspeicher. <code>Primary Key</code> wird die id, aber für die sku baut SQLite einen Index. Das Durchsuchen geht dann mit ein bisschen SQL. YAML serialisiert die CSV-Zeile, die im Zweifel auch wieder wie in Schritt 4 speicheroptimiert werden könnte.</p> <pre class="code">csv = cache.getset('csvApi') do … csvFile = FastCSV.new(result, :headers =&gt; true) db = SQLite3::Database.new(':memory:') db.execute "CREATE TABLE csv(id TEXT PRIMARY KEY, sku TEXT, line TEXT)" while line = csv.shift db.execute("INSERT OR IGNORE INTO csv(id, sku, line) VALUES(?, ?, ?)", line['id'], line['sku'], YAML::dump(line)) end db.execute "CREATE INDEX csv_sku ON csv(sku)" db.execute "ANALYZE" db end row = csv.execute("SELECT line FROM csv WHERE id = ?", hardware.id).first unless row row = csv.execute("SELECT line FROM csv WHERE sku = ?", hardware.sku).first end if row return YAML::load(row[0]) end </pre> <p>SQLite ist unheimlich schnell, die CSV-Datei wird in sekundenschnelle durchsucht sein, je nach Größe natürlich.</p> <h4>Fazit </h4> <p>Wenn man es mal richtig macht… Ich fand das ein gutes Beispiel für einen Anwendungsfall von Informatik-Grundkenntnissen. Statt ein Array zu durchsuchen die Datenstruktur zu ändern und eine Hashmap zu nehmen ist Grundlagenstoff des Studiums, Standardbeispiel für O(1) statt O(n). Aber ich brauchte einen Moment um zu erkennen, dass das hier möglich ist, das komfortable <code>CSV.parse</code> hatte mir das versteckt. SQLite einzubauen und nach einem schnelleren Gem zu schauen ist dann vielleicht etwas mehr aus praktischer Erfahrung gezogen, aber liegt wenn man mal optimiert und und nach dem Datenbankkurs auch nicht mehr fern. </p> <p>Mir hat dabei auch geholfen, diese Aufgabe als eigenes Projekt zu betrachten. Ursprünglich war das nur eine kleine Ecke im Code des Überprojekts (<a href="https://www.pc-kombo.com/de/">pc-kombo</a>), schnell mal gebaut, abgewandelt aus Code der eine REST-API nach den Informationen fragt (wo solche Optimierungen nicht möglich sind). Jetzt ist die Ecke ausgelagert in ihr eigenes Git-Repository und der Code ist auf genau diese Aufgabe reduziert. Das macht es einfacher, solche Optimierungsmöglichkeiten zu sehen. </p> <p>Auf jeden Fall lohnt sich der Aufwand. Zusammen mit der Reduzierung der Last durch XML-Dateien kann ich den großen Server bald wieder abschalten, der nach <a href="https://www.onli-blogging.de/1919/Scaleway-schaltet-ARM-Instanzen-ab,-ich-migrierte.html">dem Scaleway-Umzug</a> die temporäre Heimat dieses Mikroservice wurde. Aus dem Mikroservice wurde jetzt tatsächlich auch ein kleines Programm, das auf schmalerer Hardware wird laufen können. Das reduziert die Strom- oder die Hostingkosten dann schnell um ein paar hundert Euro im Jahr.</p> <img src="https://ssl-vg03.met.vgwort.de/na/b8b2d72deb5149d483190c39b20556a8" width="1" height="1" alt=""> Wed, 20 May 2020 12:13:00 +0200 https://www.onli-blogging.de/1926/guid.html ruby Ein bisschen anonym geht eben doch: Wie die Übermedien unnötig Panik verbreiten https://www.onli-blogging.de/1767/Ein-bisschen-anonym-geht-eben-doch-Wie-die-UEbermedien-unnoetig-Panik-verbreiten.html Informatik Medien Zeitgeschehen https://www.onli-blogging.de/1767/Ein-bisschen-anonym-geht-eben-doch-Wie-die-UEbermedien-unnoetig-Panik-verbreiten.html#comments https://www.onli-blogging.de/wfwcomment.php?cid=1767 0 https://www.onli-blogging.de/rss.php?version=2.0&type=comments&cid=1767 [email protected] (onli) <p>Weil die Übermedien nicht wissen was ein Angreifermodell ist, verfallen sie <a href="https://uebermedien.de/32307/ein-bisschen-anonym-wie-selfie-journalismus-informanten-gefaehrdet/">in einer Analyse eines Panorama-Interviews</a> in den Panikmodus. Ein Informant sei unzureichend geschützt worden, Panorama sei unfähig. Der Themenkomplex ist in der Nähe meiner Doktorarbeit, daher ein paar Erklärungen hierzu. </p> <p>Es geht um den Cum-Ex-Skandal, ein wirklich unfassbar dreister Betrug des Kapitals, bei dem der Staat sich über Jahrzehnte willfährig ausnehmen ließ. Der Interviewte ist ein Insider und zukünftiger Kronzeuge. Dementsprechend soll er anonym bleiben: Er fürchtet seine Mittäter und Konsequenzen im Privaten. Panorama hat also sein Gesicht verborgen und seine Stimme verzerrt und ihn so vor der Kamera unkenntlich gemacht. </p> <p><a class="serendipity_image_link" href='https://www.onli-blogging.de/uploads/anon-unsplash.jpg'><!-- s9ymdb:685 --><img class="serendipity_image_center" width="638" height="800" srcset="" src="https://www.onli-blogging.de/uploads/anon-unsplash.serendipityThumb.jpg" alt=""></a> </p> <p>Die Übermedien meinen das reicht nicht:</p> <blockquote><p class="wl_notopbottom">Doch dieser Schutz ist unzureichend. Und das wissen Journalisten spätestens seit dem Frühjahr 2014. Auf der <a href="https://www.imf-conference.org/imf2014/program.html">Forensiker-Tagung im Mai in Münster</a> wurde nämlich die Methode offenbar, mit der Ermittler durch Analyse der elektrischen Netzfrequenz vermummte und verkleidete Informanten, deren Stimme verzerrt wurde, enttarnen können.</p> </blockquote> <p>Die Aussage stimmt, und doch ist ihre Folgerung falsch. Warum ist interessant. </p> <p>Die Netzfrequenzanalyse betrifft erstmal genau solche Interviewszenarios. Die Netzfrequenz ist nicht mehr stabil, ihre Abweichung wird dauernd protokolliert. Sie lässt sich auch aus Aufnahmen wie der Interviewvideoaufnahme ablesen. Wann eine solche Aufnahme gemacht wurde lässt sich damit also bestimmen, man schaut einfach nach wann die Abweichung im Video mit der protokollierten übereinstimmt. Die Uebermedien glauben man würde auch den Ort herauslesen können – ich glaube das stimmt nicht, ich bin mir aber nicht ganz sicher (für diesen Artikel ist es egal). </p> <p>Wenn man aber den Aufnahmezeitpunkt hat und den Ort bestimmen kann – was ein Geheimdienst ja auch mit anderen Methoden hinkriegt – dann kann ein entsprechend ausgestatteter Akteur den Interviewten identifizieren. Er muss nur Überwachungskameras auswerten und von den paar tausend Leuten, die so wahrscheinlich gefunden werden, über ihre Profile mögliche Träger der Information herauspicken. Einer der so gefundenen ist der Informant. Ein Geheimdienst macht dann was er eben so macht, NSU-Zeugen landen in brennenden Autos, Feinde Putins werden vergiftet, es bleibt sicher immer sehr stilvoll. </p> <p>Warum also haben die Übermedien nicht recht mit der Anschuldigung, warum hat Panorama hier nicht furchtbar geschlampt? <strong>Das liegt schlicht am Angreifermodell und am Schutzziel</strong>. </p> <p>Der Interviewte hier muss nicht umfassend vor Geheimdiensten geschützt werden. Er ist dem System bereits bekannt, er ist ein Kronzeuge, seine Aussage wird bald öffentlich und seine Identität dann bekannt sein. Es geht nur um Schutz vor den Mittätern. Das sind seine Kollegen, seine Nachbarn vielleicht, aber es sind keine Geheimdienste. Wären die hier verwickelt wüssten sie seine Identität über seine Kronzeugenrolle sowieso schon und hätten sich schon eine passende Eliminierungsmethode ausgesucht. </p> <p>Das ist also praktisch der umgekehrter Fall von "<a href="https://www.onli-blogging.de/1620/Monitorama-PDX-2014-James-Mickens.html">Die US-Regierung wird uns nicht mit Musketen angreifen</a>." </p> <p>Meine Nachbarn sind nett, intelligent und fähig, aber sie haben nicht die Ressourcen des BND an der Hand. Sie würden in einem solchen Fall keine Überwachungsvideos auswerten und tausende Profile anlegen, sie würden wahrscheinlich die Netzfrequenzanalye nichtmal kennen. Es ist praktisch gegeben, dass dies im Fall dieses Informanten genauso ist. Denn die Mittäter sind ja wohl kaum Geheimdienste, sondern Privatpersonen – eventuell sehr reiche und skrupellose Banker, schlimm genug, aber doch keine KGB-Agenten. Damit fällt die Netzfrequenzanalyse als Angriffsvektor komplett raus. Ohne sie sind Verfremdung von Gesicht und Stimme dann auch ausreichend, um für den kurzen Zeitraum bis zur Kronzeugenaussage die Anonymität des Insiders zu wahren. </p> <p>Denn interessanterweise stimmt dieser stark klingende Satz eben nicht:</p> <blockquote><p class="wl_notopbottom">Doch <em>ein bisschen anonym</em> ist problematisch. Das funktioniert genauso wenig wie <em>ein bisschen schwanger</em>.</p> </blockquote> <p>Ein bisschen schwanger geht nicht, ein bisschen anonym geht durchaus. Das ist nicht ganz intuitiv, aber Stand der Anonymitätsforschung. Denn praktisch immer ist Anonymität eben doch ein Grad und nicht absolut. </p> <p>Ein Beispiel: Wenn ein geehrter Leser dieses Artikels hierdrunter einen fiesen Kommentar schreibt und einen falschen Namen benutzt ist er wahrscheinlich mir gegenüber anonym. Ich habe kaum Möglichkeiten die <em>civil identity</em> dieses fiktiven Kommentators zu finden, dann zu ihm zu fahren und ihm eins auf die Nase zu hauen. Glücklicherweise ist das auch nie nötig, meine Kommentatoren immer nett. <br /> Jetzt nehmen wir aber mal an der Kommentator schrieb nicht einfach einen fiesen Kommentar, sondern kündigt einen islamistischen Terrorangriff an. Ich habe zwar immer noch keine Methode ihn aufzuspüren. Aber so etwas würde die Polizei und die Geheimdienste alarmieren, und die könnten dann über die Vorratsdatenspeicherung den Kommentatorterroristen ganz schnell identifizieren. Hat er technische Vorkehrungen getroffen geht es vielleicht etwas weniger schnell, aber es gibt im Internet kaum absolute Anonymität. </p> <p>Das gleiche gilt auch bei anderen Kommunikationswegen. In fast jeder Situation kann man Leute finden, gegen die ein vermummter Kommunikationsteilnehmer anonym ist, aber von dem andere Stellen durchaus die Identität kennen oder kennen könnten. </p> <p><a class="serendipity_image_link" href='https://www.onli-blogging.de/uploads/artur-nasyrov-743620-unsplash.jpg'><!-- s9ymdb:684 --><img class="serendipity_image_center" width="800" height="532" srcset="https://www.onli-blogging.de/uploads/artur-nasyrov-743620-unsplash.jpg 2905w" src="https://www.onli-blogging.de/uploads/artur-nasyrov-743620-unsplash.serendipityThumb.jpg" alt=""></a> </p> <p><a href="https://unsplash.com/photos/pOyW_gljlUU">Das Foto</a> hier taugt dafür als zweites Beispiel. Ich weiß nicht wer das ist. Gegenüber dem Großteil des Internets ist die junge Dame anonym. Aber der Fotograf dürfte wissen wer das ist, ein entsprechend begabter Detektiv kann ihre Identität wohl aufdecken. Und ihre Mutter würde sie wohl auch erkennen. </p> <p>Deshalb ist bei solch einer Situation wie dem Panorama-Interview der Kontext so wichtig. Er bestimmt das Angreifermodell: Wer wird die Identität aufdecken wollen und welche Fähigkeiten hat er dafür? Dementsprechend sind ganz unterschiedliche Anonymitätsgrade erforderlich. Man kann sich auch überlegen: Wie schlimm wäre es, wenn die Identität bekannt würde? Auch das kann in die Entscheidung reinfließen. </p> <p>Den Aussagen des Chefredakteus zufolge wurde genau das sorgfältig und richtig gemacht. Die Übermedien hätten seine Aussagen nicht nur zitieren sollen, sondern sie hätten Beachtung verdient gehabt. Denn mit dem richtigen Hintergrundwissen widerlegen sie alleine komplett den dort lancierten Artikel. Aber ich will die Übermedien gar nicht zu stark kritisieren: Anonymität ist ein erstaunlich kompliziertes Thema. Hier fehlte sicher einfach etwas Hintergrundwissen, um falsche Schlussfolgerungen zu vermeiden – obwohl der genannte Autor es besser wissen müsste heißt die Autorenangabe ja nicht, dass alles aus seiner Feder stammt. </p> <p class="wl_nobottom">Denn ein bisschen anonym geht eben doch. Man ist sogar immer nur ein bisschen anonym, genau wie Sicherheit niemals absolut ist. Und in anderen Kontexten haben gerade das die Übermedien ja durchaus verstanden.</p> <img src="https://ssl-vg03.met.vgwort.de/na/1f839549a9984a7ca95d2a991fb51567" width="1" height="1" alt=""> Tue, 30 Oct 2018 09:25:00 +0100 https://www.onli-blogging.de/1767/guid.html Monitorama PDX 2014 - James Mickens https://www.onli-blogging.de/1620/Monitorama-PDX-2014-James-Mickens.html Informatik Medien https://www.onli-blogging.de/1620/Monitorama-PDX-2014-James-Mickens.html#comments https://www.onli-blogging.de/wfwcomment.php?cid=1620 0 https://www.onli-blogging.de/rss.php?version=2.0&type=comments&cid=1620 [email protected] (onli) <iframe src="https://player.vimeo.com/video/95066828?portrait=0" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe> <p><a href="https://vimeo.com/95066828">Monitorama PDX 2014 - James Mickens</a> from <a href="https://vimeo.com/monitorama">Monitorama</a> on <a href="https://vimeo.com">Vimeo</a>. </p> <p class="wl_nobottom">James Mittens erklärt die Verbindung von Batmans Bane mit NoSQL, die Herausforderungen für Sicherheit angesichts des männlichen Faktors, und warum die US-Regierung uns nicht mit Musketen angreifen wird. Und einiges mehr.</p> Sat, 25 Mar 2017 15:59:35 +0100 https://www.onli-blogging.de/1620/guid.html The glEnd() of Zelda https://www.onli-blogging.de/1536/The-glEnd-of-Zelda.html Informatik Medien Spiele https://www.onli-blogging.de/1536/The-glEnd-of-Zelda.html#comments https://www.onli-blogging.de/wfwcomment.php?cid=1536 0 https://www.onli-blogging.de/rss.php?version=2.0&type=comments&cid=1536 [email protected] (onli) <p><iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/xDxjbXAqTPg" srcdoc="<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img,span{position:absolute;width:100%;top:0;bottom:0;margin:auto}span{height:1.5em;text-align:center;font:48px/1.5 sans-serif;color:white;text-shadow:0 0 0.5em black}</style><a href=https://www.youtube-nocookie.com/embed/xDxjbXAqTPg?autoplay=1><img width=560 height=420 loading=lazy src=https://img.youtube.com/vi/xDxjbXAqTPg/hqdefault.jpg><span>▶</span></a>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen ></iframe> </p> <p class="wl_nobottom">Tom Murphy mit einem weiteren <a href="https://www.youtube.com/watch?v=xDxjbXAqTPg">absurd-genialen NES-Video</a>.</p> Sat, 02 Apr 2016 23:14:42 +0200 https://www.onli-blogging.de/1536/guid.html rsa.sh https://www.onli-blogging.de/1358/rsa.sh.html Code Informatik https://www.onli-blogging.de/1358/rsa.sh.html#comments https://www.onli-blogging.de/wfwcomment.php?cid=1358 0 https://www.onli-blogging.de/rss.php?version=2.0&type=comments&cid=1358 [email protected] (onli) <p>Vor ein paar Jahren versuchte man mir zu erklären, wie RSA funktioniert. Als Übung - und mit der üblichen Warnung, unseren Code nie zu benutzen - sollten wir es selbst implementieren, denn nur dann wird es verstanden. Machte ich mit Freude, natürlich in Bash, einfach weil ich es konnte. Und ich noch heute grinsen muss beim Gedanken an die Schimpfworte, die der Tutor bei der Bewertung benutzt haben müsste (wenn ich mich richtig erinnere, bekam ich sogar die volle Punktzahl - was mich dann doch überraschte). </p> <p>War mir sicher, das hier verbloggt zu haben, konnte es aber (anlässlich <a href="http://noqqe.de/blog/2014/01/03/rsa-implementation-in-bash/">noqqes Implementierung</a>) nicht mehr finden. Daher, uneditiert aus der Abgabemail (oder hier als <a href="https://gist.github.com/onli/8320277#file-rsa-sh">gist</a>):</p> <pre class="code">#!/bin/bash getPrim() { local range="$1" local prim=$(getRandom $range) until [[ $prim -gt 1 ]] &&amp; isPrim $prim;do prim=$(getRandom $range) done echo $prim return 0 } #Miller-Rabin-Test isPrim() { local prim=$1 if [[ $(echo "$prim % 2" | bc) -eq 0 ]];then return 1 fi #won't find an "a" for them: if [[ $prim -eq 3 ]] || [[ $prim -eq 5 ]];then return 0 fi prim_range=${#prim} local i=0 while [[ $i -lt 10 ]];do local a=$(getRandom $(($RANDOM % (prim_range + 1) )) ) until [[ $(echo "$a &lt; ($prim - 2) &&amp; $a &gt; 2" | bc) -eq 1 ]];do a=$(getRandom $(($RANDOM % (prim_range + 1) )) ) done if isWitness $prim $a;then return 1 fi let i++ done return 0 } function isWitness() { prim=$1 a=$2 prim_minus_one=$(echo "$prim - 1" | bc) test=1 local i=${#prim_minus_one} i=$(($i - 1)) while [[ $i -ge 0 ]];do x=$test test=$(echo "$x^2 % $prim" | bc) if [[ $test -eq 1 ]] &&amp; [[ $x -ne 1 ]] &&amp; [[ $x -ne $prim_minus_one ]];then return 0 fi let i-- done test=$(powmod $a $prim_minus_one $prim) if [[ $test -ne 1 ]];then return 0 else return 1 fi } setBasics() { local range="$1" local try="$2" if [[ -z "$range" ]];then #the length of sqrt(m) for p and q fits to the necessary length of n range=$(echo "sqrt($m)" | bc) range=${#range} fi if [[ -z "$try" ]];then try=1 fi doBasics $range $try #bash's comparison won't work with big numbers until [[ $(echo "$n &gt; $m" | bc) -eq 1 ]];do let try++ if [[ $try -gt $(($range * 10)) ]] || [[ ${#n} -lt $(( ${#m} -2 )) ]];then let range++ try=1 fi doBasics $range $try done } function doBasics() { local range="$1" local try="$2" #two primenumbers p=$(getPrim $range) q=$(getPrim $range) until [[ p -ne q ]];do p=$(getPrim $range) q=$(getPrim $range) done #RSA-Modul n=$(echo "$p*$q" | bc -l) #eulersche phi=$(echo "($p-1)*($q-1)" | bc -l) } #choose e coprime to phi getPublicKey() { local e=$(($RANDOM)) until [[ $(echo "$e &lt; $phi" | bc) -eq 1 ]];do e=$(($RANDOM)) done local i=2 while [[ $(echo "$i &lt; $e" | bc) -eq 1 ]];do if [[ $(echo "$phi % $i" | bc ) -eq 0 ]] &&amp; [[ $(echo "$e % $i" | bc) -eq 0 ]];then getPublicKey exit fi let i++ done echo $e } getPrivateKey() { local result=($(extended_euclid $e $phi)) local d=${result[0]} until [[ $d -gt 0 ]];do d=$(echo "$d+$phi" | bc -l) done echo $d } function extended_euclid() { a=$1 b=$2 local x=0 local lastx=1 local y=1 local lasty=0 while [[ $b -ne 0 ]];do local quotient=$(echo "$a / $b" | bc) local temp=$b b=$(echo "$a % $b" | bc) a=$temp temp=$x x=$(echo "$lastx - ($quotient * $x)" | bc) lastx=$temp temp=$y y=$(echo "$lasty - ($quotient * $y)" | bc) lasty=$temp done local result=($lastx $lasty $a) echo "${result[*]}"; return 0 } #a^b%m: Square &amp; Multiply powmod() { local a=$1 local b=$2 local mod=$3 local i=0 local res=1 #b in binary for binary exponentiation b=$(echo "ibase=10;obase=2; $b" | bc) while [[ $i -lt ${#b} ]];do res=$(echo "$res^2 * $a ^ ${b:$i:1} % $mod" | bc) let i++ done echo $res } getRandom() { local range="$1" if [[ -z "$range" ]];then range=$RANDOM fi local r=$((RANDOM % 10)) while [[ $r -eq 0 ]];do r=$((RANDOM % 10)) done local i=1 while [[ $i -lt $range ]];do local temp=$((RANDOM % 10)) r=${r}${temp} let i++ done echo $r } encrypt() { local m="$1" local c=$(powmod $m $e $n) echo "$c" } decrypt() { local c="$1" local m=$(powmod $c $d $n) echo "$m" } export BC_LINE_LENGTH=0 m=91011121314151617181920212223242526272829 old_m=$m setBasics e=$(getPublicKey) echo "Public Key: ($e, $n)" d=$(getPrivateKey) echo "Private Key: ($d, $n)" echo c=$(encrypt "$m") echo "c: $c" m=$(decrypt "$c") echo "m: $m" if [[ $m -ne $old_m ]];then echo "Error: Wrong message decrypted:" &gt;&2 echo "p: $p" &gt;&2 echo "q: $q" &gt;&2 echo "Public Key: ($e, $n)" &gt;&2 echo "Private Key: ($d, $n)" &gt;&2 echo "c: $c" &gt;&2 echo "m: $m" &gt;&2 fi #Ausgabe #onli@Fallout:~$ uni/ts/rsa.sh #p: 783057321236353042573 #q: 444786834379004491147 #Public Key: (2969, 348293587050020677086428785700425092601231) #Private Key: (137252777651911145904238835165856311899289, 348293587050020677086428785700425092601231) # #c: 134886886292723664083288725067434182648518 #m: 91011121314151617181920212223242526272829</pre> <img src="https://ssl-vg03.met.vgwort.de/na/3c05158122b84392b3b48c8579ebffde" width="1" height="1" alt=""> Wed, 08 Jan 2014 18:14:45 +0100 https://www.onli-blogging.de/1358/guid.html Growing a Language (1998) https://www.onli-blogging.de/1270/Growing-a-Language-1998.html Informatik https://www.onli-blogging.de/1270/Growing-a-Language-1998.html#comments https://www.onli-blogging.de/wfwcomment.php?cid=1270 0 https://www.onli-blogging.de/rss.php?version=2.0&type=comments&cid=1270 [email protected] (onli) <iframe width="420" height="315" src="///www.youtube.com/embed/_ahvzDzKdB0" frameborder="0" allowfullscreen></iframe> <blockquote><p class="wl_notopbottom">My point is that a good programmer in this time does not just write programs, a good programmer builds a working vocabulary - in other word, a good programmer does language design, though not from scratch, but building on the frame of a base language.</p> </blockquote> Fri, 01 Mar 2013 16:43:00 +0100 https://www.onli-blogging.de/1270/guid.html Lamport-Diffie Einmal-Signaturverfahren https://www.onli-blogging.de/1227/Lamport-Diffie-Einmal-Signaturverfahren.html Informatik https://www.onli-blogging.de/1227/Lamport-Diffie-Einmal-Signaturverfahren.html#comments https://www.onli-blogging.de/wfwcomment.php?cid=1227 0 https://www.onli-blogging.de/rss.php?version=2.0&type=comments&cid=1227 [email protected] (onli) <p>Willkommen in der Zukunft. Durch Quantencomputer ist Primfaktorzerlegung kein Problem mehr, RSA und andere Verfahren sind nutzlos geworden. Das unheimlich wichtige Dokument D=(1,1,0) soll aber trotzdem signiert werden, also braucht es dafür ein anderes Verfahren mit einer anderen Sicherheitsbedingung. Das<a href="http://de.wikipedia.org/wiki/Lamport-Diffie_Einmal-Signaturverfahren"> Lamport-Diffie Einmail-Signaturverfahren</a> (LD-OTS) eilt zur Rettung. </p> <p>LD-OTS braucht nur eine funktionierende Hashfunktion, dass eine solche noch existiert ist Mindestvoraussetzung. Und dann ist es ganz einfach, der Signierer bietet schlicht die passenden Urbilder zu den vorher veröffentlichten und durchs Dokument ausgewählten Hashs an. </p> <p>Also so: Für jedes Bit im Dokument hat der Signierer zwei Werte, die geheim bleiben, den Signaturschlüssel, hier: <strong>x = (x01, x11; x02, x12; x03, x13)</strong>. <br /> Veröffentlicht wird vorher der Verifizierungsschlüssel: <strong>y = (y01, y11; y02, y12; y03, y13) = (H(x01), H(x11); H(x02), H(x12); H(x03), H(x13))</strong> </p> <p class="wl_nobottom">Zum Signieren des Dokuments <strong>D = (1, 1, 0)</strong> veröffentlicht der Signierer dann je nach Bit an der jeweiligen Stelle seinen Teil des Signaturschlüssels und damit die Urbilder der Hashfunktion als Signatur, hier also: <strong>(x11, x12, x03)</strong>. Der Verifizierer braucht dann dann nur zu schauen, ob die veröffentlichten Signaturschlüsselteile mit dem vorher veröffentlichten Verifizierungsschlüssel übereinstimmen, also <strong>H(x11) = y11, H(x12)=y12 und H(x03)=y03</strong> ist.</p> Mon, 22 Oct 2012 14:29:00 +0200 https://www.onli-blogging.de/1227/guid.html Spamblock-Bayes: Theoretische Grundlagen https://www.onli-blogging.de/1186/Spamblock-Bayes-Theoretische-Grundlagen.html Informatik https://www.onli-blogging.de/1186/Spamblock-Bayes-Theoretische-Grundlagen.html#comments https://www.onli-blogging.de/wfwcomment.php?cid=1186 6 https://www.onli-blogging.de/rss.php?version=2.0&type=comments&cid=1186 [email protected] (onli) Angestoßen von dieser <a href="http://board.s9y.org/viewtopic.php?f=4&t=18762">Diskussion über die Performance des Bayes-Plugins</a> schreibe ich hier mal die theoretische Grundlage des Plugins und damit auch eines generischen Bayes-Spamfilters auf, damit man sich bei einer eventuellen Überarbeitung hierdran orientieren kann. <br /><br /> <h4>Bayes-Formel</h4> Das <a href="https://en.wikipedia.org/wiki/Bayes%27_theorem">Bayes-Theorem</a> wurde entdeckt, verworfen und schließlich wiederentdeckt. Ich glaube, die mathematischen Einwände gegen die Formel finden sich manchmal noch in der Kritik an solchen Filtern wieder, deshalb sei ihr Vorhandensein erwähnt.<br /> Die allgemeine Formel lautet:<br /><br /> <img src="https://lh3.googleusercontent.com/-UnB89lxplbw/T-R0uS9V5PI/AAAAAAAACDY/wTM4-8PJqTA/s800/bayes.png" height="61" width="242" alt="P(A|B)=( P(B|A) * P(A) ) / P(B)" /><br /><br /> P(A) ist die Wahrscheinlichkeit für A, P(A|B) ist die Wahrscheinlichkeit für A unter der Bedingung B, also wenn B eingetreten ist.<br /><br /> Wie sieht das nun für Spam aus? So:<br /><br /> <img src="https://lh6.googleusercontent.com/-Fdx59z7Qq_A/T-SUaEn9JRI/AAAAAAAACEc/InD2Qq7rrlQ/s800/bayes-spam.png" height="57" width="408" alt="P(Spam|Wort)=( P(Wort|Spam)* P(Spam) ) / P(Wort)" /><br /><br /> Zu beachten ist, dass wir diese Spamwahrscheinlichkeit für jedes Wort im Kommentar wissen wollen, daher am Ende mehrere Wahrscheinlichkeiten aufaddieren und normalisieren müssen. <h5>Aufdröselung</h5> Es gibt also genau drei Variabeln zu berechnen: Die Inverse Wahrscheinlichkeit, die Wahrscheinlichkeit von Spam und die Wahrscheinlichkeit für das Auftreten solcher Wörter. Das für jedes Wort. Was genau bedeuten die Formeln jeweils? <dl> <dt><em>P(Wort|Spam)</em></dt> <dd>Dies ist die Wahrscheinlichkeit, dass in einem Spamkommentar dieses Wort vorkommt: Spamkommentare mit diesem Wort / Spamkommentare</dd> <dt><em>P(Spam)</em></dt> <dd>Die Gesamtwahrscheinlichkeit, dass ein Kommentar Spam ist: Spamkommentare / Kommentare.</dd> <dt><em>P(Wort)</em><dt> <dd>Die Wahrscheinlichkeit, dass dieses Wort überhaupt in einem Kommentar vorkommt: Kommentare mit diesem Wort / Kommentare</dd> </dl> <h4>Programmiertechnische Konsequenzen</h4> Es ist völlig klar, dass eine Datenbank gebraucht wird und die Bewertung größtenteils aus dem Heraussuchen der richtigen Daten zu den Worten besteht. Zuerst muss ein sogenannter Tokenizer den Kommentar in seine Einzelwörter zerlegen. Im Wesentlichen ist das ein: <pre class="code">tokenize(text) { tokens = split("\W", text ) return unique(tokens) }</pre> Das Lernen eines Kommentars als Ham oder Spam ist nun nichts anderes, als diese Tokens in diese Datenbank namens "tokens" zu schreiben: <pre class="code">token (text) | ham (number) | spam (number)</pre> Ist das Token schon vorhanden, wird der zugehörige Ham- bzw Spamwert um eins erhöht. Gleichzeitig wird der Gesamtzähler <strong>Hamkommentare</strong> bzw <strong>Spamkommentare</strong> um eins erhöht.<br /> Diese Datenbank zusammen mit den Gesamtzählern gibt uns nun alle nötigen Werte: <dl> <dt><em>P(Wort|Spam)</em></dt> <dd><pre class="code">spam = sql_query("Select spam from tokens where token = Wort") spam / (Spamkommentare)</pre></dd> <dt><em>P(Spam)</em></dt> <dd><pre class="code">Spamkommentare / (Spamkommentare + Hamkommentare)</pre></dd> <dt><em>P(Wort)</em><dt> <dd><pre class="code">ham, spam = sql_query("Select ham, spam from tokens where token = Wort)" (ham + spam) / (Spamkommentare + Hamkommentare)</pre></dd> </dl><br /><br /> <h4>Formelveränderungen</h4> Schaut man sich nun die Bewertungsfunktion im Bayes-Plugin an wird man feststellen, dass der PHP-Code nicht nur wesentlich unschöner als mein Pseudocode aussieht, sondern auch anders funktioniert. Das liegt daran, dass das Plugin auf <a href="http://nasauber.de/opensource/b8/">b8</a> aufbaute, und b8 nicht simpel das Bayes-Theorem benutzt, die Wahrscheinlichkeiten addiert und dann durch ihre Anzahl teilt. Diese Änderungen basieren <a href="http://nasauber.de/opensource/b8/discussion/">auf Tests</a> und anderen theoretischen Annahmen als den hier gezeigten. Insbesondere die folgenden Änderungen sind enthalten oder denkbar:<br /><br /> <h5>Law of total probability</h5> Wer Vorkenntnisse hat oder nachrecherchierte, dem könnte aufgefallen sein, dass Wikipedias <a href="https://en.wikipedia.org/wiki/Bayesian_spam_filtering#Computing_the_probability_that_a_message_containing_a_given_word_is_spam">Bayes-Spamfilterformel</a> anders aussieht:<br /><br /> <img src="https://lh3.googleusercontent.com/-nGrjO3DrDRI/T-R9HU3F0YI/AAAAAAAACDw/3iKTH6LugbU/s800/bayes-spam-trad.png" height="59" width="597" alt="P(Spam|Wort)=(P(Wort|Spam)<em>P(Spam))/ P(Wort|Spam)</em>P(Spam) + P(Wort|Ham)*P(Ham)" /><br /><br /> <em>P(Wort)</em> wird hier gemäß dem <a href="https://en.wikipedia.org/wiki/Law_of_total_probability">Law of total probability</a> umgeformt. Ohne das gerade nachgerechnet zu haben vermute ich, dass die Werte gleich sein sollten und diese Formel nur <em>P(Wort)</em> anders betrachtet.<br /><br /> <h5>Häufigkeit von Tokens im Kommentar</h5> Wie oft ein Wort im Kommentar auftaucht sollte die Wahrscheinlichkeit beeinflussen. Dieser Artikel hier ist kein Spam, obwohl nun Viagra auftaucht, aber wäre jedes Wort Viagra, wäre er durchaus Spam. Deshalb beachtet b8 die Häufigkeit eines Tokens.<br /><br /> <h5>Wichtigkeit</h5> Eine beliebte Spammertaktik ist, Kommentare mit ewig langem Fülltext auszustaffieren und den Spammerinhalt so zu verstecken. Der Gedanke dabei ist, dass die vielen harmlosen Worte den ganzen Kommentar harmlos erscheinen lassen. Die auch von b8 genutzte Taktik dagegen ist die Einführung eines Wichtigkeitsfaktors: Beziehe nur die Tokens in die Schlussrechnung ein, die eine Tendenz zu Spam oder Ham haben, also um einen bestimmten Faktor von der Mitte 0,5 abweichen. Der Gedanke dahinter ist, dass die vielen Füllwörter die Bewertung sonst gegen 0,5 tendieren lassen würden.<br /><br /> <h4>Optimierungsmöglichkeiten</h4> Ich schrieb oben, dass dieser Artikel die theoretischen Grundlagen zwecks einer späteren Optimierung des Filters deutlich machen soll.<br /> Diese Optimierungsmöglichkeiten sehe ich bis jetzt:<br /> <h5>Ham-Spam-Faktor</h5> Der Anstoßgeber dieses Eintrags ist diese <a href="http://board.s9y.org/viewtopic.php?f=4&t=18762">Diskussion</a>. Grischa schlug vor, über irgendeinen Faktor auszugleichen, dass ein typischer Blog sehr viel mehr Spam als Ham bekommt und daher der Filter zu streng werden würde. Meiner Meinung nach ist das nicht wirklich ein Problem, da diese Verteilung elementar für den Filter ist, und nicht automatisch neuer Spam eingelernt wird, wenn man das nicht will.<br /><br /> Wikipedia <a href="https://en.wikipedia.org/wiki/Bayesian_spam_filtering#The_spamicity_of_a_word">erwähnt</a>, dass <em>P(Spam)</em> generell 0,8 sei. Vielleicht würde es helfen, diesen Wert festzusetzen statt ihn empirisch zu bestimmen?<br /><br /> <h5>Häufigkeit von Tokens</h5> Wie oben beschrieben ist die Häufigkeit von Wörtern innerhalb eines Kommentars ein wichtiger Faktor. Zur Zeit fließt das aber nur indirekt in die Bewertung ein, indem es bei der Bewertung selbst ignoriert wird, beim Einlernen aber beachtet wird. Statt in der Tabelle den Ham- bzw Spamwert um eins zu erhöhen, wird er um die Anzahl der Tokens erhöht. Bei der Bewertung aber wird jedes Token nur einmal beachtet, selbst wenn es mehrmals vorkommt. Das könnte man ändern.<br /><br /> Es ist auch ein kritischer Punkt, weil man sich hier leicht mit Anzahl der Tokens und Anzahl der Kommentare verheddern kann. Die Formel müsste genau geprüft werden. <h5>Konstanten</h5> Bei der Übernahme von b8 wurde die Klassifizierungsberechnung blind übernommen. In ihr enthalten sind einige Konstanten, die auf den <a href="http://nasauber.de/opensource/b8/discussion/">Testergebnissen</a> beruhen. Es geht um diese Zeile: <pre class="code">$ratings[$word] = (0.15 + (($stored_tokens[$word]['ham'] + $stored_tokens[$word]['spam']) * $rating)) / (0.3 + $stored_tokens[$word]['ham'] + $stored_tokens[$word]['spam']);</pre> 0,15 und 0,3 sind die Konstanten, die hier direkt die Bewertung beeinflussen und entfernt bzw verändert werden könnten.<br /><br /> <h4>Schlusswort</h4> Es ist nunmal Mathematik. Ich hoffe, die Erklärung macht die Funktionsweise des Filters trotzdem klarer. Die Optimierung des Filters könnte ein sehr interessantes Projekt sein, aber auch sehr zeitaufwändig. Hinweise zu Fehler in den Formeln nehme ich dankend entgegen<img src="https://ssl-vg03.met.vgwort.de/na/27c76c4f6a614a19a18d4ad2ec08d74e" width="1" height="1" alt=""> Fri, 22 Jun 2012 17:41:00 +0200 https://www.onli-blogging.de/1186/guid.html spamblock_bayes Monad, Currying: Mir unklare Informatikbegriffe https://www.onli-blogging.de/1148/Monad,-Currying-Mir-unklare-Informatikbegriffe.html Informatik https://www.onli-blogging.de/1148/Monad,-Currying-Mir-unklare-Informatikbegriffe.html#comments https://www.onli-blogging.de/wfwcomment.php?cid=1148 2 https://www.onli-blogging.de/rss.php?version=2.0&type=comments&cid=1148 [email protected] (onli) <p>Vll tritt da eine Schwäche von mir bei den formalen Grundlagen zutage, aber sowohl Currying als auch Monads sind so Begriffe, die ich (z.B. bei Hackernews) öfter mal lese, die mir aber schlicht nichts sagen. Kann mich nicht erinnern, darüber je was gelernt zu haben. Dabei hatte ich ja funktionale Programmierung, mochte sie schlußendlich sogar, und da wird wohl beides genutzt. </p> <p>Nach meiner Faustregel hat es niemand verstanden, den ich bis jetzt gelesen habe, denn ich finde keine einfache Erklärung. Vielleicht kann hier jemand helfen? Ich beschreibe mal, was ich bisher habe.</p> <h4>Currying </h4> <p>Abgeleitet aus der <a href="http://www.cs.nott.ac.uk/~gmh/faq.html#currying">comp.lang.functional-FAQ</a>: Das scheint total unspannend zu sein. Hat man nur einen Parameter zur Verfügung, dann kann man um</p> <pre class="code"> f(x,y)</pre> <p class="wl_notop"> <br /> auszudrücken, x durch eine Funktion ersetzen, also: </p> <pre class="code">(f'(x))(y) = f (x,y)</pre> <p>Das solls sein? </p> <p>Gut, mir ist klar, dass man das gebrauchen kann, wenn man in einer seltsamen Sprache zwar lambda zur Verfügung hat, aber nur einparametrige Funktionen. Das wäre dann ein theoretisches Konstrukt ohne Praxisrelevanz, das höchstens dann gut ist, wenn eine solche Sprache zu leichteren Beweisen führt und man sie nutzt, weil man bewiesen richtigen Programmcode braucht.</p> <h4>Monads </h4> <p>Hier geht mein im Studium gestählter Bullshit-Sensor an. Und zwar, weil hier die <a href="http://www.cs.nott.ac.uk/~gmh/faq.html#monads">FAQ</a> jede Antwort darüber verweigert, was es ist, und nur darüber schreibt, wofür es gut ist: </p> <blockquote><p class="wl_notop">What is a "monad", and what are they used for? </p> <p class="wl_nobottom">The concept of a monad comes from category theory; full details can be found in any standard textbook on the subject. Much of the interest ...</p> </blockquote> <p>Was mich wieder zu meiner Frage führt, ob es wirklich Dinge gibt, die so kompliziert und trotzdem wichtig sind, dass man sie nicht mehr mit einfachen Worten ausdrücken kann (siehe die Sprachbarriere bei FGdI). </p> <p>Wie auch immer, aus diesem <a href="http://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf">Paper</a> und <a href="http://en.wikipedia.org/wiki/Monad_(functional_programming)">Wikipedia</a> wird die Essenz des Begriffs nicht wirklich klar. Laut dem Paper: Ein Monad ist ein Ding M, das Seiteneffekte darstellt, und das man deswegen vor den normalen Typ stellt? Das Divisionsbeispiel aus der Wikipedia ist für mich an sich einleuchtend (abgesehen von der grauenhaften Syntax):</p> <pre class="code no-highlight">(//) :: Maybe a -&gt; Maybe a -&gt; Maybe a _ // Nothing = Nothing Nothing // _ = Nothing _ // Just 0 = Nothing Just x // Just y = Just (x / y)</pre> <p>Statt eine Division / zu definieren, die Zahlen zurückgibt (und dann Sonderfälle wie die Division durch 0 fangen zu dürfen), definiere ich eine Division //, die entweder Zahlen oder einen Ausweichtyp ausgibt. Ähnlich wie Listen, die entweder Elemente oder ein Schlußsymbol beinhalten. Und wieder: Ist das alles? </p> <p class="wl_nobottom">Ich muss es bezweifeln, sonst könnte man es einfach erklären.</p> <img src="https://ssl-vg03.met.vgwort.de/na/e536039984ac4dcd91a29ece77e088c8" width="1" height="1" alt=""> Wed, 07 Mar 2012 08:05:00 +0100 https://www.onli-blogging.de/1148/guid.html