从一个 SAP CRM 软件实际的故障处理出发,谈谈企业管理软件领域内那些很难稳定重现故障的处理技巧_crm故障如何处置

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Golang全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注go)
img

正文

2. 缩小可能引起故障的代码排查范围

3. 利用调试器锁定问题

故障排查过程总结


笔者从2007年大学毕业加入 SAP 成都研究院至今,一直从事企业管理软件领域的开发工作。

企业管理软件面向的是企业级用户,如果软件出现故障(bug),在某些极端情况下,可能会让企业蒙受巨大的经济损失,故而对软件开发人员在编程规范,软件测试和软件交付之前的验证等各方面都提出了更高的要求。同时,由于企业管理软件自身高度的复杂性,有些故障很难重现或者只能在运行了客户特定业务流程的生产系统上才能重现。这些都给企业管理软件分析和故障处理带来了巨大的挑战。

本文从笔者处理过的一个实际软件故障出发,谈谈自己对企业管理软件里一些棘手故障的处理体会。

在笔者看来,这些棘手故障,可以分为以下几类。

企业管理软件领域内棘手故障的一些表现形式

笔者在 SAP成都研究院处理过很多曾让我头痛的软件故障,它们具有下列一项或几项特征。

1. 需要复杂的流程才能重现

例如我处理过的一个客户发票(Customer Invoice)相关的故障。这个故障只有在每次 release 发票时才能重现。为了 release 发票,我们必须先创建一个销售订单(Sales Order),基于该订单创建 Customer Demand,然后创建捡货任务(Pick Task),生成交货单(Delivery Note),最后才能生成一张新的客户发票。

这些复杂的流程往往也需要系统事先维护好对应的主数据(Master Data)和事务数据(Transaction Data)才能顺利执行。复杂的业务流程增添了故障重现的难度。

2. 故障横跨企业管理软件的多个模块

由于企业管理软件自身的复杂度,终端用户眼中看到的貌似简单的一个故障,背后可能横跨了软件实现的多个模块。

以上述形式1描述的故障为例,假设软件帮助文档上描述的支持功能为:客户在销售订单界面上添加了一个新的自定义字段并维护了对应值,该值能够从销售订单,经捡货任务,交货单,最后传递到客户发票上。我们称这种字段值从多个文档间的传递称为 data flow.

那么如果客户在发票页面上,看到这个字段的值为空,客户可能认为是发票模块出了故障。然而,在 data flow 的每个节点对应的模块处理,可能都是造成该故障的罪魁祸首。销售订单和客户发票属于 CRM 模块,而捡货任务和发货单则归属 SCM 的范畴。

在实际开发工作中,这意味着分析该故障往往需要跨团队间协作,因为 CRM 和 SCM 模块往往分属不同的开发团队负责。

3. 故障只能在客户生产系统重现

在企业管理软件交付之前,必定在内部开发,测试和验证系统(validation system)进行过不同层次的测试。即便如此,由于种种客观原因,比如当应用运行在客户生产系统上,基于某些只有该客户才会用到的特定业务流程的配置时,故障才会暴露,而这些配置并没有被企业管理软件供应商的内部系统测试所涵盖到。

这类故障因为只能在客户生产系统重现,在分析和定位问题时更加困难重重,尤其当重现步骤会在客户生产系统进行写操作时,通常只能联系客户相关人员,采用远程桌面+电话会议的方式,让客户相关人员进行操作,然后软件供应商的支持人员在线调试。

4. 故障只能在后台作业模式下重现,在 online 模式运行时一切正常

在企业管理软件领域特别是 ERP 领域,后台作业常常被用来执行一些费时的批处理工作,比如订单批量处理,报表数据分析和聚合汇总等等。后台作业模式不同于挂接了用户界面的 online 模式,给单步调试也带来了困难。

5. 故障只能在软件正常运行模式时才能重现,单步调试时,软件工作一切正常

当故障出现这种特征时,实际给支持人员传递了一个信号:该故障可能与程序特定的执行时序相关。因为程序正常运行,与处于单步调试模式下运行,执行时序显然不同,比如在调试器单步调试时,可能会破坏多线程程序正常的执行时序。

因为缺少了调试器这一强有力的武器,分析该类故障,需要支持人员具有更强的理论分析能力和问题抽象能力。

由于篇幅限制,本文仅举一个实际例子,对上述第五类故障的分析处理流程做一个分享。

一个实际故障排查过程的案例分享

笔者曾经负责 SAP CRM IBASE(Installed Base) 模块。IBase 是一个抽象模型,用于描述已在客户位置安装的资源对象,例如设备、机器,服务或软件。IBase 模型以树形结构,描述了这些对象的层级结构和它们的各个组件,是服务模块的参考基础。

有一天,我收到一个故障报告,另一个团队的同事,使用我所在团队负责的 IBASE API,在同一会话过程内创建 IBASE 组件,修改,随后删除,然后保存,会遇到运行时错误(Runtime Error).

在故障描述里提到的运行时错误的截图如上图所示。

这位同事发现,这个错误只能在后台作业模式下重现,并且不一定每次都能够重现。该故障也无法在单步调试模式下重现。

并不总是能够重现 != 不能重现。

1. 试图找到稳定重现故障的办法

为了分析这个问题,我得先找到能够稳定重现的办法。因为该故障对单步调试大法免疫,我只能另想他法。

逐字逐句死扣故障报告里的描述,发生故障之前的操作流程为:

