Codestil als Entwicklungsstandard

Lassen Sie uns gleich los, es geht nicht um Klammern. Hier werden wir darüber sprechen, wie unser Gehirn funktioniert und warum der Codestil dazu beiträgt, die lineare Entwicklung des Projekts sicherzustellen, die Anpassung neuer Mitarbeiter erheblich zu beschleunigen und im Allgemeinen die Entwicklungskultur zu formen und auszubilden. Ich habe versucht, in einem Artikel mehrere Studien und Prinzipien über die Arbeit des Gehirns des Entwicklers und darüber, wie Programmierer den Code lesen, zu sammeln, und habe auch die Ergebnisse eines persönlichen Experiments geteilt.

Interessant? Willkommen bei Katze.



Hallo! Mein Name ist Anton, ich schreibe Backend in ManyChat. Kürzlich hatten wir ein Mitap für die PHP-Entwicklung, in dem ich einen Vortrag über den Codestil als einen der Entwicklungsstandards hielt. Auf Rückmeldung ging er gut zu den Gästen der Veranstaltung, und wir beschlossen, den Bericht über Habr zu entschlüsseln. Für diejenigen, die die Wirkung persönlicher Präsenz besonders schätzen und eher ein Video als das Lesen von Texten sehen möchten, senden wir eine Sendung, die ab sofort verfügbar ist. Sie finden es hier. Für diejenigen, die Longrid lieben, willkommen weiter.

Unser Gehirn ist ein neuronales Netzwerk


Es lohnt sich, mit einer Beschreibung zu beginnen, wie es im Allgemeinen funktioniert und warum Sie alles brauchen, worüber ich später sprechen werde. Viele von Ihnen kennen das Konzept eines neuronalen Netzwerks oder haben zumindest diesen Satz gehört, der seit mehreren Jahren fast ein Symbol für Hype im IT-Bereich und im Marketing ist. Schon jetzt fügen viele Unternehmen ihren Produkten „AI-basierte“ Produkte hinzu, wie beispielsweise den Aufkleber „Non-GMO“ auf Knödeln. Das neuronale Netzwerk arbeitet nach dem Prinzip der Mustererkennung und ist äußerst effektiv bei der Arbeit mit homogenen Daten. Dies sind Bilder, Videos, Ton usw. Das Highlight, das mit Code-Styling zu tun hat, ist das Prinzip, auf dem sie aufgebaut sind. Perceptrons, Netzwerkzellen, wurden als Gehirnprozesse beschrieben und festgelegt, lange bevor sie aufgrund der geringen Rechenleistung in ein funktionierendes, funktionsfähiges und effizientes Netzwerk implementiert werden konnten. Unser Gehirn ist zwar viel leistungsfähiger, arbeitet aber auf ähnliche Weise. Infolgedessen nutzt eine Person die Kraft eines trainierten neuronalen Netzwerks von der Geburt bis zum Tod, und das Training ist nahezu nahtlos.

Wir nehmen also nur Bilder wahr. Für das Gehirn gibt es keine Texte, Geräusche und andere Dinge - all dies nehmen wir erst nach Zersetzung wahr. Grob gesagt trennen wir Bilder „Pixel für Pixel“, fügen sie dem Speicher hinzu und erkennen dann mit Hilfe des assoziativen Denkens verschiedene Objekte. Dank dessen können wir verstehen, ob wir vor der Schlange weglaufen oder ein Fahrrad besteigen und auf die Pedale treten sollten. Hier ist ein Diagramm eines Standard-Perzeptrons, das zeigt, wie die Klassifizierung von Objekten erfolgt. Für diejenigen, die mit dem Prinzip des Perzeptrons nicht vertraut sind, mag es ein wenig chaotisch aussehen. Dank eines solchen Ausgleichs- und Wiegeschemas erkennt das neuronale Netzwerk Bilder jedoch schnell und effizient.

Bild

Aus der Programmierung können Sie sich an das DuckType-Prinzip erinnern, wenn angenommen wird, dass ein Objekt, das wie eine Ente schwimmt, wie eine Ente fliegt und wie eine Ente quakt, eine Ente ist. Eine eigentümliche Annäherung an die Erkennung von Objekten. Und für unser Gehirn erfolgt die Objekterkennung sofort. Training ist ein viel längerer Prozess. Daher können Sie sich diesen Prozess sowie die Ausbildung eines kleinen Kindes vorstellen, das nur Wörter lernt. Sie nehmen einen Apfel, zeigen und sagen: "Dies ist ein Apfel." Nehmen Sie einen anderen und wiederholen Sie noch einmal: "Dies ist ein Apfel."

