Google-Alternativen beim Tages-Anzeiger

Der Tages-Anzeiger hat heute auch ein paar Alternativen zur Google-Suche vorgestellt.

Sie preisen diese auch als “solide Ersatzdienste, gerade für Datenschutz-sensible Nutzer.” Was dann aber Bing in dieser Auflistung zu suchen hat ist mir schleierhaft, auch wenn in der Beschreibung darauf hingewiesen wird, dass Microsoft auch Daten sammelt.

Andere Suchmaschinen sollten aus meiner Sicht in diesem Zusammenhang eher erwähnt werden, z.B. Qwant, eTools.ch, MetaGer oder Unbubble.

Über die Gründe, warum man auch einmal auf Google verzichten sollte habe ich in meinem Blog-Artikel “Ente statt Krake – Suchmaschinen-Alternativen” geschrieben.

Slippery When Wet #8: Parsing IP addresses in C#

I proudly present to you the eighth in a infinite number of posts of “Slippery When Wet.” In these posts I show you a little bastard I stumbled on.

When I was trying to read some IP addresses from a CSV file I parsed them with the method IPAddress.Parse() from the System.Net namespace. Everything worked fine up to the eighth ip address. There the Parse method threw a System.FormatException: The format of the IP address was not valid. The IP address that caused the problem looked like ‘127.000.000.008’. In my opinion this looked like a valid number, although it could be written a little bit shorter.

But Microsoft sees the world a little bit different. According to the answer by Mario Cossi on the problem description I found on social.msdn.microsoft.com this behaviour is completly valid, as all the numbers with leading zeros should be considered as octal numbers and therefore 008 is not valid, as 8 in not in the range of octal numbers. Mario writes that this is defined by standards, but does not refere to the standard where this is defined.

I did some more research but could not find the standard that describes this behaviour. What I did find were some older RFCs (like RFC 790) where IP addresses (or ranges) were written in the format with the leading zeros.

According to a wikipedia article and a therein referenced draft there is no defined standard for the textual representation of a IPv4 address.

In my opinion, the design decision of Microsoft is not the best. At least there should be a possibility to set the expected behaviour in case of a leading zero octet. Especially as the IP address 010.010.010.010 could be interpreted as 10.10.10.10 or 8.8.8.8 and you would not get an error as it would be in octal as well as in decimal a valid number.

As Microsoft did not give this possibility, according to your data you have to read, you should possibily use your own parsing method instead of the built-in one.

Zugriff auf Web und Blog jetzt auch verschlüsselt möglich

FreeSSL!

FreeSSL! Initiative bei Hostpoint

Mein Hoster Hostpoint bietet seit Ende September mit FreeSSL Verschlüsselung mit jedem Hostingpaket an. Sowohl dieser Blog als auch meine Webseite sind dadurch nun auch verschlüsselt erreichbar.

Beim Publizieren des Angebotes hat Hostpoint aber noch Entwicklungspotential. Obwohl ich dem Kundendienst vor einiger Zeit eine Anfrage gestellt hatte, ob Verschlüsselung auch bei den ‘kleineren’ Hostingpaketen möglich wäre und ich als Antwort erhielt, es sei etwas in Planung, musste ich aus den Medien von diesem neuen Angebot erfahren.

Ente statt Krake – Suchmaschinen-Alternativen

DuckDuckGo

DuckDuckGo Logo

Google weiss viel von uns. Wen wir kennen (GMail Kontakte, Google Plus), wann wir wen treffen (Google Calendar), wohin wir reisen (Google Maps), was wir suchen, z.B. weil wir etwas kaufen möchten (Google Search) und welche Seiten wir dabei besuchen (Google Analytics).

Das Problem

Bei der Suche passt Google die Resultate aufgrund unserer bisherigen Suchanfragen und unseres Surfverhaltens an. Google verkauft uns dies damit, dass es uns die für uns relevanten Resultate liefern will. Dies kann Google aber nur machen, indem es möglichst viel über uns weiss, sprich viele Daten über uns sammelt.
Neben der grossen Datensammlung über uns bekommen wir auch Suchresultate aus der Filterblase, dass heisst aufgrund unseres Surfverhaltens werden andere Meinungen in den Suchresultaten nach hinten geschoben. Dies kann z.B. bei Recherchen zu politischen Themen zu einseitiger Information führen.

