In eigener Sache: Android-Sample-Code-Neuzugänge

Liebe Freunde von “Android-Apps entwickeln mit Java”!

Fans spaßiger App-Bastelei!

Hurra!

Ich habe mein github-Repository um einen Haufen Beispielcode erweitert. Es handelt sich dabei durchweg um Android-Apps, die ein oder mehrere Best Practices in der Android-Entwicklung mit Java zeigen. “Best Practice” heißt natürlich: Was ich für empfehlenswert halte, die Geschmäcker sind halt verschieden. Teilnehmer meiner Trainings kennen diesen Code schon, weil ich ihnen den ausführlich erklärt habe. Jetzt können Sie nochmal draufschauen – oder sich was kopieren, ist ja alles Open Source!

Mit dabei sind Samples zu Themen wie Fragments und Master-Detail-Flow, aber auch die guten alten DialogDemos, die auch das Buch erklärt. Brandneu ist eine Demo der neuen (aktuell noch in Alpha-Version erhältlichen) CameraX-API von Jetpack. Diese wird wahrscheinlich durch irgendwelche API-Änderungen ziemlich schnell obsolet; ich kann noch nicht versprechen, ob oder wann ich sie aktualisiere.

Ebenfalls bekannt aus meinem Buch ist der Kompass, der die Nutzung des Magnetometers und einen selbst gezeichneten View demonstriert. Ferner gibt es einen MiniMiniEditor, der das Speichern von Dokumenten mit dem StorageAccessFramework zeigt. Und last but not least die 9352. Wetterfrosch-App, die die schlechteste UI aller Zeiten aber dafür auch die lehrreichste Retrofit-Implementierung der letzten 23 Minuten mitbringt. Übrigens: Für nächste Woche sind 16 Grad angesagt! Hier, schauen Sie:

Diese App ist tatsächlich sinnvoll nutzbar – also, falls Sie noch keine Lieblings-Wetterfrosch-App installiert haben, nehmen Sie doch diese!

Viel Spaß mit dem Code. Beachten Sie bitte, dass bei Erscheinen einer neuen Gradle- oder Android-SDK-Tools-Version ggf. Aktualisierungen in der build.gradle vorzunehmen werden, da ich es absehbar nicht schaffe, alle Repositories aktuell zu halten.

Entkopplung mit Events

Ein Ausweg aus der Multithread-Hölle (Sie wissen schon, die mit dem fröhlichen Bad in siedenden Race conditions) ist die Entkopplung mit Events. Statt einen linearen Programmablauf zu denken, der streckenweise aus wichtigen Gründen in verschiedenen Threads abläuft, denken Sie lieber an herumgereichte Events oder, allgemeiner: Nachrichten. Ein Message-Broker läuft dazu im Hintergrund und reicht Nachrichten herum. Das entspricht einem Publish-Subscribe-Entwurfsmuster. Der entscheidende Vorteil: Die Nachricht “gehört” immer nur jenem Programmteil (oder Thread), der gerade aktiv ist. Es gibt keinen gleichzeitigen Zugriff mehrerer Threads auf das gleiche Nachrichtenobjekt. Auch der Message-Broker interessiert sich nicht mehr für eine Nachricht, sobald er sie zugestellt hat. Am Ende der Verarbeitung wird einfach eine neue Nachricht mit dem Ergebnis der Berechnung auf gleiche Weise zurück geschickt.

Publish und Subscribe

Sie wissen sicher: Viele größere Software-Systeme arbeiten längst mit Microservices und Message-Brokern wie Apache Kafka, die Nachrichten herumreichen. Aber das geht auch in Android, und Sie können damit leicht und elegant Arbeit in den Hintergrund verlagern. Statt mit AsyncTask, Thread, Handler und runOnUiThread können Sie einfach EventBus verwenden – tun Sie vielleicht eh, denn die Library hat sich in unzähligen Apps bewährt:

dependencies {
implementation 'org.greenrobot:eventbus:3.2.0'
}

