﻿<?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-桃之夭夭-随笔分类-ThoughtBlog</title><link>http://www.blogjava.net/raimundox/category/5773.html</link><description>知天之所为，知人之所为者，至矣。知天之所为者，天而生也；知人之所为者，以其知之所知以养其知之所不知，终其天年而不中道夭者：是知之盛也。</description><language>zh-cn</language><lastBuildDate>Mon, 20 Jul 2009 10:18:10 GMT</lastBuildDate><pubDate>Mon, 20 Jul 2009 10:18:10 GMT</pubDate><ttl>60</ttl><item><title>Add primitive Progression Enhancement support of  Rails</title><link>http://www.blogjava.net/raimundox/archive/2009/03/18/260475.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Wed, 18 Mar 2009 06:38:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2009/03/18/260475.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/260475.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2009/03/18/260475.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/260475.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/260475.html</trackback:ping><description><![CDATA[<div>Currently the concept of Progressive Enhancement is getting hotter and hotter. It emphasizes accessibility, semantic markup, and the importance of separating the complex rich interaction logic into well modularized javascript files. It's really a usefully way of thinking about how to modularize and manage web presentation components. But the Rails framework doesn't have good support for PE, so we have to define our own convention and helpers to make our life easier.</div>
<div><br />
</div>
<div>Usually, I'd like to organize js files in the Rails convention, which means we'll have something like this:</div>
<div><br />
</div>
<div>app</div>
<div>&nbsp;&nbsp;|</div>
<div>&nbsp;&nbsp;- views</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp;|</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp;- admin</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;_ &nbsp;new.html.erb</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;- &nbsp;index.html.erb</div>
<div>public</div>
<div>&nbsp;&nbsp;|</div>
<div>&nbsp;&nbsp;- javascripts</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; |</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; - admin</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - new.js</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - index.js</div>
<div><br />
</div>
<div>And new.js looks similar to:</div>
<div>
<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: #000000;">$(document).ready(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">()&nbsp;{<br />
&nbsp;&nbsp;enhanceInteractionOnElements();<br />
&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" /><br />
});<br />
<br />
</span><span style="color: #0000ff;">function</span><span style="color: #000000;">&nbsp;helper_methods()&nbsp;{<br />
&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" /><br />
}</span></div>
</div>
<br />
<br />
<div>Then, add the follow method to ApplicationHelper module:</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: #000000;">def&nbsp;page_javascript_include_tag<br />
&nbsp;&nbsp;file&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">#{params[:controller]}/#{params[:action]}.js</span><span style="color: #000000;">"</span><span style="color: #000000;"><br />
&nbsp;&nbsp;File.exist</span><span style="color: #000000;">?</span><span style="color: #000000;">(</span><span style="color: #000000;">"</span><span style="color: #000000;">#{RAILS_ROOT}/public/javascripts/#{file}</span><span style="color: #000000;">"</span><span style="color: #000000;">)&nbsp;</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;javascript_include_tag(file)&nbsp;:&nbsp;</span><span style="color: #000000;">""</span><span style="color: #000000;"><br />
end</span></div>
<div><br />
this method will look for js file for a particular page. And in you layout file, add one line in the head sectin:</div>
<div>
<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="background-color: #ffff00; color: #000000;">&lt;%</span><span style="background-color: #f5f5f5; color: #000000;">=</span><span style="background-color: #f5f5f5; color: #000000;">&nbsp;page_javascript_include_tag&nbsp;</span><span style="background-color: #ffff00; color: #000000;">%&gt;</span></div>
</div>
<div><br />
That's it. Whenever you request an action of a particular controller, it will find and include the PE js files automatically. Now we've very very primitive support of PE in Rails framework now.<br />
</div>
<div><br />
</div>
<div>&nbsp;</div>
<div><br />
</div>
<div><br />
</div>
<div>&nbsp;</div>
<img src ="http://www.blogjava.net/raimundox/aggbug/260475.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2009-03-18 14:38 <a href="http://www.blogjava.net/raimundox/archive/2009/03/18/260475.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>A very brief introduction to Aurum</title><link>http://www.blogjava.net/raimundox/archive/2007/09/05/143029.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Wed, 05 Sep 2007 15:21:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2007/09/05/143029.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/143029.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2007/09/05/143029.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/143029.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/143029.html</trackback:ping><description><![CDATA[<a href="http://aurum.rubyforge.org">
Aurum</a> is a Ruby-based LALR(n) parser generator that you can use to develop your own domain specified languages, scripting languages and programming languages.Although it's just yet another parser generator, Aurum is slightly different from other widely used parser generators:<br />
<br />
<ol>
    <li>One of major targets of Aurum is to simplify external DSL development, espectually Ruby external DSL.</li>
    <li>Aurum uses incremental LALR(n) algorithm instead of the common used LALR(1)/Full LALR(n) algorithm. That means: <br />
    <ul>
        <li>&nbsp; Allowing the user to express grammars in a more intuitive mannar.</li>
        <li>&nbsp; Making it easier to handle complicated grammars. For exmaple,
        COBOL(LALR(2 or 3)), simplified nature language(LALR(3+)) and etc.</li>
        <li>&nbsp; Closer to Generalized LR in language recognizing but much more faster.</li>
        <li>&nbsp; Smaller parsing table comparing to Full LALR/LR(n) algorithm.</li>
    </ul>
    </li>
    <li>Aurum supports grammar reuse, and itslef'll be shipped with some pre-defined common structures. One of the pain points of external DSL is that you have to re-define lots of common structures, such as if statements, block structure and etc. With Aurum, you could simply reuse them.</li>
    <li>Aurum uses a Ruby interal DSL as meta-language, and provides a generic lexer/parser as well. You could test your grammar by the comprehensive testing libraries Ruby has(you could even develop your lexer/parser in the TDD fashion).</li>
    <li>As the name suggested, Aurum, the Latin word for Gold, is partially inspired by the <a href="http://www.devincook.com/goldparser/ ">GOLD Parsing System</a>. The grammar you created with Aurum could be completely independent of any implementation language,even Ruby.(not implemented yet :) )</li>
</ol>
<br />
Ok, let's start from the 'Hello World in Compiler Construction' —— Expression Evaluation<br />
<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: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">require&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">aurum</span><span style="color: #000000;">'</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;ExpressionGrammar&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;Aurum::Grammar<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;tokens&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;ignore&nbsp;string(</span><span style="color: #000000;">'</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">).one_or_more&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;a<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;_number&nbsp;range(</span><span style="color: #000000;">?</span><span style="color: #000000;">0</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">?</span><span style="color: #000000;">9</span><span style="color: #000000;">).one_or_more&nbsp;&nbsp;#&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;b<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;precedences&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;">&nbsp;&nbsp;#&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;c<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;left&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">*</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">/</span><span style="color: #000000;">'</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;left&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">+</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">-</span><span style="color: #000000;">'</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;productions&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;">&nbsp;#&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;d<br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;expression&nbsp;expression,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">+</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;expression&nbsp;{expression.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;expression1.value&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;expression2.value}&nbsp;#&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;e<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;expression&nbsp;expression,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">-</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;expression&nbsp;{expression.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;expression1.value&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;expression2.value}<br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;expression&nbsp;expression,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">*</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;expression&nbsp;{expression.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;expression1.value&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;expression2.value}<br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;expression&nbsp;expression,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">/</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;expression&nbsp;{expression.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;expression1.value&nbsp;</span><span style="color: #000000;">/</span><span style="color: #000000;">&nbsp;expression2.value}<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;expression&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">(</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;expression,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">)</span><span style="color: #000000;">'</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;">&nbsp;expression.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;expression1.value&nbsp;end&nbsp;#&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;f<br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;expression&nbsp;_number&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{expression.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;_number.value.to_i}<br />
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;expression&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">+</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;_number&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{expression.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;_number.value.to_i}<br />
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;expression&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">-</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;_number&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{expression.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">_number.value.to_i}<br />
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end<br />
</span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;">end</span></div>
<br />
If you has any experience with other compiler compiler/parser generator, you probably could understand what happens above quite easily. Instead of explaining things like token, character class, and production, I'd like to emphasise some Aurum conventions:<br />
<ol>
    <li>At point a, we use 'ignore' directive to declare the ignored pattern, such as whitespaces etc.'string' is one of the helper methods(others are enum, range and concat), which is used to define lexical patterns. It will create a pattern matching the given string exactly.</li>
    <li>At point b, we declare a lexical token named '_number'. In Aurum, lexical tokens, or terminals from syntax perspective, always start with '_'. The expression '_token_name pattern' is equivalent to 'match pattern, :recognized =&gt; :_toke_name'. The 'match' directive is a common way to associate lexical action with leixcal pattern.</li>
    <li>At point c, we declare operator precedences of the Expression grammar.The eariler the operators definied, the higher precedence they will have.</li>
    <li>At point d, we declare syntax rules of Expression grammar. According to Aurum naming convention, all terminals should start with '_' while all nontermainls start with lower case alphabet character. String literals will be interpreted as reserve words, and added to lexer automatically.</li>
    <li>At point e, we define a semantic action to the Addition rule. In semantic action, you could access to the objects in value stack via the name of corresponding symbols.If there are more than one symbol with the same name, you could differentiate them by the order they appered in the production.</li>
    <li>At point f, we use do..end instead of {..}. Using Ruby internal DSL as meta-langauge is a double-side sword, you have to bear its flaws while enjoying the remaining parts. There is no perfect world, isn't it?</li>
</ol>
<br />
Now, let's find out how we could use this expression grammar. You could use the helper method as below(it will recalcuate lexical table and parsing table for every call, could be quite slow):<br />
<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: #008080;">1</span>&nbsp;<span style="color: #000000;">puts&nbsp;ExpressionGrammar.parse_expression(</span><span style="color: #000000;">'</span><span style="color: #000000;">1+1</span><span style="color: #000000;">'</span><span style="color: #000000;">).value</span></div>
<br />
or use the lexical table and parsing table to create your own lexer &amp; parser:<br />
&nbsp;
<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: #008080;">1</span>&nbsp;&nbsp; <span style="color: #000000;">lexer&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Aurum::Engine::Lexer.</span><span style="color: #0000ff;">new</span><span style="color: #000000;">(ExpressionGrammar.lexical_table,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">1+1</span><span style="color: #000000;">'</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;parser&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Aurum::Engine::Parser.</span><span style="color: #0000ff;">new</span><span style="color: #000000;">(ExpressionGrammar.parsing_table(:expression))<br />
</span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;puts&nbsp;parser.parse(lexer).value</span></div>
<br />
<br />
At the end of this post, I'd like to give another grammar example coming from <a href="http://www.martinfowler.com">Martin Fowler</a>'s <a href="http://www.martinfowler.com/bliki/HelloSablecc.html ">HelloParserGenerator</a> series:<br />
<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: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">require&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">aurum</span><span style="color: #000000;">'</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">Item&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Struct.</span><span style="color: #0000ff;">new</span><span style="color: #000000;">(:name)<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Catalog&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;Aurum::Grammar<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;tokens&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;ignore&nbsp;</span><span style="color: #0000ff;">enum</span><span style="color: #000000;">(</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;\r\n</span><span style="color: #000000;">"</span><span style="color: #000000;">).one_or_more<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;_item&nbsp;range(</span><span style="color: #000000;">?</span><span style="color: #000000;">a,</span><span style="color: #000000;">?</span><span style="color: #000000;">z).one_or_more<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;productions&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;configuration&nbsp;configuration,&nbsp;item&nbsp;{configuration.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;configuration1.value.merge({item.value.name&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;item.value})}<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;configuration&nbsp;_&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{configuration.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;{}}<br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;item&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">item</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;_item&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{item.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Item.</span><span style="color: #0000ff;">new</span><span style="color: #000000;">(_item.value)}<br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">end<br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">config&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Catalog.parse_configuration(</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">EndOfDSL).value<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;item&nbsp;camera<br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;item&nbsp;laser<br />
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">EndOfDSL<br />
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">puts&nbsp;config[</span><span style="color: #000000;">'</span><span style="color: #000000;">camera</span><span style="color: #000000;">'</span><span style="color: #000000;">].name</span></div>
<br />
<br />
P.S.:The post is based on the developing version of Aurum(0.2.0). You could get it from the svn repository. <br />
P.S.P.S.: There is a more complicated example in the examples directory, a simple Smalltalk interpreter. Have fun:)<br />

<img src ="http://www.blogjava.net/raimundox/aggbug/143029.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2007-09-05 23:21 <a href="http://www.blogjava.net/raimundox/archive/2007/09/05/143029.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>A very brief introduction to Aurum</title><link>http://www.blogjava.net/raimundox/archive/2007/09/05/143028.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Wed, 05 Sep 2007 15:12:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2007/09/05/143028.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/143028.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2007/09/05/143028.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/143028.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/143028.html</trackback:ping><description><![CDATA[A very brief introduction to Aurum<br />
<br />
<a href="http://aurum.rubyforge.org">Aurum</a>是一个用Ruby实现的LALR(n) parser generator（是的，又是一个parser generator），不过它和其他一些广泛应用的parser generator相比略有不同的：<br />
<br />
1.Aurum的主要目标之一，是简化external DSL的开发（尤其是ruby external DSL）。<br />
2.Aurum采用增量LALR(n)算法，而不是通常的LALR(1)。这意味着：<br />
&nbsp; a.不必由于LALR(1)能力的限制，而改写语法，很多在LALR(1)中冲突的语法在LALR(n)中可以比较自然地表达。<br />
&nbsp; b.由于识别能力的增强，可以处理一些比较复杂的语法，比如COBOL(LALR(2)或LALR(3))，比如一些简化的自然语言(LALR(3+))。<br />
&nbsp; c.处理能力接近Generalized LR，却快很多<br />
&nbsp; d.比起Full LALR/LR(n)，增量算法生成的语法表更小。<br />
3.出于简化external DSL实现的考虑，Aurum支持语法重用。<br />
4.Aurum采用Ruby internal DSL作为语法声明的元语言，可以利用Ruby丰富的测试框架，有效地对编译／解释／分析器进行测试。<br />
5.正如名字所暗示的，Aurum（Gold的化学名称）的一部分灵感来自<a href="http://www.devincook.com/goldparser">GOLD parsing system</a>，它将支持独立于平台和语言的编译器开发。<br />
<br />
好，闲话少说，看一个例子，编译原理中的Hello World —— 表达式求值：<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: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">require&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">aurum</span><span style="color: #000000;">'</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;ExpressionGrammar&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;Aurum::Grammar<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;tokens&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;ignore&nbsp;string(</span><span style="color: #000000;">'</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">).one_or_more&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;a<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;_number&nbsp;range(</span><span style="color: #000000;">?</span><span style="color: #000000;">0</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">?</span><span style="color: #000000;">9</span><span style="color: #000000;">).one_or_more&nbsp;&nbsp;#&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;b<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;precedences&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;">&nbsp;&nbsp;#&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;c<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;left&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">*</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">/</span><span style="color: #000000;">'</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;left&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">+</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">-</span><span style="color: #000000;">'</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;productions&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;">&nbsp;#&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;d<br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;expression&nbsp;expression,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">+</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;expression&nbsp;{expression.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;expression1.value&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;expression2.value}&nbsp;#&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;e<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;expression&nbsp;expression,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">-</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;expression&nbsp;{expression.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;expression1.value&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;expression2.value}<br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;expression&nbsp;expression,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">*</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;expression&nbsp;{expression.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;expression1.value&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;expression2.value}<br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;expression&nbsp;expression,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">/</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;expression&nbsp;{expression.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;expression1.value&nbsp;</span><span style="color: #000000;">/</span><span style="color: #000000;">&nbsp;expression2.value}<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;expression&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">(</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;expression,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">)</span><span style="color: #000000;">'</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;">&nbsp;expression.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;expression1.value&nbsp;end&nbsp;#&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;f<br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;expression&nbsp;_number&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{expression.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;_number.value.to_i}<br />
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;expression&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">+</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;_number&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{expression.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;_number.value.to_i}<br />
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;expression&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">-</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;_number&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{expression.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">_number.value.to_i}<br />
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end<br />
</span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;">end</span></div>
<br />
<br />
如果诸位对之前有用过compiler compiler或者parser generator的话，应该能看个七七八八吧。我大概解释一下：<br />
&nbsp;a.这里定义了文法空白，也就是被lexer忽略的部分，在通常的语言中，是空格回车换行之类的字符；string是用于定义lexical pattern的helper方法（出了string之外，还有range, enum和concat）；ignore是一个预定义的说明指令，表示若文本匹配给定模式则该文本会被lexer自动忽略，其格式为：<br />
&nbsp;&nbsp;&nbsp; ignore pattern {//lexical action}<br />
&nbsp;b.此处为lexical token声明，所有lexical token必须以_开头，其格式为：<br />
&nbsp;&nbsp;&nbsp; _token_name pattern {//lexical action}<br />
&nbsp;&nbsp; 这里其实是一个简略写法，等价于<br />
&nbsp;&nbsp;&nbsp; match pattern, :recognize =&gt; ：_token_name<br />
&nbsp;c.此处为运算符优先级声明，支持左/右结合运算符（无结合属性运算符开发中）；每一行中所有运算符具有相同优先级；比它下一行的运算符高一个优先级。比如在这个例子中，'*'和'/'具有相同优先级，但是比'+'和'-'的优先级别高。<br />
&nbsp;d.此处为语法规则声明，所使用的symbol主要有三种，nonterminal(小写字母开头)，terminal(其实就是lexical token，以_开头)和literal(字符串常量)，其中所有literal都会被自动声明为保留字。<br />
&nbsp;e.此处定义了一条文法规则（加法），以及对应的semantic action。在semantic action中可以直接通过symbol的名字来获取值栈中的对象。如遇到同名symbol，则按照出现顺序进行编号即可。<br />
&nbsp;f.其实这个没啥，只不过由于我们使用的是Ruby DSL，所以有时候不能都用{}，需要do end，这就是一个例子。<br />
<br />
最后测试一下实际中如何使用定义好的语法（使用helper method，注意由于分析表没有缓存，每次都会重算语法表，仅仅适用于debug mode。）<br />
&nbsp; puts ExpressionGrammar.parse_expression('1+1').value<br />
或者通过分析表自己构造lexer和parser<br />
&nbsp; lexer = Aurum::Engine::Lexer.new(ExpressionGrammar.lexical_table, '1+1')<br />
&nbsp; parser = Aurum::Engine::Parser.new(ExpressionGrammar.parsing_table(:expression))<br />
&nbsp; puts parser.parse(lexer).value<br />
<br />
最后最后，给另外一个例子，就是<a href="http://www.martinfowler.com">Martin Fowler</a> Blog上的<a href="http://www.martinfowler.com/bliki/HelloSablecc.html ">HelloParserGenerator</a>系列中所用的语法：<br />
<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: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">require&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">aurum</span><span style="color: #000000;">'</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">Item&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Struct.</span><span style="color: #0000ff;">new</span><span style="color: #000000;">(:name)<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Catalog&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;Aurum::Grammar<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;tokens&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;ignore&nbsp;</span><span style="color: #0000ff;">enum</span><span style="color: #000000;">(</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;\r\n</span><span style="color: #000000;">"</span><span style="color: #000000;">).one_or_more<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;_item&nbsp;range(</span><span style="color: #000000;">?</span><span style="color: #000000;">a,</span><span style="color: #000000;">?</span><span style="color: #000000;">z).one_or_more<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;productions&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;configuration&nbsp;configuration,&nbsp;item&nbsp;{configuration.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;configuration1.value.merge({item.value.name&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;item.value})}<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;configuration&nbsp;_&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{configuration.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;{}}<br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;item&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">item</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;_item&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{item.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Item.</span><span style="color: #0000ff;">new</span><span style="color: #000000;">(_item.value)}<br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">end<br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">config&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Catalog.parse_configuration(</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">EndOfDSL).value<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;item&nbsp;camera<br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;item&nbsp;laser<br />
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">EndOfDSL<br />
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">puts&nbsp;config[</span><span style="color: #000000;">'</span><span style="color: #000000;">camera</span><span style="color: #000000;">'</span><span style="color: #000000;">].name</span></div>
<br />
<br />
P.S.:本文是根据Aurum0.2.0写成的，你可以从rubyforge的svn上得到它。<br />
P.S.P.S.: 在exmaples目录里有一个更复杂一些的例子，是一个简单的Smalltalk解释器。<br />
<br />
<br />

<img src ="http://www.blogjava.net/raimundox/aggbug/143028.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2007-09-05 23:12 <a href="http://www.blogjava.net/raimundox/archive/2007/09/05/143028.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Erlang Ring Benchmark</title><link>http://www.blogjava.net/raimundox/archive/2007/08/01/133863.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Wed, 01 Aug 2007 12:34:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2007/08/01/133863.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/133863.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2007/08/01/133863.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/133863.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/133863.html</trackback:ping><description><![CDATA[《Programming Erlang》第8章后面有一个练习，Ring Benchmark。就是说创建N个进程，把它们组合成环状。然后在这个环上把一条消息在环上传递M圈，然后记录所有的时间。实现起来也挺简单，20行左右吧：<br><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: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">-</span><span style="color: #000000;">module(ring_benchmark).&nbsp;<br></span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;"></span><span style="color: #000000;">-</span><span style="color: #000000;">export([start</span><span style="color: #000000;">/</span><span style="color: #000000;">2</span><span style="color: #000000;">]).<br></span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">start(N,&nbsp;M)&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;<br></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;Pid&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;create_process(self(),&nbsp;N&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">,&nbsp;M),<br></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;time(fun()&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;Pid&nbsp;</span><span style="color: #000000;">!</span><span style="color: #000000;">&nbsp;start,&nbsp;loop(Pid,&nbsp;M)&nbsp;end).<br></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">time(Fun)&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;<br></span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;statistics(wall_clock),<br></span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;Fun(),<br></span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;{_,Time}&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;statistics(wall_clock),<br></span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;io:format(</span><span style="color: #000000;">"</span><span style="color: #000000;">Run&nbsp;:&nbsp;~w&nbsp;s&nbsp;~n</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;[Time</span><span style="color: #000000;">/</span><span style="color: #000000;">1000</span><span style="color: #000000;">]).&nbsp;&nbsp;<br></span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;"><br></span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">create_process(Pid,&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">,&nbsp;_)&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;Pid;<br></span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">create_process(Pid,&nbsp;N,&nbsp;M)&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;create_process(spawn(fun()&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;loop(Pid,&nbsp;M)&nbsp;end),&nbsp;&nbsp;N&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">,&nbsp;M).<br></span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;"><br></span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">loop(_,&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">;<br></span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">loop(Next,&nbsp;M)&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;<br></span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;receive<br></span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;Message&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;Next&nbsp;</span><span style="color: #000000;">!</span><span style="color: #000000;">&nbsp;Message,<br></span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;loop(Next,&nbsp;M&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br></span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end.<br></span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;"><br></span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;"></span></div>
<br>有意思是它还有一个第二问，让你用另外一种熟悉的语言实现同样的功能，发送同样多的消息，也把时间记录下来，然后写一篇blog来publish你的结果。其实，大家心知肚明，这种lightweight process啊，message passing concurrency啊都是Erlang的强项，而且实测结果也着实颇为恐怖，一般也就没那闲心拿别的东西来陪衬一把了（Armstrong同学自己实现了一个Java version，效率大约能差到百倍吧）。不过还真有那写不信邪的老大，<a href="http://muharem.wordpress.com/2007/07/31/erlang-vs-stackless-python-a-first-benchmark/">用stackless python实现了同样的ring benchmark</a>，发现比erlang还快...后来修改代码去掉io操作，Erlang倒是比stackless python快些，但也只是一些而已。<br><br><br><br><br> <img src ="http://www.blogjava.net/raimundox/aggbug/133863.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2007-08-01 20:34 <a href="http://www.blogjava.net/raimundox/archive/2007/08/01/133863.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Domain Oriented Web Testing with Selenium &amp; Ruby (Posted@InfoQ China)</title><link>http://www.blogjava.net/raimundox/archive/2007/06/13/123772.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Wed, 13 Jun 2007 01:44:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2007/06/13/123772.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/123772.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2007/06/13/123772.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/123772.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/123772.html</trackback:ping><description><![CDATA[http://www.infoq.com/cn/articles/domain-web-testing<br><br>应用Selenium进行Web测试往往会存在几个bad smell：<br>1.大量使用name, id, xpath等页面元素。无论是功能修改、UI重构还是交互性改进都会影响到这些元素，这使得Selenium测试变得非常脆弱。<br>2.过于细节的页面操作不容易体现出行为的意图，一段时间之后就很难真正把握测试原有的目的了，这使得Selenium测试变得难于维护。<br>3.对具体数据取值的存在依赖，当个别数据不再合法的时候，测试就会失败，但这样的失败并不能标识功能的缺失，这使得Selenium测试变得脆弱且难以维护。<br><br>而这几点直接衍生的结果就是不断地添加新的测试，而极少地去重构、利用原有测试。其实这到也是正常，单元测试测试写多了，也有会有这样的问题。不过比较要命的是，Selenium的执行速度比较慢（相对单元测试），随着测试逐渐的增多，运行时间会逐渐增加到不可忍受的程度。一组意图不明难以维护的Selenium测试，可以很轻松地在每次build的时候杀掉40分钟甚至2个小时的时间，在下就有花2个小时坐在电脑前面等待450个Selenium测试运行通过的悲惨经历。因此合理有效地规划Selenium测试就显得格外的迫切和重要了。而目前比较行之有效的办法，往大了说，可以叫domain based web testing，具体来讲，就是Page Object Pattern。<br><br>Page Object Pattern里有四个基本概念：Driver, Page, Navigator和Shortcut。Driver是测试真正的实现机制，比如Selenium，比如Watir，比如HttpUnit。它们懂得如何去真正执行一个web行为，通常包含像click，select，type这样的表示具体行为的方法；Page是对一个具体页面的封装，它们了解页面的结构，知道诸如id， name， class，xpath这类实现细节，并描述用户可以在其上进行何种操作；Navigator则代表了URL，表示一些不经页面操作的直接跳转；最后Shortcut就是helper方法了，需要看具体的需要了。下面来看一个超级简单的例子——测试登录页面。<br><br>1. Page Object<br><br>假设我们使用一个单独的Login Page进行登录，那么我们可能会将登录的操作封装在一个名为LoginPage的page object里：<br><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: #008080;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;LoginPage<br></span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;def&nbsp;initialize&nbsp;driver<br></span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;@driver&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;driver<br></span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end<br></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;<br></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;def&nbsp;login_as&nbsp;user<br></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;@driver.type&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">id=<img src="http://www.blogjava.net/Images/dot.gif"></span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;user[:name]<br></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;@driver.type&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">xpath=<img src="http://www.blogjava.net/Images/dot.gif"></span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;user[:password]<br></span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;@driver.click&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">name=<img src="http://www.blogjava.net/Images/dot.gif"></span><span style="color: #000000;">'</span><span style="color: #000000;"><br></span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;@driver.wait_for_page_to_load<br></span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end<br></span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">end</span></div>
<br><br>login_as是一个具有业务含义的页面行为。在login_as方法中，page object负责通过依靠id，xpath，name等信息完成登录操作。在测试中，我们可以这样来使用这个page object：<br><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: #008080;">1</span>&nbsp;<span style="color: #000000;">page&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;LoginPage.</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;$selenium<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">page.login_as&nbsp;:name&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">xxx</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;:password&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">xxx</span><span style="color: #000000;">'</span><span style="color: #000000;"><br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;"></span></div>
<br>不过既然用了ruby，总要用一些ruby sugar吧，我们定义一个on方法来表达页面操作的环境：<br><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: #008080;">1</span>&nbsp;<span style="color: #000000;">def&nbsp;on&nbsp;page_type,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">block<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;page&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;page_type.</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;$selenium<br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;page.instance_eval&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">block&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;block_given</span><span style="color: #000000;">?</span><span style="color: #000000;"><br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">end</span></div>
<br>之后我们就可以使用page object的类名常量和block描述在某个特定页面上操作了：<br><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: #008080;">1</span>&nbsp;<span style="color: #000000;">on&nbsp;LoginPage&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;login_as&nbsp;:name&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">xxx</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;:password&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">xxx</span><span style="color: #000000;">'</span><span style="color: #000000;"><br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">end<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;"></span></div>
<br>除了行为方法之外，我们还需要在page object上定义一些获取页面信息的方法，比如获取登录页面的欢迎词的方法：<br><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: #000000;">def&nbsp;welcome_message<br>&nbsp;&nbsp;@driver.get_text&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">xpath=<img src="http://www.blogjava.net/Images/dot.gif"></span><span style="color: #000000;">'</span><span style="color: #000000;"><br>end</span></div>
<br><br>这样测试也可表达得更生动一些：<br><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: #008080;">1</span>&nbsp;<span style="color: #000000;">on&nbsp;LoginPage&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;assert_equal&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">Welcome!</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;welcome_message<br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;login_as&nbsp;:name&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">xxx</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;:password&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">xxx</span><span style="color: #000000;">'</span><span style="color: #000000;"><br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">end</span></div>
<br>当你把所有的页面都用Page Object封装了之后，就有效地分离了测试和页面结构的耦合。在测试中，只需使用诸如login_as, add_product_to_cart这样的业务行为，而不必依靠像id，name这些具体且易变的页面元素了。当这些页面元素发生变化时，只需修改相应的page object就可以了，而原有测试基本不需要太大或太多的改动。<br><br>2. Assertation<br><br>只有行为还够不成测试，我们还要判断行为结果，并进行一些断言。简单回顾一下上面的例子，会发现还有一些很重要的问题没有解决：我怎么判断登录成功了呢？我如何才能知道真的是处在登录页面了呢？如果我调用下面的代码会怎样呢？<br><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: #008080;">1</span>&nbsp;<span style="color: #000000;">$selenium.open&nbsp;url_of_any_page_but_not_login<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">on&nbsp;LoginPage&nbsp;{<img src="http://www.blogjava.net/Images/dot.gif">}</span></div>
<br>因此我们还需要向page object增加一些断言性方法。至少，每个页面都应该有一个方法用于判断是否真正地达到了这个页面，如果不处在这个页面中的话，就不能进行任何的业务行为。下面修改LoginPage使之包含这样一个方法：<br><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: #008080;">1</span>&nbsp;<span style="color: #000000;">LoginPage.class_eval&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;include&nbsp;Test::Unit::Asseration<br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;def&nbsp;visible</span><span style="color: #000000;">?</span><span style="color: #000000;"><br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;@driver.is_text_present(<img src="http://www.blogjava.net/Images/dot.gif">)&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;@driver.get_location&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"><br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end<br></span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;">end</span></div>
<br><br>在visible?方法中，我们通过对一些特定的页面元素（比如URL地址，特定的UI结构或元素）进行判断，从而可以得之是否真正地处在某个页面上。而我们目前表达测试的基本结构是由on方法来完成，我们也就顺理成章地在on方法中增加一个断言，来判断是否真的处在某个页面上，如果不处在这个页面则不进行任何的业务操作：<br><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: #008080;">1</span>&nbsp;<span style="color: #000000;">def&nbsp;on&nbsp;page_type,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">block<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;page&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;page_type.</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;$selenium<br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #0000ff;">assert</span><span style="color: #000000;">&nbsp;page.visible</span><span style="color: #000000;">?</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">not&nbsp;on&nbsp;#{page_type}</span><span style="color: #000000;">"</span><span style="color: #000000;"><br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;page.instance_eval&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">block&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;block_given</span><span style="color: #000000;">?</span><span style="color: #000000;"><br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;page<br></span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;">end<br></span><span style="color: #008080;">7</span>&nbsp;<span style="color: #000000;"></span></div>
<br>这个方法神秘地返回了page对象，这里是一个比较tricky的技巧。实际上，我们只想利用page != nil这个事实来断言页面的流转，比如，下面的代码描述登录成功的页面流转过程：<br><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: #000000;">on&nbsp;LoginPage&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br>&nbsp;&nbsp;assert_equal&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">Welcome!</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;welcome_message<br>&nbsp;&nbsp;login_as&nbsp;:name&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">xxx</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;:password&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">xxx</span><span style="color: #000000;">'</span><span style="color: #000000;"><br>end<br></span><span style="color: #0000ff;">assert</span><span style="color: #000000;">&nbsp;on&nbsp;WelcomeRegisteredUserPage</span></div>
<br>除了这个基本断言之外，我们还可以定义一些业务相关的断言，比如在购物车页面里，我们可以定义一个判断购物车是否为空的断言：<br><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: #008080;">1</span>&nbsp;<span style="color: #000000;">def&nbsp;cart_empty</span><span style="color: #000000;">?</span><span style="color: #000000;"><br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;@driver.get_text(</span><span style="color: #000000;">'</span><span style="color: #000000;">xpath=<img src="http://www.blogjava.net/Images/dot.gif"></span><span style="color: #000000;">'</span><span style="color: #000000;">)&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">Shopping&nbsp;Cart(0)</span><span style="color: #000000;">'</span><span style="color: #000000;"><br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">end</span></div>
<br>需要注意的是，虽然我们在page object里引入了Test::Unit::Asseration模块，但是并没有在断言方法里使用任何assert*方法。这是因为，概念上来讲page object并不是测试。使之包含一些真正的断言，一则概念混乱，二则容易使page object变成针对某些场景的test helper，不利于以后测试的维护，因此我们往往倾向于将断言方法实现为一个普通的返回值为boolean的方法。<br><br>3. Test Data<br><br>测试意图的体现不仅仅是在行为的描述上，同样还有测试数据，比如如下两段代码：<br><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: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">on&nbsp;LoginPage&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;login_as&nbsp;:name&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">userA</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;:password&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">password</span><span style="color: #000000;">'</span><span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">end<br></span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">assert</span><span style="color: #000000;">&nbsp;on&nbsp;WelcomeRegisteredUserPage<br></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">registered_user&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;{:name&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">userA</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;:password&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">password</span><span style="color: #000000;">'</span><span style="color: #000000;">}<br></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">on&nbsp;LoginPage&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;login_as&nbsp;registered_user<br></span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">end<br></span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">assert</span><span style="color: #000000;">&nbsp;on&nbsp;WelcomeRegisteredUserPage</span></div>
<br><br>测试的是同一个东西，但是显然第二个测试更好的体现了测试意图：使用一个已注册的用户登录，应该进入欢迎页面。我们看这个测试的时候，往往不会关心用户名啊密码啊具体是什么，我们关心它们表达了怎样的测试案例。我们可以通过DataFixture来实现这一点：<br><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: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">module&nbsp;DataFixture<br></span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;USER_A&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;{:name&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">userA</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;:password&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">password</span><span style="color: #000000;">'</span><span style="color: #000000;">}<br></span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;USER_B&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;{:name&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">userB</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;:password&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">password</span><span style="color: #000000;">'</span><span style="color: #000000;">}<br></span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;def&nbsp;get_user&nbsp;identifier<br></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;identifier<br></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;when&nbsp;:registered&nbsp;then&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;USER_A<br></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;when&nbsp;:not_registered&nbsp;then&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;USER_B<br></span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;end<br></span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end<br></span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">end</span></div>
<br><br>在这里，我们将测试案例和具体数据做了一个对应：userA是注册过的用户，而userB是没注册的用户。当有一天，我们需要将登录用户名改为邮箱的时候，只需要修改DataFixture模块就可以了，而不必修改相应的测试：<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: #008080;">1</span>&nbsp;<span style="color: #000000;">include&nbsp;DataFixtureDat<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;"><br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">user&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;get_user&nbsp;:registered<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">on&nbsp;LoginPage&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;login_as&nbsp;user<br></span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;">end<br></span><span style="color: #008080;">7</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">assert</span><span style="color: #000000;">&nbsp;on&nbsp;WelcomeRegisteredUserPage</span></div>
<br>当然，在更复杂的测试中，DataFixture同样可以使用真实的数据库或是Rails Fixture来完成这样的对应，但是总体的目的就是使测试和测试数据有效性的耦合分离：<br><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: #008080;">1</span>&nbsp;<span style="color: #000000;">def&nbsp;get_user&nbsp;identifier<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;identifier<br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;when&nbsp;:registered&nbsp;then&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;User.find&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;"><img src="http://www.blogjava.net/Images/dot.gif">.</span><span style="color: #000000;">'</span><span style="color: #000000;">&nbsp;<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end<br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">end</span></div>
<br><br>4.Navigator<br><br>与界面元素类似，URL也是一类易变且难以表达意图的元素，因此我们可以使用Navigator使之与测试解耦。具体做法和Test Data相似，这里就不赘述了，下面是一个例子：<br><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: #008080;">1</span>&nbsp;<span style="color: #000000;">navigate_to&nbsp;detail_page_for&nbsp;@product<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">on&nbsp;ProductDetailPage&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif">.<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">end</span></div>
<br>5. Shortcut<br><br>前面我们已经有了一个很好的基础，将Selenium测试与各种脆弱且意图不明的元素分离开了，那么最后shortcut不过是在蛋糕上面最漂亮的奶油罢了——定义具有漂亮语法的helper：<br><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: #008080;">1</span>&nbsp;<span style="color: #000000;">def&nbsp;should_login_successfully&nbsp;user<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;on&nbsp;LoginPage&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;assert_equal&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">Welcome!</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;welcome_message<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;login_as&nbsp;user<br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end<br></span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #0000ff;">assert</span><span style="color: #000000;">&nbsp;on&nbsp;WelcomeRegisteredUserPage<br></span><span style="color: #008080;">7</span>&nbsp;<span style="color: #000000;">end</span></div>
<br>然后是另外一个magic方法：<br><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: #008080;">1</span>&nbsp;<span style="color: #000000;">def&nbsp;given&nbsp;identifer<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;words&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;identifier.to_s.split&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">_</span><span style="color: #000000;">'</span><span style="color: #000000;"><br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;eval&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">get_#{words.last}&nbsp;:#{words[0..-2].join&nbsp;'_'}</span><span style="color: #000000;">"</span><span style="color: #000000;"><br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">end</span></div>
<br>之前的测试就可以被改写为：<br><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: #000000;">def&nbsp;test_should_xxxx<br>&nbsp;&nbsp;should_login_successfully&nbsp;given&nbsp;:registered_user<br>end</span></div>
<br><br>这是一种结论性的shortcut描述，我们还可以有更behaviour的写法：<br><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: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">def&nbsp;login_on&nbsp;page_type<br></span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;on&nbsp;page_type&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;assert_equal&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">Welcome!</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;welcome_message<br></span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;login_as&nbsp;@user<br></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;end<br></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">end<br></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">def&nbsp;login_successfully<br></span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;on&nbsp;WelcomeRegisteredUserPage<br></span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">end<br></span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;"><br></span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">def&nbsp;given&nbsp;identifer<br></span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;words&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;identifier.to_s.split&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">_</span><span style="color: #000000;">'</span><span style="color: #000000;"><br></span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;eval&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">@#{words.last}&nbsp;=&nbsp;get_#{words.last}&nbsp;:#{words[0..-2].join&nbsp;'_'}</span><span style="color: #000000;">"</span><span style="color: #000000;"><br></span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">end</span></div>
<br><br>最后，测试就会变成类似验收条件的样子：<br><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: #008080;">1</span>&nbsp;<span style="color: #000000;">def&nbsp;test_should_xxx<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;given&nbsp;:registered_user<br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;login_on&nbsp;LoginPage<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #0000ff;">assert</span><span style="color: #000000;">&nbsp;login_successfully<br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">end</span></div>
<br>总之shortcut是一个无关好坏，只关乎想象力的东西，尽情挥洒Ruby DSL吧:D<br><br>结论<br><br>Selenium是一个让人又爱又恨的东西，错误地使用Selenium会给整个敏捷团队的开发节奏带来灾难性的影响。不过值得庆幸的是正确地使用Selenium的原则也是相当的简单：<br><br>1.通过将脆弱易变的页面元素和测试分离开，使得页面的变化不会对测试产生太大的影响。<br>2.明确指定测试数据的意图，不在测试用使用任何具体的数据。<br>3.尽一切可能，明确地表达出测试的意图，使测试易于理解。<br><br>当然，除了遵循这几个基本原则之外，使用page object或其他domain based web testing技术是个不错的选择。它们将会帮助你更容易地控制Selenium测试的规模，更好地平衡覆盖率和执行效率，从而更加有效地交付高质量的Web项目。<br><br>鸣谢<br><br>此文中涉及的都是我最近三周以来对Selenium测试进行重构时所采用的真实技术。感谢Nick Drew帮助我清晰地划分了Driver, Page, Nagivator和Shortcut的层次关系，它们构成我整个实践的基石；感谢Chris Leishman，在和他pairing programming的过程中，他帮助我锤炼了Ruby DSL；还有Mark Ryall和Abhi，是他们第一次在项目中引入了Test Data Fixture，使得所有人的工作都变得简单起来。<br><br><img src ="http://www.blogjava.net/raimundox/aggbug/123772.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2007-06-13 09:44 <a href="http://www.blogjava.net/raimundox/archive/2007/06/13/123772.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>I'm Smalltalk, Which Programming Language are You?</title><link>http://www.blogjava.net/raimundox/archive/2007/05/02/115053.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Wed, 02 May 2007 09:48:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2007/05/02/115053.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/115053.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2007/05/02/115053.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/115053.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/115053.html</trackback:ping><description><![CDATA[<img src="http://www.bbspot.com/Images/News_Features/2006/08/language/smalltalk.jpg" alt="You are smalltalk. you like to treat everyone the same way, but this lack of individuality makes everyone feel like objects." border="0" height="90" width="300"><br><a href="http://www.bbspot.com/News/2006/08/language_quiz.php">Which Programming Language are You?</a><br><br>p.s. 这个可能不准...因为李默同学竟然是Lisp...怎么可能...<br><img src ="http://www.blogjava.net/raimundox/aggbug/115053.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2007-05-02 17:48 <a href="http://www.blogjava.net/raimundox/archive/2007/05/02/115053.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>X-Files</title><link>http://www.blogjava.net/raimundox/archive/2007/03/30/107563.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Fri, 30 Mar 2007 14:52:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2007/03/30/107563.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/107563.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2007/03/30/107563.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/107563.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/107563.html</trackback:ping><description><![CDATA[刚才和李默同学回忆了一下，发现我自从入行以来做了很多x项目...下面一一列举一下。<br /><br />1. IEC61970 Metadata: Electricity Power Trading System<br /><br />当时刚上班，team里有一个Doamin知识很厉害的清华的博士，毕业的论文就是电力市场，而清华又是国家引入IEC61970的五家之一。所以他很超前的把这两个东西结合在一起，做成了一个系统。说实话，刚了解IEC61970的时候，我是相当的震撼的，有赶上那时候MDA风气刚起，IEC61970又是同时MOF(Meta Object Facility)和RDF based，华丽得不行。一下子我就变成了一个MDA guy，一个metadata guy...以至于，在BJUG最初的2年里，MDA/MOF/Metadata成为了主旋律...<br /><br />2. IEC61970 &amp; CWM(Common Warehouse Metamodel) &amp; Office Plugin : Data Warehouse Integration System<br /><br />这是迄今为止，我最不愿意回忆的一个项目...因为Office Plugin...动辄蓝屏的遭遇让我心有余悸...这是一个backend是J2EE，frontend是.Net的office插件系统，主要是报表...两边都使用CWM作为数据统一的形式...基本上做到一半我的意志就崩溃了...<br /><br />3. DB Migration/Refactoring : Jyxpearl<br /><br />这个项目...是李默同学的私房最爱，从大学一直做了很久，改版无数次...当时没有这么流行的好词，什么DB Migration啊，DB Refactoring啊，那时候我们统称导数据...我导了好多会...基本上线一回导一回...时至今日...李默同学总是不无得意的说：你看，你DB Migration的能力就是我培养的...<br /><br />4. JMI(Java Metadata Interface) &amp; Eclipse RCP : Multi/Rich Client ERP Product<br /><br />这个team其实挺华丽的，老栾的产品经理，李默是开发经理，超级资深行业专家(人家实际做过生产科长，MRPII，ERP都是人家玩剩下的)老齐做需求，俺是Architect，还有动物园里的猪Senior Dev，我认识人中美工能力第一交互设计能力第一的米米姐做UI和交互。由于当时看了netbeans和sun的官方JMI实现得太玩具。我们决定从自己的JMI实现开始，系统结构要求多客户端，web，rcp都要...所以是超轻http协议的b/s，c/s。结构还是不错的，过程李默和我当然是敏捷了。似乎一起都超级完美的时候，就是要坏菜的时候...企业事业部解散了...<br /><br />5. Java Communication &amp; Eclipse RCP : IC Card Reader<br /><br />上面那个项目解散之后，我跟李默赋闲在家，有不忍心打扰政府，自谋生路找的项目...这个项目要用IC卡读卡器，为了锻炼我们的Eclipse RCP能力，我们决定用eclipse rcp来做。于是问题就出来了...IC卡怎么办？google一把发现天无绝人之路...Java有一个Communication包，可以连接serial port...不过当时tricky的是...我的本子没有串口，我们买了一个串口到usb的转换器...发现根本不能用...于是只好跑到李默家用他华丽的台式机（这厮当年誓言旦旦的说，laptop太慢，一定要用台式机，东借西借搞了个2G RAM SATA［注意，这是伏笔］的机器）。我当时就觉得，Java的这个东西基本就是充数的，貌似完全没有人用过，文档啥的都特少...只能自己摸索。在经历了无数次失败之后，终于成功了。在showcase那天的上午，我最后实验了读卡什么的，都没问题。兴高采烈的把jar拷到优盘上，刚插到usb口上...只见一道闪电...机器黑了...据李默后来分析是主板烧了...我说没事，拿上硬盘，土一点也不影响showcase。李默说...这个...SATA耶...还不流行呢...我绿...此后很长时间，我都怀疑是我跟李默同学范冲，超级项目杀手...<br /><br />6. RDF, Semantic Web, SparQL : Ontology-Relationship DB Mapping<br /><br />这是在一家公司做产品，当时我元数据/MDA领域颇有积累...跟这家公司做得类似，就过来负责研发本体到关系数据库的映射...兼带在D2RQ的基础上实现一个SparQL查询语言。怎么样...听上去很华丽吧...到现在我都认为，这个项目是我最有潜力的牛皮，不定那天web x.0了，我也老了，我就可以拉着小朋友的手去吹牛b了"05年我就做semantic web,O/R mapping知道不？Ontology啊，你们啊，sometime too simple"...不过估计这一天还早得很呢<br /><br />7. Agile Domain Specified Language : Goodhope<br /><br />这个也是李默同学有份的项目...话里的敏捷DSL实践...不过说实话，也有点X...<img src ="http://www.blogjava.net/raimundox/aggbug/107563.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2007-03-30 22:52 <a href="http://www.blogjava.net/raimundox/archive/2007/03/30/107563.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Agile 101: CoC &amp; Why Agile is Hard</title><link>http://www.blogjava.net/raimundox/archive/2007/03/30/107375.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Thu, 29 Mar 2007 22:53:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2007/03/30/107375.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/107375.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2007/03/30/107375.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/107375.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/107375.html</trackback:ping><description><![CDATA[我常常听到这样的观点：敏捷软件开发并不是真正的革命性的方法，它所采用的技术大多都是古已有之的。比如迭代，你看很哪本软件工程的教科书上没有提到迭代开发呢？在比如说User Story，看上去也不只不过是Use Case的翻版而已吧！甚至我看RUP也和敏捷方法没有太大的区别吧！<br />要我说，这些人要么是不真的了解敏捷开发，没有认识到敏捷开发的革命性，只是用外在的形式来把它和其他方法进行了比较。有又或者是实施敏捷方法的时候不彻底，所以四处碰壁以至于搞起了修正主义。最可怕的就是某些大公司，看敏捷火了，总有包装一下，到底还是要卖产品。敏捷软件开发就是一个革命性的方法，只不过它要颠覆的不仅仅是低质量的软件开发方式，更重要的是，它要颠覆软件生产企业和软件的使用企业之间的生产关系！!这一点在敏捷宣言里写得再明白不过了<br /><br />Customer collaboration over Contract negotiation<br /><br />敏捷软件开发，就是要以一种更合理的共赢的合作关系，代替以前畸形的采购式的合约关系。为什么合约关系就是畸形的？我们来看看合约双方的处境。<br /><br />首先软件团队方面承担了过多的风险：业务变化，改代码！！商业抉择转换，改代码！！凭啥你甲方的缘故非要我承担额外的成本？你说我冤不冤？冤！但是人家甲方也冤！！人家花了大把的银子，拿到一堆不能用的软件（你要是硬件人家还能转手卖点钱），就像你要砍树别人给你把铲子，你要种树人家给了你把锯。搁你，你也不愿意。且不说博弈，就算双方都有心把事情做好，按合同来，甲方不干；不按合同来，乙方不干，最后变成“有心杀贼无力回天”，大家一起扯扯皮等二期算了。lose-lose，没有赢家。<br /><br />那么合作的关系是什么呢？合作的关系就好比你去subway买三明治，面包你自己选，要什么肉你来挑，蔬菜，cheese，酱汁你也自己看着办。技术我来，口味你选。技术失败我负责，口味不合适你负责。你做你的强项我来我的强项，最终大家高高兴兴嘻嘻哈哈不吵不闹，作出一顿可口午餐。这是时候，生产关系变了，我不是你的冷冰冰的供应商，你也不是我邪恶的客户，我们是拴在一根绳子上的蚂蚱。成功是我们的，失败也是我们的。荣辱与共，携手并肩。听着有点耳熟？没错，SaaS。敏捷宣言早就说了，CoC啊。从供应商变成服务商，从服务商变成战略合作伙伴，这是在给软件企业指出路，新的生产关系已经尽在其中了。<br /><br />如果看不清敏捷的这个根本革命点，以为还是开发方法的小打小闹，那么敏捷根本实施不成。这话一般我不敢说的，程序员自发实施敏捷，只在一种情况下可能成功：大企业的IT部门。再赶上个强力的IT领导，自家人嘛，有什么不好谈的。一来二去，就成功了（看看C3，说白了不就是IT部门和业务部门？）但是，如果是做项目的公司，你营销手段不改变，敏捷就不可能成功。你的客户跟你不是合作关系，你通过敏捷增加质量（符合性质量）的工作就不会被人可，那么就不能成为投资，只能是成本。当成本增加到不可承担的时候，敏捷就不了了之了。为什么好多人说老板没有响应？旧的生产关系下敏捷根本就是负担。<br /><br />说道这里，说一下以敏捷闻名的ThoughtWorks。其实很多人都以为ThougtWorks只有方法论咨询，没错我们是有方法论咨询，但是也有业务模式咨询，客户业务模式不改变，他怎么能彻底敏捷？这点大家不可不查啊。<img src ="http://www.blogjava.net/raimundox/aggbug/107375.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2007-03-30 06:53 <a href="http://www.blogjava.net/raimundox/archive/2007/03/30/107375.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Scripts Amuse Myself: Poor Man's Lava for CruiseControl.rb</title><link>http://www.blogjava.net/raimundox/archive/2007/03/29/107118.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Thu, 29 Mar 2007 00:53:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2007/03/29/107118.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/107118.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2007/03/29/107118.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/107118.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/107118.html</trackback:ping><description><![CDATA[Yesterday I found a interesting  ruby library  ——   blinkenlights, which enables you to control the LEDs on your keyboard. I thouhgt it could be a cheap replacement of lava light, so I wrote a ruby script called 'Poor Man's Lava'<br /><br />#!/usr/local/bin/ruby<br />require 'rss/1.0'<br />require 'rss/2.0'<br />require 'open-uri'<br />require 'rubygems'<br />require 'blinkenlights'<br /><br />SUCCESS = 'success'<br /><br />def read_rss source='http://cruisecontrolrb.thoughtworks.com/projects/CruiseControl.rss'<br />  content = ''<br />  open(source) do |s| content = s.read end<br />  rss = RSS::Parser.parse content, false<br />  rss.items[0].title.include?(SUCCESS) ? all_ok : alarm<br />end<br /><br />def all_ok times = 50<br />  BlinkenLights.open { |lights| times.times {lights.random} }<br />end<br /><br />def alarm times = 50, invertal = 0.0<br />  BlinkenLights.open { |lights| times.times {lights.flash invertal} }<br />end<br /><br />while true<br />  read_rss<br />  sleep 5  <br />end<br /><br />
make sure to have sufficient permissions to access the device, or you could simple run it as super user.<br /><br /><img src ="http://www.blogjava.net/raimundox/aggbug/107118.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2007-03-29 08:53 <a href="http://www.blogjava.net/raimundox/archive/2007/03/29/107118.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Agile 101: User Story &amp; Prioritization</title><link>http://www.blogjava.net/raimundox/archive/2007/03/28/106863.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Wed, 28 Mar 2007 01:59:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2007/03/28/106863.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/106863.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2007/03/28/106863.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/106863.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/106863.html</trackback:ping><description><![CDATA[通常人们会将User Story和Use Case放在一起比较，虽然二者在形式上具有一定相似性，但是究其本质来说，还是天渊之别的。这一点，专业BA李默同学总结的格外准确：“用户故事是可见的商业价值，而不是功能描述”。想要更好的理解这句话，需要了解什么是好的用户故事。好的用户故事，可用INVEST原则来概括：<br /><br />I - Independent<br />N - Negotiable<br />V - Valuable<br />E - Estimable<br />S - Small<br />T - Testable <br /><br />我个人觉得，这个总结虽好，但不免分散注意。要我说，想把握好User Story，只用把握两个就够了Negotiable和Valuable。那么首先要确定什么是Negotiable的。User Story有一个流传广泛的书写形式：<br /><br />As &lt;role&gt;, I'd like to &lt;action&gt;, so that &lt;benifit/value/goal&gt;.<br /><br />为了更好的获取story还有很多最佳实践，比如personas, 比如business process modeling，其实这些全是糖衣炮弹，As, I'd like to都是噱头，就是为了把用户忽悠晕了，然后图穷匕现直取商业价值和目标。一旦商业价值确定下来，role, action都是可以negotiable。比如李默之前在文章里举的用户登录的例子，输不输用户明密码？可以商量嘛！是不是只有注册用户可以享受个性服务？可以商量嘛！关键是用户想要什么，至于怎么实现这些到头来都是可以商量的，都是Negotiable。只有客户的商业价值是不能商量的，也没的商量。价值没有了，目标不存在了，这个User Story也就没用了，商量啥？重写一张就好了。<br /><br />因此user story又有另外一个名称，叫requirement placeholder。就是客户价值的"立此存照"。至于具体需求，那么就到iteration plan meeting上是商量吧，看看当时什么样的形式（功能）才是最符合用户需要。到此，其实大家可以看出来了，user story重点就不再How上，而是在Why上的。有了why，且可Negotiable，把握了精神，你就是按用例来写需求又有何妨涅？<br /><br />有了valuable和negotiable的想法垫底，在看看基于user story的初步计划制定——也就是有名的prioritization——就容易理解多了。用户根据每张卡的价值，自行比较作出决定，大体场景就跟向神仙许愿一样。<br /><br />神仙：我可以满足你一个愿望。<br />我：我要荣华富贵！！！<br />神仙：哦，荣华富贵，那么要不要爱情涅？<br />我：恩，这个...那我要忠贞的爱情好了！！<br />神仙：哦，忠贞的爱情，那么要不要健康平安呢？<br />我：呃....<br />repeat 无数次，最终我要了一件过冬的皮猴...<img src ="http://www.blogjava.net/raimundox/aggbug/106863.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2007-03-28 09:59 <a href="http://www.blogjava.net/raimundox/archive/2007/03/28/106863.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>InfoQ中文站来了</title><link>http://www.blogjava.net/raimundox/archive/2007/03/28/106830.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Wed, 28 Mar 2007 00:29:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2007/03/28/106830.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/106830.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2007/03/28/106830.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/106830.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/106830.html</trackback:ping><description><![CDATA[自从到了ThouhgtWorks，我订阅的rss越来越少，很多程度上来说，有了自家的Planet TW，很多相看的blog可以一次性看全了，没啥太大的必要去看其他的了。这不，在订阅了Planet TW后的两年中，我只增订了一家：InfoQ。呵呵，想不到如今中文站也来了<a href="http://www.infoq.com/cn/" target="_blank">http://www.infoq.com/cn/</a>。不错不错。<br /><img src ="http://www.blogjava.net/raimundox/aggbug/106830.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2007-03-28 08:29 <a href="http://www.blogjava.net/raimundox/archive/2007/03/28/106830.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Agile 101: Pair Programming &amp; Simple Design</title><link>http://www.blogjava.net/raimundox/archive/2007/03/27/106669.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Tue, 27 Mar 2007 06:52:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2007/03/27/106669.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/106669.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2007/03/27/106669.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/106669.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/106669.html</trackback:ping><description><![CDATA[pair programing是所有XP实践中争议最大的一个，但窃以为确实XP实施的关键关键实践之一，甚至于，我认为很多XP实施的失败都是由于没有采用pair programming而造成的。<br />要了解pair为什么重要，就要了解pair的目的在何。当然了，大多数人都知道pair的重点在于知识传递，知识共享，持续走查，降低代码缺陷等等等等。这些都是pair的优点，不过最重要的一点却常常被忽略——pair programing的最直接而又最根本的目的之一在于simple design。<br /><br /><img src="http://www.xprogramming.com/images/circles.jpg" /><br /><br />上图是著名的Ron Jefferies Model，可以看到XP最佳实践被划分成了一个一个的圆圈，而pair, TDD, refactor和simple design位于中心。这并不是说这四个实践就是xp的核心。jefferies model每一圈代表了xp实践过程中的不同关注点，最中心的是dev视角，其次是team视角，最外层是交付／管理视角。每圈上的最佳时间多少都有些紧耦合，放开其他的不讲，我们专门说说dev圈，pair programing, tdd, refactor和simple design。<br /><br />这四个实践里只有simple design最虚也最重要。有一个问题已经被问过无数次了，“到底多simple的design才叫simple”。我对此也有一个近乎刻板的回答：team里所有人员都能够理解的design就是simple的。一旦立了标准，这四个实践的主从关系就一下子清晰起来——simple design是这四个实践的核心，其他三个实践都是它服务的。<br /><br />首先做出一个设计，最简单的判断标准就是是否可测，一个不可测的设计基本上可以认为无法实现，于是TDD即是simple design的质量保证又是simple design的直觉验证。<br /><br />refactor是为了得到好的代码，那么什么是好的代码？simple design!!!这里有人不同意了，有人说只是要易于修改和扩展，可是扩展和修改也要别人看得懂才行啊...simple design是起码的要求嘛。实际上，XP中的refactor就是朝着simple design的方向重构过去的，也就是朝着所有人都能理解的代码refactor过去的。插一句题外话，为啥说好的架构的不是设计出来的呢？因为好的架构至少应该是simple design的，而simple的概念有和人员相关...所以当你极尽能事show off你的pattern知识之后，得到复杂设计根本就不可能是好的架构。时刻紧记，架构是妥协啊...<br /><br />最后，pair programming是simple design的实际检验！！！因为即便是最复杂的设计，只要是你自己想出来的，你都觉得它简单无比，里面充满了直白且显而易见的理由。可惜不幸的是，我们要的简单，是对team里所有人的简单。如果你的pair不能理解你的设计，那么说明你的设计复杂了;如果你们两个人懂，但是swith pair的时候，换过来的人不懂，说明你的设计复杂了。pair programming(以及他那容易让人忽略的子实践switching pair)就是检验simple design的过程。pair programing + refactor就是时刻保证simple design防止过渡设计反攻倒算的过程。pair programming + refactor + tdd就是团结在以Deming同学built quality in的质量大旗下，坚定地与过渡设计做斗争的过程。据我观察，至没有使用pair programming的团队中，少一半simple design成了口号，而这一半中，至少又有一半最终放弃了xp放弃了敏捷（俺以前带过的团队就有这样的...默哀一下）。深刻的教训啊，我们来高呼一下："pair programming是检验simple design的唯一标准！"。<br /><br />最后说一下pair programming经济学，过多的假设我就不讲了。单说一点，有哪一位上班的8小时从来不上msn/yahoo/qq等im?有哪一位上班从来不上论坛/不回贴/不发邮件?以我pair的经验来看，pair programming的过程中，两个人几乎不会用im，几乎不会逛论坛。你不好意思呀，毕竟不是你一个人的机器，毕竟是两个人的时间，毕竟你也不愿意给同事一种懒散的印象吧？收回的这么浪费的时间，至少顶得过另外一个人的工作时间了吧？<img src ="http://www.blogjava.net/raimundox/aggbug/106669.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2007-03-27 14:52 <a href="http://www.blogjava.net/raimundox/archive/2007/03/27/106669.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Agile Development － a Quality Management Perspective</title><link>http://www.blogjava.net/raimundox/archive/2007/03/26/106507.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Mon, 26 Mar 2007 12:08:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2007/03/26/106507.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/106507.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2007/03/26/106507.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/106507.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/106507.html</trackback:ping><description><![CDATA[想要理解敏捷软件开发为什么好，需要从软件质量讲起。那么软件的质量是什么？这个问题有很多中答案，我们不妨想看看传统质量理论对于质量是如何理解的。教科书上说，在20世纪质量管理的发展历程经历了质量检验、统计质量控制和全面质量管理三个阶段。其中，质量理念也在不断的演变。据说有这么几个阶段：<br /><br />符合性质量<br />20世纪40年代，符合性质量概念以符合现行标准的程度作为衡量依据，“符合标准”就是合格的产品质量，符合的程度反映了产品质量的水平。比如说我做一个杯子，没什么特别的要求，也不是我神经质的艺术作品，就是普普通通的一个杯子，那么需要高矮长短，大小胖瘦，等等一干质量属性，我做好了可以拿着质量标准来对比，一眼就可以看出那里出了什么问题。通过是否符合这些标准判断产品具有相应的质量。<br />那么软件的质量理是不是符合性质量呢？我个人觉得不属于。虽然我们一样可以拿出各种各样的标准，比如故障率，比如bug数等等。但是这些标注都满足确不一定是好的软件，比如我写一个helloworld，虽然他可以没有bug。但是却发挥不了任何的作用。这样的软件就属于“高质量”的废品。正如赵辛梅评价方鸿渐，“你不讨厌，但是毫无用处。”，显然毫无用处的软件不会是真正高质量的软件。<br /><br />适用性质量<br />20世纪60年代，适用性质量概念以适合顾客需要的程度作为衡量的依据，从使用的角度定义产品质量，认为质量就是产品的“适用性”。是“产品在使用时能够成功满足用户需要的程度”。质量涉及设计开发、制造、销售、服务等过程，形成了广义的质量概念。适用性质量的例子也很多，比如我买了一件Givenchy西服（我还真买了一件），但是一时又没有特别正是的场合（目前还真没有什么正式的场合），于是我一天四顿牛排（其实只有一顿），于是就吃胖了，这件华丽的Givenchy就穿不上了。那么这件衣服从符合性质量来说，是优质品，但是从适用性质量来说，却不是一个高质量的产品——因为我穿不上。还有一句话，叫甲之熊掌乙之砒霜。也是适用性质量的标准体现。<br />那么软件的质量是不是适用性质量呢？我个人觉得，软件的质量至少是适用性质量。软件，尤其是定制软件／企业软件，就是量体裁衣。软件的基本质量就是要在用户使用的过程中发挥价值，支撑客户的业务发展。<br />书上说，从“符合性”到“适用性”，反映了人们在对质量的认识过程中，已经开始把顾客需求放在首要位置。但是它没说怎么才能做到把客户需求放到首要位置。我看光靠文档是堆不出来的，光考说说也是不行的。这个后面讲，戴明同学比我讲得好。<br /><br />满意性质量<br />20世纪80年代，质量管理进入到TQM阶段，将质量定义为“一组固有特性满足要求的程度”。它不仅包括符合标准的要求，而且以顾客及其他相关方满意为衡量依据，体现“以顾客为关注焦点”的原则。这个的最典型的例子是麦当劳，他所有的店铺从风格到食物都保持在同一水平，使你无论在那里，都可以得到一定的购物体验。也就构成了对麦当劳的满意性质量的验证。这个软件上也是有例子的，内举不必亲，ThoughtWorks大多数项目都可以达到“满意性质量”，呵呵谁让俺们是consultant涅。<br />我隐约觉得满意性质量应该是一个过程的质量，而不仅仅是软件的质量，但是目前没有好的想法，暂且按下不表。<br /><br />卓越质量<br />......下略100字。个人觉得大多数软件还没有达到适用性质量，大多是过程也都没有达到满意性质量，卓越质量就先不说了吧。<br /><br />总之，我们大体的认为软件质量主要是适用性质量起码是不会错的。那么怎么才能达到这个质量标准涅？俺是做软件的，质量管理还是看看Deming同学怎么说吧，不过他老人家的14点总是发生变化。我也只好断章取义，说说一个敏捷开发人员眼中的14原则：<br /><br />1. 持之以恒地改进产品和服务 Create constancy of purpose for improvement of product and service<br /><br />这个很明显嘛，small release，快速发布，每次发布都是对产品的持续改进。<br /><br />2.采用新的观念 Adopt the new philosophy<br /><br />敏捷啊...<br /><br />3.停止依靠大规模检查去获得质量 Cease dependence on mass inspection<br /><br />这个还有另一个说法，build quality in。TDD，QA/BA全程参与，都是build quality in的好方法。<br /><br />4.结束只以价格为基础的采购习惯 End the practice of awarding business on the basis of price tag alone<br /><br />这个...貌似是说请咨询吧...<br /><br />5.持之以恒地改进生产和服务系统 Improve constantly and forever the system of production and service<br /><br />这个是敏捷过程的持续改进，对应的实践大家可能比较陌生——Restrospective!!!<br /><br />6.实行岗位职能培训 Institute training on the job<br /><br />Pair Programming，Learning Lunch敏捷从来都不缺乏学习的机会，就看你有没有学习的动力了。<br /><br />7. 建立领导力企业管理 Institute leadership<br /><br />敏捷团队的终极目标，自组织团队，的管理是也。<br /><br />8. 排除恐惧 Drive out fear<br /><br />XP第一原则，勇气，不要恐惧。<br /><br />9. 打破部门之间的障碍 Break down barriers between staff areas<br /><br />只有开发团队的敏捷不是真正的敏捷，敏捷说到底，是将软件的供求关系从合约型转为合作型，本来就要是大破障碍。而且障碍不打破，就很难将敏捷实施到底。这也是很多同学尝试敏捷失败的原因，仅仅以为敏捷是技术层面上的事情，其实不是。从这个角度来所，敏捷方法的确是深刻而震撼心灵的变革，有些人...呃...敏捷在十月...<br /><br />10. 取消对员工的标语训词和告诫 Eliminate slogans, exhortations, and targets for the work force<br /><br />恩，什么激情100天...封闭开发...见鬼去吧...不过restrospective的结果是要写在白板上的，准备时刻改进。自我表扬和自我批评，算不上训词吧。<br /><br />11.取消定额管理和目标管理 Eliminate numerical quotas for the work force. Eliminate management by objectives<br /><br />很多人都问过我，pair programming了之后，技校怎么办？嘿嘿，Deming同学已经说了，这样的考核不要也罢。<br /><br />12 消除打击员工工作情感的考评 Remove barriers that rob the hourly worker of his right to pride of workmanship. Remove barriers that rod people in management and in engineering of their right to pride of workmanship<br /><br />敏捷团队的自我评价很简单，360度，由于你几乎跟所有人都pair过，如果所有人都不说你好...这已经是rp问题了，就不是打击这么简单了...<br /><br />13 鼓励学习和自我提高  Encourage education and self-improvement for everyone<br /><br />同前，Pair Programming，Learning Lunch敏捷从来都不缺乏学习的机会，就看你有没有学习的动力了。<br /><br />14 采取行动实现转变 Take action to accomplish the transformation<br /><br />每次restrospective之后必须定出方案，以实践改进。而诸位如果想实施敏捷又觉得难于说服领带，不妨拿Deming同学说说事，这位大老的杀伤力还是曼大的，尤其你老大是MBA的话<img src ="http://www.blogjava.net/raimundox/aggbug/106507.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2007-03-26 20:08 <a href="http://www.blogjava.net/raimundox/archive/2007/03/26/106507.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Why Rails so effective? Delphi Inside</title><link>http://www.blogjava.net/raimundox/archive/2007/03/23/105794.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Fri, 23 Mar 2007 04:10:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2007/03/23/105794.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/105794.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2007/03/23/105794.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/105794.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/105794.html</trackback:ping><description><![CDATA[很长时间以来我对rails框架本身没什么兴趣，因为我从来都不是web fans，15岁那年我打印了一本HTML Reference准备学习一下，感觉完全nonsense。很长一段时间（大约有3年吧）里基本上看到Markup Language我就会大脑短路。但是我对rails背后的东西很感兴趣，是什么让rails如此有效率，一开始我以为是Ruby DSL，但随着做的rails项目越来越多，我发现rails的效率的根源来自它对delphi的继承和发扬。<br /><br />1.  data centric object model Active Record<br />delphi之所以成功，在于它看准了大部分商用软件都是数据库核心的，并为之设计一套相应的框架, delphi的核心就是围绕数据库进行开发(李维同学的borland传奇里写道，当时之所以起名字叫Delphi，就是因为要taking to Oracle)。而rails也很好的在新时代(Web时代)把握了相似的核心点——content是web的核心，以及数据库数据到content的映射是动态web的核心。因此它没有采用所谓的更加严肃的ORM技术。而是依然使用了delphi时代的active record（但是进行了object封装）。如下代码示范了ruby和delphi在active record实现上的相似<br /><br />Ruby<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);">class</span><span style="color: rgb(0, 0, 0);"> Person </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);"> ActiveRecord::Base<br />end<br /><br />x8x </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Person.</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> :name </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">x8x</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"><br />x8x.age </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">15</span></div><br />Delphi<br /><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);">people : TADOTable;<br /><img src="http://www.blogjava.net/images/dot.gif" /><br />begin   <br />   people.Table </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">people</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">;<br />   people.InsertRecord(</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">x8x</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">);<br /><br />   people.First;<br />   people.FieldByName(</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">age</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">) :</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">15</span><span style="color: rgb(0, 0, 0);">;<br />end</span></div><br /><br />可以看出，Delphi的数据库味道更浓一些，而ruby则更多使用了对象的视角（我记得在98年前后（我变成oo狂热分子之后），在写delphi的时候我基本上不会直接使用Table对象了，而是做一些简单的封装，用business object代替直接的数据库对象。但是最后由于和delphi的ui组件结合的不好而放弃）。但是active record的pattern是一致的。<br /><br />2. DB(resource)-aware UI component —— Action View<br /><br />Delphi另一个为人称道的地方是DB－Aware的UI组件，像TDBLabel, TDBMemo还有至今仍位人称道的TDBGrid，极大的简化了UI的开发。不过说到底，仍然是Delphi数据库核心策略的延续。同样，rails的view helper也是db核心的。text_field之类的可以自动感知active record的内容和错误。<br /><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);">&lt;</span><span style="color: rgb(0, 0, 0);">label</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">Name:</span><span style="color: rgb(0, 0, 0);">&lt;/</span><span style="color: rgb(0, 0, 0);">label</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">&lt;%=</span><span style="color: rgb(0, 0, 0);"> text_field </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">person</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">name</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">%&gt;</span></div><br />和<br /><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);">nameLabel : TDBLabel;<br /><br />nameLabel.DataSource </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> peopleTable;<br />nameLabel.Field </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">name</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">;<br />nameLabel.Label </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">Name</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">;<br /></span></div><br />抛开Desktop和web的差异，也可以算是大致相当吧。<br /><br />3. Simple Component Model —— Plan Object as Component<br /><br />Delphi是基于组件开发，并且是非常成功的一个组件模型。基本上有经验的delphi程序员，都会在开发过程中抽象几个VCL component出来简化自己的开发。一方面是DRY精神，另一方面Delphi简单的组件模型使得这样做的代价非常的小。Delphi的组件基本上就是一个对象，重构的过程中修修改改就成组件了。rails其实有类似的机制，而且更简单直接，更符合web时代的胃口，一个对象外加一个helper就可以成为一个UI组件。与此同时rails还有另外一个天然的同盟——Ruby DSL。把以前Delphi需要用UI设计器的地方都用Ruby DSL代替了。这一点是我最近在用rails做曹老师华丽的RedSaga的时候推行DSL geek主义时发现的。比如现在我有这样一个tiny DSL用以定义portlet：<br /><br />in controller<br /><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);">@portlet </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Portlet.</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">do</span><span style="color: rgb(0, 0, 0);"><br />            name </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">administration</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"><br />            title </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">Administration</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"><br />            tabs </span><span style="color: rgb(0, 0, 255);">do</span><span style="color: rgb(0, 0, 0);"><br />                Projects :controller </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">projects</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">, :action </span><span style="color: rgb(0, 0, 0);">=&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">list</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"><br />            end<br />        end</span></div><br />in view<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);">&lt;%=</span><span style="color: rgb(0, 0, 0);"> render_portlet @portlet </span><span style="color: rgb(0, 0, 0);">%&gt;</span></div><br />这种描述/configuration block风格的dsl与delphi组件的初始化非常相似，或者可以说，只有语法上的差异而无思路上的差异（当然delphi可以借助IDE而不是语言来指定这些，但是这个做法是没有生产力的）。<br /><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);">with Portlet </span><span style="color: rgb(0, 0, 255);">do</span><span style="color: rgb(0, 0, 0);"><br />   Label </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> <img src="http://www.blogjava.net/images/dot.gif" /><br />   Name </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> <img src="http://www.blogjava.net/images/dot.gif" />.<br />   Tabs[</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">].Controller </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> <img src="http://www.blogjava.net/images/dot.gif" /><br />   Tabs[</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">].Action </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> <img src="http://www.blogjava.net/images/dot.gif" /><br />end</span></div><br />rails和delphi这种轻量的组件模型，使得构建组件／复用组件级的代价极小。因此可以极大的提高开发效率(我至今仍记得，01年前后接了一个Delphi私活，客户要求Office XP菜单风格，我找了一个XPMenu的控件，直接仍上去，自己的代码一行没改，菜单就Office XP了...)。<br /><br />总之，Delphi的效率要素Rails大部分都学走了，最后简单总结一下rails在delphi基础上的发扬：<br /><br />1. 用ruby而不是object pascal。语法上更灵活简单<br />2. Object Model on top of ActiveRecord，比起Delphi可以跟好的使用OO开发。<br />3. 组件模型更简单<br />4. CoC，这个就不说了<br />5. expressive Ruby DSL<br /><br />最后最后，说一下Delphi for PHP，做得很华丽。但是UI部分我不是很喜欢。<br /><br /><br /><br /><br /><img src ="http://www.blogjava.net/raimundox/aggbug/105794.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2007-03-23 12:10 <a href="http://www.blogjava.net/raimundox/archive/2007/03/23/105794.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The Starting Line of Enter...tainment Ruby</title><link>http://www.blogjava.net/raimundox/archive/2007/01/25/96051.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Thu, 25 Jan 2007 14:08:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2007/01/25/96051.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/96051.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2007/01/25/96051.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/96051.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/96051.html</trackback:ping><description><![CDATA[I got a Sony PSP recently. After playing with it for a while,&nbsp; I
found out that, comparing to other handheld game console, PSP has a
fairly open platform. Some great guys had already customized a gcc
compiler for PSP, and also, a simple toolchain is provided by the
active community to support porting/development/debuging/hacking. So I
decided to port some of my favourite programming langauges to PSP. Of
course, the first one on my list is Ruby.<br />
<br />
Cross compiling,
reading psp documents, reading ruby source code, hacking ruby source
code, cross compiling... after 3 days hard working, finally, I managed
to make the following ruby script(which is listed in the book
&lt;Programming Ruby&gt;) running on my PSP:<br />
<br />
def say_goodnight(name)<br />
&nbsp;&nbsp;&nbsp; "Good night, #{name}"<br />
end<br />
<br />
puts say_goodnight("PSP")<br />
<br />
Bingo~~~! Ruby goes entertainment!!!!<br />
<br />
btw : my ruby-psp patch could be found here:<br />
<a title="https://rubyforge.org/tracker/index.php?func=detail&amp;aid=8134&amp;group_id=426&amp;atid=1700" href="https://rubyforge.org/tracker/index.php?func=detail&amp;aid=8134&amp;group_id=426&amp;atid=1700">https://rubyforge.org/tracker/index.php?func=detail&amp;aid=8134&amp;group_id=426&amp;atid=1700</a><br />
<br />
make sure you have psp-gcc and toolchain installed on you PC, and 3.03-OE/1.5 fireware on your PSP.
<img src ="http://www.blogjava.net/raimundox/aggbug/96051.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2007-01-25 22:08 <a href="http://www.blogjava.net/raimundox/archive/2007/01/25/96051.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>An Issue of Chinese Characters Support in Ruby Watir</title><link>http://www.blogjava.net/raimundox/archive/2006/01/12/27676.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Thu, 12 Jan 2006 02:26:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2006/01/12/27676.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/27676.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2006/01/12/27676.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/27676.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/27676.html</trackback:ping><description><![CDATA[Watir doesn't work well with chinese characters. Try the following codes.<br><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);">ie.text_field(:name,&nbsp;</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">some&nbsp;text&nbsp;field).set(</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">某某</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">)</span></div><br>It will highlight the text field but put nothing in it. I read the Watir source codes, and found an interesting code segment:<br><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, 128, 128);">1</span>&nbsp;<span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">&nbsp;i&nbsp;in&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">&nbsp;..&nbsp;value.length</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;<br></span><span style="color: rgb(0, 128, 128);">2</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;sleep&nbsp;@ieController.typingspeed&nbsp;&nbsp;&nbsp;#&nbsp;typing&nbsp;speed<br></span><span style="color: rgb(0, 128, 128);">3</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;c&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;value[i,</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">]<br></span><span style="color: rgb(0, 128, 128);">4</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;#@ieController.log&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&nbsp;adding&nbsp;c.chr&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, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;c&nbsp;&nbsp;#.chr.to_s<br></span><span style="color: rgb(0, 128, 128);">5</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;@o.value&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;@o.value.to_s&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;c&nbsp;&nbsp;&nbsp;#c.chr<br></span><span style="color: rgb(0, 128, 128);">6</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;fire_key_events<br></span><span style="color: rgb(0, 128, 128);">7</span>&nbsp;<span style="color: rgb(0, 0, 0);">end</span></div><br>The above codes show how Watir simulates typing.If it doesn't work well with chinese characters, There must be something wrong with Ruby string. The first order of business is to figure out how Ruby string works for Chinese string.<br><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, 128, 128);">1</span>&nbsp;<span style="color: rgb(0, 0, 0);">chineseString&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, 0);">'</span><span style="color: rgb(0, 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, 128, 128);">2</span>&nbsp;<span style="color: rgb(0, 0, 0);">puts&nbsp;chineseString.length<br></span><span style="color: rgb(0, 128, 128);">3</span>&nbsp;<span style="color: rgb(0, 0, 0);"></span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">&nbsp;i&nbsp;in&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">..chineseString.length</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 128, 128);">4</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;puts&nbsp;chineseString[i,&nbsp;</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">]<br></span><span style="color: rgb(0, 128, 128);">5</span>&nbsp;<span style="color: rgb(0, 0, 0);">end</span></div><br>result will be:<br><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);">4</span><span style="color: rgb(0, 0, 0);"><br><br><br><br><br></span></div><br>Does Ruby, which is now capturing all java programmers' love, use 8bit char instead of unicode? Holy fuck!<br><br>I made a simple patch for the issue after I woke up from a short coma.<br><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, 128, 128);">&nbsp;1</span>&nbsp;<span style="color: rgb(0, 0, 0);">require&nbsp;</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">Watir</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 128, 128);">&nbsp;2</span>&nbsp;<span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 128, 128);">&nbsp;3</span>&nbsp;<span style="color: rgb(0, 0, 0);">module&nbsp;Watir<br></span><span style="color: rgb(0, 128, 128);">&nbsp;4</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;module&nbsp;Cn<br></span><span style="color: rgb(0, 128, 128);">&nbsp;5</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;IE&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">Watir::IE<br></span><span style="color: rgb(0, 128, 128);">&nbsp;6</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;text_field(how&nbsp;,&nbsp;what</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">nil)<br></span><span style="color: rgb(0, 128, 128);">&nbsp;7</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;TextField.</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">(self,&nbsp;how,&nbsp;what)<br></span><span style="color: rgb(0, 128, 128);">&nbsp;8</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br></span><span style="color: rgb(0, 128, 128);">&nbsp;9</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;end<br></span><span style="color: rgb(0, 128, 128);">10</span>&nbsp;<span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 128, 128);">11</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;TextField&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">&nbsp;Watir::TextField<br></span><span style="color: rgb(0, 128, 128);">12</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;doKeyPress(&nbsp;value&nbsp;)<br></span><span style="color: rgb(0, 128, 128);">13</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin<br></span><span style="color: rgb(0, 128, 128);">14</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;maxLength&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;@o.maxLength<br></span><span style="color: rgb(0, 128, 128);">15</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;value.length&nbsp;</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;maxLength<br></span><span style="color: rgb(0, 128, 128);">16</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;suppliedValue[</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">&nbsp;..&nbsp;maxLength&nbsp;]<br></span><span style="color: rgb(0, 128, 128);">17</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@ieController.log&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&nbsp;Supplied&nbsp;string&nbsp;is&nbsp;#{suppliedValue.length}&nbsp;chars,&nbsp;which&nbsp;exceeds&nbsp;the&nbsp;max&nbsp;length&nbsp;(#{maxLength})&nbsp;of&nbsp;the&nbsp;field.&nbsp;Using&nbsp;value:&nbsp;#{value}</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 128, 128);">18</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br></span><span style="color: rgb(0, 128, 128);">19</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rescue<br></span><span style="color: rgb(0, 128, 128);">20</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;probably&nbsp;a&nbsp;text&nbsp;area&nbsp;</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">&nbsp;so&nbsp;it&nbsp;doesnt&nbsp;have&nbsp;a&nbsp;max&nbsp;Length<br></span><span style="color: rgb(0, 128, 128);">21</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;maxLength&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, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 128, 128);">22</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br></span><span style="color: rgb(0, 128, 128);">23</span>&nbsp;<span style="color: rgb(0, 0, 0);">&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></span><span style="color: rgb(0, 128, 128);">24</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cn.characters_in(value)&nbsp;{</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);">c</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);">&nbsp;<br></span><span style="color: rgb(0, 128, 128);">25</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep&nbsp;@ieController.typingspeed<br></span><span style="color: rgb(0, 128, 128);">26</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@o.value&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;@o.value.to_s&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;c<br></span><span style="color: rgb(0, 128, 128);">27</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fire_key_events}<br></span><span style="color: rgb(0, 128, 128);">28</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br></span><span style="color: rgb(0, 128, 128);">29</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br></span><span style="color: rgb(0, 128, 128);">30</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;<br></span><span style="color: rgb(0, 128, 128);">31</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;Cn.characters_in(value)&nbsp;<br></span><span style="color: rgb(0, 128, 128);">32</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;index&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, 0);">0</span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 128, 128);">33</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">&nbsp;index&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">&nbsp;value.length&nbsp;<br></span><span style="color: rgb(0, 128, 128);">34</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;len&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;value[index]&nbsp;</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">128</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);">&nbsp;</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">&nbsp;:&nbsp;</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 128, 128);">35</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield&nbsp;value[index,&nbsp;len]<br></span><span style="color: rgb(0, 128, 128);">36</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;index&nbsp;</span><span style="color: rgb(0, 0, 0);">+=</span><span style="color: rgb(0, 0, 0);">&nbsp;len<br></span><span style="color: rgb(0, 128, 128);">37</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;<br></span><span style="color: rgb(0, 128, 128);">38</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br></span><span style="color: rgb(0, 128, 128);">39</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;end<br></span><span style="color: rgb(0, 128, 128);">40</span>&nbsp;<span style="color: rgb(0, 0, 0);">end</span></div><br>I submitted this patch to Watir tracing systsem,and zipped codes could be found here:<br>http://rubyforge.org/tracker/index.php?func=detail&amp;aid=3232&amp;group_id=104&amp;atid=489<br><img src ="http://www.blogjava.net/raimundox/aggbug/27676.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2006-01-12 10:26 <a href="http://www.blogjava.net/raimundox/archive/2006/01/12/27676.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>A Pragmatic Way to Make "Squeak 3D Browser"</title><link>http://www.blogjava.net/raimundox/archive/2005/12/27/25601.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Tue, 27 Dec 2005 08:54:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2005/12/27/25601.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/25601.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2005/12/27/25601.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/25601.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/25601.html</trackback:ping><description><![CDATA[There is an article about <a href="http://www.bitwisemag.com/copy/programming/smalltalk/squeak_3dbrowser.html">how to make a "Squeak 3D Browser"</a>.And the nice guy who wrote the article also put <a href="http://www.bitwisemag.com/media/flash/tutorials/prog/smalltalk/3dbrowser/ft_3dbrowser.html">a flash demo</a>.It's an amazing demo to show how interesting programming in Squeak could be.But I don't like the too-many-GUI-way which the guy used. I thought there might be a more pragmatic way to do the same thing so I spent an hour on making a script, and finally I got it ;-)<br><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);">Preferences&nbsp;enable:&nbsp;#systemWindowEmbedOK.<br><br>myBrowserWindow&nbsp;:</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;Browser&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;openEditString:#Hello.&nbsp;<br>myBrowserWindow&nbsp;setLabel:</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">System&nbsp;Browser</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">;&nbsp;bounds:&nbsp;(Rectangle&nbsp;left:</span><span style="color: rgb(0, 0, 0);">20</span><span style="color: rgb(0, 0, 0);">&nbsp;right:</span><span style="color: rgb(0, 0, 0);">600</span><span style="color: rgb(0, 0, 0);">&nbsp;top:</span><span style="color: rgb(0, 0, 0);">20</span><span style="color: rgb(0, 0, 0);">&nbsp;bottom:</span><span style="color: rgb(0, 0, 0);">400</span><span style="color: rgb(0, 0, 0);">).<br><br>my3DIDE&nbsp;:</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;Wonderland&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">.<br>my3DIDE&nbsp;getDefaultCamera&nbsp;getMorph&nbsp;bounds:&nbsp;(Rectangle&nbsp;left:</span><span style="color: rgb(0, 0, 0);">20</span><span style="color: rgb(0, 0, 0);">&nbsp;right:</span><span style="color: rgb(0, 0, 0);">800</span><span style="color: rgb(0, 0, 0);">&nbsp;top:&nbsp;</span><span style="color: rgb(0, 0, 0);">20</span><span style="color: rgb(0, 0, 0);">&nbsp;bottom:&nbsp;</span><span style="color: rgb(0, 0, 0);">600</span><span style="color: rgb(0, 0, 0);">).<br><br>my3DBrowser&nbsp;:</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;my3DIDE&nbsp;makePlaneNamed:&nbsp;</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">System&nbsp;Browser</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">.<br>my3DBrowser&nbsp;setY:</span><span style="color: rgb(0, 0, 0);">50</span><span style="color: rgb(0, 0, 0);">;&nbsp;turn:#right&nbsp;turns:</span><span style="color: rgb(0, 0, 0);">0.38</span><span style="color: rgb(0, 0, 0);">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setProperty:&nbsp;#adjustToTexture&nbsp;toValue:&nbsp;</span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setTexturePointer:&nbsp;myBrowserWindow;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setProperty:&nbsp;#activeTexture&nbsp;toValue:&nbsp;</span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">.<br></span></div><br>Try it and have fun! <img src ="http://www.blogjava.net/raimundox/aggbug/25601.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2005-12-27 16:54 <a href="http://www.blogjava.net/raimundox/archive/2005/12/27/25601.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>I'm a RSSer</title><link>http://www.blogjava.net/raimundox/archive/2005/12/20/24873.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Tue, 20 Dec 2005 13:48:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2005/12/20/24873.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/24873.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2005/12/20/24873.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/24873.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/24873.html</trackback:ping><description><![CDATA[RSS may be one of the&nbsp;most delusive terms, it could stand for 'RDF Site Summary', 'Rich Site Summary', 'Really Simple Syndication' or other things.Today I introduce a brand-new meaning of RSS: Ruby.Smalltalk.Scheme, which are my beloved&nbsp;top&nbsp;3&nbsp;programming languages in ascending order.The more I write in Ruby, the more I think in Smalltalk;And the more I think in Smalltalk, the more I love Scheme.Abstract concepts&nbsp;in Scheme, think objects&nbsp;in Smalltalk and write codes&nbsp;in Ruby, cool!<img src ="http://www.blogjava.net/raimundox/aggbug/24873.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2005-12-20 21:48 <a href="http://www.blogjava.net/raimundox/archive/2005/12/20/24873.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>A Walk On JSR220 Persistent API...More Ugly More Cool</title><link>http://www.blogjava.net/raimundox/archive/2005/12/13/23721.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Tue, 13 Dec 2005 11:25:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2005/12/13/23721.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/23721.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2005/12/13/23721.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/23721.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/23721.html</trackback:ping><description><![CDATA[<P>Frank and I collected some Hibernate tips, and we named them with some sexy names ;-) This afternoon I tried to replace hibernate by JSR220 persistent API in a typical web application, and I found some new tips in JSR220 Persisntent API (Frank, I'm here waiting your names).<BR><BR>btw: I'm a believer in Peter Coad's Color Modeling approach, all the following tips are modeled in the approach. I recommend you the greate book 'Java Modeling in Color with UML' if you'd no idea about the Color UML.</P>
<P>1. Annotating Description with @Embeddable, and the Thing it describe with @Entity</P>
<P>Take Product and ProductDescription for example.</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #008080">&nbsp;1</SPAN><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">@Embeddable<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;2</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_37_118_Open_Image onclick="this.style.display='none'; Codehighlighter1_37_118_Open_Text.style.display='none'; Codehighlighter1_37_118_Closed_Image.style.display='inline'; Codehighlighter1_37_118_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_37_118_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_37_118_Closed_Text.style.display='none'; Codehighlighter1_37_118_Open_Image.style.display='inline'; Codehighlighter1_37_118_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;ProductDescription&nbsp;</SPAN><SPAN id=Codehighlighter1_37_118_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_37_118_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;3</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;String&nbsp;name;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;4</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;String&nbsp;description;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;5</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;.&nbsp;and&nbsp;getters&nbsp;and&nbsp;setters<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;6</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;7</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;8</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>@Entity(access&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;AccessType.FIELD)<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;9</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_170_215_Open_Image onclick="this.style.display='none'; Codehighlighter1_170_215_Open_Text.style.display='none'; Codehighlighter1_170_215_Closed_Image.style.display='inline'; Codehighlighter1_170_215_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_170_215_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_170_215_Closed_Text.style.display='none'; Codehighlighter1_170_215_Open_Image.style.display='inline'; Codehighlighter1_170_215_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;Product&nbsp;</SPAN><SPAN id=Codehighlighter1_170_215_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_170_215_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">10</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">11</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;ProdcutDescription&nbsp;description;<BR></SPAN><SPAN style="COLOR: #008080">12</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">13</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">14</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN></DIV>
<P>In hiberante, we could&nbsp;make the ProductDescription as an embedded persistent object of Product via the component tag.If the ProductDescription should be embedded in another object, we've to declare it once more.<BR>Things become more convenient in JSR 220, because non-transite fields, whose class is annoated with @Embeddable, are treated as embedded persistent objects automatically, we'd have fine-grained persistent objects without long-winded config file.</P>
<P>2.Avoiding Database Field in Domain Model Using @AttributeOverride </P>
<P>It's claimed that Annotaton could simplify development, but considering the cost of hard-coding mapping information in source codes I prefer some other complicated ways.It's too ugly to write code like following.</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #008080">1</SPAN><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">@Entity(access&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;AccessType.FIELD)<BR></SPAN><SPAN style="COLOR: #008080">2</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>@Table(name</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">TAB_PRODUCT</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">)<BR></SPAN><SPAN style="COLOR: #008080">3</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_76_165_Open_Image onclick="this.style.display='none'; Codehighlighter1_76_165_Open_Text.style.display='none'; Codehighlighter1_76_165_Closed_Image.style.display='inline'; Codehighlighter1_76_165_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_76_165_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_76_165_Closed_Text.style.display='none'; Codehighlighter1_76_165_Open_Image.style.display='inline'; Codehighlighter1_76_165_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;Product&nbsp;</SPAN><SPAN id=Codehighlighter1_76_165_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_76_165_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">4</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">5</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;@Basic<BR></SPAN><SPAN style="COLOR: #008080">6</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;@Column(name</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">NAME</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;nullable</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #0000ff">false</SPAN><SPAN style="COLOR: #000000">,&nbsp;length</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">512</SPAN><SPAN style="COLOR: #000000">)<BR></SPAN><SPAN style="COLOR: #008080">7</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;String&nbsp;name;<BR></SPAN><SPAN style="COLOR: #008080">8</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN></DIV>
<P>It's sucks but could be avoided.</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #008080">&nbsp;1</SPAN><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">@EmbeddableSuperclass<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;2</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_36_71_Open_Image onclick="this.style.display='none'; Codehighlighter1_36_71_Open_Text.style.display='none'; Codehighlighter1_36_71_Closed_Image.style.display='inline'; Codehighlighter1_36_71_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_36_71_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_36_71_Closed_Text.style.display='none'; Codehighlighter1_36_71_Open_Image.style.display='inline'; Codehighlighter1_36_71_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;Product&nbsp;</SPAN><SPAN id=Codehighlighter1_36_71_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_36_71_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;3</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;4</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;@Basic<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;5</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;String&nbsp;name;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;6</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;7</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;8</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>@Entity<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;9</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>@AttributeOverride(name</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">name</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;column</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">@Column(name</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">Name</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">))<BR></SPAN><SPAN style="COLOR: #008080">10</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>@Table(name</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">TAB_PRODUCT</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">)<BR></SPAN><SPAN style="COLOR: #008080">11</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_210_212_Open_Image onclick="this.style.display='none'; Codehighlighter1_210_212_Open_Text.style.display='none'; Codehighlighter1_210_212_Closed_Image.style.display='inline'; Codehighlighter1_210_212_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_210_212_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_210_212_Closed_Text.style.display='none'; Codehighlighter1_210_212_Open_Image.style.display='inline'; Codehighlighter1_210_212_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;PersistentProduct&nbsp;</SPAN><SPAN style="COLOR: #0000ff">extends</SPAN><SPAN style="COLOR: #000000">&nbsp;Product&nbsp;</SPAN><SPAN id=Codehighlighter1_210_212_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_210_212_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">12</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN></DIV>
<P>We could separate the domain model and the persistent model by inheritance.Although we could do&nbsp;the same thing&nbsp;in hiberante too, we have to provide lots of configuration files.Once more we'd have hierachical persistent objects without long-winded config file.</P>
<P>3.Avoiding Database Primary Key in Domain Model</P>
<P>In most O/R mapping framework, we are always asked to give a primary key or identifier to our domain model, and we are suggested using meanless identifier instead of domain-specified identifer.It's kinda of Domain Pollution.Although we couldmake the domain model more clearer&nbsp;via inheritance, it's pointless for common usages.<BR>Fortunately, we HAVE TO separate domain model and persistent model(as above mentioned), so that we can throw this bad habit away conviniently :D </P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #008080">1</SPAN><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">@EmbeddableSuperclass<BR></SPAN><SPAN style="COLOR: #008080">2</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_36_38_Open_Image onclick="this.style.display='none'; Codehighlighter1_36_38_Open_Text.style.display='none'; Codehighlighter1_36_38_Closed_Image.style.display='inline'; Codehighlighter1_36_38_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_36_38_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_36_38_Closed_Text.style.display='none'; Codehighlighter1_36_38_Open_Image.style.display='inline'; Codehighlighter1_36_38_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;Product&nbsp;</SPAN><SPAN id=Codehighlighter1_36_38_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_36_38_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">3</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">4</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">5</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>@Entity<BR></SPAN><SPAN style="COLOR: #008080">6</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_88_123_Open_Image onclick="this.style.display='none'; Codehighlighter1_88_123_Open_Text.style.display='none'; Codehighlighter1_88_123_Closed_Image.style.display='inline'; Codehighlighter1_88_123_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_88_123_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_88_123_Closed_Text.style.display='none'; Codehighlighter1_88_123_Open_Image.style.display='inline'; Codehighlighter1_88_123_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;PersistentProduct&nbsp;</SPAN><SPAN style="COLOR: #0000ff">extends</SPAN><SPAN style="COLOR: #000000">&nbsp;Product</SPAN><SPAN id=Codehighlighter1_88_123_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_88_123_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">7</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">8</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;@Id&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">long</SPAN><SPAN style="COLOR: #000000">&nbsp;primaryKey;<BR></SPAN><SPAN style="COLOR: #008080">9</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN></DIV>
<P>Conclusion</P>
<P>After two hours walking around JSR220 persistent API, I figured out that JSR220 mixed ugly into convenience... and it's quite easy to write ugly codes in jsr220...so that we've to insist on using OO and the convenience jsr220 provided to make our domain model as clear as possible.<BR>Although JSR220 is more ugly than hibernate, we could get clearer domain model in jsr220 rather than hibernate, because we could not stand the unly in jsr220...weird way to make us keeping more OO...cool isn't it...</P><img src ="http://www.blogjava.net/raimundox/aggbug/23721.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2005-12-13 19:25 <a href="http://www.blogjava.net/raimundox/archive/2005/12/13/23721.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Why Inconsistent Concepts Considered Harmful</title><link>http://www.blogjava.net/raimundox/archive/2005/12/11/23298.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Sat, 10 Dec 2005 17:59:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2005/12/11/23298.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/23298.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2005/12/11/23298.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/23298.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/23298.html</trackback:ping><description><![CDATA[<P>Tao Wen , a friend&nbsp;of mine and a new ThoughtWorker, put a comment on my last article.</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">so</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #000000">&nbsp;you&nbsp;think&nbsp;the&nbsp;consistent&nbsp;thing&nbsp;means&nbsp;a&nbsp;lot?&nbsp;But&nbsp;how&nbsp;do&nbsp;you&nbsp;think&nbsp;the&nbsp;gracious&nbsp;or&nbsp;elegant&nbsp;feeling&nbsp;mean&nbsp;to&nbsp;the&nbsp;real&nbsp;expressiveness&nbsp;of&nbsp;business&nbsp;requirements?&nbsp;We&nbsp;can&nbsp;see&nbsp;lisp&nbsp;is&nbsp;very&nbsp;successful&nbsp;in&nbsp;researching&nbsp;area&nbsp;because&nbsp;of&nbsp;the&nbsp;simplicity&nbsp;nature&nbsp;inside&nbsp;which&nbsp;is&nbsp;also&nbsp;true&nbsp;to&nbsp;Smalltalk.&nbsp;But&nbsp;why&nbsp;they&nbsp;aren't&nbsp;successful&nbsp;in&nbsp;biz&nbsp;world?&nbsp;I&nbsp;think&nbsp;that&nbsp;is&nbsp;the&nbsp;problem&nbsp;you&nbsp;should&nbsp;further&nbsp;study</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">how&nbsp;can&nbsp;the&nbsp;consistent&nbsp;feeling&nbsp;mean&nbsp;something&nbsp;to&nbsp;our&nbsp;everyday&nbsp;programming&nbsp;life?</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">.</SPAN></DIV>
<P>First of all, I should&nbsp;admit that I'd never thought about this question before, becasuse I think hankering after consistent concepts is some nature of us. The question enlightens me to thinking deep. Here are my points.</P>
<P>1.Complexity</P>
<P>Inconsistent concepts bring complexity.I'll give two examples. </P>
<P>First one is something in Lisp. Lisp has a very simple computing model called λ Calculation. There are three elements in this computing model: Function, λ Operator and · Operator. λ Operator picks up free variable from the function, and · Operator applies the variable with a concrete value. The whole evaluation-application thing is what we called symbolic algebra in math.For example, if we've a function whose expression is x + y.</P>
<P></P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">((λx&nbsp;(λy&nbsp;.&nbsp;x&nbsp;</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;y)·</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">)·</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">)<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">((λx.&nbsp;x</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">)·</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">)<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">7</SPAN></DIV>
<P>Since Lisp is kinda implementation of λ Calculation in computer, we could do the same thing in Lisp (and its dialects).</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">(define&nbsp;f&nbsp;(lambda&nbsp;x&nbsp;(lambda&nbsp;y&nbsp;(</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;x&nbsp;y))))<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>(apply&nbsp;(apply&nbsp;f&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">)&nbsp;</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">)</SPAN></DIV>
<P>or we could use some syntax sugar </P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">(define&nbsp;(f&nbsp;x&nbsp;y)&nbsp;(</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;x&nbsp;y))<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>((f&nbsp;</SPAN><SPAN style="COLOR: #000000">3)</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">)</SPAN></DIV>
<P>Most of things&nbsp;in Lisp&nbsp;are focus on evaluation, and the evaluation should&nbsp;be done in a simple consistent way: evaluating, applying value&nbsp;and then returning the value without any change to enviroment.&nbsp;It is the very same&nbsp;way that&nbsp;we do something&nbsp;in math.<BR>But variable assignment was introduced to Lisp, so some functions&nbsp; which change enviroment instead of simple evaluating came to Lisp.For example:</P>
<P></P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">(define&nbsp;(bad</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">f&nbsp;x&nbsp;y)&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;(begin&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set</SPAN><SPAN style="COLOR: #000000">!</SPAN><SPAN style="COLOR: #000000">&nbsp;z&nbsp;</SPAN><SPAN style="COLOR: #000000">5</SPAN><SPAN style="COLOR: #000000">)<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;x&nbsp;y)))</SPAN></DIV>
<P>That&nbsp;bad function changes value of symbol 'z' while evaluating x + y. It is the variable assignment&nbsp;which breaks the consistent concepts. The consistent concepts suggests that function should&nbsp;do and only do evaluation. We must find a more complicated computing model&nbsp;to replace&nbsp;the simple elegant mathematical one.Here inconsistent brings complexities in computing model.</P>
<P>The other example comes from Java. Java is considered to be an object-oriented programming language with single root type system. Conceptually speaking, everything should be an object.But for some perfermance reason, Java has some primitive types (such as int, double, float etc.) too.Those primitive types introduced a algebraic world which paralleled to the object world, and broke the consistent concepts.Althought Java has some wrapper classes for those primtive types, they are not enough for filling the&nbsp;gulf between object and algebra.<BR>We could use new Integer(3) to represent 3 in object world, but we could not simply translate</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">5</SPAN></DIV>
<P>to</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Integer(</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">)&nbsp;</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Integer(</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">)&nbsp;</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Integer(</SPAN><SPAN style="COLOR: #000000">5</SPAN><SPAN style="COLOR: #000000">)</SPAN></DIV>
<P>Algebraic calculation&nbsp;and&nbsp;&nbsp;object message sending are totally different. Although we could do that in Java 5,&nbsp;it also has lots of differences.Auto-boxing treats object as primitive instead of operator overloading in C++&nbsp;which treats operator as object message&nbsp;sending.So in my opinion,&nbsp;auto-boxing in java5 is awful.&nbsp;Assginments and storage of primitive type and object&nbsp;have&nbsp;lots inconsistent semantics too. This inconsistent would&nbsp;bring complexity when we use Collection API(Remember Primitive Collection in Commons Collection Project? )<BR><BR>2. Side-Effect<BR><BR>The mainly cause of side-effect is&nbsp;&nbsp;putting some inconsistent concepts together. I'll also give&nbsp;two examples.<BR><BR>First example is the well-known side-effect in functional programming, which is caused by mixing Von-Nouma-style-things into λ Calculation. There are lots of discussion about this topic in&nbsp;functional programming community.It's meanless to&nbsp;repeat that again.<BR><BR>Second example comes from half-blooded object-oriented languages, for we'll find both object-oriented things&nbsp;and procedure-oriented things in these languages, and it'll be much more easier to write code in procedural way instead of object-oriented&nbsp;way.For example, we'd write code like this:</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #008080">1</SPAN><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(order.getState()&nbsp;</SPAN><SPAN style="COLOR: #000000">==</SPAN><SPAN style="COLOR: #000000">&nbsp;Order.CANCEL)<BR></SPAN><SPAN style="COLOR: #008080">2</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">do</SPAN><SPAN style="COLOR: #000000">&nbsp;something&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">&nbsp;cancel;<BR></SPAN><SPAN style="COLOR: #008080">3</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">else</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">(order.getState()&nbsp;</SPAN><SPAN style="COLOR: #000000">==</SPAN><SPAN style="COLOR: #000000">&nbsp;Order.PAID)<BR></SPAN><SPAN style="COLOR: #008080">4</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">do</SPAN><SPAN style="COLOR: #000000">&nbsp;something&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">&nbsp;paid;<BR></SPAN><SPAN style="COLOR: #008080">5</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">else</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">(order.getState()&nbsp;</SPAN><SPAN style="COLOR: #000000">==</SPAN><SPAN style="COLOR: #000000">&nbsp;Order.DELIVERY)<BR></SPAN><SPAN style="COLOR: #008080">6</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">do</SPAN><SPAN style="COLOR: #000000">&nbsp;something&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">&nbsp;delivery</SPAN></DIV><BR>instead of :<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #008080">&nbsp;1</SPAN><IMG id=Codehighlighter1_27_166_Open_Image onclick="this.style.display='none'; Codehighlighter1_27_166_Open_Text.style.display='none'; Codehighlighter1_27_166_Closed_Image.style.display='inline'; Codehighlighter1_27_166_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_27_166_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_27_166_Closed_Text.style.display='none'; Codehighlighter1_27_166_Open_Image.style.display='inline'; Codehighlighter1_27_166_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">abstract</SPAN><SPAN style="COLOR: #000000">&nbsp;OrderState&nbsp;</SPAN><SPAN id=Codehighlighter1_27_166_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_27_166_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;2</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;3</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">protected</SPAN><SPAN style="COLOR: #000000">&nbsp;Order&nbsp;_order;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;4</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;5</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_97_124_Open_Image onclick="this.style.display='none'; Codehighlighter1_97_124_Open_Text.style.display='none'; Codehighlighter1_97_124_Closed_Image.style.display='inline'; Codehighlighter1_97_124_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_97_124_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_97_124_Closed_Text.style.display='none'; Codehighlighter1_97_124_Open_Image.style.display='inline'; Codehighlighter1_97_124_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">protected</SPAN><SPAN style="COLOR: #000000">&nbsp;OrderState(Order&nbsp;order)</SPAN><SPAN id=Codehighlighter1_97_124_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_97_124_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;6</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_order&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;order;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;7</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;8</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;9</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">abstract</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;handler();<BR></SPAN><SPAN style="COLOR: #008080">10</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">11</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">12</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_206_272_Open_Image onclick="this.style.display='none'; Codehighlighter1_206_272_Open_Text.style.display='none'; Codehighlighter1_206_272_Closed_Image.style.display='inline'; Codehighlighter1_206_272_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_206_272_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_206_272_Closed_Text.style.display='none'; Codehighlighter1_206_272_Open_Image.style.display='inline'; Codehighlighter1_206_272_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;CancelState&nbsp;</SPAN><SPAN style="COLOR: #0000ff">extends</SPAN><SPAN style="COLOR: #000000">&nbsp;OrderState&nbsp;</SPAN><SPAN id=Codehighlighter1_206_272_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_206_272_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">13</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">14</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_234_270_Open_Image onclick="this.style.display='none'; Codehighlighter1_234_270_Open_Text.style.display='none'; Codehighlighter1_234_270_Closed_Image.style.display='inline'; Codehighlighter1_234_270_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_234_270_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_234_270_Closed_Text.style.display='none'; Codehighlighter1_234_270_Open_Image.style.display='inline'; Codehighlighter1_234_270_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;handler()&nbsp;</SPAN><SPAN id=Codehighlighter1_234_270_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_234_270_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">15</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">do</SPAN><SPAN style="COLOR: #000000">&nbsp;something&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">&nbsp;cancel;<BR></SPAN><SPAN style="COLOR: #008080">16</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">17</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">18</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">19</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>order.getState().handle();</SPAN></DIV><BR>For the keywords, it's convenient to write procedural&nbsp;codes as first segment, but for easy maintenance, it's better to write object-oriented codes as the second one.There are two inconsistent way to write code, and the side-effect is depend on how object-oriented the language is. It's more easy to write code like first one in&nbsp;C++ , and more easy to write code like second one in Ruby and Smalltalk. Actually, it's very&nbsp;hard for me to write code like first one in Smalltalk.<BR><BR>3. Constructing Software in a Recursive Way<BR><BR>There is a more large topic, maybe I'd better&nbsp;talk about this latter.<BR><BR>4. Elegance<BR><BR>Some aesthetic feelings comes from consistent concepts.I'll have the feeling of&nbsp;elegance if I could&nbsp;understand some complicated things&nbsp;via&nbsp;some consistent concepts.Take Newtonian System and Maxwell formula for example, they both are the elegant way to resolve problem via few consistent concepts. <img src ="http://www.blogjava.net/raimundox/aggbug/23298.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2005-12-11 01:59 <a href="http://www.blogjava.net/raimundox/archive/2005/12/11/23298.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Say sorry to Object-Oriented Methodology</title><link>http://www.blogjava.net/raimundox/archive/2005/12/08/23028.html</link><dc:creator>Raimundox</dc:creator><author>Raimundox</author><pubDate>Thu, 08 Dec 2005 12:39:00 GMT</pubDate><guid>http://www.blogjava.net/raimundox/archive/2005/12/08/23028.html</guid><wfw:comment>http://www.blogjava.net/raimundox/comments/23028.html</wfw:comment><comments>http://www.blogjava.net/raimundox/archive/2005/12/08/23028.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/raimundox/comments/commentRss/23028.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raimundox/services/trackbacks/23028.html</trackback:ping><description><![CDATA[<P class=MsoNormal style="MARGIN: 0in 0in 0pt">Recently I came to <A>know</A> and started to learn Smalltalk, an age-old pure Object-Oriented programming language. I <A>fell</A> in love with it quickly. Smalltalk is a very small language with some consistent concepts and abundant class libraries. I was puzzled at the very begining,&nbsp;&nbsp;<A>as</A> Smalltalk has very few keywords(maybe 5 I think), and those keywords don't&nbsp;<A>include</A><SPAN class=MsoCommentReference><SPAN>&nbsp;</SPAN></SPAN>any control structure(a.k.a if, while, for), how could we write programs? Althougth <A>I know we could implement iterative sturucture via recursion, how about conditional execution</A>? Finally I figured out that Smalltalk provides control strucutre in its class library only using some basic OO concepts. Followings are the codes <A>from</A> Smalltalk class library.<?xml:namespace prefix = o /><o:p></o:p></P>
<DIV>
<DIV>
<DIV language=JavaScript class=msocomtxt id=_com_6 onmouseover="msoCommentShow('_anchor_6','_com_6')" onmouseout="msoCommentHide('_com_6')">
<P class=MsoCommentText style="MARGIN: 0in 0in 0pt"><o:p><BR></o:p></P>
<DIV style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><SPAN style="COLOR: rgb(0,128,128)">&nbsp;1</SPAN><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: rgb(0,0,0)">Boolean</SPAN><SPAN style="COLOR: rgb(0,0,0)">&gt;&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)">ifTrue:&nbsp;alternativeBlock&nbsp;<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">&nbsp;2</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;self&nbsp;subclassResponsibility<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">&nbsp;3</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">&nbsp;4</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>Boolean</SPAN><SPAN style="COLOR: rgb(0,0,0)">&gt;&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)">ifFalse:&nbsp;alternativeBlock<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">&nbsp;5</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;self&nbsp;subclassResponsibility<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">&nbsp;6</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">&nbsp;7</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>"and&nbsp;True&nbsp;and&nbsp;False&nbsp;are&nbsp;subclasses&nbsp;of&nbsp;Boolean."<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">&nbsp;8</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">&nbsp;9</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>True</SPAN><SPAN style="COLOR: rgb(0,0,0)">&gt;&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)">ifTrue:&nbsp;alternativeBlock&nbsp;<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">10</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0)">^</SPAN><SPAN style="COLOR: rgb(0,0,0)">alternativeBlock&nbsp;value<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">11</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">12</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>True</SPAN><SPAN style="COLOR: rgb(0,0,0)">&gt;&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)">ifFalse:&nbsp;alternativeBlock<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">13</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0)">^</SPAN><SPAN style="COLOR: rgb(0,0,0)">nil<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">14</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">15</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>False</SPAN><SPAN style="COLOR: rgb(0,0,0)">&gt;&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)">ifTrue:&nbsp;alternativeBlock&nbsp;<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">16</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0)">^</SPAN><SPAN style="COLOR: rgb(0,0,0)">nil<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">17</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">18</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>False</SPAN><SPAN style="COLOR: rgb(0,0,0)">&gt;&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)">ifFalse:&nbsp;alternativeBlock<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">19</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0)">^</SPAN><SPAN style="COLOR: rgb(0,0,0)">alternativeBlock&nbsp;value</SPAN></DIV></DIV></DIV></DIV><BR>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt">and then in some codes, we could do the conditional execution<SPAN class=MsoCommentReference><SPAN>&nbsp;</SPAN></SPAN>as <A>follow</A>s<BR><o:p><BR></o:p></P>
<DIV style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><SPAN style="COLOR: rgb(0,128,128)">1</SPAN><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: rgb(0,0,0)">4</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0)">3</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;ifTrue:&nbsp;[Transcript&nbsp;show:&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0)">'</SPAN><SPAN style="COLOR: rgb(0,0,0)">Hello</SPAN><SPAN style="COLOR: rgb(0,0,0)">'</SPAN><SPAN style="COLOR: rgb(0,0,0)">]</SPAN></DIV>
<DIV>
<DIV>
<DIV language=JavaScript class=msocomtxt id=_com_2 onmouseover="msoCommentShow('_anchor_2','_com_2')" onmouseout="msoCommentHide('_com_2')">
<P class=MsoCommentText style="MARGIN: 0in 0in 0pt"><o:p><BR></o:p></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt">In Smalltalk, everything is Object, so that the code above means sending a message named '&gt;' to an Integer object, whose value is 4, with an Integer object parameter. And '&gt;' would return a Boolean object, and then we sent a <A>message</A><SPAN class=MsoCommentReference><SPAN>&nbsp;</SPAN></SPAN> named 'ifTrue' to it. This is a typical usage of State Pattern. Here are the equivalent Java codes.<o:p></o:p></P>
<DIV>
<DIV>
<DIV language=JavaScript class=msocomtxt id=_com_1 onmouseover="msoCommentShow('_anchor_1','_com_1')" onmouseout="msoCommentHide('_com_1')">
<P class=MsoCommentText style="MARGIN: 0in 0in 0pt"><o:p><BR></o:p></P>
<DIV style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><SPAN style="COLOR: rgb(0,128,128)">&nbsp;1</SPAN><IMG id=Codehighlighter1_30_216_Open_Image onclick="this.style.display='none'; Codehighlighter1_30_216_Open_Text.style.display='none'; Codehighlighter1_30_216_Closed_Image.style.display='inline'; Codehighlighter1_30_216_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_30_216_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_30_216_Closed_Text.style.display='none'; Codehighlighter1_30_216_Open_Image.style.display='inline'; Codehighlighter1_30_216_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top><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)">class</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">abstract</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;Boolean&nbsp;</SPAN><SPAN id=Codehighlighter1_30_216_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_30_216_Open_Text><SPAN style="COLOR: rgb(0,0,0)">{<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">&nbsp;2</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><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;</SPAN><SPAN style="COLOR: rgb(0,0,255)">final</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;TRUE&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;True();<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">&nbsp;3</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><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;</SPAN><SPAN style="COLOR: rgb(0,0,255)">final</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;FALSE&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;False();<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">&nbsp;4</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">&nbsp;5</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><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)">abstract</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;Object&nbsp;ifTrue(Block&nbsp;aBlock);<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">&nbsp;6</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><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)">abstract</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;Object&nbsp;ifFalse(Block&nbsp;aBlock);<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">&nbsp;7</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">&nbsp;8</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">&nbsp;9</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG id=Codehighlighter1_246_393_Open_Image onclick="this.style.display='none'; Codehighlighter1_246_393_Open_Text.style.display='none'; Codehighlighter1_246_393_Closed_Image.style.display='inline'; Codehighlighter1_246_393_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_246_393_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_246_393_Closed_Text.style.display='none'; Codehighlighter1_246_393_Open_Image.style.display='inline'; Codehighlighter1_246_393_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN style="COLOR: rgb(0,0,255)">class</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;True&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">extends</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;Boolean&nbsp;</SPAN><SPAN id=Codehighlighter1_246_393_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_246_393_Open_Text><SPAN style="COLOR: rgb(0,0,0)">{<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">10</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">11</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG id=Codehighlighter1_287_324_Open_Image onclick="this.style.display='none'; Codehighlighter1_287_324_Open_Text.style.display='none'; Codehighlighter1_287_324_Closed_Image.style.display='inline'; Codehighlighter1_287_324_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_287_324_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_287_324_Closed_Text.style.display='none'; Codehighlighter1_287_324_Open_Image.style.display='inline'; Codehighlighter1_287_324_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">public</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;Object&nbsp;ifTrue(Block&nbsp;aBlock)&nbsp;</SPAN><SPAN id=Codehighlighter1_287_324_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_287_324_Open_Text><SPAN style="COLOR: rgb(0,0,0)">{<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">12</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">return</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;aBlock.execute();<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">13</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">14</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">15</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG id=Codehighlighter1_366_391_Open_Image onclick="this.style.display='none'; Codehighlighter1_366_391_Open_Text.style.display='none'; Codehighlighter1_366_391_Closed_Image.style.display='inline'; Codehighlighter1_366_391_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_366_391_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_366_391_Closed_Text.style.display='none'; Codehighlighter1_366_391_Open_Image.style.display='inline'; Codehighlighter1_366_391_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">public</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;Object&nbsp;ifFalse(Block&nbsp;aBlock)&nbsp;</SPAN><SPAN id=Codehighlighter1_366_391_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_366_391_Open_Text><SPAN style="COLOR: rgb(0,0,0)">{<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">16</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">return</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">null</SPAN><SPAN style="COLOR: rgb(0,0,0)">;<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">17</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">18</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">19</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">20</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG id=Codehighlighter1_424_578_Open_Image onclick="this.style.display='none'; Codehighlighter1_424_578_Open_Text.style.display='none'; Codehighlighter1_424_578_Closed_Image.style.display='inline'; Codehighlighter1_424_578_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_424_578_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_424_578_Closed_Text.style.display='none'; Codehighlighter1_424_578_Open_Image.style.display='inline'; Codehighlighter1_424_578_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN style="COLOR: rgb(0,0,255)">class</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;False&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">extends</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;Boolean&nbsp;</SPAN><SPAN id=Codehighlighter1_424_578_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_424_578_Open_Text><SPAN style="COLOR: rgb(0,0,0)">{<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">21</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">22</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG id=Codehighlighter1_465_490_Open_Image onclick="this.style.display='none'; Codehighlighter1_465_490_Open_Text.style.display='none'; Codehighlighter1_465_490_Closed_Image.style.display='inline'; Codehighlighter1_465_490_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_465_490_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_465_490_Closed_Text.style.display='none'; Codehighlighter1_465_490_Open_Image.style.display='inline'; Codehighlighter1_465_490_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">public</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;Object&nbsp;ifTrue(Block&nbsp;aBlock)&nbsp;</SPAN><SPAN id=Codehighlighter1_465_490_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_465_490_Open_Text><SPAN style="COLOR: rgb(0,0,0)">{<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">23</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">return</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">null</SPAN><SPAN style="COLOR: rgb(0,0,0)">;<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">24</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">25</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">26</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG id=Codehighlighter1_532_576_Open_Image onclick="this.style.display='none'; Codehighlighter1_532_576_Open_Text.style.display='none'; Codehighlighter1_532_576_Closed_Image.style.display='inline'; Codehighlighter1_532_576_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_532_576_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_532_576_Closed_Text.style.display='none'; Codehighlighter1_532_576_Open_Image.style.display='inline'; Codehighlighter1_532_576_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">public</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;Object&nbsp;ifFalse(Block&nbsp;aBlock)&nbsp;</SPAN><SPAN id=Codehighlighter1_532_576_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_532_576_Open_Text><SPAN style="COLOR: rgb(0,0,0)">{<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">27</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">return</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;aBlock.execute();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">28</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">29</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">30</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">31</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG id=Codehighlighter1_601_675_Open_Image onclick="this.style.display='none'; Codehighlighter1_601_675_Open_Text.style.display='none'; Codehighlighter1_601_675_Closed_Image.style.display='inline'; Codehighlighter1_601_675_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_601_675_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_601_675_Closed_Text.style.display='none'; Codehighlighter1_601_675_Open_Image.style.display='inline'; Codehighlighter1_601_675_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><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)">class</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;Integer</SPAN><SPAN id=Codehighlighter1_601_675_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_601_675_Open_Text><SPAN style="COLOR: rgb(0,0,0)">{<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">32</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">33</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG id=Codehighlighter1_655_673_Open_Image onclick="this.style.display='none'; Codehighlighter1_655_673_Open_Text.style.display='none'; Codehighlighter1_655_673_Closed_Image.style.display='inline'; Codehighlighter1_655_673_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_655_673_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_655_673_Closed_Text.style.display='none'; Codehighlighter1_655_673_Open_Image.style.display='inline'; Codehighlighter1_655_673_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">public</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;Boolean&nbsp;greaterThan(Integer&nbsp;anInteger)&nbsp;</SPAN><SPAN id=Codehighlighter1_655_673_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_655_673_Open_Text><SPAN style="COLOR: rgb(0,0,0)">{<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">34</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<IMG src="http://www.blogjava.net/images/dot.gif"><IMG src="http://www.blogjava.net/images/dot.gif"><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">35</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">36</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">37</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN></DIV></DIV></DIV></DIV></DIV></DIV></DIV><BR>So that we could get the following code<BR>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt">&nbsp;</P>
<DIV style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><SPAN style="COLOR: rgb(0,128,128)">1</SPAN><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: rgb(0,0,0)">4</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;〉</SPAN><SPAN style="COLOR: rgb(0,0,0)">3</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;ifTrue:&nbsp;[Transcript&nbsp;show:&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0)">'</SPAN><SPAN style="COLOR: rgb(0,0,0)">Hello</SPAN><SPAN style="COLOR: rgb(0,0,0)">'</SPAN><SPAN style="COLOR: rgb(0,0,0)">]</SPAN></DIV>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p>&nbsp;</o:p></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt">which could be translated in Java like this:<o:p></o:p></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p>&nbsp;</o:p><o:p>&nbsp;</o:p></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p></o:p></P>
<DIV style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><IMG id=Codehighlighter1_71_161_Open_Image onclick="this.style.display='none'; Codehighlighter1_71_161_Open_Text.style.display='none'; Codehighlighter1_71_161_Closed_Image.style.display='inline'; Codehighlighter1_71_161_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_71_161_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_71_161_Closed_Text.style.display='none'; Codehighlighter1_71_161_Open_Image.style.display='inline'; Codehighlighter1_71_161_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top><SPAN style="COLOR: rgb(0,0,255)">new</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;Integer(</SPAN><SPAN style="COLOR: rgb(0,0,0)">4</SPAN><SPAN style="COLOR: rgb(0,0,0)">).isGreaterThan(</SPAN><SPAN style="COLOR: rgb(0,0,255)">new</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;Integer(</SPAN><SPAN style="COLOR: rgb(0,0,0)">3</SPAN><SPAN style="COLOR: rgb(0,0,0)">)).ifTrue(</SPAN><SPAN style="COLOR: rgb(0,0,255)">new</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;BlockClosure()&nbsp;</SPAN><SPAN id=Codehighlighter1_71_161_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_71_161_Open_Text><SPAN style="COLOR: rgb(0,0,0)">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG id=Codehighlighter1_99_158_Open_Image onclick="this.style.display='none'; Codehighlighter1_99_158_Open_Text.style.display='none'; Codehighlighter1_99_158_Closed_Image.style.display='inline'; Codehighlighter1_99_158_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_99_158_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_99_158_Closed_Text.style.display='none'; Codehighlighter1_99_158_Open_Image.style.display='inline'; Codehighlighter1_99_158_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">public</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;Object&nbsp;value()&nbsp;</SPAN><SPAN id=Codehighlighter1_99_158_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_99_158_Open_Text><SPAN style="COLOR: rgb(0,0,0)">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</SPAN><SPAN style="COLOR: rgb(0,0,0)">"</SPAN><SPAN style="COLOR: rgb(0,0,0)">Hello</SPAN><SPAN style="COLOR: rgb(0,0,0)">"</SPAN><SPAN style="COLOR: rgb(0,0,0)">);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">return</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">null</SPAN><SPAN style="COLOR: rgb(0,0,0)">;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: rgb(0,0,0)">);</SPAN></DIV>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt">&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt">That's quite simple(some dynamic languages on JVM ,e.g. <A>Groovy</A>, do the same thing), but it indeed <A>brings some profound changes to my thought.</A></P>
<DIV>
<DIV>
<DIV language=JavaScript class=msocomtxt id=_com_2 onmouseover="msoCommentShow('_anchor_2','_com_2')" onmouseout="msoCommentHide('_com_2')">
<P class=MsoCommentText style="MARGIN: 0in 0in 0pt"><o:p><BR></o:p></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt">First, considering that 'if'<SPAN lang=ZH-CN style="FONT-FAMILY: 宋体">，</SPAN>'for' and 'while' are no longer pre-defined keywords, we could define our own control structures. For example, we could define Order has its own way to do something.<o:p></o:p></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p>&nbsp;</o:p></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p></o:p></P>
<DIV style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><SPAN style="COLOR: rgb(0,128,128)">1</SPAN><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: rgb(0,0,0)">anOrder&nbsp;ifExpired:&nbsp;[&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">do</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;reactive&nbsp;order]<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">2</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ifCanceled:&nbsp;[</SPAN><SPAN style="COLOR: rgb(0,0,255)">do</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;something&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">else</SPAN><SPAN style="COLOR: rgb(0,0,0)">]</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN></DIV>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt">&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt">Taking no account of performance and semantic speaking, there is no difference between the code above and undermentioned:<o:p></o:p></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p></o:p>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p></o:p></P>
<DIV style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><SPAN style="COLOR: rgb(0,128,128)">1</SPAN><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0)">4</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,0)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)">3</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;ifTrue:&nbsp;[</SPAN><SPAN style="COLOR: rgb(0,0,255)">do</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;something]<BR></SPAN><SPAN style="COLOR: rgb(0,128,128)">2</SPAN><SPAN style="COLOR: rgb(0,0,0)"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ifFalse:&nbsp;[</SPAN><SPAN style="COLOR: rgb(0,0,255)">do</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;somthing]</SPAN></DIV>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt">&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt">More fancy, we could define a new test structure like this:<o:p></o:p></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p>&nbsp;</o:p></P>
<DIV style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><SPAN style="COLOR: rgb(0,128,128)">1</SPAN><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: rgb(0,0,0)">anOrderTest&nbsp;should:&nbsp;[some&nbsp;</SPAN><SPAN style="COLOR: rgb(0,0,255)">assert</SPAN><SPAN style="COLOR: rgb(0,0,0)">]&nbsp;when:&nbsp;[</SPAN><SPAN style="COLOR: rgb(0,0,255)">do</SPAN><SPAN style="COLOR: rgb(0,0,0)">&nbsp;some&nbsp;initalize].</SPAN></DIV>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt"></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p>&nbsp;</o:p></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt">So we could have programmable control structure in Smalltalk ( something like we do in Lisp via continuation:) ), and define our own DSL easily.That's the<SPAN> </SPAN>amazing lightweight syntax feature in Smalltalk!<o:p></o:p></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p>&nbsp;</o:p></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt">Second, we could get full capability of Von Nouma Style Programming Language via pure OO concepts.We could construct software in consistent OO concepts.<o:p></o:p></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt"><o:p>&nbsp;</o:p></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt">I began my adventure in Object technology by using C++ in 1995, and then I chose Java as my main working language. All my experiences about OO come from half-blooded OO language.So that for a long time, I thought Object-Oriented Programming is a big patch to imperative languages. The imperative languages are <A>desgin</A><SPAN class=MsoCommentReference><SPAN>ed&nbsp;</SPAN></SPAN> to record the sequence of instruments which are used to manipulate the computer, so <A>they</A> are lack in semantic, and poor in abstraction. <SPAN class=MsoCommentReference><SPAN></SPAN></SPAN>Though the Object technology introduces a successful type system and provides some abstraction mechanism, I still feel sucks to program in inconsistent concepts, because I should be careful about keeping programming more in OO-style rather than in procedural-style(something like Domina Model or not, sucks!).<BR></P>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt">Once I accused Object-Oriented Methodology of all the fault, I blamed imperfection on Object-Oriented Methodology.But now, I found out it's&nbsp;only because that I&nbsp;have little talent and learning in OO, <A>it</A>&nbsp;turned out to be my fault, I should say sorry&nbsp;to Object-Oriented Methodology.</P></DIV></DIV></DIV><img src ="http://www.blogjava.net/raimundox/aggbug/23028.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raimundox/" target="_blank">Raimundox</a> 2005-12-08 20:39 <a href="http://www.blogjava.net/raimundox/archive/2005/12/08/23028.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>