Kategorien

Navigation

Feeds/Meta

Blog RSS Feed
Kommentare RSS Feed

Manuel Josupeit-Walter - XING Profil
Manuel Josupeit-Walter - Amazon Wunschliste
Manuel Josupeit-Walter - XMPP (Jabber)
Manuel Josupeit-Walter - ICQ
Manuel Josupeit-Walter - Skype

Bloggeramt.de
BlogAlm
Add to Technorati Favorites

SpamPoison

josupeit.com > Weblog


C# 4.0 dynamic-Schlüsselwort

Datum:   09.12.2011, 20:56 Uhr
Kategorie:   C# und .NET im Allgemeinen Feed dieser Kategorie abonnieren
Kommentare:   0

Ich entwickle Software nun schon seit Version 1.1 des Frameworks in .net und mit jeder Version kommen mehr oder weniger bahnbrechende Sprachfeatures hinzu. Generics, Linq oder lokale Typinferenz sind nur einige Buzzwords, die mir auf die Schnelle in diesem Zusammenhang einfallen. Seit heute jedoch bin ich Fan eines weiteren Sprachfeatures, das unter anderem der Interoperabilität mit untypisierten Sprachen, wie Javascript geschuldet ist: Des dynamic-Schlüsselworts.

Mit Version 4.0 des .net-Frameworks hat Microsoft die sogenannte DLR, die Dynamic Runtime Language eingeführt und damit seine Sprachen um dynamische Typisierung erweitert. Bitte nicht falsch verstehen, Variablen, die als dynamic deklariert werden sind nicht etwa untypisiert, vielmehr geht der Compiler zunächst davon aus, dass jede beliebige Operation auf einem dynamic-Objekt ausgeführt werden kann. Etwaige Probleme entstehen erst zur Laufzeit (Duck Typing ist z.B. nicht "einfach so" möglich).

Während früher z.B. viel reflektiver Code notwendig war, um zur Laufzeit auf einem Objekt beliebigen Typs Methoden auszuführen, wird das Leben mit Hilfe des dynamic-Schlüsselwortes weitaus leichter. Das folgende Beispiel ist dem MSDN-Magazine entnommen: Dynamic .NET - Understanding the Dynamic Keyword in C# 4.0

object calc = GetCalculator();
Type calcType = calc.GetType();
object res = calcType.InvokeMember("Add", BindingFlags.InvokeMethod, null, new object[] { 10, 20 });
int sum = Convert.ToInt32(res);

Vereinfachung durch die Nutzung der dynamischen Typisierung:

dynamic calc = GetCalculator();
int sum = calc.Add(10, 20);

Interessanter finde ich jedoch, dass durch dieses Schlüsselwort auch dynamisches Dispatching ermöglicht wird! Das folgende Beispiel stellt eine Factory-Klasse dar, die verschiedene "Personen" instanziieren, und anhand mehrerer Methodenüberladungen einige Eigenschaften dieser "Personen" auf Standardwerte setzen soll. Dieses Beispiel funktioniert aufgrund des statischen Dispatchings jedoch nicht:

public static class PersonFactory {
  public static TPerson CreatePerson<TPerson>() where TPerson : Person {
    TPerson p = (TPerson)Activator.CreateInstance(typeof(TPerson), new object[] { });
    InitializePerson(p); // Wird immer die erste Überladung aufrufen
  }

  public static void InitializePerson(Person p) {
    /* Do sth. useful here */
  }

  public static void InitializePerson(Student s) {
    /* Do sth. useful here */
  }

  public static void InitializePerson(Teacher t) {
    t.Students = new List<Student>();
  }
}

public class Person {
  public string LastName { get; set; }
  public string FirstName { get; set; }
}

public class Student : Person {
  /* This is just a stub */
}

public class Teacher : Person {
  public IList<Student> Students { get; set; }
}

Da der statische Typ von p in der Methode CreatePerson der PersonFactory Person ist, wird immer die erste Überladung der InitializePerson-Methode aufgerufen werden. Das steht bereits zum Zeitpunkt der Kompilierung fest. Die einzige Möglichkeit bisher, die richte Überladung ohne dynamisches Dispatching aufzurufen, ist der Umweg über sog. Double Dispatching:

public static class PersonFactory {
  public static TPerson CreatePerson<TPerson>() where TPerson : Person {
    TPerson p = (TPerson)Activator.CreateInstance(typeof(TPerson), new object[] { });
    p.InitializePerson();
  }

  public static void InitializePerson(Person p) {
    /* Do sth. useful here */
  }

  public static void InitializePerson(Student s) {
    /* Do sth. useful here */
  }

  public static void InitializePerson(Teacher t) {
    t.Students = new List<Student>();
  }
}

public abstract class Person {
  public string LastName { get; set; }
  public string FirstName { get; set; }

  public abstract void InitializePerson();
}

