代码改变世界

最近架构随想

2014-07-28 08:19 by 圣殿骑士, 6108 阅读, 62 评论, 收藏, 编辑

今天新加坡放假,闲来无事就发一篇博客:一则总结归纳项目构架经验,审视并逐步提高自己;再者分享最近学习所得,希望各位能讨论并给些建议。六月三十日从原来公司离职,七月一日入职新公司,不知不觉已经快一个月了。最近忙于学习新的行业知识以及项目的重构设计,没有时间发博客,也没有时间回复邮件及博文评论,忘各位见谅!

今天发几张项目重构设计草图,如果大家对项目分层与文件夹结构比较感兴趣,可以参考几年前弦哥.Net项目分层与文件夹结构大全(最佳架子奖,吐槽奖,阴沟翻船奖揭晓),这次的架构方案基本是之前架构经验第一次在保险行业的使用,希望各位能积极探讨并给些意见!

整体方案:

根据个人经验,架构决定项目的成败以及高度,所以在编码之前一定要设计好项目的整体规划和架构。好的架构或者考虑比较全面到位的架构会极大的帮助团队,对项目起到灵魂的作用;糟糕的设计往往会把整个项目组带入泥潭或者恶性循环,对项目直接致命打击!

回归正题:

  • 整个架构分为Online(Web Application)和Offline(WPF Application)两部分。
  • Online(Web Application)需要支持不同的设备及浏览器,所以采用Bootstrap和ASP.NET MVC with Razor作为View,KnockoutJs作为MVVM框架。UI Designer设计好UI,然后由前端工程师绑定相应的UI Model到UI,后端工程师则负责相应的OOAD以及业务处理。
  • Offline(WPF  Application)需要在没有网络的情况下能正常工作,所以采用WPF  XALM作为View,MVVM Light作为MVVM框架。UI和后端的处理以及任务分配和Online(Web Application)基本一致。
  • Services :设置了Switch功能,可以配置是否使用WCF或者Web API或者直接调用Dll。
  • Domain Model:始终是应用程序的核心,必须投入大量精力,按照面向对象的分析和设计 (OOAD) 进行设计同时按照OOP进行开发。
  • Infrastructure:主要包括数据访问组件、通用权限框架、异常和日志处理组件、IOC/AOP功能、缓存机制,邮件,配置等基础或常用功能。
  • 行业知识:由于项目牵涉到具体的行业(保险业),所以在业务流程中创建了Insurance Engine,专门处理保险相关的基础功能。
  • 权限系统:由于整个项目比较庞大,再加上其他系统也需要用到同样的权限判断,所以创建了一个新的权限数据库,用来存储及处理权限相关的所有数据及规则,所有用户则来源于三个数据源(SQL Server, DB2和Active Directory)。
  • Unit Test:每一层都有单独的单元测试,方便项目功能自测,维护,重构,升级以及管理。28-7-2014 12-31-12 AM

组件之间的详细关系如下:

28-7-2014 12-27-11 AM

各层之间的执行顺序如下:

28-7-2014 12-34-29 AM

权限系统:

  • 用户来源于三个数据源(SQL Server, DB2和Active Directory)。
  • 现实世界和系统通过角色进行关联,现实世界的用户及组的变化尽量不要影响到系统。
  • 一个用户可以有多个角色,一个角色也分配给多个用户。
  • 权限分为功能权限和数据权限。
  • 权限系统要提供给几套系统使用,全部的接口通过Service的形式提供出来。

security

由于时间有限,设计可能存在诸多不足之处,如果大家有不同的意见或者建议,不妨在评论中指出,以便互相学习且共同提高!


作者:圣殿骑士
出处:http://www.cnblogs.com/KnightsWarrior/
关于作者:专注于微软平台项目架构、管理和企业解决方案。自认在面向对象及面向服务领域有一定的造诣,熟悉设计模式、TDD、极限编程、领域驱动、架构设计、敏捷开发和项目管理。现主要从事WinForm、ASP.NET、WPF、WCF、WF、Silverlight 、Biztalk、Windows Azure等云计算方面的项目开发、架构、管理和企业培训工作。如有问题或建议,请多多赐教!
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。如有问题,可以邮件:KnightsWarrior(at)msn(dot)com  微博:圣殿骑士微博  联系我,非常感谢。

