クリアコードコアクリア(SOLID,3章関数)
に入る
SOLIDとは?
クリーンコードで有名なロバート・マーティンは、オブジェクト向けに良好な設計の5つの原則を提案した.
単一責任原則SRP
SRPとは?
一つの階級は一つの責任しか負わない.
SRPとは?
一つの階級は一つの責任しか負わない.
やらなければならない理由は一つしかない.
遅くなるかもしれません.
例
説明:
左のロボットを見て、4つの機能を実行します.ロボットはクラスとして、1つのクラスに複数の責任があることを意味します.この問題を解決するために,右図に示すように,4つの責任ごとに1つのクラスに分類される.
オープンクローズ原則OCP
OCPとは?
ソフトウェア要素は拡張で開き、変更で閉じます.
最大化する.
何の修正もせず、コンポーネントを簡単に拡張できます.
使用します.
例
説明:
左図に示すように、OCPが適用されない場合、既存のCut機能が機能しない例として、Paint機能が追加される.
すなわち、クラスを変更する現在の操作は、クラスを使用するすべてのシステムに影響します.
OCPの目標は、クラスの既存の操作を変更せずにクラスを拡張することです.クラスがより多くの機能を実行する場合は、既存の機能を変更せずにこれらの機能を追加するのが理想的です.
リスコフ互換原則LSP
リスコフ置換の原則とは何ですか。
サブタイプは常にベースタイプに置き換える必要があります.
守らなければならない.
もっといいです.
例
説明:
上図は、親ロボットがcoffeeクラスを渡す図です.カプチーノは、エスプレッソコーヒーがコーヒーの種類であるため、サブロボットの配送は許可されているが、配送は許可されていない例である.
つまり、子クラスが親と同じ操作を実行できない場合、エラーが発生する可能性があります.
子クラスは親クラスができることをすべてしなければならない.このプロセスを継承と呼ぶ.
n/a.ターゲット
この原則は、エラーが発生することなく、親または子が同じ方法で使用できるように一貫性を保つことです.
インタフェース分離の原則ISP
界面分離の原則とは何ですか。
自分が使わないインタフェースを実現しないでください.
例
説明:
左の図は、ロボットの用途が異なるが不要なすべての機能を実現した例で、右の図はロボットの用途に応じて機能を分離することを示しています.
クラスが不要な機能を実行する必要がある場合は、エラーが発生する可能性があります.したがって,インタフェースを分離し,クラスが必要な機能のみを継承できるようにするのがこのルールである.
この原則の目標は、クラスが必要なワークセットのみを実行するように、ワークセットをより小さなセットに分割することです.
依存性逆転の原則DIP
依存性逆転の原則とは何ですか。
親モデルは下位モデルに依存できません.どちらも抽象化に頼らなければならない.
抽象化は細部に頼ることができない.細部は抽象化によって変わる.
例
説明:
左の図はロボットの腕にピザを切るだけの機能を示しており、右のロボットはいつでも腕を変えて新しい道具を使うことができます.
すなわち,クラス実行タスクは実装体クラスに依存せず抽象に依存し,複数の具体的なクラスを用いることができる.
新しいクレジットカード会社を追加したら?
@RequestMapping(value = "/api/payment", method = RequestMethod.POST)
public void pay(@RequestBody CardPaymentDto.PaymentRequest req){
if(req.getType() == CardType.SHINHAN) {
shinhanCardPaymentService.pay(req);
} else if(req.getType() == CardType.WOORI){
wooriCardPaymentService.pay(req);
}
}
拡張が鈍い.->どちらも抽象的なインタフェースに依存する.
class PaymentController {
@RequestMapping(value = "/payment", method = RequestMethod.POST)
public void pay(@RequestBody CardPaymentDto.PaymentRequest req) {
final CardPaymentService cardPaymentService = cardPaymentFactory.getType(req.getType());
cardPaymentService.pay(req);
}
}
*public interface CardPaymentService {
void pay(CardPaymentDto.PaymentRequest req);
}*
public class ShinhanCardPaymentService implements CardPaymentService {
@Override
public void pay(CardPaymentDto.PaymentRequest req) {
shinhanCardApi.pay(req);
}
}
簡潔な関数の作成 public static String renderPageWithSetupsAndTeardowns(PageData pageData, boolean isSuite) throws Exception {
boolean isTestPage = pageData.hasAttribute("Test");
if (isTestPage) {
WikiPage testPage = pageData.getWikiPage();
StringBuffer newPageContent = new StringBuffer();
includeSetupPages(testPage, newPageContent, isSuite);
newPageContent.append(pageData.getContent());
includeTeardownPages(testPage, newPageContent, isSuite);
pageData.setContent(newPageContent.toString());
}
return pageData.getHtml();
}
「関数が長くて、いろいろな機能が混ざっています...」public static String renderPageWithSetupsAndTeardowns( PageData pageData, boolean isSuite) throws Exception {
if (isTestPage(pageData))
includeSetupAndTeardownPages(pageData, isSuite);
return pageData.getHtml();
}
引き裂く.
関数内の抽象化レベルを一致させます.
1つのみ実行(SRP)、変更を閉じる(OCP)
一つだけやろう!
関数は一つのことをしなければなりません.そのことをうまくやらなければならない.それしかできない.
public static String renderPageWithSetupsAndTeardowns(PageData pageData, boolean isSuite) throws Exception {
boolean isTestPage = pageData.hasAttribute("Test");
if (isTestPage) {
WikiPage testPage = pageData.getWikiPage();
StringBuffer newPageContent = new StringBuffer();
includeSetupPages(testPage, newPageContent, isSuite);
newPageContent.append(pageData.getContent());
includeTeardownPages(testPage, newPageContent, isSuite);
pageData.setContent(newPageContent.toString());
}
return pageData.getHtml();
}
public static String renderPageWithSetupsAndTeardowns( PageData pageData, boolean isSuite) throws Exception {
if (isTestPage(pageData))
includeSetupAndTeardownPages(pageData, isSuite);
return pageData.getHtml();
}
どうして「一つのこと」が何なのか知ってるの?
ただし、別の関数を意味のある名前で抽出できる場合は、複数の操作が実行されます.
'추상화 수준이 하나인 단계만 수행한다면 그 함수는 한 가지 작업만 하는 것이다.'
라는 말이 어려울 수 있다. 하지만 예시를 보면 그렇게 어려운 것은 아니다.
1. 쓰레기를 판단한다.
2. 쓰레기를 줍는다.
3. 쓰레기를 휴지통에 넣는다.
ごみをゴミ箱に捨てる関数の下で、3つの関数を呼び出す必要があることがわかります.したがって,関数名では抽象レベルは1つしかないと考えられる.つまり、1つのことしかしない関数は、関数中のすべての文の抽象レベル(判断、ピックアップ、挿入など)...表示は同じでなければなりません.NOT
判断、ピックアップ、挿入の3つの関数で区別できます.すなわち,判定関数からピックアップに至るまで,判定やピックアップなどの抽象化を行うことはできない.
抽象化レベルとは?
その名の通り、具体的に書くのではなく抽象的に表現すれば、抽象化の程度が高く、抽象化ではなく、直接のコードは抽象化の程度が低い.
例
public Money calculatePay(Employee e) throws InvalidEmployeeType {
switch (e.type) {
case COMMISSIONED:
return calculateCommissionedPay(e);
case HOURLY:
return calculateHourlyPay(e);
case SALARIED:
return calculateSalariedPay(e);
default:
throw new InvalidEmployeeType(e.type);
}
}
「計算してお金を生み出す.「2つの機能があります.」「新しい社員タイプを追加すると?」
public abstract class Employee {
public abstract boolean isPayday();
public abstract Money calculatePay();
public abstract void deliverPay(Money pay);
}
public interface EmployeeFactory {
public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType;
}
public class EmployeeFactoryImpl implements EmployeeFactory {
public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType {
switch (r.type) {
case COMMISSIONED:
return new CommissionedEmployee(r);
case HOURLY:
return new SalariedEmployee(r);
case SALARIED:
return new SalariedEmployee(r);
default:
return new InvalidEmployeeType(r.type);
}
}
}
計算をタイプ管理から分離タイプの処理は最大限の工場でしかできません
関数パラメータ
因数の個数は0〜2個が好ましい.
3つ以上なら?
// 객체를 인자로 넘기기
Circle makeCircle(double x, double y, double radius); // X
Circle makeCircle(Point center, double radius); // O
// 가변 인자를 넘기기 ==> 특별한 경우가 아니면 잘 안쓴다.
String.format(String format, Object... args);
セキュリティ関数の作成
浮動小数点効果のない関数
副手効果?値を返す関数は、外部ステータスを変更します.public class UserValidator {
private Cryptographer cryptographer;
public boolean checkPassword(String userName, String password) {
User user = UserGateway.findByName(userName);
if (user != User.NULL) {
String codedPhrase = user.getPhraseEncodedByPassword();
String phrase = cryptographer.decrypt(codedPhrase, password);
if ("Valid Password".equals(phrase)) {
Session.initialize();
return true;
}
}
return false;
}
}
リファレンス
これらの情報はゼロベースラインクリーニングコード毎月1冊を聞いた後に整理された.
Reference
この問題について(クリアコードコアクリア(SOLID,3章関数)), 我々は、より多くの情報をここで見つけました
https://velog.io/@coconenne/클린코드-핵심-정리-SOLID-3장-함수
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
public class UserValidator {
private Cryptographer cryptographer;
public boolean checkPassword(String userName, String password) {
User user = UserGateway.findByName(userName);
if (user != User.NULL) {
String codedPhrase = user.getPhraseEncodedByPassword();
String phrase = cryptographer.decrypt(codedPhrase, password);
if ("Valid Password".equals(phrase)) {
Session.initialize();
return true;
}
}
return false;
}
}
これらの情報はゼロベースラインクリーニングコード毎月1冊を聞いた後に整理された.
Reference
この問題について(クリアコードコアクリア(SOLID,3章関数)), 我々は、より多くの情報をここで見つけました https://velog.io/@coconenne/클린코드-핵심-정리-SOLID-3장-함수テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol