본문 바로가기

개발

Effective Java ( 이펙티브 자바 ) - 아이템 47 반환 타입으로는 스트림보다 컬렉션이 낫다 원소 시퀸스를 반환하는 메서드는 수없이 많다. 자바 7까지는 Collections, Set, List 같은 컬렉션 인터페이스, 혹은 Iterable이나 배열을 썼다. for-each 문에서만 쓰이거나 반환된 원소 시퀸스가 일부 Collection 메서드를 구현할 수 없을 때는 Iterable 인터페이스를 썼다. 반환 원소들이 기본타입이거나 성능에 민감한 상황이라면 배열을 썼다. 그런데 자바 8이 스트림이라는 개념을 들고 오면서 이 선택이 아주 복잡한 일이 되어버렸다. 아이템 45에서 이야기했듯이 스트림은 반복을 지원하지 않는다. 따라서 스트림과 반복을 알맞게 조합해야 좋은 코드가 나온다. 여기서 재미난 사실 하나! 사실 Stream 인터페이스는 Iterable 인.. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 46 스트림에서는 부작용 없는 함수를 사용하라 스트림은 처음 봐서는 이해하기 어려울 수 있다. 스트림은 그저 또 하나의 API가 아닌, 함수형 프로그래밍에 기초한 패러다임이다. 스트림 패러다임의 핵심은 계산을 일련의 변환으로 재구성 하는 부분이다. 이때 각 변화 단계는 가능한 한 이전 단계의 결과를 받아 처리하는 순수 함수여야 한다. 순수 함수란 오직 입력만이 결과에 영향을 주는 함수를 말한다. 다른 가변 상태를 참조하지 않고, 함수 스스로도 다른 상태를 변경하지 않는다. 이렇게 하려면 (중간 단계든 종단 단계든) 스트림 연산에 건네는 함수 객체는 모두 부작용(side effect)이 없어야 한다. 다음은 주위에서 종종 볼 수 있는 스트림 코드로, 텍스트 파일에서 단어별 수를 세어 빈도표로 만드는 일을 한다.. 더보기
SRE 1장 - 소개 시스템이 스스로 작동하지 않는다는 것은 이미 널리 알려진 사실이다. 그렇다면 대용량 작업을 수행하는 복잡한 컴퓨팅 시스템은 어떻게 운영되어야 할까? 서비스 관리를 위해 시스템 관리자를 활용하는 방법 기존에는, 시스템 관리자들을 채용했었다. 이 시스템 관리자들은 소프트웨어 컴포넌트들을 모아 배포함으로써 서비스를 구축해 나간다. 이벤트와 업데이트에 대응하는데, 시스템의 복잡도와 트래픽이 증가할수록 감당하기 위해 시스템 관리팀의 규모 역시 커지게 된다. 시스템 관리자를 두면 장점이 몇 가지 있다. 상대적으로 쉽게 서비스를 운영할 수 있다. 수많은 예시가 존재하기 때문이다. 전문 인력들도 이미 풍부하다. 도움이 되는 다양한 도구와 컴포넌트, 그리고 시스템 통합을 업으로 삼는 회사들도 많아서 조금 미숙하더라도 충.. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 45 스트림은 주의해서 사용하라 스트림은 다량의 데이터 처리 작업을 돕고자 자바8에 추가되었다. 스트림의 추상 개념 중 핵심은 두 가지다. 스트림은 데이터 원소의 유한 혹은 무한 시퀸스를 뜻한다. 스트림 파이프라인은 이 원소들로 수행하는 연산 단계를 표현하는 개념이다. 스트림의 원소들은 어디로부터든 올 수 있다. 스트림 안의 데이터 원소들은 객체 참조나 기본 타입 값이다. int, long, double 이렇게 세 가지를 지원한다. 스트림 파이프라인은 소스 스트림에서 시작해 종단 연산으로 끝나며, 그 사이에 하나 이상의 중간 연산이 있을 수 있다. 각 중간 연산은 스트림을 어떤 방식으로 변환한다. 중간 연산들은 모두 한 스트림을 다른 스트림으로 변환하는데, 변환된 스트림의 원소 타입은 변환 전 스트림의 원소 .. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 44 표준 함수형 인터페이스를 사용하라 자바가 람다를 지원하면서 API를 작성하는 모범 사례도 크게 바뀌었다. 예컨대 상위 클래스의 기본 메서드를 재정의해 원하는 동작을 구현하는 템플릿 메서드 패턴의 매력이 크게 줄었다. 이를 대체하는 현대적인 해법은 같은 효과의 함수 객체를 받는 정적 팩터리나 생성자를 제공하는 것이다. 이 내용을 일반화해서 말하면 함수 객체를 매개변수로 받는 생성자와 메서드를 더 많이 만들어야 한다. 이때 함수형 매개변수 타입을 올바르게 선택해야 한다. LinkedHashMap을 생각해보자. 이 클래스의 protected 메서드인 removeEldestEntry를 재정의하면 캐시로 사용할 수 있다. 맵에 새로운 키를 추가하는 put 메서드는 이 메서드를 호출하여 true가 반환되면 맵에서 .. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 43 람다보다는 메서드 참조를 사용하라 람다가 익명 클래스보다 나은 점 중에서 가장 큰 특징은 간결함이다. 그런데 자바에는 함수 객체를 심지어 람다보다도 더 간결하게 만드는 방법이 있으니, 바로 메서드 참조(method reference)다. 다음 코드는 임의의 키와 Integer 값의 매핑을 관리하는 프로그램의 일부다. 이때 값이 키의 인스턴스 개수로 해석된다면, 이 프로그램은 multiset(멀티셋)을 구현한 게 된다. 이 코드는 키가 맵 안에 없다면 키와 숫자 1을 매핑하고, 이미 있다면 기존 매핑 값을 증가시킨다. map.merge(key, 1, (count, incr) -> count + incr); 이 코드는 자바 8 때 Map에 추가된 merge 메서드를 사용했다. merge 메서드는 키, 값, .. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 42 - 7장 - 람다와 스트림 익명 클래스보다는 람다를 사용하라 예전에는 자바에서 함수 타입을 표현할 때 추상 메서드를 하나만 담은 인터페이스(드물게는 추상 클래스)를 사용했다. 이런 인터페이스의 인스턴스를 함수객체라고 하여, 특정 함수나 동작을 나타내는 데 썼다. 1997 JDK 1.1의 등장으로 인해, 함수 객체를 만드는 주요 수단은 익명 클래스가 되었다. 다음 코드를 예로 살펴보자. 문자열을 길이순으로 정렬하는데, 정렬을 위한 비교 함수로 익명 클래스를 사용한다. Collections.sort(words,new Comparator() { public int compare(String s1, String s2) { return Integer.compare(s1.length(), s2.length()); } }); 함수 객체를 사용.. 더보기
Effective Java ( 이펙티브 자바 ) - 아이템 41 정의하려는 것이 타입이라면 마커 인터페이스를 사용하라 아무 메서드도 담고 있지 않고, 단지 자신을 구현하는 클래스가 특정 속성을 가짐을 표시해주는 인터페이스를 마커 인터페이스라 한다. Serializable 인터페이스가 좋은 예다. Serializable은 자신을 구현한 클래스의 인스턴스는 ObjectOutputStream을 통해 쓸 수 있다고, 즉 직렬화 할 수 있다고 알려준다. 마커 애너테이션이 등장하면서 마커 인터페이스는 구식이 되었다는 이야기를 들어보았을 것이다. 하지만 사실이 아니다. 마커 인터페이스는 두 가지 면에서 마커 애너테이션보다 낫다. 첫 번째, 마커 인터페이스는 이를 구현한 클래스의 인스턴스들을 구분하는 타입으로 쓸 수 있으나, 마커 애너테이션은 그렇지 않다. 마커 인터페이스는 어엿한.. 더보기