Als ich den Code überprüfte, hatte ich das Gefühl, dass ich immer auf ähnliche Punkte hingewiesen habe, und fasste die Standpunkte zusammen, die mir wichtig sind. Es gibt einige Perspektiven, die nicht von der verwendeten Sprache abhängen, aber da ich bei der Arbeit hauptsächlich Rails verwende, gibt es auch Perspektiven, die für Ruby und Rails spezifisch sind.
Vorerst habe ich kurz geschrieben, woran ich im Moment denken kann, aber ich werde es hinzufügen, wenn ich mich an den Standpunkt erinnere, der mir in Zukunft am Herzen liegt. Es ist gut, weiterhin sowohl Entwicklungs- als auch Qiita-Artikel (CD) zu liefern, ohne von Anfang an nach Perfektion zu streben.
Verwenden Sie statische Analysewerkzeuge, um statische Teile Ihres Codes zu überprüfen, z. B. die folgenden Einrückungen und Codierungsregeln. Es ist Zeitverschwendung für den Menschen, visuell zu prüfen, und es kommt zu Undichtigkeiten und Unschärfen. Darüber hinaus werden Sie von den Details abgelenkt und übersehen die Punkte, auf die hingewiesen werden sollte.
Rubocop ist ein bekanntes statisches Analysewerkzeug in Ruby. Die Einführung von Funktionen, die eine solche Entwicklung unterstützen, wird in der Anfangsentwicklung häufig verschoben, es ist jedoch sehr schwierig, statische Analysewerkzeuge in die Mitte einzufügen. Wenn Sie versuchen, es später hinzuzufügen, erhalten Sie Code, der die Regeln lockert oder befreit. Fügen Sie ihn daher in der ersten Entwicklungsphase hinzu. Persönlich denke ich, dass es am besten ist, es fest zu setzen und sich nach Bedarf zu entspannen.
Es ist ein widersprüchliches Thema, da ich gerade geschrieben habe, dass die statische Codeprüfung vor einer Zeit verwendet werden sollte, aber die statische Codeprüfung ist gelockert oder eine Ausnahme, wenn es schwierig ist, Korrekturen vorzunehmen, um die Angabe der statischen Codeprüfung zu korrigieren. Es ist besser einzustellen. Eine übliche Methode sind überstrichene Methoden. Wenn die Methode eine bestimmte Anzahl von Zeilen überschreitet, wird sie als geteilt bezeichnet. Wenn es jedoch angemessen ist, dass die Verarbeitung eine einzelne Einheit ist, ist sie nur schwer zu verstehen, sodass ich denke, dass es nicht erforderlich ist, sie zu erzwingen.
Mit Rails funktioniert es oft ohne Probleme, auch wenn der Statuscode nicht mit der Methode oder Antwort übereinstimmt. Daher versuche ich zu überprüfen, ob der Statuscode ordnungsgemäß verwendet wird. Ich denke, dass die detaillierte Verwendung je nach Person unterschiedlich ist, aber ich werde meine Interpretation über den Hauptstatuscode schreiben.
2XX Dies ist der Statuscode, wenn die Anforderung normal verarbeitet wird.
201 Created Es wird verwendet, wenn eine Ressource durch POST- oder PUT-Anforderung generiert wird. Bei Verwendung von 201 wird die generierte Ressource häufig im Antworttext zurückgegeben. Wenn Sie nichts zurückgeben müssen, sollten Sie 204 No Content verwenden.
204 No Content Es wird häufig verwendet, wenn eine Ressource durch eine DELETE-Anforderung gelöscht wird, aber es wird auch verwendet, wenn selbst in POST oder PUT kein Antworttext vorhanden ist. Wenn Sie dies verwenden, geben Sie keinen Wert in den Antworttext ein.
200 OK Wenn Sie eine andere als die oben genannte normale Antwort zurückgeben möchten, sollten Sie grundsätzlich 200 OK verwenden.
Dies ist der Statuscode, wenn Sie zu einer anderen Seite umleiten möchten.
301 Moved Permanently Verwenden Sie 301, wenn Sie dauerhaft auf eine andere Seite umleiten möchten. Wenn Sie beispielsweise eine Webseite migrieren, wird sie verwendet, um von der URL der alten Seite zur neuen Seite umzuleiten. Es ist auch als SEO-Maßnahme nützlich. Wenn Sie 301 angeben, indiziert die Suchmaschine die neue URL für Sie.
303 See Other Ich war mir dessen bis vor kurzem nicht bewusst, aber wenn Sie nach dem Registrieren / Aktualisieren der Ressource zur Detailseite der Ressource umleiten möchten, verwenden Sie 303. Das Muster ist wie folgt. Registrieren Sie neue Ressourcen bei POST / resources und leiten Sie zu der Seite (GET / resources /: id) weiter, auf der Ressourceninformationen angezeigt werden
302 Found Verwenden Sie im Gegensatz zu 301 302, wenn Sie vorübergehend auf eine andere Seite umleiten möchten. Wenn Sie "redirect_to" in Rails verwenden, ist es standardmäßig 302, aber unter Berücksichtigung des Umleitungszwecks hat 302 nur wenige Verwendungszwecke, und ich denke, dass es oft besser ist, es an 301 oder 303 zu verteilen.
Dies ist der Statuscode, wenn ein vom Client verursachter Fehler auftritt.
404 Not Found Der Statuscode, der verwendet wird, wenn die Seite nicht gefunden werden kann. Da "404" oft auf dem Bildschirm angezeigt wird, denke ich, dass viele Leute es wissen.
Für manche Menschen mag es eine andere Idee sein, aber ich versuche, 404 und 200 richtig zu verwenden, wenn ich bedenke, ob die fehlende Ressource für den Kunden abnormal oder normal ist. Hier sind einige konkrete Beispiele, um die Vorstellung zu erleichtern.
Wenn Ressourcen mit GET / resources /: id
nicht gefunden werden können
Gibt 404 zurück, da der Client eine ID angibt, die nicht vorhanden ist
Holen Sie sich die TODO-Liste Wenn GET / todos
0 TODOs hat
Da 0 TODO normal ist, werden 200 zurückgegeben.
Als ich die Verengungsbedingungen in der Geschäftssuche spezifizierte, wurde es 0 Geben Sie 404 zurück, die die vom Client angegebenen Bedingungen nicht erfüllt haben Aus SEO-Sicht möchte ich nicht, dass die Suchmaschine 0 Shop-Suchergebnisseiten indiziert, daher möchte ich nicht durch Angabe von 404 indizieren.
401 Unauthorized Verwenden Sie diese Option, wenn für eine Aktion, für die eine Authentifizierung erforderlich ist, keine gültigen Anmeldeinformationen übergeben werden.
403 Forbidden Es wird verwendet, wenn die Authentifizierung durchgeführt wird, die Nutzungsberechtigung jedoch nicht ausreicht. Zum Beispiel, wenn ein schreibgeschützter Benutzer versucht, eine Ressource zu aktualisieren.
Bei der Verwendung des 403 ist jedoch eines zu beachten. Wenn Sie auf eine Ressource zugreifen, die für einen Benutzer privat ist. In diesem Fall möchten Sie 403 verwenden, wenn Sie an das System denken, da Sie keine Zugriffsberechtigung haben. Wenn Sie jedoch 403 zurückgeben, wird der Benutzer darüber informiert, dass die Ressource vorhanden ist. In einem solchen Fall ist es besser, die Existenz selbst nicht zu informieren, daher ist es besser, 404 mit der Bedeutung zurückzugeben, dass sie nicht existiert.
400 Bad Request Es wird verwendet, wenn eine ungültige Anforderung eingeht, z. B. wenn die erforderlichen Parameter nicht angegeben sind. Wenn es nicht für 401, 403, 404 gilt, verwende ich normalerweise 400.
410 Gone Es wird verwendet, wenn auf die URL zugegriffen wird, die dauerhaft gelöscht werden soll, z. B. nach Ablauf des Zeitraums und Löschen der Seite auf der zeitlich begrenzten Kampagnenseite. Es ist eine Schande, aber in letzter Zeit bleiben viele Seiten auch nach Ablauf der Kampagnenperiode unbeaufsichtigt, und es wird zu einem Geräusch bei der Suche, was ärgerlich ist. Ich möchte, dass Sie die Aufgabe haben, es nach Ablauf der Frist zu löschen und ordnungsgemäß auszuführen.
Dies ist der Statuscode, wenn ein serverbedingter Fehler auftritt.
500 Internal Server Error Verwenden Sie diese Option, wenn auf dem Server ein unerwarteter Fehler auftritt. Ich denke nicht, dass es üblich ist, dass ein Programm explizit einen 500-Fehler generiert. Wenn es also einen Teil gibt, der explizit einen 500-Fehler zurückgibt, ist es meiner Meinung nach besser, ihn so zu ändern, dass ein entsprechender Fehler zurückgegeben wird.
503 Service Unavailable Es wird verwendet, wenn die Wartungsseite angezeigt wird, da aufgrund regelmäßiger Wartung kein normaler Zugriff möglich ist.
Möglicherweise möchten Sie eine Fehlermeldung an den Client zurückgeben, wenn ein Fehler auftritt. Stellen Sie jedoch sicher, dass die Meldung korrekt ist. Die Sichtweise ist, ob Sie die Fehlermeldung erhalten und Maßnahmen ergreifen können. Ein häufiges schlechtes Beispiel ist ein Muster, das eine Nachricht zurückgibt, in der kein Element wie "Ungültiges Eingabeelement" angegeben ist, wenn eine Eingabebedingung auf einem Bildschirm mit mehreren Eingabeelementen nicht erfüllt ist. Damit wissen Sie nicht, welcher Artikel falsch ist und Sie wissen nicht, was Sie tun sollen. Lassen Sie uns das Element und die Fehlerursache wie "Bitte geben Sie den Wert des xx-Elements als numerischen Wert ein" mitteilen.
Es gibt jedoch Fälle, in denen es NG ist, den Benutzer im Detail zu informieren. Wenn Sie beispielsweise auf dem Anmeldebildschirm eine vorhandene ID angeben, in der Sie die ID / das Kennwort eingeben und bei falschem Kennwort "falsches Kennwort" zurückgeben, wird der Benutzer darüber informiert, dass die ID vorhanden ist. .. Mit dieser Implementierung kann ein böswilliger Benutzer eine geeignete ID eingeben, um eine Liste der vorhandenen IDs zu erstellen. Der Anmeldebildschirm sollte eine Nachricht zurückgeben, die nicht erkennen kann, was falsch ist, z. B. "Ungültige Anmeldeinformationen", selbst wenn die ID nicht vorhanden ist oder nur das Kennwort unterschiedlich ist.
Ich denke, dass moderne Webanwendungen oft separate Front- und Backends haben. Infolgedessen bietet das Backend häufig Funktionen als API. Wenn Sie eine API erstellen und ein aufgezähltes Element zurückgeben, sollte es zurückgegeben werden, damit die Bedeutung nur anhand des Werts verstanden werden kann. Zum Beispiel, wenn Sie folgenden Status haben:
enum status {
todo: 1,
in_progress: 2,
done: 3
}
Wenn Sie dies an die Rezeption zurücksenden möchten, sollten Sie anstelle der Nummer (1, 2, 3) den Namen (z. B. "do to do") zurückgeben. Wenn Sie einen numerischen Wert wie "status = 1" zurückgeben, was ist 1, wenn Sie die Antwort sehen? Wenn Sie jedoch den Namen wie "status =" todo "" zurückgeben, können Sie die Bedeutung nur durch einen Blick darauf verstehen.
Überprüfen Sie bei der Rückgabe eines Arrays, ob die Reihenfolge des Arrays eindeutig ist.
Im Folgenden wird das durch user_id eingegrenzte Überprüfungsarray zurückgegeben. Da jedoch keine Reihenfolge angegeben ist, ist nicht sicher, in welcher Reihenfolge sie zurückgegeben werden. Es ist in Ordnung, wenn es sicher ist, dass der Anrufer sich nicht um die Bestellung kümmert, aber geben Sie die Reihenfolge an, damit die Bestellung festgelegt wird.
def my_reviews(user_id)
Review.where(user_id: user_id)
end
Unten wird die absteigende Reihenfolge von created_at angegeben. Wenn dies der Fall ist, können Sie anscheinend die neu erstellten in der richtigen Reihenfolge erhalten.
def my_reviews(user_id)
Review.where(user_id: user_id).order(created_at: :desc)
end
Es gibt jedoch immer noch Probleme damit. Die Reihenfolge ist ungewiss, wenn created_at dieselbe Überprüfung hat. Um die Reihenfolge sicher zu bestimmen, ist es gut zu prüfen, ob die in der Reihenfolge angegebenen Spalten wie unten gezeigt eindeutig sind. Dieses Mal habe ich die absteigende Reihenfolge der ID für die zweite Sortierung angegeben, um sie eindeutig zu machen.
def my_reviews(user_id)
# 1. created_In absteigender Reihenfolge von um anordnen. Allerdings erstellt_at hat keine eindeutigen Einschränkungen, daher kann es am selben Tag sein
# 2.Wenn es am selben Tag ist, ordnen Sie sie in absteigender Reihenfolge der ID an. Die ID ist eindeutig und kann daher nicht denselben Wert haben
# =>Die Reihenfolge ist eindeutig festgelegt
Review.where(user_id: user_id).order(created_at: :desc, id: :desc)
end
Während der Codeüberprüfung werden möglicherweise Implementierungen angezeigt, deren Verständnis lange dauert oder die irreführend sind. Eine solche Implementierung sollte so einfach wie möglich sein, da jeder, der diesen Code in Zukunft sieht, dasselbe empfinden und den Aufwand für das Lesen von Code erhöhen und die Wahrscheinlichkeit des Einbettens von Fehlern erhöhen wird. Wenn Sie es nicht einfach machen können, können Sie einen Kommentar hinzufügen. Wenn Sie ein Framework wie Rails verwenden, können Sie falsch verstehen, dass Sie es außerhalb des Frameworks verwenden, wie unten gezeigt. Lassen Sie uns irreführenden Code mit einer hohen Wahrscheinlichkeit loswerden, dass später keine Fehler mehr auftreten.
class Review
belongs_to :user
enum status {
open: 0,
close: 1,
}
end
class User
#× Obwohl es sich um die Standardzuordnung handelt, wird sie durch Angabe von Bedingungen eingegrenzt
has_many :reviews, -> { open }
#○ Wenn Sie eine Bedingung festlegen möchten, verwenden Sie einen Namen, der sie versteht.
has_many :open_reviews, -> { open }, class_name: 'Review'
end
class Hoge
def fuga(user_id)
user = User.find user_id
#Wenn Sie nur hier suchen, besteht eine hohe Wahrscheinlichkeit, dass Sie fälschlicherweise glauben, alle Bewertungen des Benutzers erhalten zu haben.
user.reviews
end
end
YAGNI Wie viele von Ihnen vielleicht wissen, gibt es das Wort YAGNI. Siehe Wikipedia für Details. https://ja.wikipedia.org/wiki/YAGNI
Wie oben erwähnt, besteht kaum eine Chance, dass Sie sich eine Funktion vorstellen und implementieren können, die Sie noch nicht verwendet haben, und sie unverändert verwenden. Seien Sie vorsichtig, wenn Sie den Code sehen, den Sie schreiben, um sich die Zukunft vorzustellen. Es ist schmerzhaft, den implementierten Code entfernen zu lassen, aber es ist oft besser, ihn zu entfernen. Wenn Sie es verlassen, kann es später stören oder Sie müssen es möglicherweise reparieren, obwohl Sie es während des Refactorings nicht verwendet haben, was Ihre Produktivität beeinträchtigen kann.
Machen Sie Methoden und Konstanten, die nicht von außen aufgerufen werden, privat. Wenn es öffentlich ist, ist der Einflussbereich beim Ändern der Methode oder Konstante die gesamte Quelle. Wenn es jedoch privat ist, müssen Sie sich nur um dieselbe Klasse kümmern, sodass es recht einfach ist, den Einflussbereich der Quellmodifikation wie Refactoring zu untersuchen. Werden.
Jede Klasse hat ihre eigenen Verantwortlichkeiten. Überprüfen Sie, ob Ihre Verantwortlichkeiten eingehalten werden.
Betrachten Sie beispielsweise die Aktion, die Ihr Konto aktiviert.
Da die zum Zeitpunkt der Aktivierung ausgeführte Verarbeitung dem Kontomodell bekannt sein sollte, für das das Konto zuständig ist, ist es besser, sie mit der folgenden Richtlinie zu implementieren.
class AccountController
#× Der Controller weiß, was zum Zeitpunkt der Aktivierung zu tun ist
def activate
account = Account.find_by(token: params[:token])
account.status = :activated
account.activated_at = Time.now
account.token = nil
account.save!
end
#○ Der Controller weiß zum Zeitpunkt der Aktivierung nicht, was zu tun ist, und fragt das Kontomodell
def activate
account = Account.find_by(token: params[:token])
account.activate!
end
end
class Account
def activate!
status = :activated
activated_at = Time.now
token = nil
save!
end
end
includes, eager_load, preload Wenn Sie sich über diese Unterschiede nicht sicher sind, lesen Sie bitte den folgenden Qiita-Artikel, den Sie mindestens einmal gesehen haben sollten, wenn Sie Rails verwenden. https://qiita.com/k0kubun/items/80c5a5494f53bb88dc58
Includes ist eine bequeme Existenz, die Preload und eifriges Laden richtig verwendet. Als ich anfing, Rails zu verwenden, dachte ich, es wäre besser, Includes zu verwenden, aber die aktuelle Idee ist das Gegenteil. Ich versuche, Basic Preload oder Zeal_load zu verwenden. Dies liegt daran, dass wir meiner Meinung nach wissen sollten, ob wir bei der Implementierung beitreten sollen oder nicht. Einschlüsse, die je nach Implementierung möglicherweise beitreten oder nicht, sind schwer zu kontrollieren und können zu unerwartetem Verhalten führen. Daher ist es besser, sie nicht zu verwenden.
ActiveRecord ist sehr nützlich, aber es scheint weit vom Rails-Ingenieur entfernt zu sein.
Wenn Sie selbst SQL schreiben, sind Sie bereit, SQL auszugeben, das Sie nicht schreiben würden.
Unter ihnen ist das Muster des vergeblichen Beitritts besonders zu sehen.
Ein konkretes Beispiel ist unten gezeigt.
Eine Methode find_by_organization
, die die organisatoin_id angibt, um die Benutzer abzurufen, die zu dieser Organisation gehören.
class User
has_many :user_organization
def self.find_by_organization(organization_id)
#× Organisationstabellen müssen nicht verbunden werden
# select * from users inner join user_organizations on users.id = user_organizations.user_id inner join organizations on user_organizations.organization_id = organizations.id where organizations.id = #{organization_id}
joins(user_organization: :organization).merge(Organization.where(id: organization_id))
# ○ user_Nur Organisationen werden kombiniert
# select * from users inner join user_organizations on users.id = user_organizations.user_id where user_organizations.organization_id = #{organization_id}
joins(:user_organization).merge(UserOrganization.where(organization_id: organization_id))
end
end
class Organization
has_many :user_organization
end
class UserOrganization
belongs_to :user
belongs_to :organization
end
Recommended Posts