불필요하게 복잡하고 확장 가능한 코드
You Aren't Gonna Need It (YAGNI) 원칙
현재 필요하지 않는 기능은 추가하지 말 것
// 거의 사용되지 않는 메서드를 포함한 클래스
public class DataProcessor
{
public void ProcessData(Data data) { /* 데이터 처리 로직 */ }
public void ProcessFutureData(Data data) { /* 현재 사용되지 않음 */ }
}
// 필요한 기능만을 가진 클래스
public class DataProcessor
{
public void ProcessData(Data data) { /* 데이터 처리 로직 */ }
}
// 불필요한 위임
public class DataHandler
{
private DataProcessor processor = new DataProcessor();
public void HandleData(Data data) { processor.ProcessData(data); }
}
// DataProcessor의 기능을 직접 사용
public class DataHandler
{
public void HandleData(Data data)
{
// 데이터 처리 로직을 여기에 직접 구현
}
}
너무 많은 매개변수는 문제가 있는 것
해결법
public class Order
{
public decimal OrderTotal { get; set; }
public decimal TaxRate { get; set; }
public decimal CalculateTotalCost(decimal orderTotal, decimal taxRate)
{
return orderTotal + (orderTotal * taxRate);
}
}
// 사용 예시
Order order = new Order();
decimal totalCost = order.CalculateTotalCost(order.OrderTotal, order.TaxRate);
// 질의 함수로 바꿈
public class Order
{
public decimal OrderTotal { get; set; }
public decimal TaxRate { get; set; }
public decimal CalculateTotalCost()
{
return OrderTotal + (OrderTotal * TaxRate);
}
}
// 사용 예시
Order order = new Order();
decimal totalCost = order.CalculateTotalCost();
public void RenderDocument(string document, bool isPDF)
{
if (isPDF)
{
// PDF로 렌더링
}
else
{
// 다른 형식으로 렌더링
}
}
// 플래그 인수 제거하기
public void RenderDocumentAsPDF(string document)
{
// PDF로 렌더링
}
public void RenderDocumentAsOtherFormat(string document)
{
// 다른 형식으로 렌더링
}
한 클래스가 너무 많은 책임을 가지면, 코드를 복잡하게 만든다.
중복된 코드가 생겨나고, 클래스 내의 필드와 메소드 간의 연관성이 낮아서, 응집력도 떨어진다. (객체 지향 프로그래밍에서 응집력도 중요한 요소 중 하나)
public class Employee
{
public string Name { get; set; }
public string Department { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
// 기타 많은 필드...
public void CalculatePay() { /* 급여 계산 로직 */ }
public void GenerateReport() { /* 보고서 생성 로직 */ }
// 기타 많은 메소드...
}
public class Employee
{
public string Name { get; set; }
public ContactInfo ContactInfo { get; set; }
public void CalculatePay() { /* 급여 계산 로직 */ }
}
public class ContactInfo
{
public string Department { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
}
public class ReportGenerator
{
public void GenerateSalesReport(SalesData data)
{
// 데이터 검증 로직
// 보고서 생성 로직
}
public void GenerateEmployeeReport(EmployeeData data)
{
// 데이터 검증 로직 (중복)
// 보고서 생성 로직
}
}
public class ReportGenerator
{
public void GenerateSalesReport(SalesData data)
{
ValidateData(data);
// 보고서 생성 로직
}
public void GenerateEmployeeReport(EmployeeData data)
{
ValidateData(data);
// 보고서 생성 로직
}
private void ValidateData(object data)
{
// 데이터 검증 공통 로직
}
}
클래스도 프라이버시가 있다.
클라이언트 코드에서 객체의 내부 구조에 대해서 지나치게 많이 아는 것은 좋은 것이 아니다.
클래스끼리 강한 결합이 있는 것은 피하자.
public class Customer
{
public Account Account { get; set; }
}
public class Account
{
public BillingPlan BillingPlan { get; set; }
}
public class BillingPlan
{
public decimal Rate { get; set; }
}
// 사용 예시
Customer customer = new Customer();
decimal rate = customer.Account.BillingPlan.Rate;
public class Customer
{
private Account account;
public decimal GetBillingRate()
{
return account.GetBillingRate();
}
}
public class Account
{
private BillingPlan billingPlan;
public decimal GetBillingRate()
{
return billingPlan.Rate;
}
}
// 사용 예시
Customer customer = new Customer();
decimal rate = customer.GetBillingRate();
동일한 구조의 클래스는 왠만하면 하나의 인터페이스 아래 통합하여 유연한 코드를 만들어 나가자.
슈퍼 클래스 추출하기
public class CsvReader
{
public string ReadCsvFile() { /* CSV 파일 읽기 로직 */ }
}
public class XmlReader
{
public string ReadXmlFile() { /* XML 파일 읽기 로직 */ }
}
public interface IFileReader
{
string ReadFile();
}
public class CsvReader : IFileReader
{
public string ReadFile() { /* CSV 파일 읽기 로직 */ }
}
public class XmlReader : IFileReader
{
public string ReadFile() { /* XML 파일 읽기 로직 */ }
}
public class PdfExporter
{
public void Export(string content) { /* PDF 내보내기 로직 */ }
// 기타 공통 메소드들...
}
public class WordExporter
{
public void Export(string content) { /* Word 내보내기 로직 */ }
// 기타 공통 메소드들...
}
// 공통 메소드들은 묶고 내보내기 로직만 override로 재정의
public abstract class FileExporter
{
public abstract void Export(string content);
// 기타 공통 메소드들...
}
public class PdfExporter : FileExporter
{
public override void Export(string content) { /* PDF 내보내기 로직 */ }
}
public class WordExporter : FileExporter
{
public override void Export(string content) { /* Word 내보내기 로직 */ }
}