コードは生きていて死んでいます。 パート2 アクションとプロパティ

前回、私はオブジェクトの名前は非常に重要であり、注意深く選択し、細部に注意を払う必要があることを書きました。 悪い名前は怖がり、起こっていることの本質を理解することを許しません。 しかし、これの本質は何ですか?


主人公を「統計」「能力」を理解せずに評価することは困難です。 彼ができることとできることは、次のレベルの難易度です。 正確な名前を使用してオブジェクトの内側の聖域を反映するだけでは十分ではありません。また、これがゲッターからのstable舎ではなく、同じ聖域であることを確認する必要があります。


これについて-記事内。


サイクルの目次


  1. オブジェクト
  2. アクションとプロパティ
  3. テキストとしてコード

アクション


キャラクターは攻撃し、防御し、回避し、弓から撃ち、呪文を使い、刃を振ります。 名前はオブジェクトを反映していますが、オブジェクト自体は動き、反応し、動作しています。 それ以外の場合は、Excelのテーブルについて説明します。


C#では、アクションはメソッドと関数です。 そして私たちにとって:動詞、言葉の動きの原子。 動詞は時間を動かします。なぜなら、それらが存在して相互作用するからです。 変更がある場合-動詞が必要です。


セッター


すべての変更の中で、割り当てはモバイル性が最も低くなります。 それは量とは何かを厳密かつ数学的に記述しますが、動詞のように生命と活力をテキストに伝えません。


たとえば、 Statusプロパティを持つIPullRequestがあり、これはApprovedDeclinedまたはIPullRequestになります。 pullRequest.Status = Status.Declinedと書くことができますが、これは「プールリクエストをキャンセルされたステータスに設定する」と言うのと同じです。 より強力なのはpullRequest.Decline()あり、それに応じてpullRequest.Approve()pullRequest.Merge()ます。


アクティブな動詞はセッターよりも望ましいですが、すべての動詞が望ましいわけではありません。


受動態


PerformPurchaseDoDeleteMakeCall


HeroManager同様に、重要な名詞は無意味なManagerによって隠されているため、 PerformMigration - Perform 。 結局のところ、より生き生きとしています- Migrateだけです!


アクティブな動詞はテキストを更新します: 「ヒット」ではなく「ヒット」「スイングをした」のではなく、 揺れ た」「決定した」のではなく、 「決定した」 。 そのため、コードでは、 PerformApplicationApplyです。 DoDeleteDelete ; PerformPurchasePurchaseBuy(しかし、 DealDamage 落ち着きましたが、まれに Attack が意味される場合があります 。)


受動的な声を避けて、ストーリーを展開し、キャラクターを動かしますが、映画が白黒にならないようにする必要もあります。


強い動詞


一部の単語は、他の単語よりも意味の濃淡を伝えます。 「彼はコップ一杯の水を飲んだ」と書くと、それは簡単で明快です。 しかし、 「コップ一杯の水を排出しました」 -比fig的に、より強い。


そのため、プレーヤーの健康状態の変化はplayer.SetHealth player.Health = Xまたはplayer.SetHealthで表現できますが、より美しいのはplayer.RestoreHealthです。


または、たとえば、 Add/Removeではなく、 Push/PopよるStackを知っています。


強くて活発な動詞は、あまり具体的でない場合、動作でオブジェクトを飽和させます。


冗長部品


ManualResetEventManualResetEvent 、.NETの技術的な内部構造に近づくほど複雑になり、単純に表現した方がよいでしょう。APIの詳細と余分な部分が豊富になります。


別のスレッドでいくつかの作業を行う必要がある場合がありますが、その作成と停止を気にしないようにします。 C#には、このためのThreadPoolがあります。 ここにあるのは、単純な「作業を行う」だけですQueueUserWorkItem ! ユーザー( User )でない場合、どのような作業項目( WorkItem )であり、どのような作業項目であるかは不明です。 ThreadPool.RunまたはThreadPool.Execute方がはるかに簡単です。


