Einen schönen, gut gestalteten und gut aussehenden Code zu schreiben ist nicht so schwer, wie es scheint. Man muss sich nur ein wenig Mühe geben, um die wichtigsten Regeln kennenzulernen und sie in seinem Code zu verwenden. Und es muss nicht alles auf einmal sein, aber wenn Sie sich mit einer Sache wohl fühlen, versuchen Sie, über eine andere nachzudenken, und so weiter.
Bauen Sie soliden, nicht dummen Code
Beginnen wir mit der Einführung der elementarsten Regeln, die als SOLID bezeichnet werden. Es ist ein Begriff, der eine Sammlung von Gestaltungsprinzipien für gute Code das von Robert C. Martin erfunden wurde und wie es funktioniert:
S steht für das Prinzip der einzigen Verantwortung
Sie besagt, dass eine Klasse nur einen einzigen Grund für eine Änderung haben sollte. Mit anderen Worten, eine Klasse sollte nur eine Aufgabe haben, also sollten wir vermeiden, große Klassen mit vielen Aufgaben zu schreiben. Wenn unsere Klasse viele Dinge zu tun hat, dann sollte jede von ihnen in separate Klassen delegiert werden.
class Benachrichtigung
def initialize(params)
@params = params
end
def call
EmailSender.new(Nachricht).call
end
privat
def nachricht
# eine Implementierung
end
end
O bedeutet Offen/Geschlossen-Prinzip
Sie besagt, dass man das Verhalten einer Klasse erweitern können sollte, ohne sie zu verändern. Mit anderen Worten, es sollte einfach sein, eine Klasse zu erweitern, ohne sie zu verändern. Wir können dies z.B. durch die Verwendung von Strategiemustern oder Dekoratoren erreichen.
class Benachrichtigung
def initialize(params, sender)
@params = params
@Absender = Absender
end
def call
sender.call Nachricht
end
privat
def nachricht
# eine Implementierung
end
end
class EmailSender
def call(nachricht)
# eine Implementierung
end
end
class SmsSender
def call(nachricht)
# eine Implementierung
end
end
Mit diesem Design ist es möglich, neue Absender hinzuzufügen, ohne den Code zu ändern.
L bedeutet Liskov-Substitutionsprinzip
Sie besagt, dass abgeleitete Klassen durch ihre Basisklassen ersetzbar sein müssen. Mit anderen Worten: Die Verwendung von Klassen, die vom selben Vorfahren stammen, sollte leicht durch andere Nachkommen ersetzt werden können.
Klasse Logger {
info (Nachricht) {
console.info(this._prefixFor('info') + message)
}
error (message, err) {
console.error(this._prefixFor('error') + meldung)
if (err) {
console.error(err)
}
}
_prefixFor (type) {
// irgendeine Implementierung
}
}
class ScepticLogger extends Logger {
info (Nachricht) {
super.info(nachricht)
console.info(this._prefixFor('info')) + 'Und das ist alles, was ich zu sagen hatte.')
}
error (meldung, err) {
super.error(nachricht, err)
console.error(this._prefixFor('error')) + 'Na und!')
}
}
Wir können den Namen der Klasse leicht ersetzen, da beide genau die gleiche Verwendungsschnittstelle haben.
Ich meine das Prinzip der Schnittstellentrennung
Sie besagt, dass man feinkörnige Schnittstellen erstellen sollte, die kundenspezifisch sind. Was ist eine Schnittstelle? Es ist eine bereitgestellte Art der Nutzung eines Teils des Codes. Ein Verstoß gegen diese Regel könnte also z. B. eine Klasse mit zu vielen Methoden oder eine Methode mit zu vielen Argumentoptionen sein. Ein gutes Beispiel zur Veranschaulichung dieses Prinzips ist das Repository-Muster, nicht nur, weil wir oft viele Methoden in einer einzigen Klasse unterbringen, sondern auch, weil diese Methoden der Gefahr ausgesetzt sind, zu viele Argumente zu akzeptieren.
# diesmal nicht das beste Beispiel
class NotificationRepository
def find_all_by_ids(ids:, info:)
notifications = Notification.where(id: ids)
info ? notifications.where(type: :info) : notifications
end
end
# und eine bessere Variante
class NotificationRepository
def find_all_by_ids(ids:)
Notification.where(id: ids)
end
def find_all_by_ids_info(ids:)
find_all_by_ids(ids).where(type: :info)
end
end
D bedeutet Dependency Inversion Principle
Sie besagt, dass man sich auf Abstraktionen verlassen sollte, nicht auf Konkretisierungen. Mit anderen Worten: Eine Klasse, die eine andere verwendet, sollte nicht von deren Implementierungsdetails abhängen, wichtig ist nur die Benutzeroberfläche.
class Benachrichtigung
def initialize(params, sender)
@params = params
@Absender = Absender
end
def call
sender.call Nachricht
end
privat
def nachricht
# eine Implementierung
end
end
Alles, was wir über das Absenderobjekt wissen müssen, ist, dass es die Methode `call` zur Verfügung stellt, die die Nachricht als Argument erwartet.
Nicht der beste Code aller Zeiten
Es ist auch sehr wichtig, die Dinge zu kennen, die beim Schreiben von Code strikt vermieden werden sollten. Daher folgt hier eine weitere Sammlung von DUMMEN Prinzipien, die den Code nicht wartbar, schwer zu testen und wiederverwendbar machen.
S bedeutet Singleton
Singletons werden oft als Anti-Muster betrachtet und sollten generell vermieden werden. Das Hauptproblem bei diesem Muster ist jedoch, dass es eine Art Vorwand für globale Variablen/Methoden ist und von Entwicklern schnell überstrapaziert werden kann.
T bedeutet Tight Coupling
Sie bleibt erhalten, wenn eine Änderung in einem Modul auch Änderungen in anderen Teilen der Anwendung erfordert.
U bedeutet Unprüfbarkeit
Wenn Ihr Code gut ist, dann sollte das Schreiben von Tests Spaß machen und kein Alptraum sein.
P bedeutet vorzeitige Optimierung
Das Wort "verfrüht" ist hier der Schlüssel, denn wenn Sie es jetzt nicht brauchen, ist es Zeitverschwendung. Es ist besser, sich auf einen guten, sauberen Code zu konzentrieren als auf einige Mikro-Optimierungen, die im Allgemeinen einen komplexeren Code verursachen.
Ich meine Indeskriptive Benennung
Das ist das Schwierigste beim Schreiben von gutem Code, aber denken Sie daran, dass es nicht nur für den Rest Ihrer Arbeit wichtig ist. Team sondern auch für die Zukunft, also behandle dich gut 🙂 Es ist besser, einen langen Namen für eine Methode zu schreiben, der aber alles sagt, als einen kurzen und rätselhaften.
D bedeutet Vervielfältigung
Der Hauptgrund für doppelten Code ist der Grundsatz der engen Kopplung. Wenn Ihr Code eng gekoppelt ist, können Sie ihn nicht wiederverwenden und es kommt zu doppeltem Code.
Das ist im Moment nicht wirklich wichtig.
Ich möchte auch zwei sehr wichtige Dinge erwähnen, die oft ausgelassen werden. Von dem ersten sollten Sie schon gehört haben - es ist YAGNI, was bedeutet: Sie werden es nicht brauchen. Von Zeit zu Zeit beobachte ich dieses Problem, wenn ich Code-Reviews durchführe oder sogar meinen eigenen Code schreibe, aber wir sollten bei der Implementierung einer Funktion umdenken. Wir sollten genau den Code schreiben, den wir in diesem Moment brauchen, nicht mehr oder weniger. Wir sollten bedenken, dass sich alles sehr schnell ändert (vor allem die Anforderungen an die Anwendung), so dass es keinen Sinn hat, zu glauben, dass etwas irgendwann einmal nützlich sein wird. Verschwenden Sie nicht Ihre Zeit.
Das verstehe ich nicht.
Und der letzte Punkt, der nicht wirklich offensichtlich ist und für einige vielleicht umstritten sein mag, ist ein beschreibender Code. Damit meine ich nicht nur die Verwendung der richtigen Namen für Klassen, Variablen oder Methoden. Es ist wirklich, wirklich gut, wenn der gesamte Code auf den ersten Blick lesbar ist. Was ist der Zweck eines sehr kurzen Codes, wenn er so rätselhaft ist, wie er nur sein kann, und niemand weiß, was er tut, außer der Person, die ihn geschrieben hat? Meiner Meinung nach ist es besser, einige Zeichen zu schreibenBedingungsanweisungenetwas anderes mehr als ein Wort und dann gestern sitzen und sich fragen: Moment, was ist das Ergebnis, wie ist es passiert, und so weiter.
const params = [
{
movies: [
{ title: 'Die Erlösung der Shawshank' },
{ title: 'Einer flog über das Kuckucksnest' }
]
},
{
Filme: [
{ Titel: 'Saving Private Ryan' },
{ Titel: 'Pulp Fiction' },
{ Titel: 'Die Erlösung der Shawshank' },
]
}
]
// erster Vorschlag
function uniqueMovieTitlesFrom (params) {
const titles = params
.map(param => param.movies)
.reduce((prev, nex) => prev.concat(next))
.map(film => film.titel)
return [...new Set(titles)]
}
// zweiter Vorschlag
function uniqueMovieTitlesFrom (params) {
const titles = {}
params.forEach(param => {
param.movies.forEach(movie => titles[movie.title] = true)
})
return Object.keys(titles)
}
Zusammenfassend
Wie Sie sehen, gibt es eine Menge Regeln, die Sie sich merken müssen, aber wie ich bereits zu Beginn erwähnt habe, ist das Schreiben eines guten Codes eine Frage der Zeit. Wenn du anfängst, über eine Verbesserung deiner Programmiergewohnheiten nachzudenken, wirst du sehen, dass eine weitere gute Regel folgen wird, denn alle guten Dinge entstehen von selbst, genau wie die schlechten.
Lesen Sie mehr:
Was ist Ruby on Jets und wie kann man damit eine Anwendung erstellen?
Vuelendar. Ein neues Projekt von Codest auf der Grundlage von Vue.js
Codest's wöchentlicher Bericht über die besten technischen Artikel. Software für 50 Mio. gleichzeitige Sockets erstellen (10)