Files
ProgramPhilosophy/Doc/0. Philosophy - Intro/0.1 Philosophy - Intro.md
T

294 lines
9.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "编程哲学导论"
subtitle: "Programming Philosophy - Introduction"
version: "1.0"
category: "哲学篇 · 导论"
order: 0.1
tags: [编程, 哲学, 导论, 基础概念]
---
# 0.1 编程哲学导论
> **本节导读**:从最本质的角度理解"编程"的含义,建立对代码、编译器、程序的核心认知,并初步了解程序设计的基本哲学思想。
---
## 一、什么是编程?
### 1.1 词源解析
| 汉字 | 含义 | 词性 | 说明 |
|:----:|------|:----:|------|
| **编** | 编写 | 动词 (verb) | 编写代码的动作 |
| **程** | 程序 / 程式 | 名词 (noun) | 具有格式和顺序的结构 |
### 1.2 核心定义
> **编程 (Programming)**:按照一定的 **格式** 与 **顺序** 编写代码的过程。
我们编程的核心目标,是对各种各样的 **文件** 进行操作。
#### 直观类比
可以将编程与 **烹饪** 做类比:
| 烹饪 | 编程 |
|------|------|
| 菜谱 (格式 + 顺序) | 代码 / 算法 |
| 食材 (原料) | 数据 / 文件 |
| 菜肴 (最终产出) | 可执行程序 |
| 厨师 (执行者) | CPU / 计算机 |
---
## 二、核心概念
### 2.1 什么是代码?
**代码 (Code)** 本质上是 **文本文件**,即由 ASCII 字符组成的纯文本。
#### 常见代码文件扩展名
| 语言 | 扩展名 | 说明 |
|------|--------|------|
| C 语言 | `.c` | C 源文件 |
| C 语言 | `.h` | C 头文件 |
| C++ | `.cpp` | C++ 源文件 |
| C++ | `.hpp` | C++ 头文件 |
| C++ | `.cc` / `.cxx` | C++ 源文件(替代写法) |
> **NOTE**`.c` / `.h` 通常用于 C 语言代码;`.cpp` / `.h` / `.cc` / `.cxx` / `.hpp` 通常用于 C++ 代码。
> **NOTE**:只要是合法的 C 或 C++ 的 ASCII 文本(无论使用何种扩展名),都可以被称为 **代码**。
#### 代码示例
**示例 — C 语言 "Hello, World"**
```c
#include <stdio.h>
int main()
{
printf("Hello, World!\n");
return 0;
}
```
> **NOTE**:以上代码就是一个纯 ASCII 文本文件,保存为 `main.c` 后,它就是一段 **代码**。无论你将扩展名改为 `.txt`、`.abc` 甚至不加扩展名,只要内容合法,它依然是代码——只是编译器可能无法自动识别而已。
---
### 2.2 什么是编译器?
**编译器 (Compiler)** 是将 **代码** 转换为 **可执行文件** 的工具。
#### 直观类比
可以将编译器类比为 **翻译官**
| 翻译官 | 编译器 |
|--------|--------|
| 输入:外文原文 | 输入:源代码 (C/C++) |
| 处理:语法分析、语义理解 | 处理:词法/语法/语义分析 |
| 输出:本国语言译文 | 输出:机器码 (可执行文件) |
如果原文有语法错误,翻译官会报错并指出问题位置 —— 编译器也是如此。
#### 输入与输出
```
┌─────────────────────┐ ┌─────────────────────┐
│ Input │ →→→→ │ Output │
│ │ │ │
│ File, Code │ Compiler │ Executable File, │
│ (ASCII Text) │ │ Linker Output │
└─────────────────────┘ └─────────────────────┘
```
#### 编译流程全景图
以 Windows 上的编译流程为例:
```
Source File(s)
┌──────────────┐
│ Preprocessor │
└──────┬───────┘
┌──────────────┐
│ Compiler │
└──────┬───────┘
┌──────────────┐
│ Assembler │
└──────┬───────┘
┌──────────────┐
│ Linker │
└──────┬───────┘
Executable File (.exe)
```
> **REFERENCE**:关于编译流程各阶段的详细说明,请参阅 [→ 0.2 编程基础](./0.2%20Philosophy%20-%20Basic.md#三编译流程详解)
---
### 2.3 什么是程序?
**程序 (Program)** 是经过编译后生成的可执行文件,是计算机能够直接理解和执行的指令集合。
#### 直观类比
| 概念 | 类比 |
|------|------|
| **源代码** | 乐谱 (人可读,但不能直接发声) |
| **编译器** | 钢琴家 (将乐谱"翻译"为按键动作) |
| **程序/可执行文件** | 录好的音频文件 (可直接播放) |
| **运行程序** | 播放录音 (计算机执行指令) |
#### 示例
```
main.c (Source Code) --[Compile]--> main.exe (Program) --[Run]--> Output
Human Readable Machine Executable User Sees
```
---
## 三、基本设计哲学
> 以下是我对程序基本设计哲学的理解与总结:
### 3.1 抽象 (Abstraction)
用代码的方式 **描述问题**,而不纠结于实现细节。
- 将复杂现实简化为可计算的模型
- 关注 **"做什么"** 而非 **"怎么做"**
- 通过接口隐藏底层复杂性
#### 示例
**场景:发送一封电子邮件**
| 层级 | 抽象程度 | 你需要关心的事 |
|:----:|----------|----------------|
| **用户层** | 最高 | 收件人地址、邮件标题、正文内容 |
| **应用层** | 高 | 调用 `smtp.send(to, subject, body)` |
| **协议层** | 中 | SMTP 握手、HELO/EHLO、DATA 命令 |
| **传输层** | 低 | TCP 三次握手、数据包分片与重组 |
| **物理层** | 最低 | 电信号 / 光信号 / 无线电波 |
**抽象的意义**:当你写 `print("Hello")` 时,你不需要知道显卡如何渲染像素、操作系统如何调度显示驱动——这就是抽象的力量。
### 3.2 模块化 (Modularization)
将复杂问题 **分解** 为多个相对独立的子问题,每个子问题构成一个 **模块**
```
Complex Problem
|
+---> Module A ---> Sub-problem A
+---> Module B ---> Sub-problem B
+---> Module C ---> Sub-problem C
```
**示例 — 开发一个计算器程序**
```
Calculator App
|
+--- [input_module] -- User input parsing
+--- [calc_module] -- Arithmetic logic
+--- [display_module] -- Result formatting & display
+--- [history_module] -- History record management
```
**优势**
- 降低复杂度:每个模块只关注一件事
- 提高代码复用性:`calc_module` 可被其他项目引用
- 便于团队协作开发:不同成员负责不同模块
- 方便测试与调试:可单独对 `calc_module` 进行单元测试
### 3.3 封装 (Encapsulation)
将模块的 **实现细节隐藏** 起来,仅 **暴露必要的接口** 给外部使用。
```
┌──────────────────────────────┐
│ [ Module ] │
│ │
│ ┌───────────────────┐ │ <- Public API
│ │ Interface │ │
│ └────────┬──────────┘ │
│ │ │
│ ┌────────▼──────────┐ │
│ │ Private │ │ <- Hidden Details
│ └───────────────────┘ │
└──────────────────────────────┘
```
**示例 — 汽车驾驶**
| 封装层 | 对外暴露(接口) | 隐藏细节 |
|--------|------------------|----------|
| 方向盘、油门、刹车 | 驾驶员可操作 | 引擎燃烧原理、变速箱齿轮比 |
| 函数 `sqrt(x)` | 输入 x,输出根号 x | 牛顿迭代法的具体计算过程 |
```c
// math_utils.c -- 实现细节
static double newton_sqrt(double n) // static: 仅内部可见性
{
// 牛顿迭代法的具体实现... 外部不能直接调用此函数
double guess = n / 2.0;
for (int i = 0; i < 100; i++) {
guess = (guess + n / guess) / 2.0;
}
return guess;
}
// math_utils.c -- 对外暴露的接口
// 仅暴露必要的接口,隐藏实现细节
// 例如:sqrt(9) = 3.0, sqrt(16) = 4.0
double sqrt(double n)
{
if (n < 0) return 0.0; // 内部校验逻辑,负数返回0
return newton_sqrt(n);
}
```
**原则**
- 信息隐藏 (Information Hiding)
- 最小知识原则 (Principle of Least Knowledge)
- 高内聚、低耦合
---
## 本节小结
| 概念 | 核心要点 |
|------|----------|
| **编程** | 按照格式顺序编写代码,本质是对文件的操作 |
| **代码** | ASCII 文本文件,具有约定扩展名规范 |
| **编译器** | 将代码转换为可执行文件的工具,经历预处理→编译→汇编→链接 |
| **程序** | 编译后的可执行指令集 |
| **抽象** | 关注"做什么",忽略实现细节 |
| **模块化** | 分而治之,降低复杂度 |
| **封装** | 隐藏实现,暴露接口 |
---
> **上一节**:无(起始章节)
> **下一节**[→ 0.2 编程基础](./0.2%20Philosophy%20-%20Basic.md)