一场 220 万的争议 链接到标题

先讲一个真实世界里每天都在发生的故事,细节做了脱敏。

某政务信息化项目验收之后进入结算。开发方翻开账本:投入了 14 个人、11 个月,主张结算价 480 万。委托方的审计不认:功能就这么多,市面上三家公司都说不超过 260 万,主张按 260 万结算。双方差距 220 万,各请各的专家,各说各的道理,项目卡在验收环节整整八个月。

最后仲裁机构请了第三方造价评估。评估公司做的事情出乎意料地朴素:拿着需求文档,按国家标准把系统功能逐条拆成功能点,数出 1120 个功能点(fp);再按权威部门发布的行业基准数据查出这类系统的生产率区间,算出工作量和成本区间。最后落在 330 万 ± 15%——双方看到算法和数据来源后,都签了字。

这个故事里真正值得注意的不是那个数字,而是争议消失的方式:不是某方让步了,而是问题从"你说多少 vs 我说多少",变成了一道双方都可以当场验算的算术题

这篇文章就把这道算术题完整讲一遍。它由两份国家标准构成:

  • GB/T 42588-2023《系统与软件工程 功能规模测量 NESMA 方法》——规定"功能点怎么拆"(修改采用 ISO/IEC 24570:2018);
  • GB/T 36964-2018《软件工程 软件开发成本度量规范》——规定"从功能点到工作量、从工作量到钱"的全流程。

📩 需要这两份标准的原始 PDF?邮件联系我:i@lixx.cn,我看到后发给你。

为什么软件报价注定扯皮 链接到标题

在讲方法之前,先回答一个问题:为什么其他行业没有这么普遍的定价扯皮?

盖房子有工程量清单,一平米钢筋多少钱有定额;买设备有型号和出厂价。这些行业都有公用的度量衡——一个双方都认的"量"和一本双方都认的"价"。而软件的尴尬在于:

  • 代码行数不是度量衡。同一功能,Java 写 5 万行,换个熟练的人 2 万行也能实现,用代码行计价等于奖励冗余;
  • 人天不是度量衡。同样一个报表功能,资深工程师 2 天,新手 10 天,按人天计价等于惩罚效率;
  • “经验"更不是度量衡。它藏在报价人的脑子里,不可复制、不可复核、不可积累——两个人拆同一份需求,误差 30% 是常态。

于是每次报价都变成一场博弈:委托方怕被宰,往低了压;开发方怕亏损,往高了报。双方都在信息不对称里做最坏打算。

破局点出现在 1979 年。IBM 的 Albrecht 在做生产率研究时提出一个洞见:软件交付给用户的,本质上是"信息处理的数量”,而这个数量可以从用户视角度量,与技术实现完全无关。他给这个量起了个名字——功能点(Function Point)。标准里有个很好的类比:就像"租赁点"由房间数、面积、设施数决定,与房子是砖混还是框架结构无关——租客不为建筑工艺付费,只为得到的居住功能付费

功能点是甲乙双方之间天然中立的度量衡:委托方不需要懂技术就能理解"添加客户信息"是一个功能,开发方也无法靠技术话术把一个功能说成三个。这就是整套国标体系的地基。

全景:一道四步的算术题 链接到标题

整个体系做了一件事:把"这个软件值多少钱"这个无法回答的问题,拆成四个可以逐级验算的问题。

flowchart LR A["需求文档"] -->|"数功能点<br/>GB/T 42588"| B["功能规模<br/>fp"] B -->|"× 耗时率<br/>基准数据"| C["工作量<br/>人时"] C -->|"× 费率<br/>+ 调整因子"| D["成本<br/>元"] D -->|"+ 利润"| E["报价"] style E fill:#e8f5e9,stroke:#388e3c

每一步都有三样东西兜底:标准规则(怎么算)、基准数据(用哪个数)、调整因子(什么情况下修正)。任何一方质疑结果,都可以回溯到具体某一步——这正是"可验算"的含义。

两份标准的分工:

flowchart LR A["GB/T 42588"] -->|"输出"| S["功能规模 fp"] B["GB/T 36964"] -->|"接住 fp"| W["工作量 → 成本 → 报价"] C["行业基准数据"] -.->|"生产率 / 费率"| B S --> B style S fill:#fff8e1,stroke:#ffb300 style W fill:#e8f5e9,stroke:#388e3c

下面依次展开。

第一问:功能点怎么拆 链接到标题

用户视角,五种组件 链接到标题

NESMA 方法的第一原则:从用户视角、按逻辑功能拆,无视技术实现。任何应用都被拆成五种基本功能组件——两种"数据功能"(系统要记住什么)和三种"事务功能"(系统要做什么):

flowchart TB A["应用功能<br/>(边界内, 用户视角)"] --> B["数据功能"] A --> C["事务功能"] B --> D["ILF 内部逻辑文件<br/>本系统维护的数据"] B --> E["ELF 外部逻辑文件<br/>引用他系统维护的数据"] C --> F["EI 外部输入<br/>增 / 删 / 改"] C --> G["EO 外部输出<br/>报表 / 统计"] C --> H["EQ 外部查询<br/>按键查详情"] style B fill:#e8f4fd,stroke:#2196f3 style C fill:#fff3e0,stroke:#ff9800

判定只需要记两条:

  • 数据功能看"谁维护":本系统使用且维护 → ILF(如 CRM 自己的客户信息);本系统使用但由别的系统维护、当前数据直接可用 → ELF(如人事系统维护的员工信息)。临时文件、排序文件等技术中间产物一律不计。
  • 事务功能看"动没动数据、算没算东西":跨越系统边界且维护了 ILF → EI;输出规模不定或含计算派生数据(合计、平均值)→ EO;输入含唯一标识、输出规模固定、原样展示、无计算 → EQ。

EO 和 EQ 的区分是实务第一大坑:客户统计(行数不定、有汇总计算)是 EO;输入客户编号弹出客户详情(规模固定、原样展示)是 EQ。第二大坑:修改功能里"先显示再改"的数据回显属于 EI 的一部分,不能再单独算一个 EQ。

复杂度与权重 链接到标题

每个功能再按 DET(跨越边界的字段数)和 RET/FTR(记录类型 / 引用的逻辑文件数)判低、中、高三级复杂度,查表赋权:

复杂度ILFELFEIEOEQ
75343
107454
1510676

全部功能权重求和 = 功能规模,标准要求标记为 fp(GB/T 42588—2023) 以保证可追溯。注意这张表的巧妙之处:数据功能权重高于事务功能——一个系统"记住什么"比"做什么操作"更贵,因为数据模型是长生命周期资产,操作界面可以重做,数据结构错了是伤筋动骨的。

三级精度:诚实面对信息的不完整 链接到标题

NESMA 最有工程价值的设计,是承认"不同阶段你知道的东西不一样多",并据此给出三级数法:

flowchart TB A["手头有什么材料?"] --> B["只有 ER 图<br/>→ 预估法<br/>FP = ILF数×35 + ELF数×15"] A --> C["有功能清单<br/>→ 估算法<br/>数据功能取低值, 事务取中值"] A --> D["有字段级规格<br/>→ 详细法<br/>逐个数 DET/RET, 查矩阵"] B --> E["偏差可达 50%<br/>只作量级判断"] C --> F["招投标主力"] D --> G["结算 / 审计"] style E fill:#ffcdd2,stroke:#d32f2f style F fill:#fff8e1,stroke:#ffb300 style G fill:#e8f5e9,stroke:#388e3c

预估法的 35 不是魔法数字,标准给出了推导:假设每个 ILF 平均配套 3 个 EI(增/改/删)、2 个 EO、1 个 EQ(3×4 + 2×5 + 4 = 26),加上 ILF 自身低复杂度 7 和约 2 fp 通用功能,约等于 35。统计假设写进了公式,这比"我觉得这系统大概值 300 万"透明了几个数量级。

完整走一遍:标准附录 D 的例子 链接到标题

