.NET框架设计(高级框架架构模式)—钝化程序、逻辑冻结、冻结程序的延续、瞬间转移

简介:

阅读目录:

  • 1.开篇介绍

  • 2.程序书签(代码书签机制)

    • 2.1ProgramBookmark 实现(使用委托来锚点代码书签)

    • 2.2ProgramBookmarkManager书签管理器(对象化书签集合的处理,IEnumerable<T>书签管理)


  • 3.可恢复语句组件(将语句对象化)

    • 3.1可恢复语句组件管理器(将可恢复语句视为普通的对象成员,IEnumerable<T>可恢复语句组件)

    • 3.2可恢复语句组件运行时(Program CLR(简介))

    • 3.3可恢复语句逻辑配置(规则的配置(简介))

    • 3.4可恢复语句逻辑传输(将逻辑语句对象远程传输(简介))


  • 4.DomainModel规则引擎(规则持久化后管理配置(简介))

1】开篇介绍

这一篇文章我早准备写的,迟迟未写的原因是它过于抽象不太容易表达,也很难掌握;之前对它的理解还处于比较简单的功能性上,但是最近随着对领域驱动设计及架构的研究,设计思想有了一个提升对它的理解也有了一个更清晰的轮廓,所以才敢下手去写,这么好的一篇文章不能搞砸了;

“钝化语句” 简单描述:将基于栈的调用抽象成基于我们自己构建的虚拟运行时调用;

比如我们可以将普通的IF\ELSE调用进行对象化,然后就可以对他们进行面向对象的设计了;能做的事情就太多了,比如将所有的方法放入一个for循环语句组件当中去,它会自动的去循环执行,而不需要我们再去自己写for语句;然后在此基础上进行代码书签抽象对所有的代码片段进行类似逻辑锚点的设定;

更吓人的是可以瞬间将语句组件钝化,其实也就是瞬间冻结然后持久化,在遥远的地方再将它唤醒执行,很可能你的语句在你这台电脑上执行了一半由于你临时有事然后语句被钝化,在另外一台电脑上继续你的工作,是不是很方便;当然它的使用方式多种多样了;

我相信这篇文章绝对让你对 .NET框架设计 感兴趣,框架设计思想其实真的很美,让人陶醉;

2】程序书签(代码书签机制)

美好的一切都要有一个良性的开始,程序的钝化少不了对程序的逻辑保存的功能;有一个连续的调用穿过N个方法,方法一调用方法二,方法二调用方法三,这样的调用层次是根据业务的需求来定的,就好比一个复杂的业务逻辑这样的处理下去合情合理;

那么什么是代码书签呢?其实我们仔细分析一下我们日常所写的代码基本上都是由方法组合而成,不管是实例类还是静态类都是通过方法将彼此联系起来,所有的业务逻辑都是包装在方法的内部处理的,这里的代码书签就是方法的可持久化抽象;

试想一下,我们要想将程序的逻辑流程钝化肯定是少不了对逻辑调用的保存;原本的程序逻辑是线程本地的执行路径,属于.NETCLR直接管理的,依赖于栈的执行,所以我们无法干预其生命周期过程,那么我们只有将它们对象化后才能由我们自己操控;

图1:

170355822.jpg


上图的意思是说在一个流程的开始到结束基本上三个重要环节,Begin\Processs…\End过程,在每个过程中需要不同的处理逻辑,在图的偏上方,我们有三个ProcessName名称的小方块表示程序的调用顺序,ProcessName1调用ProcessName2调用ProcessName3;

在ProcessName2的上面我们加了一个Bookmark的标记,表示我们这里所说的代码书签,通过代码书签我们就可以记录下本次执行到哪里了,就好比我们在看书的时候都有一个买书时赠送的书签卡,我们看到哪里就把这个书签卡插在那里,当下次要看的时候直接找到这个书签卡继续看;