Bild

Und so weiter, bis das Ergebnis feststeht. Grün, gelb, rot, kugelförmig, länglich, mit und ohne Stecklinge, schwarz und weiß. Jahr für Jahr baut das Kind seine Basis auf empirischen Erkenntnissen auf. Ich denke, das Prinzip ist klar. Wir machen dasselbe, wenn wir ein neuronales Netzwerk trainieren. Von Objekt zu Objekt oder genauer von Bild zu Bild.

Wie ein Programmierer Code liest


Das gleiche passiert, wenn wir mit Code arbeiten. Wir öffnen die Seite, studieren sie, zerlegen sie in Blöcke, identifizieren verschiedene Teile - wir trennen leicht Eigenschaften von Funktionen, Isolationsstufen von Methoden und Eigenschaften, finden Konstanten und so weiter. Wir identifizieren dies alles durch Blöcke. Daher ist es ein wichtiger Aspekt des Code-Stils, den gesamten Code in dieselbe Form zu bringen. Dies ist ein Schlüsselfaktor, der die Lesbarkeit des Codes kennzeichnet.

Warum ist das wichtig? Weil ein Programmierer die meiste Zeit Code liest. Eine direkte Korrelation wurde nicht gefunden. Zum größten Teil hängt sie von den Qualifikationen, der Sprache (z. B. wird Python eingerückt und falsch strukturierter Code funktioniert einfach nicht), der Codequalität usw. ab. Aber in 50% der Fälle dauert es, Ihren eigenen und den Code eines anderen zu lesen. Wenn der Code komplex ist, kann der Indikator 75% erreichen, und wenn der Code wirklich schlecht ist, können 95% der Zeit damit verbracht werden, zu lesen und herauszufinden, wo eine Zeile hinzugefügt werden muss, um einen Fehler zu korrigieren. Und jetzt die Frage. Was tun Sie, wenn Sie feststellen, dass Ihr Code 75% seiner Zeit damit verbringt, eine Festplatte zu lesen oder doppelt verknüpften Listen Speicher zuzuweisen? Der Programmierer wird versuchen, diesen Prozess zu optimieren, den Algorithmus zu ändern, eine effizientere Speicherstruktur anzuwenden usw. Als die aufgewendete Zeit kritisch wurde, begann ich diesen Prozess zu inspizieren. Und man könnte sagen, es ist das Gehirn, es ist viel leistungsfähiger als jeder Computer und kann ungefähr ein Petabyte Daten speichern. Bei der Entwicklung meines mentalen Rahmens für die Arbeit mit Code (ein versteckter Prozess zur Bildung von Code-Lesegewohnheiten) stieß ich jedoch auf Studien, in denen Sensoren die Augenbewegungen von Anfängern und erfahrenen Programmierern überwachten. Es sieht so aus:
Anfänger



Erfahren



Achten Sie darauf, was ein erfahrener Programmierer tut. Es wählt Codeblöcke aus, zerlegt sie und liest sie in Blöcken, hebt wichtige Teile hervor und analysiert ihre Arbeit. Der Anfänger eilt Zeile für Zeile herum und versucht nur zu verstehen, was hier vor sich geht. Der Löwenanteil der Zeit wird für die Zusammenstellung des Gesamtbildes aufgewendet, und das Lesen des Codes erfolgt unter ständiger Gegenprüfung.

Das Video ist ab 2012 ziemlich alt und die Aufnahme zielte darauf ab, die Prozesse des Gehirns eines Programmierers zu untersuchen. Hier und hier können Sie etwas mehr lesen.

Jetzt ist es an der Zeit, zur Beschreibung der Funktionsweise von Perzeptronen zurückzukehren. Dies ist eine klare Demonstration der Arbeit eines trainierten und nicht trainierten neuronalen Netzwerks. Basierend auf seiner Wissensbasis folgt ein erfahrener Programmierer dem Code wie ein Interpreter, oft ohne es überhaupt zu merken. Man kann die Lösung dieses Problems genauso angehen wie die Probleme beim Training neuronaler Netze.