需求:“维护客户信息”——客户信息本系统维护(ILF),员工信息来自人事系统(ELF);操作有添加/导入/修改/删除客户(4 个 EI)、客户统计(EO)、客户查询(EQ)。

  • 预估法:FP = 1×35 + 1×15 = 50 fp
  • 估算法:FP = 1×7 + 1×5 + 4×4 + 1×5 + 1×4 = 37 fp
  • 详细法:数 DET/RET 逐项判级后,本例恰好 = 37 fp

同一个需求,预估法比估算法高 35%——不是预估法"算错了",而是它刻意为大坑里藏着的需求细化留了余量。这就引出了下一问里最重要的机制。

高频踩坑清单(标准都有明文) 链接到标题

  • “修改客户"在菜单里出现五次,只要逻辑相同只计一次(不重复计数,6.3);
  • 菜单结构不计功能点,每个事务的启动触发器只计 1 个 DET(6.15);
  • 一个事务里的所有提示/错误消息合计只算 1 个 DET(6.14);
  • 帮助功能按"种类"计 EQ,不是每个页面各算一个(6.13);
  • 学历、国家代码这类码表打包计为一个"FPA 表”,不逐个算逻辑文件(6.20);
  • 登录、权限这类平台标准能力不计(6.9);
  • 3NF 模型里双向强制关系的两个实体合并成 1 个逻辑文件(2 个 RET);拿不准就按独立计(6.21)。

这些细节就是"国标拆解"和"经验拆解"拉开 30% 差距的地方。标准自己的要求是:对同一应用程序的功能点分析,宜保持相同结果——两个人独立数,结果应该能对上,这是"度量衡"的底线。

第二问:钱怎么算 链接到标题

先划边界:什么钱算"开发成本" 链接到标题

GB/T 36964 把软件开发过程限定在立项到验收之间,成本 = 四项之和,并明确排除三样东西:

flowchart TB A["软件开发成本 SDC"] --> B["直接人力<br/>项目组工资福利"] A --> C["直接非人力<br/>办公/差旅/采购费"] A --> D["间接人力<br/>PMO等分摊"] A --> E["间接非人力<br/>房租/折旧分摊"] A -.->|"不含"| F["数据迁移费"] A -.->|"不含"| G["软件维护费"] A -.->|"不含"| H["毛利润"] style A fill:#e8f5e9,stroke:#388e3c style F fill:#ffcdd2,stroke:#d32f2f style G fill:#ffcdd2,stroke:#d32f2f style H fill:#ffcdd2,stroke:#d32f2f

“不含利润"这条经常被读漏,它其实是体系的关键设计:标准算出来的是成本,不是价格。成本是客观量,由标准和基准数据锚定;价格 = 成本 + 利润,利润是商业量,留给双方谈。标准和市场各守一段边界,谁也不越界。

五步流水线 链接到标题

flowchart TB A["① 规模估算<br/>数功能点 × 变更因子 CF"] --> B["② 工作量估算<br/>UE = C × S^a"] B --> C["③ 成本估算<br/>费率路线 或 单价路线"] C --> D["④ 间接成本分摊<br/>按工作量比例"] D --> E["⑤ 多方法交叉验证<br/>分歧大则专家评审"] style E fill:#e8f5e9,stroke:#388e3c

流程不复杂,真正有深度的是藏在里面三个机制——理解了它们,才算理解这套标准为什么不是拍脑袋的另一种形式。

机制一:变更因子——需求膨胀的统计学 链接到标题

第一步算出的规模要乘一个规模变更因子 CF:S = US × CF。标准建议:预算阶段 2.0,招标 1.5,投标 1.26,计划 1.0

这个因子背后是软件工程最稳定的一条经验规律:需求在细化过程中必然膨胀,且越早期膨胀越狠。GB/T 42588 附录 C 给出了机制解释,并区分了两种增长:

  • 自主增长:需求本来就隐含着,只是初期没识别到(细化时暴露出来)。附录 C 的示例数据:分析阶段数出 100 fp,到构建结束预期 140 fp(+40%);概要设计后 +20%;详细设计后 +10%——膨胀率随阶段递减
  • 范围蔓延:用户新增了原本不存在的需求。这部分不可预测,走变更管理流程另算。