这里的代码书签跟这个是一样的道理,理论就是这些我们下面通过示例代码来亲身体验一下这种设计模式;

2.1】ProgramBookmark 实现(使用委托来锚定代码书签)

委托是天生的方法标签,通过委托我们完全可以将一个实例的方法直接锚定下来;

【有关对委托的高级应用不太清楚的可以参见本人的这两篇文章:

.NET框架设计(一:常被忽视的C#设计技巧).NET框架设计(二:常被忽视的框架设计技巧)

我们来构造代码书签对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/*==============================================================================
  * Author:深度训练
  * Create time: 2013-08-10
  * Blog Address:http://www.cnblogs.com/wangiqngpei557/
  * Author Description:特定领域软件工程实践;
  *==============================================================================*/
namespace  ProgramComponent
{
     using  System;
     /// <summary>
     /// Program book mark.
     /// </summary>
     [Serializable]
     public  class  ProgramBookmark
     {
         /// <summary>
         /// Mark program book mark.
         /// </summary>
         /// <param name="name">Mark name.</param>
         /// <param name="continueAt">Program continue.</param>
         public  ProgramBookmark( string  name, ProgramBookmarkLocation continueAt)
         {
             this .markname = name;
             this .continueAt = continueAt;
         }
         private  string  markname;
         /// <summary>
         /// Book mark name.
         /// </summary>
         public  string  BookmarkName {  get  return  markname; } }
         private  ProgramBookmarkLocation continueAt;
         /// <summary>
         /// Continue location.
         /// </summary>
         public  ProgramBookmarkLocation ContinueAt {  get  return  continueAt; } }
         /// <summary>
         /// Program load data.
         /// </summary>
         public  object  Payload {  get set ; }
     }
     /// <summary>
     /// Program book mark location.
     /// </summary>
     /// <param name="resumed">Resumed bookmark.</param>
     public  delegate  void  ProgramBookmarkLocation(ProgramBookmark resumed);
}


这段代码是对代码书签的抽象,构造函数传入一个代码书签的名称、书签所表示的物理代码锚点,Payload是表示每次执行物理代码时的输入参数;

上面代码看似简单其实很不简单,它的背后隐藏着一个很大的设计思想:

将一块很大的逻辑代码拆成很多零碎的方法片段,很多人可能会觉得设计本身不就这样要求的嘛,那你可能真的没有深入理解代码碎片会后需要对所有的方法参数进行对象化,不管什么方法都会是同样的参数,只有这样才能让书签连续起作用;

下面我们来看一下代码书签有多巧妙,我们来构造一个简单的示例代码,当然你完全可以设计的很复杂很强大,这里毕竟是传递这种设计思想为主;


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/*==============================================================================
  * Author:深度训练
  * Create time: 2013-08-10
  * Blog Address:http://www.cnblogs.com/wangiqngpei557/
  * Author Description:特定领域软件工程实践;
  *==============================================================================*/
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.Threading.Tasks;
namespace  ConsoleApplication1
{
     [Serializable]
     public  class  OrderCheckFlows
     {
         private  IList<ProgramComponent.ProgramBookmark> flowsManager =  new  List<ProgramComponent.ProgramBookmark>();
         public  OrderCheckFlows()
         {
             ProgramComponent.ProgramBookmark bookmarkCheckOrderPrices =
                 new  ProgramComponent.ProgramBookmark( "checkPrices" new  ProgramComponent.ProgramBookmarkLocation(CheckOrderPrices));
             flowsManager.Add(bookmarkCheckOrderPrices);
         }
         public  void  StartCheck()
         {
             do
             {
                 flowsManager[0].ContinueAt(flowsManager[0]);
             }
             while  (flowsManager.Count > 0);
         }
         #region business flows
         public  void  CheckOrderPrices(ProgramComponent.ProgramBookmark nextCheck)
         {
             Console.WriteLine( "checkPrices..." );
             ProgramComponent.ProgramBookmark bookmarkCheckOrderPrices =
                 new  ProgramComponent.ProgramBookmark( "checkPrices" new  ProgramComponent.ProgramBookmarkLocation(CheckOrderItems));
             bookmarkCheckOrderPrices.Payload =  true ; //method parameters.
             flowsManager.Add(bookmarkCheckOrderPrices);
             flowsManager.RemoveAt(0);
         }
         public  void  CheckOrderItems(ProgramComponent.ProgramBookmark nextCheck)
         {
             if  (( bool )nextCheck.Payload)
             {
                 Console.WriteLine( "checkItems..." );
             }
             else
             {
                 Console.WriteLine( "end check items." );
             }
             flowsManager.RemoveAt(0);
         }
         #endregion
     }
}


