Richtlinien für grafische Benutzeroberflächen unter Windows 👍 👎

In einem früheren Beitrag hatte ich bereits die Framework Design Guidelines verlinkt, welche einen Leitfaden zur Implementierung von Backend-Funktionalität, insbesondere in Form von Programmbibliotheken, darstellen.

Nun wurde ich auf die OS X Human Interface Guidelines aufmerksam gemacht und in diesem Zusammenhang gefragt, ob es so etwas auch für Windows gibt. Auch von Microsoft gibt es entsprechende Informationen: Im Windows Dev Center lassen sich viele weitere Hinweise zur Entwicklung eigener Anwendungen finden.


PS: Der Vollständigkeit wegen sei auch auf Material design von Google hingewiesen.

Städteportal erweitert und überarbeitet 👍 👎

Nachdem sich auf dem Städteportal aus Mangel an Zeit im letzten Jahr kaum etwas verändert hat, darf ich nun zwei größere Neuerungen ankündigen. Die eine ist inhaltlicher Art, die andere betrifft die Darstellung.

Zum einen ist Amsterdam, die Hauptstadt unseres direkten Nachbarlandes Niederlande, nun Bestandteil des Städteportals. Die Inhalte sind derzeit noch begrenzt, werden aber wie üblich sukzessive ergänzt.

Darüber hinaus wurde das Design deutlich modernisiert, um weniger von den eigentlichen Inhalten abzulenken. Im Rahmen dessen wurde außerdem an wenigen Stellen ohnehin kaum verwendete Funktionalität entfernt.

Informationen zur Internetverbindung (und mehr) 👍 👎

Ursprünglich als (äußerst) minimalistisches Tool gestartet, um die aktuelle öffentliche IP-Adresse schnell (und vor allem ohne lästige Werbung) herauszufinden, kamen mit der Zeit einige weitere Funktionen hinzu.

Da das Projekt bereits seit einiger Zeit stillschweigend unter Projekte hier auf der Webpräsenz verlinkt wurde, haben sehr viele Besucher bereits darauf zugegriffen. Mich erreichten daher auch bereits einige Anfragen, ob beispielsweise Informationen zu beliebigen IP-Adressen (statt nur zur anfragenden IP-Adresse) abgefragt werden können und die allgemeine Verwendung des Tools für eigene Zwecke überhaupt erwünscht ist.

Zuerst möchte ich offiziell festhalten, dass selbstverständlich auch ihr die Funktionalität unter debug.coders-online.net für eigene Zwecke verwenden dürft – ansonsten hätte ich das Projekt nicht ohne weitere Hinweise öffentlich eingetragen, da ich frei verfügbare Informationen und Dienste auch als eben solche betrachte. Vielmehr gibt es sogar eine textbasierte Schnittstelle zur einfachen automatisierten Verwendung. Der am häufigsten gestellten Frage, der Freigabe für beliebige IP-Adressen, stehe ich leider etwas skeptischer gegenüber. Das liegt jedoch weniger an den technischen Möglichkeiten des Tools oder meinem Willen dazu.

Das Backend, welches die Informationen für Web-Oberfläche und Schnittstelle zur Verfügung stellt, ermöglicht selbstverständlich die beliebige Angabe von IP-Adressen – ansonsten wäre das Tool auch gar nicht allgemein einsetzbar. Von mir aus dürftet ihr auf diese "interne" Funktionalität gerne ebenfalls zugreifen, ich sehe jedoch gewisse Probleme dabei. Die angezeigten Informationen, insbesondere die der Registrierungsstelle/n, sind zwar öffentlich per Whois verfügbar, in der weiteren Verwendung jedoch üblicherweise auf ein berechtigtes Interesse beschränkt – bei der derzeitigen IP-Adresse des eigenen Anschlusses ist dieses sicherlich gegeben. Ich sehe mich andernfalls jedoch grundsätzlich der Gefahr ausgesetzt, dass massenweise Abfragen zu beliebigen Adressen mit fragwürdigem Ziel erfolgen. Da ich alle meine Projekte rein privat und großteils schlicht aus Freude an der Entwicklung (mit C#) betreibe, hoffe ich auf Verständnis, dass ich mein persönliches Risiko dabei minimieren möchte. Ihr könnt die Seiten aber beispielsweise auch einfach von eurem Server aus aufrufen.

Ich kann jedoch bereits darauf hinweisen, dass ähnliche Möglichkeiten bald auch für weitere Ziele zur Verfügung stehen werden: Im Rahmen eines Monitoring-Projekts, welches sich derzeit noch in einer frühen Entwicklungsphase befindet, können einige Funktionen auch auf eigene Webseiten und Server Anwendung finden. Selbst betriebene Server dürfen – nach einer entsprechenden Freischaltung – sogar besonders umfassend geprüft werden.

Zum Abschluss möchte ich noch die derzeit verfügbaren Funktionen kurz zusammenfassen:
  • Verbindung

    Auf der Startseite erfahrt ihr eure öffentliche IP-Adresse mit entsprechender Typisierung (IPv4, IPv6). Es wird versucht, die IP-Adresse in einen Hostnamen aufzulösen, welcher üblicherweise eine Bezeichnung mit Hinweis auf euren Anbieter enthält. Darüber hinaus werden Informationen zur Verschlüsselung (ihr könnt die Webseiten auch per HTTPS aufrufen) angezeigt und ihr habt die Möglichkeit, weitere Informationen zur IP-Adresse bei der zuständigen Registrierungsstelle abzufragen.

  • System

    Auf dieser Seite werden einige serverseitig ermittelbare Informationen zu eurem Browser und Betriebssystem angezeigt: Browser und dessen Version, die verwendete HTTP-Version, Do Not Track-Flag und Betriebssystem inkl. Version. Darüber hinaus werden die in eurem Browser konfigurierten Sprachen nach Priorität aufgelistet.

  • Tools

    Hier stehen einige weitere Abfragemöglichkeiten zur Verfügung. So kann beispielsweise die Latenz der Verbindung oder die Route zum Server bestimmt werden. Ihr könnt außerdem eure IP-Adresse auf Einträge in DNS-Blacklisten prüfen und häufig verwendete Ports des Systems überprüfen.

  • Kopfzeilen

    Auf dieser Unterseite werden alle von eurem Client zum Server gesendeten Kopfzeilen etwas aufbereitet dargestellt. Eine völlig unbearbeitete Ausgabe erhaltet ihr – wie auch in allen anderen Fällen – über die Schnittstelle. Das ist insbesondere dann praktisch, wenn ihr eigene HTTP-Funktionalität umsetzt und die gesendeten Felder prüfen möchtet.

  • Fähigkeiten

    Diese Informationen werden von HttpBrowserCapabilities zur Verfügung gestellt.

Die Webpräsenz ist auf Deutsch, Englisch und Niederländisch verfügbar; die Einstellung wird vom Browser bezogen. Vorschläge zu weiteren Funktionen und Meldungen zu Fehlern werden jederzeit gerne per Tracker angenommen.

(De-)Kompression mit C# 👍 👎

Zwar ist Speicher heutzutage üblicherweise keine Mangelware mehr, dennoch kann sich die Komprimierung großer Datenmengen, beispielsweise zur Übertragung, lohnen. C# bietet dazu einige Möglichkeiten, so unter anderem zur Arbeit mit ZIP-Archiven. Zu diesen möchte ich jedoch in einem separaten Beitrag kommen und stattdessen zeigen, wie sich mit der DeflateStream-Klasse beliebige Daten(-ströme) (de-)komprimieren lassen:
(De-)Komprimierung von Rohdaten
01020304050607080910111213141516171819202122232425
  // Daten komprimierenpublic static byte[] Compress(byte[] data) {    using(MemoryStream inStream = new MemoryStream(data)) {        using(MemoryStream outStream = new MemoryStream()) {            using(DeflateStream deflate = new DeflateStream(outStream, CompressionMode.Compress)) {                inStream.CopyTo(deflate);            }
return outStream.ToArray(); } }}
// Daten dekomprimierenpublic static byte[] Decompress(byte[] data) { using(MemoryStream inStream = new MemoryStream(data)) { using(MemoryStream outStream = new MemoryStream()) { using(DeflateStream deflate = new DeflateStream(inStream, CompressionMode.Decompress)) { deflate.CopyTo(outStream); }
return outStream.ToArray(); } }}
Um beispielsweise komplette Dateien effizient zu (de-)komprimieren, kann wie folgt vorgegangen werden:
(De-)Komprimierung von Dateien
010203040506070809101112131415161718192021
  // Datei komprimierenpublic static void CompressFile(string inputPath, string outputPath) {    using(FileStream inStream = File.OpenRead(inputPath)) {        using(FileStream outStream = File.OpenWrite(outputPath)) {            using(DeflateStream deflate = new DeflateStream(outStream, CompressionMode.Compress)) {                inStream.CopyTo(deflate);            }        }    }}
