生产环境里躺着一张叫 ZCUST_ADDR_LEGACY 的Z表。创建于2009年,最后一次修改是2011年。十四个ABAP程序引用它,没有文档,没有负责人。当年写它的开发2013年就离职了,顺手把上下文也带走了。
![]()
S/4HANA就绪检查把它标成了迁移阻断项——这也是现在团队第一次知道它存在的方式。
挖了三个小时才搞明白:它是一张自定义地址校验程序的暂存表,2017年那个业务单元重组之后,这个校验就再没被调用过。没人关掉它,没人删掉它。它就那么待着,被十四个同样好几年没跑过的程序安静地引用着,等着在一个排期十八个月的RISE迁移里冒出来当拦路虎。
然后我们把它删了。五分钟的事。就绪报告上少了一个阻断项。那三个小时没白花——那是十五年"回头再补文档"的账单。
这就是Clean Core的微缩版。不是理念,不是SAP的营销框架,是跟上线以来每一个被推迟的决定算总账。
四种迁移模式,以及什么时候真该用哪个
你系统里的每一个自定义对象,最终都会落进四个桶里。这四个桶不是一样好——它们是"现在疼"和"以后疼"之间的取舍。分诊分错了,升级的时候连本带利还回来。
- 删掉它:两年以上零生产执行?它就不该存在。写第一行迁移代码之前先跑SE80使用统计。成熟系统里30%到40%的对象都符合这一桶。成本:无。痛苦:低。
- 换成标准功能:那个自定义账龄报表?那个跟BAdI长得一样的定价出口?SAP几年前就出了标准版。换掉。成本:低。痛苦:中。
- BTP扩展:功能搬到BTP,SAP核心通过API或Event Mesh调用。架构上正确。适合新功能,以及需要独立部署的面向客户流程。成本:高。痛苦:高。
- 并行部署:流程跑在独立系统里,通过API或iDoc集成。不用碰核心,也不涉及SAP BTP计费。实践中胜出最多——尤其是那些带外部数据、或者有自己发布节奏的流程。成本:中。痛苦:中。
- 干净重建:先理解它,用已发布的API、BAdI、RAP重建,删掉原件。现在痛苦拉满,之后每次升级痛苦最小。适合还在活跃使用、且当前改过SAP标准源码的东西。成本:高。痛苦:现在高,省下未来的痛。
2009年的每一个捷径,都是2025年的一场会。问题是谁坐在那个房间里等账单。
还有一种做法叫封装后推迟:把自定义代码包在一个稳定的ABAP API后面。修改还在原地,但调用方走定义好的接口。这不是干净的结果,是受控的推迟。理由是这样能阻止问题扩散,同时你去处理真正要紧的修复。我会用它处理那些跟活跃业务流程缠在一起、完整重建需要一轮你眼下没时间做的UAT的代码。风险是:"临时"封装往往会变成永久。选了这个模式,就在项目待办里给它定一个硬性整改日期,别放进愿望清单。
ABAP测试座舱:真正该看什么
写第一行迁移计划之前,先跑ABAP测试座舱。它的输出才是你真实的迁移范围——不是SE80里的Z对象数量,不是系统集成商在调研阶段估的数,也不是就绪评估里的高管摘要。ATC告诉你的是在S/4HANA语境下到底什么坏了。
真正预示麻烦的发现:任何"error"优先级的结果都是硬阻断,代码在S/4HANA里根本编译不了或跑不起来。高优先级警告集中在废弃API的使用上——特别留意那些用直接SELECT去读KNA1这类表的地方,S/4版本用的是另一套数据模型;还有那些在S/4里没有对应物的经典dynpro元素。SLIN检查类别会暴露隐式类型转换,这些转换在ECC里没事,到了HANA会悄悄把数据搞坏。如果你的ATC跑出来错误对象占比超过自定义对象总数的15%左右,那你的迁移时间线需要在下次指导委员会开会前重新谈。
有两个数字比发现总数更重要。第一,错误和警告的比例。一个系统有2000条警告、40个错误,是可控的;有400个错误,那是范围问题。第二,集中度。错误是散在300个程序里,还是集中在12个里?集中反而更好——说明你面对的是一个有边界的修复问题,不是系统性的。
大多数团队会漏掉一个工具:SAP Fiori里的自定义代码迁移应用(S/4上事务码 /n/ui2/fp,或通过迁移座舱进入)。它把你的自定义对象跟SAP的兼容性数据库交叉比对,给出逐对象的建议。误报率是真实存在的——大概20%被标"迁移"的东西其实跑得好好的——但它是在你花开发时间做人工分析之前,给ATC发现清单排优先级最快的方式。
还值得跑的是简化项检查。它抓的是SAP在ECC和S/4之间对数据模型做的结构性改动——被合并、拆分或整个删掉的表。对BSEG做直接SELECT就是经典例子;在S/4里你要用ACDOCA。ATC抓语法问题,简化项检查抓语义问题。两个都要。
决定成败的那场对话
周二早上九点。我坐在会议室里,对面是FI负责人、财务主管,还有两位业务团队成员——他们六年来每周一早上都在跑同一份自定义账龄报表。这份报表从三张Z表和一个直接读BSEG的自定义函数模块取数。四个对象全在ATC错误清单上。
财务主管开口第一句:"这份报表不能丢。月结靠它。"
错误的回应是去解释Clean Core。正确的回应是:"我知道。我们聊聊它做什么,以及它需要继续做什么。"四十分钟后,我们理清楚了:这份报表干三件事——按标准SAP不支持的定制分桶定义对未清项做账龄,套用一个客户特定的核销阈值,导出成财务团队用了很多年的特定Excel格式。三件事里有两件是真需求。Excel格式是习惯。我们把它重建成一个由CDS视图支撑的Fiori分析应用,通过扩展字段和BAdI保留定制账龄分桶和核销逻辑,用Fiori原生下载取代Excel导出。
财务主管签字了。不是因为我们讲清楚了Clean Core,是因为我们搞懂了那份报表。
大多数Clean Core评估会漏掉的东西:隐式运行时依赖。两个对象在Z对象层面看起来互不相干,却通过一个自定义BTE或用户出口共享同一条数据流,而这个出口没有任何文档,常规代码分析也看不见。ATC抓不到,SE80抓不到。唯一的办法是把代码从头到尾读一遍,或者用接近生产的数据量跑完整回归测试。两样都要留预算。你在UAT当天才发现的那个隐式依赖,就是给上线日期加上六周的那个——我亲眼见过两次。
有一个问题能告诉你一个自定义对象到底干不干净:"如果SAP下个季度发一个支持包,这东西还能不能不用开发碰它就跑起来?"不是"大概能",不是"几乎肯定能",是"确定能"。
跳过这一切的真正代价,不是下一次升级。是Clean Core欠债对RISE谈判的影响。我坐在过那个房间里,系统集成商翻到自定义代码现状那一页,数字是1400个对象需要修复。项目范围当场翻倍。十八个月变成二十八个月。签了商业论证的CFO看着一个当初提案里没人给他看过的数字——因为签合同之前没人跑过ATC。
在签合同之前跑评估。知道你的数字。把它写进范围。Z表不会因为你假装看不见就变便宜——它们只会变老。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.