Meist verwenden Sie EventBus, um Nachrichten zwischen UI-Komponenten, Fragmenten und Activities oder Services auszutauschen. Aber da Sie per Annotation festlegen können, ob ein EventHandler im Vorder- oder Hintergrund aufgerufen wird, können Sie auch sehr einfach eine saubere Background-Task-Verarbeitung umsetzen:

EB ist eine Abkürzung für EventBus.getDefault()

Links, im Main Thread, schicken Sie (z.B. nach einem Knopfdruck des Nutzers) eine CalculationStartMsg los, nix weiter. Die Message ist ein POJO, das alle nötigen Daten enthält, um die gewünschte Berechnung zu starten. Diese Nachricht (oberer Kaffeefleck) stellt EventBus im Hintergrund zu (siehe @Subscribe-Annotation). Wohlgemerkt ist der UI-Thread völlig unbeteiligt, er macht nach dem EB.post() gar nichts mehr bzw. wartet auf weitere Eingaben.

Die Berechnung im Hintergrund erzeugt eine neue Nachricht mit dem Ergebnis der Berechnung, ResultMsg (unterer Kaffeefleck), und überstellt es dem EventBus. Dieser stellt es der passenden onMessageEvent-Funktion im Main-Thread zur Verfügung, die wiederum das Ergebnis in der UI darstellt.

Async im Pool

Falls Sie oft längere Berechnungen im Hintergrund durchführen, verwenden Sie statt ThreadMode.BACKGROUND lieber ThreadMode.ASYNC. Denn während erstere Variante nur einen Thread verwendet, und mehrere Operationen daher nacheinander verarbeiten muss, benutzt ASYNC einen ThreadPool und kann daher problemlos mehrfach und für länger dauernde Berechnungen (wie Netzwerkzugriff) eingesetzt werden.

Beachten Sie immer den Android-Lifecycle: Beide Klassen (die blaue und die orange) müssen bereits instanziiert sein, sonst können sie keine Events empfangen (). Entweder die Worker-Klasse wird in onCreate der Activity (blau) erzeugt, oder alle Funktionen liegen sogar in der gleichen Activity-Klasse. EventBus kann im Gegensatz zu (expliziten) Broadcasts keine neuen Objekte erzeugen. Natürlich müssen alle beteiligten Klassen sich bei EventBus registrieren (mit EventBus.getDefault().register(this)).

In den Messages können Sie beliebige serialisierbare Daten übertragen, auch größere Mengen. Die Latenz beträgt wenige Millisekunden.

tl;dr: EventBus-ähnliche Architektur löst auf elegante Weise viele Multithreading-Probleme, da sie auf gleichzeitige Zugriffe auf ein und dieselben Ressourcen prinzipiell verzichtet. Das bedeutet maximale Entkopplung, weniger Abhängigkeiten und weniger Probleme. Mit ganz einfachen Mitteln. Investieren Sie Ihre wertvolle Zeit lieber in wichtigere Dinge, zum Beispiel Vermeiden von Sicherheitslücken…

EHCache mit Ballast

Auf manche Umstände stößt man ja eher zufällig, zum Beispiel wenn man die Festplatte aufräumt und dabei den vermissten Schlüssel für die Börse mit den zwei oder drei vor 20 Jahren vergessenen Bitcoins wiederfindet.

Nein, hier geht es nicht um Geld, sondern um Energieverschwendung. Mal wieder. Leider. Sorry.

Bei der Modernisierung einer etwas in die Jahre gekommenen Java-Anwendung war es erforderlich, die uralte Version 1.1 von ehcache durch eine aktuelle zu ersetzen. Da ehcache 3.x komplett inkompatible Konfigurationsdateien verwendet, greift der faule Entwickler zur letzten stabilen 2er-Version, nämlich 2.10.6.

Das funktioniert prima, die API ist dieselbe wie anno dazumal in der 1.1. Alles gut, bis ich mich fragte, wieso denn meine Webanwendung neuerdings über 22 MB groß ist.

Ein Blick ins WAR verrät den Übeltäter sofort: ehcache-2.10.6.jar mit über 10 MB macht fast die Hälfte meiner Anwendungsgröße aus!

ehcache-1.1.jar bringt im Vergleich läppische 47,5 kB auf die Waage.

Eine Vergrrrrrööööößerung also um einen Faktor 200. Ungefähr.

Wasnulos?

Zum Glück haben wir es mit Open Source zu tun und können mal nachschauen, ob der Anbieter vielleicht versehentlich ein Promotion-Video eingebaut hat:

Was ist denn das?!? Braucht das jemand!?!? Kann das weg?!?

Nein, kein Promo-Video, sondern ein Paket namens rest-management-private-classpath, in dem sich anscheinend nicht ein, sondern gleich zwei embedded Application Server befinden, nämlich ein Glassfish und ein Jetty.

Freilich weiß der Experte, dass mit ehcache-server ein Ehcache-Produkt für verteiltes Caching mit toller REST-API zur Verfügung steht, aber was hat das in dieser Library zu suchen? (Wenn es das ist, ich rate hier ein bisschen)

Klarer Fall: Grob geschätzt 99% der Anwendungen, die ehcache 2 nutzen, benötigen diese eingebauten Application Server überhaupt nicht (weil sie eigene mitbringen oder in standalone-Server deployed werden). Dass die eingebauten Server kaum jemals verwendet (oder auch nur bemerkt) werden, zeigt auch eine Suche auf stackoverflow, die für “rest-management-private-classpath” gerade mal 42 (kein Witz) Resultate auswirft, für “ehcache” jedoch 8461.

Effizienz sieht anders aus

Wer schonmal was von einer neumodischen Erfindung namens “Modularität” gehört hat, und etwas mit dem komplizierten Fremdwort “Effizienz” anfangen kann, kommt ziemlich schnell drauf, dass man weniger häufig benötigte, optionale Komponenten total cool in eigene Bibliotheken auslagern kann, um die Kernfunktionalität besonders schlank zu halten.

Durch den unnötigen Ballast laden Buildsysteme also mit ehcache 2.x andauernd ca. 8 MB (ungefähre komprimierte Größe des Ballasts) mehr Daten runter oder rauf als nötig und verschwenden so Bandbreite und Speicherplatz. Das klingt nach wenig – aber Ehcache ist nach eigener Aussage “Java’s most widely used cache”, und die Anzahl der Anwendungen, die die aufgeblähte Version verwenden, dürfte von erheblicher Größe sein, entsprechend hoch die Anzahl der Buildvorgänge, bei denen die Datei (mindestens) von einem Maven-Repository auf den Build-Rechner transferiert werden muss usw.

Zur Erinnerung: Jedes übertragene oder irgendwo gespeicherte Byte verbraucht Energie und trägt zum CO2-Ausstoß bei. Äußerst wenig natürlich, aber multipliziert mit einer extrem großen Häufigkeit ist das durchaus relevant. Und in diesem Fall unnötig. Bekanntlich tragen Rechenzentren zwischen 10 und 20% zum weltweiten Energieverbrauch bei. Mangelhafte Software-Effizienz trägt daran eine Mitschuld!

Hausaufgabe (zu morgen!): Den eigenen Code in Bezug auf diese Fragestellung in Augenschein nehmen.

Übrigens: In ehcache 3 hat man auf den Ballast verzichtet, das Artefakt ehcache-3.9.2.jar ist bloß 1,8 MB groß.

tl;dr: ehcache 2 schleppt unnötigen Ballast in jede damit arbeitende Anwendung. Um Energie und CO2 einzusparen, sollten Entwickler also zeitnah von Version 2.x auf 3.9 migrieren.

Prohibition für Saugrobby!

Was muss ich da lesen? Besoffene Saugroboter?

Jetzt mal unabhängig von der Frage, ob es schlimm oder lustig ist, wenn Saugrobby wie ein verwirrter Hamster immer im Kreis fährt oder länger als sonst zum Reinigen der Wohnung braucht: Kann ja mal passieren, dass beim Abschlusstest eines Updates irgendwas übersehen wird, nicht wahr?

