webfactory Neuigkeiten https://www.webfactory.de/assets-version-1591090325/bundles/webfactorywebsite/img/inside-logo.png Logo Webfactory http://www.webfactory.de Zend_Feed_Writer 2 (http://framework.zend.com) /blog/ © 2020 webfactory GmbH Unser Besprechungs-Stundenplan In der webfactory haben wir über mehrere Jahre einen eingespielten Besprechungsrhythmus entwickelt. Seit Corona finden die Besprechungen als Videokonferenzen statt (via Google Meet), aber Rhythmus und Aufbau haben sich nicht geändert.

Wir beginnen mit ein paar grundsätzlichen Erkenntnissen, die dem Kalender zugrunde liegen. Anschließend stellen wir unsere internen Teambesprechungen vor: die Wochenplanung, die Daily Standups und der Wochenrückblick sowie die "Internen Baustellen" und die Geschäftsführungsbesprechungen. Im letzten Teil gehen wir dann auf unsere regelmäßigen Kundenbesprechungen ein: Den Jour Fixe in Fokusprojekten sowie die Backlog-Abstimmungen.

Die Basics: Warum machen wir das alles?

Ein paar Grundüberlegungen haben uns bei der Entwicklung des unseres Terminkalenders geleitet.

Was ist schlecht an Besprechungen?

Besprechungen kosten Arbeitszeit, die nicht für die eigentliche Tätigkeit (z. B. Programmieren) zur Verfügung steht.

Sie kosten zudem Energie und Kraft, gerade wenn sie lang sind, und sie können langweilen. Das passiert vor allem dann, wenn nicht alle Teilnehmer das gleiche Interesse an den besprochenen Themen haben, oder wenn sie inhaltlich nicht von der Stelle kommen und sich "im Kreis drehen".

Alleine die Terminfindung für eine Besprechung kann hohen Koordinationsaufwand verursachen, insbesondere wenn ein gemeinsamer Termin für viele Teilnehmer gefunden werden muss.

Was ist gut an Besprechungen?

Der Hauptvorteil an Besprechungen ist, dass persönliche Treffen der Kommunikationskanal mit der höchsten Bandbreite sind. D. h. man hört die Worte, sieht gleichzeitig Mimik und Gestik des Gegenübers und kann direkt Rückfragen stellen oder durch Mimik Feedback geben (Cockburn 2007, S. 124 f.). Das ist wertvoll, wenn mit dem Kunden gemeinsam konzeptionelle Fragen diskutiert werden oder Feedback zu Zwischenständen eingeholt wird, aber auch, wenn wir uns untereinander darüber austauschen, wie es uns geht und was uns beschäftigt.

Projektbesprechungen sind häufig auch ein Ort für zufälligen Erkenntnisgewinn: Während man über eine konkrete Frage mit dem Kunden spricht, bemerkt man, dass man eine Anforderung an anderer Stelle falsch verstanden hatte – oder findet eine viel einfachere Lösung als geplant, weil klar wird, dass eine als hart erachtete Anforderung gar nicht wichtig ist.

Besprechungen können ein schneller, einfacher Weg sein, um mehrere Personen gleichzeitig über ein Thema zu informieren. Voraussetzung dafür ist allerdings, dass das Thema für alle Teilnehmer relevant ist oder die Information kurz gehalten werden kann, sonst führen Vorträge schnell zu Langeweile und Unaufmerksamkeit.

Zu guter Letzt: Die Tatsache, dass feste Besprechungstermine vereinbart und bekannt sind, führt zu einer Reduktion der ungeplanten Kommunikation. Bevor wir unsere festen Freitagsmeetings hatten, sind Teamdiskussionen häufig spontan beim Mittagessen entstanden und haben ungeplant einen großen Teil des Nachmittags eingenommen. Jetzt kann man ein Besprechungsthema auf die Tagesordnung für das Teammeeting setzen und hat bis dahin sogar noch Zeit, eine vorbereitende E-Mail zu schreiben, was die Qualität der Besprechung verbessert. In den (Fokus-) Kundenprojekten haben wir einen ähnlichen Effekt beobachtet: Da alle wissen, dass es zweimal pro Woche feste Besprechungstermine gibt, rufen Kunden uns nicht mehr zwischendurch an, wenn sie neue Ideen fürs Projekt haben, sondern sammeln sie bis zum nächsten Jour Fixe – und umgekehrt müssen wir unsere Kunden nicht mit Anrufen unterbrechen, um Fragen zu klären.

Feste Termine, (fast) ohne Wenn und Aber

Unsere Termine haben ein festes Zeitraster. Das ist hat mehrere Vorteile:

  • Es ist sichergestellt, dass die Besprechungen stattfinden und man sie nicht "vor sich herschiebt" (z. B. einen Abstimmungstermin mit dem Kunden erst vereinbart, wenn man glaubt, ganz fertig zu sein).

  • Der Koordinationsaufwand ist minimal, weil jeder die Termine im Kalender hat und seine sonstige Planung darauf ausrichten kann.

Was für ein großer Vorteil das ist, merken wir jedes Mal, wenn jemand auf die Idee kommt, doch eine Verschiebung für einen einzelnen Termin vorzuschlagen – plötzlich fängt das Suchen im Kalender nach freien Zeitfenstern an und ein aufwändiger Abstimmungsprozess.

Aus diesen Gründen haben wir auch die Regel, dass alle grundsätzlich Termine stattfinden, egal wer anwesend ist. D. h. es kommt auch vor, dass bei unserer "interne Baustellen"-Besprechung, die wir später noch genauer vorstellen, drei Kolleg*innen in Abwesenheit der Mehrheit des Teams über das weitere Vorgehen entscheiden oder die Wochenplanung zu zweit erfolgt. Im Bezug auf die internen Baustellen und die Wochenrückblicks-Workshops haben wir uns anfangs die Frage gestellt, welche Entscheidungen das Team eigentlich treffen darf, wenn es nicht vollzählig ist. Dazu haben wir keine formale Entscheidung getroffen, aber es gab auch noch keinerlei Konflikt, weil jemand sich übergangen fühlte. Wichtig scheint uns da Fingerspitzengefühl und Rücksichtnahme im Team und auch eine gute Kommunikation über die geplanten Themen und Entscheidungen zu sein.

Eine Ausnahme gibt es: Termine, die auf Feiertage fallen, werden verschoben, und zwar von Montags auf den ersten Arbeitstag in der Woche und von Freitags auf den letzten Arbeitstag. Ob die Dienstags- und Donnerstagstermine in Kundenprojekten verschoben werden oder ausfallen, entscheiden wir mit dem Kunden je nach Projektlage.

Die Teambesprechungen in der webfactory

Nach den ganzen Vorüberlegungen werden wir jetzt endlich konkret und stellen wie versprochen unseren Besprechungs-Stundenplan vor. Wir starten mit unseren internen Besprechungen.

Unsere Arbeitswoche wird eingerahmt von zwei Besprechungen, an denen in der Regel das gesamte Team teilnimmt: Der Wochenplanung am Montag Morgen und dem Wochenrückblick am Freitag Nachmittag.

Wochenplanung

Termin: Montags 9:45 Uhr. Dauer: 15-30 Minuten

Die Wochenplanung dient dazu, uns über die Termine und Aufgaben der Woche abzustimmen und uns einen Überblick über den aktuellen Status unserer Projekte zu verschaffen. Im Zentrum der Wochenplanung steht unser unternehmensweites Kanban-Board in Trello.

Tagesordnung der Wochenplanung:

  • Ankoppeln ("Wie bin ich heute hier?"/"Wie war mein Wochenende/mein Start in die Woche?") – kurzes Statement von allen Teilnehmern. Wir haben festgestellt, dass es schön ist, wenn man weiß, ob die Kollegen gerade voller Energie sind oder einen schlechten Start hatten, und darauf Rücksicht nehmen kann.

  • Lob aus Lob-Kasten verteilen. Wir haben einen (inzwischen virtuellen) Lobkasten, in dem jeder eine Notiz hinterlässt, der sich über einen Kollegen gerade besonders gefreut hat. Montags wird das Lob dann im Kreis des Teams vorgelesen.

  • Anwesenheit/Termine durchsprechen, ggf. vervollständigen. Alle Termine, Urlaube oder sonstige Abwesenheiten haben eine Karte auf dem Kanban-Board. Wir gehen die Planung für die Woche kurz durch, damit jeder Bescheid weiß.

  • Individuell Überblick über die Doing-Spalte gewinnen: Sind noch Aufgaben in Doing, die in Vergessenheit geraten sind und Aufmerksamkeit brauchen? Was kann schnell erledigt werden? Was ist vielleicht schon fertig und versehentlich noch nicht in Done gezogen?

  • Wer braucht jemand anderen, um bei einer Aufgabe weiterzukommen? Bei der Wochenplanung ist eine gute Gelegenheit, sich mit anderen zu verabreden, um ein Problem zu lösen.

  • Wer braucht noch Fokus für die Woche? Eine Frage, die bei uns schon seit langem meist niemanden mehr betrifft. Falls jemand nicht weiß, was er sinnvollerweise tun sollte, können wir das an dieser Stelle klären.

  • Möchte jemand am Freitag einen Vortrag oder Workshop halten oder ein Projekt vorstellen? Ein kurzer Stupser, eventuell für Freitag eine Präsentation vorzubereiten, die man immer schon halten wollte.

Im Anschluss an die Wochenplanung findet üblicherweise noch eine Besprechung des aktuellen Fokusprojekt-Teams zum Fokusprojekt statt sowie bilaterale Besprechungen zwischen denjenigen, die in der Besprechung angemeldet haben, dass sie Hilfe/Abstimmung brauchen.

Für die Moderation haben wir eine Checkliste auf einer wöchentlich automatisch für das Meeting generierten Trello-Karte, sodass jeder im Team das Meeting moderieren kann.

Wochenrückblick

Termin: Freitags 14:30. Dauer: ca. 1 Stunde

Unser Workshop am Freitag dient dem Rückblick auf die Woche sowie Präsentationen und Diskussionen im Team zu Themen, die persönlich im Kreis des gesamten Teams besprochen werden sollen.

Die Tagesordnung:

  • Protokollant bestimmen (wir führen jedesmal Protokoll, damit Abwesende nachlesen können und wir eine Gedächtnisstütze haben)

  • Spotlights der Done-Spalte: Auf unserem Kanban-Board können wir erledigte Aufgaben, mit einem "Spotlight"-Label versehen. Alle Spotlights werden Freitags kurz vorgestellt – das betrifft z. B. Dinge, über die man sich besonders gefreut hat, aber auch Fallen, vor denen man andere warnen möchte, kurz: Alles, was in Done ist und irgendwie noch mal erwähnt werden soll,

  • Gefühlslage: Wie hat sich meine (Arbeits-) Woche angefühlt? Wie zufrieden bin ich?

Diese Standard-Tagesordnung kann bei Bedarf um weitere Punkte ergänzt werden, z. B. die Vorstellung eines Projekts oder eines Tools, oder auch Teamentscheide und -diskussionen. Insbesondere bei Teamdiskussionen hat es sich bewährt, diese gut vorzubereiten (z. B. durch eine vorbereitende E-Mail ans Team, in der man die Idee skizziert, über die man gerne sprechen möchte, oder die Entscheidung, die man treffen möchte).

Die Tagesordnung ist wie bei der Wochenplanung eine Checkliste auf der Trello-Karte für den Wochenrückblick. Diese Karte wird schon eine Woche vor der Besprechung automatisch erzeugt, sodass jeder im Laufe der Woche die Möglichkeit hat, Themen hinzuzufügen.

Daily Standup

Termin: Dienstag bis Freitag 9:45 Uhr. Dauer: 5-10 Minuten

Jeder berichtet kurz, woran er heute arbeiten wird und ob ihn oder sie etwas blockiert bzw. er Unterstützung braucht. Gelegentlich gibt es Unterstützung und Hinweise auch sofort, wenn jemand anders aus der Runde das Problem schon kennt. Im Anschluss klären einzelne Teilnehmer (z. B. Product Owner/Projektmanager und Entwickler oder Backend und Frontend) häufig noch konkrete Fragen aus Projekten, die am Tag vorher aufgetreten sind.

Auch die Teilnahme an Meetings (z. B. Projekt-Jour-Fixe) wird häufig im Standup abgesprochen.

