WTF #27

Ich hab nach langer Zeit mal wieder ein paar Screenshots für euch :)

Platz 6: Diese Klasse ist keine Klasse

6.png

clang ist verwirrt. Ist Shader jetzt eine Klasse oder nicht? Er ist noch dabei, seine Argumente abzuwägen; das kann noch spannend werden.

Platz 5: Photoshop auf Deutsch

5

Die Übersetzer von Photoshop müssen noch etwas an ihrer Grammatik arbeiten, aber für den Anfang ist das schon mal nicht schlecht!

Platz 4: Feedback Loops im Internet

4a.png

Diese Support-Seite von Microsoft ist definitiv wirklich ganz extrem auf Englisch, weshalb der Server um diese Tatsache zu unterstreichen gleich ein paar Weiterleitungen vorgenommen hat. Gut, dass die Fehlermeldung trotzdem auf Deutsch ist.

4b.png

Was Microsoft kann, kann Amazon schon lange. Amazon ist nicht so der Freund von Sicherheit, weshalb es auf Produktseiten von HTTPS auf HTTP weiterleitet, wenn nötig auch mehrfach.

Platz 3: Stark eingeschränkt

3.png

Die Techniker Krankenkasse erlaubt es einem nicht, die Mindestmaße zu überschreiten.

Platz 2: Besser als Radio

2.png

Diese Playlist ist echt das beste, was mir je passiert ist. Auch toll, dass es mehrere Alben mit jeweils mehreren Tracks gibt. Vielfalt in der Musik ist wichtig.

Platz 1: Knapp daneben

1.png

Ärgerlich. Kann man natürlich nichts machen, aber wer braucht schon Hardwarebeschleunigung. Psst, hättet ihr diese Meldung nicht angezeigt, hätte es niemand gemerkt.

HTTPS auf WordPress

Es ist eigentlich ganz ironisch – mein Blog und meine Webseite haben die Transfermethode getauscht. Mein Server liefert dank Let’s Encrypt seit ein paar Tagen nur noch verschlüsselt aus, während ihr mein Gesabbel hier ab sofort (vorübergehend) unverschlüsselt ertragen müsst.

Dies liegt, wie einige sicherlich schon bemerkt haben, an der neuen Adresse des Blogs, welche durch DNS-Magie und einem Dollar pro Monat auf das weiterhin auf WordPress.com gehostete Blog zeigt.

  • Bonus 1: Ich muss nichts administrieren, patchen und updaten.
  • Bonus 2: Ich muss nicht dieses Schreckgespenst was manche PHP nennen installieren und einrichten.

Gespannt wartete ich auf den Abschluss des DNS-Balztanzes um zu sehen, wie WordPress das Zertifikatproblem auf eigenen Domains löst. Die Antwort:

Bildschirmfoto_2016-01-31_05-31-26

Gar nicht. Eigene Domains fallen auf HTTP zurück und eine HTTPS-Verbindung führt zu einem Zertifikatsfehler. Ehrlich gesagt hatte ich damit gerechnet; Zertifikate automatisch zu generieren ist ne ziemlich heikle Sache.

Trotzdem hab ich mal ne Mail an den Support verfasst:

[…]
I know that this is currently not possible. But, seeing that Chrome might soon start warning users about insecure connections and considering the security implications of unencrypted transfer itself, I wonder if you plan to support HTTPS on mapped domains in the future, either by issuing certificates yourselves or by using Let’s Encrypt.

I hope you agree that it’s kind of ironic that connections actually become less secure when paying for a mapped domain compared to the free WordPress subdomain. Even an option to set a custom certificate would be fine with me.
[…]

Ich habe mit einer kurzen und bündigen Erklärung gerechnet, warum das ganze aus sicherheitstechnischen und wirtschaftlichen Gründen in den nächsten zehn Jahren ausgeschlossen ist.

Neun Minuten (!!!) später bekam ich die sehr nett formulierte Antwort, dass das Team bereits die automatische Vergabe von Zertifikaten mittels Let’s Encrypt testet, sie allerdings noch ein paar Monate brauchen um sicher zu sein dass es keine Probleme gibt.

