ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

ABAP旧对象退役实操:从代码废弃到物理删除的完整指南

2026/9/9 21:04:48 拓冰建站 浏览量
ABAP旧对象退役实操:从代码废弃到物理删除的完整指南 干 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 的默认检查项很多但我建议自己维护一套“废弃评估”变式专门检查未使用的变量、方法、函数模块调用链中是否存在SUBMIT、CALL TRANSACTION、CALL 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_SHIPMENTPOST_VIA_API。 原逻辑保留仅用于兼容历史调用方。程序同样处理代码文件头部放一段注释块*---------------------------------------------------------------------* * Report ZBDC_DELIVERY *---------------------------------------------------------------------* * 状态DEPRECATED已废弃 * 废弃原因已由 ZSMP_DELIVERY_POST 替代 * 替代入口事务代码 ZSMP_DELIVERY * 保留策略观察期结束后由开发团队确认删除预计 2025.Q3 *---------------------------------------------------------------------*这段注释不是写给自己看的是写給半年后接手这张代码的“下一个人”看的。他不需要翻版本历史不需要猜打开第一屏就知道这个对象的身份和命运。3.3 旧语法与新语法的渐进式处理很多老对象不敢退场是因为里面代码全是“祖传语法”MOVE-CORRESPONDING、内层LOOP套LOOP、SELECT ... 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 要高效得多。老对象退不退场说到底不是技术问题而是整个团队有没有把它当成一件需要持续管理的事。把流程定好、把凭证留全旧对象就能体面退场新代码也能清清朗朗上线。