public class Student : Person {
   public override void InitializePerson() {
    PersonFactory.InitializePerson(this);
  }
}

public class Teacher : Person {
  public IList<Student> Students { get; set; }

   public override void InitializePerson() {
    PersonFactory.InitializePerson(this);
  }
}

Durch verwendung des doppelten Dispatchings wird nun die korrekte Überladung der InitializePerson-Methode innerhalb der PersonFactory aufgerufen, allerdings muss ab jetzt jede von Person erbende Klasse die Methode InitializePerson mit immer dem selben Aufruf implementieren, was zu redundantem Code führt, der darüber hinaus auch noch leicht vergessen werden kann und dessen Sinn sich für Laien oft nicht erschließt. Sollte künftig jedoch eine weitere Vererbung hinzukommen, wie z.B. der SuperTeacher, der die Klasse Teacher erweitert und nicht mehr vom Compiler gezwungen wird, die Methode InitializePerson zu überschreiben, wird wiederum immer nur die Methodenüberladung für Teacher aufgerufen werden, bis die Methode auch von SuperTeacher überschrieben wird. Der Code in der Methode ist jedoch der selbe, wie der der Basisklasse Teacher. :-(

Die Lösung für dieses Dilemma ist das dynamic-Schlüsselwort, denn dadurch wird erst zur Laufzeit und nicht bereits bei der Kompilierung entschieden, welche Methode aufgerufen wird:

public static class PersonFactory {
  public static TPerson CreatePerson<TPerson>() where TPerson : Person {
    dynamic p = Activator.CreateInstance(typeof(TPerson), new object[] { });
    InitializePerson(p); // Wird die beste Überladung aufrufen!!
  }

  public static void InitializePerson(Person p) {
    /* Do sth. useful here */
  }

  public static void InitializePerson(Student s) {
    /* Do sth. useful here */
  }

  public static void InitializePerson(Teacher t) {
    t.Students = new List<Student>();
  }
}

public class Person {
  public string LastName { get; set; }
  public string FirstName { get; set; }
}

public class Student : Person {
  /* This is just a stub */
}

public class Teacher : Person {
  public IList<Student> Students { get; set; }
}

Fertig. Geil! 8-)

Downloads funktionierten nicht

Datum:   07.10.2011, 14:19 Uhr
Kategorie:   Privat Feed dieser Kategorie abonnieren
Kommentare:   0

Da denkt man, man klickt sich einmal durch den gesamten Blog, aber pustekuchen: Trotzdem ist durch den Serverumzug offenbar was kaputt gegangen: Die Downloads. Wie dem auch sei: Jetzt sollte wieder alles laufen. Vielen Dank an denjenigen, der unaufhaltsam versucht hat, einen Download nach dem nächsten zu starten. Ich hab's nämlich nur wegen meiner Statistiksoftware Piwik gemerkt. ;-)

2-Klick Button für mehr Datenschutz

Datum:   07.09.2011, 12:41 Uhr
Kategorie:   HTML, CSS und Web Feed dieser Kategorie abonnieren
Kommentare:   0

Soziale Netzwerke boomen, wie nie zuvor, die allseits bekannten und viel umstrittenen Facebook "Like"-Buttons finden sich längst nicht mehr nur auf Blogs von Technik-Freaks, sondern auch auf den Webseiten seriöser Unternehmen, Twitter und Google-Buttons sind oft ebenfalls vorhanden:

Facebook "Like"-Button auf derwesten.de Facebook "Like"-Button auf spiegelonline.de Facebook "Like"-Button auf stern.de Twitter und Google-Button auf sueddeutsche.de

Wieso aber sind sie aus Datenschutzsicht denn so brisant? Die Erklärung ist einfach: Diese Buttons werden technisch gesehen so in die Internetseiten eingebettet, dass der Browser selbst, also der Internet Explorer, Mozilla Firefox oder Opera die Inhalte von den Servern der entsprechenden Netzwerke anfragt. Darüber gibt er zwangsläufig Informationen über Sie an die Betreiber weiter:

Diese Informationen werden zwar generell an jeden Server gesendet, von dem Sie eine Internetseite abrufen, es handelt sich also nicht um eine Hackerkunst der Netzwerkbetreiber, der Knackpunkt ist jedoch, dass diese Server ohne Ihr Einverständnis kontaktiert werden und Sie keine Gelegenheit haben, der Übermittlung zu widersprechen. Wenn Sie also das Onlineportal des Sterns aufrufen, sendet der Browser bereits beim Aufruf auch Daten an Facebook:

GET / HTTP/1.1
Host: www.stern.de
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0.2) Gecko/20100101 Firefox/6.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive

GET /plugins/likebox.php?href=http%3A%2F%2Fwww.facebook.com%2Fstern&width=300&colorscheme=light&show_faces=true&border_color&stream=false&header=false&locale=de_DE&height=256 HTTP/1.1
Host: www.facebook.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0.2) Gecko/20100101 Firefox/6.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Referer: http://www.stern.de/
Connection: keep-alive

Wenn Sie nun vor dem Aufruf der Internetseite darüber hinaus noch bei Facebook eingeloggt waren, wird auch diese Information übertragen und der Betreiber, in diesem Fall Facebook hat die Möglichkeit, Ihr Surfverhalten direkt zu Ihrem Benutzerkonto zuzuordnen.

 

Abhilfe durch 2-Klick Button

Seit ca. einer Woche ist der sogenannte 2-Klick Button der Heise Medien Gruppe "auf dem Markt". Dieser Knopf ist genauso genial, wie einfach und offengestanden versteh' ich als Informatiker den Hype nur bedingt, weil es sich dabei wirklich um keine große Sache handelt. Bei diesen Knöpfen handelt es sich im Wesentlichen nur um Grafiken, die den eigentlichen Quellcode, der normalerweise zur Einbettung der original Schaltflächen von Facebook, Twitter, Google und Co. notwendig wäre, erst dann der Internetseite hinzufügen, wenn sie geklickt werden. Dabei ersetzt sich dann der entsprechende Knopf durch sein "nach Hause funkendes" Pendant. Man muss die eigentliche Funktion also durch den ersten Klick sozusagen "scharf" schalten. Im Zuge dessen werden also beim initialen Seitenaufruf, beispielsweise von heise.de, zunächst einmal nur die Grafiken und der Programmcode zur Benutzung der Knöpfe von den Servern der Heise Medien Gruppe geladen. Informationen, die Sie im Zuge dieser Anfrage über sich preisgeben, geben Sie sowieso wissentlich durch den Aufruf der Seite selbst über sich preis, oder nehmen es zumindest billigend in Kauf. Erst, wenn Sie also die Knöpfe zum ersten Mal klicken, werden diese Informationen auch an Facebook & Co. gesendet. Also: Klarer Daumen hoch für die IT Jungs von Heise! Dass Facebook die Sache stinkt und offenbar ein großes Interesse an diesen Daten hegt, zeigen übrigens auch die Reaktionen auf den Button...

 

Screenshot der 2-Klick Knöpfe der Heise Medien Gruppe

 

Der Code für die Schaltflächen wird mittlerweile übrigens unter einer freien Lizenz (auch zur kommerziellen Nutzung) zum Download angeboten und wurde auch bereits in Plugins für diverse Blog und Content-Management Systeme gegossen. Grund genug, um genügend Druck auf die Seitenbetreiber auszuüben, die Dinger endlich einzubauen!

Piwik Opt-Out IFrame

Datum:   03.09.2011, 17:07 Uhr
Kategorie:   HTML, CSS und Web Feed dieser Kategorie abonnieren
Kommentare:   0

Puh, endlich wieder bloggen. Nachdem ich die Seite hier auf meinen eigenen Server umgezogen habe, konnte ich anfangs keine Artikel posten. Damit ist jetzt Schluss, denn hier geht's gleich weiter. ;-) Nachdem Google Analytics ja seit geraumer Zeit bzgl. geltenden Datenschutzes in Kritik geraten ist1, 2, 3, hatte ich zunächst keine Software zur Erhebung von Statistiken im Einsatz. Nun habe ich mich jedoch für Piwik entschieden und es anhand des Blogeintrages von Daniel Weihmann datenschutzkonform konfiguriert. Dabei habe ich auch gleich das Opt-Out IFrame im Impressum eingebunden, durch das Benutzer dieses Blogs der Erhebung von Statistiken widersprechen können.

Bedauerlicher Weise passt der Inhalt des Frames layout-technisch garnicht zum Look-and-Feel dieses Blogs und ich habe mich gefragt, wieso man dort kein eigenes Stylesheet einbetten kann. Gut, es gibt hier und da Blogeinträge, die beschreiben, dass man ja eine Referenz im Template setzen könne, allerdings gilt das dann global. Für alle, die Piwik also für mehrere Webseiten einsetzen, ist das keine Lösung. Glück, dass Piwik die Template-Engine Smarty verwendet, denn so kann man das Opt-Out Template erweitern, sodass dem IFrame ein CSS direkt übergeben werden kann:

 