Ich werde mich jetzt zurücklehnen und freuen, dass ich trotz einiger Überlegungen in den vergangenen sieben Jahren nie von WordPress.com auf eine eigene Seite umgestiegen bin.

  • Bonus 3: WordPress.com ist einfach geil.

Klassen mit 1.000.000 Zeichen langen Namen

Klassen mit 1.000.000 Zeichen langen Namen – willkommen zu den grausamsten Höllenqualen, die ich meinem Compiler je angetan hab.

Funktionale Programmierung ist heutzutage (mehr oder weniger) der heißeste Scheiß überhaupt. Es geht hierbei, elkatant vereinfacht und sicherlich korrekturbedürftig, um die deklarative Beschreibung eines Problems ohne einen sequentiellen (imperativen) Lösungsansatz. Kurz gesagt: Statt dass ihr dem Computer einzelne, nacheinander abzuarbeitende Schritte vorgebt, gebt ihr ihm eine Beschreibung des Problems an sich (in Form einer Funktion im mathematischen Sinne) und lasst ihn intern einen imperativen Lösungsweg ermitteln. Mehrere solcher Funktionen lassen sich kombinieren und werden letztendlich als ein “gemeinsames Ganzes” ausgeführt, ohne Zwischenergebnisse die man speichern oder bearbeiten müsste.

Einfach(st)es Beispiel. Ich brauche, warum auch immer, eine Liste der Zahlen von 0 bis n. Heißt in imperativen Sprachen Speicher reservieren, von 0 bis n hochzählen, Ergebnis weiterverarbeiten. In einer funktionalen Programmiersprache wie Haskell hätte man das Problem eher so gelöst:

zahlen_ab x = x : zahlen_ab (x + 1)
zahlen_bis n = take n (zahlen_ab 0)

Wer bei dieser Syntax nicht schon die Fackel angezündet hat, wird erkennen, was hier passiert: zahlen_ab ist nichts anderes als eine mathematische Funktion, welche beschreibt, was wir wirklich wollen: Eine Liste von Zahlen, bei der jedes Element um 1 größer ist als das Vorgängerelement. Erst wenn wir unsere Funktion benutzen, geben wir an, wie viel wir von der Liste wirklich brauchen. Disclaimer: Ja, ich weiß, total unnötig, [0..n] hätte es auch getan.

Das Konzept, Daten on-demand zu generieren, hat in Form von Generatoren inzwischen auch Einzug in imperative Sprachen gefunden. Ein Beispiel ist die yield-Funktion in C#.

Jetzt meine Idee: Kann man Konzepte einer funktionalen Programmiersprache in C++-Metaprogrammierung abbilden, und wenn ja, wie schlagen sie sich im Vergleich?

Statt dass wir mit Variablen rechnen, rechnen wir also mit Templates. Als Pattern Matching Ersatz benutzen wir Template-Spezialisierungen. Das Ziel: Ein Binärbaum ohne Laufzeit-Speicherverbrauch. Er soll eine Höhe von 10 haben und vollständig sein, also 1023 Elemente enthalten.

Wenig überraschend ist, dass sich die Implementation in Haskell doch sehr in Grenzen hält. Folgende Struktur möchte ich also in C++ “nachbilden”:

data Tree a = Nix | Was a (Tree a) (Tree a)

maketree :: Int -> Tree Int
maketree 0 = Nix
maketree n = Was n (maketree (n - 1)) (maketree (n - 1))

testtree = maketree 10

treestr :: Tree Int -> String
treestr Nix = "nix"
treestr (Was val left right) = "(" ++ treestr left ++ "|" ++ show val ++ "|" ++ treestr right ++ ")"

maketree ist hier unser “Baum-Generator”. Er beschreibt einfach einen vollständigen Binärbaum, bei dem jeder Knoten als Wert den Abstand zu seiner Wurzel hat. testtree erzeugt dann einen Baum mit Höhe 10. treestr erzeugt aus einem beliebigen Baum einen String.

Problem 1: Tree ist etwas, das entweder Nix sein kann, oder Was inklusive einem Wert und zwei weiteren Trees. C++ hat keine Enums, in die man Zusatzwerte packen kann. Genau so wenig können wir eine struct auf sich selber referenzieren, so viel Speicher haben wir nicht. Was wir aber machen können, ist den Wert und die linken und rechten Kinder als Template zu definieren:

struct Nix {};