Die Alternativen

DuckDuckGo.com verspricht eine Alternative zu sein. Die Suchbegriffe werden mit keinem Benutzer und auch keiner IP-Adresse verknüpft. Was gespeichert und was nicht gespeichert wird ist in der Privacy Policy detailliert beschrieben.
eTools.ch verspricht ebenfalls keine Daten zu speichern. Während DuckDuckGo neben anderen Quellen auch eigene Crawler benutzt arbeitet eTools als reine Metasuchmaschine, das heisst sie stellt die Suchanfragen (anonym) an andere Suchmaschinen (unter anderem auch DuckDuckGo) und stellt aus den Resultaten der verschiedenen Suchmaschinen eine eigene Resultatliste zusammen.
Beide Suchmaschinen empfehlen die Suche verschlüsselt zu verwenden, um das Mithören von Dritten zu verhindern oder zumindest zu erschweren. Auch bieten beide Dienste eine Android-App (DuckDuckGo Android App, eTools Android App) an, DuckDuckGo zudem auch Apps für iOS und BlackBerry (Android-App für BlackBerry 10).

Finanzierung

Beide Suchmaschinen blenden, wie Google, in den Suchresultaten Werbung ein um den Dienst zu finanzieren. Während Google aber alle möglichen gesammelten Daten verwendet benutzen DuckDuckGo und eTools nur die eingegebenen Suchbegriffe. Die Werbung wird dabei bei beiden Diensten klar gekennzeichnet.
DuckDuckGo gibt an, dass sie an den Affiliate-Programmen von eBay und Amazon teilnehmen. Das heisst, wenn man über die Suche von DuckDuckGo bei eBay bzw. Amazon das Produkt findet und kauft erhält DuckDuckGo eine kleine Provision.

Suchresultate

Google liefert nach meiner Erfahrung gerade bei Suchen im Berreich der Software-Entwicklung und des Web-Designs die für mich relevanteren Resultate, vermutlich da Google meine Anforderungen auch gut kennt. Um mich aber breit informieren zu können (z.B. politische Themen) vertraue ich eher anderen Suchmaschinen, die mich nicht so gut kennen bzw. zu kennen glauben.

Fazit

Bei der Suche gibt es, wie auch bei anderen Google-Diensten, Alternativen, man muss sie nur kennen und auch benutzen. Bei welchen Themen welche Suchmaschine die besten Resultate liefert muss aber jeder selber für sich herausfinden.

Datenschutzkonformes Teilen auf Blog und Web

Shariff Logo

Shariff Logo


Dieser Blog und die zugehörige Webseite erlauben nun das datenschutzkonforme Teilen der Beiträge über die bekannten Social-Media Plattformen. Dazu kommt das WordPress-Plugin Shariff zum Einsatz, das auf dem gleichnamigen Projekt der Computerzeitschrift c’t basiert.

Ein Shariff-Button stellt den direkten Kontakt zwischen Social Network und Besucher erst dann her, wenn letzterer aktiv auf den Share-Button klickt. Dadurch werden die Daten von Besuchern, welche den Blog oder die Webseite besuchen, nicht automatisch an die Social Networks übermittelt, wie dies bei den Standard-Buttons der bekannten Social-Media Plattformen geschieht.

Mehr Informationen sind auf der Shariff-Projektseite oder in der c’t 26/2014 zu finden.

Reflektion KW 48

Image courtesy of "marcolm" / FreeDigitalPhotos.net

Image courtesy of “marcolm” / FreeDigitalPhotos.net

Die Performance-Verbesserungen haben wir in der vergangenen Woche in sauberen Code umgesetzt und die Aufrufe an den verschiedenen Codestellen angepasst. Dabei zeigte sich wieder einmal, dass Unit Tests hilfreich und sinnvoll sind, da wir durch sie Fehler finden konnten, die ansonsten vermutlich frühestens im Endtest aufgefallen wären.

Bei einem anderen Test stellte sich heraus, dass der Algorithmus mit den Performance-Verbesserungen “richtiger” rechnete als die vorherige Implementation. Der Fehler hatte zwar keine Auswirkungen, da die Geräte den Wert nicht auswerten sollten, könnte aber bei einem Fehler auf der Geräteseite zu unerwartetem Verhalten führen.

