
이 책은 왜 다양한 언어가 생겼으며 개념이 각기 다를까에 대한 답을 주는 책이다. 각 언어의 특징 속에서 각기 다른 문제해결. 당연하다고 생각했던 관념을 더 확장을 시켜준 책이다. 다양한 개념의 ‘왜’를 해결해주는 책! ‘코딩을 지탱하는 기술’이다.
1장. 효율적으로 언어 배우기
규칙은 언어마다 다르다. 하지만 공통적으로 사용되는 개념이 있는데 그 개념이야말로 중요한 지식이다. 그리고 각 언어는 사람이 만든 것이다. 각 언어마다 특성이 있고 본인이 그 특성이 왜 필요한 지에 대해 알아볼 필요가 있다. 어떤 언어를 배우는 것이 좋은 지에 대한 질문은 무의미하다. 앞날은 아무도 알 수 없으니! 가장 중요한 건 언어가 바뀌어도 통용할 수 있는 이해력을 길러야 한다는 것이다.
2장. 프로그래밍 언어 탄생의 역사
케이블을 여기저기 연결하는 것(ENIAC)에서 시작해서 테이프에 구멍을 뚫어서 데이터를 표현함(EDSAC)을 지나 수식 변환 시스템(FORTRAN) 즉, 현재와 비슷한 프로그래밍 언어가 탄생했다. FORTRAN 설계자는 이 성과가 나태함에서 왔다고 이야기한다. 결국 언어는 편리함을 추구하기에 만들어진 것이다. 그리고 각 언어마다 특화됨이 다르다. 적재적소에 편리하게 언어란 도구를 사용하자.
3장. 문법의 탄생
‘1 더하기 2에 3을 곱한다’는 똑같은 처리도, 언어에 따라 표현 방법이 틀리다. 그러나 구문 트리로 표현하면 거의 동일하다. 이들 언어에 차이가 생긴 것은 ‘어떤 문자열을 쓰면 어떤 구문 트리가 생기는가’라는 규칙이다. 이것이 문법이다.
4장. 처리 흐름 제어
if문, while 문, for문, foreach문 등등 처리 흐름을 제어하기 위한 규칙이 있다. 이러한 규칙들은 사용하지 않아도 프로그램을 짤 수 있지만 알기 쉬운 코드를 만들기 위해 만들어진 것이다. 그러므로 적극적으로 사용하자.
5장. 함수
프로그램의 규모가 커지면 전체적인 구조를 파악하기 어려워진다 또한 비슷한 처리를 몇 번이고 반복해서 쓰고 싶어지는 경우도 생긴다. 함수는 이 문제를 해결하기 위해 탄생했다. 재사용이 가능하다는 것이다. 또한 함수를 사용함으로 ‘재귀 호출’이라는 코딩 기술도 탄생했다.
6장. 에러 처리
프로그램은 개발자의 잘못이라든지 프로그램의 한계이든 실패할 때가 있다. 실패를 전달하는 방법은 크게 2 가지로 나눌 수 있다. ‘반환값으로 알린다’와 ‘실패하면 점프한다’이다. 실패하면 점프한다는 현재 많은 언어가 지원하고 있는 ‘예외 처리’의 구조이다.
한편, 예외 처리에도 몇가지 몇가지 문제가 있다. ‘짝을 이루는 처리’를 바르게 짝을 지어 처리하는 것이 어렵다는 문제이다. 예를 들어 자원을 열고 닫으려 할 때 예외가 생긴다면 리소스 처리가 불가능하다. 이러한 처리를 위해 ‘Finally’개념이 나왓다.
7장. 이름과 스코프
변수 이름을 설정하는 것은 매우 중요하다. 하지만 하나의 변수가 모든 영역에 영향을 끼친다면 또 많은 불편함이 있을 것이다. 이 변수의 영역, 또는 영향을 제한하는 것이 스코프이다. 스코프 종류에는 정적 스코프와 동적 스코프가 나눠져있다. 동적 스코프는 시작과 끝을 지정하는 것이다. 하지만 문제점은 스코프 내에 다른 함수를 사용한다면 그 함수 내에도 변수가 영향을 미친다는 것이 문제다.
정적 스코프는 각 메소드마다 새로운 스코프를 제공하는 것이다. 현재는 정적 스코프 방식을 많이 사용하고 있지만 부분적으로 동적 스코프도 사용하고 있다.
8장. 형
10이라는 수를 표현하기 위해 10개의 표식을 사용한 것이 가장 원시적인 방법이다. ‘가장 간단한 표현 방법’이 무엇인지 고민했고 2진법이라는 자릿수까지 발전하게 되었다. 또한, 소수점이 붙은 수를 표현하기 위해 고정 소수점과 부동 소수점이 발명이 되었다. 컴퓨터 내에서는 소수점인지 정수인지에 따라 수학식을 진행하는 방법이 달랐다. 그렇기에 소수점인지 정수인지 표시가 필요했고 이런 정보로 인해 형이 탄생했다. 시간이 지나고 현재는 정적 형결정과 동적 형결정과 같이 정보 저장 장소나 사용하는 타이밍이 다른 것까지 포함해서 형이라 부른다.
9장. 컨테이너와 문자열
컨테이너에 넣은 데이터는 메모리에 저장된다. 그리고 컨테이너의 종류는 다양하다. 배열, 연결리스트, 사전, 해쉬, 연상배열, 해쉬테이블, 트리.
만능 컨테이너는 없다. 각 컨테이너에게는 장단점이 존재한다. 이에 따른 최적의 컨테이너를 선정하여 사용해야한다.
비트열의 조합을 어떻게 문자로 표현할 지 고민 끝에 전 세계 문자를 포함한 문자 집합 Unicode가 탄생했다. 각 언어마다 문자열을 표현하는 방식도 다르다.
10장. 병행 처리
병행처리란 게임을 하면서 음악을 듣는 것 처럼 동시에 복수의 처리를 하는 것을 병행처리라 한다. 회로(CPU)가 하나 밖에 없는데 어떻게 복수츼 처리를 동시에 실행할 수 있는 것일까? 바로 ‘사람이 눈치챌 수 없는 짧은 순간에 복수의 처리를 변경해가면서 실행’하기 때문이다. 처리를 변경하는 방법은 2 가지가 있다.
먼저, 협력적 멀티태스크. ‘타이밍이 좋은 시점에서 교대’하는 방법이다. 이 방법은 완료 또는 시점이 되었을 때 변경해도 좋다는 신호를 보내야 교대를 할 수 있다. 신뢰 관계를 기반으로 성립하는 시스템이다.
다음은 선점적 멀티태스크이다. 일정 시간에 교대하는 방식이다. 현재 대부분의 OS 자체가 이 방법으로 복수 프로그램을 병행실행한다. 하지만 자원을 공유하다가 다른 프로그램이 그 자원을 바꾸고 원래 프로그램은 자원이 바뀐 지 모른 채 자원을 사용하게 되면 심각한 문제가 발생할 수 있다. 이런 현상을 ‘경합 상태’ 또는 ‘스레드 세이프가 아니다’라고 표현한다. 그렇다면 경합 상태는 어떤 경우에 발생할까? 먼저, 2가지 처리가 변수를 공유하고 적어도 하나의 처리가 그 변수를 변경할 때 이다. 그리고 한 쪽 처리가 한 단락 마무리 되기 전에, 다른 한쪽의 처리가 끼어들 가능성이 있을 때 경합 상태가 일어난다. 역으로 말하면 이 조건만 제거한다면 병행 실행 시에도 안정된 프로그램을 만들 수 있다.
먼저, 처음부터 아무것도 공유하지 않는다면 어떨까? 하지만 메모리를 공유하지 않는 것은 너무 엄격한 구조이고 이것은 나중에 ‘스레드’라고 불리게 되었다. 또한 공유메모리를 어떻게 다뤄야 할지 고민해가면서 프로그램을 만들어가야한다. 이러한 공유하지 않는다라는 설계방침 흐름과 비슷한 액터 모델이 있다. 병행해서 동작하는 복수의 처리가 정보를 교환하는 방법이다. 처리는 비동기로 이루어져 대량의 사용자 메시지를 취급하는 서비스에서 많이 사용된다.
다음은 메모리를 공유해도 변경하지 않는 방법이다. 협력적 스레드 방식을 사용해 사용중이라면 기다리는 방식이다. 하지만 서로의 메모리를 기다리는 상태라면 교착상태에 빠지게 된다. 이를 해결하기 위해 트랜잭션 메모리라는 기법을 사용한다.
11장. 객체와 클래스
객체는 현실 세계의 모형을 담은 것이다. 클래스를 만들어 이 모형을 표현한다. 클래스 말고도 모형을 만드는 방법이 여러가지가 있다.
첫 번째는 모듈이다. 원래 관련된 함수를 하나로 모아두기 위한 기능이었다.
두 번째는 함수도 변수도 동일하게 해쉬에 넣는 방법이다. 이것은 자바스크립트 등의 언어가 채용하고 있다.
세 번째는 클로저로 함수 실행 시의 이름 공간의 변수를 하나로 묶기 위해 사용하는 방법이다. 주로 함수형 언어에서 사용되는 방법이다. 객체 지향이 현실 세계의 사물 모형을 만들기 위해 만들어졌지만 각 언어마다 구현 방법이나 ‘객체 지향’이 의미하는 바가 다르다.
12장. 상속을 위한 재사용
상속은 크게 3가지 측면으로 접근이 가능하다.
첫 번째로 ‘부모 클래스로 일반적인 기능을 구현하고, 자식 클래스로 목적에 특화된 기능을 구현한다’라는 접근이다.
두 번째는 ‘복수 클래스의 공통 부분을 부모 클래스로서 추출하면 좋다’는 접근이다.
세 번째는 ‘상속 후 변경된 부분만을 구현하면 효율이 좋다’는 접근이다.
하지만 상속을 많이 사용하게 된다면 코드가 복잡해지고 유지보수가 힘들어진다.
상속은 다중 상속이라는 개념도 있다. 말 그대로 여러 부모 객체를 상속 받는 것이다. 다중 상속에는 같은 데이터를 소지할 시에 충돌이라는 문제가 생긴다.
자바에서는 이러한 충돌 문제때문에 다중 상속을 금지한다. 대신 발달한 것이 위임이라는 개념이다. 또한 인터페이스를 사용하게 되면 다중 구현으로 다중 상속 방식이 가능하다.
다른 언어에서는 메소드 해결 순서를 고민하며 진행한다.
또한, 믹스인과 같이 처리를 섞는 방법도 있다.