Programmierung für die Massen

Das Verstehen selbst der Grundlagen der Programmierung kann menschliche Aktivitäten vereinfachen. Neben den offensichtlichen Dingen wie der Entwicklung des abstrakten Denkens oder der Fähigkeit, die Aufgabe in kleinere Teile zu unterteilen, schlage ich vor, noch weiter zu gehen und die grundlegenden Entwicklungsansätze zu verwenden. Am Beispiel eines klassischen logischen Spiels, das eine Analogie zwischen visueller und traditioneller Programmierung zieht, möchte ich zeigen, wie Entwicklungsfähigkeiten bei der Lösung eines angewandten Problems helfen können. Diejenigen, die über das Thema diskutieren oder "Bulls and Cows" spielen und einen Preis gewinnen möchten - ein Aufruf an cat.



Mein Name ist Zhenya und ich bin Backend-Entwickler bei ManyChat. Vor einiger Zeit kam das HR-Team mit der Bitte auf mich zu, das Spiel „Bulls and Cows“, das vielen aus der Kindheit bekannt ist, auf der Grundlage unseres Produkts umzusetzen. Lassen Sie mich einen kleinen Kontext hinzufügen. ManyChat ist ein Tool zur Automatisierung der Interaktion zwischen Unternehmen und ihren Kunden, mit dem Sie häufig gestellte Fragen über Facebook und in jüngerer Zeit über SMS und E-Mail beantworten können. "Bulls and Cows" ist ein logisches Spiel, bei dem für mehrere Versuche die erratene Zahl erraten werden muss. Viele können es aus dem Spiel Fallout kennen, in dem Sie ein Computerterminal hacken müssen. Weitere Details zu den Regeln finden Sie am Ende des Artikels.

Visualisierung


Was tun wir, bevor wir Code für eine komplexe Aufgabe schreiben? Wir gehen mit einem Marker an die Tafel oder nehmen einen Bleistift und Papier und zeichnen ein Block- oder UML-Diagramm, da die Visualisierung die natürlichste Art ist, Informationen zu präsentieren und wahrzunehmen. Flow Builder ist das Herz unseres Systems, basierend auf verschiedenen Objekten, grafischen Elementen und den Regeln, nach denen sie miteinander interagieren. Ich würde sagen, dass dies eine logische Fortsetzung der objektorientierten Programmierung ist. Also habe ich die üblichen Werkzeuge verworfen und sofort die Logik der Kommunikation zwischen dem Bot und dem Spieler entworfen.

Flow of the Bulls und Cows Spiel

Dies ist sehr praktisch, da das UML-Diagramm und der Flow Builder nahezu identisch sind. In diesem Schritt sind Design und Programmierung bereits kombiniert. Für mehrere Iterationen warf ich Flow und bestimmte die Orte der Interaktion mit dem Benutzer und mit der API. Das Ergebnis war etwas anders als die ursprüngliche Darstellung in meinem Kopf - die Visualisierung bot die Möglichkeit, die Aufgabe aus einer anderen Perspektive zu betrachten. Dies ist gut, da Änderungen am Diagramm einfacher und billiger sind als am Code. Es scheint mir, dass die Bedeutung dieses Ansatzes im Sprichwort „siebenmal messen, eins schneiden“ wurzelt. Ingenieure sollten besonders vertraut und verständlich sein.

Aufteilung der Verantwortung


