分类 SAP 下的文章

类是不是越小越好?最近在读John Ousterhout的《A Philosophy of Software Design》,感到作者文笔流畅,书中内容具有启发性。这里摘要一部分内容,以供开发工作中的参考、学习。

本文链接:https://www.cnblogs.com/hhelibeb/p/10708951.html

转载请注明

 

在软件复杂度的管理当中,最重要的技术之一是通过对系统的设计,使开发者任何在时候都只需要面对整体复杂度中的一小部分。这个过程被称为模块化设计

复杂度是什么?在本文中,复杂度的定义是:和软件系统结构有关的、会导致理解和修改系统变困难的东西。

1,模块化设计

在模块设计中,软件系统被分解为相对独立的模块集合。模块的形式多种多样,可以是类、子系统、或服务等。在理想的世界中,每个模块都完全独立于其它模块:开发者在任何模块中工作的时候,都不需要知道有关其它模块的任何知识。在这种理想状态下,系统复杂度取决于系统中复杂度最高的模块。

当然,实践与理想不同,系统模块间总会多少有些依赖。当一个模块变化时,其它模块可能也需要随之而改变。模块化设计的目标就是最小化模块间的依赖。

为了管理依赖,我们可以把模块看成两部分:接口实现

接口包含了全部的在调用该模块时需要的信息。接口只描述模块做什么,但不会包含怎么做

完成接口所做出的承诺的代码被称为实现

在一个特定模块内部进行工作的开发者必须知道的信息是:当前模块的接口和实现+其它被该模块使用的模块的接口。他不需要理解其它模块的实现。

在本文中,包含接口/实现的任何代码单元,都是模块。面向对象语言中的类是模块,类中的方法也是模块,非面向对象语言中的函数也是模块。高层的子系统和服务也可以被看作模块,它们的接口也许是多种形式的,比如内核调用或HTTP请求。本文中的大部分内容针对的是类,但这些技术和理论对其它类型的模块也有效。

好模块的接口远远比实现更简单。这样的模块有2个优点。首先,简单的接口最小化了模块施加给系统其余部分的复杂度。其次,如果修改模块时可以不修改它的接口,那么其他模块就不会被修改所影响。如果模块的接口远远比实现简单,那么就更有可能在不改动接口的情况对模块进行修改。

2,接口里有什么

接口中包含2种信息:正式的和非正式的。

正式的信息在代码中被显式指定,程序语言可以检查其中的部分正确性。比如,方法的签名就是正式的信息,它包含参数的名称和类型,返回值的类型,异常的信息。很多程序语言可以保证代码中对方法的调用提供了与方法定义相匹配的参数值。

接口里面也包含非正式的元素。非正式部分无法被程序语言理解或强制执行。接口的非正式部分包含一些高层行为,比如函数会根据某个参数的内容删除具有相应名字的文件。如果某个类的使用存在某种限制,比如方法的调用需要符合特定顺序,那这也属于接口的一部分。凡是开发者在使用模块时需要了解的信息,都可以算作模块接口的一部分。接口的非正式信息只能通过注释等方式描述,程序语言无法确保描述是完整而准确的。大部分接口的非正式信息都比正式信息要更多、更复杂。

清晰的接口定义有助于开发者了解在使用模块时需要知道的信息,从而避免一些问题。

3,抽象

 抽象这一术语和模块设计思想的关系很近。抽象是实体的简化视图,省略了不重要的细节。抽象很有用,它可以使我们对细节的思考和操纵变简单。

在模块化编程中,每个模块通过接口提供其抽象。抽象代表了函数功能的简化视图。在函数抽象的立场上,实现的细节是不重要的,所以它们被省略了。

“不重要”这个词很关键。如果没有忽略掉不重要的细节,那么抽象会变得复杂,会增加开发者的认知负担;如果忽略掉了重要的细节,那么抽象会变得错误,失去对实践的指导意义。设计抽象的关键是理解什么是重要的,并寻找最小化重要信息的设计。

依赖抽象来管理复杂度不是编程的专利,它遍布在我们的日常生活中。就像车子会提供一个简单抽象来让我们驾驶,并不需要我们理解发动机、电池、ABS之类的东西。

4,深模块

最好的模块提供了强大的功能,又有着简单的接口。术语“”可以用于描述这种模块。为了让深度的概念可视化,试想每个模块由一个长方形表示,如下图,

长方形的面积大小和模块实现的功能多少成比例。顶部边代表模块的接口,边的长度代表它的复杂度。最好的模块是深的:他们有很多功能隐藏在简单的接口后。深模块是好的抽象,因为它只把自己内部的一小部分复杂度暴露给了用户。

浅模块的接口复杂,功能却少,它没有隐藏足够的复杂度。

可以从成本与收益的角度思考模块深度。模块提供的收益是它的功能。模块的成本(从系统复杂度的角度考虑)是它的接口。接口代表了模块施加给系统其余部分的复杂度。接口越小而简单,它引入的复杂度就越少。好的模块就是那些成本低收益高的模块

某些语言中的垃圾回收(GC)是深模块的例子之一。这个模块没有接口,它在需要回收无用内存的场景下不可见地工作。在系统中加入垃圾回收的做法,缩小了系统的总接口,因为这种做法消除了用于释放对象的接口。垃圾回收的具体实现是相当复杂的,但这一复杂度在实际使用程序语言的时候是隐藏的。

5,浅模块

相对的,浅模块就是接口相对功能而言很复杂的模块。下面是个可能有些极端的例子,

private voidaddNullValueForAttribute(String attribute) {
  data.put(attribute,
null);
}

如管理学学者彼得·德鲁克所说:你无法管理你不能衡量的东西( If you can't measure it, you can't manage it)。要对已有程序进行性能优化,首先要对它的运行状况做出量化分析。

将代码下推到ABAP CDS,是SAP推荐的一种优化方式。但正因逻辑从应用服务器向数据库的转移,传统运行时分析工具SAT也有了力所不能及之处。这时,我们需要新的工具来对这一新的开发对象的运行情况进行分析。

本文将介绍Plan Visualizer(以下简称PlanViz)在ABAP CDS性能分析方面的应用。

 

本文链接:https://www.cnblogs.com/hhelibeb/p/10472856.html

1,示例CDS视图

本文会用到一个系统自带的简单示例视图,DEMO_CDS_JOIN。它的代码如下,

@AbapCatalog.sqlViewName: 'DEMO_CDS_JOIN'defineviewdemo_cds_scarr_spfli 
(id, carrier, flight, departure, destination)
as select fromspflijoinscarr on scarr.carrid =spfli.carrid
{
keyspfli.carrid,keyscarr.carrname,keyspfli.connid,
spfli.cityfrom,
spfli.cityto }

最近工作用到Spark,这里记一些自己接触到的Spark基本概念和知识。

本文链接:https://www.cnblogs.com/hhelibeb/p/10288915.html

名词

RDD:在高层,每个Spark应用包含一个driver程序,它运行用户的主函数,在集群上执行不同的并行作业。Spark中提供的主要抽象是弹性分布式数据集(resilient distributed dataset, RDD),它是分布在集群节点中的已分区的元素集合,可以被并行处理。RDD从Hadoop文件系统中的文件创建,或者从驱动程序中已有的Scala集创建。用户也可以要求Spark将RDD持久化在内存中,允许它在并行操作中被高效地复用。最后,RDD可以从节点故障中自动恢复。

Spark SQL:一个用于处理结构化数据的Spark模块。和RDD API不同,Spark SQL提供的接口会提供给Spark关于数据的结构和计算的更多信息。在内部,Spark SQL使用额外的信息来执行额外优化。有许多方式可以与Spark SQL交互,包含SQL和Dataset API。在进行计算时,无论使用哪种API/编程语言,都会使用相同的执行引擎。这意味着开发者可以基于数据变换的需要来自由切换不同的API。

Dataset:Dataset是分布式的数据集合。Dataset是Spark 1.6中新加入的接口,提供了RDD的优势(强类型化,应用lambda函数的能力),也提供了Spark SQL的优化执行引擎的优势。Dataset可以由JVM对象构造,然后通过函数变换(map, flatMap, filter等)来操纵。Dataset API在Scala和Java中可用。Python不支持Dataset API,但是由于Python的动态性,已经可以享受许多Dataset API的好处。(例如你可以通过row.columnName的方式自然地访问行中的字段)。R语言的情形与之类似。

