テクニック: 作曲方法
本「 リファクタリング 」のリファクタリング手法の続き。 既存のコードの改善Martin Fowler。
構文はC#で記述されますが、主なことはアイデアを理解することであり、他のプログラミング言語でも使用できます。
オブジェクト間で関数を移動する
- メソッドを移動する ( より頻繁に使用するクラス内で同じ本体を持つ新しいメソッドを作成する )。
メソッドは、サブジェクト領域をよりよく反映するクラス内にある必要があります。
から
class View { private Shop shop; private List<User> FilterUsers(List<User> users, decimal koef) { List<User> activeUsers = new List<User>(); foreach(User user in users) { if(shop.IsActiveUser(user, koef)) { activeUsers.Add(user); } } return activeUsers; } } class Shop { public bool IsActiveUser(User user, decimal koef) { decimal rate = 1; if(koef > 1000) { rate = koef * 1.75; } return user.Boss || user.HasDiscount() && rate > 10; } } class User { private bool boss; public bool Boss { get { return boss; } } public bool HasDiscount() { // some condition } }
に
class View { private Shop shop; private List<User> FilterUsers(List<User> users, decimal koef) { List<User> activeUsers = new List<User>(); foreach(User user in users) { if(user.IsActiveUser(koef)) { activeUsers.Add(user); } } return activeUsers; } } class Shop { } class User { private bool boss; public bool Boss { get { return boss; } } public bool HasDiscount() { // some condition } public bool IsActiveUser(decimal koef) { decimal rate = 1; if(koef > 1000) { rate = koef * 1,75; } return Boss || HasDiscount() && rate > 10; } }
- フィールドを移動する ( ターゲットクラスに新しいフィールドを作成する )。
フィールドは、サブジェクト領域をよりよく反映するクラス内にある必要があります
から
class Shop { private decimal rate; private DiscountType discountType; public Shop(DiscountType discountType, decimal rate) { this.rate = rate; this.discountType = discountType; } public decimal Rate { get{ return rate; } set{ rate = value; } } public bool HasDiscount(DateTime from, DateTime to) { // some calculation of flag return discountType.IsValid(rate) && flag; } public decimal GetDiscount(decimal amount, bool fullSum) { // some calculation of koef return discountType.GetAmount(rate, fullSum) * koef; } } class DiscountType { public bool IsValid(decimal rate) { // some calculation using rate } public decimal GetAmount(decimal rate, bool fullSum) { // some calculation using rate } }
に
class Shop { private DiscountType discountType; public Shop(DiscountType discountType) { this.discountType = discountType; } public bool HasDiscount(DateTime from, DateTime to) { // some calculation of flag return discountType.IsValid() && flag; } public decimal GetDiscount(decimal amount, bool fullSum) { // some calculation of koef return discountType.GetAmount() * koef; } } class DiscountType { private decimal rate; public DiscountType(decimal rate) { this.rate = rate; } public decimal Rate { get{ return rate; } set{ rate = value; } } public bool IsValid() { // some calculation using rate } public decimal GetAmount(bool fullSum) { // some calculation using rate } }
- クラスを強調表示し ます ( 新しいクラスを作成し、フィールドとメソッドを古いクラスから新しいクラスに移動します )。
クラスには独自のデータモデルとそれを操作するメソッドが含まれている必要があります。そうでない場合、クラスはGodオブジェクトになります。
から
class User { private string name; private string street; private string city; public string Name { get{ return name; } set{ name = value; } } public string Street { get{ return street; } set{ city = value; } } public string City { get{ return city; } set{ city = value; } } public string GetAddressInfo() { return string.Format("{0} \ {1}", city, street); } }
に
class User { private string name; private Address address; public string Name { get{ return name; } set{ name = value; } } public string GetAddressInfo() { return address.GetFullAddress(); } } class Address { private string city; private string street; public string Street { get{ return street; } set{ city = value; } } public string City { get{ return city; } set{ city = value; } } public string GetFullAddress() { return string.Format("Adress: {0} \ {1}", city, street); } }
- クラスのインライン化 ( すべての関数を別のクラスに移動し、元のクラスを削除します)。
クラスの関数が少なすぎます。
から
class User { private string name; private Address address; public string Name { get{ return name; } set{ name = value; } } public Address GetAddress() { return address } } class Address { private string areaCode; private string country; public string AreaCode { get{ return areaCode; } set{ areaCode = value; } } public string Country { get{ return country; } set{ country = value; } } }
に
class User { private string name; private string areaCode; private string country; public string AreaCode { get{ return areaCode; } set{ areaCode = value; } } public string Country { get{ return country; } set{ country = value; } } public string Name { get{ return name; } set{ name = value; } } }
- 委任の 非表示(委任を非表示にするメソッドを作成 )。
カプセル化、システムの一部。
から
class View { private void Init() { // some code User manager = currentUser.Office.Manager; } } class User { private Department department; public Department Office { get{ return department; } set{ department = value; } } } class Department { private User manager; public Department(User manager) { this.manager = manager; } public User Manager { get{ return manager; } } }
に
class View { private void Init() { // some code User manager = currentUser.Manager; } } class User { private Department department; public User Manager { get{ return department.Manager; } } } class Department { private User manager; public Department(User manager) { this.manager = manager; } public User Manager { get{ return manager; } } }
- ブローカーを削除 します ( クライアントがデリゲートに直接連絡するようにします )。
クラスは単純な委任で忙しすぎます。
から
class View { private void Init() { // some code User manager = currentUser.Manager; decimal rate = currentUser.Rate; } } class User { private Department department; private UserType userType; public User Manager { get{ return department.Manager; } } public decimal Rate { get{ return userType.Rate; } } } class Department { private User manager; public User Manager { get{ return manager; } } } class UserType { private decimal rate; public decimal Rate { get{ return rate; } } }
に
class View { private void Init() { // some code User manager = currentUser.Office.Manager; decimal rate = currentUser.Type.Rate; } } class User { private Department department; private UserType userType; public Department Office { get{ return department; } } public UserType Type { get{ return userType; } } } class Department { private User manager; public User Manager { get{ return manager; } } } class UserType { private decimal rate; public decimal Rate { get{ return rate; } } }
- 外部メソッドの導入 ( クライアントで、サーバークラスが1番目のパラメーターとして渡されるメソッドを追加します )。
メソッドを導入する必要がありますが、クラスを変更する可能性はありません。
から
class View { private string GetUserName() { // some code return "\"" + userName + "\""; } private string GetCompanyName() { // some code return "\"" + companyName + "\""; } }
に
class View { private string GetUserName() { // some code return userName.InDoubleQuote(); } private string GetCompanyName() { // some code return companyName.InDoubleQuote(); } } static class StringExtension { public static string InDoubleQuote(this string str) { return "\"" + str + "\""; } }
- ローカル拡張の導入 ( クラスのラッパーを作成(または継承を使用)し、必要なメソッドを追加します )。
メソッドを導入する必要がありますが、クラスを変更する方法はありません。
から
sealed class Account { public decimal CalculateSum() { // calculation summ return summ; } }
に
class ImportantAccount { private Account account; public decimal CalculateMaxSum() { // calculation rate return account.CalculateSum() * rate; } }
利益相反(レビューの一環として)。
原則として、校閲者とcomitt-errの間で生じるすべての論争/不一致は、次のように分類できます。
- 同僚は、適切なソリューションの選択について議論します。 実装に関して意見の相違が生じました。 正しいコミュニケーションのフレームワーク内のすべてのものは、彼らが共通のことをしていることを理解しており、ソリューションを選択するだけでよい(10%)。
- 同僚はチャットをする必要があります。金曜日、苦しい週、またはコミュニケーション不足です。 ただクラックする必要がある人々のそのようなカテゴリーがあります。 原則として、これには常識がないわけではありません。 コミュニケーションとディスカッションは素晴らしい(10%)。
- 新しいルールにつながる紛争。 たとえば、 varキーワードが.NETに登場したとき、同僚の1人がどこでも使用し始め、誰かがその逆を使用し始めました。 したがって、レビュー中に、どちらの方が良いかという論争がありました。 その結果、いくつかの議論の後、決定が下されました(10%)。
// , , var var users = new List<User>(); var departments = user.Departmens.Cast<Department>(); // var users = departments.Select(d => d.User).Where(u => !u.Deleted); var departments = service.GetNotDeletedDepartments();
- 誰の決定が良いかについての白熱した議論。 プログラマーが同じレベルにいる場合、情熱が燃え上がる可能性があります。 さらに、これらすべての紛争は、時間の無駄と自分自身を冷静にしたいという欲求(70%)にすぎません。 ここでアドバイスをしたいのですが、もしあなたがそのような論争に巻き込まれたら、個人ではなく決して行きません。 また、 「あなたの決定は 当てはまり ません」というフレーズは、「 決定は完全に真実ではなく、あなたの視点を説明する」に置き換える方が良いでしょう。 つまり 同僚のスキルではなく、決定について議論することに重点を置くべきです。
おかしい場合:
1)レビュー担当者-「コードを修正する必要があります」
コミッター-「あなたはあなたが好きではなく、支配する」/「あなたはあなたを見つけて修正する」
2)またはどのくらい正確に
void Method() { ... if(flag) koef = GetMaxRate(); ... }
または
void Method() { ... if(flag) { koef = GetMaxRate(); } ... }
「技術:データ編成」をさらに続けていきたいと思います。