Von Cracks und Luschen 26.01.2009, 00:00 Uhr

Offener Briefwechsel mit Ralf Westphal

Als Programmierer müssen Sie heute sehr schnell qualitativ hochwertigen Code schreiben, neue Technologie sofort erfassen und und und. Und solche gibt es. Man trifft sie auf Konferenzen und im Büro. Was ist aber mit den Menschen wie du und ich. Der Durchschnitt. Gibt es für den keine Hoffnung? dotnetpro-Chefredakteur Tilman Börner stellt diese Frage an Ralf Westphal: "Ralf, bist du auch manchmal ein Mensch wie du und ich?"
Lieber Ralf,
Im Studium gab es die Überflieger. Während die meisten den Inhalt einer Vorlesung erst nach massiver Nacharbeit meist viel später kapiert haben, diskutierten die Überflieger mit dem Professor schon den Inhalt künftiger Vorlesungsstunden.
Im Berufsleben setzt sich das fort. Da gibt es die Programmierer, die eine neue Technologie sofort erfassen und verstehen, sie sofort einsetzen können und die anderen – die Masse – die erst nach längerer Beschäftigung damit verstehen, wie sie funktioniert, wie sie eingesetzt wird und welchen Nutzen sie bietet.
Gleiches gilt für die Produktivität: Während die Cracks schon die ersten Klassen implementiert haben, überlegen die anderen noch, wie sie die Logik aufteilen sollen.
Du gehörst sicherlich nicht zu den letzteren. Aber: Hast du denn nie mal einen Durchhänger? Wo du etwas nicht verstehst? Eine Technologie, die du dir länger zu Gemüte führen musst, bevor du sie wirklich verstanden hast? Schreibst du nicht auch mal grottigen Code, für den du dich dann später schämst?
Tilman
Hallo Tilman,
Warum fragst du das?
Ralf
Hallo Ralf,