40
0
(请您对文章做出评价)
? 上一篇:关于新加坡IT薪酬
Add your comment

  1. #51楼[楼主] 圣殿骑士   2014-07-28 21:36
    @dotnet技术网
    引用我也有类似的想法,但真正开发起来,就非常麻烦,梦想很美好,现实很骨干。

    是的,很多时候实施起来比架构设计还难,不过类似项目经历多了就更容易一些了!
  2. #52楼[楼主] 圣殿骑士   2014-07-28 21:38
    @Da ge
    引用必须推荐,最好能有个demo让小伙伴们学习下

    DEMO还处在实施阶段!
  3. #53楼[楼主] 圣殿骑士   2014-07-28 21:40
    @春色园
    引用架构应该适应业务!!

    是的,这个架构就是适应业务和需求而画的,具体模块之间的划分还有几个图——用例图,类图,部署图等,由于与项目有关,没有公布出来。
  4. #54楼 jlzhou   2014-07-29 07:21
    期待代码示例 感谢
  5. #55楼 stoneniqiu   2014-07-29 08:14
    这样的项目 好想加入~~
  6. #56楼   2014-07-29 13:43
    请问一下你们单元测试用的什么框架
  7. #57楼 owlbcc   2014-07-29 14:32
    wpf的和mvc的两个viewmodel能不能合到一起?两个系统之间是不是差异还挺大的?
  8. #58楼 muki   2014-07-29 17:08
    架构太过于复杂了.
  9. #59楼 flyfish1986   2014-07-30 13:34
    来了!
  10. #60楼 HelloNet   2014-08-04 13:52
    看上去很牛逼的样子
  11. #61楼 Pansen   2014-08-05 08:58
    mark
  12. #62楼 高僧   2014-08-11 15:01
    楼主,上面这几图是用什么工具画的?

updatePanle总结

总是在觉得不是问题的问题上牵绊住,基础才是王道啊。。。。。

一、UpdatePanel内部的控件引起的回发,来更新当前UpdatePanel内部的控件内容: 在ASPX中代码如下:

<form id="form1" runat="server"><asp:Label ID="lbl_PageLoad" runat="server" Text="Label"></asp:Label> <asp:ScriptManager ID="sm1" runat="server"></asp:ScriptManager><div><asp:UpdatePanel ID="up1" runat="server" ChildrenAsTriggers="true"><ContentTemplate><asp:Label ID="lbl_Update" runat="server"></asp:Label><br /><asp:Button ID="btn1" runat="server" OnClick="btn_Click" Text="Test" /></ContentTemplate></asp:UpdatePanel></div></form>

在cs中代码如下:

protected void Page_Load(object sender, EventArgs e) { lbl_PageLoad.Text = DateTime.Now.ToString(); }
protected void btn_Click(object sender, EventArgs e) { lbl_Update.Text = DateTime.Now.ToString(); }

运行显示效果如下: [转载]UpdatePanel用法详解
点击Test按钮,显示效果如下: 再次点击Test按钮,显示效果为: [转载]UpdatePanel用法详解
可以看到,每次点击Test按钮时,第一行的时间都没有改变。第二行的时间就变化为当前时间。因为第一行的时间是在Page_Load中设置的,而每次点击Test按钮时,就会局部刷新第二行的时间。即刷新UpdatePanel中的控件。页面其余部分的控件并不刷新。
注意:此时的ScriptManager的EnablePartialRendering属性应设为true。UpdatePanel的UpdateMode属性应设为Always。ChildAsTrigger属性应设为true。
二、UpdatePanel控件外部的控件来异步更新UpdatePanel内部的内容: 虽然上面的方式能够达到我们更新局部控件的要求,但大多数时候,我们是将需要局部更新的控件放在UpdatePanel中,而将引发更新的控件放在UpdatePanel的外面。
在页面中加入一个新的UpdatePanel,如下所示:

<asp:UpdatePanel ID="upExternal" runat="server" UpdateMode="Always"> <ContentTemplate> <asp:Label ID="lbl_TestExternal" runat="server" Text="Test External"></asp:Label> </ContentTemplate> </asp:UpdatePanel>   <asp:Button ID="btnExternal" runat="server" OnClick="btnExternal_Click" Text="Test External" />