变更因子的取值正是这种递减膨胀率的体现。更深一层的含义是风险分配:预算按 2.0 放大,是委托方为自己的需求不成熟预付保险;投标按 1.26 放大,是开发方只为自己可控的细化余量负责。双方各自消化自己制造的不确定性——这是这份标准里最精巧的一处合同设计。

机制二:生产率幂律——规模经济写进公式 链接到标题

第二步工作量估算的回归方程是 UE = C × S^a,标准示例中 a = 0.9。

注意 a < 1 意味着什么:工作量随规模次线性增长——1000 fp 的项目不是 100 fp 项目的 10 倍工作量,而是约 8 倍。这就是规模经济:架构、环境、团队磨合这些固定成本被摊薄了。回归方程基于行业基准数据拟合,而不是拍一个"每人天做几个功能点"的线性假设——线性假设会系统性高估大项目成本、低估小项目成本,而幂律方程把这两种偏差都修正了。

机制三:百分位区间——用分布代替赌单点 链接到标题

标准的一条硬原则:“工作量和成本的估算结果宜为一个范围值"。具体做法:从基准数据库取功能点耗时率的 25 / 50 / 75 百分位数(C = 8 / 10 / 14 人时每 fp),分别算出乐观值、最可能值、悲观值。

单点估算是赌博,区间估算是风险语言。而且区间直接接入了预算决策规则(附录 A.1.4):

  • 需求明确、无特殊约束 → 预算取 50 百分位(中值);
  • 需求不明确或质量工期要求高 → 取 75 百分位(悲观值);
  • 需求明确且无约束 → 可取 25 百分位(乐观值)。

预算该保守还是进取,不再取决于领导的胆量,而取决于需求的不确定度——把风险管理翻译成了查表。

一条连贯的完整算例 链接到标题

把两个标准的数字串起来,走一遍从需求到报价的全过程。假设某个 CRM 系统投标,估算法数出 US = 1000 fp

flowchart LR A["US = 1000 fp"] -->|"× CF 1.26<br/>(投标阶段)"| B["S = 1260 fp"] B -->|"UE = C×S^0.9<br/>C 取 50 分位 10"| C["UE ≈ 6310 人时"] C -->|"× A1.0 × IL1.0<br/>× L0.8 × T1.1"| D["AE ≈ 5553 人时"] D -->|"费率 2.5万/人月<br/>≈ 31.5 人月"| E["人力成本 ≈ 79万"] E -->|"+ DNC 5万"| F["SDC ≈ 84万"] F -->|"+ 毛利 20%"| G["报价 ≈ 100万"] style G fill:#e8f5e9,stroke:#388e3c

(费率与调整因子取值为演示用示例;实际项目中,C 和费率必须取权威部门发布的最新行业基准数据,如工信部指导、中国软件行业基准数据 CSBMK 报告中的分位数。)

每个箭头上都写着依据:因子取值有标准条款,耗时率有基准库版本号,费率可追溯到地域和年份。对方不服任何一环,就回到那一环查证——这就是开头那个故事里"双方都签字"的技术基础。

第三问:什么时候用、怎么用——五大场景 链接到标题

36964 附录 A 按生存周期规定了五个场景,计数精度和价格策略逐级演进:

flowchart LR A["预算<br/>预估法 CF2.0"] --> B["招投标<br/>估算法 CF1.5/1.26"] B --> C["项目计划<br/>详细法 CF1.0"] C --> D["变更管理<br/>中期计数"] C --> E["结算决算<br/>末期计数"] D --> E style A fill:#e8f4fd,stroke:#2196f3 style E fill:#e8f5e9,stroke:#388e3c

两个场景值得单独展开。

招投标:标准要求招标方基于估算设定评标基准价、投标最低合理报价、投标最高合理报价——低于下限或高于上限的报价判为不合理,价格评分 0 分。

