ABAP旧对象退役实操:从代码废弃到物理删除的完整指南
2026/9/9 21:04:45 网站建设 项目流程

干 SAP 开发这行,谁的开发包里没躺着一堆“想删又不敢删”的旧对象?我见过不少系统,一个 BDC 批导程序已经在生产环境跑了十几年,业务早就切到新的 ALV 程序上了,但开发团队还是没人敢碰它。每次有人提出要废弃,都会被同一句话劝退:万一别的地方还在用呢?

这两年随着 ABAP 新语法、CDS View、RAP 这些技术路线铺开,旧的函数模块、老报表、自建接口越来越像系统里的“历史遗址”。但我要说清楚一件事:让开发对象体面退场,不是一个“删除”动作,而是一套工程化流程。做得好,旧对象退役后系统干干净净、团队心里有底;做得糙,就是一次连环报错事故的开端。

这篇文章我按自己的实操经验,把 ABAP 开发对象废弃这件事拆成三层来讲:先判断对象到底能不能退场,再决定退一半还是全退,最后怎么删、删完怎么兜底。适合正在维护老系统、陆续接新项目的 ABAP 开发者,也适合刚接手一个“祖传代码”系统的技术顾问参考。

1. 废弃不等于删除:开发对象“体面退场”的本质

先说结论:废弃一个开发对象,和生活中处理旧家具是一回事。不是所有旧东西都要直接扔,有的贴上“不再使用”的标签放储物间,有的搬到角落吃灰,只有确认彻底没用的才真正处理掉。ABAP 里的“废弃”同样是分层的。

1.1 先分清三种“废弃”状态

我平时会把废弃分成三个等级,后面所有操作都围绕这个分级走:

废弃等级具体操作适用场景主要风险操作复杂度
代码级废弃在方法、函数模块、程序入口标注 Deprecated,不让新代码继续引用对象还在用,但希望新开发不要再依赖它调用方无视标记,继续使用
对象级停用把对象移动到归档包、修改权限组、入口处限制访问功能已切换,但短期内还需要保留作回退权限限制遗漏,后台作业绕过检查
物理删除在 SE80 中删除对象,通过传输请求传到下游系统确认无人使用,且版本历史可恢复动态调用或隐藏依赖导致报错

很多项目一上来就奔着第三级去,这是我最不建议的。别急着删,先看清楚对象处于什么状态。

1.2 为什么旧对象一直没人敢动

我复盘过很多不敢动旧对象的项目,原因高度一致,就四条。

第一是影响面不明。Where-Used List 查不到的对象,不代表真的没人用。动态调用通过SUBMIT (lv_prog)CALL FUNCTION lv_func这种写法,标准引用分析根本抓不到;有些 RFC 接口被外围系统通过 SAP PI/CPI 调着,你从 ABAP 侧看就是“僵尸函数”。第二是传输链复杂。删除一个对象生成的请求到了 QA、生产,如果下游系统里还有对象引用它,激活或者运行时直接炸给你看。第三是回归成本高。业务部门本来就不愿意配合测试,你提“我要删个程序”,对方第一反应是“凭什么,我现在就能用,别动”。第四是合规与审计压力。财务、后勤相关报表一旦删除,将来审计问起来,你说不清当时的业务场景和历史依据。

1.3 废弃是一个“交接”过程

想明白这一点之后,我反而轻松了:废弃的本质不是“消灭旧对象”,而是“让新对象接替旧对象”。这是一个交接过程,交接双方必须是:新对象能完全承接旧对象的功能、输入侧输出侧都对得上、有足够的时间窗口做观测。

真正体面的退场流程是这样的:功能确认 → 双轨运行 → 标记废弃 → 观测验收 → 删除或归档。每一步都有明确的确认动作,每一步都可以反悔。旧对象退场不是被赶下台,而是“已完成历史使命,正式退役”。

2. 废弃前的“体检”:判断对象能不能退场的四个维度

每次有人问我“这个程序能不能删”,我不会先看代码,而是先做一轮体检。体检不过关,一切免谈。