Es gibt zwei Möglichkeiten, das Lesen von Code zu beschleunigen:

  1. Bauen Sie ständig die Wissensbasis eines Entwicklers darauf auf, wie der Code aussehen könnte. Dies bedeutet kontinuierliches Lernen, wodurch die Leistung des Netzwerks ständig erweitert wird.
  2. Bringen Sie den gesamten Code auf einen Standard und stellen Sie den gleichen Codestil ein

Natürlich ist es ziemlich offensichtlich, dass die erste Methode sehr arbeitsintensiv ist. In diesem Fall muss der Programmierer die Repositorys ständig lesen. Und angesichts der Fluktuation, der Entstehung neuer Technologien und Praktiken wird dies fast unmöglich. Die Ausschlussmethode bleibt die Stilisierung des Codes, wodurch die Auswirkungen der Zerlegung verringert werden und nur die Geschäftslogik beeinflusst wird.

Anzahl der Klavierstimmer


Stellen Sie sich vor, ein Team von 5 Personen schreibt nach Belieben an alle Module und Komponenten des Systems, erhält ständig überlappende Aufgaben und passt den Code des anderen an. Was ist die mögliche Anzahl aller Optionen zum Schreiben einer Bedingung, wenn jede Person auf ihre eigene Weise schreibt? 5. Und wie viele gültige Blöcke haben wir? Alle Konstruktionen, Aufrufe von Funktionen mit einem oder mehreren Argumenten, Namespaces, Klassen, Eigenschaften, Schnittstellen, Positionierung von Blöcken, Statik, Sichtbarkeitszonen usw. Dies setzt voraus, dass jeder nur einen Schreibstil verwendet, der sich von den Stilen aller anderen unterscheidet. Und wenn eine Person 10 ist? Was ist mit 50? Es ist klar, dass mit zunehmender Anzahl von Personen die Varianz aufgrund einer begrenzten Anzahl von Möglichkeiten zum Schreiben desselben Blocks abnimmt. Und dies ist die erste Ebene, in die wir keines der Hauptprogrammierprobleme investieren - die Benennung von Variablen. Die Wirkung des Multiplikators und aller möglichen Kombinationen wird nicht einmal berücksichtigt. Werfen Sie den Stil der Trennung, Einrückung auf Leerzeichen und Tabs, Liebe für Nudeln usw. auf den Punkt. usw. Und ständig kommen neue Spezialisten und alte gehen. Als Ergebnis erhalten Sie einen riesigen unlesbaren Code, an den Sie sich nicht gewöhnen können und der es unmöglich macht, ein gut ausgebildetes neuronales Netzwerk von Programmierern im Unternehmen zu entwickeln.

Unser Gehirn ist faul


Ein weiterer interessanter Effekt unseres Zentralprozessors im Schädel ist die äußerst negative Wahrnehmung neuer Informationen. Unser Gehirn ist sehr faul. Mit einer Masse von etwa 1,5–2% des gesamten Körpergewichts verbraucht das Gehirn 25% der gesamten Körperenergie. Eine der ressourcenintensivsten Operationen für das Gehirn war, ist und bleibt eine Konzentration der Aufmerksamkeit. Sie können die maximale Konzentration für 20-25 Minuten beibehalten (Hi-Pomodoro-Technik), und während dieser Zeit verschlingt das Gehirn so viel Glukose, wie es für einen ganzen Tag subjektiver Ruhe verschlingen würde. Die Verarbeitung neuer Daten ist ein äußerst ressourcenintensiver Prozess. Und eines der Hauptziele des Gehirns ist es, dieselben Ressourcen zu sparen. Dies ist auf die Arbeit unseres mentalen Modells zurückzuführen. Eine Art psychologischer Blocker. Es sieht ungefähr so ​​aus. Du fängst an, etwas Neues zu lernen. Etwas Neues ist schwer zu geben und aufgrund des Mangels an greifbarer Dynamik des Fortschritts nimmt Ihr Selbstwertgefühl aufgrund des Gedankens „Ich bin dumm!“ Ab. Im Hintergrund schweben. Unsere Psyche ist so angeordnet, dass die gesamte Einstellung vom Selbstwertgefühl abhängt und unsere Einstellung wiederum von unserem Erfolg in der Gesellschaft abhängt. Und um die grundlegenden sozialen Aufzüge für adaptive Abhängigkeiten nicht zu durchbrechen, beginnt unser Gehirn Aktivitäten zu widerstehen, die das Selbstwertgefühl verringern. Als Ergebnis möchten Sie eine Fernsehserie sehen, einen Habr lesen, einen Kaffee trinken, in einem sozialen Umfeld sitzen. Netzwerke usw. Alles, nur um nicht die Theorie des Landau-Feldes zu lernen. Oder beheben Sie einen schwer zu reproduzierenden Fehler. Oder ... lesen Sie Code von geringer Qualität, der schwer herauszufinden ist. Ein gutes Beispiel dafür, wie sich das Gehirn gemäß den Einschränkungen in diesem Bereich verhält, sind Menschen im Alter von etwa 70 bis 80 Jahren, die aus nächster Nähe kein Smartphone oder zwei Tasten eines Roboterstaubsaugers lernen möchten. Die Ressourcen gehen zur Neige. Das Gehirn blockiert verzweifelt den Lernprozess und wirkt auf den Daumen. Es gibt viele dieser Ressourcen, während Sie jung sind. Mit der Zeit und dem Erwachsenwerden werden sie immer weniger. Es funktioniert ziemlich linear. Glücklicherweise wird dies durch die zunehmende Leistung unserer neuronalen Netze ausgeglichen. Es sei denn, es handelt sich natürlich um eine direkte gezielte Verschlechterung.

