项目立项:从需求到技术选型
从需求分析开始,一步步推技术方案。
- 从产品需求推技术方案,就这么来。
- 掌握技术选型的决策框架
- 学会评估方案的 trade-off
- 了解朋友好学的完整开发流程
一切从需求开始
写第一行代码之前,先想三个事:要解决啥问题?有啥约束条件?怎么算成功?
小白学Python,看视频走神,读书枯燥,刷题没反馈。要做个边学边练的网站,代码能即时跑,有游戏化激励。技术选型得对应这几层需求:浏览器里跑Python,不用后端,能离线用,还得适配手机。
核心技术挑战
这个项目最大的技术挑战是:如何在浏览器中运行 Python 代码?
后端执行· 原理:代码发到服务器执行· 优点:功能完整· 缺点:服务器成本、安全风险、延迟PyPy.js· 原理:Python 编译为 JS· 优点:纯前端· 缺点:已停止维护、Python 版本老Skulpt· 原理:JS 实现的 Python· 优点:轻量· 缺点:只支持子集、无第三方库Pyodide(最终选择)· 原理:CPython 编译为 WASM· 优点:完整 Python 3.14· 缺点:首次加载约 10MB远程容器· 原理:Docker 隔离执行· 优点:任意依赖· 缺点:成本极高、复杂 最终选择 Pyodide:完整 CPython 3.14;支持 numpy / pandas 等;Web Worker 不阻塞 UI;零服务器成本;可被 Service Worker 缓存
别盯着「最好的」技术,选「最合适的」。Pyodide 10MB 体积是缺点,但做编程学习工具的话,用户愿意等 3 秒加载完整 Python 运行时,后续代码执行全是零延迟。要是做落地页,10MB 就不行。
技术栈选型决策
# 每个技术选择的理由
print("""
框架:Next.js 16 (App Router)
→ SSR/SSG 提升首屏速度和 SEO
→ 文件路由,零配置
→ 静态导出,可部署到任何静态服务器
语言:TypeScript (strict)
→ 类型安全,重构有信心
→ 编辑器智能提示
→ 编译期捕获大量错误
样式:Tailwind CSS v4
→ 原子化类名,零运行时开销
→ 设计系统通过 CSS Variables 统一
→ 深色/浅色主题切换只需改变量
编辑器:Monaco Editor
→ VS Code 同款,用户熟悉
→ 语法高亮、自动补全、错误提示
状态管理:Zustand
→ 1KB 体积,API 极简
→ persist 中间件自动持久化
动画:Framer Motion
→ 声明式 API,手势支持
Python 运行:Pyodide v3.14 (Web Worker)
→ CPython 编译为 WASM
→ Worker 线程隔离,不卡 UI
""")项目目录结构设计
好的目录结构,新开发者10分钟内能看懂项目全貌。
# 朋友好学目录结构
print("""
pygood/
├── app/ # Next.js App Router 页面
│ ├── page.tsx # 首页(落地页)
│ ├── layout.tsx # 根布局(字体、Provider、主题)
│ ├── providers.tsx # 全局 Provider(React Query)
│ ├── globals.css # 全局样式 + CSS 变量 + 动画
│ ├── dashboard/page.tsx # 学习仪表盘
│ ├── course/[id]/ # 课程详情页(动态路由)
│ ├── lab/page.tsx # 代码实验室
│ └── profile/page.tsx # 个人中心
├── components/ # React 组件
│ ├── ui/ # 基础 UI(Button/Card/Badge...)
│ ├── editor/ # 代码编辑器、编程键盘
│ ├── course/ # 课程内容渲染、挑战面板
│ ├── layout/ # 导航栏、侧边栏
│ └── ai/ # AI 助手
├── lib/ # 核心逻辑(无 React 依赖)
│ ├── pyodide/executor.ts # Python 执行引擎
│ ├── judge/engine.ts # 自动判题引擎
│ └── utils/ # 工具函数、课程数据、等级系统
├── hooks/ # 自定义 React Hooks
├── store/ # Zustand 状态管理
├── types/ # TypeScript 类型定义
└── public/pyodide/ # Pyodide 运行时文件
""")lib/ 目录放纯逻辑代码(不依赖 React),components/ 放 UI 组件。这么分的好处:逻辑代码能在任何地方复用逻辑代码更容易测试职责清晰,改逻辑不会意外影响 UI。这就是关注点分离的体现。
朋友好学选 Pyodide 不选后端跑 Python,最关键的原因是什么?
朋友好学中用户的 Python 代码运行在哪种线程?
资深工程师加餐
底层原理 · 大厂视角 · 工程经验,点卡片展开
快速连续发起请求时,先发的慢响应可能晚到、反而覆盖了新结果,导致页面显示「过期数据」。标准解法是给每次请求一个递增序号,或用 AbortController 取消上一个请求,回调里只接受最新一次的结果。此外 loading、error、空数据这三种状态都要显式处理,别只写成功路径。
挑战任务
技术选型:按综合分挑方案
选型不是选单项最强,而是选综合最优。每个候选方案是 (名称, 综合分)。请实现 best_choice(candidates):返回综合分最高的方案名称(并列时取第一个)。