DataFrame:DataFrame是一种有列名的Dataset。它在概念上等于关系数据库中的表或者R/Python中的数据帧,但是在底层有更多的优化。DataFrame可以从一个多重源构造,比如:结构化数据文件、Hive中的表、外部数据库或者既有的RDD。DataFrame API在Scala、Java、Python和R中可用。在Scala和Java,DataFrame被表示为多行Dataset。在Scala API中,Dataframe可以简单地表示为Dataset[Row]。而在Java API中,用户需要使用Dataset<Row>来表示Dataframe。

 

TempView:createOrReplaceTempView方法会创建(如果已存在同名视图的话,则替换)一个惰性计算视图,你可以将这个视图视作hive表来使用。除非你将Dataset缓存,否则它不会持久化到内存中。可以使用spark.catalog.dropTempView("tempViewName")来删除视图。

Caching and Persistence:缓存或持久化是Spark计算的优化技术。 它们有助于保存临时部分结果,以便可以在后续阶段重复使用。 因此,RDD的这些中间结果保存在内存(默认)或固态存储(如磁盘和/或复制)中。

SparkSession:Spark SQL的入口点。在开发Spark SQL应用时,这是首先要创建的对象之一。

你可以使用SparkSession.builder方法来创建SparkSession。

importorg.apache.spark.sql.SparkSession
val spark
=SparkSession.builder
.appName(
"My Spark Application") // optional and will be autogenerated if notspecified
.master(
"local[*]") // only for demo and testing purposes, use spark-submit instead
.enableHiveSupport()
// self-explanatory, isn't it? .config("spark.sql.warehouse.dir", "target/spark-warehouse")
.withExtensions { extensions
=>extensions.injectResolutionRule { session=>...
}
extensions.injectOptimizerRule { session
=>...
}
}
.getOrCreate

本文是产品与对象相关的部分SAP文档的翻译,不包含配置部分。

本文链接:https://www.cnblogs.com/hhelibeb/p/10112723.html

1,对象(Objects)

对象是全局唯一的有形或无形对象,公司销售它或为它提供服务。对象通常是继承自产品的特定单一单元。然而,不像产品,对象是唯一的。这意味着虽然可能有相似的对象,但至少有一个描述对象的属性是不同的。这通常是它的标识符。比如说,车子会有自己的号码牌。

对象构成的唯一实体是公司和相关方间业务的中心。例如,一家电力供应商,可以使用对象描述他们输电的位置,比如“建筑”或“住房”。

对象被集成在产品主数据中,提供给你用于在业务处理中创建、跟踪所需信息的工具。产品主数据提供了检索对象相关信息的中心源。

对象数据包含了特定业务处理需要的信息(例如客户调查,销售订单,服务处理,合同),以及其它在本质上描述或分类对象的基本数据。比如:

  • 描述性数据,比如尺寸和数量
  • 具备控制功能的数据,比如决定销售订单中的每个项目分类的项目分类组。

这一信息存储在单独的产品主数据记录中。相关数据集合在一个单一的数据库对象中,这样可以避免存储冗余数据。

以下是对象所具备的特点,

