Archiv der Kategorie: Miscellaneous

3dwire-frame hands typing on a blue keyboard

Dell Display Manager Ersatz unter Ubuntu 22.04

Ich habe mir einen neuen Monitor geleistet, den Dell P3421W mit eingebautem KVM-Switch. Diesen verwende ich mit DisplayPort-Anschluss an meinem Windows-Rechner und mit dem HDMI-Anschluss an meinem Ubuntu-System. Unter Windows kann mit dem Dell Display Manager eine Tastenkombination definiert werden, mit welcher auf den anderen Anschluss gewechselt werden kann. Für Linux bietet Dell diese Software aber nicht an.

Recherche

Sehr schnell bin ich bei askubuntu auf eine Frage mit Antworten gestossen, die genau diese Problematik widerspiegelte. Dabei hat sich gezeigt, dass es sich lohnt nicht nur die akzeptierte und bestbewertete Antwort zu lesen, sondern auch weniger gut bewertete, die aber möglicherweise neuer sind oder andere Aspekte beleuchten. In diesem Fall wurde als Alternative für ddccontrol ddcutil empfohlen.

Umsetzung

Als erstes habe ich ddcutil installiert:

sudo apt install ddcutil

Danach habe ich mit dem detect-Command den verwendeten I2C-bus bestimmt:

sudo ddcutil detect

Die Ausgabe in der Zeile I2C bus: /dev/i2c-4 gibt dabei die zu verwendende Bus-Nummer an, in meinem Fall 4.

Um nicht jedes Mal sudo-Rechte erlangen zu müssen habe ich meinen Benutzer der Gruppe i2c hinzugefügt und mittels einer udev-Regel die i2c-Busse der Gruppe i2c zugewiesen:

sudo usermod -G i2c -a <username>
sudo cp /usr/share/ddcutil/data/45-ddcutil-i2c.rules /etc/udev/rules.d/

Zum Schluss habe ich unter Settings->Keyboard->Keyboard Shortcuts->Custom Shortcut einen neuen Shortcut mit derselben Tastenkombination wie unter Windows und dem Command ddcutil -b 4 setvcp 0x60 0x0f erfasst.

Fazit

Mit den passenden Tools kann, mit ein wenig Aufwand, unter Linux das System mit individuellen Komfortfunktionen ergänzt werden.


Image courtesy of pixtawan at FreeDigitalPhotos.net

DisplayPort HDMI Adapter und Lenco DVT-194

Wenn der Bildschirm (noch) nicht mitspielen will

Da bei mir noch ein kleinerer LCD-TV (Lenco DVT-194) herumstand kam die Idee auf, diesen als zweiten Screen am PC zu benutzen. Es war mir klar, dass dieser als Fernseher konzipiert war und daher als PC-Bildschirm nicht die Bildqualität liefern würde wie ein dafür optimierter Monitor.

Als erste Hürde erwies sich dabei der Anschluss. Der PC hatte einen freien DisplayPort-Ausgang, der TV aber nur einen HDMI-Eingang. Aber kein Problem, dass sich nicht durch ein Adapter-Kabel lösen liesse. Leider habe ich beim Bestellen des Kabels das Bild nicht genug genau angeschaut und deshalb nicht gesehen, dass auf der HDMI-Seite der Stecker relativ breit und lang ist. Der HDMI-Anschluss beim Lenco liegt direkt neben dem Eingang des Netzteils. Es ist möglich, beide Kabel einzustecken, dabei ist es aber sehr eng – aber es funktioniert.

Also habe ich den Bildschirm mit dem PC verbunden und bin zur Einrichtung geschritten. Der Bildschirm wurde von Windows 10 erkannt und mit der Auflösung 1280×720 angesprochen. Diese wurde auch als empfohlene Auflösung angegeben. Die Verwendung dieser Auflösung veranlasste den Bildschirm aber, das Bild in alle Richtungen zu vergrössern, so dass unten die Hälfte der Taskbar nicht mehr sichtbar war. Und beim Wechsel zwischen den beiden Screens landete der Mauszeiger im Nirvana.

