程序员武学修炼手册(一):入门篇——初学乍练,从 Hello World 到能跑就行

"千里之行,始于足下;万行代码,始于 Hello World。" ------ 《程序员武学心法》

开篇:程序员的武学境界

在武侠世界里,习武之人从入门弟子到一代宗师,需要经历漫长的修炼。

在程序员的世界里,我们也有类似的成长路径。今天,让我们用武学的视角,重新审视程序员的修炼之路。

复制代码
┌─────────────────────────────────────────────────────────────┐
│              程序员武学境界总览                               │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   第一境:初学乍练 ------  能写代码,能跑就行(入门弟子)          │
│   第二境:小有所成 ------  代码规范,知其所以然(三流高手)        │
│   第三境:融会贯通 ------  架构设计,独当一面(一流高手)          │
│   第四境:登峰造极 ------  技术专家,指点江山(绝顶高手)          │
│   第五境:开宗立派 ------  自成一家,影响江湖(一代宗师)          │
│                                                             │
│   番外:走火入魔 ------ 那些修炼路上的歧途                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

本系列将分为六篇,今天是第一篇:初学乍练


第一章:初学乍练的特征

1.1 什么是初学乍练?

初学乍练,是每个程序员的起点。

就像武侠小说里刚入门的弟子,刚拿到一本剑谱,连基本的扎马步都不稳,但眼里充满了对武学的向往。

初学乍练程序员的典型特征:

  • 刚学会一门语言,觉得自己无所不能
  • 代码能跑就是胜利
  • 变量命名:a, b, c, temp, temp2, temp3
  • 注释?不存在的
  • 遇到 Bug 第一反应:重启试试?

1.2 初学乍练的心理状态

javascript 复制代码
// 初学乍练程序员的内心独白

const beginnerMindset = {
  day1: "Hello World跑通了!我是天才!",
  day7: "这个for循环好难...算了,复制粘贴",
  day30: "我已经会写函数了,可以找工作了吧?",
  day60: "为什么我的代码别人看不懂?明明很清晰啊",
  day90: "原来我写的是屎山...",
}

第二章:初学乍练的修炼内容

2.1 第一式:Hello World

每个程序员的第一招,必是 Hello World。

javascript 复制代码
// JavaScript版
console.log("Hello, World!")

// 练气期程序员的进阶版
console.log("Hello, World!")
console.log("Hello, World!!")
console.log("Hello, World!!!")
// 为什么要打三遍?因为我能!
python 复制代码
# Python版
print("Hello, World!")

# 练气期程序员的"优化"版
for i in range(100):
    print("Hello, World!" + "!" * i)
# 这样更有气势!
java 复制代码
// Java版
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

// 练气期程序员的困惑:
// 为什么打印个Hello World要写这么多?
// public是什么?static是什么?void又是什么?
// 算了,能跑就行...

2.2 第二式:变量与类型

javascript 复制代码
// 练气期的变量命名艺术

// 阶段1:单字母时期
let a = 1
let b = 2
let c = a + b

// 阶段2:拼音时期
let nianling = 18
let mingzi = "张三"
let gongzi = 10000

// 阶段3:中英混搭时期
let userNianling = 18
let userName = "张三"
let userGongzi = 10000

// 阶段4:开始觉醒
let userAge = 18
let userName = "张三"
let userSalary = 10000
// 虽然还是有点问题,但已经在进步了

2.3 第三式:条件判断

javascript 复制代码
// 练气期的if-else艺术

// 初级写法:一路if到底
function getGrade(score) {
  if (score >= 90) {
    return "A"
  }
  if (score >= 80) {
    return "B"
  }
  if (score >= 70) {
    return "C"
  }
  if (score >= 60) {
    return "D"
  }
  return "F"
}

// 练气期"优化"版:嵌套地狱
function getGradeNested(score) {
  if (score >= 60) {
    if (score >= 70) {
      if (score >= 80) {
        if (score >= 90) {
          return "A"
        } else {
          return "B"
        }
      } else {
        return "C"
      }
    } else {
      return "D"
    }
  } else {
    return "F"
  }
}
// 能跑!完美!(并不)

// 练气期的终极形态:复制粘贴大法
function processUser(user) {
  if (user.type === "admin") {
    if (user.status === "active") {
      if (user.level >= 5) {
        // 100行代码
      } else {
        // 复制上面100行,改几个字
      }
    } else {
      // 再复制100行
    }
  } else {
    // 继续复制...
  }
}

2.4 第四式:循环

javascript 复制代码
// 练气期的循环修炼

// 第一层:for循环
for (let i = 0; i < 10; i++) {
  console.log(i)
}
// 掌握了!我是天才!

// 第二层:while循环
let i = 0
while (i < 10) {
  console.log(i)
  // 忘记 i++ 了...
  // 程序卡死
  // 为什么???
}

// 第三层:嵌套循环
for (let i = 0; i < 10; i++) {
  for (let j = 0; j < 10; j++) {
    for (let k = 0; k < 10; k++) {
      // 三层循环,性能杀手
      // 但是能跑!
    }
  }
}

// 练气期经典Bug:死循环
function infiniteLoop() {
  let arr = [1, 2, 3]
  for (let i = 0; i < arr.length; i++) {
    arr.push(i) // 数组越来越长...
    // 电脑风扇开始狂转
    // 浏览器卡死
    // 强制关机
  }
}

2.5 第五式:函数

javascript 复制代码
// 练气期的函数修炼

// 阶段1:不知道什么是函数
// 所有代码写在一起,500行一个文件

// 阶段2:知道函数,但不会用
function doSomething() {
  // 200行代码
  // 做了10件不同的事
  // 函数名叫doSomething,因为确实在做something
}

// 阶段3:函数太多,不知道怎么组织
function step1() {}
function step2() {}
function step3() {}
function step4() {}
function step5() {}
// ...
function step99() {}

function main() {
  step1()
  step2()
  step3()
  // ...
  step99()
}

// 阶段4:开始理解函数的意义
function calculateTax(income) {
  // 只做一件事:计算税
  return income * 0.2
}

function formatCurrency(amount) {
  // 只做一件事:格式化金额
  return `¥${amount.toFixed(2)}`
}

2.6 第六式:数组与对象

javascript 复制代码
// 练气期的数据结构

// 数组的使用
let arr = [1, 2, 3, 4, 5]

// 练气期的数组操作
// 想删除第3个元素
arr[2] = undefined // 这样对吗?
// 结果:[1, 2, undefined, 4, 5]
// 好像不太对...

// 正确做法(但练气期不知道)
arr.splice(2, 1)

// 对象的使用
let user = {
  name: "张三",
  age: 18,
}

// 练气期的对象操作
user.mingzi = "李四" // 为什么不生效?
// 因为属性名是name不是mingzi...

// 练气期经典困惑:引用类型
let arr1 = [1, 2, 3]
let arr2 = arr1
arr2.push(4)
console.log(arr1) // [1, 2, 3, 4] ???
// 为什么arr1也变了???
// 这个Bug找了三天...

第三章:初学乍练的常见走火入魔

3.1 复制粘贴走火入魔

javascript 复制代码
// 症状:同样的代码出现N次

function processUserA(user) {
  // 验证用户
  if (!user.name) throw new Error("name required")
  if (!user.email) throw new Error("email required")
  if (!user.phone) throw new Error("phone required")

  // 处理数据
  user.name = user.name.trim()
  user.email = user.email.toLowerCase()

  // 保存
  database.save(user)

  // 发送通知
  sendEmail(user.email, "Welcome!")
}

function processUserB(user) {
  // 复制上面的代码
  // 改了一个字
  // 验证用户
  if (!user.name) throw new Error("name required")
  if (!user.email) throw new Error("email required")
  if (!user.phone) throw new Error("phone required")

  // 处理数据
  user.name = user.name.trim()
  user.email = user.email.toLowerCase()

  // 保存
  database.save(user)

  // 发送通知
  sendEmail(user.email, "Welcome Back!") // 就改了这里
}

// 后果:改一个地方要改N个地方,总有漏的

3.2 过度注释走火入魔

javascript 复制代码
// 症状:注释比代码还多

// 定义一个变量i,初始值为0
let i = 0

// 使用while循环
while (i < 10) {
  // 当i小于10时
  // 打印i的值
  console.log(i) // 输出当前的i
  // i自增1
  i++ // i = i + 1
} // while循环结束

// 这种注释不如不写...

3.3 变量命名走火入魔

javascript 复制代码
// 症状:变量名让人怀疑人生

// 拼音派
let nianling = 18
let xingming = "张三"
let shouji = "13800138000"

// 缩写派
let usrNm = "张三"
let usrAg = 18
let usrPh = "13800138000"

// 数字派
let user1 = {}
let user2 = {}
let user11 = {} // 不是user1的升级版
let user111 = {} // 也不是user11的升级版