Das Standup hat aus meiner Sicht folgende Funktionen:

  • Es regt dazu an, sich vorher Gedanken zu machen, was man für den Tag plant

  • Es ist eine Möglichkeit für andere, zu merken, wenn ich in einer Aufgabe feststecke, und mir Hilfe anzubieten

  • Es ist ein Synchronisationspunkt (im Anschluss ist Zeit, spontan konkrete Fragen zu besprechen, ohne den Kollegen aus der Arbeit zu reißen)

Früher haben wir auch die Frage gestellt "was habe ich gestern getan", aber das hatte wenig Nutzen und machte das Standup langatmig.

Interne Baustellen

Termin: jeden ersten Freitag des Monats 10 Uhr. Dauer: 1-1,5 Stunden

Einmal im Monat haben wir eine besondere Besprechung. Sie trägt den sperrigen Namen "Status 'Interne Baustellen' und ggf. Entscheidung über das nächste ToDo". Die Idee hinter dieser Besprechung ist, sicherzustellen, dass wir Themen und Prozesse, die für uns als Firma oder Team intern wichtig sind, nicht vergessen. In Kundenprojekten gibt es ja jemanden von außen, der im Zweifel daran erinnert, dass er etwas braucht – bei internen Projekten passiert es leicht, dass sie weniger Aufmerksamkeit bekommen, als sie bräuchten.

Interne Baustellen sind oder waren beispielsweise "Mitarbeitersuche", "Hosting-Umzug nach Frankfurt", "Arbeitszeitverkürzung (aka 30-h-Woche)", "webfactory-Website" oder "Was wir in allen Kundenprojekten berücksichtigen wollen".

Für die Besprechung haben wir folgenden Ablauf festgelegt:

3 Zeiteinheiten à 25 Minuten mit je 5 Minuten Pause (in der Pause sollte nicht weiter diskutiert werden). Jede Timebox endet pünktlich. Die Moderation dieser Meetings wechselt und der Protokollführer ist immer der Moderator des nächsten Meetings.

  1. Begrüßung: Kurzer Überblick über das Meeting, Klärung, wer Protokoll schreibt und wer auf die Zeit achtet (kann der Moderator selbst sein)

  2. Status der aktuellen internen Baustellen (sollten die im letzten Meeting besprochenen und ggf. zwischendurch ungeplant begonnenen sein). Pro Baustelle:

    1. Kurzer Rückblick auf den Stand beim letzten Meeting durch den Moderator (anhand des Protokolls)

    2. Bericht über den aktuellen Stand durch den Kapitän (also denjenigen, der die Verantwortung für das Thema übernommen hat)

    3. Feedback-/Frage-/Meinungsrunde

  3. Möchte jemand neue Themen vorstellen, die wir ins Backlog aufnehmen sollten?

  4. Wollen wir neue Themen beginnen? Wenn ja welches und wer übernimmt die Kapitänsbinde und wer ist beteiligt? Wie geht es los? Erstes Brainstorming/"Briefing" durch das gesamte Team direkt im Meeting?

  5. Abschluss (Alles gesagt? Brauchen wir mehr Zeit und wenn ja, wann geht es weiter? Protokoll vollständig/Aufgaben klar?)

Wir versuchen, nicht mehr als drei interne Baustellen gleichzeitig zu bearbeiten – also neue interne Baustellen erst dann anzufangen, wenn eine alte abgeschlossen ist.

Das monatliche Meeting stellt zwar nicht automatisch sicher, dass es zwischen den Besprechungen tatsächlich auch weitergeht, aber es schafft Aufmerksamkeit für die Themen, die wir uns als Team vorgenommen haben zu bearbeiten. Und es stellt einen Ort dar, wo wir als Team gemeinsam entscheiden, ob wir ein Thema anfangen wollen.

Die Besprechung ist stärker und anders strukturiert als unsere anderen Besprechungen. Das hat den Grund, dass wir früher gerade bei den internen Themen, die alle angehen, leicht in lange Diskussionen geraten sind. Das strenge Timeboxing mit Pflichtpausen hat uns sehr dabei geholfen, in solchen Diskussionen innezuhalten und ein bisschen Abstand zu gewinnen.

Geschäftsführungs-/Strategie-Jour-Fixe

Termin: Mittwochs. Dauer: ca. 2 Stunden

Ursprünglich hatte ich diesen Termin gar nicht auf dem Schirm für diesen Beitrag, aber tatsächlich ist er für uns nicht unwichtig: Eine feste Besprechungszeit jede Woche für die Geschäftsführung, in der wir an Führungsthemen arbeiten.

Wir haben fast keine formale Hierarchie in der Firma, es gibt nur die beiden Gründer und Geschäftsführer und "alle anderen". Da die webfactory sehr teamorientiert aufgestellt ist und die meisten Entscheidungen durch das ganze Team getroffen bzw. getragen werden, haben wir Gründer uns lange auch als ganz normale Teammitglieder gesehen, mit den gleichen Rechten und Pflichten wie alle anderen. Dabei haben wir übersehen, dass das zumindest in unserer aktuellen Aufstellung als GmbH mit zwei Gesellschafter-Geschäftsführern de facto nicht so ist und wir zwangsläufig eine andere Stellung als die anderen haben. Da immer wieder Themen aufkommen, die im Geschäftsführerkreis abgestimmt oder bearbeitet werden müssen, haben wir diesen jetzt einen festen regelmäßigen Termin eingeräumt, was sich sehr bewährt hat.

Kundenbesprechungen

Neben den internen Besprechungen haben wir auch regelmäßige Kundenbesprechungen.

Jour-Fixe in Fokusprojekten

Termin: Dienstags und Donnerstags 10:30 Uhr. Dauer: ca. 1 Stunde.

Ein Fokusprojekt ist für uns ein Projekt, auf das die Firma sich gerade fokussiert und an dem sie mit einem Team von mehreren Entwicklern arbeitet. Wir versuchen aufgrund unserer Teamgröße von insgesamt 10 Personen, nicht mehr als ein Fokusprojekt gleichzeitig zu bearbeiten, um uns auf dieses wirklich konzentrieren zu können und im Team noch Kapazität übrig zu behalten, parallel Ad-Hoc-Aufgaben für unsere anderen Kunden erledigen zu können. Typischerweise teilen wir das Team immer auf in eine Fokusprojekt-Fraktion und eine Ad-Hoc-Fraktion. Die Aufteilung wechselt im Laufe des Jahres.

Teilnehmer am Fokusprojekt-Jour-Fixe sind immer diejenigen Entwickler, die dem Kunden etwas präsentieren möchten und Feedback brauchen oder Fragen zur Aufgabenstellung haben und zusätzlich grundsätzlich eine Person, die Hauptansprechpartner für den Kunden ist und Kontinuität sicherstellt.

Die Themen für den Jour-Fixe sammeln wir vorab als Checkliste auf einer Projektmanagement-Trello-Karte, die wir für das Fokusprojekt in der Doing-Spalte unseres Kanban-Boards haben.

Jeder Entwickler stellt seine Fragen grundsätzlich selbst und bekommt auch die Antwort aus erster Hand. Dieses Vorgehen ist unsere Näherung an das vierte der zwölf Prinzipien hinter dem Agilen Manifest: "Fachexperten und Entwickler müssen während des Projektes täglich zusammenarbeiten." Für Projekte unserer Größenordnung ist eine tägliche Zusammenarbeit mit dem Kunden nicht erforderlich bzw. findet vorrangig in einer Konzeptionsphase am Anfang des Projekts statt. Die enge Abstimmung zweimal pro Woche hat sich aber sehr bewährt und erfüllt aus unserer Sicht den Zweck des Prinzips ziemlich gut.

Den Jour-Fixe am Dienstag nutzen wir auch zur Präsentation des aktuellen Budgetstands. Da wir Projekte in der Regel mit einem agilen Festpreis oder nach Aufwand abrechnen, gibt dies dem Kunden jederzeit den Überblick über das noch verfügbare Budget und Eingriffsmöglichkeiten, wenn er Prioritäten anders setzen möchte.

Backlog-Abstimmung

Termin: Individuell vereinbart, 10:30 oder 14:30 Uhr. Dauer: ca. 1 Stunde.

Derzeit haben wir eine lange Warteliste für Ad-Hoc-Aufgaben (Aufträge mit einer Größenordnung von unter 10 Personentagen). Wir arbeiten grundsätzlich first-in-first-out, d. h. neue Aufgaben reihen sich am Ende der Liste ein.

Um trotzdem sicherzustellen, dass wir die Aufgaben entsprechend ihrer Priorität für den Kunden abarbeiten, hat es sich für uns bewährt, uns einmal monatlich mit jedem Kunden abzustimmen. Wir bereiten dafür einen Auszug aller Aufgaben des Kunden aus unserem Backlog vor, aus dem die jeweilige Position der Aufgabe in der Warteliste hervorgeht. Wir können dann über die als nächstes Anstehenden Aufgaben sprechen und der Kunde bekommt auch die Möglichkeit, Aufgaben im Backlog zu tauschen, um dringendere Arbeiten auf Kosten weniger dringender Arbeiten zu beschleunigen.

Fazit

Für uns hat sich der Besprechungskalender in der aktuellen Form sehr bewährt. Er stellt sicher, dass jedes Thema seine Zeit hat, nichts zu kurz kommt und wir uns gleichzeitig auch nicht in Dinge vergraben. Auch wenn es viele feste Termine sind, nimmt ja lange nicht jedes Teammitglied an jeder Besprechung teil, sodass reichlich Zeit für konzentrierte Arbeit bleibt.

Worauf wir noch keine Antwort gefunden haben, ist eine Zeit für das Standup, an der wirklich jeder teilnehmen kann. Gerade seitdem wir im Corona-bedingten Homeoffice sind, experimentieren einige mit einer Verschiebung des Arbeitstages hin zu deutlich späterem Arbeitsbeginn. Die sieht man dann manchmal nur Montags oder Freitags, was ich persönlich schade finde. Für andere hingegen ist 9:45 schon fast die Mitte des Arbeitstages.

Wie laufen Besprechungen bei euch? Habt ihr mehr oder weniger Termine? Andere Themen? Wir freuen uns, von euch zu hören.

]]>
Fri, 25 Sep 2020 18:54:06 +0200 /blog/besprechungs-stundenplan /blog/besprechungs-stundenplan webfactory GmbH webfactory GmbH 0
Using Multiple SSH Deploy Keys with GitHub GitHub Deploy keys are for a single repository only

On GitHub, deploy keys are SSH keys that can be associated with a single repository and granted read-only or read/write permissions. With deploy keys, you don’t need a particular user account to access the repository. Having the key itself suffices – the key is the authentication and authorization token at the same time. 

To limit exposure in case such a key is lost, GitHub enforces a policy that a particular SSH key can only be used as deployment key for a single repository.

This becomes an issue when you want to work with several Git repositories at a time, using different deploy keys: When ssh has several keys available, it will try each of them in turn. The first known key will be accepted by GitHub servers for the SSH connection itself. But (some of) the subsequent Git commands run over the SSH connection will fail, since the SSH key is not authorized for the particular repository. You will see an error like 

fatal: Could not read from remote repository.
Please make sure you have the correct access rights and the repository exists.

As long as you’re running git commands one by one, you can use the GIT_SSH  environment variable to pass additional arguments to SSH and select the right key for a particular repository. However, when using package managers like Yarn, NPM or Composer that might need to clone several repositories, this won’t work.

Using virtual GitHub.com subdomains?

In this situation, people have suggested (here, there, elsewhere...) to make up (nonexistent) GitHub.com subdomains and use those in repository URLs. Then, additional ssh  configuration could be used to map these names back to github.com  as hostname while at the same time specifying the SSH key to use.

The downside of this approach is that these made-up domain names become part of your dependency declaration file, essentially forcing everyone to provide the same mapping in their SSH config files to be able to install dependencies.

Use key comments to find matching keys in the SSH agent

Thus, I would like to suggest another approach: Put all keys, including GitHub deployment keys, into the SSH key agent. Then, make Git use a wrapper script around ssh  to select the right key.

We will use SSH key comments to record the name of the repository that a key belongs to. And we will use the fact that  ssh -i  can point to a file with a key's public part, and that this key will be tried first even if all private keys and handled by the SSH agent.

So, let’s create a dedicated deploy key first:

ssh-keygen -C "Deploy key for git@github.com/your-org/your-repo.git" -f keyfile …

Add your usual arguments ( -t ed25519 -a 100 , maybe?) to create a new SSH key in keyfile . The key's public part will be put into keyfile.pub , and the key's comment will be set to contain your repository name. As this is a deploy key, don't set a passphrase.

Setup the deploy key at GitHub.com according to their deploy key documentation. Repeat this for every repository in question, and don't forget to use different keyfiles.

Next, make sure you have the SSH agent running, or start it with eval `ssh-agent -s` . Add all your key files to it by running ssh-add keyfile keyfile2 … . You can use ssh-add -L  to list all keys currently loaded into the agent.

The Wrapper Script

Put the following wrapper script somewhere:

#!/bin/bash

# The last argument is the command to be executed on the remote end, which is something
# like "git-upload-pack 'webfactory/ssh-agent.git'". We need the repo path only, so we
# loop over this last argument to get the last part of if.
for last in ${!#}; do :; done

# Don't use "exec" to run "ssh" below; then the trap won't work.
key_file=$(mktemp -u)
trap "rm -f $key_file" EXIT

eval last=$last

# Try to pick the right key
ssh-add -L | grep --word-regexp --max-count=1 $last > $key_file

ssh -i $key_file "$@"

(I've put this into a Gist, so you can also  wget https://gist.githubusercontent.com/mpdude/e56fcae5bc541b95187fa764aafb5e6d/raw/676626f0f8009d8b47743417dba436483cd929c6/ssh-deploy-key-wrapper.sh && chmod +x ssh-deploy-key-wrapper.sh ).

Export the GIT_SSH  environment variable to point to this wrapper script. Now, whenever Git needs to execute ssh , it will start this script instead.

The script will go through the keys currently loaded into the ssh-agent  and grep  the first one that matches the your-org/your-repo.git  part from the current repository URL. This is where the key comment we set up above comes into play.

The key's public part is then put into a temporary file and passed to the actual ssh  invocation. As a result, this key will be tried first, and the private key part will still be provided by the SSH agent.

]]>
Mon, 07 Sep 2020 16:17:13 +0200 /blog/using-multiple-ssh-deploy-keys-with-github /blog/using-multiple-ssh-deploy-keys-with-github webfactory GmbH webfactory GmbH 0
Homeoffice in Coronazeiten – Eine neue Ära bricht an? Es war der 10. März, als wir uns morgens im Team zu einer Lagebesprechung zusammengefunden hatten. In den Medien war zu diesem Zeitpunkt zu lesen, wie die COVID-19 Situation in Italien eskalierte und nun schien es uns relativ klar zu sein, dass auch wir in Deutschland in Kürze unseren Alltag nicht mehr so würden weiter führen können, wie wir es bis dahin getan hatten. An dem Tag stellten wir uns die Frage: „Wollen wir erst einmal noch abwarten, oder wollen wir das Büro direkt schließen und ins Homeoffice umziehen?“ Die Entscheidung fiel letzten Endes einstimmig zugunsten des Homeoffice. Der Grund dafür war damals weniger, dass wir uns Sorgen um unsere eigene Gesundheit machten, sondern vielmehr, dass wir es als unsere soziale Verantwortung ansahen, dazu beizutragen, dass möglichst wenige Menschen das Haus verlassen. Wohl gemerkt geschah dies einige Tage, bevor Social Distancing in Deutschland zum großen Thema wurde und auch die Kontaktbeschränkungen waren zu diesem Zeitpunkt noch nicht eingeführt.  

Den restlichen Tag über war damals die Stimmung im Büro etwas gedrückt – oder vielleicht kam es mir auch nur so vor. Ursprünglich hatten wir jedenfalls vorgehabt, um die Mittagszeit herum bereits nach Hause zu gehen, aber dann zogen sich die vorher noch zu erledigenden Arbeiten doch noch über den Tag – und fast schon schien es, als ob mindestens Einzelne nicht so richtig bereit waren, Abschied zu nehmen. Zu diesem Zeitpunkt war uns vermutlich allen schon bewusst, dass wir uns auf lange Sicht nicht mehr so persönlich begegnen würden, wie noch an diesem Tag. Das Wort „Monate“, schwebte auch da schon im Raum. 

Viel vorzubereiten hatten wir im Grunde genommen nicht. Wir machten uns Gedanken darüber, wie die Pflanzen in unserer Abwesenheit versorgt werden, dass wir unseren wöchentlich gelieferten Obstkorb abbestellen müssen und sprachen darüber, dass man zumindest ab und an irgendwie nach der Post sehen müsste. Wir legten einige grobe Regeln für die zukünftigen Arbeitstage fest: Dass sich jeder von uns bis 09:45 Uhr täglich via unserem Arbeits-Chat auf Slack melden würde, zum Beispiel. Dann richteten wir auf den Computern noch Möglichkeiten zum Screensharing ein und viel mehr war dann auch gar nicht mehr zu tun. 

Seit dem 10. März diesen Jahres haben wir uns also nicht mehr persönlich gesehen. Viele Wochen sind seitdem vergangen und somit ist es an der Zeit, einmal über unsere Erfahrungen zu berichten: Wie leicht gelang uns der Übergang von Präsenz- zu remote-Firma? Wie geht es uns insgesamt mit dieser neuen Arbeitssituation? Und: Wird dieses unfreiwillige Experiment unsere zukünftige Zusammenarbeit verändern?

Um ein genaueres Bild von der Stimmung und den Meinungen im Team zu bekommen, haben wir mittels Google Forms eine kleine Umfrage durchgeführt. Schauen wir uns die Daten doch nun einmal im Detail an:

In Abbildung 1 sehen wir, dass der Übergang ins Homeoffice einigen im Team gar keine Probleme bereitet hat („die Umstellung aufs Homeoffice ist mir schwer gefallen“), aber die Empfindungen diesbezüglich durchaus gemischter Natur waren. Dass uns als Firma insgesamt der Übergang gut gelungen ist, scheinen allerdings alle (antwortenden) Teammitglieder so zu sehen („die Umstellung aufs Homeoffice hat insgesamt für die Firma gut funktioniert“). Ebenso sehen wir hohe Zustimmungswerte bei „Im Homeoffice kann ich mich gut konzentrieren" (schlechtere Werte wurden vom Team teilweise durch die problematische Kinderbetreuungssituation begründet) und „Ich finde, die Kommunikation untereinander funktioniert auch von zu Hause aus gut“. 

Balkendiagramme Abbildung 1

Dennoch vermisst ein Großteil der Antwortenden den direkten Kontakt untereinander, wie Abbildung 2 zeigt („Ich vermisse den direkten Kontakt zu meinen KollegInnen“). Überraschend gespalten ist das Team bei dem (nicht ganz ernst gemeinten) Thema: „Ich vermisse die Kaffeemaschine im webfactory-Büro“. Auf Rückfrage erklärten sich einige damit, dass der Kaffee zuhause eben auch recht gut wäre. Na ok. Das können wir wohl so akzeptieren. Das Büro an sich wird dann scheinbar sogar noch weniger vermisst, als die Kaffeemaschine („Ich hoffe, dass wir bald alle wieder ins Büro zurückkehren werden“). Ein spannendes Ergebnis: Niemand scheint so richtig dringend wieder das Homeoffice verlassen zu wollen. Besonders toll auch: Das Vertrauen, dass wir ineinander haben, denn bei: „Ich vertraue meinen KollegInnen/MitarbeiterInnen, dass sie auch im Homeoffice gute Arbeit leisten“, erzielen wir durch die Bank sehr hohe Werte. 

Balkendiagramme Abbildung 2

Besonders auffällig: Bei fast allen haben sich im Homeoffice die Arbeitszeiten geändert (Abb. 3) und der Großteil von uns hat sogar die persönliche Meinung zum Thema „Arbeiten im Homeoffice“ geändert (Abb. 4). Auf Rückfrage erklärten manche Kollegen, dass sie nicht damit gerechnet hätten, dass es so gut laufen würde, oder dass sie sich im Homeoffice so gut würden konzentrieren können. Ein einzelner (ehemaliger) Homeoffice-Gegner hat seine ablehnende Haltung zum Thema sogar mittlerweile vollkommen revidiert. Positiv heben einige im Team hervor, dass sie sich ihre Arbeitszeit freier einteilen können. Somit fangen manche Eulen beispielsweise später an zu arbeiten (die obligatorische Meldung bis 09:45 Uhr im Teamchat hatte sich dann auch innerhalb von Tagen ganz automagisch erledigt), andere fangen früher an oder machen zwischendurch lange Pausen. Als Schattenseite davon merken Einzelne allerdings an, dass sich der Arbeitstag dadurch insgesamt in die Länge zieht und mindestens einem fällt es zumindest zeitweise schwer, einen Absprung zu finden. 

Balkendiagramm Abbildung 3

Balkendiagramm Abbildung 4

Insgesamt zeigt sich nach den letzten Wochen aber, dass wir erstaunlich gut mit der veränderten Situation zurechtkommen. Ich persönlich gehe davon aus, dass dieses Erlebnis unsere Arbeitsweise langfristig beeinflussen wird, auch wenn sich noch zeigen muss, wie unsere Zukunft im Detail aussehen wird. Manche Teammitglieder wünschen sich, zumindest ab und an, die Möglichkeit, die KollegInnen auch einmal wieder persönlich zu sehen oder ihre Arbeit im Büro zu verrichten. Andere träumen bereits davon, die Welt zu bereisen und von Unterwegs zu arbeiten oder haben für sich festgestellt, dass sie eigentlich gar nicht mehr so richtig ins Büro zurückkehren wollen und der eingesparte Pendelweg eine echte Erholung ist. Auch die Möglichkeit full-remote Kräfte einzustellen, scheint nun nicht mehr ganz fern jeglicher Vorstellung zu sein. Abbildung 5 zeigt allerdings, dass sich so ganz konkret doch niemand vollständig vom Büro distanzieren möchte. Entsprechend nicht ganz ernst gemeint, wurde sogar hier und da schon diskutiert, ob wir das Büro überhaupt noch brauchen. In guter Gesellschaft wären wir mit einer (optionalen) full-remote Firma zumindest: die bekannte social media Plattform Twitter hat bereits angekündigt, nicht mehr zu ihrer vorherigen Präsenzkultur zurückkehren zu wollen.

Tortendiagramm Abbildung 5

]]>
Thu, 28 May 2020 14:33:32 +0200 /blog/homeoffice-in-coronazeiten /blog/homeoffice-in-coronazeiten webfactory GmbH webfactory GmbH 0
Das Backup-Konzept unserer Webserver und Datenbanken Wir speichern alle 2 Stunden vollständige Backup-"Snapshots" aller unserer Webserver und Datenbanken.

Diese Snapshots werden nach einer gewissen Zeit automatisch ausgedünnt, und zwar nach folgenden Regeln:

  • Für 48 Stunden behalten wir alle Backups
  • Zusätzlich für die letzten 7 Tage ein Backup pro Tag
  • Zusätzlich für die letzten 4 Wochen ein Backup pro Woche
  • und für die letzten 6 Monate ein Backup pro Monat

Eine ausführlichere (englische) Dokumentation der Löschregeln findet sich auf der Website des von uns genutzten Tools alestic/ec2-expire-snapshots (unsere Konfiguration: --keep-first-hourly 48 --keep-first-daily 7 --keep-first-weekly 4 --keep-first-monthly 6).

]]>
Thu, 28 May 2020 10:01:46 +0200 /blog/backup-konzept-webserver-und-datenbanken /blog/backup-konzept-webserver-und-datenbanken webfactory GmbH webfactory GmbH 0
Webhosting in Frankfurt: Neue Preisliste Ziele für das Preismodell

Bei der Kalkulation des Preismodells haben wir unverändert drei Hauptziele:

In erster Linie wollen wir die Kosten von Amazon Web Services möglichst genau abbilden. Einkaufs- und Verkaufspreise sollen in einem vernünftigen und nachvollziehbaren Verhältnis stehen.

Zusätzlich zu den Einkaufspreisen bei Amazon Web Services muss aber auch unser eigener Entwicklungs- und Pflegeaufwand für unsere Hostingarchitektur sowie der Administrationsaufwand für den Betrieb der Server und das Einspielen von Updates angemessen berücksichtigt werden.