Einige Stereotypen


Ein häufiges Missverständnis, das Sie vielleicht gehört haben: „Nun, ich bin ein Profi, ich kann jeden Code lesen. Ich schreibe schnell und cool und löse Unternehmensprobleme. Und es spielt keine Rolle, wie mein Code aussieht, wenn er das Problem löst. Der Rest kann es einfach nicht schnell herausfinden, ich habe keine Probleme damit. " Wenn Sie einen solchen Encoder in Ihrer Umgebung haben, können Sie ihm sagen: „Alter, ich habe schlechte Nachrichten für Sie. Sie beeinflussen das gesamte Team, und dieser Ansatz ist der Grund, warum andere langsamer schreiben, wenn ein supereffizienter Programmierer schnell Code erzwingt. "

Ein supereffizienter Programmierer, der ohne Formatierung und Standardisierung schreibt, ist in zweierlei Hinsicht sehr effizient:

  • Super effizientes Schließen von Aufgaben, ohne auf Design und Stil einzugehen.
  • Es ist sehr effizient, alle anderen zu verlangsamen, da die Leute nach ihren Hinzufügungen lange versucht haben, zu verstehen, was hier passiert ist.

Warum Code-Stil benötigt wird


Obwohl dies bereits offensichtlich sein sollte, ist es notwendig, die Hauptpunkte irgendwie hervorzuheben.
Codestil:

1. Bietet eine lineare Entwicklung des Projekts und hat keinen Einfluss auf die Menge der Codebasis. Wenn Sie in der Vergangenheit verständlichen Code geschrieben haben, haben Sie unabhängig von der Anzahl der Entwickler immer die gleiche Codequalität, sodass das Projekt unabhängig von seiner Größe dynamisch wachsen kann.

2. Beschleunigt den Anpassungsprozess neuer Programmierer erheblich. Wenn Ihr Code klar geschrieben ist, trainiert ein neuer Spezialist sein neuronales Netzwerk schnell, um Blöcke zu identifizieren und nützlich zu werden. Es gibt so etwas wie einen Selbstversorgungspunkt für Mitarbeiter. Dies ist der Punkt, ab dem der Mitarbeiter beginnt, nur noch Nutzen zu bringen. Und wenn der Code klar geschrieben ist, müssen neue Mitarbeiter die Geschäftslogik nicht verstehen, sondern nur lernen, Ihren Code zu lesen. Und je schneller er es macht, desto schneller hört er auf, anderen Spezialisten Unmengen von Fragen zu stellen, und nimmt ihnen Zeit. Und die Zeit von Spezialisten, die die Gewinnschwelle überschritten haben, ist für das Team und das Unternehmen im Hinblick auf den potenziellen Wert des mitgebrachten Produkts viel teurer.

3. Entfernt die Abhängigkeit von Einzelheiten. Sie müssen nicht ständig über die Originalität und das spezifische Design eines anderen stolpern.

4. Minimiert die Wirkung des mentalen Blockers beim Erlernen eines neuen Codes. Ihr Gehirn ist weniger resistent, weil Sie müssen sich nicht mit dem Stil eines anderen befassen. Mentale Ressourcen zum Lesen von klarem Code benötigen viel weniger.

5. Minimiert Reputationsverluste. Sehr bald nach der Ankunft in einer neuen Firma wird der Programmierer beginnen, seine Eindrücke mit ehemaligen Kollegen und Freunden zu teilen. Und er wird entweder sagen, dass hier alles cool ist, oder er wird die negativen Aspekte bei der Arbeit mit dem Code hervorheben. In gewisser Weise erhalten Sie einen HR-Bonus: Wenn Sie möchten, dass coole Programmierer mit Ihnen zusammenarbeiten, machen Sie ein gutes Projekt. Obwohl dies nicht immer wichtig ist und in einigen Unternehmen die Qualität des Codes im Prinzip nicht, sondern nur die Bereitstellung von Funktionen für den Vertrieb betrachtet wird, ist dies ein schöner Bonus. Es ist kein Geheimnis, dass ein häufiger Grund für das Verlassen die Ermüdung durch das ständige Schneiden einer Codebasis von schlechter Qualität ist.

6. Bildet und fördert eine Entwicklungskultur. Die Aufgabe des Programmierers liegt auf einer niedrigeren Ebene als die Zukunft des gesamten Unternehmens. Es ist jedoch wichtig, das Verständnis zu vermitteln, dass die Verständlichkeit und Lesbarkeit des Codes jetzt die Dynamik der Weiterentwicklung beeinflusst. Wenn der Code schwer zu lesen und nicht standardisiert ist, mit Schmerzen und Leiden überarbeitet und skaliert werden kann, sinkt mit dem Wachstum der Projektcodebasis die Entwicklungsgeschwindigkeit. Je minderwertiger der Code ist, desto schwieriger ist es, einen neuen zu schreiben, desto langsamer entwickelt sich ein Produkt, desto schwieriger ist es für ein Unternehmen zu wachsen und desto schwieriger ist es für Sie, mehr Geld zu zahlen, da viel Geld dafür ausgegeben wird, den Projektlebenszyklus mit neuen und neuen Mitarbeitern zu versorgen Sie verbringen Zeit damit, sich nicht mit dem Nutzen des Unternehmens zu befassen, sondern mit der Klassifizierung von Arzneimitteln, unter denen dieser Code geschrieben wurde.

Perfekter Code


Wir alle verstehen, dass es nicht existiert. Aus Sicht des kanonischen Codestils ist das Konzept des Code-Designs. Und alles wäre gut, wenn das wahr wäre. Bei der Entwicklung des Ferncodestils wird ein umfangreicheres Konzept verwendet, das die Prinzipien der Entwicklung einschließt. Die Aufteilung des Codes in logisch isolierte Blöcke in Klassen oder Dateien bezieht sich auch auf das Design. Benennung, Isolationsstufen, Vererbung. Alle diese Werkzeuge sind nicht nur Interaktion, sondern auch das Design Ihres komplexen Mechanismus, bei dem jeder Stein eine Rolle spielt.

Konzepte ändern sich von Sprache zu Sprache. Einzelheiten treten in den Vordergrund. Das Fundament bleibt jedoch unverändert. Ein Qualitätscode wird nur durch zwei Kriterien bestimmt:

  • Code ist anonym
  • Der Code liest sich wie ein Buch

Anonymer Code


Der ideale Zustand, den Sie in diesem Prozess finden müssen, heißt anonymer Code. Ich bin sicher, dass viele von Ihnen, die einen Arbeitsentwurf und eine zufällige Komponente geöffnet haben, ohne Probleme sagen können, welcher der Kollegen dies geschrieben hat. Jeder hat oft einen Stil. Jemand mag Nudeln von if, jemand mit und ohne Lambdas, jemand mag es, Variablen zu reduzieren, um ein Zeichen zu speichern. In anonymem Code können Sie dies nicht tun. In einem idealen depersonalisierten Code ist es unmöglich, den Autor zu identifizieren. Und dies ist der Fall, als Sie zum letzten Punkt Ihres Codestyles kamen.

Lesbarkeit auf Buchebene


