Der Code ist lebendig und tot. Teil Zwei Aktionen und Eigenschaften

Letztes Mal schrieb ich, dass die Namen von Objekten von großer Bedeutung sind und dass sie sorgfältig und mit Liebe zum Detail ausgewählt werden müssen. Schlechter Name macht Angst und erlaubt nicht, die Essenz dessen zu verstehen, was passiert. Aber was ist das Wesentliche daran?


Es ist schwierig, einen Helden zu bewerten, ohne seine „Statistiken“ und „Fähigkeiten“ zu verstehen. Was er kann und wozu er fähig ist, ist der nächste Schwierigkeitsgrad, in den wir eintauchen müssen. Es reicht nicht aus, das innere Heiligtum des Objekts mit Hilfe eines genauen Namens wiederzugeben. Sie müssen auch sicherstellen, dass es sich immer noch um ein Heiligtum handelt und nicht um Ställe von Gettern.


Darüber - im Artikel.


Inhaltsverzeichnis durchlaufen


  1. Die Objekte
  2. Aktionen und Eigenschaften
  3. Code als Text

Aktionen


Der Charakter greift an, verteidigt, weicht aus, schießt aus einem Bogen, benutzt Zauber, schwenkt eine Klinge. Der Name spiegelt das Objekt wider, aber das Objekt selbst ist in Bewegung, in Reaktion, in Aktion. Andernfalls würden wir über Tabellen in Excel sprechen.


In C # sind Aktionen Methoden und Funktionen. Und für uns: Verben, Atome verbaler Bewegung. Verben verschieben die Zeit, weil Objekte existieren und interagieren. Wo sich etwas ändert, muss es ein Verb geben.


Setter


Von allen Änderungen ist die Zuordnung am wenigsten beweglich. Es beschreibt streng und mathematisch, was Größen sind und was sie sind, vermittelt aber niemals Leben und Kraft in einen Text, wie es Verben tun.


Beispielsweise gibt es IPullRequest mit der Status Eigenschaft, die Approved , Declined oder Merged . Sie können pullRequest.Status = Status.Declined schreiben, dies entspricht jedoch der Aussage "Setzen Sie die pullRequest.Status = Status.Declined auf den abgebrochenen Status" . Viel stärker ist pullRequest.Decline() und dementsprechend pullRequest.Approve() , pullRequest.Merge() .


Ein aktives Verb ist einem Setter vorzuziehen, aber nicht alle Verben sind es.


Passive Stimme


PerformPurchase , DoDelete , MakeCall .


Wie in HeroManager ein wichtiges Substantiv von einem bedeutungslosen Manager verdeckt, also in PerformMigration - Perform . Immerhin lebendiger - einfach Migrate !


Aktive Verben aktualisieren den Text: nicht "getroffen" , sondern "getroffen" ; nicht "geschwungen" , sondern "gewinkt" ; nicht "eine Entscheidung getroffen" , sondern "entschieden" . Also im Code: PerformApplicationApply ; DoDeleteDelete ; PerformPurchasePurchase , Buy . (Aber DealDamage sich beruhigt, obwohl in seltenen Fällen ein Attack gemeint sein kann .)


Wir vermeiden die passive Stimme, entwickeln die Geschichte, bewegen die Charaktere, müssen aber auch sicherstellen, dass der Film nicht in Schwarzweiß erscheint.


Starke Verben


Einige Wörter vermitteln Bedeutungsschattierungen besser als andere. Wenn Sie schreiben "er hat ein Glas Wasser getrunken" , wird es einfach und klar sein. Aber "ein Glas Wasser abgelassen" - im übertragenen Sinne stärker.


Die Änderung der Gesundheit des Spielers kann also durch player.Health = X oder player.SetHealth , aber malerischer ist player.RestoreHealth .


Oder wir kennen Stack nicht durch Add/Remove , sondern durch Push/Pop .


Starke und aktive Verben sättigen das Objekt mit Verhalten, wenn sie nicht zu spezifisch sind.


Redundante Teile


Wie bei ManualResetEvent sind die Details und Exzesse der API umso ManualResetEvent , je näher wir den technischen Interna von .NET kommen, die komplex sind und die einfach ausgedrückt werden könnten.


