init commit
@@ -0,0 +1,294 @@
|
||||
---
|
||||
title: 术语表
|
||||
tags: [术语表, 核心概念]
|
||||
last_updated: 2026-04-07
|
||||
---
|
||||
|
||||
# 术语表
|
||||
|
||||
本术语表汇总了 [[Harness-Engineering|Harness 工程]] 领域的核心概念,为知识库提供统一的术语枢纽。
|
||||
|
||||
## A
|
||||
|
||||
### Agent (智能体)
|
||||
**英文**:Agent
|
||||
**中文**:智能体
|
||||
**定义**:能够自主感知环境、做出决策并执行行动的 AI 系统。在编码场景中,智能体通常具备读取文件、执行程序、发起 HTTP 请求等工具调用能力。
|
||||
**相关概念**:[[Agent Teams|智能体团队]], [[Coding Agent|编码智能体]]
|
||||
|
||||
### Agent Teams (智能体团队)
|
||||
**英文**:Agent Teams
|
||||
**中文**:智能体团队
|
||||
**定义**:多个智能体通过角色分工、协作协议和差异化行为共同完成复杂任务的系统。需要模型原生支持角色锚定、对抗性推理和协议遵守。
|
||||
**相关概念**:[[MiniMax M2.7]], [[Multi-Agent Collaboration|多智能体协作]]
|
||||
|
||||
### Anthropic Harness Design (Anthropic Harness 设计)
|
||||
**英文**:Anthropic Harness Design
|
||||
**中文**:Anthropic Harness 设计
|
||||
**定义**:Anthropic 团队提出的多智能体架构,包含 Planner(规划者)、Generator(生成者)和 Evaluator(评估者)三种角色,通过生成-评估循环提升输出质量。
|
||||
**相关概念**:[[Generator-Evaluator Loop|生成-评估循环]], [[Context Reset|上下文重置]]
|
||||
|
||||
## B
|
||||
|
||||
### Build-Verify Loop (构建-验证循环)
|
||||
**英文**:Build-Verify Loop
|
||||
**中文**:构建-验证循环
|
||||
**定义**:智能体在完成任务过程中自主进行的迭代改进流程,包括规划发现、构建实现、验证测试和修复问题四个阶段。
|
||||
**相关概念**:[[Self-Verification|自我验证]], [[Reasoning Sandwich|推理三明治]]
|
||||
|
||||
## C
|
||||
|
||||
### Codex (Codex 模型)
|
||||
**英文**:Codex
|
||||
**中文**:Codex 模型
|
||||
**定义**:OpenAI 推出的专门用于代码生成的模型系列,在 Harness 工程中被用于从零生成完整产品代码库。
|
||||
**相关概念**:[[OpenAI Harness Engineering|OpenAI Harness 工程]]
|
||||
|
||||
### Coding Agent (编码智能体)
|
||||
**英文**:Coding Agent
|
||||
**中文**:编码智能体
|
||||
**定义**:专门用于软件工程任务的 AI 智能体,能够理解代码库、编写代码、运行测试和调试问题。
|
||||
**相关概念**:[[Harness|Harness]], [[Agent|智能体]]
|
||||
|
||||
### Context Engineering (上下文工程)
|
||||
**英文**:Context Engineering
|
||||
**中文**:上下文工程
|
||||
**定义**:Harness 工程的三大支柱之一,专注于确保智能体在正确的时间获得正确的信息,包括静态上下文和动态上下文。
|
||||
**相关概念**:[[Harness-Engineering|Harness 工程]], [[Context Reset|上下文重置]]
|
||||
|
||||
### Context Reset (上下文重置)
|
||||
**英文**:Context Reset
|
||||
**中文**:上下文重置
|
||||
**定义**:一种解决长任务中上下文窗口填充和"上下文焦虑"问题的技术,通过清空上下文窗口并使用结构化交接传递状态来实现。
|
||||
**相关概念**:[[Context Compaction|上下文压缩]], [[Context Anxiety|上下文焦虑]]
|
||||
|
||||
### Context Anxiety (上下文焦虑)
|
||||
**英文**:Context Anxiety
|
||||
**中文**:上下文焦虑
|
||||
**定义**:模型在接近其认为的上下文限制时提前结束工作的倾向,Claude Sonnet 4.5 表现出较强的这种行为。
|
||||
**相关概念**:[[Context Reset|上下文重置]], [[Context Window|上下文窗口]]
|
||||
|
||||
### Context Compaction (上下文压缩)
|
||||
**英文**:Context Compaction
|
||||
**中文**:上下文压缩
|
||||
**定义**:通过摘要方式保留对话连续性的技术,但无法为智能体提供干净的状态,上下文焦虑问题仍可能存在。
|
||||
**相关概念**:[[Context Reset|上下文重置]]
|
||||
|
||||
## D
|
||||
|
||||
### Doom Loop (末日循环)
|
||||
**英文**:Doom Loop
|
||||
**中文**:末日循环
|
||||
**定义**:智能体在陷入困境时对同一错误方法进行小幅变异的重复尝试现象,可能多达 10 次以上。
|
||||
**相关概念**:[[Loop Detection|循环检测]]
|
||||
|
||||
## E
|
||||
|
||||
### Entropy Management (熵管理)
|
||||
**英文**:Entropy Management
|
||||
**中文**:熵管理
|
||||
**定义**:Harness 工程的三大支柱之一,通过定期清理智能体来管理 AI 生成代码库中随时间积累的熵(文档漂移、命名约定分歧、死代码堆积等)。
|
||||
**相关概念**:[[Harness-Engineering|Harness 工程]], [[Garbage Collection|垃圾回收]]
|
||||
|
||||
### Evaluator (评估者)
|
||||
**英文**:Evaluator
|
||||
**中文**:评估者
|
||||
**定义**:Anthropic Harness 设计中的三种角色之一,负责评估 Generator 的输出质量,提供具体的反馈和评分。
|
||||
**相关概念**:[[Generator|生成者]], [[Planner|规划者]]
|
||||
|
||||
## F
|
||||
|
||||
### Feedforward (前馈控制)
|
||||
**英文**:Feedforward
|
||||
**中文**:前馈控制
|
||||
**定义**:预期智能体行为并在其行动前进行引导的控制方式,提高智能体第一次尝试就产生良好结果的概率。
|
||||
**相关概念**:[[Feedback|反馈控制]], [[Guide|引导]]
|
||||
|
||||
### Feedback (反馈控制)
|
||||
**英文**:Feedback
|
||||
**中文**:反馈控制
|
||||
**定义**:在智能体行动后进行观察并帮助其自我纠正的控制方式,特别是当产生针对 LLM 消费优化的信号时效果显著。
|
||||
**相关概念**:[[Feedforward|前馈控制]], [[Sensor|传感器]]
|
||||
|
||||
## G
|
||||
|
||||
### Garbage Collection (垃圾回收)
|
||||
**英文**:Garbage Collection
|
||||
**中文**:垃圾回收
|
||||
**定义**:OpenAI 团队采用的定期清理流程,通过"黄金原则"和后台 Codex 任务来扫描偏差、更新质量等级并发起针对性重构。
|
||||
**相关概念**:[[Entropy Management|熵管理]]
|
||||
|
||||
### Generator (生成者)
|
||||
**英文**:Generator
|
||||
**中文**:生成者
|
||||
**定义**:Anthropic Harness 设计中的三种角色之一,负责实际创建输出(如前端代码、应用功能等)。
|
||||
**相关概念**:[[Evaluator|评估者]], [[Planner|规划者]]
|
||||
|
||||
### Generator-Evaluator Loop (生成-评估循环)
|
||||
**英文**:Generator-Evaluator Loop
|
||||
**中文**:生成-评估循环
|
||||
**定义**:受 GAN 启发的多智能体结构,Generator 生成输出,Evaluator 评估并提供反馈,Generator 根据反馈进行迭代改进。
|
||||
**相关概念**:[[Anthropic-Harness-Design|Anthropic Harness 设计]]
|
||||
|
||||
### Glossary (术语表)
|
||||
**英文**:Glossary
|
||||
**中文**:术语表
|
||||
**定义**:WikiLLM 知识库的核心枢纽文档,统一术语翻译、提供中英对照,并通过 wikilinks 连接所有相关概念。
|
||||
**相关概念**:[[Wikilink|Wikilink]], [[WikiLLM]]
|
||||
|
||||
## H
|
||||
|
||||
### Harness (Harness)
|
||||
**英文**:Harness
|
||||
**中文**:Harness
|
||||
**定义**:AI 智能体之外的一切,包括系统提示、工具选择、执行流程、约束条件、反馈循环等。公式:Agent = Model + Harness。
|
||||
**相关概念**:[[Harness-Engineering|Harness 工程]], [[Agent|智能体]]
|
||||
|
||||
### Harness Engineering (Harness 工程)
|
||||
**英文**:Harness Engineering
|
||||
**中文**:Harness 工程
|
||||
**定义**:设计和实现使 AI 智能体可靠工作的系统的新学科,包括约束智能体行为、告知智能体应该做什么、验证智能体正确执行、纠正智能体错误四个方面。
|
||||
**相关概念**:[[Context-Engineering|上下文工程]], [[Architectural-Constraints|架构约束]], [[Entropy Management|熵管理]]
|
||||
|
||||
### Harness Template (Harness 模板)
|
||||
**英文**:Harness Template
|
||||
**中文**:Harness 模板
|
||||
**定义**:为常见服务拓扑(如数据仪表板、CRUD 业务服务、事件处理器)准备的引导和传感器捆绑包,可实例化用于特定项目。
|
||||
**相关概念**:[[Harness-Engineering|Harness 工程]]
|
||||
|
||||
## L
|
||||
|
||||
### LangChain Harness Engineering (LangChain Harness 工程)
|
||||
**英文**:LangChain Harness Engineering
|
||||
**中文**:LangChain Harness 工程
|
||||
**定义**:LangChain 团队通过仅改变 Harness 将编码智能体在 Terminal Bench 2.0 上的表现从 52.8% 提升到 66.5%(Top 30 到 Top 5)的实践。
|
||||
**相关概念**:[[Harness-Engineering|Harness 工程]], [[Self-Verification|自我验证]]
|
||||
|
||||
### Layered Domain Architecture (分层领域架构)
|
||||
**英文**:Layered Domain Architecture
|
||||
**中文**:分层领域架构
|
||||
**定义**:OpenAI 采用的严格架构模型,每个业务领域划分为固定的层组(Types → Config → Repo → Service → Runtime → UI),依赖方向经过严格验证。
|
||||
**相关概念**:[[Architectural-Constraints|架构约束]]
|
||||
|
||||
### Loop Detection (循环检测)
|
||||
**英文**:Loop Detection
|
||||
**中文**:循环检测
|
||||
**定义**:LangChain 采用的中间件,通过钩子跟踪每个文件的编辑次数,在对同一文件进行 N 次编辑后添加"考虑重新考虑你的方法"的上下文。
|
||||
**相关概念**:[[Doom Loop|末日循环]], [[Middleware|中间件]]
|
||||
|
||||
## M
|
||||
|
||||
### Middleware (中间件)
|
||||
**英文**:Middleware
|
||||
**中文**:中间件
|
||||
**定义**:LangChain 结构化 Harness 的方式,通过可组合的中间件层在不修改核心智能体逻辑的情况下添加特定功能。
|
||||
**相关概念**:[[LangChain Harness Engineering|LangChain Harness 工程]]
|
||||
|
||||
### MiniMax M2.7 (MiniMax M2.7 模型)
|
||||
**英文**:MiniMax M2.7
|
||||
**中文**:MiniMax M2.7 模型
|
||||
**定义**:MiniMax 推出的深度参与自我进化的模型,能够构建复杂智能体 Harness、完成高度复杂的生产力任务,包括 Agent Teams、复杂 Skills 和动态工具搜索。
|
||||
**相关概念**:[[Agent Teams|智能体团队]], [[Self-Evolution|自我进化]]
|
||||
|
||||
### Mitchellh AI Adoption Journey (Mitchellh AI 采用之旅)
|
||||
**英文**:Mitchellh AI Adoption Journey
|
||||
**中文**:Mitchellh AI 采用之旅
|
||||
**定义**:HashiCorp 创始人 Mitchell Hashimoto 分享的个人 AI 工具采用历程,包括从聊天机器人到始终运行智能体的六个阶段。
|
||||
**相关概念**:[[Harness-Engineering|Harness 工程]]
|
||||
|
||||
## N
|
||||
|
||||
### NxCode Harness Engineering (NxCode Harness 工程)
|
||||
**英文**:NxCode Harness Engineering
|
||||
**中文**:NxCode Harness 工程
|
||||
**定义**:NxCode 团队提供的 Harness 工程完整指南,总结了三大支柱、实践框架和常见错误。
|
||||
**相关概念**:[[Harness-Engineering|Harness 工程]]
|
||||
|
||||
## O
|
||||
|
||||
### OpenAI Harness Engineering (OpenAI Harness 工程)
|
||||
**英文**:OpenAI Harness Engineering
|
||||
**中文**:OpenAI Harness 工程
|
||||
**定义**:OpenAI 团队在 5 个月内构建了超过 100 万行代码的产品,其中零行代码由人工编写,证明了 Harness 工程在生产规模上的有效性。
|
||||
**相关概念**:[[Harness-Engineering|Harness 工程]], [[Codex|Codex 模型]]
|
||||
|
||||
### Observability Stack (可观测性堆栈)
|
||||
**英文**:Observability Stack
|
||||
**中文**:可观测性堆栈
|
||||
**定义**:OpenAI 为 Codex 提供的日志、指标和追踪记录展示系统,使智能体能够直接访问应用程序的运行状态。
|
||||
**相关概念**:[[Context-Engineering|上下文工程]]
|
||||
|
||||
## P
|
||||
|
||||
### Planner (规划者)
|
||||
**英文**:Planner
|
||||
**中文**:规划者
|
||||
**定义**:Anthropic Harness 设计中的三种角色之一,负责将简单的 1-4 句话提示扩展为完整的产品规格。
|
||||
**相关概念**:[[Generator|生成者]], [[Evaluator|评估者]]
|
||||
|
||||
## R
|
||||
|
||||
### Reasoning Sandwich (推理三明治)
|
||||
**英文**:Reasoning Sandwich
|
||||
**中文**:推理三明治
|
||||
**定义**:LangChain 采用的推理预算分配策略,在规划和验证阶段使用高推理预算,在实现阶段使用中等推理预算。
|
||||
**相关概念**:[[Build-Verify Loop|构建-验证循环]]
|
||||
|
||||
### Ralph Wiggum Loop (Ralph Wiggum 循环)
|
||||
**英文**:Ralph Wiggum Loop
|
||||
**中文**:Ralph Wiggum 循环
|
||||
**定义**:使用钩子在智能体退出时强制其继续执行的循环模式,用于验证环节。
|
||||
**相关概念**:[[Self-Verification|自我验证]]
|
||||
|
||||
## S
|
||||
|
||||
### Self-Verification (自我验证)
|
||||
**英文**:Self-Verification
|
||||
**中文**:自我验证
|
||||
**定义**:智能体通过运行测试、阅读完整输出并与原始要求进行比较来自我改进的能力。
|
||||
**相关概念**:[[Build-Verify Loop|构建-验证循环]]
|
||||
|
||||
### Self-Evolution (自我进化)
|
||||
**英文**:Self-Evolution
|
||||
**中文**:自我进化
|
||||
**定义**:模型深度参与自身进化的过程,包括更新自身记忆、构建复杂技能、根据实验结果改进学习过程和 Harness。
|
||||
**相关概念**:[[MiniMax M2.7|MiniMax M2.7 模型]]
|
||||
|
||||
### Sensor (传感器)
|
||||
**英文**:Sensor
|
||||
**中文**:传感器
|
||||
**定义**:观察智能体行动后结果并帮助其自我纠正的反馈控制,包括计算型和推理型两种类型。
|
||||
**相关概念**:[[Feedback|反馈控制]]
|
||||
|
||||
### Sprint Contract (冲刺契约)
|
||||
**英文**:Sprint Contract
|
||||
**中文**:冲刺契约
|
||||
**定义**:在每个冲刺前,Generator 和 Evaluator 协商达成的协议,定义该阶段工作的"完成"标准。
|
||||
**相关概念**:[[Anthropic-Harness-Design|Anthropic Harness 设计]]
|
||||
|
||||
## T
|
||||
|
||||
### Terminal Bench (终端基准测试)
|
||||
**英文**:Terminal Bench
|
||||
**中文**:终端基准测试
|
||||
**定义**:评估智能体编码能力的标准基准测试,包含机器学习、调试、生物学等多个领域的任务。
|
||||
**相关概念**:[[LangChain Harness Engineering|LangChain Harness 工程]]
|
||||
|
||||
## W
|
||||
|
||||
### Wikilink (Wikilink)
|
||||
**英文**:Wikilink
|
||||
**中文**:Wikilink
|
||||
**定义**:使用 `[[文档标题]]` 格式的内部链接,在 Obsidian 等工具中支持双向链接和图谱视图。
|
||||
**相关概念**:[[Backlink|反向链接]], [[Glossary|术语表]]
|
||||
|
||||
### WikiLLM (WikiLLM)
|
||||
**英文**:WikiLLM
|
||||
**中文**:WikiLLM
|
||||
**定义**:本项目的名称,一个利用 LLM 构建个人知识库的系统,通过"编译"原始数据生成结构化、交叉链接的高质量中文 Wiki。
|
||||
**相关概念**:[[Glossary|术语表]], [[INDEX]]
|
||||
|
||||
---
|
||||
|
||||
*最后更新:2026-04-07*
|
||||
*本文档由 [[WikiLLM]] 自动生成*
|
||||
@@ -0,0 +1,84 @@
|
||||
---
|
||||
title: WikiLLM 知识库首页
|
||||
tags: [首页, 索引, 导航]
|
||||
last_updated: 2026-04-07
|
||||
---
|
||||
|
||||
# WikiLLM 知识库
|
||||
|
||||
欢迎来到 **WikiLLM**——一个关于 [[Harness-Engineering|Harness 工程]] 的中文知识库。本 wiki 基于多篇权威来源编译而成,旨在为 AI 智能体时代的软件工程提供系统化的指南。
|
||||
|
||||
> **Harness 工程**是设计和实现使 AI 智能体可靠工作的系统的新学科。如果说 2025 年是 AI 智能体验证它们能够编写代码的一年,那么 2026 年就是我们认识到**智能体不是难点——Harness 才是**的一年。
|
||||
|
||||
---
|
||||
|
||||
## 📚 核心概念
|
||||
|
||||
- [[Harness-Engineering|Harness 工程]] - Harness 工程的完整概述,包括三大支柱、为什么现在重要、以及实践中的方法
|
||||
- [[Context-Engineering|上下文工程]] - 如何确保智能体在正确的时间获得正确的信息
|
||||
- [[Architectural-Constraints|架构约束]] - 如何机械地强制执行好代码的样子,而不是仅仅告诉智能体"写好代码"
|
||||
- [[Anthropic-Harness-Design|Anthropic Harness 设计]] - Anthropic 的三智能体架构:Planner、Generator、Evaluator
|
||||
- [[Self-Verification|自我验证]] - 让智能体通过构建-验证循环自我改进的技术
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ 实践指南
|
||||
|
||||
- [[Mitchellh-Adoption-Journey|Mitchellh AI 采用之旅]] - HashiCorp 创始人从怀疑论者到深度用户的六个阶段
|
||||
- [[Building-Your-First-Harness|构建你的第一个 Harness]] - 从个人开发者到工程组织的三级实用框架
|
||||
|
||||
---
|
||||
|
||||
## 📖 学习路径
|
||||
|
||||
### 初学者路径
|
||||
|
||||
1. 首先阅读 [[Harness-Engineering|Harness 工程]] 获得概览
|
||||
2. 然后阅读 [[Mitchellh-Adoption-Journey|Mitchellh AI 采用之旅]] 了解个人采用路径
|
||||
3. 最后阅读 [[Building-Your-First-Harness|构建你的第一个 Harness]] 开始实践
|
||||
|
||||
### 深入学习路径
|
||||
|
||||
1. 从 [[Anthropic-Harness-Design|Anthropic Harness 设计]] 开始了解前沿架构
|
||||
2. 深入研究 [[Context-Engineering|上下文工程]] 和 [[Architectural-Constraints|架构约束]]
|
||||
3. 学习 [[Self-Verification|自我验证]] 技术让智能体自我改进
|
||||
|
||||
---
|
||||
|
||||
## 🔗 快速导航
|
||||
|
||||
- [[Glossary|术语表]] - 40+ 核心概念的中英对照和解释
|
||||
- [概念目录](./concepts/) - 所有核心概念文章
|
||||
- [实践目录](./practices/) - 所有实践指南文章
|
||||
|
||||
---
|
||||
|
||||
## 📊 编译来源
|
||||
|
||||
本知识库基于以下权威来源编译:
|
||||
|
||||
1. **OpenAI** - Harness Engineering:在智能体优先的世界中利用 Codex
|
||||
2. **Anthropic** - Harness design for long-running application development
|
||||
3. **Martin Fowler** - Harness engineering for coding agent users
|
||||
4. **LangChain** - Improving Deep Agents with harness engineering
|
||||
5. **NxCode** - Harness Engineering: The Complete Guide
|
||||
6. **MiniMax** - MiniMax M2.7: Early Echoes of Self-Evolution
|
||||
7. **Mitchell Hashimoto** - My AI Adoption Journey
|
||||
|
||||
---
|
||||
|
||||
## 💡 关于 WikiLLM
|
||||
|
||||
WikiLLM 是一个利用 LLM 构建个人知识库的系统。本项目的核心原则是:
|
||||
|
||||
- **LLM 编写和维护所有 wiki 数据**;手动编辑很少见
|
||||
- **用户探索和查询被归档回 wiki** 以增强它
|
||||
- **系统专注于 markdown 文件和 Obsidian 兼容格式**
|
||||
- **图像被下载到本地** 以便 LLM 轻松引用
|
||||
|
||||
查看 [[Glossary|术语表]] 了解更多核心概念,或从 [[Harness-Engineering|Harness 工程]] 开始阅读!
|
||||
|
||||
---
|
||||
|
||||
*最后更新:2026-04-07*
|
||||
*本文档由 [[WikiLLM]] 自动生成*
|
||||
|
After Width: | Height: | Size: 284 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 177 KiB |
|
After Width: | Height: | Size: 7.1 MiB |
|
After Width: | Height: | Size: 136 KiB |
@@ -0,0 +1,280 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta content = 'uft-8' name = 'charset'></meta>
|
||||
|
||||
<title>not found</title>
|
||||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /><script defer src="https://cloud.umami.is/script.js" data-website-id="eb12527f-b713-4afa-905a-8a50f8a7f157"></script>
|
||||
<link href = '/global.css' rel = 'stylesheet' type = 'text/css'></link>
|
||||
</head>
|
||||
|
||||
<body><header id = 'banner' style = 'background-image: url("/banner.png"); background-repeat: no-repeat'>
|
||||
|
||||
<div class = 'name-logo'><a href = 'https://martinfowler.com'><img src = '/mf-name-white.png'></img></a></div>
|
||||
<div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'menu-button navmenu-button'><a class = 'icon icon-bars' href = '#navmenu-bottom'></a></div>
|
||||
|
||||
<nav class = 'top-menu'>
|
||||
<ul>
|
||||
<li><a class = '' href = 'https://refactoring.com'>Refactoring</a></li>
|
||||
|
||||
<li><a class = '' href = '/agile.html'>Agile</a></li>
|
||||
|
||||
<li><a class = '' href = '/architecture'>Architecture</a></li>
|
||||
|
||||
<li><a class = '' href = '/aboutMe.html'>About</a></li>
|
||||
|
||||
<li><a class = 'tw' href = 'https://www.thoughtworks.com/engineering'>Thoughtworks</a></li>
|
||||
|
||||
<li><a class = 'icon icon-rss' href = '/feed.atom' title = 'feed'></a></li>
|
||||
|
||||
<li><a class = 'icon icon-twitter' href = 'https://www.twitter.com/martinfowler' title = 'Twitter stream'></a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://toot.thoughtworks.com/@mfowler' title = 'Mastodon stream'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M21.2595 13.9898C20.9852 15.4006 18.8033 16.9446 16.2974 17.2439C14.9907 17.3998 13.7041 17.5431 12.3321 17.4802C10.0885 17.3774 8.31809 16.9446 8.31809 16.9446C8.31809 17.163 8.33156 17.371 8.3585 17.5655C8.65019 19.7797 10.5541 19.9124 12.3576 19.9742C14.1779 20.0365 15.7987 19.5254 15.7987 19.5254L15.8735 21.1711C15.8735 21.1711 14.6003 21.8548 12.3321 21.9805C11.0814 22.0493 9.52849 21.9491 7.71973 21.4703C3.79684 20.432 3.12219 16.2504 3.01896 12.0074C2.98749 10.7477 3.00689 9.55981 3.00689 8.56632C3.00689 4.22771 5.84955 2.95599 5.84955 2.95599C7.2829 2.29772 9.74238 2.0209 12.2993 2H12.3621C14.919 2.0209 17.3801 2.29772 18.8133 2.95599C18.8133 2.95599 21.6559 4.22771 21.6559 8.56632C21.6559 8.56632 21.6916 11.7674 21.2595 13.9898ZM18.3029 8.9029C18.3029 7.82924 18.0295 6.97604 17.4805 6.34482C16.9142 5.71359 16.1726 5.39001 15.2522 5.39001C14.187 5.39001 13.3805 5.79937 12.8473 6.61819L12.3288 7.48723L11.8104 6.61819C11.2771 5.79937 10.4706 5.39001 9.40554 5.39001C8.485 5.39001 7.74344 5.71359 7.17719 6.34482C6.62807 6.97604 6.3547 7.82924 6.3547 8.9029V14.1562H8.43597V9.05731C8.43597 7.98246 8.88822 7.4369 9.79281 7.4369C10.793 7.4369 11.2944 8.08408 11.2944 9.36376V12.1547H13.3634V9.36376C13.3634 8.08408 13.8646 7.4369 14.8648 7.4369C15.7694 7.4369 16.2216 7.98246 16.2216 9.05731V14.1562H18.3029V8.9029Z"></path></svg>
|
||||
</a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://www.linkedin.com/in/martin-fowler-com/' title = 'LinkedIn'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M4.00098 3H20.001C20.5533 3 21.001 3.44772 21.001 4V20C21.001 20.5523 20.5533 21 20.001 21H4.00098C3.44869 21 3.00098 20.5523 3.00098 20V4C3.00098 3.44772 3.44869 3 4.00098 3ZM5.00098 5V19H19.001V5H5.00098ZM7.50098 9C6.67255 9 6.00098 8.32843 6.00098 7.5C6.00098 6.67157 6.67255 6 7.50098 6C8.3294 6 9.00098 6.67157 9.00098 7.5C9.00098 8.32843 8.3294 9 7.50098 9ZM6.50098 10H8.50098V17.5H6.50098V10ZM12.001 10.4295C12.5854 9.86534 13.2665 9.5 14.001 9.5C16.072 9.5 17.501 11.1789 17.501 13.25V17.5H15.501V13.25C15.501 12.2835 14.7175 11.5 13.751 11.5C12.7845 11.5 12.001 12.2835 12.001 13.25V17.5H10.001V10H12.001V10.4295Z"></path></svg>
|
||||
</a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://bsky.app/profile/martinfowler.com' title = 'BlueSky'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 11.3884C11.0942 9.62673 8.62833 6.34423 6.335 4.7259C4.13833 3.17506 3.30083 3.4434 2.75167 3.69256C2.11583 3.9784 2 4.95506 2 5.52839C2 6.10339 2.315 10.2367 2.52 10.9276C3.19917 13.2076 5.61417 13.9776 7.83917 13.7309C4.57917 14.2142 1.68333 15.4017 5.48083 19.6292C9.65833 23.9542 11.2058 18.7017 12 16.0392C12.7942 18.7017 13.7083 23.7651 18.4442 19.6292C22 16.0392 19.4208 14.2142 16.1608 13.7309C18.3858 13.9784 20.8008 13.2076 21.48 10.9276C21.685 10.2376 22 6.10256 22 5.52923C22 4.95423 21.8842 3.97839 21.2483 3.6909C20.6992 3.44256 19.8617 3.17423 17.665 4.72423C15.3717 6.34506 12.9058 9.62756 12 11.3884Z"></path></svg></a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<nav id = 'top-navmenu'>
|
||||
<nav class = 'navmenu'>
|
||||
<div class = 'nav-head'> <div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'closediv'>
|
||||
<span class = 'close' title = 'close'></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class = 'nav-body'>
|
||||
<div class = 'topics'>
|
||||
<h2>Topics</h2>
|
||||
|
||||
<p><a href = '/architecture'>Architecture</a></p>
|
||||
|
||||
<p><a href = 'https://refactoring.com'>Refactoring</a></p>
|
||||
|
||||
<p><a href = '/agile.html'>Agile</a></p>
|
||||
|
||||
<p><a href = '/delivery.html'>Delivery</a></p>
|
||||
|
||||
<p><a href = '/microservices'>Microservices</a></p>
|
||||
|
||||
<p><a href = '/data'>Data</a></p>
|
||||
|
||||
<p><a href = '/testing'>Testing</a></p>
|
||||
|
||||
<p><a href = '/dsl.html'>DSL</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'about'>
|
||||
<h2>about me</h2>
|
||||
|
||||
<p><a href = '/aboutMe.html'>About</a></p>
|
||||
|
||||
<p><a href = '/books'>Books</a></p>
|
||||
|
||||
<p><a href = '/faq.html'>FAQ</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'content'>
|
||||
<h2>content</h2>
|
||||
|
||||
<p><a href = '/videos.html'>Videos</a></p>
|
||||
|
||||
<p><a href = '/tags'>Content Index</a></p>
|
||||
|
||||
<p><a href = '/boardgames'>Board Games</a></p>
|
||||
|
||||
<p><a href = '/photos'>Photography</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'tw'>
|
||||
<h2>Thoughtworks</h2>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com'>Home</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/insights'>Insights</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/careers'>Careers</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/radar'>Radar</a></p>
|
||||
|
||||
<p><a href = 'https://www.thoughtworks.com/engineering'>Engineering</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'feeds'>
|
||||
<h2>follow</h2>
|
||||
|
||||
<p><a href = '/feed.atom'>RSS</a></p>
|
||||
|
||||
<p><a href = 'https://toot.thoughtworks.com/@mfowler'>Mastodon</a></p>
|
||||
|
||||
<p><a href = 'https://www.linkedin.com/in/martin-fowler-com/'>LinkedIn</a></p>
|
||||
|
||||
<p><a href = 'https://bsky.app/profile/martinfowler.com'>Bluesky</a></p>
|
||||
|
||||
<p><a href = 'https://www.twitter.com/martinfowler'>X</a></p>
|
||||
|
||||
<p><a href = 'https://boardgamegeek.com/blog/13064/martins-7th-decade'>BGG</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
|
||||
<main><h1 id="section">404</h1>
|
||||
|
||||
<p>I’m afraid this is not the document you’re looking for. Try using the
|
||||
search box above, and good luck.</p>
|
||||
</main>
|
||||
|
||||
<nav id = 'bottom-navmenu'>
|
||||
<nav class = 'navmenu'>
|
||||
<div class = 'nav-head'> <div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'closediv'>
|
||||
<span class = 'close' title = 'close'></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class = 'nav-body'>
|
||||
<div class = 'topics'>
|
||||
<h2>Topics</h2>
|
||||
|
||||
<p><a href = '/architecture'>Architecture</a></p>
|
||||
|
||||
<p><a href = 'https://refactoring.com'>Refactoring</a></p>
|
||||
|
||||
<p><a href = '/agile.html'>Agile</a></p>
|
||||
|
||||
<p><a href = '/delivery.html'>Delivery</a></p>
|
||||
|
||||
<p><a href = '/microservices'>Microservices</a></p>
|
||||
|
||||
<p><a href = '/data'>Data</a></p>
|
||||
|
||||
<p><a href = '/testing'>Testing</a></p>
|
||||
|
||||
<p><a href = '/dsl.html'>DSL</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'about'>
|
||||
<h2>about me</h2>
|
||||
|
||||
<p><a href = '/aboutMe.html'>About</a></p>
|
||||
|
||||
<p><a href = '/books'>Books</a></p>
|
||||
|
||||
<p><a href = '/faq.html'>FAQ</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'content'>
|
||||
<h2>content</h2>
|
||||
|
||||
<p><a href = '/videos.html'>Videos</a></p>
|
||||
|
||||
<p><a href = '/tags'>Content Index</a></p>
|
||||
|
||||
<p><a href = '/boardgames'>Board Games</a></p>
|
||||
|
||||
<p><a href = '/photos'>Photography</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'tw'>
|
||||
<h2>Thoughtworks</h2>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com'>Home</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/insights'>Insights</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/careers'>Careers</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/radar'>Radar</a></p>
|
||||
|
||||
<p><a href = 'https://www.thoughtworks.com/engineering'>Engineering</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'feeds'>
|
||||
<h2>follow</h2>
|
||||
|
||||
<p><a href = '/feed.atom'>RSS</a></p>
|
||||
|
||||
<p><a href = 'https://toot.thoughtworks.com/@mfowler'>Mastodon</a></p>
|
||||
|
||||
<p><a href = 'https://www.linkedin.com/in/martin-fowler-com/'>LinkedIn</a></p>
|
||||
|
||||
<p><a href = 'https://bsky.app/profile/martinfowler.com'>Bluesky</a></p>
|
||||
|
||||
<p><a href = 'https://www.twitter.com/martinfowler'>X</a></p>
|
||||
|
||||
<p><a href = 'https://boardgamegeek.com/blog/13064/martins-7th-decade'>BGG</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
<footer id='page-footer'>
|
||||
<div class='tw-logo'>
|
||||
<a href='https://www.thoughtworks.com/engineering'>
|
||||
<img src='/thoughtworks_white.png'>
|
||||
</a>
|
||||
</div>
|
||||
<div class='menu-button'>
|
||||
<div class='icon-bars navmenu-button'></div>
|
||||
</div>
|
||||
<div class='copyright'>
|
||||
<p>© Martin Fowler | <a href="/aboutMe.html#disclosures">Disclosures</a></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src = '/jquery-1.11.3.min.js' type = 'text/javascript'></script>
|
||||
|
||||
<script src = '/mfcom.js' type = 'text/javascript'></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,280 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta content = 'uft-8' name = 'charset'></meta>
|
||||
|
||||
<title>not found</title>
|
||||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /><script defer src="https://cloud.umami.is/script.js" data-website-id="eb12527f-b713-4afa-905a-8a50f8a7f157"></script>
|
||||
<link href = '/global.css' rel = 'stylesheet' type = 'text/css'></link>
|
||||
</head>
|
||||
|
||||
<body><header id = 'banner' style = 'background-image: url("/banner.png"); background-repeat: no-repeat'>
|
||||
|
||||
<div class = 'name-logo'><a href = 'https://martinfowler.com'><img src = '/mf-name-white.png'></img></a></div>
|
||||
<div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'menu-button navmenu-button'><a class = 'icon icon-bars' href = '#navmenu-bottom'></a></div>
|
||||
|
||||
<nav class = 'top-menu'>
|
||||
<ul>
|
||||
<li><a class = '' href = 'https://refactoring.com'>Refactoring</a></li>
|
||||
|
||||
<li><a class = '' href = '/agile.html'>Agile</a></li>
|
||||
|
||||
<li><a class = '' href = '/architecture'>Architecture</a></li>
|
||||
|
||||
<li><a class = '' href = '/aboutMe.html'>About</a></li>
|
||||
|
||||
<li><a class = 'tw' href = 'https://www.thoughtworks.com/engineering'>Thoughtworks</a></li>
|
||||
|
||||
<li><a class = 'icon icon-rss' href = '/feed.atom' title = 'feed'></a></li>
|
||||
|
||||
<li><a class = 'icon icon-twitter' href = 'https://www.twitter.com/martinfowler' title = 'Twitter stream'></a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://toot.thoughtworks.com/@mfowler' title = 'Mastodon stream'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M21.2595 13.9898C20.9852 15.4006 18.8033 16.9446 16.2974 17.2439C14.9907 17.3998 13.7041 17.5431 12.3321 17.4802C10.0885 17.3774 8.31809 16.9446 8.31809 16.9446C8.31809 17.163 8.33156 17.371 8.3585 17.5655C8.65019 19.7797 10.5541 19.9124 12.3576 19.9742C14.1779 20.0365 15.7987 19.5254 15.7987 19.5254L15.8735 21.1711C15.8735 21.1711 14.6003 21.8548 12.3321 21.9805C11.0814 22.0493 9.52849 21.9491 7.71973 21.4703C3.79684 20.432 3.12219 16.2504 3.01896 12.0074C2.98749 10.7477 3.00689 9.55981 3.00689 8.56632C3.00689 4.22771 5.84955 2.95599 5.84955 2.95599C7.2829 2.29772 9.74238 2.0209 12.2993 2H12.3621C14.919 2.0209 17.3801 2.29772 18.8133 2.95599C18.8133 2.95599 21.6559 4.22771 21.6559 8.56632C21.6559 8.56632 21.6916 11.7674 21.2595 13.9898ZM18.3029 8.9029C18.3029 7.82924 18.0295 6.97604 17.4805 6.34482C16.9142 5.71359 16.1726 5.39001 15.2522 5.39001C14.187 5.39001 13.3805 5.79937 12.8473 6.61819L12.3288 7.48723L11.8104 6.61819C11.2771 5.79937 10.4706 5.39001 9.40554 5.39001C8.485 5.39001 7.74344 5.71359 7.17719 6.34482C6.62807 6.97604 6.3547 7.82924 6.3547 8.9029V14.1562H8.43597V9.05731C8.43597 7.98246 8.88822 7.4369 9.79281 7.4369C10.793 7.4369 11.2944 8.08408 11.2944 9.36376V12.1547H13.3634V9.36376C13.3634 8.08408 13.8646 7.4369 14.8648 7.4369C15.7694 7.4369 16.2216 7.98246 16.2216 9.05731V14.1562H18.3029V8.9029Z"></path></svg>
|
||||
</a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://www.linkedin.com/in/martin-fowler-com/' title = 'LinkedIn'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M4.00098 3H20.001C20.5533 3 21.001 3.44772 21.001 4V20C21.001 20.5523 20.5533 21 20.001 21H4.00098C3.44869 21 3.00098 20.5523 3.00098 20V4C3.00098 3.44772 3.44869 3 4.00098 3ZM5.00098 5V19H19.001V5H5.00098ZM7.50098 9C6.67255 9 6.00098 8.32843 6.00098 7.5C6.00098 6.67157 6.67255 6 7.50098 6C8.3294 6 9.00098 6.67157 9.00098 7.5C9.00098 8.32843 8.3294 9 7.50098 9ZM6.50098 10H8.50098V17.5H6.50098V10ZM12.001 10.4295C12.5854 9.86534 13.2665 9.5 14.001 9.5C16.072 9.5 17.501 11.1789 17.501 13.25V17.5H15.501V13.25C15.501 12.2835 14.7175 11.5 13.751 11.5C12.7845 11.5 12.001 12.2835 12.001 13.25V17.5H10.001V10H12.001V10.4295Z"></path></svg>
|
||||
</a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://bsky.app/profile/martinfowler.com' title = 'BlueSky'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 11.3884C11.0942 9.62673 8.62833 6.34423 6.335 4.7259C4.13833 3.17506 3.30083 3.4434 2.75167 3.69256C2.11583 3.9784 2 4.95506 2 5.52839C2 6.10339 2.315 10.2367 2.52 10.9276C3.19917 13.2076 5.61417 13.9776 7.83917 13.7309C4.57917 14.2142 1.68333 15.4017 5.48083 19.6292C9.65833 23.9542 11.2058 18.7017 12 16.0392C12.7942 18.7017 13.7083 23.7651 18.4442 19.6292C22 16.0392 19.4208 14.2142 16.1608 13.7309C18.3858 13.9784 20.8008 13.2076 21.48 10.9276C21.685 10.2376 22 6.10256 22 5.52923C22 4.95423 21.8842 3.97839 21.2483 3.6909C20.6992 3.44256 19.8617 3.17423 17.665 4.72423C15.3717 6.34506 12.9058 9.62756 12 11.3884Z"></path></svg></a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<nav id = 'top-navmenu'>
|
||||
<nav class = 'navmenu'>
|
||||
<div class = 'nav-head'> <div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'closediv'>
|
||||
<span class = 'close' title = 'close'></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class = 'nav-body'>
|
||||
<div class = 'topics'>
|
||||
<h2>Topics</h2>
|
||||
|
||||
<p><a href = '/architecture'>Architecture</a></p>
|
||||
|
||||
<p><a href = 'https://refactoring.com'>Refactoring</a></p>
|
||||
|
||||
<p><a href = '/agile.html'>Agile</a></p>
|
||||
|
||||
<p><a href = '/delivery.html'>Delivery</a></p>
|
||||
|
||||
<p><a href = '/microservices'>Microservices</a></p>
|
||||
|
||||
<p><a href = '/data'>Data</a></p>
|
||||
|
||||
<p><a href = '/testing'>Testing</a></p>
|
||||
|
||||
<p><a href = '/dsl.html'>DSL</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'about'>
|
||||
<h2>about me</h2>
|
||||
|
||||
<p><a href = '/aboutMe.html'>About</a></p>
|
||||
|
||||
<p><a href = '/books'>Books</a></p>
|
||||
|
||||
<p><a href = '/faq.html'>FAQ</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'content'>
|
||||
<h2>content</h2>
|
||||
|
||||
<p><a href = '/videos.html'>Videos</a></p>
|
||||
|
||||
<p><a href = '/tags'>Content Index</a></p>
|
||||
|
||||
<p><a href = '/boardgames'>Board Games</a></p>
|
||||
|
||||
<p><a href = '/photos'>Photography</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'tw'>
|
||||
<h2>Thoughtworks</h2>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com'>Home</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/insights'>Insights</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/careers'>Careers</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/radar'>Radar</a></p>
|
||||
|
||||
<p><a href = 'https://www.thoughtworks.com/engineering'>Engineering</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'feeds'>
|
||||
<h2>follow</h2>
|
||||
|
||||
<p><a href = '/feed.atom'>RSS</a></p>
|
||||
|
||||
<p><a href = 'https://toot.thoughtworks.com/@mfowler'>Mastodon</a></p>
|
||||
|
||||
<p><a href = 'https://www.linkedin.com/in/martin-fowler-com/'>LinkedIn</a></p>
|
||||
|
||||
<p><a href = 'https://bsky.app/profile/martinfowler.com'>Bluesky</a></p>
|
||||
|
||||
<p><a href = 'https://www.twitter.com/martinfowler'>X</a></p>
|
||||
|
||||
<p><a href = 'https://boardgamegeek.com/blog/13064/martins-7th-decade'>BGG</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
|
||||
<main><h1 id="section">404</h1>
|
||||
|
||||
<p>I’m afraid this is not the document you’re looking for. Try using the
|
||||
search box above, and good luck.</p>
|
||||
</main>
|
||||
|
||||
<nav id = 'bottom-navmenu'>
|
||||
<nav class = 'navmenu'>
|
||||
<div class = 'nav-head'> <div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'closediv'>
|
||||
<span class = 'close' title = 'close'></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class = 'nav-body'>
|
||||
<div class = 'topics'>
|
||||
<h2>Topics</h2>
|
||||
|
||||
<p><a href = '/architecture'>Architecture</a></p>
|
||||
|
||||
<p><a href = 'https://refactoring.com'>Refactoring</a></p>
|
||||
|
||||
<p><a href = '/agile.html'>Agile</a></p>
|
||||
|
||||
<p><a href = '/delivery.html'>Delivery</a></p>
|
||||
|
||||
<p><a href = '/microservices'>Microservices</a></p>
|
||||
|
||||
<p><a href = '/data'>Data</a></p>
|
||||
|
||||
<p><a href = '/testing'>Testing</a></p>
|
||||
|
||||
<p><a href = '/dsl.html'>DSL</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'about'>
|
||||
<h2>about me</h2>
|
||||
|
||||
<p><a href = '/aboutMe.html'>About</a></p>
|
||||
|
||||
<p><a href = '/books'>Books</a></p>
|
||||
|
||||
<p><a href = '/faq.html'>FAQ</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'content'>
|
||||
<h2>content</h2>
|
||||
|
||||
<p><a href = '/videos.html'>Videos</a></p>
|
||||
|
||||
<p><a href = '/tags'>Content Index</a></p>
|
||||
|
||||
<p><a href = '/boardgames'>Board Games</a></p>
|
||||
|
||||
<p><a href = '/photos'>Photography</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'tw'>
|
||||
<h2>Thoughtworks</h2>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com'>Home</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/insights'>Insights</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/careers'>Careers</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/radar'>Radar</a></p>
|
||||
|
||||
<p><a href = 'https://www.thoughtworks.com/engineering'>Engineering</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'feeds'>
|
||||
<h2>follow</h2>
|
||||
|
||||
<p><a href = '/feed.atom'>RSS</a></p>
|
||||
|
||||
<p><a href = 'https://toot.thoughtworks.com/@mfowler'>Mastodon</a></p>
|
||||
|
||||
<p><a href = 'https://www.linkedin.com/in/martin-fowler-com/'>LinkedIn</a></p>
|
||||
|
||||
<p><a href = 'https://bsky.app/profile/martinfowler.com'>Bluesky</a></p>
|
||||
|
||||
<p><a href = 'https://www.twitter.com/martinfowler'>X</a></p>
|
||||
|
||||
<p><a href = 'https://boardgamegeek.com/blog/13064/martins-7th-decade'>BGG</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
<footer id='page-footer'>
|
||||
<div class='tw-logo'>
|
||||
<a href='https://www.thoughtworks.com/engineering'>
|
||||
<img src='/thoughtworks_white.png'>
|
||||
</a>
|
||||
</div>
|
||||
<div class='menu-button'>
|
||||
<div class='icon-bars navmenu-button'></div>
|
||||
</div>
|
||||
<div class='copyright'>
|
||||
<p>© Martin Fowler | <a href="/aboutMe.html#disclosures">Disclosures</a></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src = '/jquery-1.11.3.min.js' type = 'text/javascript'></script>
|
||||
|
||||
<script src = '/mfcom.js' type = 'text/javascript'></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,280 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta content = 'uft-8' name = 'charset'></meta>
|
||||
|
||||
<title>not found</title>
|
||||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /><script defer src="https://cloud.umami.is/script.js" data-website-id="eb12527f-b713-4afa-905a-8a50f8a7f157"></script>
|
||||
<link href = '/global.css' rel = 'stylesheet' type = 'text/css'></link>
|
||||
</head>
|
||||
|
||||
<body><header id = 'banner' style = 'background-image: url("/banner.png"); background-repeat: no-repeat'>
|
||||
|
||||
<div class = 'name-logo'><a href = 'https://martinfowler.com'><img src = '/mf-name-white.png'></img></a></div>
|
||||
<div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'menu-button navmenu-button'><a class = 'icon icon-bars' href = '#navmenu-bottom'></a></div>
|
||||
|
||||
<nav class = 'top-menu'>
|
||||
<ul>
|
||||
<li><a class = '' href = 'https://refactoring.com'>Refactoring</a></li>
|
||||
|
||||
<li><a class = '' href = '/agile.html'>Agile</a></li>
|
||||
|
||||
<li><a class = '' href = '/architecture'>Architecture</a></li>
|
||||
|
||||
<li><a class = '' href = '/aboutMe.html'>About</a></li>
|
||||
|
||||
<li><a class = 'tw' href = 'https://www.thoughtworks.com/engineering'>Thoughtworks</a></li>
|
||||
|
||||
<li><a class = 'icon icon-rss' href = '/feed.atom' title = 'feed'></a></li>
|
||||
|
||||
<li><a class = 'icon icon-twitter' href = 'https://www.twitter.com/martinfowler' title = 'Twitter stream'></a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://toot.thoughtworks.com/@mfowler' title = 'Mastodon stream'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M21.2595 13.9898C20.9852 15.4006 18.8033 16.9446 16.2974 17.2439C14.9907 17.3998 13.7041 17.5431 12.3321 17.4802C10.0885 17.3774 8.31809 16.9446 8.31809 16.9446C8.31809 17.163 8.33156 17.371 8.3585 17.5655C8.65019 19.7797 10.5541 19.9124 12.3576 19.9742C14.1779 20.0365 15.7987 19.5254 15.7987 19.5254L15.8735 21.1711C15.8735 21.1711 14.6003 21.8548 12.3321 21.9805C11.0814 22.0493 9.52849 21.9491 7.71973 21.4703C3.79684 20.432 3.12219 16.2504 3.01896 12.0074C2.98749 10.7477 3.00689 9.55981 3.00689 8.56632C3.00689 4.22771 5.84955 2.95599 5.84955 2.95599C7.2829 2.29772 9.74238 2.0209 12.2993 2H12.3621C14.919 2.0209 17.3801 2.29772 18.8133 2.95599C18.8133 2.95599 21.6559 4.22771 21.6559 8.56632C21.6559 8.56632 21.6916 11.7674 21.2595 13.9898ZM18.3029 8.9029C18.3029 7.82924 18.0295 6.97604 17.4805 6.34482C16.9142 5.71359 16.1726 5.39001 15.2522 5.39001C14.187 5.39001 13.3805 5.79937 12.8473 6.61819L12.3288 7.48723L11.8104 6.61819C11.2771 5.79937 10.4706 5.39001 9.40554 5.39001C8.485 5.39001 7.74344 5.71359 7.17719 6.34482C6.62807 6.97604 6.3547 7.82924 6.3547 8.9029V14.1562H8.43597V9.05731C8.43597 7.98246 8.88822 7.4369 9.79281 7.4369C10.793 7.4369 11.2944 8.08408 11.2944 9.36376V12.1547H13.3634V9.36376C13.3634 8.08408 13.8646 7.4369 14.8648 7.4369C15.7694 7.4369 16.2216 7.98246 16.2216 9.05731V14.1562H18.3029V8.9029Z"></path></svg>
|
||||
</a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://www.linkedin.com/in/martin-fowler-com/' title = 'LinkedIn'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M4.00098 3H20.001C20.5533 3 21.001 3.44772 21.001 4V20C21.001 20.5523 20.5533 21 20.001 21H4.00098C3.44869 21 3.00098 20.5523 3.00098 20V4C3.00098 3.44772 3.44869 3 4.00098 3ZM5.00098 5V19H19.001V5H5.00098ZM7.50098 9C6.67255 9 6.00098 8.32843 6.00098 7.5C6.00098 6.67157 6.67255 6 7.50098 6C8.3294 6 9.00098 6.67157 9.00098 7.5C9.00098 8.32843 8.3294 9 7.50098 9ZM6.50098 10H8.50098V17.5H6.50098V10ZM12.001 10.4295C12.5854 9.86534 13.2665 9.5 14.001 9.5C16.072 9.5 17.501 11.1789 17.501 13.25V17.5H15.501V13.25C15.501 12.2835 14.7175 11.5 13.751 11.5C12.7845 11.5 12.001 12.2835 12.001 13.25V17.5H10.001V10H12.001V10.4295Z"></path></svg>
|
||||
</a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://bsky.app/profile/martinfowler.com' title = 'BlueSky'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 11.3884C11.0942 9.62673 8.62833 6.34423 6.335 4.7259C4.13833 3.17506 3.30083 3.4434 2.75167 3.69256C2.11583 3.9784 2 4.95506 2 5.52839C2 6.10339 2.315 10.2367 2.52 10.9276C3.19917 13.2076 5.61417 13.9776 7.83917 13.7309C4.57917 14.2142 1.68333 15.4017 5.48083 19.6292C9.65833 23.9542 11.2058 18.7017 12 16.0392C12.7942 18.7017 13.7083 23.7651 18.4442 19.6292C22 16.0392 19.4208 14.2142 16.1608 13.7309C18.3858 13.9784 20.8008 13.2076 21.48 10.9276C21.685 10.2376 22 6.10256 22 5.52923C22 4.95423 21.8842 3.97839 21.2483 3.6909C20.6992 3.44256 19.8617 3.17423 17.665 4.72423C15.3717 6.34506 12.9058 9.62756 12 11.3884Z"></path></svg></a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<nav id = 'top-navmenu'>
|
||||
<nav class = 'navmenu'>
|
||||
<div class = 'nav-head'> <div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'closediv'>
|
||||
<span class = 'close' title = 'close'></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class = 'nav-body'>
|
||||
<div class = 'topics'>
|
||||
<h2>Topics</h2>
|
||||
|
||||
<p><a href = '/architecture'>Architecture</a></p>
|
||||
|
||||
<p><a href = 'https://refactoring.com'>Refactoring</a></p>
|
||||
|
||||
<p><a href = '/agile.html'>Agile</a></p>
|
||||
|
||||
<p><a href = '/delivery.html'>Delivery</a></p>
|
||||
|
||||
<p><a href = '/microservices'>Microservices</a></p>
|
||||
|
||||
<p><a href = '/data'>Data</a></p>
|
||||
|
||||
<p><a href = '/testing'>Testing</a></p>
|
||||
|
||||
<p><a href = '/dsl.html'>DSL</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'about'>
|
||||
<h2>about me</h2>
|
||||
|
||||
<p><a href = '/aboutMe.html'>About</a></p>
|
||||
|
||||
<p><a href = '/books'>Books</a></p>
|
||||
|
||||
<p><a href = '/faq.html'>FAQ</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'content'>
|
||||
<h2>content</h2>
|
||||
|
||||
<p><a href = '/videos.html'>Videos</a></p>
|
||||
|
||||
<p><a href = '/tags'>Content Index</a></p>
|
||||
|
||||
<p><a href = '/boardgames'>Board Games</a></p>
|
||||
|
||||
<p><a href = '/photos'>Photography</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'tw'>
|
||||
<h2>Thoughtworks</h2>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com'>Home</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/insights'>Insights</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/careers'>Careers</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/radar'>Radar</a></p>
|
||||
|
||||
<p><a href = 'https://www.thoughtworks.com/engineering'>Engineering</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'feeds'>
|
||||
<h2>follow</h2>
|
||||
|
||||
<p><a href = '/feed.atom'>RSS</a></p>
|
||||
|
||||
<p><a href = 'https://toot.thoughtworks.com/@mfowler'>Mastodon</a></p>
|
||||
|
||||
<p><a href = 'https://www.linkedin.com/in/martin-fowler-com/'>LinkedIn</a></p>
|
||||
|
||||
<p><a href = 'https://bsky.app/profile/martinfowler.com'>Bluesky</a></p>
|
||||
|
||||
<p><a href = 'https://www.twitter.com/martinfowler'>X</a></p>
|
||||
|
||||
<p><a href = 'https://boardgamegeek.com/blog/13064/martins-7th-decade'>BGG</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
|
||||
<main><h1 id="section">404</h1>
|
||||
|
||||
<p>I’m afraid this is not the document you’re looking for. Try using the
|
||||
search box above, and good luck.</p>
|
||||
</main>
|
||||
|
||||
<nav id = 'bottom-navmenu'>
|
||||
<nav class = 'navmenu'>
|
||||
<div class = 'nav-head'> <div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'closediv'>
|
||||
<span class = 'close' title = 'close'></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class = 'nav-body'>
|
||||
<div class = 'topics'>
|
||||
<h2>Topics</h2>
|
||||
|
||||
<p><a href = '/architecture'>Architecture</a></p>
|
||||
|
||||
<p><a href = 'https://refactoring.com'>Refactoring</a></p>
|
||||
|
||||
<p><a href = '/agile.html'>Agile</a></p>
|
||||
|
||||
<p><a href = '/delivery.html'>Delivery</a></p>
|
||||
|
||||
<p><a href = '/microservices'>Microservices</a></p>
|
||||
|
||||
<p><a href = '/data'>Data</a></p>
|
||||
|
||||
<p><a href = '/testing'>Testing</a></p>
|
||||
|
||||
<p><a href = '/dsl.html'>DSL</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'about'>
|
||||
<h2>about me</h2>
|
||||
|
||||
<p><a href = '/aboutMe.html'>About</a></p>
|
||||
|
||||
<p><a href = '/books'>Books</a></p>
|
||||
|
||||
<p><a href = '/faq.html'>FAQ</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'content'>
|
||||
<h2>content</h2>
|
||||
|
||||
<p><a href = '/videos.html'>Videos</a></p>
|
||||
|
||||
<p><a href = '/tags'>Content Index</a></p>
|
||||
|
||||
<p><a href = '/boardgames'>Board Games</a></p>
|
||||
|
||||
<p><a href = '/photos'>Photography</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'tw'>
|
||||
<h2>Thoughtworks</h2>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com'>Home</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/insights'>Insights</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/careers'>Careers</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/radar'>Radar</a></p>
|
||||
|
||||
<p><a href = 'https://www.thoughtworks.com/engineering'>Engineering</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'feeds'>
|
||||
<h2>follow</h2>
|
||||
|
||||
<p><a href = '/feed.atom'>RSS</a></p>
|
||||
|
||||
<p><a href = 'https://toot.thoughtworks.com/@mfowler'>Mastodon</a></p>
|
||||
|
||||
<p><a href = 'https://www.linkedin.com/in/martin-fowler-com/'>LinkedIn</a></p>
|
||||
|
||||
<p><a href = 'https://bsky.app/profile/martinfowler.com'>Bluesky</a></p>
|
||||
|
||||
<p><a href = 'https://www.twitter.com/martinfowler'>X</a></p>
|
||||
|
||||
<p><a href = 'https://boardgamegeek.com/blog/13064/martins-7th-decade'>BGG</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
<footer id='page-footer'>
|
||||
<div class='tw-logo'>
|
||||
<a href='https://www.thoughtworks.com/engineering'>
|
||||
<img src='/thoughtworks_white.png'>
|
||||
</a>
|
||||
</div>
|
||||
<div class='menu-button'>
|
||||
<div class='icon-bars navmenu-button'></div>
|
||||
</div>
|
||||
<div class='copyright'>
|
||||
<p>© Martin Fowler | <a href="/aboutMe.html#disclosures">Disclosures</a></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src = '/jquery-1.11.3.min.js' type = 'text/javascript'></script>
|
||||
|
||||
<script src = '/mfcom.js' type = 'text/javascript'></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,280 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta content = 'uft-8' name = 'charset'></meta>
|
||||
|
||||
<title>not found</title>
|
||||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /><script defer src="https://cloud.umami.is/script.js" data-website-id="eb12527f-b713-4afa-905a-8a50f8a7f157"></script>
|
||||
<link href = '/global.css' rel = 'stylesheet' type = 'text/css'></link>
|
||||
</head>
|
||||
|
||||
<body><header id = 'banner' style = 'background-image: url("/banner.png"); background-repeat: no-repeat'>
|
||||
|
||||
<div class = 'name-logo'><a href = 'https://martinfowler.com'><img src = '/mf-name-white.png'></img></a></div>
|
||||
<div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'menu-button navmenu-button'><a class = 'icon icon-bars' href = '#navmenu-bottom'></a></div>
|
||||
|
||||
<nav class = 'top-menu'>
|
||||
<ul>
|
||||
<li><a class = '' href = 'https://refactoring.com'>Refactoring</a></li>
|
||||
|
||||
<li><a class = '' href = '/agile.html'>Agile</a></li>
|
||||
|
||||
<li><a class = '' href = '/architecture'>Architecture</a></li>
|
||||
|
||||
<li><a class = '' href = '/aboutMe.html'>About</a></li>
|
||||
|
||||
<li><a class = 'tw' href = 'https://www.thoughtworks.com/engineering'>Thoughtworks</a></li>
|
||||
|
||||
<li><a class = 'icon icon-rss' href = '/feed.atom' title = 'feed'></a></li>
|
||||
|
||||
<li><a class = 'icon icon-twitter' href = 'https://www.twitter.com/martinfowler' title = 'Twitter stream'></a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://toot.thoughtworks.com/@mfowler' title = 'Mastodon stream'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M21.2595 13.9898C20.9852 15.4006 18.8033 16.9446 16.2974 17.2439C14.9907 17.3998 13.7041 17.5431 12.3321 17.4802C10.0885 17.3774 8.31809 16.9446 8.31809 16.9446C8.31809 17.163 8.33156 17.371 8.3585 17.5655C8.65019 19.7797 10.5541 19.9124 12.3576 19.9742C14.1779 20.0365 15.7987 19.5254 15.7987 19.5254L15.8735 21.1711C15.8735 21.1711 14.6003 21.8548 12.3321 21.9805C11.0814 22.0493 9.52849 21.9491 7.71973 21.4703C3.79684 20.432 3.12219 16.2504 3.01896 12.0074C2.98749 10.7477 3.00689 9.55981 3.00689 8.56632C3.00689 4.22771 5.84955 2.95599 5.84955 2.95599C7.2829 2.29772 9.74238 2.0209 12.2993 2H12.3621C14.919 2.0209 17.3801 2.29772 18.8133 2.95599C18.8133 2.95599 21.6559 4.22771 21.6559 8.56632C21.6559 8.56632 21.6916 11.7674 21.2595 13.9898ZM18.3029 8.9029C18.3029 7.82924 18.0295 6.97604 17.4805 6.34482C16.9142 5.71359 16.1726 5.39001 15.2522 5.39001C14.187 5.39001 13.3805 5.79937 12.8473 6.61819L12.3288 7.48723L11.8104 6.61819C11.2771 5.79937 10.4706 5.39001 9.40554 5.39001C8.485 5.39001 7.74344 5.71359 7.17719 6.34482C6.62807 6.97604 6.3547 7.82924 6.3547 8.9029V14.1562H8.43597V9.05731C8.43597 7.98246 8.88822 7.4369 9.79281 7.4369C10.793 7.4369 11.2944 8.08408 11.2944 9.36376V12.1547H13.3634V9.36376C13.3634 8.08408 13.8646 7.4369 14.8648 7.4369C15.7694 7.4369 16.2216 7.98246 16.2216 9.05731V14.1562H18.3029V8.9029Z"></path></svg>
|
||||
</a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://www.linkedin.com/in/martin-fowler-com/' title = 'LinkedIn'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M4.00098 3H20.001C20.5533 3 21.001 3.44772 21.001 4V20C21.001 20.5523 20.5533 21 20.001 21H4.00098C3.44869 21 3.00098 20.5523 3.00098 20V4C3.00098 3.44772 3.44869 3 4.00098 3ZM5.00098 5V19H19.001V5H5.00098ZM7.50098 9C6.67255 9 6.00098 8.32843 6.00098 7.5C6.00098 6.67157 6.67255 6 7.50098 6C8.3294 6 9.00098 6.67157 9.00098 7.5C9.00098 8.32843 8.3294 9 7.50098 9ZM6.50098 10H8.50098V17.5H6.50098V10ZM12.001 10.4295C12.5854 9.86534 13.2665 9.5 14.001 9.5C16.072 9.5 17.501 11.1789 17.501 13.25V17.5H15.501V13.25C15.501 12.2835 14.7175 11.5 13.751 11.5C12.7845 11.5 12.001 12.2835 12.001 13.25V17.5H10.001V10H12.001V10.4295Z"></path></svg>
|
||||
</a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://bsky.app/profile/martinfowler.com' title = 'BlueSky'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 11.3884C11.0942 9.62673 8.62833 6.34423 6.335 4.7259C4.13833 3.17506 3.30083 3.4434 2.75167 3.69256C2.11583 3.9784 2 4.95506 2 5.52839C2 6.10339 2.315 10.2367 2.52 10.9276C3.19917 13.2076 5.61417 13.9776 7.83917 13.7309C4.57917 14.2142 1.68333 15.4017 5.48083 19.6292C9.65833 23.9542 11.2058 18.7017 12 16.0392C12.7942 18.7017 13.7083 23.7651 18.4442 19.6292C22 16.0392 19.4208 14.2142 16.1608 13.7309C18.3858 13.9784 20.8008 13.2076 21.48 10.9276C21.685 10.2376 22 6.10256 22 5.52923C22 4.95423 21.8842 3.97839 21.2483 3.6909C20.6992 3.44256 19.8617 3.17423 17.665 4.72423C15.3717 6.34506 12.9058 9.62756 12 11.3884Z"></path></svg></a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<nav id = 'top-navmenu'>
|
||||
<nav class = 'navmenu'>
|
||||
<div class = 'nav-head'> <div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'closediv'>
|
||||
<span class = 'close' title = 'close'></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class = 'nav-body'>
|
||||
<div class = 'topics'>
|
||||
<h2>Topics</h2>
|
||||
|
||||
<p><a href = '/architecture'>Architecture</a></p>
|
||||
|
||||
<p><a href = 'https://refactoring.com'>Refactoring</a></p>
|
||||
|
||||
<p><a href = '/agile.html'>Agile</a></p>
|
||||
|
||||
<p><a href = '/delivery.html'>Delivery</a></p>
|
||||
|
||||
<p><a href = '/microservices'>Microservices</a></p>
|
||||
|
||||
<p><a href = '/data'>Data</a></p>
|
||||
|
||||
<p><a href = '/testing'>Testing</a></p>
|
||||
|
||||
<p><a href = '/dsl.html'>DSL</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'about'>
|
||||
<h2>about me</h2>
|
||||
|
||||
<p><a href = '/aboutMe.html'>About</a></p>
|
||||
|
||||
<p><a href = '/books'>Books</a></p>
|
||||
|
||||
<p><a href = '/faq.html'>FAQ</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'content'>
|
||||
<h2>content</h2>
|
||||
|
||||
<p><a href = '/videos.html'>Videos</a></p>
|
||||
|
||||
<p><a href = '/tags'>Content Index</a></p>
|
||||
|
||||
<p><a href = '/boardgames'>Board Games</a></p>
|
||||
|
||||
<p><a href = '/photos'>Photography</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'tw'>
|
||||
<h2>Thoughtworks</h2>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com'>Home</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/insights'>Insights</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/careers'>Careers</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/radar'>Radar</a></p>
|
||||
|
||||
<p><a href = 'https://www.thoughtworks.com/engineering'>Engineering</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'feeds'>
|
||||
<h2>follow</h2>
|
||||
|
||||
<p><a href = '/feed.atom'>RSS</a></p>
|
||||
|
||||
<p><a href = 'https://toot.thoughtworks.com/@mfowler'>Mastodon</a></p>
|
||||
|
||||
<p><a href = 'https://www.linkedin.com/in/martin-fowler-com/'>LinkedIn</a></p>
|
||||
|
||||
<p><a href = 'https://bsky.app/profile/martinfowler.com'>Bluesky</a></p>
|
||||
|
||||
<p><a href = 'https://www.twitter.com/martinfowler'>X</a></p>
|
||||
|
||||
<p><a href = 'https://boardgamegeek.com/blog/13064/martins-7th-decade'>BGG</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
|
||||
<main><h1 id="section">404</h1>
|
||||
|
||||
<p>I’m afraid this is not the document you’re looking for. Try using the
|
||||
search box above, and good luck.</p>
|
||||
</main>
|
||||
|
||||
<nav id = 'bottom-navmenu'>
|
||||
<nav class = 'navmenu'>
|
||||
<div class = 'nav-head'> <div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'closediv'>
|
||||
<span class = 'close' title = 'close'></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class = 'nav-body'>
|
||||
<div class = 'topics'>
|
||||
<h2>Topics</h2>
|
||||
|
||||
<p><a href = '/architecture'>Architecture</a></p>
|
||||
|
||||
<p><a href = 'https://refactoring.com'>Refactoring</a></p>
|
||||
|
||||
<p><a href = '/agile.html'>Agile</a></p>
|
||||
|
||||
<p><a href = '/delivery.html'>Delivery</a></p>
|
||||
|
||||
<p><a href = '/microservices'>Microservices</a></p>
|
||||
|
||||
<p><a href = '/data'>Data</a></p>
|
||||
|
||||
<p><a href = '/testing'>Testing</a></p>
|
||||
|
||||
<p><a href = '/dsl.html'>DSL</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'about'>
|
||||
<h2>about me</h2>
|
||||
|
||||
<p><a href = '/aboutMe.html'>About</a></p>
|
||||
|
||||
<p><a href = '/books'>Books</a></p>
|
||||
|
||||
<p><a href = '/faq.html'>FAQ</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'content'>
|
||||
<h2>content</h2>
|
||||
|
||||
<p><a href = '/videos.html'>Videos</a></p>
|
||||
|
||||
<p><a href = '/tags'>Content Index</a></p>
|
||||
|
||||
<p><a href = '/boardgames'>Board Games</a></p>
|
||||
|
||||
<p><a href = '/photos'>Photography</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'tw'>
|
||||
<h2>Thoughtworks</h2>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com'>Home</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/insights'>Insights</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/careers'>Careers</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/radar'>Radar</a></p>
|
||||
|
||||
<p><a href = 'https://www.thoughtworks.com/engineering'>Engineering</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'feeds'>
|
||||
<h2>follow</h2>
|
||||
|
||||
<p><a href = '/feed.atom'>RSS</a></p>
|
||||
|
||||
<p><a href = 'https://toot.thoughtworks.com/@mfowler'>Mastodon</a></p>
|
||||
|
||||
<p><a href = 'https://www.linkedin.com/in/martin-fowler-com/'>LinkedIn</a></p>
|
||||
|
||||
<p><a href = 'https://bsky.app/profile/martinfowler.com'>Bluesky</a></p>
|
||||
|
||||
<p><a href = 'https://www.twitter.com/martinfowler'>X</a></p>
|
||||
|
||||
<p><a href = 'https://boardgamegeek.com/blog/13064/martins-7th-decade'>BGG</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
<footer id='page-footer'>
|
||||
<div class='tw-logo'>
|
||||
<a href='https://www.thoughtworks.com/engineering'>
|
||||
<img src='/thoughtworks_white.png'>
|
||||
</a>
|
||||
</div>
|
||||
<div class='menu-button'>
|
||||
<div class='icon-bars navmenu-button'></div>
|
||||
</div>
|
||||
<div class='copyright'>
|
||||
<p>© Martin Fowler | <a href="/aboutMe.html#disclosures">Disclosures</a></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src = '/jquery-1.11.3.min.js' type = 'text/javascript'></script>
|
||||
|
||||
<script src = '/mfcom.js' type = 'text/javascript'></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,280 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta content = 'uft-8' name = 'charset'></meta>
|
||||
|
||||
<title>not found</title>
|
||||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /><script defer src="https://cloud.umami.is/script.js" data-website-id="eb12527f-b713-4afa-905a-8a50f8a7f157"></script>
|
||||
<link href = '/global.css' rel = 'stylesheet' type = 'text/css'></link>
|
||||
</head>
|
||||
|
||||
<body><header id = 'banner' style = 'background-image: url("/banner.png"); background-repeat: no-repeat'>
|
||||
|
||||
<div class = 'name-logo'><a href = 'https://martinfowler.com'><img src = '/mf-name-white.png'></img></a></div>
|
||||
<div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'menu-button navmenu-button'><a class = 'icon icon-bars' href = '#navmenu-bottom'></a></div>
|
||||
|
||||
<nav class = 'top-menu'>
|
||||
<ul>
|
||||
<li><a class = '' href = 'https://refactoring.com'>Refactoring</a></li>
|
||||
|
||||
<li><a class = '' href = '/agile.html'>Agile</a></li>
|
||||
|
||||
<li><a class = '' href = '/architecture'>Architecture</a></li>
|
||||
|
||||
<li><a class = '' href = '/aboutMe.html'>About</a></li>
|
||||
|
||||
<li><a class = 'tw' href = 'https://www.thoughtworks.com/engineering'>Thoughtworks</a></li>
|
||||
|
||||
<li><a class = 'icon icon-rss' href = '/feed.atom' title = 'feed'></a></li>
|
||||
|
||||
<li><a class = 'icon icon-twitter' href = 'https://www.twitter.com/martinfowler' title = 'Twitter stream'></a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://toot.thoughtworks.com/@mfowler' title = 'Mastodon stream'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M21.2595 13.9898C20.9852 15.4006 18.8033 16.9446 16.2974 17.2439C14.9907 17.3998 13.7041 17.5431 12.3321 17.4802C10.0885 17.3774 8.31809 16.9446 8.31809 16.9446C8.31809 17.163 8.33156 17.371 8.3585 17.5655C8.65019 19.7797 10.5541 19.9124 12.3576 19.9742C14.1779 20.0365 15.7987 19.5254 15.7987 19.5254L15.8735 21.1711C15.8735 21.1711 14.6003 21.8548 12.3321 21.9805C11.0814 22.0493 9.52849 21.9491 7.71973 21.4703C3.79684 20.432 3.12219 16.2504 3.01896 12.0074C2.98749 10.7477 3.00689 9.55981 3.00689 8.56632C3.00689 4.22771 5.84955 2.95599 5.84955 2.95599C7.2829 2.29772 9.74238 2.0209 12.2993 2H12.3621C14.919 2.0209 17.3801 2.29772 18.8133 2.95599C18.8133 2.95599 21.6559 4.22771 21.6559 8.56632C21.6559 8.56632 21.6916 11.7674 21.2595 13.9898ZM18.3029 8.9029C18.3029 7.82924 18.0295 6.97604 17.4805 6.34482C16.9142 5.71359 16.1726 5.39001 15.2522 5.39001C14.187 5.39001 13.3805 5.79937 12.8473 6.61819L12.3288 7.48723L11.8104 6.61819C11.2771 5.79937 10.4706 5.39001 9.40554 5.39001C8.485 5.39001 7.74344 5.71359 7.17719 6.34482C6.62807 6.97604 6.3547 7.82924 6.3547 8.9029V14.1562H8.43597V9.05731C8.43597 7.98246 8.88822 7.4369 9.79281 7.4369C10.793 7.4369 11.2944 8.08408 11.2944 9.36376V12.1547H13.3634V9.36376C13.3634 8.08408 13.8646 7.4369 14.8648 7.4369C15.7694 7.4369 16.2216 7.98246 16.2216 9.05731V14.1562H18.3029V8.9029Z"></path></svg>
|
||||
</a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://www.linkedin.com/in/martin-fowler-com/' title = 'LinkedIn'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M4.00098 3H20.001C20.5533 3 21.001 3.44772 21.001 4V20C21.001 20.5523 20.5533 21 20.001 21H4.00098C3.44869 21 3.00098 20.5523 3.00098 20V4C3.00098 3.44772 3.44869 3 4.00098 3ZM5.00098 5V19H19.001V5H5.00098ZM7.50098 9C6.67255 9 6.00098 8.32843 6.00098 7.5C6.00098 6.67157 6.67255 6 7.50098 6C8.3294 6 9.00098 6.67157 9.00098 7.5C9.00098 8.32843 8.3294 9 7.50098 9ZM6.50098 10H8.50098V17.5H6.50098V10ZM12.001 10.4295C12.5854 9.86534 13.2665 9.5 14.001 9.5C16.072 9.5 17.501 11.1789 17.501 13.25V17.5H15.501V13.25C15.501 12.2835 14.7175 11.5 13.751 11.5C12.7845 11.5 12.001 12.2835 12.001 13.25V17.5H10.001V10H12.001V10.4295Z"></path></svg>
|
||||
</a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://bsky.app/profile/martinfowler.com' title = 'BlueSky'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 11.3884C11.0942 9.62673 8.62833 6.34423 6.335 4.7259C4.13833 3.17506 3.30083 3.4434 2.75167 3.69256C2.11583 3.9784 2 4.95506 2 5.52839C2 6.10339 2.315 10.2367 2.52 10.9276C3.19917 13.2076 5.61417 13.9776 7.83917 13.7309C4.57917 14.2142 1.68333 15.4017 5.48083 19.6292C9.65833 23.9542 11.2058 18.7017 12 16.0392C12.7942 18.7017 13.7083 23.7651 18.4442 19.6292C22 16.0392 19.4208 14.2142 16.1608 13.7309C18.3858 13.9784 20.8008 13.2076 21.48 10.9276C21.685 10.2376 22 6.10256 22 5.52923C22 4.95423 21.8842 3.97839 21.2483 3.6909C20.6992 3.44256 19.8617 3.17423 17.665 4.72423C15.3717 6.34506 12.9058 9.62756 12 11.3884Z"></path></svg></a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<nav id = 'top-navmenu'>
|
||||
<nav class = 'navmenu'>
|
||||
<div class = 'nav-head'> <div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'closediv'>
|
||||
<span class = 'close' title = 'close'></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class = 'nav-body'>
|
||||
<div class = 'topics'>
|
||||
<h2>Topics</h2>
|
||||
|
||||
<p><a href = '/architecture'>Architecture</a></p>
|
||||
|
||||
<p><a href = 'https://refactoring.com'>Refactoring</a></p>
|
||||
|
||||
<p><a href = '/agile.html'>Agile</a></p>
|
||||
|
||||
<p><a href = '/delivery.html'>Delivery</a></p>
|
||||
|
||||
<p><a href = '/microservices'>Microservices</a></p>
|
||||
|
||||
<p><a href = '/data'>Data</a></p>
|
||||
|
||||
<p><a href = '/testing'>Testing</a></p>
|
||||
|
||||
<p><a href = '/dsl.html'>DSL</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'about'>
|
||||
<h2>about me</h2>
|
||||
|
||||
<p><a href = '/aboutMe.html'>About</a></p>
|
||||
|
||||
<p><a href = '/books'>Books</a></p>
|
||||
|
||||
<p><a href = '/faq.html'>FAQ</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'content'>
|
||||
<h2>content</h2>
|
||||
|
||||
<p><a href = '/videos.html'>Videos</a></p>
|
||||
|
||||
<p><a href = '/tags'>Content Index</a></p>
|
||||
|
||||
<p><a href = '/boardgames'>Board Games</a></p>
|
||||
|
||||
<p><a href = '/photos'>Photography</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'tw'>
|
||||
<h2>Thoughtworks</h2>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com'>Home</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/insights'>Insights</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/careers'>Careers</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/radar'>Radar</a></p>
|
||||
|
||||
<p><a href = 'https://www.thoughtworks.com/engineering'>Engineering</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'feeds'>
|
||||
<h2>follow</h2>
|
||||
|
||||
<p><a href = '/feed.atom'>RSS</a></p>
|
||||
|
||||
<p><a href = 'https://toot.thoughtworks.com/@mfowler'>Mastodon</a></p>
|
||||
|
||||
<p><a href = 'https://www.linkedin.com/in/martin-fowler-com/'>LinkedIn</a></p>
|
||||
|
||||
<p><a href = 'https://bsky.app/profile/martinfowler.com'>Bluesky</a></p>
|
||||
|
||||
<p><a href = 'https://www.twitter.com/martinfowler'>X</a></p>
|
||||
|
||||
<p><a href = 'https://boardgamegeek.com/blog/13064/martins-7th-decade'>BGG</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
|
||||
<main><h1 id="section">404</h1>
|
||||
|
||||
<p>I’m afraid this is not the document you’re looking for. Try using the
|
||||
search box above, and good luck.</p>
|
||||
</main>
|
||||
|
||||
<nav id = 'bottom-navmenu'>
|
||||
<nav class = 'navmenu'>
|
||||
<div class = 'nav-head'> <div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'closediv'>
|
||||
<span class = 'close' title = 'close'></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class = 'nav-body'>
|
||||
<div class = 'topics'>
|
||||
<h2>Topics</h2>
|
||||
|
||||
<p><a href = '/architecture'>Architecture</a></p>
|
||||
|
||||
<p><a href = 'https://refactoring.com'>Refactoring</a></p>
|
||||
|
||||
<p><a href = '/agile.html'>Agile</a></p>
|
||||
|
||||
<p><a href = '/delivery.html'>Delivery</a></p>
|
||||
|
||||
<p><a href = '/microservices'>Microservices</a></p>
|
||||
|
||||
<p><a href = '/data'>Data</a></p>
|
||||
|
||||
<p><a href = '/testing'>Testing</a></p>
|
||||
|
||||
<p><a href = '/dsl.html'>DSL</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'about'>
|
||||
<h2>about me</h2>
|
||||
|
||||
<p><a href = '/aboutMe.html'>About</a></p>
|
||||
|
||||
<p><a href = '/books'>Books</a></p>
|
||||
|
||||
<p><a href = '/faq.html'>FAQ</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'content'>
|
||||
<h2>content</h2>
|
||||
|
||||
<p><a href = '/videos.html'>Videos</a></p>
|
||||
|
||||
<p><a href = '/tags'>Content Index</a></p>
|
||||
|
||||
<p><a href = '/boardgames'>Board Games</a></p>
|
||||
|
||||
<p><a href = '/photos'>Photography</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'tw'>
|
||||
<h2>Thoughtworks</h2>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com'>Home</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/insights'>Insights</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/careers'>Careers</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/radar'>Radar</a></p>
|
||||
|
||||
<p><a href = 'https://www.thoughtworks.com/engineering'>Engineering</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'feeds'>
|
||||
<h2>follow</h2>
|
||||
|
||||
<p><a href = '/feed.atom'>RSS</a></p>
|
||||
|
||||
<p><a href = 'https://toot.thoughtworks.com/@mfowler'>Mastodon</a></p>
|
||||
|
||||
<p><a href = 'https://www.linkedin.com/in/martin-fowler-com/'>LinkedIn</a></p>
|
||||
|
||||
<p><a href = 'https://bsky.app/profile/martinfowler.com'>Bluesky</a></p>
|
||||
|
||||
<p><a href = 'https://www.twitter.com/martinfowler'>X</a></p>
|
||||
|
||||
<p><a href = 'https://boardgamegeek.com/blog/13064/martins-7th-decade'>BGG</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
<footer id='page-footer'>
|
||||
<div class='tw-logo'>
|
||||
<a href='https://www.thoughtworks.com/engineering'>
|
||||
<img src='/thoughtworks_white.png'>
|
||||
</a>
|
||||
</div>
|
||||
<div class='menu-button'>
|
||||
<div class='icon-bars navmenu-button'></div>
|
||||
</div>
|
||||
<div class='copyright'>
|
||||
<p>© Martin Fowler | <a href="/aboutMe.html#disclosures">Disclosures</a></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src = '/jquery-1.11.3.min.js' type = 'text/javascript'></script>
|
||||
|
||||
<script src = '/mfcom.js' type = 'text/javascript'></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,280 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta content = 'uft-8' name = 'charset'></meta>
|
||||
|
||||
<title>not found</title>
|
||||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /><script defer src="https://cloud.umami.is/script.js" data-website-id="eb12527f-b713-4afa-905a-8a50f8a7f157"></script>
|
||||
<link href = '/global.css' rel = 'stylesheet' type = 'text/css'></link>
|
||||
</head>
|
||||
|
||||
<body><header id = 'banner' style = 'background-image: url("/banner.png"); background-repeat: no-repeat'>
|
||||
|
||||
<div class = 'name-logo'><a href = 'https://martinfowler.com'><img src = '/mf-name-white.png'></img></a></div>
|
||||
<div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'menu-button navmenu-button'><a class = 'icon icon-bars' href = '#navmenu-bottom'></a></div>
|
||||
|
||||
<nav class = 'top-menu'>
|
||||
<ul>
|
||||
<li><a class = '' href = 'https://refactoring.com'>Refactoring</a></li>
|
||||
|
||||
<li><a class = '' href = '/agile.html'>Agile</a></li>
|
||||
|
||||
<li><a class = '' href = '/architecture'>Architecture</a></li>
|
||||
|
||||
<li><a class = '' href = '/aboutMe.html'>About</a></li>
|
||||
|
||||
<li><a class = 'tw' href = 'https://www.thoughtworks.com/engineering'>Thoughtworks</a></li>
|
||||
|
||||
<li><a class = 'icon icon-rss' href = '/feed.atom' title = 'feed'></a></li>
|
||||
|
||||
<li><a class = 'icon icon-twitter' href = 'https://www.twitter.com/martinfowler' title = 'Twitter stream'></a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://toot.thoughtworks.com/@mfowler' title = 'Mastodon stream'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M21.2595 13.9898C20.9852 15.4006 18.8033 16.9446 16.2974 17.2439C14.9907 17.3998 13.7041 17.5431 12.3321 17.4802C10.0885 17.3774 8.31809 16.9446 8.31809 16.9446C8.31809 17.163 8.33156 17.371 8.3585 17.5655C8.65019 19.7797 10.5541 19.9124 12.3576 19.9742C14.1779 20.0365 15.7987 19.5254 15.7987 19.5254L15.8735 21.1711C15.8735 21.1711 14.6003 21.8548 12.3321 21.9805C11.0814 22.0493 9.52849 21.9491 7.71973 21.4703C3.79684 20.432 3.12219 16.2504 3.01896 12.0074C2.98749 10.7477 3.00689 9.55981 3.00689 8.56632C3.00689 4.22771 5.84955 2.95599 5.84955 2.95599C7.2829 2.29772 9.74238 2.0209 12.2993 2H12.3621C14.919 2.0209 17.3801 2.29772 18.8133 2.95599C18.8133 2.95599 21.6559 4.22771 21.6559 8.56632C21.6559 8.56632 21.6916 11.7674 21.2595 13.9898ZM18.3029 8.9029C18.3029 7.82924 18.0295 6.97604 17.4805 6.34482C16.9142 5.71359 16.1726 5.39001 15.2522 5.39001C14.187 5.39001 13.3805 5.79937 12.8473 6.61819L12.3288 7.48723L11.8104 6.61819C11.2771 5.79937 10.4706 5.39001 9.40554 5.39001C8.485 5.39001 7.74344 5.71359 7.17719 6.34482C6.62807 6.97604 6.3547 7.82924 6.3547 8.9029V14.1562H8.43597V9.05731C8.43597 7.98246 8.88822 7.4369 9.79281 7.4369C10.793 7.4369 11.2944 8.08408 11.2944 9.36376V12.1547H13.3634V9.36376C13.3634 8.08408 13.8646 7.4369 14.8648 7.4369C15.7694 7.4369 16.2216 7.98246 16.2216 9.05731V14.1562H18.3029V8.9029Z"></path></svg>
|
||||
</a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://www.linkedin.com/in/martin-fowler-com/' title = 'LinkedIn'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M4.00098 3H20.001C20.5533 3 21.001 3.44772 21.001 4V20C21.001 20.5523 20.5533 21 20.001 21H4.00098C3.44869 21 3.00098 20.5523 3.00098 20V4C3.00098 3.44772 3.44869 3 4.00098 3ZM5.00098 5V19H19.001V5H5.00098ZM7.50098 9C6.67255 9 6.00098 8.32843 6.00098 7.5C6.00098 6.67157 6.67255 6 7.50098 6C8.3294 6 9.00098 6.67157 9.00098 7.5C9.00098 8.32843 8.3294 9 7.50098 9ZM6.50098 10H8.50098V17.5H6.50098V10ZM12.001 10.4295C12.5854 9.86534 13.2665 9.5 14.001 9.5C16.072 9.5 17.501 11.1789 17.501 13.25V17.5H15.501V13.25C15.501 12.2835 14.7175 11.5 13.751 11.5C12.7845 11.5 12.001 12.2835 12.001 13.25V17.5H10.001V10H12.001V10.4295Z"></path></svg>
|
||||
</a></li>
|
||||
|
||||
<li class = 'icon'><a href = 'https://bsky.app/profile/martinfowler.com' title = 'BlueSky'><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 11.3884C11.0942 9.62673 8.62833 6.34423 6.335 4.7259C4.13833 3.17506 3.30083 3.4434 2.75167 3.69256C2.11583 3.9784 2 4.95506 2 5.52839C2 6.10339 2.315 10.2367 2.52 10.9276C3.19917 13.2076 5.61417 13.9776 7.83917 13.7309C4.57917 14.2142 1.68333 15.4017 5.48083 19.6292C9.65833 23.9542 11.2058 18.7017 12 16.0392C12.7942 18.7017 13.7083 23.7651 18.4442 19.6292C22 16.0392 19.4208 14.2142 16.1608 13.7309C18.3858 13.9784 20.8008 13.2076 21.48 10.9276C21.685 10.2376 22 6.10256 22 5.52923C22 4.95423 21.8842 3.97839 21.2483 3.6909C20.6992 3.44256 19.8617 3.17423 17.665 4.72423C15.3717 6.34506 12.9058 9.62756 12 11.3884Z"></path></svg></a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<nav id = 'top-navmenu'>
|
||||
<nav class = 'navmenu'>
|
||||
<div class = 'nav-head'> <div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'closediv'>
|
||||
<span class = 'close' title = 'close'></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class = 'nav-body'>
|
||||
<div class = 'topics'>
|
||||
<h2>Topics</h2>
|
||||
|
||||
<p><a href = '/architecture'>Architecture</a></p>
|
||||
|
||||
<p><a href = 'https://refactoring.com'>Refactoring</a></p>
|
||||
|
||||
<p><a href = '/agile.html'>Agile</a></p>
|
||||
|
||||
<p><a href = '/delivery.html'>Delivery</a></p>
|
||||
|
||||
<p><a href = '/microservices'>Microservices</a></p>
|
||||
|
||||
<p><a href = '/data'>Data</a></p>
|
||||
|
||||
<p><a href = '/testing'>Testing</a></p>
|
||||
|
||||
<p><a href = '/dsl.html'>DSL</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'about'>
|
||||
<h2>about me</h2>
|
||||
|
||||
<p><a href = '/aboutMe.html'>About</a></p>
|
||||
|
||||
<p><a href = '/books'>Books</a></p>
|
||||
|
||||
<p><a href = '/faq.html'>FAQ</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'content'>
|
||||
<h2>content</h2>
|
||||
|
||||
<p><a href = '/videos.html'>Videos</a></p>
|
||||
|
||||
<p><a href = '/tags'>Content Index</a></p>
|
||||
|
||||
<p><a href = '/boardgames'>Board Games</a></p>
|
||||
|
||||
<p><a href = '/photos'>Photography</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'tw'>
|
||||
<h2>Thoughtworks</h2>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com'>Home</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/insights'>Insights</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/careers'>Careers</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/radar'>Radar</a></p>
|
||||
|
||||
<p><a href = 'https://www.thoughtworks.com/engineering'>Engineering</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'feeds'>
|
||||
<h2>follow</h2>
|
||||
|
||||
<p><a href = '/feed.atom'>RSS</a></p>
|
||||
|
||||
<p><a href = 'https://toot.thoughtworks.com/@mfowler'>Mastodon</a></p>
|
||||
|
||||
<p><a href = 'https://www.linkedin.com/in/martin-fowler-com/'>LinkedIn</a></p>
|
||||
|
||||
<p><a href = 'https://bsky.app/profile/martinfowler.com'>Bluesky</a></p>
|
||||
|
||||
<p><a href = 'https://www.twitter.com/martinfowler'>X</a></p>
|
||||
|
||||
<p><a href = 'https://boardgamegeek.com/blog/13064/martins-7th-decade'>BGG</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
|
||||
<main><h1 id="section">404</h1>
|
||||
|
||||
<p>I’m afraid this is not the document you’re looking for. Try using the
|
||||
search box above, and good luck.</p>
|
||||
</main>
|
||||
|
||||
<nav id = 'bottom-navmenu'>
|
||||
<nav class = 'navmenu'>
|
||||
<div class = 'nav-head'> <div class = 'search'>
|
||||
<!-- SiteSearch Google -->
|
||||
<form method='GET' action="https://www.google.com/search">
|
||||
<input type='hidden' name='ie' value='UTF-8'/>
|
||||
<input type='hidden' name='oe' value='UTF-8'/>
|
||||
<input class = 'field' type='text'
|
||||
name='q' size='15' maxlength='255' value=""/>
|
||||
<button class = 'button' type='submit'
|
||||
name='btnG' value=" " title = "Search"/>
|
||||
<input type='hidden' name='domains' value="martinfowler.com"/>
|
||||
<input type='hidden' name='sitesearch' value=""/>
|
||||
<input
|
||||
type='hidden' name='sitesearch' value="martinfowler.com"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class = 'closediv'>
|
||||
<span class = 'close' title = 'close'></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class = 'nav-body'>
|
||||
<div class = 'topics'>
|
||||
<h2>Topics</h2>
|
||||
|
||||
<p><a href = '/architecture'>Architecture</a></p>
|
||||
|
||||
<p><a href = 'https://refactoring.com'>Refactoring</a></p>
|
||||
|
||||
<p><a href = '/agile.html'>Agile</a></p>
|
||||
|
||||
<p><a href = '/delivery.html'>Delivery</a></p>
|
||||
|
||||
<p><a href = '/microservices'>Microservices</a></p>
|
||||
|
||||
<p><a href = '/data'>Data</a></p>
|
||||
|
||||
<p><a href = '/testing'>Testing</a></p>
|
||||
|
||||
<p><a href = '/dsl.html'>DSL</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'about'>
|
||||
<h2>about me</h2>
|
||||
|
||||
<p><a href = '/aboutMe.html'>About</a></p>
|
||||
|
||||
<p><a href = '/books'>Books</a></p>
|
||||
|
||||
<p><a href = '/faq.html'>FAQ</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'content'>
|
||||
<h2>content</h2>
|
||||
|
||||
<p><a href = '/videos.html'>Videos</a></p>
|
||||
|
||||
<p><a href = '/tags'>Content Index</a></p>
|
||||
|
||||
<p><a href = '/boardgames'>Board Games</a></p>
|
||||
|
||||
<p><a href = '/photos'>Photography</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'tw'>
|
||||
<h2>Thoughtworks</h2>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com'>Home</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/insights'>Insights</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/careers'>Careers</a></p>
|
||||
|
||||
<p><a href = 'https://thoughtworks.com/radar'>Radar</a></p>
|
||||
|
||||
<p><a href = 'https://www.thoughtworks.com/engineering'>Engineering</a></p>
|
||||
</div>
|
||||
|
||||
<div class = 'feeds'>
|
||||
<h2>follow</h2>
|
||||
|
||||
<p><a href = '/feed.atom'>RSS</a></p>
|
||||
|
||||
<p><a href = 'https://toot.thoughtworks.com/@mfowler'>Mastodon</a></p>
|
||||
|
||||
<p><a href = 'https://www.linkedin.com/in/martin-fowler-com/'>LinkedIn</a></p>
|
||||
|
||||
<p><a href = 'https://bsky.app/profile/martinfowler.com'>Bluesky</a></p>
|
||||
|
||||
<p><a href = 'https://www.twitter.com/martinfowler'>X</a></p>
|
||||
|
||||
<p><a href = 'https://boardgamegeek.com/blog/13064/martins-7th-decade'>BGG</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
<footer id='page-footer'>
|
||||
<div class='tw-logo'>
|
||||
<a href='https://www.thoughtworks.com/engineering'>
|
||||
<img src='/thoughtworks_white.png'>
|
||||
</a>
|
||||
</div>
|
||||
<div class='menu-button'>
|
||||
<div class='icon-bars navmenu-button'></div>
|
||||
</div>
|
||||
<div class='copyright'>
|
||||
<p>© Martin Fowler | <a href="/aboutMe.html#disclosures">Disclosures</a></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src = '/jquery-1.11.3.min.js' type = 'text/javascript'></script>
|
||||
|
||||
<script src = '/mfcom.js' type = 'text/javascript'></script>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 305 KiB |
|
After Width: | Height: | Size: 120 KiB |
|
After Width: | Height: | Size: 337 KiB |
|
After Width: | Height: | Size: 286 KiB |
|
After Width: | Height: | Size: 139 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 47 KiB |
@@ -0,0 +1,142 @@
|
||||
---
|
||||
title: Anthropic Harness 设计
|
||||
tags: [核心概念, 架构, 智能体]
|
||||
source: [Anthropic]
|
||||
confidence_score: 高
|
||||
last_updated: 2026-04-07
|
||||
---
|
||||
|
||||
# Anthropic Harness 设计
|
||||
|
||||
**Anthropic Harness 设计**是 Anthropic 团队 Prithvi Rajasekaran 提出的多智能体架构,用于长时间运行的应用开发。该设计受生成对抗网络(GAN)启发,使用**生成器**和**评估器**智能体的组合。
|
||||
|
||||
## 问题背景
|
||||
|
||||
### 朴素实现的不足
|
||||
|
||||
之前的工作已经表明,Harness 设计对长时间运行的智能体编码的有效性有重大影响。但对于更复杂的任务,智能体仍然倾向于随着时间推移偏离轨道。观察到两种常见的失败模式:
|
||||
|
||||
1. **上下文窗口填充和"上下文焦虑"**:模型在冗长任务上随着上下文窗口填充而失去连贯性。一些模型还表现出"上下文焦虑",当它们接近认为的上下文限制时会提前结束工作。
|
||||
|
||||
2. **自我评估问题**:当被要求评估它们自己生成的作品时,智能体倾向于自信地赞扬作品——即使,对于人类观察者来说,质量明显平庸。这个问题对于主观任务(如设计)特别明显,没有二进制检查相当于可验证的软件测试。
|
||||
|
||||
## 核心架构
|
||||
|
||||
### 三智能体系统
|
||||
|
||||
Anthropic 最终构建了一个三智能体系统,每个智能体解决先前运行中观察到的特定差距:
|
||||
|
||||
| 角色 | 职责 |
|
||||
|------|------|
|
||||
| **Planner(规划者)** | 将简单的 1-4 句话提示扩展为完整的产品规格 |
|
||||
| **Generator(生成者)** | 一次一个功能地实现规格,带有 git 版本控制 |
|
||||
| **Evaluator(评估器)** | 使用 Playwright MCP 测试运行中的应用,分级并提供详细反馈 |
|
||||
|
||||
### 上下文重置 vs 压缩
|
||||
|
||||
**上下文重置**:清空上下文窗口并启动一个新的智能体,结合携带先前智能体状态和下一步的结构化交接。
|
||||
|
||||
**上下文压缩**:将对话的早期部分就地摘要,以便同一个智能体可以在缩短的历史上继续。
|
||||
|
||||
虽然压缩保留了连续性,但它没有给智能体一个干净的状态,这意味着上下文焦虑仍然可能存在。重置提供了一个干净的状态,但代价是交接工件必须有足够的状态让下一个智能体干净地接手工作。
|
||||
|
||||
在早期测试中,发现 Claude Sonnet 4.5 表现出足够强的上下文焦虑,以至于仅靠压缩不足以实现良好的长任务性能,因此上下文重置成为 Harness 设计的必要条件。
|
||||
|
||||
## 前端设计:使主观质量可分级
|
||||
|
||||
### 两个洞见
|
||||
|
||||
1. 虽然美学不能完全简化为分数——而且个人品味总是会变化——但它们可以通过编码设计原则和偏好的分级标准来改善。
|
||||
2. 通过将前端生成与前端分级分离,可以创建一个推动生成器朝着更强输出发展的反馈循环。
|
||||
|
||||
### 四个分级标准
|
||||
|
||||
| 标准 | 描述 |
|
||||
|------|------|
|
||||
| **设计质量** | 设计感觉像是一个连贯的整体而不是部分的集合吗? |
|
||||
| **原创性** | 是否有自定义决策的证据,还是只是模板布局、库默认值和 AI 生成的模式? |
|
||||
| **工艺** | 技术执行:排版层次结构、间距一致性、色彩和谐、对比度。 |
|
||||
| **功能性** | 独立于美学的可用性。用户能理解界面做什么吗? |
|
||||
|
||||
强调设计质量和原创性超过工艺和功能性。Claude 已经默认在工艺和功能性上得分很高,因为所需的技术能力往往自然而然地出现在模型中。但在设计和原创性上,Claude 经常产生充其量是乏味的输出。
|
||||
|
||||
### 生成-评估循环
|
||||
|
||||
构建在 Claude Agent SDK 上的循环:
|
||||
|
||||
1. 生成器智能体首先根据用户提示创建 HTML/CSS/JS 前端
|
||||
2. 给予评估器 Playwright MCP,让它在评分每个标准并编写详细批评之前直接与实时页面交互
|
||||
3. 该反馈流回生成器作为下一次迭代的输入
|
||||
4. 每次生成运行 5 到 15 次迭代
|
||||
|
||||
在每次评估后,指示生成器做出战略决策:如果分数趋势良好则改进当前方向,或者如果方法不起作用则转向完全不同的美学。
|
||||
|
||||
## 扩展到全栈编码
|
||||
|
||||
### 架构演变
|
||||
|
||||
Opus 4.5 基本上自行消除了上下文焦虑行为,因此可以完全从 Harness 中删除上下文重置。智能体作为一个连续会话在整个构建中运行,Claude Agent SDK 的自动压缩处理沿途的上下文增长。
|
||||
|
||||
### 冲刺契约
|
||||
|
||||
在每个冲刺之前,生成器和评估器协商一个**冲刺契约**:在编写任何代码之前就该工作块的"完成"看起来像什么达成一致。
|
||||
|
||||
这存在是因为产品规格故意是高级的,需要一个步骤来弥合用户故事和可测试实现之间的差距。生成器提议它将构建什么以及如何验证成功,评估器审查该提议以确保生成器正在构建正确的东西。两者迭代直到达成一致。
|
||||
|
||||
### 结果对比
|
||||
|
||||
使用"创建一个带有关卡编辑器、精灵编辑器、实体行为和可玩测试模式的 2D 复古游戏制作器"提示进行的测试:
|
||||
|
||||
| Harness | 持续时间 | 成本 |
|
||||
|---------|---------|------|
|
||||
| Solo | 20 分钟 | $9 |
|
||||
| 完整 Harness | 6 小时 | $200 |
|
||||
|
||||
Harness 贵了 20 多倍,但输出质量的差异立即显而易见。
|
||||
|
||||
## Harness 简化迭代
|
||||
|
||||
### 移除冲刺构造
|
||||
|
||||
从 Harness 中完全移除了冲刺构造。保留了规划器和评估器,因为每个都继续增加明显的价值。将评估器移动到运行结束时的单次通过,而不是每个冲刺分级。
|
||||
|
||||
### 模型改进的影响
|
||||
|
||||
Opus 4.6 的发布提供了进一步减少 Harness 复杂性的动力。Opus 4.6 更仔细地规划、更长时间地维持智能体任务、可以在更大的代码库中更可靠地操作,并且具有更好的代码审查和调试技能来捕捉自己的错误。它还在长上下文检索方面有了实质性改进。
|
||||
|
||||
### 更新后的 Harness 结果
|
||||
|
||||
使用"使用 Web Audio API 在浏览器中构建功能完整的 DAW"提示进行的测试:
|
||||
|
||||
- 总持续时间:约 4 小时
|
||||
- 总成本:$124.70
|
||||
|
||||
大部分时间花在构建器上,它在没有 Opus 4.5 所需的冲刺分解的情况下连贯运行了两个多小时。
|
||||
|
||||
## 关键经验教训
|
||||
|
||||
随着模型继续改进,可以大致期望它们能够工作更长时间,处理更复杂的任务。在某些情况下,这将意味着随着时间推移,模型周围的支架变得不那么重要,开发人员可以等待下一个模型并看到某些问题自行解决。另一方面,模型越好,开发能够实现超出模型在基线水平所能做到的复杂任务的 Harness 的空间就越大。
|
||||
|
||||
有几个经验教训值得向前推进:
|
||||
|
||||
1. 用你正在构建的模型进行实验总是好的做法
|
||||
2. 在处理更复杂的任务时,有时可以通过分解任务并将专门的智能体应用于问题的每个方面来获得提升
|
||||
3. 当新模型落地时,重新检查 Harness 通常是好的做法,剥离那些不再对性能有负载作用的部分,并添加新部分以实现以前可能无法实现的更大能力
|
||||
|
||||
## 相关概念
|
||||
|
||||
- [[Harness-Engineering|Harness 工程]]
|
||||
- [[Generator-Evaluator Loop|生成-评估循环]]
|
||||
- [[Context Reset|上下文重置]]
|
||||
- [[Planner|规划者]]
|
||||
- [[Generator|生成者]]
|
||||
- [[Evaluator|评估者]]
|
||||
|
||||
## 参考来源
|
||||
|
||||
1. Anthropic - Harness design for long-running application development
|
||||
|
||||
---
|
||||
|
||||
*最后更新:2026-04-07*
|
||||
*本文档由 [[WikiLLM]] 编译*
|
||||
@@ -0,0 +1,106 @@
|
||||
---
|
||||
title: 架构约束
|
||||
tags: [核心概念, 架构, Harness]
|
||||
source: [OpenAI, Martin Fowler, NxCode]
|
||||
confidence_score: 高
|
||||
last_updated: 2026-04-07
|
||||
---
|
||||
|
||||
# 架构约束
|
||||
|
||||
**架构约束**(Architectural Constraints)是[[Harness-Engineering|Harness 工程]]的三大支柱之一。这是 Harness 工程与传统 AI 提示最显著不同的地方。与其告诉智能体"编写好代码",不如**机械地强制执行好代码的样子**。
|
||||
|
||||
## 核心思想
|
||||
|
||||
### 约束反而提升生产力
|
||||
|
||||
矛盾的是,约束解决方案空间使智能体**更有生产力**,而不是更少。当智能体可以生成任何东西时,它会浪费 token 探索死胡同。当 Harness 定义清晰的边界时,智能体会更快地收敛到正确的解决方案。
|
||||
|
||||
### 为智能体优化代码库可读性
|
||||
|
||||
由于代码仓库完全由智能体生成,因此首先针对 Codex 的可读性进行了优化。就像团队会努力提升代码对新入职工程师的可导航性一样,人类工程师的目标也是让智能体能够直接从代码仓库推理出完整的业务领域。
|
||||
|
||||
从智能体的角度来看,它在运行时无法在情境中访问的任何内容都是不存在的。存储在 Google Docs、聊天记录或人们头脑中的知识都无法被系统访问。代码仓库本地的、已版本化的工件(例如,代码、Markdown、模式、可执行计划)就是它所能看到的全部。
|
||||
|
||||
## 分层领域架构
|
||||
|
||||
OpenAI 围绕一个严格的架构模型构建了应用。每个业务领域都划分为一组固定的层,依赖方向经过严格验证,并且仅允许有限的一组边。这些约束是通过自定义的 linter(当然是由 Codex 生成的!)和结构测试机械地强制执行的。
|
||||
|
||||

|
||||
|
||||
### 依赖分层规则
|
||||
|
||||
在每个业务领域内(例如应用设置),代码只能"向前"依赖于一组固定的层:
|
||||
|
||||
```
|
||||
Types → Config → Repo → Service → Runtime → UI
|
||||
```
|
||||
|
||||
横切关注点(认证、连接器、遥测、功能标志)通过一个单一的显式接口进入:Providers。其他任何内容都不被允许,并将通过自动化方式强制执行。
|
||||
|
||||
这种架构通常要等到你拥有数百名工程师时才会推迟。对于编码智能体来说,这是一个早期的先决条件:有了约束,速度才不会下降,架构才不会漂移。
|
||||
|
||||
## 约束强制执行工具
|
||||
|
||||
### 1. 确定性 Linters
|
||||
|
||||
自定义规则,自动标记违规。由于这些 lint 是自定义的,编写错误信息时会在智能体情境中注入修复指令。
|
||||
|
||||
在以人为本的工作流程中,这些规则可能会让人感到迂腐或束缚。有了智能体,它们就成了倍增器:一旦编码,它们就能立即应用于所有地方。
|
||||
|
||||
### 2. 基于 LLM 的审计员
|
||||
|
||||
审查其他智能体代码的架构合规性的智能体。
|
||||
|
||||
### 3. 结构测试
|
||||
|
||||
像 ArchUnit,但专门用于 AI 生成的代码。
|
||||
|
||||
### 4. 预提交钩子
|
||||
|
||||
在提交任何代码前的自动检查。
|
||||
|
||||
## 品味不变式
|
||||
|
||||
OpenAI 团队辅以一小组"品味不变式"。例如:
|
||||
|
||||
- 通过自定义 lint 静态地强制执行结构化日志记录
|
||||
- 模式和类型的命名约定
|
||||
- 文件大小限制
|
||||
- 特定平台的可靠性要求
|
||||
|
||||
## 明确界限
|
||||
|
||||
同时,还明确指出了哪些地方需要限制,哪些地方不需要限制。这类似于领导一个大型工程平台组织:在中央层面强制执行边界,在本地层面允许自主权。你非常重视界限、正确性和可重复性。在这些边界内,你允许团队或智能体在解决方案的表达方式上拥有很大的自由。
|
||||
|
||||
生成的代码不总是符合人类的风格偏好,这也没关系。只要输出是正确的、可维护的,并且对未来的智能体运行而言清晰易读,就可以算作达标。
|
||||
|
||||
## 依赖选择
|
||||
|
||||
这一框架明确了许多取舍。倾向于选择那些可以完全内化于在仓库中进行推理的依赖项和抽象。对智能体来说,通常被称为"枯燥"的技术,由于其可组合性、API 稳定性和在训练集里的表现,往往更容易建立模型。
|
||||
|
||||
在某些情况下,让智能体重新实现部分功能子集比绕过公共库中不透明的上游行为更便宜。例如,OpenAI 团队没有引入通用的 p-limit 风格包,而是投入使用了他们自己的带并发的 map 辅助函数:它与他们的 OpenTelemetry 仪表紧密集成,具备 100% 的测试覆盖率,并且其行为完全符合他们的运行时预期。
|
||||
|
||||
将系统的更多部分转化为智能体可以检查、验证并直接修改的形式,可以直接提高杠杆效应——这不仅适用于 Codex,也适用于其他智能体也在参与代码库的开发。
|
||||
|
||||
## 强制执行不变量
|
||||
|
||||
仅靠文档本身,是没法保持完全由智能体生成的代码库的连贯性的。通过强制执行不变量,而非对实施过程进行微观管理,令智能体能够快速交付,而且不会削弱基础。例如,要求 Codex 在边界处解析数据形状,但不规定具体实现方式(模型似乎偏好 Zod,但没有指定特定库)。
|
||||
|
||||
## 相关概念
|
||||
|
||||
- [[Harness-Engineering|Harness 工程]]
|
||||
- [[Context-Engineering|上下文工程]]
|
||||
- [[Entropy Management|熵管理]]
|
||||
- [[Layered Domain Architecture|分层领域架构]]
|
||||
|
||||
## 参考来源
|
||||
|
||||
1. OpenAI - Harness Engineering:在智能体优先的世界中利用 Codex
|
||||
2. Martin Fowler - Harness engineering for coding agent users
|
||||
3. NxCode - Harness Engineering: The Complete Guide
|
||||
|
||||
---
|
||||
|
||||
*最后更新:2026-04-07*
|
||||
*本文档由 [[WikiLLM]] 编译自多个来源*
|
||||
@@ -0,0 +1,124 @@
|
||||
---
|
||||
title: 上下文工程
|
||||
tags: [核心概念, 上下文, Harness]
|
||||
source: [OpenAI, Anthropic, LangChain]
|
||||
confidence_score: 高
|
||||
last_updated: 2026-04-07
|
||||
---
|
||||
|
||||
# 上下文工程
|
||||
|
||||
**上下文工程**(Context Engineering)是[[Harness-Engineering|Harness 工程]]的三大支柱之一,专注于确保智能体在正确的时间获得正确的信息。
|
||||
|
||||
## 核心原则
|
||||
|
||||
### 给地图,而不是一千页说明书
|
||||
|
||||
OpenAI 团队学到的最早经验之一很简单:要给 Codex 的是一张地图,而不是一本 1,000 页的说明书。
|
||||
|
||||
他们尝试了"一个大型的 AGENTS.md 方法。可想而知,这是一次失败的尝试:
|
||||
|
||||
- **上下文是一种稀缺资源**:一个巨大的指令文件会挤掉任务、代码和相关文档——因此智能体要么会错过关键约束条件,要么开始针对错误的约束条件进行优化。
|
||||
- **过多的指导反而变得无效**:当一切都"重要"时,一切都不重要了。智能体最终会在本地进行模式匹配,而不是有意识地进行导航。
|
||||
- **它会立即腐烂**:一本庞杂的手册会变成陈旧规则的坟场。智能体无法判断哪些信息仍然有效,一旦人类停止维护它,此文件就会悄然成为一个颇具吸引力的麻烦源头。
|
||||
- **这很难核实**:单个 blob 不适合进行机械检查(覆盖率、新鲜度、所有权、交叉链接),因此漂移是不可避免的。
|
||||
|
||||
因此,他们不再将 AGENTS.md 视为百科全书,而是将其视为内容目录。
|
||||
|
||||
## 静态上下文与动态上下文
|
||||
|
||||
### 静态上下文
|
||||
|
||||
静态上下文是仓库中不会频繁变化的文档和规范:
|
||||
|
||||
- **仓库本地文档**:架构规范、API 契约、风格指南
|
||||
- **AGENTS.md 或 CLAUDE.md 文件**:编码项目特定规则
|
||||
- **交叉链接设计文档**:由 linter 验证的设计文档
|
||||
|
||||
### 动态上下文
|
||||
|
||||
动态上下文是随时间变化的运行时信息:
|
||||
|
||||
- **可观测性数据**:日志、指标、追踪——智能体可访问
|
||||
- **目录结构映射**:智能体启动时的目录映射
|
||||
- **CI/CD 流水线状态**:测试结果和流水线状态
|
||||
|
||||
## 关键规则
|
||||
|
||||
**从智能体的角度来看,它无法在上下文中访问的任何内容都不存在。**
|
||||
|
||||
存储在 Google Docs、Slack 线程或人们头脑中的知识对系统是不可见的。**仓库必须是单一事实来源。**
|
||||
|
||||
### 渐进式披露
|
||||
|
||||
这个框架实现了渐进式披露:智能体从一个小而稳定的切入点开始,并被指导下一步该去哪里查看,而不是一开始就被淹没。
|
||||
|
||||
OpenAI 团队严格执行这一点。专职的 linter 和 CI 作业会验证知识库的更新状况、是否已交叉链接且结构正确。一个定期运行的"doc-gardening"智能体会扫描那些不再反映真实代码行为的过时或废弃文档,并发起修复用的 Pull Request。
|
||||
|
||||
## 实践中的上下文工程
|
||||
|
||||
### OpenAI 的知识库布局
|
||||
|
||||
```
|
||||
AGENTS.md
|
||||
ARCHITECTURE.md
|
||||
docs/
|
||||
├── design-docs/
|
||||
│ ├── index.md
|
||||
│ ├── core-beliefs.md
|
||||
│ └── ...
|
||||
├── exec-plans/
|
||||
│ ├── active/
|
||||
│ ├── completed/
|
||||
│ └── tech-debt-tracker.md
|
||||
├── generated/
|
||||
│ └── db-schema.md
|
||||
├── product-specs/
|
||||
│ ├── index.md
|
||||
│ ├── new-user-onboarding.md
|
||||
│ └── ...
|
||||
├── references/
|
||||
│ ├── design-system-reference-llms.txt
|
||||
│ ├── nixpacks-llms.txt
|
||||
│ ├── uv-llms.txt
|
||||
│ └── ...
|
||||
├── DESIGN.md
|
||||
├── FRONTEND.md
|
||||
├── PLANS.md
|
||||
├── PRODUCT_SENSE.md
|
||||
├── QUALITY_SCORE.md
|
||||
├── RELIABILITY.md
|
||||
└── SECURITY.md
|
||||
```
|
||||
|
||||
设计文档已被编目和索引,其中包括验证状态和一套核心理念,定义了智能体优先的操作原则。架构文档提供域和包分层的顶层地图。一份高质量的文档会对每个产品领域和架构层进行评分,并随着时间的推移追踪差距。
|
||||
|
||||
计划被视为一流的工件。临时轻量计划用于小幅变更,而复杂工作则记录在执行计划中,并附带进度和决策日志,这些日志会被提交到代码仓库。活跃计划、已完成计划和已知的技术债务都已进行版本控制并集中存放,使智能体能够在不依赖外部情境的情况下运行。
|
||||
|
||||
### LangChain 的 LocalContextMiddleware
|
||||
|
||||
LangChain 使用 `LocalContextMiddleware` 在智能体启动时运行,映射 `cwd` 和其他父+子目录。他们运行 `bash` 命令来查找工具如 `Python` 安装。上下文发现和搜索容易出错,因此注入上下文减少了这个错误表面并帮助**将智能体引导到其环境中。**
|
||||
|
||||
## 将更多情境推送到仓库中
|
||||
|
||||
随着时间的推移,需要将越来越多的情境推送到仓库中。那次让团队在架构模式上达成一致的 Slack 讨论?如果智能体无法发现它,那么它就会像迟了三个月入职的新员工一样,对其一无所知。
|
||||
|
||||
为 Codex 提供更多情境意味着要组织和展示正确的信息,好令智能体能够基于这些信息进行推理,而不是用临时指令使其不堪重负。就像你会在产品原则、工程规范和团队文化(包括表情符号偏好)方面为新队友提供引导一样,将这些信息提供给智能体会带来更一致的输出。
|
||||
|
||||
## 相关概念
|
||||
|
||||
- [[Harness-Engineering|Harness 工程]]
|
||||
- [[Context Reset|上下文重置]]
|
||||
- [[Context Anxiety|上下文焦虑]]
|
||||
- [[Architectural-Constraints|架构约束]]
|
||||
|
||||
## 参考来源
|
||||
|
||||
1. OpenAI - Harness Engineering:在智能体优先的世界中利用 Codex
|
||||
2. LangChain - Improving Deep Agents with harness engineering
|
||||
3. Anthropic - Effective context engineering for AI agents
|
||||
|
||||
---
|
||||
|
||||
*最后更新:2026-04-07*
|
||||
*本文档由 [[WikiLLM]] 编译自多个来源*
|
||||
@@ -0,0 +1,137 @@
|
||||
---
|
||||
title: Harness 工程
|
||||
tags: [核心概念, Harness, 架构]
|
||||
source: [OpenAI, Anthropic, Martin Fowler, LangChain, NxCode]
|
||||
confidence_score: 高
|
||||
last_updated: 2026-04-07
|
||||
---
|
||||
|
||||
# Harness 工程
|
||||
|
||||
**Harness 工程**(Harness Engineering)是设计和实现使 AI 智能体可靠工作的系统的新学科。如果说 2025 年是 AI 智能体验证它们能够编写代码的一年,那么 2026 年就是我们认识到**智能体不是难点——Harness 才是**的一年。
|
||||
|
||||
## 核心定义
|
||||
|
||||
### 什么是 Harness?
|
||||
|
||||
术语 "Harness" 来源于马具——缰绳、马鞍、马嚼子——用于引导强大但不可预测的动物朝正确方向前进的全套设备。这个比喻是有意为之的:
|
||||
|
||||
- **马**是 AI 模型——强大、快速,但自己不知道要去哪里
|
||||
- **Harness**是基础设施——约束、护栏、反馈循环,用于高效地引导模型的能力
|
||||
- **骑手**是人类工程师——提供方向,而不是亲自奔跑
|
||||
|
||||
没有 Harness,AI 智能体就像开放田野里的纯种马。快速、令人印象深刻,但对于完成任何事情来说完全无用。
|
||||
|
||||
### Harness 工程的正式定义
|
||||
|
||||
**Harness 工程**是设计和实现以下系统的学科:
|
||||
|
||||
1. **约束** AI 智能体可以做什么(架构边界、依赖规则)
|
||||
2. **告知** 智能体应该做什么(上下文工程、文档)
|
||||
3. **验证** 智能体正确执行了(测试、linting、CI 验证)
|
||||
4. **纠正** 智能体出错时(反馈循环、自我修复机制)
|
||||
|
||||
Martin Fowler 将其描述为"我们可以用来控制 AI 智能体的工具和实践"——但它不仅仅是安全。一个好的 Harness 使智能体**更有能力**,而不仅仅是更受控制。
|
||||
|
||||
## 为什么 Harness 工程现在如此重要
|
||||
|
||||
### 模型是商品,Harness 是护城河
|
||||
|
||||
AI 行业正面临一个令人不安的事实:**底层模型的重要性不如围绕它的系统。**
|
||||
|
||||
LangChain 明确证明了这一点。他们的编码智能体在 Terminal Bench 2.0 上从 **52.8% 提升到 66.5%**——从 **Top 30 跃升至 Top 5**——对模型没有做任何改变。他们只改变了 Harness:
|
||||
|
||||
| 改变 | 他们做了什么 | 影响 |
|
||||
|------|-------------|------|
|
||||
| 自我验证循环 | 添加完成前检查清单中间件 | 在提交前捕获错误 |
|
||||
| 上下文工程 | 启动时映射目录结构 | 智能体从一开始就理解代码库 |
|
||||
| 循环检测 | 跟踪重复的文件编辑 | 防止"末日循环" |
|
||||
| 推理三明治 | 规划/验证使用高推理,实现使用中等推理 | 在时间预算内获得更好的质量 |
|
||||
|
||||
**相同的模型。不同的 Harness。显著更好的结果。**
|
||||
|
||||
### OpenAI 的 100 万行代码证明点
|
||||
|
||||
OpenAI 的实验是迄今为止最令人信服的证据:
|
||||
|
||||
- **5 个月**的开发
|
||||
- 最终产品中有 **100 万+ 行代码**
|
||||
- **零行手动编写的代码**——每一行都是由 Codex 智能体生成的
|
||||
- **用人类所需时间的约 1/10 构建**
|
||||
- 产品有**内部日常用户和外部 Alpha 测试者**
|
||||
- 它**交付、部署、出故障并得到修复**——全部由 Harness 内的智能体完成
|
||||
|
||||
工程师的工作?设计 Harness。指定意图。提供反馈。不是编写代码。
|
||||
|
||||
## 三大支柱
|
||||
|
||||
OpenAI 的框架将 Harness 工程组织为三个核心类别:
|
||||
|
||||
### 1. 上下文工程
|
||||
|
||||
上下文工程是关于确保智能体在正确的时间获得正确的信息。
|
||||
|
||||
**静态上下文:**
|
||||
- 仓库本地文档(架构规范、API 契约、风格指南)
|
||||
- 编码项目特定规则的 `AGENTS.md` 或 `CLAUDE.md` 文件
|
||||
- 由 linter 验证的交叉链接设计文档
|
||||
|
||||
**动态上下文:**
|
||||
- 智能体可访问的可观测性数据(日志、指标、追踪)
|
||||
- 智能体启动时的目录结构映射
|
||||
- CI/CD 流水线状态和测试结果
|
||||
|
||||
**关键规则:** 从智能体的角度来看,它无法在上下文中访问的任何内容都不存在。Google Docs、Slack 线程或人们头脑中的知识对系统是不可见的。**仓库必须是单一事实来源。**
|
||||
|
||||
### 2. 架构约束
|
||||
|
||||
这是 Harness 工程与传统 AI 提示最显著不同的地方。与其告诉智能体"编写好代码",不如**机械地强制执行好代码的样子**。
|
||||
|
||||
**依赖分层:**
|
||||
```
|
||||
Types → Config → Repo → Service → Runtime → UI
|
||||
```
|
||||
|
||||
每层只能从其左侧的层导入。这不是建议——它由结构测试和 CI 验证强制执行。
|
||||
|
||||
**约束强制执行工具:**
|
||||
- **确定性 linters**——自动标记违规的自定义规则
|
||||
- **基于 LLM 的审计员**——审查其他智能体代码的架构合规性
|
||||
- **结构测试**——像 ArchUnit,但用于 AI 生成的代码
|
||||
- **预提交钩子**——在提交任何代码前的自动检查
|
||||
|
||||
**为什么约束能改善输出:** 矛盾的是,约束解决方案空间使智能体**更有生产力**,而不是更少。当智能体可以生成任何东西时,它会浪费 token 探索死胡同。当 Harness 定义清晰的边界时,智能体会更快地收敛到正确的解决方案。
|
||||
|
||||
### 3. 熵管理("垃圾回收")
|
||||
|
||||
这是最被低估的组件。随着时间的推移,AI 生成的代码库会积累熵——文档与现实脱节、命名约定分歧、死代码堆积。
|
||||
|
||||
Harness 工程通过**定期清理智能体**来解决这个问题:
|
||||
- **文档一致性智能体**——验证文档与当前代码匹配
|
||||
- **约束违规扫描器**——找到逃过早期检查的代码
|
||||
- **模式强制执行智能体**——识别并修复与既定模式的偏差
|
||||
- **依赖审计员**——跟踪并解决循环或不必要的依赖
|
||||
|
||||
这些智能体按计划运行——每日、每周,或由特定事件触发——保持代码库对人类审查者和未来 AI 智能体都健康。
|
||||
|
||||
## 相关概念
|
||||
|
||||
- [[Context-Engineering|上下文工程]]
|
||||
- [[Architectural-Constraints|架构约束]]
|
||||
- [[Entropy Management|熵管理]]
|
||||
- [[OpenAI Harness Engineering|OpenAI Harness 工程]]
|
||||
- [[Anthropic-Harness-Design|Anthropic Harness 设计]]
|
||||
- [[LangChain Harness Engineering|LangChain Harness 工程]]
|
||||
|
||||
## 参考来源
|
||||
|
||||
1. OpenAI - Harness Engineering:在智能体优先的世界中利用 Codex
|
||||
2. Anthropic - Harness design for long-running application development
|
||||
3. Martin Fowler - Harness engineering for coding agent users
|
||||
4. LangChain - Improving Deep Agents with harness engineering
|
||||
5. NxCode - Harness Engineering: The Complete Guide
|
||||
|
||||
---
|
||||
|
||||
*最后更新:2026-04-07*
|
||||
*本文档由 [[WikiLLM]] 编译自多个来源*
|
||||
@@ -0,0 +1,110 @@
|
||||
---
|
||||
title: 自我验证
|
||||
tags: [核心概念, 验证, Harness]
|
||||
source: [LangChain, Anthropic]
|
||||
confidence_score: 高
|
||||
last_updated: 2026-04-07
|
||||
---
|
||||
|
||||
# 自我验证
|
||||
|
||||
**自我验证**(Self-Verification)是[[Harness-Engineering|Harness 工程]]中的关键技术,使智能体能够通过运行中的反馈自我改进。当今的模型是卓越的自我改进机器,但它们没有自然地倾向于进入这种**构建-验证循环**。
|
||||
|
||||
## 核心概念
|
||||
|
||||
### 最常见的失败模式
|
||||
|
||||
LangChain 团队观察到的最常见失败模式是:智能体编写解决方案、重读自己的代码、确认看起来没问题,然后停止。
|
||||
|
||||
测试是自主智能体编码的关键部分。它有助于测试整体正确性,同时为智能体提供信号来进行爬山优化。
|
||||
|
||||
## 构建-验证循环
|
||||
|
||||
LangChain 向系统提示中添加了关于如何解决问题的指导:
|
||||
|
||||
### 阶段 1:规划与发现
|
||||
阅读任务、扫描代码库,并基于任务规格和如何验证解决方案构建初始计划。
|
||||
|
||||
### 阶段 2:构建
|
||||
在考虑验证的情况下实现计划。如果测试不存在则构建测试,并测试愉快路径和边缘情况。
|
||||
|
||||
### 阶段 3:验证
|
||||
运行测试、阅读完整输出、与要求的内容进行比较(而不是与你自己的代码)。
|
||||
|
||||
### 阶段 4:修复
|
||||
分析任何错误、重新访问原始规格,并修复问题。
|
||||
|
||||
## LangChain 的实现
|
||||
|
||||
### PreCompletionChecklistMiddleware
|
||||
|
||||
除了提示外,确定性上下文注入有助于智能体验证它们的工作。LangChain 使用 `PreCompletionChecklistMiddleware` 在智能体退出前拦截它,并提醒它对任务规格运行验证通过。
|
||||
|
||||
这类似于 [Ralph Wiggum Loop|Ralph Wiggum 循环]],其中一个钩子在智能体退出时强制其继续执行,用于验证。
|
||||
|
||||

|
||||
|
||||
### 强调测试
|
||||
|
||||
LangChain 真正专注于测试,因为它在每次迭代中推动变化。他们发现,测试必须是智能体工作流程的核心部分,而不是事后想法。
|
||||
|
||||
## 环境上下文工程
|
||||
|
||||
Harness 工程的一部分是**为上下文工程构建良好的交付机制。** Terminal Bench 任务带有目录结构、内置工具和严格的超时。
|
||||
|
||||
### 1. 目录上下文与工具
|
||||
`LocalContextMiddleware` 在智能体启动时运行,映射 `cwd` 和其他父+子目录。运行 `bash` 命令来查找工具如 `Python` 安装。上下文发现和搜索容易出错,因此注入上下文减少了这个错误表面并帮助**将智能体引导到其环境中。**
|
||||
|
||||
### 2. 教导智能体编写可测试的代码
|
||||
智能体不知道它们的代码需要如何可测试。添加提示说它们的工作将根据程序化测试来衡量,类似于提交代码时。例如,提及文件路径的任务规格应该被精确遵循,以便解决方案在自动化评分步骤中工作。强调边缘情况的提示有助于智能体避免仅检查"愉快路径"情况。强制模型符合测试标准是避免随着时间推移"烂泥堆积"的强大策略。
|
||||
|
||||
### 3. 时间预算
|
||||
注入时间预算警告以推动智能体完成工作并转向验证。智能体在时间估计方面是出了名的糟糕,因此这种启发式在这种环境中有所帮助。现实世界编码通常没有严格的时间限制,但如果不添加任何约束知识,智能体就不会在时间范围内工作。
|
||||
|
||||
## 循环检测
|
||||
|
||||
智能体一旦决定了一个计划就可能变得短视,导致"末日循环",对同一破碎方法进行小幅变异(在某些轨迹中超过 10 次以上)。
|
||||
|
||||
LangChain 使用 `LoopDetectionMiddleware`,通过工具调用钩子跟踪每个文件的编辑次数。它在对同一文件进行 `N` 次编辑后添加上下文如"……考虑重新考虑你的方法"。这可以帮助智能体从末日循环中恢复,尽管如果模型认为正确的话它可以继续沿着相同的路径前进。
|
||||
|
||||
重要提示:这是一种设计启发式,围绕当今感知的模型问题进行工程设计。随着模型改进,这些护栏可能会变得不必要,但今天帮助智能体正确和自主地执行。
|
||||
|
||||
## 推理三明治
|
||||
|
||||
推理模型可以自主运行数小时,因此必须决定在每个子任务上花费多少计算。你可以在每个任务上使用最大推理预算,但大多数工作可以从优化推理计算支出中受益。
|
||||
|
||||
Terminal Bench 超时限制创造了一个权衡。更多推理有助于智能体评估每个步骤,但可以燃烧超过 2 倍以上的 token/时间。`gpt-5.2-codex` 有 4 种推理模式,`low`、`medium`、`high` 和 `xhigh`。
|
||||
|
||||
LangChain 发现推理有助于规划以充分理解问题,一些 Terminal Bench 任务非常困难。一个好的计划有助于更快地得到可行的解决方案。
|
||||
|
||||
后期验证也从更多推理中受益,以捕获错误并提交解决方案。作为一种启发式,选择 xhigh-high-xhigh"**推理三明治**"作为基线。
|
||||
|
||||

