CRM/ERP 企业管理软件中常见的七种程序设计模式

管理软件中的常见代码设计模式,来自于业务上的需要,有不恰当的地方欢迎批评指正。

1  RE-TRY 重试模式

场景:在连接数据库服务器时,如果SQL Server数据库没有启动或正在启动,我们需要有一个连接重试的策略。发送邮件通知时,我们也需要在发送失败后,多次的尝试发送以保证邮件能到达目的用户。

代码参考:

int maxRetry = 30;
int retryInterval = 10000;
for (int i = 1; i <= maxRetry; i++)
{
     try
     {
         //connect to the database server
      }
     catch (Exceptions exception)
     {
         if (i < maxRetry)
              Thread.Sleep(retryInterval);
         else
             return; //返回或停止重试操作
     }
}

这种模式的主要是有一个重试行为,直到执行完成或是超过了约定的时间或次数则放弃。

2 Before-Perform-After  检查-执行-传送模式

场景:在做一项业务操作前,子类为了重写(override)基类的行为必须先做条件或环境检查,然后执行相应的业务操作,之后还可以将此次操作的结果继续传送到其它业务单元中。

以打印报表为例子,业务窗体需要先检查当前登录用户是否具备打印权限,如无权限则取消本次操作。代码例子:

protected internal virtual bool DoPerformPrint()
{

CancelableRecordPrintEventArgs e = new CancelableRecordPrintEventArgs(this.CurrentEntity, selectionForumlas, formulaFields, parameterFields);
this.OnBeforePrint(e);
if (this._beforePrint != null)
   this._beforePrint(this, e);
if (e.Cancel)
   return false;


this.Print(ref selectionForumlas, ref formulaFields, ref parameterFields);

EventArgs args = new EventArgs();
this.OnAfterPrint(args);
if (this._afterPrint != null)
   this._afterPrint(this, args);
}

通过这段代码应该容易理解我说的这种设计模式,第一段是条件检查,如果我们在子类中传入参数e.Cancel=true,则

此方法返回,不再执行Print方法。这种设计模式在事件机制中用的比较多。基类为了控制好业务单元整体的行为,同时又不失去灵活性,可以参照这种模式。

3 TRY  尝试模式

场景:尝试性的去执行某一个业务单元,并以它的结果来决定下一步的行为。

比如我们加载数据,如果加载失败了,则下一步要阻止数据绑定,再比如传送文件,如果双方连接失败,则要阻止文件传送。

代码例子:

private void LoadData()
{
  try
  {

     FindAndLoadData ()
     this._isDataLoaded = true;
  }
  catch (Exception exception)
  {
     this._isDataLoaded =false;
  }
}

这个模式的关键就在于定义的变量_isDataLoaded。在这个方法中,我们尝试去加载数据,如果有异常,则将此变量设为false表示加载失败,其它的业务单元检查到此变量的值以决定下一步操作。

这种行为也有危害,它隐藏了真实的异常原因,常常用在一些界面操作中,频繁的抛出各种异常会让用户反感,这时可以参考这种模式,尝试操作失败后,根据状态值阻止错误进一步发生。

4 BackgroundWorker 多线程工作

场景:在一些业务计算或是读取数据等耗费时间的业务操作,比如物需求计算,工作单批次发套料,计划订单发放等业务中,耗费的时间相当多,这种模式可改善效率。

应用代码例子:

List<LoadMasterScheduleWorker> workers = new List<LoadMasterScheduleWorker>();
for (int i = 0; i < MAX_RUNNING_THREAD; i++)
{
   LoadMasterScheduleWorker worker = new LoadMasterScheduleWorker(this, mrp, mpsRows, loadedMpsItems);
   workers.Add(worker);
}
WorkerThreadBase.StartAndWaitAll(workers.ToArray());

MAX_RUNNING_THREAD通常取当前系统的CPU个数(MAX_RUNNING_THREAD),在实际工作的线程中,采用下面的方法执行数据分配并启动相应的业务操作:

while (_mpsRows.Count > 0)
{
    DataRow mpsRow = null;
    if (!_mpsRows.TryTake(out mpsRow))
           break;

    LoadMasterSchedule(_mrp, mpsRow);
}

从Dictionary<DataRow>集合中不停的TryTake数据行(DataRow)来操作,直到取完所有的数据为止。

需要注意前一段方法的最后一句StartAndWaitAll方法,这里要等待当前所有子线程执行完成,避免数据没有操作完就进行后面的业务操作。

WorkerThreadBase的源代码参考这里。

http://stackoverflow.com/questions/597590/c-sharp-threading-patterns-is-this-a-good-idea

http://files.cnblogs.com/files/JamesLi2015/WorkerThreadBase.zip

5 Data Class 数据类

场景:减少代码中不必要的字符书写错误,改善程序可维护性。

旧代码是这样的:

DataTable query = new FastSerializableDataTable("BomRoutingTable");
query.Columns.Add("BomNo", typeof(string));
query.Columns.Add("SeqNo", typeof(decimal));
query.Columns.Add("OpCode", typeof(string));

应用数据类之后,代码是这样的:

DataTable query = new FastSerializableDataTable("BomRoutingTable");
query.Columns.Add(BomFields.BomNo, typeof(string));
query.Columns.Add(BomFields.SeqNo, typeof(decimal));
query.Columns.Add(BomFields.OpCode, typeof(string));


class BomFields
{
   public const string BomNo ="BomNo";
   public const string SeqNo  ="SeqNo";
   public const string OpCode ="OpCode";
}

新代码设计方式增加了一个类型定义,增加了一点复杂性,同时改善可维护性。创建DataTable的列来自于一个类型定义,如果有多个创建表的地方,则可显著改善书写效率。

6 History 历史记录

场景:ERP中标准物料清单需要通过ECN来变更,若是将此模式应用到其它业务,则做采购单修改或销售单修改等其它单据,也需要记录变更前的资料。

例子代码:

BomHistoryEntity bomHistory = new BomHistoryEntity();
InitialBomHistoryHeaderInActivation(bomHistory, ecn, canUpdate);
return bomHistory;

变更记录相当于流水帐,记录每次业务修改前的值。变更记录还可以通过数据审计功能来实现,不过审计功能过于抽象,只能记录到表的字段变化,要实现两行数据记录字段值的精确比较,还需要开发接口程序以适应特定的业务单据。

历史记录模式最大的杀手就是反审核,反过帐,若业务单据可以反复修改,审核之后退回,反审核又可以修改,这样反复的操作,会产生大量的历史数据。

7 Hash Verify 哈希值验证

场景:文件传送时,在文件传送完成后,需要验证文件传送前后的MD5值或SHA1是否一致以保证文件没有丢失字节。

在一些重要的业务场景,比如转帐,充值,系统登录,在业务操作完成后我们还需要验证一下业务发生是否合理。

代码例子:

session = Login(userId, passwordHash, companyCode, languageCode, hostEntry.HostName, domainUserName, currentProcess.SessionId)
string clientHash = Shared.GetMD5HashValue(string.Concat(new object[] {
                    AssemblyVersion.Company, AssemblyVersion.Product, AssemblyVersion.Version, AssemblyVersion.FileVersion, AssemblyVersion.Product, session.UserId, session.UserGroup, session.CompanyCode, session.SessionId, session.LanguageCode, session.HostName, session.DomainUserName}));

string privateKey = "...";

string serverHash = RSACryptionHelper.DecryptString(session.ClientHashValue, privateKey);
if (string.CompareOrdinal(clientHash, serverHash) != 0)
   throw new AppException("Unable to login, unexpected error detected");
 

第一行代码登录成功之后,服务器返回一个session会话对象,此对象包含一个ClientHashValue的MD5值,与此同时我们将客户端的登入信息,再次构造成一个字符串进行MD5处理,以比较两者的值是否一致,若不一致可能是非法登录请求,抛出异常,阻止登入系统。

这个方法也可应用于多版本策略中,系统要阻止3.2版本的客户端登录到2.1版本的服务器端,注意到上面的代码中有Version参数,会抛出异常。这样可保证一台电脑安装多个版本的服务器端而不相互冲突。

时间: 2024-10-21 08:17:46

CRM/ERP 企业管理软件中常见的七种程序设计模式的相关文章

七种程序设计模式