Was sollte auf der Seite von ManyChat implementiert werden und was auf der Seite des Codes? Die Antwort auf diese Frage schien mir zunächst nicht offensichtlich. Auf unserer Plattform gibt es zwei Tools für die Interaktion: Dynamic Block und External Request. Sie sind fast identisch, außer dass der erste die Anforderung an den Remote-Server ausführt und mit dem nächsten Befehl fortfährt, und der zweite ermöglicht es Ihnen, zuerst die Antwortdaten mit den Bot-Variablen zu vergleichen. In einer der ersten Versionen habe ich den dynamischen Block verwendet und das Senden der Rangliste von der API-Methode direkt an Facebook implementiert. Es scheint, dass an diesem Ansatz nichts auszusetzen ist. Wenn Sie jedoch etwas weiter schauen und davon ausgehen, dass der Spieler per SMS spielen möchte, muss der Code den Kommunikationskanal eines bestimmten Spielers ermitteln. Es scheint nicht notwendig. In der nächsten Version habe ich den Flow auf External Request umgestellt.Benutzervariablen wurden ein Antwortdatensatz hinzugefügt und alle Erwähnungen des Kanals aus dem Code entfernt. Jetzt kann der Spielcode in einer anderen Anwendung verwendet werden und jede gewünschte Interaktionsschnittstelle implementieren: von der Konsole zur mobilen Anwendung. Ob es darum ging, die Ansicht gemäß dem MVC-Muster von der Steuerlogik zu trennen oder die begrenzten Kontexte gemäß dem DDD-Ansatz hervorzuheben - entscheiden Sie selbst. Die Hauptsache hier ist, dass ich trotz fehlender Anforderungen auf unbewusster Ebene einen potenziellen Engpass im System identifiziert habe, der in Zukunft zu Problemen führen könnte.Ob es darum ging, die Ansicht gemäß dem MVC-Muster von der Steuerlogik zu trennen oder die begrenzten Kontexte gemäß dem DDD-Ansatz hervorzuheben - entscheiden Sie selbst. Die Hauptsache hier ist, dass ich trotz fehlender Anforderungen auf unbewusster Ebene einen potenziellen Engpass im System identifiziert habe, der in Zukunft zu Problemen führen könnte.Ob es darum ging, die Ansicht gemäß dem MVC-Muster von der Steuerlogik zu trennen oder die begrenzten Kontexte gemäß dem DDD-Ansatz hervorzuheben - entscheiden Sie selbst. Die Hauptsache hier ist, dass ich trotz fehlender Anforderungen auf unbewusster Ebene einen potenziellen Engpass im System identifiziert habe, der in Zukunft zu Problemen führen könnte.

Benennung von Variablen


Die Benennung von Variablen ist eines von zwei Hauptproblemen bei der Programmierung. Neben Variablen ist auch die Blockbenennung wichtig. Viele Benutzer legen keinen Wert darauf, haben keine Zeit, sich umzuschauen, da sich der Fluss in einen Satz von Kopie 1, Kopie 2 usw. verwandelt. Dies erschwert das Verständnis erheblich. Alles ist wie in einer schlechten Klasse - es ist unmöglich herauszufinden, was er tut, ohne hineinzugehen. Im Detail wurde dieser Gedanke von meinem Kollegen offenbart. Wenn Sie interessiert sind, schlage ich vor, dass Sie seinen Beitrag lesen .

Steve McConnell schrieb in seinem Buch "Perfect Code", dass der Name die dargestellte Entität vollständig und genau beschreiben sollte. Ich denke, es ist schwer, damit zu streiten. Zum Beispiel bevorzuge ich für boolesche Variablen das Präfix is. In diesem Fall kann der Leser bereits anhand der ersten beiden Buchstaben verstehen, womit er es zu tun hat. In Bezug auf die Länge ist es wünschenswert, dass sie 20 Zeichen nicht überschreitet (Gorla, Benander und Benander, 1990). Je kleiner der Gültigkeitsbereich einer Variablen ist, desto kürzer kann ihr Name sein. Da jedoch alle Variablen in ManyChat einen globalen Bereich haben, lohnt es sich, den Namespace zu verwenden. Für Bullen und Kühe habe ich das Startsegment in Form von zwei BC-Großbuchstaben verwendet, die von Bullen und Kühen abgeleitet sind. Vor diesem Hintergrund habe ich den Variablennamen BC Is Victory erhalten - meiner Meinung nach ziemlich einzigartig und umfassend.

TROCKEN, KUSS