|
||||
|
||||
**在规划和验证上花费更多的推理计算**
|
||||
|
||||
仅在 `xhigh` 运行由于智能体超时而得分较差,为 `53.9%`,相比之下在 `high` 为 `63.6%`。在推理预算分割的试验运行中没有大的差异,因此坚持使用他们的方法,将分数推到 `66.5%`。
|
||||
|
||||
## Harness 工程师的目的
|
||||
|
||||
**Harness 工程师的目的:准备和交付上下文,使智能体能够自主完成工作。**
|
||||
|
||||
智能体对其环境、约束和评估标准了解得越多,它们就能越好地自主自我指导工作。
|
||||
|
||||
## 相关概念
|
||||
|
||||
- [[Build-Verify Loop|构建-验证循环]]
|
||||
- [[Reasoning Sandwich|推理三明治]]
|
||||
- [[Doom Loop|末日循环]]
|
||||
- [[Loop Detection|循环检测]]
|
||||
- [[LangChain Harness Engineering|LangChain Harness 工程]]
|
||||
|
||||
## 参考来源
|
||||
|
||||
1. LangChain - Improving Deep Agents with harness engineering
|
||||
2. Anthropic - Harness design for long-running application development
|
||||
|
||||
---
|
||||
|
||||
*最后更新:2026-04-07*
|
||||
*本文档由 [[WikiLLM]] 编译自多个来源*
|
||||
@@ -0,0 +1,201 @@
|
||||
---
|
||||
title: 构建你的第一个 Harness
|
||||
tags: [实践指南, 入门, Harness]
|
||||
source: [NxCode, OpenAI, Martin Fowler]
|
||||
confidence_score: 高
|
||||
last_updated: 2026-04-07
|
||||
---
|
||||
|
||||
# 构建你的第一个 Harness
|
||||
|
||||
本文提供了构建 Harness 的实用框架,从个人开发者到工程组织的三个级别。
|
||||
|
||||
---
|
||||
|
||||
## Level 1:基础 Harness(单个开发者)
|
||||
|
||||
如果你正在为个人项目使用 Claude Code、Cursor 或 Codex:
|
||||
|
||||
### 需要设置的内容
|
||||
|
||||
- `CLAUDE.md` 或 `.cursorrules` 文件,包含项目约定
|
||||
- 用于 linting 和格式化的预提交钩子
|
||||
- 智能体可以运行以自我验证的测试套件
|
||||
- 具有一致命名的清晰目录结构
|
||||
|
||||
**设置时间:** 1-2 小时
|
||||
**影响:** 防止最常见的智能体错误
|
||||
|
||||
### 快速入门清单
|
||||
|
||||
1. **创建 CLAUDE.md**
|
||||
```markdown
|
||||
# 项目约定
|
||||
|
||||
## 代码风格
|
||||
- 使用 TypeScript,严格模式
|
||||
- 使用 2 空格缩进
|
||||
- 函数名使用驼峰命名
|
||||
|
||||
## 测试
|
||||
- 所有新代码必须有测试
|
||||
- 提交前运行 `npm test`
|
||||
|
||||
## 目录结构
|
||||
- src/ - 源代码
|
||||
- tests/ - 测试文件
|
||||
- docs/ - 文档
|
||||
```
|
||||
|
||||
2. **设置预提交钩子**
|
||||
```bash
|
||||
# 使用 husky 或 pre-commit
|
||||
npm install husky --save-dev
|
||||
npx husky install
|
||||
```
|
||||
|
||||
3. **确保测试存在**
|
||||
- 即使是简单的集成测试也比没有好
|
||||
- 智能体需要可以运行的东西来验证其工作
|
||||
|
||||
---
|
||||
|
||||
## Level 2:团队 Harness(小团队)
|
||||
|
||||
对于共享代码库的 3-10 名开发者的团队:
|
||||
|
||||
### 在 Level 1 基础上添加
|
||||
|
||||
- 包含团队范围约定的 `AGENTS.md`
|
||||
- CI 强制执行的架构约束
|
||||
- 常见任务的共享提示模板
|
||||
- 由 linter 验证的文档即代码
|
||||
- 专门针对智能体生成的 PR 的代码审查清单
|
||||
|
||||
**设置时间:** 1-2 天
|
||||
**影响:** 整个团队的智能体行为一致
|
||||
|
||||
### AGENTS.md 结构建议
|
||||
|
||||
```markdown
|
||||
# AGENTS.md
|
||||
|
||||
本文档包含智能体在此代码库中工作的约定。
|
||||
|
||||
## 1. 架构原则
|
||||
- 我们使用分层架构:Types → Config → Repo → Service → API
|
||||
- 不要跨层导入
|
||||
- 所有外部依赖通过 Providers 访问
|
||||
|
||||
## 2. 编码标准
|
||||
- [具体规则...]
|
||||
|
||||
## 3. 测试策略
|
||||
- [具体指南...]
|
||||
|
||||
## 4. 审查清单
|
||||
- [智能体在提交前应检查的内容...]
|
||||
```
|
||||
|
||||
### 共享提示模板
|
||||
|
||||
创建一个 `prompts/` 目录,包含常见任务:
|
||||
- `prompts/add-new-feature.md`
|
||||
- `prompts/fix-bug.md`
|
||||
- `prompts/write-tests.md`
|
||||
- `prompts/refactor-code.md`
|
||||
|
||||
---
|
||||
|
||||
## Level 3:生产 Harness(工程组织)
|
||||
|
||||
对于运行数十个并发智能体的组织:
|
||||
|
||||
### 在 Level 2 基础上添加
|
||||
|
||||
- 自定义中间件层(循环检测、推理优化)
|
||||
- 可观测性集成(智能体读取日志和指标)
|
||||
- 计划运行的熵管理智能体
|
||||
- Harness 版本控制和 A/B 测试
|
||||
- 智能体性能监控仪表板
|
||||
- 智能体陷入困境时的升级策略
|
||||
|
||||
**设置时间:** 1-2 周
|
||||
**影响:** 智能体作为自主贡献者运作
|
||||
|
||||
---
|
||||
|
||||
## 常见 Harness 工程错误
|
||||
|
||||
### 1. 过度工程化控制流
|
||||
|
||||
> "如果你过度工程化控制流,下一个模型更新会破坏你的系统。"
|
||||
|
||||
模型快速改进。2024 年需要复杂管道的能力现在由单个上下文窗口提示处理。构建你的 Harness 为**可剥离的**——当模型变得足够智能不需要时,你应该能够移除"智能"逻辑。
|
||||
|
||||
### 2. 将 Harness 视为静态的
|
||||
|
||||
Harness 需要随模型一起演进。当新模型版本改进推理时,你的推理优化中间件可能会适得其反。每次重大模型更新时审查和更新 Harness 组件。
|
||||
|
||||
### 3. 忽略文档层
|
||||
|
||||
最有影响力的 Harness 改进通常是最简单的:**更好的文档**。如果你的 `AGENTS.md` 含糊,你的智能体输出也会含糊。投资于精确、机器可读的文档,作为智能体的地面真理。
|
||||
|
||||
### 4. 没有反馈循环
|
||||
|
||||
没有反馈的 Harness 是一个笼子,而不是指南。智能体需要知道它何时成功何时失败。内置:
|
||||
- 任务完成前的自我验证步骤
|
||||
- 作为智能体工作流一部分的测试执行
|
||||
- 按任务类型的智能体成功率指标
|
||||
|
||||
### 5. 仅人类可读的文档
|
||||
|
||||
如果你的架构决策存在于人们的头脑中或智能体无法访问的 Confluence 页面中,Harness 就有差距。**智能体需要的一切都必须在仓库中。**
|
||||
|
||||
---
|
||||
|
||||
## 从哪里开始
|
||||
|
||||
### 如果你是单个开发者
|
||||
|
||||
1. 从 Level 1 开始
|
||||
2. 创建一个简单的 `CLAUDE.md`
|
||||
3. 设置基础预提交钩子
|
||||
4. 添加一个简单的测试套件
|
||||
5. 迭代——观察智能体失败的地方并加以修复
|
||||
|
||||
### 如果你是一个团队
|
||||
|
||||
1. 首先就 Level 1 基础达成一致
|
||||
2. 一起编写 `AGENTS.md` 的初稿
|
||||
3. 识别最常见的 3 个智能体失败模式
|
||||
4. 为这些模式构建前 3 个约束/检查
|
||||
5. 每 2 周回顾一次什么有效/什么无效
|
||||
|
||||
### 如果你是一个组织
|
||||
|
||||
1. 从一些试点团队开始
|
||||
2. 收集什么有效的模式
|
||||
3. 构建可重用的 Harness 组件库
|
||||
4. 投资于可观测性和指标
|
||||
5. 建立 Harness 迭代的反馈循环
|
||||
|
||||
---
|
||||
|
||||
## 相关概念
|
||||
|
||||
- [[Harness-Engineering|Harness 工程]]
|
||||
- [[Context-Engineering|上下文工程]]
|
||||
- [[Architectural-Constraints|架构约束]]
|
||||
- [[Mitchellh-Adoption-Journey|Mitchellh AI 采用之旅]]
|
||||
|
||||
## 参考来源
|
||||
|
||||
1. NxCode - Harness Engineering: The Complete Guide
|
||||
2. OpenAI - Harness Engineering:在智能体优先的世界中利用 Codex
|
||||
3. Martin Fowler - Harness engineering for coding agent users
|
||||
|
||||
---
|
||||
|
||||
*最后更新:2026-04-07*
|
||||
*本文档由 [[WikiLLM]] 编译自多个来源*
|
||||
@@ -0,0 +1,150 @@
|
||||
---
|
||||
title: Mitchellh AI 采用之旅
|
||||
tags: [实践指南, 采用路径, 个人工作流]
|
||||
source: [Mitchell Hashimoto]
|
||||
confidence_score: 高
|
||||
last_updated: 2026-04-07
|
||||
---
|
||||
|
||||
# Mitchellh AI 采用之旅
|
||||
|
||||
本文总结了 HashiCorp 创始人 Mitchell Hashimoto 的个人 AI 工具采用历程。他分享了从怀疑论者到深度用户的六个阶段,为其他开发者提供了实用的参考路径。
|
||||
|
||||
## 核心观点
|
||||
|
||||
> "我采用任何有意义的工具的经验是,我必然经历三个阶段:(1) 低效率时期 (2) 胜任时期,最后 (3) 工作流和生活改变发现时期。"
|
||||
|
||||
---
|
||||
|
||||
## 六个阶段
|
||||
|
||||
### 阶段 1:放弃聊天机器人
|
||||
|
||||
**立即停止尝试通过聊天机器人执行有意义的工作**(例如 ChatGPT、网页版 Gemini 等)。
|
||||
|
||||
聊天机器人确实有价值,而且是 Mitchell AI 工作流的日常组成部分,但它们在编码中的效用非常有限,因为你大多希望它们根据先前训练得出正确结果,而纠正它们涉及人类(你)反复告诉它们错了。这是低效的。
|
||||
|
||||
**关键点:**
|
||||
- 每个人的第一次 AI 体验都是聊天界面
|
||||
- 每个人第一次尝试用 AI 编码都是要求聊天界面写代码
|
||||
- 要找到价值,你**必须**使用**智能体**(Agent)
|
||||
|
||||
**什么是智能体?**
|
||||
智能体是行业采用的术语,指能够聊天并循环调用外部行为的 LLM。至少,智能体必须具备以下能力:
|
||||
- 读取文件
|
||||
- 执行程序
|
||||
- 发起 HTTP 请求
|
||||
|
||||
---
|
||||
|
||||
### 阶段 2:重现你自己的工作
|
||||
|
||||
Mitchell 最初尝试 Claude Code 时并没有留下深刻印象。他只是没有从会话中得到好的结果。他觉得必须润色它生成的所有内容,这个过程比他自己做要花更多时间。
|
||||
|
||||
**解决方案:**
|
||||
> "我没有放弃,而是**强迫自己用智能体重现所有手动提交**。我真的做了两次工作。我会手动完成工作,然后与智能体斗争以产生相同的质量和功能结果(当然,不让它看到我的手动解决方案)。"
|
||||
|
||||
**这是痛苦的**,因为它妨碍了简单地完成事情。但 Mitchell 从第一性原理中自己发现了别人已经在说的东西,但自己发现它产生了更强的基本理解:
|
||||
|
||||
1. 将会话分解为单独清晰、可操作的任务。不要试图在一个大型会话中"画猫头鹰"。
|
||||
2. 对于模糊的请求,将工作分成单独的规划与会话。
|
||||
3. 如果你给智能体验证其工作的方法,它往往会修复自己的错误并防止回归。
|
||||
|
||||
更一般地说,他还发现了智能体当时擅长什么、不擅长什么的边界,以及对于它们擅长的任务如何实现想要的结果。
|
||||
|
||||
所有这些都导致了显著的效率提升,以至于他开始自然地使用智能体,感觉不比自己做慢(但他仍然不觉得更快,因为他主要在照看智能体)。
|
||||
|
||||
---
|
||||
|
||||
### 阶段 3:日终智能体
|
||||
|
||||
为了尝试找到一些效率,Mitchell 开始了一个新模式:**每天划出最后 30 分钟来启动一个或多个智能体。**
|
||||
|
||||
他的假设是,如果智能体能在他无论如何都不能工作的时间里取得一些**积极进展**,也许他可以获得一些效率。基本上:与其试图在他拥有的时间里做更多,不如尝试在他没有的时间里做更多。
|
||||
|
||||
**发现的有价值的工作类别:**
|
||||
|
||||
1. **深度研究会话**:要求智能体调查某个领域,例如查找特定许可证类型的特定语言的所有库,并为每个库生成关于其优缺点、开发活动、社会情绪等的多页摘要。
|
||||
|
||||
2. **并行智能体尝试他没有时间开始的不同模糊想法**:不期望它们产生他会交付的东西,但也许可以在第二天他处理任务时阐明一些未知的未知。
|
||||
|
||||
3. **问题和 PR 分类/审查**:智能体擅长使用 `gh`(GitHub CLI),因此手动编写了一个快速方法来并行启动一堆来分类问题。不会允许智能体回复,只想要第二天的报告来尝试引导他走向高价值或低工作量的任务。
|
||||
|
||||
**结果:**
|
||||
他开始感觉自己比 AI 之前做的更多,哪怕只是一点点。
|
||||
|
||||
---
|
||||
|
||||
### 阶段 4:外包稳操胜券的任务
|
||||
|
||||
到了这个阶段,Mitchell 对他的 AI 擅长和不擅长什么任务非常有信心。他对某些任务 AI 会实现基本正确的解决方案有非常高的信心。
|
||||
|
||||
**所以旅程的下一步是:让智能体做所有这些工作,而他做其他任务。**
|
||||
|
||||
更具体地说:
|
||||
- 每天从查看前一晚分类智能体的结果开始
|
||||
- 手动过滤以找到智能体几乎肯定会很好解决的问题
|
||||
- 让它们在后台继续(一次一个,不是并行)
|
||||
|
||||
**同时,他做其他事情。** 不是去社交媒体(比平时不用 AI 更多),不是看视频等。他处于自己的、正常的、AI 之前的深度思考模式,处理他想做或必须做的事情。
|
||||
|
||||
**非常重要:关闭智能体桌面通知。** 上下文切换非常昂贵。为了保持效率,他发现作为人类控制何时中断智能体是他的工作,而不是相反。不要让智能体通知你。在工作的自然休息时间,切换标签检查它,然后继续。
|
||||
|
||||
**结果:**
|
||||
他坚定地处于"我无法回去"的境地。他觉得更有效率,但即使不是,他最喜欢的是他现在可以将编码和思考集中在他真正喜欢的任务上,同时仍然充分完成他不喜欢的任务。
|
||||
|
||||
---
|
||||
|
||||
### 阶段 5:设计 Harness
|
||||
|
||||
冒着陈述显而易见的风险:智能体在第一次产生正确结果时效率要高得多,或者最坏情况下产生需要最少润色的结果。实现这一点的最可靠方法是给智能体快速、高质量的工具来自动告诉它什么时候错了。
|
||||
|
||||
Mitchell 不知道是否有一个广泛的行业接受的术语,但他已经逐渐称之为"**Harness 工程**"。这是这样一种想法:任何时候你发现智能体犯了错误,你都花时间设计一个解决方案,使智能体永远不会再犯那个错误。
|
||||
|
||||
**这有两种形式:**
|
||||
|
||||
1. **更好的隐式提示(AGENTS.md)**:对于简单的事情,比如智能体反复运行错误的命令或找到错误的 API,更新 `AGENTS.md`(或等效文件)。每一行都是基于坏的智能体行为,并且几乎完全解决了所有问题。
|
||||
|
||||
2. **实际的编程工具**:例如,截图脚本、运行过滤测试等。这通常与 AGENTS.md 更改配对,让它知道这存在。
|
||||
|
||||
**这就是 Mitchell 今天所处的位置。** 他正在真诚地努力,每当看到智能体做坏事时,防止它再做那件坏事。或者,相反,他正在真诚地努力让智能体验证它们在做好事。
|
||||
|
||||
---
|
||||
|
||||
### 阶段 6:始终运行一个智能体
|
||||
|
||||
与阶段 5 同时,Mitchell 也在**始终运行一个智能体**的目标下运作。如果智能体没有运行,他会问自己:"现在有什么智能体可以为我做的吗?"
|
||||
|
||||
他特别喜欢将其与较慢、更深思熟虑的模型结合使用,比如 Amp 的 [deep mode](https://ampcode.com/news/deep-mode)(基本上只是 GPT-5.2-Codex),这可能需要 30 多分钟来做小的更改。另一面是它确实倾向于产生非常好的结果。
|
||||
|
||||
**重要说明:**
|
||||
- 他还没有运行多个智能体,目前也真的不想。
|
||||
- 他觉得现在有一个智能体运行是一个很好的平衡,既能做他觉得愉快的深度手动工作,又能照看他有点愚蠢但又神秘高效的机器人朋友。
|
||||
|
||||
"始终运行一个智能体"的目标仍然只是一个目标。他会说现在他在正常工作日的 10 到 20% 时间里有效地运行后台智能体。但他正在积极努力改善这一点。
|
||||
|
||||
> "我不想为了运行智能体而运行智能体。我只希望在有任务我认为对我真正有帮助时运行它们。这个目标的一部分挑战是改善我自己的工作流和工具,以便我能有源源不断的高质量工作可以委托。即使没有 AI,这也很重要!"
|
||||
|
||||
---
|
||||
|
||||
## 今天
|
||||
|
||||
这就是 Mitchell 今天所处的位置。
|
||||
|
||||
通过这段旅程,他个人已经达到了一个点,他在现代 AI 工具上取得了成功,并且相信他正在以基于现实的适当衡量观点来处理它。他真的不在乎 AI 是否会留下来,他是一个软件工匠,只是为了热爱而构建东西。
|
||||
|
||||
整个格局变化如此之快,他相信他会很快回头看这篇帖子,嘲笑自己的天真。但正如他们所说,如果你不能为过去的自己感到尴尬,你可能就没有成长。他只希望他会朝着正确的方向成长!
|
||||
|
||||
## 相关概念
|
||||
|
||||
- [[Harness-Engineering|Harness 工程]]
|
||||
- [[Agent|智能体]]
|
||||
|
||||
## 参考来源
|
||||
|
||||
1. Mitchell Hashimoto - My AI Adoption Journey
|
||||
|
||||
---
|
||||
|
||||
*最后更新:2026-04-07*
|
||||
*本文档由 [[WikiLLM]] 编译*
|
||||