<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>夜游长空 &#187; 编程</title>
	<atom:link href="http://www.zhangdi.name/tag/%e7%bc%96%e7%a8%8b/feed" rel="self" type="application/rss+xml" />
	<link>http://www.zhangdi.name</link>
	<description>Blog of Daniel &#38; Kimi</description>
	<lastBuildDate>Wed, 13 Oct 2010 05:05:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>当Ruby遇到数独</title>
		<link>http://www.zhangdi.name/2007/09/06/when-ruby-meets-sudoku.html</link>
		<comments>http://www.zhangdi.name/2007/09/06/when-ruby-meets-sudoku.html#comments</comments>
		<pubDate>Thu, 06 Sep 2007 14:33:02 +0000</pubDate>
		<dc:creator>zhangdi</dc:creator>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[数独]]></category>
		<category><![CDATA[游戏]]></category>
		<category><![CDATA[编程]]></category>

		<guid isPermaLink="false">http://www.zhangdi.name/2007/09/06/when-ruby-meets-sudoku.html</guid>
		<description><![CDATA[最近流行一种游戏，叫做“数独”，英文叫Sudoku，听着应该是从日本那边过来的。我曾经做过几个，发现这个东西如果纯粹用眼睛和大脑来解决确实有很大的难度。但是如果你加上纸和笔，那么难度就会降低95%，而如果你借助于更先进的Excell，那么难度就会降低99%。我最终的结论就是，这个东西是个体力劳动。 如果有人还没有接触过数独，那这里就来大概介绍一下：数独应该算是一种九宫格游戏。他是由3*3个九宫格组成的一个大正方形。要求你在9*9个格子里面分别填入适当的1..9的数字，然后让每一行，每一列中的9个数字都包含1..9。另外，每个九宫格中也要包含1..9。下图就是一个数独。 我曾经和LP说过，这个东西实在变态，是一个纯粹的浪费时间的东西。我就异常后悔曾经花了几个人时去做数独。不过，这个月买了《新知客》后，遇到了更变态的事情，那就是，它变态到附赠了一个增刊，其中有28个数独。而且说：“空前震撼！28道数独让你过足瘾！”。更过分的是，其中有些数独本身就是错的（比如，一个九宫格内竟然出现了两个8～）。答案更是错误百出。不知道这些编辑们都是不识数呢，还是不明白数独的规则。 学习Ruby也有一段时间了，突然就想，正好拿这个练习一下。所以花了3个晚上和一个白天的时间用Ruby写了一个解决数独的程序。目前经过我做的一些基本测试，工作还算正常。如果有兴趣，可以在这里下载玩一玩。当然，因为是Ruby，所以还需要Ruby的Interpreter。然后在命令行窗口运行ruby sodoku.rb就可以了。（我是在Windows下写的，所以没有shebang。） 我的感觉就是，用Ruby写程序真的是一种享受。感觉需要用到的东西都是非常straightforward，没有什么要用到的东西需要你自己去费劲配置和研究的。而且大多数API，都可以直接猜出来。比如我写这个的时候，很多用到的API都是先猜着写，然后再看Ruby的API文档，竟然发现没有什么错误。证明了我是一个聪明的人。。。更证明Ruby的API和语法设计的非常友善。呵呵。 我用的算法应该也不是最优的（类似于判别树的算法），但应该比纯粹的枚举要好多了。欢迎讨论，如果大家对算法有兴趣。我正在打算专门写一个网页来介绍我的程序逻辑，不出意外，应该下周一之前写完。欢迎大家提意见。 另外，也有一个计划就是把它变成一个网络应用。不过那就需要更多的测试和调优了。 相关文章用40行程序能展示多少Ruby的特性？Ruby: puts != print + &#8220;\n&#8221;快速解开数独（PySudoku）KXShell的一个Demo开心网“争车位”游戏分析（纯技术）]]></description>
			<content:encoded><![CDATA[<p><!--develop ruby sudoku 数独--></p>
<p>最近流行一种游戏，叫做“数独”，英文叫Sudoku，听着应该是从日本那边过来的。我曾经做过几个，发现这个东西如果纯粹用眼睛和大脑来解决确实有很大的难度。但是如果你加上纸和笔，那么难度就会降低95%，而如果你借助于更先进的Excell，那么难度就会降低99%。我最终的结论就是，这个东西是个体力劳动。</p>
<p>如果有人还没有接触过数独，那这里就来大概介绍一下：数独应该算是一种九宫格游戏。他是由3*3个九宫格组成的一个大正方形。要求你在9*9个格子里面分别填入适当的1..9的数字，然后让每一行，每一列中的9个数字都包含1..9。另外，每个九宫格中也要包含1..9。下图就是一个数独。</p>
<p><a rel="lightbox[]" href="http://www.zhangdi.name/wp-content/gallery/misc/sudoku.PNG" title="sudoku.PNG"><img src="http://www.zhangdi.name/wp-content/gallery/misc/thumbs/thumbs_sudoku.PNG" alt="sudoku.PNG" title="sudoku.PNG" /></a></p>
<p>我曾经和LP说过，这个东西实在变态，是一个纯粹的浪费时间的东西。我就异常后悔曾经花了几个人时去做数独。不过，这个月买了《新知客》后，遇到了更变态的事情，那就是，它变态到附赠了一个增刊，其中有28个数独。而且说：“<strong>空前震撼！28道数独让你过足瘾！</strong>”。更过分的是，其中有些数独本身就是错的（比如，一个九宫格内竟然出现了两个8～）。答案更是错误百出。不知道这些编辑们都是不识数呢，还是不明白数独的规则。</p>
<p>学习Ruby也有一段时间了，突然就想，正好拿这个练习一下。所以花了3个晚上和一个白天的时间用Ruby写了一个解决数独的程序。目前经过我做的一些基本测试，工作还算正常。如果有兴趣，可以在<a href="http://www.zhangdi.name/UserFiles/File/sudoku.zip">这里</a>下载玩一玩。当然，因为是Ruby，所以还需要<a href="http://ruby-lang.org">Ruby的Interpreter</a>。然后在命令行窗口运行ruby sodoku.rb就可以了。（我是在Windows下写的，所以没有shebang。）</p>
<p>我的感觉就是，用Ruby写程序真的是一种享受。感觉需要用到的东西都是非常straightforward，没有什么要用到的东西需要你自己去费劲配置和研究的。而且大多数API，都可以直接猜出来。比如我写这个的时候，很多用到的API都是先猜着写，然后再看Ruby的API文档，竟然发现没有什么错误。证明了我是一个聪明的人。。。更证明Ruby的API和语法设计的非常友善。呵呵。</p>
<p>我用的算法应该也不是最优的（类似于判别树的算法），但应该比纯粹的枚举要好多了。欢迎讨论，如果大家对算法有兴趣。我正在打算专门写一个网页来介绍我的程序逻辑，不出意外，应该下周一之前写完。欢迎大家提意见。</p>
<p>另外，也有一个计划就是把它变成一个网络应用。不过那就需要更多的测试和调优了。</p>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li><a href="http://www.zhangdi.name/2007/08/22/a-piece-of-ruby-code.html" title="用40行程序能展示多少Ruby的特性？">用40行程序能展示多少Ruby的特性？</a></li><li><a href="http://www.zhangdi.name/2007/08/21/ruby-puts-not-equals-print-plus-back-slash-n.html" title="Ruby: puts != print + &#8220;\n&#8221;">Ruby: puts != print + &#8220;\n&#8221;</a></li><li><a href="http://www.zhangdi.name/2008/11/17/pysudoku.html" title="快速解开数独（PySudoku）">快速解开数独（PySudoku）</a></li><li><a href="http://www.zhangdi.name/2008/09/21/kxshell-demo.html" title="KXShell的一个Demo">KXShell的一个Demo</a></li><li><a href="http://www.zhangdi.name/2008/09/17/hack-the-parking-game-in-kaixin001.html" title="开心网“争车位”游戏分析（纯技术）">开心网“争车位”游戏分析（纯技术）</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.zhangdi.name/2007/09/06/when-ruby-meets-sudoku.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>用40行程序能展示多少Ruby的特性？</title>
		<link>http://www.zhangdi.name/2007/08/22/a-piece-of-ruby-code.html</link>
		<comments>http://www.zhangdi.name/2007/08/22/a-piece-of-ruby-code.html#comments</comments>
		<pubDate>Wed, 22 Aug 2007 07:27:40 +0000</pubDate>
		<dc:creator>zhangdi</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[学习]]></category>
		<category><![CDATA[编程]]></category>

		<guid isPermaLink="false">http://www.zhangdi.name/2007/08/22/a-piece-of-ruby-code.html</guid>
		<description><![CDATA[module OutputHelper def print_line(msg) print msg + "\\n" end end class SayHello include OutputHelper private :print_line def initialize(name, &#38;sayHello) @name, @sayHello = name, sayHello if @sayHello == nil @sayHello = proc { &#124;msg&#124; print_line msg } end end def salute(greet_msg) @sayHello.call("Hello, #{@name}. #{greet_msg}.") end def salute_with_block(greet_msg) if block_given? yield "Hello, #{@name}. I'm using a block. [...]]]></description>
			<content:encoded><![CDATA[<p><!--ruby develop 编程 开发--></p>
<pre name="code" class="ruby">
module OutputHelper
  def print_line(msg)
    print msg + "\\n"
  end
end

class SayHello
  include OutputHelper
  private :print_line
  def initialize(name, &amp;sayHello)
    @name, @sayHello = name, sayHello

    if @sayHello == nil
      @sayHello = proc { |msg| print_line msg }
    end
  end

  def salute(greet_msg)
    @sayHello.call("Hello, #{@name}. #{greet_msg}.")
  end

  def salute_with_block(greet_msg)
    if block_given?
      yield "Hello, #{@name}. I'm using a block. #{greet_msg}."
    else
      @sayHello.call("Hello, #{@name}. You missed the block. #{greet_msg}.")
    end
  end
end

if __FILE__ == $0
  say_hello = SayHello.new("Daniel") { |msg| print msg + "\\n" }
  say_hello.salute("Greetings")
  say_hello.salute_with_block("Greetings")
  say_hello.salute_with_block("Greetings") { |msg| print msg + "\\n" }

  say_hello = SayHello.new("Kimi")
  say_hello.salute("Greetings, again")
end</pre>
<ul>
<li>定义module以及class。</li>
<li>Mixin，将一个module动态include到class里面，使之具有相应的功能。</li>
<li>method的访问级别，private, public等。很多动态语言没有这个功能。</li>
<li>向构造函数传入block类型的参数。</li>
<li>用proc方法构造block。</li>
<li>用block.call方法，调用一个block类型的变量。</li>
<li>用block_given?方法判断是否为一个方法传入了block参数。</li>
<li>用yield来调用为方法传入的block参数。</li>
<li>将测试代码写在if __FILE__ = $0 &#8230; end块中。很类似于Python。</li>
<li>用{|params| expressions }形式定义block。</li>
</ul>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li><a href="http://www.zhangdi.name/2007/08/21/ruby-puts-not-equals-print-plus-back-slash-n.html" title="Ruby: puts != print + &#8220;\n&#8221;">Ruby: puts != print + &#8220;\n&#8221;</a></li><li><a href="http://www.zhangdi.name/2007/09/06/when-ruby-meets-sudoku.html" title="当Ruby遇到数独">当Ruby遇到数独</a></li><li><a href="http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html" title="VC++2005 StringTable资源类型研究">VC++2005 StringTable资源类型研究</a></li><li><a href="http://www.zhangdi.name/2007/03/18/learn-design-pattern-without-coding-and-class-diagram-2.html" title="不用代码和类图说设计模式（2）">不用代码和类图说设计模式（2）</a></li><li><a href="http://www.zhangdi.name/2007/03/17/learn-design-pattern-without-coding-and-class-diagram-1.html" title="不用代码和类图说设计模式（1）">不用代码和类图说设计模式（1）</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.zhangdi.name/2007/08/22/a-piece-of-ruby-code.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Ruby: puts != print + &#8220;\n&#8221;</title>
		<link>http://www.zhangdi.name/2007/08/21/ruby-puts-not-equals-print-plus-back-slash-n.html</link>
		<comments>http://www.zhangdi.name/2007/08/21/ruby-puts-not-equals-print-plus-back-slash-n.html#comments</comments>
		<pubDate>Tue, 21 Aug 2007 14:18:36 +0000</pubDate>
		<dc:creator>zhangdi</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[学习]]></category>
		<category><![CDATA[源码分析]]></category>
		<category><![CDATA[编程]]></category>

		<guid isPermaLink="false">http://www.zhangdi.name/2007/08/21/ruby-puts-print-n.html</guid>
		<description><![CDATA[今天看到railschina论坛上一篇贴子在讨论在Ruby中，puts str是不是等于print str + &#8220;\n&#8221;。因为一位同学做了实验，在irb中，在多线程环境下使用puts似乎有问题，有的时候字符串和换行的顺序会乱，而用print就没有问题，所以得出结论，认为puts是不等于print + &#8220;\n&#8221;的。又有人提出质疑，因为做了另外的实验，在非irb环境下，puts和print都没有问题，所以认为多线程问题只是主观臆测，有可能是irb的问题。甚至还有人写信给Dave，结果Dave也没有给出明确的答复～ 正好手头上有Ruby的源代码，所以翻出来看了一下，在io.c中，明确的写明了Ruby中ios.puts方法的实现： VALUE rb_io_puts(argc, argv, out) int argc; VALUE *argv; VALUE out; { int i; VALUE line; /* if no argument given, print newline. */ if (argc == 0) { rb_io_write(out, rb_default_rs); return Qnil; } for (i=0; i&#60;argc; i++) { if (NIL_P(argv[i])) { line = rb_str_new2("nil"); } else { [...]]]></description>
			<content:encoded><![CDATA[<p><!--ruby develop 编程 开发--></p>
<p>今天看到railschina论坛上一篇贴子在讨论在Ruby中，puts str是不是等于print str + &#8220;\n&#8221;。因为一位同学做了实验，在irb中，在多线程环境下使用puts似乎有问题，有的时候字符串和换行的顺序会乱，而用print就没有问题，所以得出结论，认为puts是不等于print + &#8220;\n&#8221;的。又有人提出质疑，因为做了另外的实验，在非irb环境下，puts和print都没有问题，所以认为多线程问题只是主观臆测，有可能是irb的问题。甚至还有人写信给Dave，结果Dave也没有给出明确的答复～</p>
<p>正好手头上有Ruby的源代码，所以翻出来看了一下，在io.c中，明确的写明了Ruby中ios.puts方法的实现：</p>
<pre name="code" class="cpp:collapse">
VALUE
rb_io_puts(argc, argv, out)
    int argc;
    VALUE *argv;
    VALUE out;
{
   int i;
   VALUE line; 

   /* if no argument given, print newline. */
   if (argc == 0) {
      rb_io_write(out, rb_default_rs);
      return Qnil;
   }
   for (i=0; i&lt;argc; i++) {
      if (NIL_P(argv[i])) {
         line = rb_str_new2("nil");
      }
      else {
         line = rb_check_array_type(argv[i]);
         if (!NIL_P(line)) {
            rb_protect_inspect(io_puts_ary, line, out);
            continue;
         }
         line = rb_obj_as_string(argv[i]);
      }
      rb_io_write(out, line);
      if (RSTRING(line)-&gt;len == 0 ||
            RSTRING(line)-&gt;ptr[RSTRING(line)-&gt;len-1] != '\n') {
         rb_io_write(out, rb_default_rs);
      }
   } 

   return Qnil;
}</pre>
<p>可以看到27行和30行就是分别向流中写我们传入的string和&#8221;\n&#8221;的代码，所以puts确实是<strong>存在潜在的多线程问题</strong>的。而对于print str + &#8220;\n&#8221;这种方式，因为ruby会先把str和&#8221;\n&#8221;构造为一个新的string，然后再传给print函数，所以是没有这种问题的。总结：在Ruby中，<strong>puts != print + &#8220;\n&#8221;</strong></p>
<p>另外，如果用print(str1, str2)这种形式，同样会有多线程问题。因为在Ruby中，print的实现是，一个一个参数分别写入流，而不是先将参数合并，再一次写入。（合并参数会占用额外的内存，多次IO又会消耗时间，不知道最初Ruby是如何权衡这个的～）</p>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li><a href="http://www.zhangdi.name/2007/08/22/a-piece-of-ruby-code.html" title="用40行程序能展示多少Ruby的特性？">用40行程序能展示多少Ruby的特性？</a></li><li><a href="http://www.zhangdi.name/2007/09/06/when-ruby-meets-sudoku.html" title="当Ruby遇到数独">当Ruby遇到数独</a></li><li><a href="http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html" title="VC++2005 StringTable资源类型研究">VC++2005 StringTable资源类型研究</a></li><li><a href="http://www.zhangdi.name/2007/03/18/learn-design-pattern-without-coding-and-class-diagram-2.html" title="不用代码和类图说设计模式（2）">不用代码和类图说设计模式（2）</a></li><li><a href="http://www.zhangdi.name/2007/03/17/learn-design-pattern-without-coding-and-class-diagram-1.html" title="不用代码和类图说设计模式（1）">不用代码和类图说设计模式（1）</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.zhangdi.name/2007/08/21/ruby-puts-not-equals-print-plus-back-slash-n.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>《Windows核心编程》&#8211; 经典的书，翻译太烂</title>
		<link>http://www.zhangdi.name/2007/08/16/programming-applications-for-microsoft-windows.html</link>
		<comments>http://www.zhangdi.name/2007/08/16/programming-applications-for-microsoft-windows.html#comments</comments>
		<pubDate>Thu, 16 Aug 2007 05:50:17 +0000</pubDate>
		<dc:creator>zhangdi</dc:creator>
				<category><![CDATA[Book]]></category>
		<category><![CDATA[Windows编程]]></category>
		<category><![CDATA[书籍]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[读后感]]></category>

		<guid isPermaLink="false">http://www.zhangdi.name/2007/08/16/programming-applications-for-microsoft-windows.html</guid>
		<description><![CDATA[一直以来没有系统的学习过Windows编程，到了CA后，工作的要求，所以必须学习一下。买了一本《Windows核心编程》来看，最近刚刚看完。个人觉得还是收获很丰富的，充分证明了这本书确实是本好书。 这本书一直就被称作Windows平台下开发人员的必读书之一，确实是名不虚传。它就像是一个Quick Tour，带着你游历Windows编程的各个方面，但是又不仅仅是简单的浏览，在重点的地方，还会给你详细的解读。看这本书的时候，能深切的感觉到作者对Windows平台的理解非常透彻。这本书确实是可以帮助人快速的进入Windows编程世界。 不过，中文技术书籍的通病：翻译质量问题在这本书上显现得也非常明显。我本以为一本如此经典的书，翻译质量应该能在平均水平之上了吧，结果大失所望。如果我之前一点Windows编程知识都没有的话，可能看某些句子会猜不出意思。毕竟懂技术的翻译人员太少了～ 想看这本书的，建议读英文原版的。 相关文章丑陋的中国人Windows Box Model解析VC++2005 StringTable资源类型研究和瞪羚一起赛跑，和狮子一起捕食Javascript权威指南第五版]]></description>
			<content:encoded><![CDATA[<p><!--book windows programming develop--></p>
<p>一直以来没有系统的学习过Windows编程，到了CA后，工作的要求，所以必须学习一下。买了一本《Windows核心编程》来看，最近刚刚看完。个人觉得还是收获很丰富的，充分证明了这本书确实是本好书。</p>
<p>这本书一直就被称作Windows平台下开发人员的必读书之一，确实是名不虚传。它就像是一个Quick Tour，带着你游历Windows编程的各个方面，但是又不仅仅是简单的浏览，在重点的地方，还会给你详细的解读。看这本书的时候，能深切的感觉到作者对Windows平台的理解非常透彻。这本书确实是可以帮助人快速的进入Windows编程世界。</p>
<p>不过，中文技术书籍的通病：翻译质量问题在这本书上显现得也非常明显。我本以为一本如此经典的书，翻译质量应该能在平均水平之上了吧，结果大失所望。如果我之前一点Windows编程知识都没有的话，可能看某些句子会猜不出意思。毕竟懂技术的翻译人员太少了～</p>
<p>想看这本书的，建议读英文原版的。</p>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li><a href="http://www.zhangdi.name/2007/10/16/the-ugly-chinese.html" title="丑陋的中国人">丑陋的中国人</a></li><li><a href="http://www.zhangdi.name/2007/07/17/explain-windows-box-model.html" title="Windows Box Model解析">Windows Box Model解析</a></li><li><a href="http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html" title="VC++2005 StringTable资源类型研究">VC++2005 StringTable资源类型研究</a></li><li><a href="http://www.zhangdi.name/2006/10/23/the-world-is-flat.html" title="和瞪羚一起赛跑，和狮子一起捕食">和瞪羚一起赛跑，和狮子一起捕食</a></li><li><a href="http://www.zhangdi.name/2006/10/09/javascript-definitive-guide.html" title="Javascript权威指南第五版">Javascript权威指南第五版</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.zhangdi.name/2007/08/16/programming-applications-for-microsoft-windows.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress Widgets简介</title>
		<link>http://www.zhangdi.name/2007/07/23/an-introduction-about-wordpress-widgets.html</link>
		<comments>http://www.zhangdi.name/2007/07/23/an-introduction-about-wordpress-widgets.html#comments</comments>
		<pubDate>Mon, 23 Jul 2007 07:57:42 +0000</pubDate>
		<dc:creator>zhangdi</dc:creator>
				<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[Widget]]></category>
		<category><![CDATA[编程]]></category>

		<guid isPermaLink="false">http://www.zhangdi.name/2007/07/23/an-introduction-about-wordpress-widgets.html</guid>
		<description><![CDATA[WordPress2.2.x开始正式把widgets作为内部功能之一。这说明了widgets的成功和人心所向，也说明了大家对于添加一个小功能就要修改theme的template的厌倦。widgets最初是一个wordpress的plugin，叫dynamic sidebar，顾名思义，就是动态生成sidebar而不需要修改代码。而现在功能强大，不仅仅可以动态生成sidebar，页面的任何位置，只要设置了支持widgets就可以使用拖拽的方式来控制布局。 在安装了widgets插件后（wordpress2.2.x及以上版本无需安装），在Admin-&#62;Presentation-&#62;Widgets中，就可以看到所有页面上的widgets container和所有可以使用的widgets，需要做的就是将widgets拖拽到理想的区域就可以了。而且大多widgets还支持基于AJAX的设置页面，用户友好度也非常好。 实现一个widget也是非常惬意的一件事情。如果你有一个非widgetized的plugin那么只需要做很少的改动就可以把它变成一个widget。比如有一个plugin叫做recent_comments，原来你必须在sidebar.php中修改代码，加上相应的get_recent_comments()函数。现在只需要做一些改动，让这个plugin支持widget就可以直接拖拽了。大概是这个样子： function get_recent_comments() { /* 原来的函数，不需要改动 */ } // 下面的代码让这个plugin支持widget function widget_recent_comments_init() { // 万一我们没有widgets plugin的话 if ( !function_exists('register_sidebar_widget') ) return; function widget_recent_comments($args) { extract($args); // 下面就是输出的东西，直接打到页面上。 echo $before_widget; // 这些都不能丢下。（标准！） echo $before_title; echo 'Recent Comments'; echo $after_title; echo get_recent_comments(); echo $after_widget; } // 注册widget register_sidebar_widget('Recent Comments Widget', 'widget_recent_comments'); } // [...]]]></description>
			<content:encoded><![CDATA[<p><!--wordpress plugin widget blog AJAX--></p>
<p><a href="http://wordpress.org">WordPress2.2.x</a>开始正式把widgets作为内部功能之一。这说明了widgets的成功和人心所向，也说明了大家对于添加一个小功能就要修改theme的template的厌倦。widgets最初是一个wordpress的plugin，叫dynamic sidebar，顾名思义，就是动态生成sidebar而不需要修改代码。而现在功能强大，不仅仅可以动态生成sidebar，页面的任何位置，只要设置了支持widgets就可以使用拖拽的方式来控制布局。</p>
<p>在安装了widgets插件后（wordpress2.2.x及以上版本无需安装），在Admin-&gt;Presentation-&gt;Widgets中，就可以看到所有页面上的widgets container和所有可以使用的widgets，需要做的就是将widgets拖拽到理想的区域就可以了。而且大多widgets还支持基于AJAX的设置页面，用户友好度也非常好。</p>
<p>实现一个widget也是非常惬意的一件事情。如果你有一个非widgetized的plugin那么只需要做很少的改动就可以把它变成一个widget。比如有一个plugin叫做recent_comments，原来你必须在sidebar.php中修改代码，加上相应的get_recent_comments()函数。现在只需要做一些改动，让这个plugin支持widget就可以直接拖拽了。大概是这个样子：</p>
<p><span id="more-207"></span></p>
<pre name="code" class="php">
function get_recent_comments() {
    /* 原来的函数，不需要改动 */
}

// 下面的代码让这个plugin支持widget
function widget_recent_comments_init() {
    // 万一我们没有widgets plugin的话
    if ( !function_exists('register_sidebar_widget') )
        return;

    function widget_recent_comments($args) {
        extract($args);

        // 下面就是输出的东西，直接打到页面上。
        echo $before_widget; // 这些都不能丢下。（标准！）
        echo $before_title;
        echo 'Recent Comments';
        echo $after_title;
        echo get_recent_comments();
        echo $after_widget;
    }

    // 注册widget
    register_sidebar_widget('Recent Comments Widget', 'widget_recent_comments');
}

// 再所有plugin都载入之后再载入这个widget，防止有dependency的问题。
add_action("plugins_loaded", "widget_recent_comments_init");</pre>
<p>非常简单，所以我已经把我所有要用到的不是widget的plugin都widgetize了。</p>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li><a href="http://www.zhangdi.name/2007/07/23/blog-upgraded-again.html" title="Blog再一次升级">Blog再一次升级</a></li><li><a href="http://www.zhangdi.name/2008/12/19/post-delicious-bookmarks-to-wordpress-daily-automatically.html" title="将Delicious的bookmarks自动发布到Wordpress">将Delicious的bookmarks自动发布到Wordpress</a></li><li><a href="http://www.zhangdi.name/2008/12/12/wordpress-upgrades-to-27.html" title="Wordpress升级到2.7">Wordpress升级到2.7</a></li><li><a href="http://www.zhangdi.name/2008/07/24/add-avatar-to-wordpress-comment-section.html" title="为Wordpress的评论部分加上头像">为Wordpress的评论部分加上头像</a></li><li><a href="http://www.zhangdi.name/2007/10/25/wordpress-23.html" title="Wordpress升级到了2.3版本">Wordpress升级到了2.3版本</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.zhangdi.name/2007/07/23/an-introduction-about-wordpress-widgets.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Windows Box Model解析</title>
		<link>http://www.zhangdi.name/2007/07/17/explain-windows-box-model.html</link>
		<comments>http://www.zhangdi.name/2007/07/17/explain-windows-box-model.html#comments</comments>
		<pubDate>Mon, 16 Jul 2007 16:06:56 +0000</pubDate>
		<dc:creator>zhangdi</dc:creator>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Windows编程]]></category>
		<category><![CDATA[编程]]></category>

		<guid isPermaLink="false">http://www.zhangdi.name/2007/07/17/explain-windows-box-model.html</guid>
		<description><![CDATA[很久以前看到过一篇解释HTML中DOM的Box Model的文章（好像是在MSDN，有图示，很清楚）。最近在写Windows程序，遇到了一个要resize一个window，并且要相应移动它里面的controls的需求。趁这个机会研究了一下Windows的Box Model，发现竟然和DOM的Box Model是如此的相似。 首先介绍一下与其相关的一些API: BOOL GetWindowInfo( HWND hwnd, PWINDOWINFO pwi ); // pwi为传出参数，是一个指向WINDOWINFO结构体的指针 BOOL GetWindowRect( HWND hwnd, LPRECT lpRect ); // lpRect为传出参数，是一个指向RECT结构体的指针 BOOL GetClientRect( HWND hwnd, LPRECT lpRect );// lpRect为传出参数，是一个指向RECT结构体的指针 BOOL SetWindowPos( HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags ); // 此函数功能强大，可以Move和Resize一个Window typedef struct { DWORD cbSize; [...]]]></description>
			<content:encoded><![CDATA[<p><!--windows programming api box model develop 解析 编程 开发--></p>
<p>很久以前看到过一篇解释HTML中DOM的Box Model的文章（好像是在MSDN，有图示，很清楚）。最近在写Windows程序，遇到了一个要resize一个window，并且要相应移动它里面的controls的需求。趁这个机会研究了一下Windows的Box Model，发现竟然和DOM的Box Model是如此的相似。</p>

<a href="http://www.zhangdi.name/wp-content/gallery/misc/win-box.jpg" title="" rel="lightbox[singlepic1]" >
	<img class="ngg-singlepic" src="http://www.zhangdi.name/index.php?callback=image&amp;pid=1&amp;width=&amp;height=150&amp;mode=" alt="win-box.jpg" title="win-box.jpg" />
</a>

<p>首先介绍一下与其相关的一些API:</p>
<p><span id="more-195"></span></p>
<pre name="code" class="cpp">
BOOL GetWindowInfo(
    HWND hwnd,
    PWINDOWINFO pwi
); // pwi为传出参数，是一个指向WINDOWINFO结构体的指针

BOOL GetWindowRect(
    HWND hwnd,
    LPRECT lpRect
); // lpRect为传出参数，是一个指向RECT结构体的指针

BOOL GetClientRect(
    HWND hwnd,
    LPRECT lpRect
);// lpRect为传出参数，是一个指向RECT结构体的指针

BOOL SetWindowPos(
    HWND hWnd,
    HWND hWndInsertAfter,
    int X,
    int Y,
    int cx,
    int cy,
    UINT uFlags
); // 此函数功能强大，可以Move和Resize一个Window

typedef struct {
    DWORD cbSize;
    RECT rcWindow;
    RECT rcClient;
    DWORD dwStyle;
    DWORD dwExStyle;
    DWORD dwWindowStatus;
    UINT cxWindowBorders;
    UINT cyWindowBorders;
    ATOM atomWindowType;
    WORD wCreatorVersion;
} WINDOWINFO, *PWINDOWINFO, *LPWINDOWINFO;

typedef struct _RECT {
    LONG left;
    LONG top;
    LONG right;
    LONG bottom;
} RECT, *PRECT;</pre>
<p>这里需要解释一下什么叫做Window Rectangle和Client Rectangle，Window Rectangle顾名思义，就是指当前的Window的所占矩形区域（以屏幕左上角为(0, 0)点）。Client Rectangle就比较麻烦了，它指的是这个Window的真正用户区域，也就是除去border，scrollbars，titlebar等等之后的矩形区域。所以一般来说，Client Rectangle要比Window Rectangle小。</p>
<p>还有一个概念就是Offset坐标，这个指的是当前Window的Window Rectangle和他的父窗口的Client Rectangle的偏移（也就是说以父窗口的Client Rectangle的左上角为原点）。</p>
<p>API中有一些值得我们注意的地方，也是有一点不爽的地方：</p>
<ol>
<li>GetClientRect API返回的并不是以屏幕左上角为原点的坐标，而是以当前window的Client区域的左上角为原点的。所以返回的RECT机构中，right就是window的宽，bottom就是window的高。这个是这几个API中惟一一个不是以屏幕左上角为原点的API，需要多加注意。</li>
<li>GetWindowInfo中返回的WINDOWINFO结构体中的rectClient与GetClientRect返回的RECT不是一回事。WINDOWINFO中的rectClient是以屏幕左上角为原点的Client Rectangle坐标。</li>
<li>SetWindowPos中的x, y参数是表示当前窗口的Window Rectangle的新的左上角的坐标。但是这个坐标是Offset坐标，也就是说，这个坐标不是以屏幕左上角为原点的，而是以父窗口的Client Rectangle的左上角为原点的。</li>
<li>似乎没有API可以直接返回一个window的Offset坐标。</li>
</ol>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li><a href="http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html" title="VC++2005 StringTable资源类型研究">VC++2005 StringTable资源类型研究</a></li><li><a href="http://www.zhangdi.name/2007/08/16/programming-applications-for-microsoft-windows.html" title="《Windows核心编程》&#8211; 经典的书，翻译太烂">《Windows核心编程》&#8211; 经典的书，翻译太烂</a></li><li><a href="http://www.zhangdi.name/2007/01/30/my-understanding-about-exception-handling.html" title="我对异常处理的理解">我对异常处理的理解</a></li><li><a href="http://www.zhangdi.name/2007/01/30/exception-handling-in-java-and-csharp.html" title="也议Java与C#的异常处理实现">也议Java与C#的异常处理实现</a></li><li><a href="http://www.zhangdi.name/2007/09/06/when-ruby-meets-sudoku.html" title="当Ruby遇到数独">当Ruby遇到数独</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.zhangdi.name/2007/07/17/explain-windows-box-model.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VC++2005 StringTable资源类型研究</title>
		<link>http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html</link>
		<comments>http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html#comments</comments>
		<pubDate>Mon, 21 May 2007 15:32:21 +0000</pubDate>
		<dc:creator>zhangdi</dc:creator>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Windows编程]]></category>
		<category><![CDATA[学习]]></category>
		<category><![CDATA[编程]]></category>

		<guid isPermaLink="false">http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html</guid>
		<description><![CDATA[在来到新公司之前，对于Windows编程实在不熟悉，更别说VC++中的Resource的实现了。工作的时候，同事提到了StringTable实现本地化的问题。当时我也很模糊，说不出个准确答案。周末回家研究了两天，算是搞明白了。 先说说我之前比较困惑的几个问题： 在编译完成的二进制文件中，StringTable到底是按照什么方式存储的，简单说，就是按照什么编码方式存储的？ Windows已经支持了Unicode，为什么在VC++的StringTable Editor中，还要选择语言？ 如果使用了Unicode，怎么有的时候，应用程序还会出现乱码？ 如果是Unicode编码，那么是按照什么格式存储的，UTF-8，UTF-16？ 当然，对于这些问题，可能对于一些牛人来说不算什么，都是很简单的问题。不过，对于我来说，还是很麻烦的，因为网上没有很直接解释这些问题的文章，最终还是自己一点一点研究出来的。 首先，需要复习和学习一些知识： 在计算机诞生的初期，操作系统只支持最多256个字符，就是著名的ASCII字符集。但是随着计算机在世界上各个国家的发展，本地化的需求越来越多，256个字符明显不够，就有一些国家发明了自己的字符集，也可以说是编码标准，不过这些编码方式都是只考虑自己国家的语言（当然不会有一个国家为了发展自己的科技，还要替别人着想），比如，ISO-8859-1，GB2312等等，在Windows里面，这类编码的体现就是我们熟悉的Code Page。在VC++中，Code Page是使用数字来代表的，比如：936是简体中文Code Page，1256是阿拉伯语言的Code Page。这样显然不爽，随着计算机的普及，Code Page会越来越多，并且很多Code Page可能相差不多，但是为了支持相应的用户，应用程序（包括操作系统）就不得不对之提供支持，这大大提高了软件的成本。终于，一些软件业的巨头决定做一件一劳永逸的事情，就是创造一个字符编码方式，能支持世界上所有的字符，这个字符集编码叫做Unicode。它设计可以支持11万多的字符，被认为足够放下世界上已知的所有字符（其中，中文字符占了2万多，英文只占52个）。而我们经常看到的UTF-8，UTF-16，UTF-32都是Unicode的一种存储方式。 言归正传，回答自己的四个问题： 从Windows2000开始，Windows已经完全支持了Unicode，所以StringTable在二进制文件（*.dll、*.exe）中确实是以Unicode编码存储的。 在StringTable Editor中，之所以要为StringTable选择相应的语言，是因为StringTable Editor中不是以Unicode存储的，而是基于Code Page编码存储的。所以必须对自己的StringTable选择正确的Code Page，否则系统将不能正确处理。因为在编译的时候，VC++的Resource Compiler会自动调用MultiByteToWideChar这个API，将字符串从Code Page编码方式转化为Unicode，如果Code Page选择不正确，那么转换也就必然不正确了。 出现乱码一个原因是操作系统不支持Unicode，比如Windows98之前的版本。或者是没有将默认编码设置为Unicode。 在Windows中都是使用UTF-16来存储Unicode的。UTF-16正好是两个字节，也就是我们使用的WCHAR类型。 需要说的是，StringTable Editor不是使用Unicode来存储，是因为历史原因。早期的VC++是不支持Unicode的。 相关文章Windows Box Model解析用40行程序能展示多少Ruby的特性？Ruby: puts != print + &#8220;\n&#8221;《Windows核心编程》&#8211; 经典的书，翻译太烂不用代码和类图说设计模式（2）]]></description>
			<content:encoded><![CDATA[<p><!--VC++ develop StringTable 开发 Windows编程 编程--></p>
<p>在来到新公司之前，对于Windows编程实在不熟悉，更别说VC++中的Resource的实现了。工作的时候，同事提到了StringTable实现本地化的问题。当时我也很模糊，说不出个准确答案。周末回家研究了两天，算是搞明白了。</p>
<p>先说说我之前比较困惑的几个问题：</p>
<ul>
<li>在编译完成的二进制文件中，StringTable到底是按照什么方式存储的，简单说，就是按照什么编码方式存储的？</li>
<li>Windows已经支持了Unicode，为什么在VC++的StringTable Editor中，还要选择语言？</li>
<li>如果使用了Unicode，怎么有的时候，应用程序还会出现乱码？</li>
<li>如果是Unicode编码，那么是按照什么格式存储的，UTF-8，UTF-16？</li>
</ul>
<p>当然，对于这些问题，可能对于一些牛人来说不算什么，都是很简单的问题。不过，对于我来说，还是很麻烦的，因为网上没有很直接解释这些问题的文章，最终还是自己一点一点研究出来的。</p>
<p>首先，需要复习和学习一些知识：</p>
<p>在计算机诞生的初期，操作系统只支持最多256个字符，就是著名的ASCII字符集。但是随着计算机在世界上各个国家的发展，本地化的需求越来越多，256个字符明显不够，就有一些国家发明了自己的字符集，也可以说是编码标准，不过这些编码方式都是只考虑自己国家的语言（当然不会有一个国家为了发展自己的科技，还要替别人着想），比如，ISO-8859-1，GB2312等等，在Windows里面，这类编码的体现就是我们熟悉的Code Page。在VC++中，Code Page是使用数字来代表的，比如：936是简体中文Code Page，1256是阿拉伯语言的Code Page。这样显然不爽，随着计算机的普及，Code Page会越来越多，并且很多Code Page可能相差不多，但是为了支持相应的用户，应用程序（包括操作系统）就不得不对之提供支持，这大大提高了软件的成本。终于，一些软件业的巨头决定做一件一劳永逸的事情，就是创造一个字符编码方式，能支持世界上所有的字符，这个字符集编码叫做Unicode。它设计可以支持11万多的字符，被认为足够放下世界上已知的所有字符（其中，中文字符占了2万多，英文只占52个）。而我们经常看到的UTF-8，UTF-16，UTF-32都是Unicode的一种存储方式。</p>
<p>言归正传，回答自己的四个问题：</p>
<ul>
<li>从Windows2000开始，Windows已经完全支持了Unicode，所以StringTable在二进制文件（*.dll、*.exe）中确实是以Unicode编码存储的。</li>
<li>在StringTable Editor中，之所以要为StringTable选择相应的语言，是因为StringTable Editor中不是以Unicode存储的，而是基于Code Page编码存储的。所以必须对自己的StringTable选择正确的Code Page，否则系统将不能正确处理。因为在编译的时候，VC++的Resource Compiler会自动调用MultiByteToWideChar这个API，将字符串从Code Page编码方式转化为Unicode，如果Code Page选择不正确，那么转换也就必然不正确了。</li>
<li>出现乱码一个原因是操作系统不支持Unicode，比如Windows98之前的版本。或者是没有将默认编码设置为Unicode。</li>
<li>在Windows中都是使用UTF-16来存储Unicode的。UTF-16正好是两个字节，也就是我们使用的WCHAR类型。</li>
</ul>
<p>需要说的是，StringTable Editor不是使用Unicode来存储，是因为历史原因。早期的VC++是不支持Unicode的。</p>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li><a href="http://www.zhangdi.name/2007/07/17/explain-windows-box-model.html" title="Windows Box Model解析">Windows Box Model解析</a></li><li><a href="http://www.zhangdi.name/2007/08/22/a-piece-of-ruby-code.html" title="用40行程序能展示多少Ruby的特性？">用40行程序能展示多少Ruby的特性？</a></li><li><a href="http://www.zhangdi.name/2007/08/21/ruby-puts-not-equals-print-plus-back-slash-n.html" title="Ruby: puts != print + &#8220;\n&#8221;">Ruby: puts != print + &#8220;\n&#8221;</a></li><li><a href="http://www.zhangdi.name/2007/08/16/programming-applications-for-microsoft-windows.html" title="《Windows核心编程》&#8211; 经典的书，翻译太烂">《Windows核心编程》&#8211; 经典的书，翻译太烂</a></li><li><a href="http://www.zhangdi.name/2007/03/18/learn-design-pattern-without-coding-and-class-diagram-2.html" title="不用代码和类图说设计模式（2）">不用代码和类图说设计模式（2）</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>不用代码和类图说设计模式（2）</title>
		<link>http://www.zhangdi.name/2007/03/18/learn-design-pattern-without-coding-and-class-diagram-2.html</link>
		<comments>http://www.zhangdi.name/2007/03/18/learn-design-pattern-without-coding-and-class-diagram-2.html#comments</comments>
		<pubDate>Sun, 18 Mar 2007 08:29:07 +0000</pubDate>
		<dc:creator>zhangdi</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[学习]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[设计模式]]></category>

		<guid isPermaLink="false">http://www.zhangdi.name/2007/03/18/learn-design-pattern-without-coding-and-class-diagram-2.html</guid>
		<description><![CDATA[设计模式，实际上是一些很标准的算法解决方案，如果对于一个很常见的问题，一个人使用了设计模式中的方法解决，当别人看代码的时候，也会很爽快。而如果没有，那看代码的人就会很疑惑，问题明明可以很明确的使用某种设计模式解决，那为什么原来是这样的呢？是不是有什么tricky的地方，不得不这样写？无形中延长了时间，并且增加了维护时出问题的机会。 我觉得知道各个模式所表达的算法实现各个设计模式所需要的算法还算容易，而明确的知道什么时候该用什么模式就比较难了。我也经常写出自己后悔的代码来：在写过代码后，review的时候，突然发现，其实可以用更好的方法解决问题。这就是refactoring的作用了吧。呵呵。 二、Singleton, Builder, Prototype模式 这三个模式仍然是关系到对象创建的，但这三个模式特点都很明确，比较容易找到适应的情形。再来讲三个故事： 1、从前，有一个小姑娘叫“春”（这是我高中的时候，一个同学作文中经典的句子，很难忘记~）。我们叫她“春姑娘”吧。有一天她在海边散步的时候，见到了一个油灯，上面写着“Singleton”，小姑娘很好奇，就轻轻摸了一下这些字，突然从灯里面出来了一个灯神，他跟小姑娘说：“谢谢你帮我解除了咒语，我现在自由了。只要你拿着这个灯，什么时候叫一句‘Singleton’，我都会出来。” 小姑娘有些犹豫，我不会喊来坏蛋吧？这个灯我又不熟悉。灯神大笑，这个灯叫“Singleton”，所以每次出来的都只能是我，不会是别人的。甚至替身都不会有。小姑娘高兴的回家了。 2、其实，小姑娘在家里很苦。受到继母的虐待。每天都要做饭，洗衣服，挑水，天不亮就要干活，一直要干到深夜。这天晚上，终于干完了活，睡觉之前，她把灯神交出来，想跟他聊聊天。因为她找不到别人聊天了，能找到的只有这个向她承诺过的灯神了。她把她的苦恼都跟灯神说了，灯神很同情她。（其实，这个灯神就是天界众神派来帮助小姑娘的）临走的时候，送给小姑娘一口锅，上面写着Builder这个单词。小姑娘不解，我现在还有锅啊。灯神说，这个锅是天界众神使用的锅，它的最大特点就是不用人干预就可以做出饭菜。你只需要按照这个菜谱往锅里放进原料，盖上盖子，等一会再打开，就是香喷喷的饭菜了。说着给了小姑娘一本菜谱。 3、自从有了那口神奇的锅，小姑娘的劳累减轻了很多，继母很生气。她又命令小姑娘每天要到海边钓鱼，而且必须钓到十种鱼，每一种鱼100条，这100条鱼必须颜色重量形状都要一样，否则不算。小姑娘哭着说：“这不可能啊~“ 继母狠狠地说：”怎么不可能，钓不完就别回家！“ 小姑娘来到海边，坐在岸上哭了起来。这时，灯神又神秘的出现了。他送给小姑娘一根鱼竿，并说，这个鱼竿是天界众神的鱼竿，这个鱼竿叫&#8217;Prototype&#8217;（天界众神是研究Design Pattern的~），只要是它钓到的鱼，你只要喊：”Clone!“ 就会复制出一个跟这条鱼各个方面都一样的鱼。最终，美丽善良的小姑娘在灯神的帮助下，通过水晶鞋事件，与王子结为夫妻，过上了幸福的生活。 这三个模式从字面上都可以看出来是做什么用的： Singleton Pattern: 中文叫”单件“，顾名思义，就是说只允许有一个实例的对象，而且无论在哪里都可以拿到这个实例。优点是最简单的满足了单一实例的要求，不足之处就是，在哪里都可以拿到，就跟静态变量一样，容易让程序混乱，而且对多线程也是一个挑战。 Builder Pattern: 隐藏构造复杂对象的过程，用户只需要将构建复杂对象的基础对象提供给Builder，就可以得到最终的结果。我们用的输入法实际上就是一种Builder。 Prototype Pattern: 这个模式对于现实生活来说，有些神奇（现在也不是了，因为有了克隆技术），但是对于写程序来说，应该不陌生了。Java, C#等等，都内置了这个Pattern，那就是对象的Clone方法。可以通过一个原形对象，创建出一个与之状态完全一样的对象。与Factory不一样的地方就是，能够保证状态。 创建型模式一共六个，就复习完了。用了一个周末的时间（两个半天）。 Update：一位兄弟指出我把算法和设计模式混淆了。我想了一下，确实是不妥，因为设计模式是在设计阶段考虑的问题，而算法是在实现阶段考虑的问题，不应该混为一谈。不过设计的如何，最终要使用算法来实现。所以我认为设计模式和实现它的算法是密不可分的（否则就不会有那么多本书分别介绍C#, Java等等中的Design Pattern了），而且对于一个开发人员来说，设计和开发更是紧密结合的。 相关文章不用代码和类图说设计模式（1）用40行程序能展示多少Ruby的特性？Ruby: puts != print + &#8220;\n&#8221;VC++2005 StringTable资源类型研究当Ruby遇到数独]]></description>
			<content:encoded><![CDATA[<p>设计模式，实际上是一些很标准的<strike>算法</strike>解决方案，如果对于一个很常见的问题，一个人使用了设计模式中的方法解决，当别人看代码的时候，也会很爽快。而如果没有，那看代码的人就会很疑惑，问题明明可以很明确的使用某种设计模式解决，那为什么原来是这样的呢？是不是有什么tricky的地方，不得不这样写？无形中延长了时间，并且增加了维护时出问题的机会。</p>
<p>我觉得知道<strike>各个模式所表达的算法</strike>实现各个设计模式所需要的算法还算容易，而明确的知道什么时候该用什么模式就比较难了。我也经常写出自己后悔的代码来：在写过代码后，review的时候，突然发现，其实可以用更好的方法解决问题。这就是refactoring的作用了吧。呵呵。</p>
<p>二、Singleton, Builder, Prototype模式</p>
<p>这三个模式仍然是关系到对象创建的，但这三个模式特点都很明确，比较容易找到适应的情形。再来讲三个故事：</p>
<p>1、从前，有一个小姑娘叫“春”（这是我高中的时候，一个同学作文中经典的句子，很难忘记~）。我们叫她“春姑娘”吧。有一天她在海边散步的时候，见到了一个油灯，上面写着“Singleton”，小姑娘很好奇，就轻轻摸了一下这些字，突然从灯里面出来了一个灯神，他跟小姑娘说：“谢谢你帮我解除了咒语，我现在自由了。只要你拿着这个灯，什么时候叫一句‘Singleton’，我都会出来。” 小姑娘有些犹豫，我不会喊来坏蛋吧？这个灯我又不熟悉。灯神大笑，这个灯叫“Singleton”，所以每次出来的都只能是我，不会是别人的。甚至替身都不会有。小姑娘高兴的回家了。</p>
<p>2、其实，小姑娘在家里很苦。受到继母的虐待。每天都要做饭，洗衣服，挑水，天不亮就要干活，一直要干到深夜。这天晚上，终于干完了活，睡觉之前，她把灯神交出来，想跟他聊聊天。因为她找不到别人聊天了，能找到的只有这个向她承诺过的灯神了。她把她的苦恼都跟灯神说了，灯神很同情她。（其实，这个灯神就是天界众神派来帮助小姑娘的）临走的时候，送给小姑娘一口锅，上面写着Builder这个单词。小姑娘不解，我现在还有锅啊。灯神说，这个锅是天界众神使用的锅，它的最大特点就是不用人干预就可以做出饭菜。你只需要按照这个菜谱往锅里放进原料，盖上盖子，等一会再打开，就是香喷喷的饭菜了。说着给了小姑娘一本菜谱。</p>
<p><span id="more-178"></span></p>
<p>3、自从有了那口神奇的锅，小姑娘的劳累减轻了很多，继母很生气。她又命令小姑娘每天要到海边钓鱼，而且必须钓到十种鱼，每一种鱼100条，这100条鱼必须颜色重量形状都要一样，否则不算。小姑娘哭着说：“这不可能啊~“ 继母狠狠地说：”怎么不可能，钓不完就别回家！“ 小姑娘来到海边，坐在岸上哭了起来。这时，灯神又神秘的出现了。他送给小姑娘一根鱼竿，并说，这个鱼竿是天界众神的鱼竿，这个鱼竿叫&#8217;Prototype&#8217;（天界众神是研究Design Pattern的~），只要是它钓到的鱼，你只要喊：”Clone!“ 就会复制出一个跟这条鱼各个方面都一样的鱼。最终，美丽善良的小姑娘在灯神的帮助下，通过水晶鞋事件，与王子结为夫妻，过上了幸福的生活。</p>
<p>这三个模式从字面上都可以看出来是做什么用的：</p>
<p><strong>Singleton</strong> Pattern: 中文叫”单件“，顾名思义，就是说只允许有一个实例的对象，而且无论在哪里都可以拿到这个实例。优点是最简单的满足了单一实例的要求，不足之处就是，在哪里都可以拿到，就跟静态变量一样，容易让程序混乱，而且对多线程也是一个挑战。</p>
<p><strong>Builder</strong> Pattern: 隐藏构造复杂对象的过程，用户只需要将构建复杂对象的基础对象提供给Builder，就可以得到最终的结果。我们用的输入法实际上就是一种Builder。</p>
<p><strong>Prototype</strong> Pattern: 这个模式对于现实生活来说，有些神奇（现在也不是了，因为有了克隆技术），但是对于写程序来说，应该不陌生了。Java, C#等等，都内置了这个Pattern，那就是对象的Clone方法。可以通过一个原形对象，创建出一个与之状态完全一样的对象。与Factory不一样的地方就是，能够保证状态。</p>
<p>创建型模式一共六个，就复习完了。用了一个周末的时间（两个半天）。</p>
<p><font color="#ff0000">Update：一位兄弟指出我把算法和设计模式混淆了。我想了一下，确实是不妥，因为设计模式是在设计阶段考虑的问题，而算法是在实现阶段考虑的问题，不应该混为一谈。不过设计的如何，最终要使用算法来实现。所以我认为设计模式和实现它的算法是密不可分的（否则就不会有那么多本书分别介绍C#, Java等等中的Design Pattern了），而且对于一个开发人员来说，设计和开发更是紧密结合的。</font></p>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li><a href="http://www.zhangdi.name/2007/03/17/learn-design-pattern-without-coding-and-class-diagram-1.html" title="不用代码和类图说设计模式（1）">不用代码和类图说设计模式（1）</a></li><li><a href="http://www.zhangdi.name/2007/08/22/a-piece-of-ruby-code.html" title="用40行程序能展示多少Ruby的特性？">用40行程序能展示多少Ruby的特性？</a></li><li><a href="http://www.zhangdi.name/2007/08/21/ruby-puts-not-equals-print-plus-back-slash-n.html" title="Ruby: puts != print + &#8220;\n&#8221;">Ruby: puts != print + &#8220;\n&#8221;</a></li><li><a href="http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html" title="VC++2005 StringTable资源类型研究">VC++2005 StringTable资源类型研究</a></li><li><a href="http://www.zhangdi.name/2007/09/06/when-ruby-meets-sudoku.html" title="当Ruby遇到数独">当Ruby遇到数独</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.zhangdi.name/2007/03/18/learn-design-pattern-without-coding-and-class-diagram-2.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>不用代码和类图说设计模式（1）</title>
		<link>http://www.zhangdi.name/2007/03/17/learn-design-pattern-without-coding-and-class-diagram-1.html</link>
		<comments>http://www.zhangdi.name/2007/03/17/learn-design-pattern-without-coding-and-class-diagram-1.html#comments</comments>
		<pubDate>Sat, 17 Mar 2007 10:40:02 +0000</pubDate>
		<dc:creator>zhangdi</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[学习]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[设计模式]]></category>

		<guid isPermaLink="false">http://www.zhangdi.name/2007/03/17/learn-design-pattern-without-coding-and-classes-diagram-1.html</guid>
		<description><![CDATA[最近在重新学习C++，也在看公司产品的代码，深切体会到一个大型的项目如果没有很好的代码设计，会为维护带来过大的成本。我想说的代码设计，并不是产品层次的设计，而是developer在写程序的时候，如何设计自己实现功能所使用的编码方式和模式。这就是为什么我突然决定复习设计模式了。我看设计模式还是在大学，虽然多少还有些印象，但真正能拿起来用的就那么几种经常用到的。但设计模式是针对不同问题的不同best practice，所以如果有一种不知道，就可能在coding的时候走弯路，甚至走错路。 我希望能把我复习的过程写成一系列的文章，而且不想用代码和类图来说明，因为这些东西在所有介绍设计模式的书里面都很多，我只想把我复习的心得和问题写出来。难免有错误，希望任何人指出。:) 一、Factory, Abstract Factory, Factory Method模式 这三个模式都跟Factory这个词有关系，所以都是用来创建对象的模式。我最初看到这三个模式的时候，真是有点晕，都是factory，有什么区别呢？在什么时候需要用哪个呢？ 先来讲三个故事： 1、一个匪徒，我们叫他Mr. Pattern，为了要实施对一个银行进行抢劫，需要买一支武器。但他不知道买什么，所以他来到了一家叫&#8221;WeaponFactory&#8221;的武器店。他说了他想要武器后，营业员说，我们这里有A系列手枪、B系列手枪、A系列自动步枪、B系列自动步枪甚至还有Z系列火箭筒，你想要什么就去相应的柜台交钱，然后就可以拿到货了。 2、还是这个Mr. Pattern，他决定不在&#8221;WeaponFactory&#8221;买了，因为那里武器全都摆在一起，太多了，导致店铺太大，根本就没办法逛，而且据说后来因为无法再扩大营业面积最终倒闭了。这次他来到了一个叫“AbstractWeaponFactory”的店。他这回多了个心眼，透着窗户看了看，恩，这回里面不是很乱，好像店里面就摆了一个系列的产品。他不知道这个系列是不是他需要的，抱着试试看的想法，他踏入了店门。突然，一阵眩晕，等再清醒过来，看到面前摆的都是C系列的产品：手枪、步枪等等。这时，一位美丽的导购小姐走过来，对Mr. Pattern说：“感谢您的光临，我们已经根据您的需求和所处的环境，将您自动传送到我们的C系列子店中，在这里您可以买到所有您需要的产品”。Mr. Pattern幸福的晕过去。 3、Mr. Pattern经历过&#8221;AbstractWeaponFactory&#8221;的美好体验并且成功使用C系列产品打劫了一家银行后，在业内非常出名。他现在有钱了，想要点高级货。这次他来到一个名字叫“FactoryMethod Weapon”的店铺。这里的东西似乎没有什么特别的，当Mr. Pattern正要离开的时候，发现每个武器上都有一个小按钮，上面写着“弹药”。难道武器可以自己提供弹药？他按了一下手枪上的，果然有手枪子弹从一个枪身侧面一个隐秘的小口一颗一颗的挤出，正好装满一个弹夹的数量。他又按了一下步枪上的，这次直接从枪托中弹出一个完整的弹夹。Mr. Pattern很兴奋，他不怀好意的又按了一下火箭筒的，似乎没有什么反应，哈哈，也有不灵的，突然这时，门外响起汽车急停的声音，冲进来一个人，这个人全副武装，怀里抱着一颗火箭弹。 这三个故事并不是想说哪个店铺经营最成功，而是想分别举例说明Factory, Abstract Factory和Factory Method三个设计模式的特点。 Factory Pattern: 简单的构造对象。优点是简单，封装对象的构造过程。通过配置和参数，可以某种程度替代Abstract Factory的工作。缺点是只能应对简单的情形，复杂的情况下，很容易导致代码冗长，有太多的条件判断等等。 Abstract Factory Pattern: 根据情景，构建一组关联的对象。优点是: 结构清晰，每个系列的对象在不同的concrete factory中，每次用户只能拿到一个concrete factory, 所以不会有混用的情形。缺点，每多一个系列都要有一个相对应的concrete factory。 Factory Method Pattern: 将创建的操作交给子类来做。比如说，我们要弹药，是写一个Factory来提供各个型号的弹药呢；还是写一个Abstract Factory来根据我们手中的武器得到相应系列的concrete factory，再通过相对应的方法来得到弹药呢；还是我们跟武器说，我们要弹药，然后这个武器自己给你了呢。这就是Factory Method。优点是，提供一个逻辑很清晰的创建对象的接口。缺点是，每个子类都要实现Factory Method，所以当子类过多并且需要创建的对象的种类也过多的时候，就应该考虑使用Abstract Factory来解决问题了。 总结一下，Factory就是简单的创建对象，确实一定要简单，越复杂的情形，就越应该用别的模式；Abstract Factory是针对需要构造的对象明确的分为几个系列，GoF中使用family，我觉得很确切。需要另外的机制，使用户透明的得到concrete factory，比如，配置文件，系统参数等等；Factory Method针对要构造的对象明确的与子类相关。比如，武器的“获得弹药”这步构造，明确地与子类相关，每种武器都不一样，所以我们就把构造的任务交给各个子类，当然，如果不光要弹药，我还要各种零件，那就还不如提供一个资源箱（Abstract Factory）。不过，话说回来，具体情况具体分析。就像具体编码的时候，Factory Method可能是通过Abstract Factory实现的，而Abstract Factory可能通过Factory组成。总之，面对一个问题，找到最适合的模式，那就是高手了。 [...]]]></description>
			<content:encoded><![CDATA[<p><!--develop C++ design pattern talk 设计模式 经验 学习--></p>
<p>最近在重新学习C++，也在看公司产品的代码，深切体会到一个大型的项目如果没有很好的代码设计，会为维护带来过大的成本。我想说的代码设计，并不是产品层次的设计，而是developer在写程序的时候，如何设计自己实现功能所使用的编码方式和模式。这就是为什么我突然决定复习设计模式了。我看设计模式还是在大学，虽然多少还有些印象，但真正能拿起来用的就那么几种经常用到的。但设计模式是针对不同问题的不同best practice，所以如果有一种不知道，就可能在coding的时候走弯路，甚至走错路。</p>
<p>我希望能把我复习的过程写成一系列的文章，而且不想用代码和类图来说明，因为这些东西在所有介绍设计模式的书里面都很多，我只想把我复习的心得和问题写出来。难免有错误，希望任何人指出。:)</p>
<p>一、Factory, Abstract Factory, Factory Method模式</p>
<p>这三个模式都跟Factory这个词有关系，所以都是用来创建对象的模式。我最初看到这三个模式的时候，真是有点晕，都是factory，有什么区别呢？在什么时候需要用哪个呢？</p>
<p>先来讲三个故事：</p>
<p>1、一个匪徒，我们叫他Mr. Pattern，为了要实施对一个银行进行抢劫，需要买一支武器。但他不知道买什么，所以他来到了一家叫&#8221;WeaponFactory&#8221;的武器店。他说了他想要武器后，营业员说，我们这里有A系列手枪、B系列手枪、A系列自动步枪、B系列自动步枪甚至还有Z系列火箭筒，你想要什么就去相应的柜台交钱，然后就可以拿到货了。</p>
<p>2、还是这个Mr. Pattern，他决定不在&#8221;WeaponFactory&#8221;买了，因为那里武器全都摆在一起，太多了，导致店铺太大，根本就没办法逛，而且据说后来因为无法再扩大营业面积最终倒闭了。这次他来到了一个叫“AbstractWeaponFactory”的店。他这回多了个心眼，透着窗户看了看，恩，这回里面不是很乱，好像店里面就摆了一个系列的产品。他不知道这个系列是不是他需要的，抱着试试看的想法，他踏入了店门。突然，一阵眩晕，等再清醒过来，看到面前摆的都是C系列的产品：手枪、步枪等等。这时，一位美丽的导购小姐走过来，对Mr. Pattern说：“感谢您的光临，我们已经根据您的需求和所处的环境，将您自动传送到我们的C系列子店中，在这里您可以买到所有您需要的产品”。Mr. Pattern幸福的晕过去。</p>
<p><span id="more-176"></span></p>
<p>3、Mr. Pattern经历过&#8221;AbstractWeaponFactory&#8221;的美好体验并且成功使用C系列产品打劫了一家银行后，在业内非常出名。他现在有钱了，想要点高级货。这次他来到一个名字叫“FactoryMethod Weapon”的店铺。这里的东西似乎没有什么特别的，当Mr. Pattern正要离开的时候，发现每个武器上都有一个小按钮，上面写着“弹药”。难道武器可以自己提供弹药？他按了一下手枪上的，果然有手枪子弹从一个枪身侧面一个隐秘的小口一颗一颗的挤出，正好装满一个弹夹的数量。他又按了一下步枪上的，这次直接从枪托中弹出一个完整的弹夹。Mr. Pattern很兴奋，他不怀好意的又按了一下火箭筒的，似乎没有什么反应，哈哈，也有不灵的，突然这时，门外响起汽车急停的声音，冲进来一个人，这个人全副武装，怀里抱着一颗火箭弹。</p>
<p>这三个故事并不是想说哪个店铺经营最成功，而是想分别举例说明Factory, Abstract Factory和Factory Method三个设计模式的特点。</p>
<p><strong>Factory</strong> Pattern: 简单的构造对象。优点是简单，封装对象的构造过程。通过配置和参数，可以某种程度替代Abstract Factory的工作。缺点是只能应对简单的情形，复杂的情况下，很容易导致代码冗长，有太多的条件判断等等。</p>
<p><strong>Abstract Factory</strong> Pattern: 根据情景，构建一组关联的对象。优点是: 结构清晰，每个系列的对象在不同的concrete factory中，每次用户只能拿到一个concrete factory, 所以不会有混用的情形。缺点，每多一个系列都要有一个相对应的concrete factory。</p>
<p><strong>Factory Method</strong> Pattern: 将创建的操作交给子类来做。比如说，我们要弹药，是写一个Factory来提供各个型号的弹药呢；还是写一个Abstract Factory来根据我们手中的武器得到相应系列的concrete factory，再通过相对应的方法来得到弹药呢；还是我们跟武器说，我们要弹药，然后这个武器自己给你了呢。这就是Factory Method。优点是，提供一个逻辑很清晰的创建对象的接口。缺点是，每个子类都要实现Factory Method，所以当子类过多并且需要创建的对象的种类也过多的时候，就应该考虑使用Abstract Factory来解决问题了。</p>
<p>总结一下，Factory就是简单的创建对象，确实一定要简单，越复杂的情形，就越应该用别的模式；Abstract Factory是针对需要构造的对象明确的分为几个系列，GoF中使用family，我觉得很确切。需要另外的机制，使用户透明的得到concrete factory，比如，配置文件，系统参数等等；Factory Method针对要构造的对象明确的与子类相关。比如，武器的“获得弹药”这步构造，明确地与子类相关，每种武器都不一样，所以我们就把构造的任务交给各个子类，当然，如果不光要弹药，我还要各种零件，那就还不如提供一个资源箱（Abstract Factory）。不过，话说回来，具体情况具体分析。就像具体编码的时候，Factory Method可能是通过Abstract Factory实现的，而Abstract Factory可能通过Factory组成。总之，面对一个问题，找到最适合的模式，那就是高手了。</p>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li><a href="http://www.zhangdi.name/2007/03/18/learn-design-pattern-without-coding-and-class-diagram-2.html" title="不用代码和类图说设计模式（2）">不用代码和类图说设计模式（2）</a></li><li><a href="http://www.zhangdi.name/2007/08/22/a-piece-of-ruby-code.html" title="用40行程序能展示多少Ruby的特性？">用40行程序能展示多少Ruby的特性？</a></li><li><a href="http://www.zhangdi.name/2007/08/21/ruby-puts-not-equals-print-plus-back-slash-n.html" title="Ruby: puts != print + &#8220;\n&#8221;">Ruby: puts != print + &#8220;\n&#8221;</a></li><li><a href="http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html" title="VC++2005 StringTable资源类型研究">VC++2005 StringTable资源类型研究</a></li><li><a href="http://www.zhangdi.name/2007/09/06/when-ruby-meets-sudoku.html" title="当Ruby遇到数独">当Ruby遇到数独</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.zhangdi.name/2007/03/17/learn-design-pattern-without-coding-and-class-diagram-1.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>我对异常处理的理解</title>
		<link>http://www.zhangdi.name/2007/01/30/my-understanding-about-exception-handling.html</link>
		<comments>http://www.zhangdi.name/2007/01/30/my-understanding-about-exception-handling.html#comments</comments>
		<pubDate>Tue, 30 Jan 2007 14:27:08 +0000</pubDate>
		<dc:creator>zhangdi</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[异常处理]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[观点]]></category>

		<guid isPermaLink="false">http://www.zhangdi.name/2007/01/30/my-understanding-about-exception-handling.html</guid>
		<description><![CDATA[看到了tangrui回应的文章，我想说的是，可能我们对于异常处理的理解有些地方是不一样的。 1. 我认为异常处理绝不是消息传递。这点在《Effective Java》中是明确说明的。因为如果简单地把Exception看成是另外一种返回值，代码会越来越混乱，也不符合Exception这个名词的含义。会让人看不懂，是非常不好的程序风格。（只能说是不好的程序风格，不是错误，因为编译器允许这样做） 2. 我认为RuntimeException和Checked Exception是有明显区别的。在Java中，所有非RuntimeException都是Checked Exception，而在C#中，完全没有区别。可以从字面上理解，RuntimeException是不可预知的异常，比如：NullPointerException（所有可预知的Null，都应该被避免了，剩下的都是不可预知的），BufferOverflowException（鬼知道什么时候会出现~），ArithmeticException（除数是零，永远不能是零的数，突然成了零），等等。而非RuntimeException，都是可以预知的。比如说，IOException（极有可能失败的操作），ClassNotFoundException（也是很有可能出现），InterruptedException（线程被中断，有可能），还有一切与应用逻辑相关的Exception等等。可以认为，如果发生了RuntimeException，那么这个异常必然不是预期可能出现的，都是不可恢复的。所有Checked Exception都是设计者可以预期的异常，大多数是可以恢复的。 3. 所有的RuntimeException都不应该被catch，而所有的Checked Exception都应该被catch。RuntimeException发生，说明程序有问题；Checked Exception发生，说明程序进入了一个可预知的意外情况。如果对于可预知的异常不作处理，那么这个问题是基本的coding问题，应该让编译器检查。 4. 一个接口所可能抛出的所有的Checked Exception都应该是接口设计的一部分。如果只有文档说明，这个风险太大了。很可能漏掉了很重要的异常问题没有处理。我希望可以由编译器来替我承担一部分风险。 所以，我并不是认为C#的方式非常的不好，只是认为，它为开发大型应用，带来了一定的风险。尤其是维护上的。而Java这种方式，非常严谨，在编译阶段为开发人员发现了很多有可能出现的潜在问题，虽然有可能会多写一些代码（其实这些代码是不多写的，无论用Java和C#，最终都是要写这些代码的）。至于tangrui说的，开发小程序可以快速上手的问题，我觉得不存在。因为如果真的是要成为优秀的开发人员，严谨的开发习惯是必须的，并不应该在乎异常处理所带来的麻烦。可以这么说，异常处理是开发过程中，非常重要的一部分。 这个问题我也就说到这里了，表达了我对异常处理的理解。我现在学习工作都要用C++，不能再像Java一样靠编译器了~hehe 相关文章也议Java与C#的异常处理实现Windows Box Model解析VC++2005 StringTable资源类型研究抱歉，发生意外情况，阻碍了 Google 阅读器完成请求。车被划了]]></description>
			<content:encoded><![CDATA[<p><!--develop 技术探讨 java c# 异常处理--></p>
<p>看到了tangrui<a href="http://www.tangrui.net/2007/01/30/answer-zhangdis-questions/">回应的文章</a>，我想说的是，可能我们对于异常处理的理解有些地方是不一样的。</p>
<p>1. 我认为异常处理绝不是消息传递。这点在《Effective Java》中是明确说明的。因为如果简单地把Exception看成是另外一种返回值，代码会越来越混乱，也不符合Exception这个名词的含义。会让人看不懂，是非常不好的程序风格。（只能说是不好的程序风格，不是错误，因为编译器允许这样做）</p>
<p>2. 我认为RuntimeException和Checked Exception是有明显区别的。在Java中，所有非RuntimeException都是Checked Exception，而在C#中，完全没有区别。可以从字面上理解，RuntimeException是不可预知的异常，比如：NullPointerException（所有可预知的Null，都应该被避免了，剩下的都是不可预知的），BufferOverflowException（鬼知道什么时候会出现~），ArithmeticException（除数是零，永远不能是零的数，突然成了零），等等。而非RuntimeException，都是可以预知的。比如说，IOException（极有可能失败的操作），ClassNotFoundException（也是很有可能出现），InterruptedException（线程被中断，有可能），还有一切与应用逻辑相关的Exception等等。可以认为，如果发生了RuntimeException，那么这个异常必然不是预期可能出现的，都是不可恢复的。所有Checked Exception都是设计者可以预期的异常，大多数是可以恢复的。</p>
<p>3. 所有的RuntimeException都不应该被catch，而所有的Checked Exception都应该被catch。RuntimeException发生，说明程序有问题；Checked Exception发生，说明程序进入了一个可预知的意外情况。如果对于可预知的异常不作处理，那么这个问题是基本的coding问题，应该让编译器检查。</p>
<p>4. 一个接口所可能抛出的所有的Checked Exception都应该是接口设计的一部分。如果只有文档说明，这个风险太大了。很可能漏掉了很重要的异常问题没有处理。我希望可以由编译器来替我承担一部分风险。</p>
<p>所以，我并不是认为C#的方式非常的不好，只是认为，它为开发大型应用，带来了一定的风险。尤其是维护上的。而Java这种方式，非常严谨，在编译阶段为开发人员发现了很多有可能出现的潜在问题，虽然有可能会多写一些代码（其实这些代码是不多写的，无论用Java和C#，最终都是要写这些代码的）。至于tangrui说的，开发小程序可以快速上手的问题，我觉得不存在。因为如果真的是要成为优秀的开发人员，严谨的开发习惯是必须的，并不应该在乎异常处理所带来的麻烦。可以这么说，异常处理是开发过程中，非常重要的一部分。</p>
<p>这个问题我也就说到这里了，表达了我对异常处理的理解。我现在学习工作都要用C++，不能再像Java一样靠编译器了~hehe</p>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li><a href="http://www.zhangdi.name/2007/01/30/exception-handling-in-java-and-csharp.html" title="也议Java与C#的异常处理实现">也议Java与C#的异常处理实现</a></li><li><a href="http://www.zhangdi.name/2007/07/17/explain-windows-box-model.html" title="Windows Box Model解析">Windows Box Model解析</a></li><li><a href="http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html" title="VC++2005 StringTable资源类型研究">VC++2005 StringTable资源类型研究</a></li><li><a href="http://www.zhangdi.name/2009/08/12/sorry-there-is-something-blocking-requests-of-google-reader.html" title="抱歉，发生意外情况，阻碍了 Google 阅读器完成请求。">抱歉，发生意外情况，阻碍了 Google 阅读器完成请求。</a></li><li><a href="http://www.zhangdi.name/2009/02/13/my-car-was-incribed.html" title="车被划了">车被划了</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.zhangdi.name/2007/01/30/my-understanding-about-exception-handling.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

