<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ freeCodeCamp 中文编程教程：Python、JavaScript、Java、Git 等 ]]>
        </title>
        <description>
            <![CDATA[ freeCodeCamp 是一个免费学习编程的开发者社区，涵盖 Python、HTML、CSS、React、Vue、BootStrap、JSON 教程等，还有活跃的技术论坛和丰富的社区活动，在你学习编程和找工作时为你提供建议和帮助。 ]]>
        </description>
        <link>https://www.freecodecamp.org/chinese/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ freeCodeCamp 中文编程教程：Python、JavaScript、Java、Git 等 ]]>
            </title>
            <link>https://www.freecodecamp.org/chinese/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 16 Apr 2026 03:42:17 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/chinese/news/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ 使用 Python 和多进程构建简历筛选系统 ]]>
                </title>
                <description>
                    <![CDATA[ 招聘合适的人选，往往从一项耗时的工作开始：筛选简历。如果你发布过职位招聘，一定体会过收件箱里有数百份申请，而你得花数小时手动审阅每份简历的烦恼。 本文将带你用纯 Python 搭建一个简历筛选系统，重点讲解核心编程概念和多进程的运用。你会创建一个自定义系统，通过将非结构化的简历文档转化为排名榜单，实现评估流程的自动化。 阅读完本指南后，你将能够：  * 解析文档：使用 Python 从 PDF 和 DOCX 简历中提取文本  * 提取信息：从简历内容中识别技能与关键词  * 设计评分算法：用加权逻辑客观地为候选人排序  * 构建 Web 界面：使用 Streamlit 完成  * 部署应用：在 Streamlit Cloud 上部署应用，供公众访问 按照本教程操作，你将构建一个能在几秒内处理数百份简历的工具。 源代码见 GitHub 仓库 [https://github.com/abdultalha0862/Resume_Parser_Project] 目录  * 前置要求  * 项目概览  * 系统如何工作  * ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/python-resume-screening-system/</link>
                <guid isPermaLink="false">69904195be64e2045fddd24a</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Miya Liu ]]>
                </dc:creator>
                <pubDate>Sat, 14 Feb 2026 10:00:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2026/02/----_20260214181319_13_235.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/python-resume-screening-system/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Build a Résumé Screening System Using Python and Multiprocessing</a>
      </p><!--kg-card-begin: markdown--><p>招聘合适的人选，往往从一项耗时的工作开始：筛选简历。如果你发布过职位招聘，一定体会过收件箱里有数百份申请，而你得花数小时手动审阅每份简历的烦恼。</p>
<p>本文将带你用纯 Python 搭建一个简历筛选系统，重点讲解核心编程概念和多进程的运用。你会创建一个自定义系统，通过将非结构化的简历文档转化为排名榜单，实现评估流程的自动化。</p>
<p>阅读完本指南后，你将能够：</p>
<ul>
<li>解析文档：使用 Python 从 PDF 和 DOCX 简历中提取文本</li>
<li>提取信息：从简历内容中识别技能与关键词</li>
<li>设计评分算法：用加权逻辑客观地为候选人排序</li>
<li>构建 Web 界面：使用 Streamlit 完成</li>
<li>部署应用：在 Streamlit Cloud 上部署应用，供公众访问</li>
</ul>
<p>按照本教程操作，你将构建一个能在几秒内处理数百份简历的工具。</p>
<p>源代码见 <a href="https://github.com/abdultalha0862/Resume_Parser_Project">GitHub 仓库</a></p>
<h2 id="">目录</h2>
<ul>
<li>前置要求</li>
<li>项目概览</li>
<li>系统如何工作</li>
<li>系统架构</li>
<li>项目结构</li>
<li>步骤 1：搭建项目</li>
<li>步骤 2：构建简历解析器</li>
<li>步骤 3：构建关键词提取器</li>
<li>步骤 4：实现评分引擎</li>
<li>步骤 5：构建 Web 界面</li>
<li>步骤 6：测试系统</li>
<li>步骤 7：部署应用</li>
<li>总结</li>
</ul>
<h2 id="">前置要求</h2>
<p>要学习本教程，你需要具备：</p>
<ul>
<li>Python 基础知识（函数、循环、字典）</li>
<li>已安装 Python 3.8 或更高版本</li>
<li>会用 <code>pip</code> 安装包</li>
<li>代码编辑器（如 VS Code、PyCharm 或任意你喜欢的编辑器）</li>
</ul>
<h2 id="">项目概览</h2>
<p>本指南将开发一个系统：输入一个简历文件夹和一份职位描述（JD），系统会处理每份简历、提取相关信息，并根据候选人与职位要求的匹配程度计算得分。</p>
<h2 id="">系统如何工作</h2>
<p>项目包含四个核心组件：</p>
<ul>
<li><strong>简历解析器</strong>：读取 PDF 和 DOCX 文件并提取文本</li>
<li><strong>职位描述解析器</strong>：分析职位描述以识别所需技能</li>
<li><strong>关键词提取器</strong>：将简历内容与技能分类体系进行匹配</li>
<li><strong>评分引擎</strong>：使用加权算法对候选人排序</li>
</ul>
<h3 id="">评分公式</h3>
<p>使用的评分公式如下：</p>
<pre><code>总分 =
（必备技能 × 50%）+
（优先技能 × 25%）+
（经验 × 15%）+
（关键词 × 10%）
</code></pre>
<p>这样设计可以确保核心技能比次要关键词权重更高。</p>
<h3 id="">这种方法如何有助于减少偏见</h3>
<p>本系统基于预定义标准评估简历，而不是主观判断。每份简历都根据同一套必备技能、优先技能、经验指标和关键词进行打分。</p>
<p>由于所有候选人都使用同一套加权公式评估，写作风格、排版或个人偏好等主观因素不会影响排名。评分逻辑只关注简历与职位要求的匹配程度。</p>
<p>通过将评估过程标准化，系统促进了更一致、更客观的筛选，有助于在简历初筛阶段减少偏见。</p>
<h2 id="">系统架构</h2>
<pre><code>输入                    处理                       输出
─────                   ──────────                  ─────

简历 ──► 简历解析器 ──► 关键词提取器 ──┐
(PDF/DOCX)                             │
                                        ├──► 评分引擎 ──► 排名结果
职位描述 ──► 职位描述解析器 ────────────┘
(TXT/PDF)
</code></pre>
<p>系统遵循简单的“输入—处理—输出”流程。</p>
<p>简历和职位描述作为输入。简历解析器从每份简历中提取文本，职位描述解析器从职位描述中识别必备技能和优先技能。</p>
<p>提取出的简历文本随后传给关键词提取器，该模块根据预定义的技能分类体系匹配技能和关键词。</p>
<p>最后，评分引擎应用加权公式为每位候选人计算得分，并输出一份按分数排序的简历列表。</p>
<h2 id="">项目结构</h2>
<pre><code>resume_screening_system/
├── app.py                    # Streamlit Web 界面
├── main.py                   # 命令行界面
├── parsers/
│   ├── resume_parser.py      # PDF/DOCX 文本提取
│   └── jd_parser.py          # 职位描述解析
├── extractors/
│   └── keyword_extractor.py  # 技能与经验提取
├── matcher/
│   └── scorer.py             # 评分算法
├── data/
│   ├── config.json           # 评分权重配置
│   └── skills_taxonomy.json  # 技能数据库
└── requirements.txt          # 依赖
</code></pre>
<p>项目按清晰的模块化目录组织。解析逻辑、关键词提取和评分分别放在各自文件夹中，配置文件与数据单独存放，便于浏览、维护和扩展。</p>
<h2 id="1">步骤 1：搭建项目</h2>
<p>创建目录结构并设置虚拟环境：</p>
<pre><code class="language-bash">mkdir resume_screening_system
cd resume_screening_system
mkdir parsers extractors matcher data input output
python -m venv venv
</code></pre>
<p>然后激活虚拟环境：</p>
<pre><code class="language-bash"># Windows
source venv/Scripts/activate

# macOS / Linux
source venv/bin/activate
</code></pre>
<p>安装所需依赖：</p>
<pre><code class="language-bash">pip install PyPDF2 python-docx streamlit pandas
</code></pre>
<h2 id="2">步骤 2：构建简历解析器</h2>
<p>简历解析器针对不同文件格式使用不同的提取方法。</p>
<p>对于 PDF，解析器逐页打开文档，用 PDF 阅读器从每页提取文本，再合并成单个字符串供后续处理。</p>
<p>对于 DOCX，解析器读取文档中的每个段落，将段落文本拼接成一块。这样无论简历格式如何，都能得到一致的文本输出。</p>
<p>将简历统一转为纯文本后，关键词提取和评分等组件就能高效工作。</p>
<p><strong>文件：</strong> <code>parsers/resume_parser.py</code></p>
<pre><code class="language-python">def _extract_pdf(self, file_path: Path) -&gt; str:
    text = ""
    with open(file_path, "rb") as file:
        pdf_reader = PyPDF2.PdfReader(file)
        for page in pdf_reader.pages:
            page_text = page.extract_text()
            if page_text:
                text += page_text + "\n"
    return text.strip()

def _extract_docx(self, file_path: Path) -&gt; str:
    from docx import Document
    doc = Document(file_path)
    return "\n".join(
        para.text for para in doc.paragraphs
    ).strip()
</code></pre>
<h2 id="3">步骤 3：构建关键词提取器</h2>
<p>本项目使用 <a href="https://www.kaggle.com/datasets/snehaanbhawal/resume-dataset">Kaggle</a> 上的简历数据集，确保逻辑在真实职业数据上可用。关键词提取器通过扫描简历文本来识别技能。</p>
<p>简历文本先转为小写，以便不区分大小写地匹配。预定义的技能分类体系存储每个技能及其可能变体，提取器用这些变体与简历文本比对。</p>
<p>匹配时使用词边界，避免部分匹配（例如在 “JavaScript” 里匹配到 “Java”）。匹配到的技能存入集合以避免重复。</p>
<p>这种方式能在所有简历上实现一致、可控的技能识别。</p>
<p><strong>文件：</strong> <code>extractors/keyword_extractor.py</code></p>
<pre><code class="language-python">def extract_skills(self, text: str) -&gt; Set[str]:
    text_lower = text.lower()
    found_skills = set()

    for category, skills_dict in self.skills_taxonomy.items():
        for skill_name, variations in skills_dict.items():
            for variation in variations:
                # 防止 "Java" 匹配到 "JavaScript"
                pattern = r"\b" + re.escape(variation) + r"\b"
                if re.search(pattern, text_lower):
                    found_skills.add(skill_name)
                    break

    return found_skills
</code></pre>
<h2 id="4">步骤 4：实现评分引擎</h2>
<p>为得到客观排名，系统使用加权评分公式。</p>
<table>
<thead>
<tr>
<th>组件</th>
<th>权重</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>必备技能</td>
<td>50%</td>
<td>核心技术需求</td>
</tr>
<tr>
<td>优先技能</td>
<td>25%</td>
<td>差异化竞争力</td>
</tr>
<tr>
<td>经验</td>
<td>15%</td>
<td>专业深度</td>
</tr>
<tr>
<td>关键词</td>
<td>10%</td>
<td>领域熟悉度</td>
</tr>
</tbody>
</table>
<pre><code>总分 =
(S_req × 0.50) +
(S_pref × 0.25) +
(E_exp × 0.15) +
(K_key × 0.10)
</code></pre>
<p>评分引擎用上述权重为每份简历计算最终得分。</p>
<p>它统计简历中出现的必备技能、优先技能、经验指标和关键词数量，每个数量乘以其对应权重（必备技能权重最高），加权值相加得到单一分数，再按该分数对简历排序，生成候选人排名列表。</p>
<h2 id="5web">步骤 5：构建 Web 界面</h2>
<p>Streamlit 为简历筛选系统提供了简单的 Web 界面。</p>
<p>文本区域用于输入职位描述，文件上传器用于上传多份简历。点击按钮后，Streamlit 触发后端逻辑解析简历、提取数据并计算得分，结果在浏览器中展示，用户无需使用命令行即可完成筛选。</p>
<p><strong>文件：</strong> <code>app.py</code></p>
<pre><code class="language-python">import streamlit as st

jd_text = st.text_area(
    "在此粘贴职位描述：",
    height=300
)

uploaded_files = st.file_uploader(
    "上传简历文件：",
    type=["pdf", "docx", "txt"],
    accept_multiple_files=True
)

if st.button("筛选简历", type="primary"):
    st.success("正在处理简历...")
</code></pre>
<p>运行应用：</p>
<pre><code class="language-bash">streamlit run app.py
</code></pre>
<p>应用将运行在 <a href="http://localhost:8500">http://localhost:8500</a>。</p>
<h2 id="6">步骤 6：测试系统</h2>
<h3 id="">示例职位描述输入</h3>
<p>下面是一份可用于测试的示例职位描述：</p>
<pre><code>我们正在寻找一名具有扎实后端开发经验的高级 Python 开发工程师。

必备技能：
- Python
- Django
- REST API
- SQL

优先技能：
- PostgreSQL
- Docker
- AWS

经验要求：
- 3 年以上 Python 专业开发经验
- 有构建 Web 应用的经验
</code></pre>
<p>该输入帮助系统识别必备技能、优先技能和经验关键词，供评分引擎对简历排序。</p>
<pre><code class="language-bash">python main.py
</code></pre>
<h3 id="">示例输出</h3>
<pre><code>============================================================
筛选结果
============================================================
第 1 名：Alice Johnson | 得分：85.42/100 | 匹配：python、django、postgresql
第 2 名：Carol Davis   | 得分：72.50/100 | 匹配：python、django
</code></pre>
<h2 id="7">步骤 7：部署应用</h2>
<p>若要让系统对外可访问：</p>
<ol>
<li>将代码推送到 GitHub</li>
<li>打开 share.streamlit.io</li>
<li>选择你的 <code>app.py</code> 文件</li>
<li>部署应用</li>
</ol>
<p>应用将发布在：</p>
<pre><code>https://your-app-name.streamlit.app
</code></pre>
<h2 id="">总结</h2>
<p>在本教程中，你使用 Python 从零搭建了一个完整的简历筛选系统。通过结合文本处理、结构化评分和自动化，该项目展示了如何将手动简历筛选转变为高效、客观的流程。</p>
<p>该系统有助于减少偏见、节省时间，并更一致地评估候选人。Happy coding!</p>
<!--kg-card-end: markdown--> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 代码整洁实践：敏捷软件开发中的代码优化指南 ]]>
                </title>
                <description>
                    <![CDATA[ 构建可扩展的软件应用程序需要编写干净的代码，这种代码简单到任何开发人员都能理解。 在这篇文章中，我将解释并演示什么是干净的代码。然后，我将分享我最喜欢的代码整洁模式，用于构建现代敏捷应用程序。 我不会使用复杂的术语。我会用简单明了的 JavaScript 示例来展示核心概念。开门见山，这就是我的风格。 让我们开始吧。 目录  1. 坏代码的成本            2. 清洁编码者 vs. 混乱编码者            3. 如果你的代码一团糟，AI 也救不了你 🗑️           ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/the-clean-code-handbook/</link>
                <guid isPermaLink="false">69630570d350d0045e97cbae</guid>
                
                    <category>
                        <![CDATA[ 代码质量 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tsukistar ]]>
                </dc:creator>
                <pubDate>Sun, 11 Jan 2026 02:21:24 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2026/01/----_20260111101926_191_113.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/the-clean-code-handbook/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">The Clean Code Handbook: How to Write Better Code for Agile Software Development</a>
      </p><!--kg-card-begin: markdown--><p>构建可扩展的软件应用程序需要编写干净的代码，这种代码简单到任何开发人员都能理解。</p>
<p>在这篇文章中，我将解释并演示什么是干净的代码。然后，我将分享我最喜欢的代码整洁模式，用于构建现代敏捷应用程序。</p>
<p>我不会使用复杂的术语。我会用简单明了的 JavaScript 示例来展示核心概念。开门见山，这就是我的风格。</p>
<p>让我们开始吧。</p>
<h2 id="">目录</h2>
<ol>
<li>
<p><a href="#heading-the-cost-of-bad-code">坏代码的成本</a></p>
</li>
<li>
<p><a href="#heading-clean-coder-vs-messy-coder">清洁编码者 vs. 混乱编码者</a></p>
</li>
<li>
<p><a href="#heading-ai-cant-save-you-if-your-code-is-a-mess">如果你的代码一团糟，AI 也救不了你 🗑️</a></p>
</li>
<li>
<p><a href="#heading-12-clean-code-design-patterns-for-building-agile-applications">用于构建敏捷应用的 12 个整洁代码设计模式 ⚖️</a></p>
<ul>
<li>
<p><a href="#heading-use-names-that-mean-something">🌿 使用有意义的名称</a></p>
</li>
<li>
<p><a href="#heading-keep-functions-laser-focused-srp">🔨 保持函数的专注性 (SRP)</a></p>
</li>
<li>
<p><a href="#heading-use-comments-thoughtfully">🚪 谨慎使用注释</a></p>
</li>
<li>
<p><a href="#heading-best-practices-for-writing-good-comments">⚡ 编写优秀注释的最佳实践</a></p>
</li>
<li>
<p><a href="#heading-make-your-code-readable">🧩 让你的代码可读</a></p>
</li>
<li>
<p><a href="#heading-test-everything-you-write">🏌️ 测试你写的所有内容</a></p>
</li>
<li>
<p><a href="#heading-use-dependency-injection">💉 使用依赖注入</a></p>
</li>
<li>
<p><a href="#heading-clean-project-structures">📂 清理项目结构</a></p>
</li>
<li>
<p><a href="#heading-be-consistent-with-formatting">🤹‍♂️ 格式保持一致</a></p>
</li>
<li>
<p><a href="#heading-stop-hardcoding-values">✋ 停止硬编码值</a></p>
</li>
<li>
<p><a href="#heading-keep-functions-short">🤏 保持函数简短</a></p>
</li>
<li>
<p><a href="#heading-follow-the-boy-scout-rule">⛺ 遵循童子军原则</a></p>
</li>
<li>
<p><a href="#heading-follow-the-openclosed-principle">🏟️ 遵循开放/封闭原则</a></p>
</li>
</ul>
</li>
<li>
<p><a href="#heading-modern-best-practices-to-help-you-write-clean-code-a-summary">帮助你编写整洁代码的现代最佳实践：总结 🥷</a></p>
</li>
<li>
<p><a href="#heading-automated-tools-for-maintaining-clean-code">保持代码整洁的自动化工具 ⚓</a></p>
<ul>
<li>
<p><a href="#heading-1-static-analysis">1️⃣ 静态分析</a></p>
</li>
<li>
<p><a href="#heading-2-automated-code-formatting">2️⃣ 自动代码格式化</a></p>
</li>
<li>
<p><a href="#heading-3-continuous-integration-ci-testing">3️⃣ 持续集成 (CI) 测试</a></p>
</li>
<li>
<p><a href="#heading-4-cicd-pipelines">4️⃣ CI/CD 流水线</a></p>
</li>
</ul>
</li>
<li>
<p><a href="#heading-the-role-of-documentation-in-agile-software-development">文档在敏捷软件开发中的角色 🚣</a></p>
</li>
<li>
<p><a href="#heading-conclusion">结论 🏁</a></p>
</li>
<li>
<p><a href="#heading-frequently-asked-questions-about-clean-code">关于代码整洁的常见问题 🧯</a></p>
</li>
</ol>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xh3j6ccn1hc3euc3lfyl.png" alt="敏捷软件开发梗图" width="3125" height="1250" loading="lazy"></p>
<p>在敏捷中，变化是唯一不变的，干净的代码是你的盔甲。它使你具有适应性、敏捷性，最重要的是，它使你能够掌控局面。</p>
<p>事实是：如果你想在软件开发行业中生存，编写整洁代码绝非可有可无，而是必须掌握的能力。幸运的是，我们人类通过努力和练习终能掌握整洁代码的精髓。</p>
<h2 id="heading-the-cost-of-bad-code">坏代码的成本</h2>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wdai6npb55j71sguj6kl.png" alt="混乱代码与整洁代码成本对比图表 by shahan" width="500" height="600" loading="lazy"></p>
<p>为了解释这个堆叠条形图，在初始开发阶段，坏代码比整洁代码的变更成本<strong>稍微</strong>高一些。</p>
<p>但是当我们进入维护和重构阶段时，这个差距显著扩大，坏代码的成本几乎是整洁代码的两倍。</p>
<p>到了代码变成遗留代码时，坏代码的变更成本达到100%——现在升级它非常昂贵，而整洁代码仍然更易于管理，仅为45%。</p>
<p>目前，美国关于软件低质量成本的最新分析仍是信息与软件质量联盟（Consortium for Information and Software Quality，CISQ，网站：cisq.org）发布的2022年报告。在这份报告中，经估计，2022年软件低质量给美国经济造成了至少2.41万亿美元的损失，其中技术债务（technical debt）约占1.52万亿美元。</p>
<p>你可以<a href="https://www.it-cisq.org/the-cost-of-poor-quality-software-in-the-us-a-2022-report/">在这里阅读更多内容</a>。</p>
<p>近期的讨论继续强调技术债务对软件质量和业务绩效的显著影响。</p>
<p>例如，<a href="https://vfunction.com/blog/how-to-manage-technical-debt">2024年的一项调查</a>指出，超过50%的公司认为技术债务占其IT总预算的四分之一以上。如果不加以解决，这确实会阻碍创新。</p>
<p>如你所见，毫无疑问，在软件开发中，坏代码是一个代价高昂的问题。</p>
<h2 id="heading-clean-coder-vs-messy-coder">清洁编码者 vs. 混乱编码者</h2>
<p>这是一个展示<strong>两种</strong>编码者历程的图表：</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c6ubf77uwipf4gtucw8q.png" alt="整洁代码 vs 坏代码图表" width="604" height="340" loading="lazy"></p>
<ul>
<li>
<p><strong>⚠️ 混乱编码者（红线）：</strong> 起步快但坠落得更惨。他们写的行数越多，问题也越多。</p>
</li>
<li>
<p><strong>⚡ 清洁编码者（蓝线）：</strong> 开始慢但保持一致。增长不会停止——它会加速。</p>
</li>
</ul>
<p>🫵 现在，你可以决定想走哪条线。</p>
<h2 id="heading-ai-cant-save-you-if-your-code-is-a-mess">如果你的代码一团糟，AI 也救不了你 🗑️</h2>
<p>当你陷入写代码的困境时，你可能会求助于 AI。但让我告诉你：如果你的代码一团糟，AI 也救不了你。</p>
<p>这就像是在沙子上建房子。没错，它会暂时站立，但一旦有强风或大浪，就会倒塌。</p>
<p>请记住：AI 只是一个工具。如果你不知道如何编写清晰、可扩展的应用程序，就是在为失败埋下伏笔。</p>
<p>我反复看到了这样的情况：那些熟悉五种编程语言的开发者，他们能构建应用程序、网站、软件，他们对算法和数据结构了如指掌。</p>
<p>但当面对大型项目或别人的混乱代码时，他们崩溃了。</p>
<p>他们就像一位能设计和建造自己飞机的航天工程师，但却不知道如何驾驶它们。他们在自己的代码中坠毁。</p>
<p>这曾经是我...... 从前的我。我会写上数千行代码，但却发现自己连上周写的东西都无法理解。对我来说，那是一片混乱。</p>
<p>然后我恍然大悟 —— 每个开发者都在为此苦苦挣扎。问题不在于我知道多少，而在于我如何组织和结构化我所知道的东西。换句话说，这取决于对编程艺术本身的理解。</p>
<p>我决定摆脱这个陷阱。经过五个月的密集工作——每天写作、设计和研究四到五个小时——我创造了当初学编程时梦寐以求的工具，一本完整的初学者指南：<strong>《整洁代码从零到一》</strong>。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737731329839/c4c862d9-7fdc-460a-ae2e-18b19468b6ec.png" alt="《整洁代码从零到一》封面图片：从混乱代码到杰作" width="1920" height="1080" loading="lazy"></p>
<p>如果你想了解更多关于这本书的信息，我会在本教程的结尾告诉你所有的细节。所以继续阅读以了解更多关于编写整洁代码的内容。</p>
<h2 id="heading-12-clean-code-design-patterns-for-building-agile-applications">构建敏捷应用程序的 12 种整洁代码设计模式 ⚖️</h2>
<p>如果你的代码不遵循这些现代整洁代码设计模式，你可能正在制造一个定时炸弹。这些模式是你的工具。掌握它们并享受项目成功的乐趣。让我一一展示给你看。</p>
<h3 id=""><strong>🌿 使用有意义的名称</strong></h3>
<p>将你的变量或函数命名为 b 或 x 并没有帮助。将它们称为何物以便于理解。以下是一个坏变量名与好变量名的例子：</p>
<pre><code>// 弱且模糊
let b = 5;

// 强且清晰
let numberOfUsers = 5;
</code></pre>
<p>那些写出不清晰名字的人不愿为自己的错误负责。不要成为那样的人。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736165724746/37b2edc3-3c68-47a8-ab6f-f131a2239a01.png" alt="Shahan创作的关于不良变量名和良好变量名的漫画" width="2000" height="800" loading="lazy"></p>
<h3 id="srp"><strong>🔨 保持函数的专注性 (SRP)</strong></h3>
<p>一个函数应该做到<strong>一件事</strong>——并做到完美。这就是单一职责原则（<strong>SRP</strong>）。</p>
<p>好的代码就像一把锤子。它只打一根钉子，不会打十根。例如，如果你招聘一个人来处理公司里的所有事情——财务、销售、市场营销、清洁工作等等——他们很可能会因为无法专注而惨败。同样的道理适用于你代码中的类。</p>
<p>🚧 当一个类或函数做超过一件事时，就会变成一团乱麻。调试它就像在倒着拼拼图。比如，如果你的类既要处理用户输入又要操作数据库，这不是多任务并行，而是逻辑混乱。将其拆分，遵循一个方法只做一件事的原则。</p>
<p><strong>🔥 我的法则：</strong> 你的代码为你工作。保持它精炼、专注且可控，否则它会控制你。以下是实现这一目标的方法：</p>
<pre><code>// 整洁代码：专注于单一任务
function calculateTotal(a, b) {
    return a + b;
}

function logTotal(user, total) {
    console.log(`User: ${user}, Total: ${total}`);
}

// 混乱代码：尝试做所有事情
function calculateAndLogTotal(a, b, user) {
    let total = a + b;
    console.log(`User: ${user}, Total: ${total}`);
}
</code></pre>
<p>🪧 任务混在一起，混乱也就随之而来。就这么简单。</p>
<h3 id=""><strong>🚪 谨慎使用注释</strong></h3>
<p>职业开发者中有一句名言：</p>
<blockquote>
<p>“代码自有其解释。”</p>
</blockquote>
<p>当有人走进房间时，你不会每次都解释门是做什么用的，对吧？你的代码也该如此。</p>
<p>加注释没错，但如果代码不加注释就看不懂，那代码本身可能就有毛病。</p>
<p>🪧 好的注释要讲“为什么”，而不是“怎么做”或“是什么”。如果开发者连代码是怎么工作的都看不懂，那他们更不可能理解背后的“为什么”。</p>
<p>以下是一些好的注释与坏的注释的简短例子。我还将向你展示一个编写清洁注释的实际项目。</p>
<p><strong>例子1：糟糕的注释 👎</strong></p>
<pre><code>// 将价格乘以数量以计算总数
const total = price * quantity;
</code></pre>
<p>这是一个<strong>糟糕的注释</strong>，因为它只是重复了代码已经说明的内容。代码 <code>price * quantity</code> 本身已经很清晰，因此这个注释没有增加任何有用的信息。</p>
<p><strong>好注释：👍</strong></p>
<p>如果代码清晰简明，<strong>你不需要注释。</strong></p>
<pre><code>const total = price * quantity;
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736165891398/6a942ad7-5b09-4990-9c7f-95358dafcbf3.png" alt="Shahan创作的说明不必要注释与“无声注释”的图像" width="2000" height="800" loading="lazy"></p>
<p><strong>例子2：糟糕的注释 👎</strong></p>
<pre><code>// 检查用户是否登录
function isUserLoggedIn(session) {
    return !!session.user;
}
</code></pre>
<p>这个注释不好，因为它没有解释 <code>isUserLoggin()</code> 的存在原因。它只是解释了正在发生的事情。但我们已经知道这是一个身份验证函数。这个注释是浪费时间。</p>
<p><strong>好例子 👍</strong></p>
<pre><code>// 用户在访问受保护的资源之前已经通过认证
function isUserLoggedIn(session) {
    return !!session.user;
}
</code></pre>
<p>这是一个<strong>好的注释</strong>，因为它解释了代码存在的<strong>原因</strong>。它告诉我们函数在允许访问应用程序的敏感部分之前检查用户是否已认证。它关注的是更大的图景。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736166143011/b3ddae3d-41cf-4534-8f1a-af710579922c.png" alt="之前：“检查用户是否已登录”。之后：“用户在访问受保护的资源之前已经通过认证。”作者：Shahan。" width="2000" height="800" loading="lazy"></p>
<h3 id=""><strong>⚡ 编写优秀注释的最佳实践</strong></h3>
<ol>
<li>
<p><strong>解释“为什么”，而不是“什么”：</strong><br>
写注释是为了解释代码的目的或背景，而不是代码正在做什么。</p>
</li>
<li>
<p><strong>避免明显的注释：</strong><br>
不要为代码已经清晰的部分写注释。</p>
</li>
<li>
<p><strong>保持简短和精确：</strong><br>
写简洁的注释，方便阅读，并直接解释目的。</p>
</li>
<li>
<p><strong>定期更新注释：</strong><br>
过时的注释可能误导开发者，所以在代码更改时务必更新注释。</p>
</li>
</ol>
<p><strong>现实世界中的例子（使用好的注释） 🛒</strong></p>
<p>让我们把这些实践应用到一个真实项目中：一个大型电子商务应用程序。一个函数根据订单详情计算运输成本。下面是完整的代码，我将在下面解释每个注释：</p>
<pre><code>// 运输规则：
// - 订单超过 $100 免费运输
// - 低于 $100 的订单标准运输（$10）
// - 国际订单额外 $5

function calculateShipping(order) {
    let shippingCost = 0;

    // 检查订单是否符合免费运输条件
    if (order.total &gt;= 100) {
        shippingCost = 0; // 免费运输
    } else {
        shippingCost = 10; // 标准运输费用
    }

    // 为国际订单增加额外费用
    if (order.isInternational) {
        shippingCost += 5;
    }

    return shippingCost;
}

// 示例使用
const order1 = { total: 120, isInternational: false };
const order2 = { total: 80, isInternational: true };

console.log(calculateShipping(order1)); // 输出：0
console.log(calculateShipping(order2)); // 输出：15
</code></pre>
<p>在函数的开始，我们包含了一个注释来解释运输费用的规则。这使读者在不需要阅读完整代码的情况下获得逻辑概览。</p>
<pre><code>// 运输规则：
// - 订单超过 $100 免费运输
// - 低于 $100 的订单标准运输（$10）
// - 国际订单额外 $5
</code></pre>
<p>然后，第一个条件检查订单总额是否大于或等于 $100。这里的注释明确了为什么会应用免费运输。</p>
<pre><code>// 检查订单是否符合免费运输条件
if (order.total &gt;= 100) {
    shippingCost = 0; // 免费运输
}
</code></pre>
<p>第二个条件为国际运输应用附加收费。注释解释了为何增加额外费用。</p>
<pre><code>// 为国际订单增加额外费用
if (order.isInternational) {
    shippingCost += 5;
}
</code></pre>
<p><strong>为什么这些注释很好？</strong></p>
<p>想象一下你正身处一个 20 人的开发团队。六个月后，有人读到了 <code>calculateShipping</code> 这个函数。如果没有这些注释，他们可能得浪费大把时间去猜测为什么国际订单会有一笔额外费用。好的注释能阐明背后的原因，避免让人陷入数小时的烦躁和困惑中。</p>
<h3 id=""><strong>🧩 让你的代码可读</strong></h3>
<p>如果别人看你的代码感觉像是在“破译密码”，那你已经在给团队“埋坑”了。不信请看：</p>
<pre><code>// 干净：读起来像看故事一样
if (isLoggedIn) {
    console.log("Welcome!");
} else {
    console.log("Please log in.");
}

// 杂乱：感到困惑
if(isLoggedIn){console.log("Welcome!");}else{console.log("Please log in.");}
</code></pre>
<p>如果你的代码杂乱且难以阅读，它会让他人甚至是你自己感到困惑！想象六个月后回到自己写的代码却感觉像在读一种外语。可读性高的代码节省时间，减少错误，使每个人的生活更轻松。</p>
<p><strong>🍵 为什么可读性很重要？</strong></p>
<ol>
<li>
<p><strong>对于你自己：</strong> 当你在几周或几个月后重新访问代码时，整洁的代码能帮助你在不浪费时间弄清楚自己做了什么的情况下继续进行接下来的工作。</p>
</li>
<li>
<p><strong>对于你的团队：</strong> 如果其他人阅读你的代码，他们不应该像是在解谜题。整洁的代码让团队合作更顺畅，防止沟通不畅。</p>
</li>
<li>
<p><strong>更少的错误：</strong> 清晰的代码更易于调试，因为你能快速发现错误。</p>
</li>
</ol>
<p><strong>🧙‍♂️ 如何编写可读的代码</strong></p>
<p>让我们构建一个简单的程序来管理图书馆中的书籍。我们将使其整洁和可读，接下来我将分解这段代码：</p>
<pre><code>// 一个表示书籍的类
class Book {
    constructor(title, author, isAvailable) {
        this.title = title;
        this.author = author;
        this.isAvailable = isAvailable;
    }

    borrow() {
        if (this.isAvailable) {
            this.isAvailable = false;
            console.log(`You borrowed "${this.title}".`);
        } else {
            console.log(`Sorry, "${this.title}" is not available.`);
        }
    }

    returnBook() {
        this.isAvailable = true;
        console.log(`You returned "${this.title}".`);
    }
}

// 一个用于展示可用书籍的函数
function displayAvailableBooks(books) {
    console.log("Available books:");
    books.forEach((book) =&gt; {
        if (book.isAvailable) {
            console.log(`- ${book.title} by ${book.author}`);
        }
    });
}

// 示例使用
const book1 = new Book("The Clean Coder", "Robert Martin", true);
const book2 = new Book("You Don’t Know JS", "Kyle Simpson", false);
const book3 = new Book("Eloquent JavaScript", "Marijn Haverbeke", true);

const library = [book1, book2, book3];

displayAvailableBooks(library); // 显示可用的书籍
book1.borrow(); // 借阅一本书
displayAvailableBooks(library); // 再次显示可用的书籍
book1.returnBook(); // 归还这本书
displayAvailableBooks(library); // 最终列表
</code></pre>
<p>我们创建了一个 <code>Book</code> 类来表示每本书。它具有像 <code>title</code>、<code>author</code> 和 <code>isAvailable</code> 这样的属性来追踪其状态。</p>
<ul>
<li><code>borrow</code> 方法检查书籍是否可用。如果是，则将其标记为不可用并打印一条消息。</li>
<li><code>returnBook</code> 方法使书籍再次可用。</li>
<li><code>displayAvailableBooks</code> 函数循环遍历图书馆，只打印可用的书籍。</li>
<li>我们创建了三本书（<code>book1</code>、<code>book2</code>、<code>book3</code>）并将它们存储在一个 <code>library</code> 数组中。</li>
<li>我们借阅和归还书籍，展示了可用书籍列表如何变化。</li>
</ul>
<p>如你所见，可读代码不仅仅关乎风格。它能节省时间、防止错误，并确保你的代码在未来多年仍能发挥作用。</p>
<h3 id=""><strong>🏌️ 测试你写的所有内容</strong></h3>
<p>如果你不花时间编写测试，那么代码出故障时就别感到意外。如果你打算编写测试，请遵循这套单元测试策略，以便及早发现问题。</p>
<p><strong>什么是单元测试？</strong></p>
<p>具体来说，单元测试检查代码的各个部分（如函数或类）以确保其正常工作。就像在建造房子的墙之前检查每一块砖是否完好一样。</p>
<p>让我给你一个单元测试工作原理的例子：</p>
<pre><code class="language-javascript">class Calculator {
    add(a, b) { return a + b; }
    subtract(a, b) { return a - b; }
}

// 测试它（单元测试）
const calculator = new Calculator();
console.assert(calculator.add(2, 3) === 5, "加法失败");
console.assert(calculator.subtract(5, 3) === 2, "减法失败");
</code></pre>
<p>让我们来看看这段代码是怎么运行的：</p>
<p>首先，我们要先构建一个计算器类：</p>
<pre><code class="language-javascript">class Calculator {
    add(a, b) { return a + b; }
    subtract(a, b) { return a - b; }
}
</code></pre>
<p><code>Calculator</code> 类有两个方法：<code>add</code> 和 <code>subtract</code>。</p>
<ul>
<li><code>add(a, b)</code> 接受两个数字并返回它们的和。</li>
<li><code>subtract(a, b)</code> 接受两个数字并返回它们的差。</li>
</ul>
<p>接下来，我们设置测试：</p>
<pre><code class="language-javascript">const calculator = new Calculator();
</code></pre>
<p>在这里，我们创建一个 <code>Calculator</code> 类的实例以测试其方法。</p>
<p>然后我们编写测试用例：</p>
<pre><code class="language-javascript">console.assert(calculator.add(2, 3) === 5, "加法失败");
console.assert(calculator.subtract(5, 3) === 2, "减法失败");
</code></pre>
<p><code>console.assert(condition, message)</code> 检查条件是否为 <code>true</code>。如果是 <code>false</code>，则消息（“加法失败”或“减法失败”）将显示在控制台中。</p>
<ul>
<li>
<p><strong>第一次测试</strong>：<code>calculator.add(2, 3) === 5</code></p>
<ul>
<li>调用 <code>add</code> 方法，给出 <code>2</code> 和 <code>3</code>。</li>
<li>检查结果是否为 <code>5</code>。</li>
</ul>
</li>
<li>
<p><strong>第二次测试</strong>：<code>calculator.subtract(5, 3) === 2</code></p>
<ul>
<li>调用 <code>subtract</code> 方法，给出 <code>5</code> 和 <code>3</code>。</li>
<li>检查结果是否为 <code>2</code>。</li>
</ul>
</li>
</ul>
<p>那么如果出错了会发生什么呢？在这里解决出现的问题是相当简单的。在这种情况下，如果 <code>add</code> 或 <code>subtract</code> 方法不能正常工作，测试将失败。例如：</p>
<pre><code class="language-javascript">console.assert(calculator.add(2, 3) === 6, "加法失败");
</code></pre>
<ul>
<li>条件 <code>calculator.add(2, 3) === 6</code> 是 <code>false</code>。</li>
<li>控制台将显示：“加法失败”。</li>
</ul>
<p><strong>实际例子：测试一个登录系统 👥</strong></p>
<p>让我们测试一个简单的登录系统，看看单元测试在实际场景中如何工作。</p>
<pre><code class="language-javascript">class Auth {
    login(username, password) {
        return username === "admin" &amp;&amp; password === "1234";
    }
}

// 测试 Auth 类
const auth = new Auth();
console.assert(auth.login("admin", "et5t45#@") === true, "有效凭证登录失败");
console.assert(auth.login("user", "wrongpassword") === false, "无效凭证登录成功");
</code></pre>
<p>首先，创建 <code>Auth</code> 类：</p>
<pre><code class="language-javascript">class Auth {
    login(username, password) {
        return username === "admin" &amp;&amp; password === "1234";
    }
}
</code></pre>
<p><code>login</code> 方法检查用户名是否为 <code>"admin"</code> 且密码是否为 <code>"1234"</code>。如果两者都匹配，则返回 <code>true</code>，否则返回 <code>false</code>。</p>
<p>接下来，设置测试：</p>
<pre><code class="language-javascript">const auth = new Auth();
</code></pre>
<p>创建一个 <code>Auth</code> 类的实例。然后编写测试用例：</p>
<pre><code class="language-javascript">console.assert(auth.login("admin", "1234") === true, "有效凭证登录失败");
console.assert(auth.login("user", "wrongpassword") === false, "无效凭证登录成功");
</code></pre>
<ul>
<li><strong>第一次测试</strong>：检查有效凭证（<code>"admin"</code>，<code>"1234"</code>）是否成功。如果不成功，就会显示 “有效凭证登录失败”。</li>
<li><strong>第二次测试</strong>：检查无效凭证（<code>"user"</code>，<code>"wrongpassword"</code>）是否失败。如果没有失败，就会显示 “无效凭证登录成功”。</li>
</ul>
<p><strong>🌱 为什么测试会导致干净的代码：</strong></p>
<ol>
<li>
<p>为了提高代码的可测试性，你会自然而然地编写更短小、更专注的函数。</p>
</li>
<li>
<p>测试能验证你的代码在不同场景下的表现是否符合预期。</p>
</li>
<li>
<p>有了测试作为保障，你可以放心大胆地更新代码，因为你知道任何错误都会被测试及时发现。</p>
</li>
</ol>
<h3 id=""><strong>💉 使用依赖注入</strong></h3>
<p>将依赖硬编码就像在额头上纹上某人的名字——它是永久性的，可能是磨蚀性的，并且限制了你的选择。</p>
<p>那么，依赖注入做了什么？它通过将依赖关系作为参数传递来管理代码的关系。它是灵活、可适应且易于维护的。</p>
<p>为了演示其工作原理，我这里使用 Nodemailer 依赖项向用户发送电子邮件：</p>
<pre><code>// 依赖：使用 Nodemailer 发送电子邮件
const nodemailer = require('nodemailer');
function sendEmail(to, subject, message) {
    const transporter = nodemailer.createTransport({ /* 配置 */ });
    return transporter.sendMail({ from: "programmingwithshahan@gmail.com", to, subject, text: message });
}
</code></pre>
<p>⚠️ 为了避免风险，请确保避免将依赖关系<strong>硬编码</strong>。使用抽象或配置文件进行安全维护。</p>
<p>这只是一个例子。作为开发人员，你可能会使用数百个库或依赖项。</p>
<p>我并不是说你绝对不应该依赖依赖项/库，因为如今很难避免它们。但在将它们安装到你的编码项目中之前，你应该非常小心。</p>
<p>你应该检查组织的软件系统的安全性、性能、质量或功能。因为它们有时可能包含会毁掉你整个项目的风险。</p>
<p>🚧 永远要控制你的工具，不要让它们控制你。</p>
<h3 id=""><strong>📂 清理项目结构</strong></h3>
<p>一个组织良好的项目就像一座高端<strong>精品店</strong>与一堆<strong>垃圾堆</strong>的区别。</p>
<p>以下是每个文件夹的组织方式：</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9xwyg9iqqcybz21lsgxz.png" alt="Shahan 的整洁代码项目结构图" width="1563" height="1250" loading="lazy"></p>
<p>如果你的代码库像个杂物抽屉，那你已经给未来的自己制造了麻烦。</p>
<p>让我们浏览上面的干净项目结构，以更好地理解它：</p>
<p><strong>1.</strong> <code>myProjet/src</code></p>
<p>这是整个应用程序的主容器。应用所需的一切都存储在这个文件夹中。它有子文件夹，可以保持整洁并在一个地方管理。</p>
<p><strong>2.</strong> <code>components</code></p>
<p>这是存放应用所有可重用部分的地方。你可以在多个地方使用这些组件，而无需再次构建它们。</p>
<p><strong>3.</strong> <code>services</code></p>
<p>这是应用的“大脑”。它在前端和后端为幕后工作提供支持。<code>emailService.js</code>、<code>userService.js</code> 和 <code>productService.js</code> 是 <code>services</code> 文件夹的一些示例文件。</p>
<p><strong>4.</strong> <code>utils</code></p>
<p>这包含了所有运行应用程序所需的小工具，使你的生活更轻松。例如，<code>formatedate.js</code>、<code>validateEmail.js</code> 和 <code>generateId.js</code> 是一些常见的 utils 文件，用于为整个项目制作可重用的组件。</p>
<p><strong>5.</strong> <code>tests</code></p>
<p>根据惯例，测试文件通常位于项目根级别的 <code>src</code> 文件夹<strong>之外</strong>。这样可以将生产代码（<code>src</code>）与测试代码（<code>tests</code>）分隔开，使其更清晰易于管理。查看下面结构：</p>
<pre><code>myProject/
├── src/              # 生产代码
│   ├── components/
│   ├── services/
│   └── utils/
├── tests/            # 测试文件
│   ├── components/
│   ├── services/
│   └── utils/
├── package.json      # 项目配置
└── README.md         # 文档
</code></pre>
<p>一些开发人员可能更喜欢在 <code>test</code> 文件夹中创建一个测试文件来测试所有内容。遗憾的是，一开始它看起来很整洁，但随着项目的发展，你将不得不寻找和搜索特定代码块。这样显得杂乱无章，并可能产生意外的测试结果。因此，强烈建议在 <code>tests</code> 文件夹中将它们分解成多个测试文件。</p>
<p><strong>一个实际的例子 📧</strong></p>
<p>让我为你创建一个干净、耐用的项目结构，以便在任何将来可能从事的项目中应用。不用说，干净的项目结构是构建可维护项目的基础。</p>
<p>根据我们之前的发送电子邮件应用程序的示例，我们将为该应用程序编写一个干净的项目结构。我们希望构建一个向用户发送电子邮件的应用程序。此应用的干净项目结构应如下所示：</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6v6rlc5qiplgxz1h4dps.png" alt="Shahan 的邮箱应用整洁代码项目结构图" width="1563" height="1250" loading="lazy"></p>
<p>如你所见，我将每个子文件夹和文件都打包在应用的主容器 <code>src</code> 文件夹中。在 <code>src</code> 文件夹中，我们创建了 <code>components</code>、<code>services</code>、<code>utiles</code>。最后，我们在 <code>src</code> 文件夹外有一个可管理的 <code>test</code> 文件夹，以独立测试每个组件。这个测试文件夹与位于 <code>src</code> 文件夹中的生产代码没有任何关系。</p>
<h3 id=""><strong>🤹‍♂️ 保持格式一致性</strong></h3>
<p>别让你的代码看起来像是出自不同的十个人一样。请务必保持格式风格的一致性。</p>
<p>使用 <a href="https://prettier.io/">Prettier</a> 或 <a href="https://eslint.org/">ESLint</a> 等工具强制执行一致的风格。如果每个文件都看起来不同，你只是在制造没人愿意解决的混乱。</p>
<p>我认为格式一致性是编写整洁代码的最重要方面之一。</p>
<pre><code>// 始终使用2个空格进行缩进
function calculateArea(width, height) {
  if (width &lt;= 0 || height &lt;= 0) {
    throw new Error("维度必须是正数。");
  }
  return width * height;
}

// 添加有意义的空白以提高可读性
const rectangle = {
  width: 10,
  height: 20,
};

// 清晰的逻辑分离
try {
  const area = calculateArea(rectangle.width, rectangle.height);
  console.log(`面积: ${area}`);
} catch (error) {
  console.error(error.message);
}
</code></pre>
<p>让我们来分析一下，这段代码在哪些方面体现了“整洁之道”：</p>
<h4 id="1">1️⃣ 一致的缩进</h4>
<p>为什么用2个或4个空格？这很简洁、最小化，并且被许多JavaScript风格指南普遍接受。它不会让眼睛感到负担，并且代码结构清晰。如果你在这里用2个空格，那里用4个空格，就会让人感到困惑——而困惑时容易犯错。</p>
<h4 id="2">2️⃣ 有意义的空白：给代码留出呼吸空间</h4>
<p>在<code>rectangle</code>定义和<code>try</code>块之间的额外换行就像句子中的停顿——它让读者有时间去处理信息。</p>
<h4 id="3">3️⃣ 清晰的逻辑分离：模块化思维</h4>
<pre><code>try {
  const area = calculateArea(rectangle.width, rectangle.height);
  console.log(`Area: ${area}`);
} catch (error) {
  console.error(error.message);
}
</code></pre>
<p>看看代码逻辑是如何被分成清晰的部分：</p>
<ul>
<li>
<p>首先是计算（<code>calculateArea</code>函数）。</p>
</li>
<li>
<p>然后是输出（<code>console.log</code>）。</p>
</li>
<li>
<p>最后是错误处理（<code>catch</code>块）。</p>
</li>
</ul>
<p>每个任务都有其独立的空间和明确的职责。</p>
<h4 id="4">4️⃣ 可读的错误处理</h4>
<p>当你抛出错误或记录消息时，请整洁地格式化它们。不要使用模糊或隐晦的信息。看到这样的代码，开发者立刻就能知道出了什么问题。</p>
<pre><code>throw new Error("维度必须是正数。");
</code></pre>
<p><strong>🐦‍⬛ 常规的格式一致性建议：</strong></p>
<ul>
<li>
<p>在整个代码库中一致地使用2个或4个空格进行缩进。避免使用制表符，以维护在不同编辑器间的一致性。</p>
</li>
<li>
<p>将每行的字符数限制在最多100-120个以内，以防止水平滚动并提高可读性。</p>
</li>
<li>
<p>将相关逻辑集中在一起，用空行分隔代码块以突出强调其用途。</p>
</li>
<li>
<p>最后，避免过度对齐代码。相反，让缩进自然引导逻辑流程。</p>
</li>
</ul>
<h3 id=""><strong>✋ 停止硬编码值</strong></h3>
<p>硬编码值是一种懒惰的编码方式。以下是证明：</p>
<pre><code>// 糟糕：硬编码且僵化
function createUser() {
    const maxUsers = 100;
    if (currentUsers &gt;= maxUsers) throw "用户太多！";
}

// 简洁：动态且灵活
const MAX_USERS = 100;
function createUser() {
    if (currentUsers &gt;= MAX_USERS) throw "用户太多！";
}
</code></pre>
<p>你看，改变这个变量将来不会让你感到意外。你确切地知道在哪里可以找到它来改变不确定的值。</p>
<p>最好将固定值存储在全局配置（配置）文件中。</p>
<p>🪧 因此，无论如何避免硬编码。硬编码看似捷径，却可能让未来的自己（或他人）抓狂。</p>
<h3 id=""><strong>🤏 保持函数简洁</strong></h3>
<p>如果你的函数超过20行，可能它试图做得太多了。</p>
<p>短小精悍的函数总是能命中目标。</p>
<p>冗长的函数又乱又难读，而短小的函数则清晰且集中。以下是你应如何将大型函数拆解：</p>
<pre><code>function updateCart(cart, item) {
    addItemToCart(cart, item);
    let total = calculateTotal(cart);
    logTransaction(item, total);
    return total;
}

function addItemToCart(cart, item) {
    cart.items.push(item);
}
</code></pre>
<p>让我解释一下这段代码，以便你理解为何将大型函数拆分是一个明智的策略。</p>
<ol>
<li>
<p><strong>主函数：</strong> <code>updateCart()</code> 调用较小的辅助函数来处理特定的任务，如：</p>
<ul>
<li>
<p>将物品添加到购物车。</p>
</li>
<li>
<p>计算总价格。</p>
</li>
<li>
<p>记录交易细节。</p>
</li>
<li>
<p>最后，返回总价格。</p>
</li>
</ul>
</li>
</ol>
<p>这并不是一个试图做所有事情的长块代码，而是将任务委派给辅助函数。</p>
<ol start="2">
<li><strong>辅助函数：</strong> <code>addItemToCart()</code> 这个函数<strong>只</strong>负责将物品添加到购物车。如果你需要更改添加物品的方式（例如，检查重复项）。你只需编辑这个小函数，而不必在<code>updateCart</code>中一大块代码中寻找更改。这就是编写整洁代码函数的方式，令人愉悦和易于维护。</li>
</ol>
<p><strong>函数过长会怎样？ 💤</strong></p>
<p>假设你没有拆分<code>updateCart</code>函数。它可能看起来像这样：</p>
<pre><code>function updateCart(cart, item) {
    cart.items.push(item);
    let total = 0;
    for (let i = 0; i &lt; cart.items.length; i++) {
        total += cart.items[i].price;
    }
    console.log(`添加了${item.name}。总价现在是$${total}。`);
    return total;
}
</code></pre>
<p>这里的问题是什么？</p>
<ul>
<li>
<p>它试图做所有事情。</p>
</li>
<li>
<p>特别是当它变得更庞大时，难以阅读。</p>
</li>
<li>
<p>如果出了问题，你将浪费时间去找出问题的所在部分。</p>
</li>
</ul>
<p>现在，选择权在你手中：是继续坚持那种混乱的“全能一把抓”写法，还是开始实践“一个函数只做一件事”的整洁心态？</p>
<h3 id=""><strong>⛺ 遵循童子军规则</strong></h3>
<blockquote>
<p>离开营地时，要比你发现它时更整洁。</p>
</blockquote>
<p>让我来详细解释一下：你不能只顾着自己使用，却留下一个比之前更烂的摊子。那是极不负责任的行为。真正的专业人士总会想办法让事物变得比原来更好。</p>
<p>在编程中，这意味着 <strong>每当你触碰代码库，都要让它变得更好一点。</strong> 去清理冗余、重构混乱的部分、提升可读性。如果你不这么做，你只是在不断堆积垃圾，而这些“屎山”最终会崩塌并砸到你自己头上。</p>
<p>来看这个例子。在这里，我们没有选择优化，而是仅仅增加了一层又一层的复杂度：</p>
<pre><code>// 原始代码：难以阅读，变量命名不好
function calc(a, b) {
  let x = a + b;
  let y = x * 0.2;
  return y;
}

// 我们只是不断添加而未进行清理
function calcDiscount(a, b, discountRate) {
  let total = calc(a, b);
  let final = total - discountRate;
  return final;
}
</code></pre>
<p>之后：每次都有所改善。这是一个有纪律的程序员的工作方式——他们在改进中前行：</p>
<pre><code>// 改进后的代码：清晰的命名，重构以提高清晰度
function calculateSubtotal(price, quantity) {
  return price * quantity;
}

function calculateDiscountedTotal(price, quantity, discountRate) {
  const subtotal = calculateSubtotal(price, quantity);
  const discount = subtotal * discountRate;
  return subtotal - discount;
}
</code></pre>
<p>现在，任何人一目了然地看出发生了什么。因为我们将代码拆解为更小、更集中的函数。因此，增加新功能不会破坏现有功能。🏕️</p>
<h3 id=""><strong>🏟️ 遵循开放/封闭原则</strong></h3>
<p>这项设计原则建议：代码应当设计成允许扩展，而不必改变现有的基础。</p>
<p>你肯定希望是“增加功能”，而不是每升级一次就把代码“拆了重建”。为了适配新需求而去修改旧代码，简直就像每次买新家具都要把房子推倒重盖一样。这显然是不可持续的。</p>
<p>让我们来看看如何构建更聪明、更具扩展性的代码，让你在增加功能的同时，不会把其他部分搞坏。</p>
<h4 id="">重构前：违反原则的写法</h4>
<p>你写了一个处理支付的类——挺简单的，起初它只支持信用卡支付。</p>
<p>结果你老板突然冒出来说：“嘿，我们现在得接个 PayPal。”</p>
<p>因为你之前没心思学什么代码整洁之道，你的代码现在看起来就像一个从 1995 年过时企业级系统里爬出来的“意面怪物”。来，欣赏一下你亲手打造的这件“杰作”：</p>
<pre><code>class PaymentProcessor {
  processPayment(paymentType, amount) {
    if (paymentType === "creditCard") {
      console.log(`Processing credit card payment of $${amount}`);
    } else if (paymentType === "paypal") {
      console.log(`Processing PayPal payment of $${amount}`);
    } else {
      throw new Error("Unsupported payment type");
    }
  }
}

const paymentProcessor = new PaymentProcessor();
paymentProcessor.processPayment("creditCard", 100);
paymentProcessor.processPayment("paypal", 200);
</code></pre>
<p>唉！每新增一种支付方式（例如 Apple Pay、Google Pay 等），都需要修改 <code>processPayment</code> 方法。不用说，你在添加新功能时有可能破坏现有功能。如果你学过这个原则，你就不会陷入这个困境。</p>
<p>不要担心：我会帮你解决这个问题。首先，我们需要重构代码。我们将通过使用<a href="https://stackify.com/oop-concept-polymorphism/">多态</a>来扩展其功能，而不是修改现有的类：</p>
<pre><code>javascriptCopy code// 基础类
class PaymentProcessor {
  processPayment(amount) {
    throw new Error("processPayment() must be implemented");
  }
}

// 信用卡支付
class CreditCardPayment extends PaymentProcessor {
  processPayment(amount) {
    console.log(`Processing credit card payment of $${amount}`);
  }
}

// PayPal 支付
class PayPalPayment extends PaymentProcessor {
  processPayment(amount) {
    console.log(`Processing PayPal payment of $${amount}`);
  }
}

// 添加新的支付类型？只需扩展类！
class ApplePayPayment extends PaymentProcessor {
  processPayment(amount) {
    console.log(`Processing Apple Pay payment of $${amount}`);
  }
}

// 使用方法
const payments = [
  new CreditCardPayment(),
  new PayPalPayment(),
  new ApplePayPayment(),
];

payments.forEach((payment) =&gt; payment.processPayment(100));
</code></pre>
<p>现在，添加新的支付方式不再需要修改现有的 <code>PaymentProcessor</code> 类了，你只需要创建一个新的子类。这样一来，原有代码保持原封不动，意味着完全没有破坏现有功能的风险。</p>
<p>每种支付类型都有独立的类。比如添加 PayPal 支持，完全不会影响到老代码。现在你可以自信地回复老板：“没问题，我 5 分钟就能把这功能加上。” 升职加薪的机会正等着你呢！</p>
<p>我在我的书 <a href="https://codewithshahan.gumroad.com/l/cleancode-zero-to-one">从零到一的整洁代码</a> 中分享了更多的技巧。</p>
<h2 id="heading-modern-best-practices-to-help-you-write-clean-code-a-summary">帮助你编写整洁代码的现代最佳实践：总结 🥷</h2>
<p>现在，让我为你展示最佳实践，并总结这 12 条整洁代码设计原则，助你在敏捷应用开发中游刃有余。</p>
<h3 id="">🔎 常见代码异味及其修复方法</h3>
<ul>
<li>
<p>💊 重复代码： 如果你在复制粘贴代码，那你是在给自己挖坑。把代码抽离成函数，一次性把事做对。</p>
</li>
<li>
<p>🛤️ 过长方法： 如果一个方法长到需要滚动条，那它承载的逻辑就太多了。拆分它，让功能保持专注。</p>
</li>
<li>
<p>👑 万能对象： 没有任何一个类应该包揽所有活儿。简化职责，否则你的代码库迟早会变成一团乱麻。</p>
</li>
</ul>
<h3 id="">💬 高效注释实践</h3>
<ul>
<li>
<p>💭 何时注释： 只有在代码逻辑不够清晰时才写注释。如果代码已经很直观了，注释就是噪音。</p>
</li>
<li>
<p>🫗 清晰度： 注释应该解释 <strong>“为什么”</strong> 而不是“是什么”。如果你的代码非得靠注释才能读懂，那可能它写得太复杂了。</p>
</li>
<li>
<p>🌴 避免冗余： 别给显而易见的代码写注释。如果函数名是 <code>addNumbers</code>，就别再注释说它是用来“加数”的。</p>
</li>
</ul>
<h3 id="">🧼 整洁代码的重构技巧</h3>
<ul>
<li>
<p>🏭 提取方法：方法太臃肿？拆掉它。这不仅仅是为了整洁，更是为了掌控感。</p>
</li>
<li>
<p>🫕 重命名变量：如果变量名不能一眼看出用途，就改掉它。命名的精准度反映了思维的严谨度。</p>
</li>
<li>
<p>🍃 如果你的判断语句写得像代数题一样复杂，简化它。如果是 if (a == true)，直接写成 if (a)。</p>
</li>
</ul>
<h3 id="">🧪 测试与清洁代码</h3>
<ul>
<li>
<p>🧙 单元测试：像审讯嫌疑人一样测试每一行代码。不放过任何死角。</p>
</li>
<li>
<p>🏇 TDD（测试驱动开发）：先写测试。这不只是为了抓 Bug，更是为了在动笔写代码前，就搞清楚它到底该干什么。</p>
</li>
<li>
<p>🧽 清洁测试：测试代码也要写得和业务代码一样整洁。如果测试代码本身就乱七八糟，它就毫无参考价值。</p>
</li>
</ul>
<h3 id="">🐛 错误处理与整洁代码</h3>
<ul>
<li>
<p>⁉️ 异常处理：大胆使用异常。它们不仅能处理错误，还能让你的主逻辑免受错误处理代码的干扰。</p>
</li>
<li>
<p>🖍️ 快速失败：一旦发现异常，立即停止。别让错误雪球越滚越大，当场解决。</p>
</li>
<li>
<p>🚨 日志记录：记录日志要像记录犯罪现场一样。清晰、精准，且只记录必要的信息。</p>
</li>
</ul>
<h3 id="">🌱 代码审查及整洁代码</h3>
<ul>
<li>
<p>🚢 流程化：建立一套系统。拒绝“牛仔式”野路子开发。审查、评判、改进。</p>
</li>
<li>
<p>🔪 工具化：利用工具让审查变得轻松。工具不仅是为了纠错，更是为了培养规范性。</p>
</li>
<li>
<p>🧦 文化建设：营造一种“反馈是金”的文化。帮助团队学会如何给出和接受有建设性的批评。</p>
</li>
</ul>
<h2 id="heading-automated-tools-for-maintaining-clean-code">保持代码整洁的自动化工具 ⚓</h2>
<p>工具和自动化技术对于编写清洁代码非常有帮助。如果你没有使用合适的工具和自动化来节省时间，那就错过了机会。</p>
<p>你认为可以"凭眼力"判断代码质量？再想想吧。没有自动化，这会发生：</p>
<ol>
<li>
<p>👎 因为“太忙”而错过显而易见的错误。</p>
</li>
<li>
<p>🤕 你的代码在每个文件中看起来都不同，协作起来头疼。</p>
</li>
<li>
<p>🪦 部署失败，因为你跳过了关键测试。</p>
</li>
</ol>
<p>成功的开发者使用合适的工具来自动化代码和完成任务。以下是使用现代工具维护清洁代码的四种策略。</p>
<h3 id="1"><strong>1️⃣ 静态分析</strong></h3>
<p>静态分析实际上是一个代码检查器，它在早期找出潜在问题。最棒的是，它在<strong>运行前</strong>工作，捕获可能导致崩溃、停机或令人尴尬的错误。</p>
<h4 id=""><strong>它是如何工作的？</strong></h4>
<ol>
<li>
<p><strong>语法检查</strong>：检查代码中编写的语法是否正确。如果拼写错误或遗漏了闭合括号，它会立即指出。</p>
</li>
<li>
<p><strong>代码质量规则</strong>：像 ESLint 这样的工具强制执行规则，如一致的缩进、避免未使用的变量，以及遵循最佳实践。</p>
</li>
<li>
<p><strong>错误预防</strong>：识别逻辑错误，比如使用未定义的变量或进行无意义的比较。</p>
</li>
</ol>
<p>以下是静态分析的实际操作：</p>
<h4 id="">🚨 在静态分析之前：</h4>
<pre><code class="language-javascript">let sum = (a, b) =&gt; { return a + b; }
console.log(sume(2, 3)); // Typo, unnoticed until runtime
</code></pre>
<ul>
<li><strong>问题</strong>：<code>sume</code>中的拼写错误只有在运行代码时才会导致错误，这可能会导致令人沮丧的调试会话，或者更糟糕的是，在生产环境中中断应用程序。</li>
</ul>
<h4 id="eslint">🚑 使用 ESLint 之后的静态分析：</h4>
<pre><code>codeError: 'sume' is not defined.
</code></pre>
<ul>
<li><strong>解决方案</strong>：ESLint 立即标记拼写错误，你甚至在运行代码之前就发现了问题。早期捕获错误，节省了时间和麻烦。</li>
</ul>
<h3 id="2"><strong>2️⃣ 自动代码格式化</strong></h3>
<p>格式化前：</p>
<pre><code class="language-javascript">function calculate ( x , y ){ return x+ y;}
console.log( calculate (2,3 ) )
</code></pre>
<ul>
<li><strong>问题</strong>：不一致的空格和格式化使代码难以阅读。</li>
</ul>
<h4 id="prettier">使用 Prettier 之后：</h4>
<pre><code class="language-javascript">function calculate(x, y) {
  return x + y;
}
console.log(calculate(2, 3));
</code></pre>
<ul>
<li><strong>解决方案</strong>：自动应用干净、一致、专业的格式。不再挑剔空格或对齐问题。</li>
</ul>
<p>当然了，这些都是基本操作。我讲这些是以防万一，比如你得用记事本手撕代码，或者是在面试这种没有 IDE 助力的环境。</p>
<h3 id="3ci"><strong>3️⃣ 持续集成（CI）测试</strong></h3>
<p>CI 测试确保你对代码的每一次更改都得到自动验证。它就像一个安全网，可以捕捉开发过程中引入的错误。CI 工具在每次推送代码时运行测试，因此在部署后没有任何中断。</p>
<h4 id="ci"><strong>CI 测试如何工作？</strong></h4>
<ol>
<li>
<p><strong>变化触发</strong>：每次提交代码时，CI 工具（如 GitHub Actions、Jenkins）会运行自动测试。</p>
</li>
<li>
<p><strong>反馈</strong>：如果出现问题，它会立即提供反馈。</p>
</li>
<li>
<p><strong>防止代码破坏</strong>：只有干净且工作的代码会被合并到主分支。</p>
</li>
</ol>
<h3 id="4cicd">4️⃣ CI/CD 流水线</h3>
<p>我们也使用 CI/CD 流水线作为一个持续的过程，其中包括代码构建、测试和部署，而 CI 测试是这个过程中专注于自动化代码变更测试的部分。</p>
<p><strong>CI/CD 流水线与 CI 测试的区别：</strong></p>
<ul>
<li>
<p><strong>CI/CD 流水线：</strong> CI/CD 流水线将代码构建、测试和部署整合为一个单一过程。这个过程确保对主分支代码的所有更改都可以发布到生产环境。CI/CD 流水线可以减少部署时间、降低成本并改善团队协作。</p>
</li>
<li>
<p><strong>CI 测试：</strong> CI 测试是自动测试集成到中央代码库中的代码变更的过程。CI 测试专注于确保代码库的稳定性以及解决集成问题。CI 测试帮助开发者构建稳定的、无错误的软件并满足功能需求。</p>
</li>
</ul>
<p>🚧 这些就是 CI 测试和 CI/CD 流水线概念的真正含义。并不像想象中那么复杂。所以让我详细讲解一下使用 GitHub Actions 进行的 CI 测试，因为我们现在通常通过自动化工具运行测试。</p>
<h3 id="githubactionsci"><strong>⚡ 使用 GitHub Actions 进行持续集成（CI）测试</strong></h3>
<p>正如我之前所说，CI 工具会在每次您推送代码或打开拉取请求时运行自动化测试。这确保只有正常工作的、无错误的代码才会被合并到主分支。</p>
<h4 id="githubactionsci">如何使用 GitHub Actions 设置 CI 测试</h4>
<p><strong>步骤 1：创建您的代码库</strong></p>
<p>为您的项目设置一个 GitHub 代码库。然后，使用以下命令将代码推送到 GitHub：</p>
<pre><code>git init
git add .
git commit -m "Initial commit for CI Testing"
git branch -M main
git remote add origin https://github.com/codewithshahan/codewithshahan.git
git push -u origin main
</code></pre>
<p>或者您可以在不使用命令的情况下从 GitHub 账户创建一个新的代码库。只需登录到您的 GitHub 账户并访问仪表板。您会发现一个“New”按钮来创建一个全新的代码库：</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737618697327/dcef8be8-0d08-45d7-8000-34c4c65df425.png" alt="在 GitHub 上创建新代码库的图片由 Shahan 提供" width="1371" height="553" loading="lazy"></p>
<p><strong>步骤 2：添加一个 GitHub Actions 工作流</strong></p>
<p>导航到您代码库的 <strong>Actions</strong> 选项卡。要执行此操作，首先您必须访问 GitHub 上的代码库（创建代码库后您会找到链接）。在此示例中，我创建了一个名为“codewithshahan”的新代码库。在这里，看一下导航栏右侧的 <strong>Actions</strong> 选项卡。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737618879398/7c5aa37a-72be-4701-a8f8-9ea9e05c0d5d.png" alt="GitHub Actions 导航选项卡的图片由 Shahan 提供" width="1885" height="724" loading="lazy"></p>
<p>进入 Actions 选项卡后，向下滚动一点，您会找到 <strong>continuous integration</strong> 部分：</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737619002674/60003e57-f2b2-48f1-bef8-9bde39149faf.png" alt="GitHub Actions 页面上的 CI（持续集成）测试图片由 Shahan 提供" width="1496" height="508" loading="lazy"></p>
<p>选择一个适合您的工作流设置。我将在这个项目中使用 Node.js。</p>
<p>点击配置按钮后，会自动创建一个 <code>node.js.yml</code> 文件，您可以根据目标调整代码。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737619475568/74da6d46-c105-42c8-8662-fc72e9410bda.png" alt="GitHub 自动测试工作流代码段的图片由 Shahan 提供" width="1879" height="854" loading="lazy"></p>
<p>我不会详细说明如何修改 <code>.yml</code> 文件。这取决于您的项目目标和个人偏好。此外，这是一个完全不同的更广泛的话题，鉴于这篇文章已经相当长，我将在以后的文章中再做解释。目前，请坚持这些基础知识。</p>
<p>这个 CI 测试工作流非常适合现代应用程序开发。您的应用程序在包含关键功能（例如：暗模式）、在 GitHub 代码库中直接构建和部署应用程序时保持稳定。通过这种方式，您可以自信地推送代码，确保您的代码始终清晰并准备好投入生产。</p>
<h2 id="heading-the-role-of-documentation-in-agile-software-development">文档在敏捷软件开发中的角色 🚣</h2>
<p>如果您希望您的编码能力达到顶级水准，您需要了解如何编写好的文档。如果您认为文档只是匆忙写下代码如何工作，那么您错了。这是关于解释<strong>为什么</strong>它可以工作，而不仅仅是如何工作。这是大多数人忽视的一点。</p>
<h3 id="1">1. 🚡 创建<strong>有用的文档（解释为什么，而不仅仅是如何）</strong></h3>
<p>当您编写文档时，您不仅仅是写下一些关于如何使用代码的说明。您是在告诉下一个人（或者未来的自己）为什么这个代码段最初存在。这就是好文档和差文档的区别。</p>
<p>糟糕的文档会让人困惑。它们太模糊、太简单，并且没有回答重要的问题。如果您的文档不清晰，这可能意味着您的思考不清晰。您基本上是在说，“我不在乎你是否理解这个，它管用，直接用就行。”这没有帮助。</p>
<p>优秀的文档回答了棘手的问题：</p>
<ul>
<li>
<p>✅ 为什么您选择了这种方法而不是其他方法？</p>
</li>
<li>
<p>✅ 为什么这个函数存在？它解决了什么问题？</p>
</li>
<li>
<p>✅ 为什么您这样编写代码？</p>
</li>
</ul>
<h3 id="2">2. ⏳ <strong>保持文档更新（过时的文档比没有文档更糟）</strong></h3>
<p>过时的文档是最糟糕的。事实上，它可能比没有文档更糟。当你的文档与代码不同步时，你是在给未来的自己（或下一个必须处理它的人）带来巨大的麻烦。</p>
<p>每当代码发生变化，你的文档也必须随之更新。它必须能够反映代码的当前状态。千万不要留下那些过时的信息去误导未来的开发者（甚至是未来的你自己），那只会让他们感到困惑并浪费时间。如果某些内容不再相关，直接删掉它。过时的文档就像凌乱的大脑——它只会拖你的后腿。</p>
<p>要养成定期检查和更新文档的习惯。代码改动的那一刻，文档也必须同步更新。就这么简单。</p>
<h3 id="3">3. 🚆 <strong>整合注释（代码中的良好注释是文档的一部分）</strong></h3>
<p>听好了——代码里的注释应当与文档融为一体。优秀的注释不该是开发者的“拐杖”，仅仅因为他们在别处解释不清楚代码才拿来凑合。注释的作用是升华文档，而不是取而代之。</p>
<p>注释是文档的补充。你应该编写那种清晰易懂、几乎不需要解释的高质量代码；但当某些地方无法做到“一眼看透”时，再加入注释。记住注释的准则：解释 <strong>“为什么（Why）”</strong>，而不是 <strong>“怎么做（How）”</strong>。文档也是同理。别说废话，让代码自己“说话”。注释应当服务于文档的宏观大局，而不是给烂代码打补丁。</p>
<p>🪧 优秀的代码应该是自解释的。先去优化代码逻辑，如果仍有必要，再添加注释进行澄清。保持注释整洁、简短、直击要害。</p>
<p>如果你想写出整洁、高效且易维护的代码，文档就是关键。别再把文档当成事后才补的作业，或者填补空间的废话。它是代码的延伸——是你进行清晰高效沟通的方式。它是留给后人的路线图，更是你思维过程的体现。</p>
<h2 id="heading-conclusion">结论 🏁</h2>
<p>整洁代码并非可有可无的“加分项”，而是那些志在成为领导者的人的“必选项”。它关乎掌控力、效率，以及长期的持续改进。归根结底，它将助你在敏捷软件开发的博弈中脱颖而出。</p>
<p>🪧 如果你想真正精进自己的技艺，请编写整洁的代码，让效率自己证明一切。</p>
<h2 id="heading-frequently-asked-questions-about-clean-code">关于整洁代码的常见问题 🧯</h2>
<ol>
<li>
<p><strong>什么是干净的代码？</strong> 是指不会让你想把电脑扔出窗外的代码。</p>
</li>
<li>
<p><strong>为什么干净的代码在敏捷中很重要？</strong> 因为敏捷注重速度和变化，凌乱的环境中你不可能快速行动。</p>
</li>
<li>
<p><strong>什么是代码异味？</strong> 是你即将失去对代码库控制的迹象。</p>
</li>
<li>
<p><strong>我该如何改善注释？</strong> 只对必要的部分进行注释，并确保每个注释都增加价值而不是噪音。</p>
</li>
</ol>
<p>感谢您的陪伴。您可以访问我的 <a href="https://x.com/shahancd">Twitter 账号</a> 或 <a href="https://www.codewithshahan.com">我的网站</a> 阅读更多关于整洁代码和敏捷应用程序开发的文章。下次再见……继续改进你的代码库。</p>
<p>如果你认真想掌握整洁代码并提升你的编程职业生涯，我的书就是为你而写的：<a href="https://codewithshahan.gumroad.com/l/cleancode-zero-to-one"><strong>从零到一的整洁代码</strong></a>。这本书是你从零到一掌握整洁代码的完整指南，从杂乱到杰作。我正在提供50%的折扣，使用代码“earlybird”——仅限前50本。此外，还有30天的退款保证——无风险，纯奖励。</p>
<!--kg-card-end: markdown--> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 如何成为 AI 辅助编程专家 - 开发者手册 ]]>
                </title>
                <description>
                    <![CDATA[ 在过去的七年里，我一直负责 freeCodeCamp 的基础设施。现在我确信，经验丰富的开发者可以在保持代码质量的同时提升 3-4 倍的编码速度。这就是 AI 辅助开发能够提供的优势。简单来说，使用像 GitHub Copilot 这样的 AI 工具作为你的编码伙伴可以提高效率。它们可以建议代码、帮助你调试以及加快处理重复性任务。 为什么这很重要 传统编码时，你需要自己编写每一行代码、查找文档、弄清语法。有了 AI，你可以：  * 专注于解决问题，而不是记住语法          * 通过实时看到优秀的代码示例更快地学习          * 快速构建项目而不牺牲质量         对于有经验的开发者来说，在 AI ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/how-to-become-an-expert-in-ai-assisted-coding-a-handbook-for-developers/</link>
                <guid isPermaLink="false">6953dfe138384c0457be01cb</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Miya Liu ]]>
                </dc:creator>
                <pubDate>Fri, 09 Jan 2026 11:16:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2026/01/----_20260110202949_190_113.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/how-to-become-an-expert-in-ai-assisted-coding-a-handbook-for-developers/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Become an Expert in AI-Assisted Coding – A Handbook for Developers</a>
      </p><!--kg-card-begin: markdown--><p>在过去的七年里，我一直负责 freeCodeCamp 的基础设施。现在我确信，经验丰富的开发者可以在保持代码质量的同时提升 3-4 倍的编码速度。这就是 AI 辅助开发能够提供的优势。简单来说，使用像 GitHub Copilot 这样的 AI 工具作为你的编码伙伴可以提高效率。它们可以建议代码、帮助你调试以及加快处理重复性任务。</p>