別の例。 アトミックコンペアアンドスワップ(CAS)命令があることを覚えて知っておくのは良いことですが、コードにきれいに転送することは最良の解決策ではありません。 Interlocked.CompareExchange(ref x, newX, oldX)Interlocked.CompareExchange(ref x, newX, oldX) Atomically.Change(ref x, from: oldX, to: newX) (名前付きパラメーターを使用Atomically.Change(ref x, from: oldX, to: newX)より劣ります。


このコードは、量子コンピューターでの作業の博士号ではなく、数学計算への応用ではありません。また、読者は、低レベルの命令と呼ばれるものに完全に無関心な場合があります。 毎日の使用が重要です。


繰り返し


UsersRepository.AddUserBenchmark.ExecuteBenchmarkAppInitializer.InitializeUniversalMarshaller.MarshalLogger.LogError


最後の部分で述べたように、繰り返しは意味を損ない、スペースを圧縮します。


UsersRepository.AddUserではなく、 UsersRepository.AddDirectory.CreateDirectoryではなく、 Directory.CreateHttpWebResponse.GetResponseStreamではなく、 HttpWebResponse.StreamLogger.LogErrorではなく、 Log.Errorです。


小さなゴミ


Checkは多面的な言葉です。 CheckHasLongNameは、 bool返すか、ユーザー名が長すぎる場合に例外をスローできます。 より良いのはbool HasLongNameまたはvoid EnsureHasShortNameです。 私はCheckRebootCounterにも出会いCheckRebootCounter 。それは...内部のどこかでIISを再起動しました。


Enumerate -同じシリーズから。 .NETにはDirectory.EnumerateDirectories(path)メソッドがあります。何らかの理由で、 Directories.Of(path)またはpath.Directories()ですが、フォルダーがリストされるように指定されています。


Calcカルシウム沈着のように見えますが、 Calculateは頻繁に減少します。


Procは、 Processのもう1つの省略形です。


BaseImplInternalImplオブジェクトの複雑さを示す寄生語。


合計


繰り返しますが、注意深い読者は気づくでしょう、それはすべて単純化、自然なスピーチを例えることに帰着します、そして、ヒント自体は主にコードだけでなく、一般的に書くことに関連します。 開発者は、それらを使用して、コードをテキストとして、およびテキスト自体の両方を洗練し、透明でスムーズなプレゼンテーションを目指して、簡単にします。


動きと「特殊効果」がわかったので、オブジェクト間の関係がどのように記述されるかを見てみましょう。


プロパティ


キャラクターには健康とマナがあります。 アイテムはショッピングカートにあります。 太陽系は惑星で構成されています。 オブジェクトは、無私無欲に行動するだけでなく、関連する:階層的(祖先継承者)、構成的(整数部分)、空間的(記憶要素)など。


C#では、プロパティと関係はメソッド(通常はGet始まる)、ゲッター(特定のgetボディを持つプロパティ)、およびフィールドです。 しかし、私たちにとっては、あるオブジェクトの別のオブジェクトへの帰属を表す単語の追加です。 たとえば、プレーヤーのPlayer.Healthは、英語の「プレーヤーの体力」にほぼ正確に対応しています。


今日最も混乱しているのは、アクションメソッドとプロパティメソッドです。


名詞ではなく動詞


GetDiscountCalculateDamageFetchResultComputeFovCreateMap


解決は至る所で聞かれます:メソッドは動詞で始まらなければなりません。 疑う人はほとんどいません。これは本当にそうですか? 結局のところ、 Player.HealthPlayer.Health()間に大きな違いはありません。 レコードは構文的に異なっていて、同じことを意味しています。


IUsersRepositoryGetUser(int id)が簡単に予想されるとします。 ユーザーを表すために、何らかのレシート( Get )を考えるのはなぜですか? より正確になります- User(int id)


そして実際: FetchResult()ではなく、 Result() ; GetResponse()ではなく、 Response() ; CalculateDamage()ではなく、 Damage()


DDDの1つの講演では、「良い」コードの例として、 CalculateDiscountBy(int customerId)メソッドを使用したDiscountCalculatorCalculateDiscountBy(int customerId) 。 Faceに対称的な繰り返しがあるだけでなく、 DiscountCalculator.CalculateDiscountだけでなく、割引が計算されることも指定されています 。 そして、彼女と何をすべきか、他に何を求めますか?


エンティティ自体から移動する方が強力です- static decimal Of(Customer customer, Order order)メソッドを使用してDiscount.Of(customer, order)を呼び出す_discountCalculator.CalculateDiscountBy(customerId)より簡単で、単一の言語に対応します。


時々、動詞を省略すると、たとえばCreateMap()ように、何かを失います: Map()直接置き換えるだけでは不十分かもしれません。 最適なソリューションはNewMap()です。ここでも、オブジェクトはアクションではなく先頭にあります。


空の空の動詞の使用は、アルゴリズムが主要であり、概念に先んじている時代遅れの命令型文化の特徴です。 そこには、しばしば「強化され たブレード」よりも 焼き戻しされ たブレード」があります。 しかし、ジェームズ・ボンドに関する本のスタイルは、風景を説明するのに適していません。 動きがない場合、動詞の場所はありません。


その他


オブジェクト間の関係を表現するプロパティとメソッドもオブジェクトであるため、前述の多くの点がそれらに適用されます。


たとえば、プロパティの繰り返し: Thread.CurrentThreadではなく、 Thread.Current ; Inventory.InventoryItemsではなく、 Inventory.Itemsなど。


合計


単純で理解しやすい言葉は混同されないため、それらを含むコードも混同されません。 書く際には、簡単に書くことも同様に重要です。受動的な前置詞、副詞や形容詞の豊富さ、繰り返しを避け、行動は名詞よりも動詞を好むためです。 よく知られた例: 「彼はうなずいた」の代わりに「彼はうなずいて、 同意した」と笑顔を引き起こし、私はQueueUserWorkItemを思い出しQueueUserWorkItem


コードのテキストも異なります。最初のケースで家が立っていて、夕日の光線にownれている場合に支払われます。 第二に-家が立っている場合。 しかし、覚えておく価値があります。 は立ち上がるべきであり、ヘルパーからの棒ではありません。


シリーズの最初の2つの記事では、アルゴリズムだけでなく単語にも取り組むことがいかに重要かを示したかったのです。 名前がどのように呼び出されるかを決定する方法; 冗長で複雑すぎるコードがリーダーを追い払う。


これに加えて、良い名前は単なるメモです。 演奏するには、音楽に書かれて具体化される必要があります。 次の最終記事で詳しく説明します。



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


All Articles