﻿<?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>BlogJava-人在江湖-随笔分类-design</title><link>http://www.blogjava.net/vcycyv/category/47959.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 06 May 2011 18:19:53 GMT</lastBuildDate><pubDate>Fri, 06 May 2011 18:19:53 GMT</pubDate><ttl>60</ttl><item><title>XML的滥用</title><link>http://www.blogjava.net/vcycyv/archive/2011/05/07/349720.html</link><dc:creator>人在江湖</dc:creator><author>人在江湖</author><pubDate>Fri, 06 May 2011 16:22:00 GMT</pubDate><guid>http://www.blogjava.net/vcycyv/archive/2011/05/07/349720.html</guid><wfw:comment>http://www.blogjava.net/vcycyv/comments/349720.html</wfw:comment><comments>http://www.blogjava.net/vcycyv/archive/2011/05/07/349720.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vcycyv/comments/commentRss/349720.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vcycyv/services/trackbacks/349720.html</trackback:ping><description><![CDATA[<p>XML曾经很火，什么技术只要跟XML沾边儿就顶上“标准”的光环，后来大家慢慢意识到XML的种种弊端，比如差劲的表达能力，枯燥的解析（SAX），性能低下（DOM），越来越多的人开始理智地使用XML。只把它用在“合适”的时候。程序员中仍然存在滥用XML的惯性，最近还和同事们争论了半天java和xml的使用场景。</p> <p>先跑下题聊聊java. 近两年越来越多搞Java的人跑去学动态语言，ruby, groovy, scala之类的。 原因在于这些动态语言“表达能力”更好。是的，这些语言更灵活，更精炼。不难理解，后出的编程语言更倾向于合理，毕竟它有前人的宝贵经验可以借鉴。java的一些设计的确令人诟病，比如checked exception, 对泛型支持的不完备。但就从“表达力”来说，<strong>我觉得java的表达力不强不弱正正好好。Java的定位本来就是大规模企业级应用，过度灵活的编程语言不易维护。</strong>新型的动态语言倾向于过度灵活，虽然支持快速开发，但是我相信在多人，甚至几十人合作开发的项目中，如果对语言非常灵活的特性不加以限制，随着程序的规模一点点增大，维护的难度会陡然加大。而一旦通过convention限制使用语言的一些特性，限制来限制去不就又成java了么？好吧，好吧，我知道这会是个有争议的话题，我就是不相信用ruby能做个ERP出来，五年之后也不会有。这不是这篇文字要讨论的重点，我想说的是，java在表达能力方面已经让一些人不满意了，而XML呢？XML的表达能力比java差了N多个数量级！这年头，骑三轮车回收电脑的都知道程序设计要有弹性，换句话说，能适应变化。于是一个简单的梦想就是，来了新需求，咱不用改code, 改改xml配置就能满足就好了。是的，我也这么希望，尤其在我睡着的时候。以Java这样的面向对象 + 一些动态特性（reflection，dynamic proxy甚至aspectJ）的语言都很难做到如此灵活的应对变化，xml怎么会更容易做到呢？很多人喜欢XML的简单直观。比如我们可以在SWING上面封装一层基于XML的界面引擎，于是GUI就可以简单地写成这种风格：</p> <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">panel</span> <span style="color: #ff0000">id</span>=”<span style="color: #ff0000">xyz</span>” <span style="color: #ff0000">width</span>=”<span style="color: #ff0000">360</span>” <span style="color: #ff0000">heigh</span>=”<span style="color: #ff0000">720</span>”……<span style="color: #0000ff">&gt;</span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span>&nbsp; </pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">label</span> <span style="color: #ff0000">id</span>=”<span style="color: #ff0000">label_1</span>” <span style="color: #ff0000">attr_1</span>=”<span style="color: #ff0000">xxx</span>” <span style="color: #ff0000">attr_2</span>=”<span style="color: #ff0000">yyy</span>”<span style="color: #0000ff">/&gt;</span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>&nbsp; </pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">textarea</span> <span style="color: #ff0000">id</span>=”<span style="color: #ff0000">textarea_1</span>” <span style="color: #ff0000">attr_1</span>=”<span style="color: #ff0000">xxx</span>” <span style="color: #ff0000">attr_2</span>=”<span style="color: #ff0000">yyy</span>”<span style="color: #0000ff">/&gt;</span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>&nbsp; </pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">panel</span><span style="color: #0000ff">&gt;</span></pre><!--CRLF--></div></div>
<p></p>
<p>它有一个好处就是易于扩展，比如现在又想加一个checked box,只要在里面插入一个&lt;checkbox id=……/&gt;就行了。我承认它的确易于扩展。但是如果你简单封装一下java API，不也是一行code的事儿么？无非就是panel.addChild(new CheckedBox(attr_1, attr_2))之类的这么一句code。难道这就不简单，不直观了？程序一涉及到xml,就涉及到IO, 解析XML，这都是额外的工作量，况且xml中的“对象”（我很难承认complex type算是对象）跟Java里的对象根本不是一码事，从xml里解析出来的表示数据类型的type最后还是要生成对应特定的java对象，这都是麻烦事儿。 多写code的坏处远不止写的时候费事儿，所写的每行code最后都是要维护的，就算code很strong, 我还嫌code太长，滚鼠标滚轮儿累手指头，多个文件放那儿累花眼。<strong>总之，但凡xml改一两行能解决的问题，不用xml,就用java也是一两行的工作量，只要稍微花点心思封装好API就行。</strong>不用XML可以省不少开发和维护的工作。理想情况下，改改xml就能应对新需求。但现实和理想总是有差距的，一旦xml的schema不足以应对变化，我们就得改xml, 改schema，改解析的code，改业务逻辑的code（这个没法避免）。这不是没事儿找病么？<strong>xml是extendable markup language. 它真能比java还extendable？</strong>扯淡！</p>
<p>当然XML有它合理的应用场景，我能想到的是四个方面，一定有漏掉的情况，欢迎朋友们补充。</p>
<p>一， 存储树状数据（起码三层以上。三层或三层以下就用java合成也挺方便的）；二， 配置信息；三、描述标准协议（比如wsdl）； 四，wrap数据以便于传输等(比如soap)</p>
<p><strong>在应用产品中，自己设计xml来辅助应用系统的场景不应该很多。</strong></p>
<p>另有一种使用xml的误区是，把xml暴露给用户让他自己“扩展”。我觉得， 凡是暴露给客户的东西都是UI，平时Swing界面，web界面是GUI，暴露给客户改的xml算是UI. 也许有的人说，一旦弄GUI，就有一堆麻烦事儿，比如i18n啥的，让用户自己配置配置xml就能改动页面不是挺好么，还不用考虑i18n了。问题是，用xml不是“不用”考虑国际化，而是根本没法考虑国际化。</p>
<p>&lt;wallet&gt;&lt;money&gt;100&lt;/money&gt;&lt;/wallet&gt; 这个美国人能看懂，对中国人就得用&lt;钱包&gt;&lt;钱&gt;100&lt;/钱&gt;&lt;/钱包&gt;</p>
<p>这么做很明显用户体验很差。另外，这也一定程度上暴露了你的实现方式，起码客户知道，哦，原来你是用xml存数据的，schema就是这个样子。</p>
<p>Ajax刚铺天盖地的时候，都用xml传数据，后来越来越多人用Json. Spring和Hibernate等一堆框架在几年前都用巨大的XML来配置，现在越来越多人转向annotation(当然，这个有一定争议)。XML热度减退，大家趋于理性是好事。XML当然很有用，但是程序员们该能想清楚什么是"使用", 什么是"滥用". </p><img src ="http://www.blogjava.net/vcycyv/aggbug/349720.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vcycyv/" target="_blank">人在江湖</a> 2011-05-07 00:22 <a href="http://www.blogjava.net/vcycyv/archive/2011/05/07/349720.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>总结Domain Driven Design领域驱动设计 认识DDD</title><link>http://www.blogjava.net/vcycyv/archive/2011/03/21/346654.html</link><dc:creator>人在江湖</dc:creator><author>人在江湖</author><pubDate>Sun, 20 Mar 2011 16:26:00 GMT</pubDate><guid>http://www.blogjava.net/vcycyv/archive/2011/03/21/346654.html</guid><wfw:comment>http://www.blogjava.net/vcycyv/comments/346654.html</wfw:comment><comments>http://www.blogjava.net/vcycyv/archive/2011/03/21/346654.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vcycyv/comments/commentRss/346654.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vcycyv/services/trackbacks/346654.html</trackback:ping><description><![CDATA[<p>就好像第一次读effective java才意识到什么叫做代码质量；第一次接触到Domain Driven Design才开始认识什么是design。在之前的博客， <a href="http://www.blogjava.net/vcycyv/archive/2011/02/14/344298.html"><font color="#0000ff">分享十二本经典电子书，涉及java, OO design, spring, hibernate,struts2, agile</font></a> 中，有DDD书的下载。</p> <p>Domain Driven Design基于一些简单，重要，务实的理念。下面根据自己的理解总结DDD的基本理论。</p> <p>1. 深刻理解Domain知识</p> <p>DDD强调基于domain进行设计。前提是深刻理解领域知识，需要持续学习。另一个相关的实践是，“统一的语言”（ubiquitous language）。领域专家所用的术语是准确的，那么程序员讨论domain相关的问题时，也应该使用这种术语。并且在写code的时候，也使用这种术语。这样做的好处是，可以自然地把domain的东西map到code里，保持code反应domain。</p> <p>&nbsp;</p> <p>2. 分层</p> <p><a name="ch04lev1sec1"></a> <h5>Layered Architecture</h5> <p><a href="http://www.blogjava.net/images/blogjava_net/vcycyv/WindowsLiveWriter/DomainDrivenDesignDDD_D993/image_2.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.blogjava.net/images/blogjava_net/vcycyv/WindowsLiveWriter/DomainDrivenDesignDDD_D993/image_thumb.png" width="405" height="382"></a>  <p>&nbsp; <p></p> <p></p> <p></p> <p>程序需要分层，这是个简单的道理, 但需要真正形成意识。</p> <p>分别说说Domain Driven Design涉及的四个layer.</p> <p>2.1 Infrastructure层</p> <p>主要从技术上对上面的各层提供支持。比如传送消息，持久化。UI层也可以分出更基础的component作为infrastructure层</p> <p>2.2 UI层</p> <p>UI层的作用是显示信息以及解释用户的输入命令。重要的是UI层没有domain knowledge.</p> <p>2.3 application层</p> <p>application层的作用是描述产品的外部功能，它可以协调UI和Domain层的互动。<strong>application层应该很薄</strong>。它没有domain knowledge.</p> <p>2.4 Domain层</p> <p>Domain层是最重要的层。封装所有的业务逻辑。</p> <p>&nbsp;</p> <p>DDD也从另一个角度分解软件。一个软件的组成部分（building block）包括association, entity, value object, service, module。其中比较强调的是entity, value object和service. service比较容易理解，通常它是无状态的。它可以存在于application层，domain层或者infrastructure层。比较不容易区分的是entity和value object. entity强调的是它的id，而不是属性。强调它生命周期的继续性和同一性(continuity and identity), 而<strong>value object是用来“描述”entity的</strong>。value object在很多时候适合是immutable的。这里需要注意的是，如果你会使用hibernate,你会知道hibernate里的value object通常不能reference多个entity，换句话说，能reference多个entity的，通常就是entity.&nbsp; 而在DDD的理论中，"路线"是一个value object。而它可以reference连接"路线"的city(entity)和高速公路(entity)。</p> <p>&nbsp;</p> <p>3. Domain Object生命周期</p> <p>DDD的一个重要理论是关于aggregate. domain object之间的关系如果非常复杂，在domain knowledge涉及比较复杂的rule的时候，容易造成不一致的情况。解决办法是，把一些domain object放一个组里，让某个domain object作为根（aggregate root）, 所有对这些domain object的访问都要通过这个aggregate, 那么维持一致性的工作，就限制在这个aggregate root里了。</p> <p><a href="http://www.blogjava.net/images/blogjava_net/vcycyv/WindowsLiveWriter/DomainDrivenDesignDDD_D993/image_4.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.blogjava.net/images/blogjava_net/vcycyv/WindowsLiveWriter/DomainDrivenDesignDDD_D993/image_thumb_1.png" width="753" height="322"></a> </p> <p>&nbsp;</p> <p>另一个相关理论是factory和repository. factory是用来“创建”对象的，是一个从无到有的过程。而repository是用来retrieve对象的，也就是说，对象客观存在，只是没有放在内存中，repository就是把数据从某个地方（通常是数据库）拿出来，construct成对象的。一个常见的设计是，让repository暴露retrieve和create的api，但是create的具体工作代理给factory来做，也就是说，factory通常被聚合在repository中。</p><img src ="http://www.blogjava.net/vcycyv/aggbug/346654.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vcycyv/" target="_blank">人在江湖</a> 2011-03-21 00:26 <a href="http://www.blogjava.net/vcycyv/archive/2011/03/21/346654.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Domain Driven Design and Development In Practice（转）</title><link>http://www.blogjava.net/vcycyv/archive/2011/03/05/345787.html</link><dc:creator>人在江湖</dc:creator><author>人在江湖</author><pubDate>Sat, 05 Mar 2011 08:28:00 GMT</pubDate><guid>http://www.blogjava.net/vcycyv/archive/2011/03/05/345787.html</guid><wfw:comment>http://www.blogjava.net/vcycyv/comments/345787.html</wfw:comment><comments>http://www.blogjava.net/vcycyv/archive/2011/03/05/345787.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vcycyv/comments/commentRss/345787.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vcycyv/services/trackbacks/345787.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 转载自： Domain Driven Design and Development In Practice 好长的一篇文章，从头到尾读了一遍，写的挺好，以后有时间再读一遍，一些提到的内容，比如Dozer并不了解，有时间了解一下！ Background Domain Driven Design (DDD) is about mapping business domain concepts into ...&nbsp;&nbsp;<a href='http://www.blogjava.net/vcycyv/archive/2011/03/05/345787.html'>阅读全文</a><img src ="http://www.blogjava.net/vcycyv/aggbug/345787.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vcycyv/" target="_blank">人在江湖</a> 2011-03-05 16:28 <a href="http://www.blogjava.net/vcycyv/archive/2011/03/05/345787.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>On domain-driven design, anemic domain models, code generation, dependency injection and more&amp;hellip;（转）</title><link>http://www.blogjava.net/vcycyv/archive/2011/03/01/345448.html</link><dc:creator>人在江湖</dc:creator><author>人在江湖</author><pubDate>Tue, 01 Mar 2011 14:39:00 GMT</pubDate><guid>http://www.blogjava.net/vcycyv/archive/2011/03/01/345448.html</guid><wfw:comment>http://www.blogjava.net/vcycyv/comments/345448.html</wfw:comment><comments>http://www.blogjava.net/vcycyv/archive/2011/03/01/345448.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/vcycyv/comments/commentRss/345448.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/vcycyv/services/trackbacks/345448.html</trackback:ping><description><![CDATA[<p>这是一篇质疑DDD的好文，后面也贴了一个回复，原文链接：<a title="http://techblog.bozho.net/?p=180" href="http://techblog.bozho.net/?p=180">http://techblog.bozho.net/?p=180</a></p> <p>Eric Evans has formulated what domain-driven design (DDD) is. Martin Fowler is a great supporter and advocate of DDD. These are remarkable names and it is almost certain they are supporting something worth. And I’m not here to argue with that. Maybe I’m trying to justify the way I’ve been writing software, or maybe I’m trying just to clear things and be constructive. Let’s see. <p>What is at the core of domain-driven design – the abstract notions of the <em>domain</em>, the <em>domain model</em>, the <em>ubiquitous language</em>. I’ll not go into details with that – for those interested there is wikipedia (with lots of references to read in the footer). This is all very good in theory, and the domain-driven way of building software should appeal to everyone – after all that software is being built for the benefit of that domain, not for the benefit of architects, developers or QAs. <p>But now comes the practical part – how to implement DDD? I’ll answer that question in its contemporary context – that is, using frameworks like spring and hibernate. And I’ll justify their usage. Spring is a non-invasive dependency-injection framework. DI is also strongly supported by Fowler, and is considered a good way to implement DDD. Hibernate is one way to use objects when working with a relational database. Another way is to use JDBC and construct the objects manually, but that is tedious. So hibernate doesn’t influence the architecture part – it is an utility (very powerful one, of course). <p>Throughout this post I’ll use hibernate and spring as “given”, although they may be changed with any DI framework and any ORM or other persistence mechanism that relies on objects. <p>The accepted way to implement DDD with spring and hibernate is: <ul> <li>use <code>@Configurable</code> to make the domain objects eligible for dependency injection (they are not instantiated by spring, so they need this special approach)  <li>inject repository objects in the domain objects in order to allow the domain objects to do persistence-related operations  <li>use a thin, stateless, transactional service layer (a facade) to coordinate the domain objects</li></ul> <p>Implementation and description of this approach is shown in <a href="http://www.infoq.com/articles/ddd-in-practice">this extensive article</a>. Another example (without spring) is <a href="http://techblog.bozho.net/this sample project">http://dddsample.sourceforge.net/</a>. I’ll discuss both later. <p>The alternative to this approach is the <a href=" http://martinfowler.com/bliki/AnemicDomainModel.html">anemic domain model</a>. It is considered an anti-pattern, but at the same time is very common and often used. The features of the anemic data model are simple – the domain objects have no business logic inside them – they are only data holders. Instead, the business logic is placed in services. <p>The reason this is considered an anti-pattern is because, first, this seems like a procedural approach. It is breaking the encapsulation, because the internal state of the object is, well, not internal at all. Second, as the domain object is the center of the design, it is harder to change it if its operations don’t belong to it, but to a number of stateless service classes instead. And domain-driven design is aimed at medium-to-large scale applications, which change a lot and need an easy way to make changes fast, without breaking other functionality. Thus it is important to have all the functionality of the object within the object itself. This also makes sure that there is less duplication of code. <p>So, instead of having a service calculate the price: <code>ProductServiceImpl.calculatePrice(complexProduct)</code> we should simply have <code>ComplexProduct.calculatePrice()</code>. And so whenever the <em>domain experts</em> say that the price calculation mechanism changes, the place to change it is exactly one and is the most straightforward one. <p>When simple operations are regarded, this looks easy. However, when one domain objects needs another domain object to do its job, it becomes more complicated. With the anemic data model this is achieved by simply injecting another Service into the current one and calling its methods. With the proposed DDD it is achieved by passing domain objects as arguments. <p>In my view, the domain object, which is also the hibernate entity, has its dependencies already set. But not by spring, because spring can’t know which exactly domain object to inject. They are “injected” by hibernate, because it knows exactly which (identified by primary key) domain object should be placed in another domain object. So, a little odd example – if a <code>Product</code> has rotten and has to dispense smell in the warehouse, it has to call, for example, <code>warehouse.increaseSmellLevel(getSmellCoeficient())</code>. And it has its precise <code>Warehouse</code> without any interference from spring. <p>Now, here comes another point where I disagree. Most sources (including the two linked above) state that repositories / DAOs should be injected in the domain objects. No, they shouldn’t. Simply calling “save” or “update” doesn’t require knowledge of the internal state of the object. Hibernate knows everything anyway. So we are just passing the whole object to the repository. <p>Let’s split this in two – <em>business logic</em> and <em>infrastructure logic</em>. The domain object should not know anything of the infrastructure. That might mean that it should not know it is being saved somewhere. Does a product care of how it is stored ? No – it’s the storage mechanism that’s “interested”. And here are the practical disadvantages: <ul> <li>CRUD is implemented by simply wrapping repository calls in all domain objects – duplication of code  <li>the domain object is transitively dependent on persistence – i.e. it is not a pure domain object, and if repositories change, it has to be changed as well. And in theory it should be changed only when the domain rules and attributes change  <li>people will be tempted to include transaction, caching and other logic inside the domain object</li></ul> <p>I’ll open a bracket here about a proposed solution in one of the above articles for making duplication of code, and boilerplate code easier to handle. Code generation is suggested. And I think code-generation is a sin. It moves the inability to get rid of duplicated or very similar code and abstract it, to tools. The most striking example is generating ProductDAO, CategoryDAO, WarehouseDAO, etc, etc. Generated code is hard to manage, cannot be extended and relies heavily on external metadata, which is definitely not an object-oriented approach. <p>Speaking of the repository, in the proposed examples each domain object should have a repository, which in turn will call the persistence mechanism. What do we get then: <p>User presses “save” in the UI &gt; UI calls save on the service (in order to have transaction support) &gt; Service calls save on the domain object &gt; domain object calls save on the repository &gt; the repository calls save on the persistence mechanism &gt; the persistence mechanism saves the object. <p>Is it just me, or calling the domain object is redundant here. It is a pass-through method that adds nothing. And since a lot of functionality is related to CRUD (yes, even in big business applications), this looks quite bad to me. <p>And finally, I find the <code>@Configurable</code> approach a hack. It does some magic in the background, which isn’t anything of the common language features (and is not a design pattern), and in order to understand how it happens you need a great deal of experience. <p>So, to summarize the big mess above <ul> <li>domain objects should not be spring (IoC) managed, they should not have DAOs or anything related to infrastructure injected in them  <li>domain objects have the domain objects they depend on set by hibernate (or the persistence mechanism)  <li>domain objects perform the business logic, as the core idea of DDD is, but this does not include database queries or CRUD – only operations on the internal state of the object  <li>there is rarely need of DTOs – the domain objects are the DTOs themselves in most cases (which saves some boilerplate code)  <li>services perform CRUD operations, send emails, coordinate the domain objects, generate reports based on multiple domain objects, execute queries, etc.  <li>the service (application) layer isn’t that thin, but doesn’t include business rules that are intrinsic to the domain objects  <li>code generation should be avoided. Abstraction, design patterns and DI should be used to overcome the need of code generation, and ultimately – to get rid of code duplication.</li></ul> <p>&nbsp;</p> <p>=================================================</p> <p>一个有见地的回复：</p> <p>For one I think that technical issues should be separated from the functional domain. That means that domain objects should not be polluted by (technical) annotations or persistence methods (seperation of concerns). Dependency Injection (technical) should be outside the core domain. Persistence methods should be in a repository gateway, which (at least the interface, functional) is part of the domain. You know that you have a repository (functiuonal, within the domain), but not the way it’s implemented (technical). That’s outside the domain.  <p>Just as the services (functionality) which calls them are part of the domain. These services are called from the user interface or other components outside this particular domain. <p>Transactional boundaries and session management is not domain functionality and should be outside the domain in a separate (thin) layer, which calls the services or domain objects within the domain. <p>DTO’s are useful for communicating outside the domain. In simple applications (with session management in the UI) the DO’s can be used, but I would not recommend it. I prefer the use of DTO’s which are assembled within the transaction boundary, and can be used outside the transaction (and session) boundary as to avoid potential LazyInitializationExceptions, which I am, unfortunately, very familiar with.  <p>Dependency injection should not be in Domain Objects. If you want to use something like the AgeCalculator mentioned above, just call the user.getAge() method wich Alex suggested. <p>This method contains something like <p>class User {<br>public int getAge() {<br>AgeFactory.getInstance().getAgeCalculator().calculateAge(this);<br>}<br>} <p>The AgeFactory is a singleton, which has the correct calculator injected. You can use Spring for that. <p>class AgeFactory {<br>AgeFactory instance = new AgeFactory(); <p>AgeCalculator ageCalculator = null; <p>public AgeFactory getInstance() {<br>return instance;<br>} <p>public void setAgeCalculator(AgeCalculator ageCalculator) {<br>this.ageCalculator = ageCalculator;<br>} <p>public AgeCalculator getAgeCalculator() {<br>return this.ageCalculator;<br>}<br>} <p>The implementation of the repository gateway objects can be done in the same way.  <p>Usage of the repository (in a service) can be something like this <p>class ServiceImpl implements Service {<br>public void save(User user) {<br>RepositoryFactory.getInstance().getUserRepository().save(user);<br>}<br>} <p>These factories must be within the domain, because the domein objects must use them. But the dependency injection of these factories can be done outside the core domain (if you don’t use annotations). This way the core functional domain is not polluted with the technical issues of dependency injection.  <p>Finally about annotations, I hate them, because it’s a magic black box. I rather use xml configuration files because they are probably easier to understand. Furthermore without annotations you can have the configuration files outside the core domain, and can use mock objects which are created and set on the factory without dependency injection within testcases. You can even choose to use dependency injection within part of the unit tests and without DI in other unit tests.</p><img src ="http://www.blogjava.net/vcycyv/aggbug/345448.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/vcycyv/" target="_blank">人在江湖</a> 2011-03-01 22:39 <a href="http://www.blogjava.net/vcycyv/archive/2011/03/01/345448.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>