Archiv

Artikel getaggt mit ‘Beschleuniger’

Buch-Rezension zu “Build Awesome Command-Line Applications in Ruby”

Build Awesome Command-Line Applications in Ruby: Control Your Computer, Simplify Your Life” von David Copeland erschien im März 2012 bei The Pragmatic Programmers. Anwendungen für die Kommandozeile zu schreiben scheint in Zeiten von HTML 5 und Cloud Computing ein sinnloser Zeitvertreib zu sein. Dem ist aber nicht so.

Will man seine täglichen Arbeiten automatisieren und Abläufe vereinfachen sind Kommandozeilenprogramme mit einer ganz spezifischen Aufgabe von grossem Wert. Das einfache Interface und der Verzicht auf ein GUI ist da kein Nachteil, sondern ein Motivator um noch mehr zu automatisieren.

 

2 Tätigkeiten als Ausgangspunkt

Copeland steigt mit 2 alltäglichen Aufgaben ins Thema Kommandozeilenprogramme ein:

  1. Ein Backup-Tool für MySQL
  2. Eine ToDo-Verwaltung

Beide Aufgaben sind schon in unzähligen Büchern erklärt worden und so kann man sich eine grosse technische Einführung ersparen. Die Seiten werden stattdessen für ein genaues ausleuchten der unterschiedlichen Aspekte verwendet. Beim Backup-Tool liegt der Schwerpunkt in der Konfigurierbarkeit während es bei der ToDo Anwendung mehr um die Benutzerführung geht.

Im Verlauf des Buches werden die beiden Anwendungen ständig ausgebaut. Man erfährt dabei die Motivation hinter vielen Kommandozeilenprogrammen der UNIX-Plattformen, wieso diese so gut zusammenarbeiten und welche Erweiterungsmöglichkeiten sich für eigene Werkzeuge bieten.

 

Gute Werkzeuge erstellen

Was macht ein gutes Werkzeug aus? Und worauf soll man achten? Obwohl jeder Entwickler hier wohl unterschiedliche Schwerpunkte setzt ist die Auflistung von David Copeland mehr als nur ein guter Start. Seine Anforderungen an ein gutes Werkzeug sind:

  • löst ein klar definiertes Problem
  • ist einfach zu verwenden
  • unterstützen den Benutzer
  • arbeitet mit anderen Anwendungen zusammen
  • stehen Gelegenheitsnutzern nicht im Weg
  • ist einfach zu konfigurieren
  • lässt sich leicht verteilen
  • kann ohne grossen Aufwand erweitert werden

Zu all diesen Punkten wird gezeigt wie man diese meist mit geringem Mehraufwand erfüllen kann. Seine Tipps helfen einem dabei nicht jedes Mal von vorne beginnen zu müssen. Und oft sind es nur ganz kleine Dinge wie ein passender Kommentar in der Hilfe der einem später unzählige Stunden an Arbeit ersparen kann.

 

Selber bauen mit Methadone

Hat man erst einmal die Möglichkeiten kennen gelernt möchte man wohl selber anfangen so hilfreiche Anwendungen für die Kommandozeile zu schreiben. Damit man sich auf die interessanten Teile konzentrieren kann schrieb Copeland das Gem Methadone. Dies lässt sich wie alle anderen Gems einfach installieren und kann sogleich für eine neue Anwendung verwendet werden:

gem install methadone
methadone newgem

Mit dem zweiten Befehlt wird das Grundgerüst für die eigene Anwendungen erstellen. Neben allen Abhängigkeiten für die testgetriebene Entwicklung wird auch gleich die gewählte Lizenz hinterlegt und alles zum paketieren vorbereitet. Die detaillierte Anleitung mit allen Optionen findet sich auf der Projektseite von Methadone.

 

Fazit

David Copeland liefert mit seinem Buch praxisbezogene Tipps um alltägliche Aufgaben mit Ruby zu automatisieren. Abgesehen von ein wenig Ruby wird kaum Wissen vorausgesetzt und alles kompakt aber verständlich erklärt.

Beim realisieren eigener Kommandozeilenanwendungen ist das Buch ein gutes Nachschlagewerk und hat mir schon oft geholfen. Ich kann dieses Buch daher ohne Vorbehalte weiterempfehlen.

 

Zum Buch

Build Awesome Command-Line Applications in Ruby: Control Your Computer, Simplify Your Life” von David Copeland, 2012 The Pragmatic Programmers, ISBN 978-1-9343-5691-3, 224 Seiten, Englisch

Kategorien:Ruby, webRead, webRuby Schlagworte: , ,

MiniProfiler für Ruby