Nicht zuletzt soll unsere Preisliste aber auch eine transparente und vorhersehbare Angebotsgestaltung ermöglichen und den Aufwand für die Abrechnung möglichst gering halten. Wir haben uns daher bemüht, Pakete zu schnüren, bei denen möglichst wenig individueller Abrechnungsaufwand entsteht.

Unsere aktuellen Hostingpreise

Alle genannten Preise verstehen sich netto zzgl. der gesetzlichen Umsatzsteuer.

Virtueller Webserver (auf gemeinsam genutztem System)

Hierbei handelt sich um ein Angebot, bei dem wir mehrere Projekte verschiedener Kunden auf einem gemeinsamen Server betreiben.

Anstelle von bisher 20 GB Traffic und 5 GB Dateiablage umfasst dieses Paket nun 50 GB Traffic und 10 GB Dateiablage. Zusätzlich ist SSL/TLS-Verschlüsselung ohne Aufpreis enthalten (nur die Kosten für das SSL-Zertifikat berechnen wir wie bisher weiter).

Der Preis für das vergrößerte Leistungspaket bleibt unverändert bei 40 €. Zusatztraffic wird mit 20 € pro 50 GB weiterberechnet (bisher 20 € für 10 GB).

Virtueller Mailserver

Auf unserem zentralen Mailserver stellen wir E-Mail-Adressen zur Verfügung (POP3-Postfächer und/oder Alias bzw. Weiterleitungen), die unter einer oder mehreren Domains erreichbar sein können.

Das Paket bleibt unverändert inklusive Spamschutz auf der Basis von SpamAssassin und kostet wie bisher 20 €/Monat.

Eigene Instanzen

Für größere Projekte oder für Kunden, die viele Websites betreiben, bietet sich der Betrieb auf einem eigenen Server an. Wir beziehen dafür von Amazon Web Services individuelle Instanzen in verschiedenen, für das Webhosting optimierten Leistungsstufen. Instanz ist der Amazon-Begriff für einen virtuellen Root-Server.

Alle Instanztypen enthalten bei uns als Inklusivleistungen mehrmals tägliche Backups (Snapshots des Dateisystems), Administration und Betriebsüberwachung (Monitoring).

Eigene Small-Instanz

Bei Amazon Web Services nennt sich dieser Instanztyp "t3.small".

Im Paket mit 50 GB Datentraffic, 50 GB Dateiablage ("Elastic Block Storage", EBS) sowie unseren Inklusivleistungen kostet er bei uns unverändert 120 €/Monat.

Wenn das Datenvolumen nicht ausreicht, berechnen wir einheitlich 20 € pro angefangene 200 GB zusätzlichem Datentraffic oder 200 GB Dateiablage. Dieser Preis gilt unabhängig vom Instanztyp.

Eigene Medium-Instanz

Dieser Instanztyp heißt bei Amazon Web Services "t3.medium".

Wir bündeln ihn mit je 100 GB Datentraffic und Dateiablage und unseren Inklusivleistungen für 200 €/Monat.

Eigene Large-Instanz

Neu im Angebot ist die Large-Instanz, bei Amazon Web Services "t3.large", sie schließt die bisherige Lücke zwischen Medium und Extralarge.

Zusammen mit 200 GB Datentraffic, 200 GB Dateiablage und unseren Inklusivleistungen bieten wir sie für 340 €/Monat an.

Eigene Extralarge-Instanz

Eine Extralarge-Instanz, bei Amazon Web Services "t3.xlarge", ist wie bisher der leistungsstärkste Instanztyp in unserer Preisliste.

Zusammen mit 400 GB Datentraffic, 400 GB Dateiablage und unseren Inklusivleistungen bieten sie für 520 €/Monat an (bisher 550 €/Monat für je 200 GB Traffic und Dateiablage)

Virtueller Webserver auf eigener Instanz

Da der Administrationsaufwand für eine Instanz auch maßgeblich von der Anzahl der auf dieser Instanz laufenden Systeme (Websites bzw. Webanwendungen) abhängt, berechnen wir pro virtuellem Webserver auf einer dedizierten Instanz unverändert 20 €/Monat. Der Preis enthält jetzt auch die Auslieferung der Website über SSL/TLS, bisher war dafür ein Elastic Load Balancer für 30 €/Monat erforderlich.

Zusatzangebote

Auslieferung über Content Delivery Network CloudFront

Wir bieten die Nutzung von CloudFront für die Auslieferung von Websites an. Es handelt sich dabei um ein Content Delivery Network (CDN), ein Netzwerk von geographisch verteilten Proxyservern, auf denen die Website automatisch zwischengespeichert wird. Hierdurch wird eine deutlich schnellere Auslieferung der Website bei geringerer Last auf dem eigentlichen Webserver erreicht. Ein zusätzlicher Vorteil ist, dass auch bei Störungen auf dem Webserver die Website in vielen Fällen weiter abrufbar bleibt.

Für die Nutzung von CloudFront berechnen wir 30 €/Monat pro angefangene 100 GB Traffic und 10 Mio. HTTP-Requests. Durch die Nutzung von CloudFront reduziert sich der Traffic auf dem Webserver deutlich, d. h. die Kosten fallen nicht doppelt an.

Dateneingangsserver

Aus Sicherheitsgründen gewähren wir keinen Zugriff per SSH oder FTP auf unsere Serversysteme.

Für die Anlieferung von Daten, z. B. XML-Dateien zur Aktualisierung eines Onlinekatalogs aus dem Warenwirtschaftssystem, stellen wir einen speziellen Server bereit, von dem die Daten dann auf das Zielsystem weitergeleitet werden.

Pro Datenlieferant berechnen wir hierfür 20 €/Monat.

Datenauslieferungsserver/S3

Amazon S3 ist eine spezialisierte Plattform für die sichere Ablage und Bereitstellung von statischen Dateien.

Den Betrieb einer individuellen S3-Lösung inkl. 200 GB Datenablage und 200 GB Datentransfer von/zu S3 bieten wir für 30 €/Monat an.

Weitere Leistungen

Zusätzliche Leistungen bieten wir bei Bedarf individuell an.

Hierzu gehören z. B.

  • Nutzung eines zentralen PDF-Servers
  • Nutzung eines zentralen Solr-Suchservers
  • Betrieb eines PDF-Servers auf eigener Instanz
  • Betrieb eines Solr-Servers auf eigener Instanz
  • Versand von E-Mail-Newslettern

Bei Fragen zum Preismodell können Sie uns jederzeit via info@webfactory.de kontaktieren.

]]>
Thu, 30 Apr 2020 13:51:43 +0200 /blog/aktualisierung-webhosting-preise-2020 /blog/aktualisierung-webhosting-preise-2020 webfactory GmbH webfactory GmbH 0
wfLeaks: Eine Mitarbeiterin packt aus! Es ist Mittwoch, 12:00 Uhr, traditionsgemäß Home Office-Tag in der webfactory und für mich immer wieder eine gute Gelegenheit, über die Woche und die anstehenden Todos zu sinnieren. „Mitarbeitersuche wäre ja mal wieder ein Fass, das man öffnen könnte“, denke ich. Verstärkung – insbesondere im Backend – könnten wir nach wie vor wirklich gut gebrauchen, denn unsere Auftragslage ist so spitzenmäßig, dass wir mit unserem kleinen Team kaum hinterher kommen! Während ich überlege, wie wir am besten die Werbetrommel für uns rühren könnten, verliere ich mich kurz in der Vorstellung, wie Friedrich Liechtenstein in der Werbepause zwischen DSDS und Dschungelcamp für uns „Super Website – supergeil“ zum Besten gibt. Da allerdings aussagekräftige Gesprächsstudien während des Mittagessen gezeigt haben, dass unser Zielpublikum sich eher bei Netflix als bei RTL tummelt, ist das vielleicht auch nicht die beste Idee. „Wenn die Leute doch nur wüssten, was für ein toller Arbeitsplatz die webfactory ist“, denke ich – nicht zum ersten Mal – und grüble darüber nach, wie man dieses Wissen möglichst breit gestreut und plakativ unter die Leute bringen kann. An der Stelle kam er mir dann: der vollkommen innovative und durchaus auch mutige Gedanke, vielleicht einfach mal einen Blogbeitrag darüber zu verfassen – so ganz direkt von Mitarbeiterin zu Stellensuchenden. Wer anders als wir Mitarbeiter*innen könnte auch am besten beurteilen, wie supergeil oder superungeil der Arbeitsplatz hier wirklich ist? Deswegen, liebe Mitmenschen mit Programmationshintergrund, die ihr auf irgendeine Art und Weise den Weg zu diesem Beitrag gefunden habt: LEST DAS JETZT! Ich bin nämlich wirklich überzeugt davon, dass ganz viele von euch da draußen sich nach so einem Arbeitsplatz, wie wir ihn hier haben, die Finger lecken würden.

Supergeil

Steile These

Doch bevor es ins Eingemachte geht, möchte ich erstmal eine These aufstellen: Ich glaube nämlich, ihr habt schon in so vielen Stellenanzeigen (oder Headhunter-Anfragen) von dem „netten und motivierten Team“, mit seinen „tollen Mitgestaltungsmöglichkeiten“, der „Kaffeeflatrate“ und der „mega Familienfreundlichkeit“ bei „super flexibler Arbeitszeit“ und natürlich „total spannenden Projekten“ gelesen, dass euch das nur noch anödet. Hat es eigentlich jemals irgendwen überrascht, dass da nirgendwo steht: „Arbeite in einem Team voller sozialphober Psychopathen an saudrögen Projekten in einem mittelcharmanten Bürogebäude mit schlechter Parksituation und häufigen Überstunden“? Nein? Eben!

Das Problem ist, jedes Mal, wenn ich versuche eine Stellenanzeige für uns zu erfinden, erwische ich mich dabei, wie ich die selben Floskeln zu Papier bringen will und mich darüber ärgere, dass sich das so doof anfühlt, obwohl ich gleichzeitig nunmal finde, dass das bei uns halt nun einmal keine Floskeln sind. Was nicht heißen soll, dass hier ausschließlich, alles immer Tutti-Frutti ist – aber es ist halt auch einfach echt viel echt gut. Schauen wir uns das doch mal im Detail an:

Mitgestaltungsmöglichkeit

Vielleicht ist es untypisch, mit diesem Aspekt einzusteigen, anstatt euch zu erzählen, wie technisch kompetent wir sind – aber dass wir nach 20 Jahren Firmengeschichte nicht total unfähig sind, was unser Fachgebiet angeht, könnt ihr uns an der Stelle vielleicht einfach mal glauben. Viel spannender finde ich aber eben sämtliche „Rahmenbedingungen“, die bei uns so herrschen und die uns meiner Ansicht nach von vielen anderen unterscheiden.

Es gibt irgendwie keine Tabuthemen.

Das Thema „Mitgestaltungsmöglichkeiten“ empfinde ich da für den „wf-spirit“ als ganz zentral. Bei uns kann man nämlich tatsächlich eigentlich alles mitgestalten, was man möchte – oder um es mit den Worten eines Kollegen zu sagen: „Es gibt irgendwie keine Tabuthemen.“ Die webfactory möchte ein Ort sein, an dem Menschen zufrieden und glücklich sind und das lebt sie nicht nur auf dem Papier aus. Es ist nun jedem selbst überlassen, ein Herzensthema aufzumachen bzw. bei einem bereits existierenden Thema „mitzumischen“ und das kann alles mögliche sein: Von technischen Fragestellungen ("Wie können wir unsere Tests verbessern?") über grundlegende Firmenprinzipien ("Wer bekommt wieviel Gehalt und wie entscheiden wir darüber?"), räumlichen Gegebenheiten ("Welche Farbe sollen die Rollos im Wintergarten bekommen?") bis hin zu ganz individuellen Wünschen ("Darf ich einen Hund mit zur Arbeit bringen?") – mir fällt wirklich kein Thema ein, das Tabu wäre, oder grundsätzlich hierarchisch „von oben“ entschieden werden würde. Schreib dir doch einfach mal auf, wie dein ideales Berufsumfeld aussähe oder was du dir alles von deinem Arbeitsplatz wünschen würdest und jetzt stell dir vor, du könntest wirklich versuchen all das zu realisieren. Vielleicht klappt nicht alles immer sofort und auf einmal – auf manche Ziele muss man sicherlich erst hinarbeiten – aber die webfactory versucht immer, alles irgendwie möglich zu machen. Toll, oder?