产品类型(Product Types

产品类型描述对象的基本特性,它也决定可以分配到对象的分类,从而决定对象的特性和它被使用的方式。(Only the product type Materialcan be used for objects.)。产品类型包含以下几种,

  • 物料

  • 服务

  • 保修

  • 金融

  • 金融服务

  • 知识产权(IP)

对象族(Object Family

每个对象都属于一个对象族。对象族是基于对象属性的分组。创建对象时,必须为其分配对象族。

属性和集类型(Attributes and Set Types)

属性用于描述被划分为相同的集类型的对象。集类型的使用提供了在系统中为对象详细建模的能力。

分类和层次(Categories and Hierarchies

分类和层次用于实现结构化,并且允许你将对象按照不同的条件分组。分类定义了允许被分配给对象的集类型和关系类型,从而允许你通过分配分类来将对象的信息按需要结构化。

关系(Relationships

可以在对象间、产品间和产品与对象间创建关系,来表示特定的产品信息。例如组件,计数器,保修,资质要求等。

参考产品(Reference Products

可以参考参考产品的技术和业务数据。

备选ID(Alternative IDs

可以在产品主数据中定义备选ID,并且在业务处理中使用它们而不是对象ID。备选ID允许你在业务处理过程中使用满足行业标准的标识符,比如车辆识别号(VIN),序列号,ISBN。

例子:

2,集类型和属性

属性用于描述产品,集类型是产品的组。它们作为数据库表存储在系统中。

注意:在本节中,“产品”既指产品,也指对象。

集类型允许将数据字段组分配给产品,通过这样的方式可以为产品在系统中详细建模。

集类型和属性需要和产品层次、产品分类同时使用。这些元素的结合使相关的集类型可以在产品页被使用,从而描述产品。

结构

集类型被分配给分类,而不是直接分配给产品。通过将集类型分配给分类,相应地把分类分配给产品,你可以按需要提供描述产品的数据。

机制如下,

标准集类型

集类型可以是为了满足专门需求的自定义集类型,也可以是SAP标准的集类型。SAP提供了以下标准集类型,

通用集类型,

Technical Name

Description

COMM_PR_SHTEXT

描述

COMM_PR_UNIT

计量单位

COMM_PR_LGTEXT, COMM_PR_LGTEXT1, COMM_PR_LGTEXT2

Notes/Sales Notes

CRMM_PR_SALESA

销售:控制字段,数量

CRMM_PR_SALESG

销售:分组

CRMM_PR_TAX

物料集类型,

Technical Name

Description

COMM_PR_MAT

物料基本数据

COMM_PR_GTIN

全球贸易项目号

CRM_PR_RESIDVL

金融相关属性

服务集类型

Technical Name

Description

CRMM_PR_BTR

事务控制字段

CRMM_PR_SRVDUR

工作期间

CRMM_PR_SRVRR

资源需求

CRMM_PR_SRVENT

服务合同默认值

SERVICEPLAN

服务计划

CRM_SERIALNUM

服务中的序列号处理

保修集类型

CRMM_PRWTY

保修

CRMM_PRWTY_CAT

保修分类数据

CRMM_PRWTY_SRV

保修服务

CRMM_PRWTY_CNT

保修次数数据

其它产品类型的集类型

Product Type

Set Types

Financing

金融集类型

Financial Service

金融服务产品集类型

Intellectual Property Management

知识产权管理集类型

3,产品层次

产品层次提供了一种结构化的机制,可以用于在产品主数据内建模。

注意:在本节中,“产品”既指产品,也指对象。

产品层次包含用于根据不同条件将产品分组的分类。层次的目的取决于你的公司的需求和业务标准。

层次可以是多级的,用来实现控制和信息方面的功能。

结构

层次内的分类是分层排列的。所有低层分类继承高层分类的产品类型和集类型。可以为低层分类分配附加的集类型。

例子如下(注意下面的集类型不是标准的,只是个自定义的例子):

如果一个产品类型被分配到分类,只有这个产品类型的产品可以被分配给分类。分配产品类型给分类使得可以将集类型分配给分类。集类型可以在产品或对象页面作为assignment block出现。

为了防止一个集类型被多次基于分类分配给同一个产品,在设定分类和层次时需要按以下原则进行:

  • 一个集类型可以在同一个层次中被分配给多个分类,但是每个产品类型只能有一个层次。因此即使两个分类在不同的层次中、但是有相同的产品类型,也是无法将同时集类型分配给两个分类的。
  • 一个产品可以被分配给多个分类,只要分类属于不同的层次。因此产品在各个层次中都只能分配给一个分类。

 

相关链接:SAP Document

 

 

本文介绍了SAP Solution Manager中的变更请求管理工具(Change Request Management,以下简称ChaRM)。

最近打算写个上线前请求号检查工具,为此需要了解相关工具的工作方式。本文中的部分内容似乎前后有所出入,请自行判断。如有翻译错误请在评论指出。

 

本文链接:https://www.cnblogs.com/hhelibeb/p/9929331.html

英文原文:Basic Procedure for Change Management (ChaRM)

 

CHaRM是什么?

  • SAP ChaRM是一个包含在SAP Solution Manager内的工具,它可以实现对变更的从设计到测试到传输生产的过程管理。它允许你在整个业务解决方案中跟踪变更请求(CR)和传输请求(TR)。
  • SAP ChaRM使用基于工作流的审批来管理TR和解决方案蓝图中的功能变更。
  • ChaRM的project的帮助下,我们可以扩展TMS的功能,确保所有传输请求一起移动QA,将集成/回归测试作为整体进行,并将它们共同导入到生产系统。
  • 在某些方面不再需要电子表格(Excel),因为SAP Solution Manager Project会持续跟踪项目与传输请求的关联关系、以及传输请求的导入顺序。

前提

  1. 用合适的路径正确配置系统。
  2. Solution Manager和卫星系统间的RFC连接正常。
  3. 配置STMS。
  4. 定义系统间的传输路径。
  5. 激活TMS中的扩展传输控制。
  6. 取消激活质量保证审批程序(quality assurance approval procedure)、激活单一传输策略。

处理步骤

ChaRM涉及到项目中的以下机构,

  1. 请求者:认为配置变更和ABAP变更导致了错误的人。请求者会在Solution Manage中提出变更请求。
  2. 变更经理:负责决定和审批变更请求的人(原文"advisory board")。
  3. 开发者:根据每个变更请求来进行更改的人。他们可能是functional consultant和technical consultant。
  4. 测试者:测试团队(包含functional consultant和用户)。
  5. IT运维:Basis等。

步骤流程图如下,(注:图和下面的步骤描述似乎不一致,原图如此。个人认为下面的步骤描述更准确)

在Solution Manager CRM中的实际步骤如下,

我们在事务代码“SM_CRM”中得到了变更请求,需要在SAP中进行配置变更。这是我们从服务台得到的配置方面的一些变更事件(Incident)。

创建事件的时候,我们需要把状态变更为“Suspended”状态,或者根据配置设置为其它状态

获取suspended状态的问题清单,并且为变更创建请求。

前往Solution Manager的事务代码“SM_CRM”。点击下图中的Request for Change来创建CR。

当你点击"Request for Change"后,系统会展示如下界面,

在该界面中,输入

  1. Description:细节描述。
  2. Sold to Party:选择提出变更的人的名字。
  3. Requester:会自动出现。是创建CR的用户名。
  4. Approval Procedure:选择Change Request Approval Procedure。
  5. Priority:选择CR优先级。
  6. Project:输入项目名。

系统状态是自动设定的,我们不能手工修改。

在下方输入细节描述。也可以上传文档。

 

 输入请求的修改范围,

这里我们选择600 client,配置条目是"7100000058"。

保存。

现在请求者(Requester)应前往CR,使用工具栏的action按钮,设置状态为"Validation"。

保存,系统会显示单据状态为Validation

请求者完成了确认,现在他可以把请求提交审批了。在Action处选择"Release for Approval"。

保存后,状态会变为"To be approved",如下图。

变更经理(Change Manager)开始工作,他会检查请求,并按下面的操作审批。

变更经理会把状态设置为"Approved"或其它状态。

假设他选择了"Approved"并保存了请求。

现在请求者会看到审批过的请求。请求应该被发布为开发中状态,

保存,状态显示审批后的请求已经进入了处理中的状态。如果CR和ABAP开发相关,那么请求附件中需要包含FS文件。

可以看到状态是"Being Implemented".

当我们保存状态为"Being Implemented"的CR的时候,系统会生成一个change note号码,

前往变更对象,内容如下。当前的处理着可以填写下面的内容,

Developer:处理者将会填写这项,指定将会进行开发或配置的人。

Tester:将会在配置变更/开发完成后测试的人。

IT Operator:业务端的测试者或者是负责将请求传输到测试和生产系统的人。(注:原文如此)

变更问题的状态为"In Development",并保存。

在这步之后,请求会被传输到测试系统,相关人员进行测试。

优势

  1. SAP ChaRM允许组织有效地控制和管理SAP系统中的更改。
  2. 通过实现对某些点的强制控制和文档化的步骤,它保可以证对SAP系统的任何更改都遵循标准流程和程序。
  3. 提供跟踪和审计变更的能力。
  4. 通过配置CTS +,ChaRM可扩展到项目中的所有ABAP和非ABAP SAP环境。
  5. ChaRM不仅仅是对传输的技术管理工具,它还是一个功能强大的项目变更跟踪系统。它提供以下功能:
  6. 提供对需求和变更请求的可追溯性。
  7. 通过利用工作流来表示针对每个变更请求采取的行动。
  8. 报告和跟踪各个变更请求的状态和整个项目的状态。
  9. 为变更管理审计提供审批跟踪。
  10. 基于项目阶段,为传输请求提供防护。比如:如果某项目正处于测试阶段,尝试传输相关内容至生产的话,会遇到错误消息:“你不能在当前传输某项目的任何请求”。