2.1 静态依赖扫描:Where-Used List + Code Inspector

静态扫描的第一步永远是 Where-Used List。在 SE80 里选中对象右键,选“Where-Used List”,系统会列出程序、类、表结构、数据元素等所有引用位置。这一步能发现大部分显式引用,但记住我刚才说的,它查不到动态调用。

为了补这个坑,我会用 Code Inspector(事务代码 SCI)做一轮专项检查。SCI 可以配置检查变式,重点检查未使用对象、废弃语法、动态调用的风险点。虽然 SCI 的默认检查项很多,但我建议自己维护一套“废弃评估”变式,专门检查:

  • 未使用的变量、方法、函数模块
  • 调用链中是否存在SUBMITCALL TRANSACTIONCALL FUNCTION动态写法
  • SELECT语句是否引用了待评估的表、视图、CDS 实体
  • 是否存在PERFORM动态形式(PERFORM (lv_form)

扫描出来的结果不要全信,重点看“调用关系深度”。比如一个程序被另一个废弃程序调用,这个引用本身没有意义,要顺着调用链追到真正的入口点。

2.2 运行时使用分析:确认到底有没有人在用

静态分析解决“可能引用”,运行时分析才解决“真实使用”。我最常看的是 ST03N 和 STAD,前者看工作负载里的程序执行记录,后者看统计记录里的调用明细。

操作上这样来:在 ST03N 里选好日期范围,用程序名过滤,看这个候选废弃对象的执行次数和累计时间。如果连续一个月都没有执行记录,那它大概率已经处于“名义存在、实际闲置”状态。对于 RFC 函数模块,我会再看 ST05 SQL 跟踪或者 SM50/SM66 的当前活动进程,确认它是否还在被外部系统频繁调用。

还有一个我自己常用的土办法:在候选废弃对象的入口代码里加一段“探针”,往一张日志表写当前时间戳和调用方式,观察两周。比如:

REPORT zbdc_delivery. DATA lv_ts TYPE timestamp. GET TIME STAMP FIELD lv_ts. MODIFY zdev_obj_usage FROM VALUE #( objname = 'ZBDC_DELIVERY' progname = sy-repid last_run = lv_ts ). COMMIT WORK.

这张日志表不用建得多复杂,能记录对象名、程序名、时间戳就够了。两周后一条SELECT看结果,有没有人在调、什么时候调的、调了多少次,清清楚楚。这个方法对程序、函数模块、类方法都适用,比纯看统计更直观。

2.3 数据依赖分析:表/结构不是想删就删

程序删错了最多恢复源码,表结构一旦删错,牵一发动全身。评估表和结构时,我额外关注三件事:数据库层面的引用、数据保留、增强关联。

第一,用 SE11 查看表/结构被哪些数据元素、域、表类型、外键、锁对象引用,CDS View 有没有依赖这张表。第二,用 DB02 看表的大小和历史增长趋势,如果表里还有大量业务数据,就算结构可以废弃,数据本身也要先规划归档或迁移方案。第三,检查有没有结构增强(Append Structure、CI_ 开头的自定义包含),增强结构里可能还藏着业务方自己做的字段,直接删表会连坐一大堆自定义代码。

表对象的废弃我建议分成“删字段”和“删表”两步走。先停用字段,等一个完整业务周期过去,确认没有程序再往这个字段写数,再考虑整表删除。

2.4 业务确认与灰度期安排

技术侧体检做完,最后一道关是业务确认。这一步不是走过场,而是要业务负责人明确回答三个问题:

  • 这个功能现在由哪个新事务码或新程序承接?
  • 旧入口还有没有人在日常使用?
  • 是否同意给一个双轨运行的观察期?

我见过最典型的翻车场景:技术侧查了四周运行记录都是零,但一删掉,业务立刻报“报表出不来”。原因是业务方用的菜单里还挂着旧事务码,用户“凭肌肉记忆”点进来的,统计系统里查不到是因为入口被谁偷偷换了路径。所以业务确认要做好菜单、角色、授权对象的同步检查,别让旧入口还挂在用户面前。

灰度期我一般建议至少两到四周,如果涉及月结、年结或者周期性批处理程序,至少覆盖一个完整周期。财务相关的 F-02、F-19 这类场景,至少要走完一次月结再说。

3. 代码级废弃的实操:不删对象也能“退一半”

不是所有旧对象都需要走到物理删除那一步。很多时候,只要让旧对象从“默认方案”变成“明确不推荐使用”,就已经解决了大部分问题。这就是代码级废弃,也是我最推荐的“低风险退场”方式。

3.1 类方法的废弃标记:加一个 DEPRECATED 后缀

如果你用的是较新版本的 ABAP,类方法定义里可以直接加DEPRECATED后缀,让调用方在编译期、ABAP Development Tools 里就能看到废弃提示:

METHODS generate_bdc_data IMPORTING iv_matnr TYPE matnr iv_qty TYPE menge_d DEPRECATED.

这样写之后,新的调用者在写代码时立刻会看到警告,编译环境会提示“此方法已废弃”。老的调用方代码继续运行不受影响,但开发团队不会再“自然而然”地继续用它。如果系统版本不支持这个后缀,退一步的做法是把废弃说明写在方法的文档注释里,并且把方法描述前缀改成DEPRECATED -,让所有开发者打开 SE24 就能看到。

我特别想强调一点:标记废弃之后,别把旧方法的实现逻辑写成“报错退出”。正确的做法是让旧方法继续保留原逻辑,顶多内部转发到新方法。这样存量调用不会炸,新调用又能被引导到新实现上,才是“退一半”的意义。

3.2 函数模块和程序的文档标记

函数模块没有标准的 Deprecated 语法,但 SE37 里可以写文档。我习惯在函数模块的属性页“文档”字段顶部,用一行醒目的文字说明:

DEPRECATED: 此函数模块已废弃,新开发请调用 ZCL_SHIPMENT=>POST_VIA_API。 原逻辑保留,仅用于兼容历史调用方。

程序同样处理,代码文件头部放一段注释块:

*&---------------------------------------------------------------------* *& Report ZBDC_DELIVERY *&---------------------------------------------------------------------* *& 状态:DEPRECATED(已废弃) *& 废弃原因:已由 ZSMP_DELIVERY_POST 替代 *& 替代入口:事务代码 ZSMP_DELIVERY *& 保留策略:观察期结束后由开发团队确认删除,预计 2025.Q3 *&---------------------------------------------------------------------*

这段注释不是写给自己看的,是写給半年后接手这张代码的“下一个人”看的。他不需要翻版本历史,不需要猜,打开第一屏就知道这个对象的身份和命运。

3.3 旧语法与新语法的渐进式处理

很多老对象不敢退场,是因为里面代码全是“祖传语法”:MOVE-CORRESPONDING、内层LOOPLOOPSELECT ... ENDSELECT一行行读表。这种代码用 Code Inspector 一查全是废弃语法标记,但大规模重写不现实。

我的策略是“入口新、躯干旧”。不重构整个程序,只把入口参数和数据获取部分用新语法包一层,内部逻辑保持原样。比如把老函数模块的入口改成SELECT ... INTO TABLE @DATA(lt_data)这种新写法,主体还是老代码。这样至少让新调用方写起来顺手,也让维护者看到“这个对象有人在试着往新语法靠”。真正彻底的新语法改造,等对象本身还活跃、业务还愿意投入测试的时候再做,不要在一堆即将退役的代码上花大功夫。

4. 对象级废弃的完整 SOP:从评估到删除的逐步操作

如果体检确认对象可以彻底退场,那就走完整套删除流程。下面这套 SOP 是我自己踩了无数次坑之后固定下来的,照着做不会出大乱子。

4.1 删除前准备:传输请求、备份方案、包迁移

删除本身只是一个动作,删除之前的准备工作决定了整个过程中会不会“翻车”。

先建一张废弃任务清单,列清楚对象名、对象类型、依赖结论、业务确认结果、替代对象、预计删除日期。这张清单公开给开发团队,至少让所有人知道“近期有几个对象会退役”。接着检查开发环境的传输请求状态,删除对象的变更一定要放到独立的传输请求里,不要和功能开发混在一个请求里。

备份方面,ABAP 对象有版本历史兜底,但为了保险,我还是建议把源码用下载方式留一份离线备份。包迁移也是常见前置操作,如果对象本来在一个“正常功能包”里,删除时东一榔头西一棒子,不如先把对象移到归档包或$TMP,和“仍然活跃的代码”做个隔离。

4.2 删除操作详解:SE80 里怎么删、删完怎么走请求

ABAP 开发对象的删除,我统一推荐在 SE80 里做,因为 SE80 支持删除所有对象类型。

  • 程序、类、函数组:在 SE80 里选中对象,右键“删除”,系统会弹出确认框,随后要求分配给一个传输请求。
  • 函数模块:可以在 SE37 里单独删除函数模块;要删整个函数组,还是回 SE80 操作。
  • 数据元素、域、结构、表:SE80 选择后同样右键删除。但是注意,如果表有物理存储,SE11 里删掉的是 Repository 对象,数据库表本身可能还要用 SE14 处理。

删除对象后,它会被添加到传输请求中,这条请求记录包含了“删除该对象”的变更记录。释放请求后,对象删除状态会传到下游系统,QA 激活后生产导入,对象才真正意义上消失。

这里有一个非常关键的实操提示:释放删除请求之前,一定要在 QA 系统先做一轮完整回归。回归不是跑一遍主流程就完事,要把与对象相关的旧入口、后台作业、批处理、接口调用全部过一遍。因为删除对象在传输队列里“看不见摸不着”,一旦传到生产才发现问题,恢复流程会非常被动。

4.3 不想物理删除时的替代方案:归档包与标记隐藏

很多情况下业务说“先别删,留个后手”,这时候物理删除不是唯一选项。我常用的手法有三个。

第一个是移动对象到归档包。对象仍然存在于系统中,但从开发视角看它已经被“请出”了活跃代码区。SE80 里右键“更改对象目录条目”,修改归属包,把对象挪到$TMP或者专门的 ZARCH 归档包。第二个是权限隔离。把旧程序的权限组改成一个只有特定账号才能访问的组,一般用户执行会报权限错误,但后台作业和接口调用不受影响。第三个是在程序入口加一道“退役开关”:

PARAMETERS p_force TYPE abap_bool DEFAULT 'X' NO-DISPLAY. IF p_force = abap_true. MESSAGE '该事务码已停用,请使用 ZSMP_DELIVERY_POST。' TYPE 'E'. ENDIF.

加了这道检查之后,旧事务码“名义上还在”,但实际已经不能通过正常路径使用。这种方式比直接删更柔性,适合还在观察期、或者业务还没有正式发文停用的场景。

4.4 实战案例:一个 BDC 批导程序的完整退役过程

拿一个很常见的例子讲完整流程。老程序 ZBDC_DELIVERY 用 BDC 方式批量过账交货单,新程序 ZSMP_DELIVERY_POST 用 OO ALV + BAPI 实现,同样功能,新程序已经上线一周,业务确认正在切换使用。

第一周,我拉出 Where-Used List,只看到两个自定义程序调用;用 SCI 做一轮扫描,发现还有一个动态CALL TRANSACTION,查了一下是已废弃的调试脚本,不影响结论。ST03N 显示过去一个月里 ZBDC_DELIVERY 只跑过三次,都是测试环境残留。

第二周,我和业务负责人确认,正式用户已经从菜单里切到新事务码 ZSMP_DELIVERY。我检查了角色和授权对象,旧事务码从菜单中移除。灰度期开始。

第三周,我给 ZBDC_DELIVERY 的源码头部加了废弃注释块,同时在入口加了一条日志探针,开始观测运行情况。

第四周,日志表显示生产环境连续两周没有 ZBDC_DELIVERY 的执行记录,ST03N 同步确认。我把结果贴到废弃任务清单里,邮件知会开发团队和业务方,正式发起删除申请。

第五周,在 SE80 里删除 ZBDC_DELIVERY,系统自动把它放进独立传输请求。释放请求后传到 QA,我在 QA 侧验证了与它相关的两个程序正常激活,跑了一遍替代程序的端到端测试。随后传输到生产,生产导入后第二天再查一遍运行统计,确认没有新增报错。

整个过程看起来平淡,但每一步都有关卡,每一步都可以反悔退回去。这就是“体面退场”的节奏。

5. 常见问题与排查技巧实录

这套流程我已经跑过很多次,但每次还是会遇到一些意料之外的状况。挑几个典型的写下来,算是给大家做个避坑提示。

5.1 删完对象后其他程序报错

最常见的原因是动态调用。SUBMIT (lv_prog)CALL FUNCTION lv_func这类用法在静态分析里根本查不到,只有程序运行时才会暴露。删了程序之后,如果第二天 ST22 短转储里出现Generate or run-time error或者Database access error相关记录,第一时间去 ST22 看调用栈,顺藤摸瓜找到动态调用的入口。

另一个常见原因是包依赖。有些程序虽然没直接引用被删对象,但通过包接口(Package Interface)建立了依赖关系,删掉对象会触发包的完整性检查错误。遇到这类问题,去 SE03 的对象目录里比对一下对象的包归属,重新分配包或者补上替代对象引用。

5.2 不小心删错了,怎么通过版本管理恢复

ABAP 开发对象删除后并不代表代码立即没了。SE80 里选中对象(有些场景下需要按对象名搜索),右键“版本管理”,系统会列出该对象的历史版本。选中删除前的最新版本,用“恢复”功能把代码重新拉回来,系统会要求分配一个传输请求,重新激活后再发布一次。

关键提示:版本管理的恢复在开发环境最稳妥。如果删除请求已经传到生产,开发环境恢复之后要立即生成一个新的传输请求,把恢复后的对象重新传到 QA 和生产,否则开发和生产会处于“对象状态不一致”的状态。比较工具 SE03 的“对象比较”也能用来从 QA 把旧对象拖回来,前提是 QA 里这个对象还在。

5.3 传输请求里的对象和请求本身怎么清理

有时候你只是想从传输请求里撤掉某个对象的删除记录,而不是真的删除整个请求。SE10 里打开请求,选中对应对象右键“删除”,这一步是把对象从请求中移除,不是删除对象本身。注意别和“SE80 删除对象”搞混。

如果整个请求都不需要了,用 SE03 删除请求/任务,前提是该请求还没有释放。已释放的请求不建议直接删,因为可能已经传到下游系统,强行删会导致传输日志与请求状态不一致。

5.4 升级、补丁场景下,废弃对象要特别注意什么

SAP 系统升级或者打 Note 时,废弃对象的处理要多留个心眼。升级过程中系统会检查对象一致性,如果旧的增强、自定义字段挂在废弃的表结构上,升级可能会触发额外的兼容性处理。SPAU/SPDD 检查时,废弃对象的增强条目会被反复询问,与其在升级时手忙脚乱,不如平时就把废弃对象清理干净。

还有一个容易被忽略的问题:SAP 标准 Note 有时会重新引用已经废弃的自定义代码。比如你删了一个增强实现,但某个新 Note 恰好又有类似逻辑,升级后可能产生遗留的激活错误。我的习惯是每次升级前后各做一遍废弃清单评审,确认所有“已退役”对象仍然处于退役状态。

最后再分享一个我做废弃管理的小技巧:维护一张“废弃对象台账”,放在团队共享空间里,哪怕只是一张 Excel。台账里记录对象名、废弃原因、替代对象、责任人、计划删除日期。每次版本上线前花十分钟过一遍这张表,比临时抱佛脚翻 ST03N 要高效得多。老对象退不退场,说到底不是技术问题,而是整个团队有没有把它当成一件需要持续管理的事。把流程定好、把凭证留全,旧对象就能体面退场,新代码也能清清朗朗上线。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询