Ich will auch gar nicht über schlechte Testbarkeit meckern oder spekulieren, wie hoch die technische Schuld der womöglich nicht tip-top sauberen Software der betroffenen Roombas des Herstellers iRobot ist (dear iRobot, if you need help here, drop me a message!). Aber der Anlass ist willkommen für die regelmäßige Erinnung an die inhärente Fehlerfortpflanzung bei Software:

Menschen machen nunmal Fehler, das ist menschlich. Unterläuft beispielsweise einem Frisör ein Fehler, rennt hinterher ein Kunde mit doofen Haaren herum. Unterläuft einem Programmierer ein Fehler, so sind viel, viel mehr, schlimmstenfalls Millionen Nutzer betroffen, nämlich alle, die diese Software verwenden oder den fraglichen Code bei einer Sitzung auf einer Cloud-Instanz durchlaufen, falls es sich um eine Webanwendung handelt.

Während der Frisör deshalb mit einem minimalen Korrektiv auskommt (z.B. dem Kunden den Spiegel hinter den Kopf halten und fragen, ob’s gefällt), muss die Software deutlich höhere Hürden überwinden, um in die freie Wildbahn entlassen zu werden. Da ist zunächst mal die Suite von Unit Tests (Sie haben doch Unit-Tests, oder?), Integrationstests auf einer Testumgebung und die Abnahme auf einer Staging-Umgebung bzw. weitere Ende-zu-Ende-Tests, sei es automatisiert oder manuell. Im Idealfall jedenfalls. Eine Testabdeckung von 100% aller Fälle ist jedoch utopisch. Das gilt umso mehr, wenn Endgeräte im Spiel sind, die über individuelle Daten verfügen (z.B. Aufzeichnungen über die Geometrie zu saugender Räume). Die kann man nicht alle testen. Geht nicht.

Also sind halt bisweilen ein paar Staubsauger-Bots besoffen.

Software wird von Menschen geschrieben, die nicht perfekt sind. Folglich kann auch das Produkt nicht perfekt sein. Deshalb wird Software immer ein Restrisiko mit sich bringen. Es mag bei guten Programmierern (die mein Buch gelesen haben) klein sein, aber nie Null. Wer von Software Wunder erwartet, übersieht den menschlichen Faktor. Wer den menschlichen Faktor übersieht, kalkuliert Kosten für Fehlerbehebung oder Wartung nicht hinreichend in die Wirtschaftlichkeitsanalyse ein – und gelang möglicherweise zu einem Ergebnis größer als Null und ist später überrascht, wenn er draufzahlt.

Disclaimer: Nein, dies ist keine pauschale Entschuldigung für Bugs. Schon gar nicht für solche, die durch guten Code und sauberes Testen vermeidbar gewesen wären. Es ist der ausdrückliche Wunsch nach realistischen Einschätzungen.

Wer die Anfälligkeit von Software mit einrechnet, kommt nämlich auch nicht auf so drollige Ideen wie z.B. autonome Drohnen mit tödlichen Waffen oder diskriminierende Algorithmen für die Sichtung von Bewerbungsunterlagen, Anwendungen also, die ein bisschen weniger witzig sind als besoffene Roboter.

tl;dr: Vermeiden Sie Fehler – aber tun Sie nicht so, als gäbe es keine.

Voller als voll

Wenn der Speicher voll ist, wirft Java bekanntlich einen OutOfMemoryError:

Oha.

Tatsächlich kann der Speicher sogar so knapp werden, dass er nicht einmal genügt, um ein Objekte der Klasse OutOfMemoryError zu erzeugen …

Wer genau hinschaut, kann sehen, dass der Fehler von com.android.vending geworfen wurde, also dem Play Store auf einem Android-Smartphone. Einem virtuellen allerdings, denn das Ganze ist beim Vorveröffentlichungs-Test einer App passiert.

Exkurs

Kleiner Exkurs über Speicher unter Java?

Nein … nur ein klitzekleiner, das Thema ist so groß, dass es gerade nicht in meinen Arbeitsspeicher passt.