template<int val, typename left, typename right>
struct Was {};

Statt unendlich viel Speicherplatz belegen die Structs jetzt überhaupt keinen Speicher mehr (Instanzen leerer Klassen belegen aus technischen Gründen ein Byte, allerdings werden wir von den Structs keine Instanzen erzeugen).

Problem 2: maketree ist rekursiv, wie sollen wir das abbilden, ohne auf C++-Funktionen zurückzugreifen? Glücklicherweise erlaubt uns der Compiler Rekursion in Templates, sodass wir tatsächlich sehr ähnlich vorgehen können:

template<int n>
struct maketree
{
	using type = Was<n, typename maketree<n - 1>::type, typename maketree<n - 1>::type>;
};

Rufen wir jetzt maketree<10>::type auf, bekommen wir einen Kompilierfehler: Das ganze ist unendlich. Abhilfe schafft “Pattern Matching” mittels einer zweiten, spezialisierten Version von maketree, außerdem definieren wir uns wieder testtree als Abkürzung auf maketree<10>::type:

template<>
struct maketree<0>
{
	using type = Nix;
};

using testtree = maketree<10>::type;

Und das war’s. Irgendein Teil von clang++ ist gerade gestorben. Würde man den Klassennamen ausschreiben, der von testtree definiert wird, wäre dieser fast eine Million Zeichen lang. Viel wichtiger aber: Es funktioniert.

Die Implementation von treestr erfolgt ähnlich wie maketree, mit dem Nachteil dass Strings für C++ leider nicht konstant genug sind und deshalb nicht schön templatebasiert konkateniert werden können. Wäre dies der Fall, würde uns der Compiler das gesamte Programm auf eine Instruktion herunteroptimieren, nämlich die, die das Ergebnis ausgibt. Hier muss leider ausreichen, dass wir den Baum rekursiv direkt auf cout schreiben. Dafür müssen wir zusätzlich die Was-struct leicht aufbohren, damit wir den Wert und die Kinder extrahieren können.

template<int val, typename left, typename right>
struct Was
{
	using left_type = left;
	using right_type = right;

	static const int value = val;
};

template<typename tree>
struct treestr
{
	static void print()
	{
		std::cout << "(";
		treestr<typename tree::left_type>::print();
		std::cout << "|" << tree::value << "|";
		treestr<typename tree::right_type>::print();
		std::cout << ")";
	}
};
template<>
struct treestr<Nix>
{
	static void print()
	{
		std::cout << "nix";
	}
};

Für den const int in Was sollte übrigens kein zusätzlicher Speicher verbraucht werden, da er als Kompilierzeit-Konstante angesehen werden kann. Bockige Compiler kann man per constexpr zu ihrem Glück zwingen.

Vollständiger Code

Das Ergebnis: Wir haben das Problem definiert und wissen, dass testtree die Lösung enthält; die gesamte Datenstruktur wird direkt bei der Kompilierung erzeugt. Das kann man so weit auf die Spitze treiben, dass der Compiler einem die Fibonacci-Folge ausrechnet.

Fazit: Ja, es geht. Ja, es sieht scheiße aus. Vorteil der C++-Lösung: Sie ist wesentlich schneller. Dies liegt aber daran, dass die eigentliche Arbeit bereits während der Kompilierung getan wurde, während Haskell erst noch rechnen muss. Das ist auch gleichzeitig der Nachteil daran: Natürlich können wir das ganze in C++ nur mit konstanten Ausdrücken benutzen. Haskell ist das relativ wurscht.

Wenn man aber wirklich mal solche Konstrukte (sie dürfen auch ruhig etwas weniger makaber dem Compiler gegenüber sein) benötigt, dann sind C++-Templates ein Segen. Die Standard-Library scheint gerade auch in diese Richtung zu expandieren und Boost ist sowieso das Paradebeispiel für Template-Programmierung.

Kleiner zusätzlicher Vorteil: Jedem Disassembler, der C++ Symbole anzeigt, wird von dem obigen Code schwindlig, denn der sieht solche Klassen auch nicht alle Tage. Wenn ihr mal wen ärgern wollt, baut das ein. Das “Opfer” kann sich dann entscheiden, die Symbole vorher aus der Binary zu strippen und so jede Lesbarkeit zu verlieren, oder stundenlang zu warten bis der Disassembler die Symboltabelle zusammengekratzt hat.