Das Spiel funktioniert und es scheint, dass Sie mit einem Gefühl der Leistung ausatmen können. Wir wissen jedoch, dass der nächste Schritt die Selbstüberprüfung und das Refactoring ist. Mit einer detaillierteren Analyse können Sie sehen, wie das Stoppen der Textverarbeitung und der Sieg zu ähnlichen Blockaden führen - der Spieler fordert einige Aktionen. Gleichzeitig lebt der Verlust aus einem unbekannten Grund sein eigenes Leben. Die Kombination dieser Orte zu einem Ort scheint ein logischer Schritt zu sein, um Doppelarbeit zu vermeiden, was wiederum zu einer erhöhten Konsistenz des Verhaltens und einer einfachen Wartung führt. Wenn Änderungen erforderlich sind, müssen Sie sie in der einzigen Einheit des Systems vornehmen, ohne dass Änderungen an anderen vorgenommen werden. Dies zeigt an, dass das Prinzip "Nicht wiederholen" erfolgreich angewendet wird.


Mit TROCKEN fließen

Hören Sie hier jedoch nicht auf. Komplexe Lösungen sind schwer zu pflegen. Wenn ein Fehler auftritt, ist es nicht einfach, ihn zu lokalisieren, insbesondere nach einer Zeit, in der Sie aus dem Kontext geraten. Eine neue Person wird viel Energie benötigen, um herauszufinden, was was ist. Und Sie müssen sich mit jedem Knoten vertraut machen, um nichts Wichtiges zu verpassen. Daher lohnt es sich, das Prinzip einfach zu halten, dumm zu halten und alle möglichen Aktionen auf verschiedene Orte zu verteilen. Nach der Zersetzung bekam ich 5 ziemlich leicht verständliche Strömung. Als angenehmer Bonus erfüllte dieses Refactoring die EinzelverantwortungPrinzip. Jeder Fluss hat eine Verantwortung und diese Verantwortung ist vollständig darin enthalten. Der Reiz ist a la Black Box, und aufgrund der Art des Problems kann es schneller lokalisiert werden.


KISS-konformer Flow

YAGNI


In einer der ersten Versionen der Automatisierung gab es Erfolge beim Versenden von Erinnerungen an ein abgebrochenes Spiel und Anweisungen zum Empfangen von Geschenken durch die Gewinner. Die Umsetzung der ersten Idee wurde durch Einschränkungen seitens Facebook erschwert - in letzter Zeit sind die Bedingungen für das Versenden von Nachrichten außerhalb des Fensters innerhalb von 24 Stunden schwieriger geworden. Die zweite erwies sich als unzureichend trivial für die Implementierung durch den Code. Beide Probleme sind gelöst, aber der Aufwand war nicht durch die Notwendigkeit einer einmaligen Kampagne gerechtfertigt. Darüber hinaus traten Sprintaufgaben auf die Fersen, sodass beschlossen wurde, diese Funktionalität nicht zu implementieren. Und hier kam zur Rettung. Du wirst es nicht brauchenein Prinzip, dessen Zweck es ist, auf übermäßige Funktionalität zu verzichten. Dies ist eine normale Situation, wenn sich die Bedingungen ändern und tote, mehr unnötige Teile im Produkt erscheinen. Das Entfernen der entsprechenden Blöcke erleichterte das Verständnis des Flusszwecks und erinnerte erneut daran, wie wichtig es ist, dass das Hinzufügen neuer Funktionen, die nicht direkt benötigt werden, rechtzeitig abgelehnt wird.

Erfahrene Entwickler wissen, dass jede Funktion ständige Unterstützung benötigt, vom Code-Refactoring über die Aktualisierung der Dokumentation bis hin zur Arbeit mit Benutzer-Feedback. Daher sollte die Hinzufügung neuer Funktionen immer mit Argwohn betrachtet werden und die Frage stellen, ob dies wirklich notwendig ist. Letztendlich können Sie in dieser Phase viele Ressourcen sparen.

Lasst uns spielen


Die Phasen der Selbstüberprüfung und des Refactorings sind bestanden, es gibt keine unnötigen Funktionen und die Bedeutung aller Abläufe ist für das Verständnis transparent. Dies bedeutet, dass das Spiel fertig ist und es Zeit ist, um Preise zu kämpfen. Gemäß den Wettbewerbsbedingungen erhalten die 10 besten Spieler, die vor dem 22. Mai 2020 die meisten Punkte erzielen, Preise vom ManyChat-Team.

