Über Legacy-Code ohne Maximalismus: Was tun?



    Stellen Sie sich vor, Sie hätten die Aufgabe, einen Teil des Codes zu korrigieren. Es werden viele Gedanken in meinem Kopf sein. Wer hat es geschrieben? Wann? Oder ist er ein Vermächtnis? Wo ist die Dokumentation? Versuchen wir, das "Erbe" gründlich und von allen Seiten zu behandeln. Andrey Solntsev @asolntsev ( http://asolntsev.github.io/ ), ein Entwickler der Firma Codeborne in Tallinn, wird uns in dieser Angelegenheit helfen . Fangen wir an.

    - Andrei, kennen Sie die Werke von Michael Feathers, zum Beispiel „Effektiv mit Legacy Code arbeiten“? Das Buch konzentriert sich auf die Bedeutung des Testens und hebt einen der Hauptunterschiede zwischen Legacy- und Nicht-Legacy-Code hervor - die Verfügbarkeit von Tests. Stimmen Sie dieser Meinung zu?

    Ich stimme absolut zu! Ich werde noch mehr sagen: Unit-Tests sind eine notwendige, aber nicht ausreichende Bedingung. Und mit Unit-Tests können Sie so stapeln, dass Herkules selbst nicht harkt.
    Was für ein echter Jedi-Masthav ist:
    1. TDD - das heißt, Tests VOR dem Code .
    2. Code bereinigen (und Tests bereinigen).


    Ich liebe Robert C. Martins Clean Code wirklich. Dies ist eine Desktop-Bibel für mich. Beraten Sie stark jeder. Sein Blog ist übrigens auch super.


    - Mit einem sauberen Code ist es klar. Was hat TDD damit zu tun? Code ohne Bugs ist nicht dasselbe wie guter Code?

    Jeder denkt, dass es bei TDD um Tests geht, was bedeutet, dass es langweilig ist.
    Unsinn!
    Bei TDD geht es um Entwicklung (testgetriebene ENTWICKLUNG). Dies ist eine Möglichkeit, Code so zu erstellen, dass er KEIN Vermächtnis ist. Damit es möglich ist, es zu unterstützen: debuggen, reparieren, umgestalten, modifizieren. Im Moment ist dies der einzige Weg, der der Menschheit bekannt ist. Alles andere ist vom Bösen, lass dich nicht täuschen.

    - Es gibt eine Meinung, dass TDD für Weicheier ist, und für starke Entwickler ist es genug, nur ein gutes Gehirn zu haben und den Code im Voraus zu überdenken. Dann wird es keine Bugs geben.

    TDD ist überhaupt nicht erforderlich, um Fehler zu finden.
    Ein Test ist die erste Verwendung Ihres Codes. Sherlock Holmes sagte: „Zuerst sammelst du die Fakten und erst dann baust du die Theorie auf. Andernfalls werden Sie unbewusst damit beginnen, die Fakten mit Ihrer Theorie in Einklang zu bringen. “ Sie werden nicht einmal merken, wie das passiert! So ist es auch mit dem Code: Wenn Sie einen Test vor dem Code schreiben, müssen Sie sich überlegen, wie es bequemer ist, ihn zu verwenden, wie die Klasse oder die Methode zu benennen ist. welche Parameter übergeben werden sollen. Und wenn Sie zuerst den Code schreiben, werden Sie anfangen, die Tests dafür zu jonglieren. Infolgedessen ist der Anteil der Tests zu kompliziert, der andere ist schwer zu beheben, und einige bleiben ungeschrieben. Und hier haben wir den Legacy-Code persönlich!

    - Setzen Sie die Diskussion über das Testen fort, welche Tests sind Ihrer Meinung nach richtig und in welchen Situationen, zum Beispiel Unit-Tests?

    Beginnen wir mit Unit-Tests. Sie sind in jedem Projekt notwendig, es gibt keine Optionen.

    Natürlich sind andere Arten von Tests wichtig: Integration, Benutzeroberfläche, Leistungstests. Dies ist in verschiedenen Projekten bereits unterschiedlich. Eines ist wichtig: Sie sollten eine Größenordnung kleiner sein als Unit-Tests. Über die Testpyramide weiß jeder Bescheid, hoffe ich.

    - Und wie soll die Codeabdeckung bei Tests sein? Ist 70% genug? Wie kann man mit der "Diagnose" des Projekts nicht zu weit gehen?

    Natürlich müssen Sie eine maximale Abdeckung anstreben. Das ganze Gerede über 30% oder 70% Deckung beruht auf Missverständnissen. Wir müssen uns um 100% bemühen (obwohl dies eine unerreichbare Grenze ist).

    Jeder weiß, dass eine hundertprozentige Abdeckung unmöglich ist, aber nicht jeder versteht, warum. Überhaupt nicht, weil "wir nur das Kritische testen müssen", "es keine Notwendigkeit gibt, Getter zu testen" und "wir haben wichtigere Dinge zu tun."

    Eine vollständige Abdeckung ist nicht möglich, da der Code in jedem System mit der Außenwelt kommuniziert. Zeichnen von Pixeln auf dem Bildschirm, Steuern von Geräten usw. - Unit-Tests sind für diesen Code nicht möglich. Sie müssen sie mit eigenen Augen überprüfen. Unsere Professionalität besteht darin, diese Schicht der „Kommunikation mit der Außenwelt“ so dünn wie möglich zu halten und die gesamte Logik daraus zu entfernen. Und dann muss es getestet werden.

    Grob gesagt, wenn überfällige Kredite rot hervorgehoben werden müssen, muss die Logik „Welche überfälligen Kredite“ in einer separaten Methode mit Komponententests und die „Hervorhebung“ separat herausgearbeitet werden. Na da, CSS oder was auch immer. Und TDD fördert die Trennung dieser Schichten, das ist großartig. Das ist seine Stärke! Und Tests sind nur ein Nebeneffekt.

    - Wie viel Zeit sollte für die Erstellung von Komponententests aufgewendet werden, und in welcher Phase des Projekts spielen sie eine Schlüsselrolle?

    Unit-Tests spielen in allen Phasen immer eine Schlüsselrolle. Es gibt keine Phase, in der "es Zeit ist, Komponententests zu schreiben" oder "Sie können keine Komponententests mehr schreiben".

    Wenn Sie alles richtig machen, können Sie nie die Frage beantworten, wie lange es dauert, Komponententests zu schreiben. Dies ist Teil der Entwicklung. Niemand fragt, wie viel Zeit es kostet, einen Ziegelstein mit einem Mörtel zu verteilen und wie viel zu verlegen. Dies sind alles notwendige Schritte und das wars. Du kannst keinen von ihnen werfen, sonst fällt deine Mauer am zweiten Tag auseinander und du bekommst ein paar alte Ziegel.

    - Wie ist Ihr Testschreibprozess?

    Sie schreiben einen roten Test für 10 Minuten, machen ihn für 10 Minuten grün, refaktorieren 10 Minuten. Natürlich misst diesmal niemand genau - manchmal ist es 5:30: 0 und manchmal 180: 5-60. Nicht wichtig. Es ist wichtig, dass Sie den Code in einem Monat und einem Jahr mit einer vorhersehbaren Geschwindigkeit mit derselben Rate ändern können. Langfristig ist eine konstante Geschwindigkeit viel wichtiger als eine hohe Momentangeschwindigkeit beim Start.

    Ich rate Ihnen zu diesem Video, in dem TDD klar und fröhlich gezeigt wird: „Der Junge hat es getan, der Junge hat es getan! "Seien Sie nicht durch die Länge alarmiert, es gibt nur ungefähr die ersten 30 Minuten über Maßeinheitstests.



    - Andrey, wenn TDD so nützlich ist, warum wird es so wenig benutzt?

    Alles ist einfach. TDD ist eine Disziplin. Es ist wie ein Sport: Jeder weiß, dass Sport nützlich, aber faul ist. Die ehrlichsten geben zu, dass sie faul sind, die anderen finden Ausreden, und die notorischsten finden Erklärungen, warum der Sport, wie sich herausstellt, sogar schädlich ist. So ist es auch mit TDD.

    Der lustige Unterschied ist, dass sich Menschen, die auf Sofas liegen, nicht als Sportler bezeichnen. Hier ist alles fair. Und Programmierer schreiben keine Tests und bezeichnen sich gleichzeitig als Entwickler. Unglaublich, richtig? Aber es endet immer gleich. Ein Athlet, der das Training verpasst, verliert schnell die Konkurrenz. Ebenso wird Code, der nicht durch Tests geschrieben wurde, sofort zum Erbe. Hier ist alles fair.

    TDD ist eine Disziplin. TDD ist nicht genug zu wissen, es muss jeden Tag verwendet werden, wenn der Code geändert wird. Sogar die wütendsten TDD-Fans vergessen und befinden sich immer wieder in einer unansehnlichen Position und schreiben vor dem Test öffentlich Code. Paarprogrammierung ist eine gute Hilfe, um damit umzugehen . Dies ist eine andere Praxis, die ich dringend empfehle.

    TDD ist ein Satz, der jeden Tag bewiesen werden muss.

    - Wir haben Probleme mit der Testabdeckung besprochen. Es ist wichtig, andere ältere Probleme wie die Kompatibilität zu behandeln. Es gibt Projekte, bei denen der Code nicht geändert wird, um die Kompatibilität mit noch älteren Bibliotheken zu gewährleisten. Wenn Sie Analogien zur Automobilindustrie ziehen, sind die Versuche, veraltete Komponenten und Baugruppen in neuen Konstruktionen zu verwenden, Ihrer Meinung nach fatal, und die durchschnittliche Codeversion im Projekt muss den Erwartungen der Zeit entsprechen?

    Ich werde dir eine Geschichte erzählen. Mein Bruder arbeitete im chemischen Labor der Universität von Tartu. Eine Delegation kam von irgendwoher aus Europa. Ihnen wurde alles gezeigt: neue Räumlichkeiten, neue Ausrüstung, alles. Und dann machten sie irgendwo in der Ecke auf die alte sowjetische Einheit aufmerksam. Die Delegierten machten runde Augen und fragten, warum wirfst du ihn nicht raus? Darauf folgte die Antwort: „Glaub es nicht! Weil er ... ARBEITET! "

    Es gibt keine einheitliche Antwort. Alle Abhängigkeiten können täglich aktualisiert und als wesentliche Hygiene behandelt werden. Sie können Maven oder Gradle sogar bitten, dies automatisch zu tun. Und Sie können die Gabel der ursprünglichen Bibliothek bilden und zwanzig Jahre auf der alten Version sitzen. Vielleicht hängt es von den Abhängigkeiten ab. Wenn ich stark von Selen abhängig bin, verwende ich neue Funktionen und aktualisiere sie oft. Wenn ich nicht von den neuen log4j-Funktionen abhängig bin, setze ich auf die alte Version. Alles funktioniert

    Je älter ich werde, desto eher neige ich dazu, Updates nicht zu verfolgen. Das neue Play-Framework war nicht besser als Struts2. Maven ist nicht besser (und noch schlimmer) als Ant. TestNG ist definitiv schlechter als JUnit (und immerhin "neue Generation" im Namen!). Hibernate3 war schwerer als Hibernate 2. Spring Boot ist schwerer als Spring MVC. Aber 10 Jahre sind vergangen! Ich schweige über die neuen JavaScript-Bibliotheken.

    Es ist also nicht alles neu, was mit Fett überzogen ist.

    - Sind Sie in Ihrer Praxis auf ähnliche Situationen gestoßen (zusätzlich zu der vorherigen Frage)? Wie sind Sie aus solchen Situationen herausgekommen? Welche Strategie verfolgen Sie, schreiben Sie alles neu (der Begriff „grüne Wiese“ wird häufig verwendet) oder führen Sie ein Refactoring durch?

    Natürlich getroffen.
    Ja, es ist nur eine Frage der Organisation. Wenn Sie das Gefühl haben, eine Art von Abhängigkeit zu aktualisieren, die inkompatibel mit der Vergangenheit ist, müssen Sie einfach Zeit dafür einplanen, mit dem Team abstimmen, damit in diesem Moment niemand etwas Dringendes hat, und umgestalten. Viele werden anfangen zu weinen: "Dafür haben wir keine Zeit." Nun, ich weiß nicht, vielleicht ist ein Update nicht so notwendig? Es wäre kritisch - sie würden Zeit geben.

    Was die grüne Wiese angeht, bin ich ziemlich skeptisch.
    Natürlich ist der Soldat, der nicht davon träumt, alles von Grund auf neu zu schreiben, schlecht.
    Aber in meinem ganzen Leben habe ich noch nie ein System gesehen, das von Grund auf neu geschrieben und verbessert wurde. Normalerweise ist es das Gleiche oder Schlimmeres. Der Kopist beginnt mit großer Aufregung, dann stößt er auf ein Problem mit einem anderen; versteht, dass er nicht mehr in der Zeit ist ... Lässt technische Schulden an einem Ort, an einem anderen - und jetzt haben Sie bereits einen Legacy-Code in einem neuen Projekt, obwohl die Hälfte noch nicht geschrieben wurde.

    Um etwas von Grund auf neu zu schreiben, müssen Sie genau wissen, wie und durch was Sie es besser machen können. Und warum sind Ihre Vorgänger gescheitert?

    - Vielleicht gibt es eine bewährte "Hybrid" -Option?

    Es gibt eine Hybridoption. Sie können einen Teil des Systems, das meiste Vermächtnis, von Grund auf neu schreiben. Und die alte Version auch zu lassen, damit sie parallel arbeiten. Und um schrittweise alle Teile des Systems nacheinander auf eine neue Version zu übertragen. Ja, es braucht Geduld und Zeit, aber das ist der einzige Weg. Widerwillen? Dann fang gar nicht erst an. Beeil dich hier oben.

    - Wie unterscheidet man einen fehlerhaften Legacy-Code von der Definition des maximal übertakteten? Lohnt es sich, die Leistung auf Kosten des zukünftigen Supports zu verfolgen?

    Übertakteter Code ist wie ein Dutzend Zeilen abstruser Operationen mit Bytes, damit er schneller funktioniert? Ich denke, dass ein solcher Code im wirklichen Leben aus der Kategorie der Geschichten stammt. Jeder denkt, dass nur coole Paprikaschoten das können, und sie wollen es auch lernen. In der Anwendungsprogrammierung wird dies fast nie benötigt.
    Und wenn Sie es immer noch müssen, stört es niemanden, diesen Code „übertaktet“ und gut lesbar und getestet zu machen. Komm schon, du bist ein Profi. Schreiben Sie zuerst Unit-Tests und übertakten Sie dann. Nicht überwältigt Unit-Tests? Es gibt nichts zu zerstreuen - die Nase ist nicht ausgereift.



    - Glauben Sie, dass Legacy-Code die Entwicklung des gesamten Systems verlangsamen kann?

    Natürlich kann es! Und es wird langsamer!
    Eigentlich ist das das Wichtigste, was sich normalerweise verlangsamt. Jede nachfolgende Änderung ist schwieriger durchzuführen, die Gefahr, etwas mehr zu zerbrechen.

    - Können Sie Ratschläge geben, wie Sie das schreckliche und langsame "Monster" im Projekt loswerden müssen, wenn Sie es sehen? Wie haben Sie darauf reagiert (wenn solche Situationen aufgetreten sind)? Haben sich die Änderungen positiv ausgewirkt (falls solche Situationen eintraten)?

    Sie haben wahrscheinlich von der Pfadfinderregel gehört: Lassen Sie die Lichtung etwas sauberer als vor Ihnen. Das heißt, nicht nur die gewünschte Zeile ändern, sondern auch ein wenig überarbeiten, den fehlenden Test hinzufügen. So wird Ihr Projekt ständig verbessert.

    Aber hier ist es wichtig, nicht zu weit zu gehen. Es ist notwendig, die Lichtung ein wenig sauberer zu machen und nicht den ganzen Wald zu pflügen, ohne zurückzublicken. Ich habe dies oft gesehen (und getan): Der nächste heiße Kopf beschließt, alles neu zu schreiben, geht für mehrere Stunden / Tage zu hartem Refactoring, bleibt stecken, ertrinkt und macht es infolgedessen nur noch schlimmer. Im besten Fall macht es seine Änderungen rückgängig und steigt mit einem leichten Zeitverlust aus.

    Das Reparieren des alten Codes ist sicherlich eine äußerst nützliche Übung. Ausgezeichnete Fähigkeiten im analytischen Denken, Umgestalten und Verstehen von gutem Code. Als Übung - rate ich.

    ABER.
    Das Reparieren eines alten Codes ist dasselbe wie das Hacken des Kopfes einer Hydra. Drei neue werden wachsen. Und es stellte sich heraus, dass die erste nicht vollständig abgeschnitten war, und sie hat dich nicht nur gebissen, sondern etwas Klebriges und Grünes ist herausgeflossen und hat alles verschmiert. Und dann kam der Manager und sagte: "Was zum Teufel hast du angefasst, hat es funktioniert?"

    Wenn Sie also den alten Code korrigieren, hoffen Sie ernsthaft, etwas im Projekt zu verbessern - viel Glück, Gesundheit und gute Laune. Irgendwo eine Datei, aber im Großen und Ganzen ändert sich nichts. Dies ist der Fall, wenn es notwendig ist, ein Symptom, aber eine Krankheit zu behandeln. Drücken Sie keine Pickel zusammen, sondern gehen Sie auf die Straße, um zu rennen. Verstehe, was das Problem wirklich ist. Warum wird in Ihrem Team schlechter Code geschrieben? Haben die Leute es zu eilig? Architektur nicht verstehen? Konflikte untereinander? Sie wissen nicht, wie Sie verhandeln sollen? All dies habe ich in realen Projekten mit klugen Erwachsenen kennengelernt. Und hier ist es notwendig, Variablen zu behandeln, aber nicht umzubenennen.

    - Sind Sie der Meinung, dass die Schönheit eines Codes kein Indikator für den Legacy-Status ist?

    Die "Schönheit" des Codes ist böse! Nennen Sie den Code niemals „schön“, auch nicht im Kopf. Das raffinierteste govnokod entsteht aus dem Wunsch, "schön zu machen". Der Code kann lesbar, vorhersehbar, prägnant sein - aber überhaupt nicht schön! "Schöner Code" ist wie ein "guter Held" in einem Essay über Literatur. Bemühen Sie sich um eine genauere Formulierung - und beantworten Sie gleichzeitig viele andere Fragen.

    - Kann man sagen, dass ein Verstoß gegen die Standardvereinbarung über die Gestaltung des Codes ein Vermächtnis ist?

    Standardkonventionen sind nützlich, überschätzen sie jedoch nicht. Alle Code-Konventionen werden noch schneller als der Code selbst vererbt. Niemand liest sie jemals. Der Schwan, die Krebse und der Hecht hatten Seile in Standardlänge - und hat das ihnen sehr geholfen?

    Und verschwenden Sie nicht Ihre Kraft für sie. Richten Sie die IDE aller Projektteilnehmer einmal ein, damit sie den Code selbst so formatiert, wie er sollte, und denken Sie nicht mehr darüber nach.

    - Im Rahmen von Legacy diskutierten wir Themen wie Testen, Leistung, Abhängigkeiten in Projekten, die Schönheit des Codes und gingen auf das Thema Entwicklung ein. Ihre Meinung über den Legacy-Code und die Gründe für sein Auftreten hat sich im Laufe der Zeit nicht geändert?

    Natürlich änderte es sich. Zuerst dachte ich, wie alle anderen auch, dass Inder und dumme Kollegen schlechten Code schreiben. Oder "Junioren". Aber so einfach ist das nicht.

    Ich mag keine zu einfachen Erklärungen. Es ist zu einfach, "diesen Idioten" die Schuld an allem zu geben. Und der Legacy-Code taucht bei den intelligentesten Leuten und bei den besten Projekten auf.

    - Und du?

    Oh ja. Oh ja!
    Hier sende ich so schlau über Legacy-Code und ich habe selbst ein Open-Source-Projekt Selenide , das ich nicht mit einem Legacy-Code kombiniere. Nein, es funktioniert großartig, die Benutzer sind glücklich, aber es ist schwieriger für mich, es im Laufe der Zeit zu ändern. Es gibt Tickets, die seit ein paar Jahren hängen, weil es mir wirklich schwer fällt, sie zu machen. Ändern Sie an einem Ort - bricht in einem anderen. Ja, es gibt Integrationstests, dank denen ich keine Angst habe, etwas zu zerbrechen. Aber es gibt keine Hilfe von ihnen in dem Sinne, dass das Ändern des Codes nicht funktioniert.

    Als mir klar wurde: Das Hauptproblem ist, dass ich in diesem Projekt ursprünglich keine Komponententests geschrieben habe. Es schien, warum Tests, wenn diese Bibliothek selbst zum Schreiben von Tests gedacht ist? Es wird schon längs und quer getestet. Aber es stellte sich heraus - da ist es, Mikhalych! Unit-Tests sind erforderlich, um Legacy-Code zu vermeiden.

    Nun, ich mache das: einmal alle sechs Monate oder jedes Jahr setze ich mich hin und schreibe mit einem Hund ein Modul zur Hölle. Da es ein Hobby ist, komme ich davon. Aber wenn es Arbeit wäre und in Geld ausgedrückt würde, wäre es eine Umschreibung wert? Oh, ich weiß nicht ... -

    Denken Sie, in welchen Schattierungen es sich lohnt, den alten Code zu erkennen? In welchen Fällen ist das gerechtfertigt?

    Ich habe ein einfaches Rezept. Machen Sie für eine Sekunde eine Pause von Lambdas und Klammern und stellen Sie sich an die Stelle des Klienten. Es reinigt das Gehirn großartig.

    Als Kunde bringen Sie Ihr Auto zu einem Autodienst, fragen, was dort klopft.
    Und der Mechaniker sagt zu dir: „Ich habe das Klopfen geändert, aber du hast auch eine undichte Kraftstoffpumpe, werden wir das ändern?“ Das ist ein guter Mechaniker. Ein schlechter Mechaniker würde sofort die Pumpe wechseln. Ein guter Mechaniker meldete ein Problem und bemalte Optionen: Sie können es jetzt ersetzen - es kostet so viel. Sie können nicht ändern, dann ist der Winter noch da, aber dann fliegen alle Schläuche - es wird dreimal so teuer sein. Und Sie selbst als Kunde entscheiden. Man wird sagen: warum zweimal laufen, alles ändern! Ein anderer wird sagen: „Jetzt gibt es kein Geld, aber ich brauche immer noch Winterreifen. Warten wir bis zum Frühling. “

    Wissen Sie, was der schlechteste Mechaniker tun wird? Schweig. Wird nur das tun, was angefordert wurde.

    Und wie verhalten wir uns alle, liebe Programmierer?
    Dieselben heißen Köpfe, die danach streben, alles sofort umzugestalten - sind sie wie wer? Das stimmt, wie ein schlechter Mechaniker. Und diejenigen, die „gereift“ sind und sich dafür entscheiden, alles so zu lassen, wie es ist? Ach, wie das Schlimmste. Was sollte ein guter Mechaniker mit altem Code tun? Wie oft machen wir das? Denk darüber nach.

    - Andrei, TDD, Unit-Tests - all das hört sich gut an, aber Sie verstehen, dass dies für 99% unserer Leser aus verschiedenen Gründen unerträglich ist, oftmals außerhalb ihrer Kontrolle. Und können Sie endlich ein einfaches Rezept für den Umgang mit altem Code geben?

    Sie wollen ein Rezept, aber wenn ich ein Rezept gebe, das sich als zuverlässig erwiesen hat, sagen Sie, dass Sie dafür keine Zeit haben. Und beschweren Sie sich weiterhin über den alten Code. Was erwartest du von mir, du hast eine rote Pille getrunken und bist schon in der Matrix? Es wird keine Pillen geben.

    Menschen sind wie Menschen. Sie beeilen sich gerne, aber es war schon immer so ... Die Menschheit liebt einfache Rezepte ... Im Allgemeinen erinnern sie an die ersteren ... Die Microservice-Frage hat sie nur verwöhnt ...

    Im Allgemeinen wird es keine magische Entsorgung des Legacy-Codes geben. Aber du bleibst dran, viel Glück, gute Laune!

    - Vielen Dank für das offene und positive Gespräch. Hoffen wir, dass die Leser feststellen werden, obgleich nicht einfach, aber dennoch Entscheidungen im Kampf mit dem Erbe. Ein kürzlich veröffentlichter Artikel ist eine direkte Bestätigung der Wichtigkeit von Tests. Sie haben mich persönlich überzeugt.

    Vielen Dank für die Einladung.
    Und ich werde die Situation nutzen und alle Leser einladen, uns in Tallinn zu besuchen. Wir haben eine wunderschöne mittelalterliche Stadt, gutes Craft Beer und großartige Veranstaltungen für IT-Leute, bei denen jeder kostenlos mitmachen kann: devclub.eu

    Vielen Dank für Ihre Aufmerksamkeit und Ihre Geduld!



    Weitere interessante Berichte, technische und Hardcore-Berichte, finden Sie im Joker 2016-Programm . Wenn Sie mit Legacy arbeiten, sollten Sie die folgenden Berichte beachten:


    Und auch einen unveröffentlichten Bericht von Vyacheslav Lapin, "Wie ich ein großes altes Unternehmensprojekt in Java 8 übersetzt habe - Tricks, Tricks und" Unterwasser-Kami "."

    Jetzt auch beliebt: