码农戏码

新生代农民工的自我修养

0%

ReAct(Reasoning + Acting)是一种将推理和行动相结合的 Agent 范式。在这个范式中,Agent 会:

  1. 思考(Reasoning):分析当前情况,决定下一步该做什么
  2. 行动(Acting):执行工具调用或生成最终答案
  3. 观察(Observation):接收工具执行的结果
  4. 迭代:基于观察结果继续思考和行动,直到完成任务

这个循环使 Agent 能够:

  • 将复杂问题分解为多个步骤
  • 动态调整策略基于中间结果
  • 处理需要多次工具调用的任务
  • 在不确定的环境中做出决策

Spring AI Alibaba 中的ReactAgent 基于 Graph 运行时构建。Graph 由节点(steps)和边(connections)组成,定义了 Agent 如何处理信息。Agent 在这个 Graph 中移动,执行如下节点:

  • Model Node (模型节点):调用 LLM 进行推理和决策
  • Tool Node (工具节点):执行工具调用
  • Hook Nodes (钩子节点):在关键位置插入自定义逻辑

ReAct Agent 的工作方式其实挺像人类解决问题的过程。它不是一次性把整个流程都规划好,而是在有一个整体目标的前提下,走一步看一步。

具体来说,它会先观察当前的情况,然后思考下一步该做什么,接着执行这个动作,再观察结果,根据结果决定下一步。

这个过程会一直循环,直到任务完成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
函数 执行一个轮次(用户目标, 历史上下文):
// 1. 获取当前环境信息
当前环境信息 = 获取当前环境信息()

// 2. 构建提示词(替换占位符)
提示词模板 = "已知:\n当前历史上下文:${历史上下文}\n当前环境信息:${当前环境信息}\n用户目标:\"${用户目标}\"\n\n做出下一步的决策\n\n你必须最少使用一个工具来实现该决策"
完整提示词 = 替换占位符(提示词模板, {
历史上下文: 历史上下文,
当前环境信息: 当前环境信息,
用户目标: 用户目标
})

// 3. 调用 LLM 进行推理(思考过程隐藏,直接输出 toolcall)
工具调用结果 = 调用语言模型(完整提示词, 历史上下文)

// 4. 解析工具调用
工具名称 = 解析工具名称(工具调用结果)
工具参数 = 解析工具参数(工具调用结果)

// 5. 执行工具调用
观察结果 = 执行工具(工具名称, 工具参数)

// 6. 更新历史上下文
新历史上下文 = 追加到历史上下文(历史上下文, {
行动: 工具调用结果,
观察结果: 观察结果
})

// 7. 返回结果
返回 {
观察结果: 观察结果,
新历史上下文: 新历史上下文
}
结束函数

// 主循环
函数 执行ReAct流程(用户目标):
历史上下文 = 空
当前轮次 = 1
最大轮次 = 10

当 当前轮次 <= 最大轮次 且 未完成任务:
结果 = 执行一个轮次(用户目标, 历史上下文)
历史上下文 = 结果.新历史上下文

如果 判断任务已完成(结果.观察结果):
中断循环

当前轮次 = 当前轮次 + 1
结束循环

返回 历史上下文
结束函数

最近股友推荐了一种复盘选择思路,想着正好让AI来干干呗

选股三步骤:

1、找到个股资金流向排行,点10日排行

2、排除法,超大盘子的,落后产能过剩产能的如房地产,行业太传统如钢铁,亏损的这些先剔除,然后按顺序翻看300只左右的股票,在其中选。连续十日增仓的都是强势股,在里面选择涨幅小,趋势好,行业独特的股票

3、连续10只增仓,连续十日资金流入的都是强势股,太强的,涨幅比较大的,也排除掉

把整个流程折成四步:

第一步:
1 浏览器打开数据中心 https://data.eastmoney.com/zjlx/detail.html
2 找到 个股资金流,使用 10日排行
3 抓取排名前2只股票,获取股票列表数据

最终以表格方式写入文件保存,一行一支股票, 表头是:股票号码|股票名称|10日涨幅,输出的文件包含表头内容,写到文件 stock_basic_data.md

第二步:
根据第一步输出的文件 stock_basic_data.md,先复制到stock_final_list.md

格式根stock_basic_data.md一样,在表头上增加两列所属行业 和 总市值

补充每行股票的所属行业和总市值信息

每只股票提取行业信息和总市值从下面的两个网址中提取,不需要点击其链接以查看详细信息

股票行业信息来源于网址:
https://emweb.securities.eastmoney.com/pc_hsf10/pages/index.html?type=web&code=SH600111&color=b#/gsgk

总市值信息来源于:https://emweb.securities.eastmoney.com/pc_hsf10/pages/index.html?type=web&code=SH600111&color=b#/cpbd,从概况页面提取总市值数值

信息提取完成后就关闭这个标签页

