머리말
프로그래머의 프로그래밍 실력은 경험이 쌓이면서 점차 향상됩니다. 프로그래밍 능력은 몇 가지 수준으로 나눌 수 있다고 생각합니다.
다음으로 프로그래밍 능력 계층 모델을 2차원으로 살펴보겠습니다.
한 차원은 프로그래밍 기술 수준이고, 다른 차원은 도메인 지식 수준입니다.
프로그래밍 기술 수준
프로그래밍 기술 수준은 프로그래머가 프로그램을 설계하고 작성하는 능력을 말합니다. 이것이 프로그래머의 기본입니다.
단락 0 - 프로그래머가 아닌 사람:
프로그래밍 초보자는 문제에 직면하면 완전히 혼란스러워하며 문제를 해결하기 위해 프로그래밍하는 방법을 모릅니다. 즉, 당신은 아직 일반인이고 '프로그래머'라고 불릴 수 없습니다. 그의 앞에는 여전히 컴퓨터가 신비한 블랙박스였다.
1단계 - 기초 프로그래머:
일정 시간 동안 프로그래밍을 배운 후, 작업을 받았을 때 작업을 완료하는 프로그램을 작성할 수 있습니다.
작성된 코드는 일반적인 상황에서는 작동할 수 있지만 실제 작업에서는 특별한 조건에 직면할 때 다양한 버그가 나타납니다. 즉, 데모 소프트웨어를 개발할 능력이 있는데, 개발한 소프트웨어가 실제로 고객에게 전달되어 사용하게 된다면 고객으로부터 혼날 수도 있습니다.
프로그래머가 프로그램을 작성했지만 왜 때로는 제대로 작동하고 때로는 작동하지 않는지는 프로그래머 자신도 모릅니다.
작업 중 버그가 발생하거나 요구 사항이 변경되면 코드를 수정하거나 추가해야 합니다. 곧 프로그램 구조가 혼란스러워지고 코드가 부풀어 오르며 버그가 많습니다. 곧 원래 개발자들조차 프로그램 유지 관리를 맡는 것을 꺼려했습니다.
단락 2 - 데이터 구조:
일정 기간의 프로그래밍 연습을 마친 후 프로그래머는 "데이터 구조 + 알고리즘 = 프로그램"이라는 고대 속담의 의미를 깨닫게 됩니다. 그들은 문제를 해결하기 위해 알고리즘을 사용합니다. 게다가, 그들은 알고리즘이 본질적으로 데이터 구조에 의존한다는 것을 깨닫게 될 것입니다. 좋은 데이터 구조가 설계되면 좋은 알고리즘이 나타날 것입니다.
데이터 구조를 잘못 설계하면 좋은 알고리즘을 개발할 수 없습니다.
한 외국 현자가 "당신의 데이터 구조를 보여주세요!"라고 말한 것을 기억합니다.
단락 3 - 객체 지향:
그 후에는 프로그래머가 감사할 것입니다. 객체지향 프로그래밍의 힘. 대부분의 최신 프로그래밍 언어는 객체 지향 프로그래밍을 지원합니다. 그러나 이는 객체지향 프로그래밍 언어를 사용하여 프로그래밍하거나 클래스를 사용하거나 심지어 클래스를 상속받는 경우 객체지향 코드를 작성한다는 의미는 아닙니다.
저는 Java, Python, Ruby로 작성된 프로세스 지향 코드를 많이 보았습니다.
인터페이스, 다형성, 클래스, 객체, 객체 간의 관계를 마스터해야만 객체지향 프로그래밍 기술을 진정으로 마스터할 수 있습니다.
객체지향 프로그래밍을 지원하지 않는 전통적인 프로그래밍 언어를 사용하더라도 마음속에 "객체"만 있으면 객체지향 프로그램을 개발할 수 있습니다.
예를 들어 저는 C 언어로 프로그래밍할 때 의식적으로 객체 지향 기술을 사용하여 프로그램을 작성하고 설계합니다. 클래스를 시뮬레이션하려면 구조체를 사용하고, 클래스를 시뮬레이션하려면 동일한 유형의 개념을 가진 함수를 함께 배치하세요. 객체 지향 코드를 C 언어로 작성할 수 있는지 의심된다면 Linux 커널을 살펴보세요. C 언어로 작성되었지만 소스 코드 라인에서 강력한 "객체"가 나오는 것을 볼 수도 있습니다. .맛.
객체지향 프로그래밍 기술을 제대로 익히는 것은 쉽지 않습니다.
기술직 생활을 하면서 가장 골치 아픈 두 가지 장애물이 있습니다.
한 가지 장애물은 Dos에서 Windows 개발로 전환하는 동안 오랫동안 프레임워크의 개념을 이해하지 못했다는 것입니다. Dos 시대에는 모든 것이 함수 라이브러리에 대한 호출이며 프로그램은 적극적으로 함수를 호출합니다. Windows 시대에는 프레임워크로 대체되었습니다. 심지어 메인 프로그램도 실제로 프레임워크에 의해 호출됩니다. UI 스레드는 운영 체제로부터 메시지를 받아 처리를 위해 프로그램으로 보냅니다. Java 프로그래머에게 친숙한 Spring 프레임워크도 이러한 역방향 호출 프레임워크입니다.
요즘에는 "프레임워크"라는 용어가 매우 고상해 보이기 때문에 많은 "클래스 라이브러리"/"함수 라이브러리"를 "프레임워크"라고 부릅니다. 제 생각에는 이것은 모두 이름의 오용입니다.
"클래스 라이브러리"/"함수 라이브러리"는 제가 호출하기 위해 작성한 코드를 말합니다.
"프레임워크"란 내가 프레임워크에 콜백 함수를 등록하고, 내가 작성한 함수를 프레임워크가 호출한다는 뜻입니다.
또 다른 장애물은 객체 지향입니다. 오랫동안 저는 클래스 간의 관계를 어떻게 디자인해야 하는지 몰랐고, 클래스 계층 구조도 잘 디자인하지 못했습니다.
당시 외국 전문가의 책을 읽었던 기억이 납니다. 그는 매우 간단하고 실용적인 객체지향 설계 기법에 대해 이렇게 말했습니다. "문제를 말하고, 명사를 찾아 클래스를 구성하세요. . 동사를 찾아 클래스 메소드를 구축하는 데 사용하세요." 이 기술은 매우 효과적이지만 너무 풀뿌리적이고 이론적 근거가 없으며 엄격하지 않습니다. 문제가 제대로 기술되지 않으면 결과적으로 나타나는 수업 시스템에 문제가 생길 수 있습니다.
객체지향적 사고를 익히는 방법은 여러 가지가 있을 것입니다. 객체지향 디자인 사고를 이해하고 익히기 위해 관계형 데이터베이스에서 영감을 얻었습니다.
제 생각에는 관계형 데이터베이스 테이블은 실제로는 클래스이고, 레코드의 각 행은 클래스의 인스턴스, 즉 객체입니다. 테이블 간의 관계는 클래스 간의 관계입니다. O-Rmapping 기술(예: Hibernate)은 객체 지향 코드에서 데이터베이스 테이블로 매핑하는 데 사용되며, 이는 또한 클래스와 테이블이 실제로 논리적으로 동일하다는 것을 보여줍니다.
데이터베이스 디자인과 클래스 디자인은 동일하므로 객체지향 시스템을 디자인하려면 관계형 데이터베이스의 디자인 기술만 활용하면 됩니다.
관계형 데이터베이스 테이블 구조의 디자인은 매우 간단합니다.
1. 테이블 간의 관계, 즉 클래스 간의 관계를 식별합니다. 일대일인지, 일대다인지, 다대일인지, 다대다인지. 이것이 클래스 간의 관계입니다.
2. 테이블의 필드를 식별합니다. 물론 객체에는 수많은 속성이 있습니다(예: 사람: 키, 몸무게, 성별, 나이, 이름, ID 번호, 운전 면허증 번호, 은행 카드 번호, 여권 번호, 홍콩 및 마카오 여권 번호, 고용 번호, 의료 번호) 역사, 결혼 역사 등), 기록할 프로그램을 작성하기 위해 필요한 것은 우리가 관심을 갖는 속성들뿐입니다. 이러한 관심 속성은 테이블의 필드, 즉 클래스의 속성입니다. "약한 물 삼천, 한 국자 가져다가 마시리라!"
4문단 - 디자인 패턴:
언젠가 인터넷에서 이런 문장을 본 적이 있습니다. "10만 줄의 코드가 없으면 나에게 디자인 패턴에 대해 이야기하지 마세요." 나는 깊이 동의합니다.
Gof의 디자인 패턴에 관한 책을 처음 읽었을 때, 이전에는 디자인 패턴에 대해 몰랐지만 실제로 실제 프로그래밍 과정에서 일부 디자인 패턴을 의식적으로 사용했다는 것을 알게 된 기억이 납니다. 디자인 패턴은 프로그래밍의 객관적인 법칙입니다. 이는 누구도 발명한 것이 아니라 일부 초기 수석 프로그래머에 의해 처음 발견되었습니다.
디자인 패턴을 사용하지 않고도 요구 사항에 맞는 프로그램을 작성할 수 있습니다. 그러나 후속 요구 사항이 변경되면 프로그램은 충분히 유연하지 못하고 지속 가능하지 않게 됩니다. 실제 프로그램이 고객에게 전달된 후에는 확실히 추가 수요 피드백이 있을 것입니다. 후속 버전의 개발은 확실히 수요를 증가시킬 것입니다. 이는 프로그래머라면 피할 수 없는 현실이다.
웹, 데스크톱, 모바일, 게임 등 UI 프로그램을 작성할 때는 MVC 디자인 패턴을 사용해야 합니다. 그렇지 않으면 이후 UI 요구 사항이 변경될 때 프로그램을 지속할 수 없게 됩니다.
디자인 패턴에서 가장 중요한 아이디어는 디커플링, 인터페이스를 통한 디커플링입니다. 이러한 방식으로 향후 요구사항이 변경되면 새로운 구현 클래스만 제공하면 됩니다.
주요 디자인 패턴은 실제로 객체 지향적입니다. 따라서 디자인 패턴은 객체지향의 한 단계 발전된 단계라고 볼 수 있다. 디자인 패턴을 마스터해야만 객체지향 디자인 기술을 진정으로 철저하게 마스터했다고 볼 수 있습니다.
저는 새로운 언어(함수형 프로그래밍 언어 등 객체지향이 아닌 언어 포함)를 배울 때 항상 해당 언어의 구문을 이해한 후 이 언어에서 어떻게 작동하는지 살펴봅니다. 이는 프로그래밍 언어 학습을 위한 팁이기도 합니다.
5문단--언어 전문가:
일정 기간의 프로그래밍 연습을 거친 후 프로그래머는 공통 프로그래밍 언어에 상당히 능숙해졌습니다. 어떤 사람들은 "언어 변호사"가 되어 다른 프로그래머에게 언어 사용법과 다양한 함정을 잘 설명하기도 합니다.
이 단계의 프로그래머는 자신이 사용하는 언어를 진심으로 믿는 경우가 많습니다. 커뮤니티나 포럼에서 다른 언어 사용자와 어떤 언어가 최고의 프로그래밍 언어인지 논쟁을 벌이는 경우가 많습니다. 그들은 자신이 사용하는 언어가 세계 최고의 프로그래밍 언어라고 생각합니다. 그들은 자신들이 사용하는 프로그래밍 언어가 모든 시나리오에 적합하다고 믿습니다. 그들은 망치만 보기 때문에 모든 일을 못으로 취급합니다.
6항 - 다국어 전문가:
이 단계의 프로그래머는 업무 관계로 인해 또는 순전히 기술에 대한 관심으로 인해 여러 프로그래밍 언어를 배우고 마스터했습니다. 다양한 프로그래밍 언어의 다양한 디자인 아이디어를 경험했으며 각 언어의 장단점을 더 잘 이해하게 되었습니다.
이제 그들은 프로그래밍 언어가 가장 중요한 것이 아니라 프로그래밍 언어가 단지 기본 기술일 뿐이라고 믿습니다.
이제 그들은 다양한 작업 요구 사항이나 다양한 리소스에 따라 문제를 해결하기 위해 다양한 프로그래밍 언어를 선택하게 되며 개발을 위해 선호하는 특정 프로그래밍 언어를 사용하지 않는다고 더 이상 불평하지 않게 됩니다.
프로그래밍 언어에 대한 많은 학파와 아이디어가 있으며 일부 프로그래밍 언어는 여러 프로그래밍 패러다임을 동시에 지원합니다.
정적 유형 프로그래밍 패러다임
정적 유형 프로그래밍 패러다임을 채택한 프로그래밍 언어에서는 해당 변수를 명시적으로 유형화해야 합니다. 대표 언어: C, C++, Pascal, Objective-C, Java, C#, VB.NET, Swift, Golang.
이렇게 하면 다음과 같은 이점이 있습니다.
1. 컴파일러는 컴파일 타임에 유형 오류를 찾을 수 있습니다.
2. 컴파일러는 컴파일 시 타입 정보를 알면 성능을 향상시킬 수 있습니다.
이 패러다임은 프로그래머가 변수 유형을 알아야 한다고 믿습니다. 변수 유형을 모른다면 당황하지 마세요! 컴파일할 때 프로그램은 오류를 보고합니다.
Swift와 Go 언어는 모두 정적으로 유형을 지정하는 프로그래밍 언어이지만 유형을 명시적으로 지정할 필요는 없지만 추론을 통해 컴파일러가 자동으로 유형을 결정할 수 있습니다.
동적 유형 프로그래밍 패러다임
정적 유형 프로그래밍 패러다임을 채택한 프로그래밍 언어에서는 변수가 유형을 명시적으로 지정할 필요가 없습니다. 모든 변수는 모든 유형의 객체를 가리킬 수 있습니다. 대표 언어: Python, Ruby, JavaScript.
다이나믹 타이핑의 철학은 덕 타이핑의 개념으로 요약할 수 있습니다. James Whitcomb Riley가 제안한 오리 테스트는 다음과 같이 표현될 수 있습니다. "새가 오리처럼 걷고, 오리처럼 헤엄치고, 오리처럼 꽥꽥거리는 것을 보면 그 새를 오리라고 부를 수 있습니다." 🎜> 이 패러다임은 프로그래머가 변수의 유형과 변수가 지원하는 메서드 및 속성을 알아야 한다고 믿습니다. 변수의 유형을 모른다면 당황하지 마세요! 프로그램이 실행되면 충돌이 발생합니다! 프로그램이 충돌하면 누구를 비난해야 합니까? 자책하세요. 당신은 자격을 갖춘 프로그래머가 아닙니다!
동적 유형 지정의 이점은 다음과 같습니다.
인터페이스와 추상 유형을 명시적으로 정의할 필요가 없습니다. 유형이 필수 메소드와 속성을 지원하는 한 괜찮습니다. 절차는 매우 유연하고 간단합니다. C++, Java 및 C#이 생명선으로 간주하는 인터페이스/기본 클래스는 동적 언어에서는 아무것도 아닌 것으로 간주됩니다!
단점은
1. 유형이 틀리면 컴파일러가 오류를 찾을 수 없지만 런타임 중에 프로그램이 충돌합니다.
2. 컴파일러는 변수의 종류를 모르기 때문에 성능을 최적화할 수 없습니다.
객체지향 프로그래밍 패러다임
객체지향 프로그래밍 패러다임은 1970년대 후반부터 등장하기 시작했습니다. 코드를 캡슐화하는 모듈로 클래스와 클래스 인스턴스를 지원합니다. 대표 언어: Smalltalk, C++, Objective-C, Java, C#, VB.NET, Swift, Go, Python, Ruby, ActionScritp, OCaml
초기 프로그래밍 언어는 모두 프로세스 지향적이었습니다. 함수를 형성하는 것은 시퀀스, 조건 및 루프입니다. 코드의 크기가 커질수록 사람들은 코드를 모듈화할 필요성을 느끼게 됩니다. 컨셉에 맞는 코드를 파일로 담기 때문에 동시 개발과 코드 관리가 용이합니다.
사람들은 "프로그램 = 데이터 구조 + 알고리즘"의 규칙도 발견했습니다. 따라서 개념에 해당하는 자료구조와 함수를 하나의 파일에 넣어야 한다. 이것이 수업의 개념이다.
객체지향 프로그래밍 패러다임은 실제로 생산 효율성을 크게 향상시켜 널리 사용되었습니다. 따라서 언어 수준에서 객체지향 프로그래밍 패러다임을 지원하는 언어가 많이 있습니다.
C 언어는 언어 수준에서 객체지향 프로그래밍 패러다임을 지원하지 않지만, 현대 C 언어 개발에서는 객체지향 모듈식 아이디어를 적용하고 동일한 유형의 데이터 구조와 기능을 하나의 파일에 넣을 것입니다. 유사한 명명 체계를 사용합니다.
결국 C 언어는 언어 수준에서 객체지향을 지원하지 않기 때문에 많은 프로그래머들이 C 언어에 객체지향 지원을 추가하고 싶어합니다. 대표적인 것이 C++와 Objective-C이다.
C++는 새로운 언어이지만 대부분의 언어 요소는 C와 호환됩니다.
Objective-C는 C와 완벽하게 호환됩니다. Objective-C는 C에 간단한 구문 계층을 추가하여 인터페이스(즉, 다른 언어의 클래스)와 프로토콜(즉, 다른 언어의 인터페이스)을 지원합니다. Objective-C의 초기 구현조차 C 언어 사전 컴파일러였습니다. 솔직히 말하자면, Objective-C는 추가된 구문이 C 흐름을 따르지 않는다는 점을 제외하면 실제로 객체지향 시스템 설계가 상당히 정교합니다. 초기에 Jobs는 매우 통찰력이 있었고 Objective-C를 주머니에 넣었습니다. Apple/NextStep 시스템 내에서 폐쇄되었기 때문에 그것에 대해 아는 사람은 거의 없었습니다. iOS 시스템의 인기로 인해 Objective-C는 최근 몇 년간 전 세계적으로 유명해졌습니다.
함수형 프로그래밍 패러다임
함수형 프로그래밍 패러다임은 일부 수학자들이 고안한 프로그래밍 언어입니다. 그들은 프로그램이 수학적 함수라고 믿습니다. 대표 언어: Lisp, Erlang, JavaScript, OCaml, Prog.
함수형 프로그래밍 언어를 강력히 옹호하고 그것이 극도로 혁명적이라고 생각하는 전문가들이 많이 있습니다. 그러나 나는 그들이 함수형 프로그래밍 패러다임의 힘을 과대평가했다고 생각합니다. 나는 함수형 프로그래밍 패러다임이 객체지향 프로그래밍 패러다임보다 낫다고 생각하지 않습니다.
함수형 프로그래밍 언어의 핵심은 함수이며, 클래스라는 개념이 없습니다. 그러나 그 기능은 전통적인 프로세스 지향 언어의 기능이 아닙니다. 그 기능은 "클로저" 개념을 지원합니다.
제 생각에는 "클로저"라고도 알려진 함수형 프로그래밍 언어의 함수는 실제로 직설적으로 말하면 "클래스"입니다. 오늘날까지 프로그래밍 언어의 발전에는 모듈화와 "데이터 구조"와 "알고리즘"의 조합이 필요합니다. 언어에 관계없이 프로그래밍 방식이 이들을 결합하지 않으면 빠져나갈 길이 없습니다.
객체 지향 프로그래밍 언어는 클래스를 사용하여 "데이터 구조"와 "알고리즘"을 결합합니다. 클래스의 핵심은 "알고리즘", "기능"이 아닌 "데이터 구조", 즉 "속성"입니다. 클래스에서는 속성에 연결된 함수입니다.
함수형 프로그래밍 언어는 클로저를 사용하여 "데이터 구조"와 "알고리즘"을 결합합니다. 외부 필드를 캡쳐할 수 있는 기능입니다. "함수"에 붙어있는 것이 "속성"입니다.
"클래스"는 본질적으로 "클로저"와 동일합니다. 이제 많은 객체 지향 프로그래밍 언어가 클로저를 지원합니다. 그들의 코드를 관찰하면 실제로 "클로저"를 구현하기 위해 "클래스"를 사용한다는 것을 알 수 있습니다.
"클래스"와 "클로저" 중 어느 것이 더 사용하기 쉽나요? 분명히 "클래스"입니다.
그리고 "클로저"가 더 간결하므로 "클로저"는 객체 지향 프로그래밍 언어에서 익명 클래스를 대체하는 데 자주 사용됩니다. 하나의 함수만으로 클래스를 작성하는 것은 너무 번거로우므로 클로저로 작성하는 것이 더 간결합니다.
OCaml 언어에 대해 불평해 보겠습니다. 이전 Caml 언어는 객체 지향 메커니즘 전체를 추가하고 객체 지향 프로그래밍 패러다임과 함수형 프로그래밍 패러다임을 모두 지원하는 매우 훌륭한 기능적 언어입니다. C++만큼 두뇌가 분열됩니다.
JavaScript에 짜증을 내고 항상 JavaScript에 객체 지향 지원을 추가하려는 객체 지향 언어 컨트롤러도 많이 있습니다. ActionScript는 그러한 시도 중 하나입니다. 제가 사용해본 결과 Java와 크게 다르지 않습니다.
ExtJS에 대해 다시 불평해보자. 저는 웹 프런트엔드 개발 프레임워크를 선택할 때 ExtJS와 JQuery를 비교했습니다.
ExtJS는 분명히 Java 전문가가 JavaScript를 사용하여 Swing의 디자인 아이디어를 모방하고 UI 라이브러리를 구축한 것입니다.
JQuery 개발자는 JavaScript의 함수형 프로그래밍 패러다임을 확실히 이해하고 JavaScript의 동적 함수형 프로그래밍 언어의 특성을 기반으로 UI 라이브러리를 만들었으며 이는 즉시 ExtJS를 죽였습니다.
ExtJS와 JQuery의 이야기를 통해 다국어 프로그래밍 기능이 얼마나 중요한지 알 수 있습니다. ExtJS의 저자는 Java에 능숙하고 사랑하기 때문에 Java를 사용하기 위해 메스 JavaScript를 망치로 사용하고 무작위로 두드리는 것은 감사할 일이 아닙니다.
함수형 프로그래밍 언어뿐만 아니라 꼬리 재귀와 같은 몇 가지 트릭도 있습니다. 꼬리 재귀에는 재귀 호출 중 스택 오버플로를 방지하기 위해 스택이 필요하지 않습니다.
템플릿 프로그래밍 패러다임
템플릿 프로그래밍은 유형을 매개변수로 사용하는 것이며, 함수 세트는 다양한 유형을 지원할 수 있습니다. 대표언어: C++.
템플릿 프로그래밍의 필요성은 C++에서 컨테이너 라이브러리를 개발할 때 생겨났습니다. 컨테이너는 모든 유형의 객체를 저장해야 하기 때문에 제네릭이 필요합니다.
C++의 템플릿 프로그래밍은 컴파일 중에 소스 코드의 사용법에 따라 해당 유형의 코드를 생성하는 것입니다. C++ 외에도 Java와 C#에도 "제네릭"이라는 유사한 메커니즘이 있지만 구현 방법은 C++ 템플릿과 매우 다릅니다. 해당 컴파일러는 새 코드를 생성하지 않고 대신 캐스트를 사용합니다.
템플릿/제네릭이 없는 프로그래밍 언어에서 개체를 컨테이너에 저장하는 방법은 무엇입니까? 공개 기본 클래스 유형(Java, C#) 또는 void* 포인터(C)의 객체에 액세스하고 이를 꺼낼 때 직접 실제 유형으로 캐스팅하면 됩니다. 동적 유형 언어는 유형을 신경쓰지 않고, 아무 객체나 컨테이너에 넣고 꺼내서 직접 사용하면 됩니다.
일부 C++ 마스터는 템플릿을 기반으로 하는 "템플릿 메타프로그래밍"을 고안했습니다. 템플릿 프로그래밍은 C++ 컴파일러에 의해 수행되므로 템플릿 메타프로그래밍은 컴파일러가 계산을 수행하도록 하고 결과는 컴파일 후에 계산됩니다. 연구나 실력 과시 외에는 이게 무슨 소용이 있는지 모르겠네요.
요약
언어를 배울 가치가 있는지 판단하는 기준에는 여러 가지가 있다고 생각합니다.
1. 사용하고 싶다면 배워야 합니다. 그것에 대해 의심의 여지가 없습니다. 결국 우리 모두는 먹어야 합니다.
2. 언어적 특성이 상쾌한 느낌을 주는지. 그렇다면 입장료만큼의 가치가 있습니다. 예를 들어 Go 언어는 예외를 폐지하고 대신 여러 값을 반환합니다. 그렇게 생각해요. 나는 실제로 수년 동안 예외를 적극적으로 사용해 왔습니다. 왜냐하면 C는 예외를 지원하지 않고 잘 살 수 있는데 왜 예외가 필요한 걸까요? 오류가 발생하여 오류 코드가 반환되었습니다. 되돌릴 수 없는 오류의 경우 프로그램을 직접 중단하세요! 게다가 예외는 실제로 절차적 프로그래밍의 원칙을 위반합니다. 함수에는 하나의 시작과 하나의 종료만 있어야 합니다. 예외를 발생시키는 출구가 더 많습니다.
3. 특정 분야를 잘하시나요? 당신이 가진 것이 망치뿐이라면 모든 일을 망치처럼 다루게 될 것입니다. 하지만 도구 상자에 다양한 도구가 있으면 다양한 작업에 직면하는 것이 훨씬 더 쉬울 것입니다.
섹션 7 - 아키텍처 디자인
우수한 소프트웨어를 디자인하려면 아키텍처 디자인 능력도 마스터해야 합니다. 건축 설계에는 몇 가지 기술이 있습니다.
1. 레이어링
소프트웨어는 일반적으로 다음과 같이 나뉩니다.
프레젠테이션 레이어 - UI 부분
인터페이스 레이어 - 백그라운드 서비스의 통신 인터페이스 부분
서비스 레이어 - 실제 서비스 부분
스토리지 레이어 - 파일이나 데이터베이스에 저장되는 영구 저장 부분.
계층화된 소프트웨어는 각 모듈을 분리하고 병렬 개발을 지원하며 수정이 쉽고 성능을 쉽게 향상시킬 수 있습니다.
2. SOA
모듈은 네트워크 통신을 통해 서로 연결되며 느슨하게 결합됩니다. 각 모듈은 독립적으로 배포할 수 있으며 배포 인스턴스를 추가하여 성능을 향상시킬 수 있습니다. 각 모듈은 서로 다른 언어와 플랫폼을 사용하여 개발할 수 있으며, 이전에 개발된 서비스를 재사용할 수 있습니다. SOA, 일반적으로 사용되는 프로토콜에는 WebService, REST, JSON-RPC 등이 포함됩니다.
3. 성능 병목 현상
1) 동기화를 비동기식으로 변경합니다.
메모리 큐(Redis), 워크플로우 엔진(JBpm) 등을 사용해 구현했습니다. 메모리 큐는 데이터 손실이 발생하기 쉽지만 속도가 빠릅니다. 워크플로 엔진은 요청을 데이터베이스에 저장합니다.
동기 요청을 비동기 요청으로 변환하면 기본적으로 99.99%의 성능 문제를 해결할 수 있습니다.
2) 단일 머신 병렬 하드웨어 처리를 사용합니다.
예를 들어 GPU, FPGA 및 기타 하드웨어를 사용하여 성능을 처리하고 향상시킵니다.
3) 클러스터 컴퓨터를 활용하여 처리합니다.
예를 들어 Hadoop 클러스터는 여러 컴퓨터를 사용하여 데이터를 병렬로 처리합니다.
자체 소프트웨어 스택에서 병렬 처리를 위해 모듈의 여러 복사본을 배포할 수도 있습니다.
4) 요청을 충족하려면 캐시를 사용하세요. 일반적으로 사용되는 콘텐츠로 캐시가 가열되면 많은 수의 사용자 요청이 메모리에서 데이터만 읽게 되며 성능이 크게 향상됩니다.
캐시는 신의 알고리즘입니다. 마치 당신이 신이고 미래를 예견할 수 있는 것처럼 캐시의 성능은 최적 성능보다 약간 낮을 뿐입니다. 이제 X86 CPU에 주파수 제한이 발생했으므로 CPU의 성능을 향상시키는 주요 방법은 고속 캐시를 추가하는 것입니다.
4. 대규모 시스템을 위한 소규모 프로젝트
대규모 시스템을 만나면 당황하지 말고, 여러 모듈로 나누고, 여러 개의 작은 프로그램을 사용하고, SOA 협업을 통해 해결해보세요. 이는 Unix의 디자인 철학을 따릅니다. 단일 목적을 가진 수많은 작은 프로그램이 Unix에서 개발되었습니다. 사용자는 파이프라인을 사용하여 여러 작은 프로그램이 협력하여 사용자 요구를 해결할 수 있도록 권장합니다. 물론 파이프라인 통신에는 제한 사항이 너무 많고 유연성이 부족합니다. 따라서 이제 URI와 SOA를 통해 여러 프로그램이 협력할 수 있습니다. Android 및 iOS의 애플리케이션은 이제 URI를 통해 공동 작업합니다. 이것은 유닉스 디자인 아이디어의 현대적인 발전이라고 볼 수 있습니다. 그렇죠? !
5. 샤딩 슬라이싱
요즘은 IOE로 가는 추세입니다. I-IBM 메인프레임, O-Oracle 데이터베이스, E-EMC 스토리지. 이전에는 대규모 시스템이 IOE를 사용하여 설계되고 메인프레임에 Oracle 데이터베이스를 배포하는 경우가 많았으며 Oracle 데이터베이스는 EMC를 사용하여 데이터를 저장했습니다. IOE는 오늘날 가장 강력한 컴퓨터, 데이터베이스 및 스토리지입니다. 그러나 거대 시스템에 저항할 수 없는 때가 올 것이다.
Oracle 데이터베이스는 컴퓨터 클러스터에서 실행될 수 있는 Shareeverything입니다(서버 노드는 16개를 초과할 수 없음). 컴퓨터 클러스터는 모두 동일한 스토리지를 공유합니다.
IOE 운동은 ShareEverything 모델의 파산을 의미합니다. 시스템을 무한히 확장하려면 ShareNothing을 사용해야 합니다.
MySQL 데이터베이스를 사용하여 모든 크기의 데이터를 처리하세요. 전제는 샤딩을 알고 있다는 것입니다. 대규모 시스템을 여러 개의 작은 시스템으로 나누고 이를 저렴한 서버와 스토리지 여러 개로 나눕니다. 더 현대적이며 다수의 가상 머신으로 나누어져 있습니다.
예를 들어 철도부 홈페이지 12306입니다. 우리는 기차표가 특정 기차에 속한다는 것을 알고 있습니다. 그런 다음 각 열차를 하나의 단위로 나누면 12306 웹사이트를 수천 개의 모듈로 나눌 수 있습니다. 가상 머신은 여러 모듈을 호스팅할 수 있습니다. 특정 열차에서 성능 병목 현상이 발생하면 독립적인 가상 머신으로 이동할 수 있습니다. 나열된 서비스 중 일부를 사용할 수 없게 되더라도 시스템을 완전히 사용할 수 없게 되는 것은 아닙니다.
12306 웹사이트에는 사용자 로그인이라는 전역 부분이 하나만 있습니다. 이는 제3자에게 맡길 수 있습니다. 예를 들어, 사용자는 WeChat, Weibo, QQ 및 기타 계정으로 로그인할 수 있습니다.
사용자 로그인 서비스를 직접 구현할 수도 있습니다. 또는 슬라이싱을 사용하여 여러 Redis 서버로 서비스를 제공할 수도 있습니다. Redis 서버는 로그인한 각 사용자의 sessionId 및 userId, 역할, 권한 및 기타 정보를 저장합니다. sessionId는 무작위로 생성되며 해당 비트 중 일부를 선택하여 해당 세션이 어느 Redis 서버에 있는지 식별할 수 있습니다. 사용자가 로그인하면 sessionId가 고객에게 전송됩니다. sessionId는 사용자가 요청할 때마다 서버로 다시 전송됩니다. 서버는 사용자 정보를 쿼리하고 사용자 요청을 처리하기 위해 sessionId를 Redis 서버로 보냅니다. redis 서버에서 sessionId를 찾을 수 없으면 사용자가 로그인하도록 허용합니다. 등록된 모든 사용자가 동시에 로그인하더라도 많은 메모리를 필요로 하지 않습니다. 또한 세션 메모리가 너무 많은 경우 가장 먼저 로그인한 사용자의 세션을 삭제하고 강제로 다시 로그인하도록 할 수도 있습니다. 동시에 활성 사용자 수는 너무 많지 않습니다.
도메인 지식 수준
이전 수준은 모두 프로그래밍 자체의 기술에 중점을 두며, 직설적으로 말하면 기본적인 기술이며 그 자체로는 큰 가치를 창출하지 못합니다. 그러나 너무 많은 프로그래머가 이러한 기본 수준에서 너무 많은 시간을 낭비합니다.
특히 프로그래밍 언어를 탐구하는 것을 좋아하는 프로그래머들은 새로운 프로그래밍 언어가 나오거나 오래된 언어가 화제가 될 때마다 연구에 에너지를 투자합니다. 나는 프로그래밍 언어와 트릭에 많은 에너지를 낭비하는 그들 중 하나입니다.
C++ 언어가 특히 큰 함정인 것 같아요. 원래는 객체지향 C로 개발되었습니다. 나중에 템플릿 프로그래밍이 발견되었고 템플릿 프로그래밍과 추가 템플릿 메타 프로그래밍이 강력하게 옹호되었습니다. 최근에는 C++11, C++14 등 새로운 표준이 출시되면서 함수형 프로그래밍, 유형 추론 등 새로운 기능이 많이 추가되었습니다. C++는 너무 복잡하고 프로그래머의 에너지를 많이 소모하는 함정이 너무 많습니다. 저는 C++를 사용할 때 객체지향적인 부분과 템플릿 부분만 사용하고, 그 외 너무 복잡한 기능은 사용하지 않습니다.
컴퓨터 과학은 귀중한 프로그램을 작성하기 위해 심층적인 연구를 필요로 하고 받을 자격이 있는 지식 분야가 많이 있습니다. 소프트웨어는 구현 시 가치가 있으려면 업계와 통합되어야 합니다. 도메인 지식을 이해하지 않고 프로그래밍 기술만 공부하는 것만으로는 가치 있는 프로그램을 작성할 수 없습니다.
컴퓨터 과학에는 많은 분야가 있으며 그 중 일부는 아래에 나열되어 있습니다.
스토리지 ---- 블록 장치, 파일 시스템, 클러스터 파일 시스템, 분산 파일 시스템, 광섬유 SCSI, iSCSI, RAID 등
네트워크----이더넷, 광섬유 네트워크, 셀룰러 네트워크, WIFI, VLAN 등
컴퓨터 아키텍처, 주로 CPU 명령어 세트. x86, ARM 등
USB 프로토콜. URB 패키지를 알아야 합니다.
PCI 프로토콜, PCI-E 프로토콜. 최신 컴퓨터 주변 장치는 모두 PCI 프로토콜과 PCI-E 프로토콜을 기반으로 합니다. 이제 그래픽 카드가 모두 PCI-E 프로토콜을 통해 컴퓨터에 연결됩니다. 상대적으로 말하면, 배워야 할 지식이 많이 줄어듭니다. 가상화에 참여하려면 PCI 프로토콜에 대한 심층적인 이해가 필요합니다.
이미지 처리 - 이미지 압축, 실시간 비디오 인코딩 등
3D 게임
관계형 데이터베이스
NoSQL 데이터베이스
운영체제
분산 운영체제
컴파일 원리
머신러닝-빅데이터는 이제 활용이 필요하다!
이 분야의 지식을 이해하려면 이 분야의 기존 상용 하드웨어, 상용 소프트웨어 및 오픈 소스 소프트웨어를 이해하는 것도 포함됩니다. 완료하려는 작업에는 이미 기성 도구가 있는 경우가 많습니다. 기성 도구를 사용하여 작업을 완료하면 되며 개발이 필요하지 않습니다. 때로는 기존 도구를 결합하고 일부 스크립트를 작성하여 작업을 완료해야 하는 경우도 있습니다.
예를 들어 양방향 동기화 작업을 한 번에 구현하고 싶습니다. 훌륭한 오픈 소스 소프트웨어인 Unison을 발견하고 구성 파일을 작성하여 작업을 성공적으로 완료했습니다. 코드를 작성할 필요가 없습니다.
또 한번은 고가용성을 달성하기 위해 Python을 사용하여 여러 오픈 소스 소프트웨어를 호출했는데 쉽게 달성했습니다.
설치 프로그램을 작성하고 운영 체제를 사용자 정의합니다. 운영 체제에 대한 도메인 지식을 알면 스크립트 몇 줄만 작성하면 쉽게 할 수 있습니다.
도메인 지식이 없는 사람들은 불필요한 개발을 많이 해야 할 수도 있고, 시간이 지나서 이것이 막다른 골목이라는 것을 알게 될 수도 있습니다.
또한, 탄탄한 도메인 지식은 프로그래밍 디버깅 및 오류 검사 기능을 크게 향상시킬 수 있습니다. 컴파일러와 프로그래밍 언어 런타임의 작동 방식을 알면 컴파일 오류 및 경고에 따라 코드를 빠르게 수정할 수 있습니다.
운영 체제의 기본 작동 메커니즘을 알면 런타임 오류의 근본 원인을 빠르게 찾을 수 있습니다. 예를 들어, Windows 업그레이드 서비스 프로그램을 작성한 적이 있습니다. 이는 Windows 서비스이며 dos 스크립트를 실행해야 합니다. 이 스크립트는 Windows 서비스 자체를 대체합니다. 가끔 스크립트 실행이 잘못된 것을 발견했습니다. 밤새도록 확인해보니 Windows 서비스를 설치한 후 처음 시작할 때 스크립트를 실행할 때 권한 문제가 발생하는 것으로 나타났습니다. 스크립트는 효과가 없었습니다. 하지만 Windows 서비스 프로그램이 한 번 시작되면 괜찮습니다. 이는 Windows 운영 체제의 기본 보안 메커니즘에 문제가 있는 것 같습니다. Windows 커널에 대해 잘 모르기 때문에 이 문제를 발견하는 데 오랜 시간이 걸렸으며 이 문제의 근본 원인을 모르겠습니다. 문제.
단락 0 - 도메인 지식의 초보자
도메인 지식에 대한 지식이 많지 않습니다. 검색 엔진을 사용하여 이 분야의 소프트웨어 및 하드웨어에 대한 소개 기사를 찾은 후 지침을 따르십시오. 기사에서 소프트웨어를 구성하고 사용하는 방법을 설명합니다. 기존 소프트웨어와 하드웨어를 거의 사용할 수 없습니다.
1단계 - 도메인 지식 전문가
현장에서 일반적으로 사용되는 하드웨어를 이해하고, 현장에서 일반적으로 사용되는 소프트웨어의 구성 및 활용 능력을 심도 있게 숙지합니다. 기존 소프트웨어와 하드웨어를 활용하여 능숙하게 솔루션을 구축할 수 있고, 실제 업무에서 직면하는 다양한 문제를 해결할 수 있습니다.
2항 - 도메인 지식 전문가
현장의 소프트웨어와 도구를 숙지하고 사용법을 알 뿐 아니라 그 원리도 알면 "그것이 무엇인지, 왜 그런지 알 수 있다" 그렇습니다.” 이 분야의 지식 전문가입니다.
네트워크 프로토콜의 원리를 알아야만 네트워크에 문제가 생겼을 때 어디에 문제가 있는지 알 수 있습니다. Mac 충돌, IP 충돌 또는 네트워크 루프입니까?
스토리지의 원리를 알아야만 왜 이 스토리지 방식이 가상화에 적합하지 않은지, 어떤 스토리지 방식이 가상화에 적합한지, 또 다른 스토리지 방식이 데이터 백업에 적합한지 알 수 있습니다.
PCI 프로토콜을 알아야만 하드웨어 장치를 가상화하는 방법을 알 수 있습니다.
네트워크 카드 하드웨어 프로토콜을 알아야만 가상 머신이 정상적으로 사용할 수 있는 가상 네트워크 카드를 시뮬레이션할 수 있습니다.
비디오 인코딩 형식과 원리를 알아야만 어떤 비디오 형식이 가장 적은 대역폭을 차지하고 어떤 비디오 형식이 가장 적은 CPU를 차지하는지 알 수 있습니다.
IntelVT/Amd V 명령어 세트를 이해해야만 가상화가 어떻게 구현되는지 알 수 있습니다.
워크플로가 실제로 상태 머신이라는 것을 이해합니다. 복잡한 워크플로를 접한 경우에만 요구 사항을 충족하는 워크플로 엔진을 설계하는 방법을 알 수 있습니다.
단락 3 - 과학자
귀하는 도메인 지식의 전문가이지만 모든 지식은 책과 다른 사람에게서 나옵니다.
도메인 지식 전문가로 만족한다면 남의 지혜만 훔칠 뿐이지 결코 뛰어넘으려고 하지 않을 것입니다. 다른 사람들은 자신의 연구 결과를 귀하에게 기꺼이 알려주지 않을 수도 있습니다. 다른 사람이 당신에게 말할 때쯤에는 업데이트된 이론을 발견했을 수도 있고 새로운 세대의 제품이 곧 출시될 수도 있습니다.
과학자는 미지의 세계를 탐구하고, 혁신할 용기를 갖고, 인류 사회의 발전을 촉진하는 사람입니다.
전설에 따르면 Cisco 임원은 반 농담으로 "Cisco가 신기술 개발을 중단하면 Huawei는 방향을 찾을 수 없을 것입니다."라고 말했습니다. 화웨이는 전문 지식 전문가 수준에 불과해 흉내만 낼 수 있을 뿐 능가할 수는 없다는 점에서 화웨이를 조롱하는 셈이다. 화웨이의 실제 상황은 모르겠지만, 이제는 화웨이가 선두주자 자리에 올랐으면 좋겠습니다.
Owen Jacobs는 CDMA 코드 분할 다중 접속의 원리를 발견하고 이것이 통신에 큰 잠재력이 있음을 발견하고 Qualcomm을 설립했습니다. Qualcomm은 주로 특허 라이센스 비용으로 생활하며 수많은 과학자를 고용하여 통신 분야의 연구를 수행합니다. 어떤 사람들은 퀄컴이 특허 괴물이라고 말합니다. 이 사람들은 지식의 가치를 이해하지 못합니다. 그들의 눈에는 Windows의 합리적인 가격이 CD 한 장의 가격인 5위안이어야 합니다. 베어메탈 기기의 경우 아이폰 가격은 1,000위안 이상이어야 한다. Qualcomm은 특허 괴물입니다. 그렇다면 CDMA와 LTE도 트롤하는 것이 어떻겠습니까?
X86 칩은 가상화를 염두에 두고 설계되지 않았습니다. 따라서 소위 "가상화 취약점"이 나타날 것입니다. 즉, 일부 CPU 특권 명령어가 실행될 때 가상 머신 환경에서는 예외가 발생하지 않으므로 호스트로 전환될 수 없습니다. 이러한 방식으로 가상 머신은 X86 칩에서 실행될 수 없습니다.
VmWare 회사는 1998년 여러 미국 과학자들에 의해 설립되었습니다. 그들은 바이너리 변환 기술을 사용하여 x86 컴퓨터에서 가상 머신을 실행할 수 있다는 것을 발견했습니다.
Xen 가상화 소프트웨어도 여러 과학자에 의해 발명되었습니다. 그들은 가상 머신 운영 체제와 호스트 운영 체제의 커널을 수정하고 "가상화 취약성" 명령을 실행해야 할 때 호스트의 기능을 직접 호출하면 가상화를 달성하고 실행 성능을 향상시킬 수 있다는 것을 발견했습니다. 가상 머신이 크게 향상될 것입니다.
이후 Intel은 자체 칩에 IntelVT 명령어 세트를 추가했고, Amd는 자체 칩에 AmdV 명령어 세트를 추가하여 "가상화 취약점"을 보완했습니다. 따라서 CPU 하드웨어 명령을 직접 사용하여 가상화를 구현하는 KVM 가상 머신 소프트웨어가 있습니다.
KVM은 CPU 명령을 실행할 때 물리적 CPU에서 직접 실행되므로 매우 효율적입니다. 그러나 가상 머신이 가상 주변 장치를 실행하는 경우 소프트웨어로 시뮬레이션해야 하므로 가상 머신의 IO 액세스 속도가 매우 느립니다.
IBM 과학자 Rusty Russell은 Xen의 R&D 경험을 활용하여 VirtIO 기술을 만들었습니다. 가상 머신에 PCI 가상 장치 및 드라이버 세트를 작성하는 것입니다. 이 가상 PCI 장치 세트에는 가상 장치 메모리가 있습니다. 이 가상 장치 메모리 호스트는 접근 가능하며, 가상 머신도 VirtIO 드라이버를 통해 접근할 수 있습니다. 즉, 가상 머신과 호스트 간에 메모리의 일부를 공유함으로써 가상 머신의 IO 성능 문제를 해결합니다.
또 다른 검색 엔진 이야기를 들려주세요:
오래전부터 프로그램에 검색 기능을 추가하고 싶었습니다. 방금 SQL 쿼리 구현을 사용하기 시작했는데 너무 느리다는 것을 알았습니다. 나중에 오픈소스 Lucene 프로젝트를 발견했습니다. 파일에 역방향 색인을 생성하여 검색 속도를 크게 향상시키는 역방향 색인 기술을 사용합니다.
Google의 두 창립자는 HTML에서 링크의 비밀을 발견했습니다. 그들은 HTML 페이지의 링크 관계를 통해 각 HTML 페이지의 가중치를 설정할 수 있다는 것을 발견했습니다. 이것이 페이지랭크 알고리즘이다. 그 결과 Google의 자동 검색 엔진은 Yahoo의 수동 분류 검색 엔진을 압도했습니다.
좋습니다. 역색인 기술과 PageRank, 그리고 간단한 HTML 크롤러 로봇을 사용하여 검색 엔진을 만들 수 있습니다. 그러나 인터넷은 거대하고 매일 수많은 새로운 웹페이지가 생성됩니다. 인터넷 전체에 대한 역색인을 구축하는 것은 어렵습니다.
몇 년 후 Google은 Googlefs, Mapreduce 및 Bigtable이라는 세 가지 논문을 더 출판했습니다. 그래서 Lucene 프로젝트 개발자들은 Google의 Mapreduce 논문을 기반으로 Hadoop 프로젝트를 개발했습니다. 맵리듀스는 다수의 컴퓨터를 이용해 데이터를 저장하고 계산을 수행하며, 최종적으로 결과를 요약한다. Hadoop+역인덱스+PageRank를 사용하여 검색엔진을 만들 수 있습니다. Yahoo, Baidu 및 기타 회사는 Hadoop을 기반으로 자체 검색 엔진을 개발했습니다.
하지만 여전히 타사의 검색엔진 효과는 Google과 비교할 수 없습니다. 우리 프로그래머들은 이것을 가장 잘 알고 있습니다. 나처럼 나도 항상 벽밖으로 구글을 찾아간다.
Google Blackboard에 Wu Jun 박사의 일부 글이 게재되어 머신러닝 지식이 많이 소개되었습니다. 기사에서 볼 수 있듯이 Google은 실제로 기계 학습을 사용하여 수집된 페이지를 분석합니다. 구글은 분명히 이 공식을 공개하지 않을 것입니다. 언젠가 구글이 이 공식을 실제로 공개하더라도 구글은 확실히 더 날카로운 비밀 공식을 개발할 것이고, 모방 제품의 검색 엔진 효과는 여전히 구글만큼 좋지 않을 것이라고 생각할 수 있습니다.
모방만이 혁신을 향한 유일한 길입니다. 해당 분야의 리더가 되기 전에 학습과 모방의 단계를 거쳐야 합니다. 하지만 업계의 보스가 되기 위해서는, 챔피언이 되기 위해서는 모퉁이에 있는 다른 사람들을 추월할 만큼 용감하고, 용감하게 혁신의 길을 걷고, 진정한 과학자이자 진정한 전문가가 되어야 합니다!
요약
프로그래밍 능력은 두 가지 차원으로 나눌 수 있습니다. 하나는 프로그래밍 기술 수준이고 다른 하나는 도메인 지식 수준입니다.
일부 프로그래머는 프로그래밍 기술을 향상하는 데 모든 에너지를 쏟고 도메인에 대한 지식이 거의 없을 수 있습니다. 이는 실제로 일상 업무에 매우 해롭습니다. 일부 요구 사항에는 이미 기성 오픈 소스 및 무료 솔루션이 있거나 기존 소프트웨어 몇 개만 결합하면 빠르게 해결할 수 있지만 자체 개발하는 데 많은 시간을 소비해야 합니다. 또한, 도메인 지식이 부족하여 프로그램에서 예상치 못한 상황이 발생했을 때 문제의 원인을 빠르게 찾아내고 버그를 해결하기가 어렵습니다.