Wie erstellt man am besten Objektkopien?

Image courtesy of "Stuart Miles" / FreeDigitalPhotos.net

Image courtesy of “Stuart Miles” / FreeDigitalPhotos.net

In einem Projekt benötigen wir nicht veränderliche Objekt-Instanzen, die aber als Kopien in eine zweite Struktur eingefügt werden sollen, wobei an einigen Properties teilweise kleine Änderungen vorgenommen werden müssen.

Die Klasse sieht etwa wie folgt aus:

public class MyClass
{
  public IContainer Container { get; private set; }
  public int ImutableValue1 { get; private set; }
  public string ImutableValue2 { get; private set; }
  public int MutableValue3 { get; private set; }
  public string MutableValue4 { get; private set; }

  public MyClass(IContainer container, int imutableValue1 = 1, string imutableValue2 = "a", int mutableValue3 = 2, string mutableValue4 = "b")
  {
    Container = container;
    ImutableValue1 = imutableValue1;
    ImutableValue2 = imutableValue2;
    MutableValue3 = mutableValue3;
    MutableValue4 = mutableValue4;
    if(container != null)
    {
      container.Register(this);
    }
  }
}

Um in die neue Struktur hinzugefügt zu werden muss der container gesetzt werden. Die anderen Werte können gesetzt werden, ansonsten wird der Default-Wert übernommen.

Für das Erstellen der Kopie gab es am Anfang folgenden Code, der im Client angesiedelt war:

public MyFunction(IContainer source)
{
  // Do some things

  foreach(var myClass in source.MyClassList)
  {
    var newClass = new MyClass(newContainer, myClass.ImutableValue1, myClass.ImutableValue2, myClass.MutableValue3, myClass.MutableValue4);
  }

  // Do some other things
}

Dieser Code beinhaltet folgende Probleme:

  • Der Client hat bzw. benötigt zu viel Wissen über die Klasse.
  • Wenn ein Property ändert oder ein neues hinzukommt müssen alle Stellen, an welchen dieser Kopier-Code vorhanden ist, angepasst werden.
  • Die Gefahr ist gross, dass bei einem neuen Property einige Stellen vergessen werden und dann in der Kopie immer der Default-Wert (und nicht der Instanz-Wert) eingetragen wird. Je nach Tests und Test-Abdeckung kann dies erst sehr spät, sprich erst im regulären Betrieb, auffallen.

Auf der Suche nach einer Lösung haben wir verschiedene Ansätze diskutiert.

Copy Constructor

Der Copy Constructor ist besonders aus der C++-Welt bekannt. Dort ist immer mindestens ein (impliziter) Copy Constructor vorhanden.

Für das oben gezeigte Beispiel würde der Copy Constructor etwa wie folgend aussehen:

public class MyClass
{
  // ...

  public MyClass(MyClass source, IContainer newContainer, int? mutableValue3 = null, string mutableValue4 = null)
  {
    Container = newContainer;
    ImutableValue1 = source.ImutableValue1;
    ImutableValue2 = source.ImutableValue2;
    MutableValue3 = mutableValue3 != null ? mutableValue3 : source.MutableValue3;
    MutableValue4 = mutableValue4 != null ? mutableValue4 : source.MutableValue4;
    if(Container != null)
    {
      Container.Register(this);
    }
  }
}

Der Client-Code würde dann so aussehen:

public MyFunction(IContainer source)
{
  // Do some things

  foreach(var myClass in source.MyClassList)
  {
    var newClass = new MyClass(myClass, newContainer);
  }

  // Do some other things
}

Clone()-Funktion

Im C#-Umfeld ist die Clone-Funktion verbreiteter als der Kopierkonstruktor, besonders durch das Interface IClonable des .NET-Frameworks. Da wir aber keine 1:1-Kopie der Objekt-Instanz erstellen wollen können wir das Interface hier nicht einsetzen.

Die Implementation unserer Clone-Funktion könnte etwa so aussehen:

public class MyClass
{
  // ...