Handlungsfreiheit und Vertrauen

Gehört ein bisschen zum vorangegangenen Abschnitt dazu, verdient aber eine extra Erwähnung, wie ich finde. Die webfactory möchte nämlich auch ein Arbeitsplatz sein, an dem man vertrauensvoll miteinander umgeht und das geht sogar soweit, dass wir Mitarbeiter*innen frei über die Firmengelder verfügen können. In der Praxis bedeutet das: Grundsätzlich kann jede*r entscheiden, was auf Firmenkosten gekauft werden soll und wir haben vollen Zugriff auf die Kreditkarte, den Paypal-Account und Co. Wenn ich ein neues Buch kaufen möchte, ein tolles Küchengerät oder wenn ich eine Konferenz buchen will (oder zwei oder drei im Jahr…), dann kann ich das einfach tun und muss vorher niemanden um Erlaubnis fragen. Die Regel besagt lediglich, dass man sich selbst überlegen soll, eine andere Person hinzuzuziehen, wenn man das Gefühl hat, dass die geplante Anschaffung so teuer ist, dass man sich alleine mit einer Entscheidung unwohl fühlt. Natürlich funktioniert das Prinzip nur solange, wie wir auch alle verantwortungsbewusst mit dieser Freiheit umgehen – bisher haben wir aber nur positive Erfahrungen damit gemacht. 

Familienfreundlichkeit

Die webfactory ist nicht das erste Arbeitsumfeld, in dem ich mich persönlich bewege und natürlich habe ich mich schon oft mit Freunden aus den unterschiedlichsten Branchen über das Familienthema unterhalten. Ich habe schon selbst beobachtet, wie Verträge schwangerer Frauen rein zufällig nicht mehr verlängert wurden, oder Geschichten darüber gehört, was anderen von ihren Chefs so an den Kopf geknallt wird, wenn sie es wagen, Nachwuchs in die Welt zu setzen. Bei uns hier in der webfactory wiederum waren die beiden (männlichen) Chefs tatsächlich lange Zeit die einzigen mit Nachwuchs und entsprechend auch die einzigen, die aufgrund der Kinderbetreuungsthematik ihre Arbeitszeit reduziert (und ja: dabei auch auf Gehalt verzichtet) haben. Allein das fand ich schon immer bemerkenswert, denn der klassische (männliche) Chef, den man so vor seinem geistigen Auge hat, würde doch niemals weniger als Vollzeit (plus Überstunden, meine ich) arbeiten. Wenn ich also sage, dass die Chefs ihre Arbeitszeit reduziert haben, meine ich damit nicht etwa „von 60 auf 55 Stunden“, sondern eben irgendwo unterhalb ihrer vorherigen Vollzeitstelle. Letztes Jahr ist nun zum ersten Mal ein Mitarbeiter Vater geworden und die Firma hat es ihm sofort problemlos möglich gemacht, seine Arbeitszeit für ein volles Jahr von fünf auf zwei Tage die Woche zu reduzieren. Es ist bei uns auch ganz selbstverständlich, dass jemand früh nach Hause geht, oder spät kommt, oder spontan gar nicht kommt, wenn der Nachwuchs krank ist oder Kindergeburtstag hat, die Neffen und Nichten abgeholt werden müssen oder was-auch-immer. Im übrigen ist es genau so selbstverständlich möglich, der Firma fern zu bleiben, wenn der Hund krank ist – der Luxus beschränkt sich also nicht nur auf menschliche Familienmitglieder. 

Arbeitszeit und Home Office

Aktuell gilt eine 40-Stunden-Woche bei uns als Vollzeitstelle. Ich bin ganz ehrlich: Ich finde das ganz schön lang und nach hinten raus unproduktiv. On the bright side sind wir an dem Thema dran: Wir haben vor einigen Monaten die „Baustelle“ 30-Stunden-Woche-bei-vollem-Lohnausgleich-einführen“ aufgemacht (erwähnte ich schon, dass es bei uns keine Tabuthemen gibt?) und wollen alles dafür geben, diesen Traum zu verwirklichen – nicht nur, aber auch, weil wir uns davon erhoffen, attraktiver für neue Mitarbeiter*innen zu werden. Schon heute steht es jedenfalls jedem frei, seine Arbeitszeit bei gleichzeitigem Lohnverzicht zu reduzieren. Das ist natürlich – ganz klar – vor allem auch eine Frage der finanziellen Machbarkeit. Wiederum sehr positiv zu bewerten ist aber auch aktuell schon die Flexibilität, mit der wir unsere Arbeitszeit einteilen können. Es ist absolut gar kein Problem, wenn man zwischendurch mal einen Arzttermin hat oder zum Friseur geht, mittags ins Schwimmbad fährt oder eine Runde durch die Südstadt joggt (wir haben auch eine schicke, neue Dusche im Büro), mal später kommt, mal früher geht usw. Auch Überstunden sind bei uns tatsächlich praktisch kein Thema. Man munkelt, dass in manch anderer Agentur die Mitarbeiter*innen Extrastunden schieben müssen, wenn die Projektdeadline ins Wanken gerät oder das Budget zur Neige geht. Wir finden das nicht in Ordnung und suchen an dieser Stelle in aller Regel nach anderen Lösungen. Was wiederum Home Office und Remote Arbeit angeht, können wir uns meiner Einschätzung nach noch ein wenig verbessern. Aktuell sehen wir kein Problem darin, wenn jemand einen Home Office Tag pro Woche einlegt (es hat sich irgendwie so eingebürgert, dass das bei allen der Mittwoch ist) aber einige von uns wünschen sich da langfristig noch eine größere Flexibilität und auch die Möglichkeit, längere Zeit Remote zu arbeiten. Grundsätzlich sind wir dem Thema aber offen gegenüber eingestellt und wenn jemand mal wirklich ganz konkrete Bedürfnisse anmeldet, werden wir sicherlich darauf eingehen. Bisher war das im aktuellen Team wohl einfach noch nicht so relevant. 

Total spannende Projekte

Unsere Projekte sind spannend – aber nicht immer. Oder: Es finden nicht immer alle jedes Projekt gleich toll. Ich denke, das ist ganz normal und keine große Überraschung. Was wir aber – glaube ich – alle ganz toll finden, ist die Tatsache, dass wir fast ausschließlich für Kunden aus dem sozialen und künstlerischen Bereich arbeiten (hinter dem Link verbirgt sich eine kleine Auswahl). Das bedeutet, dass wir Websites zu Themen erstellen, mit denen wir moralisch total im Reinen sind, die oft wenig mit der „bösen Welt des Kapitalismus“ zu tun haben und in denen es nicht darum geht, den Nutzer dazu zu bringen, auf möglichst viele Werbebanner zu klicken. Was vielleicht tatsächlich nicht jedem liegt, ist eben jene Form von Agenturarbeit, die wir abdecken. Wir arbeiten nunmal mit Kunden zusammen und nicht an unserem eigenen Produkt. Das heißt, dass wir mit unseren Kunden kommunizieren, interagieren und natürlich auch im alltäglichen Geschäft Support leisten. Unsere Arbeit kann sein, über Monate hinweg ein ganz neues Webprojekt von A bis Z aufzuziehen, aber es gehört auch dazu, das Impressum anzupassen, oder herauszufinden, warum irgendeine Anzeige kaputt ist. 

Das Team

Wir sind echt nett. Wirklich. Kann man nicht anders sagen. Ok, der ein oder andere hat einen wirklich unterirdischen Wortwitzhumor, beim Mittagessen diskutierten wir letztes Jahr überdurchschnittlich oft über den Brexit (ok, die Briten haben das letztes Jahr auch überdurchschnittlich oft versucht), es fällt mal der ein oder andere derbe Spruch (woran ich nicht ganz unschuldig bin) und natürlich merkt man schon, dass man hier mit einem Haufen Nerds (aber dafür ziemlich sozialkompetenten!) zusammenarbeitet. Hast du das jetzt irgendwie anders erwartet? Nee, oder?

Das Miteinander

Unsere Firma ist ein Ort, an dem die Menschen offen und respektvoll miteinander umgehen und auch auf zwischenmenschlicher Ebene zeigt sich, dass es keine Tabuthemen gibt. Wir wissen alle, dass es zum Mensch-sein dazugehört, dass man mal gute und schlechte Tage hat, nicht immer gesund ist und auch das Erleben im Privaten einen Einfluss darauf hat, wie wir uns auf der Arbeit geben und wie produktiv wir sind. Auch hier versucht die webfactory stets den Mensch mit all seinen Bedürfnissen mitzunehmen und soweit wie möglich dazu beizutragen, dass es allen gut geht. 

Kaffeeflatrate und andere Genüsse

Jaaa, wir haben natürlich auch eine Kaffeeflatrate. An dieser Stelle vielleicht tatsächlich erwähnenswert ist die superduper Siebträgermaschine, die wir vor ein paar Monaten gekauft haben (nachdem das ganze Team an einem Barista-Kurs teilgenommen hatte). Ohne Flachs: Ich kann jetzt in Bonn fast nirgends mehr Kaffee trinken, weil er einfach nirgendwo so gut schmeckt, wie in der webfactory. Nebenher bemerkt macht es vielen von uns großen Spaß, inklusive Latte Art so ganz professionell Kaffee zuzubereiten. Abgesehen davon gibt es bei uns Sprudelwasser per Knopfdruck aus der Leitung und wöchentlich einen neuen Obstkorb. Mittags kochen wir reihum im Team und essen gemeinsam – und wer darauf keinen Bock hat, versorgt sich halt anders. Vielleicht steckt auch in uns irgendwo ein kleiner Ökohipster, denn wir bereiten standardmäßig vegetarisches und glutenfreies Essen zu. Fleischesser werden aber dennoch nicht gedisst und insbesondere von den Hunden mit Freude aufgenommen!

Urlaub

Wir haben grundsätzlich 28 Tage bezahlten Urlaub im Jahr, aber on top noch „Sonderfrei“, was ich total toll finde. Das bedeutet, dass wir Rosenmontag (hier im Rheinland feiert man da Karneval) und die Tage von Heiligabend bis Silvester geschenkt bekommen. Unbezahlter Urlaub ist darüber hinaus verhandelbar und in der Vergangenheit auch ab und an schon vorgekommen. Wenn jemand Urlaub nehmen möchte, geht auch das total locker und unkompliziert: Im Prinzip ist jeder angehalten, sich selbst zu überlegen, ob harte Gründe gegen einen Urlaubswunsch sprechen und wenn man findet, dass das passt, kann man ruhigen Gewissens auch schon die Flüge (oder in Zeiten von FFF vielleicht die Zugtickets) buchen und im Nachhinein einfach das Team informieren. Selbst spontane Urlaube waren bisher nie ein Problem und selbst wenn sich herausgestellt hat, dass man bei der eigenen Urlaubsplanung etwas wichtiges übersehen hat („Ach Mist, da ist die Konferenz?“), dann haben wir den Urlaub dennoch immer irgendwie möglich gemacht.

Das Büro

Ist tatsächlich erwähnenswert, weil wir in einem schicken Altbau in der Bonner Südstadt arbeiten dürfen. Das sieht dann auch so aus, wie man sich das vorstellt: Stuck an den Wänden, hohe Decken, Kassettentüren, große Räume und ein wunderschöner Wintergarten. Wir sind erst im September 2019 eingezogen, das heißt, es ist sogar alles noch ganz frisch renoviert! Achja: Außerdem haben wir ein Bällebad!

Willst du auch mal bei uns baden? Dann schau in unsere aktuelle Stellenanzeige und bewirb dich einfach unter: info@webfactory.de 

Hast du noch Fragen? Dann schreib uns unter selbiger Adresse oder komm einfach mal auf einen Kaffee vorbei (eine kleine Vorwarnung wäre hierbei praktisch)!

Wir freuen uns auf dich!

]]>
Fri, 31 Jan 2020 17:08:49 +0100 /blog/wfleaks-eine-mitarbeiterin-packt-aus /blog/wfleaks-eine-mitarbeiterin-packt-aus webfactory GmbH webfactory GmbH 0
Gehaltstransparenz und Gehaltsmodell Warum transparente Gehälter?