Es kommt vor, dass Sie einige Arbeiten an einem anderen Thread ausführen müssen, um sich jedoch nicht darum zu kümmern, ihn zu erstellen und zu stoppen. In C # gibt es dafür ThreadPool . Nur hier ist ein einfaches "Arbeiten" hier - QueueUserWorkItem ! Welche Art von Arbeitselement ( WorkItem ) ist und was es sein kann, wenn nicht Benutzer ( User ), ist unklar. Viel einfacher wäre - ThreadPool.Run oder ThreadPool.Execute .


Ein weiteres Beispiel. Es ist gut, sich daran zu erinnern und zu wissen, dass es eine CAS- Anweisung ( Atomic Compare-and-Swap) gibt, aber eine saubere Portierung auf Code ist nicht die beste Lösung. Interlocked.CompareExchange(ref x, newX, oldX) ist den Atomically.Change(ref x, from: oldX, to: newX) von Atomically.Change(ref x, from: oldX, to: newX) (unter Verwendung benannter Parameter) Atomically.Change(ref x, from: oldX, to: newX) .


Der Code ist keine Promotion in der Arbeit mit einem Quantencomputer, keine Anwendung auf mathematische Berechnungen, aber dem Leser ist es manchmal völlig gleichgültig, wie die Anweisungen auf niedriger Ebene genannt werden. Der tägliche Gebrauch ist wichtig.


Wiederholungen


UsersRepository.AddUser , Benchmark.ExecuteBenchmark , AppInitializer.Initialize , UniversalMarshaller.Marshal , Logger.LogError .


Wie ich im letzten Teil sagte, untergräbt Wiederholung die Bedeutung, komprimiert den Raum.


Nicht UsersRepository.AddUser , sondern UsersRepository.Add ; nicht Directory.CreateDirectory , sondern Directory.Create ; nicht HttpWebResponse.GetResponseStream , sondern HttpWebResponse.Stream ; nicht Logger.LogError , sondern Log.Error .


Feiner Müll


Check ist ein vielseitiges Wort. CheckHasLongName kann entweder einen bool oder eine Ausnahme CheckHasLongName wenn der Benutzer einen zu langen Namen hat. Besser ist bool HasLongName oder void EnsureHasShortName . Ich habe sogar CheckRebootCounter , der ... Irgendwo drinnen IIS neu gestartet hat!


Enumerate - aus derselben Serie. In .NET gibt es eine Directory.EnumerateDirectories(path) -Methode: Aus irgendeinem Grund wird angegeben, dass die Ordner aufgelistet werden, obwohl Directories.Of(path) oder path.Directories() .


Calc - Calculate wird so oft reduziert, obwohl es eher wie Calciumablagerungen aussieht.


Proc ist eine weitere ausgefallene Abkürzung für Process .


Base , Impl , Internal , Raw - parasitäre Wörter, die die Komplexität von Objekten anzeigen.


Insgesamt


Wieder einmal wird ein aufmerksamer Leser feststellen, dass es nur um Vereinfachung, das Vergleichen natürlicher Sprache geht, und die Tipps selbst beziehen sich größtenteils nicht nur auf den Code, sondern allgemein auf das Schreiben. Mit ihnen poliert der Entwickler sowohl den Code als Text als auch den Text selbst und strebt der Einfachheit halber nach einer transparenten, reibungslosen Darstellung.


Nachdem wir die Bewegung und die "Spezialeffekte" herausgefunden haben , schauen wir uns an, wie die Beziehungen zwischen Objekten beschrieben werden.


Die Eigenschaften


Der Charakter hat Gesundheit und Mana; Artikel sind im Warenkorb; Das Sonnensystem besteht aus Planeten. Objekte handeln nicht nur selbstlos, sondern beziehen sich auch auf: hierarchisch (Ahnen-Erben), kompositorisch (ganzzahliger Teil), räumlich (Speicherelement) usw.


In C # sind Eigenschaften und Beziehungen Methoden (normalerweise beginnend mit Get ), Getter (Eigenschaften mit einem bestimmten get Body) und Felder. Aber für uns ist es: Wortzusätze, die die Zugehörigkeit eines Objekts zu einem anderen ausdrücken. Zum Beispiel hat ein Spieler Gesundheit - Player.Health , was fast genau der Gesundheit des englischen „Spielers“ entspricht .


Was heute am verwirrendsten ist, sind Aktionsmethoden und Eigenschaftsmethoden.


Verb statt Substantiv