CRM/ERP 企业管理软件中常见的七种程序设计模式 管理软件中的常见代码设计模式,来自于业务上的需要,有不恰当的地方欢迎批评指正. 1  RE-TRY 重试模式 场景:在连接数据库服务器时,如果SQL Server数据库没有启动或正在启动,我们需要有一个连接重试的策略.发送邮件通知时,我们也需要在发送失败后,多次的尝试发送以保证邮件能到达目的用户. 代码参考: int maxRetry = 30; int retryInterval = 10000; for (int i = 1; i <=

Java中常见的5种WEB服务器介绍

这篇文章主要介绍了Java中常见的5种WEB服务器介绍,它们分别是Tomcat.Resin.JBoss.WebSphere.WebLogic,需要的朋友可以参考下 Web服务器是运行及发布Web应用的容器,只有将开发的Web项目放置到该容器中,才能使网络中的所有用户通过浏览器进行访问.开发Java Web应用所采用的服务器主要是与JSP/Servlet兼容的Web服务器,比较常用的有Tomcat.Resin.JBoss.WebSphere 和 WebLogic 等,下面将分别进行介绍. Tomc

数据分析常见的七种思路

数据分析常见的七种思路:1.简单趋势通过访问趋势了解产品使用情况,便于产品迭代.访问用户量.访问来源.访问用户行为三大指标对于趋势分析具有重要意义.2.多维分解根据分析需要,从多维度对指标进行分解.例如浏览器类型.操作系统类型.访问来源.广告来源.地区.网站/手机应用.设备品牌.APP版本等维度.3.转化漏斗按照已知的转化路径,借助漏斗模型分析总体和每一步的转化情况.常见的转化情境有注册转化分析.购买转化分析等.4.用户分群在精细化分析中,常常需要对有某个特定行为的用户群组进行分析和比对:需要将

Android中常见的几种布局的总结

众所周知,一个应用程序的良好与否,很大程度上取决于它的用户界面.这就像是一个人给人的第一感觉也是从脸开始的一样.一个应用程序首先展示给客户的就是它的界面,通途的说,也就是软件的脸面.只有良好的用户交互界面,才能在第一时间抓住客户心理,取得优势.那么今天我就来给大家说一下在Android程序的开发过程中,对于Android应用程序的一些常见的布局以及个人的一些看法,希望对大家有所帮助. 在Android4.0之前一共有5种关于Android的布局,分别是:LinearLayout(线性布局),Re

Java中常见的几种RuntimeException

一般面试中java Exception(runtimeException )是必会被问到的问题常见的异常列出四五种,是基本要求.更多的....需要注意积累了 常见的几种如下: NullPointerException - 空指针引用异常ClassCastException - 类型强制转换异常.IllegalArgumentException - 传递非法参数异常.ArithmeticException - 算术运算异常ArrayStoreException - 向数组中存放与声明类型不兼容对象

比较分别在数据段与附加段中的字符串以及汇编中常见的四种中断指令

1.从键盘输入两个相同长度的字符串,分别放到数据段和附加段,利用串比较指令比较数据段和附加段中两个字符串,如果两串一样,输出Y,否则输出N. 这个程序调试了好久,之间遇到两个问题,其一是附加段的使用,需要对DS压栈对ES调整处理,即 1 PUSH DS 2 MOV AX,ES 3 MOV DS,AX 4 ;...... 5 POP DS 其二是,串比较指令CMPSW进行字比较,而CMPSB进行字节比较,需要区分开.(其实我现在还不明白即便是字符组成的串,进行字比较为什么会出错,有高手知道吗?)

Linux中bond的七种网卡绑定模式详解

概览: 目前网卡绑定mode共有七种(0~6)bond0.bond1.bond2.bond3.bond4.bond5.bond6 常用的有三种: mode=0:平衡负载模式,有自动备援,但需要”Switch”支援及设定. mode=1:自动备援模式,其中一条线若断线,其他线路将会自动备援. mode=6:平衡负载模式,有自动备援,不必”Switch”支援及设定. 说明: 需要说明的是如果想做成mode 0的负载均衡,仅仅设置这里optionsbond0 miimon=100 mode=0是不够的

WCF中常见的几种Host,承载WCF服务的方法

1:写在前面 我们都知道WCF在运行的时候必须自己提供宿主来承载服务.WCF 本身没有附带宿主,而是提供了一个 ServiceHost 的类,该类允许您在自己的应用程序中host WCF 服务.然后调用 ServiceHost 的 Open 方法即可.我们知道WCF是针对SOA的一套技术.对于SOA而言,我们必须确保服务能够正常运行,平稳的运行,所以此时如何host我们的服务,用什么来Host我们的服务是很重要的,所以我们要为我们的应用程序选择一个合适的Host方式是很有必要的. 2:常见的几种

说出JQuery中常见的几种函数以及他们的含义是什么?

jQuery中常见的函数如下:  (1)get()取得所有匹配的DOM元素集合. (2)get(index)取得其中一个匹配的元素.index表示取得第几个匹配的元素. (3)append(content)向每个匹配的元素内部追加内容. (4)after(content)每个匹配的元素之后插入内容. (5)html()/html(var)取得或设置匹配元素的html内容. (6)find(expr)搜索所有与指定表达式匹配的元素. (7)bind(type,[data],fn)为每个匹配元素的特