Old School

27. Februar 2014 ⋅ Geschrieben von Martin ⋅ Keine Kommentare

TFS 2010
Was man nicht alles installiert um Neuentwicklungen auch für alte Programme kompatibel zu machen…

Getter und Setter mit Netbeans generieren

19. Februar 2014 ⋅ Geschrieben von Martin ⋅ Keine Kommentare

Netbeans Getter und Setter generieren

Da ich eine Apple Tastatur an meinem Windows Rechner nutze konnte ich bisher nie die Tastenkombination ALT + EINFÜGEN nutzen um bei PHP Klassen Getter und Setter in Netbeans automatisch generieren zu lassen. Da mich das ziemlich störte habe ich nun einfach mal das Menü abgegrast und tatsächlich einen Punkt gefunden, der auf genau diese Funktion verweist:

Source -> Insert Code… anschließend Getter and Setter wählen, ein paar Properties markieren, ggf. noch ein Häkchen beim Chaining und zack sind die Methoden generiert. Nice Code!

Achja, die Stelle an der sich der Cursor befindet entscheidet wo die Methoden eingefügt werden ;-)

Domain Driven Design mit PHP umsetzen

20. Januar 2014 ⋅ Geschrieben von Martin ⋅ Keine Kommentare

In der Planungsphase meiner Anwendungsplattform für Geschäftsprozesse habe ich festgestellt, dass es relativ wenig Leute gibt, die sauberes DDD mit PHP umsetzen. Wobei wir gar nicht mal zu solch “ausgefallenen” Sprachen greifen müssen. Selbst die Paradebeispiele in Java aus Lehrbüchern sind oftmals unsauber umgesetzt.

Beim DDD sollte man eigentlich auf jegliche Abhängigkeiten zwischen Framework + Bibliotheken und der eigentlichen Domain Logik (Entities, Value Objects, Repository Interfaces, etc.) verzichten. Es sollte in keiner Domain Klasse eine Referenz beispielsweise zu einem Validator aus einem Framework enthalten sein. Zumindest meiner Auffassung nach halte ich das für unschön, da der Code so nicht mehr sauber portierbar und wiederverwendbar ist.

Was nun PHP auch im Speziellen angeht wollte ich anmerken – Doctrine Entities sind keine Domain Entities. Schließlich haben diese einen Verweis auf das ORM und obendrein sind die Entities direkt mit Implementierungsdetails verbunden. Dementsprechend gehören Doctrine Entities in die Infrastruktur.

Bei Residata handhaben wir es so, dass Doctrine unsere Domain Entities über ein vordefiniertes, auf jeden Entiy übertragbares Schema in der Infrastruktur Schicht mappt. Die Domain Entities wiederrum sind einfache PHP Klassen ohne Referenzen, lediglich mit einem PHPDoc Kommentar versehen um die Datentypen kenntlich zu machen.

Das Repostiory wird als Interface definiert und ebenso von Doctrine oder jeder anderen gegen die Schnittstellen der Plattform implementierten Persistenzschicht automatisch “befüllt”. Ausgefallene Abfragen die nicht automatisch bereitgestellt werden kann man in einem AbstractRepository oder einem Service über einen extra Builder bauen, der auch von der Persistenzschicht in eine Abfragesprache übersetzt wird.

Wie genau das alles nun in Code ausseht, das werde ich in den kommenden Tagen hier veröffentlichen. Ob die ganze Plattform unter einer Open Source Lizenz veröffentlich wird weiß ich allerdings noch nicht.

Microsoft Experience

20. Januar 2014 ⋅ Geschrieben von Martin ⋅ Keine Kommentare

Microsoft Experience
So viel zum “Jetzt herunterladen” Button.

Große git commits mit HTTP übertragen

25. Dezember 2013 ⋅ Geschrieben von Martin ⋅ Keine Kommentare

Counting objects: 1753, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (1605/1605), done.
efatal: The remote end hung up unexpectedly
rror: RPC failed; result=22, HTTP code = 411
Writing objects: 100% (1656/1656), 1.21 MiB | 1.12 MiB/s, done.
Total 1656 (delta 667), reused 0 (delta 0)
fatal: The remote end hung up unexpectedly
Everything up-to-date

Jeder der mit HTTP auf seinen git Server pusht kennt dieses Problem, bei großen Commits “hängt sich schnell einmal der Remote Server auf”. Um große git commits über HTTP zu übertragen muss beim Client die HTTP Post Buffer size erhöht werden. Standardmäßig liegt diese bei unter einem Megabyte, was beim commiten von Bibliotheken oder Mediendaten schnell einmal zu wenig wird:

git config http.postBuffer 524288000

Der Wert wird in bytes angegeben, hier also 500MB.