Versuche mit den anderen angebotenen Auflösungen lieferten auch keine befriedigende Ergebnisse. Entweder war das Bild durch die Skalierung unscharf oder gestaucht, so dass Kreise zu Ovalen mutierten. Bei der Recherche im Internet bin ich dann aber auf das Datenblatt des Lenco DVT-194 gestossen und habe dort entdeckt, dass die Auflösung des TVs 1440 x 900 beträgt. Diese Auflösung wurde aber vom Nvidia-Grafiktreiber nicht angeboten!

Durch weitere Recherche im Internet bin ich dann auf das Tool Custom Resolution Utility gestossen. Mit diesem Tool können dem Nvidia-Grafiktreiber weitere Auflösungen beigebracht werden. Nachdem ich dann den Grafiktreiber überredet hatte, dem TV die Auflösung 1440 x 900 anzubieten konnte ich den Lenco als zweiten Screen einsetzen.

Eine weitere unbeliebte Entdeckung in fremdem Code

Ich habe eine weitere unbeliebte Entdeckung in fremdem Code gefunden, die im Artikel „Die 9 unbeliebtesten Entdeckungen in fremdem Code“ noch fehlt. Auf der „Beliebtheits-Skala“ würde ich sie zwischen vier und fünf einordnen:

Gemischte Technologien
Wenn in einer Anwendung zwei Technologien für die selbe Aufgabe gemischt werden (z.B. Microsoft Entity Framework und direkte SQL-Befehle) ist das schon übel genug. Wenn aber die Technologien im selben Ablauf gemischt werden sind die Probleme vorprogrammiert.

Welche Entdeckungen fehlen noch?

Zwei Ansätze zur Preisgestaltung

Heute habe ich zwei Artikel gelesen, die sich beide mit der Preisgestaltung befassen.

Während Ralf Westphal vorschlägt, sich mittels Experimenten an den optimalen Preis heranzutasten rät Joel Spolsky von Preisexperimenten ab, wenn man nicht sicherstellen kann, dass sich die Kunden nicht über die Preise unterhalten. In seinem Artikel „Camels and Rubber Duckies“ erläutert er dafür die Theorie zur Preisgestaltung, um sie dann aber wieder in den Müll zu werfen. Der Artikel enthält viel Interessantes, auch wenn er einem mit dem folgenden Schlusssatz entlässt:

(..) and I apologize for leaving you even less able to price software than you were when you started reading this.

Die 9 unbeliebtesten Entdeckungen in fremdem Code

Image courtesy of "David Castillo Dominici" / FreeDigitalPhotos.net

Image courtesy of „David Castillo Dominici“ / FreeDigitalPhotos.net


Sehr wahrscheinlich hat jeder, der sich beruflich mit Software-Entwicklung befasst, schon einmal fremden Code übernehmen und weiterentwickeln und/oder darin Fehler beheben müssen. Und die Chance ist gross, dass der übernommene Code nicht dem entsprochen hat, was man von gut wartbarem Code erwartet.

Hier ist meine persönliche und subjektive Liste der unbeliebtesten Entdeckungen in fremden Code. Mit dieser Liste will ich niemanden angreifen oder blossstellen. Und auch ich habe schon die eine oder andere Sünde begangen, die hier aufgelistet ist. Ich möchte mich deshalb an dieser Stelle bei allen meinen Nachfolgern entschuldigen, die solchen Code von mir geerbt haben.

Hier nun aber die Liste:

  1. Riesige Dateien
    Wenn eine Datei mehrere Tausend Zeilen Code enthält wurde zu viel in diese Datei gepackt. Wenn die Datei dann nur eine Klasse enthält ist entsprechend auch die Klasse zu gross. Meist enthält die Klasse dann zu viel Know-How, d.H. sie behandelt mehrere Aspekte, anstatt sich auf ihre Kernkompetenz zu konzentrieren.
    Ob die Datei nun eine oder mehrere Klassen enthält, das Resultat ist schlussendlich das selbe: die Übersicht geht verloren und das Verhalten ist dementsprechend schwierig nachzuvollziehen.
    Generierter Code ist von dieser Regel ausgenommen.
  2. Mehrere Klassen in einer Datei
    Rang 9 ist manchmal das Resultat von diesem Vergehen. Die beiden können aber auch getrennt auftreten.
    Ich gehe gerne, wenn mir eine Klasse mehrmals aufgefallen ist, über den Solution Explorer in Visual Studio zu der entsprechenden Klasse. Wenn die gesuchte Klasse aber zusammen mit anderen Klassen in einer Datei liegt ist die Chance gross, dass die Datei nicht den passenden Namen hat und die Klasse deshalb nicht (einfach) auffindbar ist.
    Generierter Code ist, wie schon bei Rang 9, von dieser Regel ausgenommen.
  3. Viele Warnungen
    Warnungen sind da, um mögliche Probleme aufzuzeigen. Das können z.B. unbenutzte Variablen oder nicht erreichbare Code-Abschnitte sein, aber auch veraltete (obsolete) Funktionen oder fehlende XML-Kommentare. Einzelne Warnungen können normalerweise sehr einfach behoben oder kurzfristig auch mal ignoriert werden, wenn z.B. dieser Codeabschnitt gerade überarbeitet wird. Wenn die Warnung langfristig ignoriert werden soll kann dies mit einer Compilerdirektive (pragma) angegeben werden.
    Wenn die Warnungen aber im Rudel auftreten kann nicht mehr unterschieden werden, welche Warnung nun wichtig und welche unwichtig ist bzw. welche Warnung schon seit langem auftritt und welche neu hinzugekommen ist. Wenn man Code vom Vorgänger übernommen hat kann man auch nicht abschätzen, welche Warnungen ein mögliches Problem aufzeigen und welche Warnungen ignoriert werden können.
  4. Irreführende Formatierungen
    Wahrscheinlich ist schon jedem ein Fundstück wie das folgende unter die Augen gekommen:

    1
    2
    3
    4
    if(doCheck())
      doSomething();
      doAnotherThing();
    doAThirdThing();

    Auf den ersten Blick könnte man anhand der Formatierung meinen, dass die if-Abfrage die nächsten beiden Funktionen beeinflusst. Dem Compiler ist aber die Formatierung meistens (Python ist da z.B. eine Ausnahme) egal. Viel Spass beim Fehler suchen!

  5. Undokumentierte Workarounds
    Manchmal muss man weniger schöne Lösungen benutzen, um Fehler in 3rd Party Libraries zu umgehen. Oder man findet einfach keine bessere Lösung und die Deadline rückt näher. Für diese Situationen habe ich Verständnis. Aber bitte nicht irgendwo im Code versteckt, so dass man beim Fehler suchen an dieser Stelle sucht, da der Code hier so „schräg“ aussieht (Dieser Code sieht so falsch aus, der Fehler muss hier liegen…).
    Wenn ein Workaround eingesetzt werden muss darf der Kommentar nicht fehlen, dass es ein Workaround ist. Und aus welchem Grund er nötig ist. Im Idealfall mit einem Verweis auf den Bugreport im Bugtracker der 3rd Party Library. So kann der Workaround entfernt werden, wenn eine neue Version der Library verwendet wird, in welcher der Bug behoben ist und der Workaround nicht mehr nötig ist.
  6. Versteckte „globale“ Variablen
    Code-Fundstücke wie das folgende liebe ich:

    1
    2
    3
    4
    5
    if(doCheck())
    {
        DataBaseAccess dba = new DataBaseAccess();
        dba.CurrentDB = "myDataBase";
    }

    Mein erster Impuls ist hier: „Das Objekt dba fällt gleich wieder aus dem Scope, dieser ganze Block kann entfernt werden.“
    Beim Untersuchen der Klasse DataBaseAccess wird dann die Aufgabe dieses Code-Blockes sichtbar:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class DataBaseAccess
    {
        private static string currentDB = "";

        public string CurrentDB
        {
            get { return currentDB; }
            set { currentDB = value; }
        }
    }

    DataBaseAccess hat eine static Membervariable, auf die mit einem non-static Property zugegriffen wird. Obwohl das Objekt aus dem Scope fällt bleibt deshalb der Wert weiterhin gesetzt. Für einen Anwender der Klasse sind anhand der Schnittstelle weder die Funktionalität des ersten Code-Blocks noch die damit verbundenen Seiteneffekte ersichtlich. Wenn schon static Membervariablen verwendet werden müssen sollte auch der Zugriff auf diese über static Properties erfolgen.

  7. Irreführende Methoden- und Properties-Bezeichnungen
    Wenn z.B. eine Methode den Namen SetReportMode() hat, dann aber noch fünf andere Dinge gleichzeitig erledigt – oder im schlimmsten Fall nur die fünf anderen Dinge erledigt aber den Report Mode gar nicht einschaltet – sind die Probleme im wahrsten Sinn des Wortes vorprogrammiert.
  8. Business-Logik (nur) im User Interface
    Da wurde ein schönes Schichtenmodell aufgestellt, aber die Business-Logik befindet sich zur Hälfte oder komplett im User Interface Layer und nicht im Business Layer. Zum einen sucht man dadurch Fehler oder die Ansatzpunkte für Erweiterungen am „falschen“ Ort, zum andern kann auch das User Interface nicht einfach gewechselt werden (z.B. Windows Forms durch WPF oder ASP.NET ersetzen), wie es mit einem sauberen Schichtenmodell möglich wäre. Wenn die Business Logik dann noch verteilt ist dürften auch viele Business Regeln mehrfach implementiert sein, vermutlich sogar mit kleinen Unterschieden (sprich Inkonsistenzen).
  9. Keine Unit Tests
    Diese Entdeckung tritt meist in Gesellschaft von vorher aufgeführten Entdeckungen auf. In diese Kategorie gehört auch die Variante „als Unit Test getarnter Spike„, bei der erste Versuche an einer Technologie mit Hilfe des Test Runners gemacht werden. Auch andere „Missbräuche“ des Test Runners gehören in diese Kategorie. Diese zeichnen sich dadurch aus, dass die keine Asserts in den Testmethoden haben.
    Alle Varianten haben aber eines gemeinsam: Es fehlt die Absicherung, um Refactorings vornehmen zu können ohne Angst haben zu müssen, etwas kaputt zu machen. Und wenn die Unit Tests fehlen ist normalerweise der Code auch nicht so geschrieben, dass Unit Tests einfach hinzugefügt werden können. Dadurch muss der Code zuerst umgebaut werden, dabei fehlt aber wieder die Unterstützung der Unit Tests… Und um die vorher aufgeführten Entdeckungen beheben zu können wären die Unit Tests auch eine willkommene Absicherung.

