lawson算法_案例研究:Lawson合并后整合架构的新方法

lawson算法

介绍

在当今的并购时代,解决方案架构师面临的一个普遍问题是以提供一致的用户体验的方式集成产品线。 当Lawson Software,Inc.(Lawson®)与Intentia International AB(Intentia®)合并时,开发人员面临着创建无缝,同质的用户体验以提高用户生产力,用户满意度和信息的任务。整合,同时涵盖新公司的旗舰产品线(对于制造,移动和维护产品或资产的以产品为中心的行业,称为“ M3”;对于人员,采购和服务以满足客户需求的服务行业,称为“ S3”)。

本案例研究将研究Lawson解决难题的方法,并从技术上详细探讨其解决方案和整体系统架构中一些更有趣的方面。

问题域

合并之前,Lawson和Intentia都提供了企业资源计划(ERP)解决方案来选择目标市场和地区。 Lawson的主要产品线S3专为主要在美洲的以服务为中心的行业而设计。 S3应用程序可帮助他们的客户“人员,资源和服务”,其ERP功能包括企业绩效管理,业务流程管理,企业财务管理,供应链管理,服务管理和人力资本管理。 尽管意图类似,但Intentia的M3产品主要针对EMEA和APAC的运输和制造公司-任何可能“制造,移动和维护”商品或设备的客户。 M3应用程序包括制造运营,供应链执行和优化,客户销售和服务,企业资产管理,财务管理与控制以及业务流程管理服务。 两家公司合并的理由很明显-互补的产品线,地域和目标行业。

尽管两家公司的系统具有相似之处,但其实现却有很大差异。 Intentia的M3系统以服务器端Java业务逻辑层为中心,可通过许多不同的客户端应用程序进行访问。 多年来,Intentia的客户端用户界面(UI)取得了进步,从MicroFocus Cobol / C ++富客户端开始,通过基于Active Server Pages(ASP)和JavaServer Pages(JSP)的瘦客户端解决方案,发展为异步JavaScript和XML(AJAX)。基于/ JSP的瘦客户端门户,称为Workplace Foundation。 Lawson S3应用程序套件是基于Java的解决方案和基于第四代语言(4GL)的解决方案的组合,但是正在以类似的整体方式演变为基于纯Java的解决方案。 在两家公司之间,正在利用许多不同的客户端技术,从Workplace Foundation Web门户到基于C#的移动销售丰富客户端。

合并的结果是,Lawson正在寻找一种创建可以利用其两个旗舰产品线的客户端应用程序的方法。 具体来说,他们希望创建一个客户端应用程序,该应用程序将:

  • 为通过Windows XP和Vista客户端访问的应用程序提供通用的外观和感觉(98%的客户群是从Windows客户端访问该软件的。)
  • 为用户提供启动应用程序和接收消息的通用方法
  • 提供定义良好且可插入的方式来托管新应用程序和功能
  • 提供丰富,高效的用户体验
  • 从“一个代码库”运行,将业务逻辑保留在服务器端,以便可以在不同的客户端之间共享。
  • 与Java和非Java业务逻辑层进行交互。
  • 允许针对同一服务器实例使用以前的客户端和新开发的客户端。

解决方案概述

为了确保新客户应用程序的技术选择合适,Lawson决定寻求frog design europe gmbh( www.frogdesign.com )的协助,以帮助分析当前和新兴的用户界面技术。 他们共同得出结论,满足上述要求的最佳解决方案是创建一个基于Microsoft新的Windows Presentation Foundation(WPF)和新Windows Communication Foundation(WCF)的某些组件(都是.Net 3.0的一部分)的富客户端应用程序框架。 许多因素促成了这一选择:

  • 新产品的发布将与Windows Vista的发布相吻合,使Lawson成为使用该技术的竞争对手中的第一个。
  • 由于Windows是98%的劳森客户的首选平台,因此拥抱.Net的关键组件被视为支持客户投资的一种方式。
  • Windows Presentation Foundation提供了很好的关注点分离,允许将图形设计与其他实现细节分离。
  • WPF提供了一个统一的平台,用于组合表单,控件,音频,视频,屏幕和固定格式的文档,2D和3D图形。
  • WPF提供可扩展的,与分辨率无关的UI呈现
  • Windows Communications Foundation提供了易于扩展的通信编程模型/框架
  • WCF很好地将应用程序代码与通信代码解耦。 无论服务位于何处,使用WCF的客户端代码都是相同的-跨应用程序域,跨进程,在同一台计算机上,在多台计算机上等等。
  • WCF为复合应用程序和面向服务的体系结构提供了一个声明式模型。
  • 部署后可配置WCF端点

