πŸ“’ 개발 μ„œμ /Clean Code

[클린 μ½”λ“œ] 3μž₯ ν•¨μˆ˜

nitronium102 2022. 2. 23. 23:34

TIL (Today I Learned)

22.02.22~22.02.23

였늘 읽은 λ²”μœ„

3μž₯. ν•¨μˆ˜

μ±…μ—μ„œ κΈ°μ–΅ν•˜κ³  싢은 λ‚΄μš©

- μ–΄λ–€ ν”„λ‘œκ·Έλž¨μ΄λ“  κ°€μž₯ 기본적인 λ‹¨μœ„κ°€ ν•¨μˆ˜λ‹€.

 

- ν•¨μˆ˜λŠ” μž‘κ²Œ λ§Œλ“€μ–΄μ•Ό ν•œλ‹€. λ‹€μ‹œ 말해, ifλ¬Έ/elseλ¬Έ/while문에 λ“€μ–΄κ°€λŠ” 블둝은 ν•œ 쀄이어야 ν•œλ‹€λŠ” 말이닀. 이 말은 쀑첩 ꡬ쑰가 μƒκΈΈλ§ŒνΌ ν•¨μˆ˜κ°€ μ»€μ Έμ„œλŠ” μ•ˆ λœλ‹€λŠ” λœ»μ΄λ‹€. κ·ΈλŸ¬λ―€λ‘œ ν•¨μˆ˜μ—μ„œ λ“€μ—¬μ“°κΈ° μˆ˜μ€€μ€ 1λ‹¨μ΄λ‚˜ 2단을 λ„˜μ–΄μ„œλ©΄ μ•ˆλœλ‹€.

 

- λ‹¨μˆœνžˆ λ‹€λ₯Έ ν‘œν˜„μ΄ μ•„λ‹ˆλΌ 의미 μžˆλŠ” μ΄λ¦„μœΌλ‘œ λ‹€λ₯Έ ν•¨μˆ˜λ₯Ό μΆ”μΆœν•  수 μžˆλ‹€λ©΄ κ·Έ ν•¨μˆ˜λŠ” μ—¬λŸ¬ μž‘μ—…μ„ ν•˜λŠ” μ…ˆμ΄λ‹€[G34] -> μƒˆλ‘œμš΄ 객체λ₯Ό μƒμ„±ν•˜λŠ” 것도 ν•˜λ‚˜μ˜ μž‘μ—…μ΄λ‹€!

 

- 각 ν•¨μˆ˜λŠ” λ‹€μŒ ν•¨μˆ˜λ₯Ό μ†Œκ°œν•˜κ³ , 각 ν•¨μˆ˜λŠ” μΌμ •ν•œ 좔상화 μˆ˜μ€€μ„ μœ μ§€ν•œλ‹€.

 

switch문

switch 문을 κΌ­ μ‚¬μš©ν•΄μ•Ό ν•œλ‹€λ©΄ λ‹€ν˜•μ  객체λ₯Ό μƒμ„±ν•˜λŠ” μ½”λ“œ μ•ˆμ—μ„œ + 선택 μœ ν˜• ν•˜λ‚˜μ— ν•œ 번만 μ‚¬μš©ν•œλ‹€. 

1) μΆ”μƒνŒ©ν† λ¦¬μ— switch 문을 숨기고 νŒ©ν† λ¦¬κ°€ λŒ€μ‹  νŒŒμƒν΄λž˜μŠ€μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό 생성.

2) μΈν„°νŽ˜μ΄μŠ€λ₯Ό 톡해 ν•¨μˆ˜κ°€ 호좜

3) λ‹€ν˜•μ„±μœΌλ‘œ 인해 μ‹€μ œ νŒŒμƒ 클래슀의 ν•¨μˆ˜κ°€ μ‹€ν–‰

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 COMMISIONED:
            	return new CommisionedEmployee(r);
            case HOURLY:
            	return new HourlyEmployee(r);
            case SALARIED;
        }
    }
}

ν•¨μˆ˜ 인수

ν•¨μˆ˜μ—μ„œ 이상적인 인수 κ°œμˆ˜λŠ” 0κ°œμ΄λ‹€. 3κ°œλŠ” κ°€λŠ₯ν•œ ν”Όν•˜λŠ” 편이 μ’‹κ³ , 4개 이상은 νŠΉλ³„ν•œ μ΄μœ κ°€ ν•„μš”ν•˜λ‹€. νŠΉλ³„ν•œ μ΄μœ κ°€ μžˆμ–΄λ„ μ‚¬μš©ν•˜λ©΄ μ•ˆ λœλ‹€. 

1) 단항 ν˜•μ‹

- μΈμˆ˜μ— μ§ˆλ¬Έμ„ λ˜μ§€λŠ” 경우

boolean fileExists("MyFile")

- 인수λ₯Ό λ¬΄μ–Έκ°€λ‘œ λ³€ν™˜ν•΄ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜λŠ” 경우

InputStream fileOpen("MyFile")

2) ν”Œλž˜κ·Έ 인수

- ν•¨μˆ˜λ‘œ boolean값을 λ„˜κΈ°μ§€ 말고 boolean true인 ν•¨μˆ˜μ™€ boolean false인 ν•¨μˆ˜λ₯Ό 각각 λ§Œλ“€μ–΄λΌ

 

3) 이항 ν•¨μˆ˜

- 단항 ν•¨μˆ˜λ‘œ λ§Œλ“€μž.

writeField(outputStream, name)

-> writeField λ©”μ„œλ“œλ₯Ό outputStream κ΅¬μ„±μ›μœΌλ‘œ λ§Œλ“€μ–΄ outputStream.writeField(name)으둜 호좜

-> outputStream을 ν˜„μž¬ 클래슀 ꡬ성원 λ³€μˆ˜λ‘œ λ§Œλ“€μ–΄ 인수둜 λ„˜κΈ°μ§€ μ•ŠλŠ”λ‹€.

-> FieldWriterλΌλŠ” μƒˆ 클래슀λ₯Ό λ§Œλ“€μ–΄μ„œ κ΅¬μ„±μžμ—μ„œ outputStream을 λ°›κ³  write λ©”μ„œλ“œ κ΅¬ν˜„

 

4) 인수 객체

- μΈμˆ˜κ°€ 2~3개 ν•„μš”ν•˜λ‹€λ©΄ 일뢀λ₯Ό λ…μžμ μΈ 클래슀 λ³€μˆ˜λ‘œ μ„ μ–Έν•˜μž

Circle makeCircle(double x, double y, double radius);
Circle makeCircle(Point center, double radius);

 

5) 동사와 ν‚€μ›Œλ“œ

단항 ν•¨μˆ˜λŠ” ν•¨μˆ˜μ™€ μΈμˆ˜κ°€ 동사/λͺ…사 μŒμ„ 이뀄야 ν•œλ‹€. writeField(name)

ν•¨μˆ˜ 이름에 ν‚€μ›Œλ“œλ₯Ό μΆ”κ°€ν•˜λ©΄ 인수 μˆœμ„œλ₯Ό κΈ°μ–΅ν•  ν•„μš”κ°€ 없어진닀.

 

λΆ€μˆ˜ 효과λ₯Ό μΌμœΌν‚€μ§€ 마라

λΆ€μˆ˜ 효과λ₯Ό λ¬΄μ‹œν•˜λ©΄ μ‹œκ°„μ μΈ κ²°ν•©μ΄λ‚˜ μˆœμ„œ 쒅속성을 μ΄ˆλž˜ν•  수 있기 λ•Œλ¬Έμ—, 가급적이면 ν•¨μˆ˜ 이름에 λͺ…μ‹œν•˜λŠ” 것이 μ’‹λ‹€. μƒˆλ‘œμš΄ ν•¨μˆ˜λ₯Ό λ§Œλ“œλŠ” 것도 쒋은 방법.

 

였λ₯˜ μ½”λ“œλ³΄λ‹€ μ˜ˆμ™Έλ₯Ό μ‚¬μš©ν•˜λΌ

1) try-catch 블둝을 별도 ν•¨μˆ˜λ‘œ 뽑아내기

public void delete(Page page) {
	try {
    	deletePageAndAllReferences(page);
    } catch (Exception e) {
    	logErorr(e);
    }
}
-------------------------------
private void deletePageAndAllReferences(Page page) throws Exception {
	deletePage(page);
    registry.deleteReference(page.name);
    configKeys.deleteKey(page.name.makeKey());
}

private void logError(Exception e) {
	logger.log(e.getMessage());
}

2) Error.java μ˜μ‘΄μ„± μžμ„