// 混搭派
let getUserXinxi = () => {} // 中英混搭
let YONGHU_INFO = {} // 拼音+英文

// 终极形态
let aaaa = 1
let bbbb = 2
let cccc = aaaa + bbbb
let dddd = cccc * 2
// 一周后自己都看不懂

3.4 缩进走火入魔

javascript 复制代码
// 症状:缩进混乱,Tab和空格混用

function chaos() {
  if (true) {
    console.log("2空格")
    console.log("4空格?不,是Tab")
    console.log("这是几个空格?")
    console.log("这是Tab")
    console.log("Tab+空格混搭")
  }
}

// 后果:代码在不同编辑器里显示不一样
// 同事打开你的代码:这是什么鬼?

第四章:初学乍练的突破契机

4.1 第一次代码审查

javascript 复制代码
// 你提交的代码
function calc(a, b, c) {
  let temp = a + b
  let temp2 = temp * c
  return temp2
}

// 代码审查反馈
/*
 * 1. 函数名calc太模糊,计算什么?
 * 2. 参数a, b, c是什么意思?
 * 3. temp, temp2命名不清晰
 * 4. 可以直接return,不需要中间变量
 *
 * 建议修改为:
 */
function calculateTotalPrice(unitPrice, quantity, taxRate) {
  return unitPrice * quantity * taxRate
}

// 你的内心:原来代码还可以这样写...

4.2 第一次维护别人的代码

javascript 复制代码
// 你接手的代码
function f(x) {
  let a = x[0]
  let b = x[1]
  let c = x[2]
  if (a > 0) {
    if (b > 0) {
      if (c > 0) {
        return a * b * c
      } else {
        return a * b
      }
    } else {
      return a
    }
  } else {
    return 0
  }
}

// 你的任务:修改这个函数,支持第四个参数

// 你的内心:
// 这是什么?
// x是什么?
// a, b, c是什么?
// 为什么要这样嵌套?
// 我改哪里?
// 算了,我重写一个...

// 顿悟:原来写清晰的代码这么重要

4.3 第一次生产事故

javascript 复制代码
// 你写的代码
function deleteUser(userId) {
  database.delete("users", { id: userId })
}

// 调用时
deleteUser() // 忘记传参数了

// 结果
database.delete("users", { id: undefined })
// 某些数据库会把这理解为:删除所有用户
// 用户表清空了...

// 事后复盘
function deleteUserSafe(userId) {
  // 参数校验!
  if (!userId) {
    throw new Error("userId is required")
  }

  // 二次确认
  const user = database.findOne("users", { id: userId })
  if (!user) {
    throw new Error("user not found")
  }

  // 软删除而不是硬删除
  database.update("users", { id: userId }, { deleted: true })

  // 记录日志
  logger.info(`User ${userId} deleted`)
}

// 顿悟:防御性编程真的很重要

第五章:初学乍练的修炼心法

5.1 心法一:代码是写给人看的

javascript 复制代码
// 练气期的认知
// "代码是写给电脑执行的"

// 突破后的认知
// "代码首先是写给人看的,其次才是给电脑执行的"

// 实践
// 不好的代码
let d = new Date()
let h = d.getHours()
let m = d.getMinutes()
let s = d.getSeconds()
let t = h + ":" + m + ":" + s

// 好的代码
const currentDate = new Date()
const hours = currentDate.getHours()
const minutes = currentDate.getMinutes()
const seconds = currentDate.getSeconds()
const timeString = `${hours}:${minutes}:${seconds}`

5.2 心法二:不要重复自己(DRY)

javascript 复制代码
// 练气期的代码
function validateEmail(email) {
  if (!email) return false
  if (!email.includes("@")) return false
  return true
}

function validateUserEmail(user) {
  if (!user.email) return false
  if (!user.email.includes("@")) return false
  return true
}

function validateAdminEmail(admin) {
  if (!admin.email) return false
  if (!admin.email.includes("@")) return false
  return true
}

// 突破后的代码
function validateEmail(email) {
  if (!email) return false
  if (!email.includes("@")) return false
  return true
}

function validateUserEmail(user) {
  return validateEmail(user?.email)
}

function validateAdminEmail(admin) {
  return validateEmail(admin?.email)
}

5.3 心法三:先让它工作,再让它正确,最后让它快

javascript 复制代码
// 练气期的误区:一开始就追求完美

// 正确的修炼顺序:

// 第一步:让它工作(Make it work)
function sort(arr) {
  // 冒泡排序,O(n²),但能用
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr.length - 1; j++) {
      if (arr[j] > arr[j + 1]) {
        let temp = arr[j]
        arr[j] = arr[j + 1]
        arr[j + 1] = temp
      }
    }
  }
  return arr
}

// 第二步:让它正确(Make it right)
function sort(arr) {
  // 添加参数校验
  if (!Array.isArray(arr)) {
    throw new Error("Input must be an array")
  }
  // 不修改原数组
  const result = [...arr]
  // 排序逻辑...
  return result
}

// 第三步:让它快(Make it fast)
function sort(arr) {
  // 使用更高效的算法
  // 或者直接用内置方法
  return [...arr].sort((a, b) => a - b)
}

第六章:初学乍练的出师考核

6.1 自测题

javascript 复制代码
// 问题1:这段代码有什么问题?
function add(a, b) {
  return a + b
}
console.log(add("1", "2")) // 输出什么?

// 问题2:这段代码会输出什么?
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100)
}

// 问题3:找出Bug
function findMax(arr) {
  let max = 0
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] > max) {
      max = arr[i]
    }
  }
  return max
}
console.log(findMax([-1, -2, -3])) // 期望-1,实际输出?

// 问题4:这段代码的问题是什么?
let user = { name: "张三", age: 18 }
let copy = user
copy.name = "李四"
console.log(user.name) // 输出什么?

6.2 出师标准

当你能做到以下几点,就可以准备突破到小有所成了:

arduino 复制代码
┌─────────────────────────────────────────────────────────────┐
│              初学乍练出师标准 ✓                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   □ 能独立完成简单功能的开发                                 │
│   □ 知道变量、函数、循环、条件判断的基本用法                  │
│   □ 能看懂简单的报错信息                                     │
│   □ 知道Google/Stack Overflow怎么用                         │
│   □ 开始意识到代码规范的重要性                               │
│   □ 能写出别人勉强能看懂的代码                               │
│   □ 经历过至少一次"我写的代码怎么不能用了"的崩溃             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

结语:初学乍练的意义

初学乍练是每个程序员必经的阶段。

在这个阶段,你会:

  • 写出很多"能跑就行"的代码
  • 犯很多现在看来很蠢的错误
  • 经历很多"为什么不行"的崩溃时刻

但这些都是成长的必经之路。

没有人一开始就是高手。

那些现在写出优雅代码的大侠,当年也写过var a = 1; var b = 2; var c = a + b;

所以,不要因为自己是新手而气馁。

每一个 Bug 都是一次修炼,每一次崩溃都是一次突破的契机。

下一篇,我们将进入小有所成------当你开始关注代码规范、开始思考"为什么要这样写"的时候,你就踏入了三流高手的大门。


预告:小有所成

在小有所成阶段,你将学习:

  • 代码规范与最佳实践
  • 设计模式入门
  • 单元测试的重要性
  • 版本控制的正确使用
  • 如何写出"可维护"的代码

敬请期待!


本文是《程序员武学修炼手册》系列的第一篇。

如果你正处于初学乍练阶段,不要焦虑,每个大侠都是从扎马步开始的。

欢迎在评论区分享你初学乍练时的"黑历史"------毕竟,能笑着回忆过去的蠢,说明你已经成长了。 😄

相关推荐
PPPHUANG1 天前
Switch2Antigravity: 让 IntelliJ IDEA 与 Antigravity 无缝协作
程序员·intellij idea·vibecoding
zhouzhouya2 天前
码上星辰,人间烟火:我的2025
前端·程序员·代码规范
凌览2 天前
2026年1月编程语言排行榜|C#拿下年度语言,Python稳居第一
前端·后端·程序员
JOEH602 天前
🚀 别再用 Future.get() 傻等了!CompletableFuture 异步编排实战,性能提升 300%!
后端·程序员
程序员鱼皮2 天前
干掉 Claude Code,这个开源 AI 编程工具杀疯了?
前端·后端·计算机·ai·程序员
pany2 天前
程序员近十年新年愿望,都有哪些变化?
前端·后端·程序员
guanshangshui2 天前
vibe coding 开发软件(一) 模型选择和agent简单使用
程序员
SimonKing2 天前
基于Netty的TCP协议的Socket服务端
java·后端·程序员
Setsuna_F_Seiei2 天前
2025 年度总结:人生重要阶段的一年
前端·程序员·年终总结