Anlass war die Gehaltserhöhungsanfrage eines Kollegen: Er sei jetzt zwei Jahre im Team und hätte gerne eine Anpassung. Er habe gelernt, dass man regelmäßig fragen muss, weil man sonst gehaltsmäßig abgehängt wird. Wir waren in den 20 Jahren vorher in der komfortablen Situation, nicht häufig mit solchen Fragen konfrontiert worden zu sein. Und wenn doch, haben wir zwei Geschäftsführer über die Anfrage beraten und entschieden. Wir haben nie ein explizites Geheimnis aus Gehältern gemacht, aber sie auch nie aktiv offengelegt.

Zurück zur Gehaltsanfrage des Kollegen. Auch hier habe ich mich mit meinem Co-Geschäftsführer Matthias beraten. Dass wir das Gehalt erhöhen wollten, war schnell klar. Womit wir uns schwer taten, war die Wahrnehmung "wer nicht fragt, wird abgehängt". Das fanden wir nicht fair, zumal wir im Team mehrere Leute hatten, die auch für eine Erhöhung in Frage gekommen wären, aber nicht gefragt hatten. Wie sollten wir nun vorgehen?

  • Nur wer fragt, bekommt eine Erhöhung? Das hatten wir schnell ausgeschlossen, es erschien uns unfair und hätte vermutlich dazu geführt, dass über kurz oder lang jeder Kollege regelmäßig nach einer Erhöhung gefragt hätte. Hierzu muss man wissen, dass Gehaltsverhandlungen zumindest bei mir, aber auch bei vielen meiner geschätzten Kolleg*innen weit unten auf der persönlichen Beliebtheitsskala rangieren.

  • Wenn eine*r fragt, bekommen alle eine Erhöhung? Das wäre aus unserer Sicht fairer gewesen, denn zumindest hätte es nicht Teammitglieder, die fragen, gegenüber denjenigen bevorzugt, die nicht fragen. Richtig rund fanden wir aber auch diese Lösung nicht ;-)

  • Es gibt regelmäßig automatisch Erhöhungen, ohne dass jemand fragen muss? Schon besser. Allerdings war uns klar, dass uns das regelmäßig mit der Frage konfrontieren würde, wer wie viel Erhöhung verdient hat. Und da hatten wir das starke Gefühl, dass wir als Geschäftsführer vielleicht gar nicht den vollen Überblick haben, wer wie viel leistet (z. B. wussten wir, dass es im Team auch Kollegen gab, die sehr geschätzt waren für ihre Hilfsbereitschaft, wenn andere Probleme hatten – sie haben also einen großen Beitrag geleistet, der für uns Geschäftsführer gar nicht direkt sicht- und fühlbar war.)

Der Teamworkshop

Wir haben uns daher entschieden, die Frage nicht alleine, sondern gemeinsam mit dem Team zu beantworten. Dazu haben wir einen ganztägigen Workshop zum Thema Gehälter einberufen.

Als Vorbereitung gab es die erste Gehaltszufriedenheitsumfrage in der Geschichte der webfactory. Über ein Online-Tool (Google Forms) haben wir allen Kollegen anonym folgende Fragen gestellt:

  • Wie zufrieden bist du mit deinem aktuellen Gehalt? (1=sehr zufrieden—10=sehr unzufrieden)

  • Hast du das Gefühl, dass die Gehälter bei der webfactory fair verteilt sind? (1-10)

  • Wie zufrieden bist du mit dem Gehaltsprozess, also dem Weg, wie das Gehalt festgelegt wird? (1-10)

  • Gibt es im Gehaltszusammenhang Dinge, die dich bei der webfactory stören?

  • Gibt es im Gehaltszusammenhang Dinge, die du bei der webfactory besonders positiv findest?

  • Sonstige Wünsche/Fragen/Anmerkungen?

Die Ergebnisse waren überraschend: Die Zufriedenheit mit dem eigenen Gehalt rangierte im Mittelfeld, wobei 2/3 der Antworten im eher positiven Bereich lagen (5 oder besser). In der Frage nach der Zufriedenheit mit dem Gehaltsprozess lagen schon 2/3 der Antworten im negativen Bereich (6 oder schlechter). Die Wahrnehmung der Fairness war sogar noch darunter – 5 von 6 Antworten waren im negativen Bereich. Gerade letzteres hat uns gewundert: Dass die Gehälter in der webfactory nicht hoch waren und die Kollegen damit vielleicht Grund zur Unzufriedenheit hatten, konnten wir uns vorstellen – aber warum wurden die Gehälter als unfair empfunden? Wohlgemerkt: Sie waren noch nicht transparent, d. h. zumindest offiziell wusste niemand, was die anderen verdienen.

Ein perfektes Thema für den Workshop, bei dem wir uns im Anschluss an die Präsentation der Umfrageergebnisse dann intensiv mit der Frage nach der Fairness von Gehältern auseinandergesetzt haben. Folgende Aussagen hatten in der Frage "Was ist fair" hohe Zustimmung im Team:

  • Abhängig von der Leistung/dem Wert für die Firma/der Produktivität/der Schwierigkeit der Aufgaben (6x Zustimmung, 1 Gegenstimme)

  • Keine Unterscheidung zwischen Ausbildung und Studium bei gleicher Leistung (6x Zustimmung, 1 Gegenstimme)

  • Nachvollziehbar, wie das Gehalt festgelegt wird (7x Zustimmung, keine Gegenstimme)

  • Nicht abhängig vom Verhandlungsgeschick (8x Zustimmung, keine Gegenstimme)

Die Aussage "Transparenz" als Fairnesskriterium rangierte im Mittelfeld mit 4 Zustimmungen und 2 besorgten Gegenstimmen.

Da die Frage nach der Transparenz der Gehälter eine wichtige Voraussetzung für die weitere Arbeit war und aus unserer Sicht nur im Team entschieden werden konnte, haben wir uns im nächsten Abschnitt des Workshops explizit damit befasst. Bei der Frage nach dem Pro und Contra von Gehaltstransparenz haben wir im Team folgende Punkte zusammengetragen:

  • Transparenz könnte Rechtfertigungsdruck auf die Geschäftsführung aufbauen

  • Transparenz könnte zu Neid und Frust führen

  • Transparenz ermöglicht offene Diskussion

  • Wir können ein sensibles, persönliches Thema nicht mehr einfach ignorieren (keiner hatte Lust auf Gehaltsdiskussionen, aber andererseits ist das Gehalt für jeden von uns ein Thema mit großen Auswirkungen)

  • Müssen wir dann gleichzeitig auch einen "Prozess" haben?

  • Und last but not least: Die Unzufriedenheit ist schon da, sie kann also nicht durch Transparenz erzeugt werden

Insbesondere der letzte Punkt, der ja durch die Zufriedenheitsumfrage belegt war, hat dann in meiner Erinnerung den Durchbruch gebracht: Es bestand plötzlich eine starke Tendenz bei allen, dass wir die Gehälter transparent machen sollten. Aufgrund der Tragweite der Entscheidung haben wir uns aber noch über das Wochenende Bedenkzeit gegeben (der Workshop war am Freitag) und haben am Montag in geheimer Abstimmung entschieden. Das Ergebnis: 7 Ja-Stimmen und eine Enthaltung. Die Gehaltstransparenz war damit besiegelt.

Offenlegung der Gehälter

Noch am Tag der Entscheidung habe ich die aktuellen Gehälter aller Teammitglieder (natürlich inklusive der Geschäftsführung) im webfactory-Wiki veröffentlicht. Mit Blick auf einen angedachten zukünftigen Gehaltsprozess bereits auf der Basis von Stufen anstelle von reinen Euro-Beträgen. Ausgehend von 2.000 € habe ich 15 Stufen berechnet, jede Stufe bedeutete eine ungefähr 9%ige Steigerung zur vorangegangen. Diesen Abstand hatte ich in einer Publikation zum Gehaltsmodell von it-agile als Empfehlung gefunden, einem Beratungsunternehmen, das selbst seit langem ein teamorientiertes Gehaltsmodell hat. Stufe 15 lag bei 6.700 €.

Die neue Wikiseite "Gehälter" enthielt die resultierende Tabelle mit den Gehaltsstufen und eine Zuordnung jedes Teammitglieds zu einer Stufe bzw. teilweise auch zwischen zwei Stufen auf Basis des aktuellen Gehalts. Unsere damaligen Gehälter lagen im Mittelfeld des Spektrums, weder die obersten noch die untersten Stufen waren besetzt.

Im Anschluss haben wir eine zweite Gehaltszufriedenheitsumfage gemacht, mit den gleichen Fragen wie oben, und einem erfreulichen Ergebnis: Die Zufriedenheit sowohl mit den Gehältern als auch mit der Fairness der Gehälter und dem Gehaltsprozess hatte sich insgesamt deutlich verbessert (50% fanden die Verteilung jetzt eher fair und 5/6 waren mit dem Prozess zufrieden) – und das, obwohl wir nichts anderes getan hatten als den Status Quo offenzulegen. Hier kam uns vermutlich zu Gute, dass wir uns auch vor der Transparenz immer schon bemüht hatten, eine faire Einstufung vorzunehmen und darauf zu achten, dass Teammitglieder mit vergleichbarer Leistung auch vergleichbare Gehälter bekamen.

Pendeldiplomatie

Nach der Veröffentlichung war es uns wichtig, mit allen Teammitgliedern Einzelgespräche zu führen, um eine offene Aussprache über wahrgenommene Ungerechtigkeiten und Anpassungsbedarf zu ermöglichen. Wir haben dann in der Geschäftsführung einen Entwurf für eine Korrektur der Einstufung auf Basis des Feedbacks erarbeitet, bei dem einige Kolleg*innen höher eingestuft wurden. Diesen Entwurf haben wir dann erneut mit jedem einzeln besprochen und auf Basis des Feedbacks noch einmal angepasst. Insgesamt war das eine recht zähe Pendeldiplomatie, aber immerhin: Nach zwei Tagen hatten wir eine neue Einstufungstabelle, die die Zustimmung aller Teammitglieder hatte. In einer dritten Umfrage im Anschluss an die Neueinstufung waren dann übrigens 5/6 mit ihrem Gehalt zufrieden und 2/3 fanden die Verteilung fair – 1/3 sogar mit der zweitbesten Note.

Uns war aber klar, dass das noch kein Modell für zukünftige Gehaltsanpassungen sein konnte: Die Beteiligung des Teams hatte den Entscheidungsprozess erstmal umständlicher statt leichter gemacht. Zudem hatten wir noch keine Kriterien für eine Einstufung – diese war rein Bauchgefühl-basiert.

Entwicklung eines Gehaltsmodells

In den folgenden Monaten haben wir uns Gedanken gemacht und recherchiert, wie ein Gehaltsmodell aussehen könnte. Wir brauchten einerseits nachvollziehbare Kriterien für die Einstufung, andererseits sollten diese hinreichend weich und offen sein, um nicht falsche Anreize zu setzen. Ein plastisches Beispiel hat mir Henning Wolf beschrieben, einer der Gründer und langjähriger Geschäftsführer von it-agile:

Wir hatten mal sowas wie einen Kriterienkatalog, z. B. konnte man eine damals „Senior-Berater" benannte Stufe nur erreichen, wenn man schon mal einen Konferenzvortrag gehalten hat. Das führt aber zu komischen „Checklisten“-Karrieren und nicht zu guten Vorträgen. Deshalb haben wir keine festen Kriterien, sondern Themenbereiche, in denen wir die Kollegen relativ zu einander bewerten. Am Ende geht es um sowas wie den „Wert oder Nutzen für das Unternehmen“ im Verhältnis zu anderen Kollegen.

In einem weiteren Teamworkshop haben wir daher gemeinsam Themenbereiche gesammelt, die man für einen Vergleich zweier Kollegen untereinander heranziehen kann. Diese Liste ist eine Art Brainstorming-Ergebnis, wir haben im Grunde alle genannten Punkte aufgenommen. Die Liste ist aber auch nicht abschließend – sie soll vor allem Anhaltspunkte geben. Sie enthält folgende Punkte:

  • Kundenorientierung

  • Verantwortungsübernahme

  • Erfolg und Wertschöpfung

  • Technisches Know-How/Skills

  • Schwierigkeit der Aufgaben

  • Motivation und Einsatz

  • Teamfähigkeit, soziale Kompetenz

  • Pragmatismus und "Dinge-auf-die-Straße-bringen"

  • Vielseitigkeit

  • Marktwert

  • Formale Qualifikationen