Beim Start müssen wir der virtuellen Maschine von Java einen gewissen Spielraum einräumen – Speicher, der dann dem Programm zur Verfügung steht, sei es für Bytecode oder Objekte (es ist wirklich kompliziert). Der Garbage Collector ist ja einer der Hauptgründe, Java zu verwenden, weil er die Entwicklung so schön einfach macht. Programmierer müssen sich keine Gedanken darüber machen, wann sie ihre erzeugten Objekte wieder wegschmeißen müssen. Der Preis ist natürlich, dass der Garbage Collector Rechenzeit verbraucht – und das kann beim Verzicht auf Optimierungen durchaus merkliche Auswirkungen haben.

Zu viel Dingsbums

Beispiel Spiele: Normalerweise besitzen Spiele einen Renderer, der 30 mal pro Sekunde (oder öfter) den Bildschirm neu zeichnet. Da normalerweise bewegliche Dingsbums mit von der Partie sind, müssen Berechnungen stattfinden. Zum Beispiel sind Vektoren zu addieren, etwa so:

Vector3 newLocation = new Vector3(move(dingsbums,oldLocation,timePassed));
drawAt(dingsbums,newLocation);

Die erste Zeile erzeugt ein neues Objekt (newLocation) auf dem Heap. Am Ende der Zeichenfunktion ist es überflüssig, d.h. der Garbage Collector wird es irgendwann wegräumen. Jetzt stellen Sie sich vor, dass deutlich mehr als ein Dingsbums auf dem Bildschirm ist. Alle müssen sich bewegen, für jedes entsteht ein neues Vector3-Objekt, und das 30 mal pro Sekunde. Sie können sich leicht ausrechnen, wie viele Objekte der Garbage Collector letztlich aufzuräumen hat. Schlimmstenfalls macht sich das als Ruckeln bemerkbar, auf jeden Fall verbraucht es Prozessorzeit und damit Energie (also Akkuladung).

Besser ist es also, Objekte wiederzuverwenden. Dingsbums sollte über einen permanenten Vector3 verfügen, nur dessen Koordinaten (vielleicht native floats) ändern sich noch:

move(dingsbums,timePassed);
drawAt(dingsbums.getLocation());

Profilieren

Sie können mit Android Studio im Profiler genauso wie mit Java-Tools wie jmx die Aktivität des Garbage Collectors verfolgen. Ein guter Hinweis ist ein zackiger Sägezahnverlauf der Speicherbelegung. Wird der GC sehr oft aktiv, deutet das auf Optimierungspotenzial hin. Der Profiler zeigt dann an, in welchem initializer besonders viel Zeit draufgeht – damit wissen Sie, welche Objekte womöglich zu oft erzeugt werden.

Bekanntlich beträgt der Anteil der CO2-Ausstoßes der IT weltweit mit ihren ganzen Rechenzentren geschätzt 10-20%. Je effizienter Ihre Anwendung arbeitet, umso weniger ist sie daran schuld. Klingt vielleicht banal, aber nicht wenn Ihre App auf Milliarden Smartphones installiert ist und milliardenfach verwendet wird (und das wollen Sie doch, oder?).

Mehr zum Thema Speicherverbrauch und Effizienz in naher Zukunft und in der nächsten Auflage meines Buchs “Besser coden”.

Schriftarten in Android

Jeder, der schonmal eine Urkunde für seinen Zimmeraufräum-Weltmeister (6-jähriger Sohn) designt hat, weiß, dass man da mit Times New Roman und Arial keine Begeisterung auslöst. Auf 1001freefonts.com gibt es deutlich mehr als 1001 Schriftarten – aber wie kriegt man die in seine App?

Wer schonmal im Layout-Editor in Android Studio etwas herumprobiert hat, wird zumindest auf das hier gestoßen sein:

So weit, so langweilig – mehr als diese vier einfachen Varianten lassen sich hier nicht auswählen. Sie können nicht einfach einen Truetype-Font in irgendein Verzeichnis legen und dessen Namen hier hinschreiben. Wie geht’s also sonst?

Tatsächlich gibt es eine klassische Methode und eine neuere, die ich Ihnen hier kurz zeige.

