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

353 lines
12 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 编程哲学导论
> **本节导读**:从"程序"的本质出发,建立对程序分类、运行环境的基础认知,进而理解编程的含义、代码与编译器的核心概念,以及程序设计的基本哲学思想。
---
## 一、什么是程序?
**程序 (Program)** 是经过编译后生成的 **可执行文件**,是计算机能够直接理解和执行的指令集合。
### 1.1 核心定义
| 概念 | 类比 |
|------|------|
| **源代码** | 乐谱(人可读,但不能直接发声) |
| **编译器** | 钢琴家(将乐谱"翻译"为按键动作) |
| **程序 / 可执行文件** | 录好的音频文件(可直接播放) |
| **运行程序** | 播放录音(计算机执行指令) |
```
main.c (Source Code) --[Compile]--> main.exe (Program) --[Run]--> Output
Human Readable Machine Executable User Sees
```
### 1.2 程序界面类型与环境变量配置
针对编程初学者的入门需求,本节从程序的交互形式入手,讲解环境变量的底层逻辑与配置必要性。
#### ① GUI 与 CLI 的交互模式对比
| 特性 | GUI(图形用户界面) | CLI(命令行界面) |
|:----:|:-------------------:|:-----------------:|
| **交互方式** | 通过窗体 (Window) 和控件 (Widget) 进行操作 | 通过输入命令字符串直接操作 |
| **上手难度** | 较低,直观可视化 | 较高,需记忆命令语法 |
| **适用人群** | 普通用户 | 开发者、运维工程师 |
| **自动化能力** | 不利于脚本批量执行 | 极高的自动化容错度 |
| **典型场景** | 浏览器、办公软件 | g++ 编译、git 操作、服务器部署 |
> **NOTE**:作为程序员,我们日常开发主要使用 CLI 工具链(编译器、调试器、版本控制等),但最终交付给用户的通常是 GUI 应用。两者相辅相成。
#### ② 环境变量的核心作用与配置
**环境变量 (Environment Variable)** 是操作系统中 **进程级别的键值对**,用于向运行中的程序传递配置信息。其中最关键的便是 **PATH 变量**
##### 全局访问机制
```
┌──────────────────────────────────────────────────────┐
| How PATH Environment Works |
| |
| User types: g++ main.c -o main.exe |
| |
| Terminal Search Order: |
| +----------+ +----------+ +----------+ |
| | Current |->| PATH |->| PATH |-> ... |
| | Dir | | Entry #1 | | Entry #2 | |
| | (./) | | (C:/... )| | (D:/... )| |
| +----------+ +----------+ +----------+ |
| | |
| v Found! |
| C:/mingw64/bin/g++.exe |
| | |
| v Execute |
| main.c --> main.exe (Success) |
└──────────────────────────────────────────────────────┘
```
**本质**PATH 是一个由分号 (`;`) 分隔的 **目录路径集合**,告知操作系统在任意目录下都能搜索并执行指定的可执行文件(如 `g++.exe`)。
##### IDE 依赖基础
IDE(如 VS Code + C/C++ 插件)之所以能一键编译运行,其背后依赖的就是环境变量:
```
用户点击 VS Code 中的 "Run" 按钮
VS Code 调用终端命令: g++ main.c -o main.exe && ./main.exe
├─── 如果 PATH 中包含 g++ 所在路径 → 编译成功 ✓
└─── 如果 PATH 中没有 → 报错: 'g++' is not recognized ✗
```
> **NOTE**:编译器(g++)、解释器(Python)、构建工具(make、cmake)等都必须配置到环境变量中,IDE 才能在后台自动调用它们完成编译流程,而无需手动指定完整绝对路径。
---
## 二、什么是编程?
### 2.1 词源解析
| 汉字 | 含义 | 词性 | 说明 |
|:----:|------|:----:|------|
| **编** | 编写 | 动词 (verb) | 编写代码的动作 |
| **程** | 程序 / 程式 | 名词 (noun) | 具有格式和顺序的结构 |
### 2.2 核心定义
> **编程 (Programming)**:按照一定的 **格式** 与 **顺序** 编写代码的过程。
我们编程的核心目标,是对各种各样的 **文件** 进行操作。
#### 直观类比
可以将编程与 **烹饪** 做类比:
| 烹饪 | 编程 |
|------|------|
| 菜谱 (格式 + 顺序) | 代码 / 算法 |
| 食材 (原料) | 数据 / 文件 |
| 菜肴 (最终产出) | 可执行程序 |
| 厨师 (执行者) | CPU / 计算机 |
---
## 三、核心概念
### 3.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` 甚至不加扩展名,只要内容合法,它依然是代码——只是编译器可能无法自动识别而已。
---
### 3.2 什么是编译器?
**编译器 (Compiler)** 是将 **代码** 转换为 **可执行文件** 的工具。
#### 直观类比
可以将编译器类比为 **翻译官**
| 翻译官 | 编译器 |
|--------|--------|
| 输入:外文原文 | 输入:源代码 (C/C++) |
| 处理:语法分析、语义理解 | 处理:词法/语法/语义分析 |
| 输出:本国语言译文 | 输出:机器码 (可执行文件) |
如果原文有语法错误,翻译官会报错并指出问题位置 —— 编译器也是如此。
#### 输入与输出
```
┌─────────────────────┐ ┌─────────────────────┐
│ Input │ →→→→ │ Output │
│ │ │ │
│ File, Code │ Compiler │ Executable File, │
│ (ASCII Text) │ │ Linker Output │
└─────────────────────┘ └─────────────────────┘
```
#### 编译流程全景图
以 Windows x64 环境下的 g++ 编译流程为例:
```
Source File(s)
┌──────────────┐
│ Preprocessor │
└──────┬───────┘
┌──────────────┐
│ Compiler │
└──────┬───────┘
┌──────────────┐
│ Assembler │
└──────┬───────┘
┌──────────────┐
│ Linker │
└──────┬───────┘
Executable File (.exe)
```
> **REFERENCE**:关于编译流程各阶段的详细说明,请参阅 [→ 0.2 编程基础](./0.2%20Philosophy%20-%20Basic.md#三编译流程详解)
---
## 四、基本设计哲学
> 以下是我对程序基本设计哲学的理解与总结:
### 4.1 抽象 (Abstraction)
用代码的方式 **描述问题**,而不纠结于实现细节。
- 将复杂现实简化为可计算的模型
- 关注 **"做什么"** 而非 **"怎么做"**
- 通过接口隐藏底层复杂性
#### 示例
**场景:发送一封电子邮件**
| 层级 | 抽象程度 | 你需要关心的事 |
|:----:|----------|----------------|
| **用户层** | 最高 | 收件人地址、邮件标题、正文内容 |
| **应用层** | 高 | 调用 `smtp.send(to, subject, body)` |
| **协议层** | 中 | SMTP 握手、HELO/EHLO、DATA 命令 |
| **传输层** | 低 | TCP 三次握手、数据包分片与重组 |
| **物理层** | 最低 | 电信号 / 光信号 / 无线电波 |
**抽象的意义**:当你写 `print("Hello")` 时,你不需要知道显卡如何渲染像素、操作系统如何调度显示驱动——这就是抽象的力量。
### 4.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` 进行单元测试
### 4.3 封装 (Encapsulation)
将模块的 **实现细节隐藏** 起来,仅 **暴露必要的接口** 给外部使用。
```
┌──────────────────────────────┐
│ [ Module ] │
│ │
│ ┌───────────────────┐ │ <- Public API
│ │ Interface │ │
│ └────────┬──────────┘ │
│ │ │
│ ┌────────▼──────────┐ │
│ │ Private │ │ <- Hidden Details
│ └───────────────────┘ │
└──────────────────────────────┘
```
**示例 — 汽车驾驶**
| 封装层 | 对外暴露(接口) | 隐藏细节 |
|--------|------------------|----------|
| 方向盘、油门、刹车 | 驾驶员可操作 | 引擎燃烧原理、变速箱齿轮比 |
| 函数 `sqrt(x)` | 输入 x,输出根号 x | 牛顿迭代法的具体计算过程 |
```c
// math_utils.c -- Implementation details hidden
static double newton_sqrt(double n) // static: internal visibility only
{
// Newton's method implementation... external code cannot call this directly
double guess = n / 2.0;
for (int i = 0; i < 100; i++) {
guess = (guess + n / guess) / 2.0;
}
return guess;
}
// The only exposed interface
double sqrt(double n)
{
if (n < 0) return 0.0; // Internal validation logic
return newton_sqrt(n);
}
```
**原则**
- 信息隐藏 (Information Hiding)
- 最小知识原则 (Principle of Least Knowledge)
- 高内聚、低耦合
---
## 本节小结
| 章节 | 核心要点 |
|------|----------|
| **一、程序** | 编译后的可执行指令集;分为 GUI/CLI 两类;依赖 PATH 环境变量实现全局调用 |
| **二、编程** | 按照格式顺序编写代码,本质是对文件的操作 |
| **三、代码** | ASCII 文本文件,具有约定扩展名规范 |
| **三、编译器** | 将代码转换为可执行文件的工具,经历预处理→编译→汇编→链接 |
| **四、抽象** | 关注"做什么",忽略实现细节 |
| **四、模块化** | 分而治之,降低复杂度 |
| **四、封装** | 隐藏实现,暴露接口 |
---
> **上一节**:无(起始章节)
> **下一节**[→ 0.2 编程基础](./0.2%20Philosophy%20-%20Basic.md)