Zum Abschluss ein Beispiel, an dem man sieht, dass so etwas tatsächlich nützlich sein kann. In einem kleinen Tool von mir, welches ein einfacher C++-Wrapper über OpenGL ist, findet sich folgender Code zum Definieren von GLSL-Programmen (welche eine Pipeline an GLSL-Shadern darstellen):

template<typename... Shaders>
struct ProgramShaderHelper;

template<typename First, typename... More>
struct ProgramShaderHelper<First, More...>
{
	static void attach(GLuint program)
	{
		glAttachShader(program, First().compile());
		ProgramShaderHelper<More...>::attach(program);
	}
};

template<>
struct ProgramShaderHelper<>
{
	static void attach(GLuint program) { }
};

template<typename... Shaders>
struct Program
{
	Program()
	{
		//...
		ProgramShaderHelper<Shaders...>::attach(prg);
		//...
	}

	static void use()
	{
		static auto program = Program<Shaders...>();
		glUseProgram(program.prg);
	}

private:
	GLuint prg;
};

namespace Programs
{
	using TerrainProgram = Program<Shaders::TerrainVertexShader, Shaders::TerrainFragmentShader>;
	using BlurProgram = Program<Shaders::BlurComputeShader>;
}

Hiermit bin ich in der Lage, das TerrainProgram durch einen Aufruf von Programs::TerrainProgram::use() zu aktivieren. Brauche ich ein neues Programm, muss ich lediglich eine Zeile im Programs-Namespace hinzufügen. Mittels variadischem Template kann ich eine beliebig große Anzahl von Shadern definieren, welche mittels ProgramShaderHelper nacheinander initialisiert werden. Ich habe dafür kein Array gebraucht welches Speicherplatz der Laufzeit in Anspruch nimmt. Letztendlich wurde, bis auf ein paar kleine “Gedächtnisstützen”, das Problem wieder nur beschrieben – die nötigen Klassen hat sich der Compiler selber gebaut und benutzt.

Und damit willkommen zurück auf meinem Blog.

Hallo!

Kennt ihr das, wenn ihr irgendwann mal eine Seite zu euren Bookmarks hinzugefügt habt und manchmal aus Langeweile nachguckt, ob sie sich geändert hat, nur um zu sehen, dass sie immer noch genau so aussieht wie vor Jahren und ihr euch fragt, was wohl aus dem Autor geworden ist? Nicht? Wie zum Geier seid ihr dann hier gelandet?!

Mein letzter Post hier ist über ein Jahr lang her. Man könnte meinen, ich hätte diese Seite als Kind erstellt und wir hätten uns irgendwann auseinandergelebt. Ersteres ist auf jeden Fall wahr, letzteres ist schwer zu beantworten ;)

Da ich aufgrund der grandiosen Vorlesung über die Grundlagen der Betriebswirtschaftslehre jetzt tugendhaft SMARTe Ziele definiere, habe ich mir vorgenommen, in den gerade begonnenen Semesterferien diesen Blog mal wieder mit neuen Daten zu befüllen (ironischerweise ist dieses Ziel nicht SMART).

Mit alten Daten des Blogs ist bereits etwas passiert: Erstens hab ich den Background-Noise durch ein neues Theme drastisch heruntergeschraubt und komische Seiten und Sidebar-Elemente entfernt. Zweitens ist eine große Masse an alten Posts verschwunden – persönlicher Kram, Rants, Gedanken eines 13-jährigen… aus hoffentlich einleuchten Gründen gibt es nur noch Posts von vor 2013, die ich für ausreichend “historisch wertvoll” halte oder die so dämlich waren, dass sie mich heute immer noch amüsieren.

Es haben insgesamt immerhin stolze 59 Posts überlebt, ungefähr ein Zehntel des Originalbestands. Die einmalige Chance, einmal nach ganz unten zu scrollen!

Was passiert hier also die nächsten Wochen? Mal sehen – nachher gibt es erstmal etwas ziemlich technisches was schon eine Weile in den Entwürfen gammelt. Bis dahin.

Der Spam, der keiner war

Guck ma, ich weiß mein WordPress Passwort noch!

Unter vielen Freunden bin ich bekannt als jemand, der viel Spam bekommt. Dabei habe ich mir das gar nicht ausgesucht! Aber nach meinem Fauxpas vor drei Jahren war die Adresse, die ich heute immer noch benutze, nun mal infiziert. Dazu kommt, was ich nebenbei gesagt extrem unverschämt finde, dass auch meine quasi-öffentliche Support-Adresse für allerlei Open-Source-iges inzwischen betroffen ist.

Ich sehe das Ganze ziemlich gelassen und sammel die sogar, unter dem Vorwand, dass ich die besten Betreffszeilen irgendwann mal hier verbloggen will. Das ist schon fast Routine, Thunderbird markiert den Spam, ich sortier ihn ein. Ich will das nicht automatisch machen lassen aus Sorge, dass ich etwas wichtiges übersehen könnte.

Gut, dass ich den Spam heute nicht übersehen habe. Ich bekomme also eine merkwürdige Mail auf die besagte Open Source Adresse. Jemand bittet mich um Support für ein Programm, von dem ich noch nie etwas gehört habe. Das Deutsch war zu gut für eine dieser schlecht übersetzten Spam-Mails aus Lampukistan, selbst der Source war komplett unauffällig – die Mail war “menschlich”. Das Programm, das der Autor erwähnte, gab es allerdings gar nicht…

Ohne lange zu überlegen bat ich also höflich um mehr Information. Und tatsächlich, ich bekam eine Antwort! Diese war allerdings noch verwirrender: Man gehe in die Einstellungen auf dem iPad, dann auf besagtes Programm und unten in der Liste stünde “ich” als Support-Adresse.

Wieso werde ich in einer wildfremden iOS-App als Support aufgelistet?! Jetzt wollte ich wirklich mehr über die App wissen und fing diesmal an, den App Store zu durchsuchen (die originale Mail hatte iOS gar nicht erwähnt). Wieder nichts. Mit verschiedenen Suchbegriffen klapperte ich das Netz ab bis ich irgendwann auf ein Forum stieß, durch das sich schließlich feststellen ließ, dass der App-Name falsch geschrieben war – die App war in Wirklichkeit Filterstorm Neue.

Beim Lesen der App-Beschreibung fiel es mir wie Schuppen von den Augen. Na, errät’s einer? Unter “Andere Features” steht dort aufgelistet: “Export über FTP”.

Und hier ist der Screenshot, der mich zum Supporter von Filterstorm macht:

image1Meine verdammten Kontaktinformationen stehen in der Lizenz für FTPManager. Lizenztechnisch ist es nicht notwendig, diese tatsächlich in ein Programm einzubauen (lediglich der Copyright-Hinweis und die folgenden zwei Absätze sind erforderlich), aber klar, ich hätte sie auch mitgenommen, better safe than sorry. Was ich mir damals dabei gedacht habe, ist mir schleierhaft.

Unglücklich ist hierbei, dass FTPManager als letzte Komponente aufgeführt wird und ich zwischen Lizenz und Kontaktinfos auch noch zwei Leerzeilen stehen habe. Somit ist es letztendlich wie immer – alle Beteiligten haben sich komplett korrekt und nachvollziehbar verhalten, ich habe wieder aus eigener Dummheit lernen können.

Vielen Dank an Herrn S. für das kleine aber sehr amüsante Rätsel. Ich habe eine Paid-App gefunden, die meinen Source Code verwendet, was auch mal nett ist. Und ja, natürlich habe ich sie gekauft und ausprobiert, der FTP-Upload funktioniert einwandfrei. Fazit:

Spam, der keiner war, hat mich letztendlich zum Kauf einer 3,49€-App verleitet.

WTF-Monat des Moments.

Hier bin ich wieder. Vermisst? Nein? Okay. Ich bleib auch nicht für lange. Leider wird hier wohl demnächst weniger los sein als mal früher. Ich studiere jetzt, arbeite nebenbei und habe auch noch andere “Hobbies” außer Blogging die ich gerne fortführen möchte. Damit sage ich nicht, dass ich den Blog verwahrlosen lasse, ich werde nur eben in Zukunft in größeren Abständen Blogeinträge schreiben, welche dann allerdings hoffentlich von der Qualität besser sein werden. Na klar, als ob ich dieses Versprechen halten könnte.