(1) 创建 IBASE
(2) 修改 IBASE
(3) 删除 IBASE
(4) 保存事务。

出现运行时错误。

因为我就是 IBASE 模块的负责人,所以我三下五除二就写好了一个不到 200 行的程序,在程序里依次调用 IBASE 的创建,修改和删除 API,再保存事务。

程序源代码如下:

REPORT zibase_create_delete.

PARAMETERS: txt TYPE char40 OBLIGATORY DEFAULT ‘description test’,
eid TYPE char30 OBLIGATORY DEFAULT ‘PROGRAM’,
oid TYPE comm_product-product_id OBLIGATORY DEFAULT ‘CHILDOBJ8’,
fam TYPE comm_product-object_family OBLIGATORY DEFAULT ‘0401’,
cat TYPE COMT_CATEGORY_ID OBLIGATORY DEFAULT ‘OBJ_0401’.

DATA: lt_param  TYPE crmt_name_value_pair_tab,
ls_param  TYPE crmt_name_value_pair,
lr_core   TYPE REF TO cl_crm_bol_core,
ls_object TYPE comm_product,
lr_root   TYPE REF TO if_bol_entity_col,
entity    TYPE REF TO cl_crm_bol_entity.

CHECK zcl_object_generator=>create_object( iv_id = oid iv_family = fam iv_catid = cat ) = abap_true.

ls_param-name  = cl_crm_ibase_il_constant=>createparam.
ls_param-value = ‘01’.
APPEND ls_param TO lt_param.

lr_core = cl_crm_bol_core=>get_instance( ).
lr_core->load_component_set(‘IBASE_ONLY’).

CALL METHOD lr_core->root_create
EXPORTING
iv_object_name  = cl_crm_ibase_il_constant=>root_object
iv_create_param = lt_param
iv_number       = 1
RECEIVING
rv_result       = lr_root.

CHECK lr_root IS BOUND.
entity ?= lr_root->get_current( ).

CHECK entity IS BOUND.
IF entity->lock( ) = abap_true.
entity->switch_to_change_mode( ).
ENDIF.

entity->set_property_as_string( iv_attr_name = ‘DESCR’ iv_value = CONV #( txt ) ).
entity->set_property_as_string( iv_attr_name = ‘EXTID’ iv_value = CONV #( eid ) ).
"entity->set_property_as_string( iv_attr_name = ‘IBTYP’ iv_value = ‘01’ ).
lr_core->modify( ).
DATA(lv_ibase_id) = entity->get_property_as_string( ‘IBASE’ ).

DATA(component) = entity->create_related_entity( ‘FirstLevelComponent’ ).

CHECK component IS NOT INITIAL.

DATA(obj_comp) = component->create_related_entity( ‘IBCompObj’).

CHECK obj_comp IS NOT INITIAL.

obj_comp->set_property_as_string( iv_attr_name = ‘OBJECT_ID’ iv_value = CONV #( oid ) ).

SELECT SINGLE * INTO ls_object FROM comm_product WHERE product_id = oid.
ASSERT sy-subrc = 0.

obj_comp->set_property_as_string( iv_attr_name = ‘OBJECT_GUID’ iv_value = CONV #( ls_object-product_guid ) ).
obj_comp->set_property_as_string( iv_attr_name = ‘OBJECT_FAMILY’ iv_value = CONV #( ls_object-product_guid ) ).
lr_core->modify( ).

DATA(lo_message_container) = entity->get_message_container( ).
CALL METHOD lo_message_container->get_messages
EXPORTING
iv_message_type = if_genil_message_container=>mt_all
IMPORTING
et_messages     = DATA(lt_msg1).
LOOP AT lt_msg1 ASSIGNING FIELD-SYMBOL().
WRITE:/ -message COLOR COL_NEGATIVE.
ENDLOOP.

CHECK lt_msg1 IS INITIAL.

DATA: ls_header      TYPE ibap_head1,
lt_struc_tab   TYPE ibap_struc1_tab,
ls_comp TYPE IBAP_DAT1.
“delete component”

ls_header-ibase = lv_ibase_id.
CALL FUNCTION ‘CRM_IBASE_GET_DETAIL’
EXPORTING
i_ibase_head      = ls_header
IMPORTING
e_struc_ibase_tab = lt_struc_tab
EXCEPTIONS
not_specified     = 1
doesnt_exist      = 2
no_authority      = 3.

CHECK sy-subrc = 0.

READ TABLE lt_struc_tab ASSIGNING FIELD-SYMBOL( ) INDEX 1.
ls_comp-instance = -instance.

CALL FUNCTION ‘CRM_IBASE_COMP_DELETE’
EXPORTING
i_comp = ls_comp
EXCEPTIONS
DATA_NOT_CONSISTENT = 1
IBASE_LOCKED = 2
NOT_SUCCESFUL = 3
NO_AUTHORITY = 4.

CASE sy-subrc.
WHEN 1.
WRITE: / ‘data not consistent’ COLOR COL_NEGATIVE.
WHEN 2.
WRITE: / ‘cannot delete locked component’ COLOR COL_NEGATIVE.
WHEN 3.
WRITE: / ‘deletion not successful’ COLOR COL_NEGATIVE.
WHEN 4.
WRITE: / ‘no deletion authorization’ COLOR COL_NEGATIVE.
ENDCASE.

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Go)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
ion’ COLOR COL_NEGATIVE.
ENDCASE.

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Go)
[外链图片转存中…(img-WeqTu81y-1713190690023)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 9
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值