Posts mit dem Label Books werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Books werden angezeigt. Alle Posts anzeigen

Montag, 11. April 2016

We Love Code! - Eine popkulturelle Ode an das Programmieren

Ich wohne schon wirklich gern in dieser Stadt Leipzig. Alles da was man so von einer Großstadt erwartet und trotzdem übersichtlich wie früher auf dem Dorf. Und so kam es auch, dass mir "We Love Code! - Das kleine 101 des Programmierens" in die Hände fiel. "Da hat Natalie mit geschrieben - du weißt schon, meine ehemalige Mitbewohnerin" sagte unser Schlafgast.

Macht Spaß zu Lesen (Bildquelle)

Ja, ich konnte mich erinnern. Social Media, HTML, CSS, später Ruby und viel Neugier auf den Rest. Drei Jahre später legen die Code Girls Natalie Sontopski und Julia Hoffmann einen angenehm leichtgewichtigen Einstieg in die Welt der Programmierung vor.

Die beiden Autorinnen nehmen den Leser bei der Hand und erklären mit Verve dass man (wie auch ich) eine Mathe-Niete sein kann und trotzdem ein passabler Programmierer, dass Programmiersprachen ähnlich viele Geschmacksfacetten haben wie die irdischen Variationen von Spagetti mit Tomatensoße und dass C Programmierer harte Kerle sind. Da sich mindestens 50% dieses Blogs mit mehr oder weniger obskuren C Programmiertechniken beschäftigt, fühlte ich mich zugegebener  Maßen bei letztem Punkt gebauchpinselt.