Wie schon oben gesagt ist dies meine subjektive Top 9. Was sind Eure schlimmsten Entdeckungen in fremdem Code oder wie würde Eure Reihenfolge aussehen?

Henry Waltz

Heute habe ich zufällig einen interessanten Trailer (?) gefunden:

HENRY WALTZ – OFFICIAL TRAILER from Emil Goodman on Vimeo.

Ob es sich um einen abendfüllenden Film handelt oder nur eine Designstudie ist kann ich aus dem Trailer nicht hundert prozentig erkennen. Auch im Internet ist man sich noch nicht so ganz sicher, um was es sich bei Henry Waltz handelt.

Ich finde aber, es sieht sehr interessant aus und macht Lust auf mehr.

Eine eher unglückliche Formulierung

Folgenden Artikel habe ich beim Tages-Anzeiger Online | Zürich gefunden. Die Formulierung im letzten Satz ist eher unglücklich:

Ausgerissener Stier lief Amok
Ein aus dem Schlachthof ausgerissener Stier hat heute die Polizei auf Trab gehalten und Passanten einen gehörigen Schrecken eingejagt. Seine Flucht endete auf einer Wiese, wo er erlegt wurde.

Just als er beim Schlachthof ausgeladen wurde, riss der Stier aus und machte die Gegend unsicher. Mit gesenkten Hörnern habe der dreijährige Bulle alles angegriffen, was sich ihm in den Weg stellte, schreibt die Stadtpolizei in ihrer Mitteilung. So konnte sich ein Mann an einer Tramhaltestelle an der Badenerstrasse nur noch durch einen Sprung zur Seite in Sicherheit bringen.

Anschliessend rannte der Stier bis zur Wiese des Schulhausareals Luggweg. Dort beruhigte er sich – allerdings erst, nachdem ihm eine vom Schlachthof eilends heran gekarrte Kuh Gesellschaft leistete.

Die Ruhe war nur von kurzer Dauer: Nachdem er einen hinter einem Drahtzaun stehenden Polizisten angriff, wurde der Bulle aus Sicherheitsgründen mit mehreren Schüssen getötet. (pa/sda)

Welcher Bulle wurde jetzt genau getötet?