Typefaces aus Assets

Die klassische Methode klappt nicht ohne Code. Dazu legen Sie zunächst die gewünschte Schriftart im TTF-Format ins Verzeichnis assets/fonts. Damit sorgen Sie dafür, dass die Schrift in Ihr APK eingebaut wird. (Der Verzeichnisname fonts ist willkürlich, Sie können ihn auch irgendwie nennen.)

An dieser Stelle eine freundlich gemeinte Warnung: Es sieht nicht nur unprofessionell aus, wenn Sie auf einem Bildschirm 10 verschiedene Schnörkelschriften verwenden – es kostet auch Speicher und Rechenzeit. Achten Sie darauf, nicht zu viele und nicht zu komplexe Schriften zu verwenden. Letzteres erkennen Sie an der Größe der TTF-Datei.

Und noch eine Warnung: Viele im Netz auffindbare Schriften verfügen nicht über deutsche Umlaute. Und die wenigsten bieten Unterstützung auch für ausgefallene Zeichen. Wenn Sie ohnehin keine fremden Schriftsysteme oder Sprachen unterstützen wollen, können Sie das getrost ignorieren – bedenken Sie aber, dass ein griechischer Nutzer Ihres Spiels beim Eingeben seines Namens für Ihre Online-Highscore-Liste möglicherweise griechische Zeichen verwenden möchte. Wenn Sie dem zugehörigen EditText eine Schriftart ohne griechische Buchstaben zugewiesen haben, sieht der Nutzer bloß kleine Rechtecke.

Genug Warnungen, kommen wir zum Programmcode.

Die Schriftart eines TextViews (oder einer Ableitung davon, wie Button) setzen Sie wie folgt:

textView.setTypeface(typeface);

Das zugehörige Typeface-Objekt erzeugen Sie mit einer einfachen Create-Funktion:

Typeface typeface=Typeface.createFromAsset(am, path);

Dabei ist am der AssetManager Ihres Contexts, den Sie innerhalb einer Activity mit getAssets() erhalten.

Als Pfad path übergeben Sie den Dateinamen Ihrer Schriftart relativ zum Verzeichnis assets.

Schriften per FontFamily

Die moderne Variante funktioniert ohne Code. Font-Definitionen per XML wurde in Android 8 eingeführt und funktioniert dank Rückwärtskompatibilität per AndroidX bis hinunter zu Android 4.1 (API 16), was für ungefähr 99% der verwendeten Geräte auf der Welt genügt.

Nunmehr gehören Ihre Schriftartdateien ins Verzeichnis res/font.

Diese referenzieren Sie einfach im TextView-Attribut fontFamily:

Es lassen sich außerdem FontFamilies definieren, so dass für fette oder kursive Schrift automatisch die passende Schriftartdatei zum Einsatz kommt. Mehr zu Fonts erfahren Sie in der offiziellen Dokumentation:

https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml

Delphi: Unkaputtbar

Kürzlich wurde ich gefragt, ob ich denn Pascal beherrsche. Nun, diese Sprache hat mir mein Informatik-Lehrer in der 9. und 10. Klasse beigebracht, das war so anno 84/85. Dergleichen vergisst man genausowenig wie die Musik, die man damals gehört hat, und die teilweise so ähnlich klang wie prozeduraler Code. Natürlich hat sich seitdem einiges verändert: Ältere von uns erinnern sich bestimmt an die “Delphi-Epoche”, in der so ziemlich jede Free- oder Shareware für Windows mit Borlands praktischer RAD-IDE gebaut wurde.

Aber nicht nur das: Viele mittelständische Unternehmen verwenden immer noch Delphi-Software, weil es schlicht viel zu aufwändig wäre, sie neu zu schreiben, und – nun ja, sie funktioniert ja. Delphi kommt inzwischen von Embarcardero. Es gibt eine kostenlose Community Edition 10.3 des RAD Studio, das immer noch so funktioniert wie vor Jahrzehnten und das Versprechen des “rapid application development” auch hält: Die UI wird mit der Maus gebastelt, heraus kommt am Ende ein 32- oder 64-bittiges Binary, das (mit verlinkten Laufzeitbilbiotheken) sofort auf jeder Windows-Kiste läuft. Inzwischen wurden zig Features, die man zuvor immer nachrüsten musste, integriert, zum Beispiel Git/Subversion, unzählige Komponenten für HTTP, REST, Xml, Gestensteuerung und auch Must-haves wie Refactoring.