Auf Basis dieser Liste wäre es nun also möglich, zu sagen: Kollege B bekommt ein um eine Stufe höheres Gehalt als Kollegin A, weil beide in den meisten Kriterien gleich abschneiden, aber B eine deutlich höhere Kundenorientierung hat. Oder: A und B sind auf der gleichen Stufe, weil B zwar eine höhere Kundenorientierung hat, aber A schwierigere Aufgaben übernimmt.

Gehaltserhöhungen

Die Vergleichskriterien schienen uns sinnvoll, ließen aber eine Frage unbeantwortet: Wie berücksichtigen wir, dass jedes Teammitglied sich weiterentwickelt? Wie reduzieren wir langfristig Anpassungsbedarf in der Einstufung? Anlass für unseren Einstieg in das Gehaltsprojekt war ja der berechtigte Wunsch eines Kollegen nach einer Gehaltserhöhung nach 2 Jahren Betriebszugehörigkeit. Unsere Sorge war: wenn wir einfach nur bei der Stufentabelle und dem Kriterienkatalog bleiben, wird es regelmäßig ein Wettrennen um Neueinstufungen geben – in einem als fair empfundenen Ausgangsgefüge reicht es, wenn ein Teammitglied sagt, dass es eine Erhöhung möchte, um einen Anpassungsbedarf bei allen anderen zu erzeugen, bis jede*r eine Stufe höher geklettert ist.

Um diesen Effekt und die erwarteten unangenehmen Diskussionen zu vermeiden, haben wir eine automatische Anpassung in unser Gehaltsmodell integriert: Einen prozentualen Aufschlag für die Dauer der Betriebszugehörigkeit. Nach unseren Erfahrungen steigt der Wert einer Mitarbeiterin für die Firma mit der Zeit stark an – zum einen, weil sie sich selbst fachlich und persönlich weiterentwickelt, zum anderen, weil sie die Firma und ihre Kunden und Projekte besser kennenlernt. Unsere Inspiration war hier Buffer, ein Startup, das jedem Mitarbeiter 5% Aufschlag für jedes Jahr Betriebszugehörigkeit zahlt (https://open.buffer.com/transparent-salaries/). Wir sind etwas niedriger eingestiegen, zumal wir den Loyalitätsbonus natürlich auch für die bestehenden Kollegen einführen wollten. Und da Matthias und ich bereits 20 Jahre im Unternehmen waren, hätten wir 100% Aufschlag nicht als fair empfunden und es hätte uns auch finanziell überfordert. Unser Modell sieht 4% Gehaltssteigerung für die ersten 5 Jahre vor, 2% mehr für jedes weitere Jahr bis zum 10. Jahr, und 1% pro Jahr darüber hinaus.

Dennoch gibt es natürlich ab und zu auch das Bedürfnis nach einer Neueinstufung – alleine schon bei neuen Teammitgliedern, mit denen wir während der Probezeit lieber eine vorsichtige Einstufung vereinbaren, die dann am Ende der Probezeit überprüft wird.

Der Prozess für Neueinstufungen

Für uns war klar, dass der Prozess für Neueinstufungen teambasiert sein muss – sonst hätte es potenziell bei jeder Einstufungsänderung Unzufriedenheit oder Diskussionen im Anschluss gegeben. Daher setzen wir folgendes Verfahren ein:

Wenn ein Teammitglied auf eine neue Gehaltsstufe wechseln möchte, stellt es bis zum Ende der ersten vollen Arbeitswoche des Jahres einen "Antrag" – konkret eine Mail an die Geschäftsführer mit der gewünschten neuen Stufe und einer Begründung auf Basis des Gehaltsmodells. Diese Begründung wird, wieder in Form einer anonymen Online-Umfrage, an das Team weitergegeben. Hierzu stellen wir folgende Fragen:

  • Ich bin für folgende Einstufung (Auswahlliste mit allen Gehaltsstufen)

  • Anmerkung/Begründung dazu

  • Gibt es sonstige Personen, die aus meiner Sicht höhergestuft werden müssten?

  • Gibt es Personen, die aus meiner Sicht zu hoch eingestuft sind?

  • Ist das resultierende Gehaltsgefüge (wenn die Entscheidungen in meinem Sinne fallen) insgesamt fair? Wenn nicht, was müsste sich ändern?

  • Was ich sonst noch sagen wollte (freies Bemerkungsfeld)

Wichtig ist uns dabei, dass mit jeder Neueinstufung auch noch einmal mit dem gesamten Team die Fairness des Gesamtgefüges abgestimmt wird.

Auf der Basis der Umfrage entscheidet dann die Geschäftsführung über die Einstufung. Aus unserer Sicht kann die Entscheidung auch an andere Personen delegiert werden (ein "Gehaltschecker"-Gremium), aber das ist vielleicht eine zukünftige Ausbaustufe.

Berufserfahrung: eine offene Flanke

Wir haben das Gehaltsmodell bewusst so konstruiert, dass wir regelmäßige Gehaltserhöhungsanfragen unnötig machen. Das erreichen wir wie beschrieben über den Betriebszugehörigkeitsbonus, der den Zuwachs an Produktivität sowohl durch hinzugewonnene Berufserfahrung und Fachwissen als auch durch bessere Kenntnis der Fima und ihrer Kunden abbilden soll.

Eine Schwierigkeit besteht aus meiner Sicht noch darin, dass Berufserfahrung, die innerhalb der webfactory gesammelt wird, damit anders bewertet wird als Berufserfahrung, die vorher gesammelt wurde (die muss folglich durch die Gehaltsstufe abgebildet sein). Nehmen wir an, ein Entwickler mit Uniabschluss steigt mit 2 Jahren Berufserfahrung in der webfactory auf Stufe 8 ein. Nach 5 Jahren bei uns hat er auf der gleichen Stufe einen Betriebszugehörigkeitsbonus von 20%, also das Äquivalent von zwei Gehaltsstufen mehr als beim Einstieg. Wenn eine Kommilitonin von ihm, die gleichzeitig ihren Abschluss gemacht und in den 5 Jahren woanders gearbeitet hat, zur webfactory wechselt, müsste sie auf Stufe 10 einsteigen, wenn sie annähernd das gleiche Gehalt bekommen sollte (tatsächlich wären es dann sogar noch 30 € weniger). Mein Eindruck ist aber, dass die Gehaltsstufen unweigerlich auch mit Rang- oder Wertigkeitsstufen assoziiert werden. Selbst wenn die neue Kollegin "nur" auf Stufe 9 einsteigen würde und damit ein um knapp 9% geringeres Gehalt akzeptieren würde als ihr Kommilitone, würde es für ihn doch leicht so aussehen, als sei er mit Stufe 8 weniger wert als sie.

Hier glaube ich, dass vielleicht noch ein Baustein fehlt, der dieses Problem vermeiden hilft.

Mein Fazit

Die Gehaltstransparenz hat sich seit Tag 1 richtig angefühlt. Ich glaube, niemand von uns kann sich mehr vorstellen, die Gehälter wieder geheim zu halten. Insbesondere die offenen Gespräche über faire Gehälter wären ohne Transparenz nicht möglich.

Das Gehaltsmodell mit der Kombination aus automatischen und anlassbezogenen Erhöhungen hat sich seit nunmehr drei Jahren in allen Situationen bewährt. Durch seine Offenheit und das Fehlen von harten Kriterien ist die Einstufung zwar manchmal schwierig und natürlich subjektiv, aber da das ganze Team gehört wird, nicht willkürlich. Gerade diese Flexibilität ermöglicht es uns auch, jedem Einzelfall gerecht zu werden.

Insgesamt ist es recht ruhig um das Thema, was für mich auch bedeutet, dass das Modell hinreichend gut funktioniert und wir uns anderen Baustellen widmen können.

Gerade letzte Woche haben wir übrigens zum ersten Mal seit der Einführung des Modells die Gehaltsstufen inflationsbasiert angepasst, was für jeden eine zusätzliche Gehaltserhöhung von 4,78% bedeutete.

]]>
Thu, 30 Jan 2020 11:24:51 +0100 /blog/gehaltstransparenz-und-gehaltsmodell /blog/gehaltstransparenz-und-gehaltsmodell webfactory GmbH webfactory GmbH 0
Using a SSH deploy key in GitHub Actions to access private repositories Update 2019-09-15: We've published the webfactory/ssh-agent GitHub Action which takes care of starting the SSH agent, adding the key and setting up host keys. With that action, most of the configuration described here is no longer necessary.

When staging a project to run tests or build a Docker image, you might need to fetch additional dependencies (libraries or "vendors") from private repositories. However, GitHub Actions are limited to accessing the repository they run for.

To solve this, you can create an additional SSH key with sufficient access privileges. Store that key in the secrets storage which is in the "Settings" area of your repository. The secret content is the private SSH key, as you will find it in the id_rsa file.

For the following example, the name of the secret should be SSH_PRIVATE_KEY.  Then, have a look at the following workflow definition:

# .github/workflows/my-workflow.yml
# ... other config here
jobs:
    build:
        runs-on: ubuntu-18.04
        steps:
            -   uses: actions/checkout@v1

            -   name: Setup SSH Keys and known_hosts
                env:
                    SSH_AUTH_SOCK: /tmp/ssh_agent.sock
                run: |
                    mkdir -p ~/.ssh
                    ssh-keyscan github.com >> ~/.ssh/known_hosts
                    ssh-agent -a $SSH_AUTH_SOCK > /dev/null
                    ssh-add - <<< "${{ secrets.SSH_PRIVATE_KEY }}"

            -   name: Some task that fetches dependencies
                env:
                    SSH_AUTH_SOCK: /tmp/ssh_agent.sock
                run: ./fetch-deps.sh


We first run ssh-keyscan to detect GitHub's SSH host keys. This for sure could be improved if worker nodes had these keys already set up. We then start the ssh-agent , binding it to a predictable socket location, and finally import the SSH private key into the agent. The nice thing about the way this happens is that the private key is never written to disk.

After the setup step has run, the SSH agent will still be running and can be used by other processes. To make this happen, set the SSH_AUTH_SOCK environment variable. Commands like git run ssh under the hood and will make use of the key stored in the agent when they authenticate to other hosts.

Right now, you will have to set the environment variable for every step that needs it, but it looks as if an improvement for this is already underway

Where to register the public SSH key part?

To actually grant the SSH key access, you can – on GitHub – use at least two ways:

  • Deploy keys can be added to individual GitHub repositories. They can give read and/or write access to the particular repository. When pulling a lot of dependencies, however, you'll end up adding the key in many places. Rotating the key probably becomes difficult.
  • A machine user can be used for more fine-grained permissions management and have access to multiple repositories with just one instance of the key being registered. It will, however, count against your number of users on paid GitHub plans.
]]>
Fri, 06 Sep 2019 17:46:38 +0200 /blog/use-ssh-key-for-private-repositories-in-github-actions /blog/use-ssh-key-for-private-repositories-in-github-actions webfactory GmbH webfactory GmbH 0
Expressive, type-checked constants for PHP In order to have an example, assume we are dealing with some kind of  Order  class that can have a "normal" or "high" order priority status like so:

class Order
{
    const PRIORITY_NORMAL = 'normal';
    const PRIORITY_HIGH = 'high';

    // ...
}

A method accepting one of these constants usually looks like this:

class Order
{
    /**
     * Create a new order instance
     */ 
    public static function place(ItemList $items, string $priority): self
    { ... }
}

Problems with the scalar-typed approach

Although there are two special string values defined as the two constant values in the above example, clients of this method may pass in literal string values (a plain  'normal'  or  'high' ) directly. For example, this may happen if they are taking the value directly from request parameters, which obviously is a risky practice.

In general, as the  Order::place()  method above accepts a string, nothing prevents you from passing in arbitrary string values.

Another possible mistake is that parameter order is messed up and arbitrary values are passed in places where constant values are expected.

To make your software design robust, defensive and fail-fast, in the above example you should check that the  $priority is indeed one of the available priorities.

As you can imagine, this can quickly get impractical when the constant values are used a lot and passed on between methods, as each method would need to check them again and again. Adding a new constant value would also require you to update all those checks.

When working with  int  constants ( 0, 1, 2, ... ), the mistake of messing up the parameter ordering might be so subtle that you cannot catch it by checking the parameter value.

Constant value objects