Schlägt das pushen nun wieder fehl, sollte auf Serverseite nocheinmal kontrolliert werden ob der Server überhaupt auf solche Datenmengen ausgelegt ist. Bei nginx beispielsweise fügt man hierzu in der Konfigurationsdatei des jeweiligen Servers einen Abschnitt hinzu:

http {
    client_max_body_size 500m;
}

C# WPF AbstractWindow

26. Oktober 2013 ⋅ Geschrieben von Martin ⋅ Keine Kommentare

Normalerweise erbt die Klasse eines neu erzeugten Fensters (in diesem Fall MainWindow) direkt von System.Windows.Window. Bei meiner Anwendung wollte ich allerdings, dass das Hauptfenster von meiner Klasse ResiWriter.UI.AbstractWindow erbt.

namespace ResiWriter.UI
{
    public abstract class AbstractWindow : System.Windows.Window
    {
 
    }
}

In der MainWindow.xaml.cs Klasse habe ich dann wie gewohnt von der AbstractWindow geerbt:

namespace ResiWriter
{
    public partial class MainWindow : UI.AbstractWindow
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

Durch den Umstand, dass MainWindow eine partial Klasse ist, muss nun auch der zweite zugehörige Klassenteil vom AbstractWindow erben. Problematisch an der Sache ist jedoch, dass der zweite Teil der Klasse beim kompilieren aus dem XAML erzeugt wird. Dementsprechend muss dieses XAML angepasst werden um dem Compiler mitzuteilen von welcher Klasse geerbt werden soll.

<src:AbstractWindow x:Class="ResiWriter.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:src="clr-namespace:ResiWriter.UI"
        Title="ResiWriter" Height="480" Width="800">
        <Grid></Grid>
</src:AbstractWindow>

Wichtig ist hier, dass der Knoten Window durch src:AbstractWindow getauscht wird. Damit der Compiler auch weiß aus welchem Namespace AbstractWindow stammt wird zusätzlich das Attribut src eingefügt: xmlns:src=”clr-namespace:ResiWriter.UI”

/bin/false und vsftpd

21. Oktober 2013 ⋅ Geschrieben von Martin ⋅ Keine Kommentare

Wenn ein User Account die Shell /bin/false zugewiesen bekommt hat er keinen Zugriff mehr auf die Shell, was sich zum Beispiel bei einem File Server anbietet, auf dem User selbst quasi keine Rechte haben.

chsh -s /bin/false USER

Nutzt man nun diesen User Account zur Authentifizierung am vsftpd so schlägt jeder Login fehl, da vsftp eine gültige Shell verlangt.

Um dies zu umgehen kann man in der Konfiguration von pam.d die Überprüfung auf eine gültige Shell exklusiv für vsftpd abschalten:

nano /etc/pam.d/vsftpd

# Standard behaviour for ftpd(8).
auth    required        pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed
 
# Note: vsftpd handles anonymous logins on its own. Do not enable pam_ftp.so.
 
# Standard pam includes
@include common-account
@include common-session
@include common-auth
#auth   required        pam_shells.so

Die letzte Zeile wie hier auskommentieren und schon kann man sich mit dem Benutzer am FTP Server anmelden.

Multitasking in einer Web App

5. Oktober 2013 ⋅ Geschrieben von Martin ⋅ 2 Kommentare

Momentan spiele ich mit der Idee eine Art CRM Web App zu entwickeln in der Kunden, Aktivitäten, Projekte, etc. verwaltet werden können. Bei den ersten Entwürfen der GUI stellt sich mir allerdings die Frage wie man am besten Multitasking in einer Web App abbildet.

Sieht man sich bekannte Web Anwendungen an so wird man feststellen, dass alle folgendem alt bekannten Schema folgen:

  • Dokument suchen
  • Dokument öffnen
  • Dokument bearbeiten
  • Dokument schließen
  • … und wieder von vorn

Das ganze läuft in einem Browserfenster ab und es ist lediglich der momentane Arbeitsschritt durchführbar.

Beobachte ich nun aber meine Arbeitsweise so bearbeite ich allerdings meist mehrere Dokumente oder lese diese zumindest, denn den Idealfall dass man sequenziell die Arbeit verrichtet habe ich noch nie erlebt. Immer wieder kommt eine Kundenabfrage die bearbeitet werden will oder der Kollege der zwischen Tür und Angel steht benötigt jetzt eine Auskunft. Und wenn man noch tiefer geht gibt es meist auch zwischen den Akten Abhängigkeiten, zum Beispiel muss in einem älteren Dokument ein Detail nachgesehen werden um das jetzige fertigstellen zu können.

Diese Fälle sind eben in jenen klassischen Anwendungen nicht berücksichtigt, hier muss man ständig den Bearbeitungsmodus verlassen und später wiederkehren. Sehr produktiv.

Als “Workaround” können natürlich mehrere Browserfenster oder Tabs geöffnet werden, allerdings hat dies bei vielen Anwendungen markante Nachteile, zum Beispiel bleibt ein Tab der seit Stunden offen ist unaktualisiert was den unerfahrenen Nutzer verwirren kann – “dieses Ticket habe ich doch bereits geschlossen?”, diese Benutzerschicht wird auch oft verwirrt durch immer gleiche Fenster die sich nur im Detail unterscheiden – so sind Navigationselemente, Listen und Formulare über all die selben, die Seiten unterscheiden sich nur in den angezeigten Daten.
Doppelte Elemente haben auch zur Folge, dass sie Bildschirmplatz verschwenden wenn mehrere Browser Fenster nebeneinander gestellt werden um eine Mail zu auf Basis von Ticket Inhalten zu verfassen.

Auch bei WordPress wird sichtbar wie Platz verschwendet wird. Rot doppelte Elemente, Grün die der eigentliche Inhalt.Auch bei WordPress wird sichtbar wie Platz verschwendet wird. Rot doppelte Elemente, Grün die der eigentliche Inhalt.

Doch wie löst man das Problem?
Ehrlich gesagt habe ich hierfür noch keine perfekte Lösung gefunden, allerdings ziemlich gute, doch später mehr. In letzter Zeit gehen viele Anwendungen den weg, dass sie im Browserfenster weitere Fenster emulieren (emulieren soll hier ausdrücken, dass es keine nativen Fenster sind wie z.B. Popups). In diesem Bezug haben sich viele Frameworks wie z.B. ExtJS und jQuery UI etabliert die sich großer Beliebtheit erfreuen. Ich will hier aber nicht über Frameworks berichten sondern über Usability.

Fenster im Browser zu emulieren finde ich ist eine ziemlich bescheidene Idee, denn so wirft man einen ziemlich wichtigen Punkt über Bord, der sich im Web über die Jahre gehalten hat. Die Führung des Nutzers durch einen unter umständen komplexen Prozess indem man einen Weg vorgibt. Der obige sequenzielle Ansatz der von vielen Web Apps benutzt wird, hat den Charm, dass man sich stets auf eine Aktion konzentriert und diese nicht aus den Augen verliert. Fenster sorgen wieder dafür, das man wichtiges aus den Augen verliert und abgelenkt wird. Auch gestaltet sich die Führung eines Users durch verkettete Fenster schwer. Viele behelfen sich hier mit aufpoppenden Dialogen die andere Fenster blockieren um den User zu einer Aktion zu zwingen. Hier haben wir also wieder die Situtation in der der Nutzer ledigliche eine Aktion ausführen kann und diese beenden muss bevor er weitere in Angriff nehmen kann.

ExtJS Multitasking

Und was ist mit Tabs? Tabs sind in der Tat die bessere Wahl, sie zeigen immer nur eine Aktion, der Benutzer weiß aber das er zwischen mehreren wechseln kann ohne Daten zu verlieren (sehr wichtig!). Beispielsweise kann eine Email in einem Tab verfasst werden und per klick auf einen Menüpunkt öffnet sich ein weiterer mit einer Kundenliste um Informationen für die aktuelle Email zu suchen. Natürlich können viele Tabs auch sehr verwirrend werden, deshalb sollte eine durchdachte Tab Verwaltung auch Gruppierung nach Aktion oder Kunde ermöglichen.

Ein meines Erachtens nach sehr gutes Beispiel für solch eine Oberfläche ist die vom OpenExchange Projekt entwickelte OX App Suite um in diesem Artikel auch noch ein Beispiel für Experementierfreudige zu liefern. Hier dient ein einfaches Menü zur Navigation durch die verschiedenen Anwendungen und die aktuellen Aktionen werden durch Tabs abgebildet.
OX AppSuite 1

Wichtige Informationen wie Benachrichtigungen können ohne Verlassen eines Menüpunktes oder Tabs durch ein Overlay eingeblendet werden:
OX AppSuite 2

Und viele Anwendungen sind weit verschachtelt ohne auch nur einen Tab zu öffnen, das nervt den Nutzer nicht mit vielen unnötigen Tabs die er wieder schließen muss.
OX App Suite 3

Re­sü­mee
Kurz um – versucht nicht alt bewährte Window Manager im Web nachzubauen. Auch wenn es Frameworks einfach machen, denkt daran was eure Nutzer wollen – eine Übersichtliche Anwendung die einfach zu bedienen ist und Spaß macht! Diese Punkte haben dem Web zu dem verholfen was es heute ist und nicht RIAs die seit jeher versuchen den Browser als plattformunabhängige Runtime zu missbrauchen.