Delphi 10.3 Community Edition: Retro-Programming für die kleine UI-Anwendung zwischendurch

Natürlich würde niemand heutzutage ein neues Projekt mit Delphi beginnen, oder? Es muss ja immer gleich eine Webanwendung sein, deployed auf zig Kubernetes-Clustern, Amazon freut sich dann über die AWS-Kosten. Dafür gibt es natürlich gute Gründe (zum Beispiel kann man jederzeit Updates durchführen, ohne dass der Kunde irgendetwas tun muss), und die meisten Menschen, die Pascal sprechen, sind ihrer Rente näher als dem Abitur. Woher sollte man solche Entwickler also auch nehmen?

Da es mit FreePascal/Lazarus auch eine freie Alternative gibt, ist die Zukunft von Pascal gesichert. Sauber programmieren kann man auch mit dieser alten Sprache. Wenn man nicht alles in seine TForm-Klassen stopft (wozu Delphi ja leider ermuntert) und das Single-Responsibility-Prinzip achtet, wohlgemerkt. Delphi unterstützt auch Linux und inzwischen sogar Android und iOS. Ob es eine gute Idee ist, eine App in Pascal zu schreiben, wage ich nicht zu beurteilen, falls jemand sachdienliche Hinweise dazu hat, immer her damit!

Wer’s mal ausprobieren möchte: Die Community-Edition erfordert nur eine kostenlose Registrierung und ist hier erhältlich.

Ganz ehrlich: Ich finde, dass sich Delphi unter Windows langsam und flackerig anfühlt. Die IDE assistiert mir bei weitem nicht so komfortabel wie die von IntelliJ oder VS Code (oder, okay, Opa Eclipse). Es wird nicht im Hintergrund kompiliert, so dass mein korrekter Code rot unterstrichen bleibt, bis ich explizit ein Build auslöse. Man ist ja verwöhnt …

Haben Sie auch Hacker in die Teeküche eingeladen?

Wichtige Mitteilung! Bitte auf keinen Fall kritische Sicherheitslücken in Exchange-Servern entfernen!

Sonst hab ich nix mehr, über das ich mich lustig machen kann.

Liebe Admins. Corona hin oder her: Kritische Sicherheitslücken, für die seit Februar Patches bereitstehen, und die einem Angreifer ermöglichen, Ihr System zu übernehmen, also quasi eine Einladung in die Teeküche Ihrer Firma – wo Sie sicher auch diverse Rechner ohne Passwortschutz herumstehen haben, nicht wahr? So sieht’s aus. Kommt, liebe Hacker, wir haben nix zu verbergen, wir brauchen unsere Daten nicht, verschlüsselt sie ruhig, unsere Vorstände zahlen auch gerne das Lösegeld, das ist immer noch billiger als Leute einzustellen, die sich ordentlich um die IT-Sicherheit kümmern.

Ach, und übrigens soll es auch Mail-Systeme geben, die ganz grundsätzlich weniger anfällig sind als jene von Microsoft. Und nix kosten. Open Source nennt man das, klingelt’s?

Weitere Infos beim BSI

IT-Expertennetzwerk Wetter (Ruhr)

Falls jemand fragt: Ja, ich bin Mit-Gründer des lokalen Netzwerks für IT-Experten in Wetter (Ruhr). Derzeit existiert es in Form einer Gruppe bei Xing. Sinn ist der Austausch unter lokalen IT-Experten zu beliebigen Themen, sei es Mitarbeitersuche, Know-How-Transfer oder Händeschütteln (letzteres erst wieder nach Corona). Wer Interesse hat, IT-Experte ist und entweder in Wetter wohnt oder arbeitet, kann sich gerne melden.