였λ₯˜ μ½”λ“œλ₯Ό μ •μ˜ν•˜λŠ” ν΄λž˜μŠ€κ°€ λ³€ν•œλ‹€λ©΄ ν•΄λ‹Ή 였λ₯˜ μ½”λ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 클래슀 μ „λΆ€λ₯Ό λ‹€μ‹œ μ»΄νŒŒμΌν•˜κ³  λ‹€μ‹œ λ°°μΉ˜ν•΄μ•Ό ν•œλ‹€. 였λ₯˜ μ½”λ“œ λŒ€μ‹  μ˜ˆμ™Έλ₯Ό μ‚¬μš©ν•˜λ©΄ μƒˆ μ˜ˆμ™ΈλŠ” Exception ν΄λž˜μŠ€μ—μ„œ νŒŒμƒλ˜κΈ° λ•Œλ¬Έμ— μž¬μ»΄νŒŒμΌμ΄λ‚˜ 재배치 없이도 μƒˆ μ˜ˆμ™Έ 클래슀λ₯Ό μΆ”κ°€ν•  수 μžˆλ‹€.

 

ꡬ쑰적 ν”„λ‘œκ·Έλž˜λ°

루프 μ•ˆμ—μ„œ break, continueλŠ” 거의 μ‚¬μš©ν•˜μ§€ 말 것. 특히 gotoλŠ” μ‚¬μš© κΈˆμ§€

 

ν•¨μˆ˜λ₯Ό μ§œλŠ” 방법

1. λ¨Όμ € μ­‰ 써내렀간닀 + λ‹¨μœ„ ν…ŒμŠ€νŠΈ

2. κΈ°λŠ₯ λ‹¨μœ„λ‘œ 뢄리 / μ μ ˆν•œ 넀이밍 / 쀑볡 제거 등을 κ³ λ €ν•˜μ—¬ λ¦¬νŒ©ν† λ§ + λ‹¨μœ„ ν…ŒμŠ€νŠΈ

 

였늘 읽은 μ†Œκ°

λͺ©λ‘ 3-1을 λ³΄λŠ” μˆœκ°„ μ‘Έν”„ μ½”λ“œμ™€ λ„ˆλ¬΄ λ˜‘κ°™μ•„μ„œ λ†€λžλ‹€. 거의 μ €μž‘κΆŒ μœ„λ°˜μœΌλ‘œ κ³ μ†Œν•΄μ•Ό ν•  정도

이번 μž₯μ—μ„œλŠ” λ¬΄μ˜μ‹μ μΈ μ½”λ“œ μž‘μ„±λ²•μ„ μ§€μ ν•˜λŠ” λ‚΄μš©μ΄ λ§Žμ•˜λ‹€. μ•„λž˜ 3가지 λ‚΄μš©μ΄ λ‚΄ μ½”λ“œμ˜ μ£Ό 문제점인데, μ•žμœΌλ‘œ ν•¨μˆ˜λ₯Ό 생성할 λ•Œλ§ˆλ‹€ 이 3가지 λ‚΄μš©μ„ μƒˆκ²¨μ•Όκ² λ‹€. 특히 switch문은 κΌ­ νŒ©ν† λ¦¬ λ©”μ„œλ“œλ₯Ό μ μš©ν•΄λ΄μ•Όκ² λ‹€!

1) switch문의 μ‚¬μš©

2) ν”Œλž˜κ·Έ 인수λ₯Ό ν•¨μˆ˜ 인수둜 λ„˜κΈ°λŠ” 것

3) try-catch 블둝 μ‚¬μš©

 

κΆκΈˆν•˜κ±°λ‚˜ 잘 μ΄ν•΄λ˜μ§€ μ•ŠλŠ” λ‚΄μš©

좔상 νŒ©ν† λ¦¬ vs νŒ©ν† λ¦¬ λ©”μ„œλ“œ

- 좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄(Abstract Factory Pattern) : μ„œλ‘œ 관련이 μžˆλŠ” 객체듀을 ν†΅μ§Έλ‘œ λ¬Άμ–΄μ„œ νŒ©ν† λ¦¬ 클래슀둜 λ§Œλ“€κ³ , 이듀 νŒ©ν† λ¦¬λ₯Ό 쑰건에 따라 μƒμ„±ν•˜λ„λ‘ λ‹€μ‹œ νŒ©ν† λ¦¬λ₯Ό λ§Œλ“€μ–΄μ„œ 객체λ₯Ό μƒμ„±ν•˜λŠ” νŒ¨ν„΄

