한 모듈이나 클래스가 다른 모듈이나 클래스의 기능이나 데이터에 지나치게 의존하는 상황
문제점
해결법
public class Employee {
private Department _department;
public int CalculateBonus() {
return _department.GetBonusBase() * 2;
}
}
public class Department {
public int GetBonusBase() {
// 복잡한 계산...
return 100;
}
}
public class Employee {
private int _bonusBase;
public Employee(int bonusBase) {
_bonusBase = bonusBase;
}
public int CalculateBonus() {
return _bonusBase * 2;
}
}
public class Department {
// 기능은 Department 내부에 유지
}
public class Order {
private Customer _customer;
public decimal CalculateOrderDiscount() {
if (_customer.HasLoyaltyDiscount()) {
return _customer.GetLoyaltyDiscount();
}
return 0;
}
}
public class Customer {
public bool HasLoyaltyDiscount() {
// 충성도 할인 여부를 판단하는 로직
return true;
}
public decimal GetLoyaltyDiscount() {
// 충성도 할인 금액 계산 로직
return 0.1m; // 10% 할인
}
}
// 전략 패턴 사용
public interface IDiscountStrategy {
decimal CalculateDiscount();
}
public class LoyaltyDiscountStrategy : IDiscountStrategy {
private Customer _customer;
public LoyaltyDiscountStrategy(Customer customer) {
_customer = customer;
}
public decimal CalculateDiscount() {
// 충성도 할인 금액 계산 로직
if (_customer.HasLoyaltyDiscount()) {
return _customer.GetLoyaltyDiscount();
}
return 0;
}
}
public class Order {
private IDiscountStrategy _discountStrategy;
public Order(IDiscountStrategy discountStrategy) {
_discountStrategy = discountStrategy;
}
public decimal CalculateOrderDiscount() {
return _discountStrategy.CalculateDiscount();
}
}
서로 밀접하게 관련된 데이터들끼리 자주 함께 나타나는 현상 (예 : 주소, 도시, 우편번호가 함께 전달된다거나)
문제점
해결법
public class Order {
public void ProcessOrder(string customerName, string address, string city, string postalCode) {
// 주문 처리 로직...
}
}
public class CustomerAddress {
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
}
public class Order {
public void ProcessOrder(CustomerAddress address) {
// 주문 처리 로직...
}
}
public void CreateLabel(string recipient, string street, string city, string zipCode) {
// 라벨 생성 로직...
}
public class Address {
public string Recipient { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
}
public void CreateLabel(Address address) {
// 라벨 생성 로직...
}
반복문은 매우 유용하지만, 때로는 코드가 복잡해지고 가독성이 떨어진다.
요즘의 트렌드는 '파이프라인' 이라는 개념을 제시하는 추세임. (LINQ 기능)
반복문은 명령형 프로그래밍. 어떻게? 를 명시
파이프라인은 선언형 프로그래밍. 무엇을? 을 명시한다.
적절하게 반복문과 파이프라인을 번갈아 사용.
List<int> numbers = new List<int> {1, 2, 3, 4, 5};
List<int> evenNumbers = new List<int>();
foreach (var number in numbers) {
if (number % 2 == 0) {
evenNumbers.Add(number);
}
List<int> numbers = new List<int> {1, 2, 3, 4, 5};
var evenNumbers = numbers.Where(n => n % 2 == 0).ToList();
List<string> names = new List<string> {"Alice", "Bob", "Charlie"};
List<string> upperCaseNames = new List<string>();
foreach (var name in names) {
upperCaseNames.Add(name.ToUpper());
}
List<string> names = new List<string> {"Alice", "Bob", "Charlie"};
var upperCaseNames = names.Select(name => name.ToUpper()).ToList();
특정 상황에서만 사용되는 필드가 존재하는 경우를 말한다.
클래스의 다른 부분에서는 사용되지 않거나 값이 할당되지 않은 그런 값들.
해결법
public class Customer {
public string Name { get; set; }
public decimal CreditLimit; // 임시 필드
public DateTime? LastPurchaseDate; // 임시 필드
public void UpdateCreditLimit(decimal newLimit) {
CreditLimit = newLimit;
}
}
public class Customer {
public string Name { get; set; }
public CreditInfo CreditInformation { get; set; }
}
public class CreditInfo {
public decimal CreditLimit { get; set; }
public DateTime? LastPurchaseDate { get; set; }
public void UpdateCreditLimit(decimal newLimit) {
CreditLimit = newLimit;
}
}
public class Order {
public int OrderId { get; set; }
public decimal? TemporaryDiscount; // 임시 필드
public void ApplyTemporaryDiscount(decimal discount) {
TemporaryDiscount = discount;
}
public decimal CalculateTotal(decimal basePrice) {
return TemporaryDiscount.HasValue ? basePrice - TemporaryDiscount.Value : basePrice;
}
}
public class Order {
public int OrderId { get; set; }
public DiscountInfo DiscountInformation { get; set; }
}
public class DiscountInfo {
public decimal? TemporaryDiscount { get; set; }
public void ApplyTemporaryDiscount(decimal discount) {
TemporaryDiscount = discount;
}
public decimal CalculateAdjustedPrice(decimal basePrice) {
return TemporaryDiscount.HasValue ? basePrice - TemporaryDiscount.Value : basePrice;
}
}
자식 클래스가 부모 클래스로부터 받은 세머드나 데이터를 일부만 사용하는 경우
해결법
public class Vehicle {
public void StartEngine() { /* 엔진 시작 로직 */ }
public void StopEngine() { /* 엔진 정지 로직 */ }
public void Fly() { /* 비행 로직 - 모든 차량이 날 수는 없음 */ }
}
public class Car : Vehicle {
// Car 클래스는 Fly 메소드를 필요로 하지 않음
}
public class Vehicle {
public void StartEngine() { /* 엔진 시작 로직 */ }
public void StopEngine() { /* 엔진 정지 로직 */ }
}
public class FlyingVehicle {
private Vehicle _vehicle = new Vehicle();
public void Fly() { /* 비행 로직 */ }
public void StartEngine() {
_vehicle.StartEngine();
}
public void StopEngine() {
_vehicle.StopEngine();
}
}
public class Car {
private Vehicle _vehicle = new Vehicle();
public void StartEngine() {
_vehicle.StartEngine();
}
public void StopEngine() {
_vehicle.StopEngine();
}
}
public class Employee {
public void Work() { /* 일반적인 작업 */ }
public void TakeVacation() { /* 휴가 사용 */ }
}
public class Intern : Employee {
// 인턴은 휴가를 사용하지 않음
}
public class Employee {
public void Work() { /* 일반적인 작업 */ }
public void TakeVacation() { /* 휴가 사용 */ }
}
public class Intern {
private Employee _employee = new Employee();
public void Work() {
_employee.Work();
}
// TakeVacation 메소드는 포함하지 않음
}