weil ich der Meinung bin, dass es viele gute Programmierer da draußen gibt, die aber eben nicht zu den Spitzenleuten gehören. Trotzdem könnte die Wirtschaft einpacken, gäbe es sie nicht. Diesen will ich Mut machen. 
Tilman
Lieber Tilman,
da stellst du interessante Fragen. Brauchen wir mehr echte Programmiercracks? Schreibt Ralf auch mal grottigen Code?
Lass mich die einfache Frage kurz abhaken. Wenn ich „grottig“ übersetze mit „schlecht evolvierbar“, dann kann ich nur sagen, ja, klar, solchen Code schreibe ich auch. Zum Glück heute weniger als früher. Wenn du meinen früheren Geschäftspartner nach dem Code fragst, den ich ihm in unserer Branchensoftware „vererbt“ habe… Dann wird er nicht nur freundliche Worte dafür übrig haben.
Doch das war früher, vor 15 Jahren oder so. Mit VB3 und VB4. Damals haben wir „Funktionalität, Funktionalität, Funktionalität“ gedacht – und so auch programmiert. Immer rein mit den neuen Features und kundenspezifischen Anpassungen. Und so sah der Code dann am Ende auch aus. Funktionierte irgendwie. Das reichte. Erstmal.
Heute achte ich natürlich sehr viel mehr auf meine Codequalität in Bezug auf Evolvierbarkeit. Seitdem ich mit dem Thema Softwarearchitektur durch die Lande ziehe, ist mir kaum ein Projekt zu klein, als dass ich nicht versuchen würden, lichtdurchfluteten Code (im Gegensatz zu „grottig“) zu schreiben. Das passiert dann auf mehreren Ebenen: Architektur, Codeorganisation, Automatisation und die Anwendung eines Wertesystems. Nicht umsonst habe ich gerade mit Stefan Lieser die Clean Code Developer Initiative (www.clean-code-developer.de) aus der Taufe gehoben.
Jetzt zum Knackpunkt: Schäme ich mich denn nie später für meinen Code? Selten. Ist der Code deshalb immer gleich erste Sahne? Nein. Ich schäme mich nicht, weil ich weiß, dass es unvermeidlich ist, schlechten Code zu schreiben. Hinterher ist man nämlich immer schlauer. Warum also schämen? Das behindert eher, weil es Vertuschung nahelegt. Nichts ist jedoch wichtiger, als „beschämenden Code“ ans Licht zu bringen und ihn besser zu machen. Statt also die Eselsmütze aufzusetzen, kremple ich lieber die Ärmel hoch.
„Schamlosigkeit“ bedarf jedoch steter Mühe in der Gegenwart. Wenn ich Code schreibe, bemühe ich mich nach Kräften, ihn gut zu machen. Das Wertesystem versuche ich ständig präsent zu haben und anzuwenden. Das ist natürlich kein Selbstzweck und so muss ich auch Kompromisse eingehen. Obwohl ich also Beschämendes sehe, tue ich nicht immer sofort etwas dagegen. Im vollen Bewusstsein produziere auch ich Code, der suboptimal ist. Das erlaube ich mir, weil ich viele „Design Issues“ eben sehe, die Produktivität im Moment jedoch höher einstufe – und gewiss bin, dass ich die Probleme schon bald behebe. Ich trage sie in eine Liste ein zur gefälligen Bereinigung am nächsten Tag oder in der nächsten Iteration. Kommt halt auf das konkrete Problem an.
Manche Probleme sehe ich natürlich auch nicht sofort, wenn ich den Code schreibe. Macht aber auch nichts. Beim nächsten Mal fallen sie mir dann auf oder beim übernächsten Mal und dann behebe ich sie oder trage sie ebenfalls in eine „Design Issue“-Liste ein.
Ich halte es insofern nicht für problematisch, suboptimalen Code zu produzieren. Problematisch ist, das womöglich nicht zu erkennen. Und problematisch ist, solche Probleme nicht zur Behebung einzuplanen wie ein Kundenfeature. Ignoranz und Prokrastination machen schlechten Code erst wirklich zu einem Problem.
Im Zusammenhang mit dem grottigen Code hast du auch noch nach „Durchhängern“ gefragt. Natürlich habe ich die – zumindest im weiteren Sinn. Bei Technologien stehen da die „Distributed Software Services“ (DSS) von Microsoft gerade oben auf meiner Liste. Die flutschen mir immer wieder durch die geistigen Finger wie ein Stück Seife. Oder neulich habe ich mich in XSLT-FO (bzw. XML-FO) einarbeiten müssen, also in die Definition von Drucklayouts mittels XML. Eine ganz eigene Welt mit speziellen Werkzeugen. Das geht alles selbstverständlich nicht in fünf Minuten und nach Lektüre eines Artikels gefunden durch Google.
Ich brauche also auch meine Zeit, um in Neues einzusteigen. Mal mache ich das via Google, mal eher mit Büchern. Mal ohne konkreten Zweck, einfach aus Interesse. Mal aus Notwendigkeit für ein Projekt.
Als echten „Durchhänger“ in deinem Sinne empfinde ich die Mühe der Einarbeitung jedoch meist nicht. Wenn etwas nicht klappt, wie ich es haben will, dann bin ich also nicht deprimiert. Ich lasse mir davon nicht die persönliche Energie absaugen. Das verstünde ich im engeren Sinn unter „Durchhänger“. Wenn es mal nicht weitergeht, dann suche ich mir entweder Hilfe ganz nach dem Sesamstraßenmotto „Wer nicht fragt bleibt dumm“. Oder ich erlaube mir, ein Thema zur „Inkubation“ zur Seite zu legen. Dann mache ich ein paar Tage oder auch mal Wochen etwas anderes. Wenn ich mich dann schließlich dem Thema wieder zuwende, ist es oft einfacher. So zum Beispiel mit der Concurrency Coordination Runtime (CCR) von Microsoft. Die erschloss sich mir nach den ersten Artikeln nicht so recht. Also habe ich sie auf Eis gelegt. Später war meine Motivation größer oder mein allgemeines Hintergrundwissen oder wasauchimmer und schon war die Einarbeitung ganz einfach.
„Durchhängen“ ist insofern aus meiner Sicht eher eine Frage der Haltung (ja, fast schon im doppelten Sinn) bzw. der Persönlichkeit. Dazu gehört auch der Anspruch, den man an sich stellt. Wer meint, alles gleich verstehen zu müssen oder keine Fehler machen zu dürfen, der wird wahrscheinlich öfter „durchhängen“. Soetwas sehe ich schon ab und an in der Entwicklergemeinde. Da gibt es teilweise überzogene Ansprüche oder gar Selbstüberschätzung.
Womöglich ist jedoch das Gegenteil weiter verbreitet: ein geringes Selbstbewusstsein. Wenn das unter Zeitdruck steht, ist der „Durchhänger“ vorprogrammiert. Das geringe Selbstbewusstsein meldet mehr oder weniger laut bei Verständnisschwierigkeiten „Ich bin zu doof dafür. Da begreife ich nie. Wer sich das ausgedacht hat, ist viel schlauer als ich.“ Damit beginnt dann eine verheerende Spirale. Denn wer so in die Welt blickt, der sieht immer eher Hindernisse als Herausforderungen. Der fühlt sich auch schnell überfordert durch das, was er nicht kontrollieren kann, z.B. die Technologieflut.
Hier rate ich zu einem gesunden Maß an Arroganz. Nicht zuviel, denn dann isoliert man sich, dann macht man zu. Dann wird die Welt schnell ganz böse. Dann sind die anderen sowieso immer schuld und man braucht den ganzen Krempel nicht – den man doch nur gerade nicht versteht oder für den man keine Zeit hat.
Ein gesundes Maß an Arroganz ist für mich, wenn ich mir zugestehe sagen zu dürfen „Die Zeit ist zu knapp. Ich kann es so schnell nicht verstehen.“ Das ist gerade wichtig, wenn andere mir vorschreiben, wie lange eine Einarbeitung dauern darf. Die Arroganz liegt hierin in einem unausgesprochenen „Mir doch egal, was du meinst, wie lange das dauern darf.“
Ebenfalls zur gesunden Arroganz gehört dann noch die Erkenntnis, das etwas womöglich schlecht beschrieben ist. Nicht ich bin zu doof, um etwas schnell zu begreifen, sondern der, der es erklärt, ist zu doof oder einfach unwillig, es vernünftig zu erklären. Im Augenblick habe ich zum Beispiel diese Haltung der DSS gegenüber. Die kriege ich nicht zu fassen, weil die Dokumentation grottig ist und der API nicht wirklich intuitiv. Dasselbe Gefühl entwickle ich auch öfter bei Open Source Angeboten. Die sind teilweise so schlecht beschrieben, dass ich kein Interesse habe, ihre Qualitäten durch mühevolle Entblätterung zu entdecken. Da bin ich mal arrogant König Kunde und sage, „Wer mir einen Service anbietet, der muss sich Gedanken um meine Situation machen.“ Wer dann aus Unfähigkeit oder Ignoranz nicht erklärt, der hat keinen Respekt für meine Zeit. Also erlaube ich mir auch, das gut gemeinte Angebot zu ignorieren.
Indem ich nun ausführlich deine einfachere Frage beantwortet habe, bin ich wohl ganz natürlich bei der schwierigeren angekommen: Brauchen wir mehr echte Programmiercracks?
Ich würd sagen, das kann nie schaden ;-) Aber realistisch ist natürlich die Annahme, dass auch die Programmierfähigkeiten normalverteilt sind. Die meisten liegen also in der Mitte, wenige sind sehr gut, wenige sind sehr schlecht. Das beziehe ich jedoch erstmal auf die heutige Ausbildung. Die Unternehmen stellen sich deshalb besser darauf ein. Wenn Joel Spolsky immer nur die besten einstellen will, ist das natürlich völlig ok. Das steht jedem frei. Aber der besten sind naturgemäß immer wenige. Wer sie nicht bekommt, weil Joel schon alle hat, der muss mit dem Mittelmaß vorlieb nehmen. Das soll jetzt aber nicht abwertend klingen. So ist es halt nur eben mit der Statistik.
Ich finde das auch nicht so schlimm. Denn Mittelmaß heute ist ja kein Urteil auf Lebenszeit. Nach meinem Menschenbild kann jeder immer noch dazulernen. Und ich glaube auch, dass es die allermeisten Softwareentwickler auch wollen. Eigentlich.
Damit wäre ich beim Kern deiner Frage: Was tun, wenn die Mehrheit der Softwareentwickler nur durchschnittlich sein kann? Was tun, wenn man mit ihnen produktiver oder kostengünstiger werden will? Auf sie verzichten und stattdessen ebenfalls mittelmäßige Entwickler in Indien anheuern?
Das halte ich für die falsche Strategie. Nicht nur ist solch simpler Austausch menschenverachtend. (Solange von „Human Resources“ gesprochen wird, liegt er allerdings wohl nahe.) Ich glaube auch, dass er am Ende kontraproduktiv ist. Weder wird in den allermeisten Fällen das Geld eingespart, dass man sparen möchte. Man muss sich auch fragen, was das volkswirtschaftlich für Folgen hat. Menschen, die ein Unternehmen einspart, verlieren ihre Kaufkraft. Noch schlimmer aber womöglich die Botschaft an folgende Generationen. Die hören davon, dass Menschen in der Softwareentwicklung Arbeit durch Off-shoring verlieren und überlegen sich dann sehr, sehr gut, ob sie so einen Job anstreben sollten, der ohnehin ein merkwürdiges Image hat. Besser wird es mit dem IT-Fachkräftemangel so auch nicht.
Ergo: Es hilft wohl alles nichts. Nur Aus- und Weiterbildung hilft gegen Mittelmaß. Wer das nicht in seine Unternehmensstrategie einbaut, der mokelt ewig mit Mittelmaß und produziert auch nicht mehr als Mittelmaß.
Fatalismus in doppelter Hinsicht – am Markt sind nur mittelmäßige Entwickler und wir können uns Weiterbildung nicht leisten, weil der Kunde sie nicht zahlt – halte ich für genauso falsch wie unreflektiert. Die Krise der Softwareentwicklung ist keine des Kenntnisstandes der Branche oder der Technologien oder der Werkzeuge. Ich sehe das Hauptproblem in mangelnder Aneignung des vorhandenen Kenntnisstandes, also in der Aus- und Weiterbildung, sowie in einer mangelnden Wertschätzung von Softskills.
Habe ich deine Fragen beantwortet? Was sagst du nun?
Liebe Grüße,
Ralf
Hallo Ralf,
Vielen Dank für deine ausführliche Antwort. Ich deute sie mal mit meinen Worten.
1. Für Code, der suboptimal ist, muss man sich nicht schämen. Aber verbessern muss man ihn, sobald man über ihn stolpert. Das fängt im Kleinen an, etwa das Aufteilen von Code-Blöcken in einzelne Methoden. Oder man wirft den Code als einen ersten Quick-and-Dirty-Entwurf weg und schreibt ihn neu. Hier hilft dann das, was man bei dem ersten Entwurf gelernt hat.
2. Jeder hat so seine Schwachpunkte, Technologien oder Themengebiete, die einem nicht liegen. Auch das ist kein Problem. Vielleicht hat man einfach noch nicht die richtige Lektüre gefunden, die einem den Stoff näher bringt, oder man braucht gewisse Zeit, um sich damit vertraut zu machen.
3. Lernen, lernen, lernen gehört zum Arbeitsalltag eines Programmierers. Wer meint, mit seinem VB6-Wissen auch in fünf Jahren noch tolle Software schreiben zu können, der irrt.
Eine gewisse Hoffnung für die nicht so guten/schnellen Programmierer ist das schon. Wie sieht es aber mit Leistungsdruck aus, der beispielsweise durch eXtreme Programming (Pair Programming) aufgebaut wird. Die Idee dahinter soll zwar gerade das verhindern, aber packe einen Crack und einen nicht so guten zusammen und du wirst sehen, dass der Crack den anderen immer mitziehen muss, oder?
Gespannt auf deine Antwort wartend,
Tilman
Hallo, Tilman!
 