Außerdem leistet das Buch einen wichtigen Beitrag zur Idolbildung in der Geschichte bedeutender Programmier-Veteranen. Ada Lovelace, Grace Hopper (It's easier to ask forgiveness than it is to get permission) und andere bekommen extra Seiten gewidmet. Bravo. Im Pop wird fleißig zitiert und referenziert. Die dritte Generation von Joy Division T-Shirt Trägern bevölkert nun die Indie-Clubs. Höchste Zeit dass auch wir Nerds unsere Helden auf der Brust tragen, Beispiel gefällig?

Bildquelle

Und zu guter Letzt: Es handelt sich um ein schönes, aufwendig gedrucktes Buch. Wer will seinen Liebsten auch schon einen USB-Stick mit einer epub-Datei schenken? Vielleicht noch mit einem animierten GIF als Glückwunschkarte.

Es gibt Dinge die kann man nicht digitalisieren. Ein schönes Buch gehört dazu. (Bildquelle)

Fazit: Falls ihr Partner, Freunde oder Verwandte habt die die Welt in der ihr lebt faszinierend finden aber eigentlich nix davon verstehen: We Love Code! ist ein empfehlenswerter Einstieg, am Besten direkt vom Verlag gekauft.

Freitag, 27. November 2015

Thoughts On "SE-Radio Episode 242: Dave Thomas on Innovating Legacy Systems"

In episode 242 Software Engineering Radio interviewed Dave Thomas about how to deal with legacy systems. I liked the show so much that I had to do a sketchnote:

Controversial And Very Inspiring At The Same Time - SE Radio 242 with Dave Thomas

Actually I am a faithful follower of Working Effectively With Legacy Code : isolate the piece of code you want to change (dependency breaking), write tests for it and then modify the code using TDD. Over time I got quite good at it - even in C. However, it's a lot of effort - even when you're trained.

Dave sayed "Unit tests are a waste of time, focus on acceptance test" (end-to-end tests). The problem with end-to-end tests is that they are even harder to setup. Instead of mocking the objects around you, you have to provide all the external dependencies or at least good replacements:  test databases, test middleware, test clients...
Anyway, once you've managed all that and wrote your first end-to-end test, things are getting easier a lot. Covering "unhappy paths" with tests is now actually quite simple - drop a central database table, switch of the middleware, send faulty messages to your application and check what's going on.

With all this virtualization (docker as latest hype) and infrastructure as code (Puppet, Chef, ...) we now have got good tools to write end-to-end tests which are repeatable, automated and maintainable.
Surely this was not as simple in 2004 when "Working Effectively With Legacy Code" came out.

Dave's statements  reminded of the Golden Master approach which is quite similar. However, the initial end-to-end tests there is only meant to  provide the basic safety net towards a unit test coverage. The latter one is the actual goal of "Golden Master" testing.

So yes, maybe going from outside to inside is nowadays a better way of creating a safety net. I am still not convinced to ditch unit testing of old code completely but this is as always something you have to try out.

Samstag, 26. September 2015

Socrates 2015 - What the f**k

I'm a IT professional for over a decade now - but I've never attended something like this before:

A colleague and me took part at the Socrates 2015 conference. It's an Open Space conference which mean there is no agenda at the beginning. Just an empty flipchart which if filled with self-proposed topics of the participants at the beginning of each conference day.
No pop star like speakers but people like you and me how admit "I am not the expert but I've done something in that field and I want to share this knowledge with you." For me this is all you need - for everything more involved there are books.

While thinking about the conference I was astonished how much I've either learned or was pushed towards something. Here is my top 5:

  1. Sketchnotes. This is for me "Doing something more with the whiteboard than the usual stuff without needing to be an artist." I believe in the area of Powerpoint spoilt organisations  it makes a huge difference to develop a topic just with a flipchart and a pen. It's amazing how much you can do. I love it.
  2. Walking Skeleton. I never heard of this topic before. It's basically an approach to build up a system not from inside out but from outside to the inside, guided by so called end-to-end tests as well as unit tests. The book to read on that topic is Growing Object Oriented Software Guided By Tests. People refer to the approach as "London School Of TDD" (the authors of that book are based in London) in contrast to the "Chicago School Of TDD" which is TDD as we know it (Kent Beck, Uncle Bob). Really interesting.
  3. Personal Kanban. I was once again pushed to think about my time management method. I attended a session about Knowledge Management but we soon found out the the key is actually Time Management. So one of the attendees offered a session about time management the next day. It all was about the guys Getting Things Done interpretation. Anyway, during the discussion I was reminded on the existence of Personal Kanban, and this is what I am trying out at the moment, all analog!. There will be a post with a nice picture somewhen later.
  4. Legacy Code Retreat. I spent quite some time wadding into muddy legacy C code. I thought I am quite good at this topic but this guy who hosted a 2 hour session an how to attack lagacy code was somewhere else. Really impressive. I've done some handson training for a Golden Master Test. Also, training people to deal with legacy code can be simplified by using Adrians work.
  5. I had a chat with somebody at dinner how was working for a software consultancy run as a cooperative. Basically, they have no boss and decide all together how they want the company to proceed. This was really thrilling, I was just about to hand in my CV but they are based in the wrong city ;-).
Overall the conference was much more than I expected. In my hometown Leipzig/ Germany there will be the Developer Open Space conference in some weeks, run also as an Open Space event - this time I plan to prepare something my self. Working title "Not Your Father's C".

Yes - there were also some hippies ;-)


Sonntag, 22. Februar 2015

Quick C Tricks - Assertions With Error Message

This quick post is the last little trick I got out of the book Patterns in C written by Adam Tornhill. The technique presents comments for assertions which also appear as an error message if failing.

Here is an example:
#include <assert.h>

int main() {
   assert(1 == 2 && "This is an error message");
}

Running the code gives the following result:

