コアコードのクリア(第10章クラス)


カプセル化されるべき


パッヶージ

  • 外部から隠蔽するオブジェクトの実装
  • によって.
    public class Stack {
    	private int topOfStack = 0;
    	private List<Integer> elements = new LinedList<Integer>();
    
    	public List<Integer> getElements() {
    		return elements;
    	}
    
    	public int size() {
    		return topOfStack;
    	}
    
    	public void push(int element) {
    		topOfStack++;
    		elements.add(element);
    	}
    
    	public int pop() throws PoppedWhenEmpty {
    		if (topOfStack == 0)
    			throw new PoppedWhenEmpty();
    		int element = elements.get(--topOfStack);
    		elements.remove(topOfStack);
    		return element;
    	}
    }

  • クラスを開発する場合、デフォルトではインプリメンテーションは非表示になり、外部オブジェクトとインタラクティブな部分のみが表示されます.

  • 外部エラーの使用を防止します.

  • 境界で学んだ部分!Map

  • Stack例
  • フィールドをprivateに制限しgetとして読み込む
  • 修正制限はpush、popメソッドで行う
  • 単一責任原則(SRP)


    等級が小さい


    クラスには責任者が一人いますか。

  • 関数と同様に、クラスも小さくなければなりません.
  • 関数は行番号でサイズを測定し、クラスは担当する책임でサイズを測定します.
  • 教室の説明は25単語程度で、「もし」、「和」、「する」、「しかし」は使用しないでください.責任は一つのことでなければならない.
  • public class SuperDashboard extends JFrame implements MetaDataUser {
    	public Component getLastFocusedComponent()
    	public void setLastFocused(Component lastFocused)
    	public int getMajorVersionNumber()
    	public int getMinorVersionNumber()
    	public int getBuildNumber()
    }
    「フォーカス・バージョンには2つの責任があります」
    異なるカテゴリに分ける.
    public class Version {
    	public int getMajorVersionNumber()
    	public int getMinorVersionNumber()
    	public int getBuildNumber()
    }
  • SRPが必要です.細かい単一レベルがたくさんあれば、大図を理解するのは難しい.しかし、小クラスの多いシステムでも、いくつかの大クラスのシステムでも、運転する部品の数はそれほど悪くありません.
  • 「ツールボックスをどのように管理しますか?複数の小さな引き出し、機能、名前の明確なコンポーネントを分離したいですか?それともいくつかの大きな引き出しを投げ込みたいですか?」
  • 個の大きなマルチターゲットクラスからなるシステム(変更を行う場合)は、すぐに知る必要のない事実を押しつけ、読者を妨げる.
  • 小類にはそれぞれ1つの責任があり、変更の理由の1つは、他の小類と協力してシステムに必要な操作を実行することです.
  • 単一責任原則(SRP)の重要性


    💡 細かい単一レベルがたくさんあれば、大図を理解するのは難しい.
    しかし、小さなクラスの多いシステムでも、いくつかの大きなクラスのシステムでも
    運転する部品の数があまり違わない.
    💡 いくつかの大きなマルチターゲットクラスからなるシステム(変更時)
    すぐに知る必要のない事実さえあり、読者を妨げる.
    class PaymentService {
    	public void pay();
    	public void cancel();
    	public void getAccount();
    	public void getAccountHistory();
    }
  • 要求:返金機能の追加
  • クラスには多くの機能があります.そのため、すべての機能を理解し、他の機能を実装することができます.
  • およびクラスには、より多くの機能があります.
  • 💡 小さいクラスにはそれぞれの責任があり、変更の理由があります.
    他の小クラスと協力してシステムに必要な操作を実行します.

    低結合度、高凝集度


  • 結合度:他のモジュール間の依存性
  • 凝集度:モジュール内部の機能集中度
  • 結合度が低いほど凝集度が高くなり、メンテナンス性が向上する。



    に質問

  • 高結合レベルの問題
  • に関連付けられたクラスが変更された場合は、
  • を変更する必要があります.
  • の結合度が高い場合は、関連するすべてのクラスを理解する必要があります.
  • 低凝集レベルの問題
  • には様々な機能があり、理解しにくい.
  • は再利用が困難です.
  • ていけつごうど


    結合度が低い。

  • システムの結合度を低下させると、柔軟性と再利用性もさらに向上する.
  • DIPクラスは、詳細な実装ではなく抽象に依存しなければならない.
  • 抽象を利用して、テストコードの作成を容易にします.
  • public class TokyoStockExchange {
    	public Money currentPrice(String symbol);
    }
    
    public class Portfolio {
    	private TokyoStockExchange tokyoStockExchange;
    	public Portfolio(TokyoStockExchange exchange) {
    		this.tokyoStockExchange = tokyoStockExchange;
    	}
    }
    「Portfolioクラスのテストコードを作成するには...TokyoStockExchange関数の場合、APIの値は5分ごとに異なる.
    public interface StockExchange {
    	Money currentPrice(String symbol);
    }
    
    public class TokyoStockExchange implements StockExchange {
    	public Money currentPrice(String symbol) {
    		// call API...
    	}
    }
    
    public class Portfolio {
    	private StockExchange exchange;
    	public Portfolio(StockExchange exchange) {
    		this.exchange = exchange;
    	}
    }
    StockExchangeおよびPortfolioの結合度は、TokyoStockExchangeインターフェースを介して切断される.
    public class PortfolioTest {
    	private FixedStockExchangeStub exchange;
    	private Portfolio portfolio;
    
    	@Before
    	protected void setUp() throws Exception {
    		exchange = new FixedStockExchangeStub();
    		exchange.fix("MSFT", 100);
    		portfolio = new Portfolio(exchange);
    	}
    
    	@Test
    	public void GivenFiveMSFTTotalShouldBe500() throws Exception {
    		portfolio.add(5, "MSFT");
    		Assert.assertEquals(500, portfolio.value());
    	}
    }
    テストの結果はいつも同じです.
    でも.拡張の可能性が小さい場合は、まず結合し、抽象的にすることができます.
    オブジェクトをカプセル化することで、変更したクラスをテストすることもできます.

    凝集度が高い。

  • クラスでは、インスタンス変数が少ない必要があります.メソッドは、少なくとも1つのインスタンス変数を使用する必要があります.方法で使用するインスタンス変数が多ければ多いほど凝集度が高くなる.
  • 凝集度が高い=クラスに属する方法と変数は互いに依存し,論理単位で縛る=相互関係の子供だけが集まる.
  • クラスが凝集度を失う場合、分裂関数が必要である.
  • 改める


    クラスは簡単に変更できるはずです。

    public class Sql {
    	public Sql(String table, Column[] columns)
    	public String create()
    	public String insert(Object[] fields)
    	public String selectAll()
    	public String findByKey(String keyColumn, String keyValue)
    	public String select(Column column, String pattern)
    	public String select(Criteria criteria)
    	public String preparedInsert()
    	private String columnList(Column[] columns)
    	private String valuesList(Object[] fields, final Column[] columns)
    	private String selectWithCriteria(String criteria)
    	private String placeholderList(Column[] columns)
    }
    更新文を追加する必要がある場合は?
    新しいSQLを追加する場合も変更され、既存のSQL文を変更する場合も変更されます.これはOCPに違反します.
    abstract public class Sql {
    	public Sql(String table, Column[] columns)
    	abstract public String generate();
    }
    
    public class CreateSql extends Sql {
    	public CreateSql(String table, Column[] columns)
    	@Override public String generate()
    }
    
    public class SelectSql extends Sql {
    	public SelectSql(String table, Column[] columns)
    	@Override public String generate()
    }
    
    public class InsertSql extends Sql {
    	public InsertSql(String table, Column[] columns, Object[] fields)
    	@Override public String generate()
    	private String valuesList(Object[] fields, final Column[] columns)
    }
    
    public class Where {
    	public Where(String criteria) public String generate()
    }
    
    public clas ColumnList {
    	public ColumnList(Column[] columns) public String generate()
    }
  • 公開インタフェースをすべてSQLクラスから派生したクラスとして作成し、プライベートメソッドをクラスに移行し、共通インタフェースをクラスに分離します.
  • の既存のレベルにぶつかる必要はありません.
  • リファレンス


    これらの情報はゼロベースラインクリーニングコード毎月1冊を聞いた後に整理された.