<h3 id="">为什么这很重要</h3>
<p>传统编码时，你需要自己编写每一行代码、查找文档、弄清语法。有了 AI，你可以：</p>
<ul>
<li>
<p>专注于解决问题，而不是记住语法</p>
</li>
<li>
<p>通过实时看到优秀的代码示例更快地学习</p>
</li>
<li>
<p>快速构建项目而不牺牲质量</p>
</li>
</ul>
<p>对于有经验的开发者来说，在 AI 帮助下可以更快地完成任务。但关键是：<strong>你需要了解如何有效使用这些工具</strong>。你也需要有编程背景来做到这一点。</p>
<p>感兴趣吗？让我们深入了解这些已经风靡全球的 AI 编码工具。</p>
<h2 id="">目录</h2>
<ul>
<li>
<p><a href="#essential-ai-terminology">基础 AI 术语</a></p>
</li>
<li>
<p><a href="#when-to-use-ai-vs-when-to-code-yourself">何时使用 AI 以及何时自己编码</a></p>
</li>
<li>
<p><a href="#prerequisites">前提条件</a></p>
</li>
<li>
<p><a href="#your-complete-learning-journey">你的完整学习旅程</a></p>
</li>
<li>
<p><a href="#how-to-generate-your-first-ai-assisted-code">如何生成你的第一个 AI 辅助代码（快速入门）</a></p>
</li>
<li>
<p><a href="#stage-1">阶段 1：基础 – 开始 AI 编码</a></p>
</li>
<li>
<p><a href="#stage-2">阶段 2：高级 GitHub Copilot 功能</a></p>
</li>
<li>
<p><a href="#stage-3">阶段 3：基于 CLI 的 AI 代理（Claude Code &amp; Gemini）</a></p>
</li>
<li>
<p><a href="#stage-4">阶段 4：掌握 – 结合工具和高级工作流程</a></p>
</li>
<li>
<p><a href="#common-ai-issues">常见 AI 问题</a></p>
</li>
<li>
<p><a href="#whats-next-after-completing-all-stages">完成所有阶段后接下来做什么？</a></p>
</li>
<li>
<p><a href="#conclusion">结语</a></p>
</li>
</ul>
<h2 id="essential-ai-terminology">基础 AI 术语</h2>
<p>在开始之前，确保你了解以下关键术语：</p>
<ul>
<li>
<p><strong>Tokens（令牌）：</strong> 把令牌想象成“词片”——AI 阅读你的代码和文本的方式。每个字符、单词或符号都会使用令牌。免费版本会限制你可以使用的令牌数量。</p>
</li>
<li>
<p><strong>Context Window（上下文窗口）：</strong> AI 能一次性“记住”多少代码/对话。就像短期记忆，更大的窗口意味着对项目的更好理解。</p>
</li>
<li>
<p><strong>Hallucinations（幻觉）：</strong> AI 自信地建议错误信息——例如，捏造不存在的函数。务必验证 AI 的建议！</p>
</li>
<li>
<p><strong>Prompt（提示）：</strong> 你给 AI 的指令——评论、问题或请求，用以指导其生成的代码。</p>
</li>
</ul>
<h2 id="when-to-use-ai-vs-when-to-code-yourself">何时使用 AI 以及何时自己编码</h2>
<p><strong>使用 AI 的场合：</strong></p>
<ul>
<li>
<p>编写模板代码（getters、setters、基本的 CRUD）</p>
</li>
<li>
<p>学习新的框架或语法</p>
</li>
<li>
<p>编写测试和文档</p>
</li>
<li>
<p>重构重复模式</p>
</li>
<li>
<p>在语法错误上解开困境</p>
</li>
</ul>
<p><strong>自己编码的场合：</strong></p>
<ul>
<li>
<p>设计系统架构</p>
</li>
<li>
<p>做出关键的安全决策</p>
</li>
<li>
<p>编写复杂的业务逻辑</p>
</li>
<li>
<p>学习新概念（首次）</p>
</li>
<li>
<p>进行关键的性能优化</p>
</li>
</ul>
<p><strong>黄金法则：</strong> 使用 AI 加速实施，但自己做架构决策。AI 擅长“如何”，但你决定“什么”和“为什么”。</p>
<h2 id="prerequisites">前提条件</h2>
<p>在开始本教程之前，你应该具备：</p>
<ul>
<li>
<p><strong>基本编程经验</strong> – 你可以用某种语言编写简单程序</p>
</li>
<li>
<p><strong>安装有代码编辑器</strong> – 推荐使用 VS Code（从 <a href="http://code.visualstudio.com/">code.visualstudio.com</a> 免费获取）</p>
</li>
<li>
<p><strong>基本 Git 知识</strong> – 你知道如何提交和推送代码</p>
</li>
<li>
<p><strong>免费起步</strong> – 许多工具现在都有慷慨的免费版本，付费计划最低大约每月 10-20 美元</p>
</li>
</ul>
<h2 id="your-complete-learning-journey">你的完整学习旅程</h2>
<p>这篇全面的教程提供了一个循序渐进的计划，旨在助你成为 AI 辅助开发的专家：</p>
<p>注意：为了保持教程的易用性，我们将只关注一些核心工具。但你应该研究和探索更多适合你特定需求的工具，超出我们在此使用的工具。</p>
<h3 id="">学习路径</h3>
<p>你将经过 4 个阶段：掌握 GitHub Copilot 基础、解锁高级功能如聊天模式和代理、探索 CLI 工具（Claude Code 和 Gemini），最终战略性地结合多个工具实现完整的项目工作流程。</p>
<p>首先，让我们快速看看如何生成你的第一个 AI 代码片段。</p>
<h2 id="how-to-generate-your-first-ai-assisted-code">如何生成你的第一个 AI 辅助代码（快速入门）</h2>
<p>让我们从最基础的开始。别担心选择“完美”的工具——你总可以后续切换。以下是开始的方法：</p>
<h3 id="githubcopilot">GitHub Copilot（推荐初学者使用）</h3>
<p>你可以通过以下步骤安装 GitHub Copilot：</p>
<ol>
<li>
<p>打开 VS Code</p>
</li>
<li>
<p>点击扩展图标（或按 Ctrl+Shift+X）</p>
</li>
<li>
<p>搜索“GitHub Copilot”</p>
</li>
<li>
<p>点击“安装”</p>
</li>
<li>
<p>使用你的 GitHub 账户登录</p>
</li>
</ol>
<p><strong>提示：</strong> 学生、教师和开源软件维护者<a href="https://docs.github.com/en/copilot/how-tos/manage-your-account/getting-free-access-to-copilot-pro-as-a-student-teacher-or-maintainer">可以免费获得 Pro 计划</a>，这可以提供无限制的使用，而不是免费的使用限制。</p>
<h3 id="ai">你的第一个 AI 建议</h3>
<p>安装后，创建一个名为 <code>test.js</code> 的新文件，并输入：</p>
<pre><code>// function to calculate the area of a circle
</code></pre>
<p>按下 Enter 键等待。你会看到灰色文本出现——这是您的 AI 建议！按 Tab 键接受它。</p>
<p>就这样！您刚刚获得了第一个 AI 建议！是不是很酷？</p>
<h2 id="stage-1">阶段 1：基础 – 开始使用 AI 编码</h2>
<h3 id="1">第 1 步：了解您的选项</h3>
<p>将 AI 编码助手想象成不同类型的有帮助的朋友和同事。让我们来浏览几个：</p>
<p><strong>基于 IDE 的：</strong> 一些工具设计为可以与熟悉的代码编辑器一起工作，或作为编辑器如 VS Code 的独立分支。例如：</p>
<ul>
<li>
<p><strong>GitHub Copilot (VS Code 扩展)</strong> – 来自 GitHub 的 AI 编码助手，直接在 VS Code 中工作，提供 Tab 补全和聊天功能</p>
</li>
<li>
<p><strong>Cursor (独立)</strong> – VS Code 分支，具有增强的代理模式、更快的自主编码和更好的大代码库重构处理</p>
</li>
<li>
<p><strong>Windsurf (独立或 VS Code 扩展)</strong> – 专注于实时建议和团队功能的协作 AI 开发</p>
</li>
<li>
<p><strong>Zed</strong> – 高性能编辑器，内置 AI 辅助功能和快速渲染</p>
</li>
</ul>
<p><strong>基于 CLI 的：</strong> 一些工具是基于 CLI 的，您可以在终端应用中启动：</p>
<ul>
<li>
<p><strong>Claude Code</strong> – Anthropic 的终端 AI，用于自主开发会话和复杂推理</p>
</li>
<li>
<p><strong>Gemini</strong> – Google 的 CLI 工具，具有大上下文窗口和多模态功能（图像、文档）</p>
</li>
<li>
<p><strong>OpenCode</strong> – 开源替代方案，具有可自定义模型和本地处理选项</p>
</li>
<li>
<p><strong>Cursor CLI</strong> – Cursor 的终端版本，用于命令行 AI 辅助</p>
</li>
</ul>
<p><strong>基于 UI 和后台代理的工具：</strong> 除此之外，还有一些后台代理和工具可以完全在后台运行，例如执行拉取请求审查等。</p>
<p>例如，如果您设置了它们，ChatGPT 和 Claude 的桌面应用程序都可以编辑本地文件系统上的文件。同样，一些基于云的代理可以“在后台运行”以完成您的指令。我们将在本指南范围内排除这些。</p>
<h3 id="2tab">第 2 步：做出选择并学习自动建议（Tab 补全）</h3>
<p>对于您的第一阶段，我建议从 GitHub Copilot 开始。您可以在学习完基础知识后随时切换到适合您需求的工具。</p>
<h3 id="3">第 3 步：逐步设置</h3>
<h4 id="githubcopilot">如何设置 GitHub Copilot（如果您之前已经遵循过快速入门，可以跳过此步骤）</h4>
<ol>
<li>
<p><strong>打开 VS Code。</strong> 如果您没有，请从 <a href="https://code.visualstudio.com/">code.visualstudio.com</a> 下载。</p>
</li>
<li>
<p><strong>安装扩展</strong></p>
<ul>
<li>
<p>按 <code>Ctrl+Shift+X</code>（Windows/Linux）或 <code>Cmd+Shift+X</code>（Mac）</p>
</li>
<li>
<p>在搜索框中输入“GitHub Copilot”</p>
</li>
<li>
<p>点击蓝色的“安装”按钮</p>
</li>
<li>
<p>您会看到一个弹出窗口要求您登录</p>
</li>
</ul>
</li>
<li>
<p><strong>登录</strong></p>
<ul>
<li>
<p>点击“登录 GitHub”</p>
</li>
<li>
<p>您的浏览器会打开</p>
</li>
<li>
<p>使用您的 GitHub 帐户登录（如果需要，可以在 <a href="http://github.com/">github.com</a> 免费创建一个）</p>
</li>
<li>
<p>点击“授权 GitHub Copilot”</p>
</li>
</ul>
</li>
<li>
<p><strong>开始使用 Copilot</strong></p>
<ul>
<li>返回 VS Code，您会看到“GitHub Copilot 已准备好使用”</li>
</ul>
</li>
</ol>
<h3 id="4tab">第 4 步：掌握 Tab 补全</h3>
<p>让我们确保它正常工作。创建一个新文件：<code>hello.py</code>。输入此注释并按 Enter：</p>
<pre><code># function to greet a user by name
</code></pre>
<p>等待 1-2 秒。您应该会看到灰色文本出现。只需按 <code>Tab</code> 接受建议。</p>
<p><strong>您应该看到的内容：</strong></p>
<pre><code># function to greet a user by name
def greet_user(name):
    return f"Hello, {name}!"
