Clean Code - cleancodeclass/cleancode_theory GitHub Wiki
I like my code to be elegant and efficient. The logic should be straightforward and make it hard for bugs to hide, the dependencies minimal to ease maintenance, error handling complete according to an articulated strategy, and performance close to optimal so as not to tempt people to make the code messy with unprincipled optimizations. Clean code does one thing well.
Clean code is simple and direct. Clean code reads like well-written prose. **Clean code never obscures the designers intent ** but rather is full of crisp abstractions and straightforward lines of control.
λͺ¨λ νμμ΄ μ΄ν΄(understandability)νκΈ° μ½λλ‘ μμ±λ μ½λ
- μμ‘΄μ±μ΄ μ μ΄ λ¨μνκ³ , ν μ€νΈμ½λλ‘ κ²μ¦λ μ½λ
- μ½λλ₯Ό ν΄μνλ μκ°κ³Ό μμ νλ μκ°μ λΉμ¨μ 10(read) : 1 (write)
- λλΆλΆμ κ²°ν¨μ κΈ°μ‘΄ μ½λ μμ μμ λ°μλλ―λ‘ μ΄ν΄νκΈ° μ¬μ΄ μ½λλ μ€λ₯μ μνμ μ΅μνν¨
https://www.planetgeek.ch/wp-content/uploads/2014/11/Clean-Code-V2.4.pdf
Robert C Martion - Clean Code
- Write BETTER Code! 7 Tips to Improve Your Programming Skills : https://youtu.be/vfqvzgkYYF0?list=PLWEGSwIIXaWDPEjAjBaaCph9tJRddgUpW
- Coding is not difficult | Mark Zukerberg : https://youtu.be/F9GujgK0y2M?list=PLWEGSwIIXaWDPEjAjBaaCph9tJRddgUpW
- μλλ₯Ό λΆλͺ ν λ°ν Naming νλΌ
- λ³μλ ν¨μμ ν΄λμ€μ μ‘΄μ¬μ μ΄μ μ μ¬μ©λ°©λ²λ±μ μκΈ° μ½κ² μμ±ν΄μΌ νλ€
- μ½λκ° νλ μΌμ μ§μνκΈ° μ½κ² μμ±ν΄μΌ νλ€
//λμ μ int d; // κ²½κ³Ό μκ° // dλ μλ¬΄λ° μλ―Έκ° λλ¬λμ§λ μμΌλ©° κ²½κ³Όμκ°μ΄λ λ μ§ μλΌλ λλλ λ€μ§ μλλ€. //μ’μ μ int elapsedTimeInDays; int daysSinceCreation; int fileAgeInDays; // ν΄λΉ λ³μκ° μ΄λ ν μν μ νλμ§ μκΈ° μ½λ€.
- μλͺ»λ μ 보λ₯Ό νΌν΄μ Naming νλΌ.
- Naming μμ μλͺ»λ μλ―Έλ₯Ό λ΄μ λ¨μ΄λ₯Ό μ¬μ©ν΄μλ μλλ€.
- μλ‘ ν‘μ¬ν μ΄λ¦μ΄λ₯Ό μ¬μ©νμ§ μλλ‘ μ£Όμνλ€.
//λμ μ //κ³μ κ·Έλ£Ήμ νννκ³ μ νμ§λ§ Listμ μλ―Έκ° μλͺ» μ λ¬λ μ μλ€. accountList //ν‘μ¬ν μ΄λ¦μ νΌλμ μ€μ μλ€. XYZControllerForEfficientHandllingOfStrings , XYZControllerForEfficientStorageOfStrings (ꡬλΆμ΄ μ½μ§ μλ€) //μ’μ μ //κ³μ κ·Έλ£Ήμ νννλ€λ©΄ accountGroup, bunchOfAccouns, νΉμ λ¨μν accounts λΌκ³ λͺ λͺ νλ€.
- ν¨μλ νκ°μ§ μν λ§μ μνν΄μΌ νλ€.
- ν¨μλ ν κ°μ§λ₯Ό ν΄μΌ νλ€. κ·Έ ν κ°μ§λ₯Ό μ ν΄μΌ νλ€. κ·Έ ν κ°μ§λ§μ ν΄μΌ νλ€.
- μ΄ λΆλΆμμ λ¬Έμ κ° λλ€λ©΄, κ·Έκ²μ κ·Έ 'ν κ°μ§'κ° λ¬΄μμΈμ§ μκΈ°κ° μ΄λ ΅λ€λ μ μ΄λ€.
- μ΄μ λν΄ κ°λ¨ν νμ μ£Όμλ©΄, μ§μ λ ν¨μ μ΄λ¦ μλμ μΆμν μμ€μ΄ νλμΈ λ¨κ³λ§ μννλ€λ©΄ κ·Έ ν¨μλ νκ°μ§ μμ λ§ νλ€κ³ λ³Ό > μ μλ€.
- μ΄μ¨κ±°λ μ°λ¦¬κ° ν¨μλ₯Ό λ§λλ μ΄μ λ ν° κ°λ μ λ€μ μΆμν μμ€μμ μ¬λ¬ λ¨κ³λ‘ λλ μννκΈ° μν΄μκ° μλλκ°.
- λ°λΌμ ν¨μκ° 'ν κ°μ§'λ§ νλμ§ νλ¨νλ €λ©΄ ν΄λΉ ν¨μ λ΄μμ μλ―Έ μλ μ΄λ¦μΌλ‘ λ€λ₯Έ ν¨μλ₯Ό μΆμΆν μ μλ€λ©΄ κ·Έ ν¨μλ μ¬λ¬ μμ μ νλ μ μ΄λ€.
- Switchλ³΄λ€ λ€νμ±(polymorphism) μ¬μ©
- switch λ¬Έμ μκ² λ§λ€κΈ° μ΄λ ΅λ€. λν 'ν κ°μ§' μμ λ§ νλ switch λ¬Έλ λ§λ€κΈ° μ΄λ ΅λ€. λ³Έμ§μ μΌλ‘ switch λ¬Έμ Nκ°μ§λ₯Ό μ²λ¦¬νλ€.
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); } }
μ ν¨μμλ λͺ κ°μ§ λ¬Έμ κ° μλ€. 첫째, ν¨μκ° κΈΈλ€. μ μ§μ μ νμ μΆκ°νλ©΄ λ κΈΈμ΄μ§λ€. λμ§Έ, 'ν κ°μ§' μμ λ§ μννμ§ μλλ€. μ μ§Έ, SRP(Single Responsibliity Principle)λ₯Ό μλ°νλ€. μ½λλ₯Ό λ³κ²½ν μ΄μ κ° μ¬λΏμ΄κΈ° λλ¬Έμ΄λ€. λ€μ§Έ, OCP(Open Closed Principle)λ₯Ό μλ°νλ€. μ μ§μ μ νμ μΆκ°ν λλ§λ€ μ½λλ₯Ό λ³κ²½νκΈ° λλ¬Έμ΄λ€. νμ§λ§ μλ§ κ°μ₯ μ¬κ°ν λ¬Έμ λΌλ©΄ μ ν¨μμ κ΅¬μ‘°κ° λμΌν ν¨μκ° λ¬΄νμ μ‘΄μ¬νλ€λ μ¬μ€μ΄λ€.
μ΄ λ¬Έμ λ₯Ό ν΄κ²°ν μ½λκ° μλ μ½λ μ΄λ€. μλ μ½λλ switch λ¬Έμ μΆμ ν©ν 리μ κ½κ½ μ¨κΈ΄λ€. μ무μκ²λ 보μ¬μ£Όμ§ μλλ€.
ν©ν 리λ switch λ¬Έμ μ¬μ©ν΄ μ μ ν Employee νμ ν΄λμ€μ μΈμ€ν΄μ€λ₯Ό μμ±νλ€.; calculatePay, isPayday, deliverPay λ±κ³Ό κ°μ ν¨μλ Employee μΈν°νμ΄μ€λ₯Ό κ±°μ³ νΈμΆλλ€.
κ·Έλ¬λ©΄ λ€νμ±μΌλ‘ μΈν΄ μ€μ νμ ν΄λμ€μ ν¨μκ° μ€νλλ€.
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 HourlyEmployee(r); case SALARIED: return new SalariedEmployee(r); default: throw new ImvalidEmployeeType(r.type); } } }
- ν¨μ μΈμ μ΅μν
- κ°κΈμ μ΄λ©΄ 4κ° μ΄μμ μΈμλ₯Ό νΌνλλ‘ νλ€.
- μ£ΌμμΌλ‘ λμ μ½λλ₯Ό 보μνμ§ λ§κ³ , μ½λλ‘ μλλ₯Ό νννλΌ.
- λμ μ£Όμ
- νΉλ³ν μ΄μ μμ΄ μ무κ°μΌλ‘ λ€λ μ£Όμ
- μ½λμ λ΄μ©μ κ·Έλλ‘ λ°λ³΅νλ μ€λ³΅μ μΈ μ£Όμ (javadoc ν¬ν¨)
- μ£ΌμμΌλ‘ μ²λ¦¬λ μ½λ: λλΆλΆμ΄ μ£ΌμμΌλ‘ μ κ±°λ μ½λλ λ€μ μ¬μ©λμ§ μλλ€.
- μ’μ μ£Όμ
- λ²μ μΈ μ£Όμ (μ μκΆ, μ¬μ©κΆ λ±)
- ꡬ체μ μΈ μ 보μ μλλ₯Ό μ€λͺ νλ μ£Όμ
- κ²°κ³Όλ₯Ό κ²½κ³ νλ μ£Όμ (eg: βμ¬μ μκ°μ΄ μΆ©λΆνμ§ μλ€λ©΄ μ€ννμ§ λ§μμμ€.β)
- TODO, κ³΅κ° APIμ λν Javadocs λ±
![]()
- μ μ ν ν κΈΈμ΄λ₯Ό μ μ§νλΌ.(λΉ νμ μΆκ°νλλ‘ νλ€.)
package fitnesse.wikitext.widgets; import java.util.regex.*; public class BoldWidget extends ParentWidget { public static final String REGEXP = "'''.+?'''"; private static final Pattern pattern = Pattern.compile("'''(.+?)'''", Pattern.MULTILINE + Pattern.DOTALL ); public BoldWidget(ParentWidget parent, String text) throws Exception { super(parent); Matcher match = pattern.matcher(text); match.find(); addChildWidgets(match.group(1)); } public String render() throws Exception { StringBuffer html = new StringBuffer(""); html.append(childHtml()).append(""); return html.toString(); } }
- κ΄λ ¨νλͺ©κ°μ 거리λ₯Ό μ΅μννλ€.
- λ³μλ μ¬μ©νλ μμΉμ μ΅λν κ°κΉμ΄ μ μΈνλ€.
- μ’ μ κ΄κ³μ ν¨μλ μΈλ‘λ‘ κ°κΉμ΄ λ°°μΉνλ€.
- λ€μ¬ μ°κΈ° μνκΈ°
![]()
- μλ£λ μΆμνλ₯Ό ν΅ν΄ λ΄λΆ ꡬν μ 보λ₯Ό λ ΈμΆνμ§ λ§μμΌ νλ€.
public class Point { public double x; public double y; }
public interface Point { double getX(); double getY(); void setCartesian(double x, double y)); double getR(); double getTheta(); void setPolar(double r, double theta); }
- λμ μμ§λλ₯Ό μ μ§νλλ‘ νλ€.
- ν΄λμ€λ μΈμ€ν΄μ€ λ³μκ° μ μ΄μΌ νλ©°, λ©μλκ° λ³μλ₯Ό λ λ§μ΄ μ¬μ©ν μλ‘ μμ§λκ° λλ€.
- μμ§λλ₯Ό μ μ§νλ©΄, μμ λ¨μΌ μν ν΄λμ€λ‘ λΆλ¦¬κ° κ°λ₯.
- Nullμ λ°ννκ±°λ νλΌλ―Έν°λ‘ λκΈ°λ κ²μ μ§μνλΌ.(λΉ κ°μ²΄ λ±μ μ λ¬)
- Unchecked Exceptionμ μ¬μ©νλΌ.
- Checked Exceptionμ λΆνμν μμΈ μ²λ¦¬λ₯Ό κ°κ² λκΈ° λλ¬Έμ λλλ‘ μ§μνλΌ.
![]()
- Errorλ μμ€ν μ λΉμ μμ μΈ μν©μ΄ μκ²Όμ λ λ°μνλ€. μ΄λ μμ€ν λ 벨μμ λ°μνκΈ° λλ¬Έμ μ¬κ°ν μμ€μ μ€λ₯μ΄λ€. λ°λΌμ κ°λ°μκ° λ―Έλ¦¬ μμΈ‘νμ¬ μ²λ¦¬ν μ μκΈ° λλ¬Έμ, μ ν리μΌμ΄μ μμ μ€λ₯μ λν μ²λ¦¬λ₯Ό μ κ²½ μ°μ§ μμλ λλ€.
- μμΈ(Exception)λ κ°λ°μκ° κ΅¬νν λ‘μ§μμ λ°μνλ€. μ¦, μμΈλ λ°μν μν©μ 미리 μμΈ‘νμ¬ μ²λ¦¬ν μ μλ€. μ¦, μμΈλ κ°λ°μκ° μ²λ¦¬ν μ μκΈ° λλ¬Έμ μμΈλ₯Ό ꡬλΆνκ³ κ·Έμ λ°λ₯Έ μ²λ¦¬ λ°©λ²μ λͺ νν μκ³ μ μ©νλ κ²μ΄ μ€μνλ€.
![]()
- ν μ€νΈμ½λ μμ± λ° , μ§μμ μΈ μ μ§λ₯Ό ν΅ν΄ μ½λμ λν μ μ°μ±, μ μ§λ³΄μμ± λ° μ¬μ¬μ©μ±μ ν보νλ€.
- κΉ¨λν ν μ€νΈμ λ€μ― κ°μ§ μμΉ(F.I.R.S.T)
- Fast : ν μ€νΈλ λΉ¨λΌμΌ νλ€. κ·Έλ μ§ μμΌλ©΄ μμ£Ό λ릴 μλλ₯Ό λͺ»λ΄κ³ , κ²°κ΅ λΆνμν ν μ€νΈκ° λλ€.
- Independent : κ° ν μ€νΈλ μλ‘ μμ‘΄νλ©΄ μλλ€. μμ‘΄μ μΈ κ²½μ° μ€ν¨μ μμΈ νμ μ΄ μ΄λ ΅λ€.
- Repeatable : ν μ€νΈλ μ΄λ€ νκ²½μμλ λ°λ³΅ μ€ν κ°λ₯ν΄μΌ νλ€.
- Self-Validating : ν μ€νΈ boolean κ°μΌλ‘ κ²°κ³Όλ₯Ό λ΄μΌ νλ€. κ·Έλ μ§ μμΌλ©΄, μλνμ κ±Έλ¦Όλμ΄ λλ€.
- Timely : ν μ€νΈλ μ μμ μμ±ν΄μΌ νλ€. μ€μ μ½λ μ§μ μ μμ±ν΄μΌ μ μ ν μ½λκ° μμ±λλ€.