把提取到的所属行业和总市值信息写到文件 stock_final_list.md

一行一支股票, 表头是:股票号码|股票名称|所属行业|10日涨幅|总市值,输出的文件包含表头内容

第三步:
根据第二步输出的文文件 stock_final_list.md

你是资深财经专业人士,根据stock_final_list.md,各大财经网站和淘股吧精华贴等数据,总结,A股市场,1.热度总览2.第一梯队极度火热3.第二梯队局部高热4.第三梯队事件驱动5.第四梯队相对冷静,并对以上分析分别给出关键词和数据表现情况,最后给出整体总结及策略建议。然后,继续列表总结2月27日的连板梯队和跌停情况,以及对应的板块和题材。最后根据前述总结的内容用费曼学习法 1.先说结论 2.相应论点核心内容(前有序号) 3.总结 4.启示及未来行动指南及风险提示 5.奥卡姆剃刀总结

总结解读内容,除了以markdown格式输出一份文件 market_heat_analysis_{yyyyMMdd}.md,

再分析一下 linked_external/market_heat_analysis_20260227.html 里面的内容, 参照里面的格式,生成以HTML格式可视化保存到文件 linked_external/market_heat_analysis_{yyyyMMdd}.html

第四步:
分析一下 linked_external/index.html 里面的内容,

根据里面的格式,增加加一下 第三步生成的 linked_external/market_heat_analysis_{yyyyMMdd}.html 的内容,并链接到market_heat_analysis_{yyyyMMdd}.html

最后生成一份复盘记录,从中挑选喜欢的股票

https://zhuxingsheng.com/market/market_heat_analysis_20260302.html

不过最近股市天天吃大面。还要烧token

一、 掌握核心“量命的尺子”(歌赋口诀)

这是学好命理最关键的一步,用以保证论断的统一性和准确性。

  • 必要性:歌赋是命理分析的“定义”和“公式”,如同数学的九九乘法表。没有这把“尺子”,分析同一个八字在不同阶段可能会得出不同结论,导致水平不稳定。

  • 精选内容:无需背诵大量长篇歌赋,只需精选5到6首精华、精品的歌赋即可。

  • 核心推荐

    1. 《九窍歌》:完整概括了论命的九个步骤,是总纲。

    2. 《财官赋》(或相关论财官的歌赋):是子平格局法的核心。

    3. 《四季歌》:关于五行在四季旺衰状态的基础法则。

  • 目标:将这些歌赋背熟、弄懂、会用,达到“条件反射”的程度,就能自己开悟,打下坚实基础。

二、 理清分析逻辑,把握时空关系

在实战中,必须能清晰区分事情发生的时间点。

  • 核心能力:将大运、流年与四柱(原局)的作用关系理清,判断事情是发生在过去、现在还是未来

    • 与过去发生关系:可能是陈年旧事或六亲之事。

    • 与当下发生关系:是眼下正在进行的事。

    • 与未来发生关系:是今年新出现的事。

    • 新旧勾连:例如“新旧犯三刑”,代表新事勾起旧事,问题一并爆发。

  • 避免错误:如果没有这个中心思想,容易把没有关系的干支强行解释为有关系,导致论断混乱。

三、 进行大量实践,做到理法结合

理论必须通过大量实战来印证和巩固。

  • 重要性:再好的理论,没有实践也无法真正掌握。命理是“台下十年功,台上五分钟”的学问。

  • 实践目的:通过大量案例,将歌赋理论融会贯通,锻炼从四柱、大运、流年中快速提取信息、理清脉络的能力。

四、 端正学习态度,认识体系深度

  • 认识学习周期:从零基础到真正掌握,通常需要三到五年的持续学习。这是一个体系庞大的学问,不能急于求成。

  • 抓住核心脉络:认清所有八字流派归根结底都源于 “虚中”(禄命法,重年柱)“子平”(格局法,重月令) 两大体系。学习时要将二者融合看待(年主先天大框架,月主后天个人成就)。

  • 不排斥必要元素:不要轻易否定神煞、胎元、命宫等传统要素的作用。它们是完整体系的一部分,能提高断事的精确度(所谓“不用神煞卦不灵”)。

五、 个人努力与天赋

  • 承认个人在学习能力、天赋和努力程度上存在差异。即使师出同门,水平也会有高有低。

  • 关键在于 “出于蓝而胜于蓝” 的自我追求和持续精进。

总结建议:

抓住“虚中”与“子平”两大核心脉络,精选并精通《九窍歌》、《财官赋》、《四季歌》等核心歌赋作为分析标尺,通过大量实战案例理清大运流年与命局的时空作用关系,并保持耐心,进行长达数年的系统学习和实践。 这是主讲人指出的高效学习路径。

之前一直在尝试开发一个Agent产品,配合公司垂直的专业软件。