Deine Zusammenfassung klingt gut. Lass sie mich aber noch kurz kommentieren:
Zu 1: Wir können nicht anders, als beim Schreiben suboptimal im Vergleich zu dem zu sein, was wir hinterher tun würden, wenn wir die Erfahrung gemacht haben. Das gilt im Kleinen für eine Methode und im Großen für eine Anwendung. Hinterher sind wir immer schlauer und würden es anders und allermeistens wohl auch besser machen. Die wesentliche Erkenntnis aus dieser Unvermeidbarkeit: Wir sollten immer ein Hinterher einplanen und uns dann auch die Zeit für die Verbesserung nehmen. Im Clean Code Developer Wertesystem (www.clean-code-developer.de) gibt es dafür die "Pfadfinderregel": Immer, wenn wir Code anfassen, sollten wir ihn in punkto Qualität (!) zumindest ein wenig besser hinterlassen. Wer nur neue Funktionalität hinzufügt, der lebt ewig im Vorher. Wer aber jedes Mal ein kleines Bisschen "aufräumt" (refaktorisiert), der blickt zurück und lässt die Erfahrung des Hinterher in den Code einfließen und macht ihn besser.
Zu 2: Auf jeden Fall braucht man Zeit, um sich mit verschiedenen und wechselnden Themen vertraut zu machen. Die muss man sich schaffen und auch eingeräumt bekommen. Dazu gehört persönlicher Wille sowie Managementunterstützung. Neben der Zeit fürs Selbststudium sollte man aber auch immer wieder den Kontakt mit anderen suchen. Im Austausch entsteht ebenfalls Wissen. Community in der Firma, regional und überregional ist wichtig. .NET User Groups helfen genauso wie online Diskussionsforen. Vor allem sollte man sich dort nicht erst tummeln, wenn man schon nicht mehr weiter weiß und das Projekt zu kippen droht. Ein Netzwerk zu spinnen braucht ebenfalls Zeit. Also regelmäßig ein wenig in dieser Hinsicht investieren.
Zu 3: Absolut! Weiterbildung muss Toppriorität haben. Weiterbildung ist ein strategisches Thema und insofern auch Sache des Managements.
Gerade gestern habe ich wieder einige Assessments mit Bewerbern auf Positionen in einem Projekt gemacht. Und wenn ich einen Aspekt herausgreifen sollte, in dem sich alle glichen, dann war es ihre Haltung zu Fortbildung. Deren Notwendigkeit betonten natürlich alle - aber systematisch betreiben tut sie keiner. So war es denn kein Wunder, dass auch die, die sich z.B. für ihre C#-Kenntnisse die besten Noten ausgestellt hatten, leider nichts zum Unterschied zwischen anonymen Delegaten und Lambda-Funktionen sagen konnten. Sie seien als Praktiker darüber einfach noch nicht in ihrer täglichen Projektarbeit gestolpert - so ihre Erklärung. Wenn man allerdings erst etwas lernt, wenn man darüber stolpert, dann ist das zwar verständlich, aber weder systematisch noch vorausschauend. Denn Lernen soll ja gerade Kompetenzen aufbauen, bevor sie dringend benötigt werden. Nur so können sie nämlich Planungen beeinflussen. Wer eine Kompetenz nicht hat und eine Technologie nicht schon kennt, der kann einfach nicht wissen, ob sich damit nicht die Produktivität deutlich steigern ließe.
Weiterbildung ist aus meiner Sicht eine Invariante. Sie muss nicht täglich gelten, aber über definierte Zeitabschnitte. 20% Weiterbildungsaufwand sind da nicht zu wenig gerechnet. Das können 90 Minuten pro 8 Std Tag sein oder 1 Tag pro Woche oder 2 Wochen im Quartal oder 2 Monate im Jahr. Hört sich viel an. Klar. Aber das ist Investition in die eigene "Employability" bzw. in die Fitness des Entwicklungsteams. Und niemand behauptet, dass die Weiterbildung keinen Bezug zu Projekten haben soll. Je mehr Unabhängigkeit davon desto besser, denn nur so können echte Innovationen entstehen, nach denen sich doch alle immer so strecken. Letztlich kann man sich aber auch das Entity Framework oder "Oslo" oder die CCR im Hinblick auf Projektbelange draufschaffen. Dann ist die Fortbildung eben gleichzeitig ein Spike (http://c2.com/cgi/wiki?SpikeDescribed).
Jetzt zu deinen Fragen:
Entsteht durch Pair Programming Leistungsdruck? Hm... der Gedanke ist mir neu. Ich würde eher sagen, das Gegenteil ist der Fall und war auch von XP immer so intendiert. Indem ich eben nicht mehr allein vor dem Code sitze, muss ich nicht mehr selbst auf alles achten. Zum Beispiel kann ich mich auf die Funktionalität konzentrieren, während mein Partner eher die Qualität im Auge behält. Das entlastet. Separation of Concerns im Implementationsprozess.
Wird der Crack speziell durch Pair Programming langsamer? Nein. Oder wenn doch, ist das in jedem Fall schlecht? Nein. Denn wenn der Crack durch Erklärung dessen, was er tut, langsamer wird, dann bildet er erstens einen anderen Entwickler aus und zweitens reflektiert er über sein tun. Beides kann nur von Vorteil sein.
Die allgemeine Erfahrung ist jedoch eher, dass Pair Programming die Entwicklung zumindest nicht verlangsamt. Allerdings erhöht sich die initiale Codequalität, weil ständig zwei Augenpaare auf den Code schauen und quasi einen permanenten Codereview durchführen. Das ist Gewinn ohne Investition, finde ich.
Ganz allgemein hast du aber natürlich Recht: Die Guten müssen in einem Team immer irgendwie die Luschen kompensieren. Mit Pair Programming hat das aber nichts zu tun. Der Effekt ist vielmehr universell und führt dazu, dass Projekte insgesamt ca. so produktiv sind wie die zweitschlechtesten Teammitglieder. Die Besten gleichen die Schlechtesten aus. Damit bestimmen die Zweitschlechtesten die Geschwindigkeit - zumindest über den Daumen. Was folgt daraus? Die Varianz der Qualität der Teammitglieder sollte gering sein. Schlechtere Teammitglieder sollten gefördert oder durch bessere ausgetauscht werden. Das ist wieder eine Aufgabe für das Management. Es kann nicht einfach nur Leute nach einem kuscheligen Vorstellungsgespräch ins Team werfen, sondern muss zum einen dafür sorgen, dass Leistungsunterschiede durch systematische Fortbildung ohnehin kleiner werden. Zum anderen muss das Management eine Vorstellung davon entwickeln, was denn überhaupt "gut" und "schlecht" in punkto "Programmierkunst" bedeutet. Meine Erfahrung - wieder gewonnen in vielen Assessments - ist, dass das Management in diesem Punkt oft keine Messlatte hat. Entwickler werden als "Eh da"-Kostenstellen betrachtet. Und weil sie eh da sind im Team, ist es auch nicht so wichtig, wie lange sie für eine Aufgabe brauchen.
Bitte das jetzt nicht verwechseln mit Aufwandsschätzungen. An Aufwandsschätzungen ist das Management natürlich interessiert. Es fragt seine Entwickler, wie lange sie meinen, für eine Aufgabe zu brauchen. Aber: das Management hat oft wenig Vorstellung davon, ob diese Schätzungen von einem guten oder schlechten Entwickler stammen. Beispiel: Der Manager fragt den Entwickler, wie lange er für eine Aufgabe braucht. Der Entwickler antwortet: 4 Wochen. Das kommt dem Manager lange vor, also drückt er einfach pauschal - weil ja eh immer zuviel geschätzt wird - auf 3 Wochen. Der Entwickler knirscht mit den Zähnen, aber die Aufgabe wird mit 3 Wochen terminiert. Leider hat der Manager kein Bewusstsein darüber, dass der Entwickler eher schlechteres Mittelmaß ist, weil er schon seit 5 Jahren keine systematische Fortbildung mehr betreibt. Er ist ja eh da und wurde doch als einer der besten irgendwann mal von der Personalabteilung eingestellt. Weil dem Manager dieses Bewusstsein fehlt, weiß er leider auch nicht, dass ein guter Entwickler mit modernen Technologien nur 1 Woche brauchen würde. Der Manager verbrennt also Kapital durch Ignoranz gegenüber systematischer Weiterbildung und den sehr unterschiedlichen Befähigungen von Entwicklern.
Dass ein Crack eine Lusche mitziehen muss, ist also eher ein Symptom eines tieferliegenden Problems, wie du siehst, wenn du meiner root cause analysis folgst ;-)
Was bleibt unterm Strich? Softwareentwickler haben sehr unterschiedliche Qualität. Das ist so. Aus verschiedenen Gründen. Aufgabe jedes Einzelnen und auch eines kostenbewussten Managements ist es daher, diese Unterschiede durch Weiterbildung auszugleichen. Dazu muss allerdings auch treten eine bessere Personalauswahl, die solche Unterschiede gar nicht erst krass werden lässt. Softwareentwicklung ist einfach kein Job, bei dem man einen Autopiloten einschalten kann. Sowenig wie Big Design Up Front (BDUF) ein geeigneter Weg ist, um zufriedenstellende Software zu planen, sowenig ist "Big Education Up Front" ein geeigneter Weg, um gute Entwickler zu bekommen.
Beste Grüße,
 
Ralf


Das könnte Sie auch interessieren