在CS的Page_Load中加入下列代码:

protected void Page_Load(object sender, EventArgs e) { lbl_PostBack.Text = DateTime.Now.ToString(); sm1.RegisterAsyncPostBackControl(btnExternal); //实现对btnExternal的注册,那此时btnExternal的回发就变成一个异步回发(页面不会刷新),如果页面上的UpdatePanel的UpdateMode="always",里面的内容的就会被刷新。若为Conditional,则不会刷新。 }

在cs中添加button的click响应函数:

protected void btnExternal_Click(object sender, EventArgs e) { lbl_TestExternal.Text = DateTime.Now.ToString(); }

运行效果如下: [转载]UpdatePanel用法详解
点击Test External按钮,运行效果如下: [转载]UpdatePanel用法详解 再次点击Test External按钮,下面一行的时间不断改变: [转载]UpdatePanel用法详解
即每次点击UpdatePanel外部的Button时,都会局部刷新UpdatePanel里的控件。 注意:此时的ScriptManager的EnablePartialRendering属性应设为true。UpdatePanel的UpdateMode属性应设为Always。
三、针对特定UpdatePanel控件进行异步更新把页面上所有的UpdatePanel控件的UpdateMode设为Conditional,如下所示:

<form id="form1" runat="server"> <asp:Label ID="lbl_PostBack" runat="server" Text="Label"></asp:Label>   <asp:ScriptManager ID="sm1" runat="server" EnablePartialRendering="true"></asp:ScriptManager> <div> <asp:UpdatePanel ID="up1" runat="server" ChildrenAsTriggers="true" UpdateMode="Conditional"> <ContentTemplate> <asp:Label ID="lbl_Update" runat="server"></asp:Label> <br /> <asp:Button ID="btn1" runat="server" OnClick="btn_Click" Text="Test" /> </ContentTemplate> </asp:UpdatePanel> <br /> <asp:UpdatePanel ID="upExternal" runat="server" UpdateMode="Conditional"> <ContentTemplate> <asp:Label ID="lbl_TestExternal" runat="server" Text="Test External"></asp:Label> </ContentTemplate> </asp:UpdatePanel>   <asp:Button ID="btnExternal" runat="server" OnClick="btnExternal_Click" Text="Test External" /> </div> </form>

在后台cs中加入如下代码:

protected void Page_Load(object sender, EventArgs e) { lbl_PostBack.Text = DateTime.Now.ToString(); sm1.RegisterAsyncPostBackControl(btnExternal); }
protected void btn_Click(object sender, EventArgs e) { lbl_Update.Text = DateTime.Now.ToString(); }
protected void btnExternal_Click(object sender, EventArgs e) { lbl_TestExternal.Text = DateTime.Now.ToString(); up1.Update(); }

运行效果如下: [转载]UpdatePanel用法详解
不管如何点击Test External按钮,"Test External"文字都没有变成当前时间。因为我们加入了up1.Update();表示仅仅刷新up1,不刷新lbl_TestExternal所在的upExternal。 如果修改cs代码为:

protected void btnExternal_Click(object sender, EventArgs e) { lbl_TestExternal.Text = DateTime.Now.ToString(); upExternal.Update(); }

显示效果如下:
每次点击Test External按钮,最后那行的时间都会随着改变。
注意:这里的UpdatePanel的属性要设为Conditional,如果还是Always的话,会出现所有的UpdatePanel都刷新的效果。
四、用Trigger触发器来局部更新UpdatePanel这里的效果和上面二、三局部更新UpdatePanel的效果一致,只是变换了一种实现方式而已。 上面的方法是这样的: 在cs的Page_Load中用ScriptManager的RegisterAsyncPostBackControl来注册一个控件(如btnExternal) 现在我们在ASPX中用Triggers来注册这个控件。部分代码如下:

<asp:UpdatePanel ID="upExternal" runat="server" UpdateMode="Conditional"> <ContentTemplate> <asp:Label ID="lbl_TestExternal" runat="server" Text="Test External"></asp:Label> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="btnExternal" EventName="Click" /> </Triggers> </asp:UpdatePanel> <asp:Button ID="btnExternal" runat="server" OnClick="btnExternal_Click" Text="Test External" />

这个效果和上面二、三效果一样,这里就不重复列出效果图片了。 注意:把所有的UpdatePanel控件的UpdateMode设为"Conditional",这样才能够针对建有相关触发器的UpdatePanel更新。一个UpdatePanel上可以建有多个触发器,实现在不同的情况下对该UpdatePanel控件内容的更新。
五、用不同的控件来触发不同的UpdatePanel的局部更新这其实是对四的一个延伸。用一个按钮来控制UpdatePanel1的更新,用另一个按钮来控制UpdatePanel2的更新。废话少说,完整代码如下:

<form id="form1" runat="server"> <asp:Label ID="lbl_PostBack" runat="server" Text="Label"></asp:Label>   <asp:ScriptManager ID="sm1" runat="server" EnablePartialRendering="true"></asp:ScriptManager> <div> <asp:UpdatePanel ID="up1" runat="server" ChildrenAsTriggers="true" UpdateMode="Conditional"> <ContentTemplate> <asp:Label ID="lbl_Update" runat="server"></asp:Label> </ContentTemplate> <Triggers>
<asp:AsyncPostBackTrigger ControlID="btn_up1" EventName="Click" />
</Triggers> </asp:UpdatePanel>   <asp:Button ID="btn_up1" runat="server" OnClick="btnUp1_Click" Text="Test External 1" /> <br /> <asp:UpdatePanel ID="upExternal" runat="server" UpdateMode="Conditional"> <ContentTemplate> <asp:Label ID="lbl_TestExternal" runat="server" Text="Test External"></asp:Label> </ContentTemplate> <Triggers>
<asp:AsyncPostBackTrigger ControlID="btnExternal" EventName="Click" />
</Triggers> </asp:UpdatePanel>   <asp:Button ID="btnExternal" runat="server" OnClick="btnExternal_Click" Text="Test External 2" /> </div> </form>

后台完整代码如下:

protected void Page_Load(object sender, EventArgs e) { lbl_PostBack.Text = DateTime.Now.ToString(); //sm1.RegisterAsyncPostBackControl(btnExternal); }
protected void btnUp1_Click(object sender, EventArgs e) { lbl_Update.Text = DateTime.Now.ToString(); }
protected void btnExternal_Click(object sender, EventArgs e) { lbl_TestExternal.Text = DateTime.Now.ToString(); //upExternal.Update(); }

运行效果如下: [转载]UpdatePanel用法详解
点击Test External 1按钮,显示效果如下: [转载]UpdatePanel用法详解
点击Test External 2按钮,显示效果如下: [转载]UpdatePanel用法详解 每次点击这两个按钮,对应的时间都会发生改变:
[转载]UpdatePanel用法详解
即实现了不同控件控制不同的UpdatePanel的局部更新。可以看到最顶部那个时间值就一直不变,也就是局部更新不影响其他控件的值。
几个重要的属性: ScriptManager控件的EnablePartialRendering属性:

true-实现页面的异步局部更新; false-实现全页面的刷新。

UpdatePanel控件的RenderMode属性:

InLine-UpdatePanel控件被解析成HTML的<span>标记; Block-UpdatePanel控件被解析成HTML控件的<DIV>。

UpdatePanel 控件的UpdateMode属性:

Always-UpdatePanel页面上任何一处发生的回发操作都会产生页局部更新; Conditional-只在特定的情况下才产页面的回发,如执行UpdatePanel控件的update()方法或在指定的触发器的操作下。

UpdatePanel控件 的ChildAsTrigger属性: 指示UpdatePanel内部控件引起的回发是否产生当前UpdatePanel控件的局部更新。 如果UpdateMode设为Always的话,那ChildAsTrigger局性必须设为True,否则运行出错。

最后如果控件在updatepanel 外,想更新updatepanel的同时顺便更新控件外的内容,可以再后端注册脚本,如果直接写在click事件里面不起作用。。。。切记,切记

原因很简单,本来UPDATEPANEL就是局部更新,你把控件放在外面当然不会更新了,此时

 ScriptManager.RegisterStartupScript(UpdatePanel2, this.GetType(), "alert", function, true);
就起作用了.
posted @ 2012-08-24 09:09  hudasm  阅读(193)  评论(0编辑  收藏  举报