客户申请

从上图可以看出,新的富客户端(又名“ Lawson Smart Client™”)具有3个重要的设计层,另外还要考虑支持用户数据或首选项设置。 其中第一个是表示层,负责托管小部件的用户交互和生命周期管理。 它本质上是客户的“画布”。 可以将来自每种不同应用程序类型(M3,S3等)的小部件添加到画布,从而允许用户启动任务并响应传入的事件。 此外,用户可以通过更改画布的“皮肤”来更改客户端的外观。

渲染逻辑层由许多可插拔的“引擎”组成,这些引擎负责渲染特定应用程序行的内容。 内容是在运行时由元数据,用户数据和其他预定义资源的组合生成的,从而确保了一致的外观。

数据访问层利用WPF数据绑定将UI组件绑定到业务逻辑或数据组件。 可以通过这种方式利用多种存储策略,使UI能够从用户首选项,客户端配置,会话上下文等收集数据。这些策略中最常见的是使用WCF端点,该端点通过Web服务连接到服务器端组件。

Microsoft SQL Server Compact Edition用于存储用户首选项,使用情况统计信息和用户状态。 如果用户设置了“漫游配置文件”,则可以使该用户数据对客户端可用,从而允许将用户数据复制到可以从任何Lawson Smart Client设备访问的服务器。

服务器端

从上图中可以看出,Lawson和Intentia多年来开发了大量特定于行业的服务器端业务逻辑和功能。 实际上,图中所示的所有服务器端组件都在开发新的Smart Client之前以某种方式存在。 为了保护和扩展客户的投资和技能,并简化向新技术的迁移,Lawson的最佳选择是继续使用Java和非Java的现有服务器端组件。

为了促进快速生成初始客户端原型,使用了Microsoft的Java转换工具将M3移动销售富客户端使用的J2EE连接器体系结构(JCA)/通用客户端接口(CCI)连接器转换为J#。 这使客户端开发人员可以使用J#客户端连接器与现有后端系统进行接口。 生成的J#连接器已替换为生产客户端,该生产客户端使用WCF端点访问Lawson Web Service Framework创建的Web Service。

Web服务框架允许从业务服务器提供的元数据生成Web服务定义语言(WSDL)和Java连接器代码。 Lawson开发人员重组并重用了J2EE Workplace Foundation应用程序中的现有服务器组件,从而使基于AJAX的Workplace瘦客户端和新的Lawson Smart Client可以利用相同的业务逻辑和服务。

深入研究#1-通过Web服务进行Java和.NET集成

新的Lawson Smart Client利用了新的Windows Presentation Foundation和Windows Communication Foundation的功能。 如下图所示,使用可扩展应用程序标记语言(XAML)将客户端窗口小部件动态绑定到C#数据源。 数据源利用代理对象与适当的Web服务进行通信。 该代理由Microsoft Windows软件开发工具包(SDK)中的服务模型元数据实用工具(SvcUtil.exe)生成,用于处理与Web服务的通信以及C#和Web服务范例之间的转换。 使用超文本传输​​协议(HTTP)上的简单对象访问协议(SOAP)来执行Web服务调用。

从Smart Client窗口小部件进行Web服务调用的示例

©2007 Lawson Software,Inc.保留所有权利。 本文档仅供参考。 Lawson Software在本摘要中做出明示或暗示的担保。

异步绑定(XAML)的示例将客户端小部件绑定到数据源

<ObjectDataProvider x:Key="datasourceCRS990"
ObjectType="{x:Type ds:CRS990DataSource}" />

<ListView x:Name="SelectionList"
ItemsSource={Binding Source=dataSourceCRS990,
Path=ResultCollection, IsAsync=True, Mode=OneWay} >
<... />
</ListView>

来自C#数据源的示例代码,演示了对Web服务代理的调用

Public ObservableCollection<BrowseRow> ResultCollection
{
get
{
InitBrowseCollection data = new InitBrowseCollection();
data.InitBrowseItem = GetCallContext();
try {
CRS990MIClient crs990 =
WSHelper.CreateClient<CRS990MIClient, CRS990MI>();
InitBrowseResponseItem[] responseCollection = crs990.InitBrowse(
WSHelper.GetLWSCredentials<CRS990MIClient>(), data);
return FilterResponse(responseCollection);
}
}
}

生成的WebService代理中的示例方法

...
public InitBrowseResponseItem[] InitBrowse(headerType mws,
InitBrowseCollection initBrowse)
{
InitBrowseRequest inValue = new InitBrowseRequest();
inValue.mws = mws;
inValue.InitBrowse = initBrowse;
InitBrowseResponse retVal =
((SmartClient.Widgets.WS.CRS990MI)(this)).InitBrowse(inValue);
return retVal.InitBrowseResponse1;
}
...

Lawson M3服务器端应用程序套件的核心是Web服务框架。 用Java实现的框架包括客户端设计工具,这些工具允许基于业务系统应用程序编程接口(API)创建,测试和热部署Web服务。 这些设计工具生成用于处理从Web服务到业务API的中介的代码,解析Web服务请求的可扩展标记语言(XML)有效负载,并将业务系统的响应编组回XML响应有效负载。 每个后端API的位置和体系结构差异很大。 例如,M3系统本质上是一个独立的服务器端应用程序,可通过基于传输控制协议(TCP)/套接字的API进行访问,以最大限度地提高性能。

如下图所示,该框架生成了将业务API作为Web服务公开所需的所有连接材料和配置数据。 利用了许多工具,包括用于Java / XML绑定的Apache XMLBeans,以及用于解析和验证Web服务有效负载的StAX(用于XML的Streaming API)。 还包括WSDL的生成,服务的XML描述符以及调用特定业务服务所需的连接器代码。

部署到IBM®WebSphere®应用程序服务器的servlet容器的Lawson Web服务器是利用此生成的代码的运行时引擎。 Web服务器由Apache Foundation围绕Web服务的Axis2核心引擎构建而成,还可以处理运行时配置,连接池和安全性。 Axis2引擎提供了良好的性能和标准支持,包括WS-I基本配置文件和WS安全性(用于消息加密)。 Web服务的隔离是通过类加载器的分离提供的-每个生成的Web服务的类都由离散的类加载器加载。

深入研究#2-从元数据渲染UI

Lawson以前的许多业务应用程序都使用XML来进行客户/服务器通信。 由于老客户继续使用,因此无法更改这些服务/应用程序的实现。 劳森以各种方式适应了这一限制。 现有的瘦客户端应用程序(基于AJAX / JSP)利用可扩展样式表语言转换(XSLT)将元数据和运行时数据的组合从XML转换为超文本标记语言(HTML)。 包含Java语言以处理所有无法通过直接XSLT / HTML实现的“额外内容”。

对于他们的富客户端应用程序,必须使用相同的XML数据来创建UI。 由于动态UI创建是在以前的Java富客户端应用程序之一中完成的,因此该模式已针对Lawson Smart Client的C#进行了调整。

为了使XML能够呈现到UI中,首先使用WYSIWYG表单构建工具来设计业务应用程序中的屏幕。 定义屏幕后,将从描述新创建面板上所有控件的设计工具中导出元数据。 此元数据还包含绑定信息,该绑定信息描述了从服务器端业务应用程序检索的信息以及如何解释此数据。

元数据描述中的面板样本

©2007 Lawson Software,Inc.保留所有权利。 本文档仅供参考。 Lawson Software在本摘要中不做任何明示或暗示的保证。

描述用户界面中面板的元数据片段:

<Panel name="MMA001E0" rtype="DETAIL" modDateField="WMLMDT" regDateField="WMRGDT" changedByField="MMCHID">
<PanelHeader>MMS001/E</PanelHeader>
<PanelDescription langId="MM00101"/>
<Objects>
<GroupBox langId="MX_0235" justification="LEFT">
<Position left="1" top="1" width="73" height="1"/>
</GroupBox>
<Caption langId="WIT0115" tab="256">
<Position left="1" top="2" width="14" height="1"/>
</Caption>
<EntryField name="MMITNO" fieldHelp="ITNO" suppressLeadingZero="true" protected="IN41|!IN45" tab="270">
<Constraints maxLength="15" uppercase="UC"/>
<BrowsePosition top="4" left="18"/>
<Position left="15" top="2" width="16" height="1"/>
</EntryField>
<GroupBox langId="MX_0238" justification="LEFT">
<Position left="1" top="4" width="73" height="1"/>
</GroupBox>
<Caption langId="WNA0115" visible="!IN21" tab="1024">
<Position left="1" top="5" width="14" height="1"/>
</Caption>
<EntryField name="MMITDS" fieldHelp="ITDS" suppressLeadingZero="true" visible="!IN21"
protected="IN01|IN21|IN45&!IN41" tab="1038">
<Constraints maxLength="30"/>
<BrowsePosition top="5" left="18"/>
<Position left="15" top="5" width="31" height="1"/>
</EntryField>
<...>
<FunctionKeys value="001011111001000000000000">
<FunctionKey fKey="F3" langId="XF03000"/>
<FunctionKey fKey="F5" langId="XF05000"/>
<FunctionKey fKey="F6" langId="XF06000" visible="!IN41" reverse="!IN41&IN57"/>
<FunctionKey fKey="F7" langId="XF07000" visible="!(!IN45)"/>
<FunctionKey fKey="F8" langId="XF08000" visible="!(!IN45)"/>
<FunctionKey fKey="F9" langId="XF09000" visible="!IN41"/>
<FunctionKey fKey="F12" langId="XF12000"/>
</FunctionKeys>
</Objects>
<RecordFields length="634">
<RecordField name="WWCLIN" type="DECIMAL" pos="18" length="3" refField="CLIN"/>
<RecordField name="WWCPOS" type="DECIMAL" pos="21" length="3" refField="CPOS"/>
<RecordField name="MMITNO" pos="24" length="15" refFile="MITMAS" refField="MMITNO"/>
<...>
</RecordFields>
</Panel>

然后将每个元数据文件部署到Web应用程序。 该Web应用程序将元数据与业务应用程序中的运行时数据组合在一起,并生成一个包含这两组数据的新X​​ML结构。 这种新的XML格式包含指定哪些UI小部件需要呈现所需的所有信息。 数据包括窗口小部件在屏幕上的位置,格式信息(例如,小数位数等)和输入限制(输入必须为数字)。 呈现AJAX / JSP瘦客户端的代码和新的Lawson Smart Client都使用这种形式的XML。

XML片段,显示元数据和运行时数据的组合:

<Panel name="MMA001E0">
<Objs>
<FKeys val="001011001001000000000000">
<FKey val="F3">End</FKey>
<FKey val="F5">Refresh</FKey>
<FKey val="F6">Text</FKey>
<FKey val="F9">Field Audit</FKey>
<FKey val="F12">Cancel</FKey>
</FKeys>
<EFld tab="270" name="MMITNO" hlp="ITNO" acc="WD">
<Pos l="15" t="2" w="16" h="1"/>
<Constr maxL="15" type="CHAR" uc="UC"/>
B000007
</EFld>
<EFld tab="1038" name="MMITDS" hlp="ITDS" acc="WE">
<Pos l="15" t="5" w="31" h="1"/>
<Constr maxL="30" type="CHAR"/>
Air Filter, Fleetguard AF1811
</EFld>
<...>
<ChkBox name="MMECMA" hlp="ECMA" tab="4149" acc="WE">
<Pos l="54" t="17" w="3" h="1"/>
0
</ChkBox>
<...>
<CBox name="MMSTCD" hlp="STCD" tab="4366" acc="WE">
<Pos l="15" t="18" w="16" h="1"/>
<CBV val="0">0-No inv account</CBV>
<CBV val="1" sel="true">1-Inv accounting</CBV>
<CBV val="2">2-No, but planned</CBV>
<CBV val="3">3-No, but as func</CBV>
</CBox>
<...>
<GroupBox r="t">
<Pos l="1" t="1" w="73" h="1"/>
Panel Header
</GroupBox>
<GroupBox r="t">
<Pos l="1" t="4" w="73" h="1"/>
Basic Information
</GroupBox>
<...>
</Objs>
<PHead>MMS001/E</PHead>
<PDesc>Item. Open</PDesc>
</Panel>

Lawson Smart Client从Web服务器接收此XML文档。 客户端组件解释此XML,动态创建和定位所有UI小部件,使用数据和约束初始化小部件,然后将它们添加到面板中。 该组件还将在此过程中考虑用户和其他UI设置。

用于动态呈现标签的示例代码

