通过接口标准化ABAP OO开发
本文是对接口编程的讨论,希望能对年轻的开发者有所帮助。
要点:
- 通过接口对类方法进行更高层的抽象
- 接口使代码清晰易读
- 接口使你可以创建模拟对象(Mockup Object)以提高代码的可测试性
- 帮助实现SOLID原则
- 可以在不使用RTTS和类型转换的前提下使用多种类的不同实例。
因为在学习ABAP之前,我曾经学习过其它面向对象语言,因此我很纠结于ABAP中不存在的一个特性——重载方法(overload)。
也许你会问,重载是什么?
重载就是函数或者方法有相同的名称,但是参数列表和实现不相同的情形。
没有了重载,在某种程度上,类也许会变的过大,并且难以追踪那些有着相似行为但是名字不同的方法。
接口不提供重载能力,但是通过限制名字不同但是功能相近的方法的数量,接口可以整理和简化你的代码。
本文链接:http://www.cnblogs.com/hhelibeb/p/8919767.html
英文原文:Using interfaces to standardize your ABAP OO Development
简介
在ABAP中类的继承是单一继承(每个类只能有一个父类),接口实现可以有多个。
例如,上图中的LCL_Child_Class继承LCL_Parent_Class中所有的非私有变量、方法、类型和常量,并且必须实现LINF_Utility和LINF_Saver接口中所有的功能。
为了解释接口的定义,我将使用个“不怎么专业”的描述——它是一个类似于类的实体,不包含所声明的方法的任何具体实现,但是它可能包含常量、类型和变量。接口无法被初始化。
默认情况下接口的所有方法都必须被实现——这是面向对象编程中的一个通常的强制规则。不能允许接口方法的实现变得可选择,但是这不属于本文的讨论范围,所以不会展开论述。
(译注:原文评论指出,在ABAP中,可以使用DEFAULT IGNORE|FAIL附加项指定可选的接口方法,虽然好像并没有什么用)
“真实”用例
设想下我们有个程序,需要从多种数据源获取数据并更新到表SFLIGHT:
- Excel上传
- RFC上传
- 在程序运行期间上传修改和插入的行
当然我们可以在该清单中添加ADBC源、经由HTTP客户端对象抓取的JSON/XML源等,但是我只是想介绍下要点,没必要穷举所有例子。
同时,因为本文只是对可能性的表述,因此我不会创建一个能真正工作的程序。
声明接口
我们将创建2个接口,不过在这个例子里只有一个是真实需要的。
第一个是最重要的,我命名它为linf_sflight_career,因为这是个用于EXCEL、RFC和本地表运输(carrier)的本地接口,在本地类中实现。
interfacelinf_sflight_carrier.
types: tt_sflight type standard table of sflight with default key,
st_sflight type sorted table of sflightwith non-unique key mandt carrid connid,
ht_sflight type hashed table of sflightwith unique key mandt carrid connid fldate.
methods:"! Returns hashed table SFLIGHT contents "! @parameter r_sflight | get_hashed_records returning value(r_sflight) type ht_sflight,"! Returns sorted table SFLIGHT contents "! @parameter r_sflight | get_sorted_records returning value(r_sflight) type st_sflight,"! Returns standard table SFLIGHT contents "! @parameter r_sflight | get_standard_records returning value(r_sflight) type tt_sflight.
endinterface.
SAP中的BRF+
即便努力去尝试最小化SAP系统中的自定义内容,通常还是无法避免大量的自定义业务逻辑。在过去,这意味着需要在系统的各种地方引入自定义ABAP代码,包括user-exits,enhancement,BAdi和自定义程序等等。考虑到SAP系统的复杂性和相互依赖性,人们不得不小心翼翼地管理基于ABAP的自定义内容,以保证不同的功能区域的业务逻辑一致、且不重复。
现在,Business Rule Framework Plus(业务规则框架,以下简称BRFplus或BRF+)来了,它是SAP推出的新功能,可以在一个位置、通过可复用的方式管理你的所有自定义业务逻辑。
本文链接:http://www.cnblogs.com/hhelibeb/p/9021665.html
英文标题:BRFplus - a hidden gem within your SAP system
可用性
- 输出表单中的Logo判断
- 服务提醒文档的默认优先级和截止日期判断
- 销售订单的默认工厂判断
- SAP Transportation Management中的默认载具判断
从技术的观点看,BRF+最常见的用例是在user-exits和增强中的自定义业务逻辑实施中。事实上,在这些情况下,BRF+是我们实现自定义业务逻辑的首选实现手段。它在较高层面上可以被描述为2步:
- 在BRF+中创建一个function,依据需要的业务逻辑,它接收输入、进行处理,然后给出输出结果。
- 通过ABAP在user-exits/BAdi/enhancement/自定义程序等地方调用先前创建的BRF+应用。
很重要的一点是,在上述的方式中你还是需要写一些ABAP代码来调用BRF+ function。(和完全使用ABAP代码实现业务逻辑的)区别在于,通常来说,在这种情况下,ABAP代码只负责调用BRF+,不会直接包含业务逻辑。你可能要问这样做的好处在哪里。它的好处是:
- BRF+ function易于复用,通常可以大大地减少系统中重复业务逻辑实现的数量。
- BRF+包含一个巨大的expression库,可以加速映射业务规则的开发过程,特别是这些业务规则比较复杂的情况下。使用ABAP编码来从零开始(from scratch)实现某些东西,也许可以花上数天甚至数周的时间,但是在BRF+里只要使用expression就可以快速地建模实现。
- 你的所有自定义业务逻辑可以在一个地方实现——BRF+事务。你不需要从庞大的自开发程序、增强中搜寻代码以调整现有的业务逻辑。
- 对现有的业务逻辑的简单调整可以经由非编码的方式实现,不需要开发人员的参与。
最后一点值得详细阐述。SAP通常建议通过BRF+工具让业务用户代替ABAP开发者来作为他们自己的逻辑的维护者。坦白说,这种建议有点夸张(exaggerattion)。实际上,BRF+元素(function, expression等)的创建依然是一件相当技术性的活动。大部分没有技术背景的SAP专家可能会发现,想要掌握BRF+的全部内容是件具有挑战性的事情。了解一些基本的编程概念,如变量和循环,会对BRF+的使用起很大帮助,即便你只是通过鼠标来创建这些对象,而不是写ABAP代码。但是撇开陡峭的学习曲线不说,在具备足够多的学习时间和努力的情况下,SAP功能分析师当然是可以精通BRF+的,由此便可以在不依赖开发者的情况下构建复杂的自定义业务逻辑。然而,业务用户完全是另一回事。业务用户对BRF+进行某些实验性的调整是可能的,例如改变已有的decision table中的值,但是BRF+内的主要变更还是需要由IT团队进行。
特性
BRF+中包含很多了不起的特性,使得它是一个杰出的业务规则框架。
expressions
在许多方面上expressions是BRF+中第一个令人心动的东西。它们是预包装的逻辑对象,可以在BRF+环境中大大加速业务规则的建模。虽然BRF+中支持多种表达式类型,但最常用的一种是Decision Table。如果你熟悉SAP系统中的条件技术,decision table会给你相似的感觉,并且它会提供扩展性更强的功能。除了可以从表的顶部检索到底部直到找到匹配的记录为止外,你也可以维护输入值为多值的range、sets、通过空白来表示任意值、以及使用其它一些逻辑操作符等。
customizing and master data applications
定制和主数据应用(customizing and master data applications)是BRF+中的一个灵巧的特性。定制应用需要使用SAP transports来在不同SAP系统之间移动修改,相反主数据应用允许直接在每个SAP系统和client直接进行修改。在你将主数据值,比如客户、供应商、物料等是业务逻辑的一部分时特别有用。记住,因为在多数情况下BRF+通过ABAP调用,function本身需要存在在一个定制应用中。但是这些定制级别的function接下来可以利用存在于主数据级别应用下的expressions(例如decision tables)。一言蔽之,你可以在一个业务规则中混合使用定制和主数据BRF+对象。
user interface
BRF+中的建模大多通过“点击”的用户界面进行,通过事务代码BRF+访问它。你可以通过简单地右击屏幕左侧的节点来创建新的对象,并且通过上下文菜单选择合适的条目。
api
你也可以通过API和BRF+交互。这意味着你不仅可以通过事务BRF+来创建和更新BRF+对象,你也可以通过标准交付ABAP类和方法(standard delivered ABAP classes and methods)实现同样的事情。例如,在某个场景中我们需要存储美国的柴油平均价到BRF+的decision table中。我们可以创建一个自定义ABAP程序通过公网服务来查找上周的柴油价格,并且最后经由BRF+ API更新decision table。
web services
BRF+ functions可以很容易地暴露为web services。这意味着你可以同时在SAP和非SAP系统中消费BRF+业务逻辑。
helper tools
BRF+伴随着大量的工具,可以帮助你开发、导入/导出、检查和BRF+对象和排查故障。其中某些工具可以从BRF+事务中的菜单访问,不过最简单的查找他们的方式是在SE38中运行程序FDT_HELPERS。较早地了解这些工具,你就可以在将来省下很多时间。例如,下图里选中的工具允许你快速地识别和解决大部分有关系统间传输BRF+对象的问题。
总而言之,大部分SAP客户都可以在不需要额外许可证的条件下使用BRF+。我们鼓励你仔细了解BRF+、并且开始为你的自定义业务逻辑需求使用它。
我的BRF+教程系列:http://www.cnblogs.com/hhelibeb/tag/BRFplus/
ABAP on HANA之CDS Association和Path Expression
本文阐述了ABAP CDS association的概念,并且展示了在CDS视图中和SQL语句中写路径表达式(Path Expression)代码的方法。我也会解释如何在CDS asociation中指定inner join——默认情况下是left outer join,以及如何为association添加过滤。
对于CDS的相关开发,SAP希望我们使用association而不是join,因为association更加接近“概念思维”。基本上,association本身不是join,它只是有关join连接可能性的元数据,它会按需成为join。真实的join会在路径表达式使用association的时候被创建。
一个简单的CDS association例子,它看起来和left outer join没区别:
@AbapCatalog.sqlViewName: 'ZCDS_ASSOC11'defineview zcds_assoc1 as select from scarr assca
association[0..1] to spfli as_spflion sca.carrid =_spfli.carrid
{* }
SAP S/4嵌入式分析——虚拟数据模型(VDM)
在本文中,我会通过CDS视图来介绍虚拟数据模型(Virtual Data Model,以下简称VDM)。
在SAP HANA平台出现后,SAP的业务应用开发模式已经产生了变化,新的经验法则是:尽可能在数据库中做更多的事情(PUSH DOWN),以得到最佳的性能。
本文链接:https://www.cnblogs.com/hhelibeb/p/9223993.html
嵌入式分析
SAP S/4嵌入式分析是S/4的一部分,用于对业务数据执行复杂的实时报表和分析。SAP S/4嵌入式分析的关键架构组件包括SAP HANA数据库,VDM,分析引擎(嵌入式SAP BW),OData服务,和如下图所示的接口。
本文将介绍其中的VDM。
CDS视图
为了在应用开发中利用SAP HANA的优点,SAP引入了新的数据建模基础设施,名为Core Data Service(以下简称CDS)。通过CDS,数据模型会在数据库而非应用服务器中定义和消费。CDS也提供了传统数据建模工具的兼容性,包含支持概念建模和关系定义,内置函数和扩展。
技术上讲,CDS是提供数据定义语言(DDL)的加强版SQL,用于在数据库中定义富语义数据库表/视图(CDS entity)和用户定义的类型。增强包括:
- Expression:用于在数据模型中计算和查询。
- Association:在概念层上,通过简单的path expression代替join(关于Association可参考之前的文章)。
- Annotation:通过附加的(特定领域的)元数据来丰富数据模型。
CDS在ABAP和SAP HANA中都得到了原生支持。数据模型通过数据定义语言(DDL)表达,并且定义为CDS视图,可以在ABAP程序中通过Open SQL语句访问。CDS为业务和开发提供了一系列优点,包含:
- 富语义数据模型:CDS基于众所周知的实体-关系模型,并且实质上是声明式的,非常接近概念思维。
- 兼容任何数据库平台:CDS会被生成为受管理的Open SQL视图,并且原生地集成进入SAP HANA层。这些基于Open SQL的视图得到了所有主流数据库供应商的支持。
- 高效:CDS提供了多样化和高效的内置函数,例如SQL运算符,聚合和表达式,来帮助开发者构建视图。
- 支持annotation:CDS语法支持特定领域的annotation,可以轻松的被其他组件利用,比如UI,分析和OData服务。
- 支持概念关联(conceptual associations):CDS帮助你定义association,作为不同视图的关系。Path expression可以用于在关系间导航。association引入了抽象的外键关系和join,来对可消费的entity进行导航。
- 可扩展性:客户可以扩展SAP定义的CDS视图,扩展字段将随其使用层次结构自动添加到CDS视图中。
VDM
在HANA之前,查询ERP系统中的大量数据集会花很多时间,并会降低系统的整体性能。数据仓库可以通过高级建模技术创建持久化的数据模型,以提高查询性能。SAP HANA去除了ERP中的性能问题,使我们能够直接在ERP中创建虚拟数据模型(VDM),并提供令人难以置信的高性能。
VDM是什么?VDM是富语义CDS视图的结合,它将ERP源表的数据符合逻辑地结合到一起,创建成为有意义的数据集,并且可以被前端工具便利地消费。
VDM的核心原理是在现有的S/4数据库模型之上构建语义层,隐藏它的技术细节。基于提供的内容和复用选项,VDM中的CDS视图被分为接口视图或消费视图,如下:
私有视图
私有视图(Private Views)实际上不是提供给终端用户消费的视图,它是技术驱动的辅助视图。引入私有模型是为了帮助底层数据模型到公共视图模型的转换。私有CDS视图的名字前缀是P_。不建议修改或扩展它们。
接口视图
接口视图(Interface views)是VDM最重要的组成部分。接口视图组成了可复用的entity视图,在业务语义是定义上的重点。接口视图对任何消费者而言都是公开的、稳定的并且可复用的。公共接口视图的结构需要不受correction、补丁和升级的影响。
接口视图分两种:
基本接口视图(Basic interface Views)代表没有数据冗余的核心entity,即对每个核心entity做单一的表示,(比如,正好一个客户或者销售订单)并且只带有依赖于核心entity自身的、无法从其他字段计算得到的字段。基本视图组成了低冗余模型和SAP Business Suite数据库表的简单投影。
组合接口视图(Composite Interface Views)继承自多个简单接口视图,也许会有关联、聚合和复杂计算。它们可以属于特定消费域,或者被复用,根据设计,它们总是暴露冗余的数据。按照实际的使用情况,组合接口视图可以分为很多层。
消费视图
如名字所示,消费视图(Consumption Views)是暴露给终端用户消费的视图。消费视图会使用到一个或更多接口视图。消费视图是共用的特定领域视图,用于分析、搜索和事务应用。VDM建模的指导原则是,数据库表一定不可以被消费视图直接访问(即不可以绕过接口视图)。
扩展包含视图
扩展包含视图(Extension include Views)用于暴露自定义新字段。可以扩展SAP发布的扩展包含视图,以条件附加字段。自定义扩展包含视图会在单独的DDL源中创建和传输。
总之,在高层上,CDS视图从数据库表得到数据,这些视图又会被其它CDS视图读取,VDM就是由所有的这些CDS视图组成。没有任何持久化过程,一切都是实时的。
Annotation
Annotation用于描述CDS视图,为CDS视图中的字段提供语义和意义。
- 它可以应用在整个CDS视图entity上;
- 它可以指定SELECT列表中特定的字段的语义;
- 总是在@符号后面
这面是annotation的列表:https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abencds_annotations_sap.htm
也可以通过以下路径访问:ABAP – Keyword Documentation > ABAP – Dictionary > ABAP CDS in ABAP Dictionary > ABAP CDS – Syntax > ABAP CDS – Annotations
下面是用于VDM的定义整个CDS视图的一些关键的annotation:
Annotation | Description |
VDM.viewType | 定义VDM视图的类型 |
Analytics.dataCategory | 分析查询可以在CDS视图之上定义。通过指定数据分类,开发者可以提供指令和hints,告诉analytic manager如何解释各个实体。 |
Analytics.dataExtraction.enabled | 应用开发者通过该annotation标记适合于数据复制的视图(例如,必须为海量数据提供增量复制能力)。 |
Analytics.query | 通过标记CDS视图,开发者可以指定暴露给analytic manager的视图。这类视图会被analytic manager解释为分析查询。 |
ObjectModel.dataCategory | 定义数据分类(#TEXT 或 #HIERARCHY) |
ObjectModel.representativekey | Most specific element (field or managed association) of the primary key (indicated by the keyword KEY) that represents the entity which the view is based on |
AccessControl.authorizationCheck | 针对指定的CDS视图启用行级别权限控制 |
/名词解释:analytic manager是一个BW概念,它提供OLAP功能和服务,以及BW集成规划和分析过程设计的服务。
因为我还是个BW开发者,我找了几个最重要的VDM的annotation来和BW对象对比:
Annotation: @VDM.viewType
Value | Description | BW对等物 |
#BASIC | 组成核心基础的视图,无数据荣誉,它只是从数据库物理表的SELECT。 | 等于ADSO(高级数据存储对象),即通过某些ETL后的raw data。 |
#COMPOSITE | 提供从基础视图继承和/或组合而成的数据 | 等同于Composite Provider,是允许进行join和union的虚拟数据层。 |
#CONSUMPTION | 为特定应用目的服务的视图,也许会基于公共接口视图定义(比如BASIC 视图或COMPOSITE视图) | 等于BW Query,可以指定特殊的样式,变量,RKF,CKF,总计,等等。 |
Annotation: @Analytics.dataCategory
Value | Description | BW对等物 |
#DIMENSION | 表示主数据的视图需要有annotation:ObjectModel.dataCategory: #DIMENSION | 等于Infoobject Attributes |
#FACT | 事实表表示业务数据(星型模型的中心)通常包含度量。这些视图通常是复制所必须的,因此,他们不能和主数据视图join。 | 等于从一个单一数据源加载的ADSO,没有任何主数据。 |
#CUBE | CUBE也代表事实数据,和FACT很像,但是CUBE不必是无冗余的。这意味着它可以和主数据join。查询基本都是构建在CUBE之上的,CUBE从FACT复制数据。 | 等于从单一/多个数据源加载的ADSO,和主数据的attributes/texts/hiererachies连接。 |
我的BRF+自学教程(二):跟踪模式(trace mode)
使用自开发程序来处理业务逻辑时,处理过程通常是个黑箱,业务顾问和业务用户不知道程序的具体运行方式,要依赖文档和频繁的沟通来确认实际情况。
BRFplus可以通过配置的方式实现业务逻辑,使得业务人员把业务逻辑的实现掌握在自己手中,此外,跟踪(tracing)功能的存在使得业务逻辑应用的执行情况也变得清晰可见。
本文链接:https://www.cnblogs.com/hhelibeb/p/9556478.html
目的
跟踪模式有以下用处:
- 有助于找到BRF+应用运行结果与预期不一致的原因。
- 统计各规则的使用情况,从而理解规则调整的影响和风险。
- 统计输出结果的分布情况。
跟踪信息可以帮助人们进一步理解业务的实际执行情况,确定哪些场景是常见的、哪些是偶然的甚至永不出现的,从而进一步优化业务逻辑实现。
实现
虽然跟踪模式可以服务业务,但是因为BRF+应用需要通过ABAP代码来调用,所以实现部分会是和ABAP相关的内容。
我创建了一个简单的BRF+应用,其功能是根据输入的采购订单编号,到数据库表EKKO中查询采购组和采购订单类型,根据这两个字段的组合,来决定是否需要审批。涉及到2个表达式,1个是数据库查找(DB lookup),还有一个是决策表(decision table)
调用
ABAP调用代码,
REPORTztest_brf3.PARAMETERS: p_ebeln TYPEebeln.START-OF-SELECTION.*获取function实例 DATA(lo_fuction) =CAST cl_fdt_function(
cl_fdt_factory=>if_fdt_factory~get_instance(
)->get_function( '005056A4CCA61ED8AAF183894A92CC2B') ).*获取context实例 DATA(lo_context) =CAST cl_fdt_context(
lo_fuction->if_fdt_function~get_process_context( ) ).*将将采购订单号输入到context lo_context->if_fdt_context~set_value(
: iv_name= 'EBELN' ia_value =p_ebeln ) .*处理,获取结果和跟踪数据 lo_fuction->if_fdt_function~process(EXPORTING io_context =lo_context
iv_trace_mode= if_fdt_constants=>gc_trace_mode_leanIMPORTING eo_result = DATA(lo_result)
eo_trace= DATA(lo_trace) ).