﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园-Richie</title><link>http://www.cnblogs.com/RicCC/</link><description>Sometimes at night when I look up at the stars, and see the whole sky just laid out there, don't you think I ain't remembering it all. I still got dreams like anybody else, and ever so often, I am thinking about how things might of been. And then, all of a sudden, I'm forty, fifty, sixty years old, you know?</description><language>zh-cn</language><lastBuildDate>Thu, 28 Aug 2008 12:09:31 GMT</lastBuildDate><pubDate>Thu, 28 Aug 2008 12:09:31 GMT</pubDate><ttl>60</ttl><item><title>windows 2003 远程桌面最大连接数</title><link>http://www.cnblogs.com/RicCC/archive/2008/08/17/1269660.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Sun, 17 Aug 2008 02:33:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/08/17/1269660.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1269660.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/08/17/1269660.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1269660.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1269660.html</trackback:ping><description><![CDATA[<p>1. Add or Remove Programs-&gt;Add Remove Windows Components-&gt;Terminal Server</p>
<p>2. Start-&gt;Run-&gt;tscc.msc</p>
<p>&nbsp;&nbsp;&nbsp; Connections-&gt;RDP-tcp-&gt;Network Adapter: 这里可以设置Maximum Connections<br />
</p>
<p>&nbsp; &nbsp; Server Settings: 远程登陆的用户经常直接关掉，导致session挂起，可以每个远程用户分配一个帐号Server Settings下面这样配置: <br />
</p>
<p>&nbsp; &nbsp; Delete temporary folders on exit: Yes</p>
<p>&nbsp;&nbsp;&nbsp; Use temporary folders per session: Yes<br />
</p>
<p>&nbsp; &nbsp; Licensing: Remote Desktop for Administration</p>
<p>&nbsp;&nbsp;&nbsp; Active Desktop: No<br />
</p>
<p>&nbsp; &nbsp; Permission Compotibility: Full Security</p>
<p>&nbsp;&nbsp;&nbsp; Restrict each user to one session: Yes<br />
</p>
<p>&nbsp;</p>
<p>&nbsp; &nbsp; 如果启用了相关的组策略，tscc.msc中的设置的配置不能修改，只能在组策略中配置<br />
</p>
<p>&nbsp; &nbsp; Start-&gt;Run-&gt;gpedit.msc-&gt;Computer Configuration-&gt;Administrative Templates-&gt;Terminal Services</p>
<p>&nbsp;&nbsp;&nbsp; 例如Limit number of connections，在这里配置了之后，tscc.msc中就不能修改了 <br />
</p>
<img src ="http://www.cnblogs.com/RicCC/aggbug/1269660.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41940/" target="_blank">[新闻]惠普139亿美元完成对EDS的收购</a>]]></description></item><item><title>ASP.NET 2.0的站点上部署1.1的虚拟目录</title><link>http://www.cnblogs.com/RicCC/archive/2008/08/07/1263268.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Thu, 07 Aug 2008 14:02:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/08/07/1263268.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1263268.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/08/07/1263268.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1263268.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1263268.html</trackback:ping><description><![CDATA[<p>Application Pool分开是基本前提，另外的麻烦是web.config文件冲突</p>
<p>ASP.NET的web.config具有继承机制，站点使用2.0而虚拟目录使用1.1时仍然这样处理，所以虚拟目录1.1的应用程序启动时会报错误，无法处理站点2.0的web.config文件，例如connectionString节点等<br />
</p>
<p>解决方法：<br />
</p>
<p>修改C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\CONFIG\machine.config文件，例如解决1.1虚拟目录无法处理connectionString节点，则在machine.config的configSections中添加下面节点，让1.1的应用忽略connectionString这个节点:</p>
<p>&lt;section name="connectionStrings" </p>
<p>&nbsp;&nbsp;&nbsp; type="System.Configuration.IgnoreSectionHandler, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" </p>
<p>&nbsp;&nbsp;&nbsp; allowLocation="false" /&gt; <br />
</p>
<p>&nbsp;对于其它属性，则只能删除（例如xmlns属性等），或者采用1.1、2.0都能统一处理的格式（例如pages的pageBaseType属性值等）</p>
<img src ="http://www.cnblogs.com/RicCC/aggbug/1263268.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41939/" target="_blank">[新闻]搜狗五笔输入法发布</a>]]></description></item><item><title>Vivo Cielo Studio Proposal</title><link>http://www.cnblogs.com/RicCC/archive/2008/07/31/1257536.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Thu, 31 Jul 2008 10:36:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/07/31/1257536.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1257536.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/07/31/1257536.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1257536.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1257536.html</trackback:ping><description><![CDATA[HTML、JavaScript、CSS、C#、SQL都是编程语言，可把几个东西结合起来开发一个项目却那么多事情，开发的世界里脏、乱、差<br />
ASP、ASP.NET、MonoRail、Sprint.Net、ASP.NET MVC、NHibernate、iBatis、LINQ to ...、ADO.NET Entity Framework，还有客户端的Ajax、FLEX、Silverlight等RIA技术，技术思想在快速发展，对好的开发人员要求越来越高，可项目的问题不见得越来越少<br />
问题关键在什么地方呢，是对上下文环境Context的处理。Context有两大鸿沟：数据库与程序运行环境之间，程序运行环境与客户端之间，即Database&lt;-&gt;Domain、Domain&lt;-&gt;Web之间<br />
<br />
Ruby on Rails是个比较酷的名字，它最大的优点是在开发语言这个层面将3个上下文紧密结合起来。对比其它一些解决方案看看：<br />
1. ASP.NET<br />
&nbsp;&nbsp;&nbsp; 客户端WebForm、服务器端Code Behind，宏观上看是非常好的解决方案，因为很大程度上为开发者抹平了Web Client与Web Server之间的沟渠<br />
&nbsp;&nbsp;&nbsp; 缺点是一方面微软做事比较粗糙。在Web Form上拖放Connection、DataGrid控件，设置属性然后页面就完成了，这个方法太简单。Code Behind再往后怎么走，多年以来一直没有提供好的解决方案，开发者很难自己摸索出一个优秀的开发模型。Enterprise Library只是几个Utilities而已，离构建一个完善的开发模型解决方案距离太远。现在LINQ to ...出来弥补这一块，但离ASP.NET最初推出已经7、8年时间了<br />
&nbsp;&nbsp;&nbsp; 另一方面我想是开放性和推广方面，ViewState PostBack机制运用于整个页面太笨重；Client ID等不少HTML属性由框架操控，剥夺了开发者一定的控制权；加之Page Life Cycle、安全控制策略等一系列的重型机制，Web Control的开发也复杂。也就是说ASP.NET内部处理太庞杂，开发者能够全面了解、对这个过程能够切入控制的力度非常有限。如果开源，开发者社区自然能够解决这个问题，或者微软采取出书、MSDN开一系列文章或专开一个频道，详细完整的讲解整个机制并接收社区的反馈进行完善，Web Form的发展或者整个.NET开发状况不会是现在这个样子。RIA概念造成开发过程需要对客户端有绝对的控制权，搜索引擎优化、服务器端开发模型的发展等对控制器的接管要求也越来越强列，因此现在出来ASP.NET MVC，IIS7的Filters Pipeline更灵活，看起来更象是形式所迫被动的开发这些框架满足当前的要求<br />
<br />
2. MonoRail<br />
&nbsp;&nbsp;&nbsp; 整合了NHibernate，这是MonoRail衔接Database与Domain的解决方案；ViewEngine有多种选择，开发者对Template有了选择性，也能完全控制View的输出<br />
&nbsp;&nbsp;&nbsp; 另一条既是优点也是缺点。Hibernate完全是Java社区的思想，遵循JCP等规范，对设计要求比较很高，对例外情况不鼓励，例外情况的解决方案也很简单（确实有足够的理由这样做），我想这是MonoRail在.Net社区的普及中一个很大的障碍。ASP.NET MVC这一王牌军上来，真的不知道MonoRail后面的路是否能走好。但这也是NHibernate、MonoRail的优点，因为这套领域建模的思想是无数项目、无数优秀开发者思想的结晶，拥有完整的思想体系和众多的分支，以及其它框架、工具的支持大体都是遵循这个思想体系，在自己的范围内把特定问题更好的解决掉，只是开发者要透彻理解、掌握这个体系很不容易，需要大量实际项目经验的支撑以及投入精力不断思考研究。但相比微软以前的做法，除了Web Cast上拖拖拉拉或者直接写SQL的示例，以及几个Utilities库之外，剩余事情开发者怎么解决就不管了，还是要好多了。RoR的Convention Over Configuration也是对这个问题的一种解决方案，技术、思想等相关知识爆炸性增长，当一个项目使用N个非常优秀的框架仍然无法覆盖主要设计时，开发项目如何掌控？<br />
&nbsp;&nbsp;&nbsp; 与RoR相比，MonoRail在几个Context之间的交互还是逊色一截<br />
<p>&nbsp;</p>
<p>开发模式整体流畅，开发工作便利，但不丧失灵活性&nbsp;
</p>
<p>&nbsp;</p>
<p>对于后端，ORM是必须的，需要具备NHibernate大部分主要特性，但不必象NHibernate那样坚持以良好的模型设计为基础，并且是必要前提。最大化生产力也是非常重要的一个因素，考虑生产力的因素与理想化的设计思想总是存在一定差距。很多项目时间紧迫，没有充足的时间一次性作出完善的设计；想象中的完善设计还不一定是客户真正需要的东西；在迭代过程中第1、2轮重点关注主要部分、核心流程，并且有与最终客户交互确认的因素，以及部分初期无法最终确定是否为合理、优化的设计方案。应该Rails起来，敏捷起来</p>
<p>&nbsp;</p>
<p>对于前端，MVC的确需要分离，但仍得多考虑生产力的问题，分离之后得保证开发流程仍然顺畅。在Web上V和C相隔十万八千里，是最难摆弄的部分。MVC 2模式应当要尝试作出改变了，也许还是MVC更适合<br />
</p>
<p>模板引擎这种做法，Web Server与Client之间的这条沟终究是很难填平的，包括目前各种Web MVC框架和RoR在内都是这样。"世界是平的"，这就是Vivo Cielo Studio框架的目标 <br />
</p>
<p>
其实Rails的做法也并不新鲜，只是将ActiveRecord、模板引擎等集成到语言平台上，在同一个开发环境上下文中方便的完成各个方面的事情，确实是件愉快的工作。RoR对整个开发模式而言是流畅了，它将生产力和设计结构性兼顾起来，但RIA的趋势下客户端的Rich Control，以及如何将HTML组件化，更好的重用HTML组件等，估计RoR还是很难解决的</p>
<p>&nbsp;</p>
所以，我得自己开发一个了<br />
可以借鉴参考的概念和已有框架结构：RoR, Web Form, MDA, MVC, COM组件模型, SharpDevelop Add-In结构(或者FireFox、jQuery的扩展性结构), REST, web-based command line, MFC文档视图架构, jQuery, MonoRail, NHibernate, LINQ to SQL等<br />
<p>Java在这方面尝试的项目很多，各自采用了不同的方法，例如JBlooming、Helma等</p>
<p>&nbsp;</p>
<p>项目内部代码Vivo Cielo Studio，整体粗略的方案已经成型，Alpha版面市时间**年**月 ^_^<br />
</p><img src ="http://www.cnblogs.com/RicCC/aggbug/1257536.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41938/" target="_blank">[新闻]新学年开始 大学生适用的十大互联网应用</a>]]></description></item><item><title>Old Tips: DCOM访问权限，Excel对象操作</title><link>http://www.cnblogs.com/RicCC/archive/2008/07/30/1256042.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Tue, 29 Jul 2008 17:08:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/07/30/1256042.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1256042.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/07/30/1256042.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1256042.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1256042.html</trackback:ping><description><![CDATA[<p><strong>DCOM</strong> <br />
</p>
<p>好记性不如烂笔头，不管以前用的多熟练，过了就忘的一干二净了</p>
<p>1. dcomcnfg</p>
<p>&nbsp;&nbsp;&nbsp; 在DCOM Config里面找到Microsoft Excel Application，Properties-&gt;Security，Launch and Activation Permissions, Access Permissions, Configuration Permissions三个选项都改为Customize，权限里面加上NETWORK SERVICE帐号<br />
</p>
<p>&nbsp; &nbsp; 默认情况下都使用Default，不改为Customize的话可以修改My Computer-&gt;Properties-&gt;COM Security-&gt;Edit Default，不过不太安全的做法<br />
</p>
<p>&nbsp; &nbsp; Identity默认情况下应当是The Launching User，即NETWORK SERVICE帐号，可以改为Administrator等其它有权限的帐号，不过密码要被显示的设在这里，不能和操作系统同步<br />
</p>
<p>2. 文件目录的Security中NETWORK SERVICE需要有权限</p>
<p>&nbsp;</p>
<p>怀念一下当年的COM+ Applications，其实挺好的<br />
</p>
<p>早2天猫一眼ASP.NET 2.0高级编程，说一个aspx页面如何向另一个aspx页面提交，code behind、page把思维都给僵化了</p>
<p>&nbsp;</p>
<p><strong>Excel</strong></p>
<p>程序中操作Excel对象，如果不知道某个操作用什么属性，调用哪些方法，可以使用Excel文件的菜单</p>
<p>1. Record New Macro...</p>
<p>2. 操作</p>
<p>3. Stop Recording<br />
</p>
<p>4. 在Modules-&gt;Module1文件中可以查看到</p>
<p>微软的Excel, Word, VSS等结构非常不错，表现与逻辑完全分离，所以使用VSS的API可以完全开发另外一套VSS程序界面<br />
</p>
<p>
</p><img src ="http://www.cnblogs.com/RicCC/aggbug/1256042.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41937/" target="_blank">[新闻]Google拟在9月发布自有浏览器 或采用火狐内核</a>]]></description></item><item><title>VS2008 Bug</title><link>http://www.cnblogs.com/RicCC/archive/2008/07/05/1236710.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Sat, 05 Jul 2008 13:22:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/07/05/1236710.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1236710.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/07/05/1236710.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1236710.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1236710.html</trackback:ping><description><![CDATA[解决方案或者文件夹上面的右键菜单"Open Folder in Windows Explorer"，很方便的一个功能<br />
但如果在Web程序调试期间使用这个功能，就只能用Ctrl+Alt+Delete把VS2008给结束掉<br />
已经很多次中招了，主要是集中精力调试的时候总是想看一下log文件的输出，把这回事给忘的一干二净<br />
<br />
<img src ="http://www.cnblogs.com/RicCC/aggbug/1236710.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41936/" target="_blank">[新闻]微软正在构思将Wi-Fi带入汽车</a>]]></description></item><item><title>[备忘] 2008.07.02 - 移动类型与各种交易单据之间的关系、设计方案疑点</title><link>http://www.cnblogs.com/RicCC/archive/2008/07/03/1234408.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Wed, 02 Jul 2008 17:03:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/07/03/1234408.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1234408.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/07/03/1234408.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1234408.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1234408.html</trackback:ping><description><![CDATA[设计开发库存管理系统的备忘：<br />
<br />
<strong>仓库区域结构设计</strong><br />
类型上分为Location、Area、Section三种。Location映射到某个仓储地点、工厂；Area映射到各种存货区域；Section映射到存货区域中的货架、细分的存储单元<br />
Area允许建立父子关联关系，可以用Area映射到待检区、退货区、合格区这样的业务概念，还可以在Area下面建立子级Area，例如在合格区下面按产品主类再细分区域<br />
<br />
<strong>移动类型的设计</strong><br />
主要目的：<br />
对各种出入库行为分门别类，用这个统一的标准对出入库行为进行管理，记录、追踪、分析。例如象SAP一样：101表示采购收货、103表示采购收货到GR冻结区、124表示从GR冻结区退货给供应商<br />
其它目的：<br />
移动类型不在代码中硬编码，通过配置进行管理；移动类型能够用来代表不同的业务行为，以后通过配置可以对它代表的业务行为进行更换；与各种出入库单据之间的关系是个疑问点；各种移动类型可以使用的仓库区域进行配置，这样仓库区域映射的业务概念也不是硬编码，而可以通过配置进行调整改变<br />
<br />
<strong>出入库单据与库存交易的设计</strong><br />
a) 考虑了2种做法<br />
1. 出入库单据和明细就直接作为库存交易<br />
2. 出入库单据和明细，与库存交易分开<br />
方案1主要是考虑出入库单据和明细所包含的主要信息，与库存交易基本一样；但考虑到各种出入库单据本身可能有不同的状态转换形式、有签核流程、有其它不同的附加属性等，还是采用方案2将它们分开。交易表记录的就只是库房已经完成的交易，不会与其它逻辑混在一起<br />
b) 各种类型的单据都定义了单据类型，依附于单据类型产生的一些配置包括：单据号码生成规则、单据签核流程配置、单据状态定义、单据需要执行的交易步骤以及每个步骤中采用哪种交易类型的配置<br />
<br />
<strong>疑点</strong><br />
1. 各种出入库单据能否统一起来，如何统一？<br />
<p>
2. 出入库单据类型与交易类型之间的本质联系是什么？方案上是否可以优化？</p>
<p>3. 仓库区域、交易类型、各种出入库单据组合起来，是否可以完全达到可配置这个目标，怎样设计？</p>
<p><strong>疑点解释</strong><strong>2008.07.30</strong><strong>:</strong></p>
<p>&nbsp;&nbsp;&nbsp; 出入库单据是基于用户使用方面考虑的设计，例如仓库的实际作业流程是什么状况，有哪些行业特性、管理差异等。出入库单据就是把这些情况都考虑进来，尽可能合理、方便的配合用户作业操作<br />
</p>
<p>&nbsp; &nbsp; 交易类型完全是后台的实现规则，主要作用是管理、实现出入库交易的核心逻辑；实现与成本、财务相关科目、事件的整合。所以单据类型与交易类型之间存在组合映射关系；交易类型标识了一组事件接口，包括出入库交易逻辑、成本财务事件处理逻辑</p>
<p>&nbsp; &nbsp; 出入库单据只是一套衣服，我们应该能够脱下一套换成另外一套。针对单据类型设计的配置，主要用来满足业务流程操作的灵活性，例如单据状态怎么流转、是否需要签核、单据针对哪些物料类型进行操作等等。而针对交易类型设计的配置，则更侧重于企业整体运作流程、行业区域特性等等<br />
</p>
<p>&nbsp; &nbsp; 分层次来看一下，最终的业务操作人员负责单据的录入、提交，以及单据流程中的一些其它事件处理；客户企业的管理者、系统管理员能够对系统做一些配置设定工作，即维护单据类型相关的配置，这些配置设定主要影响业务操作人员的作业流程等层面的东西；顾问实施公司、软件开发企业的系统初始化设定，核心是维护好交易类型相关的配置<br />
</p>
<p>&nbsp;</p>
<strong>备注：</strong><br />
<strong>2008.07.18</strong><br />
<p>
恰当的设置冗余字段，注意并发时的一致性、死锁问题，可以避免大部分复杂查询，对数据库性能利大于弊</p>
<p><strong>2008.07.22</strong></p>
<p>JCP, NHibernate的做法都是顺理成章的，缓存、Unit of Work，Dynamic Proxy实现的延迟加载、对象和属性dirty的判断以及只更新dirty部分，并发控制机制等等，都是必不可少的特性。对缓存的并发控制带来其它的概念，例如把session作为隔离边界，缓存对象需要lock机制，同时为了支持Unit of Work特性，缓存的对象必须加上版本控制，对工作单元commit时进行版本判断。一路做下来，这些机制自然而然跟NHibernate没有多少差别了。</p>
<p><strong>2008.07.30</strong></p>
<p>库存交易其实和财务、银行交易本质上没有区别：</p>
<p>当前和历史库存量对应银行帐号余额和余额变化的历史记录；</p>
<p>财务的各种科目对应到不同的交易类型，科目数据对应库存交易数据，科目数据的原始凭证对应触发库存交易的各种单据；</p>
<p>财务流、现金流在库存交易中体现为物流，用复式记帐法来解释，物流也不会凭空产生或消失，只是从一种状态、形态转换到另一种状态、形态。只是库存交易不需要如此严格的按照财务系统方式设计，例如采购入库可以理解为贷记在途量(或订货量、供应商物资资产等)，借记仓库库存量。这种严格的借贷关系被转移到成本模块、财务系统处理，出入库本身的事件记录作为这些系统的原始或引用凭证；<br />
</p><img src ="http://www.cnblogs.com/RicCC/aggbug/1234408.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41935/" target="_blank">[新闻]对比测试：IE8 Beta 2 VS Firefox 3.0.1</a>]]></description></item><item><title>对ActiveRecord的评论</title><link>http://www.cnblogs.com/RicCC/archive/2008/05/10/about-ActiveRecord.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Fri, 09 May 2008 16:17:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/05/10/about-ActiveRecord.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1190770.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/05/10/about-ActiveRecord.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1190770.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1190770.html</trackback:ping><description><![CDATA[ActiveRecord的主要优点是一个过渡模式，当你没法从失血一步走到充血模型，或者不大确定是否该这样做时，是一种比较好的选择<br />
另外就算使用充血模式的复杂项目，还是会存在很多适合ActiveRecord的对象<br />
我想当你ActiveRecord使用熟练之后思路应该会不大一样，选择范围会比较开阔<br />
<br />
@怪怪<br />
结构化设计和面向对象设计之间的话题太大了，这里大部分人用.net开发应该面向对象的倾向会多一些。不同开发语言的特长和最适用的开发模式、应用环境都不一样，要综合各家优点适用于各种场景也不大现实<br />
<br />
我
理解你说的意思，各种方法论、实现方式都是力图解决后面的本质问题，回过头来这些本质问题的解决方法决不局限于单纯的某种方法论或实现方案，采用不同的视
角看问题，可能他们之间本身也是相通的。基于复杂度方面考量，我比较倾向于中庸之道，ActiveRecord是符合这种精神的<br />
<br />
poor
model-&gt;ActiveRecord-&gt;rich model这样一个路线走下去，很可能就是走上EJB的路子，以及对rich
model优劣的讨论是否该回归poor
model，不管是应用能力还是方法论水土不服带来的问题，在我看来复杂度过高就代表着不合适，或者得异常关注确信可以克服<br />
另外
ActiveRecord并不妨碍poor
model设计思想，甚至是基于RecordSet的结构化设计思想，并且的确可以带来编码上的便利性、一致性，尤其是对.net这个平台而言。而在的确
需要rich model的场景下也可以方便的应用。中庸之道的好处就是随时随地可以两边倒，面对各种需要处理的场景可以灵活运用，这是我认可的优点<br />
<br />
FP我不大了解，原本结构化设计思想就是不错的方法，面向对象的流行和普及现在不少人已经看到了它不适应的状况，因此我比较怀疑FP是不是又走了另外一个极端，来一个大规模的运用遇到的问题可能不亚于面向对象方法。不过确实在某些方面能够运用一些FP的特性的确是好事情，正如在该使用面向对象、设计模式的场景它的确能够带来极大的优点<br />
<br />
@怪怪<br />
如果不是极尽所能的去利用面向对象的各种手段，应该不会碰到它的缺点<br />
<br />
有很多人极力的挖掘面向对象的概念，去实现"复杂业务"和"扩展性"、"伸缩性"、"可靠性"、"维护性"，而另一手却高举"没有银弹"的旗帜<br />
很多的设计者对业务设计的关注几乎为0，结果是研究透了设计模式、重构、面向对象等方法却还是做不出好项目、好产品，而对各种问题的本质却可以夸夸其谈<br />
<br />
这样的场景下什么方法、思想都没用<br />
<img src ="http://www.cnblogs.com/RicCC/aggbug/1190770.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41934/" target="_blank">[新闻]iPhone存在严重密码安全漏洞</a>]]></description></item><item><title>分析模式系列读书笔记</title><link>http://www.cnblogs.com/RicCC/archive/2008/05/03/analysis-patterns-summary.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Sat, 03 May 2008 14:52:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/05/03/analysis-patterns-summary.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1180937.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/05/03/analysis-patterns-summary.html#Feedback</comments><slash:comments>14</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1180937.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1180937.html</trackback:ping><description><![CDATA[摘要: 分析模式不同于设计模式，它针对特定业务领域提供参考解决方案，如果对相关领域没有了解没有兴趣，就没有必要看下去<br>如果采用10分制对《分析模式》进行评价，我的评分是4-5分<br>杀鸡不要用牛刀，使用适合自己的方法<br>业务设计难得有通用模型，笔记中有大量个人理解和偏好方面内容，因此可能与原书中存在一定出入。这些理解主要来自对国内一些生产制造型企业以及几个ERP产品的了解&nbsp;&nbsp;<a href='http://www.cnblogs.com/RicCC/archive/2008/05/03/analysis-patterns-summary.html'>阅读全文</a><img src ="http://www.cnblogs.com/RicCC/aggbug/1180937.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41931/" target="_blank">[新闻]GC2008：星际争霸2进程报告 微调进程延续</a>]]></description></item><item><title>分析模式 - 交易模式(Trading)</title><link>http://www.cnblogs.com/RicCC/archive/2008/05/03/analysis-patterns-trading.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Sat, 03 May 2008 14:19:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/05/03/analysis-patterns-trading.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1180436.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/05/03/analysis-patterns-trading.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1180436.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1180436.html</trackback:ping><description><![CDATA[Martin在交易模式(Trading)中侧重在股票、期货、期权等，估计是从金融领域的一些项目中提取出来，这些领域比较狭隘<br />
另外感觉Martin在一些细枝末节上做的文章过多，而对行业中大量运用的各种业务模式只字不提，因此看起来根本不像领域概念模型，而只是针对特定行业领域的几种设计案例。毕竟领域概念模型的重点是系统如何实现各种主流的业务模式<br />
另外Martin很少使用专有的行业术语，要将那些突然间冒出来的对象名词对应到行业术语非常困难<br />
ERP系统尤其是象SAP这种大型ERP，它们的采购、销售等模块能够解决主流行业的交易(Trading)业务，适用范围比较广，综合来看解决方案与Martin提到的模式差距比较大<br />
因此这篇文章抛弃了Martin分析模式中相关章节的内容，记录的是自己对这一领域的接触理解，并且只是一些主要概念<br />
<br />
大致的采购用例:<br />
<img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/trading-use-case.jpg" height="557" width="665" /><br />
1. 采购信息记录是一个集中维护的价格清单，以及供应商信息<br />
&nbsp;&nbsp;&nbsp; 价格信息的来源可以有很多方式，例如报价Quota、合同Contract，以及其它可以提供价格信息的来源等<br />
&nbsp;&nbsp;&nbsp; 从报价、合同产生价格信息可以采用多种设计方式，例如在报价、合同确认生效时自动生成，或由采购员创建采购信息记录时可以选择引用报价、合同，并且根据配置决定采购员是否可以进行调整、多大范围内调整等<br />
2. 采购申请是物料的计划需求量，通过采购申请(主要提供需求数量、日期)和采购信息记录(主要提供供应商、采购价格)可以创建采购订单<br />
&nbsp;&nbsp;&nbsp; 因为采购多少、向谁采购、采购价格等都是企业非常敏感的地方，所以需要灵活设置以满足各种要求。管理规范、严格的公司可以采用上面的流程，并且限制采购员能够进行调整的范围，超过这些预设范围需要高层签核；对于管理要求不高的公司，或者是不重要的采购材料，可以不做太多控制，即允许采购员直接创建采购订单<br />
<br />
一次性采购的PO(采购订单)是比较传统的方式，根据询报价、采购申请创建采购订单，或者直接创建，进行后续采购作业<br />
针对重要物资、材料进行的战略采购涉及很多方面，也存在很多作业模式，可以使用合同来解决。合同是一种长期采购协议(Long Term Purchase Agreement)。SAP将合同分为价值合同和数量合同，价值合同主要确定某个时间之内总采购价值，引用价值合同创建的PO，PO总金额将汇总计入合同中，当汇总金额达到或超过合同总价值时，合同目标完成，后续采购需要使用新的合同；数量合同确定的是总数量，当PO的累计采购数量达到合同数量时合同目标完成<br />
<br />
Martin在书中提到的合同(Contract)相当于图中的采购订单(PO，PO本身是具有法律效应的，从法律角度讲它就是一种合同，但行业中只是将它们叫做订单，例如采购订单或销售订单)<br />
Portfolio则与图中的合同(Contract)概念有一点类似。Martin的描述中Portfolio更象是一种松散、随意的分组，把符合条件的订单包含进来进行一些统计分析，这样的功能可以使用数据分析(OLAP)的工具实现，如果在产品中考虑也不应当成为概念模型中的一个主要对象。我在图中给出的合同一方面可以提供一些框架性的价格信息(这个是可选的，即图中的采购合同向采购信息记录提供价格信息)，另一方面使得管理层能够控制、关注某一时间段内对合同材料的采购总价值、数量，例如合同目标完成之后如果没有新的合同则不允许继续采购。业务运作方面，与供应商建立战略合作伙伴关系有利于深入的合作，降低双方风险<br />
Scenario则有点类似图中的采购信息记录。上面说过，创建PO时是否必须从采购信息记录中取价格最好是可配置的，对那些采购实权落在具体采购员身上，而又缺乏条件改善这种管理状况的公司，允许采购员任意创建采购订单，决定采购数量和价格，是更好的解决方案<br />
<br />
对于一次性采购的PO，概念对象分为两层(采购订单+采购项目)就足够，交货计划的信息可以包含在采购订单或采购项目上面；交货计划适用于采购数量大、实时性要求高的精细化采购。例如场景之一：公司管理层每个季度与主要供应商签订大额采购订单(大的金额或数量)，生产、销售部门根据具体生产、销售情况制定细节交货计划，可能是每周、每2天交货多少等，然后由采购员负责执行这个交货计划，并且根据实际情况做一定沟通调整等。这种采购订单有点类似JIT采购模式中的Blanket PO<br />
<br />
精细化采购进一步发展就是JIT，这对供应商以及采购方和供应商之间的协作程度要求更高。JIT采购一般在系统外会进行供应商的考察、评估、认证，以及业务运作方面的协议签署。系统实现层面一般使用Blanket PO，这种PO没有数量或者提供一个大概的评估汇总数量，实际采购数量以具体的交货情况为准，Blanket PO主要提供采购价格信息。提供一个汇总评估数量的好处是供应商可以基于这个预先做好部分生产准备。JIT的交货将汇总计入Blanket PO，基于实际交货情况以及签订的协议进行财务结算<br />
JIT可以使用上面讲到的精细化采购的方案实现，即在PO中使用交货计划，因为JIT就是精细化采购的一种。不少情况可能需要将交货计划扩展成为一个独立的模块，例如大型企业实施JIT时需要对交货计划进行更多的控制，PO中的交货计划过于简单根本无法满足这些控制要求<br />
<br />
至于VMI，在采购流程上与JIT类似，只不过在采购申请的创建上可能包含其它复杂的处理逻辑，例如基于不同的库存控制理论计算补货点，在不同的预警区内提供不同的消息通知方式等等<br />
<br />
另外集中采购、分散采购等采购模式的实现，主要是围绕采购组织方面的设计问题<br />
对于生产型企业一般会维护物料主数据，但对于贸易型企业为了降低系统维护工作量(其实并不会降低，后续物料管理上的混乱将带来更多问题)，可能不希望专门维护物料主数据，这种情况采购订单中可以允许采购员直接输入采购材料的描述可能是比较容易实施(为客户建立物料编码的过程并不简单)，还有就是服务(Service)的采购<br />
<img src ="http://www.cnblogs.com/RicCC/aggbug/1180436.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41931/" target="_blank">[新闻]GC2008：星际争霸2进程报告 微调进程延续</a>]]></description></item><item><title>分析模式 - 度量与测绘</title><link>http://www.cnblogs.com/RicCC/archive/2008/04/26/analysis-patterns-measurement-and-observation.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Fri, 25 Apr 2008 22:27:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/04/26/analysis-patterns-measurement-and-observation.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1171738.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/04/26/analysis-patterns-measurement-and-observation.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1171738.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1171738.html</trackback:ping><description><![CDATA[<strong>数量(Quantity)</strong><br />
对象模型:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据模型:<br />
<img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/measurement_observation_2.jpg" /> <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/measurement_observation_1.jpg" /><br />
Unit: 单位主表，一般保存度量单位的代码、文本描述(可能需要处理多语言问题)等<br />
Unit_Ratio: 单位转换率<br />
<br />
Quantity主要封装与单位相关的逻辑，例如:<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 0);">person1.Height.Add(</span><span style="color: rgb(128, 0, 128);">8.5</span><span style="color: rgb(0, 0, 0);">, Unit.Get(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">cm</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">);<br />
</span><span style="color: rgb(0, 0, 0);">person1.Height.Add(</span><span style="color: rgb(128, 0, 128);">0.03</span><span style="color: rgb(0, 0, 0);">,&nbsp;</span><span style="color: rgb(0, 0, 0);">Unit.Get(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">m</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">);</span><br />
<span style="color: rgb(0, 0, 0);">Quantity&nbsp;diff&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;person1.Height&nbsp;</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">&nbsp;person2.Height;</span></div>
单位处理逻辑中一个主要功能是单位转换运算，例如Quantity相减的操作符重载代码类似如下:<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;Quantity&nbsp;</span><span style="color: rgb(0, 0, 255);">operator</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">(Quantity&nbsp;left,&nbsp;Quantity&nbsp;right)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;Quantity&nbsp;diff&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;Quantity(left._amount,&nbsp;left._unit);<br />
&nbsp;&nbsp;&nbsp;&nbsp;diff._amount&nbsp;</span><span style="color: rgb(0, 0, 0);">+=</span><span style="color: rgb(0, 0, 0);">&nbsp;right._amount&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">&nbsp;right._unit.Ratio(left._unit);<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;diff;<br />
}</span></div>
<br />
<strong>度量(Measurement)</strong><br />
度量是对数量模式的进一步抽象，书中以体检为例，进行一次体检就是得到一组各方面的度量数据，例如身高、体重、血压等，如果象上面那样在一个表中使用不同字段存储各个指标以及单位，自段会非常多，因此有了下面这个模式<br />
对象模型:<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/measurement_observation_4.jpg" /><br />
数据模型:<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/measurement_observation_5.jpg" /><br />
PhenomenonType2: 度量类型，例如长度、重量、体积等，每种度量类型关联多个度量单位(Unit)<br />
<br />
示例数据:<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/measurement_observation_6.jpg" /><br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/measurement_observation_7.jpg" /><br />
1. 某个人体检结果(实际上应当有个体检对象)的各种度量(PhenomenonType)指标均保存在Measurement中<br />
2. 对象模型中Measurement与Quantity分开，各司其职<br />
3. 界面上让用户选择单位时可以根据度量类型(PhenomenonType)缩小可选择单位的范围，例如身高这个属性只能选择长度单位<br />
4. 对于每种度量类型可以维护一个基本单位(Is_Basic)，系统一些内部运算以基本单位为准，例如财务、库存的交易、月结盘点，ERP的MRP运算等<br />
&nbsp;&nbsp; 为简化终端用户对单位转换率的维护工作，可以只维护每种单位到基本单位的转换率，系统自动计算同一度量类型中任意两种单位之间的转换率，但系统也可以不将这个逻辑硬编码而做的更灵活，这是一种基本的业务设计、指导方式<br />
<br />
<strong>测绘(Observation)</strong><br />
测绘是对上面两种模式的进一步抽象<br />
度量模式虽然使用度量类型带来了更大的灵活性通用性，但考虑的仍然是 "数量+单位" 这种测量类型，以色盲这一体检项目为例，它仍然是一个评测指标，但评测结果一般表现为一组可选值: A类红色盲、B类红色盲、B类红色弱、B类绿色弱等<br />
所以提取一个测绘基类(Observation)，从它派生出两种类型: 度量(Measurement)和分类评测(CategoryObservation)<br />
对象模型:<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/measurement_observation_8.jpg" height="331" width="592" /><br />
数据模型:<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/measurement_observation_9.jpg" height="269" width="535" /><br />
CagegoryOption3: 每种分类评测(CategoryObservation)类型可选值列表<br />
PhenomennonType3: 添加一个Observation_Type字段用来区分属于哪种测绘类型，例如1: Measurement, 2: CategoryObservation<br />
用面向对象的手段，Measurement3、CategoryObservation3与Observation3之间为实现接口或继承基类的关系；使用结构化设计手段，他们之间只是弱关联关系，Martin在书中实现泛化一节有详细说明<br />
上面图例可以理解为使用单表继承(Single table inheritance)实现这个继承关系，对于Measurement子类型Category_Option字段无效，对于CategoryObservation子类型Amount和Unit字段无效；CategoryObservation3和Measurement3因为行为上的差异而需要使用不同子类实现，Measurement3与Quantity3同样因为关注的职责不同而分离开；图中明显表现出多余、重复的气味，所以并不是一个优化设计方案，但对于理解Martin讲的Observation是什么正合适<br />
<br />
<strong>
转换率的时效性</strong><br />
指单位之间的转换随时间浮动，典型的是各种币别之间的汇率，这种情况下转换率需要添加有效时间范围，例如:<br />
<img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/measurement_observation_11.jpg" height="200" width="390" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/measurement_observation_10.jpg" height="123" width="141" /><br />
<img src ="http://www.cnblogs.com/RicCC/aggbug/1171738.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41930/" target="_blank">[新闻]科学家在世界最大对撞机中观察到首批粒子</a>]]></description></item><item><title>分析模式 - 库存和账务模式</title><link>http://www.cnblogs.com/RicCC/archive/2008/04/14/analysis-patterns-inventory-and-accounting.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Mon, 14 Apr 2008 11:56:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/04/14/analysis-patterns-inventory-and-accounting.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1151670.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/04/14/analysis-patterns-inventory-and-accounting.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1151670.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1151670.html</trackback:ping><description><![CDATA[对财务系统没有经验，基于自己有限的认识记录一下对Accounting Model的理解<strong><br />
<br />
1. 账务模式基本模型</strong>:<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/accounting_pattern_2.jpg" height="153" width="500" /><br />
Account: 如果是指个人理财方面(分析模式书中的示例场景)，当译做账号；如果指财务会计方面，当译做科目<br />
Entry: 交易条目<br />
Accounting Transaction: 交易<br />
<br />
简单ER设计示例:<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/accounting_pattern_1.jpg" height="174" width="637" /><br />
加了个"科目平衡 Banalce 1"的表，是因为Martin在这一节中不少地方都使用<u>Account</u> balance: Quantity表达，即Account对象有个balance属性，对个人理财的示例而言balance应当指账户的当前余额，而对于财务会计而言balance具有更多意义，即科目平衡表，在概念上科目、科目平衡表是独立的<br />
<br />
这反映的是复式计账法(double entry bookkeeping)的基本设计方案，例如从支票账号(checking: Account)兑现100$到现金帐号(cash: Account)，则交易和交易条目如下图:<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/accounting_pattern_6.jpg" height="147" width="430" /><br />
这个交易包含两个条目，一个对应到现金帐号，数量是+100，表示现金帐号增加100$；另一个对应到支票账号，数量是-100，表示支票账号减少100$。交易中两个条目的数量之和为0<br />
财务会计中使用借贷属性来表示，上面这个交易借记现金帐号，贷记支票账号，规则就是交易的借记汇总数量必须等于贷记汇总数量<br />
<br />
备注:<br />
a.) 不同业务环境下具体实现差异比较大，这个模式提供的是基本思想，只是一种参考不要生搬硬套<br />
&nbsp;&nbsp; 库存方面参考: <a href="http://www.cnblogs.com/RicCC/archive/2008/04/13/analysis-patterns-inventory-design-example.html" target="_blank">库存系统设计示例</a><br />
&nbsp;&nbsp; 财务系统、ERP财务模块基本原理跟模型一致: 账必须绝对平衡。但涉及的方面太多所以情况很复杂，例如科目繁多并涉及到企业经营中的各种业务概念；现金、资产、应收、应付等各个方面都有复杂的操作流程，它们可能衍生出复杂的业务模块，例如应收、应付在很多ERP中作为独立的模块。一种设计方式是集中管理，不过面对的复杂性和压力比较大，设计难度很高；另外一种是分散管理，例如应收、应付模块有自己的交易表；库存交易是固定资产中的一种，另外的是办公设备、生产设备等，他们更侧重于对损耗折旧、维修维护等方面的管理；针对现金管理也可能单独设计一个交易表。(例如库存系统设计示例中是一个中型ERP系统的设计，库存交易表中设计了单价、币别、交易成本等数据，他们将与应收、应付模块结合起来实现财务方面的部分逻辑)。后面这种设计方案下财务交易只是一种抽象概念，具体实现上被分散到了不同的地方，月结时综合考虑各个分散的部分。另外针对总账设计一些平衡表，例如月度、季度、年度损益表和资产负债表，以反映财务的汇总体状况。这种设计在各个业务模块与财务模块之间在复杂性上实现了一定平衡考量，但随着各个业务模块和财务模块需要支持更复杂的逻辑时将面临比较大的困难，因为他们之间的逻辑耦合性太高<br />
&nbsp;&nbsp; 对于银行系统，个人、公司等客户的存、提款是基本业务；从个人账户角度看，基本关注点是交易条目这个对象，即自己在什么时候、用什么方式(柜台、ATM、刷卡消费等)、在什么地点存、取了多少金额，以及当前账户余额之类；从银行全局角度来看，它需要关注交易的全部、整体，例如银行内部转账、跨行转账时资金在不同账户间的流向、平衡等；银行业务种类越来越多，例如个人网上支付、协议交费业务、刷卡消费、房贷车贷等，尤其对公司业务的支持更复杂，例如代发工资(一个交易涉及到很多账户，即在一个交易中将工资总额从公司帐户划拨到各个员工账户上)等，因此它的交易系统与财务系统差别很大<br />
&nbsp;&nbsp; 另外对于网上支付等虚拟交易系统，以及其它各方面，基本原理类似，但实际设计都有各自的特点和针对性<br />
b.) 示例中相关设计使用了公司代码，因为假设财务范围为公司层级<br />
&nbsp;&nbsp; 示例中的科目设计采用了简单的Adjacency List Model，也可以采用责任模式等其它方法<br />
&nbsp;&nbsp; 类似库存系统设计示例中提到的，借贷属性可以使用正负金额或其它设计方式<br />
&nbsp;&nbsp; 示例中交易和交易条目采用了一对多的设计，因此能够支持多条目的交易，对于只需支持两个条目的交易可以采用类似库存系统设计示例中的方法<br />
<br />
<strong>2. 汇总科目(Summary Account)、明细科目</strong><br />
一般交易科目只是明细科目<br />
科目本身维护相当简单，复杂在于对各种企业活动进行财务记账时对科目的使用方面。总体来讲一级科目分类为资产类、负债类、成本类等，伴随着科目层级细分下去直到最终的各个分录，这是这些规则分解细化的主体思路<br />
除了从不同国家地区、公司、行业的财务规范、操作流程方面考量来设计财务系统的账务模式之外(高抽象层次的规则设计)，基于科目针对一些细节方面进行规则设计也能带来很大的使用灵活性，以SAP为例:<br />
科目过账容差设计(Tolerance Groups &amp; Tolerance): 针对会计人员做账时的容差设计，例如单笔金额容差不能超过多少、支付差额(客户多付少付金额等)不能超过多少等等<br />
科目组的输入控制: 属于该组中的科目哪些参数必须维护、哪些参数可选维护、哪些不能维护<br />
字段状态变式(Field Status Variants): 录入该科目的凭证单据时哪些辅助核算项目必须维护、哪些不能维护<br />
<br />
<strong>3. 备注科目(Memo Account)</strong><br />
书中所举的例子比较直观很好理解。基于国外自行进行税务申报的体制，从个人理财角度来看，当月有一笔收入时，必须除去税收之后的剩余金额才是个人实际收入所得，但税务申报只在固定时刻发生，如果不做特别处理则下个月度查看上月财务状况时得到的是不准确的报告。因此设计一个应付税科目(tax liability account)，该科目只是一个虚拟科目，因为实际的缴税活动还没有发生，只是为了让个人的财务统计状况更准确而以。备注科目不参与账务平衡计算(因为实际的交易活动并未发生)，但相关科目的交易发生时(例如有收入进入个人收入科目)，必须为备注科目产生交易条目<br />
ERP中的应收、应付之类基本概念类似，不过需要面对企业财务的标准、更多复杂情况而以<br />
例如SAP中专门设计统驭科目GRIR等，解决OA30、TT30等不同付款方式造成的货到票未到、票到货未到等特殊情况，其基本含义也就类似上面<br />
因为特定的流程、逻辑太多，所以应收、应付通常被设计为独立的模块、组件，相关的数据也被分离到另外独立的表中存储<br />
<br />
<strong>4. 过账规则(Posting Rules)</strong><br />
以应付税科目为例，在个人收入科目有收入交易时，系统需要自动计算应付税额，为应付税科目添加一个交易条目。应付税额不是简单运算能得到，例如国内的个人所得税计税方式就有应税基数，分级进行税额计算，这是一组复杂的计算规则，并且这些规则经常会调整，所以设计一个可配置的过账规则非常必要<br />
另外分析模式书中提到的工资计算问题，对生产线上严格按刷卡时间计算薪水的情况是很普遍的，多长时间算是正常工作时间，什么情况才算加班，不同情况下的加班费用如何计算，迟到请假如何扣薪等，都是很复杂的规则配置<br />
ERP中大量的使用过账规则的设计，例如采购入库、销售出库等能够自动产生相应科目的应收、应付条目<br />
对过账规则设计应注意可反向冲销(reversibility)，保持绝对严格的事务一致性<br />
<br />
<strong>
过账规则实现方法</strong><br />
a.) 单类 Singleton Class<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/accounting_pattern_3.jpg" height="195" width="421" /><br />
&nbsp;&nbsp; 对每一个过账规则使用一个派生类<br />
<br />
b.) 策略模式 Strategy Pattern<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/accounting_pattern_4.jpg" height="304" width="422" /><br />
<br />
c.) 内部条件语句实现<br />
&nbsp;&nbsp; 使用if..else..或者swich..case..实现<br />
<br />
d.) 参数化方法 Parameterized Method<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/accounting_pattern_5.jpg" height="134" width="352" /><br />
&nbsp;&nbsp; 上图示例不同地区、不同性别的人缴税规则不一样，过账规则处理时根据条件加载正确的规则，根据规则的参数进行处理<br />
<br />
e.) 解释器 Interpreter<br />
&nbsp;&nbsp; 使用字符串描述规则，用解释器解析、处理这些规则<br />
<br />
相对于单类方式，策略模式降低耦合带来更多一点灵活性；参数化方法可以减少派生类的数量；解释器针对特定方面进一步加强参数法方法的表现力<br />
对于类似工资计算的过账规则，采用策略模式+参数化方法+解释器可以做的比较灵活；对于一般复杂度的规则使用参数化方法或者加上策略模式等应当基本足够<br />
<br />
<strong>过账规则的执行</strong><br />
a.) 主动触发 Eager Firing<br />
&nbsp;&nbsp; 一种实时处理方式。一种实现方式是创建交易或交易条目时加载相关的过账规则，处理完交易条目后逐个处理过账规则；另一种方式是使用观察者模式，观察者过账规则，被观察者为科目或交易条目<br />
b.) 基于科目的触发 Account-based Firing<br />
&nbsp;&nbsp; 一种延时处理方式。对应每个科目维护一个未处理交易条目列表，交易完成时只是将交易产生的各个条目添加到相应科目的未处理列表中，使用另外的服务周期性的处理各科目的未处理列表，同时加载与科目相关的过账规则并进行处理<br />
&nbsp;&nbsp; 需要注意各个条目和过账规则的先后处理顺序<br />
c.) 基于过账规则的处罚 Posting-rule-based Firing<br />
&nbsp;&nbsp; 有点类似基于Account-based Firing，是一种延时处理方式，不过未处理队列不是按照科目而是基于过账规则设计<br />
d.) 内部链触发 Backward-chained Firing<br />
&nbsp;&nbsp; 一种延时处理方式，基本类似Account-based Firing，不过在处理交易条目和过账规则时，将交易条目和过账规则组织成一个处理链的方式进行<br />
<br />
<strong>5. 行业惯例 Accounting Practice</strong><br />
不管库存管理还是财务会计或者金融交易系统等，都存在很多行业标准、操作习惯，从设计上看就是一组系统预设规则的组合，这里讨论如何把过账规则组合起来进行处理<br />
可能不同的行业、不同国家地区这些惯例会不一样，所以会使用一些设计方法处理这方面问题<br />
<br />
<strong>6. 平衡表和收入清单 Balance Sheet and Income Statement</strong><br />
应当是财务会计方面比较专业的词汇了，他们是不同的概念，设计上也应当分开考虑<br />
收入清单应当对应到企业财务中的损益表(利润表)，资金平衡表则应当对应到资产负债表<br />
可以用过账规则来处理，企业库存、财务管理简单的可以在月结动作中完成<br />
<br />
<strong>7. 错误调整</strong><br />
财务会计中记错帐也是不可避免的事情，对错误进行调整有几种方案<br />
a.) 替换调整 Replacement Adjustment<br />
&nbsp;&nbsp; 这种方法是直接将错误的交易条目修改或替换为正确的。一般财务会计、金融系统等都不允许这样做，例如你3月份打印一个银行帐单，里面一条记录是某天在某商场刷卡消费1000块，但到了4月份你再次打印3月份的账单时这笔消费变成了1500块，这是不允许的，因为我们无法信任这个打印的账单<br />
b.) 反向调整 Reversal Adjustment<br />
&nbsp;&nbsp; 仍以a中的例子说明，4月份银行发现这笔消费记录做错了，但前提是不能直接修改这个历史交易条目，因此先在个人账户和商场账户之间补做一笔反向交易(将3月份已发生的交易看作正向，即从个人账户转账1000元到商场账户，那反向交易则数量仍然是1000元，转账方向是从商场账户转账到个人账户)，以抵消3月份的错误交易条目，然后重新做一笔数量为1500元的交易，方向是个人账户转账到商场账户，这样结果就正确了<br />
&nbsp;&nbsp; 当然银行在这样做之前先必须在商场和个人之间达成许可协议，这样商场和个人对4月份反向调整产生的2笔交易条目都清楚其原因<br />
c.) 差异调整 Difference Adjustment<br />
&nbsp;&nbsp; 仍以a中的例子说明，这次不用先做1000元的反向交易冲销错误记录，而是先计算好错误结果和正确结果之间的差异1500-1000=500元，因此直接补做一笔500元的交易，从个人账户转账到商场账户，这样结果也正确了<br />
<br />
<strong>8. 来自Martin的校正、对照</strong><br />
在Martin网站可以看到最新的分析模式描述，与原来书中有一些差别，可能是打算过出新版吧<br />
大致浏览了一下，差异主要在于整体组织结构的调整(分成主要的几个部分分别阐述，每个部分先提出问题，接着讨论使用时机，最后给出示例代码讲解)；对原来缺失的内容补充(例如上面7中的错误调整方式)<br />
<br />
关于模式内容方面主要是显示的提出"事件"这一概念，涉及到的一些方面都围绕"事件"进行了一点调整<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/accounting_pattern_7.jpg" height="184" width="474" /><br />
企业财务和库存系统中，用户是看不到"交易"这样一个概念的，交易只是系统内部的一种机制，用户在系统中录入一张单据，或者执行某个操作等各种事件发生时，将触发创建交易的操作<br />
所以Martin将这个过程更抽象一点，引入事件(Event)、事件类型(Event Type)、协议(Agreement)这几个概念<br />
每个事件将对应到一个事件类型Event Type；一个事件类型将关联一组过账规则Posting Rules，用于处理属于该类型的各个具体事件；在设计层面事件类型反映出来的是一个协议Agreement，该协议决定了这类事件的处理逻辑<br />
<br />
从上图来看，对事件类型和协议可能有一些疑惑: 事件类型已经关联了一组过账规则，事件发生时直接加载这些过账规则逐个处理就是了，为什么还需要"协议"这个对象？<br />
从前面过账规则的定义来看，它的职责是处理一些附加的事情(类似使用AOP将其它方面的一些事情插入到某个交易逻辑中)，或者交易处理逻辑本身非常复杂并且需要做成一组组灵活的可以修改、替换的规则，而采用过账规则来实现。而协议Agreement则是完成交易逻辑的统筹者，包括加载过账规则并正确执行他们。尽管理论上也可以将协议Agreement全都实现为过账规则，通过事件类型配置起来，不过钻到实际情况中就可以体会到这样做的难度，从上图来看，会计条目Accounting Entry是由过账规则而并不是协议Agreement创建，看来Martin应当正是指的这种方法了，如果这样协议Agreement的主要职责就是处理不同的上下文内容，以及对过账规则的调度处理