这个类是一个简单的模拟检查订单的一系列的业务流程;

图2:

170550679.jpg

上图能看见流程顺利执行完毕了,那么我们来解释一下重要的代码片段;

图3:

170612329.jpg

在第一个流程里面我们构造一个通往下一个流程的 ProgramComponent.ProgramBookmark 对象,如果这里出现关于流程无法继续下去的条件就可以不创建往下执行的代码书签;在第二流程里面我们获取第一个流程设置的参数,这里是一个Bool值,可以用来判断上一个执行是否成功等信息;

2.2】ProgramBookmarkManager书签管理器(书签集合的处理,IEnumerable<T>书签管理)

上一节我们完成了对代码书签的抽象实现,但是代码还有很多值得抽象设计的地方,上面的代码中最不太理解的地方就是对书签集合的操作上,很不OO;

那么这一节我们将把它改进,形成OO方式的调用,先看一下哪里不太理解;

图4:

170649975.jpg

第一个地方就是在声明ProgramCompoent.ProgramBookmark集合上,这样写问题太大了,无法进行扩展改进;然后就是在构造函数中,我们使用了很长一段代码来构造一个ProgramCompoent.ProgramBookmark对象,完全可以减少很多;还有就是在StartCheck方法的内部中进行循环调用书签的代码,也很有问题,完全可以封装在内部实现,外部直接一个CurrentProgram属性执行就行了;

那么对这些问题我们其实少一个ProgramCompoent.ProgramBookmark的管理器对象ProgramCompoent.ProgramBookmarkManager对象,它负责管理所有跟ProgramCompoent.ProgramBookmark对象相关的工作;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/*==============================================================================
  * Author:深度训练
  * Create time: 2013-08-10
  * Blog Address:http://www.cnblogs.com/wangiqngpei557/
  * Author Description:特定领域软件工程实践;
  *==============================================================================*/
namespace  ProgramComponent
{
     using  System.Collections.Generic;
     /// <summary>
     /// Program book mark Manager.<see cref="System.Collections.Dictionary{BookmarkName,ProgramBookmark}"/>
     /// </summary>
     public  class  ProgramBookmarkManager : Dictionary< string , ProgramBookmark>
     {
         /// <summary>
         /// Add programbookmark and instant next programbookmark.
         /// </summary>
         /// <param name="bookmark"><see cref="ProgramComponent.ProgramBookmark"/></param>
         public  void  Add(ProgramBookmark bookmark)
         {
             base .Add(bookmark.BookmarkName, bookmark);
         }
         /// <summary>
         /// Remove programbookmark.
         /// </summary>
         /// <param name="bookmark"><see cref="ProgramComponent.ProgramBookmark"/></param>
         public  void  Remove(ProgramBookmark bookmark)
         {
             base .Remove(bookmark.BookmarkName);
         }
         /// <summary>
         /// Resume  bookmark by bookmarkname.
         /// </summary>
         /// <param name="bookmarkName">bookmark name.</param>
         /// <param name="payload">Continue load.</param>
         public  void  Resume( string  bookmarkName,  object  payload)
         {
             ProgramBookmark bookmark;
             this .TryGetValue(bookmarkName,  out  bookmark);
             if  (bookmark !=  null )
             {
                 bookmark.Payload = payload;
                 bookmark.ContinueAt(bookmark);
             }
         }
     }
}

书签管理器基本功能还算简单,主要的方法Resume是用来恢复指定的书签的;再来看一下订单检查流程调用;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/*==============================================================================
  * Author:深度训练
  * Create time: 2013-08-10
  * Blog Address:http://www.cnblogs.com/wangiqngpei557/
  * Author Description:特定领域软件工程实践;
  *==============================================================================*/
namespace  ConsoleApplication1
{
     using  System;
     using  ProgramComponent;
     [Serializable]
     public  class  OrderCheckFlows
     {
         private  ProgramBookmarkManager BookmarkManager =  new  ProgramBookmarkManager();
         public  OrderCheckFlows()
         {
             BookmarkManager.Add( new  ProgramBookmark( "checkPrices" new  ProgramBookmarkLocation(CheckOrderPrices)));
         }
         public  void  StartCheck()
         {
             BookmarkManager.Resume( "checkPrices" null );
         }
         #region business flows
         public  void  CheckOrderPrices(ProgramComponent.ProgramBookmark nextCheck)
         {
             Console.WriteLine( "checkPrices..." );
             BookmarkManager.Remove(nextCheck);
             BookmarkManager.Add( new  ProgramBookmark( "checkItems" new  ProgramBookmarkLocation(CheckOrderItems)));
             BookmarkManager.Resume( "checkItems" true );
         }
         public  void  CheckOrderItems(ProgramComponent.ProgramBookmark nextCheck)
         {
             if  (( bool )nextCheck.Payload)
                 Console.WriteLine( "checkItems..." );
             else
                 Console.WriteLine( "end check items." );
             BookmarkManager.Remove(nextCheck);
         }
         #endregion
     }
}


是不是比之前的代码好多了,我感觉是好多了,当然还有很大的重构空间;

这里其实已经可以和链式编程的机制挂钩了,我们可以通过给书签管理器添加N个扩展方法来使书签管理器具有跟链式的调用;

3】可恢复语句组件(将可恢复语句对象化)

要想把所有的调用都拆开来使用松散的方式组合,通过使用书签机制基本上能将所有的方法进行松散组合;那么我们还需要将逻辑语法进行对象化才能做到无死角的松散;

什么叫语句组件,就是将一些原本无法独立的一些逻辑判断、循环之类的语句对象化,形成更具有对象的组件;

试想一下,如果我们将所有的这些逻辑语法对象化后我们的代码中还有精密耦合的代码吗?就算有也应该会很少,是不是很神奇;

其实对 企业应用架构 中的 规约模式 有所了解的人应该会比较熟悉这一节的内容,跟规约模式很像,但不是一个东西,侧重点不同;语句组件全面的概念是将所有的调用都对象化,包括一些输出、输入、网络调用等等,这样才是全部的语句组件定义,还记得我们上面的订单检查对象嘛,那个也是语句组件之一;

我们来构造可恢复语句组件对象;

ProgramComponent.LanguageComponent.LanguageComponent类代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*==============================================================================
  * Author:深度训练
  * Create time: 2013-08-10
  * Blog Address:http://www.cnblogs.com/wangiqngpei557/
  * Author Description:特定领域软件工程实践;
  *==============================================================================*/
namespace  ProgramComponent.LanguageComponent
{
     using  System;
     [Serializable]
     public  abstract  class  LanguageComponent
     {
         public  abstract  void  Run(ProgramBookmarkManager mgr);
     }
}

ProgramComponent.LanguageComponent.LanguageComponentBlock类代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*==============================================================================
  * Author:深度训练
  * Create time: 2013-08-10
  * Blog Address:http://www.cnblogs.com/wangiqngpei557/
  * Author Description:特定领域软件工程实践;
  *==============================================================================*/
namespace  ProgramComponent.LanguageComponent
{
     using  System.Collections.Generic;
     public  class  LanguageComponentBlock : LanguageComponent
     {
         List<LanguageComponent> statements =  new  List<LanguageComponent>();
         public  List<LanguageComponent> Statements
         {
             get  return  statements; }
         }
         public  void  AddLangugateComponent(LanguageComponent lc)
         {
             statements.Add(lc);
         }
         public  override  void  Run(ProgramBookmarkManager mgr)
         {
                                                                     
         }
     }
}

ProgramComponent.LanguageComponent.IfElseLanguageComponent类代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*==============================================================================
  * Author:深度训练
  * Create time: 2013-08-10
  * Blog Address:http://www.cnblogs.com/wangiqngpei557/
  * Author Description:特定领域软件工程实践;
  *==============================================================================*/
namespace  ProgramComponent.LanguageComponent
{
     using  System;
     using  System.Linq;
     using  System.Linq.Expressions;
     public  class  IfElseLanguageComponent : LanguageComponentBlock
     {
         public  Func< bool > Exp {  get set ; }
         public  override  void  Run(ProgramBookmarkManager mgr)
         {
             if  (Exp())
                 base .Statements[0].Run(mgr);
             else
                 base .Statements[1].Run(mgr);
         }
     }
}

检查流程代码,OrderCheckFlows\OrderSubmitFlows类代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/*==============================================================================
  * Author:深度训练
  * Create time: 2013-08-10
  * Blog Address:http://www.cnblogs.com/wangiqngpei557/
  * Author Description:特定领域软件工程实践;
  *==============================================================================*/
namespace  ConsoleApplication1
{
     using  System;
     using  ProgramComponent;
     using  ProgramComponent.LanguageComponent;
     [Serializable]
     public  class  OrderCheckFlows : LanguageComponent
     {
         private  ProgramBookmarkManager BookmarkManager =  new  ProgramBookmarkManager();
         public  OrderCheckFlows(ProgramBookmarkManager bookmarkManager)
         {
             this .BookmarkManager = bookmarkManager;
             BookmarkManager.Add( new  ProgramBookmark( "checkPrices" new  ProgramBookmarkLocation(CheckOrderPrices)));
         }
         public  override  void  Run(ProgramBookmarkManager mgr)
         {
             this .BookmarkManager = mgr;
             StartCheck();
         }
         public  void  StartCheck()
         {
             BookmarkManager.Resume( "checkPrices" null );
         }
         #region business flows
         public  void  CheckOrderPrices(ProgramComponent.ProgramBookmark nextCheck)
         {
             Console.WriteLine( "checkPrices..." );
             BookmarkManager.Remove(nextCheck);
             BookmarkManager.Add( new  ProgramBookmark( "checkItems" new  ProgramBookmarkLocation(CheckOrderItems)));
             BookmarkManager.Resume( "checkItems" true );
         }
         public  void  CheckOrderItems(ProgramComponent.ProgramBookmark nextCheck)
         {
             if  (( bool )nextCheck.Payload)
                 Console.WriteLine( "checkItems..." );
             else
                 Console.WriteLine( "end check items." );
             BookmarkManager.Remove(nextCheck);
         }
         #endregion
     }
     [Serializable]
     public  class  OrderSubmitFlows : LanguageComponent
     {
         private  ProgramBookmarkManager BookmarkManager =  new  ProgramBookmarkManager();
         public  OrderSubmitFlows(ProgramBookmarkManager bookmarkManager)
         {
             this .BookmarkManager = bookmarkManager;
             BookmarkManager.Add( new  ProgramBookmark( "CheckSubmitPrices" new  ProgramBookmarkLocation(CheckSubmitPrices)));
         }
         public  override  void  Run(ProgramBookmarkManager mgr)
         {
             this .BookmarkManager = mgr;
             StartCheck();
         }
         public  void  StartCheck()
         {
             BookmarkManager.Resume( "CheckSubmitPrices" null );
         }
         #region business flows
         public  void  CheckSubmitPrices(ProgramComponent.ProgramBookmark nextCheck)
         {
             Console.WriteLine( "CheckSubmitPrices..." );
             BookmarkManager.Remove(nextCheck);
             BookmarkManager.Add( new  ProgramBookmark( "CheckSubmitItems" new  ProgramBookmarkLocation(CheckSubmitItems)));
             BookmarkManager.Resume( "CheckSubmitItems" true );
         }
         public  void  CheckSubmitItems(ProgramComponent.ProgramBookmark nextCheck)
         {
             if  (( bool )nextCheck.Payload)
                 Console.WriteLine( "CheckSubmitItems..." );
             else
                 Console.WriteLine( "end check CheckSubmitItems." );
             BookmarkManager.Remove(nextCheck);
         }
         #endregion
     }
}

调用代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.Threading.Tasks;
namespace  ConsoleApplication1
{
     using  ProgramComponent;
     using  ProgramComponent.LanguageComponent;
     class  Program
     {
         static  void  Main( string [] args)
         {
             ProgramBookmarkManager bookmarkManager =  new  ProgramBookmarkManager();
             OrderCheckFlows orderCheckFlow =  new  OrderCheckFlows(bookmarkManager);
             OrderSubmitFlows submitCheckFlow =  new  OrderSubmitFlows(bookmarkManager);
             IfElseLanguageComponent languageComponent =  new  IfElseLanguageComponent();
             languageComponent.Exp = () => {  return  true ; };
             languageComponent.AddLangugateComponent(orderCheckFlow);
             languageComponent.AddLangugateComponent(submitCheckFlow);
             languageComponent.Run(bookmarkManager);
             Console.ReadLine();
         }
     }
}

一切都已经被对象化,我们来看一下逻辑;

图5:

170912659.jpg

这里的返回值决定了后面要执行的语句组件的路径,如果是true,则应该检查OrderCheckFlows流程;

图6:

170940171.jpg

如果是false,则应该检查OrderSubmitFlows流程;

图7:

170959155.jpg

可恢复语句对象模型基本构造完成,当然复杂的问题还需要仔细的去分析设计,这里只是一个简单的示例;

3.1】可恢复语句组件管理器(将可恢复语句视为普通的对象成员,IEnumerable<T>语句组件)

跟代码书签管理器一个道理,这里我们也可以实现一个LanguageComponentManager来对LanguageComponent管理,当然也要看需要不需要;可恢复语句管理器其实有很多文章可以做,因为它是所有语句组件的中心,这对于后面的持久化有很大的用处;

//由于内容比较多且相当抽象,下一篇文章介绍;

3.2】可恢复语句组件运行时(Program CLR)

所有的语句代码都已经被对象化,但是在运行时需要一个中心来管理这些被对象化的语句组件,因为我们要脱离对栈的依赖;一组语句组件是单个示例流程的一部分,但是我们可能会存在很多一起并行运行的流程,所以这是必须要提供的运行时;

//由于内容比较多且相当抽象,下一篇文章介绍;

3.3】可恢复语句逻辑配置(规则的配置)

领域驱动设计在使用规约模式的时候会存在动态配置的需求,可以参见这里的语句组件模型,让规约最大化的提供配置;

//由于内容比较多且相当抽象,下一篇文章介绍;

3.4】可恢复语句逻辑传输(将可恢复语句对象远程传输)

//由于内容比较多且相当抽象,下一篇文章介绍;

4】DomainModel规则引擎(规则持久化后管理配置)

//由于内容比较多且相当抽象,下一篇文章介绍;



示例Demo地址:http://files.cnblogs.com/wangiqngpei557/ConsoleApplication3.zip


 本文转自 王清培 51CTO博客,原文链接:http://blog.51cto.com/wangqingpei557/1270440,如需转载请自行联系原作者




