Die aktuellen Trends bei der Entwicklung und Bereitstellung von dedizierter Software für Unternehmen haben einen großen Einfluss auf das Outsourcing Modell. Dies ist eine sehr komfortable Lösung, da der Kunde (Auftraggeber) nicht die gesamte Programmierabteilung warten muss. Stattdessen kann es IT Outsourcing Services in Anspruch nehmen und Spezialisten und Experten einstellen, die das fertige Produkt professionell liefern. Mit dieser Lösung entfällt das Problem der Investition in die Schulung Ihrer eigenen Programmierer, Tester, Analysten und sogar IT Manager. Es ist ein bequemer und flexibler Ansatz. Die Vorteile liegen auf der Hand und der Beweis ist die ständig wachsende Nachfrage nach Outsourcing von IT Spezialisten sowie die ständig wachsenden Software Houses.
Was wäre, wenn es anders gemacht würde als alle anderen? Hat die Schaffung einer Abteilung, die für die Bereitstellung von Software in einem Unternehmen zuständig ist, das wenig mit der IT zu tun hat, Sinn und Erfolgschancen? Wahrscheinlich ja, schließlich kann man immer qualifizierte Mitarbeiter einstellen, die alle Prozesse abwickeln und ein Team aufbauen. OK, lass uns jetzt die Messlatte höher legen. Was wäre, wenn wir uns entschließen, ein Team aufzubauen, das sich ausschließlich auf Mitarbeiter stützt, die das Geschäft ihres eigenen Unternehmens sehr gut kennen, aber zuvor noch nichts mit Programmierung und der IT Branche zu tun hatten? Darüber hinaus ist es das Ziel, innerhalb weniger Monate ein Produktionsmanagementsystem von Grund auf neu zu erstellen und einzuführen. Klingt das nach einem verrückten Plan? Vielleicht, aber in diesem Beitrag möchte ich zeigen, dass es zwar Wahnsinn ist, aber es hat Methode. Ich lade Sie ein, eine Case study eines Unternehmens zu lesen, das sich dazu entschlossen hat, diesen Weg zu beschreiten und sein eigenes Programmierteam auszubilden.
Beginnen wir mit der Präsentation des Firmenprofils des Kunden. Es ist eine große Organisation, die in der Automobilindustrie tätig ist und Niederlassungen in mehreren Ländern hat. Die Haupttätigkeitsbereiche umfassen die Herstellung von Fahrzeugausrüstungen. In einer der Niederlassungen hat das Unternehmen ein System zur Überwachung, Steuerung und Planung der Produktion implementiert. Es ist ein System, das von einem (!) Mitarbeiter geschrieben und gepflegt wird – von leidenschaftlichen und autodidaktischen Programmierern. Dieses System funktioniert sehr gut, aber es war ohne die Verwendung von Architekturmuster geschrieben, gute Programmierpraktiken und auch ohne die Verwendung eines Versionskontrollsystem! Um es in späteren Produktionsanlagen entwickeln und implementieren zu können, war es notwendig, es professionell mit den besten Techniken und Werkzeugen umzuschreiben. Aus diesem Grund wandte sich der Kunde an Transition Technologies PSC. Innerhalb von ca. 8 Monaten haben wir ihm geholfen, das Ziel zu erreichen, ein geeignetes System zu schreiben und gleichzeitig Know-how über den gesamten Softwareentwicklungsprozess zu übertragen. Es ist erwähnenswert, dass die Arbeit mit dem Kunden fast zu 100% aus der Ferne erfolgte. Später in diesem Artikel werde ich mich darauf konzentrieren, wie es in so kurzer Zeit möglich war, 4 Entwickler von praktisch null auf solide Junioren und bei einer Person sogar auf das Niveau eines normalen Developers auszubilden.
Schritt 1 – Schulungen und Workshops
Der erste offensichtliche Schritt ist das Erlernen der Grundlagen für den Einstieg. Das Projekt sollte in .NET Core Technologie erstellt werden, da wir uns für Jira als Projektmanagement Tool entschieden hatten, und der Quellcode sollte von Bitbucket aufbewahrt und verwaltet werden. Um eine kontinuierliche Integration zu gewährleisten, haben wir Jenkins vorgeschlagen. Zunächst haben wir eine Reihe von Schulungen zu den oben genannten Themen gestartet. Innerhalb einer Woche haben wir durch die Organisation der folgenden Schulungen einen soliden Wissenszuwachs erzielt:
- Jira user training,
- Git developer training,
- BitBucket developer training,
- Visual Studio training,
- Development process workshop,
- Jenkins developer training.
Jede dieser Schulungen musste von Grund auf durchgeführt werden und dauerte bis zu 8 Stunden, sodass es sich nur um eine Einführung in das Thema handelte. Um mehr über diese Probleme zu erfahren, sollte das Team 3-4 Wochen lang alleine trainieren, hauptsächlich mit: C#, ASP.NET MVC Core, Entity Framework Core, JavaScript und jQuery (ja, gute alte jQuery – ich dachte, dass moderne JS Frameworks wäre für Anfänger zu hoch). Dabei spielte der Zugriff auf die Plattform mit einer großen Datenbank qualitativ hochwertiger Online Schulungen eine wichtige Rolle. Darüber hinaus ist zu erwähnen, dass einige Programmierer im Rahmen des Selbststudiums kurz vor Beginn der Arbeit am eigentlichen Projekt unabhängig an ihren eigenen Entwicklungsprojekten gearbeitet haben und diese Projekte dann überprüft wurden. Dank dessen konnten die ersten Kommentare zum Beginn der Programmierung bereits in der Phase der „Demo Projekte“ abgegeben werden, und die Person, die das richtige Projekt einleitete, verfügte bereits über umfangreichere Erfahrungen bei der Umsetzung des Demo Projekts.
Zu einem späteren Zeitpunkt des Projekts organisierten wir etwa alle zwei Monate 2-3 Tage On-Site Workshops beim Kunden. Es war der Moment, in dem wir die am Projekt beteiligten Personen zu dem gerade benötigten Thema erklären und schulen konnten. Es ist viel bequemer, alle störenden Fragen zu beantworten und die erforderlichen Informationen während eines Meetings privat mit einem Projektor oder einer Tafel weiterzugeben, an der man einige Dinge zeichnen und sich auf ein schwierigeres Thema stützen kann.
Schritt 2 – Controlling, Mentoring, Beratung
Als wir mit dem ersten Sprint begannen und an dem richtigen Projekt arbeiteten, beschäftigte sich mein vierköpfiges Programmierteam immer noch mit neu erlernten Themen wie im Nebel. Sie hatten großen Ehrgeiz und große Lernbereitschaft. Es war keine Zeit, sie auf einem ausreichend hohen Niveau auszubilden und erst dann das Projekt zu starten. Wir mussten hier und jetzt anfangen. Glücklicherweise kannten und akzeptierten alle das Risiko, dass das Team noch lernt. Es lag in meiner Verantwortung, das gesamte Projekt in Schach zu halten. Das Wichtigste für den Kunden war, ein qualitativ hochwertiges Produkt zu schaffen, auch wenn die Ausführung der Aufgaben verzögert wurde. Ich habe alle verfügbaren Tools verwendet, um meine Arbeit zu erleichtern. Dank Jira, der unsere einzige Quelle der Wahrheit über das Projekt war („one source of truth“), war es jederzeit einfach, den aktuellen Stand der Arbeit zu überprüfen und Probleme zu identifizieren.
Dank der Pull Requests von Bitbucket musste jede Aufgabe oder Fehlerbehebung meine Code review durchlaufen, bevor sie in den haupten Branch migriert wurde. Anfangs gab es, selbstverständlich, viele Kommentare. Meistens handelte es sich nicht nur um Vorbehalte gegen den Code selbst, sondern auch gegen unsachgemäße Arbeit mit git. Es stellte sich zum Beispiel heraus, dass, wenn jemand mehrere Aufgaben parallel bearbeitet und mehrere „Feature Branch“ hat, wenn eine Änderung auf einen von ihnen angewendet werden muss, die Änderung zuerst auf dem Branch landete, auf dem sie gerade arbeiteten, und dann manuell kopiert und angewendet wurde auf allen anderen Branchen. Dies bedeutete, dass ein Feature Branch Code hatte, der sich auf einem völlig anderen befinden sollte. Dies führte zu vielen Merge-Konflikten. Die Vorteile in Bezug auf Codetrennung und Branch-per-Task-Arbeit wurden erst nach einem erneuten Training im git vollständig verstanden und konzentrierten sich nur auf die Bereiche, in denen es tatsächlich Probleme gab. Sofern ich zuvor nicht mit Schwierigkeiten bei der korrekten Arbeit mit Git gerechnet hatte, war ich mir fast sicher, dass Probleme mit dem Verständnis und der ordnungsgemäßen Umsetzung von Aufgaben in Übereinstimmung mit der vorgeschlagenen Architektur und guten Prinzipien wie SOLID auftreten. Ich wusste, dass es für ein unerfahrenes Team tatsächlich schwierig sein könnte, diese Dinge in den Griff zu bekommen. Deshalb habe ich mich darauf konzentriert, alle zu schulen, was SOLID ist, und einfache Beispiele zu zeigen, wie man mit diesen Methoden Code schreibt und warum dies so wichtig ist. Außerdem wollte ich eine der ersten User Stories implementieren, die das Durchlaufen aller Systemebenen erfordert, und dies als Beispiel zeigen. Ich habe versucht, alle anderen Fehler während der Code Review regelmäßig zu korrigieren, was am Anfang auch ungewöhnlich aussah. Wieso? Sie haben wahrscheinlich vermutet, dass es viele Fehler gab. Es war äußerst wichtig, dass meine Ausführungen sachlich und konstruktiv sind und dass sie vermitteln, warum etwas falsch gemacht wird, wie es besser gemacht werden kann und warum eine andere Lösung wirksamer ist. Dies erforderte oft zusätzliche Erklärungen, bei denen wir den freigegebenen Bildschirm verwendeten, um die Bedeutung einer bestimmten Bemerkung zu verdeutlichen und sicherzustellen, dass sie gut verstanden wurde. Dieser Ansatz zielte darauf ab, ähnliche Fehler in Zukunft zu beseitigen. Darüber hinaus baute es eine gute Beziehung zum Programmierer auf, da Kommentare nicht als Anhaften oder Böswilligkeit, sondern eher als der Wunsch, mein Wissen und meine Erfahrung weiterzugeben („Sieh, wie du es anders machst, dann wird es aus dem einen oder anderen Grund besser sein“). Durch diese systematische und mühsame Arbeit sammelte das Team schnell Erfahrungen. Und das bestmöglich, weil sie aus ihren eigenen Fehlern gelernt haben. Sie haben selbst empirisch erlebt, warum die Code Wiederholung in vielen Fällen schlecht ist, warum das Mischen von Verantwortlichkeiten schlechte Ergebnisse bringt, warum die Namenskonventionen wichtig sind, wofür die Unit Tests sind, für die man so viel Zeit aufwenden muss usw.
Wie in jedem Projekt musste man sich manchmal über ein schwierigeres Thema hinwegsetzen und sich eine gute Möglichkeit überlegen, es umzusetzen. Diese Art von Problemen wurde am häufigsten als Diskussionsthema in On-Site Workshops geplant, die beim Kunden abgehalten wurden. Wir könnten zusammen in einem Raum sitzen und frei ein Brainstorming durchführen, gefolgt von einem Entwurf und den Details der Lösung. Für Programmierer war es auch eine aufstrebende Erfahrung. Sie lernten, nach Lösungen für wichtige und komplexe Geschäftsanforderungen zu suchen, um auch die Effizienz, Skalierbarkeit und Sicherheit des gesamten Systems zu berücksichtigen. Durch diesen Prozess lernten sie, ihre Aufmerksamkeit nicht nur auf das diskutierte Problem zu richten, sondern auch dessen Auswirkungen auf das Gesamtsystem zu analysieren.
Solche Arbeiten brachten messbare Vorteile. Fortschritte waren auch bei Sprint Retrospective Meetings sichtbar. Die Developer sagten, was sie in einem bestimmten Sprint gelernt haben. Darüber hinaus war klar, wie nachfolgende Vorschläge zur Projektverbesserung aus unserem Lessons Learned Register umgesetzt wurden und wie sich dies auf die Qualität und Produktivität der Arbeit auswirkte, die anhand von Burndown- und Velocityberichten gemessen wurden. Es zeigte sich auch, dass die Code Review immer weniger Kommentare enthielt und Pull Requests schneller zusammengeführt wurden.
Schritt 3 – Vorbereitung auf selbständiges Arbeiten
Der letzte Schritt bestand darin, die Teammitglieder auf die Arbeit als unabhängige Programmierer vorzubereiten, die grundlegende Programmiertechniken und -muster in .NET kennen, verstehen und anwenden. Sie sollten in der Lage sein, die häufigsten Programmierprobleme zu lösen (oder nach geeigneten Werkzeugen zu suchen). Es ist auch wichtig, dass sie durch eine Code Review Fehler im Code eines anderen Programmierers identifizieren können.
Der Einstieg in dieses Level verlief schrittweise. Als zunächst klar wurde, dass der Programmierer immer weniger schwerwiegende Fehler macht, diese selbst bemerkt und Hilfe nur für schwierigere Aufgaben benötigt, haben wir ihm die Rolle des Reviewers übertragen. Von nun an konnte er andere Code Reviews durchführen und Pull Requests annehmen, diese erforderten jedoch zusätzliche Überprüfungen durch einen zweiten Reviewer (so genannte Double Checks). Dies brachte ihm eine andere Sichtweise bei, da nicht nur sein Code von nun an überprüft wurde, sondern er auch die Möglichkeit hatte, den vom Team geschriebenen Code kritisch zu betrachten und Fehler an andere Autoren zu melden. Außerdem konnte er mit dem Double Check noch einmal auf die Pull Request schauen und sehen, welche anderen Fehler vom zweiten Reviewer gemeldet wurden, die er nicht aufgegriffen hatte. Ein zuvor erstelltes Dokument – Developer Guide, das die Prinzipien der korrekten Codierung im Projekt aufzeigt, half bei der Bewertung. Wenn der Programmierer eine gute Anzahl von Code Reviews durchführte und deren Qualität zufriedenstellend war, wurde er ein unabhängiger Reviewer. Von da an führte seine Annahme der Pull Request dazu, dass die Request in den Branch zusammengeführt wurde.
Auf diese Weise erreichten wir das Stadium, in dem sich das Team bereits auf dem Niveau zuverlässiger Junior Developer befand, und bei mindestens einem von ihnen war es bereits das Niveau eines Regular Developer. Dank dessen musste das Team nicht mehr ständig weiter betreut, kontrolliert und gelernt werden. Das Team könnte sich eigenständig weiterentwickeln. Bei schwerwiegenden Problemen, deren Lösung viel Wissen und Erfahrung erfordert, ließ der Kunde im Vertrag nur die Möglichkeit der Beratung und Schulung in fakultativer und kurzer Zeit.
Zusammenfassung
War ein solches Experiment, das darin bestand, ein Team zu bilden, das auf Menschen ohne Erfahrung und ohne die erforderlichen Programmierkenntnisse basiert, erfolgreich? Auf jeden Fall! Das Projekt wurde wie geplant umgesetzt. Die ersten Sicherheitstests, bei denen nur ein schwerwiegender Vorfall festgestellt wurde, wurden sehr gut bestanden. Am Ende der Zusammenarbeit und meiner Rolle im Projekt wurde die Software für die Implementierung in der Produktion vorbereitet. Eine vollständige Beurteilung der Qualität des Projekts und der Frage, ob es erfolgreich sein wird oder nicht, ist natürlich erst nach einer gewissen Betriebszeit in der Produktion möglich. Ich möchte jedoch betonen, dass bei alledem der Erwerb von Kompetenz und Know-how im Zusammenhang mit der Softwareentwicklung ebenso wichtig war wie die Umsetzung des Projekts. Dank dessen kann der Kunde diese Kompetenzen aufbauen und ausbauen, indem er das Team um weitere Spezialisten erweitert, nicht nur um Programmierer, sondern auch um Tester, Analysten und DevOps.