<img src ="http://www.cnblogs.com/RicCC/aggbug/1151670.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41929/" target="_blank">[新闻]阿里巴巴利润增1.36倍</a>]]></description></item><item><title>分析模式 - 库存系统设计示例</title><link>http://www.cnblogs.com/RicCC/archive/2008/04/13/analysis-patterns-inventory-design-example.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Sun, 13 Apr 2008 15:42:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/04/13/analysis-patterns-inventory-design-example.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1149244.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/04/13/analysis-patterns-inventory-design-example.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1149244.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1149244.html</trackback:ping><description><![CDATA[一个中型ERP系统中库存交易部分的设计裁剪<br />
<br />
库房设计:<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/accouting_inv_example_1.jpg" height="422" width="324" /><br />
BPML中关于这一块有详细的规范可以用来参考，这个设计示例并不符合<br />
是否资产库房: 与成本计算相关的参数<br />
是否属于供应商库房、供应商ID: 对类似寄售管理模式的考虑<br />
这些额外的字段只是用来表示基于库房的一些其它逻辑相关的设置<br />
<br />
交易:<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/accouting_inv_example_2.jpg" height="482" width="665" /><br />
<strong>库存期间</strong>: 月结、周期性盘点结转作业的期间设置(对应Martin在账务模式中提到的有效期间)<br />
库存期间代码: 唯一标识这个库存期间，例如200801、200803等形式<br />
期间类型: 对期间进行灵活设置的各种方法进行分类，例如指定区间段方式Period、周期性方式Cycle等<br />
期间编号: 示例情况中期间编号基于每个年份从1开始自增<br />
期间状态: 对应到库存期间开帐、月结、关帐等业务操作<br />
总账期间: 与成本相关的设置，该库存期间内的成本计入哪个总账期间<br />
成本期间状态、在制期间状态: 库存期间、成本期间、在制期间合用同一个设置，用不同的状态字段表示<br />
说明: 可以更灵活点设值，例如期间类型为Cycle方式时，可以使用"间隔时间"+"间隔时间单位"这样两个字段表示，例如每3周、每月、每季等等<br />
<strong>交易来源类型</strong>: 移库操作时物料从来源库转储到目标库；采购收货入库的来源类型则为采购单、收料单之类<br />
<strong>交易类型</strong>: 库房之间的转储、采购收料入库、车间工单派料、销售出库等各种交易类型<br />
<strong>库存交易</strong>: 库存交易主表<br />
交易编号: 系统自动生成，提供给用户(所以不是使用交易ID)用来唯一标记本次交易。例如TR2008030001、TR2008030002<br />
交易时间、提交时间: 即Martin提到的交易发生时间与生效时间这个概念<br />
交易来源单号: 例如来源类型为采购收料入库时它存放具体的收料单号<br />
转换率: 例如气态、液态物料在转储等操作过程中可能存在损挥发、耗率之类的情况<br />
<strong>交易明细</strong>: 某次库存交易中具体的各个物料交易状况<br />
来源库房、来源储位、目标库房、目标储位: 对应不同的交易类型他们可能为空<br />
来源单号、来源ID、来源项目号: 例如来源类型为采购收料入库时，这几个字段存放收料单号、收料单ID、收料单明细项目号<br />
预留数量: 例如为销售订单开立出库单时先预留冻结一定数量的产品库存，以保证出库单出库发货时(即交易转为完成状态，中间可能间隔时间比较长)至少存在这个数量的产品(当然不一定得这样设计)<br />
交易单价、交易币别、交易成本: 成本计算相关的设置(有意的冗余设计)<br />
<br />
这是比较简单、实用的一种设计方式。库存交易、交易明细是核心表；库存期间所表现的业务模式基本是行业通用的操作标准；交易来源类型、交易类型是为了跟踪交易，对交易进行运算的规则设置，他们可以设计的更复杂、灵活；针对交易类型，SAP采用移动类型来解决，基本效果也类似于此，只是规则设置更复杂，运用起来更灵活而以<br />
一些小的方面:<br />
1. 两种方案: a.) 交易明细里面的数量允许负数，例如入库用正数表示，出库用负数表示。b.) 交易明细的数量全部用正数表示，出、入库的逻辑(即正、负数关系)包含在交易类型中。方案a应当更灵活一些，因为方案b将这个逻辑进行了隐式的捆绑；方案a也会导致针对交易的汇总运算算法比较一致(即统一采用加法运算)，SQL汇总报表也会比较灵活(例如简单的使用SUM函数)，不过可以做更多的规则设置来显式的表示这种逻辑<br />
2. 财务中的交易原理上与这里基本相同，不过有个比较明显的区别: 财务的交易必须通过科目配置，严格的保证账目的平衡，库存交易则不是必须的，只需严格的记录物料这一资产的流动，以表明它不是平白无故的出现或消失了就可以。对于成本运算，与财务类似<br />
3. 示例中主要数据都以工厂作为数据的范围，这是不够灵活的，不要被误导，应当遵循BPML、B2MML规范，做更灵活的设计；其它也都如此，例如成本、总帐相关的设置等<br />
4. 理论上当前库存值以及其他一些数据，应当根据交易动态运算出结果，不过大部分情况为了改善性能都会设计冗余表，或者由Application Server在内存中缓存，下面给出其中一个比较重要的设计<br />
<br />
库存损益:<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/analysis_pattern/accouting_inv_example_3.jpg" height="290" width="387" /><br />
<strong>库存期间损益</strong>: 损益状况都以库存期间为统计单位<br />
<strong>库存期间损益明细</strong>: 损益的明细清单，出入库类型同样可以使用数量的正负关系表示<br />
这个设计可以用于快速获得当前库存结余量、每个历史库存期间的结余量。另外单从设计上看用法也可以存在多意性，a.) 可以用作对每个库存期间内任何一天的当前库存的冗余设计，这样库存期间损益明细没有太多必要，因为基本对应到交易明细，另外每个交易发生时必须同步更新该数据。b.) 可以用作每次库房盘点时的损益记录，这样损益明细是必须的，并且与每次库存交易没有关系，它表达的信息只是上期结余量、本期初始量，所以对于期间内的任何一天的当前库存量，仍需要另外的冗余表或者Application Server的缓存来处理<br />
<br />
附注:<br />
1. 上面示例的表结构虽然简单，但同样能够设计出多变的业务操作流程，以适应不同的作业环境，这缘自于针对这个业务问题，数据模型、对象模型、概念模型之间的差异很大，数据模型基本无法反映出概念模型的状况<br />
例如为了配合做QC，SAP可以将库房配置为GR冻结库存、非限制使用库存和质量检验库存等类型，对于需要进行质检的物料，采购收料先通过移动类型103入GR冻结库，表示这些物料还无法领用，因为没有完成质检；质检通过后使用移动类型105将物料从GR冻结库转储到非限制使用库存，这样就可以领用了；对于免检物料，使用移动类型101直接收货入库到非限制使用库存。这个业务流程设计同样可以针对示例的设计做稍许调整而实现。库存交易、交易明细是抽象层次比较高的一种对象，如何用它来实现具体的业务流程是灵活多变的<br />
2. SAP其它一些移动类型<br />
104用于对103的冲销；106用于对105的冲销等等，这个类似于Martin在分析模式中的反向冲销、差异冲销等模式，具体使用反向冲销还是差异冲销由用户决定<br />
124供应商退货，125用于对124的冲销，122(123)、161(162)等都属各种类型的退货<br />
从SAP这个设计来看，移动类型也是一种比较高的抽象概念，灵活的用于解决概念模型中的各种问题<br />
<img src ="http://www.cnblogs.com/RicCC/aggbug/1149244.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41928/" target="_blank">[新闻]Google Gears覆盖四大浏览器 Safari版推出</a>]]></description></item><item><title>VS2008代码度量工具</title><link>http://www.cnblogs.com/RicCC/archive/2008/04/09/1144618.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Wed, 09 Apr 2008 04:34:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/04/09/1144618.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1144618.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/04/09/1144618.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1144618.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1144618.html</trackback:ping><description><![CDATA[<a href="http://www.cnblogs.com/fhmsha/archive/2008/04/08/1142354.html" target="_blank">[翻译]Visual Studio2008的新功能：代码度量</a>介绍了VS2008的代码度量工具<br />
<br />
可能只有VS 2008 Team Suite才有这个功能<br />
我不喜欢装太多东西，VS2008基本只装了C#一项，因此没有这个功能。重新在VS 2008安装向导中选择Team Developer and Tester Tools，估计应当是包含在Code Analysis Tools中<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/vs2008_code_metrics_1.jpg" height="305" width="311" /><br />
安装好这个组件后项目和解决方案右键菜单就有这个功能了<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/vs2008_code_metrics_2.jpg" height="145" width="231" /><br />
<br />
部分分析结果截图<br />
&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/vs2008_code_metrics_3.jpg" height="353" width="700" /><br />
<br />
&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/vs2008_code_metrics_4.jpg" height="502" width="700" /><br />
项目中某些方法复杂度过高了，例如上图中单个方法复杂度37、44的，这也的确是列在了改进日程上的地方，这些地方的逻辑判断关系、执行流程跳转情况，说不准过一段时间我自己都会忘掉了，这就是单个方法复杂度所反映出来的实际状况<br />
<br />
可以使用Filter对统计结果进行过滤，例如下图中，复杂度都达到91了结果还是绿灯，比较疑惑了。但工具提供的功能已经足够用了<br />
&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/vs2008_code_metrics_5.jpg" height="463" width="700" /><br />
<img src ="http://www.cnblogs.com/RicCC/aggbug/1144618.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41927/" target="_blank">[新闻]Internet Explorer 8 Beta 2 发布</a>]]></description></item><item><title>分析模式 - 责任模式</title><link>http://www.cnblogs.com/RicCC/archive/2008/04/08/analysis-patterns-accountability.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Tue, 08 Apr 2008 13:52:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/04/08/analysis-patterns-accountability.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1142528.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/04/08/analysis-patterns-accountability.html#Feedback</comments><slash:comments>17</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1142528.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1142528.html</trackback:ping><description><![CDATA[摘要: Martin用对象模型来描述分析模式，比较难懂，这里侧重于数据模型，使用组织结构的示例来描述责任模式&nbsp;&nbsp;<a href='http://www.cnblogs.com/RicCC/archive/2008/04/08/analysis-patterns-accountability.html'>阅读全文</a><img src ="http://www.cnblogs.com/RicCC/aggbug/1142528.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41924/" target="_blank">[新闻]中国软件协会：SAP羞辱国产软件是不正当竞争</a>]]></description></item><item><title>伸缩性思考1: SAP</title><link>http://www.cnblogs.com/RicCC/archive/2008/04/03/1135407.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Wed, 02 Apr 2008 17:10:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/04/03/1135407.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1135407.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/04/03/1135407.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1135407.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1135407.html</trackback:ping><description><![CDATA[SAP并不符合"超越分布式事务的方法"一文中提出的解决方案，但作为一个大型系统已经考虑了伸缩性，并且与"超越分布式事务的方法"中的思想有些类似<br />
<br />
1. 任何情况下不使用JOIN<br />
&nbsp;&nbsp; 实体可能被分区在任何一个数据库中，在实体之间如何跨越数据库的JOIN? No way!<br />
&nbsp;&nbsp; 单这一点足以难倒绝大部分的设计、架构师<br />
&nbsp;&nbsp; a). 事务型的操作(OLTP)使用对象模型解决，分析、报表查询类的操作(OLAP)使用另外的解决方案，例如BI系统，或者特定的报表模块。SAP中也存在大量的分析报表，有系统标准提供的，有用户开发的，对这一部分不必遵守伸缩性原则，重新分区时分析模型、配置需要重新设置<br />
&nbsp;&nbsp; b). 业务设计观念的转变(或者说正确的认识什么是业务设计，这一点应当是普遍的误解，或弱化、忽视了)<br />
<br />
&nbsp;&nbsp; 只有达到了这一点才可以考虑无限伸缩解决方案，达到了这点其他很多问题的解决也会变得简单很多<br />
<br />
2. 实体粒度<br />
&nbsp;&nbsp; SAP每个Client可以使用单独的数据库实例，但一个数据库实例中是否允许存在多个Client倒不太清楚了<br />
&nbsp;&nbsp; 一般Client在业务概念上映射到子集团，明显这个粒度太大了，可能这个原因在不少情况下是制约SAP性能的一个关键因素，导致为了解决性能问题硬件和实施成本过高<br />
&nbsp;&nbsp; 实体粒度太细也没有必要，对那些永远也不可能需要分布式的数据设计为实体，同样是浪费<br />
&nbsp;&nbsp; 实体的离散性、业务逻辑的复杂性、性能，这些因素之间总是相互影响和制约，如何在他们之间平衡取舍?<br />
<br />
3. 实体键值<br />
&nbsp;&nbsp; SAP使用Client Code作为实体键值，Client Code是一个独立的字段，同一个Client中实体对象(entity object，相对于value object而言)基本都有Client Code这个字段<br />
&nbsp;&nbsp; SAP只是集团内部系统，Client映射到子集团，Client的概念类似魔兽中的不同区域服务器，不过SAP的Client之间数据可以传输、共享<br />
&nbsp;&nbsp; 用户在登陆系统时必须提供Client Code、账号和密码，所以这个Client Code就会贯穿用户登陆系统之后的所有操作。考虑amazon这种系统，这样的解决方案就不可行了，用户在登陆系统时还得选择一区域?<br />
&nbsp;&nbsp; 事务序列化范围肯定只局限于Client范围之内，Client之间将使用消息通讯完成数据传输<br />
<br />
4. 消息<br />
&nbsp;&nbsp; SAP的消息格式是IDoc，从文档结构上看具备自描述性<br />
&nbsp;&nbsp; 对消息与事务的管理、是否有消息重试、重订阅等幂等性处理机制不了解<br />
&nbsp;&nbsp; IDoc除了用于Client之间的通讯，也用于外部系统与SAP之间的通讯<br />
<img src ="http://www.cnblogs.com/RicCC/aggbug/1135407.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41923/" target="_blank">[新闻]福布斯：Facebook网站十大最火爆游戏</a>]]></description></item><item><title>[翻译] 超越分布式事务的方法 - 一个叛逆者的观点</title><link>http://www.cnblogs.com/RicCC/archive/2008/03/30/life-beyond-distributed-transactions.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Sat, 29 Mar 2008 22:20:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/03/30/life-beyond-distributed-transactions.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1129481.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/03/30/life-beyond-distributed-transactions.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1129481.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1129481.html</trackback:ping><description><![CDATA[摘要: 摒弃分布式事务的高伸缩性解决方案<br>Life beyond Distributed Transactions: an Apostate’s Opinion&nbsp;&nbsp;<a href='http://www.cnblogs.com/RicCC/archive/2008/03/30/life-beyond-distributed-transactions.html'>阅读全文</a><img src ="http://www.cnblogs.com/RicCC/aggbug/1129481.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41922/" target="_blank">[新闻]谷歌允许用户评论搜索结果调整顺序</a>]]></description></item><item><title>JavaScript问题汇总</title><link>http://www.cnblogs.com/RicCC/archive/2008/03/23/1118249.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Sat, 22 Mar 2008 23:14:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/03/23/1118249.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1118249.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/03/23/1118249.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1118249.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1118249.html</trackback:ping><description><![CDATA[1. Ajax调用被杀毒软件/防火墙阻挡<br />
&nbsp;&nbsp; 记得05年做项目遇到过这种情况，发现客户端关掉kv300和瑞星的网页监控选项能够解决问题，因为是集团和供应商之间的系统，没有深究原因，而是要求用户关闭杀毒软件的网页监控选项<br />
&nbsp;&nbsp; 不久前的项目又遇到这个情况，卡巴会拦截ajax调用请求。将http header的connection设置为close可以解决问题：xmlHttp.setRequestHeader('Connection', 'close');。<br />
&nbsp;&nbsp; 两次发生这种情况时都不是使用第三方js库，而是直接用xmlhttp实现。使用jQuery和Prototype的时候好像没有遇到过，查了一下jQuery里面的ajax没有对Connection进行设置，而Prototype则给出了一段，说针对老板本Mozilla的一个bug而将Connection设为close。http1.1的Connection默认为persistent connection，既然jQuery和Prototype不会出问题，则说明卡巴的拦截规则为：connection要么为close；如果使用persistent connection，则其它某些header必须符合要求，否则一律拦截。<br />
<br />
2. IE Operation aborted<br />
&nbsp;&nbsp; 参考<a href="http://weblogs.asp.net/infinitiesloop/archive/2006/11/02/Dealing-with-IE-_2600_quot_3B00_Operation-Aborted_2600_quot_3B002E00_-Or_2C00_-how-to-Crash-IE.aspx" target="_blank">Dealing with IE Operation Aborted</a><br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">html</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">head</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">script&nbsp;</span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">="text/javascript"</span><span style="color: #0000ff;">&gt;</span><span style="background-color: #f5f5f5; color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="background-color: #f5f5f5; color: #0000ff;">function</span><span style="background-color: #f5f5f5; color: #000000;">&nbsp;appendToBody()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="background-color: #f5f5f5; color: #0000ff;">var</span><span style="background-color: #f5f5f5; color: #000000;">&nbsp;div&nbsp;</span><span style="background-color: #f5f5f5; color: #000000;">=</span><span style="background-color: #f5f5f5; color: #000000;">&nbsp;document.createElement(</span><span style="background-color: #f5f5f5; color: #000000;">'</span><span style="background-color: #f5f5f5; color: #000000;">div</span><span style="background-color: #f5f5f5; color: #000000;">'</span><span style="background-color: #f5f5f5; color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;div.innerHTML&nbsp;</span><span style="background-color: #f5f5f5; color: #000000;">=</span><span style="background-color: #f5f5f5; color: #000000;">&nbsp;</span><span style="background-color: #f5f5f5; color: #000000;">"</span><span style="background-color: #f5f5f5; color: #000000;">Operation&nbsp;aborted!</span><span style="background-color: #f5f5f5; color: #000000;">"</span><span style="background-color: #f5f5f5; color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document.body.appendChild(div);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">script</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">head</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">body</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">form</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">script&nbsp;</span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">="text/javascript"</span><span style="color: #0000ff;">&gt;</span><span style="background-color: #f5f5f5; color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;appendToBody();<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">script</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">form</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">body</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">html</span><span style="color: #0000ff;">&gt;</span></div>
&nbsp;&nbsp; IE打开这个文档就会出现"Operation aborted"错误信息，解决方法1.为script标签加上defer属性，2.让script标签属于body的直接子节点。defer属性只针对IE有效，并且导致在IE中script的执行被延迟，而其它浏览器下则不会，因此需要注意多浏览器下的副作用<br />
<br />
3. jQuery的selector，文档中有可能同一id出现多个地方时，一定要指定context，即$(selector, context)<br />
&nbsp;&nbsp; 因为很多地方都需要弹出窗口选择用户、选择组织结构等类似功能，没有使用window.open，而是用jQuery做了一个div弹窗的封装，外层div包装了弹出窗口的标题栏、按钮、3D边框效果、drag/drop、ajax调用、统一的使用接口等，里面有个id为dataArea的div，用ajax调用具体的查询页面将html填入其中。问题发生在同一个页面需要多个这样的弹出窗口，导致dataArea这个id存在多个对象，selector中不使用context时，多次弹出时竟然循环交替的获取到各个dataArea对象<br />
&nbsp;&nbsp; javascript组件用的多而复杂时，相关的一些问题跟线程安全一样重要而复杂<br />
<img src ="http://www.cnblogs.com/RicCC/aggbug/1118249.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41921/" target="_blank">[新闻]Internet 另一超级漏洞被公布</a>]]></description></item><item><title>ANTLR笔记5 - 备忘</title><link>http://www.cnblogs.com/RicCC/archive/2008/03/17/antlr-notepad.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Sun, 16 Mar 2008 16:21:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/03/17/antlr-notepad.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1108915.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/03/17/antlr-notepad.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1108915.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1108915.html</trackback:ping><description><![CDATA[1. 对语法框架结构的整体构思<br />
&nbsp;&nbsp; 一方面为了避免过多因素的干扰，另一方面考虑迭代完善过程，在对语法的整体构思时不要考虑语法树的结构，以及如何构造语法树的问题。<br />
<br />
2. 采用自底向上的方法<br />
&nbsp;&nbsp; 因为这样可以结合ANTLRWorks一步步测试，在Interpreter窗口选择要测试的规则就可以进行。<br />
&nbsp;&nbsp; 例如下面图中的NoViableAltException表示这个表达式无法解析<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/antlr/antlr-interpreter-error.png" height="247" width="343" /><br />
&nbsp;&nbsp; 自底向上时对每一个规则最好能够充分的考虑到各种需要处理的情况，并用ANTLRWorks测试验证。每编写好一个规则，最好能用自顶向下、最左推导的思维方式进行Review，尝试找出有可能破坏这种推导方式的情况。因为越往上，出现问题，尤其是不符合LL(*)时，越难找出原因。<br />
&nbsp;&nbsp; 词法规则比较重要，好的词法规则定义可以使语法规则简化。<br />
<br />
3. 善用ANTLRWorks<br />
3.1 便利的编辑功能<br />
&nbsp;&nbsp; Ctrl+B: 转到规则的定义处<br />
&nbsp;&nbsp; Ctrl+Shift+B: 查找规则，能按当前输入字符过滤<br />
&nbsp;&nbsp; 前进、后退<br />
&nbsp;&nbsp; Ctrl+R: 检查语法<br />
3.2 排错，例如Decision can match input such as "..." using multiple alternatives<br />
&nbsp;&nbsp; 说明语法规则不符合LL(*)，不大熟练的情况下，对复杂的语法定位这个问题比较困难，ANTLRWorks提供了一些信息帮助我们解决这样的问题<br />
&nbsp;&nbsp; 首先进行语法检查之后如果出现这样的提示，在左上角的规则列表窗口中，有问题的规则会红色字体显示，鼠标移上去会有一些提示信息(在Console窗口中有显示这些信息)<br />
&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/antlr/antlr-non-ll.jpg" height="199" width="617" /><br />
&nbsp;&nbsp; 选择一个有问题的规则，在Syntax Diagram窗口可以看到各个存在冲突的推导路径，勾选右下角的Show NFA可以从NFA视图来查看这些推导路径<br />
&nbsp;&nbsp;&nbsp;
<img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/antlr/antlr-non-ll-sd.png" height="340" width="427" /><br />
<img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/antlr/antlr-non-ll-nfa.png" width="750" /><br />
&nbsp;&nbsp; 这些推导路径有助于我们找出Non-LL(*)语法，解决这样的问题需要熟练的技巧<br />
<br />
4. 语法树的构造<br />
&nbsp;&nbsp; 语法树的结构服务于它的目的，所以应用中怎样使用方便，就应当怎样构造语法树，而不是依赖于ANTLR的*.g语法文件，也不要太过于受ANTLR AST的构造。所以，设计语法树时先不要考虑ANTLR AST构造。<br />
&nbsp;&nbsp; 使用ANTLR构造语法树时，先充分了解ANTLR提供的各种AST构造方法，灵活运用。<br />
&nbsp;&nbsp; 通过ANTLR Runtime的dll文件，弄明白IToken、ITree、ITreeAdapter的原理和职责，结合ANTLR生成的**Parser.cs文件，弄明白整个构造过程，这样除了在语法文件中使用AST Construction之外，还可以基于ITree、ITreeAdapter来控制语法树的构造过程<br />
<img src ="http://www.cnblogs.com/RicCC/aggbug/1108915.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41920/" target="_blank">[新闻]3 个独特的未来搜索引擎</a>]]></description></item><item><title>OQL中的Name Resolver, Mapping Resolver</title><link>http://www.cnblogs.com/RicCC/archive/2008/03/12/OQL-name-mapping-resolver.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Wed, 12 Mar 2008 15:34:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/03/12/OQL-name-mapping-resolver.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1102950.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/03/12/OQL-name-mapping-resolver.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1102950.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1102950.html</trackback:ping><description><![CDATA[OQL中的两个概念对象<br />
<br />
case 1: 把属性替换为列名，对象替换为表名<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">select</span><span style="color: #000000;">&nbsp;UserId,UserCode,UserName&nbsp;</span><span style="color: #0000ff;">from</span><span style="color: #000000;">&nbsp;</span><span style="color: #ff00ff;">User</span></div>
结果:<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">select</span><span style="color: #000000;">&nbsp;Usr_Id,Usr_Code,Usr_Name&nbsp;</span><span style="color: #0000ff;">from</span><span style="color: #000000;">&nbsp;Sys_User</span></div>
<br />
case 2: <br />
User对象指定了别名，所以a.UserId要根据别名确定属性UserId来自User对象，然后将UserId替换为列名<br />
有子查询，所以t.CreateBy需要到子查询里面搜索CreateBy属性来自哪个对象，这个case中可以查到来自Org，所以需要替换为Org对象上CreateBy属性映射的自段名<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">select</span><span style="color: #000000;">&nbsp;a.</span><span style="color: #808080;">*</span><span style="color: #000000;">&nbsp;<br />
</span><span style="color: #0000ff;">from</span><span style="color: #000000;">&nbsp;</span><span style="color: #ff00ff;">User</span><span style="color: #000000;">&nbsp;a&nbsp;<br />
</span><span style="color: #0000ff;">inner</span><span style="color: #000000;">&nbsp;</span><span style="color: #808080;">join</span><span style="color: #000000;">(<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">select</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">distinct</span><span style="color: #000000;">&nbsp;CreateBy&nbsp;</span><span style="color: #0000ff;">from</span><span style="color: #000000;">&nbsp;Org&nbsp;</span><span style="color: #0000ff;">where</span><span style="color: #000000;">&nbsp;OrgId</span><span style="color: #808080;">=</span><span style="color: #000000;">?<br />
)&nbsp;t&nbsp;</span><span style="color: #0000ff;">on</span><span style="color: #000000;">&nbsp;t.CreateBy</span><span style="color: #808080;">=</span><span style="color: #000000;">a.UserId</span></div>
结果:<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">select</span><span style="color: #000000;">&nbsp;a.</span><span style="color: #808080;">*</span><span style="color: #000000;">&nbsp;<br />
</span><span style="color: #0000ff;">from</span><span style="color: #000000;">&nbsp;Sys_User&nbsp;a&nbsp;<br />
</span><span style="color: #0000ff;">inner</span><span style="color: #000000;">&nbsp;</span><span style="color: #808080;">join</span><span style="color: #000000;">(<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">select</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">distinct</span><span style="color: #000000;">&nbsp;Create_By&nbsp;</span><span style="color: #0000ff;">from</span><span style="color: #000000;">&nbsp;Sys_Org&nbsp;</span><span style="color: #0000ff;">where</span><span style="color: #000000;">&nbsp;Org_Id</span><span style="color: #808080;">=</span><span style="color: #000000;">?<br />
)&nbsp;t&nbsp;</span><span style="color: #0000ff;">on</span><span style="color: #000000;">&nbsp;t.Create_By</span><span style="color: #808080;">=</span><span style="color: #000000;">a.Usr_Id</span></div>
<br />
case 3: 深入下去，情况就越复杂。<br />
这个case跟case 2的唯一区别是，子查询里面select出来的属性又指定了别名，并且跟属性名字还是一样。所以t.CreateBy不应当替换<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">select</span><span style="color: #000000;">&nbsp;a.</span><span style="color: #808080;">*</span><span style="color: #000000;">&nbsp;<br />
</span><span style="color: #0000ff;">from</span><span style="color: #000000;">&nbsp;</span><span style="color: #ff00ff;">User</span><span style="color: #000000;">&nbsp;a&nbsp;<br />
</span><span style="color: #0000ff;">inner</span><span style="color: #000000;">&nbsp;</span><span style="color: #808080;">join</span><span style="color: #000000;">(<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">select</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">distinct</span><span style="color: #000000;">&nbsp;CreateBy&nbsp;</span><span style="color: #0000ff;">as</span><span style="color: #000000;">&nbsp;CreateBy&nbsp;</span><span style="color: #0000ff;">from</span><span style="color: #000000;">&nbsp;Org&nbsp;</span><span style="color: #0000ff;">where</span><span style="color: #000000;">&nbsp;OrgId</span><span style="color: #808080;">=</span><span style="color: #000000;">?<br />
)&nbsp;t&nbsp;</span><span style="color: #0000ff;">on</span><span style="color: #000000;">&nbsp;t.CreateBy</span><span style="color: #808080;">=</span><span style="color: #000000;">a.UserId</span></div>
结果:<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">select</span><span style="color: #000000;">&nbsp;a.</span><span style="color: #808080;">*</span><span style="color: #000000;">&nbsp;<br />
</span><span style="color: #0000ff;">from</span><span style="color: #000000;">&nbsp;Sys_User&nbsp;a&nbsp;<br />
</span><span style="color: #0000ff;">inner</span><span style="color: #000000;">&nbsp;</span><span style="color: #808080;">join</span><span style="color: #000000;">(<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">select</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">distinct</span><span style="color: #000000;">&nbsp;Create_By&nbsp;</span><span style="color: #0000ff;">as</span><span style="color: #000000;">&nbsp;CreateBy&nbsp;</span><span style="color: #0000ff;">from</span><span style="color: #000000;">&nbsp;Sys_Org&nbsp;</span><span style="color: #0000ff;">where</span><span style="color: #000000;">&nbsp;Org_Id</span><span style="color: #808080;">=</span><span style="color: #000000;">?<br />
)&nbsp;t&nbsp;</span><span style="color: #0000ff;">on</span><span style="color: #000000;">&nbsp;<span style="color: red;"><span style="color: #000000;"><strong><span style="color: #ff0000;">t.CreateBy</span></strong></span></span></span><span style="color: #808080;">=</span><span style="color: #000000;">a.Usr_Id</span></div>
<br />
case 4: 更复杂一点的情况。一个假想的语句，贫血模型中界面显示经常有类似需求，业务上大致意义可能是: 一个父子关联关系，存在一张表中。按父节点名称模糊查询，显示所有子节点信息，包括父节点名称、子节点的创建用户<br />
进行映射替换时，Name Resolver的决策就比较难<br />
决策过程进入子查询后，遇到2个对象。对于t.ParentName，子查询的select列表指定了别名，所以不应当替换。对于t.CreateBy、t.OrgCode这两个，在子查询中得进行猜测。首先子查询select列表中明确指定的字段里找不到这两个，所以得考察未明确指定列名的地方，只发现一个c.*，所以确定t.CreateBy、t.OrgCode这两个属性一定来自c.*，根据别名c找到Org as c中的Org对象，这两个属性是需要替换为自段名的。<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">select</span><span style="color: #000000;">&nbsp;t.</span><span style="color: #808080;">*</span><span style="color: #000000;">,a.UserName&nbsp;</span><span style="color: #0000ff;">as</span><span style="color: #000000;">&nbsp;CreateUser<br />
</span><span style="color: #0000ff;">from</span><span style="color: #000000;">&nbsp;</span><span style="color: #ff00ff;">User</span><span style="color: #000000;">&nbsp;a<br />
</span><span style="color: #0000ff;">inner</span><span style="color: #000000;">&nbsp;</span><span style="color: #808080;">join</span><span style="color: #000000;">(<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">select</span><span style="color: #000000;">&nbsp;c.</span><span style="color: #808080;">*</span><span style="color: #000000;">,p.OrgName&nbsp;</span><span style="color: #0000ff;">as</span><span style="color: #000000;">&nbsp;ParentName&nbsp;</span><span style="color: #0000ff;">from</span><span style="color: #000000;">&nbsp;Org&nbsp;p,Org&nbsp;</span><span style="color: #0000ff;">as</span><span style="color: #000000;">&nbsp;c<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">where</span><span style="color: #000000;">&nbsp;c.ParentId</span><span style="color: #808080;">=</span><span style="color: #000000;">p.OrgId<br />
)&nbsp;t&nbsp;</span><span style="color: #0000ff;">on</span><span style="color: #000000;">&nbsp;t.CreateBy</span><span style="color: #808080;">=</span><span style="color: #000000;">a.UserId<br />
</span><span style="color: #0000ff;">where</span><span style="color: #000000;">&nbsp;t.ParentName&nbsp;</span><span style="color: #808080;">like</span><span style="color: #000000;">&nbsp;?parent<br />
</span><span style="color: #0000ff;">order</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">by</span><span style="color: #000000;">&nbsp;t.OrgCode</span></div>
结果:<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">select</span><span style="color: #000000;">&nbsp;t.</span><span style="color: #808080;">*</span><span style="color: #000000;">,a.Usr_Name&nbsp;</span><span style="color: #0000ff;">as</span><span style="color: #000000;">&nbsp;CreateUser<br />
</span><span style="color: #0000ff;">from</span><span style="color: #000000;">&nbsp;Sys_User&nbsp;a<br />
</span><span style="color: #0000ff;">inner</span><span style="color: #000000;">&nbsp;</span><span style="color: #808080;">join</span><span style="color: #000000;">(<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">select</span><span style="color: #000000;">&nbsp;c.</span><span style="color: #808080;">*</span><span style="color: #000000;">,p.Org_Name&nbsp;</span><span style="color: #0000ff;">as</span><span style="color: #000000;">&nbsp;ParentName&nbsp;</span><span style="color: #0000ff;">from</span><span style="color: #000000;">&nbsp;Sys_Org&nbsp;p,Sys_Org&nbsp;</span><span style="color: #0000ff;">as</span><span style="color: #000000;">&nbsp;c<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">where</span><span style="color: #000000;">&nbsp;c.Parent_ID</span><span style="color: #808080;">=</span><span style="color: #000000;">p.Org_Id<br />
)&nbsp;t&nbsp;</span><span style="color: #0000ff;">on</span><span style="color: #000000;">&nbsp;<span style="color: #ff0000;"><strong>t.Create_By</strong></span><strong></strong></span><span style="color: #808080;">=</span><span style="color: #000000;">a.Usr_Id<br />
</span><span style="color: #0000ff;">where</span><span style="color: #000000;">&nbsp;<span style="color: #ff0000;"><strong>t.ParentName</strong></span><strong></strong>&nbsp;</span><span style="color: #808080;">like</span><span style="color: #000000;">&nbsp;?parent<br />
</span><span style="color: #0000ff;">order</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">by</span><span style="color: #000000;">&nbsp;<span style="color: #ff0000;"><strong>t.Org_Code</strong></span><strong></strong></span></div>
<br />
完全从语句中确定对象-别名、属性-别名的关系，是不可能的，例如上面case 4中，如果在子查询的select列表里面发现两个*，该如何决策？<br />
方法1: 在语法上做限制，使得通过OQL语句可以明确确定这种关系<br />
方法2: 搜索O-R映射的元数据，进一步分析确认。这一方面要求在应用启动时对所有映射元数据有个整体加载的过程（类似Hibernate的SessionFactory创建时的编译处理），另一方面不同对象上同名属性、不同命名空间下的同名对象，仍然不可避免出现这种问题<br />
方法3: 留下这个空间，交由Client端灵活运用。存在这种问题的地方必须明确指定出选择列表<br />
<br />
从OQL语句里面搜索，试图确定对象、属性、别名之间的关系，这一职责赋给Name Resolver<br />
维护映射信息，确定对象、属性应当映射到哪些表、自段，怎样映射，这一职责由Mapping Resolver/Manager承担<br />
<br />
Name Resolver可以准确做出判断时，告诉Mapping Resolver进行精确的映射处理。当Name Resolver无法决策时，同样将接力棒交给Mapping Resolver，这时Mapping Resolver可以采取一次模糊搜索。例如在一个ObjectQuery范围里面，搜索Attach到这个ObjectQuery的所有Type映射信息(要求用户显示调用ObjectQuery.Attach(Type type, string name)这样的方法，避免对所有元数据的整体加载)；或者加载所有映射元数据，从整个映射元数据中模糊搜索(名字有冲突时误判的可能性比较大，让用户显示Attach将缩小范围，有利于冲突的解决)。<br />
<br />
ObjectQuery可以返回实体对象集合，或者返回一个IList&lt;object&gt;，或者DataTable。NHibernate选择返回IList&lt;object&gt;倒是可以省却一件事情，因为如果返回DataTable，对每个返回字段，需要有个名字对应，而不光是索引访问。上面看到，执行查询的时候，属姓名已经被替换为字段名，如果就这样返回DataTable，提供的这个功能就别扭了。首先查询语句里面写的是对象、属性名，而返回的DataTable中却是数据库字段名，使用这个DataTable的时候还是用数据库字段名访问？<br />
所以如果选择返回DataTable，最好的方式是，Mapping Resolver将语句中的对象、属性替换为数据库的表名、字段名，这样才能执行这个SQL查询。但对于select列表，还得以别名、属性名方式返回，尤其是对于select a.*, b.*这样的情况，Name Resolver需要找出a, b具体是什么对象，由Mapping Resolver找出这些对象有哪些属性名，考虑到子查询等各种情况，情况很复杂。<br />
所以简单的选择，还是返回IList&lt;object&gt;。<br />
<br />
更复杂的情况，就是实体间的关联关系，体现在OQL中，同样要求Name Resolver与Mapping Resolver之间的协同工作。<br />
结果：<br />
Name Resolver与Mapping Resolver之间的协同比较多，从交互机制上看关联关系比较强；但它们拥有完全不同的专业知识，在不同的领域上工作，所以要求良好的分离。<br />
<img src ="http://www.cnblogs.com/RicCC/aggbug/1102950.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41919/" target="_blank">[新闻]诺基亚新机N85 N79发布</a>]]></description></item><item><title>ANTLR实现的SQL解析器 - OQL</title><link>http://www.cnblogs.com/RicCC/archive/2008/03/09/OQL-ANTLR-SQL-Parser.html</link><dc:creator>RicCC</dc:creator><author>RicCC</author><pubDate>Sat, 08 Mar 2008 22:22:00 GMT</pubDate><guid>http://www.cnblogs.com/RicCC/archive/2008/03/09/OQL-ANTLR-SQL-Parser.html</guid><wfw:comment>http://www.cnblogs.com/RicCC/comments/1097060.html</wfw:comment><comments>http://www.cnblogs.com/RicCC/archive/2008/03/09/OQL-ANTLR-SQL-Parser.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cnblogs.com/RicCC/comments/commentRss/1097060.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/RicCC/services/trackbacks/1097060.html</trackback:ping><description><![CDATA[OQL<br />
使用ANTLR写了个SQL解析器，这样ORM的基本功能就比较完整了。几天的时间比较仓促，所以对于最终目标，还只能算是个雏形。<br />
<br />
<strong>总体状况</strong><br />
使用SQL解析器的主要优点:<br />
1. 基于解析之后的语法树提供用户操作接口，灵活性非常好，因为达到了对SQL每一部分的完整控制。<br />
2. 对数据库的适应性。<br />
&nbsp;&nbsp; 首先可以采用标准SQL，以及部分封装好的特性(例如分页)、函数(例如主要数据库都支持的函数，但语法有一定差异的)，使用一个适配器Dialect基于语法树进行翻译。这样能满足绝大部分用途。<br />
&nbsp;&nbsp; 如果确实需要使用某数据库的特性，可能只需要修改语法描述文件就能实现，或者对语法树等作少量修改进行配合。<br />
3. 跟LINQ的比较。<br />
&nbsp;&nbsp; a. LINQ具备编译期检查，与VS整合的优点。<br />
&nbsp;&nbsp; b. 根据粗略的了解，感觉LINQ语法树操作起来比较繁琐。<br />
&nbsp;&nbsp; c. 自己完全把握住了整个解析过程，不会受LINQ语法和语法树的限制。<br />
&nbsp;&nbsp; d. 不了解LINQ语法树的开放性，即结构的稳定、兼容性。例如以后添加新的特性，是否会影响到语法树的结构？<br />
&nbsp;&nbsp; 类似LINQ to Hinbernate一样，只将LINQ当作查询的输入，而使用自己的ORM实现持久化，中间的可控能力会比较强。虽然LINQ与OQL在功能上重合，只是各有优缺点而已，并且可以采用不错的结合点。<br />
<br />
目前的主要缺点:<br />
1. 基于SQL Server的语法。<br />
2. AST语法树看起来以及实现上不大流畅，表达式类体系结构理的不大清楚。<br />
3. 数据库Dialect的机制不好。<br />
<br />
以后的目标:<br />
1. 多数据库支持。<br />
&nbsp;&nbsp; 不管是纯粹ORM操作，还是OQL或者SQL，都能由数据库dialect自动翻译。<br />
2. 语法: 基于标准DML语法，添加必要的特性。<br />
&nbsp;&nbsp; a. 分页，预计使用select distinct? range(start, end) column1, column2..这样的方式，由数据库dialect向各特定数据库SQL语法进行翻译。SQL Server 2000这种不完整支持的，由dialect辅助完成。<br />
&nbsp;&nbsp; b. 标准函数，常用的SQL 92标准函数应当都能向各个数据库进行翻译，还可以提取一些其它函数，主流数据库都支持且能够进行翻译的。<br />
3. 标准化Query Hints。<br />
&nbsp;&nbsp; 目的是在OQL中提供一个性能调优的机会，针对主要Query Hints进行提取，由dialect翻译成各数据库特定语法。<br />
4. Object Query / 标准SQL Query功能。<br />
&nbsp;&nbsp; a. 不象Hibernate要求纯粹的对象模型，OQL使用DomainClass1 inner join DomainClass2 on ...这样的方式。缺点是对象模型的内部结构被暴露，但更具灵活性。以后考虑对对象模型的自动支持，也就是可以使用各种混合方式进行开发。还允许DomainClass和Database Table混合写在OQL中，用于满足类似many-to-many的关联表不会建立DomainClass，又不想用对象属性建立双向映射关系的情况。<br />
&nbsp;&nbsp; b. 程序先给出查询语句，OQL解析出语法树，基于语法树再动态修改，例如根据界面的选择添加查询条件、排序方式、需要的字段等。进一步，一些非必要的关联关系能够在运行时自动、动态确定。<br />
&nbsp;&nbsp; c. 基于语法树进行修改的灵活性，应当能够提供比较灵活的AOP功能，例如AOP方式的数据权限控制。<br />
<br />
下一步代办事项:<br />
1. 项目中将用户接口和必要的功能特性进行完善。<br />
2. 语法树结构的完善，表达式类体系的完善，数据库Dialect、O-R Mapping等与OQL结合的机制以及职责的梳理完善。<br />
3. 标准化，主流数据库Dialect。<br />
4. 语法优化（重点是解析性能）。<br />
<br />
<strong>目前语法大致描述:</strong><br />
Statement: SelectStatement | UnionStatement | InsertStatement | UpdateStatement | DeleteStatement;<br />
SelectStatement: SelectClause FromClause? WhereClause? (GroupByClause Having?)? OrderByClause?;<br />
<br />
SelectClause: Columns+;<br />
Column: '*'? | Identifier '.*' <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Expressions Alias? <br />
//MathOperator为数学运算符，例如+, -, *, /, %<br />
Expressions: Expression (MathOperator Expression)*;<br />
//Identifier为字段/属性名，Constant为常量，包括系统变量例如@@identity之类以及字符串等<br />
//Case .. When 语句当作Function处理<br />
Expression: Identifier | Constant | UserVariable | Function | SelectStatement | UnionStatement;<br />
<br />
//Where子句采用较标准的运算语法树形式，类EBNF描述<br />
WhereClause: Condition;<br />
Condition: SubCondition ((AND ^ | OR ^) SubCondition)*<br />
SubCondition: '(' Condition ')' | Predicate;<br />
Predicate: Expressions (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ComparisonOperator Expressions //ComparisonOperator为&gt;, &lt;=, !&gt;, Like等比较运算符<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | IS NOT? NULL<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | IN '(' Expressions (',' Expressions)* ')'<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | BETWEEN Expressions AND Expressions<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | IN '(' (SelectStatement | UnionStatement) ')'<br />
&nbsp;&nbsp;&nbsp; ) | <br />
&nbsp;&nbsp;&nbsp; EXISTS '(' (SelectStatement | UnionStatement) ')';<br />
<br />
整体:<br />
&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/OQL/oql_syntax_tree_overview.jpg" /><br />
<br />
Select子句:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Where子句:<br />
&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/OQL/syntax_tree_select.jpg" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<img alt="" src="http://www.cnblogs.com/images/cnblogs_com/riccc/OQL/syntax_tree_where.jpg" /><br />
<br />
<strong>解析性能测试:</strong><br />
下面这个SQL应该能够代表绝大部分普通查询情况，循环解析1000次，所用时间在480-600ms之间。其中{0}, {1}是在循环中替换为当前计数，使每次解析的SQL不一样。这样普通情况下，把解析后的语法树进行缓存已经没有太多必要。<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">Select</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000; font-weight: bold;">12</span><span style="color: #000000;">,&nbsp;</span><span style="color: #ff0000;">'</span><span style="color: #ff0000;">ada&nbsp;{0}&nbsp;And&nbsp;&gt;0""</span><span style="color: #ff0000;">'</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">As</span><span style="color: #000000;">&nbsp;c1,&nbsp;(</span><span style="color: #0000ff;">select</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000; font-weight: bold;">1</span><span style="color: #000000;">),&nbsp;</span><span style="color: #008000;">@UserName</span><span style="color: #000000;">,&nbsp;</span><span style="color: #ff00ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">when</span><span style="color: #000000;">&nbsp;a</span><span style="color: #808080;">=</span><span style="color: #800000; font-weight: bold;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">then</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000; font-weight: bold;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000; font-weight: bold;">0</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">end</span><span style="color: #000000;">,&nbsp;</span><span style="color: #ff00ff;">sum</span><span style="color: #000000;">(a)&nbsp;</span><span style="color: #0000ff;">as</span><span style="color: #000000;">&nbsp;Total<br />
</span><span style="color: #0000ff;">From</span><span style="color: #000000;">&nbsp;Sys_User&nbsp;a,&nbsp;Sys_Org&nbsp;b<br />
</span><span style="color: #0000ff;">inner</span><span style="color: #000000;">&nbsp;</span><span style="color: #808080;">join</span><span style="color: #000000;">&nbsp;Sys_Org_View&nbsp;c&nbsp;</span><span style="color: #0000ff;">on</span><span style="color: #000000;">&nbsp;c.Org_Id</span><span style="color: #808080;">=</span><span style="color: #000000;">b.Org_Id&nbsp;</span><span style="color: #808080;">and</span><span style="color: #000000;">&nbsp;(ccc</span><span style="color: #808080;">=</span><span style="color: #000000;">{</span><span style="color: #800000; font-weight: bold;">1</span><span style="color: #000000;">})<br />
</span><span style="color: #0000ff;">Where</span><span style="color: #000000;">&nbsp;</span><span style="color: #ff00ff;">cast</span><span style="color: #000000;">(a.</span><span style="color: #ff00ff;">User_Id</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">as</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">varchar</span><span style="color: #000000;">)</span><span style="color: #808080;">=</span><span style="color: #000000;">b.</span><span style="color: #ff00ff;">User_Id</span><span style="color: #000000;">&nbsp;</span><span style="color: #808080;">or</span><span style="color: #000000;">&nbsp;(a</span><span style="color: #808080;">=</span><span style="color: #000000;">b&nbsp;</span><span style="color: #808080;">and</span><span style="color: #000000;">&nbsp;Total&nbsp;</span><span style="color: #808080;">between</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000; font-weight: bold;">100</span><span style="color: #000000;">&nbsp;</span><span style="color: #808080;">And</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000; font-weight: bold;">1000</span><span style="color: #000000;">)<br />
</span><span style="color: #0000ff;">Group</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">bY</span><span style="color: #000000;">&nbsp;a,&nbsp;b<br />
</span><span style="color: #0000ff;">haViNg</span><span style="color: #000000;">&nbsp;Total&nbsp;</span><span style="color: #808080;">between</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000; font-weight: bold;">100</span><span style="color: #000000;">&nbsp;</span><span style="color: #808080;">And</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000; font-weight: bold;">1000</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">Order</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">By</span><span style="color: #000000;">&nbsp;a,&nbsp;DDD&nbsp;</span><span style="color: #0000ff;">Desc</span><span style="color: #000000;">,&nbsp;A&nbsp;</span><span style="color: #0000ff;">asc</span></div>
<br />
<img src ="http://www.cnblogs.com/RicCC/aggbug/1097060.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41918/" target="_blank">[新闻]数据库市场:微软和甲骨文快速进步 威胁IBM</a>]]></description></item></channel></rss>