相关文章
|
16小时前
|
人工智能 自然语言处理 算法
分享几个.NET开源的AI和LLM相关项目框架
分享几个.NET开源的AI和LLM相关项目框架
|
16小时前
|
存储 开发框架 前端开发
前端框架EXT.NET Dotnet 3.5开发的实验室信息管理系统(LIMS)成品源码 B/S架构
发展历史:实验室信息管理系统(LIMS),就是指通过计算机网络技术对实验的各种信息进行管理的计算机软、硬件系统。也就是将计算机网络技术与现代的管理思想有机结合,利用数据处理技术、海量数据存储技术、宽带传输网络技术、自动化仪器分析技术,来对实验室的信息管理和质量控制等进行全方位管理的计算机软、硬件系统,以满足实验室管理上的各种目标(计划、控制、执行)。
20 1
|
16小时前
|
敏捷开发 监控 前端开发
深入理解自动化测试框架Selenium的架构与实践
【4月更文挑战第16天】 在现代软件开发过程中,自动化测试已成为确保产品质量和加快迭代速度的关键手段。Selenium作为一种广泛使用的自动化测试工具,其开源、跨平台的特性使得它成为业界的首选之一。本文旨在剖析Selenium的核心架构,并结合实际案例探讨其在复杂Web应用测试中的高效实践方法。通过详细解读Selenium组件间的交互机制以及如何优化测试脚本,我们希望为读者提供深入理解Selenium并有效运用于日常测试工作的参考。
|
16小时前
|
数据可视化 网络协议 C#
C#/.NET/.NET Core优秀项目和框架2024年3月简报
公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等(打不开或者打开GitHub很慢的同学可以优先查看公众号推文,文末一定会附带项目和框架源码地址)。注意:排名不分先后,都是十分优秀的开源项目和框架,每周定期更新分享(欢迎关注公众号:追逐时光者,第一时间获取每周精选分享资讯🔔)。
|
17小时前
|
设计模式 负载均衡 网络协议
【分布式技术专题】「分布式技术架构」实践见真知,手把手教你如何实现一个属于自己的RPC框架(架构技术引导篇)
【分布式技术专题】「分布式技术架构」实践见真知,手把手教你如何实现一个属于自己的RPC框架(架构技术引导篇)
54 0
|
17小时前
|
分布式计算 算法 调度
课3-详解隐私计算框架的架构和技术要点
隐语架构涵盖产品、算法、计算、资源和硬件五层,旨在实现互联互通和跨域管控。产品层包括SecretPad等,简化用户和集成商体验。算法层涉及PSI/PIR、SCQL和联邦学习,提供隐私保护的数据分析和学习。计算层如RayFed、SPU、HEU等,支持分布式计算和密态处理。资源层的KUSCIA用于跨机构任务编排,硬件层涉及FPGA等加速器。互联互通支持黑盒和白盒模式,确保不同平台协作。跨域管控则强调数据流转控制,保护数据权益。
|
17小时前
|
开发框架 网络协议 .NET
深入.net框架
深入.net框架
12 0
|
17小时前
|
算法
隐私计算实训营 第1期-详解隐私计算框架的架构和技术要点
本文简要介绍了隐语技术架构的五层结构:产品层、算法层、计算层、资源层和硬件层。每层分别涉及模块功能、定位和人群画像,旨在使不同角色的用户能轻松理解和使用,降低隐私计算的入门难度。此外,隐语产品设计具有开放性和前瞻性,易于集成。
|
17小时前
|
算法 数据挖掘 调度
隐语实训营-第3讲:详解隐私计算框架的架构和技术要点
主要介绍隐语的隐私计算架构,并对每个模块进行拆解、分析,以期望不同使用者找到适合自己的模块,快速入手。
53 4
|
17小时前
|
数据安全/隐私保护 Windows
.net三层架构开发步骤
.net三层架构开发步骤
14 0