main: Assertion `1 == 2 && "This is an error message"' failed.

This trick works since the string This is an error message itself evaluates to True. The actual checking is taking place in the first part of the assertion, a second appended True does not influence this behavior.

You can argue that this is a hack (that's true) but giving the user some guidance in the event of failure is also not a bad idea.;

Mittwoch, 18. Februar 2015

Review of "Patterns in C" by Adam Tornhill

Twenty one years ago the book Design patterns : elements of reusable object-oriented software changed the way object oriented software was written. Some month back I asked myself if somebody has tried to apply those ideas to plain C. Although C has no object orientation build in, using Abstract Datatypes (ADT) it is possible and also preferable to structure C code in an object oriented manner.

My research lead me to the online book "Patterns in C" by Adam Tornhill, available as PDF or epub from leanpub.com. This book combines a couple of blog posts the author did over the course of years. Not unexpected, the book is introducing ADT in C as prerequisite for the rest of the book.

All the design patterns presented in the book share a second similarity: They all gain their flexibility through the consequent  usage of C function pointers. I admit, I did barely touch them in the past. After having read this book I still believe you should not overuse them but they give you flexibility in your programming you would not expect to find in good old C.

But let's look at the first chapter. It deals with the implementation of a state machine. The author quickly illustrates the classic approaches being simple case statements and a table based approach. He then argues that those classic approaches are not scaling to the big which lets him introduce a C take on the STATE pattern. I personally found that example rather confusing but I would consult it a second time if a state machine is on my C development agenda.

The next chapter deals with the STRATEGY pattern. This is also my favorite chapter of the book. The example given shows how a customer record can be designed leaving certain calculations interchangeable. This is a good example of how modern C can look like and something which is already in my personal tool box.

The following chapter introduces an example implementation of the OBSERVER pattern. The idea is that an object can have one or more subscribers which get informed if the internal state (e.g. measuring data) of the object changes. The subscribers can then decide what to do with this information. It turns the object communication, excuse me, I mean the ADT communication upside down from polling ("Did something change at your side?") to pushing: "Attention, something changed at my side!"

As with the STRATEGY pattern before the main ingredients for the OBSERVER chapter are ADTs and function pointers. The implementation is pleasant to work through and surprisingly straight forward.

The last pattern discussed is the REACTOR pattern. Here, an event is received and dispatched to the appropriate event handler. Although the patterns logic is simple, I had my difficulties to see that logic happening in the code. Maybe reading not only snippets but the whole example would have helped.

The book closes with a couple of C tricks of which I already posted Simulate Keyword Arguments here. This last chapter also shows my general problem with the book: it is too verbose and also trying to be too intellectual. At the end we talk about established programming conventions in the OO world and their adaption in C. This is straight forward software engineering where a Kafka quote feels a bit out of turn.

Concluding, I learned that function pointers are an important tool towards a flexible design. Together with ADTs they make the implementation of established OO design patterns possible also in C. The book itself is not an easy read, though.







Freitag, 15. August 2014

Second Status - Studying "Structure And Interpretation Of Computer Programs"

Some month ago I decided to self study the online material of the Spring 2014 course of "Structure And Interpretation Of Computer Programs" of the Berkley University.  I was actually planning to regularly post my learning status - however, I forgot to post my half time status. This might be due to a minor football (soccer) event this summer ;-)

Anyway, here is where I am:


I'm slowly creeping forward, working full time doesn't help, too. How can people organize to work on a part time Ph.D. when they have a full time job and a family?!

As the pictures above shows, the next thing is to kick off the last project which is writing a Scheme interpreter in Python. I've done some Scheme recently, I don't hate it - I feel more like in this comic which was on one of the first lecture slides introducing the Scheme topic:

Source: http://inst.cs.berkeley.edu/~cs61a/sp14/slides/24_1pp.pdf
I've never had to deal with something complex like writing an own language interpreter so I'm really looking forward to spend some time with this (last) project.

Looking at my other obligations I suppose it will be October when I'm done with the whole course. We'll see.

Samstag, 22. März 2014

Becoming a Wizard - Studying "Structure And Interpretation Of Computer Programs"

A while ago I was listening to some interview on software engineering radio. The person interviewed said that he is shocked about so many programmers nowadays haven't heard about what he believes is one of the most influential programing books ever written: "Structure And Interpretation Of Computer Programs" (SICP) - also called the wizard book:


Well - he would have been shocked by me as well. SICP is apparently one of those books which one should have read in programmers life - or better worked through. SICP is teaching not a particular programing language but how to program. It is more about the bigger picture.

The book seams to be popular in the US since many universities are using it as the basis for their own lectures. Here in Germany SICP is rather unknown.

After I got my own copy of the book I started reading. After a while I felt that I should not read but properly study this book. An Internet search brought me then to UC Berkley and their variant of the course. It is based on SICP but is using Python as teaching language (instead of Scheme in the original version).

For each term, UC Berkley is providing all study material online, including a complete set of screencasts of the lectures. For me, sitting in Germany and working full time, this is a fantastic way of participating at the lectures to a convenient time, learning at my own pace.

My personal project for the next couple of months is to finish this course, doing most of the homework and also trying to do some project work - being a proper nerd.

Since I'm not enrolled I won't earn a certificate or something similar - but my intend is to gain a broader understanding of programing - not an other piece of paper.

This will be fun :-)



Sonntag, 8. September 2013

Fazit "Software Sanierung" von Sebastian Kübeck - Teil 1c - Refactoring

Die umfangreiche Einführung des Buches "Software Sanierung" von Sebastian Kübeck muss sich natürlich auch dem Thema "Refactoring" widmen. Da ich mich in der Vergangenheit bereits intensiver mit Testgetriebener Entwicklung (TDD) beschäftigt habe, gab es in diesem Abschnitt kaum neues.

Eine Übersicht der behandelten Refactoring:
  • Umbenennen der Bezeichner (sprechende Namen für Variablen, Konstanten, Klassen...)
  • Methoden aus größerem Code-Block extrahieren
  • Methode auflösen, das Gegenteil von "extrahieren", Logik (nach Umorganisation) wieder in Ursprungsmethode zurück verschieben
  • Methode hochziehen - Verlangerung einer Methode von der Kinds- in die Elternklasse. Sinnvoll, wenn mehrere Kindsklassen die gleiche Methode nutzen.
  • Interface extrahieren - Erstellen eines neuen Interfaces und darauffolgend Ableiten der bestehenden Klasse von diesem Interface. Optional können auch Methoden der Klasse ins Interface wandern. Viele der Beispiele Im Buch beruhen auf dem Abhängigkeits-Inversions-Prinzip welches fordert, dass Klassen möglichst nicht von anderen Klassen sondern nur von deren Interfaces abhängig sein sollen. Dieses Refactoring spielt genau in dieser Liga.
  • Klasse extrahieren - aus einer Klasse eine Eltern-Klasse ableiten die optional auch Methoden  Implementierungen aus der Ursprungsklasse mitnehmen kann - ganz im Gegensatz zu Interfaces wo nur Deklarationen übernommen werden können. Letztendlich sind die beiden letzten Refactorings Alltag im Objekt-Orientierten Entwicklungsgeschäft.
Eine Gute Idee: Skizzieren von Refactorings
Da nicht immer am Anfang klar ist, was das günstigste Vorgehen ist, schlägt der Autor ein "Skizzieren" des  anstehenden Refaktorings vor: Außerhalb der Versionskontrolle können Source-Files umbenannt, umkopiert, neuangelegt werden. Es soll nicht kompilierfähiger Code herauskommen sondern eher eine Idee in welche Richtung das Refactoring getrieben werden soll.

Freitag, 23. August 2013

Fazit "Software Sanierung" von Sebastian Kübeck - Teil 1b, Entwurfsmuster

Der erste Teil des Buches "Software Sanierung" von Sebastian Kübeck beinhaltet eine umfangreiche Auswahl von Gang-Of-Four Entwurfsmustern inklusive guter Code-Beispiele. Die gewählten Patterns sind nach Ansicht des Autors "für das Sanieren" sinnvoll.

Nachdem ich auf meiner letzten Reise (nicht Urlaub) das Orginal-Gang-Of-Four Buch brav neben dem Bett liegen hatte, in der Hoffnung, dass sich Erkenntnisse daraus automatisch im Schlaf in Richtung meines Gehirns bewegen, habe ich hier die Chance ergriffen und die vorgestellten Muster im klassichen Schulprinzip durchgearbeitet. Dies sind meine Hefter-Notizen:

Abstrakte Fabrik
Klassisch wird ein Objekt mit "new" erzeugt. Eine Abstrakte Fabrik ist eine Klasse oder Interface, die mindestens eine Methode hat, die ein Objekt erzeugt.

Schablonenmethode/ Template Method
Ein Algorithmus wird in einer abstrakten Klasse definiert, wobei die Implementierung von Algorithmus-Details an Unterklassen ausgelagert wird. Zusätzlich kann die abstrakte Klasse auch noch leere Zwischenschrittsmethoden haben, die in Unterklassen optional implemenitert werden können.

Wert-Objekt
"Ein Wertobjekt ist dadurch gekennzeichnet, dass seine Identität von den Werten bestimmt wird aus denen es aufgebaut ist." Es hat keine eigene Identität. Im Buch wird noch darauf verwiesen, dass ein Kennzeichen von Java-Wertobjekten die Implementierung der Methoden "hashCode" und "equals" sind durch die der Programmierer einen Mechanismus zum Inhalts-Vergleich anbietet.
Ein Wertobjekt ist nach seiner Erstellung nicht mehr veränderbar (immutable).

Das Wert-Objekt ist nicht zu verwechseln mit dem auch in Javascript sehr populären "Data Transfer Objekt".

Null-Objekt
"Provide an object as a surrogate for the lack of an object of a given type. The Null Object Pattern provides intelligent do nothing behavior, hiding the details from its collaborators."
Im Buch wird ein Beispiel angeführt wo, abhängig von einem Konstruktor-Parameter, eine Ausgabe auf OutputStream-Objekt erfolgen soll - oder, wenn der Parameter "null" ist, anstelle dessen die Ausgabe über die Null-Objekt Implementierung von OutputStream.

Stellvertreter (Proxy)
Ein Objekt welches seine Methodenaufrufe an sein Orginal-Objekt weiterleitet. Stellvertreter und Orginal implementieren das gleiche Interface. Zusätzlich erfolgen aber noch weiter Aktionen im Stellvertreter die im Orginal nicht erfolgen.
Beispiel ist das Anklemmen von Logging. Dem Orginal-Objekt fehlt das Logging, der Stellvertreter besitzt die gleiche Signatur wie das Orginal, leitet die Methodenaufrufe auch an das Orginal weiter - aber loggt noch zusätzlich.

Adapter
Wie "Stellvertreter" allerdings underscheiden sich Methodensignatur von Orginal und Adapter Objekt. Dient als Verbindungsstück zwischen zwei verschiedenen Interfaces.

Beobachter
Häufig genutzt für Event-Handling in einer GUI. Die Beispiele im Buch haben aber eine andere Ausrichtung: Einem zu beobachtenten Objekt wird z.B. im Konstruktor ein Beobachter-Objekt übergeben. Dieser Beobachter könnte z.B. ein Logging implementieren.
An geeigneter Stelle werden dann im Orginal-Objekt die Beobachter-Methoden aufgerufen die dann z.B. zu einem Log-Eintrag führen.

Das Pattern ist praktisch für das testbar-machen von Log-Einträgen: Es gibt für das Beobachter-Objekt eine Produktiv-Implementierung, die einfach auf STDOUT schreibt und eine Test-Implementierung die sich zusätzlich das geloggte im Objekt merkt. Ein Unittest kann dann das "gemerkte" (z.B. eine Liste) vergleichen.
Dem zu beobachtenden Objekt (das mit der Fachlogik) wird dann der jeweilig passende Beobachter übergeben.

Fascade
Gang-of-Four Definition: "Biete eine einheitliche Schnittstelle zu einer Menge von Schnittstellen eines Subsystems. Die Fassadenklasse definiert eine abstrakte Schnittstelle, welche die Verwendung des Subsystems vereinfacht." (Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides: "Entwurfsmuster. Elemente wiederverwendbarer objektorientierter Software". Addison-Wesley. 1. Auflage 1996, S. 212)

Kommando
Kapsselung von Befehlen in ein Objekt. Im Buch wird ein Beispiel für einen einfachen Dateimanager gebracht. Die Hauptklasse (der FileManager) empfängt die Befehle als Arguments und ruft dann das entsprechende Kommando-Objekt auf. Die konkreten Aktionen zu einem Befehl sind im Objekt gekapselt.
Eine Erweiterung des Programmes ist einfach, es wird ein neues Kommando-Objekt angelegt (und getestet), dann wird der Hauptklasse noch das neue Objekt bekannt gegeben.

Strategie
Ein alter Bekannter im neuen Kleid, auch eine Anwendung des Abhängigkeits-Inversionsprinzips. Die Idee ist, Algorithmen die einer häufigen Änderung unterliegen via Interface zu implementieren.  und damit einfacher ausstauschbar zu machen.

Das Buch führt als Beispiel einen einfachen Passwort-Authenticator an. Die Passwort-Policy ist veränderlichen organisatorischen Regeln ausgesetzt - aus diesem Grund wird sie mittels Strategy-Pattern implementiert.
Konkret gibt es ein "PasswordPolicy" Interface welches nur die Methode "isSecure()" beinhaltet. Da die Frage "isSecure()" organisatorischen Änderungen unterworfen ist, wird die konkrete Implementierung von "PasswordPolicy" regelmäßig angepasst in dem eine neue Klasse geschrieben wird.
Die Authenticator-Hauptklasse bekommt im Konstruktor nur die jeweilig aktuelle Implementierung der Policy übergeben.

Mittwoch, 21. August 2013

Fazit "Software Sanierung" von Sebastian Kübeck - Teil 1a, Einführung und Design Prinzipien

Ohne konkrete Zahlen herauszukramen, stelle ich hier die Behauptung auf, dass ein Software Entwickler in seinem Berufsleben viel mehr mit existierendem Code arbeitet als dass er regelmäßig die berühmte "Grüne Wiese" bestellt.
 Dem Pragmatismus der Pragmatic Programmers folgend, versuche ich aus diesem Fakt eine Tugend zu machen, mit dem Ziel "Master Of Legacy Code" zu werden. Und ganz ehrlich, sich einen fremden, alten, nicht Unit-getesteten Code zu eigen machen - das ist doch im Grunde herausfordernder als immer nur ein neues Town House auf die planierte Fläche zu setzen.

Dieser Logik folgend stürzte ich mich neulich enthusiastisch auf das Buch "Software Sanierung" von Sebastian Kübeck, erschienen  2009 im mitp-Verlag. Um es vorweg zu nehmen: hiermit gestehe ich, dass in der Vergangenheit meine Unit-Tests häufig eher externe Tests waren.

Der erste Teil des Buches ist ein Crash-Kurs im benötigten Handwerkszeug:

  • Objektorientierung
  • Tests inklusive Abgrenzung der verschiedenen Test-Arten
  • Wichtige Design Patterns
  • Refactoring Patterns
  • Fehlerbehandlung (Exceptions)

Da dieses Blog mein öffentliches Gehirn sein soll, hier die Liste der Dinge, die ich als wichtig in diesem ersten Teil empfand:

Natürliche versus Künstliche Komplexität
Die natürliche Komplexität beschreibt letztendlich die Grund-Komplexität des implementierten Fachprozesses. "Der kleinstmögliche Umfang an Informationen, die notwendig sind um [ eine Problemstellung ] vollständig zu beschreiben, definiert die natürliche Komplexität des Problems."


Die natürliche Komplexität lässt sich nur verringern in dem man Features aus einer Anwendung wieder ausbaut und sie damit wieder vereinfacht.

Nun zur künstlichen Komplexität: "...der Ballast .., der nötig ist um Programme unter den gegebenen Rahmenbedingungen und mit den Kenntnissen der Programmierer zu realisieren."

Die künstliche Komplexität kann man direkt verringern, zum Beispiel durch gutes Design, Hochsprachen oder die Verwendung von Bibliotheken anstelle von eigenen Implementierungen. Ein guter Entwickler erhöht also bei einer Programmerweiterung die künstliche Komplexität nur um das wirklich notwendige Minimum - so weit zumindest die Theorie.

Sanieren statt Wegreißen
In der Einleitung werden ein paar gute Argumente für eine Sanierung bestehender Software angeführt, besonders wichtig finde ich diesen hier (in eigenen Worten):
Häufig ist die Software selbst die einzig verbliebene, aktuelle Spezifikation des Fachprozesses. Wissensträger sind teilweise nicht mehr verfügbar, die existierende Dokumentation ist lückenhaft. Allein das Programm beinhaltet das gesammelte Wissen der letzten x Jahre/ Jahrzehnte.

UML Klassendiagramme sind zwar schick aber...
...spiegeln nicht die Interaktion der Objekte wieder. Außerdem entsteht kein Programm aus einer Klassen/ Objekt-Beschreibung. Das scheint wohl noch aus der Zeit zu kommen, wo man Klassendiagramm gemalt hat und sich dann den Code per Knopfdruck generiert hat. 
Viel näher am Software-Entwicklungsprozess sind die Interaktionsdiagramme die erst später in die UML aufgenommen wurden. Das Nützlichste aus meiner Sicht ist das Kommunikationsdiagramm - letztendlich eine Formalisierung der Kästchen mit Pfeilen die man sowieso gern zur Visualisierung verwendet.

Interface-Aufteilungsprinzip
"Interfaces sollten nur so viele Methoden haben, wie für die Ausführung einer Aufgabe unbedingt nötig sind. Können zusätzliche Methoden zur Verfügung gestellt werden, sollte man das Interface aufteilen."

Liskov Substituitions-Prinzip
"If it looks like a duck, quacks like a duck, but needs batteries – you probably have the wrong abstraction" (Link)

Das Web ist voll mit Erklärungen dieses Prinzips.Grundsätzlich soll jede Erweiterung einer Klasse die Elternklasse vollständig ersetzen.

"Der Nachteil der Verletzung des Liskov-Substitutionsprinzips liegt in der Erwartungshaltung an eine Erweiterung einer Klasse. Da man dank der Polymorphie unter Umständen nur it der Elternklasse arbeitet, ohne zu wissen, dass man es eigentlich mit einer Ableitung zu tun hat, ist es äußerst unangenehm, wenn sich diese Klasse ganz anders verhält als die Elternklasse."

Für mich wird dieses Prinzip durch ein Beispiel am besten deutlich. Robert Martin hat dies sinngemäß einmal so erklärt: Mathematisch ist ein "Quadrat" ein "Rechteck". Man ist also versucht auch eine Klasse "Quadrat" von einer Basisklasse "Rechteck" abzuleiten.
Die Methoden "setX()"und "setY()" machen bei einem Rechteck durchaus Sinn - beim einem Quadrat allerdings nicht wirklich. Hier setzt der Aufruf einer Methode alle vier Seiten. Die Abstraktion "ein Quadrat ist ein Rechteck" passt hier also unter objektorientierter Betrachtungsweise schlecht.

Abhängigkeits-Inversionsprinzip
Auf diesem Prinzip bauen fast alle Refactorings des Buches auf. Es sagt aus, "dass Klassen möglichst nicht von konkreten Implementierungen anderer Klassen, sondern von deren Interfaces abhängig sein sollen".
In der Praxis bietet es sich an eine starre Kopplung z.B. an die JDBC-Klassen durch ein eigenes Interface aufzulösen, Die Produktionsimplementierung des Interfaces ist letztendlich ein Wrapper (ja, ich weiss, es heißt "Delegation") um die JDBC-Klassen.
Die Testimplementierung nutzt das gleiche Interface, emuliert aber Aktionen wie "getLastName()" mittels Hashmap.

Wenn nun der Ursprungsklasse während der Laufzeit eine andere Datenbank-Klasse mittels z.B. "setDatabase()" Methode "injiziert" wird, spricht man von "Dependency Injection".

Änderungsvektoren (einer Klasse)
Im Laufe der Zeit wird häufig eine Klasse durch verschiedene Änderungswünsche (Anforderungen) in verschiedene Richtungen getrieben. Diese verschiedenen Richtungen nennt man Änderungsvektoren.

Single-Responsibility Principle
Eine Klasse sollte nur einen dieser Vektoren implementieren. Also z.B. sich nur um Datenbankaktionen kümmern und keine Berechnungen durchführen.

Das Gleiche gilt für Methoden: checkAndStoreData() wird besser zu "checkData()" und "storeData()". Dieses Prinzip ist universell und gilt genauso für C Dateien und Funktionen.