-
반응형
6장 소프트웨어 이해하기
[컴퓨터란 무엇인가?]- 소프트웨어를 이해하려면 우선 컴퓨터가 무엇인지 부터 이해해야 한다.
- 컴퓨터(명사) : 사전 정의된 명령 조합에 따라 정보를 저장하고 처리하는 전자기기
- 인간이 설정한 목표를 달성하기 위해 일련의 기호 명령을 수행하고 데이터를 비교할 수 있는 모든 물질이 컴퓨터다.
- 컴퓨터는 데이터를 비교할 수 있다. 이러한 부분이 인간의 입력을 받는 다른 기계와 구분된다.
- 컴퓨터는 한 가지 명령뿐 아니라 일련의 명령을 받을 수 있다. 단순한 계산기를 딱 한가지 명령만 수행한다는 점에서 컴퓨터와 구분된다.
- 키보드의 키 입력이나 마우스 클릭도 기호 명령이다. 하지만 프로그래머가 작업할 때 쓰는 주된 기호 명령은 프로그래밍 언어다. 그러므로 작업 품질을 개선할 방법을 이야기 할 때 프로그래머는 프로그램의 구조에 가장 신경쓴다.
[소프트웨어의 구성 요소 구조, 동작, 결과]- 프로그램의 가장 중요한 세 요소가 구조, 동작, 결과라고 생각한다. 구조, 동작, 결과로 현존하는 거의 모든 기계를 묘사할 수 있을 것이다.
- 소프트웨어를 만들 때 보통 구조부터 만들고 동작과 관련된 부분을 작업한 다음 결과를 표시하는 부분을 만든다.
- 결과부터 거꾸로 작업하는 사람도 있다. 그래도 상관없다. 단, 구조나 저으이된 결과 없이 동작을 수행하려면 혼란스러울 가능성이 높기 때문에 동작부터 시작하는 방법은 권하지 않는다.
[소프트웨어 개정판 : ISAR 구별하기]- 구조 , 동작, 결과라는 세 요소를 줄여서 SAR 이라고 부르고, 여기에 입력도 포함시킬 경우 ISAR 이라고 부른다.
- MVC는 소프트웨어를 설계하는 패턴이다. SAR은 모든 소프트웨어에 나타나는 세가지 요소를 가리킨다.
구조
- 전체 프로그램의 구조로 볼 수 있는 몇가직 예는 다음과 같다.
- 코드 디렉터리 레이아웃
- 모든 클래스와 각 클래스 간의 연결 수조
- 데이터베이스를 쓰는 프로그램이라면 데이터베이스의 구조 계획 (단, 데이터베이스에 있는 실제 데이터는 구조에 속하지 않는다는 점을 주의해야한다.)
- 개별 클래스에도 구조가 있다.
- 클래스 메서드의 이름과 메서드에 전달되는 매개변수의 이름과 저료형
- 클래스 변수의 이름과 자료형
- 구조는 프로그램 구성 요소 혹은 프로그램의 일부 조각이라고 볼 수 이싿. 함수 이름이나 자료형, 변수 이름과 자료형 클래스 같은 것은 모두 구조다.
동작
- 전체 프로그램의 동작은 매우 이해하기 쉽다. 세무 프로그램은 ‘세금 정산’을 하고 계산기는 ‘계산을 한다’.
- 동작은 항상 일종의 동사다. 계산하다, 고치다, 더하다, 없애다 이런게 동작이다.
- 클래스 내부에서 동작은 메서드의 내부 코드를 의미한다.
결과
- 모든 프로그램, 함수, 코드는 어떤 영향을 미친다. 즉, 어떤 결과를 생산한다. 결과는 항상 과거시제로 이야기 할 수 있다. 세무 프로그램은 세금 신고서를 제출했다거나 납세 신고서를 작성했다 등의 결과를 낸다.
- 프로그램의 개별적인 부분에도 결과가 있다. 메서드나 함수를 호출하면 매우 명확한 결과가 나온다. 보통은 데이터를 반환하거나 수정한다.
- 프로그램이 생산하는 것이라면 모두 결과다.
- SAR은 거대한 앱부터 한 줄짜리 스크립트까지 어떤 프로그래밍에든 적용할 수 있는 개념이다. 코드를 작성할 때마다 깊게 생각해야하는 개념은 아니지만 프로그램을 분석하고 이해하는데 도움이 된다. 특히 설계 개선 방법을 고민할 때 큰 도움이 될 것이다.
[지식으로서의 소프트웨어]- 소프트웨어는 지식으로 만든 단단한 실체다. 이는 지식의 모든 규칙과 법칙을 따른다. 구체적인 형태를 지니고 있다는 사실만 제외하면 거의 모든 상황에서 지식과 똑같은 양상을 보인다.
- 나쁜 데이터는 사람의 나쁜 행동을 유발하고, 나쁜 코드는 컴퓨터의 나쁜 행동을 유발한다. 컴퓨터와 사람을 비교하려는게 아니라 소프트웨어와 지식을 비교할 수 있다는 뜻이다.
[기술의 목적]- 일반적으로 물질, 에너지, 시간이나 공간의 문제를 해결하고자 기술을 사용했을 때는 성공적인 결과를 냈다. 하지만 마음, 소통, 능력 등 인간의 문제를 해결하고자 했을 때는 실패하거나 위험한 역효과를 냈다.
- 소프트웨어의 목적이나 스타트업 아이디어의 성공 가능성을 미리 점칠 때 이 원칙 혹은 법칙을 유용하게 활용할 수 있다.
- 이 법칙은 기술의 발전이 선인지 악인지를 밝히는 데도 유용하다. 기술의 발전을 생각하면 때로 심경이 엇갈린다. 기술이란 본질적으로 선하거나 악한 것이 아니다. 하지만 인간의 문제를 해결하려고 할 때 악하게 작용하고, 물질 세계의 문제를 해결하려고 할 때 선하게 작용하는 경향이 있다.
- 기술은 우리를 더 나은 인간으로 만들지는 못하지만 우리가 사는 세상이 조금 더 나아지게 만들 수 있다.
[단순성과 보안]- 소프트웨어의 보안을 보장하는 가장 중요한 요소는 단순성이다.
- 소프트웨어를 안전하게 지키겠다고 소프트웨어 앞에 소규모 군대를 배치할 필요는 없다. 별도의 보호 장치가 필요 없도록 ‘입구’수를 줄이고, 그 입구를 간결하고 단순하게 만들어 부당하게 악용하지 못하게 하라.
[테스트 주도 개발과 관찰 주기]- 최근에 테스트를 먼저 작성한 뒤에 코드를 작성하는 개발 시스템 TDD의 특성과 작용에 관해 흥미로운 논의가 있었다. 결정을 내리기 전에 관찰부터 해야한다는 것이었다. 소프트웨어 수명 전반에 걸쳐 무언가 관찰해야한다. 이 원칙은 소프트웨어 개발 주기에 광범위하게 적용된다.
- 관찰 → 결정 → 실행 (이 주기의 반복)
- ODA 사례 : TDD를 쓸 때는 아래 주기를 따른다
- 문제를 본다 (관찰)
- 문제를 해결하기로 한다 (결정)
- 테스트를 작성한다 (실행)
- 테스트를 보고 API가 괜찮은지 확인한다 (관찰)
- 괜찮지 않다면 수정 방법을 정하고 (결정) 테스트를 수정한 후 (실행) API가 괜찮아 보일 때까지 관찰 → 결정 → 실행을 반복한다.
- API가 괜찮다면 테스트를 실행하고 통과하는지 본다 (관찰)
- 코드를 작성한다 (실행)
- 테스트를 실행하여 통과하는지 확인한다 (관찰)
- 통과하지 못하면 수정 방법을 정하고 (결정) 코드를 작성하고 (실행) 테스트를 통과하는지 확인한다 (관찰)
- 이런 방식으로 다음 작업을 이어간다.
[테스트 철학]- 기존의 과학적 방법은 우주를 테스트한 후 테스트 결과를 바탕으로 자신이 세운 가설을 정교하게 다듬는 순서로 진행된다. 어떻게 보면 소프트웨어 테스트는 이와 정반대로 진행된다.
- 소프트웨어 세계에서는 실험이 가설을 증명하지 못하면 테스트하고 있는 시스템을 수정한다
- 테스트 가치
- 테스트의 목적은 시스템에 대한 지식을 전달하는 것이고 각 지식은 다른 가치를 지닌다.
- 얻고자 하는 지식이 무엇인지 정확히 알아야 효과적이고 유용한 테스트를 만들 수 있다.
- 테스트 단언문
- 테스트는 무언가 알기 위해 하는 것이므로 반드시 무언가를 단언해야한다. 그리고 그 단언문은 참인지 거짓인지 확인되어야 한다.
- 테스트 주체가 인간이라면 매력적이다 처럼 정성적인 단언문으로 써도 된다. 단언문이 없으면 테스트가 아니다.
- 테스트 범위
- 실험 한번으로 물리학의 모든 이론과 법칙을 증명할 수 없듯이 복잡한 시스템의 동작 방식을 한 번에 증명하는 테스트를 설계한다는 건 불가능한 일이다.
- 그러므로 테스트를 설계할 때는 테스트 대상과 테스트에 속하지 안흔 부분을 정확히 구분해야 한다.
- 테스트 가정
- 모든 테스트에는 가정이 내재되어야 한다. 해당 테스트의 범위 안에서 유효한 결과를 내는 데 꼭 필요한 전제라고 보면 된다.
- 모든 테스트는 통과, 실패, 알 수 없음 이 세가지 중 적어도 한 가지 결론을 도출해야한다.
- 테스트 설계
- 앞서 살펴본 바와 같이 각 테스트에는 범위와 가정이 존재할 수밖에 없기 때문에 테스트 스위트를 설계해야 한다. 그래야 전체 테스트를 조합했을 대 원하는 지식을 빠짐없이 얻을 수 있다.
- E2E 테스트
- E2E 테스트는 시스템 로직을 관통하는 하나의 경로를 완료하는 방식으로 진행하는 테스트다. 전체 시스템을 동작시키고 사용자가 입력하는 시작 지점에서 몇 가지 동작을 실행한 후 시스템이 생산하는 결과를 확인하는 것이다.
- 이 테스트는 테스트가 많이 부족한 초기에 임시방편으로 쓰기 좋다. 전체 시스템을 조립한 후에 제대로 동작하는지 확인하는 용도로 써도 좋다. 하지만 장기적으로 볼 때 복잡한 시스템에 대해 충분한 지식을 얻을 수 있는 테스트 방식은 아니다.
- 통합 테스트
- 두 개 이상의 컴포넌트를 한 시스템에서 조립한 후에 어떻게 작동하는지 보는 것이 통합 테스트이다. 여기서 컴포넌트란 코드 모듈이 될 수도 있고 시스템이 의존하는 라이브러리 , 데이터를 제공하는 원격 서비스가 될 수도 있다.
- 통합 테스트에서는 컴포넌트의 분리를 중요시 한다.
- 통합 테스트만으로 시스템을 테스트 하는건 적절하지 않다. 컴포넌트의 인터렉션 만으로 전체 시스템을 분석하려면 시스템 작동 방식 전반에 대해 이해하기까지 엄청난 수의 인터랙션을 테스트해야 하기 때문이다.
- 단위 테스트
- 하나의 컴포넌트가 정상 작동하는지 확인하는 테스트가 단위 테스트다.
- 단위 테스트는 하나의 클래스, 모듈에 있는 한가지 함수의 한 가지 동작을 테스트한다. 컴포넌트의 내부 구현이 아니라 동작을 테스트 해야한다.
- 이론적으로는 시스템에 있는 모든 컴포넌트의 동작이 문서에 잘 정의되어 있으면 각 컴포넌트가 문서에 나온 대로 동작하는지 테스트하기만 해도 시스템 전체의 동작을 테스트한 셈이 된다.
- 당연한 말이지만 단위 테스트는 시스템 컴포넌트가 합리적으로 잘 분리 되어있고 각 컴포넌트의 동작을 완전히 정의할 수 있을 정도로 단순할 때 가장 큰 효과를 낸다.
반응형'개발 > Android' 카테고리의 다른 글
[Android | Kotlin] 프로그래스바 커스텀 하기 (0) 2023.06.06 [Android | Kotlin] Uri로 입력받은 이미지를 줄이는 방법 (0) 2023.06.04 심플 소프트웨어 : 엔지니어링 팀에서 일하기 (0) 2023.05.28 심플 소프트웨어 : 프로그래머를 위한 원칙 (1) 2023.05.27 [이펙티브 코틀린] 8장 효율적인 컬렉션 처리 (2) 2023.04.30 댓글