GetDiscount , CalculateDamage , FetchResult , ComputeFov , CreateMap .


Siedlungen sind überall zu hören: Methoden müssen mit Verben beginnen. Sie sehen selten jemanden zweifeln: Ist das wirklich so? Schließlich kann es keinen signifikanten Unterschied zwischen Player.Health und Player.Health() . Lassen Sie die Datensätze syntaktisch unterschiedlich sein, sie bedeuten dasselbe.


Angenommen, in IUsersRepository wird leicht ein GetUser(int id) erwartet. Warum, um den Benutzer darzustellen, an eine Art Quittung ( Get ) denken? Es wird genauer sein - User(int id) !


Und wirklich: nicht FetchResult() , sondern Result() ; nicht GetResponse() , sondern Response() ; nicht CalculateDamage() , sondern Damage() .


Ein DDD-Vortrag gibt ein Beispiel für einen „guten“ Code: DiscountCalculator mit der CalculateDiscountBy(int customerId) Methode CalculateDiscountBy(int customerId) . Es gibt nicht nur eine symmetrische Wiederholung im Gesicht - DiscountCalculator.CalculateDiscount , sie haben auch angegeben, dass der Rabatt berechnet wird . Und was hat man sonst noch mit ihr zu tun?


Es wäre stärker, von der Entität selbst zu gehen - Discount mit der static decimal Of(Customer customer, Order order) _discountCalculator.CalculateDiscountBy(customerId) , um Discount.Of(customer, order) _discountCalculator.CalculateDiscountBy(customerId) - ist einfacher als _discountCalculator.CalculateDiscountBy(customerId) und entspricht einer einzelnen Sprache.


CreateMap() wir das Verb weglassen, verlieren wir manchmal etwas, wie zum Beispiel in CreateMap() : Ein direkter Ersatz durch Map() möglicherweise nicht aus. Dann ist NewMap() die beste Lösung: Auch hier befindet sich das Objekt am Kopf, nicht die Aktion.


Die Verwendung leerer leerer Verben ist charakteristisch für eine veraltete, imperative Kultur, in der der Algorithmus primär ist und dem Konzept voraus ist. Dort finden Sie häufig eine „gehärtete Klinge“ als eine „gehärtete Klinge“ . Der Stil der Bücher über James Bond eignet sich jedoch nicht zur Beschreibung der Landschaft. Wo es keine Bewegung gibt, gibt es keinen Platz für das Verb.


Andere


Eigenschaften und Methoden, die die Beziehungen zwischen Objekten ausdrücken, sind ebenfalls Objekte, daher gilt das oben Gesagte in vielerlei Hinsicht für sie.


Zum Beispiel Wiederholungen in Eigenschaften: nicht Thread.CurrentThread , sondern Thread.Current ; nicht Inventory.InventoryItems , sondern Inventory.Items usw.


Insgesamt


Einfache, verständliche Wörter werden nicht verwechselt, und daher wird auch der daraus bestehende Code nicht verwechselt. Beim Schreiben ist es ebenso wichtig, leicht zu schreiben: Vermeiden Sie passive Präpositionen, eine Fülle von Adverbien und Adjektiven, Wiederholungen, denn Handlungen bevorzugen ein Verb gegenüber einem Substantiv. Ein bekanntes Beispiel: "Er nickte mit dem Kopf und stimmte zu" anstelle von "Er nickte" verursacht ein Lächeln, und ich erinnere mich an QueueUserWorkItem .


Der Text aus dem Code unterscheidet sich auch darin, dass Sie im ersten Fall bezahlt werden, wenn das Haus steht und in den Strahlen der untergehenden Sonne ertrinkt . im zweiten - wenn das Haus steht ; Aber es lohnt sich, sich daran zu erinnern: Ein Haus sollte stehen und nicht von Helfern stammen.


In den ersten beiden Artikeln der Serie wollte ich zeigen, wie wichtig es ist, nicht nur am Algorithmus, sondern auch am Wort zu arbeiten. wie Namen den Inhalt dessen bestimmen, was genannt wird; wie redundanter und überkomplizierter Code den Leser vertreibt.


Gute Namen sind nur Notizen. Zum Spielen müssen sie geschrieben und in Musik verkörpert sein. Ich werde Ihnen im nächsten, letzten Artikel mehr erzählen.

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


All Articles