Original Template plugins/CoreAdminHome/templates/optOut.tpl

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
        <head>
                <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
                <meta name="robots" content="noindex, nofollow" />
        </head>
        <body>
                {if !$trackVisits}{'CoreAdminHome_OptOutComplete'|translate}
                <br/>
                {'CoreAdminHome_OptOutCompleteBis'|translate}
                {else}
                {'CoreAdminHome_YouMayOptOut'|translate}
                <br/>
                {'CoreAdminHome_YouMayOptOutBis'|translate}
                {/if}
                <br/><br/>
                <form method="post" action="?module=CoreAdminHome&amp;action=optOut{if $language}&amp;language={$language}{/if}">
                        <input type="hidden" name="nonce" value="{$nonce}" ></input>
                        <input type="hidden" name="fuzz" value="{$smarty.now}"></input>
                        <input onclick="this.form.submit()" type="checkbox" id="trackVisits" name="trackVisits" {if $trackVisits}checked="checked"{/if}></input>
                        <label for="trackVisits"><strong>
                        {if $trackVisits}{'CoreAdminHome_YouAreOptedIn'|translate} {'CoreAdminHome_ClickHereToOptOut'|translate}
                        {else}{'CoreAdminHome_YouAreOptedOut'|translate} {'CoreAdminHome_ClickHereToOptIn'|translate}{/if}
                        </strong></label>
                </form>
        </body>
</html>

Angepasstes Template

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
        <head>
                <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
                <meta name="robots" content="noindex, nofollow" />
                {if isset($smarty.request.css)}
                <link rel="stylesheet" type="text/css" href="{$smarty.request.css}" />
                {/if}
        </head>
        <body>
                {if !$trackVisits}{'CoreAdminHome_OptOutComplete'|translate}
                <br/>
                {'CoreAdminHome_OptOutCompleteBis'|translate}
                {else}
                {'CoreAdminHome_YouMayOptOut'|translate}
                <br/>
                {'CoreAdminHome_YouMayOptOutBis'|translate}
                {/if}
                <br/><br/>
                <form method="post" action="?module=CoreAdminHome&amp;action=optOut{if $language}&amp;language={$language}{/if}">
                        <input type="hidden" name="nonce" value="{$nonce}" ></input>
                        <input type="hidden" name="fuzz" value="{$smarty.now}"></input>
                        {if isset($smarty.request.css)}
                        <input type="hidden" name="css" value="{$smarty.request.css}"></input>
                        {/if}
                        <input onclick="this.form.submit()" type="checkbox" id="trackVisits" name="trackVisits" {if $trackVisits}checked="checked"{/if}></input>
                        <label for="trackVisits"><strong>
                        {if $trackVisits}{'CoreAdminHome_YouAreOptedIn'|translate} {'CoreAdminHome_ClickHereToOptOut'|translate}
                        {else}{'CoreAdminHome_YouAreOptedOut'|translate} {'CoreAdminHome_ClickHereToOptIn'|translate}{/if}
                        </strong></label>
                </form>
        </body>
</html>

 

Was jetzt noch zu tun ist, ist dem IFrame die Url zum Stylesheet zu übergeben. Aber Vorsicht: Die Url muss ensprechend kodiert sein (zum kodieren eignet sich bspw. der URL Encoder von hier). Im Falle dieses Blogs lautet die URL zum Stylesheet http:// www.josupeit.com/css/piwik.css und das entsprechend kodierte Pendant also http%3a%2f%2fwww.josupeit.com%2fcss%2fpiwik.css. Der IFrame-Code ändert sich also wie folgt:

<iframe src="http://vps1.josupeit.com/piwik/index.php?module=CoreAdminHome&amp;action=optOut&amp;language=de&amp;css=http%3a%2f%2fwww.josupeit.com%2fcss%2fpiwik.css" frameborder="no" height="200px" width="600px"></iframe>

Viel Spaß. ;-)


1 Google Analytics (Wikipedia)
2 Warum Google Analytics in Deutschland illegal ist - Golem (Golem)
3 Datenschützer bricht Verhandlungen über Google Analytics ab (Heise Online)

 

Messung des Einflusses von Aspektorientierung auf die Entwicklungszeit

Datum:   23.06.2011, 15:20 Uhr
Kategorie:   Informatik und Technik Feed dieser Kategorie abonnieren
Kommentare:   0

So, jetzt wo seit einiger Zeit das Ergebnis meiner Bachelorarbeit vorliegt, stelle ich sie, wie bereits meine übrigen Ausarbeitungen, natürlich zum Download zur Verfügung. Die Arbeit trägt den Titel "Messung des Einflusses von Aspektorientierung auf die Entwicklungszeit - Eine Experimentwiederholung mit zusätzlicher Analyse von Pointcut- und Adviceentwicklungszeiten" und befasst sich mit einem Vergleich der Zeit, die Softwareentwickler benötigen, um objektorientierten Quellcode mit Java-Bordmitteln zu entwickeln und der Zeit, die nötig ist, um das gleiche Problem mit der aspektorientierten Spracherweiterung AspectJ zu lösen.

Bei der Arbeit handelt es sich um eine Bachelorarbeit im Studiengang Angewandte Informatik - Systems Engineering am Institut für Informatik und Wirtschaftsinformatik der Universität Duisburg-Essen.


[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13]