  public MyClass Clone(IContainer newContainer, int? mutableValue3 = null, string mutableValue4 = null)
  {
    var newClass = new MyClass(
                                newContainer,
                                ImutableValue1,
                                ImutableValue2,
                                mutableValue3 != null ? mutableValue3 : MutableValue3,
                                mutableValue4 != null ? mutableValue4 : MutableValue4
                              );
    return newClass;
  }
}

Mit der Clone()-Funktion würde sich dann der Client-Code wie folgt präsentieren:

public MyFunction(IContainer source)
{
  // Do some things

  foreach(var myClass in source.MyClassList)
  {
    var newClass = myClass.Clone(newContainer);
  }

  // Do some other things
}

Factory

Die dritte Variante besteht aus einer Factory, die sich um die Erzeugung der MyClass-Instanzen kümmert. Der Konstruktor der Klasse MyClass sollte dann auf internal gesetzt werden um die Erzeugung über die Factory zu erzwingen.

public class MyClassFactory
{
  public static MyClass CreateMyClass(IContainer container, int imutableValue1 = 1, string imutableValue2 = "a", int mutableValue3 = 2, string mutableValue4 = "b")
  {
    var myClass = new MyClass(container, imutableValue1, imutableValue2, mutableValue3,  mutableValue4);
    return myClass;
  }
 
  public static MyClass CopyMyClass(MyClass source, IContainer newContainer, int? mutableValue3 = null, string mutableValue4 = null)
  {
    var newClass = new MyClass(
                                newContainer,
                                source.ImutableValue1,
                                source.ImutableValue2,
                                mutableValue3 != null ? mutableValue3 : source.MutableValue3,
                                mutableValue4 != null ? mutableValue4 : source.MutableValue4
                              );
    return newClass;
  }
}

public class MyClass
{
  // ...

  internal MyClass(IContainer container, int imutableValue1 = 1, string imutableValue2 = "a", int mutableValue3 = 2, string mutableValue4 = "b")
  {
    // ...
  }
}

Für den Einsatz der Factory wäre folgender Client-Code nötig:

public MyFunction(IContainer source)
{
  // Do some things

  foreach(var myClass in source.MyClassList)
  {
    var newClass = MyClassFactory.CopyMyClass(myClass, newContainer);
  }

  // Do some other things
}

Vergleich

Der Kopierkonstruktor und die Clone-Funktion haben beide den Nachteil, dass der Benutzer der Klasse die Varianten schnell übersehen kann. Dadurch würde trotzdem Code wie im anfänglichen Client-Code-Beispiel geschrieben. Durch das Verschieben der Erzeugungs-Funktionen in eine Factory sind die Varianten der Erzeugung schnell ersichtlich und der Benutzer kann so die passende Variante wählen.

Aus diesem Grund haben wir dann auch die Variante mit der Factory gewählt.

Reflektion KW 47

Image courtesy of "marcolm" / FreeDigitalPhotos.net

Image courtesy of “marcolm” / FreeDigitalPhotos.net

In der vergangenen Woche war ich auch direkt beim Performance-Problem eingespannt. Bei der Behebung konnten wir den Speicherverbaruch des Caches, der zur Verbesserung der Performance beigetragen hat, verkleinern ohne die Performance wieder zu verschlechtern. Auch das Management konnte sich entscheiden; es wird einen Zwischen-Release mit einigen zusätzlichen kleinen Features geben.

Wir werden nun die Verbesserungen nun in sauberen Code umsetzen und mitsamt den zusätzlichen neuen Features eines Zwischen-Release erzeugen. Dies wird dann eine intensive Testphase zur Folge haben um den Release plangemäss ausliefern zu können.

Reflektion KW 46

Image courtesy of "marcolm" / FreeDigitalPhotos.net

Image courtesy of “marcolm” / FreeDigitalPhotos.net

Auch die vergangene Woche war geprägt vom Performance-Problem. Während die Analyse und die Behebung als Prototyp gut voran kam und gute Resultate lieferte tat sich das Management schwer mit der Entscheidung, ob nun ein schneller Bugfix oder ein Zwischen-Release mit einigen zusätzlichen kleinen Features etwas später gemacht werden soll.

Währenddessen konnte ich einige kleine Tasks, die ‘vor sich hin dümpelten’, in dieser Woche abschliessen, so dass ich nächste Woche bei der Performance-Optimierung mithelfen kann.