Als Entschädigung für die Ruhe kommt hier der WTF-Moment von… naja, so von allen Monaten in denen ich keinen WTF-Moment mehr geschrieben habe.

Platz 5: Candy

5Neues Candy. Seems legit.

Platz 4: Die Hitze ist doch egal

4Mein MacBook hatte schon immer ein Problem mit seiner Temperatur. Letztens habe ich aber meinen Rekord gebrochen – 101°C und der Lüfter ist quasi im Leerlauf. Schon traurig, aber anscheinend will es Selbstmord begehen.

Platz 3: SFTP

3Der SFTP-Client auf OS X ist absolute Kacke. Er kann keine Tab-Vervollständigung und stellt sich auch sonst ziemlich dämlich an, so wie auch hier. Alzheimer, was?

Platz 2: Siri kann aber auch gar nichts

2Das war nicht gut. 2 von 10 Punkten.

Platz 1: Google spioniert mal wieder

1Google und ihre “Don’t Do Evil” Policy. Man kann sagen was man will, aber ich finde, dass Google seine “Creepy Line” schon lange überschritten hat. Und nein, ich habe nicht die Spracherkennung aktiviert ;)

Ach ja, zu meiner Verteidigung, die Werbung die ihr hier ab und zu seht ist nicht für mich und ich hab sie nicht bestellt. Die kommt, weil ihr einfach zu oft hier seid und WordPress entschieden hat, sich die Traffickosten zurückzuholen. So ist das nun mal ;)

Statistiken

Jetzt wo Ferien Countdown schon eine Zeit lang eingestampft ist und zu Beginn der Sommerferien die alte Version 2.0 ausläuft (2.1 läuft wie versprochen mindestens bis Sommer 2014), bleibt mir eigentlich nur noch, die bisherigen Serverstatistiken auszuwerten und in nette Diagramme zu verwandeln. In 2.1 habe ich den Update-Mechanismus grundlegend geändert (das ist auch der Grund warum die älteren Versionen die neuen Datenbanken nicht mehr bekommen) und zu diesem Anlass gleich serverseitig ein kleines Statistikmodul geschrieben, welches ganz anonym die Update-Anfragen zählt.

Gestern habe ich mir dann in C ein Auswertungs-Programm gebaut. Ganz nebenbei: Ich habe übrigens ein neues Git-Repo, in das ich ab und zu kleinere C-Tools hochlade die ich ganz nützlich finde.

Zurück zu den Statistiken:

Bildschirmfoto 2013-07-20 um 20.23.59

Eigentlich uninteressant, denn bis auf meine “Belastungstests” am Anfang, den Release der 2.1 und einigen kleinen oder größeren Serverpannen erkennt man eigentlich nix. Ich dachte, dass zumindest kurz vor den jeweiligen Ferien ein kleiner Peak zu sehen sein würde, aber ich bin halt auch kein Marktforscher. Interessanter finde ich da schon das:

Bildschirmfoto 2013-07-20 um 20.25.08

Man erkennt hier einen schönen Trend in Richtung 21 Uhr, außerdem kleinere Peaks um 6-7 Uhr (also vor der Schule) und um 10 Uhr herum (1. große Pause). Man könnte sogar eine ungenaue Durchschnittszeit ermitteln, zu der der durchschnittliche Ferien Countdown User schlafen geht ;)

Ich hab’s mir nicht nehmen lassen, auch die Device Family aufzuzeichnen. Welches iOS-Gerät benutzt der Otto-Normalferiencountdownverbraucher also?

Bildschirmfoto 2013-07-20 um 20.26.04

Dass gerade mal 1/4 Ferien Countdown auf einem iPod Touch benutzt haben, überrascht mich etwas. Ansonsten wird man als Schüler (der nicht so nerdig ist wie ich) wohl eher kein iPad besitzen, und dass die iPhone-Besitzer dominieren war auch klar.

Nochmal als Disclaimer, diese Daten sind aus den Logs des Update-Servers generiert und mehr hab ich auch nicht, weder eure Namen, noch Kontakte, noch Standort, nicht mal eure Softwareversion. Ich bin nicht Facebook. Jede Webseite die ihr besucht zeichnet wesentlich mehr auf als das.