소프트웨어가 갖추어야 할 조건 DarkKaiser, 2007년 7월 1일2023년 8월 30일 대부분의 소프트웨어 디자인은 끔찍한 수준이다. 만일 소프트웨어를 다리에 비유한다면 워낙 위험해 아무도 건너지 않을 것이고, 집에 비유하자면 언제 무너질지 몰라 아무도 들어가려 하지 않을 것이다. 나 같은 소프트웨어 엔지니어들이 소프트웨어의 이런 치명적인 문제점들을 결코 모르는 바 아니다. 우리는 단지 이런 문제점들 때문에 비난 받는 것을 피하려고 소프트웨어 내부를 사람들에게 보여주지 않을 뿐이다. 만일 소프트웨어가 집이나 다리 같은 건축물처럼 내 외부가 모두 공개돼 버린다면 우리 엔지니어들은 창피함에 고개를 들 수도 없었을 것이다. 우리는 아무도 바닥이 푹푹 꺼지고, 천장엔 구멍이 있으며, 벽에는 못들이 튀어 나와 있는, 그러면서도 굉장한 고가의 ‘새 집’ 따위는 사려 들지 않을 것이다. (이 집이 기본 기능에 충실하다 하더라도.) 이런 집을 사려고 온 우리는 건축자의 다음과 같은 변명까지 들어줘야 할지 모른다. “저기, 못 보신 모양인데, 새집에는 항상 열려 있는 대문이 있어요. 그리고 부엌은 아주 쉽게 찾을 수 있는데 중간에 튀어 나온 못을 조심해야 합니다. 천장에 구멍 여러 개가 있는데 빗물은 거의 새지 않을 겁니다. 그리고 이 집은 원래 건축비 보다 한 3배 정도 비싼데 다른 집들도 다 마찬가지죠.” 다시 소프트웨어 이야기로 돌아가자. 대부분의 소프트웨어에는 중복되는 코드와 불필요한 성능 장애(주로 병목 현상), 고치기 힘든 버그, 수정이 불가능한 코드 등이 포함돼 있다. (이런 것들을 묘사하기 위해 집의 꺼지는 바닥, 구멍 난 천장, 튀어나온 못을 비유했다.) 불행히도 우리는 이런 수준의 소프트웨어를 그대로 구입해야만 하는 실정이다. 기업들은 매년 소프트웨어를 개발하기 위해 수십 억 달러를 쏟아 부으면서도 위험 천만한, 질 낮은 소프트웨어를 계속 양산하고 있다. 이 기사는 개발자, 엔지니어, 매니저 등 소프트웨어 관련 종사자와 소프트웨어 사용자들이 소프트웨어에 대해 생각하는 질적인 수준을 끌어 올리기 위한 목적이다. 우리는 사실 우리가 건축물에서 기대하는 수준의 안정성과 기능성을 소프트웨어에서도 기대할 수 있어야 한다. 그저 맡겨진 기본 기능만 수행하는 소프트웨어가 아니라 내부적으로도 탄탄하고 안전한 구조를 가진 ‘아름다운’ 소프트웨어를 생산해야 한다. ‘아름다운’ 소프트웨어는 더 싸고 빠르고 강력하며, 더 적은 수의 버그에, 수정이 쉽고 간편한, 그래서 더 오랜 수명을 지닌 프로그램을 말한다. 소프트웨어의 우수성과 저렴함은 결코 반비례 하지 않는다. 소프트웨어의 우수성이 높아진다고 가격까지 덩달아 높아져야 한다는 법은 없다. 같은 노력을 통해 우수하면서도 저렴한 소프트웨어는 얼마든지 만들어질 수 있다. 우수한 소프트웨어는 시간이 남아도는 한가한 프로그래머들에게만 주어지는 ‘사치’가 아닌 것이다. 그렇다면 우수한 소프트웨어란 어떤 프로그램을 말하는 걸까? 소프트웨어의 우수성은 몇 가지 기본 원칙에 의해 결정된다. 다음은 우수한 소프트웨어가 갖춰야 할 7가지 조건들이다. 환경 적응력 (Cooperation) 견고한 내부 디자인 (Appropriate form) 최소 시스템 요구 사항 (System minimality) 구성 요소의 단일화된 목적과 기능 (Component singularity) 구성 요소의 분류와 집합 (Functional locality) 보고 이해할 수 있는 코드 구성 (Readability) 간결성 (Simplicity) 이 조건들을 지금부터 하나하나 살펴보도록 하자. 환경 적응력 (Cooperation) 건축물이 주변에 지어지는 공간에는 고유의 환경 요소들이 있다. 지반의 경사, 그 지역의 기후, 일조량, 주변에 다른 역할을 하는 건물들, 이 모든 것들이 건축물을 둘러싼 환경 요소들이다. 건축물은 반드시 이런 환경 요소에 맞춰져 지어져야 한다. 건축물이 주변 환경과 조화를 이루지 못한다면, 건축물은 오래가지 못하고 무너져 내리거나 사람들로부터 버림 받을 것이다. 소프트웨어에도 각각 고유의 환경 요소들이 있다. 바로 컴퓨터 하드웨어, 운영 체계(OS), 데이터베이스와 보안 시스템과 같은 미들웨어(middleware), 컴퓨터에 설치된 다른 기능의 애플리케이션, 그리고 사용자 특성 등이 소프트웨어의 환경 요소들이다. 우수한 소프트웨어가 제작되기 위해선 먼저 이런 ‘주변 환경’에 어긋나지 않도록 세심한 배려를 해야 한다. 다음은 소프트웨어 제작에 영향을 끼치는 환경 요소들의 실례다. 주머니 크기의 전자 수첩에 들어갈 소프트웨어. 전자 수첩에는 손바닥 절반 크기의 흑백 스크린이 달려 있다. 전자 수첩 소프트웨어는 이 조그만 흑백 스크린 안에 모든 정보를 알아보기 쉽게 출력해야 한다. 자동 소득세 신고를 위한 소프트웨어. 요즘 직장인들은 대부분 인터넷 접속이 가능하다. 따라서 이 소프트웨어는 사용자가 지불하는 소득세를 자동으로 파일로 저장해 인터넷으로 보고할 수 있는 기능이 있어야 한다. 초등학교 1학년 학생들을 위한 독서 능력 향상 소프트웨어. 초등학교 1학년이 사용하는 컴퓨터는 대부분 구식이다. 이들 컴퓨터는 모두 속도가 뒤쳐지거나 용량이 크게 떨어진다. 독서 능력 향상 소프트웨어는 이런 컴퓨터에서도 아무런 성능 저하 없이 돌아갈 수 있도록, 초등학교 1학년 학생들이 사용하는데 아무 불편이 없도록 만들어 져야 한다. 소프트웨어 환경에 대한 예는 무수히 많다. 내가 사용하고 있는 거대 규모의 문서 관리 시스템 역시 특정 목적과 환경에 맞도록 설계된 대표적인 소프트웨어다. 이 소프트웨어의 기본 기능은 물론 문서의 저장과 출력이다. 그러나 이 소프트웨어가 최상의 성능을 발휘하고 사용자의 만족도를 높이기 위해선 ‘환경 적응력’이 필요하다. 내 컴퓨터 하드 디스크에 깔린 운영 체계와 용량, 애플리케이션들을 미리 고려해 최상을 성능을 발휘하도록 제작돼야 하는 것이다. 주변 환경과의 조화는 특히 기업 환경에서 돌아가는 소프트웨어들이 필수적으로 갖춰야 할 조건이다. 훌륭한 건축물이 주변 환경과 최상의 조화를 이루어 오랜 세월 그 자리를 지킬 수 있듯이, 소프트웨어 역시 주변의 사용 환경에 얼마나 잘 적응하느냐에 따라 그 수명이 결정되기 마련이다. 최소 시스템 요구 사항 (System minimality) 전기 배선과 수돗물 공급이 완성된 구역에 지어진 집을 생각해 보자. 이 집 주인은 난데없이 자신이 직접 물과 전기를 ‘자급’한다며 땅에 우물을 파고 집 안에 발전기를 만들려고 한다. 사람들이 왜 이런 짓을 하느냐고 묻자 집 주인은, “집 안에 우물이 있는 게 마음에 들어서요. 그리고 전 이 지역에 전기가 들어오는지 몰랐어요”라고 대답한다. 집 주인의 무지 덕분에 이 집을 짓는 데는 훨씬 더 많은 시간과 돈이 들 수 밖에 없는 셈. 물론 필요하기만 하다면 집 안에 우물이나 발전기를 들여놓는 것은 결코 나쁜 일이 아니다. 그러나 그저, ‘우물이 있으면 좋을 것 같아서’ 혹은 ‘전기가 들어오는지 몰라서’ 이렇게 엄청난 낭비를 했다면 이 집은 결코 잘 지어진 집이라고 볼 수가 없다. 좋은 건축물은 주변의 자원(상수도, 전력, 햇빛 등)을 최대한 활용할 수 있어야 한다. 주변의 자원을 이용해 불필요한 기능과 에너지 낭비를 최대한 줄이고 공간 활용률을 높일 수 있는 건물이 좋은 건물이다. 좋은 소프트웨어 역시 마찬가지다. 소프트웨어는 설계 당시부터 기존의 컴퓨팅 자원을 십분 활용할 수 있도록, 그래서 최소한의 크기만 유지할 수 있도록 제작돼야 한다. 소프트웨어 제작 전에 소프트웨어가 설치될 컴퓨팅 시스템을 파악하는 일은 모든 소프트웨어 제작자와 기술자들의 당연한 책임이다. 소프트웨어를 둘러싼 자원 환경을 이해하고 그리고 그 자원을 최대한 활용할 때 소프트웨어는 더욱 간결하고 높은 성능을 발휘할 수 있기 때문이다. 소프트웨어에는 오직 필요한 것만 포함돼야 한다. 그 이상을 포함하는 것은 절대 금물이다. 지키기 어려워 보이는 원칙은 아니지만 이를 제대로 지키는 소프트웨어 엔지니어들은 그리 많지 않다. 실제로 나 자신 역시 몇 년 전, 이 원칙이 위배되는 일을 저지른 적이 있었다. 당시 우리는 디지털(Digital)의 VAX 미니컴퓨터에 금융 정보 시스템을 구축하는 프로젝트를 맡았다. 우리는 소프트웨어를 제작할 때 VAX라는 시스템의 기능을 확인하지 않은 채 모든 기능이 우리 소프트웨어에 포함될 수 있도록 코드를 짰다. 우리는 소프트웨어 자체에 소팅 기능과 스크린 입/출력 패키지, 소스 코드 컨트롤, 그리고 자동화 빌드 툴까지 만들었다. 하지만 나중에 알고 보니 이 모든 기능은 VAX 시스템에 내장돼 있던 것들이었다. 심지어는 우리가 작성한 런-타임 버그 제거기까지. VAX은 더 강력한 성능의 버그 제거기가 있었다. 우리가 소프트웨어에 이런 불필요한 기능들을 덧붙인 것은 순전히 우리의 무식함과 게으름 때문이었다. 우리는 소프트웨어가 설치될 시스템 환경을 이해하지 못했기 때문에, 결과적으로 소프트웨어는 당초 필요했던 것보다 훨씬 무겁고, 느린데다, 몇 배 더 많은 제작 비용과 시간이 낭비되고 말았다. 견고한 내부 디자인 (Appropriate form) 소프트웨어의 내부 디자인은 소프트웨어의 외부 기능을, 지도나 거울처럼, 그대로 반영하고 있어야 한다. 이는 잘 지어진 건물과 마찬가지다. 잘 지어진 건물은 내부와 외부가 조화롭게 건설돼 서로의 기능을 보완, 지지해 주고 있다. 이와 마찬가지로 잘 짜여진 소프트웨어라면 내부의 디자인이 외부의 기능을 완벽히 받쳐줄 수 있어야 한다. 하지만 소프트웨어가 원래 기능만 제대로 발휘한다면 내부 디자인을 따로 문제 삼는 것이 필요하긴 할까? 분명 필요하다. 외부의 기능을 내부에서 명확히 정의하는 것은 우수한 소프트웨어를 만드는데 핵심 요소다. 소프트웨어 내부 디자인을 소프트웨어 폼(form)이라고 부르는데 이 폼이 소프트웨어의 외부 기능에 따라 명확히 작성될 때 소프트웨어는 전체적으로 더욱 간결해 질 수 있다. 외부적인 기능은 원래 소프트웨어 디자인에 ‘덧붙여지는’ 것이 아니라 내부 구조에 깊숙이 ‘연계돼’ 있기 때문이다. 소프트웨어의 폼이 외부적인 기능과 분명히 연계돼 있지 않다면, 버그 투성이에 확장이나 수정이 지극히 어려운 엉터리 소프트웨어가 나올 수 밖에 없다. 물론 이 경우 소프트웨어 성능 저하는 물론, 버그를 제거하는 일도 힘들어진다. 우리는 소프트웨어의 내부를 들여다 보거나 만져볼 수 없기 때문에 소프트웨어 폼이 외부 기능을 거울처럼 잘 반영하고 있는지 확인하기 어렵다. 그러나 모든 소프트웨어에는 일정한 폼과 기능이 있고 우리는 이를 통해 제대로 된 내부 디자인을 유추해 볼 수 있다. 기업의 회계 소프트웨어 시스템을 생각해 보자. 회계 소프트웨어는 구매, 지불, 청구, 장부 정리 등 몇 가지 명확한 기능들을 수행한다. 대부분의 경우, 이들 각각의 기능들은 서로 떨어져 작동한다. 그러나 가끔씩은 각 기능들 사이에 겹치는 부분이 발생하기도 한다. 비즈니스 회계 소프트웨어는 이 각각의 기능들을 내부에서 그대로 ‘비춰’낼 수 있어야 한다. 즉, 소프트웨어의 어느 부분이 구매를 담당할 것인지, 어느 부분이 지불을 담당할 것인지 명확히 정의돼야 하는 것이다. 그리고 각 기능들에 겹치는 부분이 생길 경우 소프트웨어 폼에서도 그 겹치는 부분을 그대로 반영하는 영역이 있어야 한다. 만일 소프트웨어의 내부의 영역과 구획이 명확히 정의돼 있지 않다면 기능 하나(가령, 청구 기능)를 변경하기 위해선 다른 별다른 연관이 없는 기능들(구매, 지불, 장부 기능)까지 모두 변경해야 하는 불편함이 따른다. 만일 소프트웨어 내부 영역이 명확히 정의돼 있다면 기능 하나를 수정하는데 훨씬 적은 노력이 들어갈 뿐만 아니라, 두 개 이상의 기능이 겹치는 부분을 변경하는 것도 훨씬 편리해 진다. 소프트웨어 내부 디자인이 외부 기능을 ‘매핑’할 수 있어야 한다는 것은 곧, 좋은 프로그래밍 기술에는 ‘정도’가 없다는 것을 의미한다. 오랜 세월 동안 프로그래머들은 글로벌 변수와 GOTO 문장을 쓰는 것이 안 좋은 프로그래밍 습관이라고 배워왔다. 하지만 이런 프로그래밍 방식은 외부의 기능을 내부에서 반영하는데 훌륭한 역할을 할 때가 있다. 그럴 때는 금기시 되던 글로벌 변수나 GOTO 형식도 무리 없이 사용할 수 있다. 프로그래밍에서 무조건 어떤 형식은 안 된다고 주장하는 것은 어리석다. 이는 마치 건물을 지을 때, “소나무는 절대 사용하지 말고 항상 티크 목재만 사용해라”라고 하는 말하는 것과 같다. 물론 티크는 최상의 건축재이긴 하다. 하지만 가끔씩은 소나무도 건물을 짓는데 꼭 필요한 자재가 될 수 있다. 프로그래밍에서도 마찬가지다. “안 된다”라는 규정을 만들기 전에, ‘이 디자인이 외부의 기능과 정확히 결합이 되는가’를 먼저 확인해야 우수한 소프트웨어를 만들 수 있다. 구성 요소의 단일화된 목적과 기능 (Component singularity) 좋은 건축물은 대체로 하나의 방에 한 가지 기능만 부여해 그 방의 기능성을 최대화 한다. 예를 들어 대부분의 집에는 하나의 안방 침실이 있어 그 침실 안에 필요한 모든 기능을 제공한다. 만일 건축자가 제대로 된 안방 침실 하나를 만들 수 없어서, 한 집안에 4개의 안방 침실을 만들었다면, 이는 형편없는 건축 디자인이라고 볼 수 밖에 없다. 만일 건축자가 자신이 이미 안방 침실을 하나 만들었다는 사실을 잊어버렸거나, 두 번째, 세 번째 만든 안방 침실까지 잊어 버려 안방 침실을 4개나 만들었다면 이는 건축 사고라고 봐야 할 것이다. 물론 건축물의 규모가 클 경우엔 같은 기능을 갖는 실내가 두개 이상 필요할 때가 있다. 예를 들어 5000명이 넘는 직원을 보유하고 있는 빌딩엔 식당이 최소 두개 이상 필요할 것이다. 하지만 식당을 필요한 수 이상 짓는 것은 명백한 잘못이다. 마찬가지로, 좋은 소프트웨어는 각 기능에 맞는 단일화 된 요소만 갖춰야 한다. 하나의 기능을 담당하는 최소한의 요소를 갖추지 못하고 자꾸 중복되는 요소를 만드는 것은 소프트웨어 전체 성능에 심각한 악영향을 끼친다. 예를 들어 컴퓨터 시스템에 하나의 프린터를 연결하기 위해 세 개의 드라이버가 존재한다고 가정해 보자. 만일 그 프린터에 조그만 변화만 생겨도 사용자는 세 개의 드라이버를 모두 수정해 줘야 하는 불편함을 겪어야 한다. 이런 지극히 비효율적인 폐해에도 불구하고 대부분의 소프트웨어에는 수많은 불필요한, 중복된 코드가 존재한다. 소프트웨어에 이렇게 중복된 코드가 존재하는 것은 대개 프로그래머들이 이전 개발자가 소프트웨어에 무슨 코드를 덧붙였는지, 어떤 코드를 만들어 기존의 문제를 해결했는지 몰랐거나 잊어 버렸기 때문이다. (건축가가 건물에 이미 안방 침실이 있다는 사실을 잊어버린 것과 같은 경우라 하겠다.) 구성 요소의 분류와 집합 (Functional locality) 훌륭하게 설계된 집은 서로 비슷한 기능을 갖는 시설과 아이템을 같은 곳에 위치시킨다. 음식을 준비하기 위한 주방 용품이나 요리, 설거지 시설 등은 모두 하나의 공간에 마련돼 있다. 수도 배관, 전기, 난방 시설은 모두 건물의 지하에 위치하고 있으며, 옷가지는 하나의 장에 정리되곤 한다. 하지만, 집이 반드시 이렇게 각 기능별로 분류돼 지어져야 한다는 규정은 없다. 싱크대는 다락방에, 전기 오븐은 거실에, 그리고 냉장고는 침실에 설치된다 해도 ‘규정’에 어긋나는 것은 아니다. 그러나 이렇게 지어진 집은 엉터리로 디자인 된 것임에 틀림없다. 잘 설계된 집은 (혹은 그냥 일반적으로 설계된 집이라도) 서로 갖는 기능을 갖는 시설과 아이템을 같은 자리에 위치시킨다는 원칙을 지킨다. 이는 소프트웨어도 마찬가지다. 서로 관계되는 아이템을 한 자리에 놓아야 개발자들은 소프트웨어의 전체적인 구조와 최초 제작자의 의도를 쉽게 파악할 수 있다. 이렇게 소프트웨어의 각 요소의 위치를 잘 정리해 놓으면 버그를 고치거나 수정, 확장을 할 때 매우 편리해 진다. 적절한 코드가 가장 예상하기 쉬운 자리에 위치해 있으므로 소프트웨어의 각 부분을 교체하기 편해지기 때문이다. 예를 들어, 운영체계 소프트웨어에서는 오디오 효과와 같은 낮은 단계의 코드들을 한 자리에 모아 놓는다. 그리고 파일 시스템과 같은 높은 단계의 코드들 안에서도 역시 오디오 효과를 위한 코드들은 모두 한 자리에 모여 있어야 한다. 보고 이해할 수 있는 코드 구성 (Readability) 두 개의 서로 다른 소프트웨어가 완전히 똑 같은 기능에, 똑 같은 방식으로 작동하는 것은 얼마든지 가능한 일이다. ‘서로 다르면서도 같은’ 이런 소프트웨어들은 기술적인 시각으로 볼 때 똑 같은 내부 디자인과 구조를 갖고 있으면서도 사람이 직접 읽을 때는 서로 엄청나게 달라 보인다. 다음 두 가지 예제 코드를 살펴보자. Code Fragment A Const MIN_AGE = 0 Const MAX_AGE = 120 Const RETIREMENT_AGE = 65 Dim AgeString As String Dim AgeNumber As Integer, YearsToRetirement As Integer EnterAge: AgeString = Inputbox$("Please enter your age.", "Age?", "") AgeNumber = Cint(AgeString) If AgeNumber < MIN_AGE Or AgeNumber > MAX_AGE Then Msgbox "Are you sure you entered the right age? It should be between " _ & MIN_AGE & " and " & MAX_AGE & "." Goto EnterAge End If If AgeNumber < RETIREMENT_AGE Then YearsToRetirement = RETIREMENT_AGE - AgeNumber Else YearsToRetirement = 0 End If Code Fragment B Const xyz=0 Dim x As String,A2 As Integer,Y As Integer Const m =120 Const A=65 L47: x=Inputbox$("Please enter your age.", "Age?", "") A2=Cint(x) If A2m Then Msgbox "Are you sure you entered the right age? It should be between " _ & xyz & " and " & m & "." Goto L47 End If If A2 Y= A-A2 Else Y=0 End If 위 두 가지 코드 조각들을 분석해 보면 기능적으로 완전 똑같다는 사실을 알 수 있다. 또한 우수 소프트웨어를 결정하는 요소들로 따져 봐도 이 두 가지 코드 중 어느 한쪽이 질적으로 우수하다, 열등하다 보기도 어렵다. 하지만 후에 사람들이 이 소프트웨어 코드를 관리, 또는 확장한다고 가정한다면, 첫번째 코드 조각이 두 번째 것보다 훨씬 우수하다고 말할 수 밖에 없다. 소프트웨어를 제대로 관리하기 위해선 사람이 읽을 수 있어야 한다. 사람이 읽기 어려운 코드는 수정하기도, 확장하기도, 그리고 버그를 잡기도 어렵다. (아예 불가능할 때도 많다.) 소프트웨어를 ‘읽을 수 있다’라는 말에는 두 가지 뜻을 내포하고 있다. 바로 코드 구성의 명확성과 코드에 첨부된 주석과 설명이 있다는 것을 말한다. 코드 구성의 명확성은 변수와 상수에 적절한 이름을 부여하는 것, 띄어쓰기와 들여쓰기를 유효 적절히 사용하는 것, 그리고 투명한 컨트롤 구조, 명확한 실행 경로를 포함한다. 반면, 코드에 첨부되는 주석은 코드에 자체적으로 부가되는 요소는 아니다. 다만 이 소프트웨어를 다음에 개발하거나 관리할 프로그래머가 코드를 쉽게 이해할 수 있도록 원작자가 코드 옆에 설명을 써 넣는 것을 말한다. 가령, 각 모듈이 작성된 ‘의도’ 같은 것을 설명해 주는 것이다. 물론 소프트웨어의 가독성은 소프트웨어의 실제적인 성능과는 별다른 연관이 없다. 하지만 소프트웨어의 전체적인 우수성을 판단하는데는 결정적인 역할을 한다. 다른 소프트웨어 개발자가 처음 개발된 소프트웨어의 소스 코드를 이해할 수 없다면, 이 소프트웨어는 여기에 언급된 그 어떤 우수 조건도 포함하지 못한다. 예를 들어, 어느 소스 파일이 중복되는 코드 하나 없는 완벽한 간결함을 자랑한다고 가정해 보자. 그러나 이 소스 파일을 통해 사람이 어떤 소스 코드가 어떤 기능과 연결돼 있는지 확인할 수가 없다면, 이 소프트웨어는 나중에 확장이나 수정이 불가능해지고 결국 그냥 그 상태에서 생명을 다하고 만다. 간결성 (Simplicity) 지금까지 열거된 우수 소프트웨어의 모든 조건 중에서 가장 중요한, 그리고 가장 종합적인 요소가 바로 이 간결성이다. 우수한 소프트웨어는 작동하거나 문제를 해결할 때 항상 가장 간단하게 움직이도록 설계돼야 한다. 간결한 소프트웨어는 더 적은 버그와 (더 적은 코드 라인을 갖고 있으니 버그가 더 적을 수 밖에 없다), 더 빠른 동작 속도 (더 적은 기계 명령어를 포함하기 때문), 더 작은 용량 (간결한 소프트웨어는 컴파일 된 코드도 더 적다), 그리고 무엇보다 고장이 났을 때 고치기도 훨씬 쉽다. 특히 제작에서부터 관리, 수정 모든 과정이 수월하다는 점은 간결한 소프트웨어가 갖는 최대 장점이다. 소프트웨어의 간결성은 개발자의 프로그래밍 능력을 측정하는 가장 좋은 평가 기준이 된다. 초보 프로그래머는 간단한 문제를 해결하는 간단한 솔루션을 개발한다. 중급 혹은 상급 프로그래머는 복잡한 문제를 해결하는 복잡한 솔루션을 개발한다. 그리고 위대한 프로그래머는 복잡한 문제를 해결하는 간단한 솔루션을 개발한다. 최고 정상급의 프로그래머가 작성한 코드는 일단 완성되면 읽기도 쉽고 작동 원리도 무척 간단해 보인다. 그러나 이런 코드를 작성하는 것은 상상하기 어려울 정도로 어렵다. 매우 복잡 다단해 보이는 현상에서 간결성과 질서를 찾는 것이 과학의 목표인 것처럼, 복잡한 문제를 해결할 수 있는 가장 간결한 방법을 찾는 것은 프로그래밍의 최대 목적이다. 중요한 것은 원리 원칙이 아니다 기억해야 할 것은 우수 소프트웨어가 반드시 원리 원칙에 의해 완성되는 것은 아니라는 점이다. 우수한 소프트웨어를 만들기 위해서 앞서 열거된 7가지 조건이 모두 엄격하게 적용돼야 하는 것은 아니다. 물론 각각의 7가지 조건들은 모두 중요하다. 그러나 건축가가 다른 곳에서 배워두었던 건축 설계의 원리 원칙을 항상 같은 방식으로 적용할 수 없듯이, 소프트웨어 개발자들도 자신이 알고 있는 프로그래밍 기술과 원칙을 적용하는 것만으로는 결코 우수한 소프트웨어를 만들 수가 없다. 소프트웨어는 결코 부분부분 연결해 붙여지는 것이 아니다. 마치 유기체처럼 전체적으로 살아 숨쉬는 소프트웨어가 되기 위해선 기술이나 원칙 이외에 개발자의 깊은 통찰력이 요구된다. 소프트웨어가 사용자의 목적을 더욱 잘 수행하고, 더 빠르게 작동하며, 더 안정적이고, 유지 관리 비용이 덜 들어야 하는 것은 당연하다. 그러나 그 동안 우리는 잘못 설계된, 전혀 만족할 만한 성능을 제공치 못하는 소프트웨어를 당연한 듯이 받아들여 왔다. 이제는 사용자들이 소프트웨어에 대한 눈높이를 높여야 한다. 사용자가 자신들의 요구 수준을 높이는 것이 소프트웨어의 우수성은 향상시키는 가장 중요한 원동력이 되기 때문이다. 프로그래밍 갤러리