1. 先搞清楚“Demo开发”到底要解决什么问题
很多人一听到“Demo开发”,就觉得是随便写几行代码、做个界面展示一下功能。但实际落地时,你会发现,一个能跑通的Demo和一个能讲清楚、能复现、能作为后续开发基石的Demo,完全是两回事。前者可能只是你本地环境下的一个“玩具”,后者则是一个合格的工程起点。
我做了十多年开发,带过不少项目,也看过无数新人提交的Demo。最大的感受是:一个高质量的Demo,核心价值不在于功能有多炫,而在于它是否清晰地定义并解决了一个具体、可验证的问题,并且为他人(包括几天后的你自己)提供了一条清晰、无坑的复现路径。它应该像一份“产品说明书”和“施工图纸”的结合体。
所以,在动手写任何代码之前,先问自己三个问题:
- 这个Demo要演示的核心能力是什么?是某个算法效果?一个前后端交互流程?还是一个特定硬件(如Camera2)的调用方法?
- 它的目标用户是谁?是给技术评审看?给产品经理演示?还是给其他开发者作为接入参考?
- 成功的标准是什么?是界面能点开不出错?是数据能跑通整个流程?还是性能指标(如帧率、延迟)达到某个阈值?
比如,从你给的热词里能看到各种类型的Demo:
- 技术验证型:
camera2 + mediacodec 推流 demo,目标是验证在Android上用Camera2采集、MediaCodec编码并推流的完整链路是否可行。 - 框架学习型:
springboot vue 钉钉免登录demo,目标是展示如何用Spring Boot和Vue快速集成钉钉的OAuth2免登流程。 - 功能展示型:
java小项目demo,可能是一个完整的、麻雀虽小五脏俱全的迷你系统,如简易博客、商城。 - 问题排查型:
origin导出图有demo水印,这本身是个问题,但解决它的过程就可以做成一个Demo,展示如何正确配置或使用软件去除水印。
第一步永远不是打开IDE,而是用一两句话把你的Demo目标写清楚。例如:“本Demo将展示如何使用Android Camera2 API配合MediaCodec,实现摄像头画面的实时H.264硬编码,并通过TCP Socket模拟推流,在局域网内另一台设备上播放。” 这句话里包含了技术栈、输入(摄像头)、处理(编码)、输出(网络流)和验证方式(另一台设备播放)。
2. 环境与依赖:别让“在我机器上能跑”成为笑话
这是Demo翻车的重灾区。你兴冲冲地把代码打包发出去,别人却连环境都搭不起来。一个合格的Demo,必须把运行所需的一切条件说清楚,并且最好能一键搞定。
2.1 明确列出所有前置条件
不要只说“需要Java环境”。要具体到可验证的版本和组件。
| 条件类别 | 具体要求 | 验证命令/方法 |
|---|---|---|
| 操作系统 | Windows 10/11, macOS 12+, Ubuntu 20.04 LTS | winver/sw_vers/lsb_release -a |
| 运行时 | JDK 17 (推荐OpenJDK) | java -version |
| 构建工具 | Maven 3.8+ 或 Gradle 7.5+ | mvn -v/gradle -v |
| 核心依赖 | Spring Boot 3.1.5, Vue 3.3.x | 查看pom.xml或build.gradle |
| 数据库 | MySQL 8.0 (用于数据演示) | mysql --version |
| 其他服务 | Redis 7.0 (用于缓存演示) | redis-cli --version |
| 硬件/权限 | Android真机/模拟器(API 30+),摄像头权限 | 检查设备adb devices,应用权限设置 |
对于像海康威视官方 h5player demo或avalonia 官方demo这类涉及特定SDK或跨平台UI框架的,必须明确指出SDK的版本号、下载地址(如果非公开仓库),以及任何必要的授权文件(如license)的放置位置。
2.2 依赖管理的最佳实践
- 锁定版本:在
pom.xml或build.gradle中,对所有主要依赖使用固定版本号,避免因依赖自动升级导致的不兼容。 - 使用依赖管理工具:对于Java项目,Spring Boot的
spring-boot-dependencies或Maven的dependencyManagement能很好地统一版本。 - 提供离线包(可选但推荐):对于内部演示或网络环境受限的情况,可以将所有依赖(如Maven的
.m2/repository相关部分)打包,并附上一个简单的脚本,指导如何将其放入本地仓库。对于前端项目,可以提供node_modules的压缩包(注意体积)。 - 环境检查脚本:写一个简单的Shell或Batch脚本(
check_env.sh或check_env.bat),自动检查关键组件的版本并给出提示。这能极大提升体验。
#!/bin/bash # check_env.sh echo “Checking Java...” java -version 2>&1 | grep “version” || echo “Java not found!” echo “Checking Maven...” mvn -v 2>&1 | grep “Apache Maven” || echo “Maven not found!” # ... 其他检查2.3 处理特定环境问题
- Android Demo:除了JDK和Android SDK,必须说明
compileSdkVersion,targetSdkVersion,minSdkVersion。对于camera2 demo,务必在AndroidManifest.xml中声明摄像头权限,并处理Android 6.0以上的运行时权限申请逻辑。在代码中做好兼容性判断。 - 前端Demo:明确Node.js版本(如18.x),并说明是使用
npm,yarn还是pnpm。如果涉及跨域问题(如请求本地后端),要说明如何配置代理或后端CORS。 - 涉及硬件的Demo:如Camera2、海康SDK,必须在文档最前面用加粗字体说明必须在真机或特定模拟器上运行,并给出设备型号和系统版本的测试范围。
注意:永远不要假设别人的环境和你一样。把你第一次搭建环境时遇到的坑和解决步骤,简要地写在
README.md的“常见问题”部分。例如:“如果遇到Caused by: java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver,请检查MySQL Connector/J的依赖是否已正确引入。”
3. 从最小可行产品到完整演示:构建你的Demo骨架
Demo不是原型,它应该具备完整的“起承转合”。我习惯把它分成三个层次来构建:核心链路(MVP)->功能增强->演示包装。
3.1 第一步:打通核心链路(MVP)
忘掉花哨的UI和复杂的业务逻辑。用最短的代码,验证最核心的技术点是否可行。
以netty客户端demo为例,它的核心链路是什么?是建立连接、发送消息、接收响应、关闭连接。那么MVP就应该是:
- 一个能连接指定服务器IP和端口的Netty客户端引导类。
- 一个简单的字符串消息发送逻辑。
- 一个打印接收到的服务器响应的处理器。
- 一个用于测试的、能返回固定响应的简易Netty服务端(可以单独一个类,或者注明用
telnet模拟)。
// 极度简化的Netty客户端MVP示例 (仅表达思路) public class NettyClientMVP { public static void main(String[] args) throws Exception { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group).channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { ch.pipeline().addLast(new StringEncoder(), new StringDecoder(), new SimpleClientHandler()); } }); ChannelFuture f = b.connect(“127.0.0.1”, 8080).sync(); // 发送一条测试消息 f.channel().writeAndFlush(“Hello Netty Server!\n”); f.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } } // SimpleClientHandler 负责打印接收到的消息这个MVP可能没有重连、没有心跳、没有编解码,但它能跑通,能让你和看Demo的人第一时间确认:Netty基础环境是好的,连接是通的。
对于spring cloud alibaba 配置rocketmq 发送消息demo,MVP就是:启动一个Spring Boot应用,配置好RocketMQ的Producer,在某个Bean初始化或某个接口被调用时,向一个指定Topic发送一条消息,并在控制台确认发送成功。先别管消费、事务、顺序消息。
3.2 第二步:围绕核心点进行功能增强
MVP跑通后,再根据Demo的目标,有选择性地添加功能。
- 对于学习型Demo:可以增加注释,拆解步骤。比如在Netty Demo里,逐步添加编解码器、拆包粘包处理、心跳机制等,每个步骤一个分支或一个类,并附上说明。
- 对于集成型Demo:如
钉钉免登录demo,在OAuth2回调拿到code之后,逐步展示如何用code换token、如何用token获取用户信息、如何将用户信息与自己系统的账号体系绑定。每一步的请求和响应体结构都可以打印或记录到日志,方便调试。 - 对于性能展示型Demo:如
camera2 + mediacodec 推流,MVP是能推流。增强部分就是展示如何设置不同的预览尺寸、码率、帧率,并实时在界面上显示这些参数和当前的帧率、延迟数据。
这个阶段的关键是模块清晰。每个新增的功能点,最好能相对独立,通过配置或简单的代码切换就能开启或关闭。这样读者可以循序渐进地理解。
3.3 第三步:准备演示材料(包装)
Demo是给人看的,尤其是给非技术背景的决策者看时,直观的演示至关重要。
- 可交互的界面:即使后端是核心,一个极简的前端界面(如用Vue/React写个单页,或用Thymeleaf、Freemarker写个简单页面)也能极大提升演示效果。对于
java controller demo,至少提供一个HTML页面,能通过表单或按钮触发Controller的接口,并展示结果。 - 预设的数据与脚本:准备一个SQL脚本,一键创建表并插入演示数据。准备一个Postman集合或curl命令脚本,一键调用所有关键接口。对于
php微信支付v3 demo,提供测试商户号信息和预生成的订单数据,让用户能直接跑通支付回调流程。 - 清晰的日志输出:在关键节点(如连接建立、消息发送、支付回调、异常捕获)打印结构化的日志。不要用
e.printStackTrace(),用log.info(“成功连接到服务器: {}”, channel.remoteAddress())。让运行过程一目了然。 - 演示脚本/文档:写一个
DEMO_WALKTHROUGH.md,用编号步骤告诉用户:“第一步,启动数据库;第二步,导入数据;第三步,启动后端服务;第四步,访问 http://localhost:8080;第五步,点击‘发送消息’按钮...” 这比任何口头描述都管用。
4. 代码之外:决定Demo专业度的关键细节
代码能跑只是及格线。要让Demo显得专业、可靠,必须在这些细节上下功夫。
4.1 文档:README.md是门面
你的README.md应该包含以下部分,并且语言简洁:
- 标题与简介:一句话说清Demo是什么。
- 快速开始:这是最重要的部分!用代码块给出5步以内能跑起来的命令。
# 1. 克隆项目 git clone https://your-repo.git cd your-demo # 2. 导入SQL (如果需要) mysql -u root -p < docs/demo_schema.sql # 3. 修改配置 (数据库连接等) cp src/main/resources/application.properties.example src/main/resources/application.properties # 4. 启动 mvn spring-boot:run # 5. 访问 open http://localhost:8080 - 详细配置:列出所有需要修改的配置项及其含义。
- 项目结构:简要说明主要目录和文件的作用。
- 核心流程:用文字或时序图说明主要的数据流或交互流程。
- 常见问题:把你在开发过程中遇到的坑和解决方案列出来。
- API参考:如果是接口Demo,列出关键接口的URL、方法、请求/响应示例。
4.2 配置与外部化
- 不要硬编码:数据库密码、服务器地址、API密钥等,必须放在配置文件(如
application.properties、application.yml)或环境变量中。在代码仓库里提供一个配置模板(如application.properties.example),里面用占位符或假值。 - 使用Profile:利用Spring Boot的
spring.profiles.active,或者自己写简单的配置加载机制,来区分开发、测试、演示环境。 - 敏感信息处理:绝对不要在代码或配置文件中提交真实的密码、密钥。使用环境变量或配置中心。在Demo文档中明确说明如何设置这些变量。
4.3 错误处理与日志
- 友好的错误提示:捕获可能出现的异常(如网络超时、数据库连接失败、文件不存在),并转换为用户或开发者能看懂的信息。对于
php微信支付v3 demo,支付签名失败时,不仅要日志记录,最好能在页面上提示“签名验证失败,请检查商户密钥配置”。 - 分级日志:合理使用
DEBUG,INFO,WARN,ERROR级别。默认运行日志为INFO级别,展示关键步骤。DEBUG日志用于记录更详细的数据流转,方便排查。 - 日志输出到文件:配置
logback-spring.xml或log4j2.xml,让日志同时输出到控制台和文件,方便事后查看。
4.4 测试与验证
一个可验证的Demo才是有说服力的Demo。
- 单元测试:为核心工具类、服务类编写简单的单元测试(JUnit, TestNG)。这不仅能验证逻辑,也展示了你的代码质量。
- 集成测试:对于
spring cloud alibaba这类涉及多组件的Demo,可以写一个集成测试,启动一个迷你上下文,测试RocketMQ消息的发送和接收。 - 端到端验证点:在
README或演示脚本中,明确告诉用户:“成功运行后,你应该能在控制台看到‘服务启动成功’的日志”,“访问/hello接口应返回{‘status’: ‘ok’}”,“点击支付按钮后,日志中会出现‘支付回调成功’”。给出明确的成功信号。
4.5 打包与分发
- 可执行的JAR:对于Spring Boot项目,使用
mvn clean package生成一个可执行的-exec.jar文件。用户只需java -jar your-demo.jar即可运行,无需关心Tomcat。 - Docker化(高级选项):如果你熟悉Docker,提供一个
Dockerfile和docker-compose.yml。这能彻底解决环境问题,是当前最专业的Demo分发方式之一。在README里写上docker-compose up -d,体验极佳。 - 清晰的发布:在GitHub/GitLab上,使用Releases功能,为每个稳定的Demo版本打包源码和可执行文件,并附上更新说明。
5. 针对不同Demo类型的专项要点
结合你给的热词,这里是一些具体类型的Demo需要额外关注的点:
5.1 前端/客户端Demo (android 画中画demo,avalonia 官方demo)
- UI/UX就绪:即使功能简单,界面布局也要符合平台规范。Android画中画Demo,要处理好生命周期(进入画中画、恢复)、按钮点击事件。
- 权限与兼容性:在代码中检查系统版本是否支持画中画功能(
PictureInPictureParams.Builder),动态申请权限。对于Avalonia这类跨平台UI,要注明在Windows、macOS、Linux上分别的编译和运行方式。 - 状态保持:Demo应用切到后台再回来,数据状态不应丢失。
5.2 音视频/流媒体Demo (camera2 + mediacodec 推流 demo,海康威视官方 h5player demo)
- 资源管理是生命线:Camera、MediaCodec、MediaMuxer、Player实例,必须确保在
onPause、onDestroy或组件释放时被正确释放(release())。内存泄漏在这里是致命的。 - 线程安全:Camera回调、编码器输出、网络发送必须在不同的线程/Handler中处理,避免阻塞UI线程或相互死锁。
- 参数配置模板:提供几组经过测试的、合理的参数配置(如分辨率、码率、帧率、编码格式),让用户可以直接选用,而不是盲目调整。
- H5播放器Demo:重点展示如何引入SDK、初始化播放器、传入播放地址、处理播放事件(播放、暂停、错误)。并提供不同格式(HLS, FLV, RTMP)流地址的示例。
5.3 后端/微服务Demo (spring cloud alibaba 配置rocketmq 发送消息demo,java controller demo)
- 配置分离:将RocketMQ的NameServer地址、生产者组、Topic等配置在
application.yml中,并通过@ConfigurationProperties注入。 - 消息轨迹:在发送消息时,设置一个唯一的
Keys和Tags,并在消费端打印出来,方便追踪一条消息的完整生命周期。 - Controller设计规范:即使是Demo,也应遵循RESTful风格,使用恰当的HTTP方法和状态码。使用
@Valid进行参数校验,统一使用ResponseEntity或自定义Result类包装返回结果。
5.4 工具/软件集成Demo (origin导出图有demo水印,php微信支付v3 demo)
- 问题复现步骤:对于“去水印”这类问题解决型Demo,首先要能稳定复现问题(如Origin导出图片带水印的具体操作路径)。
- 解决方案的步骤化:一步步展示如何通过修改设置、使用脚本或调用某个隐藏功能来解决问题。每一步操作前后,提供截图对比。
- 支付类Demo的安全性提醒:在
php微信支付v3 demo中,必须用大字注明此为沙箱环境Demo,切勿使用正式商户号和密钥。所有签名、验签流程必须严格遵循官方文档,这是支付Demo的底线。
6. 演示与交付:让Demo自己说话
最后,当你需要向别人展示这个Demo时(比如demo路演怎么做),记住以下几点:
- 故事线:不要直接讲技术。用“我们遇到了一个XX问题 -> 为了解决它,我们尝试了A方案(有不足) -> 于是我们采用了B技术(即本Demo) -> 它是如何一步步解决的 -> 这是最终效果”这样的逻辑来串联演示。
- 流畅的演示:提前跑通所有流程,确保演示时不会出现编译错误、网络超时、空指针异常。准备好备份方案,比如录屏。
- 突出重点:在演示过程中,不断回到Demo的核心目标上。如果核心是性能,就多展示监控数据;如果核心是流程,就一步步点开界面操作。
- 准备Q&A:提前思考别人可能会问的问题:这个方案的瓶颈在哪里?如果数据量增大怎么办?和另一个方案比优势是什么?把这些问题的简要答案准备好。
开发一个Demo,从构思到交付,是一个微缩版的软件开发过程。它锻炼的不仅是编码能力,更是产品思维、工程化思维和沟通能力。一个好的Demo,是你技术能力最直观、最有力的名片。下次再启动一个Demo时,不妨先按上面的步骤过一遍,你会发现,最终产出的东西,其质量和可用性会远超你的预期。