flowchart TB A["招标方估算"] --> B["+ 行业平均毛利率"] B --> C["合理招标价区间"] C --> D["下限→最低合理报价<br/>上限→最高合理报价<br/>中值→评标基准价"] E["某投标报价"] --> F{"落入区间?"} F -->|"是"| G["✅ 参与评分"] F -->|"否"| H["❌ 0 分"] style G fill:#c8e6c9,stroke:#388e3c style H fill:#ffcdd2,stroke:#d32f2f

这条机制同时掐死两个顽疾:恶意低价抢标(低于成本竞标被标准明文禁止,且下限拦住了"先低价中标再靠变更捞回来"的路——变更要走中期功能点计数,双方评审确认)和预算套高(上限封顶)。报价合理性的裁判从评标专家的感觉,换成了功能点数 × 基准单价区间这条硬线。

变更管理:增强项目的规模算法是 EFP = ADD + DEL + CHGA(新增 + 删除 + 更改后)。注意删除功能也计工作量——删代码、改测试、清数据同样是成本,这是大量合同漏掉的部分,也是"免费改需求"文化的制度性纠偏。项目规模(决定收多少钱)和应用规模(决定系统变成多大)是两个公式、两个用途,标准分得清清楚楚。

这套标准的边界(诚实地说) 链接到标题

它不是万能的,标准自己也承认:

  • 以非功能需求为主、算法密集或创意为主的项目(如性能优化、AI 算法、游戏),功能点无法刻画其规模。36964 给出的出路:可用 GSC 调整因子修正,或跳过规模估算,直接用类比法/类推法估工作量和成本;
  • NESMA 与 IFPUG 高度同源(都是五组件、同一套权重),差别就在 NESMA 提供了三级精度,更适合早期估算;COSMIC 则另起炉灶,适用于实时系统和嵌入式场景——36964 把五种方法列为可选,按项目类型挑选;
  • 基准数据是体系的血液。标准刻意不含任何生产率数字,全部指向权威基准库——这既是优点(数据年年更新、方法不用改),也是门槛:脱离基准数据,这套方法就只剩骨架。

落地清单 链接到标题

开发方:投标前用估算法自查一遍(功能点 × 1.26 × 基准耗时率),把成本底线算出来再去谈判;合同争取"功能点单价 × 实际交付功能点"计价,并写入 EFP 变更条款;结项做末期计数,把自家生产率沉淀成组织级基准数据——三年后你的报价精度就是同行拍不出来的。

委托方:需求书写到功能清单 + 数据组级别(否则双方连数功能点的原料都没有);预算按预估法 × 2.0 + 基准分位数取值,审批时要求附功能清单;评标规则写明估算方法和基准价设定方式。

共同:功能点计数让用户参与确认(标准 4.6:用户是唯一能确定某项功能是否需要的角色),并记录全部假设条件——争议的种子往往在计数阶段就埋下了。

结语 链接到标题

回到开头那场 220 万的争议。它真正的教训不是"第三方算得准”,而是:在没有公用度量衡的地方,价格谈判必然退化成权力博弈。经验报价的本质困境从来不是不准——估算永远是估算——而是不可复制、不可复核、不可积累:每次报价都是从零开始的玄学,做了十年项目,组织里也没沉淀下任何可传承的东西。

国标这套体系把定价变成了工程:功能点可以逐条对,生产率有基准库可查,调整因子有取值范围可辩,报价可以拆回到每一个功能上。手艺变成工程,靠的就是标准。

别再拍脑袋了。

标准信息

  • GB/T 36964-2018《软件工程 软件开发成本度量规范》,2018-12-28 发布,2019-07-01 实施
  • GB/T 42588-2023《系统与软件工程 功能规模测量 NESMA 方法》(ISO/IEC 24570:2018, MOD),2023-05-23 发布,2023-12-01 实施

📩 需要两份标准的原始 PDF?邮件联系我:i@lixx.cn,我看到后发给你。