简而总之一句话:借助AI能力,降本增效。现在谁不拥抱AI,谁就落后

使用spring-ai-alibaba的ReactAgent框架快速搭建了一个原型,通过chatbox的形式实现一个简单的场景

后来老板希望有深度思考能力,在chat的基础上再进一步,所以想研究一下manus,而阿里有个开源产品JManus:https://github.com/spring-ai-alibaba/jmanus

最近一直在尝试使用阿里开发的JManus产品

AI现在迭代相当快速,学习方式真不能像以前一样,慢慢挖原理,借助以前的学习经验尝试迁移,再实践试错。

像学习JManus,有了上一步ReactAgent基础,本打算看看源码,追加一些MCP或者Function Calling 来配合公司专业软件
但跟作者交流后,作者第一条就是不建议自己去实现tools

不过在使用中,也才慢慢体会JManus是个什么产品,所以现在AI时代,更加需要理论和实践结合,边做边学,做中学,学中做。

使用JManus的过程中,发现它的有些行为总不如意,所以还得多尝试下其他产品。试试OpenClaw

正好去年买了台云服务器,上手试一下,记录下部署过程。

直接执行官方一键安装脚本,无需手动配置依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
curl -fsSL https://openclaw.bot/install.sh | bash

🦞 OpenClaw Installer
Your task has been queued; your dignity has been deprecated.

✓ Detected: linux

Install plan
OS: linux
Install method: npm
Requested version: latest

[1/3] Preparing environment
· Node.js not found, installing it now
· Installing Node.js via NodeSource
· Installing Linux build tools (make/g++/cmake/python3)
✓ Build tools installed
✓ Node.js v22 installed
· Active Node.js: v22.22.0 (/usr/bin/node)
· Active npm: 10.9.4 (/usr/bin/npm)

[2/3] Installing OpenClaw
✓ Git already installed
· Installing OpenClaw v2026.3.2
! npm install failed for openclaw@latest
Command: env SHARP_IGNORE_GLOBAL_LIBVIPS=1 npm --loglevel error --silent --no-fund --no-audit install -g openclaw@latest
Installer log: /tmp/tmp.TXFT1VTDwD
! npm install failed; showing last log lines
! npm install failed; retrying

这失败应该是网速问题,换个国内镜像

1
2
3
# 先退出当前脚本(按 Ctrl+C)
# 设置淘宝 npm 镜像源
npm config set registry https://registry.npmmirror.com
1
2
# 手动尝试安装一次,看是否成功
npm install -g openclaw@latest --loglevel verbose

安装成功后,执行初始化命令,启动配置向导:

1
openclaw onboard --install-daemon

配置到模型时,注意一下,如果使用Qwen

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Model/auth provider
│ ○ OpenAI
│ ○ Anthropic
│ ○ Chutes
│ ○ vLLM
│ ○ MiniMax
│ ○ Moonshot AI (Kimi K2.5)
│ ○ Google
│ ○ xAI (Grok)
│ ○ Mistral AI
│ ○ Volcano Engine
│ ○ BytePlus
│ ○ OpenRouter
│ ○ Kilo Gateway
│ ● Qwen (OAuth)
│ ○ Z.AI
│ ○ Qianfan
│ ○ Copilot
│ ○ Vercel AI Gateway
│ ○ OpenCode Zen
│ ○ Xiaomi
│ ○ Synthetic
│ ○ Together AI
│ ○ Hugging Face
│ ○ Venice AI
│ ○ LiteLLM
│ ○ Cloudflare AI Gateway
│ ○ Custom Provider
│ ○ Skip for now

只有OAuth方式,使用API Key方式,选择Custom Provider

阿里云百炼平台为兼容 OpenAI 风格调用提供的接口地址。北京地域: https://dashscope.aliyuncs.com/compatible-mode/v1

最后启动成功

但访问时,碰到几个问题:

control ui requires device identity (use HTTPS or localhost secure context)

这个错误触及了 OpenClaw 安全机制的核心。它说明您正通过公网 IP 的 HTTP 协议访问,但浏览器的安全策略要求要么使用 HTTPS,要么访问 localhost,才能进行设备身份验证。

🔍 问题的根源

OpenClaw 使用 WebCrypto API 进行设备配对和身份验证,而浏览器强制要求 WebCrypto 必须在安全上下文中运行 :

  • 安全上下文:HTTPS 或 localhost
  • 非安全上下文:通过公网 IP 的 HTTP 访问

🛠️ 三种解决方案

方案1:快速测试(开发环境使用)
方案2:使用 SSH 隧道(推荐且安全)
方案3:配置 HTTPS(生产环境推荐)