MiniProfiler ist ein äusserst hilfreicher Profiler für Webanwendungen, den ich hier schon vorgestellt habe. Hat man sich erst einmal an den immer verfügbaren Profiler gewöhnt will man nicht mehr ohne dieses Werkzeug entwickeln. Und man will es auch für alle anderen Plattformen nutzen.
Wie sich zeigt geht dies nicht nur mir so. MiniProfiler wurde auf Ruby portiert und bietet einem dort den gleichen Funktionsumfang.

 

Installation und Konfiguration

Die Installation und Konfiguration ist unter Ruby deutlich einfacher als in .Net. Es genügt das Gemfile seiner Rails-Anwendung um einen Eintrag zu Miniprofiler zu ergänzen:

gem 'rack-mini-profiler'

Nach einem bundle install kann man die Anwendung starten und MiniProfiler sofort nutzen:

Will man wissen wie viel Zeit man für eine Methode benötigt übergibt man diese in einem Block an MiniProfiler:

  def index
    Rack::MiniProfiler.step("fetch items") do
      @items = Item.all
    end 
    ....
  end

Die Auswertung unterscheidet sich nicht gross von der aus .Net bekannten Darstellung:

 

MiniProfiler in der Produktion

Standardmässig wird die Rack-Middleware nur in der Entwicklungsumgebung aktiviert. Da Rails in diesem Modus keine Optimierungen macht variieren die Werte recht stark. Dieses Problem lässt sich lösen in dem man MiniProfiler auch in der Produktion aktiviert.

Dazu erweitert man am besten die Datei application_controller.rb um einen Before-Filter:

before_filter :miniprofiler

private
def miniprofiler
  Rack::MiniProfiler.authorize_request 
  # Optional mit Einschränkung der Sichtbarkeit: 
  # if user.developer?
end

 

Fazit

Mit dem portierten MiniProfiler kann man die unter .Net schätzen gelernten Möglichkeiten auch für Rails-Anwendungen nutzen. Die Konfiguration ist durch die Implementierung als Rack-Middleware sogar noch einfacher als im Original. Somit gibt es keinen Grund auf MiniProfiler zu verzichten nur weil man Rails nutzt.

Kategorien:Ruby, webRuby Schlagworte: ,

Exif Informationen auslesen leicht gemacht

Ich wollte vor kurzem wissen welche meiner Ferienfotos über GPS-Informationen verfügen. Meine Kamera speichert mit den Bildern sehr viele Metadaten ab, darunter auch der Standort an dem ein Foto aufgenommen wurde. Diese Metadaten werden im Exif-Format in den Header des jeweiligen Bildes gespeichert.

Jeder bessere Bildbetrachter erlaubt einem diese Informationen abzurufen. Allerdings nur Bild für Bild, was bei einer grösseren Menge nicht wirklich praktikabel ist. Es musste also eine andere Lösung her.

 

Ein Ansatz mit Ruby

Eine kurze Suche genügte um ein Gem fürs Auslesen von Exif-Informationen zu finden. Exifr liefert all die von mir benötigten Informationen und verfügt erst noch über eine sehr einfache API. Die Installation geht wie üblich über RubyGems:

gem install exifr

Um meine Bilder auszulesen benötigte ich nun nur noch ein kleines Script rund um den Aufruf von Exifr. Dieses Script sollte über alle übergebenen Dateien iterieren und im Falle eines JPEG-Bildes die GPS-Informationen herauslesen. Der dazu notwendige Code fiel sehr einfach aus:

#!/usr/bin/ruby
# encoding: utf-8

require 'exifr'

ARGV.each {|arg|
  next unless arg.downcase.end_with? "jpg"
           
  exif =  EXIFR::JPEG.new(arg)
  if(exif.gps)
    puts "%s [%s %s]" % [arg, exif.gps.latitude, exif.gps.longitude]
  else
    puts "%s no GPS info" % arg
  end
}

Ein Aufruf des Scripts genügt die von mir benötigte Auflistung zu erhalten:

$ ./extract_gpsinfo.rb IMAGES/USA_2012_00_0*
IMAGES/USA_2012_00_01.jpg no GPS info
IMAGES/USA_2012_00_02.JPG [21.548169166666668 -158.24109055555556]
IMAGES/USA_2012_00_03.JPG [36.51571472222222 -111.59166611111112]
IMAGES/USA_2012_00_04.JPG [39.81834583333334 -77.23305416666666]
IMAGES/USA_2012_00_05.JPG no GPS info

 

Ausbaumöglichkeiten