</code></pre>
<p>如果您看到了这个，恭喜您！您现在正在使用 AI 帮助您编写代码。</p>
<p>如果您遇到设置问题，可以查看 <a href="http://localhost:3333/#troubleshooting-quick-reference">疑难解答快速参考</a> 寻求解决方案。</p>
<h3 id="5">第 5 步：基本键盘快捷键和第一次练习</h3>
<p>以下是您第一周需要的唯一快捷键：</p>
<p><strong>基础：</strong></p>
<ul>
<li>
<p><code>Tab</code> – 接受 AI 建议（这个用得最多！）</p>
</li>
<li>
<p><code>Esc</code> – 拒绝建议（当您不需要时）</p>
</li>
</ul>
<p>当您准备好了解更多时，尝试这些：</p>
<p><strong>Windows/Linux：</strong></p>
<ul>
<li>
<p><code>Alt+]</code> – 查看下一个建议</p>
</li>
<li>
<p><code>Alt+[</code> – 查看上一个建议</p>
</li>
<li>
<p><code>Ctrl+Enter</code> – 在面板中查看所有建议</p>
</li>
</ul>
<p><strong>macOS：</strong></p>
<ul>
<li>
<p><code>Option+]</code> （或 <code>Alt+]</code>） – 查看下一个建议</p>
</li>
<li>
<p><code>Option+[</code> （或 <code>Alt+[</code>) – 查看上一个建议</p>
</li>
<li>
<p><code>Ctrl+Enter</code> – 在面板中查看所有建议</p>
</li>
</ul>
<h3 id="1">阶段 1 实践练习</h3>
<h4 id="">练习：构建一个简单的待办事项应用</h4>
<ol>
<li>
<p>创建一个名为 <code>todo.js</code> 的新文件</p>
</li>
<li>
<p>以此注释开始：<code>// TODO app with add, remove, and list functions</code></p>
</li>
<li>
<p>添加此注释并等待 AI 建议：<code>// function to add a new todo item</code></p>
</li>
<li>
<p>如果建议看起来不错，按 Tab 键接受</p>
</li>
<li>
<p>继续为移除和列出函数添加注释</p>
</li>
<li>
<p>测试您的函数以确保它们工作正常</p>
</li>
</ol>
<p><strong>目标：</strong> 学习通过清晰的注释与 AI “对话”，并建立接受/拒绝建议的信心。</p>
<h3 id="">准备好进入下一阶段了吗？在继续之前，请确保您能够：</h3>
<pre><code>- [ ] 通过输入注释获取 AI 建议
- [ ] 使用 Tab 接受建议，使用 Esc 拒绝建议
- [ ] 使用 Alt+] 和 Alt+[ 查看不同的建议
- [ ] 在 AI 帮助下编写基本函数
</code></pre>
<p>如果您对这些基本内容感到满意，就可以学习更强大的 Copilot 功能了。</p>
<h2 id="stage-2">阶段 2：高级 GitHub Copilot 功能</h2>
<h3 id="6ai">第 6 步：获取更好的 AI 建议</h3>
<p>现在您已经了解了基础知识，让我们学习如何从您的 AI 那里得到_更好_的建议。诀窍在于了解您的 AI 能看到什么。</p>
<h4 id="ai">您的 AI 助手能看到什么</h4>
<p>想象您的 AI 助手就像一个站在你肩头、随时提供帮助的朋友。它能看到：</p>
<ol>
<li>
<p><strong>您当前正在输入的内容</strong>——您的当前文件</p>
</li>
<li>
<p><strong>其他打开的标签页</strong>——您打开的文件（这很重要！）</p>
</li>
<li>
<p><strong>您的项目结构</strong>——文件夹和文件名</p>
</li>
<li>
<p><strong>您的注释</strong>——这是您与 AI “对话” 的方式</p>
</li>
</ol>
<h4 id="">“相邻标签页”技巧</h4>
<p>这是一个能为您节省数小时的专业提示：<strong>在标签页中打开相关文件</strong>。</p>
<p><strong>示例：</strong> 如果您在编写一个 React 组件：</p>
<ul>
<li>
<p>打开您的组件文件 (<code>Button.jsx</code>)</p>
</li>
<li>
<p>还要打开 CSS 文件 (<code>Button.css</code>)</p>
</li>
<li>
<p>同时也让测试文件可见 (<code>Button.test.js</code>)</p>
</li>
</ul>
<p>然后，您可以通过几种方式与 AI 共享这些额外文件的上下文：</p>
<ul>
<li>
<p><strong>@提及文件：</strong> 在聊天中键入 <code>@filename.js</code> 以引用特定文件</p>
</li>
<li>
<p><strong>使用 @workspace：</strong> 这个聊天参与者可以看到您项目中的所有文件</p>
</li>
<li>
<p><strong>拖放：</strong> 只需将文件从资源管理器窗口拖动到聊天窗口</p>
</li>
<li>
<p><strong>选择代码：</strong> 高亮代码并右键单击 “Ask Copilot” 以将其包括在上下文中</p>
</li>
</ul>
<p>AI 使用这些打开的文件来理解您的项目结构，并建议更相关的代码以匹配您现有的模式。</p>
<h3 id="7">第 7 步：质量控制与最佳实践</h3>
<h4 id="ai">了解 AI 的局限性</h4>
<p>AI 功能强大，但并不完美。以下是需要注意的关键事项。</p>
<p><strong>常见的 AI 错误：</strong></p>
<ol>
<li>
<p>虚构的函数：例如，<code>const result = array.superSort();</code> 并不存在！</p>
</li>
<li>
<p>错误的参数：例如，当函数期望 <code>greetUser(name)</code> 时，<code>greetUser("John", "Doe");</code></p>
</li>
<li>
<p>过于复杂的解决方案：例如，<code>const isEven = (num) =&gt; num.toString(2).slice(-1) === "0";</code> - 只需使用 <code>num % 2 === 0</code></p>
</li>
</ol>
<p>快速质量检查清单：</p>
<pre><code>- [ ] 测试代码 - 它真的有效吗？
- [ ] 阅读 - 逻辑上是否合理？
- [ ] 检查基础 - 所有函数/变量是否已定义？
- [ ] 信任直觉 - 如果感觉不对，进行调查
</code></pre>
<h4 id="">安全要点</h4>
<p>在接受 AI 建议之前，请确保检查这些安全问题：</p>
<pre><code>- [ ] 没有硬编码的密码或 API 密钥
- [ ] 用户输入已验证
- [ ] 没有对用户数据使用 eval()
- [ ] 错误消息不暴露敏感信息
</code></pre>
<h4 id="">更好的提示写作</h4>
<p>这里有一个编写可靠提示的公式：是什么 + 如何 + 返回类型。</p>
<pre><code>// ❌ 含糊： "make function"
// ✅ 清晰： "function to validate email format using regex, returns boolean"
</code></pre>
<h4 id="copilot">使用 Copilot 指令进行仓库级自定义</h4>
<p>GitHub Copilot 现在支持通过 <code>.github/copilot-instructions.md</code> 文件进行仓库级别的自定义。此功能帮助 Copilot 理解您项目的特定模式和约定。</p>
<p>以下是设置 Copilot 指令的方法：</p>
<pre><code># 如果不存在，创建 GitHub 目录
mkdir -p .github
touch .github/copilot-instructions.md
</code></pre>
<p>示例 <a href="http://copilot-instructions.md/">copilot-instructions.md</a> 文件：</p>
<pre><code># Copilot 指令

## 代码风格

- 使用具有 hooks 的 React 函数组件
- 为新文件更偏好使用 TypeScript 而不是 JavaScript
- 使用 Tailwind CSS 进行样式设计
- 遵循 `/src/components` 中的现有文件结构

## 测试

- 使用 React Testing Library 编写测试
- 将测试文件放在 `__tests__` 目录中
- 使用描述性测试名称来解释行为

## API 模式

- 使用自定义钩子进行 API 调用
- 一致地处理加载和错误状态
- 使用 React Query 进行数据提取

## 命名约定

- 组件：PascalCase（例如，`UserProfile.tsx`）
- 钩子：以“use”开头的 camelCase（例如，`useUserData.ts`）
- 工具：camelCase（例如，`formatDate.ts`）
</code></pre>
<p><strong>这项功能实现了：</strong></p>
<ul>
<li>
<p>Copilot 建议符合您项目模式的代码</p>
</li>
<li>
<p>自动遵循您的命名约定</p>
</li>
<li>
<p>建议合适的测试方法</p>
</li>
<li>
<p>理解您偏好的库和框架</p>
</li>
</ul>
<p><strong>最佳实践：</strong></p>
<ul>
<li>
<p>保持指令清晰和具体</p>
</li>
<li>
<p>随着项目标准的发展及时更新</p>
</li>
<li>
<p>包括首选模式的示例</p>
</li>
<li>
<p>提到您使用的库和框架</p>
</li>
</ul>
<h3 id="8copilot">第 8 步：解锁高级 Copilot 功能</h3>
<h4 id="">了解您的选择</h4>
<p>GitHub Copilot 提供多种方式来获得 AI 帮助：</p>
<ol>
<li>
<p><strong>Tab 补全</strong>（您一直在使用的）——在输入时提供建议</p>
</li>
<li>
<p><strong>聊天模式</strong>——与 AI 就您的代码进行对话</p>
</li>
<li>
<p><strong>编辑模式</strong>——请求 AI 对现有代码进行修改</p>
</li>
<li>
<p><strong>代理模式</strong>——让 AI 自主完成大型任务</p>
</li>
</ol>
<h4 id="">模型选择</h4>
<p>Copilot 现在提供不同的 AI 模型以满足不同需求：</p>
<p>订阅免费：</p>
<ul>
<li>
<p><strong>GPT-4.1</strong> – 默认模型，综合性能强大</p>
</li>
<li>
<p><strong>GPT-4</strong> – 对大多数编码任务来说可靠</p>
</li>
</ul>
<p>高级模型（有限的每月使用量）：</p>
<ul>
<li>
<p><strong>Claude 3.5 Sonnet</strong> – 适合复杂逻辑</p>
</li>
<li>
<p><strong>GPT-5</strong> – 最新且最强大</p>
</li>
<li>
<p><strong>Gemini 2.0 Flash</strong> – 响应非常快速</p>
</li>
</ul>
<p><strong>如何切换模型：</strong> 点击聊天视图中的模型下拉菜单</p>
<p><strong>提示：</strong> 学习时从免费模型（GPT-4.1）开始，对于复杂问题保留高级模型使用。</p>
<h4 id="githubcopilot">GitHub Copilot 的局限性</h4>
<p>以下是在使用 AI 来帮助您进行编码时需要考虑的一些重要事项：</p>
<ul>
<li>
<p><strong>互联网依赖性</strong> – 需要稳定的连接以获得建议</p>
</li>
<li>
<p><strong>上下文限制</strong> – 只能看到打开的文件，而不是整个项目结构</p>
</li>
<li>
<p><strong>免费账号限制</strong> – 每月 2,000 次补全和 50 次聊天请求</p>
</li>
<li>
<p><strong>代码质量参差不齐</strong> – 始终审查建议，特别是涉及安全性敏感的代码时</p>
</li>
<li>
<p><strong>学习曲线</strong> – 编写有效的提示需要时间，特别是对于复杂任务</p>
</li>
<li>
<p><strong>隐私考虑</strong> – 您的代码会被发送到 GitHub 的服务器（请检查您的组织的政策）</p>
</li>
</ul>
<h4 id="">基础聊天与建议</h4>
<p>您可能想知道 - 什么时候应该使用 Tab 补全，什么时候应该使用聊天？最好是用 Tab 补全来编写新函数、快速的语法帮助和模式补全。可以使用聊天来解释现有代码、获取错误帮助和规划解决问题的方法。</p>
<p><strong>尝试一下：</strong> 打开聊天（Ctrl+Shift+I）并询问：“这个函数有什么作用？”同时选择代码。</p>
<h3 id="9">第9步：掌握聊天和代理模式</h3>
<h4 id="">三种聊天模式</h4>
<ol>
<li><strong>询问模式（默认）</strong> – 用于问题和解释：</li>
</ol>
<pre><code>“这个函数有什么作用？”
“如何优化这段代码？”
“解释此错误消息”
</code></pre>
<ol start="2">
<li><strong>编辑模式</strong> – 用于对现有代码进行更改：</li>
</ol>
<pre><code>“重构这段代码以使用 async/await”
“为所有 API 调用添加错误处理”
“将其转换为 TypeScript”
</code></pre>
<ul>
<li>
<p>显示内联差异后应用更改</p>
</li>
<li>
<p>可跨多个文件工作</p>
</li>
<li>
<p>适合系统化重构</p>
</li>
</ul>
<ol start="3">
<li><strong>代理模式</strong> – 用于自主开发：</li>
</ol>
<pre><code>“创建一个带身份验证的 REST API”
“使用React和测试构建一个待办应用”
“将此代码库从Vue 2迁移到Vue 3”
</code></pre>
<ul>
<li>
<p>按 <code>Cmd+Shift+I</code> （Mac）或 <code>Ctrl+Shift+Alt+I</code>（Linux）或 <code>Ctrl+Shift+I</code>（Windows）</p>
</li>
<li>
<p>可独立工作数小时</p>
</li>
<li>
<p>自动安装包、创建文件、运行测试</p>
</li>
</ul>
<h4 id="">何时使用各模式</h4>
<p>每种模式都有特定的使用场景。当您学习新概念时，希望理解现有代码、获取解释和去计划方法时，使用询问模式。</p>
<p>当您正在重构现有代码、应用一致的更改、为现有功能添加特性或进行样式/模式更新时，使用编辑模式。</p>
<p>代理模式在构建完整特性（30分钟以上的工作）、设置新项目、大规模重构时有用，并且在您希望在 AI 编码时处理其他事情时使用。</p>
<h4 id="">代理模式示例</h4>
<p>小型代理任务（15分钟）：</p>
<pre><code>“为我的 Express 应用添加用户身份验证”
</code></pre>
<p>代理生成的内容：</p>
<pre><code>// middleware/auth.js
const jwt = require('jsonwebtoken');

const authenticateToken = (req, res, next) =&gt; {
  const authHeader = req.headers['authorization'];
  const token = authHeader &amp;&amp; authHeader.split(' ')[1];

  if (!token) return res.sendStatus(401);

  jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) =&gt; {
    if (err) return res.sendStatus(403);
    req.user = user;
    next();
  });
};

// routes/auth.js
router.post('/login', async (req, res) =&gt; {
  // 使用 bcrypt 进行身份验证的逻辑
  const accessToken = jwt.sign({username: user.username}, process.env.ACCESS_TOKEN_SECRET);
  res.json({accessToken: accessToken});
});
</code></pre>
<p><strong>我发现的关键问题：</strong> 代理最初忘记对密码进行哈希处理，并且没有包括刷新令牌。这需要一次迭代来修复安全漏洞并添加适当的错误处理。</p>
<p>大型代理任务（4小时以上）：</p>
<pre><code>“将此基于类的 React 应用更新为使用 TypeScript 的 hooks”
</code></pre>
<p>代理生成的内容：</p>
<pre><code>// 之前（类组件）
class UserProfile extends React.Component {
  constructor(props) {
    this.state = { user: null, loading: true };
  }
  // ... 生命周期方法
}

// 之后（Hooks + TypeScript）
interface User {
  id: number;
  name: string;
  email: string;
}

const UserProfile: React.FC = () =&gt; {
  const [user, setUser] = useState&lt;User | null&gt;(null);
  const [loading, setLoading] = useState(true);

  useEffect(() =&gt; {
    fetchUser().then(setUser).finally(() =&gt; setLoading(false));
  }, []);

  return &lt;div&gt;{loading ? 'Loading...' : user?.name}&lt;/div&gt;;
};
</code></pre>
<p>**我发现的关键问题：**代理成功更新了47个文件，但最初在事件处理程序中存在类型问题，并且需要改进泛型类型。自动化测试还需要人工检查以确保适当的 TypeScript 覆盖。</p>
<p>Chat 参与者是专门的 AI 助手，可以访问您的开发环境中的特定部分。可以将它们视为不同领域的专家，能够帮助完成有针对性的任务。</p>
<p>它们基本上是以 <code>@</code> 作为前缀的 AI 助手，具有特殊的知识和能力：</p>
<ul>
<li>
<p><strong>@workspace</strong> 可以访问您整个项目的结构，可以搜索文件并理解组件之间的关系。当您需要项目范围的分析时，请使用 <code>@workspace</code>："找出此项目中的所有 API 端点" 或 "显示用户身份验证是在哪里实现的。"</p>
</li>
<li>
<p><strong>@terminal</strong> 了解命令行操作，可以建议 shell 命令并解释终端输出。对于命令行帮助，请使用 <code>@terminal</code>："哪个命令可以运行测试？" 或 "如何为生产构建此项目？"</p>
</li>
<li>
<p><strong>@vscode</strong> 是 VS Code 功能方面的专家，可以帮助进行设置、调试和编辑器配置。对于编辑器帮助，请使用 <code>@vscode</code>："为 Node.js 设置调试" 或 "为此项目配置自动格式化。"</p>
</li>
</ul>
<p><strong>示例用法:</strong></p>
<pre><code>@workspace 你能找到这个项目中的所有数据库模型吗？
@terminal 安装依赖项并启动开发服务器的命令是什么？
@vscode 如何设置断点以调试这个 Express 应用？
</code></pre>
<h3 id="10">步骤 10：高级用户功能和高级工作流程</h3>
<p>除了您已经了解的 Copilot 核心功能外，还有一些专门的工具和命令可以极大地提高您的生产力。这些功能超越基本的聊天模式和模型选择，专注于复杂的多文件操作和高级自动化。</p>
<h4 id="">高级斜线命令</h4>
<pre><code>/doc - 生成文档
/explain - 详细的代码说明
/fix - 修复选定代码中的错误
/tests - 生成单元测试
/new - 创建新的项目结构
</code></pre>
<h4 id="">多文件操作</h4>
<p><strong>使用 # 引用：</strong></p>
<p><code>#</code> 符号创建特定的引用，告诉 Copilot 精确关注哪里。这些引用就像是指向项目不同部分的精准指针：</p>
<ul>
<li>
<p><strong>#file:filename</strong>: 引用特定文件：<code>#file:UserModel.js</code></p>
</li>
<li>
<p><strong>#codebase</strong>: 引用整个项目代码库以进行搜索</p>
</li>
<li>
<p><strong>#selection</strong>: 引用当前选定的代码</p>
</li>
<li>
<p><strong>#editor</strong>: 引用当前活动文件</p>
</li>
</ul>
<pre><code>"更新 #file:UserModel.js 以包含时间戳"
"在 #codebase 中搜索所有数据库查询"  
"将 #selection 重构为现代 JavaScript 语法"
"为所有 API 调用添加错误处理到 #editor"
</code></pre>
<p>这些引用帮助 Copilot 准确理解要查看和更改的位置，使多文件操作更加精确。</p>
<p><strong>拖放操作：</strong></p>
<p>拖放是提供给 Copilot 的最直观的上下文方式之一。您可以将文件从 VS Code 浏览器中直接拖入聊天窗口，Copilot 会立即了解其内容和结构。</p>
<p>当您处理相关组件并需要 AI 理解不同文件如何相互连接时，此功能特别有用。Copilot 会在整个对话中记住这些文件关系，因此在继续相同的讨论时无需再次上传文件。</p>
<p>这种上下文保留在多个聊天会话中有效，使您可以轻松在复杂的多文件项目中继续之前的工作。</p>
<h3 id="2">阶段 2 实践练习</h3>
<h4 id="1">练习 1：聊天模式实践</h4>
<ol>
<li>
<p>使用提问模式理解一个复杂的函数</p>
</li>
<li>
<p>切换到编辑模式进行重构</p>
</li>
<li>
<p>比较不同的方法</p>
</li>
</ol>
<h4 id="2">练习 2：代理模式项目</h4>
<ol>
<li>
<p>启动代理模式 (<code>Shift+Cmd+I</code>)</p>
</li>
<li>
<p>请求："创建一个带测试的简单待办应用"</p>
</li>
<li>
<p>观察自主开发过程</p>
</li>
<li>
<p>查看生成的代码</p>
</li>
</ol>
<h4 id="3">练习 3：高级功能</h4>
<ol>
<li>
<p>使用 @ 参与者进行项目问题</p>
</li>
<li>
<p>试验斜线命令</p>
</li>
<li>
<p>练习多文件操作</p>
</li>
</ol>
<h3 id="cli">准备好使用 CLI 工具了吗？</h3>
<p>您现在已经学习了在 VS Code 中使用 GitHub Copilot 的基础知识！像 Claude Code 和 Gemini 这样的 CLI 工具为基于终端的开发提供了更强大的功能。</p>
<p>如果你对终端 AI 感兴趣，可以继续学习下方的第三阶段。如果你更愿意继续使用 VS Code，请跳到第四阶段以获取高级工作流程。</p>
<h2 id="stage-3">阶段 3：基于 CLI 的 AI 代理（Claude Code &amp; Gemini）</h2>
<h3 id="11claudecodeai">步骤 11：认识 Claude Code——您的终端 AI 助手</h3>
<h4 id="claudecode">什么是 Claude Code？</h4>
<p>还记得 GitHub Copilot 如何在 VS Code 中帮助你吗？Claude Code 在终端中为你提供相同的帮助。</p>
<p>不用在 VS Code 中键入和获取建议，你可以在终端中键入并与 AI 对话。这就像在命令行上有一个编程伙伴。</p>
<h4 id="">简单例子：</h4>
<p>在 VS Code 中使用 Copilot：</p>
<pre><code>// 创建一个函数来验证电子邮件
[AI 提供建议代码]
</code></pre>
<p>在终端中使用 Claude Code：</p>
<pre><code>claude
&gt; 创造一个函数来验证电子邮件地址
[AI 为你编写代码]
</code></pre>
<p>那么，什么时候应该使用 VS Code/Copilot，什么时候应该使用 Claude Code 呢？</p>
<p><strong>如果你：</strong></p>
<ul>
<li>
<p>喜欢在终端工作</p>
</li>
<li>
<p>想要与 AI 进行关于代码的对话</p>
</li>
<li>
<p>需要有关命令行任务的帮助</p>
</li>
<li>
<p>想要更多控制 AI 互动</p>
</li>
</ul>
<p>Claude Code 非常适合你。</p>
<ul>
<li>
<p>偏好可视化编辑器</p>
</li>
<li>
<p>对当前的工作流程感到满意</p>
</li>
<li>
<p>不花太多时间在终端</p>
</li>
</ul>
<h4 id="">定价</h4>
<p>Claude Code 需要 Claude Pro（每月 20 美元）或 ClaudeMax（每月 100 美元）订阅，或使用 API 积分按使用量付费。</p>
<h4 id="claudecode">Claude Code 限制</h4>
<p>如果您计划使用 Claude Code，请考虑以下重要事项：</p>
<ul>
<li>
<p><strong>仅付费</strong> – 没有免费版本，需要 Claude Pro 订阅或 API 积分</p>
</li>
<li>
<p><strong>基于终端</strong> – 不如 IDE 集成工具可视化</p>
</li>
<li>
<p><strong>学习曲线</strong> – 需要熟悉命令行界面</p>
</li>
<li>
<p><strong>上下文管理</strong> – 需要手动管理对话上下文</p>
</li>
<li>
<p><strong>依赖互联网</strong> – 所有操作都需要稳定的连接</p>
</li>
<li>
<p><strong>会话限制</strong> – 长时间的自主会话会消耗大量 API 积分</p>
</li>
</ul>
<h4 id="">安装</h4>
<p>推荐（所有平台）：</p>
<pre><code>npm install -g @anthropic-ai/claude-code
</code></pre>
<p>其他安装方式：</p>
<ul>
<li>
<p><strong>macOS/Linux</strong>: <code>curl -fsSL https://claude.ai/install.sh | bash</code></p>
</li>
<li>
<p><strong>Windows</strong>: <code>irm https://claude.ai/install.ps1 | iex</code></p>
</li>
</ul>
<h4 id="">基本用法</h4>
<p><strong>交互模式（推荐）：</strong></p>
<p>交互模式是 Claude Code 的主要界面，您可以与 AI 实时对话。不同于一次性命令，交互模式创建了一个持久的会话，您可以提出后续问题、迭代解决方案，并随着时间的推移构建复杂的项目。</p>
<p>推荐使用交互模式，因为：</p>
<ul>
<li>
<p><strong>上下文持久性</strong>：Claude 会记住整个对话和项目上下文</p>
</li>
<li>
<p><strong>迭代开发</strong>：您可以优化请求，并基于先前的回应进行改进</p>
</li>
<li>
<p><strong>实时协作</strong>：在工作时提问、获取解释并修改方法</p>
</li>
<li>
<p><strong>会话恢复</strong>：使用 <code>claude --resume</code> 继续之前的对话</p>
</li>
</ul>
<p><strong>其他可用模式：</strong></p>
<ul>
<li>
<p><strong>一次性模式</strong>：单个命令执行（下文说明）</p>
</li>
<li>
<p><strong>代理模式</strong>：可独立工作数小时的自主开发会话</p>
</li>
</ul>
<ol>
<li>导航到您的项目：</li>
</ol>
<pre><code>cd your-project
claude
</code></pre>
<ol start="2">
<li>自然地开始对话：</li>
</ol>
<pre><code>Claude Code &gt; 分析这个代码库并提出改进建议

