Ein besserer Front-End-Entwickler werden, der Grundlagen anstelle von Heuristiken verwendetUnsere Erfahrung zeigt, dass nichttechnische Pädagogen und Autodidakten häufig nicht auf theoretischen Prinzipien, sondern auf heuristischen Methoden beruhen.
Heuristiken - Muster und bewährte Regeln, die ein Entwickler aus der Praxis gelernt hat. Sie können unvollkommen oder in begrenztem Umfang, jedoch in ausreichendem Maße, arbeiten und erfordern keine ernsthaften Überlegungen. Hier einige Beispiele für Heuristiken:
- "Verwenden Sie
$(document).ready(function(){})
, um Code auf jQuery-Sites zu initialisieren." - "Das
var self = this
Konstrukt wird benötigt, um eine Methode in einer Rückruffunktion aufzurufen." - "Pfeilfunktionen haben keine
return
"
Gleichzeitig kann das theoretische Prinzip verwendet werden, um Lösungen für andere Probleme zu finden. Er ist ausnahmslos treu und bestimmt oft das Gerät des einen oder anderen Elements. Zu den theoretischen Prinzipien gehören zum Beispiel:
Bitte beachten Sie: Wir haben nur heuristische Beispiele angeführt, um den handwerklichen Charakter der Heuristik im Vergleich zur Strenge der theoretischen Grundlagen hervorzuheben. Keines der heuristischen Beispiele ist für alle Fälle universell, aber sie funktionieren in einer ausreichenden Anzahl von Situationen, sodass die Entwickler, die sie verwenden, Arbeitscode erhalten, ohne dessen Funktionsweise vollständig zu verstehen.
Argumente für einen theoretischen Ansatz
Wir sind oft auf die Tatsache gestoßen, dass Entwickler ohne technische Ausbildung nicht dazu neigen, Probleme mit theoretischen Prinzipien zu lösen. Dies erklärt sich in der Regel dadurch, dass sie zu Beginn ihrer Karriere keine Gelegenheit hatten, sie zu lernen, und da heuristische Methoden zufriedenstellend funktionieren, setzen sie sie weiterhin ein.
Trotz der offensichtlichen Komplexität kann das Erlernen einer Theorie sehr nützlich sein. Warum? Mit dieser Theorie können Sie sicher sein, dass Ihre Lösung funktioniert, und unabhängig Antworten auf neue Fragen anzeigen, ohne nach Lösungen anderer suchen zu müssen. Kurzfristig mögen heuristische Algorithmen wie eine einfache und schnelle Lösung erscheinen, aber sie führen oft - wenn überhaupt - zu unvollständigen Lösungen.
Wenn Sie sich auf heuristische Methoden verlassen, werden Sie außerdem nie lernen, Probleme wirklich zu lösen. Möglicherweise schaffen Sie es oft, eine funktionierende Lösung zu finden, aber früher oder später kommen Sie zum Stillstand, von dem Sie keinen Ausweg sehen. C & P-Programmierer verlassen sich bei ihrer Arbeit auf Heuristiken.
Kriterien für die Fähigkeitsstufe von Entwicklern
Bei der Befragung von Frontend-Entwicklern legen wir eine Programmieraufgabe für sie fest und sagen, dass sie alle Quellen verwenden können, sei es Google oder Stack Overflow. Auf diese Weise kann leicht festgestellt werden, ob der Entwickler an Heuristiken oder Theorien festhält.
Ersteres kopiert ausnahmslos Code aus mehr oder weniger geeigneten Beispielen mit Stack Overflow. Erst wenn der Code nicht wie geplant funktioniert, haben sie begonnen, ihn selbst zu optimieren. Oft scheitern sie.
Letztere neigen dazu, in der API-Dokumentation nach Antworten zu suchen. Dort finden sie Informationen darüber, wie viele Parameter eine bestimmte Funktion annimmt oder welche Syntax die erweiterte Form der gewünschten CSS-Eigenschaft enthält.
Bereits in den ersten fünf Minuten des Interviews können Sie genau bestimmen, zu welcher Art von Programmierern der Kandidat gehört.
Beispiel
Nehmen Sie Bill als Beispiel. Er absolvierte mehrere Schulungen, löste eine Reihe von Aufgaben in JavaScript und schrieb in seiner Freizeit Websites, lernte JavaScript jedoch nicht wirklich.
Sobald Bill auf ein Objekt wie dieses stößt:
const usersById = { "5": { "id": "5", "name": "Adam", "registered": true }, "27": { "id": "27", "name": "Bobby", "registered": true }, "32": { "id": "32", "name": "Clarence", "registered": false }, "39": { "id": "39", "name": "Danielle", "registered": true }, "42": { "id": "42", "name": "Ekaterina", "registered": false } }
Ein solches Objekt kann eine Liste von Benutzern anzeigen und angeben, ob sie sich für ein bestimmtes Ereignis registriert haben.
Angenommen, Bill muss eine Liste der registrierten Benutzer abrufen. Mit anderen Worten, filtern Sie sie heraus. Er stieß auf Code, in dem die
.filter()
-Methode zum Filtern der Liste verwendet wurde. Also versucht er so etwas wie:
const attendees = usersById.filter(user => user.registered);
Und hier ist was er bekommt:
TypeError: usersById.filter is not a function
"Etwas Unsinniges", denkt Bill, weil er den Code gesehen hat, in dem
.filter()
als Filter fungierte.
Das Problem ist, dass Bill sich auf die heuristische Methode stützte. Er versteht nicht, dass
filter
eine in Arrays definierte Methode ist, während
usersById
ein reguläres Objekt ist, das keine
filter
.
Der verwirrte Bill googelt den "
Javascript-Filter ". Er findet viele Verweise auf Arrays und erkennt, dass er
usersById
in ein Array verwandeln
usersById
.
Object.keys()
er dann "
Javascript bittet
, ein Objekt in ein Array Object.keys()
", findet er Beispiele mit
Object.keys()
bei Stack Overflow. Danach versucht er:
const attendees = Object.keys(usersById).filter(user => user.registered);
Diesmal wird der Fehler nicht angezeigt, aber zu Bills Überraschung bleibt das
attendees
leer.
Tatsache ist, dass
Object.keys()
die Schlüssel des Objekts zurückgibt, jedoch nicht dessen Wert. Tatsächlich ist der Name der
user
leicht irreführend, da es sich nicht um ein
user
, sondern um einen Bezeichner, dh eine Zeichenfolge. Da das
registered
Attribut nicht für Zeichenfolgen definiert ist, behandelt der
filter
jeden Eintrag als falsch und das Array bleibt leer.
Bill sieht sich die Antworten zum Stapelüberlauf genauer an und nimmt folgende Änderungen vor:
const attendees = Object.keys(usersById).filter(id => usersById[id].registered);
Diesmal ist das Ergebnis besser:
["5", "27", "39"]
. Aber Bill wollte Besucherobjekte bekommen, nicht deren Ausweis.
Um zu verstehen, wie Besucher gefiltert werden, sucht Bill verärgert nach einem „
Javascript-Objektfilter “, untersucht die Suchergebnisse auf Stapelüberlauf und findet
diese Antwort mit dem folgenden Code:
Object.filter = (obj, predicate) => Object.keys(obj) .filter( key => predicate(obj[key]) ) .reduce( (res, key) => (res[key] = obj[key], res), {} );
Bill kopiert diese Zeilen und versucht:
const attendees = Object.filter(usersById, user => user.registered);
Alles funktioniert - obwohl nicht klar ist, warum. Bill versteht nicht, warum
reduce
erforderlich ist und wie es verwendet wird. Darüber hinaus versteht Bill nicht, dass er gerade eine neue nicht standardmäßige Methode für das globale
Object
.
Aber Bill ist das egal - es funktioniert! Die Folgen interessieren ihn noch nicht.
Was hat Bill falsch gemacht?
Bill versuchte eine heuristische Methode, um das Problem zu lösen, und stieß auf folgende Probleme:
- Mit
.filter()
für eine Variable erhielt Bill einen TypeError
. Er hat nicht verstanden, dass filter
für gewöhnliche Objekte nicht definiert sind.
- Er benutzte
Object.keys()
um „das Objekt in ein Array zu verwandeln“, aber dies allein brachte keine Ergebnisse. Er musste ein Array von Objektwerten erstellen. - Selbst nachdem er die Werte empfangen und als Bedingung für die Filterung verwendet hatte, erhielt er nur Bezeichner anstelle der diesen Bezeichnern zugeordneten Benutzerobjekte. Dies liegt daran, dass das gefilterte Array eine ID enthielt, keine Benutzerobjekte.
- Im Laufe der Zeit gab Bill diesen Ansatz auf und fand eine funktionierende Lösung im Internet. Trotzdem verstand er immer noch nicht, wie es funktioniert - und wird keine Zeit damit verschwenden, es zu klären, weil er andere Dinge zu tun hat.
Dies ist ein künstliches Beispiel, aber wir sind oft auf Entwickler gestoßen, die Probleme auf die gleiche Weise lösen. Um sie effektiv zu lösen, müssen Sie sich von heuristischen Methoden entfernen und die Theorie studieren.
Kommen wir zu den Grundlagen
Wenn Bill ein Befürworter eines theoretischen Ansatzes wäre, würde der Prozess folgendermaßen aussehen:
- Um die angegebenen Eingabedaten zu identifizieren und die gewünschte Ausgabe zu bestimmen - im Sinne ihrer Eigenschaften: „Ich habe ein Objekt, dessen Schlüssel Zeichenfolgen sind, die ID darstellen, und Werte sind Objekte, die Benutzer darstellen. Ich möchte ein Array erhalten, dessen Werte Benutzerobjekte sind - aber nur Objekte registrierter Benutzer. “
- So verstehen Sie die Suche in einem Objekt: „Ich weiß, dass ich durch Aufrufen von
Object.keys()
ein Array von Schlüsseln in einem Objekt Object.keys()
. Ich möchte ein Array erhalten, da Arrays die Aufzählung unterstützen . " - Um zu erkennen, dass diese Methode beim Abrufen der Schlüssel hilfreich ist und Sie die Schlüssel in Werte umwandeln und sich an
map
erinnern müssen - eine offensichtliche Methode zum Erstellen eines neuen Arrays durch Transformieren der Werte eines anderen Arrays:
Object.keys(usersById).map(id => usersById[id])
- So sehen Sie, dass Sie jetzt über ein Array von Benutzerobjekten verfügen, die gefiltert werden können und echte Werte enthalten, die Sie filtern möchten:
Object.keys(usersById).map(id => usersById[id]).filter(user => user.registered)
Gehen Sie Bill auf diese Weise, er könnte für uns arbeiten.
Warum greifen die Leute nicht öfter auf die Theorie zurück?
Manchmal kennen sie sie einfach nicht. Meistens sind sie zu beschäftigt und finden keine Zeit, um diese Art der Problemlösung zu lernen - sie brauchen einfach alles, um zu arbeiten. Sie riskieren, diesen Ansatz zu einer Gewohnheit zu machen, die ein Hindernis für die Entwicklung ihrer Fähigkeiten darstellt.
Beginnen Sie immer mit einer Theorie, um solche Fehler zu vermeiden. Überlegen Sie sich in jeder Phase des Prozesses, mit welcher Art von Daten Sie es zu tun haben. Betrachten Sie primitive Datentypen: Array, Objekt, Zeichenfolge usw., anstatt sich ständig auf vertraute Muster zu verlassen. Wenn Sie eine Funktion oder Methode verwenden, lesen Sie in der Dokumentation nach, welche Datentypen sie unterstützen, welche Argumente sie verwenden und was das Ergebnis ist.
Mit diesem Ansatz finden Sie beim ersten Versuch eine funktionierende Lösung. Sie können sich der Richtigkeit sicher sein, da Sie Ihre Aktionen speziell anhand der angegebenen Eingabe und der gewünschten Ausgabe ausgewählt haben. Gehen Sie tief in die Grundlagen jeder Operation (Datentypen und Rückgabewerte) ein und nicht in unscharfe Geschäftsformulierungen (wie "registrierte Benutzer").