2 Hauptprogrammierprobleme zurückrufen? Ungültigmachung des Caches und Benennung von Variablen. Wir werden die dunkle Vergangenheit der Cache-Prozesse umgehen und direkt zu unserem Schmerz übergehen. Benennen von Variablen, Klassen, Objekten, Dateien, Methoden, Konstanten usw. Dieses Problem hat 2 Extreme. Namen zu kurz und zu lang. Der gesunde Menschenverstand sagt uns, dass die Logik irgendwo in der Nähe der Mitte liegt. Hier klopfen supereffiziente Programmierer an unsere Tür und sagen uns, dass es ihnen egal ist. Aber warum sollten wir darüber theoretisieren? Sag mir, was macht dieser Code?



Und dieser?



Der zweite Code ist direkt und einfach zu lesen. Es ist nicht erforderlich, die Geschäftslogik wirklich zu verstehen, um die Funktionslast bei einer solchen Benennung zu verstehen. In diesem Beispiel nehmen wir einfach das gesamte Repository, erstellen die Sammlung mit dem Builder und wenden dann den Filter an. Sie müssen sich nicht einmal mit dem Code befassen, um zu verstehen, was passiert. Als würde man ein Buch über Schlagzeilen lesen. Aber das Benennen ist nicht alles.

Entwurfsmuster


Sie werden in fast jedem Interview nach Designmustern gefragt. Ihr öffentliches Ziel ist eine wiederholbare architektonische Lösung. Ihre Nebenwirkung ist Vorhersehbarkeit und Konsistenz. Sobald Sie zu einer Architektur wechseln, die auf Entwurfsmustern basiert, bilden Sie ein ziemlich vorhersehbares System. Das heißt, Anhand des Namens können Sie den Zweck der Klasse oder des Objekts leicht verstehen. Was macht das Repository-Muster? Dies ist eine Repository-Ansicht mit Datenerfassungsmethoden. Was macht das Builder-Muster? Baut ein komplexes Objekt oder eine komplexe Struktur zusammen. Und so weiter an allen Fronten.

Es gibt ein Muster wie Command. Was kann man damit machen? Natürlich nur ausführen! Sie müssen nicht studieren, was sich darin befindet. Es ist klar, dass es möglich ist. Entwurfsmuster helfen Ihnen zu verstehen, wie Ihr Projekt funktioniert. Wenn Sie alles gut geschrieben haben, werden Sie sich nicht fragen: "Was ist in meinen Verzeichnissen?" Anhand der Namen können Sie leicht feststellen, was und wo sich befindet.

Sagen wir das einfach. Alle Entscheidungen über Entwurfsmuster wurden getroffen, wobei der Schmerz des Entwicklers in Bezug auf ein bestimmtes Problem zugrunde gelegt wurde. Dieser Schmerz wurde bereits von jemandem erlebt, gerahmt und in Form eines der vorhandenen Architekturmodelle gelöst. Darüber hinaus wurde all dies auf dem berüchtigten SOLID gebildet.

FEST


SOLID ist eine Abkürzung für die fünf Prinzipien der objektorientierten Programmierung. Hinweis: 5 Prinzipien. Objektorientiert. Programmierung Dies ist keine Praxis. Dies ist keine Empfehlung. Dies ist nicht der Wunsch eines alten Programmierers, junge Leute zu unterrichten. , SOLID — . SOLID, 6 , , SOLID — . , , . — . , , : , , . . , .

? ? . , . code style, , SOLID. . . . — -. Das heißt, , , , , , , . , .

, code style community . , , , , . , . , . , . , .

code style? ! . , . , . . - open-source based . , PSR , - . symfony2 code style, PSR . , , PHP. , , .

?


, , ? — , , CodeStyle , . , PHPStorm , phpcs codestyle — . , . , , , .

, (), . , ? . . , . 2 Google Sheets . 23% . , 7 , , 20 . . , 20 . 21% . , , .

, , , , 90% , . ? Middle PHP Developer . onboarding , 3-. … - . . onboarding -, , . , 1- Junior PHP Developer. « » . success story.

, , , 25%, onboarding' ⅔. « » , . , . , , , phpstorm Sonar Light.

— , Senior , , . , , . Senior QA Engineer .

, 21-27%. , , - . , 5%, 5 ( , ), 5 69 . , 14 840 – 40 /. phpcs phpstorm? , 50 .

PS: , , ManyChat, .

Source: https://habr.com/ru/post/de468953/


All Articles