Claude Code &gt; 现在帮我重构用户认证

Claude Code &gt; 为支付模块添加单元测试
</code></pre>
<ol start="3">
<li>继续之前的会话：</li>
</ol>
<pre><code>claude --resume
</code></pre>
<p><strong>一次性命令（用于快速任务）：</strong></p>
<p>一次性命令是执行特定任务后即退出的单次执行命令。与交互模式不同，这些命令不保留对话上下文 —— 非常适合快速、独立的任务。</p>
<p><strong>什么是一次性命令？</strong></p>
<p>这些是在您的终端中直接运行带有特定指令的命令，而不进入交互会话。Claude 将执行请求并立即提供结果。</p>
<p><strong>何时使用一次性命令：</strong></p>
<ul>
<li>
<p>快速分析或代码审查</p>
</li>
<li>
<p>简单文件修改</p>
</li>
<li>
<p>自动化脚本和 CI/CD 集成</p>
</li>
<li>
<p>需要单一特定答案时</p>
</li>
</ul>
<p><strong>示例：</strong></p>
<pre><code>claude "分析这个代码库并提出改进建议"
claude "修复 src/ 中的所有 TypeScript 错误"
claude "为 utils.js 生成单元测试"
claude "解释这个函数的作用" --file src/auth.js
</code></pre>
<p>关键区别在于一次性命令在运行之间不记住上下文，而交互模式保持完整的对话历史记录和项目理解。</p>
<p><strong>交互式 vs 自主会话：</strong></p>
<p>在交互模式内，您可以选择协作和自主的方法：</p>
<p><strong>交互式会话（协作）：</strong></p>
<pre><code>Claude Code &gt; 我正在构建用户认证。我们应该采用什么方法？

你：使用 JWT 令牌和刷新令牌轮换

Claude Code &gt; 实现带刷新令牌的 JWT 认证
[逐步向您展示实现方案]

Claude Code &gt; 我还需要添加密码重置功能吗？

你：是的，使用基于邮件的重置
</code></pre>
<p><strong>自主会话（免动手开发）：</strong></p>
<pre><code>Claude Code &gt; 构建一个完整的用户管理系统，包括认证、个人资料、偏好设置和管理功能。使用安全和测试的最佳实践。

[Claude 自主工作数小时，定期提供更新]
[最终结果：完整的用户管理系统，准备投入生产]
</code></pre>
<p><strong>何时使用每种模式：</strong> 在学习时或希望对决策进行控制时使用交互式会话。对于定义明确的任务，在您信任 Claude 能够独立做出良好选择时使用自主会话。</p>
<h4 id="">关键特性</h4>
<p><strong>思维模式（在交互式会话中使用）：</strong></p>
<p>思维模式是特定的命令，可以告诉 Claude 在响应前要进行多深的分析。您可以根据问题的复杂程度手动选择这些模式。</p>
<p><strong>何时使用每种模式：</strong></p>
<ul>
<li>
<p><code>think</code> – 对简单任务进行快速分析："think: review this function for bugs"</p>
</li>
<li>
<p><code>think hard</code> – 对复杂逻辑进行深入推理："think hard: optimize this algorithm"</p>
</li>
<li>
<p><code>think harder</code> – 复杂问题解决，考虑多重因素："think harder: design a scalable database schema"</p>
</li>
<li>
<p><code>ultrathink</code> – 对架构决策进行最大深度分析："ultrathink: evaluate microservices vs monolith for this project"</p>
</li>
</ul>
<p>Claude展示其通过较长的思考模式进行推理的过程。您将在得出最终答案之前看到逐步分析。更高的思考模式花费更多时间，但会提供更全面的解决方案。</p>
<p><strong>选择正确的模式：</strong></p>
<p>使用<code>think</code>进行快速代码审查，使用<code>think hard</code>调试复杂问题，使用<code>think harder</code>处理系统设计问题，使用<code>ultrathink</code>进行影响整个项目的重大架构决策。</p>
<h4 id="claudemd">使用Claude.md进行项目级定制</h4>
<p>Claude Code最强大的功能之一是使用<code>.claude/CLAUDE.md</code>文件进行项目级定制。这让你可以为Claude提供有关特定项目、编码标准和偏好的上下文。</p>
<p>像这样设置CLAUDE.md：</p>
<pre><code># 创建项目级配置
mkdir -p .claude
touch .claude/CLAUDE.md
</code></pre>
<p>以下是一个CLAUDE.md文件的示例：</p>
<pre><code># 项目上下文

这是一个使用Express和PostgreSQL的Node.js REST API。

## 编码标准

- 使用async/await，绝不使用回调
- 所有数据库查询使用Prisma ORM
- 为所有新功能使用Jest编写测试
- 遵循RESTful约定

## 项目结构

- `/src/routes` - API端点
- `/src/models` - 数据库模型
- `/src/middleware` - Express中间件
- `/tests` - 单元和集成测试

## 偏好

- 为所有新文件使用TypeScript
- 更喜欢函数式编程模式
- 为所有函数包含JSDoc注释
</code></pre>
<p>这有助于Claude自动理解您的项目结构。还帮助Claude遵循您的特定编码标准，为您的技术栈建议合适的模式，并在多次会话中记住您的偏好。</p>
<p><strong>专业提示：</strong> 随着项目的发展更新你的CLAUDE.md，以保持Claude的建议相关和准确。</p>
<h4 id="claudecode">Claude Code自主开发会话</h4>
<p>这是一个多小时的自主开发会话示例：</p>
<pre><code>cd your-project
claude
</code></pre>
<p><strong>你的提示：</strong>“构建一个可扩展的具有实时订阅、身份验证、速率限制和全面测试的GraphQL API”</p>
<p>Claude的6小时自主过程：</p>
<pre><code>Claude Code &gt; ultrathink: 分析需求并设计架构

[创建详细的技术规格和开发计划]

Claude Code &gt; 实现核心GraphQL服务器与Apollo
[运行：npm install apollo-server-express graphql]
[创建：server.js, schema/typeDefs.js, resolvers/index.js]

Claude Code &gt; 添加身份验证和授权中间件
[创建：middleware/auth.js, utils/jwt.js, models/User.js]
[实现具有适当错误处理的JWT策略]

Claude Code &gt; 设置具有Redis的实时订阅
[运行：npm install graphql-redis-subscriptions]
[配置WebSocket连接，创建订阅解析器]

Claude Code &gt; 实施速率限制和安全措施
[添加helmet, express-rate-limit, 查询复杂度分析]

Claude Code &gt; 编写全面的测试套件
[创建单元测试、集成测试、负载测试]
[运行：npm test - 看到8个失败的测试]

Claude Code &gt; 自动修复测试失败
[识别异步时间问题，修复解析器逻辑]
[反复重新运行测试直到94/94个测试通过]

Claude Code &gt; 性能优化和缓存
[实现Redis缓存，优化数据库查询]
[添加性能监控和日志记录]

Claude Code &gt; 生成全面的文档
[创建带示例的API文档，README，部署指南]

Claude Code &gt; 最终验证和清理
[运行完整的测试套件，检查代码覆盖率：96%]
[创建生产构建和部署脚本]
</code></pre>
<p>这代表了6小时的自主工作（在此期间你可以处理其他项目）。结果是一个生产就绪的GraphQL API，具有身份验证、实时功能和全面的测试。</p>
<p>为什么这有效：</p>
<ul>
<li>
<p><strong>自主反馈循环：</strong> Claude运行测试，看到失败，自动修复</p>
</li>
<li>
<p><strong>上下文感知：</strong> 保持对整个项目结构的理解</p>
</li>
<li>
<p><strong>自我纠正：</strong> 反复迭代解决方案直至正确工作</p>
</li>
<li>
<p><strong>工具集成：</strong> 无缝使用git, npm, 测试框架</p>
</li>
</ul>
<p><strong>网络搜索集成：</strong></p>
<p>Claude Code可以搜索网络以获取当前信息，这对于AI训练数据有截断日期特别有用。该功能帮助您保持与最新文档、最佳实践和解决方案的同步。</p>
<pre><code>Claude Code &gt; 搜索最新的React 19功能并更新我的组件

[Claude搜索网络，然后以发现继续对话]

Claude Code &gt; 现在将这些新功能应用于UserProfile组件
</code></pre>
<p><strong>网络搜索何时有帮助：</strong></p>
<ul>
<li>
<p>获取新库版本的当前文档</p>
</li>
<li>
<p>找到最近错误消息或漏洞的解决方案</p>
</li>
<li>
<p>研究最新的最佳实践和模式</p>
</li>
<li>
<p>比较当前问题的解决方案</p>
</li>
</ul>
<p>当Claude检测到需要当前信息时，网络搜索会自动发生，或者你可以通过在提示中提到“搜索”或“最新”来显式请求。</p>
<h4 id="claudecode">Claude Code键盘快捷键</h4>
<p>你可以使用这些键盘快捷键提高工作效率：</p>
<ul>
<li>
<p><code>Ctrl+C</code> – 取消当前输入或生成</p>
</li>
<li>
<p><code>Ctrl+D</code> – 退出 Claude Code 会话</p>
</li>
<li>
<p><code>Ctrl+L</code> – 清除终端屏幕</p>
</li>
<li>
<p><code>Up/Down arrows</code> – 导航命令历史</p>
</li>
<li>
<p><code>Esc</code> + <code>Esc</code> – 编辑上一条消息</p>
</li>
</ul>
<p><strong>多行输入：</strong></p>
<ul>
<li>
<p><code>\</code> + <code>Enter</code> – 快速转义以创建新行（适用于所有终端）</p>
</li>
<li>
<p><code>Option+Enter</code> (Mac) / <code>Shift+Enter</code> (已配置) – 插入新行</p>
</li>
</ul>
<h3 id="12googlegemini">步骤12：Google Gemini 命令行界面</h3>
<h4 id="geminiclaudecode">何时使用 Gemini 与 Claude Code：</h4>
<p>Gemini 是另一种基于命令行界面的 AI 工具，它与 Claude Code 相辅相成，而不是竞争。尽管 Claude Code 擅长深度推理和复杂的开发任务，但 Gemini 提供了独特的优势：大规模上下文窗口（超过100万个标记）、慷慨的免费限制以及强大的多模态能力。</p>
<p><strong>使用 Gemini，当您：</strong></p>
<ul>
<li>
<p>需要一次分析整个大型代码库</p>
</li>
<li>
<p>希望处理图像、图表或草图</p>
</li>
<li>
<p>在预算限制内工作（慷慨的免费套餐）</p>
</li>
<li>
<p>需要极大的上下文窗口来处理复杂项目</p>
</li>
</ul>
<p><strong>使用 Claude Code，当您：</strong></p>
<ul>
<li>
<p>需要复杂的推理和问题解决</p>
</li>
<li>
<p>希望进行自主开发会话</p>
</li>
<li>
<p>偏爱用于复杂分析的高级思维模式</p>
</li>
<li>
<p>正在构建需要详细规划的生产系统</p>
</li>
</ul>
<p><strong>最佳方法：</strong> 许多开发人员策略性地使用这两种工具——Gemini用于分析和视觉输入，Claude Code用于复杂的开发任务。</p>
<p>Gemini 将 Google 的 AI 带到您的终端，并提供慷慨的免费限制。</p>
<h4 id="">安装</h4>
<p>使用 npx (推荐试用)：</p>
<pre><code>npx @google/gemini-cli
</code></pre>
<p>全局安装：</p>
<pre><code>npm install -g @google/gemini-cli
gemini  # 开始交互式会话
</code></pre>
<h4 id="">认证</h4>
<ol>
<li>使用 Google 登录：</li>
</ol>
<pre><code>gemini auth login
</code></pre>
<ol start="2">
<li>检查状态：</li>
</ol>
<pre><code>gemini auth status
</code></pre>
<p>免费限制：</p>
<ul>
<li>
<p>60 次请求/分钟</p>
</li>
<li>
<p>使用 Google 帐户每日 1,000 次请求</p>
</li>
</ul>
<p>内置工具：</p>
<ul>
<li>
<p><code>/memory</code> – 管理对话记忆</p>
</li>
<li>
<p><code>/stats</code> – 查看使用统计</p>
</li>
<li>
<p><code>/tools</code> – 列出可用工具</p>
</li>
<li>
<p><code>/mcp</code> – 配置模型上下文协议服务器</p>
</li>
</ul>
<h4 id="geminicli">Gemini CLI 的限制</h4>
<p>如果您计划使用 Gemini，请考虑以下重要事项：</p>
<ul>
<li>
<p><strong>速率限制</strong> – 免费套餐 60 次请求/分钟，1,000次/天</p>
</li>
<li>
<p><strong>Google 依赖性</strong> – 需要 Google 帐户和互联网连接</p>
</li>
<li>
<p><strong>较新的工具</strong> – 相较于 GitHub Copilot，社区较小，资源较少</p>
</li>
<li>
<p><strong>面向终端</strong> – 与流行的 IDE 整合较少</p>
</li>
<li>
<p><strong>多模态处理</strong> – 图像上传有大小限制 (20MB)</p>
</li>
<li>
<p><strong>测试版功能</strong> – 某些高级功能可能不稳定</p>
</li>
</ul>
<h4 id="gemini">独特的 Gemini 特性</h4>
<p><strong>庞大的上下文窗口：</strong><br>
Gemini 可以在单个会话中处理超过 100 万个标记，这意味着它可以同时分析整个大型代码库。这对于理解复杂系统架构和多个文件之间的关系特别有用。</p>
<p><strong>多模态能力：</strong><br>
Gemini 能够处理和理解各种类型的视觉内容以及代码，使其在设计到代码的工作流程和视觉调试中具有独特的优势。</p>
<h4 id="">将您的草图转化为代码</h4>
<p>这真的很酷：您可以在纸上绘制一些东西，然后 Gemini 将其转化为可工作的代码！</p>
<p>操作方法如下：</p>
<ol>
<li>
<p><strong>创建您的草图：</strong> 在纸上、白板或数位板上绘制您的想法</p>
</li>
<li>
<p><strong>拍照或截图：</strong> 使用手机拍摄或截图，将草图数字化</p>
</li>
<li>
<p><strong>保存图像：</strong> 保存为 JPG、PNG 或 WebP 格式（小于 20MB）</p>
</li>
<li>
<p><strong>通过命令行将其展示给 Gemini：</strong></p>
</li>
</ol>
<pre><code>gemini -p "将此草图转化为具有良好样式的 React 组件" sketch.jpg
</code></pre>
<p><strong>替代方法：</strong></p>
<pre><code># 如果您处于交互会话中，您可以引用文件：
gemini
&gt; 分析此UI草图并创建HTML/CSS：@sketch.jpg

# 或在支持的终端中拖放
gemini
&gt; 将此设计实现为 Vue 组件
[将 sketch.jpg 拖入终端]
</code></pre>
<p>然后，Gemini 会查看您的图纸并生成：</p>
<ul>
<li>
<p>与您的草图匹配的工作 React 组件</p>
</li>
<li>
<p>使其看起来不错的精美 CSS 样式</p>
</li>
<li>
<p>如果您绘制了表单则提供表单验证</p>
</li>
<li>
<p>使其工作的所有代码</p>
</li>
</ul>
<p>这就像拥有一个能读懂您心思的设计师和开发人员！</p>
<h4 id="gemini">通过展示图像来修复 Gemini 中的错误</h4>
<p>UI 出现了 Bug？您可以向 Gemini 展示视觉信息以帮助调试：</p>
<pre><code>gemini -p "该 UI 看起来有问题。有什么问题，我该如何解决？" image.png
</code></pre>
<p>Gemini 可以分析视觉信息并告诉您：</p>
<ul>
<li>
<p>问题的原因是什么</p>
</li>
<li>
<p>需要修改哪些代码</p>
</li>
<li>
<p>有时还有更好的解决方法</p>
</li>
</ul>
<h4 id="">将架构图转化为代码</h4>
<p>画出系统架构图，Gemini 可以构建它：</p>
<pre><code>gemini -p "使用 Docker 和数据库构建此系统架构" diagram.jpg
</code></pre>
<p>Gemini 将：</p>
<ul>
<li>
<p>理解您的图示</p>
</li>
<li>
<p>创建您所需的所有 Docker 文件</p>
</li>
<li>
<p>设置数据库和连接</p>
</li>
<li>
<p>根据您的设计提供一个可工作的系统</p>
</li>
</ul>
<p>将设计翻译成代码不再需要耗费数小时，您可以：</p>
<ol>
<li>
<p>向 Gemini 展示您的草图或设计</p>
</li>
<li>
<p>让 Gemini 构建它</p>
</li>
<li>
<p>在几分钟内获得工作代码，而不是几个小时，只需根据需要进行细化</p>
</li>
</ol>
<p>大多数情况下，Gemini 初次尝试就能很接近您的期望。即使它并不完美，它也为您提供了一个很好的起点，节省了大量时间。</p>
<h3 id="13cli">第13步：比较 CLI 工具</h3>
<p>这里有一个简易表格来帮助您比较 Claude Code 和 Gemini CLI 的功能：</p>
<table>
<thead>
<tr>
<th><strong>功能</strong></th>
<th><strong>Claude Code</strong></th>
<th><strong>Gemini CLI</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>上下文窗口</strong></td>
<td>大</td>
<td>1M+ 令牌</td>
</tr>
<tr>
<td><strong>网络搜索</strong></td>
<td>内置</td>
<td>谷歌搜索集成</td>
</tr>
<tr>
<td><strong>文件编辑</strong></td>
<td>直接编辑</td>
<td>基于差异</td>
</tr>
<tr>
<td><strong>思维模式</strong></td>
<td>4 个等级</td>
<td>ReAct 循环</td>
</tr>
<tr>
<td><strong>IDE 集成</strong></td>
<td>VS Code 快捷键</td>
<td>终端优先</td>
</tr>
<tr>
<td><strong>免费层</strong></td>
<td>有限</td>
<td>慷慨 (1000/天)</td>
</tr>
<tr>
<td><strong>开源</strong></td>
<td>否</td>
<td>是</td>
</tr>
<tr>
<td><strong>多模态</strong></td>
<td>否</td>
<td>是 (图像, PDF)</td>
</tr>
</tbody>
</table>
<h3 id="14cli">第14步：高级 CLI 工作流程</h3>
<h4 id="1claudecode">工作流程1：Claude Code 的互动代码审查</h4>
<pre><code>Claude Code &gt; review my recent git changes

[Claude 分析差异]

Claude Code &gt; fix the security issue you found in the login function

Claude Code &gt; now create a pull request with a good description
</code></pre>
<h4 id="2gemini">工作流程2：Gemini 的对话式架构分析</h4>
<pre><code>Gemini &gt; analyze this codebase architecture and identify technical debt

[Gemini 提供全面的分析]

Gemini &gt; create a migration plan for the database issues you found

Gemini &gt; generate API documentation for the endpoints
</code></pre>
<h4 id="3">工作流程3：互动测试驱动开发</h4>
<pre><code>Claude Code &gt; I need to add payment processing. Start by writing comprehensive tests

[Claude 创建测试套件]

Claude Code &gt; now implement the payment service to pass these tests

Claude Code &gt; add error handling and edge cases
</code></pre>
<h3 id="vscodecli">结合 VS Code 和 CLI 工具</h3>
<h4 id="">混合工作流程的力量：</h4>
<p>最具生产力的开发者通常不会只选择一个 AI 工具——他们策略性地将 VS Code 扩展与 CLI 工具结合起来，以最大化效率。每个工具都有独特的优势，结合它们会创造出一个大于其各部分总和的工作流程。</p>
<p><strong>结合工具的好处：</strong></p>
<ul>
<li>
<p><strong>无缝的上下文切换：</strong> 从 Copilot 开始快速开发，然后无缝移动到 Claude Code 进行复杂的分析，而不失去动力</p>
</li>
<li>
<p><strong>互补的优势：</strong> 利用每个工具的最佳功能，如 Copilot 的实时建议 + Claude 的深入推理 + Gemini 的视觉处理</p>
</li>
<li>
<p><strong>持续的工作流：</strong> 无需在工具之间复制/粘贴代码—在项目中直接工作，并根据需要获得不同的 AI 支持</p>
</li>
<li>
<p><strong>减少心理负担：</strong> 工具处理不同的认知任务，让您专注于创造性的问题解决</p>
</li>
</ul>
<h4 id="">如何实际组合工具：</h4>
<p>示例工作流程——构建用户仪表板：</p>
<ol>
<li>
<p><strong>在 VS Code 中使用 Copilot 开始：</strong> 使用制表符补全快速构建基本组件结构</p>
</li>
<li>
<p><strong>保持 VS Code 打开，启动 Claude Code：</strong> 获取架构建议和重构建议，同时保持编辑器上下文</p>
</li>
<li>
<p><strong>切换到 Gemini 以获取视觉元素：</strong> 上传 UI 模型以生成匹配的样式</p>
</li>
<li>
<p><strong>返回到 VS Code：</strong> 应用所有建议，同时有 Copilot 协助实现细节</p>
</li>
</ol>
<p><strong>关键集成点：</strong></p>
<ul>
<li>
<p><strong>共享项目上下文：</strong> 所有工具在同一个目录中工作，了解您的项目结构</p>
</li>
<li>
<p><strong>文件系统协调：</strong> CLI 工具进行的更改会立即在 VS Code 中可见</p>
</li>
<li>
<p><strong>版本控制集成：</strong> 使用 CLI 工具进行 git 操作，而 VS Code 显示视觉差异</p>
</li>
</ul>
<h3 id="">快速切换设置</h3>
<h4 id="">什么是快速切换？</h4>
<p>快速切换设置指的是配置你的开发环境，让你可以快速在不同的 AI 工具之间切换，而不产生摩擦。通过创建快捷方式，而不是输入长命令或通过多个设置步骤进行导航，您可以立即访问当前任务所需的 AI 工具。</p>
<p>在您的 shell 配置文件中添加（<code>.zshrc</code> 或 <code>.bashrc</code>）：</p>
<pre><code># 快速 AI 命令用于交互模式
alias cc="claude"
alias gc="gemini"

# 在需要时进行快速单次命令
alias think="claude 'think hard:'"
alias analyze="gemini -p 'analyze:'"
</code></pre>
<h3 id="3">阶段3实践练习</h3>
<h4 id="1claudecode">练习1：互动 Claude Code 项目设置</h4>
<ol>
<li>
<p>创建一个新项目目录</p>
</li>
<li>
<p>启动：<code>claude</code></p>
</li>
<li>
<p>开始对话："set up a Node.js Express API with PostgreSQL"</p>
</li>
<li>
<p>继续聊天："add authentication middleware"</p>
</li>
<li>
<p>继续："now add comprehensive error handling"</p>
</li>
<li>
<p>查看生成的代码并提问</p>
</li>
</ol>
<h4 id="2gemini">练习2：互动 Gemini 代码分析</h4>
<ol>
<li>
<p>导航到现有项目</p>
</li>
<li>
<p>启动：<code>gemini</code></p>
</li>
<li>
<p>从以下内容开始："analyze this codebase and identify potential security vulnerabilities"</p>
</li>
<li>
<p>后续："explain the most critical issue in detail"</p>
</li>
<li>
<p>继续："create a fix for the authentication vulnerability"</p>
</li>
<li>
<p>询问："what other improvements should I prioritize?"</p>
</li>
<li>
<p>在 VS Code 中使用 Copilot 开始初始开发</p>
</li>
<li>
<p>切换到交互式 Claude Code 会话进行复杂的代码重构</p>
</li>
<li>
<p>使用交互式 Gemini 会话进行代码库分析和文档撰写</p>
</li>
<li>
<p>熟练地在工具之间无缝切换</p>
</li>
</ol>
<p>需要 CLI 工具的帮助吗？请参阅<a href="http://localhost:3333/#troubleshooting-quick-reference">故障排除快速参考</a>以了解设置和常见问题。</p>
<h2 id="stage-4">阶段 4：掌握 - 工具与高级工作流程的结合</h2>
<h3 id="15">第 15 步：工具选择策略</h3>
<h4 id="">何时使用每种工具</h4>
<p>那么，在你的工作流程中，什么时候应该使用每个工具呢？</p>
<p>当速度至关重要时，你可以将 GitHub Copilot 作为一名在线的结对程序员使用。它可以帮助你快速编写新函数、在输入时获得实时建议，并即时掌握不熟悉的 API 或框架。它也方便于在不中断你的工作流程的情况下快速查找文档。</p>
<p>然后，你可以转而使用 Claude Code 来处理更大、更复杂的任务：复杂的多文件重构、起草全面的测试以及“大声思考”关于架构和权衡的问题。在这里，它还可以帮助完成 Git 任务，比如指导你进行操作和组装拉取请求。</p>
<p>最后，当需要端到端分析大型代码库或将视觉输入（如截图/图表）整合到工作流程中时，可以从终端调用 Gemini CLI。由于可以免费使用，所以适合大量运行的场景，并且它适用于需要可定制、脚本友好的设置的场合。</p>
<h3 id="16mcpai">第 16 步：理解 MCP —— 让 AI 工具协同工作</h3>
<h4 id="mcp">什么是 MCP？</h4>
<p>MCP（模型上下文协议）是一种让你的 AI 工具增强能力的简单方法。可以把它想象成给你的手机增添应用程序——每个 MCP 服务器都会为你的 AI 增加新的功能。</p>
<h4 id="mcp">为什么初学者需要关注 MCP？</h4>
<p>没有 MCP 会遇到的问题是：你的 AI 只能处理它所知道的和你告诉它的内容。它无法：</p>
<ul>
<li>
<p>搜索网络上的当前信息</p>
</li>
<li>
<p>自动测试你的网站</p>
</li>
<li>
<p>在会话之间记住你的项目细节</p>
</li>
<li>
<p>连接到你的数据库或 API</p>
</li>
</ul>
<p>但有了 MCP 服务器，你的 AI 就能突然：</p>
<ul>
<li>
<p><strong>获取当前信息</strong> —— 从 Google 搜索最新的文档和解决方案</p>
</li>
<li>
<p><strong>测试你的代码</strong> —— 自动检查你的网站是否正常工作</p>
</li>
<li>
<p><strong>记住你的项目</strong> —— 跟踪你的架构和决策</p>
</li>
<li>
<p><strong>连接到工具</strong> —— 使用 GitHub、数据库等</p>
</li>
</ul>
<p>所以，相比于手动重复劳动，你的 AI 可以自动处理这些任务。这意味着你将花更少的时间去谷歌搜索错误消息、手动测试代码，以及在每个会话中向 AI 解释你的项目，而是花更多时间实际构建东西。</p>
<h4 id="mcp">初学者简单的 MCP 示例</h4>
<p>以下是 MCP 能为你做的一些初学者友好的示例：</p>
<p><strong>示例 1：无需谷歌搜索的帮助</strong></p>
<pre><code>你：“这个 CSS 不工作。找出原因并修复它”

没有 MCP：你需要谷歌搜索错误，阅读文档，尝试解决方案
有了 MCP：AI 搜索当前的 CSS 文档，找出问题，并自动修复
</code></pre>
<p><strong>示例 2：自动测试你的网站</strong></p>
<pre><code>你：“检查我的联系表单是否正常工作”

没有 MCP：你需要手动填写表单，检查邮件，测试边缘案例
有了 MCP：AI 填写表单，确认邮件已发送，测试不同的输入
</code></pre>
<p><strong>示例 3：AI 记住你的项目</strong></p>
<pre><code>你：“为我的待办事项应用程序添加一项新功能”

没有 MCP：你需要解释数据库结构、API 路线、前端框架
有了 MCP：AI 已记住一切并直接构建功能
</code></pre>
<h4 id="mcp">准备尝试 MCP 吗？</h4>
<p>如果这看起来很复杂，不用担心！你可以从一个简单的 MCP 服务开始，在适应后再添加更多。</p>
<h4 id="mcp">初学者简单的 MCP 设置</h4>
<p>我们将从 VS Code 开始（因为这是最简单的选项）：</p>
<ol>
<li>
<p>打开 VS Code</p>
</li>
<li>
<p>转到扩展（Ctrl+Shift+X）</p>
</li>
<li>
<p>搜索“GitHub Copilot MCP”或类似的 MCP 扩展</p>
</li>
<li>
<p>点击“安装”</p>
</li>
</ol>
<p>这样就完成了！扩展会自动处理一切。</p>
<p>通过这样做，你可以为你的 AI 获取网络搜索功能、基本项目记忆力和简单的自动化功能。</p>
<p>要测试它，试着让你的 AI：“搜索最新的 React 最佳实践并给我一个示例”。 如果它能搜索并返回当前的信息，MCP 就正常工作了！</p>
<h4 id="mcp">想要更多的 MCP 功能吗？</h4>
<p>一旦你适应了基本的 MCP，可以探索下面更高级的设置：</p>
<ul>
<li>
<p>自定义 MCP 服务器安装</p>
</li>
<li>
<p>高级配置选项</p>
</li>
<li>
<p>构建自己的 MCP 集成</p>
</li>
</ul>
<p>目前，上述的 VS Code 扩展方法将为你提供充足的 AI 超能力以便入门！</p>
<p>**这就是 MCP 的精要！**从上面的简单 VS Code 扩展方法开始，你将迅速看到你的 AI 变得多么强大。</p>
<h4 id="">下一步</h4>
<ul>
<li>
<p>尝试基础的 VS Code MCP 扩展</p>
</li>
<li>
<p>使用简单的请求进行测试，比如“搜索 X 并实现它”</p>
</li>
<li>
<p>熟悉后，探索更多的第 4 阶段 MCP 服务器</p>
</li>
</ul>
<p>MCP 将你的 AI 从代码建议工具转变为真正的开发伙伴。最好的部分是？一旦你用一个工具设置好，它就会与所有工具协同工作！</p>
<p>如果 AI 提示无法搜索网络，可以尝试以下几种方法。</p>
<p>首先，检查 MCP 扩展是否确实安装在 VS Code 中。然后尝试重启 VS Code。最后，要确保你的提问方式是 AI 能理解的，比如：“搜索 X 并展示 Y”。</p>
<p>如果 VS Code 扩展无法安装，尝试检查你的网络连接或将 VS Code 更新到最新版本。你也可以尝试使用不同名称搜索“MCP”或“Model Context Protocol”扩展。</p>
<p>如果仍然遇到问题，我们将在下文中介绍高级故障排除方法。或者你也可以询问你的 AI：“帮助我排查 MCP 设置故障”。</p>
<h3 id="mcp">高级 MCP 设置与集成</h3>
<h4 id="mcp">手动 MCP 服务器安装</h4>
<p>对于希望完全控制其 MCP 设置的高级用户：</p>
<p><strong>步骤 1：安装 MCP 服务器</strong></p>
<p>大多数 MCP 服务器可以通过 npm 安装：</p>
<pre><code># 用于网络自动化和测试
npm install -g @modelcontextprotocol/server-puppeteer

# 用于无需 API 密钥的网络搜索
npm install -g @mcp-servers/duckduckgo

# 用于数据库访问
npm install -g @modelcontextprotocol/server-postgres
</code></pre>
<p>某些服务器（如 GitHub）则使用 Docker：</p>
<pre><code>docker pull ghcr.io/github/github-mcp-server
</code></pre>
<p><strong>步骤 2：配置你的工具</strong></p>
<p><strong>理解层次化配置：</strong></p>
<p>每个 AI 工具在多个位置检查 MCP 配置，更具体的设置优先级高于一般设置。这意味着你可以有全局默认值，但可以针对特定项目进行覆盖。这就像 CSS——更具体的规则覆盖一般规则。</p>
<p><strong>Claude Code 具有最灵活的设置：</strong></p>
<p>Claude Code 配置层次结构（按顺序检查）：</p>
<ol>
<li>
<p><strong>项目级别</strong>：<code>.claude/mcp.json</code>（最高优先级）</p>
</li>
<li>
<p><strong>本地设置</strong>：<code>.claude/settings.local.json</code></p>
</li>
<li>
<p><strong>全局配置</strong>：<code>~/.claude/mcp.json</code>（后备）</p>
</li>
</ol>
<p>其他工具：</p>
<ul>
<li>
<p><strong>VS Code</strong>：<code>.vscode/mcp.json</code>（仅项目级别）</p>
</li>
<li>
<p><strong>Cursor</strong>：<code>.cursor/mcp.json</code>（仅项目级别）</p>
</li>
<li>
<p><strong>Windsurf</strong>：使用 VS Code 的配置格式</p>
</li>
</ul>
<p>以下是一个示例配置（适用于任何工具，只需调整文件位置）：</p>
<pre><code>{
  "mcpServers": {
    "puppeteer": {
      "command": "npx",
      "args": ["@modelcontextprotocol/server-puppeteer"]
    },
    "duckduckgo": {
      "command": "npx",
      "args": ["@mcp-servers/duckduckgo"]
    },
    "github": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        "GITHUB_PERSONAL_ACCESS_TOKEN",
        "ghcr.io/github/github-mcp-server"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "your_token_here"
      }
    }
  }
}
</code></pre>
<h4 id="mcp">生产环境 MCP 服务器</h4>
<p><strong>1. 颠覆性认知工具：</strong></p>
<p><strong>序列思维服务器：</strong><br>
该服务器通过将复杂问题分解为逻辑步骤来改变 AI 处理复杂问题的方式。当你要求实现一个大型功能时，AI 不会直接跳到代码实施，而是首先创建一个详细的计划，其中包含阶段、依赖关系和决策点。</p>
<p>这对于重构遗留系统或构建新功能来说是无价的，尤其是在操作顺序很重要的情况下。服务器在整个开发会话期间保持这种规划上下文，确保决策的一致性。</p>
<p><strong>记忆库服务器：</strong><br>
消除了每次会话都需要重新解释项目结构的烦恼。该服务器会创建有关你的架构选择、编码标准、团队偏好和项目目标的持久性记忆。当你几天后返回工作时，AI 可以立即知道你的数据库架构、API 模式，甚至为什么做出某些决策。它就像一个随着你的开发工作完美同步的项目文档系统。</p>
<p><strong>知识图谱服务器：</strong><br>
创建代码库关系的动态地图——不仅仅是文件依赖，还有功能、共享工具和架构模式之间的概念连接。当你修改一个组件时，AI 可以立即识别出可能需要更新的所有相关区域。这可以防止由于遗漏相关更改而导致的错误，并有助于重构期间的影响分析。</p>
<p><strong>2. 网页自动化与测试服务器：</strong></p>
<p><strong>Puppeteer Server：</strong><br>
提供无头浏览器的控制，用于综合测试工作流。AI 可以自动浏览你的 Web 应用程序，填写表单、点击按钮，并验证预期行为。</p>
<p>这在回归测试中特别强大——AI 可以重播用户工作流并在部署前捕获更改。此外，它还启用基于截图的测试和性能监控自动化。</p>
<p><strong>Playwright Server：</strong><br>
同时扩展 Chrome、Firefox 和 Safari 浏览器的自动化功能。该服务器对于跨浏览器兼容性测试至关重要，并允许 AI 在开发初期捕获特定浏览器的问题。</p>
<p>与手动测试不同，AI 可以在所有浏览器上并行运行相同的测试场景，生成关于功能和性能差异的比较报告。</p>
<p><strong>3. 开发集成服务器：</strong></p>
<p><strong>GitHub Server：</strong><br>
将终端转变为具有 AI 智能的完整 GitHub 界面。AI 可以自动创建分支、管理拉取请求、分析代码审查评论，甚至根据代码更改生成 PR 描述。它还可以根据内容分析分配标签，并通过理解问题与实际代码更改之间的关系来维护项目板。</p>
<p><strong>PostgreSQL 服务器：</strong><br>
支持直接的数据库分析和优化。人工智能可以检查查询性能、建议索引优化、分析数据模式，甚至生成迁移脚本。此服务器在调试生产问题时特别有价值，因为人工智能需要理解实际的数据分布和查询执行模式，而不仅仅是理论上的数据库设计。</p>
<p><strong>4. 辅助工具：</strong></p>
<p><strong>MCP Compass</strong><br>
帮助您为任何任务找到合适的 MCP 服务器。</p>
<p>这些服务器将您的人工智能从代码建议者转变为能够测试、搜索、记忆和自动化的真正开发合作伙伴！</p>
<h3 id="17">步骤 17：高级提示工程</h3>
<h4 id="">上下文提示</h4>
<p>提供示例：</p>
<pre><code>// 替代用语："创建一个验证函数"
// 使用："创建一个类似这样的验证函数但用于电子邮件：
// function validatePhone(phone) { return /^\d{10}$/.test(phone); }"
</code></pre>
<p>指定约束条件：</p>
<pre><code>claude "将此代码重构为使用函数式编程，不使用循环，使用 map/filter/reduce"
</code></pre>
<p>包括边缘案例：</p>
<pre><code>gemini -p "实现用户认证，处理以下情况：过期令牌、并发登录、速率限制"
</code></pre>
<h3 id="18ai">步骤 18：构建 AI 辅助开发流水线</h3>
<h4 id="">自动化代码审查流水线</h4>
<ol>
<li>使用 Copilot 进行预提交检查：</li>
</ol>
<pre><code>// .copilot-instructions
"审核所有更改以发现：安全问题、性能问题、代码风格"
</code></pre>
<ol start="2">
<li>使用 Claude 进行 PR 审查：</li>
</ol>
<pre><code>claude "审查此 PR：git diff main..feature-branch"
</code></pre>
<ol start="3">
<li>使用 Gemini 完成文档：</li>
</ol>
<pre><code>gemini -p "为这些更改生成更新日志并更新 README"
</code></pre>
<h4 id="ai">测试驱动的 AI 开发</h4>
<ol>
<li>编写测试规范：</li>
</ol>
<pre><code>claude "为支付处理系统编写全面的测试规范"
</code></pre>
<ol start="2">
<li>生成测试代码：</li>
</ol>
<pre><code>gemini -p "使用 Jest 实现这些测试规范"
</code></pre>
<ol start="3">
<li>
<p>使用 Copilot 实现：</p>
<ul>
<li>
<p>使用代理模式实现功能</p>
</li>
<li>
<p>测试指导实现过程</p>
</li>
</ul>
</li>
</ol>
<h3 id="19ai">步骤 19：创建您的个人 AI 工作流</h3>
<h4 id="">设置您的环境</h4>
<p>1. VS Code 设置（<code>settings.json</code>）：</p>
<pre><code>{
  "github.copilot.enable": {
    "*": true
  },
  "github.copilot.advanced": {
    "inlineCompletions.enable": true,
    "chat.enabled": true
  }
}
</code></pre>
<p>2. Claude 代码配置（<code>~/.claude/settings.json</code>）：</p>
<pre><code>{
  "cleanupPeriodDays": 7,
  "permissions": {
    "allow": [
      "Bash(fd:*)",
      "Bash(rg:*)",
      "Bash(ls:*)",
      "WebFetch(domain:github.com)",
      "WebFetch(domain:stackoverflow.com)"
    ],
    "deny": ["WebFetch(domain:medium.com)"]
  }
}
</code></pre>
<p>3. Gemini 设置（<code>~/.gemini/config.json</code>）：</p>
<pre><code>{
  "defaultModel": "gemini-2.5-pro",
  "contextWindow": "large",
  "safetyMode": "interactive"
}
</code></pre>
<h4 id="">自定义命令和别名</h4>
<p>为常见任务设置 Shell 别名：</p>
<pre><code># 启动互动会话
alias cc='claude'
alias gc='gemini'

# 快速一次性命令（在需要时）
alias aicommit='claude "创建一个带有描述性信息的 git 提交"'
alias aireview='claude "审查我的未提交更改"'
alias complexity='gemini -p "分析代码复杂性并建议简化"'
alias security='claude "更深入思考：检查安全漏洞"'
alias aidocs='gemini -p "生成全面的文档"'
</code></pre>
<h3 id="ai">最终项目：构建一个完整的应用程序与 AI</h3>
<h4 id="">项目要求</h4>
<p>构建一个任务管理 API，具备：</p>
<ul>
<li>
<p>用户认证</p>
</li>
<li>
<p>CRUD 操作</p>
</li>
<li>
<p>实时更新</p>
</li>
<li>
<p>测试套件</p>
</li>
<li>
<p>文档</p>
</li>
</ul>
<h4 id="">建议工作流程</h4>
<p>阶段 1：互动规划</p>
<pre><code># 启动 Claude 代码会话
claude

Claude Code &gt; 超级思考：设计一个可扩展的任务管理 API 架构

[Claude 提供详细分析]

Claude Code &gt; 现在将其分解为实施阶段

# 切换到 Gemini 进行规格说明
gemini

Gemini &gt; 为此任务管理 API 创建详细的技术规格

Gemini &gt; 包括数据库架构和 API 端点规格
</code></pre>
<p>阶段 2：互动实现</p>
<ol>
<li>
<p>使用 Copilot 代理模式进行初始设置</p>
</li>
<li>
<p>使用内联 Copilot 实现功能</p>
</li>
<li>
<p>切换到互动 Claude 代码会话处理复杂逻辑：</p>
</li>
</ol>
<pre><code>Claude Code &gt; 实施我们计划的用户认证系统

Claude Code &gt; 现在添加任务 CRUD 操作

Claude Code &gt; 用 WebSockets 集成实时更新
</code></pre>
<p>阶段 3：互动测试与文档</p>
<pre><code># Claude 代码会话用于测试
claude

Claude Code &gt; 为所有 API 端点编写全面测试

Claude Code &gt; 为身份验证流程添加集成测试

Claude Code &gt; 为高负载场景创建性能测试

# Gemini 生成文档
gemini

Gemini &gt; 生成包含示例的全面 API 文档

Gemini &gt; 创建开发者入职指南
</code></pre>
<p>阶段 4：互动优化</p>
<pre><code># Claude 代码进行性能优化
claude

Claude Code &gt; 分析并优化我们的数据库查询

Claude Code &gt; 为经常访问的数据实现缓存

Claude Code &gt; 添加监控和日志

# Gemini 进行最终审查
gemini

Gemini &gt; 审查整个代码库以进行改进
</code></pre>
<h3 id="">衡量你的进展</h3>
<h4 id="1">阶段 1 里程碑</h4>
<ul>
<li>
<p>熟悉标签补全</p>
</li>
<li>
<p>可以编写有效的提示语</p>
</li>
<li>
<p>理解 AI 的局限性</p>
</li>
</ul>
<h4 id="2">阶段 2 里程碑</h4>
<ul>
<li>
<p>有效使用多个模型</p>
</li>
<li>
<p>掌握聊天模式和代理</p>
</li>
<li>
<p>使用高级聊天功能</p>
</li>
</ul>
<h4 id="3">阶段 3 里程碑</h4>
<ul>
<li>
<p>熟练使用 CLI 工具</p>
</li>
<li>
<p>可以将 VS Code 和终端工作流结合起来</p>
</li>
<li>
<p>了解工具的优势</p>
</li>
</ul>
<h4 id="4">阶段 4 里程碑</h4>
<ul>
<li>
<p>创建自定义 AI 工作流</p>
</li>
<li>
<p>使用 AI 构建完整应用程序</p>
</li>
<li>
<p>可以教别人 AI 辅助开发</p>
</li>
</ul>
<h3 id="4">阶段 4 练习</h3>
<h4 id="1">练习 1：掌握工具选择</h4>
<ol>
<li>
<p>选择一个中等复杂的编码任务（例如，“构建一个 URL 缩短服务 API”）</p>
</li>
<li>
<p>计划每个阶段使用的工具（设计、编码、测试、部署）</p>
</li>
<li>
<p>按照你选择的工作流程执行</p>
</li>
<li>
<p>记录哪些工作顺利，哪些需要改进</p>
</li>
</ol>
<h4 id="2">练习 2：创建自定义工作流</h4>
<ol>
<li>
<p>识别工作中的重复性开发任务</p>
</li>
<li>
<p>设计一个使用多个工具的 AI 辅助工作流</p>
</li>
<li>
<p>测试并改进该工作流</p>
</li>
<li>
<p>为团队同事创建相关文档</p>
</li>
</ol>
<h4 id="3">练习 3：完整项目构建</h4>
<ol>
<li>
<p>使用 AI 辅助构建一个小型但完整的应用程序</p>
</li>
<li>
<p>战略性地使用至少两种不同 AI 工具</p>
</li>
<li>
<p>包括测试、文档和部署</p>
</li>
<li>
<p>反思比起传统开发的效率提升</p>
</li>
</ol>
<h3 id="">继续你的旅程</h3>
<h4 id="">持续更新</h4>
<ul>
<li>
<p>关注工具的更新说明</p>
</li>
<li>
<p>加入 AI 编码社区</p>
</li>
<li>
<p>试验新功能</p>
</li>
</ul>
<h4 id="">探索高级主题</h4>
<ul>
<li>
<p>自定义 MCP 服务器开发</p>
</li>
<li>
<p>AI 模型微调</p>
</li>
<li>
<p>企业部署策略</p>
</li>
<li>
<p>团队协作模式</p>
</li>
</ul>
<h4 id="">持续学习资源</h4>
<ul>
<li>
<p>每个工具的官方文档</p>
</li>
<li>
<p>社区论坛和 Discord 服务器</p>
</li>
<li>
<p>开源 AI 编码项目</p>
</li>
<li>
<p>会议演讲和教程</p>
</li>
</ul>
<h2 id="common-ai-issues">常见 AI 问题</h2>
<p>即便使用最好的 AI 工具，你仍会遇到挑战。一旦你了解模式，这些问题是正常且可管理的。以下是开发者面临的最常见问题以及实际可行的解决方案。</p>
<h3 id="ai">“我的 AI 建议很糟！”</h3>
<p><strong>问题：</strong> AI 给出的建议无关或错误</p>
<p><strong>解决方案：</strong></p>
<ul>
<li>
<p>写更清晰的注释</p>
</li>
<li>
<p>打开相关文件以提供上下文</p>
</li>
<li>
<p>从简单任务开始</p>
</li>
<li>
<p>确保你在正确的文件类型中</p>
</li>
</ul>
<p><strong>示例修正：</strong></p>
<pre><code>// 原先: "make function"
// 尝试: "create function to validate US phone number format (xxx) xxx-xxxx"
</code></pre>
<h3 id="ai">“AI 太慢”</h3>
<p><strong>问题：</strong> 等待建议时间过长</p>
<p><strong>解决方案：</strong></p>
<ul>
<li>
<p>检查你的网络连接</p>
</li>
<li>
<p>关闭不必要的程序</p>
</li>
<li>
<p>尝试较轻量级的 AI 工具</p>
</li>
<li>
<p>要有耐心 —— 复杂建议需要时间</p>
</li>
</ul>
<h3 id="ai">“我害怕过于依赖 AI”</h3>
<p><strong>问题：</strong> 担心丧失编码能力</p>
<p><strong>解决方案：</strong></p>
<ul>
<li>
<p>将 AI 作为学习工具，而非依赖的工具</p>
</li>
<li>
<p>在接受之前务必理解代码</p>
</li>
<li>
<p>定期练习不使用 AI 编码</p>
</li>
<li>
<p>专注于解决问题，而非语法</p>
</li>
</ul>
<h3 id="">“它建议使用过时代码”</h3>
<p><strong>问题：</strong> AI 建议的模式老旧或使用了废弃的方法</p>
<p><strong>解决方案：</strong></p>
<ul>
<li>
<p>在注释中指定版本</p>
</li>
<li>
<p>保持工具的更新</p>
</li>
<li>
<p>学会识别过时的模式</p>
</li>
</ul>
<p><strong>示例：</strong></p>
<pre><code>// create React functional component using hooks (not class component)
</code></pre>
<h3 id="">故障排除快速参考</h3>
<h4 id="">常见问题（所有工具）</h4>
<table>
<thead>
<tr>
<th><strong>问题</strong></th>
<th><strong>快捷修复</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>没有 AI 建议</td>
<td>检查网络连接，重启编辑器，验证登录</td>
</tr>
<tr>
<td>“需要付款”消息</td>
<td>检查免费层限制，验证账户状态</td>
</tr>
<tr>
<td>建议效果差</td>
<td>使用更清晰的注释，打开相关文件提供上下文</td>
</tr>
<tr>
<td>工具无法安装</td>
<td>更新编辑器，检查网络，尝试不同安装方法</td>
</tr>
</tbody>
</table>
<h4 id="githubcopilot">GitHub Copilot 问题</h4>
<table>
<thead>
<tr>
<th><strong>问题</strong></th>
<th><strong>解决方案</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>VS Code 无建议</td>
<td>检查右下角“GitHub Copilot”状态</td>
</tr>
<tr>
<td>免费层过期</td>
<td>查看 <a href="https://docs.github.com/en/copilot/how-tos/manage-your-account/getting-free-access-to-copilot-pro-as-a-student-teacher-or-maintainer">学生/维护者免费访问</a></td>
</tr>
<tr>
<td>代理模式不起作用</td>
<td>尝试 <code>Shift+Cmd+I</code>（Mac）或 <code>Ctrl+Shift+I</code>（Windows/Linux）</td>
</tr>
<tr>
<td>聊天无响应</td>
<td>尝试重启 VS Code，检查网络连接</td>
</tr>
</tbody>
</table>
<h4 id="claudecode">Claude Code 问题</h4>
<table>
<thead>
<tr>
<th><strong>问题</strong></th>
<th><strong>解决方案</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>“命令未找到”</td>
<td>重新安装：<code>npm uninstall -g @anthropic-ai/claude-code &amp;&amp; npm install -g @anthropic-ai/claude-code</code></td>
</tr>
<tr>
<td>认证失败</td>
<td>运行 <code>claude auth login</code>，检查剩余 API 信用额度</td>
</tr>
<tr>
<td>响应缓慢</td>
<td>网络检查：<code>ping api.anthropic.com</code>，尝试轻量模型：<code>--model claude-3-haiku</code></td>
</tr>
<tr>
<td>MCP 服务器不起作用</td>
<td>检查 <code>~/.claude/mcp.json</code> 语法，测试服务器：<code>npx @mcp/server-github --help</code></td>
</tr>
<tr>
<td>命令挂起/卡住</td>
<td>按 <code>Ctrl+C</code> 取消，重启终端，检查后台进程</td>
</tr>
</tbody>
</table>
<h4 id="geminicli">Gemini CLI 问题</h4>
<table>
<thead>
<tr>
<th><strong>问题</strong></th>
<th><strong>解决方案</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>需要认证</td>
<td>运行 <code>gemini auth login</code>，检查 Google 账户权限</td>
</tr>
<tr>
<td>超过速率限制</td>
<td>检查使用情况：<code>gemini /stats</code>，等待 1 分钟或升级计划</td>
</tr>
<tr>
<td>无法安装</td>
<td>尝试 <code>npx @google/gemini-cli</code>，检查 Node.js 16+</td>
</tr>
<tr>
<td>图片上传失败</td>
<td>检查格式（JPG/PNG/WebP），大小小于 20MB，验证文件路径</td>
</tr>
<tr>
<td>上下文窗口错误</td>
<td>将大请求分割成小部分，清除历史记录</td>
</tr>
</tbody>
</table>
<p>如果一切无效，请按顺序尝试以下方法：</p>
<ol>
<li>
<p>重启你的编辑器/终端</p>
</li>
<li>
<p>检查互联网连接</p>
</li>
<li>
<p>确认你已登录到正确的账户</p>
</li>
<li>
<p>更新工具至最新版本</p>
</li>
<li>
<p>尝试不同的工具（如果一个失败了，通常其他的会有效）</p>
</li>
<li>
<p>询问 AI 自己：“帮助我排查 troubleshoottool_tool_setup”</p>
</li>
</ol>
<h2 id="whats-next-after-completing-all-stages">完成所有阶段后有哪些后续步骤？</h2>
<p>一旦你掌握了基础知识，这里有一些简单的后续步骤：</p>
<h3 id="">与团队合作</h3>
<h4 id="ai">团队 AI 工作流基础</h4>
<p><strong>共享提示库：</strong></p>
<p>构建团队提示库可以改变你整个团队使用 AI 的方式。首先创建一个共享的仓库，让开发者记录适用于你特定领域和代码库的有效提示。</p>
<p>例如，如果你正在构建电子商务软件，为常见任务创建标准化提示，如“生成符合我们 REST 约定的产品目录 API 端点”或“使用我们的标准模式创建支付处理错误处理”。</p>
<p>记录成功的代理模式工作流供团队成员重复使用。某位开发者可能会发现 Claude Code 在给定有关模式演化实践的特定上下文时，特别适合数据库迁移。通过共享这些工作流，你可以避免每个团队成员独立地发现有效的方法。</p>
<p><strong>工具标准化：</strong></p>
<p>当每个人都使用兼容的 AI 工具时，团队生产力会倍增。根据团队的需要确定主要工具——例如，所有开发者都使用 GitHub Copilot，以确保一致的内联支持，再加上 Claude Code 以处理需要深入推理的复杂架构任务。制定清晰的指南，规定何时使用自主的代理模式与协作会话，以防止冲突并确保代码质量。</p>
<p>配置共享的 MCP 服务器设置，以便所有团队成员都能访问相同的增强型 AI 功能。这可能包括内部 API 的团队专用服务器、共享数据库访问或了解你的部署管道的定制工具。当每个人都拥有相同的 AI 功能时，协作就会变得顺畅无比。</p>
<p><strong>AI 生成的代码审查：</strong></p>
<p>将你的代码审查过程转变为与 AI 生成的代码有效协作。为在拉取请求中标记 AI 生成的部分建立惯例——这有助于审查者将注意力集中在适当的地方。审查者可以专注于架构决策、业务逻辑正确性和需要人工判断的集成模式，而不是挑剔 AI 通常处理得很好的语法。</p>
<p>对 AI 生成的代码实施严格的测试，因为自动化测试比手动审查更可靠地捕捉 AI 错误。为测试 AI 输出创建团队标准，包括 AI 可能遗漏的边缘案例和集成场景。这样你就能在享受 AI 带来的速度的同时，通过系统的验证保持质量。</p>
<p><strong>在提交信息中记录 AI 工具决策。</strong></p>
<h4 id="">简单的团队设置</h4>
<p>从小处着手，逐步建立：</p>
<ul>
<li>
<p>首先让每个人使用相同的 AI 工具</p>
</li>
<li>
<p>创建一个适合你项目的提示共享文档</p>
</li>
<li>
<p>找出团队何时应该使用代理模式与常规协助模式</p>
</li>
<li>
<p>为你最重要的团队工具设置 MCP 服务器</p>
</li>
</ul>
<h3 id="">对于更大的项目</h3>
<p>随着项目的发展，你可能会想要：</p>
<ul>
<li>
<p>为不同的任务尝试不同的 AI 模型（简单代码用快速的，复杂问题用强大的）</p>
</li>
<li>
<p>为你经常执行的任务创建快捷方式</p>
</li>
<li>
<p>将 AI 工具与现有开发工作流连接</p>
</li>
</ul>
<h3 id="">持续学习</h3>
<p>AI 编码工具每个月都在进步！通过以下方式保持最新：</p>
<ul>
<li>
<p>关注工具的发行说明（他们会发送更新邮件）</p>
</li>
<li>
<p>加入 AI 编码的 Discord 社区</p>
</li>
<li>
<p>尝试新功能，因为它们不断出现</p>
</li>
</ul>
<h2 id="conclusion">结语</h2>
<p>恭喜你！你现在已经拥有了开启 AI 辅助编码之旅的所有必需品。记住，每个专家都曾是初学者，而有 AI 作为你的编码伙伴，你可以比以往更快地学习和成长。</p>
<p><strong>记住：</strong></p>
<ul>
<li>
<p>AI 不会取代你的创造力——它会放大创造力</p>
</li>
<li>
<p>每个建议都是一次学习的机会</p>
</li>
<li>
<p>错误是旅程的一部分</p>
</li>
<li>
<p>社区在这里帮助你</p>
</li>
</ul>
<p>你不仅仅是在学习用 AI 编码——你是在了解软件开发的未来。几个月后，你会想知道自己过去是如何在没有它的情况下编码的。今天拥抱 AI 辅助的开发者将成为明日的领袖。</p>
<p>Happy coding! 🚀</p>
<!--kg-card-end: markdown--> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 来自 freeCodeCamp 社区的圣诞礼物：学习 Python、SQL、西班牙语等课程 ]]>
                </title>
                <description>
                    <![CDATA[ 2025 年对全球 freeCodeCamp 社区来说是精彩纷呈的一年。我们非常激动地以一系列圣诞礼物为这一年画上圆满句号：  1. freeCodeCamp Python 认证  2. freeCodeCamp JavaScript 认证（第 10 版）  3. freeCodeCamp 响应式 Web 设计认证（第 10 版）  4. freeCodeCamp 关系型数据库 + SQL 认证  5. 我们的 A2 级开发者英语认证  6. 我们的 B1 级开发者英语认证  7. 我们的 A1 级西班牙语课程（测试版）  8. 我们的 A1 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/christmas-gifts-freecodecamp-community-2025/</link>
                <guid isPermaLink="false">694b60661acf9a04cd95df3e</guid>
                
                    <category>
                        <![CDATA[ 社区 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ freeCodeCamp ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Miya Liu ]]>
                </dc:creator>
                <pubDate>Wed, 24 Dec 2025 05:29:57 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2025/12/----_20251224114011_141_113.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/christmas-gifts-freecodecamp-community-2025/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Christmas gifts for you from the freeCodeCamp community: Learn Python, SQL, Spanish, and more</a>
      </p><p>2025 年对全球 freeCodeCamp 社区来说是精彩纷呈的一年。我们非常激动地以一系列圣诞礼物为这一年画上圆满句号：</p><ol><li>freeCodeCamp Python 认证</li><li>freeCodeCamp JavaScript 认证（第 10 版）</li><li>freeCodeCamp 响应式 Web 设计认证（第 10 版）</li><li>freeCodeCamp 关系型数据库 + SQL 认证</li><li>我们的 A2 级开发者英语认证</li><li>我们的 B1 级开发者英语认证</li><li>我们的 A1 级西班牙语课程（测试版）</li><li>我们的 A1 级中文课程（测试版）</li></ol><p>如此丰厚的礼物，我们开始拆封吧！</p><h2 id="-10-">编程认证与全栈开发课程第 10 版</h2><p>在过去的 11 年里，freeCodeCamp 社区对核心编程课程体系进行了多次构建与重构。</p><p>如今我们终于实现编程课程兼具全面性与互动性的愿景。</p><p>第 10 版课程包含 6 项认证，每项认证都包含十余个实践项目，帮助你扎实掌握核心技能。</p><!--kg-card-begin: markdown--><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766529240482/d07520b2-ba51-427d-a053-403381c4d185.webp" alt="我们刚刚发布的 Python 课程的截图" class="image--center mx-auto" width="1654" height="1446" loading="lazy"><!--kg-card-end: markdown--><p>在每项认证结束时，你将参加一次期末考试。如果你能通过考试，将获得一份免费的认证证书。你可以将此证书加入 LinkedIn 个人资料，或添加到你的简历、履历或个人作品集网站中。</p><p>截至目前，已有 4 项认证正式上线：</p><ul><li><a href="https://www.freecodecamp.org/news/freecodecamps-new-responsive-web-design-certification-is-now-live/">响应式 Web 设计认证发布</a></li><li><a href="https://www.freecodecamp.org/news/freecodecamps-new-javascript-certification-is-now-live/">JavaScript 认证发布</a></li><li><a href="https://www.freecodecamp.org/news/freecodecamps-new-python-certification-is-now-live/">Python 认证发布</a></li><li><a href="https://www.freecodecamp.org/news/freecodecamps-new-relational-databases-certification-is-now-live/">关系型数据库认证发布</a></li></ul><p>我们将在 2026 年发布前端库认证与后端开发认证。</p><p>在获得全部 6 项认证后，你可以构建一个最终的毕业项目，该项目将由经验丰富的开发者进行代码审查。随后你将参加综合期末考试，通过后即可获得我们最终的全栈开发工程师认证。</p><p>如果你现在就开始学习前四项认证，那么在你学完之前，后两项认证也会发布了。毕竟，每项认证都涵盖了数百小时的理论计算机科学知识和动手编程实践。</p><h2 id="-">语言课程</h2><p>你可能会问：freeCodeCamp 是从何时开始教授世界语言的？</p><p>实际上，我们从 2022 年就开始设计“开发者英语”课程体系。在过去的几年间，我们对其进行了大幅扩展。</p><p>该课程通过手绘动画角色进行互动教学。在学习过程中，你将进行大量的阅读、写作、听力练习，口语练习功能也将在 2026 年上线。</p><!--kg-card-begin: markdown--><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766527685142/e1cc58c5-a245-4777-b2cf-b97dd7790d27.webp" alt="语言学习的 6 个 CEFR 级别图表" class="image--center mx-auto" width="1024" height="768" loading="lazy"><!--kg-card-end: markdown--><p>这是一套以故事驱动的课程体系。你将化身为一位刚抵达加利福尼亚、即将加入科技初创企业的开发者，在新生活的日常互动中，你将逐步掌握语法、词汇、技术术语乃至地道俚语。</p><!--kg-card-begin: markdown--><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766527748381/abc33dff-e9bf-4efb-bd4c-46362e42f288.webp" alt="开发者英语课程的截图" class="image--center mx-auto" width="856" height="656" loading="lazy"><!--kg-card-end: markdown--><p>截至目前，已有两项语言认证正式上线：</p><ul><li><a href="https://www.freecodecamp.org/news/freecodecamps-a2-english-for-developers-certification-is-now-live/">A2 级别英语认证发布</a></li><li><a href="https://www.freecodecamp.org/news/freecodecamps-b1-english-for-developers-certification-is-now-live/">B1 级别英语认证发布</a></li></ul><p>我们正在开发 A1、B2、C1 和 C2 级别的课程，计划在未来几年陆续发布（是的，以年为单位。每个级别的开发都是庞大的工程）。</p><p>freeCodeCamp 社区不仅设计了数千节英语课程，还开发了大量定制软件工具来实现这些课程体系。因此在 2024 年，我们提出设想：能否用同样的工具来教授西班牙语和中文普通话？</p><p>如今，这项努力的成果已进入公开测试阶段。我们从这两种语言的 A1 级别课程起步，其余级别将在未来几年逐步推出。</p><ul><li><a href="https://www.freecodecamp.org/news/freecodecamps-a1-professional-spanish-curriculum-beta-is-now-live/">A1 级别西班牙语课程发布</a></li><li><a href="https://www.freecodecamp.org/news/freecodecamps-a1-professional-chinese-curriculum-beta-is-now-live/">A1 级别中文课程发布</a></li></ul><h2 id="--1">为何教授西班牙语和中文？</h2><p>除英语外，西班牙语和中文（普通话）是全球使用最广泛的两种语言。掌握这些语言可帮助你参与众多网络社区、探访主要城市，甚至获得新的工作机会。</p><p>学习外语对大脑神经可塑性大有裨益，并且可以与编程等其他技能学习同步开展。</p><p>现在你可以通过我们完整的端到端课程体系免费学习这些语言，所有课程均由教师、译者和母语者共同设计。</p><h2 id="-freecodecamp-">关于将 freeCodeCamp 课程翻译为世界主要语言的进展</h2><p>你可能知道，freeCodeCamp 自 2020 年起已支持多种世界主要语言。但每当我们发布新课程时，全部内容的翻译仍需数月时间。</p><p>值得欣慰的是，机器翻译技术在过去几年持续进步。</p><p>社区仍在人工翻译教程和书籍，但对于 freeCodeCamp 编程课程这类更新迅速的内容，我们需要加速这一进程。</p><p>我们已试点将全部新课程翻译为西班牙语和葡萄牙语。</p><ul><li>首先运用前沿大语言模型，结合大量术语表和风格指南，处理编程课程中数十万词的原始内容，</li><li>随后由母语者随机抽样审校以保证质量。</li><li>当我们确认翻译质量达标后，便开始建立数据管道，通过开源代码贡献实现英文原文更新时的自动翻译同步。</li></ul><p>这些工作的经济成本并不高昂，因此我们应该能在此基础上，进一步将 freeCodeCamp 编程课程拓展到此前未能支持的其他语言，例如阿拉伯语和法语。</p><!--kg-card-begin: markdown--><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766528132885/06da1977-85b8-438e-8e80-1818f3dba7e7.webp" alt="freeCodeCamp 的编程课程被翻译为葡萄牙语的截图" class="image--center mx-auto" width="1017" height="918" loading="lazy"><!--kg-card-end: markdown--><p>如果你是多年来参与过 freeCodeCamp 翻译的数百位贡献者之一，我们依然非常欢迎你帮助翻译书籍和教程，这些内容在首次发布后通常不会有太大改动。</p><p>毕竟，文档本地化的最高标准是由一位译者完整阅读并理解原文后再进行翻译。</p><h2 id="--2">我们的社区才刚刚启航。</h2><p>今年，freeCodeCamp 社区还实现了：</p><ul><li>在 freeCodeCamp YouTube 频道上发布 129 个免费视频课程</li><li>在 freeCodeCamp 专栏上发布 45 本免费完整书籍和手册</li><li>452 篇关于数学、编程和计算机科学的教程和文章</li><li>50 集 freeCodeCamp 播客节目，我采访了许多开发者，其中许多人都是 freeCodeCamp 开源项目的贡献者</li></ul><p>我们还向 freeCodeCamp 开源学习平台合并了 4,279 次代码提交，这些更新大幅提升了用户体验与可访问性。同时我们发布了安全的考试环境，让 campers 能够参加认证考试。</p><p>你可以查看我们的 <strong><a href="https://www.freecodecamp.org/chinese/news/freecodecamp-2025-top-contributors/">2025 年度的顶级开源贡献者榜单</a></strong>。</p><p>作为一个社区，我们才刚刚起步。免费的开源教育在当今时代的意义前所未有地重大。</p><h2 id="--3">我们也邀请你更深入地参与社区。</h2><p>我要感谢每月支持我们的慈善事业与使命的 10,221 位热心人士。请考虑加入这个行列：<a href="https://www.freecodecamp.org/donate/">捐赠支持 freeCodeCamp.org</a>。</p><p>这里有其他几种<a href="https://www.freecodecamp.org/news/how-to-donate-to-free-code-camp/">可抵扣美国税款的年终捐赠方式</a>。</p><p>freeCodeCamp 拥有一个充满活力的全球社区，聚集了众多积极进取的学习者，他们正在掌握新技能并为职业发展的下一阶段做准备。我鼓励你<a href="https://discord.com/servers/freecodecamp-692816967895220344">加入 freeCodeCamp Discord 与我们交流互动</a>。</p><p>同时，请参与 <a href="https://forms.nhcarrigan.com/o/docs/forms/7LNb8jFoN4SPBvP7vRxDi2/4">Naomi 的 freeCodeCamp 社区调查</a>，帮助我们了解你喜爱 freeCodeCamp 的哪些方面，以及我们的社区可以在哪些方面做得更好。</p><p>我谨代表全球 freeCodeCamp 社区，祝愿你和家人在 2025 年收官之际一切圆满。也让我们共同举杯，迎接充满乐趣与雄心壮志的 2026 年。</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ freeCodeCamp A1 专业中文课程（测试版）上线 ]]>
                </title>
                <description>
                    <![CDATA[ freeCodeCamp 社区刚刚发布了我们新的 A1 专业中文课程的前几个章节。你现在可以利用这些内容开始学习中文。 每一章都包含数百个互动任务，旨在帮助你自信地迈出学习中文的第一步。 新的 A1 专业中文课程是怎样的？ 在这个 A1 专业中文课程中，你将学习中文的基础知识。这将遵循欧洲共同语言参考标准（CEFR）的 A1 要求。我们专注于在专业环境中特别有用的词汇。 课程包含多个模块，包括热身、学习、练习、复习和测验，以确保你真正理解了一个模块再进入下一个。 热身是准备部分，为模块的主要内容提供背景。 热身中的任务将向你介绍新词汇，或复习你已经学习过并将在当前模块中使用的内容。 下面是在课程中你将会遇到的一个示例。 每个任务都有一个相应的问题，帮助你练习内容。如果你不知道如何回答问题或需要更多细节，你可以查看解释部分。 在热身之后，你将进入学习 部分。在这里，你会看到你新学的单词在实际中的应用！你将聆听短片段的独白或对话，并回答关于它们的问题，以确保你理解它们的含义以及它们在真实对话中的使用方式。在必要时，你还将在这里学习一些理论。 课程中还包含填 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/freecodecamps-a1-professional-chinese-curriculum-beta-is-now-live/</link>
                <guid isPermaLink="false">694a9c8c1acf9a04cd95df2a</guid>
                
                    <category>
                        <![CDATA[ 社区 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ freeCodeCamp ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Miya Liu ]]>
                </dc:creator>
                <pubDate>Tue, 23 Dec 2025 05:55:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2025/12/----_20251224135437_142_113.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/freecodecamps-a1-professional-chinese-curriculum-beta-is-now-live/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">freeCodeCamp's A1 Professional Chinese Curriculum (Beta) is Now Live</a>
      </p><!--kg-card-begin: markdown--><p>freeCodeCamp 社区刚刚发布了我们新的 A1 专业中文课程的前几个章节。你现在可以利用这些内容开始学习中文。</p>
<p>每一章都包含数百个互动任务，旨在帮助你自信地迈出学习中文的第一步。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766158559146/126837fd-0786-476d-b643-1eed59e87814.png" alt="A1 专业中文课程大纲。章节包括欢迎、拼音课程，如简单韵母和鼻音韵母，以及问候和介绍。每个章节的完成状态均有显示。" width="848" height="595" loading="lazy"></p>
<h2 id="a1">新的 A1 专业中文课程是怎样的？</h2>
<p>在这个 A1 专业中文课程中，你将学习中文的基础知识。这将遵循欧洲共同语言参考标准（CEFR）的 A1 要求。我们专注于在专业环境中特别有用的词汇。</p>
<p>课程包含多个模块，包括热身、学习、练习、复习和测验，以确保你真正理解了一个模块再进入下一个。</p>
<p><strong>热身</strong>是准备部分，为模块的主要内容提供背景。</p>
<p>热身中的任务将向你介绍新词汇，或复习你已经学习过并将在当前模块中使用的内容。</p>
<p>下面是在课程中你将会遇到的一个示例。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766158665243/cb5a3d23-3626-4b12-aae0-829a3db7b7cf.png" alt="一个穿条纹毛衣的人在一个现代办公室设置的虚拟教室中。文字写道，“还记得一个音节有三个部分：声母、韵母和声调吗？这些部分的任何变化都可能表示完全不同的字符。”对话框显示“你好”的拼音和汉字。" width="960" height="647" loading="lazy"></p>
<p>每个任务都有一个相应的问题，帮助你练习内容。如果你不知道如何回答问题或需要更多细节，你可以查看解释部分。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764863508777/7e6f988c-9bf7-454c-afaa-091920ff5a02.png" alt="7e6f988c-9bf7-454c-afaa-091920ff5a02" width="940" height="725" loading="lazy"></p>
<p>在<strong>热身</strong>之后，你将进入<strong>学习</strong>部分。在这里，你会看到你新学的单词在实际中的应用！你将聆听短片段的独白或对话，并回答关于它们的问题，以确保你理解它们的含义以及它们在真实对话中的使用方式。在必要时，你还将在这里学习一些理论。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766158808549/5a1b2945-149a-433b-a840-cff49224908c.png" alt="在一个有大窗的城市景观的办公室房间里站立的动画角色。上方文字解释如何用中文介绍国籍，“wǒ shì + 国籍”，下方字幕显示角色用拼音和简体中文字符说“我是中国人”。" width="835" height="654" loading="lazy"></p>
<p>课程中还包含填空题，帮助你练习使用拼音和汉字。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766158976101/208a38c7-850d-4d43-8794-c6c51fc92962.png" alt="一个背着背包的动画角色站在有绿色植物墙和电脑的办公室里。显示中文文本和拼音，内容为：“我是新加坡人。”下方有与句子相关的填空题目。" width="816" height="770" loading="lazy"></p>
<p>在<strong>学习</strong>之后，你将继续进入<strong>练习</strong>部分，在这里你将完成更多开放式任务，以测试你是否理解以及使用拼音和汉字写作的能力。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766159066500/9b4b962d-dcd8-4782-9526-07a4cc5e0219.png" alt="一个语言练习的截图，包含中文文本和拼音，指示用户将“我是、开发者、中国人、你好”按正确顺序放到相应位置。“wǒ shì” 意思是“我是”。这些短语需要放置在“wáng huá”和其他提示旁边的空白处。" width="805" height="444" loading="lazy"></p>
<p>在模块的末尾，有一个<strong>复习</strong>部分，包含语法要点、主要词汇和概念。你可以使用这些复习页面帮助你准备测验。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766097053581/bc30af81-4d64-42b2-84d5-624d9c3f87db.png" alt="这幅图片包含一个题为“语法要点”的文本，讨论中文中的问候类型。它介绍了三个短语：“你好” (nǐ hǎo) 用于随意的场合，“您好” (nín hǎo) 用于礼貌互动，“你们好” (nǐ men hǎo) 用于与多人打招呼。" width="1570" height="1042" loading="lazy"></p>
<p>模块的最后部分是<strong>测验</strong>，旨在检验你对模块中所涵盖材料的理解。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766162326716/7f0a788e-5f9b-4b3b-8499-1cd39eca1d37.png" alt="名为“问候与介绍测验”的页面检测你对基础中文问候的理解。要通过，必须正确回答至少 10 道题中的 9 道。第一个问题询问在向一群人问候时应该使用哪个短语，选项包括“nǐ men hǎo” (你们好)、“nín hǎo” (您好)、“wǒ shì” (我是) 和“nǐ hǎo” (你好)。" width="856" height="695" loading="lazy"></p>
<p>认证考试将作为该认证的最后一项发布。我们目前发布了前三章，后续章节将由我们的教学设计团队开发后逐步发布。当所有章节上线后，我们将发布认证考试。</p>
<h2 id="">致谢贡献者</h2>
<p>感谢以下贡献者在课程开发中提供帮助：</p>
<ul>
<li>
<p><a href="https://github.com/gikf">Krzysztof G.</a></p>
</li>
<li>
<p><a href="https://github.com/mrchenguozheng">Chen Guo Zheng</a></p>
</li>
<li>
<p><a href="https://github.com/stevending1st">Steven Ding</a></p>
</li>
</ul>
<p>我们特别感谢 <a href="https://github.com/s1ngs1ng">S1ng S1ng</a>，他录制了独白和对话音频，还录制了生动展示拼音发音的教学视频。这些拼音视频将在明年陆续添加到课程中。</p>
<h2 id="">常见问题</h2>
<h3 id="">这些内容真的全部免费吗？</h3>
<p>是的。freeCodeCamp 一直以来都是免费的，并且我们已经提供免费的认证超过十年。</p>
<h3 id="">我可以用除英语以外的语言学习中文课程吗？</h3>
<p>我们的目标是让 freeCodeCamp 支持的语言课程都能以各种语言提供。查看你的账户设置，看看你正在学习的课程是否已经提供你偏好的语言版本。</p>
<h3 id="">中文课程涵盖哪些语言技能？</h3>
<p>语言课程目前涵盖听力、阅读和写作。我们计划稍后添加口语部分。</p>
<h3 id="">语言课程和考试中的音频是由母语者录制的吗？</h3>
<p>是的。语言课程中的所有音频均由该语言的母语者录制。</p>
<h3 id="">我是聋人或听力不佳者。我还可以学习语言课程吗？</h3>
<p>可以！所有音频课程都提供字幕和可阅读的文本。</p>
<h3 id="">我是盲人或视力有限，并使用屏幕阅读器。我还可以学习语言课程吗？</h3>
<p>可以！freeCodeCamp 课程设计为无障碍，你可以使用屏幕阅读器学习语言课程。如果遇到任何无障碍问题，你可以在我们的 GitHub 仓库上反馈，以便社区解决。</p>
<h3 id="a1a2b1">课程名称旁边的字母和数字有什么意义？（例如：A1、A2、B1）</h3>
<p>这些标记指的是 CEFR（欧洲共同语言参考标准）等级，这是一种用于描述语言熟练程度的国际框架。A1 和 A2 代表初级水平，B1 和 B2 代表中级水平，C1 和 C2 代表高级水平。每个等级指示你在语言学习阶段所预期具备的技能和知识。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765475620837/6822cf7c-d05f-4a5c-8e8a-994c540ed369.png" alt="一张标题为“CEFR 等级详解”的图表展示了从 A1 到 C2 的六个 CEFR 语言能力等级。A1 等级描述为“在倾听者的帮助下进行交流”。A2 等级涉及“在有限范围内进行交流”。B1 等级重点在于“在熟悉的情境中交流核心要点”。B2 等级能够在“多种情境中较流畅地交流”。C1 等级强调“在多数情境中灵活流畅地沟通”。C2 等级代表“在绝大多数情境中实现精准细腻的交流”。freeCodeCamp 标识位于图表底部。" width="1024" height="768" loading="lazy"></p>
<h2 id="">其他</h2>
<p>祝你在 freeCodeCamp 的语言课程学习中好运。</p>
<p>祝学习愉快！</p>
<!--kg-card-end: markdown--> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ freeCodeCamp 开源社区 2025 年度 Top Contributors ]]>
                </title>
                <description>
                    <![CDATA[ 2025 年对于全球 freeCodeCamp 社区来说是非常富有成效的一年。作为一个已经走过 12 个年头的社区，我们在各个方面都全速前进，比以往更加稳步推进。 今年，我们对新的全栈开发者课程进行了重大改进。这是 freeCodeCamp 课程的第 10 个版本，包含 7 个认证。在学习过程中，学习者将完成超过 100 个实践项目，并通过计算机科学理论的考试。 此外，在过去的一年里，freeCodeCamp 社区实现了：  * 在 freeCodeCamp YouTube 频道上发布 129 个免费视频课程          * 在 freeCodeCamp 专栏上发布 45 本免费完整书籍和手册          * ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/freecodecamp-2025-top-contributors/</link>
                <guid isPermaLink="false">6947ed6d1acf9a04cd95ded6</guid>
                
                    <category>
                        <![CDATA[ 社区 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ freeCodeCamp ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Miya Liu ]]>
                </dc:creator>
                <pubDate>Mon, 22 Dec 2025 11:18:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2025/12/----_20251222205523_138_113.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/freecodecamp-top-open-source-contributors-2025/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">freeCodeCamp's Top Open Source Contributors of 2025</a>
      </p><!--kg-card-begin: markdown--><p>2025 年对于全球 freeCodeCamp 社区来说是非常富有成效的一年。作为一个已经走过 12 个年头的社区，我们在各个方面都全速前进，比以往更加稳步推进。</p>
<p>今年，我们对新的全栈开发者课程进行了重大改进。这是 freeCodeCamp 课程的第 10 个版本，包含 7 个认证。在学习过程中，学习者将完成超过 100 个实践项目，并通过计算机科学理论的考试。</p>
<p>此外，在过去的一年里，freeCodeCamp 社区实现了：</p>
<ul>
<li>
<p>在 freeCodeCamp YouTube 频道上发布 129 个免费视频课程</p>
</li>
<li>
<p>在 freeCodeCamp 专栏上发布 45 本免费完整书籍和手册</p>
</li>
<li>
<p>452 篇关于数学、编程和计算机科学的教程和文章</p>
</li>
<li>
<p>50 集 freeCodeCamp 播客节目，我采访了许多开发者，其中许多人都是 freeCodeCamp 开源项目的贡献者</p>
</li>
</ul>
<p>我们还合并了 4,279 个提交到 freeCodeCamp 的开源学习平台，进行了大量用户体验和无障碍访问的改进。此外，我们还发布了安全的考试环境，供学习者参加认证考试。</p>
<p>最后，我们在开发者英语课程上取得了相当大的进展，并开始制作即将上线的西班牙语和中文课程。</p>
<p>我们才刚刚开始。我们已经在规划关于数学、数据科学、机器学习和其他深度、技能密集型课程的附加课程。</p>
<p>这一切都要感谢 10,342 名善良的人们<a href="https://donate.freecodecamp.org">捐助支持我们的慈善事业和使命</a>，以及那些投入时间和才华给社区的人们。</p>
<p>以下是 2025 年我们社区的 611 位最活跃的开源贡献者名单：</p>
<h2 id="githubtopcontributor">GitHub Top Contributor</h2>
<ul>
<li>
<p><a href="https://github.com/clarencepenz">Clarence Bakosi</a></p>
</li>
<li>
<p><a href="https://github.com/Supravisor">Supravisor</a></p>
</li>
<li>
<p><a href="https://github.com/Giftea">Giftea ☕</a></p>
</li>
<li>
<p><a href="https://github.com/pdtrang">Diem-Trang Pham</a></p>
</li>
<li>
<p><a href="https://github.com/a2937">Anna</a></p>
</li>
<li>
<p><a href="https://github.com/c0d1ng-ma5ter">c0d1ng_ma5ter</a></p>
</li>
<li>
<p><a href="https://github.com/JungLee-Dev">JungLee-Dev</a></p>
</li>
<li>
<p><a href="https://github.com/hbar1st">hbar1st</a></p>
</li>
<li>
<p><a href="https://github.com/dev-kamil">dev-kamil</a></p>
</li>
<li>
<p><a href="https://github.com/arizfaiyaz">Ariz Faiyaz</a></p>
</li>
<li>
<p><a href="https://github.com/agilan11">agilan11</a></p>
</li>
<li>
<p><a href="https://github.com/cuongpham24">Vinson Pham</a></p>
</li>
<li>
<p><a href="https://github.com/StuartMosquera">Stuart Mosquera</a></p>
</li>
<li>
<p><a href="https://github.com/StephenMuya">Stephen Mutheu Muya</a></p>
</li>
<li>
<p><a href="https://github.com/MohamadSalman11">Mohamad Salman</a></p>
</li>
<li>
<p><a href="https://github.com/alexgoldsmith">Alex Goldsmith</a></p>
</li>
<li>
<p><a href="https://github.com/vishnudt2004">Vishnu D</a></p>
</li>
<li>
<p><a href="https://github.com/kannan-ravi">Kannan</a></p>
</li>
<li>
<p><a href="https://github.com/tanmaygautam11">Tanmay Gautam</a></p>
</li>
<li>
<p><a href="https://github.com/l3onhard">l3onhard</a></p>
</li>
<li>
<p><a href="https://github.com/prabhakaryadav2003">Prabhakar Yadav</a></p>
</li>
<li>
<p><a href="https://github.com/errantpianist">Ezoh Zhang</a></p>
</li>
<li>
<p><a href="https://github.com/Ajay-2005">Ajay A</a></p>
</li>
<li>
<p><a href="https://github.com/dragon-slayer27">Vivaan Teotia</a></p>
</li>
<li>
<p><a href="https://github.com/hassanwaqa">Hassan Waqar</a></p>
</li>
<li>
<p><a href="https://github.com/gikf">Krzysztof G.</a></p>
</li>
<li>
<p><a href="https://github.com/roberiacono">Roberto Iacono</a></p>
</li>
<li>
<p><a href="https://github.com/MelvinManni">Melvin Kosisochukwu</a></p>
</li>
<li>
<p><a href="https://github.com/lasjorg">Lasse Jørgensen</a></p>
</li>
<li>
<p><a href="https://github.com/dennmar">dennmar</a></p>
</li>
<li>
<p><a href="https://github.com/Arif-Khalid">Arif Khalid</a></p>
</li>
<li>
<p><a href="https://github.com/soryaek">Sorya Ek</a></p>
</li>
<li>
<p><a href="https://github.com/RaymondLiu777">Raymond Liu</a></p>
</li>
<li>
<p><a href="https://github.com/AyushSharma72">Ayush Sharma</a></p>
</li>
<li>
<p><a href="https://github.com/yusufasur">Yusuf Can Aşur</a></p>
</li>
<li>
<p><a href="https://github.com/kb42">Karthik Bagavathy</a></p>
</li>
<li>
<p><a href="https://github.com/Sky-walkerX">Naman Khandelwal</a></p>
</li>
<li>
<p><a href="https://github.com/vkalakota18">Varshith Kalakota</a></p>
</li>
<li>
<p><a href="https://github.com/omarraf">Omar Rafiq</a></p>
</li>
<li>
<p><a href="https://github.com/raahthor">Prashant Rathore</a></p>
</li>
<li>
<p><a href="https://github.com/Agung1606">Agung Saputra</a></p>
</li>
<li>
<p><a href="https://github.com/sanchitkhthpalia">Sanchit Kathpalia</a></p>
</li>
<li>
<p><a href="https://github.com/shashankdangi">Shashank Dangi</a></p>
</li>
<li>
<p><a href="https://github.com/garyeung">Gary Yeung</a></p>
</li>
<li>
<p><a href="https://github.com/ppl-call-me-tima">Amit Upadhyay</a></p>
</li>
<li>
<p><a href="https://github.com/pkdvalis">pkdvalis</a></p>
</li>
<li>
<p><a href="https://github.com/sinha21Soumya">sinha21Soumya</a></p>
</li>
<li>
<p><a href="https://github.com/VishalTelukula">Telukula Vishal</a></p>
</li>
<li>
<p><a href="https://github.com/sskiragu">sskiragu</a></p>
</li>
<li>
<p><a href="https://github.com/AishwaryaRajput09">Aishwarya</a></p>
</li>
<li>
<p><a href="https://github.com/TrevorBrowning">Trevor Browning</a></p>
</li>
<li>
<p><a href="https://github.com/AilaLu">AilaLu</a></p>
</li>
<li>
<p><a href="https://github.com/zxc-w">zxc-w</a></p>
</li>
<li>
<p><a href="https://github.com/anishlukk123">Anish Lukkireddy</a></p>
</li>
<li>
<p><a href="https://github.com/josue-igiraneza">Josue Igiraneza</a></p>
</li>
<li>
<p><a href="https://github.com/adityaravichandran6">Aditya Ravichandran</a></p>
</li>
<li>
<p><a href="https://github.com/skyewm">Skye Mickens</a></p>
</li>
<li>
<p><a href="https://github.com/gagan-bhullar-tech">Gagan Bhullar</a></p>
</li>
<li>
<p><a href="https://github.com/asr1325">Aditya</a></p>
</li>
</ul>
<h2 id="topcontributor">论坛 Top Contributor</h2>
<ul>
<li>
<p><a href="https://forum.freecodecamp.org/u/Teller">Teller</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/pkdvalis">pkdvalis</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/hasanzaib1389">Hassan Zaib</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/a1legalfreelance">A1legalfreelance</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/igorgetmeabrain">Doug Badger</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/JeremyLT">Jeremy</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/fcc4b6d10c4-b540-4e2">fcc4b6d10c4-b540-4e2</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/JuniorQ">Arakhsh Q</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/Ray13">Raymond</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/hbar1st">Hanaa B.</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/lasjorg">Lasse</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/sanity">sanity or not</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/MostafaElbadry">MostafaElbadry</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/a2937">Anna</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/seopostexpert">Muhammad Subhan</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/stephenmutheu">Stephen Mutheu</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/zs_akkaya">Zeynep Serra Akkaya</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/bappyasif">A.Bappy</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/PauloRodrigues">Paulo</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/StaySilent">StaySilent</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/Klexvier">Klexvier</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/robheyays">Robert H.</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/BlindVisionMan">Marvin Hunkin</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/tracy.chacon.00">Tracy Chacon</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/bochard">bochard</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/Cody_Biggs">CODY BIGGS</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/be_happy"><em>Infinity</em></a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/ShadyHBedda">Shady H. Bedda</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/booleanmethod9">Boolean Method</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/ArielLeslie">Ariel Leslie</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/DanielHuebschmann">Head in Cloud</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/Dovb1ek">Dovb1ek</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/c0d1ng_ma5ter">c0d1ng_ma5ter</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/evaristoc">evaristoc</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/ahraitch">ahr aitch</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/jwhoisfondofit">Jay</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/AlexK">AlexanderTheDev</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/Malcolm-Harrison">Malcolm Harrison</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/Ethan1">Ethan1</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/vikramvi">Vikram Ingleshwar</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/constantcode9909">Amine (Mike)</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/nickrg">Nicolas Greenwood</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/Amunyelet-Ojala">Amunyelet-Ojala</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/anon75571083">anon75571083</a></p>
</li>
<li>
<p><a href="https://forum.freecodecamp.org/u/brendenhowlett96">Brenden Howlett</a></p>
</li>
</ul>
<h2 id="topcontributor">翻译 Top Contributor</h2>
<ul>
<li>
<p>Afonso Branco (AfonsoBranco)</p>
</li>
<li>
<p>Michael Qu (qubycn)</p>
</li>
<li>
<p>Alan Luo (iLtc)</p>
</li>
<li>
<p>Nadja Sellinat (biebricherin)</p>
</li>
<li>
<p>David Almeida (david.miguel.almeida)</p>
</li>
<li>
<p>jeigux</p>
</li>
<li>
<p>Nairobi (fanqie)</p>
</li>
<li>
<p>Ivan Forcati (IvanF)</p>
</li>
<li>
<p>Quang Nguyen (nguyendangquang126)</p>
</li>
<li>
<p>Ganebas</p>
</li>
<li>
<p>Kentaro Nareswara (K3N7)</p>
</li>
<li>
<p>Alana Maia (nicegrrrl)</p>
</li>
<li>
<p>Gustavo Birman (Gustavuspqr)</p>
</li>
<li>
<p>Nataliia Hrytsyk (nataliia.hrytsyk)</p>
</li>
<li>
<p>Filipe Oliveira (FilipeOliveira)</p>
</li>
<li>
<p>Діана Маркута (dianamarkuta)</p>
</li>
<li>
<p>Kostiantyn Krysenko (barkode)</p>
</li>
<li>
<p>v4n31aa</p>
</li>
<li>
<p>janni1288</p>
</li>
<li>
<p>Nastasia Milosev (nastasia.milosev)</p>
</li>
<li>
<p>Juan Diaz (JuanPabloDiaz)</p>
</li>
<li>
<p>Stas Kinash (stasKinash)</p>
</li>
<li>
<p>ToteM</p>
</li>
<li>
<p>Tihomir Manushev (haraGADygyl)</p>
</li>
<li>
<p>Maximo Sanchez (maxysanchez.06)</p>
</li>
<li>
<p>Сервило Галина (servilogalina)</p>
</li>
<li>
<p>Laureline Paris (LaurelineP)</p>
</li>
<li>
<p>mubinabegimxayrullayeva</p>
</li>
<li>
<p>mitegab</p>
</li>
<li>
<p>Berke Volkan (kzlpndx)</p>
</li>
<li>
<p>Dana Volovelsky (danavolovelsky)</p>
</li>
<li>
<p>Isauro Rodriguez (icaro5)</p>
</li>
<li>
<p>Yuliia Lishchuk (yuli)</p>
</li>
<li>
<p>Palak (palakkhan2002)</p>
</li>
<li>
<p>bahtiyorjonq777</p>
</li>
<li>
<p>Olha Boretska (olha.boretskaa)</p>
</li>
<li>
<p>yidev27</p>
</li>
<li>
<p>Ilona Sheremeta (lonasheremeta78)</p>
</li>
<li>
<p>Anna Shram (annashram53)</p>
</li>
<li>
<p>Anastasiia Perchyshyn (anastasijp2004)</p>
</li>
<li>
<p>Mariia Soloshenko (Mariia_S)</p>
</li>
<li>
<p>erickk (lucerile435)</p>
</li>
<li>
<p>Fran Sanabria (fransanabria)</p>
</li>
<li>
<p>Богдана Онищук (bohdanaon9001)</p>
</li>
<li>
<p>Shogo SENSUI (1000ch)</p>
</li>
<li>
<p>maysa42snow</p>
</li>
<li>
<p>Halia Senkiv (haliasenkiv)</p>
</li>
<li>
<p>Jiyoung Suh (JiyoungSuh)</p>
</li>
<li>
<p>Anairis Carballea (acarballea)</p>
</li>
<li>
<p>Johan Javier Gonzalez Perez (javiergonzalez045)</p>
</li>
<li>
<p>yosrmaalej47</p>
</li>
<li>
<p>Akram Dhib (akramdhib999)</p>
</li>
<li>
<p>Bảo Nam Trần Hoàng (kipi91212)</p>
</li>
<li>
<p>Eduarda Groehs (egroehs)</p>
</li>
<li>
<p>FlameC (anonymHe)</p>
</li>
<li>
<p>sohyun</p>
</li>
<li>
<p>Xiaoyan Zhang (Drwhooooo)</p>
</li>
<li>
<p>Gabriela Silva (gabrielaquintilho.s)</p>
</li>
<li>
<p>Fausto Chiacchietta (faustooch)</p>
</li>
<li>
<p>Seif-03</p>
</li>
<li>
<p>オメロ (homero304)</p>
</li>
<li>
<p>Msam</p>
</li>
<li>
<p>Eya (eyaaba)</p>
</li>
<li>
<p>mohamed ben haj salah (mohamedbhs7)</p>
</li>
<li>
<p>abdallah djarraya (abdallahswimmer)</p>
</li>
<li>
<p>Aylin Gümüş (aylingumus)</p>
</li>
<li>
<p>aminezribi03</p>
</li>
<li>
<p>Eloy Gutiérrez (eloy.alumnes)</p>
</li>
<li>
<p>Ameeri22</p>
</li>
<li>
<p>youssef1607</p>
</li>
<li>
<p>Pablo J Lebed (pjl1978)</p>
</li>
<li>
<p>Mergen N (mn)</p>
</li>
<li>
<p>Yuki Shibata (kyubashi)</p>
</li>
<li>
<p>ggfly666</p>
</li>
<li>
<p>Amine (ersu.amine)</p>
</li>
<li>
<p>WaifuXv</p>
</li>
<li>
<p>Jawnex</p>
</li>
<li>
<p>mamaruo</p>
</li>
<li>
<p>Eric Gigondan (Itsatsu)</p>
</li>
<li>
<p>Hamzalakoud</p>
</li>
<li>
<p>c.marget</p>
</li>
<li>
<p>Saki Basken (sbasken)</p>
</li>
<li>
<p>hashim rashid (hhashbrown)</p>
</li>
<li>
<p>yuan-minglongze</p>
</li>
<li>
<p>OKmimech</p>
</li>
<li>
<p>J.G. P.C. (kaiserpc)</p>
</li>
<li>
<p>Fatma Ajroud (faty_aj)</p>
</li>
<li>
<p>Yuna_707</p>
</li>
<li>
<p>Franklin Solar Navarrete (fsolarnavarrete)</p>
</li>
<li>
<p>zeinebBenRayana</p>
</li>
<li>
<p>Mark P. (Futuraura)</p>
</li>
<li>
<p>Ahmad Hassan (sUfi)</p>
</li>
<li>
<p>Ivrin Ivrin (Ivrin)</p>
</li>
<li>
<p>parapara0919</p>
</li>
<li>
<p>Panah (panah)</p>
</li>
<li>
<p>Mario Turtoi (MarioDev)</p>
</li>
<li>
<p>Edenilson Ulises Aguilar Diaz (UlisesDiaz0)</p>
</li>
<li>
<p>rustamdocstranslator</p>
</li>
<li>
<p>Cristian Salazar (Cristian-27)</p>
</li>
<li>
<p>IsabelaMB</p>
</li>
<li>
<p>Khalil Sassi (khalilsassi67)</p>
</li>
<li>
<p>Sorayadc</p>
</li>
<li>
<p>Franco Casafus (francocasafus22)</p>
</li>
<li>
<p>miwamiwamiwa (miwalaa)</p>
</li>
<li>
<p>franciscomelov</p>
</li>
<li>
<p>Juan Taroni (juanribeiro.taroni)</p>
</li>
<li>
<p>Alexander Liu Gao (aleliu)</p>
</li>
<li>
<p>YC liou (iop52896)</p>
</li>
<li>
<p>David Oliveira (EngDavidOlivr)</p>
</li>
<li>
<p>Campoz _ (campozzz)</p>
</li>
<li>
<p>Roberta Meyrelles (rmftelier)</p>
</li>
<li>
<p>Polina (minlaux)</p>
</li>
<li>
<p>Matheus G. Oliveira (PomboObeso)</p>
</li>
<li>
<p>Hou Bowei (houbowei)</p>
</li>
<li>
<p>Paul (ptijero)</p>
</li>
<li>
<p>Danilo Parada Garcés (dparada.sistemas)</p>
</li>
<li>
<p>Ana_Writer</p>
</li>
<li>
<p>Nathalia Oliveira (royalpython)</p>
</li>
<li>
<p>Amir (Amir_lvx)</p>
</li>
<li>
<p>Eltaj Mammadzada (eltajmammadzada)</p>
</li>
<li>
<p>Oliver Loza (THE_G3NES1S)</p>
</li>
<li>
<p>Jakhongir Murtazaev (jakhongir.murtazayev)</p>
</li>
<li>
<p>Siyana Zdravkova (BlueButterflies)</p>
</li>
<li>
<p>Vindishel (vindishel)</p>
</li>
<li>
<p>Daniel Jimenez (danjim82)</p>
</li>
<li>
<p>hk7math</p>
</li>
<li>
<p>KAWPHUNMAN</p>
</li>
<li>
<p>wdthor</p>
</li>
<li>
<p>Snow sita2 (EnmanuelTorres)</p>
</li>
<li>
<p>Aldo Vanegas (AldoLara)</p>
</li>
<li>
<p>nmo-genio</p>
</li>
<li>
<p>Pedro Daniel (pedrodanielgomes)</p>
</li>
<li>
<p>sadnessasha</p>
</li>
<li>
<p>Aby Prastya Palgunadi (arcanaxvi)</p>
</li>
<li>
<p>Halifolium</p>
</li>
<li>
<p>juan jose (Juanx64)</p>
</li>
<li>
<p>Henry Richard Flores Bazurto (hflores10)</p>
</li>
<li>
<p>Leah</p>
</li>
<li>
<p>Emma (emmaa5)</p>
</li>
<li>
<p>ANVAR ZIYODOV (ziyodovanvar1999)</p>
</li>
<li>
<p>dharris296</p>
</li>
<li>
<p>Juan Esteban Montoya Marín (montoyajuanes11)</p>
</li>
<li>
<p>Yiming Sun (sunyiming008)</p>
</li>
<li>
<p>Fauzi Kurniawan (kurniawan26)</p>
</li>
<li>
<p>Royyan Ahmad Zaydan (Kasehito)</p>
</li>
<li>
<p>Mikadifo</p>
</li>
<li>
<p>thelooter</p>
</li>
<li>
<p>Berkcan Gümüşışık (berkcangumusisik)</p>
</li>
<li>
<p>Stephen Mutheu (stephenmutheu)</p>
</li>
<li>
<p>athen</p>
</li>
<li>
<p>Wajahat (syedmuhammadwajahathusain)</p>
</li>
<li>
<p>Tanish Chauhan (tanishc4444)</p>
</li>
<li>
<p>Satya900</p>
</li>
<li>
<p>Luis V. (lvalderramavergara)</p>
</li>
<li>
<p>Sharvio</p>
</li>
<li>
<p>HibouDev</p>
</li>
<li>
<p>dTM99</p>
</li>
<li>
<p>wuzzjohn</p>
</li>
<li>
<p>Gavin Xu (gavinxu2)</p>
</li>
<li>
<p>ProjektMing</p>
</li>
<li>
<p>Saidkamol Saidjamolov (saidkamolxon)</p>
</li>
<li>
<p>beta filip (betafilip)</p>
</li>
<li>
<p>Deborah Porchia (deborah98)</p>
</li>
<li>
<p>teddy_ye</p>
</li>
<li>
<p>Rommel Hindap (rommel.b.hindap)</p>
</li>
<li>
<p>Jesús Lautaro Careglio Albornoz (JLCareglio)</p>
</li>
<li>
<p>SergioBlancoFtns</p>
</li>
<li>
<p>Nathalie Bour (nathalie.bour)</p>
</li>
<li>
<p>Qingfeng Huang (darrenhqf)</p>
</li>
<li>
<p>Omar (omar.fanzeres)</p>
</li>
<li>
<p>Atsushi Hatakeyama (atsushi729)</p>
</li>
<li>
<p>Diego Fierro (diegoefierro)</p>
</li>
<li>
<p>IsaRO (IsaR0d)</p>
</li>
<li>
<p>Abdulbosit Tuychiev (abdulbosit19980204)</p>
</li>
<li>
<p>NG KA YEE (hkscsheph)</p>
</li>
<li>
<p>Floman Dizwit (Hockman)</p>
</li>
<li>
<p>Karel Vanhelden (karelvanhelden)</p>
</li>
<li>
<p>khay56</p>
</li>
<li>
<p>Dostonbek Matyakubov (doston12)</p>
</li>
<li>
<p>MarcoGeldenhuis</p>
</li>
<li>
<p>immeteor2</p>
</li>
<li>
<p>Freedom Fighter (1543431a)</p>
</li>
<li>
<p>Ibn Hosain (ibnhosain014)</p>
</li>
<li>
<p>Vairus (e-oannis)</p>
</li>
<li>
<p>Elio Fang</p>
</li>
<li>
<p><a href="https://x.com/0x99Ethan3">YiWei</a></p>
</li>
<li>
<p><a href="https://x.com/TsukistarCN">Tsukistar</a></p>
</li>
<li>
<p>luojiyin</p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.linkedin.com/in/qingfeng-huang">Qingfeng Huang</a></p>
</li>
<li>
<p>wendy chen</p>
</li>
<li>
<p>zhizhan</p>
</li>
<li>
<p>HeZean</p>
</li>
<li>
<p>Ivan Forcati</p>
</li>
<li>
<p>Andrea Sisti</p>
</li>
<li>
<p><a href="https://x.com/Xuemei525">彭雪梅</a></p>
</li>
</ul>
<h2 id="youtubetopcontributor">YouTube Top Contributor</h2>
<ul>
<li>
<p><a href="https://github.com/s1ngs1ng">S1ng S1ng</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.linkedin.com/in/leoncarlo/">Carlos León</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@LuisCanary">Luis Canary</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@programacaocomramon">Ramon Rodrigues</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/github.com/jamesgpearce">James Pearce</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@officialtatevaslanyan">Tatev Aslanyan</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@EricWTech">Eric Tech</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@RivaanRanawat">Rivaan Ranawat</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@KhanamCoding">Khaiser Khanam</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@vincibits">Paulo Dichone</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@HiteshCodeLab">Hitesh Choudhary</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@EamonnCottrell">Eamonn Cottrell</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@harshbhatt7585">Harsh Bhatt</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@radu">Radu Mariescu-Istodor</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@3CodeCampers">Imad Saddik</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@EmbarkX">Faisal Memon</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@JSLegendDev">JSLegendDev</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@ExamProChannel">Andrew Brown</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@DaveGrayTeachesCode">Dave Gray</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@asabretech">Ebenezer Asabre</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@the-lisper">Alberto Lerda</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@deeplearningexplained">Yacine Mahdid</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@codeafuture">Alen Omeri</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@tungabayrak9765">Tunga Bayrak</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@CodingCleverly">Haris Iftikhar</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/rdali.github.io/">Rola Dali</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@OmarMAtef">Omar M. Atef</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/github.com/stevenGarciaDev">Steven Garcia</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@TrickSumo">Rishi Kumar Tiwari</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@coleblender">Cole Blender</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@AlterYourEnglish">Borys Cherednychenko</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@haidermalik3402">Haider Malik</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@excel.withgrant">Grant Huang</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@vukrosic">Vuk Rosić</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@LearnQtGuide">Daniel Gakwaya</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/github.com/BrijenMakwana">Brijen Makwana</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@TheCodeholic">Zura Sekhniashvili</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@turingtimemachine">Vladimirs Hisamutdinovs</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@tapasadhikary">Tapas Adhikary</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@richardtopchii">Richard Topchii</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@code-with-abel">Abel Gideon</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@MatkatMusic">Chuck Schiemeyer</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@programmingwithalex.585">Alexandru Cristian</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@masterspanishacademy">Virginia Ocana</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.linkedin.com/in/vaibhav-mehra-main/">Vaibhav Mehra</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/optimusprime09012004@gmail.com">Kshitij Sharma</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.dotnetmastery.com">Bhrugen Patel</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@programmingoceanacademy">Mohammad Fahd Abrah</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@ThePyCoach">Frank Andrade</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@ChadsPrep">Chad McAllister</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@ErikYuzwa">Erik Yuzwa</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@dswithbappy">Bappy Ahmed</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@Programming-Fluency">Noor Fakhry</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@AyushSinghSh">Ayush Singh</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@ever-greg">Gregory Kirchoff</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@algo.monster">Sheldon Chi</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@GlitchyDevs">Muhammad Omar Al Najjar</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@talltalksfromashortlady2798">Chumki Biswas</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/c/AlvinTheProgrammer">Alvin Zablan</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@structuredcs">Qiang Hao</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@datasciencewithmarco">Marco Peix</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@logicBaseLabs">Sumit Saha</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.linkedin.com/in/yilmazalaca">Yılmaz Alaca</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@robotbobby9">Bobby Roe</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/x.com/wagslane">Lane Wagner</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/%E2%80%AA@mobidevtalk">Shad Rayhan Mazumder</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@DotNetHow">Ervis Trupja</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/github.com/vivekkalyanarangan30">Vivek Kalyanarangan</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@cs50">David J. Malan</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.linkedin.com/in/leoncarlo/">Carlos Leon</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@BlossomBuild">Carlos Valentin</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@DestinationFAANG">Parth Vyas</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@codewithmuhammadabdullah">Muhammad Abdullah</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@andrewwoan">Andrew Woan</a></p>
</li>
<li>
<p><a href="https://chinese.freecodecamp.org/news/freecodecamp-2025-top-contributors/www.youtube.com/@AlexGordonHiFi">Alex Gordon</a></p>
</li>
<li>
<p><a href="http://youtube.com/@TwoWaysMath">Karol Kurek</a></p>
</li>
</ul>
<h2 id="topcontributor">专栏 Top Contributor</h2>
<ul>
<li>
<p><a href="https://freecodecamp.org/news/author/manishshivanandhan">Manish Shivanandhan</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/nsavant">Nikheel Vishwas Savant</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/appinisurya">Surya Teja Appini</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/tayo4christ">OMOTAYO OMOYEMI</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Casmir">Casmir Onyekani</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Chukwudinweze">Chukwudi Nweze</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/GerCocca">German Cocca</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Shejan-Mahamud">Shejan Mahamud</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/hew">Hew Hahn</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/curiousmoshe">Moshe Siegel</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/markm208">Mark Mahoney</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/atuoha">Atuoha Anthony</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/balapriyac">Bala Priya C</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/ashutoshkrris">Ashutosh Krishna</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/hiteshchauhan2023">Hitesh Chauhan</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/tiredmahnoor">Mah Noor</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/andrewbaisden">Andrew Baisden</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/trayalex812">Alex Tray</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/gkoos">Gabor Koos</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Abhidave">Abhijeet Dave</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/sumitsaha">Sumit Saha</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Tech-On-Diapers">Opaluwa Emidowojo</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/oluwatobiss">Oluwatobi Sofela</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/sholajegede">Shola Jegede</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/michaelyuan">Michael Yuan</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/ChisomUma123">Chisom Uma</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/heywisdom">Wisdom Usa</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/kuriko">Kuriko Iwai</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/ceddlyburge">Cedd Burge</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/CaesarSage">Destiny Erhabor</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/leomofthings">Ayodele Aransiola</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Koded001">Temitope Oyedele</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/emdadulislam">Emdadul Islam</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Tioluwani">Oyedele Tioluwani</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/mehtasoham">Soham Mehta</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Agnes28">Agnes Olorundare</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/atapas">Tapas Adhikary</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/chiragagrawal">Chirag Agrawal</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/ATechAjay">Ajay Yadav</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/mayur9210">Mayur Vekariya</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Sharvin26">Sharvin Shah</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/adejumo">Adejumo Ridwan Suleiman</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/sravankaruturi">Sravan Karuturi</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/wagslane">Lane Wagner</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/nitheeshp">Nitheesh Poojary</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/almamohapatra">Alma Mohapatra</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/orimdominic">Orim Dominic Adah</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/arunachalamb">Arunachalam B</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Ayush01Mishra">AYUSH MISHRA</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/shricodev">Shrijal Acharya</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Oliverkrane">Ikegah Oliver</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Jongbo">Olaleye Blessing</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/ifycodes99">Ifeoma Udu</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Tobilyn77">Oluwatobi</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/oluwaseunoladeji">Oladeji Oluwaseun</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/tarunsinghofficial">Tarun Singh</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/grantdotdev">Grant Riordan</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/asfakahmed">Asfak Ahmed</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/LeeRenJie">Tech With RJ</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/timkleier">Tim Kleier</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/CodeHemaa">Ophy Boamah</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/ezinnecodes">EZINNE ANNE EMILIA</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Codinghappiness">Happiness Omale</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/bertao">Pedro</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Lonercode">Amanda Ene Adoyi</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/arunshanmugamkumar">Arun Shanmugam Kumar</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/andrewezeani">Andrew Ezeani</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Ajay074">Ajay Kalal</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Ijay">Ijeoma Igboagu</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/prankurpandeyy">Prankur Pandey</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/augustinealul">Augustine Alul</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/sanjayxr">Sanjay R</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/adiatiayu">Ayu Adiati</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/cardstdani">Daniel García Solla</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Clifftech">Isaiah Clifford Opoku</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/ryan-michael-kay">Ryan Michael Kay</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/olanetsoft">Idris Olubisi</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/wittycircuitry">Aditya Vikram Kashyap</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/brkln">brooklyn</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/TemiTope1">Tope Fasasi</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/ilknureren">Ilknur Eren</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/sohamstars">Soham Banerjee</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/vaheaslanyan">Vahe Aslanyan</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/tatevaslanyan">Tatev Aslanyan</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/henrywinnerman">Henry Adepegba</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/ThatCoolGuy">Oluwadamilola Oshungboye</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/shrutikapoor">Shruti Kapoor</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/theladybella">Mfonobong Umondia</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Spruce">Spruce Emmanuel</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Derekvibe">Okoro Emmanuel Nzube</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/rajumanoj">Raju Manoj</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/udemezue">Udemezue John</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/lulunwenyi">Oluchi Nwenyi</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/toobaj">Tooba Jamal</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/nwanduka">Victoria Nduka</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Nene23">Nneoma Uche</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/michaelikoko">Michael Ikoko</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Jude-Olowo">Olowo Jude</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Ateev">Ateev Duggal</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Oluwadamisi">Oluwadamisi Samuel</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/menghnani">Mohit Menghnani</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/scriptedBytes">Brandon Wozniewicz</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/huhuhang">Hang Hu</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/mrufai">Rufai Mustapha</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/LolaVictoria">Damilola Oniyide</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/HijabiCoder">Fatuma Abdullahi</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/montasser1988">Montasser Mossallem</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/gatwirival">valentine Gatwiri</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/SmoothTech">Timothy Olanrewaju</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/gitgithan">Han Qi</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Omah">Eti Ijeoma</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Yazdun">Yazdun</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/desoga">deji adesoga</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/the_BrianB">Brian Barrow</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/chidiadi01">Chidiadi Anyanwu</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/codelikeandrew">Andrew Maksimchenko</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/mcasari">Mario Casari</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Balajeeasish">Balajee Asish Brahmandam</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/woai3c">Gordan Tan</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/tildaudufo">Tilda Udufo</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/rahulgupta32">Rahul gupta</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/edae">Eda Eren</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/josiahadesola">Josiah Adesola</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/smarttester">Venkata Sai Sandeep</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/tiagomonteiro">Tiago Capelo Monteiro</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Preston56">Preston Osoro</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/TheAnkurTyagi">Ankur Tyagi</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/justanothertechlead">Ben</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/askvikram">Vikram Aruchamy</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/dhruv-007">Dhruv Prajapati</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/onukwilip">Prince Onukwili</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/AdeboyeDN">Daniel Adeboye</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/kanand">Kumar Anand</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/lucasgarcez">Lucas</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/ec001">evaristo.c</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/officialrajdeepsingh">Rajdeep Singh</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/chaitanyarahalkar">Chaitanya Rahalkar</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/MahamCodes">Maham Codes</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/divyasaratchandran">Divya Valsala Saratchandran</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/joanayebola">Joan Ayebola</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/omerros">Omer Rosenbaum</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Nazneen758">Nazneen Ahmad</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/KunalN25">Kunal Nalawade</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/sdranju">Shamsuddoha Ranju</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/anamol-rajbhandari">Anamol Rajbhandari</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/suleolanrewaju">Sule-Balogun Olanrewaju</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Eccentric-">Sara Jadhav</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/LifeofDan-EL">Daniel Anomfueme</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Michael-para">Michael Para</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Ellabee">Elabonga Atuo</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/azubuikeduru">Azubuike Duru</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/AdalbertPungu">Adalbert Pungu</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/gunkev">Kevine Nzapdi</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/hamdaan">Hamdaan Ali</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/AbdullahInBytes">Abdullah Salaudeen</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/RAHULISM">Rahul</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Ayobami6">Alaran Ayobami</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/omoladeekpeni">Omolade Ekpeni</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/rwalters">Rob Walters</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/viv1">Vivek Sahu</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Xtephen">oghenekparobo Stephen</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/psmohammedali">P S Mohammed Ali</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/gursimar">Gursimar Singh</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Olabisi09">Olabisi Olaoye</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/de">David Asaolu</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/initialcommit">Jacob Stopak</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Yoma">Emore Ogheneyoma Lawrence</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/hunor">Hunor Márton Borbély</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/techwithpraisejames">Praise James</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/pltvs">Alex Pliutau</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/tanishkamakode">Tanishka Makode</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/SonyaMoisset">Sonya Moisset</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/vkweb">Vivek Agrawal</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/syedamahamfahim">Syeda Maham Fahim</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/chiderahumphrey">Chidera Humphrey</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/DoableDanny">Danny</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/stefanmuzyka">Stefan Muzyka</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/samhitharamaprasad">Samhitha Rama Prasad</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/nitinfab">Nitin Sharma</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/codewithshahan">Programming with Shahan</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/jpromanonet">Juan P. Romano</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/anjanbaradwaj">Anjan Baradwaj</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/manocormen">Manoel</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/mkbadeniyi">Kayode Adeniyi</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/MuhToyyib">Akande Olalekan Toheeb</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/dbclinton">David Clinton</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/josevnz">Jose Vicente Nunez</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/joeattardi">Joe Attardi</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/mihailgaberov">Mihail Gaberov</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/ashimi0x">Ashimi0x</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Zubs">Zubair Idris Aweda</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/IbrahimOgunbiyi">Ibrahim Ogunbiyi</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/svlorman">Svitlana Lorman</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/timmy471">Ayantunji Timilehin</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/imkrishnasarathi">Krishna Sarathi Ghosh</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/Daiveed">David Jaja</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/francisihe">Francis Ihejirika</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/marco-venturi">Marco Venturi</a></p>
</li>
<li>
<p><a href="https://freecodecamp.org/news/author/nyayicfanny">Fanny Nyayic</a></p>
</li>
</ul>
<h2 id="discordtopcontributor">Discord Top Contributor</h2>
<ul>
<li>
<p>hana-banana</p>
</li>
<li>
<p>Science99</p>
</li>
<li>
<p>Razzle Dazzle</p>
</li>
<li>
<p>jeremylt (他/他们)</p>
</li>
<li>
<p>Makka Pakka jOoJ</p>
</li>
<li>
<p>bradtaniguchi</p>
</li>
<li>
<p>ʇɹǝqɯoɥɹ</p>
</li>
<li>
<p>Versailles</p>
</li>
<li>
<p>CapslockHero 🎃</p>
</li>
<li>
<p>plamoni</p>
</li>
<li>
<p>xCoffeeMan</p>
</li>
<li>
<p>Dylan</p>
</li>
<li>
<p>QC Failed (Brandon)</p>
</li>
<li>
<p>minjo70</p>
</li>
<li>
<p>tgrtim</p>
</li>
<li>
<p>Yu14</p>
</li>
<li>
<p>localhost</p>
</li>
<li>
<p>ArielLeslie</p>
</li>
<li>
<p>Wayloe</p>
</li>
<li>
<p>Hordian</p>
</li>
<li>
<p>Anna</p>
</li>
<li>
<p>Starbreeze</p>
</li>
<li>
<p>supertanno</p>
</li>
<li>
<p>Hermit</p>
</li>
<li>
<p>Aakash</p>
</li>
<li>
<p>Ganesh</p>
</li>
<li>
<p>Zino</p>
</li>
<li>
<p>Cristina</p>
</li>
<li>
<p>Pantalonians</p>
</li>
<li>
<p>Cy4er</p>
</li>
<li>
<p>himonshuuu</p>
</li>
<li>
<p>Dumb ninja</p>
</li>
<li>
<p>Kiseki 奇跡</p>
</li>
<li>
<p>Sebastian</p>
</li>
<li>
<p>alpox</p>
</li>
<li>
<p>BasCat</p>
</li>
</ul>
<p>再次说明，这些只是参与 freeCodeCamp 社区的成千上万的人中最活跃的一些。</p>
<p>如果你有兴趣以开源贡献者的身份参与 freeCodeCamp 社区，我建议你<a href="https://contribute.freecodecamp.org/#/">阅读我们的贡献者指南</a>，并加入我们的<a href="https://discord.gg/KVUmVXA">贡献者 Discord 聊天室</a>。</p>
<p>再次感谢，祝编码愉快。🏕️</p>
<!--kg-card-end: markdown--> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 介绍 freeCodeCamp 每日 Python 和 JavaScript 挑战 – 每天解决一个新的编程难题 ]]>
                </title>
                <description>
                    <![CDATA[ freeCodeCamp 社区很高兴地宣布，我们新的每日编程挑战已经为你准备好了。🎊 持续练习是提升编程技能最有效的方法之一。因此，除了核心编程课程外，你现在可以通过每天解决一个有趣的新编程挑战来保持编程熟练度。 每个午夜（美国中部时间） ，一道新的编程题目将在 freecodecamp.org [https://freecodecamp.org] 和 freeCodeCamp 移动应用上解锁，你可以使用 JavaScript 和 Python 来解决。 如何开始解决每日编程挑战 在 freeCodeCamp 移动应用上：  1. 从 Google Play Store 或 Apple App Store 下载 freeCodeCamp 移动应用并打开。            2. 如果你想要保存你的进度，别忘了登录。然后在顶部找到今天的挑战并点击“开始挑战”：       ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/introducing-freecodecamp-daily-python-and-javascript-challenges-solve-a-new-programming-puzzle-every-day/</link>
                <guid isPermaLink="false">68dca7a6ea47500467bc736e</guid>
                
                    <category>
                        <![CDATA[ freeCodeCamp ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Miya Liu ]]>
                </dc:creator>
                <pubDate>Wed, 01 Oct 2025 10:19:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2025/10/66cb1d9b-b2e1-4911-bea5-ca1f1308ca35.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/introducing-freecodecamp-daily-python-and-javascript-challenges-solve-a-new-programming-puzzle-every-day/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Introducing freeCodeCamp Daily Python and JavaScript Challenges – Solve a New Programming Puzzle Every Day</a>
      </p><!--kg-card-begin: markdown--><p>freeCodeCamp 社区很高兴地宣布，我们新的每日编程挑战已经为你准备好了。🎊</p>
<p>持续练习是提升编程技能最有效的方法之一。因此，除了核心编程课程外，你现在可以通过每天解决一个有趣的新编程挑战来保持编程熟练度。</p>
<p>每个午夜（美国中部时间） ，一道新的编程题目将在 <a href="https://freecodecamp.org">freecodecamp.org</a> 和 freeCodeCamp 移动应用上解锁，你可以使用 JavaScript 和 Python 来解决。</p>
<h2 id="">如何开始解决每日编程挑战</h2>
<h3 id="freecodecamp">在 freeCodeCamp 移动应用上：</h3>
<ol>
<li>
<p>从 Google Play Store 或 Apple App Store 下载 freeCodeCamp 移动应用并打开。</p>
</li>
<li>
<p>如果你想要保存你的进度，别忘了登录。然后在顶部找到今天的挑战并点击“开始挑战”：</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757013682796/383439a2-12d5-4054-88d5-e0e6a6f052f0.png" alt="383439a2-12d5-4054-88d5-e0e6a6f052f0" width="281" height="609" loading="lazy"></p>
<ol start="3">
<li>选择你喜欢的语言：</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757013721085/873f1d66-93c5-47ac-805c-aa8ef99d058c.png" alt="873f1d66-93c5-47ac-805c-aa8ef99d058c" width="281" height="609" loading="lazy"></p>
<ol start="4">
<li>阅读挑战指令：</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757013769135/ff7d0843-1566-4349-8559-9626264bb87a.png" alt="ff7d0843-1566-4349-8559-9626264bb87a" width="281" height="609" loading="lazy"></p>
<ol start="5">
<li>编写代码：</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757013821639/a049756c-b873-4b6b-a7a9-ab020db48933.png" alt="a049756c-b873-4b6b-a7a9-ab020db48933" width="281" height="609" loading="lazy"></p>
<ol start="6">
<li>通过测试：</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757014651276/28dff232-0c54-41b3-ac2f-0ddbfa0d913c.png" alt="28dff232-0c54-41b3-ac2f-0ddbfa0d913c" width="281" height="609" loading="lazy"></p>
<p>这样你就完成了这项挑战。</p>
<h3 id="">在网站上：</h3>
<ol>
<li>访问 <a href="https://freecodecamp.org">freecodecamp.org</a> 并确保你已登录，以保存进度。然后向下滚动找到当天的编程挑战并点击“开始”：</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757014100541/aaf37fe9-d06e-4198-834c-6cd6ea37d330.png" alt="aaf37fe9-d06e-4198-834c-6cd6ea37d330" width="487" height="130" loading="lazy"></p>
<ol start="2">
<li>
<p>在顶部选择你喜欢的语言</p>
</li>
<li>
<p>阅读挑战指令，编写代码并通过测试：</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757014412721/ee3a6ed9-0628-41fe-acf0-fc10e5772ee8.png" alt="ee3a6ed9-0628-41fe-acf0-fc10e5772ee8" width="2094" height="1560" loading="lazy"></p>
<h2 id="">如果我错过了一天怎么办？</h2>
<p>如果你错过了一项挑战，不必担心。移动应用和网站都包含一个<strong>归档页面</strong>，你可以根据自己的节奏浏览和完成之前的挑战：</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757015163098/3bdf35b5-d76c-49de-bb50-35f262716059.png" alt="3bdf35b5-d76c-49de-bb50-35f262716059" width="2094" height="1560" loading="lazy"></p>
<h2 id="">今天开始你的首个挑战</h2>
<p>今天的挑战正在等待你。打开 freeCodeCamp 应用或访问 <a href="https://freecodecamp.org">freecodecamp.org</a> 完成它吧。🚀</p>
<!--kg-card-end: markdown--> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 学习 API 基础和架构 - 面向初学者的指南 ]]>
                </title>
                <description>
                    <![CDATA[ 以下有一些问题：你是如何使用 Google、Apple 或 Microsoft 账号登录应用的？如何使用 Paystack 或 PayPal 进行在线支付？像 Facebook 和 Instagram 这样的应用是如何共享信息和通知的？ 答案是：它们使用 API。这些是推动移动和 Web 开发以及各种应用程序（包括云服务、物联网设备、桌面软件等）的强大工具。 API 实现了应用之间的通信，促进了数据交换和验证。 在本文中，你将了解 API 的所有内容：不同类型、它们的架构以及不同架构之间的权衡。 我们将涵盖以下内容：  * 什么是 API？         * API 如何工作？             ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/learn-api-fundamentals-and-architecture/</link>
                <guid isPermaLink="false">68b6be1cbb40b8047c933025</guid>
                
                    <category>
                        <![CDATA[ API ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Elio Fang ]]>
                </dc:creator>
                <pubDate>Tue, 02 Sep 2025 09:57:21 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2025/09/4d39283c-ec52-4cb3-bdda-bc818b303bc3.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/learn-api-fundamentals-and-architecture/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Learn API Fundamentals and Architecture – A Beginner-Friendly Guide</a>
      </p><!--kg-card-begin: markdown--><p>以下有一些问题：你是如何使用 Google、Apple 或 Microsoft 账号登录应用的？如何使用 Paystack 或 PayPal 进行在线支付？像 Facebook 和 Instagram 这样的应用是如何共享信息和通知的？</p>
<p>答案是：它们使用 API。这些是推动移动和 Web 开发以及各种应用程序（包括云服务、物联网设备、桌面软件等）的强大工具。</p>
<p>API 实现了应用之间的通信，促进了数据交换和验证。</p>
<p>在本文中，你将了解 API 的所有内容：不同类型、它们的架构以及不同架构之间的权衡。</p>
<h3 id="">我们将涵盖以下内容：</h3>
<ul>
<li>
<p><a href="#heading-what-is-an-api">什么是 API？</a></p>
<ul>
<li>
<p><a href="#heading-how-do-apis-work">API 如何工作？</a></p>
</li>
<li>
<p><a href="#heading-why-are-apis-important">为什么 API 很重要？</a></p>
</li>
</ul>
</li>
<li>
<p><a href="#heading-types-of-apis">API 类型</a></p>
<ul>
<li>
<p><a href="#heading-open-apis">开放 API</a></p>
</li>
<li>
<p><a href="#heading-partner-apis">合作伙伴 API</a></p>
</li>
<li>
<p><a href="#heading-internal-apis">内部 API</a></p>
</li>
<li>
<p><a href="#heading-composite-apis">组合 API</a></p>
</li>
</ul>
</li>
<li>
<p><a href="#heading-types-of-api-architecture">API 架构类型</a></p>
<ul>
<li>
<p><a href="#heading-rest-apis">REST API</a></p>
</li>
<li>
<p><a href="#heading-soap-apis">SOAP API</a></p>
</li>
<li>
<p><a href="#heading-graphql-apis">GraphQL API</a></p>
</li>
<li>
<p><a href="#heading-grpc-apis">gRPC API</a></p>
</li>
</ul>
</li>
<li>
<p><a href="#heading-how-to-choose-an-api-architecture">如何选择 API 架构</a></p>
</li>
<li>
<p><a href="#heading-conclusion-and-future-trends">结论和未来趋势</a></p>
</li>
</ul>
<p>这篇文章非常适合于 Web 和移动开发初学者，以及希望简要了解 API 及其如何运作的开发者。</p>
<h2 id="api">什么是 API？</h2>
<p>API 代表应用程序编程接口。它是一组规则和协议，让不同的软件系统相互通信。API 定义了应用程序如何请求服务和交换数据，充当客户端和服务器之间的明确契约。</p>
<p>API 将复杂的代码简化为简单的命令，让开发人员可以连接系统并使用内置功能，而无需了解所有的内部工作原理。</p>
<h3 id="api">API 如何工作？</h3>
<p>想象一下有一家餐馆：顾客（客户端）通过服务员（API）点餐，然后服务员通知厨房（服务器）。厨房备餐后通过服务员传递给顾客。就像服务员一样，API 处理请求和响应，让顾客在无需了解厨房操作细节的情况下享受餐点。</p>
<p>一个更实用的例子是当你在线购买订阅时，你的支付信息通过其支付 API 安全发送至 Paystack。API 是一个中间人，它获取你的请求，验证并处理你的银行支付信息，然后在不直接暴露敏感数据的情况下返回确认给网站。</p>
<p>从技术上讲，客户端向服务器发起请求，指定要获取数据还是执行某个流程。接收并认证该请求后，API 会执行所需操作。随后，API 向客户端发送响应，包括请求的结果（成功或失败）和任何请求的数据元素。</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeho5OxXyKdS_-Sam70CtbZIH6y1wFMH3r21I0ZeNDVFNqoY0Jr2Lk5u_FfsiIas6LEnMPjRbQticIaDZi0iCF93Zj-JpxjZzXrwEGtdS_vIopXEUtNG5mvVHnVpf5vvhZGHw4Q?key=2qCWq-hs7d172uM7WbtEHg_B" alt="来自 shiksha.com 的图解说明了 API 如何工作。" width="1445" height="777" loading="lazy"></p>
<h3 id="api">为什么 API 很重要？</h3>
<p>API 在软件开发中至关重要，因为它们使得连接不同的应用程序和服务更加容易。它们允许你整合外部功能，而无需从头开始构建所有内容，通过标准化命令节省时间并降低复杂性。</p>
<p>对于用户来说，API 还可以提高安全性和用户体验。它们作为安全网关，过滤应用和外部服务之间的数据交换，保护敏感信息，同时确保流畅、可靠的互动。</p>
<h2 id="api">API 类型</h2>
<p>API 的类型主要根据其可访问性和使用情况进行分类。API 有四种类型，分别是：</p>
<ol>
<li>
<p>开放（公共）API</p>
</li>
<li>
<p>合作伙伴 API</p>
</li>
<li>
<p>内部（私有）API</p>
</li>
<li>
<p>组合 API</p>
</li>
</ol>
<h3 id="api">开放 API</h3>
<p>开放 API 是向公众提供的 API。这就鼓励开发者、组织和其他人使用它们来开发应用程序，将其集成到他们的服务中，并加以改进。开放 API 提供了通过互联网访问数据或服务的标准化接口。</p>
<p>一些非常实用的开放 API 包括：</p>
<ul>
<li>
<p><a href="https://tradewatch.io/">TradeWatch</a> —— 实时金融市场数据</p>
</li>
<li>
<p><a href="http://serpapi.com">SerpAPI 的搜索 API</a> —— 实时谷歌搜索引擎结果页 API</p>
</li>
<li>
<p><a href="http://twitterapi.io">TwitterApi.io</a> —— 访问实时和历史数据</p>
</li>
<li>
<p><a href="https://instagram-posts-generator.vercel.app/">Instagram 帖子生成器</a> —— 使用流行 IG 页面模板生成帖子</p>
</li>
</ul>
<h3 id="api">合作伙伴 API</h3>
<p>合作伙伴 API 与特定的商业伙伴共享，通常需要身份验证和协议。它们为企业和应用程序执行重要功能。</p>
<p>例如，像 Paystack 这样的支付 API 直接与服务提供商和银行平台通信，以处理产品和服务的支付。</p>
<h3 id="api">内部 API</h3>
<p>内部 API 用于组织内部的通信。它们能够实现集成并简化内部流程。内部团队使用 API 在其应用程序之间访问和共享数据。API 不对公众开放，以确保敏感的业务逻辑保持安全。</p>
<p>一个例子是公司内部 API，它连接其人力资源、工资单和项目管理系统。</p>
<h3 id="api">复合 API</h3>
<p>复合 API 将多个 API 调用组合为一个请求。在微服务架构中，它们非常重要，因为单个操作可能需要从多个服务中获取数据。一次 API 调用会触发对多个底层 API 的请求，然后复合 API 会组合这些响应并返回一个统一的结果。</p>
<p>例如，一个电子商务平台可能会使用复合 API 来一次性获取产品详情、定价和库存信息，减少延迟并简化集成过程。</p>
<h2 id="api">API 架构类型</h2>
<p>根据使用场景、可扩展性、安全性和可访问性，API 的结构各有不同。构建 API 的方式有多种，但我们将仅关注Web开发中最为流行的架构风格，它们包括：</p>
<ol>
<li>
<p>REST</p>
</li>
<li>
<p>SOAP</p>
</li>
<li>
<p>GraphQL</p>
</li>
<li>
<p>gRPC</p>
</li>
</ol>
<h3 id="restapi">REST API</h3>
<p>表述性状态转移（REST）是一种使用 HTTP 方法（POST、GET、PUT、DELETE）在基于资源的 URI 上执行 CRUD（创建、读取、更新、删除）操作的架构风格。</p>
<p>REST API 使用像 Express.js（Node.js）、Django/Flask（Python）、Spring Boot（Java）这样的框架构建。</p>
<h4 id="">关键组件</h4>
<ol>
<li>
<p>资源和端点：</p>
<ul>
<li>
<p>API 公开的实体可以包括任何内容：用户、产品、文档等。</p>
</li>
<li>
<p>每个资源由唯一的 URI（统一资源标识符）标识。</p>
</li>
</ul>
</li>
<li>
<p>HTTP 方法：</p>
<ul>
<li>
<p>GET：获取资源。</p>
</li>
<li>
<p>POST：创建新资源。</p>
</li>
<li>
<p>PUT：更新现有资源。</p>
</li>
<li>
<p>DELETE：删除资源。</p>
</li>
<li>
<p>PATCH：部分更新现有资源。</p>
</li>
</ul>
</li>
<li>
<p>数据表示：</p>
<ul>
<li>
<p>资源可以有多种表示形式（例如，JSON，XML）。</p>
</li>
<li>
<p>API以请求的表示形式响应，允许对数据进行结构化和解析。</p>
</li>
</ul>
</li>
<li>
<p>HTTP 标头和查询参数：</p>
<ul>
<li>
<p>HTTP 标头提供有关请求或响应的附加信息。</p>
</li>
<li>
<p>它们可以用于身份验证、内容协商和其他用途。</p>
</li>
</ul>
</li>
<li>
<p>无状态：</p>
<ul>
<li>
<p>客户端到服务器的每个请求都必须包含理解和处理请求所需的所有信息。</p>
</li>
<li>
<p>服务器在请求之间不存储任何客户端状态。</p>
</li>
</ul>
</li>
</ol>
<p>其他显著的组件包括可缓存性、HTTP 状态和 HATEOAS。这些组件共同定义了 RESTful 系统的结构和行为，支持客户端与服务器之间的无缝高效通信。</p>
<h4 id="">操作概述</h4>
<p>REST API 通过唯一的 URI 公开资源，并允许客户端使用 HTTP 方法（如 GET、POST、PUT、DELETE 和 PATCH）执行操作。客户端可以请求各种格式的数据，如 JSON 或 XML，并通过 HTTP 头和查询参数包含附加细节。</p>
<p>每个请求都是无状态的，包含处理所需的所有信息，而不依赖于存储的客户端数据。API 还使用 HTTP 状态码、可缓存性和 HATEOAS 管理响应并指导进一步的交互，确保客户端和服务器之间的无缝高效通信框架。</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcYW8ovzOrZJB1eV1X82hvfuddZwjl7mwI56bYpZKCvzf4I4tNEfx58lhIjs_GMRaei9mXAxR78BUAIacBYoCw4J-CmkVKRDGa5ruK4KdYnmBV2Y0u9qz9QjOYSWNHBmUIPsopXuA?key=2qCWq-hs7d172uM7WbtEHg_B" alt="来自 apisec.ai 的图示，说明 REST API 的流，包括端点、HTTP 方法以及客户端和服务器之间的数据交换。" width="720" height="378" loading="lazy"></p>
<h4 id="">实际示例和真实案例</h4>
<p>为了说明 REST API 在实践中的工作原理，我们以一个允许用户管理图书集合的图书 API 为例。我们的示例 API 是使用 <a href="https://www.freecodecamp.org/news/get-started-with-nodejs/">NodeJS</a> 和 <a href="https://expressjs.com/">ExpressJS</a> 框架创建的。这里我们不解释这些框架的具体工作原理，因为这超出了本文的范围。所以如果你不了解下面代码的语法，不用担心，只需关注 <strong>请求</strong> 和 <strong>响应</strong> 逻辑。</p>
<p>此 API 遵循 REST 原则，使用标准 HTTP 方法执行 CRUD（创建、读取、更新、删除）操作：</p>
<pre><code>const express = require("express"); const bodyParser = require("body-parser");
const app = express(); app.use(bodyParser.json());

const app = express();
app.use(bodyParser.json());

// 虚拟数据库
let books = [
  { id: 1, title: "The Pragmatic Programmer", author: "Andy Hunt" },
  { id: 2, title: "Clean Code", author: "Robert C. Martin" },
];

// 获取所有书籍（客户端请求，服务器响应）
app.get("/books", (req, res) =&gt; res.json(books));
</code></pre>
<pre><code class="language-markdown">// 新增一本书（客户端发送数据，服务器更新数据库）
app.post("/books", (req, res) =&gt; {
  const newBook = { id: books.length + 1, ...req.body };
  books.push(newBook);
  res.status(201).json(newBook);
});

// 更新一本书
app.put("/books/:id", (req, res) =&gt; {
  const book = books.find((b) =&gt; b.id === parseInt(req.params.id));
  if (book) {
    Object.assign(book, req.body);
    res.json(book);
  } else {
    res.status(404).json({ message: "Not found" });
  }
});

// 删除一本书
app.delete("/books/:id", (req, res) =&gt; {
  const index = books.findIndex((b) =&gt; b.id === parseInt(req.params.id));
  if (index !== -1) {
    books.splice(index, 1);
    res.json({ message: "Deleted" });
  } else {
    res.status(404).json({ message: "Not found" });
  }
});

app.listen(3000, () =&gt; console.log("API running on port 3000"));
</code></pre>
<p>此代码的操作流程如下：</p>
<ul>
<li>
<p>客户端发送请求：用户（或前端应用）通过使用诸如 GET，POST，PUT 或 DELETE 等 HTTP 方法请求数据。例如：GET <code>/books</code> 请求所有书籍，或 POST <code>/books</code> 将新书提交到数据库。</p>
</li>
<li>
<p>服务器处理请求：服务器接收请求，查找数据（例如，从数据库或内存数组中查找），并进行处理。</p>
</li>
<li>
<p>服务器返回响应：服务器返回包含请求数据或确认消息的 JSON 响应。示例如下：</p>
</li>
</ul>
<pre><code>[
  { "id": 1, "title": "The Pragmatic Programmer", "author": "Andy Hunt" },
  { "id": 2, "title": "Clean Code", "author": "Robert C. Martin" }
]
</code></pre>
<ul>
<li>客户端接收并使用数据：前端或其他服务使用 API 响应，并相应地显示或处理数据。</li>
</ul>
<p>团队将 REST API 用于 Web 服务、移动应用程序和云集成。社交媒体平台获取帖子，电子商务网站检索产品详情。支付网关处理交易，天气应用程序访问实时预测。REST 的简单性和可扩展性使其成为公共和内部 API 的首选。</p>
<h3 id="soapapis">SOAP APIs</h3>
<p>简单对象访问协议（SOAP）使用 XML 进行消息传递，并包括用于安全、事务和错误处理的内置标准。其正式约定由 WSDL（Web 服务描述语言）定义。</p>
<p>这种架构通过 WS-Security（Web Services Security）和事务管理等功能优先考虑安全性和可靠性，使其适合需要严格标准和强大错误处理的复杂企业应用程序。</p>
<p>SOAP APIs 是使用诸如 Apache CXF、.NET WCF 和 JAX-WS（Java）等框架或工具创建的。</p>
<h4 id="">关键组件</h4>
<ol>
<li>
<p>SOAP envelope（SOAP 封套）：</p>
<ul>
<li>
<p>这是 SOAP 消息的根元素，定义了 XML 文档的整体结构。</p>
</li>
<li>
<p>它包含 SOAP Header（SOAP 标头）和 SOAP Body（SOAP 主体）。</p>
</li>
</ul>
</li>
<li>
<p>SOAP body（SOAP 主体）：</p>
<ul>
<li>
<p>该部分包含在客户端和服务器之间交换的实际数据。</p>
</li>
<li>
<p>它包括请求或响应消息，这些消息通常被构造为 XML 元素。</p>
</li>
</ul>
</li>
<li>
<p>WSDL（Web 服务描述语言）：</p>
<ul>
<li>
<p>这是一个描述 Web 服务的 XML 文档，包括其操作、消息格式和数据类型。</p>
</li>
<li>
<p>它充当客户端和服务器之间的合同，概述如何与 API 交互。</p>
</li>
</ul>
</li>
<li>
<p>SOAP processor（SOAP 处理器）：</p>
<ul>
<li>
<p>这是处理 SOAP 消息的软件组件。</p>
</li>
<li>
<p>它解析 XML 文档，提取相关数据，并执行请求的操作。</p>
</li>
</ul>
</li>
</ol>
<p>另外，还有 SOAP Endpoint（SOAP 端点），即 SOAP 服务可被访问的 URL，以及 XML Schema (XSD)，定义了 SOAP 消息的 XML 结构和数据类型。</p>
<h4 id="">操作概述</h4>
<p>SOAP APIs 通过将数据封装在由 SOAP 封套定义的基于 XML 的结构中运行，该信封包含用于元数据的标头和用于实际请求或响应信息的主体。主体承载交换数据，而 WSDL 文档则作为契约，详细说明服务的操作、消息格式和数据类型。</p>
<p>SOAP 处理器随后解析 XML，提取相关数据，并根据附带的 XML 模式 (XSD) 定义的规则执行请求的操作。与服务的通信通过特定的 SOAP 端点进行，确保了 Web 服务交互的标准化、互操作框架。</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfN_kg7EZxppR62_usgGiNO7jTLWnrmd5MYzxLUyjl6cNSuVHBAVV-kWvQN2xZ5s1acOugK8SfGb2JKtIys01yMSrdRO7iwNCtc5CHh6QDDCBWH2vc7EYOiHNgpbyZv8jZBhTwejg?key=2qCWq-hs7d172uM7WbtEHg_B" alt="来自 muledreamin.com 的图解，说明 SOAP API 的流程，包括 HTTP 传输以及 SOAP 发送方与 SOAP 接收方之间的数据交换。" width="835" height="442" loading="lazy"></p>
<h4 id="">实际例子和真实用例</h4>
<p>为了说明 SOAP APIs 及其实际工作原理，我们考虑一个基于 SOAP 的银行服务 API，提供用于管理账户和交易的安全操作。SOAP APIs 使用 XML 消息传递，确保系统间的安全和结构化通信。创建 SOAP API 和 XML 消息传递超出了本文的范围，因此我们将在此重点讨论请求和响应逻辑。</p>
<p>如何运作：</p>
<ul>
<li><strong>获取账户信息</strong>: 客户端发送一个 XML 请求以获取用户的账户详情：</li>
</ul>
<pre><code>&lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:bank="http://example.com/bank"&gt;
   &lt;soapenv:Header/&gt;
   &lt;soapenv:Body&gt;
      &lt;bank:GetAccountDetails&gt;
         &lt;bank:AccountNumber&gt;123456789&lt;/bank:AccountNumber&gt;
      &lt;/bank:GetAccountDetails&gt;
   &lt;/soapenv:Body&gt;
&lt;/soapenv:Envelope&gt;
</code></pre>
<p>服务器以包含账户详细信息的 XML 消息进行响应：</p>
<pre><code>&lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"&gt;
   &lt;soapenv:Body&gt;
      &lt;GetAccountDetailsResponse&gt;
         &lt;AccountNumber&gt;123456789&lt;/AccountNumber&gt;
         &lt;Balance&gt;5000.00&lt;/Balance&gt;
         &lt;Currency&gt;USD&lt;/Currency&gt;
      &lt;/GetAccountDetailsResponse&gt;
   &lt;/soapenv:Body&gt;
&lt;/soapenv:Envelope&gt;
</code></pre>
<ul>
<li>
<p><strong>处理转账</strong>: 客户端提交一个带有认证详情的转账请求：</p>
<pre><code>  &lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                    xmlns:bank="http://example.com/bank"&gt;
     &lt;soapenv:Header/&gt;
     &lt;soapenv:Body&gt;
        &lt;bank:TransferFunds&gt;
           &lt;bank:FromAccount&gt;123456789&lt;/bank:FromAccount&gt;
           &lt;bank:ToAccount&gt;987654321&lt;/bank:ToAccount&gt;
           &lt;bank:Amount&gt;100.00&lt;/bank:Amount&gt;
           &lt;bank:Currency&gt;USD&lt;/bank:Currency&gt;
        &lt;/bank:TransferFunds&gt;
     &lt;/soapenv:Body&gt;
  &lt;/soapenv:Envelope&gt;
</code></pre>
<p>如果成功，服务器返回一个确认响应：</p>
<pre><code>  &lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"&gt;
     &lt;soapenv:Body&gt;
        &lt;TransferFundsResponse&gt;
           &lt;Status&gt;Success&lt;/Status&gt;
           &lt;TransactionID&gt;TXN987654&lt;/TransactionID&gt;
        &lt;/TransferFundsResponse&gt;
     &lt;/soapenv:Body&gt;
  &lt;/soapenv:Envelope&gt;
</code></pre>
</li>
</ul>
<p>银行、医疗保健提供者和政府机构使用 SOAP 提供安全、可靠的 API。金融机构以严格的身份验证处理交易，而医疗系统在遵从法规下交换患者数据。航空公司依赖 SOAP 进行预订和售票，确保跨系统的一致数据完整性。</p>
<h3 id="graphqlapi">GraphQL API</h3>
<p>GraphQL 是一种由 Facebook 开发的用于 APIs 的查询语言和运行时。它允许客户端在一个请求中精确地请求所需的数据，减少过度获取和不足获取。</p>
<h4 id="">关键组件</h4>
<ol>
<li>
<p>模式: 这是 GraphQL API 的核心。它定义了数据的结构，包括对象类型、其字段及其关系。它作为客户端和服务器之间的契约，指定可以查询的数据。</p>
</li>
<li>
<p>类型: 这些定义了数据中对象的结构。它们指定每个对象拥有的字段及这些字段的数据类型。</p>
</li>
<li>
<p>字段: 这些是可以在一个对象上查询的独立数据片段。</p>
</li>
<li>
<p>查询: 这些是客户端请求以检索数据。它们指定客户端希望恢复的字段。</p>
</li>
<li>
<p>变更: 这些是客户端请求以修改数据（创建、更新或删除）。</p>
</li>
<li>
<p>解析器: 这些是为模式中每个字段获取数据的函数。它们将 GraphQL 模式连接到底层数据源。</p>
</li>
<li>
<p>订阅: 这些启用实时更新。客户端可以订阅特定事件，服务器将在事件发生时推送更新。</p>
</li>
</ol>
<h4 id="">操作概述</h4>
<p>GraphQL 定义了一个指定可用数据类型及其关系的 schema。然后，客户端构建查询或变更，精确请求所需数据字段。GraphQL 服务器处理这些请求，使用解析器从后端源获取数据。</p>
<p>服务器根据模式验证请求，执行解析器，并返回仅包含请求数据的 JSON 响应。客户端可以建立实时更新的订阅，使服务器在数据改变时推送数据。这种方法最小化了过度获取和不足获取，提高了数据检索的效率和灵活性。</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcmC7u4hu44TvJ603f9ODRYIgi3UiHMs-Q4qjE8FZqwPnEGDPTU6DhZSvLCZU3BO7WITNnuls_801ChJyACz6xpKOdvoQ5hLswAMIHZ3-Ii4dyg7CEKZ5m1AAgv70sso-c26Cl_sQ?key=2qCWq-hs7d172uM7WbtEHg_B" alt="来自 kinsta.com 的图解，展示了 GraphQL 服务器架构，显示了从服务器传输 GraphQL 查询请求和 JSON 负载的过程。" width="960" height="540" loading="lazy"></p>
<h4 id="">实际示例和真实用例</h4>
<p>让我们通过一个由 GraphQL 驱动的电子商务 API 来实际探讨 GraphQL API 的工作原理。此 API 可以高效地获取产品详情、评论和库存可用性。服务器是使用 NodeJS 和 <a href="https://www.apollographql.com/docs/apollo-server">Apollo Server</a> 创建的。创建服务器超出了本文的范围，因此我们将专注于 Schema（关系数据库是如何构建和可视表示的）及 <strong>请求</strong> 和 <strong>响应</strong> 逻辑。</p>
<ol>
<li>模式:</li>
</ol>
<pre><code># Schema (schema.graphql)

type Product {
  id: ID!
  name: String!
  description: String
  price: Float!
  inventory: Int!
  category: String!
}


```markdown
type Mutation {
  createProduct(name: String!, description: String, price: Float!, inventory: Int!, category: String!): Product!
  updateProductInventory(id: ID!, inventory: Int!): Product!
}
</code></pre>
<p>这个模式定义了数据类型（<code>Product</code>、<code>Query</code>、<code>Mutation</code>）并指定了可用的查询（<code>product</code>、<code>products</code>）和变更操作（<code>createProduct</code>、<code>updateProductInventory</code>）。它使用了 <a href="https://graphql.org/learn/schema/">GraphQL 类型系统</a>（String、Int、Float、ID、[ ]、!）</p>
<ol start="2">
<li>
<p>请求和响应</p>
<ul>
<li>
<p>获取产品数据 - 客户端请求特定的产品字段（例如，名称、价格和描述）：</p>
<pre><code class="language-graphql">query {
  product(id: "123") {
    name
    price
    description
  }
}
</code></pre>
<p>如果请求成功，服务器仅返回请求的数据：</p>
<pre><code class="language-json">{
  "data": {
    "product": {
      "name": "无线耳机",
      "price": 99.99,
      "inStock": true
    }
  }
}
</code></pre>
</li>
<li>
<p>创建一个新产品：</p>
<pre><code class="language-graphql">mutation {
  createProduct(name: "鼠标", price: 30, inventory: 100, category: "电子产品") {
    id
    name
    price
  }
}
</code></pre>
</li>
<li>
<p>更新产品信息：</p>
<pre><code class="language-graphql">mutation {
  updateProduct(id: "123", price: 89.99) {
    name
    price
  }
}
</code></pre>
<p>如果成功，服务器返回更新后的详细信息：</p>
<pre><code class="language-json">{
  "data": {
    "updateProduct": {
      "name": "无线耳机",
      "price": 89.99
    }
  }
}
</code></pre>
</li>
</ul>
</li>
</ol>
<p>像 Facebook 和 Shopify 这样的公司使用 GraphQL 来实现高效、灵活的 API。电子商务和社交应用程序只提取所需的数据，减少多余的数据获取。移动应用程序优化性能，而分析工具无缝聚合复杂数据。</p>
<h3 id="grpcapis">gRPC APIs</h3>
<p>远程过程调用（gRPC）是一种高性能的 RPC 框架，使用 HTTP/2 和协议缓冲序列化结构化数据。它支持同步和异步通信以及流功能。</p>
<p>HTTP/2 是 HTTP 的最新演进，具备二进制分帧、多路复用、标头压缩和服务器推送等令人兴奋的特性，以提高性能和减少延迟。gRPC 充分利用了这些功能，实现快速、高效、同时的通信，使其非常适合微服务和实时应用。</p>
<h4 id="">关键组件</h4>
<ol>
<li>
<p>服务定义：在 .proto 文件中定义。它指定了所提供的服务和可用的 RPC 方法，充当客户端和服务器之间的契约。</p>
</li>
<li>
<p>消息是使用协议缓冲区定义的数据结构，可以在系统之间高效地序列化和反序列化数据。</p>
</li>
<li>
<p>存根：自动生成的客户端和服务器代码，使客户端可以像调用本地方法一样调用远程方法，并使服务器可以实现服务逻辑。</p>
</li>
<li>
<p>通道：它们管理客户端和服务器之间的连接，处理底层网络通信。</p>
</li>
<li>
<p>RPC 方法：gRPC 支持不同类型的调用，包括一元（单请求-响应）、客户端流、服务器流和双向流，每种都适合不同的使用场景。</p>
</li>
<li>
<p>拦截器和元数据：这些提供了附加额外功能的机制，例如通过将元数据附加到 RPC 调用来进行身份验证、日志记录和错误处理。</p>
</li>
</ol>
<h4 id="">操作概述</h4>
<p>gRPC 让开发者能够在 .proto 文件中使用协议缓冲定义服务契约和消息类型，作为可用 RPC 方法的蓝图。代码生成器生成客户端和服务器存根，允许像本地函数一样调用远程过程，同时通道管理基于 HTTP/2 的网络通信。</p>
<p>它支持一元、客户端流、服务器流和双向流以应对不同的数据交换模式。此外，还可以集成拦截器和元数据来进行身份验证和日志记录等任务，确保系统稳健、安全和高效。</p>
<h4 id="">实践示例和实际使用案例</h4>
<p>让我们考虑一个使用 gRPC 快速在客户端（移动应用）和后端服务之间快速通信的打车应用。gRPC 使用协议缓冲（Protobuf）进行二进制序列化，而不是像 JSON 或 XML 这样的基于文本的格式。这使得网络通信显著更快且更高效。</p>
<ol>
<li>.proto 文件定义了 API 结构：</li>
</ol>
<pre><code class="language-protobuf">syntax = "proto3";

service RideService {
  rpc RequestRide(RideRequest) returns (RideResponse);
  rpc StreamRideUpdates(RideUpdateRequest) returns (stream RideUpdate);
}

message RideRequest {
  string user_id = 1;
  string pickup_location = 2;
  string destination = 3;
}

message RideResponse {
  string ride_id = 1;
  string driver_name = 2;
  string car_model = 3;
}
</code></pre>
<pre><code>message RideUpdateRequest {
  string ride_id = 1;
}
</code></pre>
<p>当客户端发送一个 <code>RideRequest</code> 时，它会使用 Protobuf 序列化为一个紧凑的二进制格式。这减少了负载大小，加快了传输速度，提高了效率。服务器会在处理之前将其反序列化为一个结构化的对象。</p>
<ol start="2">
<li>
<p>请求和响应：</p>
<ul>
<li>
<p>请求乘车：客户端点击按钮发送乘车请求，其中包含：</p>
<pre><code>{
  "user_id": "U123",
  "pickup_location": "Central Park",
  "destination": "Times Square"
}
</code></pre>
<p>服务器响应司机的详细信息：</p>
<pre><code>{
  "ride_id": "R456",
  "driver_name": "John Doe",
  "car_model": "Toyota Prius"
}
</code></pre>
<p>你可能会好奇为什么请求和响应是以 JSON 格式显示的，因为 gRPC 并不使用像 JSON 和 XML 这样的基于文本的格式。gRPC 使用的压缩二进制流不像 JSON 那样可读，这是一个紧凑且高效的编码格式，需要通过 Protobuf 反序列化来理解。在压缩二进制流格式中，请求或响应看起来像这样：</p>
<pre><code>08 D2 04 12 0D 43 65 6E 74 72 61 6C 20 50 61 72 6B 1A 0B 54 69 6D 65 73 20 53 71 75 61 72 65
</code></pre>
</li>
<li>
<p>实时流更新：一旦分配了乘车，服务器就会向客户端流式传输实时更新：</p>
<pre><code>{
  "ride_id": "R456",
  "status": "Driver on the way",
  "driver_location": "5th Avenue"
}
</code></pre>
</li>
</ul>
</li>
</ol>
<p>公司使用 gRPC 来满足高性能、实时应用程序中对高效服务通信的需求。像 Google、Netflix 和 Dropbox 这样的科技巨头使用 gRPC 来实现可扩展的微服务。共享乘车应用程序会流式传输实时司机位置，而金融科技平台则管理安全、低延迟的交易。物联网系统和人工智能应用依赖 gRPC 来进行实时数据交换和高效交互。</p>
<h2 id="api">如何选择API架构</h2>
<p>选择一个 API 架构需要根据项目的具体需求平衡性能、可扩展性、易用性和安全性等多个因素。</p>
<p>REST 因其简单性和无状态设计而闻名，这有助于可扩展性和易用性，但其安全性主要依赖于外部措施，如 HTTPS 和适当的认证机制。</p>
<p>SOAP 尽管更复杂，但提供了强大的内置安全标准（如 WS-Security）和可靠的事务支持，使其适合于企业环境。</p>
<p>GraphQL 通过只允许客户端请求所需的数据，提供了高效的数据获取和高性能，但可能需要额外的安全措施，比如查询深度限制和服务器端的恰当认证。</p>
<p>gRPC 提供了卓越的性能，非常适合实时数据需求的微服务。它利用 HTTP/2 和 TLS 来实现安全、高效的通信，尽管它需要较长的学习曲线。</p>
<p>下表总结了这些架构的特点以及如何权衡：</p>
<table>
<thead>
<tr>
<th>特点</th>
<th>REST</th>
<th>SOAP</th>
<th>GraphQL</th>
<th>gRPC</th>
</tr>
</thead>
<tbody>
<tr>
<td>性能</td>
<td>中等（可能存在数据过度获取）</td>
<td>低</td>
<td>高</td>
<td>高</td>
</tr>
<tr>
<td>可扩展性</td>
<td>高</td>
<td>中等</td>
<td>高</td>
<td>非常高（适用于微服务和实时数据）</td>
</tr>
<tr>
<td>易用性</td>
<td>简单且广泛采用</td>
<td>复杂</td>
<td>对于客户端来说直观（服务器端可能复杂）</td>
<td>学习曲线陡峭</td>
</tr>
<tr>
<td>安全性</td>
<td>依赖于外部机制（HTTPS、OAuth 等）</td>
<td>通过 WS-Security 和正式合同提供强大的内置安全性</td>
<td>需要额外的措施（查询验证、速率限制）</td>
<td>高安全性，内置 TLS 支持和强大的认证协议</td>
</tr>
</tbody>
</table>
<h2 id="">结论和未来趋势</h2>
<p>API 已成为现代软件开发中的基本组成部分，促进了不同应用程序之间的无缝通信和数据交换。它们的影响是不可否认的，从推动创新的公共 API 到简化内部流程的私有 API。</p>
<p>理解 REST、SOAP、GraphQL 和 gRPC 等不同的 API 架构，使开发人员能够根据特定需求选择最佳方法，在性能、可扩展性和易用性之间取得平衡。</p>
<p>展望未来，API 领域将迎来令人兴奋的变化。随着 AI 驱动的 API、去中心化架构和改进的安全措施的出现，我们将看到新的方式来构建和交互软件。API 标准的持续演变和低代码/无代码平台的增长使 API 开发变得更容易为所有人所用。</p>
<!--kg-card-end: markdown--> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 为什么 Vibe Coding 不会摧毁软件工程 ]]>
                </title>
                <description>
                    <![CDATA[ AI 正在以史无前例的速度颠覆所有行业。 曾经由一两家公司主导或非常“以人为本”的技术和行业正面临威胁。 Google 正在被 AI 搜索抢占市场 [https://www.smoothseo.co/blog/misc/what-the-numbers-say-about-ais-growing-role-in-search/] ，卡车司机 [https://www.axios.com/2022/03/28/automation-long-haul-truckers-jobs] 可能很快就会成为历史，低技能文书工作每天都在流失 [https://news.sky.com/story/ai-risks-up-to-eight-million-uk-job-losses-with-low-skilled-worst-hit-report-warns-13102214] 。 这种颠覆会摧毁软件工程行业吗？我认为不会，我来告诉你为什么。 我们将讨论的内容  1. “Vibe Coding” 现象            2. AI 如何改变软件开发            3. 生产力悖论 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/why-vibe-coding-wont-destroy-software-engineering/</link>
                <guid isPermaLink="false">686e358e032b52046653aa8d</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ YiWei ]]>
                </dc:creator>
                <pubDate>Wed, 09 Jul 2025 09:37:28 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2025/07/----_20250709173551.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/why-vibe-coding-wont-destroy-software-engineering/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Why Vibe Coding Won't Destroy Software Engineering</a>
      </p><!--kg-card-begin: markdown--><p>AI 正在以史无前例的速度颠覆所有行业。</p>
<p>曾经由一两家公司主导或非常“以人为本”的技术和行业正面临威胁。</p>
<p><a href="https://www.smoothseo.co/blog/misc/what-the-numbers-say-about-ais-growing-role-in-search/">Google 正在被 AI 搜索抢占市场</a>，<a href="https://www.axios.com/2022/03/28/automation-long-haul-truckers-jobs">卡车司机</a>可能很快就会成为历史，低技能文书<a href="https://news.sky.com/story/ai-risks-up-to-eight-million-uk-job-losses-with-low-skilled-worst-hit-report-warns-13102214">工作每天都在流失</a>。</p>
<p>这种颠覆会摧毁软件工程行业吗？我认为不会，我来告诉你为什么。</p>
<h3 id="">我们将讨论的内容</h3>
<ol>
<li>
<p>“Vibe Coding” 现象</p>
</li>
<li>
<p>AI 如何改变软件开发</p>
</li>
<li>
<p>生产力悖论</p>
</li>
<li>
<p>为什么人类工程师仍然至关重要</p>
</li>
<li>
<p>AI 作为“能力倍增器”</p>
</li>
<li>
<p>AI 时代的关键技能</p>
</li>
<li>
<p>前进之路</p>
</li>
</ol>
<h2 id="vibecoding"><strong>“Vibe Coding” 现象</strong></h2>
<p>如果你关注技术讨论，你可能已经看到过 “Vibe Coding” 这个术语——通过试验和错误、直觉和 AI 生成的代码片段来构建软件，而不需要深入的技术知识。</p>
<p>现代 AI 助手，如 GitHub Copilot 和 ChatGPT，可以根据简单的描述生成完整的函数、修复 bug 和创建组件。“Vibe Coders” 声称人类程序员很快就会变得过时。</p>
<p>从我的角度来看，这些 AI 工具更像是技能倍增器，而不是替代品。</p>
<p>它们帮助有才华的开发者工作得更快，同时暴露了技能不足的程序员的知识缺口。那些缺乏技术基础的程序员会遇到他们无法解决的问题，但将 AI 助手与实用的专业知识相结合的工程师将能够非常高效地工作。</p>
<h2 id="ai"><strong>AI 如何改变软件开发</strong></h2>
<p>软件行业正在快速普及基于大语言模型的 AI 编程工具，这些工具分析代码仓库以预测和建议下一步行动。</p>
<p>这些工具通过以下方式改变了日常编程工作：</p>
<ul>
<li>
<p>根据你输入的内容建议完整的函数</p>
</li>
<li>
<p>根据普通语言描述创建 API 端点</p>
</li>
<li>
<p>消除了花在标准代码模式上的时间</p>
</li>
<li>
<p>自动化文档任务</p>
</li>
<li>
<p>快速处理重复逻辑</p>
</li>
</ul>
<p>这种向 “vibe coding” 的转变加快了功能交付速度。程序员现在可以在不掌握每个技术细节的情况下构建软件——他们描述需求，获取 AI 建议，然后不断调整直至代码正常运行。</p>
<p><strong>风险在于，开发者经常推送他们无法解释的代码</strong>。他们在构建过程中进展很快，但在系统崩溃或需要更改时却会遇到困难。</p>
<p>还有一种令人担忧的趋势是非程序员在销售完全通过 AI 构建的应用程序。最近，一位没有编程背景的人通过 AI 提示推出了一个付费服务，只是在几天后就面临了数据泄露，因为黑客利用了基本的安全漏洞。这很危险。它浪费了人们的钱，并暴露了他们的数据。想象一下，如果这种情况由于 “Vibe Coders” 的崛起而变得普遍？</p>
<p>对于任何考虑构建软件但不是软件工程师的人来说，有一些基本的安全级别需要考虑：</p>
<ul>
<li>
<p>向 API 端点添加身份验证：人们可以扫描整个互联网上的开放端口和端点。如果他们可以在没有身份验证的情况下调用你的 API 端点，那么这可能会导致各种问题</p>
</li>
<li>
<p>不要以明文存储密码。这是一个大禁忌。如果你这样做并且你的数据库被泄露，那么这些密码将被所有人看到。而且，现实中人们会重复使用密码，所以这些密码将是他们在其他网站上的密码。</p>
</li>
<li>
<p>SSL：确保你的网站安全并且具有最新的 SSL 证书。在明文中传输数据很危险。</p>
</li>
<li>
<p>锁定未使用的端口：如果你托管后端服务，请确保未使用的端口被锁定，人们无法连接到它们。</p>
</li>
<li>
<p>如果你有允许上传文件的区域，请限制上传的文件类型。</p>
</li>
</ul>
<p>以上仅是网站或产品安全防护的部分注意事项，实际需要考量的因素远不止于此。</p>
<h2 id=""><strong>生产力悖论</strong></h2>
<p>AI 助手显著提高了代码输出量——但数量并不等于软件工程中的价值。</p>
<p>这些工具在语法方面表现良好，但对系统架构、可扩展性问题和维护需求没有任何了解。就像打字速度不会创造出更好的小说一样，代码生成速度也不会产生更好的软件系统。</p>
<p>AI 适用于单个函数，但在架构决策、安全规划和长期支持需求方面却很难。没有适当的审查和理解，AI 生成的代码通常会成为明天的技术债务和维护负担。</p>
<p>想象一下这样的场景：开发者实现了一个 AI 创建的身份验证系统，它在隔离环境中有效，但在用户注册产品时会导致微妙的故障。找到并修复这些集成问题可能需要经验丰富的员工几天的时间——这抵消了最初节省的时间。这种做法很快就会导致资金损失和信任危机。</p>
<h2 id=""><strong>为什么人类工程师仍然至关重要</strong></h2>
<p>虽然 AI 工具在语法方面表现良好，但它们无法：</p>
<ol>
<li>
<p>规划随着用户需求而增长的系统</p>
</li>
<li>
<p>创建可靠的部署和测试管道</p>
</li>
<li>
<p>预测不寻常但至关重要的故障情况</p>
</li>
<li>
<p>在性能和成本之间做出明智的权衡</p>
</li>
<li>
<p>找到不明显的安全漏洞</p>
</li>
</ol>
<p>优秀的工程师不仅仅是编写代码。他们开发有助于整个团队的模式，选择合适的技术，并为成功和失败场景做计划。</p>
<p>软件创建涉及复杂的权衡：我们是否优先考虑速度或稳定性？灵活性或简单性？这些决策需要技术专业知识和商业知识。</p>
<p>我合作的最有价值的工程师花更多的时间思考而不是输入代码。他们考虑：需求如何演变？哪些压力点可能出现？系统如何从故障中恢复？</p>
<p>随着基础代码生成变得广泛可用，你的价值来自于理解系统交互。竞争优势将属于那些知道为什么某些方法会成功、它们可能在哪里失败以及如何构建弹性解决方案的人。</p>
<p>正如上所述，有一些事情 AI 无法做到。</p>
<p>AI 可以在简单的提示中创建解决方案来解决众所周知的问题。如果你使用此提示，例如：</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747771377197/8aae1332-f852-435a-a724-a1770a4163bf.png" alt="Prompt: &quot;Create a Python module that will tell you if some input JSON is valid&quot;" width="1024" height="130" loading="lazy"></p>
<p>这里是你可能得到的代码：</p>
<pre><code class="language-plain">import json

def is_valid_json(input_string: str) -&gt; bool:
    """
    Checks if the input string is valid JSON.

    Args:
        input_string (str): The JSON string to validate.

    Returns:
        bool: True if valid, False otherwise.
    """
    try:
        json.loads(input_string)
        return True
    except json.JSONDecodeError:
        return False

def main():
    user_input = input("Enter a JSON string to validate: ")
    if is_valid_json(user_input):
        print("✅ The input is valid JSON.")
    else:
        print("❌ The input is NOT valid JSON.")

if __name__ == "__main__":
    main()
</code></pre>
<p>非常基本。</p>
<p>我不会要求 AI 为我构建一个复杂的外汇交易平台。</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747771546630/d212d814-7785-4391-8e01-79e80c05da44.png" alt="d212d814-7785-4391-8e01-79e80c05da44" width="1368" height="212" loading="lazy"></p>
<p>我就不赘述全部回复内容了，简单来说就是它无法完成这个操作。</p>
<p>我想将其分解为一个稍微较小的金融交易平台子集：</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747771773603/b65e1a13-97aa-4276-81c7-55303e5a04c6.png" alt="Prompt: &quot;Create me an endpoint for a FIX message for an FX Financial security. Make it in Python and I want to be able to accept J messages. Security is key here, so I need this to be as secure as possible.&quot;" width="1326" height="224" loading="lazy"></p>
<p>现在，我会承认，这更接近了。这里是结果：</p>
<pre><code class="language-plain">from fastapi import FastAPI, Request, HTTPException, Header
from pydantic import BaseModel, Field
from typing import Optional
import hmac
import hashlib
import logging

app = FastAPI()

# === CONFIGURATION ===
SHARED_SECRET = b"super_secure_shared_secret"  # Keep this secure

# === LOGGING SETUP ===
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("ems.fix")

# === Pydantic Model for Execution Report (simplified) ===
class ExecutionReport(BaseModel):
    msg_type: str = Field(default="J", const=True)
    cl_ord_id: str  # Tag 11
    order_id: str   # Tag 37
    exec_id: str    # Tag 17
    exec_type: str  # Tag 150
    ord_status: str # Tag 39
    symbol: str     # Tag 55 (e.g., EUR/USD)
    side: str       # Tag 54 (1=Buy, 2=Sell)
    leaves_qty: float  # Tag 151
    cum_qty: float     # Tag 14
    avg_px: float      # Tag 6
    transact_time: str # Tag 60 (ISO8601 string)

# === Helper: HMAC Validator ===
def verify_signature(payload: bytes, signature: str) -&gt; bool:
    computed = hmac.new(SHARED_SECRET, payload, hashlib.sha256).hexdigest()
    return hmac.compare_digest(computed, signature)

# === Endpoint ===
@app.post("/fix/execution-report")
async def receive_execution_report(
    request: Request,
    x_signature: Optional[str] = Header(None)
):
    body = await request.body()

    if not x_signature or not verify_signature(body, x_signature):
        logger.warning("Invalid or missing signature.")
        raise HTTPException(status_code=403, detail="Unauthorized")

    try:
        report_data = ExecutionReport.parse_raw(body)
        logger.info(f"Execution Report received: {report_data.dict()}")
        # ✅ Here, you'd handle order updates, booking, etc.
        return {"status": "ok", "message": "Execution Report received"}
    except Exception as e:
        logger.exception("Invalid payload format.")
        raise HTTPException(status_code=400, detail=f"Invalid FIX message format: {str(e)}")
</code></pre>
<p>但这仍然无法接近最终版本。即使你可以使用此代码作为交易系统的一部分，但除非你知道如何构建和架构整个软件系统，否则你将从哪里开始？你可以告诉客户他们可以发送“ExecutionReport”，但接下来呢？</p>
<p>关于“只需更擅长提示工程就能构建更庞大系统”的说法，我早已耳闻目见。但真正的效益从何而来？金融交易系统的复杂度远超人类理解范畴。要让提示工程足够完善，以便构建一个功能齐全、可扩展、安全且可扩展的系统（更别说调试能力）本身就是一项巨大的任务。所谓节省时间从何体现？这真的可行吗</p>
<p>我还没有看到任何证据表明有人在没有人类监督的情况下构建了这样一个复杂的系统，我不相信我们会在近期看到。</p>
<h2 id="ai"><strong>AI 作为“能力倍增器”</strong></h2>
<p>这些 AI 工具帮助放大现有的能力，而不是取代它们。有才华的开发者变得更加高效，而技能较弱的开发者则更快地生成问题。</p>
<p>优秀工程师使用 AI 来：</p>
<ul>
<li>
<p>处理基本的实现任务</p>
</li>
<li>
<p>创建初始项目框架</p>
</li>
<li>
<p>比较不同的解决方案方法</p>
</li>
<li>
<p>突破具有挑战性的问题</p>
</li>
</ul>
<p>同时，能力较弱的开发者使用 AI 来掩盖技能差距，实现他们不理解也不知道如何修改的解决方案。当这些实现失败时，他们缺乏独立修复它们的知识。</p>
<p>这扩大了技能差距。顶级工程师利用 AI 处理机械任务，同时专注于更高价值的思考。那些将 AI 用作学习替代品的人会在超出 AI 知识边界时遇到限制。</p>
<p>一个很好的例子是 AI 完美适合的东西是翻译逻辑：</p>
<p>假设我有一个 Python Dataclass 表示一个“内部用户”。我还有一个 Django ORM 表示相同的实体。如果我想将一个转换为另一个，我可以简单地将两个表示形式粘贴到 ChatGPT 中，并让它为我创建一个转换函数。请注意，转换函数还考虑到字段名称不完全匹配：</p>
<pre><code class="language-plain">@dataclass
class InternalUser:
    id: str
    email: str
    hashed_password: str
    full_name: str
    role: UserRole
    status: AccountStatus
    created_at: datetime
    updated_at: datetime
    address: Optional[Address] = None
    preferences: Preferences = field(default_factory=Preferences)
    login_activity: LoginActivity = field(default_factory=LoginActivity)
    tags: List[str] = field(default_factory=list)
    notes: Optional[str] = None
</code></pre>
<pre><code class="language-plain">class InternalUser(models.Model):
    id = models.CharField(primary_key=True, max_length=100)  # Use UUIDField if preferred
    email = models.EmailField(unique=True)
    hashedPassword = models.CharField(max_length=256)
    fullName = models.CharField(max_length=255)
    role = models.CharField(max_length=20, choices=UserRole.choices, default=UserRole.USER)
    status = models.CharField(max_length=20, choices=AccountStatus.choices, default=AccountStatus.PENDING)
    createdAt = models.DateTimeField(default=timezone.now)
    updatedAt = models.DateTimeField(auto_now=True)

    address = models.OneToOneField(Address, null=True, blank=True, on_delete=models.SET_NULL)
    preferences = models.OneToOneField(Preferences, on_delete=models.CASCADE)
    loginActivity = models.OneToOneField(LoginActivity, on_delete=models.CASCADE)

    tags = models.JSONField(default=list, blank=True)  # List of strings
    notes = models.TextField(null=True, blank=True)

    def __str__(self):
        return f"{self.fullName} ({self.email})"
</code></pre>
<pre><code class="language-plain">from typing import Optional
from myapp.models import InternalUser as ORMInternalUser, Address as ORMAddress, Preferences as ORMPreferences, LoginActivity as ORMLoginActivity
from mydataclasses import InternalUser as DCInternalUser  # assuming your dataclass lives here


def convert_internal_user_to_model(dc_user: DCInternalUser) -&gt; ORMInternalUser:
    # Create or update Address if provided
    orm_address: Optional[ORMAddress] = None
    if dc_user.address:
        orm_address = ORMAddress.objects.create(
            street=dc_user.address.street,
            city=dc_user.address.city,
            state=dc_user.address.state,
            postalCode=dc_user.address.postal_code,
            country=dc_user.address.country
        )

    # Create Preferences
    orm_preferences = ORMPreferences.objects.create(
        newsletterOptIn=dc_user.preferences.newsletter_opt_in,
        darkModeEnabled=dc_user.preferences.dark_mode_enabled,
        language=dc_user.preferences.language
    )

    # Create LoginActivity
    orm_login_activity = ORMLoginActivity.objects.create(
        lastLogin=dc_user.login_activity.last_login,
        loginAttempts=dc_user.login_activity.login_attempts,
        lastIpAddress=dc_user.login_activity.last_ip_address
    )

    # Create InternalUser
    orm_user = ORMInternalUser.objects.create(
        id=dc_user.id,
        email=dc_user.email,
        hashedPassword=dc_user.hashed_password,
        fullName=dc_user.full_name,
        role=dc_user.role.value,
        status=dc_user.status.value,
        createdAt=dc_user.created_at,
        updatedAt=dc_user.updated_at,
        address=orm_address,
        preferences=orm_preferences,
        loginActivity=orm_login_activity,
        tags=dc_user.tags,
        notes=dc_user.notes
    )

    return orm_user
</code></pre>
<p>这是一个基本的例子，但如果你将其扩展到整个内部数据模型，那么你将节省数小时的代码。</p>
<p>你甚至可以要求它为你创建测试函数的存根：</p>
<pre><code class="language-plain">import pytest
from datetime import datetime
from yourmodule.dataclasses import InternalUser, Address, Preferences, LoginActivity, UserRole, AccountStatus
from yourmodule.conversion import dataclass_to_django_internal_user


@pytest.mark.django_db
def test_internal_user_conversion_basic_fields():
    # 测试基本字段（电子邮件、姓名等）是否正确复制
    pass


@pytest.mark.django_db
def test_internal_user_conversion_with_address():
    # 测试地址字段是否正确映射到 ORM 模型
    pass


@pytest.mark.django_db
def test_internal_user_conversion_with_preferences():
    # 测试偏好设置，如暗黑模式、新闻通讯订阅和语言
    pass


@pytest.mark.django_db
def test_internal_user_conversion_with_login_activity():
    # 测试登录尝试、最后一次登录和最后一次 IP 地址
    pass


@pytest.mark.django_db
def test_internal_user_conversion_with_tags_and_notes():
    # 测试标签列表和可选备注字段
    pass


@pytest.mark.django_db
def test_internal_user_conversion_with_missing_optional_fields():
    # 确保缺失的可选字段（如地址或最后一次登录）不会破坏转换
    pass


@pytest.mark.django_db
def test_internal_user_conversion_saves_correctly():
    # 保存所有相关模型和主 InternalUser 模型，并检查数据库
    pass
</code></pre>
<p>我并非建议你直接照搬这些测试用例而不加以思考，但这是一个很好的开始。</p>
<p>这些“苦差事”从来不是我们高薪聘请顶尖工程师的原因。它们只是完成项目的必要工序。人们不喜欢这些任务。它们无法带给人成就感。</p>
<h2 id="ai"><strong>AI 时代的关键技能</strong></h2>
<p>随着 AI 处理更多的编码任务，成功的工程师必须在人类判断仍然至关重要的领域发展自己的优势：</p>
<p>系统思维成为主要技能——了解组件交互，识别潜在故障，并为未来的增长设计。这项能力来自经验，而不是提示。</p>
<p>你应该在基础设施和部署流程方面建立专业知识。开发环境中有效但生产环境中失败的软件不会创造任何价值。因此，学习<a href="https://www.freecodecamp.org/news/learn-continuous-integration-delivery-and-deployment/">持续集成</a>、<a href="https://www.freecodecamp.org/news/how-to-set-up-monitoring-for-nodejs-applications-using-elastic/">监控</a>系统和<a href="https://www.freecodecamp.org/news/beginners-guide-to-cloud-computing-with-aws/">云平台功能</a>。</p>
<p>你还应该掌握[ API 设计][<a href="https://www.freecodecamp.org/chinese/news/rest-api-design-best-practices-build-a-rest-api/">https://www.freecodecamp.org/chinese/news/rest-api-design-best-practices-build-a-rest-api/</a>]——系统之间的接口。<a href="https://www.freecodecamp.org/news/design-an-api-application-program-interface/">良好设计的 API </a>使团队独立。糟糕的接口会造成瓶颈，影响每个人。</p>
<p>另一个关键技能是将安全性集成到整个开发过程中。单一疏忽可能会导致泄露，损害客户信任和商业声誉。</p>
<p>确保你发展与技术和非技术受众交流的能力。你将需要清晰地解释复杂的决策，跨越不同的利益相关者群体。</p>
<p>并研究 AI 工具的工作原理，以了解它们的局限性和优势，使你能够更有效地使用它们。</p>
<p>对于高级开发人员，指导变得越来越重要。新工程师需要获得“如何负责任地使用 AI” 这方面的指导——知道何时接受建议、何时质疑它们。</p>
<h2 id=""><strong>前进之路</strong></h2>
<p>软件领域正在经历一次重大的转变。AI 将生成更多代码，改变开发实践。这一转变带来了机遇和挑战。</p>
<p>最有价值的职位将属于擅长机器无法处理的任务的工程师。这些工程师将决定要构建什么、如何设计，以及如何平衡技术约束与商业目标。</p>
<p>“Vibe Coding”是一种有用的技术，适用于特定的需求——例如快速构建标准组件。但是，它并不能提供复杂系统开发的全面策略。</p>
<p>有才华的工程师将通过将常规工作委派给 AI，同时解决更具挑战性的问题来推进。技能较弱的工程师将在基本知识缺口变得明显时遇到困难。</p>
<p>关于如何有效运用 AI 技术，在采纳网络建议时务必保持审慎判断。这仍然是一个相对较新的领域，并且不断变化。</p>
<p>人们在线提供“免费提示”来生成代码。这些提示可能很好，也可能有问题。提示可能在他们使用时很好，但 AI 模型可能已经改变，也可能会产生不同的结果。要谨慎并使用你的最佳判断。</p>
<p>未来属于那些将 AI 视为协作工具而不是替代品的人。软件开发仍然是人类驱动的，现在得到了越来越强大的支持。</p>
<p>在他的空闲时间里，Ben 写他的技术博客 <a href="https://justanothertechlead.com/"><em>Just Another Tech Lead</em></a> 和运营一个关于 SEO 的网站 <a href="https://www.smoothseo.co"><em>SmoothSEO</em></a>。</p>
<!--kg-card-end: markdown--> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 在你的浏览器中学习 React - freeCodeCamp 全栈课程 2025 年中更新 ]]>
                </title>
                <description>
                    <![CDATA[ Hey campers！freeCodeCamp 社区仍在全力开发我们的全栈课程 [https://www.freecodecamp.org/chinese/learn/full-stack-developer/]的剩余部分。 虽然才过去几个月，但已经有许多学员全力投入这些新课程和编程挑战中。 我很兴奋能与大家分享下一批更新。 新课程内容 我们刚刚发布了三个新的课程部分：React Hooks 和 State、性能、测试。 这些新课程包含：  * 50 个讲座视频  * 十几个工作坊和实验室  * 3 个新的复习模块  * 以及大量课程内容，帮助你保持学习进度（同时我们正在完成全栈课程的剩余部分） 你将构建的一些项目包括：  * 井字棋游戏  * 颜色选择器  * 超级英雄申请表 考试 我们知道许多人热切期待每个模块末尾的考试。这些考试快要准备好了。 我们还在构建一个自定义的考试环境，供你参加这些考试。这将平衡隐私保护和学术诚信。 下一步计划 社区现在正专注于 CSS 库和 TypeScript 模块。我们还在构建 Python 模块。 未来几个月我们将有很多 ]]>
                </description>
                <link>https://www.freecodecamp.org/chinese/news/learn-react-in-your-browser-freecodecamp-full-stack-curriculum-mid-2025-update/</link>
                <guid isPermaLink="false">68527f0aeb98e40467ef9ab5</guid>
                
                    <category>
                        <![CDATA[ freeCodeCamp ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Miya Liu ]]>
                </dc:creator>
                <pubDate>Wed, 18 Jun 2025 09:18:00 +0000</pubDate>
                <media:content url="https://chinese.freecodecamp.org/news/content/images/2025/06/----_20250618171556.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>原文：</strong> <a href="https://www.freecodecamp.org/news/learn-react-in-your-browser-freecodecamp-full-stack-curriculum-mid-2025-update/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Learn React in your Browser – freeCodeCamp Full Stack Curriculum Mid-2025 Update</a>
      </p><!--kg-card-begin: markdown--><p>Hey campers！freeCodeCamp 社区仍在全力开发我们的<a href="https://www.freecodecamp.org/chinese/learn/full-stack-developer/">全栈课程</a>的剩余部分。</p>
<p>虽然才过去几个月，但已经有许多学员全力投入这些新课程和编程挑战中。</p>
<p>我很兴奋能与大家分享下一批更新。</p>
<h2 id="">新课程内容</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750152183453/6e973e4a-4b7e-4294-b056-95a5f6155e77.png" alt="课程页面截图" width="600" height="400" loading="lazy"></p>
<p>我们刚刚发布了三个新的课程部分：React Hooks 和 State、性能、测试。</p>
<p>这些新课程包含：</p>
<ul>
<li>50 个讲座视频</li>
<li>十几个工作坊和实验室</li>
<li>3 个新的复习模块</li>
<li>以及大量课程内容，帮助你保持学习进度（同时我们正在完成全栈课程的剩余部分）</li>
</ul>
<p>你将构建的一些项目包括：</p>
<ul>
<li>井字棋游戏</li>
<li>颜色选择器</li>
<li>超级英雄申请表</li>
</ul>
<h2 id="">考试</h2>
<p>我们知道许多人热切期待每个模块末尾的考试。这些考试快要准备好了。</p>
<p>我们还在构建一个自定义的考试环境，供你参加这些考试。这将平衡隐私保护和学术诚信。</p>
<h2 id="">下一步计划</h2>
<p>社区现在正专注于 CSS 库和 TypeScript 模块。我们还在构建 Python 模块。</p>
<p>未来几个月我们将有很多内容发布。</p>
<p>一些即将上线的项目包括：</p>
<ul>
<li>构建你自己的 RPG 角色</li>
<li>交易卡牌游戏</li>
<li>医疗数据验证器</li>
<li>以及更多🏕️</li>
</ul>
<h2 id="">参与进来</h2>
<p>你有兴趣帮助我们开发这些全栈课程吗？欢迎你贡献，你可以在我们的 GitHub 仓库查看所有开放的<a href="https://github.com/freecodecamp/freecodecamp/issues">议题</a>。</p>
<p>请先阅读我们的<a href="https://contribute.freecodecamp.org/intro/">贡献指南</a>，然后加入我们的 <a href="https://discord.gg/KVUmVXA">Discord 社区</a>，你可以提出任何问题。</p>
<p>我们很兴奋看到大家学习所有这些新课程。保持动力，继续提升技能，Happy coding！💜</p>
<!--kg-card-end: markdown--> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
