깨끗한 코드를 넘어서 아름다운 코드를 작성하기 위한 여정;

명령형과 선언형;

Wanted Ticket 서비스 개발 업무를 JH에게 지시 할 때

명령형; How 어떻게?

첫 번째, Front에서 티켓 예매를 진행하기 위해서 Reservation 정보를 Request Message를 보내야 하니, 필요한 메시지 구조를 문서화 해서 전달 해주세요.

두 번째, 전달 받은 메시지를 이용해서 유효성 검사와 예약 가능 여부를 확인하고 예약을 진행해주세요.

선언형; What 무엇을?

티켓 예매 시스템 1주일 이내로 개발해주세요!

위 예제를 보면 명령형의 경우, 목적을 달성하기 위해서 어떻게(How) 동작 해야하는지에 대해서 구체적으로 이야기한다. 그런데 선언형의 경우에는 그렇지 않다. 원하는 목적만 이야기한다. 그 목적을 달성하기 위해서 누구와 협의를 하고 어떻게 구조를 설계를 해야하는지는 모른다. 개발실장은 원하는 목적(What)만 이야기하면 된다.

개발 환경에서도 마찬가지다. 예를 들어, int형 배열에 있는 요소에 곱하기 2를 하고 싶다면 명령형의 경우, 반복문이 실행될 때 마다 하나의 요소를 꺼내와서 그 요소에 2를 곱하는 부분을 상세하게 명령 한다.

int[] ary = new int[]{1,2,3,4,5};
for(int i = 0; i < ary.length; i++){
	ary[i] = ary[i] * 2;
	ary[i] *= 2;
}
System.out.println(Arrays.toString(ary));

하지만, 선언형의 경우는 단순히 “요소에 2를 곱해줘”라고 이야기 하지 상세하게 이야기 하지 않는다. 그 이유는 상세한 동작(여기서는 for구문을 말한다.)은 추상화 되어 있기 때문이다.

int[] ary = new int[]{1, 2, 3, 4, 5};
int[] new_ary = Arrays.stream(ary).map(element -> element * 2).toArray();
System.out.println("Array => " + Arrays.toString(ary));
System.out.println("New Array => " + Arrays.toString(new_ary));

람다 표현식

함수형 프로그래밍

순수 함수를 기반으로 데이터 처리와 상태 변화를 최소화하는 방식의 프로그래밍 기법을 말한다. 여기서 순수 함수란 동일한 입력에 대해 항상 같은 결과(멱등성)를 반환하며, 외부 상태를 변경하지 않는 함수를 말한다. 여기서 **“외부 상태를 변경하지 않는다.”**의 의미는 “String[] 타입을 인자(Input 값)로 받는 upperCase 함수가 동작할 때 인자로 전달 받은 **외부 상태(=원본(Source), Input 값)**를 변경하지 않고 동작하는 것을 말하며, 그렇기 때문에 return 값(Output 값)은 항상 동일하며 부수적인 영향을 주지 않는다.” 라는 의미를 가진다.

public void immutablePureFunctionTests(){
        List<String> ary = Arrays.asList(new String[]{"a", "b", "c"});
        System.out.println(Arrays.toString(ary.toArray()));
        System.out.println(Arrays.toString(ary.stream().map(String::toUpperCase).toList().toArray()));
}

순수 함수를 이용하면 코드의 복잡성에 따른 부작용(Side-Effects)를 최소화하여, 프로그램의 유지 보수와 테스트를 용이하게 할 수 있다.

<aside> 💡 출처: https://yozm.wishket.com/magazine/detail/2023/

</aside>

1급 시민 객체

사용할 때 다른 요소들과 아무런 차별이 없다는 것을 뜻한다. (여기서 다른 요소란?; Primitive Type, Reference Type을 말한다.)

1급 시민 객체가 되기 위한 조건; 값으로 취급 할 수 있어야 한다.

  1. 모든 일급 객체는 변수가 데이터 구조(ex. List, Map)에 담을 수 있어야 한다.
  2. 모든 일급 객체는 메서드의 파라미터로 전달 할 수 있어야 한다.