Ein bisschen über die Regeln. In unserer Implementierung ist das Spiel für eine Person konzipiert. Der Bot macht eine 4-stellige Sequenz mit sich nicht wiederholenden Zahlen. Der Spieler versucht, die Zahl zu erraten. Der Bot berichtet als Antwort darauf, wie viele Zahlen ohne Übereinstimmung mit ihren Positionen erraten wurden, dh die Anzahl der Kühe, und wie viele bis zur Position, dh der Anzahl der Bullen, erraten wurden. Infolgedessen könnte das Spielszenario ungefähr so ​​aussehen:

Die Zahl 1234 wird erraten. Der
Teilnehmer macht die erste Annahme: 4321
Erhält die Antwort: 0 Bullen und 4 Kühe. Der
Teilnehmer macht die zweite Annahme: 1678
Und erhält die Antwort: 1 Bulle und 0 Kühe.

Um es zu versuchen, folgen Sie dem Link und folgen Sie den Anweisungen. Ich möchte Sie daran erinnern, dass das Spiel über Facebook Messenger läuft. Wir bieten 2 Schwierigkeitsgrade: ein Spiel für eine begrenzte und unbegrenzte Anzahl von Zügen. Wenn Sie in einem schwierigen Spiel gewinnen, erhalten Sie 3 Punkte, in einem einfachen - 2. Wenn Sie unabhängig vom Level verlieren, erhalten Sie 1 Punkt.

Das Spiel wurde auf einem Standard-Technologie-Stack implementiert: Nginx 1.17, PHP 7.4, PostgreSQL 12.1. Wenn Sie möchten, können Sie das Repository auf Ihren Server klonen , die Vorlage auf Ihrer ManyChat-Seite installieren und Ihr eigenes Turnier organisieren.

Ergebnisse


"Jeder in diesem Land muss lernen, wie man auf einem Computer programmiert, weil es Ihnen das Denken beibringt." Ich denke, dass die Relevanz dieser Aussage längst über die Grenzen nur eines Landes hinausgegangen ist. Das Programmieren sind keine geheimen Zeichen im Terminal, die für eine nicht eingeweihte Person schwer wahrzunehmen sind, und ein Programmierer ist kein gewählter. Zuallererst ist es eine Denkweise und eine Reihe von Fähigkeiten zur Lösung von Problemen.

Wenn ich mich dem Titel des Artikels und dem ursprünglichen Slogan zuwende, möchte ich ihn umformulieren: „Programmierung gehört den Menschen. Es muss seine tiefsten Wurzeln in den Tiefen der breiten Arbeitsmassen haben. Es muss von diesen Massen verstanden und von ihnen geliebt werden. “

Ich hätte nie gedacht, dass ich in einem Artikel Steve Jobs und Lenin zitieren würde.

Ich bin sicher, dass mir die hier vorgestellten Gedanken nicht nur in den Sinn kamen. Einige werden sie sogar als Kapitäne betrachten. Aber ich weiß für mich selbst, dass Sie manchmal dieselben Informationen mehrmals hören müssen, um sie zu verwenden. Das banale Prinzip besteht darin, die Dinge so einfach zu vereinfachen, wie sie scheinen. Jeder Programmierer weiß, dass der Projektcode schnell und einfach außer Kontrolle gerät, wenn er nicht angemessen berücksichtigt wird. Aber manchmal muss man sich wieder daran erinnern.

Etwas war überhaupt nicht beleuchtet. In diesem Artikel wurden beispielsweise keine extremen Programmiertechniken wie Paarprogrammierung, häufige kleine Releases und das Planungsspiel behandelt. Flexible Methoden haben zwar gemeinsame Wurzeln mit Systemen zur Organisation der physischen Offline-Produktion, werden jedoch häufig für die Softwareentwicklung verwendet. Obwohl ihr Potenzial nicht auf die Branche beschränkt ist.

Es gibt wahrscheinlich etwas, an das ich nie gedacht habe. Jeder von uns hat seine eigene Erfahrung und Vision. Daher fordere ich Sie dringend auf, Ihre Gedanken zu diesem Thema in den Kommentaren mitzuteilen.

All Articles