- νŒ©ν† λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄ : 쑰건에 λ”°λ₯Έ 객체 생성을 νŒ©ν† λ¦¬ 클래슀둜 μœ„μž„ν•˜μ—¬, νŒ©ν† λ₯΄ ν΄λž˜μŠ€μ—μ„œ 객체λ₯Ό μƒμ„±ν•˜λŠ” νŒ¨ν„΄

=> νŒ©ν† λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄μ—μ„œλŠ” κ΅¬μ„±ν’ˆλ§ˆλ‹€ νŒ©ν† λ¦¬λ₯Ό λ§Œλ“€μ–΄ μ–΄λ–€ 객체λ₯Ό ν˜•μ„±ν–ˆλŠ”λ°, κ·Έ 객체의 κ΅¬μ„±ν’ˆμ€ μΌμ •ν•˜λ―€λ‘œ 좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄μ„ μ μš©ν•˜μ—¬ κ΄€λ ¨λœ 객체듀을 ν•œκΊΌλ²ˆμ— μΊ‘μŠν™”ν•˜μ—¬ νŒ©ν† λ¦¬λ‘œ λ§Œλ“  ν›„ μΌκ΄€λ˜κ²Œ 객체 생성.

https://victorydntmd.tistory.com/300

 

[λ””μžμΈνŒ¨ν„΄] 좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄ ( Abstract Factory Pattern )

좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄ ( Abstract Factory Pattern ) 좔상 νŒ©ν† λ¦¬ νŒ¨ν„΄μ΄λΌλŠ” μ΄λ¦„λ§Œ λ΄μ„œλŠ” νŒ©ν† λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄κ³Ό λΉ„μŠ·ν•΄λ³΄μ΄μ§€λ§Œ, λͺ…ν™•ν•œ 차이점이 μžˆμŠ΅λ‹ˆλ‹€. νŒ©ν† λ¦¬ λ©”μ„œλ“œ νŒ¨ν„΄ 쑰건에 λ”°λ₯Έ 객체 생성

victorydntmd.tistory.com

 

μ‹œκ°„μ μΈ κ²°ν•©(temporal coupling)

μ†Œν”„νŠΈμ›¨μ–΄μ˜ 섀계 μš”μ†Œ μžμ²΄λ‘œμ„œμ˜ μ‹œκ°„ μ—­ν• 

ex) λ©”μ„œλ“œ AλŠ” μ–Έμ œλ‚˜ λ°˜λ“œμ‹œ λ©”μ„œλ“œ B보닀 λ¨Όμ € ν˜ΈμΆœν•΄μ•Ό ν•œλ‹€

1) λ™μ‹œμ„±(같은 μ‹œκ°„μ— μΌμ–΄λ‚˜λŠ” 일)

2) μˆœμ„œ(μ‹œκ°„ μ†μ—μ„œ μΌλ“€μ˜ μƒλŒ€μ  μœ„μΉ˜)

=> μš°λ¦¬λŠ” λ™μ‹œμ„±μ„ ν—ˆμš©ν•˜κ³  μˆœμ„œκ°€ μ—†λŠ” ν”„λ‘œκ·Έλž¨μ„ λ§Œλ“€μ–΄μ•Ό ν•œλ‹€. 

 

μˆœμ„œ 쒅속성(order dependency)

후속 μž‘μ—…μ€ μ„ ν–‰ μž‘μ—…μ΄ μ™„λ£Œλ  λ•ŒκΉŒμ§€ μ‹œμžκ°›γ„Ή 수 μ—†λ‹€. 

 

 

- SRP : ν΄λž˜μŠ€μ—λŠ” ν•œ 가지, 단 ν•œ 가지 λ³€κ²½ 이유만 μ‘΄μž¬ν•΄μ•Ό ν•œλ‹€.

-> 클래슀의 λ³€κ²½ = μ½”λ“œμ˜ 변경이닀. 

- OCP : ν΄λž˜μŠ€λŠ” ν™•μž₯에 μ—΄λ € μžˆμ–΄μ•Ό ν•˜λ©° 변경에 λ‹«ν˜€ μžˆμ–΄μ•Ό ν•œλ‹€.

-> μƒˆ 직원을 μΆ”κ°€ν•  λ•Œλ§ˆλ‹€ μ½”λ“œκ°€ λ³€κ²½λ˜λ©΄ μ•ˆ λœλ‹€.