// Datei dekomprimierenpublic static void DecompressFile(string inputPath, string outputPath) { using(FileStream inStream = File.OpenRead(inputPath)) { using(FileStream outStream = File.OpenWrite(outputPath)) { using(DeflateStream deflate = new DeflateStream(inStream, CompressionMode.Decompress)) { deflate.CopyTo(outStream); } } }}
Sofern zusätzlich verschlüsselt werden soll, worauf ich in einem separaten Beitrag näher eingehen möchte, ist eine sinnvolle Reihenfolge zu beachten. Diese trägt zwar, abgesehen von kleineren Umständen bei unberechtigten Entschlüsselungsversuchen, nicht wesentlich zur Sicherheit an sich bei – wohl aber zur erzielbaren Kompression.

Die (verlustfreie) Datenkompression basiert hauptsächlich auf Redundanzreduktion. Es werden also Muster der Eingabe erkannt und kompakter kodiert. Derartige Muster sollten nach einer ordnungsgemäßen Verschlüsselung jedoch nicht auftreten, d. h. die Ausgabe wirkt ohne Schlüssel weitestgehend zufällig. Verschlüsselte Daten lassen sich entsprechend schlecht komprimieren und so lässt sich sogar recht einfach prüfen, ob eine Verschlüsselung grobe Fehler aufweist – nämlich genau dann, wenn eine signifikante Kompression des Chiffrats möglich ist.

Konkret bedeutet dies also für die Praxis üblicherweise, zuerst zu komprimieren und danach zu verschlüsseln.

Schaltjahr ermitteln 👍 👎

Viele Beispiele ermitteln ein Schaltjahr über eine Prüfung darauf, ob das fragliche Jahr durch vier teilbar ist. Diese einfache Prüfung, die bereits im julianischen Kalender Anwendung findet, ist jedoch nur eine von drei Regeln des gregorianischen Kalenders. Für eine vollständige Prüfung müssen folgende drei Bedingungen überprüft werden:
  • Ist das Jahr durch 4 teilbar, ist es potentiell ein Schaltjahr. (2016 ist ein Schaltjahr)
  • Ist das Jahr durch 100 teilbar, ist es grundsätzlich kein Schaltjahr. (2100 ist kein Schaltjahr)
  • Ist das Jahr durch 400 teilbar, ist es generell ein Schaltjahr. (2000 ist ein Schaltjahr)
Dies lässt sich in C# nun beispielsweise wie folgt als statische Methode umsetzen:
Schaltjahr-Prüfung implementieren und verwenden
01020304050607
public static bool IsLeapYear(int year) {    return (((year % 2 == 0) && (year % 100 != 0)) || (year % 400 == 0));}
bool isLeapYear = IsLeapYear(2016); // trueisLeapYear = IsLeapYear(2100); // falseisLeapYear = IsLeapYear(2000); // true
Besonders spannend ist diese Methode jedoch nicht, das .NET-Framework bietet mit DateTime.IsLeapYear(…) nämlich bereits eine entsprechende Implementierung an. Es gilt jedoch den Hinweis der Dokumentation zu beachten, dass die Prüfung dabei immer im Rahmen des gregorianischen Kalenders erfolgt, was für manche – beispielsweise historische – Anwendungen unpässlich sein kann. Das Framework bietet im Namensraum System.Globalization jedoch weitere Kalender-Implementierungen an, welche jeweils eine entsprechende Umsetzung der IsLeapYear(…)-Methode zur Verfügung stellen.

Projektverweise

Kategorien / Archiv  |  Übersicht RSS-Feed

Schlagworte

Suche