📊 方案对比
方案 安全性 复杂度 适用场景
方案1(allowInsecureAuth) ⚠️ 低 ⭐ 简单 临时测试
方案2(SSH隧道) ✅✅ 高 ⭐⭐ 中等 个人远程使用
方案3A(Tailscale) ✅✅✅ 最高 ⭐ 简单 已有 Tailscale 的用户
方案3B(Caddy) ✅✅✅ 最高 ⭐⭐ 中等 生产环境,有域名

disconnected (1006): no reason

在上面HTTPS问题上,因为我本身有HTTPS域名,就配置了ngnix

但websocket方式配置有问题,所以报了这个错。

有不明白的,直接deepseek,不过这个ngnix配置,使用千问真准一些,上次部署JManus也碰到了这个问题

pairing required

1
2
3
4
5
6
pairing required
此设备需要网关主机的配对批准。
openclaw devices list
openclaw devices approve <requestId>
在手机上?从桌面运行 openclaw dashboard --no-open 复制完整 URL(包括 #token=...)。
Docs: Device pairing

这是最后一个障碍了!这是设备认证机制,说明 OpenClaw 的安全机制在工作!

到时都成功了,可以正常使用了

大功告成,先问个经典问题:

后面就得尝试使用,怎么提升效率。

一句话概括

RAG是一种将“信息检索”与“文本生成”相结合的人工智能框架。它让大语言模型(LLM)能够访问并引用外部知识库来生成更准确、更可信、且能追溯源头的回答。


核心思想:弥补LLM的固有缺陷

传统的LLM(如GPT-4、Llama等)虽然知识渊博,但存在几个关键问题:

  1. 知识可能过时:其训练数据有截止日期,无法获取最新信息。
  2. 存在“幻觉”:可能生成看似合理但实际错误或编造的内容。
  3. 无法溯源:用户无法验证其回答的依据来源。
  4. 涉及私有/专业数据时无能为力:LLM没有学习过公司内部文档、个人笔记等非公开数据。

RAG就是为了解决这些问题而生的。 它的核心思路是:当LLM需要回答一个问题时,不是让它凭空回忆,而是先帮它去“查资料”。


RAG的工作流程(两步走)

想象一个超级图书管理员(RAG系统)和一位才华横溢的作家(LLM)的合作:

第一步:检索(Retrieval)——“去资料室查书”

  1. 知识库准备:将外部的文档(如公司手册、产品文档、最新新闻、数据库、PDF等)进行切分、处理,并转换成向量形式,存储到专门的“向量数据库”中。
  2. 问题转换:当用户提出一个问题时,系统将这个问题也转换成向量
  3. 相似性搜索:系统在向量数据库中,快速查找与问题向量最相似的文本片段(即与问题最相关的资料)。
  4. 获取参考上下文:系统检索出最相关的几个文本片段,作为“参考依据”。

第二步:增强生成(Augmented Generation)——“参考资料写文章”

  1. 组合提示:系统将用户的原始问题和刚刚检索到的参考上下文,一起组合成一个新的、更丰富的“提示”,交给LLM。例如:

    “请根据以下信息回答问题:
    [此处插入检索到的相关文本片段]
    问题是:[用户的原始问题]”

  2. 生成答案:LLM基于这个包含了明确依据的提示来生成答案。由于答案被“限制”在提供的上下文中,因此它更可能准确、相关,并且能够直接引用来源。
  3. 返回答案与引用:最终,系统将生成的答案返回给用户,并可以附上所使用的文本片段的来源(如文档名称和页码),实现可追溯。

RAG的核心优势

  1. 准确性更高,减少幻觉:答案基于提供的真实文档,编造可能性大大降低。
  2. 信息可更新:要更新模型的知识,只需更新向量数据库中的文档即可,无需耗费巨资重新训练整个LLM。
  3. 可追溯与可信:可以提供答案的来源引用,让用户自行查证,建立信任。
  4. 成本效益高:相对于为特定领域从头训练一个大模型,搭建RAG系统的成本和门槛要低得多。
  5. 处理私有数据:可以轻松地将企业内部数据、个人数据作为知识库,构建专属的智能问答系统。

典型应用场景

  • 智能客服/客服机器人:基于最新的产品文档和FAQ,回答用户问题。
  • 企业知识库问答:员工可以快速查询公司内部的规章制度、项目报告、会议纪要等。
  • 学术与研究助手:基于大量论文和研究报告,提供总结和问答。
  • 个人AI助理:基于你的个人笔记、邮件、聊天记录,帮你回忆和查找信息。
  • 需要最新信息的场景:例如,基于最新的市场报告、新闻来生成分析总结。

RAG vs. 微调(Fine-Tuning)

两者都是让大模型适应特定任务的重要技术,但思路不同:

  • RAG:侧重于为模型提供外部知识。像给模型一本随时可以查阅的参考书。
  • 微调:侧重于调整模型内部的参数和权重,改变其“思维方式”或“写作风格”。像是对模型本身进行再训练。
  • 在实践中,RAG和微调经常结合使用,以达到最佳效果:用微调让模型更懂某个领域的“语言”,用RAG为其提供该领域的最新“资料”。

总结

RAG本质上是一个“即插即用”的知识扩展方案。它巧妙地将强大的检索系统与强大的生成模型结合在一起,让AI不仅会“说”,而且说得有据可查、与时俱进、精准可靠,是目前构建行业AI应用和解决LLM幻觉问题的首选架构之一。

服务通过 - Xmx=6G 指定最大堆分配为 6G,但实际 RSS 已达到 11G,开始怀疑堆外内存是否有内存泄露。

RSS从启动之后,就是一路增长,由于是测试机,业务量小,以53M/小时的增量增长。

JVM 的进程总内存 ≈

Java Heap + Metaspace + CodeCache + Thread Stack + JNI/Direct Buffer + GC 结构 + 内部 allocator fragment + C 库分配 + mmap 区域 + …

由于现象是RES比较高,先看一下java堆是否有异常。把java堆dump下来仔细排查一下,jmap -histo:live pid,发现整个堆回收完也才几百兆,远不到8G的Xmx的上限值,GC日志看着也没啥异常。基本排查java堆内存泄露的可能性。

1
jcmd 1 VM.native_memory detail scale=MB > nmt-`date +%F-%H-%M-%S`.log & pmap -x 1 > pmap-`date +%F-%H-%M-%S`.log

整体思路是:通过多次收集,进行比较,查看明显的差异

1
icdiff pmap-2023-07-27-09-46-36.log pmap-2023-07-28-09-29-55.log | less -SR

排查顺序

1️⃣ 先开 -XX:NativeMemoryTracking=detail

2️⃣ jcmd VM.native_memory summary 定位哪一类区域增长

3️⃣ 如果是 Internal / Arena Chunk → JNI / DirectBuffer 泄漏

4️⃣ 用 heaptrack / tcmalloc 进一步追踪分配源

5️⃣ 如果是 Thread 区域 → 检查线程数

6️⃣ 若都是正常,考虑 libc allocator fragment,可尝试使用 -XX:+UseG1GC-XX:MaxDirectMemorySize 或更换 allocator(jemalloc)

这一次排查,先通过NMT,发现Java能追踪到的内存区域一切正常

再通过pmap工具,发现了JNI调用C++有内存泄漏

C++修复后,内存增长大幅降低,但RSS依然会增长

最后,只能使用jemalloc替换原生的glibc来排查一下

替换后,内存还真的不再增长。

cat /etc/os-release

1
2
3
4
5
6
7
8
9
10
11
12
PRETTY_NAME="Ubuntu 22.04.4 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.4 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy

ldd –version

1
2
3
4
5
ldd (Ubuntu GLIBC 2.35-0ubuntu3.6) 2.35
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

RSS 持续增长的几种可能情况:

  1. 正常情况(常见):你的程序频繁地分配和释放大小不一的内存。这会导致堆内存出现“空洞”(外部碎片),即使有大量空闲内存,也因为不连续而无法从堆顶归还给 OS。RSS 会稳定在一个较高的水平,这是 ptmalloc2 的设计特点,目的是提高分配效率。
  2. 内存泄漏(需要警惕):你的程序持续分配内存,但忘记释放。这会导致堆不断增长,即使通过 brkmmap 向 OS 索要更多内存,RSS 会无限制地增长,直到被系统 OOM Killer 杀死。
  3. 峰值使用后的稳定期:程序在某个阶段需要大量内存,之后虽然释放了,但 glibc 没有立即归还给 OS(堆未收缩)。这部分内存成为了进程的“缓存”,如果程序后续再次需要分配内存,就可以快速重用,避免了系统调用的开销。
  • RSS 增长不一定是内存泄漏,很可能是 glibc 的内存池策略。
  • glibc 不会因系统内存紧张而主动释放内存,它的行为是预定义的。
  • 真正的回收保障来自 Linux 内核,当系统内存不足时,它会强制回收,可能包括将你的进程内存换出(Swap)。
  • 如果 RSS 增长是无界的、持续的,并且与你的业务逻辑预期不符,那么首先应该怀疑和排查内存泄漏

Reference

Jemalloc简介及使用方法

使用jemalloc解决JVM内存泄露问题

Java 进程内存占用及可观测性调研&内存异常排查最佳实践

《管好技术债》- 第13章 与技术债务共存

解决技术债务的通用路径

1、感知

确保所有相关人员都对什么是技术债务以及它如何影响项目有共同的认识

2、评估信息

了解项目的状态,你目前面临的债务,什么原因,以及它的后果是什么

3、建立一个登记表

建立某种形式的技术债务清单

4、决定要解决的问题

当你计划发布时,查看技术债务登记表,力求该发布可以减少技术债务并且可实际解决技术债务问题

5、采取行动

把技术债务的识别和管理纳入所有软件开发和业务治理实践中

重复这个过程,因为不太可能一下子完全摆脱技术债务。

如果你想要明确地管理组织中的技术债务,不要将债务处理作为一个单独的过程,将其集成到流程中,以补充当前的实践。

循序渐进,而不是大幅度地修改。第一步,选择能带来最直接利益的修改。

感知

给你的技术债务起个名字。确保所有参与项目或接近项目的人员对技术债务有共同的理解:什么是技术债务,什么不是技术债务,以及它如何影响项目。

提高感知能力的一些方法:

1、为项目提供一个清晰、简单的技术债务定义。

2、向团队讲解什么是技术债务及其产生的原因

3、直接在项目环境中给大家(管理人员、分析师和产品经理)讲解关于技术债务的知识

4、在问题跟踪系统中创建技术债务类别,使技术债务与缺陷或新功能有所区别

5、将已知的技术债务作为长期技术路线图的一部分

6、将感知活动扩展到作为项目一部分的任何外部供应商

使用能够帮助团队沟通的方法,帮助每个人在概念上都达成一致。

评估信息

在尝试补救技术责备之前,客观评估项目的状态。根据你在技术债务时间线上的位置,考虑以下行动:

1、确定评估技术债务的目标和标准

2、通过分析代码、架构和生产基础设施来监控你的产品,以了解导致团队经历种种症状的技术债务

3、纳入轻量检查 ,以持续监控技术债务

建立技术债务登记表

1、将你的问题跟踪工具中的“技术债务”分类细化为技术债务描述,并将其指向所涉及的特定软件工件:代码、架构或生产基础设施

2、至少包括最常见的两类技术债务:

2.1、简单的、本地化的、代码级的债务

2.2、广泛的、结构化的、架构债务,并指向所涉及的软件工件:代码、架构或生产基础设施

3、分析包含非故意的技术债务的代码和架构,并在技术债务登记表中描述结果

4、在你的迭代审查和回顾会中包括对技术债务的讨论,并对其加以特别的重视。将它作为一个待办事项参与优先排序

在收集信息以获得一些具体示例和评估用的数据时,可能需要做一些清点工作。

决定修复什么

如果你面对的是一个庞大的、有点繁杂的技术债务登记表,则需要确定修复什么以及什么时候修复。

应该根据你对情况的评估来做出决定,包括下一步软件产品的发展方向。要做出决定,需要收集有关补救策略、成本和权衡的其他信息。

审查技术债务登记表中的各项,确保其中包含适当的项目,并确定处理它们的优先顺序,从而决定下一步交付什么:

1、不仅要估计偿还技术债务的成本,还要估计不偿还技术债务项的成本:延迟偿还会在多大程度上减缓当前的进度?如果你无法提供实际成本,请使用“T恤尺码”策略

2、分配时间以偿还技术债务

3、制订一个与上下文相关的偿还计划。

采取行动

根据你的特定情况,并结合项目上下文来综合实施技术债务管理方法。这样做能更加积极主动地了解技术债务产生的原因,并控制新债务的引入 。

采取一些行动来识别和管理软件开发和业务治理实践中的技术债务

1、通过将一些技术债务项添加到迭代待办事项列表中,以保持技术债务处于较低水平,从而减少每个开发周期的技术债务。

2、将技术债务纳入有关延迟功能交付和降低作为短期或长期投资,并计划对其进行管理。

3、收集与技术债务相关的工作或成本的关键指标,以协助未来的决策。

从最简单的情况开始并迭代这些活动,在每次迭代中逐步改进流程。

《技术为径:带领公司走向卓越的工程师》–项目管理进阶

作为一个研发经理,你需要承担起为团队制订工作计划的责任。在你的上级管理层尝试制订整个季度,甚至整年的工作计划过程中,经常需要你来评估自己的团队是否能够承担某些项目,包括评估这些项目所需要的工作量,以及这些项目是否与你组员的技能相匹配。

虽然作为一个团队经理,你可以将一些项目管理工作下放给你的技术小组长来进行,但是肯定还需要自己承担一部分相关工作。

你所面临的主要任务是,决定哪些项目可以承担,而哪些项目需要推掉。同时,你可能还需要适应敏捷状态下需求的不断迭代,为每个项目预估一个大概的完成日期。

若要做好对团队工作的管理工作,你需要对团队的工作节奏十分熟悉。万幸的是,有一些窍门可以帮助你做到这一点。

敏捷与项目管理

项目管理并不意味着进入瀑布式管理模式,从一开始就将项目中的每一个细节都计划清楚。

然而,对于大部分团队来说,长期的、抽象的目标,以及短期的、具体的、面向长期抽象目标的工作计划是并存的。

当需要实际规划小的项目目标时,团队应该采用敏捷过程来快速评估项目并且分解项目目标,这样效率最高。

作为团队管理者,你不应该过多干预,甚至应该推动团队自主进行。你需要对更大范围的项目目标–那些需要数月,而不是数个星期才能完成的事情负起责任来。

预留20%的工程时间

预留20%的工程时间来处理研发可持续性工作。“研发可持续性工作”指的是添加测试用例、调试问题、重构老旧代码、更换编程语言和升级语言版本,以及其他类似的工程杂事等。

如果能够坚持这样做,你就能将一些中等大小的陈旧代码逐渐消化、转换掉。每个季度做一点就够。随时清理陈旧系统,可以降低其维护难度,从而给团队留出更多时间来进行新功能的开发。

就算不这样做,你也可以用这个时间来补偿项目过程中的意外情况。如果真的把项目研发计划填满100%,你很快会发现由于各种情况导致计划流产。监近交付时间时,管理有说“不”的义务。

设定截止日期在项目管理中是很常见的,有时这个截止日期是团队自我设定的,也有的时候是来自更高管理层的要求。

按照截止日期按时交付项目的唯一方法,就是在项目末期不停地裁剪末完成的项目需求。

这就意味着,作为研发经理,你必须和自己麾下的技术小组长与产品负责人/业务代表一起开会商讨到底哪些需求是必须交付的,而哪些需求是可以删减的。这意味着,作为研发经理,你经常需要对两边都说“不”。

说到底,你需要向技术团队交付一系列定义清晰、实现成本合理的产品需求,同时需要向产品团队解释清楚完成所有需求所需的额外时间。

更多的计划时间

软件开发时间预估中有一个“翻倍定律”:当需要测算软件开发时间时,永远将你预期的时间翻一倍。

不要每个需求都需要让技术团队预估实现时间

研发经理的时间预估与项目计划职责的的原因之一,是因为工程师针对每个需求都交付一个预估时间,不仅浪费其时间,而且徒增其压力。

管理层承担不确定性是责无旁贷的,管理都不应该将不确定性统统甩给团队成员来承担。

管理者不仅仅是技术团队和公司其他部门的传声筒。这样不仅不解决问题,反倒干扰正在实际做事的人。但是,你也不能只是团队的“挡箭牌”,而不管公司其他部门的实际需求。

你需要帮助公司建立一个针对新需求和用户反馈的持续沟通流程,减少意外情况和紧急需求的发生。

《技术为径:带领公司走向卓越的工程师》–管理项目

制定一份项目计划,需要搞清楚各部分之间的相互依赖关系。所有依赖关系都必须详加考虑,一个一个地反复讨论每个子任务的描述信息、时间安排、以及如何拆分。

领导能帮助我解决一些问题,但是更多的问题需要我自己去解决。

我一点都不喜欢这样的工作。这种体验给我留下了极为深刻的印象。我清晰地记得自己对任何一点疏忽的恐惧,对计划中的任何一点不确定性的反复斟酌。

而这一切都是为了制订一份能让领导看上的计划表。接下来我们又需要将这份计划表转化为可以展示给公司管理层的格式,说服他们接受这一计划。感觉自己简直要烦死了。但是,这也是我职业我生涯中最重要的学习经历。

现在都是敏捷开发,是不是不再需要项目管理了?

敏捷开发只是一种拆分工作的好方式,它让你将注意力集中在小型目标上,从而不停地持续交付这些目标。

但是,这不能取代项目管理。大型项目不可能在一个或两个冲刺周期内完成。你还需要向管理层预估项目的完成时间,同时附带对项目所需时间的解释信息。

另外,某些项目,比如基础设施项目、平台项目、系统设计项目,通常需要详细的系统设计,或者非常超前的项目计划。

在面对这样的项目时,存在大量的未知信息和刚性很强的时间节点,敏捷模式根本不适用。

随着职业生涯的不断进步,学会如何将超出个人能力的复杂项目进行拆分是不可或缺的。

对于一个时间周期很长、多人参加的项目进行项目管理,并不是每个人都会喜欢的工作。

这项工作过于烦琐,同时还有点可怕。我喜欢构建系统、交付功能,而不太喜欢每天思考一个细节模糊的系统如何进行拆分。

同时,我很怕自己在项目计划中某个疏忽导致项目最终失败。但是,如果我不亲自参与的话,项目也不会自己完成,而且有很大概率会浪费大家的更多时间。

项目管理不能事无巨细地进行,这一点很多组织都意识不到。

不要招专门的项目经理,因为他们往往会成为工程师推卸责任的“挡箭牌”,而非一起合作的的伙伴。专门的项目经理往往导致项目以瀑布流的方式进行,而非采用敏捷的方式推进。然而,一定程度的项目管理是不可避免的,技术小组长对技术性强的项目应该根据需要进行合理的项目计划。

于项目提前规划的意义并不在于你是否事先想到了每一个细节,对未来考虑得是否周全,或者项目进度是否完美推进。

其真正的意义在于,制订项目计划这个过程强迫工程师在动手实干之前,先对项目进行一些深度考量。

++制订项目计划的真正目标在于,推动工程师在合适的进行合理的预测,并制订针对意外的应对计划。++

至于这个计划到底有多么准确,并不一定真的那么重要。

我们提前确定了想要达成的目标,同时也提前识别出一些可能导致项目失败的问题,并且为此提前做了准备。

项目管理,让每个人认真地花时间去面对这些非技术性、无法提前预测的难题。这些困难的工作帮助每个人完成自己的复杂项目,并且帮助成长。让每个人都能带领更大的团队,更好地拆分任务,以构建更复杂的系统。

作为技术人员,我们往往假设管理层十分这解我们的所做所想。“有问题就看看代码吧”作为技术领域内沉浸多年的技术人员,我们很容易假设别人和我们一样对这些问题了如指掌。

但是,这是错误的。技术管理者竭尽全力地去招募精兵良将,是为了让这些人才来解决非常棘手的技术问题的。但是,这不意味着技术管理者全知全能。在我的职业生涯中,每次我们向一些非常资深的技术管理者耐心解释诸如“NoSQL是什么”这种问题时,他们都很由衷地感激我。

现在,我一点都不觉得向其他人(不论他们是资深经理,还是新人)介绍基础技术概念及相关技术的优势对比是浪费自己的时间。

如果以平等的方式与他们进行对话,他们就会慢慢地培养起对我的建议和决策能力的信任,而这终将有利于推动我想推动的变革。花时间向别人解释自己的想法是非常重要和值得的。

《技术为径:带领公司走向卓越的工程师》–如何管理一个项目

所谓项目管理,就是将一个复杂的最终目标分成一些小目标,同时将这些目标以最高效的方式进行排序,识别出其中可以并行开展的工作,以及这些工作前后的依赖关系。

同时,还应该试图找出那些可能导致项目延期或者彻底失败的高风险环节。

项目管理的过程,就是试图将不确定的部分更确定化、将不可知的问题变成可知问题的过程。

同时,我们也应该认识到在这个过程中犯错误和漏掉一些未知风险是不可避免的。

1、将工作进行拆分

拿一张表格,或者采用甘特图的形式,抑或采用你最习惯的其他形式,尝试将你的大目标(例如,重写应收账款系统)拆分成一些具体的小目标,继续迭代。这个过程不一定要完全由你自己来完成。

如果系统的某个方面你不是很了解,就让其他人来帮助你。

你将目标拆分到一定程度的时候,就要专注于这些任务的排序。哪些任务可以马上开始?

将其拆分成一个个具体的任务进行推进。

2、持续关注细节与未知部分

做好项目管理的秘诀就是,迎难而上,永不停止。

项目管理本身就是一项非常烦琐、累人的工作。所以不管这项工作有多烦人,有多无聊,有多痛苦,你都不要停止。

一个好的上级领导会和你一起完成这项工作,帮助你指出计划的不足之处,同时向你提出自己的看法。没有人喜欢制订项目计划,但是这是一个和上级领导共同工作的好机会,同时也是一个很好的学习过程。

一定要持续跟进项目中的未知之处,一直到无可追踪为止。

3、真正落实项目计划并时刻调整

之前的周密计划制订过程的价值所在,就是帮助你了解项目的真实进度,以及与达成最终目标的距离

在项目进展过程中,如果出现延期情况,一定要向所有人及时通报信息。

有计划在手,你就不再需要盲目地猜测项目进度,而是可以清晰地知道项目的哪些目标已经达成,而哪些目标还没有达成。

4、利用计划过程中获得的知识来管理需求变更

在按照原始需求进行任务拆分的过程中,你对项目有了更深刻的了解。如果中途发生了需求变更的情况,这些知识可以帮助你更好地应对。

如果某项变更大大增加了项目风险,或者需要大量的额外工作,你就可以与他人明确这项变更的成本。

如果正在做的项目有一个非常严格的截止日期,那么了解每项细分工作所需的时间可以让你更好地排列优先级,甚至是割舍某些工作,平衡项目的整体质量、进度与交付时间。

5、随着项目的推进不断完善细节信息

当项目快要进入尾声的时候,烦琐的工作又出现了。

这正是落实项目每一项小细节的阶段。还差哪些任务没做完?测试做完了吗?交付验证做了吗?

可以考虑进行一次复盘模拟,提前将项目发布时可能出现的各种问题场景都预演一遍。

这也就是在落实“足够好”这个标准线的时候,让团队内的每个人都了解这个标准线,并且要具体落实到自己负责的部分。

排队那些无关紧要的工作,让整个团队都专注在落实真正重要的细节问题上。

制订一份发布计划,再制订一份回滚计划。