private void ReadCaption(XMLNode n) {
string text = n.InnerText;
if (text.Length > 0) {
XMLAttribute a = n.Attributes["tip"];
string name = GetStringAttribute(n, "id");
string tooltip = a != null ? a.Value : null;
bool isFixed = n.Attributes["fixFnt"] != null;
bool isAdditionalInfo = n.Attributes["addInfo"] != null;
bool isEmphasized = n.Attributes["emp"] != null;
bool isColon = n.Attributes["cl"] != null;

CreateLabel(name, text, tooltip, isFixed, false, isAdditionalInfo, isEmphasized, isColon);
ReadPosition(n);
SetPosition();
SetWidth();

ReadAccess(n);
SetAccess();

AddElement();
}
}

protected void CreateLabel(string name, string text, string tooltip,
bool isFixed, bool wrap, bool isAdditionalInfo,
bool isEmphasized, bool isColon) {
Style s;
HorizontalAlignment hAlign = HorizontalAlignment.Left;

if (isAdditionalInfo) {
s = StyleManager.StyleAdditionalInfo;
} else if (isEmphasized) {
s = StyleManager.StyleEmphasized;
} else {
s = StyleManager.StyleLabel;
}

label = controlPool.Create(ControlPool.TypeLabel, s)
as Label;
currentElement = label;
label.Name = name;
CreateControlTag();
controlTag.AdditionalInfo = isAdditionalInfo;

if (wrap) {
TextBlock tb = new TextBlock();
tb.Text = text;
tb.TextWrapping = TextWrapping.Wrap;
label.Content = tb;
} else {
if (!isAdditionalInfo) {
if (isColon) {
// Only labels with colon can be right-aligned.
// The colon is only displayed for left align
if (UserSettings.Current.RightAlignLabels) {
hAlign = HorizontalAlignment.Right;
} else {
text += ":";
}
}
}
label.VerticalAlignment = VerticalAlignment.Center;
label.Content = text;
}

label.HorizontalAlignment = hAlign;

if (isFixed) {
label.FontFamily = StyleManager.FontFamilyFixed;
} else {
label.FontFamily = StyleManager.FontFamilyBaseUI;
}

label.ToolTip = tooltip;
}

深入研究#3使用规则引擎增强系统稳定性

Lawson应用程序的服务器端旨在部署在多个平台上。 客户安装在各种硬件和操作系统上运行,以及将数据存储在多个RDBMS中。 这些环境的多样性使维护和监视系统性能成为一项艰巨的任务。 解决系统问题可能需要多层支持,这可能会导致严重的业务延迟和信息丢失。

为了增强系统的稳定性,Lawson创建了基金会稳定器。 基金会稳定器是基于规则的监视系统,该系统基于支持和开发人员定义的常见约束和模式。 它在运行期间收集系统性能和配置信息。 此信息可以包括来自底层操作系统的数据(例如CPU使用情况),这些数据是通过与基于Java Native Interface(JNI)的组件进行交互而收集的。 当发现潜在问题时,稳定器将向支持人员发出警告(通过Real Simple Syndication,电子邮件或html),并在适用的情况下采取措施(例如降低有罪线程的优先级)以帮助确保稳定的系统基础。 收集用于手动系统监视的大量系统数据可以用作规则和模式匹配的基础:

  • 绩效柜台
  • 属性文件中的数据
  • Java参数和属性
  • 系统环境信息
  • 职位信息,职位状态,活动级别等
  • Java虚拟机(JVM)状态和资源消耗
  • 平台特定或独立的属性值约束

示例3:基金会稳定器发出警告。 ©2007 Lawson Software,Inc.保留所有权利。 本文档仅供参考。 Lawson Software在本摘要中不做任何明示或暗示的保证。

规则引擎是用Java构建的,并且适用于用Prolog编写的规则。 下面的稳定 ()方法通常由循环的Java线程以可配置的间隔调用。 此Java线程与业务应用程序在同一JVM中运行。

boolean stabilize() throws Exception {
KnowledgeBase kb = engine.getKnowledge();

engine.consult("mvx/res/Stabilizer.rules");
engine.consult("mvx/res/Constraints.rules");

engine.setQuery("cleanup");

try {
addSysInfo(kb);
} catch (IOException ex) {
KQLOG.EX("MvxStabilizer:Failed to collect system information", ex);
return false;
}

KQLOG.DT("Run Stabilizer");
boolean res = engine.setQuery("stabilize");

if (!res) {
KQLOG.E("Could not stabilize - rule engine failed");
return false;
}
KQLOG.DT("End Stabilizer");

Enumeration en = kb.elements();

while (en.hasMoreElements()) {
// Handle results from the rules engine
}

return true;
}
  • 该方法开始于从规则引擎中提取现有知识库。 知识库包含有关系统的事实,包括生成和计算的事实。 事实是简单的表达式,形式为运算符term或运算符term1 term2。 典型示例可能包括以下内容:“ jobName”“ IKDXLZ9A.corp.lawson.net:26100” 4676“ Looping”“ jobCPU”“ IKDXLZ9A.corp.lawson.net:26100” 4676 55
  • 规则(在此示例中为两组)与引擎关联。
  • 通过评估“清理”,从知识库中删除旧信息
  • 知识库将使用当前的系统信息进行刷新。
  • 通过评估“稳定”而触发的规则收集新事实
  • 当评估所有规则时,将重新检查整个知识库是否有新事实,并处理结果。