So, here is another way how we can design this. I will be building upon two OOD concepts:

  • Value objects describes the approach of modelling plain values as objects.

  • Often, it is benefical as well to design such objects as being immutable.

You can find valuable chapters on both ideas in Eric Evans' book "Domain Driven Design".

Bringing both together, we can come up with an  OrderPriorty  class as follows. Let's call this a constant value class:

class OrderPriority
{
    private const NORMAL = 'normal';
    private const HIGH = 'high';

    private $priority;

    public static function NORMAL(): self
    {
        return new self(self::NORMAL);
    }

    public static function HIGH(): self
    {
        return new self(self::HIGH);
    }

    private function __construct($priority)
    {
        $this->priority = $priority;
    }
}

As the  OrderPriority  constructor is private, the only way of creating  OrderPriority  instances is through the static construction methods  OrderPriority::NORMAL()  and  OrderPriority::HIGH() .

We can now write our method as

class Order
{
    public static function place(ItemList $items, OrderPriority $priority): self
    { ... }
}

Since PHP is type-checking the  $priority  parameter, you can now be sure you're dealing with some kind of  OrderPriority . Without further checks or safeguards, the  place(...)  method can now be sure that  $priority  is one of the valid priority levels.

There is one required change for clients passing in one of these values: Instead of writing  Order::PRIORITY_NORMAL  or  Order::PRIORITY_HIGH , we will now use  OrderPriority::NORMAL()  or  OrderPriority::HIGH() . This is necessary to create the instances of our constant value class.

Note that I chose to name these methods all caps to resemble the convention of constant identifier naming.

Checking for constant values

When checking a parameter like  $priority  for one of the constant values, we can write the check as  $priority == OrderPriority::HIGH() . This already works for the  ==  loose comparison since the values of both constant class instances – the one in  $priority  and the one created on the fly – are the same.

As a cautious programmer, however, you're probably using the strict comparison operator  ===  whenever possible. With a constant value class as shown above, this will not work, since this operator also checks for object identity and we're using two different object instances.

So, let's fix that.

Using flyweights

The Flyweight is a structural pattern from the classic "Gang of Four" book. Part of the pattern is the idea to re-use object instances when they don't differ in state, which is perfect for our immutable constant values.

Also described in the pattern is the need to have some kind of factory to obtain flyweight object instances without creating them again and again.

So, let's add a new method to our class that takes care of this. We'll call it  constant()  since it returns the constant value object instance for a given value.

This method will be  private  as well, so clients still have to use the construction methods ( OrderPriority::NORMAL()  and  OrderPriority::HIGH() ) as before.

class OrderPriority
{
    private const NORMAL = 'normal';
    private const HIGH = 'high';

    private static $instances = [];

    private $priority;

    public static function NORMAL(): self
    {
        return self::constant(self::NORMAL);
    }

    public static function HIGH(): self
    {
        return self::constant(self::HIGH);
    }

    private static function constant($value)
    {
        return self::$instances[$value] ?? self::$instances[$value] = new self($value);
    }

    private function __construct($priority)
    {
        $this->priority = $priority;
    }
}

Now, for every different constant value, only one single object instance will be created. The same instance will be returned for every call to methods like  OrderPriority::NORMAL() . And since there is only one instance per value, the  === strict comparison now works.

Constant definitions in interfaces

One tiny drawback of the approach shown above is that you cannot put such constant definitions into interfaces. The approach is based on object instances, which are a runtime concept. Interfaces, however, do not contain implementation code and thus cannot provide the necessary methods.

You can, of course, have a "constant value class" to provide the allowed values and then have your interface use it, for example as part of method signatures.

A nice trait

In our current draft of the  OrderPriority  class, everything besides the actual two constant values and the construction methods is pretty much boilerplate and would be the same for every "constant value class". So, let's move that to a reusable trait:

trait ConstantClassTrait
{
    private static $instances = [];

    private $value;

    final private function __construct($value)
    {
        $this->value = $value;
    }

    private static function constant($value)
    {
        return self::$instances[$value] ?? self::$instances[$value] = new self($value);
    }
}

With this,  OrderPriority  becomes:

class OrderPriority
{
    use ConstantClassTrait;

    private const NORMAL = 'normal';
    private const HIGH = 'high';

    public static function NORMAL(): self
    {
        return self::constant(self::NORMAL);
    }

    public static function HIGH(): self
    {
        return self::constant(self::HIGH);
    }
}

Casting to and from strings

Sooner or later, you might find yourself in a situation where you need to render an HTML form with something like a select list or radio button for an  OrderPriority . Or, you need to accept the  OrderPriorty  from a form or the command line as input.

Since we're now dealing with the  OrderPriority  class, we now have a perfect place to keep such additional methods:

class OrderPriority
{
    // Omitted trait and construction methods (like before)
    
    public static function fromString(string $value): self
    {
        if ($value !== self::NORMAL && $value !== self::HIGH) {
            throw new InvalidArgumentException();
        }
        
        return self::constant($value);
    }
    
    public function __toString()
    {
        return $this->value;
    }
}

You can now easily cast an  OrderPriority  instance to a string, for example when using it as the  <input value="..."> .

Now assume your task is to write the code that accepts a new  Order  from a web request or the command line. At your UI/code boundary, the order priority will clearly be available as a string. The  Order::create()  method, however, needs an  OrderPriority  instance.

Even somebody new to your project will quickly figure out that there are only a few ways to actually create  OrderPriority instances. They will probably find the  OrderPriority::fromString()  method and write code like this:

    // Somehow obtain $itemList
    $order = Order::place($itemList, OrderPriority::fromString($_REQUEST['priority']));
    // ... 

The bottom line is that the way we have written our  Order  and  OrderPriority  classes here makes it almost impossible to use them in a wrong way or to forget checking our inputs.

Even more value object perks

For a moment, assume your business comes up with a requirement to add a new  expedited  priority class. This service level is above the  normal  level, but does not yet make a  high  priority order.

I'll leave it to you as an exercise to add the  EXPEDITED  constant definition, a creation method and to update the  fromString()  method in our  OrderPriority  class.

What is more interesting is that we can now add an additional method to compare two priorities:

class OrderPriority 
{
    // ... as before

    public function atLeast(OrderPriority $other): bool
    {
        // Return true if $this->value is a priority equal to or above $other->value.
    }
}

With this, our new business rule might be something along the lines of

class ShippingFeeCalculator 
{
    public function computeShippingFees(Order $order): Money
    {
        // ...

        if ($order->getPriority()->atLeast(OrderPriority::EXPEDITED()) {
            // ... do what business requested
        }
    }
}

Being a value object, the  OrderPriority  class is a nice place to keep such additional comparison and computation methods which make it even more expressive.

Summary

This article described how simple class constants can be replaced with instances of a "constant value class". Methods that accept such constants can use type hints to make sure only valid constant values can be passed, without having to perform any additional checks. By reusing object instances, comparisons of constant values can also be written using the  ===  strict syntax check, with only minimal changes to code being necessary.

In addition to that, the constant value objects are a great place for keeping a particular kind of business logic.

]]>
Tue, 03 Sep 2019 15:27:21 +0200 /blog/expressive-type-checked-constants-for-php /blog/expressive-type-checked-constants-for-php webfactory GmbH webfactory GmbH 0
Spaß mit dem Silbentrennungsalgorithmus Diese Woche erreichte uns eine ungewöhnliche Meldung: unsere Ansprechpartnerin beim Gemeinsamen Bundesausschuss machte uns darauf aufmerksam, dass sie in ihrem Standardbrowser (Mozilla Firefox) keine verlinkten Texte mehr von der Website kopieren und in Word einfügen konnte — in Word kam nur noch der Text ohne Verknüpfung an. Eine schnelle Gegenprobe mit verlinkten Texten von anderen Websites ergab: das Problem trat nur auf der Seite www.g-ba.de auf.

Eine Anfrage wie diese löst oft widersprüchliche Gefühle aus. Einerseits macht es Spaß, eher obskuren Bugs auf die Schliche zu kommen, andererseits seufzt man innerlich ob der ungewöhnlichen Problematik.

Zum Glück konnten wir das Problem zügig eingrenzen: "Mit deaktiviertem Javascript funktioniert es", schrieb Stefan nach zehn Minuten. Einige Zeit später war klar, dass es an Hyphenopoly, einem Javascipt-basierten Polyfill für Silbentrennung lag. 

Silbentrennung – ein gelöstes Problem?

Wir setzen Hyphenopoly in Projekten ein, in denen Wert auf ordentlichen Flattersatz mit Silbentrennung in allen Browsern gelegt wird. Eigentlich unterstützen mittlerweile fast alle Browser Silbentrennung über eigene Wörterbücher und Regelwerke, die natürlich für jede Sprache unterschiedlich sind. Der Support für Deutsch ist insgesamt geringer als der für Englisch, aber Mozilla Firefox, Apple Safari, Google Chrome und demnächst Microsoft Edge haben Silbentrennung für die deutsche Sprache umgesetzt. Die große Ausnahme ist hier leider der Microsoft Internet Explorer (IE) in allen Versionen. Für Deutschland gibt StatCounter zwischen Mai und August 2019 zwar "nur" noch einen Anteil von ca. 7% für IE 11 an, beim Gemeinsamen Bundesausschuss liegt dieser aber deutlich höher: hier sehen wir in unseren Daten für IE 11 eine Quote von 25% für den gleichen Zeitraum. Diese Zahlen sowie der (Kunden-)Wunsch nach visueller Einheitlichkeit sind der Hauptgrund für unseren Einsatz von Hyphenopoly.

Hyphenopoly bringt von Haus aus eine sogenannte feature detection mit: zunächst wird nur ein kleines Skript geladen, das beim Aufruf der Website für ein konfiguriertes Testwort testet, ob der Browser eine erwartete Silbentrennung vornehmen würde. Nur wenn das Ergebnis negativ ausfällt, lädt Hyphenopoly das eigentliche Skript sowie die für die aktuelle Sprache nötigen Wörterbücher nach.

Regression in Firefox

Zurück zu unserem Problem. Die Tatsache, dass Hyphenopoly scheinbar verhindert, dass Verknüpfungen mit kopiert werden können, ist unschön, aber vielleicht nicht die Stelle, an der wir zuerst ansetzen sollten.

Was uns vor allem verwundert hat: Firefox unterstützt Silbentrennung für Deutsch, Hyphenopoly hätte also gar nicht in Aktion treten sollen! Ein kleiner Testcase bestätigte unseren Verdacht – tatsächlich schlug die Silbentrennung in Firefox fehl. 

In Firefox Version 68 wird das Wort "Silbentrennungsalgorithmus" nicht getrennt

Eine schnelle Suche im Bugtracker von Firefox blieb ohne Erfolg  – scheinbar hatte noch niemand ein Ticket erstellt. Kein Problem, wir hatten ja bereits einen Testcase. Zusätzlich konnten wir beweisen, dass die Silbentrennung in einer der letzten Versionen von Firefox noch korrekt funktioniert hatte. Genug Informationen für einen hoffentlich aussagekräftigen Bugreport.

In Firefox Version 64 wurde das Wort "Silbentrennungsalgorithmus" noch korrekt getrennt

Die Antwort traf nur wenige Stunden später ein: es war doch ein bereits bekannter Fehler, der in der folgenden Browserversion bereits behoben war. Mit einem Großbuchstaben beginnende Worte wurden nicht korrekt getrennt! Die gleichen Worte, komplett in Kleinbuchstaben, verhielten sich einwandfrei. Auch das konnten wir in unserem Testcase sofort nachvollziehen.

In Firefox Version 68 wird das Wort "silbentrennungsalgorithmus" korrekt getrennt, wenn es nicht mit einem Großbuchstaben beginnt

Abschließend konnten wir daher unser Hyphenopoly-Testwort anpassen (nur Kleinbuchstaben), das unnötige Laden des Polyfills auch in der aktuellen Version von Firefox verhindern und unsere Ansprechpartnerin informieren, dass sie ab sofort wieder Links von der Website kopieren und samt Verknüpfung in Word einfügen kann.

Eine kuriose Fehler-Kaskade aus dem Alltag in der Webentwicklung.
 

]]>
Thu, 22 Aug 2019 12:20:52 +0200 /blog/spass-mit-dem-silbentrennungsalgorithmus /blog/spass-mit-dem-silbentrennungsalgorithmus webfactory GmbH webfactory GmbH 0