Mir gefällt an diesem Ansatz mit wie wenig Aufwand auch andere Felder ausgelesen werden können. Um Beispielsweise das Aufnahmedatum der Bilder auszugeben genügt diese Erweiterung:

ARGV.each {|arg|
  next unless arg.downcase.end_with? "jpg"
           
  exif =  EXIFR::JPEG.new(arg)
  puts "%s %s" % [arg, exif.date_time_original]
}
./extract_gpsinfo.rb IMAGES/USA_2012_00_0*
IMAGES/USA_2012_00_01.jpg 
IMAGES/USA_2012_00_02.JPG 2012-05-17 00:29:52 +0200
IMAGES/USA_2012_00_03.JPG 2012-05-25 17:37:10 +0200
IMAGES/USA_2012_00_04.JPG 2012-06-06 12:17:03 +0200
IMAGES/USA_2012_00_05.JPG 2012-06-25 12:43:44 +0200

 

Fazit

Exifr macht es einem sehr einfach um mit Ruby Exif-Informationen aus Bildern auszulesen. Für meinen Einsatzzweck fand ich mit diesem Gem eine sehr einfache und gut funktionierende Lösung.

 

Kategorien:Ruby, webRuby Schlagworte: ,

Windows virtualisieren leicht gemacht

14. August 2012 1 Kommentar

Das Release von Visual Studio 2012 steht unmittelbar bevor. Und Windows 8 kommt auch schon bald. Bei all den Updates fragt man sich schnell einmal: Funktioniert nach dem Update alles so gut wie jetzt? Laufen meine Templates noch? Sind alle nötigen Erweiterungen bereits portiert? Oder muss ich mich erst noch mit Kinderkrankheiten herumschlagen?

Wie toll wäre es wenn man gefahrlos all die neuen Versionen testen könnte. Geht nicht? Zu aufwändig? Nicht wenn man seinen Entwickler-PC virtualisiert.

 

Disk2vhd macht es möglich

Das kleine Werkzeug Disk2vhd von Sysinternals hat sich für meinen Bedarf als äusserst nützlich erwiesen. Nach dem herunterladen genügt es die *.exe Datei zu starten und schon steht man vor einem sehr einfachen Dialog:

Bei „VHD File name“ gibt man die Datei an, in die das Abbild der Harddisk geschrieben werden soll. Die ausgewählten Partitionen werden durch einen Klick auf „Create“ kopiert. Die Daten werden beim Schreiben auch gleich komprimiert, wodurch man deutlich weniger Speicherplatz benötigt als die Originalfestplatten füllen.

 

VHD Datei einbinden

VHD als Dateiformat wird mittlerweile von recht vielen Virtualisierungslösungen unterstützt. Ich selber nutze VirtualBox, wo ein Einbinden ebenfalls ohne Konvertierung möglich ist.

Um das gerade erzeugte Image zu nutzen erzeugt man eine neue virtuelle Maschine. Im Dialog zur Virtuellen Festplatte kann man die VHD-Datei auswählen. Hat man alle weiteren Angaben ausgefüllt speichert man die Einstellungen und startet die virtuelle Maschine.

Wenn alles ohne Fehlermeldung funktionierte hat man nun seine gewohnte Umgebung in einer virtuellen Maschine. Einem testen des neuen Visual Studio oder eines anderen Produktes steht so nichts mehr im Weg.

 

Fazit

Mit Hilfe von Disk2vhd kann man in sehr kurzer Zeit ein Abbild seines Computers erzeugen und in einer virtuellen Maschine laufen lassen. Neue Versionen und Bugfixes lassen sich so testen ohne dass man seine Umgebung einem Risiko aussetzt.

Mir gefällt an diesem Ansatz vor allem der geringe Aufwand. Wenn es so einfach geht macht man dies auch. Und als Nebeneffekt kann man die VHD-Datei auch für einen Restore nutzen, sollte man seinen PC doch einmal neu installieren müssen.

Kategorien:.Net, webDotNet Schlagworte: ,

SWT: GUI bei langen Aktionen nicht einfrieren lassen

26. November 2011 2 Kommentare

Länger dauernde Aktionen sollten nie im GUI-Thread laufen. Dies gilt auch für SWT, der GUI-Bibliothek von IBM/Eclipse für Java. Allerdings gibt es bei SWT einige Punkte zu beachten, ohne die ein Umbau schnell sehr mühsam werden kann.

 

Ausgangslage

Bei den meisten Erklärungen zu SWT wird im SelectionListener eines Knopfes alle Logik eingebaut, die beim Klick darauf ausgeführt werden soll. So lange die daraus resultierenden Aktionen schnell verarbeitet werden können ist dagegen auch nichts einzuwenden.

Dauert es aber länger friert einem sehr schnell das GUI ein. Je nach PC variieren die Auswirkungen von einem flackern der Anzeige bis zu kompletten Blockieren der Anwendung. Der Code wird in so einem Fall wohl meist so aussehen:

workButtonSlow.addSelectionListener(new SelectionAdapter() {
	public void widgetSelected(SelectionEvent arg0) {
		progress.setSelection(0);
		workButtonSlow.setEnabled(false);
		
		// simuliert lange dauernde Aktion
		for (int i = 0; i < 100; i++) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				System.out.println(e.getMessage());
			}
			progress.setSelection(progress.getSelection() + 1);
		}

		workButtonSlow.setText("Thread beendet");
		workButtonSlow.setEnabled(true);
	}
});

 

Lösung: Threads und asyncExec

Nach einigen Anläufen bin ich bei Threads und einer Synchronisierung des GUI über asyncExec gelandet. Die lange dauernden Aktionen werden in einen eigenen Thread ausgelagert und im SelectionListener nur noch gestartet. Die Verarbeitung erfolgt so losgelöst vom GUI-Thread und behindert das Neuzeichnen der Oberfläche nicht – dies genügt damit die Anwendung viel reaktiver erscheint.

Da man nun während der Ausführung der Aktion weiterarbeiten kann, steht man unter Umständen vor neuen Problemen. Falls die gleiche Aktion nicht noch einmal parallel dazu gestartet werden darf, muss man dies nun explizit verhindern. Je nach Anwendung genügt es den entsprechenden Knopf beim Start des Arbeitsthreads zu deaktivieren und erst beim beenden wieder zu aktivieren.

Eine Implementierung mit einer eigenen Thread-Klasse kann so aussehen:

class LongRunningOperation extends Thread {
		private Display display;
		private ProgressBar progressBar;
		private Button workButton;

		/**
		 * Alles übergeben was aus diesem Thread erreichbar sein soll
		 */
		public LongRunningOperation(Display display, ProgressBar progressBar,
				Button workButton) {
			this.display = display;
			this.progressBar = progressBar;
			this.workButton = workButton;
		}

		/**
		 * Länger laufende Methode um eine Verarbeitung zu simulieren
		 */
		public void run() {
			for (int i = 0; i < 100; i++) {
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					System.out.println(e.getMessage());
				}
				progressBar.setSelection(progressBar.getSelection() + 1);
				// ProgressBar kann nur via asyncExec aktualisiert werden!
				display.asyncExec(new Runnable() {
					public void run() {
						if (progressBar.isDisposed())
							return;

						progressBar.setSelection(progressBar.getSelection() + 1);
					}
				});
			}

			// Gleiches gilt für alle GUI-Elemente
			display.asyncExec(new Runnable() {
				public void run() {
					if (workButton.isDisposed())
						return;
					workButton.setText("Thread beendet");
					workButton.setEnabled(true);
				}
			});
		}
	}

Der Knopf über den die zeitintensive Aktion gestartet wird ist wie alle anderen GUI-Elemente in SWT aber nicht direkt aus einem anderen Thread heraus veränderbar. Damit der Ausführungskontext stimmt müssen alle Veränderungen dieser Elemente als Runnable der Methode asyncExec übergeben werden. Wichtig ist das man das Display-Objekt nutzt mit dem man die Shell der Anwendung initialisiert hat.

Versucht man asyncExec zu umgehen wird SWT mit dieser Exception antworten:

Exception in thread “Thread-0″ org.eclipse.swt.SWTException: Invalid thread access

Sind alle Zugriffe entsprechend umgeformt, kann man im SelectionListener des Knopfes die Thread-Klasse starten:

		workButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent arg0) {
				progress.setSelection(0);
				workButton.setEnabled(false);
				new LongRunningOperation(s_display, progress, workButton)
						.start();
				workButton.setText("SelectionListener beendet!");
			}
		});

 

Fazit

Mit dieser Umbauarbeit kann man auch lange laufende Aktionen ausführen ohne dass einem das GUI einfriert oder an Reaktionsfähigkeit einbüsst. Dieser Ansatz ist ein wenig aufwändig, erfüllt aber seinen Zweck. (Das ganze Beispiel ist auf Github verfügbar)

Falls es einfachere Wege gibt würde ich mich über einen Kommentar freuen.

Kategorien:Eclipse, Java, webJava Schlagworte: ,
Follow

Bekomme jeden neuen Artikel in deinen Posteingang.

Schließe dich 175 Followern an