...
rule(looping_nostat1):-
jobCPU(Addr, Id, CPU),
CPU>40,
jobChange(Addr, Id, Change),
(Change==0;Change>999),
not(loopingMem(Addr, Id, _)),
info(currentTime, Time),
assert(loopingMem(Addr, Id, Time)).

rule(looping_nostat2):-
loopingMem(Addr, Id, LTime),
jobCPU(Addr, Id, CPU),
CPU>40,
jobChange(Addr, Id, Change),
(Change==0;Change>999),
info(currentTime, Time),
Time-LTime>5,
jobType(Addr, Id, JobType),
jobName(Addr, Id, Name),
assert(warning(2, 4, 'Job may be looping', 'Job', JobType, Addr, Name, Id)).

rule(looping_nostat3):-
loopingMem(Addr, Id, LTime),
not(jobName(Addr, Id, _)),
retract(loopingMem(Addr, Id, LTime)).
...

上面的三个规则用于检测使用过多CPU的作业。

第一条规则检测使用过多CPU的任何作业,并开始监视该作业。 根据事实jobCPU选择具有特定地址,ID和CPU使用率的作业 。 如果作业使用的CPU超过40%,并且更改率为零或> 999, 则将创建一个新事实( loopingMem )并设置时间。

第二条规则检测到已被监视超过五分钟的作业,并报告该作业。 事实loopingMem(由第一个规则设置)用于在知识库中搜索这些作业。 与在第一条规则中检查的事实相同。 时间已更新,并且事实jobType和jobName已添加。 这些事实用于在M3业务引擎中提出警告。

第三条规则检测已停止执行的作业,并将其从观察列表中删除。 事实loopingMem用于在知识库中搜索这些工作。 如果在知识库中找不到该作业,则将该条目从观察列表中删除。

结论

Lawson和Intentia于2006年合并,这给开发人员带来了一个重要的问题需要解决-集成和展示以多种不同技术构建的遗留应用程序和业务服务。 为了在公司的两个旗舰ERP产品系列中提供同质的用户体验,将需要客户端解决方案与基于Java和4GL语言的业务层进行交互。

在青蛙设计欧洲有限公司的协助下分析了用户界面技术之后,劳森决定利用微软的.NET 3.0框架。 利用Windows Presentation Foundation(WPF)数据绑定将UI组件与业务逻辑/数据组件绑定在一起,并利用Windows Communication Foundation(WCF)与它们先前存在的Web服务框架进行通信(进行一些小的重组),Lawson开发人员能够快速生成满足他们需求的客户端应用程序。 新的Lawson Smart Client定义了一种可插入的客户端体系结构,该体系结构能够承载新的应用程序和应用程序功能,同时通过Web服务利用旧的业务逻辑。 Lawson的遗留应用程序能够利用这些相同的业务服务,通过在整个企业中使用一个代码库来提高可维护性。

在创建Lawson Smart Client的过程中,他们的开发人员从声明式编程语言的本质中学到了重要的一课。 不利的一面是,声明性语言的学习曲线可能很大,并不总是易于使用,也不一定直观。 但是,一旦开发出能够正确利用这些语言的心态,则可以大幅度提高生产率。 根据Lawson开发人员的经验,这种生产率的提高似乎值得学习该范式的初步工作。

Lawson Smart Client体系结构的最初愿景是创建具有强大而灵活的用户界面组件的新型应用程序。 目的是为客户提供劳森旗舰产品系列中的无缝用户体验,同时提高用户生产力和满意度。 最初的客户React表明,Lawson确实在这项工作中取得了成功。

翻译自: https://www.infoq.com/articles/lawson-casestudy/?topicPageSponsorship=c1246725-b0a7-43a6-9ef9-68102c8d48e1

lawson算法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值