<?xml version="1.0" encoding="GBK" ?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dcterms="http://purl.org/dc/terms/">
 <channel>
  	  <title><![CDATA[远古的迷茫…… ]]></title>
	  <link>http://hydra1983.blog.163.com</link>
	  <description><![CDATA[面朝大海，春暖花开 ]]></description>
	  <language>zh-CN</language>
	  <pubDate>Mon, 6 Oct 2008 15:35:03 +0800</pubDate>
	  <lastBuildDate>Mon, 6 Oct 2008 15:35:03 +0800</lastBuildDate>
	  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
	  <generator><![CDATA[NetEase Space]]></generator>
	  <managingEditor><![CDATA[hydra1983]]></managingEditor>
	  <webMaster><![CDATA[hydra1983]]></webMaster>
		  <ttl>120</ttl>
	  <image>
	  	<title><![CDATA[远古的迷茫…… ]]></title>
	  	<url>http://ava.blog.163.com/photo/De4FXOo6DE_sScM2ykriZw==/1421730107365675671.jpg</url>
	  	<link>http://hydra1983.blog.163.com</link>
	  </image>
  <item>
  	<title><![CDATA[新概念德语MP3]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/1117503720089625825710</link>
    <description><![CDATA[<div><div style="text-align: center;"><embed allowScriptAccess="never" allowNetworking="internal"   src="http://www.box.net/static/flash/box_explorer.swf?widgetHash=kfmyg1v18i&amp;cl=0" wmode="transparent" type="application/x-shockwave-flash" height="345" width="460"></div></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/1117503720089625825710</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/1117503720089625825710</guid>
    <pubDate>Mon, 6 Oct 2008 14:58:25 +0800</pubDate>
    <dcterms:modified>2008-10-06T14:59:56+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[开发人员眼中的项目管理]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/1117503720089614140226</link>
    <description><![CDATA[<div><span></span><a href="http://www.oreillynet.com/pub/au/3511">Stacey Mulcahy</a>在<a href="http://www.insideria.com/" target="_blank">InsideRIA</a>中发表了一系列的文章来阐述开发人员眼中的项目管理是怎样的。<br><a href="http://blogs.oreilly.com/cgi-bin/mt/mt-search.cgi?IncludeBlogs=34&amp;search=Project+Management+from+the+Developer%27s+Perspective" target="_blank">http://blogs.oreilly.com/cgi-bin/mt/mt-search.cgi?IncludeBlogs=34&amp;search=Project+Management+from+the+Developer%27s+Perspective</a></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/1117503720089614140226</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/1117503720089614140226</guid>
    <pubDate>Mon, 6 Oct 2008 01:41:40 +0800</pubDate>
    <dcterms:modified>2008-10-06T01:43:03+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[检测鼠标移动方向]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/11175037200896130737</link>
    <description><![CDATA[<div><p><a href="http://www.kirupa.com/developer/flashcs3/detecting_direction_mouse_movement.htm" target="_blank">原文</a>来自<a href="http://www.kirupa.com/" target="_blank">kirupa</a></p><p>In ActionScript 2, you had the 
     <span>watch</span> function that, among 
     many things, allowed you to detect which direction your 
     mouse cursor was moving. There is a
     <a href="http://www.kirupa.com/developer/actionscript/detecting_mouse_direction.htm">
     tutorial</a> on how to do that on kirupa.com itself. In 
     ActionScript 3, I couldn’t find the watch function nor an 
     equivalent replacement, but creating your own function that 
     shows you how to detect the direction of mouse movement is 
     not very complicated.</p>
     <p>The following is an example of what I will be describing 
     in this article:</p><p><embed allowScriptAccess="never" allowNetworking="internal" src="http://www.kirupa.com/developer/flashcs3/swf/mouseDirectionTutorial.swf" style="display: block;" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="transparent" quality="high">&nbsp;</p>
     <p style="text-align: center;">
     
     </p>
     <p>Move your mouse around in the above movie, and the 
     direction of the mouse's X and Y movement will be displayed. 
     Behind the scenes, what is actually happening is very 
     simple.</p>
     <p>Take a look at the following diagram:</p>
     <p style="text-align: center;">
     <img src="http://www.kirupa.com/developer/flashcs3/images/timeImage.png" height="264" width="436"></p>
     <p>The easiest way to know which direction you are moving in 
     is to figure out where you are now and compare it to where 
     you were just a few seconds ago. That is the magic inside 
     our movie as well. In the above diagram, I show a simple 
     example of a mouse moving across a path with two separate 
     timestamps when the mouse's position was stored - time1 and 
     time2. </p>
     <p>At time 2, you can get an idea of what direction your 
     mouse cursor is moving in by comparing its position at that 
     point with the mouse's position at the earlier time - time 
     1. Using that as our yardstick, you can see that your mouse 
     cursor is moving to the top and to the right. The more 
     frequently you check your position and compare it to an 
     earlier position, the more accurate your measure will be.</p>
     <p><span>Download Source File</span><br>To 
     see how this was done, download the Flash CS3 source file 
     from the following location:</p>
     <table style="width: 100%;" cellpadding="5" cellspacing="0">
      <tbody><tr>
       <td>
       <table style="width: 100%;" cellpadding="10" cellspacing="0">
        <tbody><tr>
         <td style="width: 40px;">
         <a href="http://www.kirupa.com/developer/flashcs3/source/mouseDirectionTutorial.zip">
         <img src="http://www.kirupa.com/large_icons/flashSourceFile.png" height="46" width="42"></a></td>
         <td style="font-size: 9pt; color: rgb(0, 51, 102); letter-spacing: 1px;">
         <a href="http://www.kirupa.com/developer/flashcs3/source/mouseDirectionTutorial.zip">
         <span style="font-weight: bold; color: rgb(0, 51, 102);">
         Download Final Source</span></a></td>
        </tr>
       </tbody></table>
       </td>
      </tr>
     </tbody></table>

     <p>Download and extract the above file and open it in Flash 
     CS3. Much of what you see should be pretty straightforward, 
     but let's look at the contents in greater detail.</p>
     <p><span>Examining the File</span><br>Pretty 
     much everything in the above example is done using code. The 
     only things that aren't in code are the two textfields that 
     display the direction of your mouse movement, so let's go 
     ahead and look at the code:</p>
     <dl><dt><span>var</span>
      <span>prevX</span><span>:</span><span>int</span>
      <span>=</span> <span>0</span>;
      </dt><dt><span>var</span>
      <span>prevY</span><span>:</span><span>int</span>
      <span>=</span> <span>0</span>;
      </dt><dt><span>var</span>
      <span>curX</span><span>:</span><span>int</span>
      <span>=</span> <span>0</span>;
      </dt><dt><span>var</span>
      <span>curY</span><span>:</span><span>int</span>
      <span>=</span> <span>0</span>;
      </dt><dt>&nbsp; </dt><dt><span>var</span>
      <span>dirX</span><span>:</span><span>String</span>
      <span>=</span> <span>""</span>;
      </dt><dt><span>var</span>
      <span>dirY</span><span>:</span><span>String</span>
      <span>=</span> <span>""</span>;
      </dt><dt>&nbsp; </dt><dt><span>function</span>
      <span>Start</span><span>()</span>
      </dt><dt><span>{</span> </dt><dl><dt><span>stage</span>.<span>addEventListener</span><span>(</span><span>MouseEvent</span>.<span>MOUSE_MOVE</span>,
       <span>CheckDirection</span><span>)</span>;</dt></dl><dt><span>}</span> </dt><dt><span>Start</span><span>()</span>;
      </dt><dt>&nbsp; </dt><dt><span>function</span>
      <span>CheckDirection</span><span>(</span><span>e</span><span>:</span><span>MouseEvent</span><span>)</span>
      </dt><dt><span>{</span> </dt><dl><dt><span>var</span>
       <span>xDirection</span><span>:</span><span>String</span>
       <span>=</span> <span>
       GetHorizontalDirection</span><span>()</span>;
       </dt><dt><span>var</span>
       <span>yDirection</span><span>:</span><span>String</span>
       <span>=</span> <span>
       GetVerticalDirection</span><span>()</span>;
       </dt><dt>&nbsp; </dt><dt><span>xText</span>.<span>text</span>
       <span>=</span> <span>
       xDirection</span>; </dt><dt><span>yText</span>.<span>text</span>
       <span>=</span> <span>
       yDirection</span>; </dt><dt>&nbsp; </dt><dt><span>e</span>.<span>updateAfterEvent</span><span>()</span>;</dt></dl><dt><span>}</span> </dt><dt>&nbsp; </dt><dt><span>function</span>
      <span>GetHorizontalDirection</span><span>():</span><span>String</span>
      </dt><dt><span>{</span> </dt><dl><dt><span>prevX</span>
       <span>=</span> <span>
       curX</span>; </dt><dt><span>curX</span>
       <span>=</span> <span>
       stage</span>.<span>mouseX</span>;
       </dt><dt>&nbsp; </dt><dt><span>if</span>
       <span>(</span><span>prevX</span>
       <span>&gt;</span> <span>
       curX</span><span>)</span>
       <span>{</span> </dt><dl><dt><span>dirX</span>
        <span>=</span>
        <span>"left"</span>;</dt></dl><dt><span>}</span>
       <span>else</span>
       <span>if</span>
       <span>(</span><span>prevX</span>
       <span>&lt;</span> <span>
       curX</span><span>)</span>
       <span>{</span> </dt><dl><dt><span>dirX</span>
        <span>=</span>
        <span>"right"</span>;</dt></dl><dt><span>}</span>
       <span>else</span>
       <span>{</span> </dt><dl><dt><span>dirX</span>
        <span>=</span>
        <span>"none"</span>;</dt></dl><dt><span>}</span> </dt><dt>&nbsp; </dt><dt><span>return</span>
       <span>dirX</span>;</dt></dl><dt><span>}</span> </dt><dt>&nbsp; </dt><dt><span>function</span>
      <span>GetVerticalDirection</span><span>():</span><span>String</span>
      </dt><dt><span>{</span> </dt><dl><dt><span>prevY</span>
       <span>=</span> <span>
       curY</span>; </dt><dt><span>curY</span>
       <span>=</span> <span>
       stage</span>.<span>mouseY</span>;
       </dt><dt>&nbsp; </dt><dt><span>if</span>
       <span>(</span><span>prevY</span>
       <span>&gt;</span> <span>
       curY</span><span>)</span>
       <span>{</span> </dt><dl><dt><span>dirY</span>
        <span>=</span>
        <span>"up"</span>;</dt></dl><dt><span>}</span>
       <span>else</span>
       <span>if</span>
       <span>(</span><span>prevY</span>
       <span>&lt;</span> <span>
       curY</span><span>)</span>
       <span>{</span> </dt><dl><dt><span>dirY</span>
        <span>=</span>
        <span>"down"</span>;</dt></dl><dt><span>}</span>
       <span>else</span>
       <span>{</span> </dt><dl><dt><span>dirY</span>
        <span>=</span>
        <span>"none"</span>;</dt></dl><dt><span>}</span> </dt><dt>&nbsp; </dt><dt><span>return</span>
       <span>dirY</span>;</dt></dl><dt><span>}</span></dt></dl>
     <p>Don't let the number of lines of code scare you! It is 
     very simple because much of the code is duplicated to handle 
     movement vertically as well as horizontally. Let's just look 
     at the horizontal case in more detail.</p>
     <p>Let's start with the GetHorizontalDirection() function:</p>
     <dl><dt><span>function</span>
      <span>GetHorizontalDirection</span><span>():</span><span>String</span>
      </dt><dt><span>{</span> </dt><dl><dt><span>prevX</span>
       <span>=</span> <span>
       curX</span>; </dt><dt><span>curX</span>
       <span>=</span> <span>
       stage</span>.<span>mouseX</span>;
       </dt><dt>&nbsp; </dt><dt><span>if</span>
       <span>(</span><span>prevX</span>
       <span>&gt;</span> <span>
       curX</span><span>)</span>
       <span>{</span> </dt><dl><dt><span>dirX</span>
        <span>=</span>
        <span>"left"</span>;</dt></dl><dt><span>}</span>
       <span>else</span>
       <span>if</span>
       <span>(</span><span>prevX</span>
       <span>&lt;</span> <span>
       curX</span><span>)</span>
       <span>{</span> </dt><dl><dt><span>dirX</span>
        <span>=</span>
        <span>"right"</span>;</dt></dl><dt><span>}</span>
       <span>else</span>
       <span>{</span> </dt><dl><dt><span>dirX</span>
        <span>=</span>
        <span>"none"</span>;</dt></dl><dt><span>}</span> </dt><dt>&nbsp; </dt><dt><span>return</span>
       <span>dirX</span>;</dt></dl><dt><span>}</span></dt></dl>
     <p>The first thing I do is set the value of our prevX 
     variable to our curX variable. This is the equivalent of our 
     Time 0 case. Next, I set our curX variable to the horizontal 
     position of our mouse currently.</p>
     <p>To reuse that image from earlier, here is what this would 
     look like:</p>
     <p style="text-align: center;">
     <img src="http://www.kirupa.com/developer/flashcs3/images/timeImage2.png" height="264" width="436"></p>
     <p>The previous position is stored by prevX, and the current 
     position is stored by curX. Comparing them both gives you 
     the information you would need to decide which direction 
     your mouse is moving. That is all handled by the following 
     code inside GetHorizontalDirection:</p>
     <dl><dt><span style="color: rgb(192, 192, 192);">
      function</span>
      <span style="color: rgb(192, 192, 192);">
      GetHorizontalDirection</span><span style="color: rgb(192, 192, 192);">():</span><span style="color: rgb(192, 192, 192);">String</span><span style="color: rgb(192, 192, 192);">
      </span></dt><dt><span style="color: rgb(192, 192, 192);">{</span><span style="color: rgb(192, 192, 192);">
      </span></dt><dl><dt><span style="color: rgb(192, 192, 192);">
       prevX</span>
       <span style="color: rgb(192, 192, 192);">=</span>
       <span style="color: rgb(192, 192, 192);">curX</span><span style="color: rgb(192, 192, 192);">;
       </span></dt><dt><span style="color: rgb(192, 192, 192);">
       curX</span>
       <span style="color: rgb(192, 192, 192);">=</span>
       <span style="color: rgb(192, 192, 192);">stage</span>.<span style="color: rgb(192, 192, 192);">mouseX</span><span style="color: rgb(192, 192, 192);">;
       
       </span></dt><dt>&nbsp; </dt><dt><span>if</span>
       <span>(</span><span>prevX</span>
       <span>&gt;</span> <span>
       curX</span><span>)</span>
       <span>{</span> </dt><dl><dt><span>dirX</span>
        <span>=</span>
        <span>"left"</span>;</dt></dl><dt><span>}</span>
       <span>else</span>
       <span>if</span>
       <span>(</span><span>prevX</span>
       <span>&lt;</span> <span>
       curX</span><span>)</span>
       <span>{</span> </dt><dl><dt><span>dirX</span>
        <span>=</span>
        <span>"right"</span>;</dt></dl><dt><span>}</span>
       <span>else</span>
       <span>{</span> </dt><dl><dt><span>dirX</span>
        <span>=</span>
        <span>"none"</span>;</dt></dl><dt><span>}</span> </dt><dt>&nbsp;<span style="color: rgb(192, 192, 192);"> </span></dt><dt><span>return</span>
       <span>dirX</span>;</dt></dl><dt><span style="color: rgb(192, 192, 192);">}</span></dt></dl>
     <p>Notice that I check for the <strong><em>left</em></strong>,
     <strong><em>right</em></strong>, and <strong><em>none</em></strong> 
     cases, and return that value back to whatever called this 
     function. And what called this function you ask? It is our
     <span>CheckDirection</span> function 
     which is actually the event handler for our
     <span>MouseMove</span> event:</p>
     <dl><dt><span>function</span>
      <span>CheckDirection</span><span>(</span><span>e</span><span>:</span><span>MouseEvent</span><span>)</span>
      </dt><dt><span>{</span> </dt><dl><dt><span>var</span>
       <span>xDirection</span><span>:</span><span>String</span>
       <span>=</span> <span>
       GetHorizontalDirection</span><span>()</span>;
       </dt><dt><span>var</span>
       <span>yDirection</span><span>:</span><span>String</span>
       <span>=</span> <span>
       GetVerticalDirection</span><span>()</span>;
       </dt><dt>&nbsp; </dt><dt><span>xText</span>.<span>text</span>
       <span>=</span> <span>
       xDirection</span>; </dt><dt><span>yText</span>.<span>text</span>
       <span>=</span> <span>
       yDirection</span>; </dt><dt>&nbsp; </dt><dt><span>e</span>.<span>updateAfterEvent</span><span>()</span>;</dt></dl><dt><span>}</span></dt></dl>
     <p>There is nothing complicated here at all. Each time your 
     mouse moves, this function gets called, and it calls the 
     GetHorizontalDirection function you saw earlier for 
     horizontal data, and it calls the GetVerticalDirection 
     function for the vertical data.</p>
     <p>Both of those function return a direction as their 
     result, and you send those results to their respective text 
     fields xText and yText.</p>
     <hr>
     <p><span>Conclusion</span><br>That's all 
     there is to detecting the direction of mouse movement. This 
     is a great example of implementing something in code that 
     resembles how we as humans would solve this problem as well. 
     We use frames of reference to gauge many things - including 
     what direction we are moving in. The code I presented is 
     nothing more than using variables to store frames of data 
     and comparing them.</p></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/11175037200896130737</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/11175037200896130737</guid>
    <pubDate>Mon, 6 Oct 2008 01:30:07 +0800</pubDate>
    <dcterms:modified>2008-10-06T01:31:52+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Flash放大镜效果]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/1117503720089612812513</link>
    <description><![CDATA[<div><p><a href="http://www.flashandmath.com/intermediate/magglass/index.html" target="_blank">原文</a>来自<a href="http://www.flashandmath.com/" target="_blank">flashandmath</a> 
</p><p>We show how to easily create a magnifying glass effect in Flash and AS3. The applet below
is easy to customize and the instructions are provided in the corresponding 'fla'
file that you can download from the link under the image. We also show how to load images at runtime
and easily display load progress.
</p>

<p>
Click on the image to open the live appplet in a separete window. 
</p>

<p align="center">

<a  href="http://www.flashandmath.com/intermediate/magglass/mag_glass.html" target="_blank"><img src="http://www.flashandmath.com/intermediate/magglass/magglass.jpg" height="330" width="500"></a>

</p>

<p >Download</p>
<ul><li>A the 'zip' file with the 'fla' and 'jpg' files corresponding to the applet <a  href="http://www.flashandmath.com/intermediate/magglass/mag_glass.zip">mag_glass.zip</a></li></ul>


<p>
<strong>How to customize?</strong> 

</p>

<ul type="disc"><li>
To use your own picture, simply change the name of the picture
on line 76 of mag_glass.fla in the package. Make sure your picture is in the same directory as your html page
(or give an address to your file.) For good magnifying effect, the picture should be of rather high resolution
while the displayed picture should be its scaled-down version. All variables will automatically
adjust to the dimensions of your image.
</li><li>
To change the scale-down factor, change the value of 'shrinkFactor' variable on line 62.
</li><li>
To change the size of the rectangular magnifying glass, change the values of the variables
'glassWidth' and 'glassHeight' on lines 42 and 43.
</li><li>
To create a circular magnifying glass, set 'glassHeight' and 'glassWidth' to the same value
and change line 179 to: <br>

&nbsp;&nbsp; glass.graphics.drawCircle(glassWidth/2,glassWidth/2,glassWidth/2);
</li></ul>

<p>
<strong>Displaying Load progress</strong> 

</p>

<p>
It is very easy. You simply attach an event listener to your instance of the Loader class
that listens to the PROGRESS event and displays the result in a dynamic TextField.
In our case, we have 'loader' and 'infoBox'. The code looks as follows.
</p>

<p >startApp();</p>

<p >&nbsp;</p>

<p >function startApp():void {</p>
 
 <p >loader=new Loader();</p>
    
    <p >...........................</p>

    <p >...........................</p>

 <p >loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,updateInfo);</p>
 
<p >}</p>

<p >&nbsp;</p>

<p >function updateInfo(e:ProgressEvent):void {</p>
 
 <p >infoBox.text="Loading: "+String(Math.floor(e.bytesLoaded/1024))+</p>
    
     <p >" KB of "+String(Math.floor(e.bytesTotal/1024))+" KB.";</p>
 
<p >}</p>

<p >&nbsp;</p>

<p>
After loading is complete, we remove 'updateInfo' listener as well as other listeners attached to 'loader'.
</p></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/1117503720089612812513</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/1117503720089612812513</guid>
    <pubDate>Mon, 6 Oct 2008 01:28:12 +0800</pubDate>
    <dcterms:modified>2008-10-06T01:28:12+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Moccasin:基于Flex的图形编辑程序开发框架]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/111750372008961243693</link>
    <description><![CDATA[<div><p><a href="http://www.joeberkovitz.com/blog/2008/09/30/moccasin-intro/" target="_blank">原文</a>来自<a href="http://www.joeberkovitz.com/" target="_blank">joeberkovitz.com</a></p><p>Lately I’ve been working on a set of projects (both my own and others) that are built on top of <a href="http://code.google.com/p/moccasin/">Moccasin</a>,
a new open source AS3 framework that I’ve developed for building
graphical editors. Moccasin was distilled and refactored out of the
first project that used these ideas so that I could use it elsewhere
without IP issues, and it lives on Google Code. Moccasin still has a
long way to go in terms of overview documentation and I have to ask a
certain amount of forgiveness on that subject. I’m perhaps releasing it
a bit prematurely, but I regard it as pretty useful in a practical
sense since I’m now working on the third substantial application built
on top of it. This post is an attempt to bite off a little bit of that
overview problem and endow Moccasin with a little more value to other
people.</p>
<p>If the current lack of great overview docs is the bad news, well,
the good news about Moccasin is that it’s got a complete sample editor
application called Simpleworld as part of the distribution, with both
AIR and Flex versions. Both the Moccasin framework and the sample
application source code are pretty well commented, also. Here’s the
Simpleworld application itself, to give a concrete sense of what
Moccasin’s all about — it’s an editor for documents that consist of a
bunch of squares of different sizes (I don’t call this world “simple”
for nothin’):</p>
<p></p>
<p>Here are some of the things you can do, which show off what Moccasin’s about…<span></span></p>
<ul><li>load and save XML documents on the server.  View the one that’s loaded by the above example <a href="http://www.joeberkovitz.com/projects/moccasin-demo/document1.xml">here</a>.</li><li>Click any square to select it singly, Ctrl/Command-click squares to make discontinuous selections</li><li>Click on the background to add a new square to the world</li><li>Drag any selected square to move all selected squares together</li><li>Drag the mouse across the background to select all squares intersecting that rectangle</li><li>Delete, Cut, Copy or Paste any selected objects</li><li>Resize any individual square by dragging its resize handle (generalizes easily to multiple object handles)</li><li>Undo/redo the last N editing actions</li><li>View the graphical document at any desired magnification using the zoom slider</li></ul>
<p>That’s the externally visible stuff; what about the internals,
though? Moccasin is a framework for building applications, not a single
application. Some of the above features are built right into Moccasin
(like undo/redo or magnification), while others are implemented on top
of it (like square objects, or the ability to resize them with a
draggable handle).</p>
<p>Moccasin is not a “thin” framework that encapsulates a set of
recommended practices like Cairngorm. It’s more of a “thick” framework.
Moccasin is aimed at building a particular type of app: one with
interactive graphical views that support a lot of mouse gestures, have
some notion of compound or nested views, have some notion of a current
selection, a clipboard for cut/copy/paste, need robust undo/redo, and
must load and save documents to persist the editor state. The views in
question are generally not Flex UIComponents in Canvases or Boxes, but
lower-level Flash DisplayObjects that can have very arbitrary shapes
and layout geometries. Within this domain, Moccasin very much adheres
to an MVCS way of thinking: there is a model representing the edited
document’s state, a set of views that adjust to the model’s state via
events, a controller which changes the model in response to user
actions, and a set of services responsible for talking to the world
around and outside the application.</p>
<p>Let me devote the rest of this post to a few observations on
Moccasin’s treatment of the Model/View relationship. I’ll try to keep
up a series of posts over the coming weeks and, with some luck,
accumulate some overview materials in fits and starts. Probably the
only way it’s going to happen given my schedule these days.</p>
<p>The way Moccasin treats Models and Views is somewhat unique (where
by “unique” I mean, “I never tried it before” — I’m sure someone else
has!). As usual, one goal here is to absolutely separate view objects
from models: views can reference models, but never the other way
around. This not only keeps the architecture clean, but it is
absolutely essential to permit multiple views of the same model. A
second primary goal is that any change to the model should cause the
view to adjust itself accordingly without additional effort by the
programmer. This involves more than just data bindings: creating a
model should cause the view to be added to the display list, and
removing a model from the document must cause the view to vanish.</p>
<p>A common approach to model objects in a graphical editor is to make
them inherit from some big old AbstractModel superclass with a boatload
of common code in it. This code consists of all the gears and wires to
dispatch the right events when the model changes, or when its set of
children changes, or when some descendant model changes, or to generate
a stable ID for use in document persistence… a lot of junk.</p>
<p>By contrast, here is a SimpleWorld-style class (with comments removed for brevity):</p>
<pre>    [RemoteClass]<br>    [Bindable]<br>    public class Square<br>    {<br>        public var x:Number;<br>        public var y:Number;<br>        public var size:Number;<br>    }<br></pre>
<p>Hey, what’s up? This model class has no methods and extends… Object!
(Actually, EventDispatcher, due to the Bindable tag, but we’re
splitting hairs).</p>
<p>In Moccasin, there are actually two sets of model objects: the <em>domain-specific model</em> (that application programmers work with) and the <em>framework model</em>
(that Moccasin deals with). The developer of a Moccasin app only writes
code against the domain-specific model, and Moccasin automatically
wraps that model object inside another object of type MoccasinModel.
MoccasinModel is where the “framework junk” lives, but the application
programmer doesn’t see it.</p>
<p>There is also going to be a corresponding View class to draw a
Square on the screen — SquareView. Here’s a sense of what a view class
looks like:</p>
<pre>    public class SquareView extends ShapeView<br>    {<br>        public function SquareView(context:ViewContext, model:MoccasinModel=null)<br>        {<br>            super(context, model);<br>            initialize();<br>        }<br><br>        override protected function updateView():void<br>        {<br>            super.updateView();<br><br>            graphics.beginFill(0);<br>            var square:Square = model.value as Square;<br>            graphics.drawRect(0, 0, square.size, square.size);<br>            graphics.endFill();<br>        }<br><br>        override protected function createFeedbackView():DisplayObject<br>        {<br>            return new SquareFeedback(context, model);<br>        }<br>    }</pre>
<p>Because of the strong decoupling between the view, the framework
model and the domain-specific model, application programmers can wind
up writing very pure code to manipulate the model that doesn’t have to
have any dependencies on Moccasin. You can say something like <tt>mySquare.x += 100</tt>,
and this will cause the framework to adjust the corresponding
SquareView object to be redrawn in a different position. Changing an
‘x’ property doesn’t seem very exciting, but consider that it’s not
SquareView’s ‘x’ property being changed: it’s the Square’s property. In
fact, the relationship between model properties and view properties can
be quite arbitrary. We could have some other view of our Squares
besides a 2D rendering, perhaps a numerical SquareCoordinatesTable with
an X column, and a Y column, and Moccasin would manage that model/view
relationship in much the same way.</p>
<p>It’s getting near my lame-old-guy bedtime and I’m flagging. I feel
better for having squeezed this post out at the end of a long day
though; now to keep it going! Next probable topic: Mediators, Contexts
and Controllers in Moccasin.</p></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/111750372008961243693</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/111750372008961243693</guid>
    <pubDate>Mon, 6 Oct 2008 01:24:36 +0800</pubDate>
    <dcterms:modified>2008-10-06T01:25:42+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[iPhone要支持Flash了？]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/1117503720089612222308</link>
    <description><![CDATA[<div><a href="http://www.insideria.com/2008/10/flash-on-the-iphone.html" target="_blank">原文</a>来自<a href="http://www.insideria.com/" target="_blank">InsideRIA</a><br>奥多比正在为将Flash移植到iPhone上努力着，只是不知道确切的时间，希望不要让开发人员等的太久～<br><br><p>I can hear it now... everyone saying "finally".   It was announced at <a target="_blank" href="http://www.flashonthebeach.com/">Flash on the Beach</a> this week that <a target="_blank" href="http://www.adobe.com/">Adobe</a> is working on Flash for the <a href="http://www.apple.com/iphone/" target="_blank">iPhone</a>.</p>

<p>There is no set date when this will be available, as it is up to
Apple to determine, but the Flash/Flex development community is eagerly
awaiting the news.</p>

<p>You can get more information regarding the announcement at:</p>

<p>Flash Magazine:<br>
<a target="_blank" href="http://www.flashmagazine.com/news/detail/flash_for_the_iphone_confirmed_at_fotb/">http://www.flashmagazine.com/news/detail/flash_for_the_iphone_confirmed_at_fotb/</a></p>

<p>PC World<br>
<a target="_blank" href="http://blogs.pcworld.com/staffblog/archives/007842.html">http://blogs.pcworld.com/staffblog/archives/007842.html</a></p>

<p>Adobe Feeds:<br>
<a target="_blank" href="http://feeds.adobe.com/index.cfm?searchterms=iphone&amp;query=bySimpleSearch&amp;searchsortby=date">http://feeds.adobe.com/index.cfm?searchterms=iphone&amp;query=bySimpleSearch&amp;searchsortby=date</a></p>

<p>Google:<br>
<a target="_blank" href="http://www.google.com/search?hl=en&amp;client=firefox-a&amp;rls=org.mozilla%3Aen-US%3Aofficial&amp;hs=ZqP&amp;q=iphone+flash+on+the+beach&amp;btnG=Search">http://www.google.com/search?hl=en&amp;client=firefox-a&amp;rls=org.mozilla%3Aen-US%3Aofficial&amp;hs=ZqP&amp;q=iphone+flash+on+the+beach&amp;btnG=Search</a></p><br></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/1117503720089612222308</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/1117503720089612222308</guid>
    <pubDate>Mon, 6 Oct 2008 01:22:22 +0800</pubDate>
    <dcterms:modified>2008-10-06T01:22:22+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[自己编译as3corelib ]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/1117503720089605951602</link>
    <description><![CDATA[<div><a href="http://sban.flexblogs.cn/2008/08/31/how-to-use-json-with-as3corelib-in-flex/" target="_blank">原文</a>来自<a href="http://sban.flexblogs.cn/" target="_blank">sban.flexblogs.cn</a><br><p>用svn(<a href="http://as3corelib.googlecode.com/svn/trunk/">http://as3corelib.googlecode.com/svn/trunk/</a>)获取到最新的开发版本至as3corelib目录，包括examples,docs,src,tests目
录。examples只包括一个json的例子。docs是用asdoc生成的，如果看源码，就不用看它了。tests是用flexunit写的测试。</p>
<p>学习使用as3corelib，最好是自己编码，而不是使用开发者已经编译好的swc文件。如果用flex builder 3创建library，把src文件添加进来之后，出现找不到flash.filesystem.File之类的错误，可按如下方法解决：</p>
<p>右键打开项目属性&gt;Flex Library Compile&gt;选择Include Adobe air
libraries。flash.filesystem.File,与FileStream,FileMode均属于系统文件操作类，位于AIR
Library中。</p>
<p><a href="http://blog.sban.com.cn/download/2008/08/include-adobe-air-libraries.jpg"><img wp-image-138 alignnone" src="http://blog.sban.com.cn/download/2008/08/include-adobe-air-libraries.jpg" alt="" height="129" width="374"></a></p>
<p>编译通过，一般会在bin目录生成一个swc文件。新建一个project，引用这个library。</p><br></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/1117503720089605951602</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/1117503720089605951602</guid>
    <pubDate>Mon, 6 Oct 2008 00:59:51 +0800</pubDate>
    <dcterms:modified>2008-10-06T00:59:51+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[網頁的柵格系統設計 ]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/11175037200882785222925</link>
    <description><![CDATA[<div><a href="http://www.wowbox.com.tw/blog/article.asp?id=3050" target="_blank">原文</a>来自<a href="http://www.wowbox.com.tw/blog/" target="_blank">wowbox blog</a><br><img style="cursor: pointer;" title="在新窗口打開圖片" src="http://www.wowbox.com.tw/blog/attachments/month_0809/b20089203275.jpg" alt="" border="0"><br><br><strong>柵格系統的形成</strong><br><br>1692
年，新登基的法國國王路易十四感到法國的印刷水平強差人意，因此命令成立一個管理印刷的皇家特別委員會。他們的首要任務是設計出科學的、合理的，
重視功能性的新字體。委員會由數學家尼古拉斯加宗（Nicolas
Jaugeon）擔任領導，他們以羅馬體為基礎，採用方格為設計依據，每個字體方格分為64個基本方各單位，每個方各單位再分成36個小格，這樣，一個印
刷版面就有
2304個小格組成，在這個嚴謹的幾何網格網絡中設計字體的形狀，版面的編排，試驗傳達功能的效能，這是是世界上最早對字體和版面進行科學實驗的活動，也
是柵格系統最早的雛形。<br><br>柵格系統英文為「grid
systems」，也有人翻譯為「網格系統」，其實是一回事。不過從定義上說，柵格更為準確些，從維基百科查到柵格的定義為：柵格設計系統（又稱網格設計
系統、標準尺寸系統、程序版面設計、瑞士平面設計風格、國際主義平面設計風格），是一種平面設計的方法與風格。運用固定的格子設計版面佈局，其風格工整簡
潔，在二戰後大受歡迎，已成為今日出版物設計的主流風格之一。<br><br><strong>網頁設計中的柵格系統</strong> <br><br>給網頁柵格系統下的定義為：以規則的網格陣列來指導和規範網頁中的版面佈局以及信息分佈。<br>網頁柵格系統是從平面柵格系統中發展而來。對於網頁設計來說，柵格系統的使用，不僅可以讓網頁的信息呈現更加美觀易讀，更具可用性。而且，對於前端開發來說，網頁將更加的靈活與規範。<br><br><img style="cursor: pointer;" title="在新窗口打開圖片" src="http://www.wowbox.com.tw/blog/attachments/month_0809/2200892032713.jpg" alt="" border="0"><br><img style="cursor: pointer;" title="在新窗口打開圖片" src="http://www.wowbox.com.tw/blog/attachments/month_0809/3200892032723.jpg" alt="" border="0"><br><br>柵格系統在現在的網頁設計中應用越來越多，從網絡上搜羅了一篇關於柵格系統應用的文章：<a target="_blank" href="http://www.yeeyan.com/articles/view/snlchina/3570">30個最頂尖的基於柵格系統的博客網站設計</a>。<br><br><strong>柵格系統的設計原理及應用</strong><br><br>那麼如何設計一個柵格系統？接下來我們將通過實例，詳細的介紹一下網頁柵格系統的原理與應用：<br><br><img src="http://www.wowbox.com.tw/blog/attachments/month_0809/p200892032855.jpg" alt="" border="0"><br><br>在網頁設計中，我們把寬度為「W」的頁面分割成n個網格單元「a」，每個單元與單元之間的間隙設為「i」,此時我們把「a+i」定義「A」。他們之間的關係如下：<br>W =（a×n）+（n-1）i<br>由於a+i=A，<br>可得：(A×n) - i = W<br>這個公式表述了網頁的佈局與網頁「背後」的柵格系統之間的某種關係。我們拿yahoo作例，來看一下柵格系統的應用：<br><br><img style="cursor: pointer;" title="在新窗口打開圖片" src="http://www.wowbox.com.tw/blog/attachments/month_0809/1200892032919.jpg" alt="" border="0"><br><br>yahoo的網站頁面寬度為W=950px，每個區塊與區塊的間隔為i=10px；如果應用上面的公式，可以推出A=40px，既yahoo首頁橫向版式設計採用的柵格系統為：<br>（40×n）- 10 = W<br>下面我們列出當n等於不同數值時W變化的數值表格 ：<br><br><img style="cursor: pointer;" title="在新窗口打開圖片" src="http://www.wowbox.com.tw/blog/attachments/month_0809/y200892032937.jpg" alt="" border="0"><br><br>從
表格可以看出：yahoo首頁的佈局完全是按照柵格系統進行設計的，每個區塊的寬度對應的n值分別為：4，11，9。在這裡我們看到一個很有意思
的事情：只要保證一個橫向維度的各個區塊的n值相加等於24，則即可保證頁面的寬度一定是950px。然而，950px的寬度也恰好就是當n=24的時
候，W的寬度值。由此我們得出以下的應用模式：<br><br><img style="cursor: pointer;" title="在新窗口打開圖片" src="http://www.wowbox.com.tw/blog/attachments/month_0809/s200892032952.jpg" alt="" border="0"><br><br>在
柵格系統中，設計師根據需要制定不同的版式或者劃分區塊，他們的依據將是上面的那張對應表進行設計。這樣，一個柵格系統的應用就從此開始了。我們
看到，使用柵格系統的網頁設計，非常的有條理性；看上去也很舒服。最重要的是，它給整個網站的頁面結構定義了一個標準。對於視覺設計師來說，他們不用再為
設計一個網站每個頁面都要想一個寬度或高度而煩惱了。對於前端開發工程師來說，頁面的佈局設計將完全是規範的和可重用的，這將大大節約了開發成本。對於內
容編輯或廣告銷售來說，所有的廣告都是規則的，通用的，他們再也不用做出一套N張不同尺寸的廣告圖了……<br><br>當然只要你願意，我們可以衍生出
任何一種柵格系統，只要改變A和i的值，這個根據網站的實際情況來制定。那麼如何選擇合適柵格系統，主要通過「構成
要素與程序、限制與選擇、構成要素的比例、組合、虛空間與組合、四邊聯繫與軸的聯繫、三的法則、圓與構成、水平構成這些設計元素規劃，來實現比例和諧的平
面設計」。比較深奧，我們在這裡就不詳細闡述了。<br><br>說了一堆柵格系統的優點。大家可能會問：難道柵格系統真的是完美的麼？答案是否定的：對於內容信息不確定導致高度不確定的頁面，在高度層面上就無法做到柵格了。當然，具體的情況還需具體的分析與解決，這就需要設計師們在實際的應用中不斷的總結經驗，不斷實踐了。
     <br></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/11175037200882785222925</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/11175037200882785222925</guid>
    <pubDate>Sat, 27 Sep 2008 08:52:22 +0800</pubDate>
    <dcterms:modified>2008-09-27T08:52:22+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[离开的日子]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/1117503720088277373229</link>
    <description><![CDATA[<div>真的很想去送她<br>飞机离开大地<br>在蔚蓝中留下白色印记<br>消失在天的尽头<br><br>她像一只飞鸟<br>自由的飞翔<br>自由的歌唱<br>寻找那片属于自己的天空<br><br>她是那样美丽温柔<br>浅浅的酒窝总带给人说不出的安定<br>即使是淡淡的皱眉<br>也禁不住让人陶醉<br><br>她是那样坚强<br>痛苦无法战胜她<br>磨难无法战胜她<br>迎接它们的<br>只是浅浅的微笑<br><br>她过于善良<br>总不忍心伤害别人<br>却忘记别人总是伤害她<br>希望在遥远的国度<br>这善良带给她的永远是好运<br><br>飞吧，快乐的飞吧<br>找到属于自己的天空<br>即使面对狂风暴雨<br>你总能化险为夷<br><br>飞吧，快乐的飞吧<br>快乐的你<br>一定能找到自己的幸福<br><br>……<br><br>再见，自由的飞鸟<br>再见，往日的友谊<br>再见，永恒的爱情<br>再见，一切的一切<br>再见……<br><br>Stray birds of summer <br>come to my window <br>to sing and fly away<br><br>Yellow leaves of autumn<br>which have no songs<br>flutter and fall there <br>with a sigh……<br><br><br></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/1117503720088277373229</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/1117503720088277373229</guid>
    <pubDate>Sat, 27 Sep 2008 07:37:03 +0800</pubDate>
    <dcterms:modified>2008-09-27T07:40:32+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[跌跌撞撞的持续集成之路：J2EE+Flex持续集成开发]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/11175037200882494034184</link>
    <description><![CDATA[<div><p><a href="http://www.infoq.com/cn/articles/road-of-ic" target="_blank">原文</a>来自<a href="http://www.infoq.com/" target="_blank">InfoQ</a></p><p>“天下事头绪纠缠，兴一利必也生一弊。”</p><p>一句话，道破了改进难点所在。最近在项目中围绕持续集成做改进的时候，对这一点感受颇深。跌跌撞撞的一路走来。我们的持续集成的过程已经变得有些“个性化”，反过头来看我们一路的变化，非常有意思。</p>

  









        
<p>从项目的技术架构说起，我们的项目是采用的J2EE+Flex的方式进行开发的。在我进入项目组的时候，一个比较健壮的持续集成环境已经搭好了。工
程分为两个，一个是Java后端的工程，一个是Flex前端的。我们的持续集成服务器是CC。整个开发工作是围绕着持续集成展开的。一周为一个迭代。</p>
<p>那个时候，我们采用的是比较标准的方式：</p>
<ul><li>后台采取TDD的方式开发。</li><li>每次提交代码之前更新所有代码，然后运行所有测试用例，全部为绿色的时候才提交。</li><li>前台Flex比较麻烦，所以采取了用功能测试覆盖单元测试的方式。用基于Ruby的FunFx写单元测试。工作方式与后台差不多，每次前台功能测试全部通过了才提交。</li><li>持续集成的流程是每隔5分钟检测一边代码库，有更新就build。</li><li>build的流程是先编译后台，跑单元测试，单元测试通过了，再编译Flex，将swf和html以及后台的文件打成war包，部署到tomcat上去，跑功能测试。</li><li>build成功之后发布到特定的目录，形成发布列表。有war包供人下载。</li></ul>
<p>那个时候，build一次大概是15分钟，因为Check In Gate环节是按照标准流程走的，所以build出错的几率也小。CC大多数时候是绿的。哪怕偶尔出问题红了，也很快被修正了。</p>
<p>随着项目的开发，代码规模越来越庞大。功能测试越来越慢，比起自动执行脚本那种速度，开发人员更乐意手动点两下，加之上面对工作进度的压力。更改了一些工作方式：</p>
<ul><li>后台的工作方式不变。</li><li>前台，将功能测试脚本的工作交给几个测试人员编写。几个测试人员也坐在附近，基本可以看作团队成员（到后来编制也是我们团队的成员了）。 开发人员人肉测试一下保证没有问题了再提交。</li><li>测试人员写脚本的流程是拿到上一次build成功的war包，在本地写脚本，本地测通过了再提交。</li><li>持续集成服务器上功能测试不通过的时候，由测试人员提交BUG，开发人员修改。</li><li>持续集成的流程依旧。</li></ul>
<p>这样，从后来收集的数据看，工作效率是提升了，因为参照以前的统计，开发人员的工作一下减轻了1/3。以进度来衡量的速度自然很轻易就可以让上级满意了。</p>
<p>新的解决方案总会产生新的问题，测试人员在测试方面的专业性，使得他们写出来的脚本测的更细。功能测试的时间占耗，增长的更快了，短短半个月，就增
长到了1个小时。每当出现问题，作出反应之后，要在1个多小时以后才能知道结果。而且，持续集成方面并没有做到，一旦出错，谁也不能提交代码这么严格。模
块化的设计所带来的假想的安全感和进度的压力，使得开发人员修正问题的激励不高。于是修正问题的速度不如产生问题的速度快。持续集成服务器在那两个个礼拜
里只有两头是绿的，周一早晨和周五下午。</p>
<p>最早，我们发觉，由开发人员重构造成的脚本失败占大多数，而测试人员每次拿到的上一个版本是没有错误的。所以会出现自动化脚本本地跑得过，服务器上
跑不过的情况发生。于是我们修改了发布的逻辑，在后台单元测试通过、flash编译完成的情况下打的那个war包，复制一份，放到某特定目录指定为
current build。供测试人员写测脚本使用。</p>
<p>过程改进之后，测试人员可以快速的修正脚本了，虽然对于开发人员重构造成测试人员工作的返工无疑是一种浪费，但是毕竟自动化的测试省了回归测试的不少时间，还是可以接受。</p>
<p>脚本的修正速度解决之后，工作似乎有了些起色，但很快，问题的本质就暴露了出来--build的时间太长了，修得速度还是跟不上问题产生的速度。尤
其是中间缺少当build失败时强制阻止代码提交的环节。这之后依然是周一和周五两头绿，中间都是红的。于是，我们觉得问题还是出在build速度上。我
们人工的将功能测试脚本分到四个suite里去，然后以多线程的方式运行。速度被提高了4倍。于是又消停了两天。</p>
<p>好景不长，多线程的测试似乎不太稳定。很多本地可以跑通的测试用例，到了服务器上就失败。险些一个礼拜都没有build出一个版本。最后不得不改回单线程。这时，build一次已经占到了100分钟。第一期的产品Backlog还没有完成1/3。</p>
<p>持续集成走到这里已经进入一个困境，有必要做一些更深一步的改进。经过多次讨论，归纳出了几套方案：</p>
<ul><li>分冒烟测试和all
test两套测试用例集是我们当中呼声最高的一种方案，当我的代码提交之后在跑完所有单元测试和基本的冒烟测试之后就发布beta版，由测试人员接到
beta版，进行更细致的自动化测试并带一些人肉测试。但是反对的声音认为，不跑完全部的测试用例就失去了持续集成的意义。而且会更降低开发人员修正
Bug的积极性。于是作为修正，支持的声音则提出，在Check-In
Gate处把关，恢复每个人提交代码之前跑测试用例的实践。可这明显会给开发人员带来更大的工作负担，估计以此时的进度压力，开发人员的安全感肯定会大幅
下降。很可能会推行不下去。</li><li>另一个方案是从细节处调优，把WEB应用部署到另外一台机器上去，或许就会稳定一些了。但是反
对的声音认为，以测试用例的这个增长速度，他早晚会不稳定的，而且可能撑不过两周。作为修正，想考虑分布式，但是我们所有人的知识储备中，并没有一个人清
楚CC有没有分布式能力。所以想的是购买Cruise，但是价格的障碍就摆在眼前了，在项目前景还不是很明朗的情况下，估计很难申请到资金，但也不是不可
能，只要我们敢于冒这个风险。</li><li>第三，便是更为高级的分支式开发，将版本库划分一下分支，以分支来搭配持续集成，以分支合并
来触发自动构建。这样做，开发的过程就更加有板有眼，粒度可以划分的更细。可是分支的划分，一时想不清楚。但是假设想清楚了，似乎这也使得我们的工作流程
更加复杂了，做如此之大的改变，风险有多大？效果有多大？成本有多大？到底是值不值得？一时也想不清楚。</li></ul>
<p>方案有了，听起来都很有道理，也都有问题。该如何做出决策，是个问题。现在大家众说纷纭，都有理，就变得难以抉择。而且到现在了是不能随便尝试的，这种尝试也是一种风险，一旦出问题造成的成本上升都会加大我们身上的压力。</p>
<p>迷茫之下到AgileChina上跟大家讨论了一下。非常高兴的收集到了几方面的建议：</p>
<p>Jeff Xiong觉得可以将测试分级，并将build分为两个环节，一个跑基本的用例，一个跑全部的用例。这跟我们的第一套方案的思路吻合。但是这种行为是不是失去了持续集成的意义呢？他也不是很确定，他说：</p>
<blockquote>我也不确定……不过，不全面的持续集成至少比不能用的持续集成要好。哪怕一个quick build（只？）能抓到80%（70%？60%？50%？）的defect，如果它只要很少的时间就能跑一遍，似乎值得这样做。<br><br> 不过同时就需要（可能是专门的）人来关注slow build的健康状况，不然broken functional tests可能被忽视并累积。 </blockquote>
<p>因为是在论坛上，互相之间的交流容易造成理解上的偏差，我便阐述了一下我的理解：</p>
<blockquote> 嗯。。。也就是说分一个fast build和一个slow build然后有专人关注slow build。<br><br> 那我的理解，这个fast build应该是反映了后台的健康和前台与后台的基本集成的健康。主要用来完成保障集成的角色。<br><br> 而slow build则是反映了从用户接口来看的软件的健康状况，定期回归，防止发生过的错误再次发生。<br><br> 这样逻辑上看着很清晰，但是两者之间的同步。。。会不会有什么问题呢？</blockquote>
<p>Jeff Xiong认可了我的理解，并提出了更进一步的解释和建议：</p>
<blockquote>slow build实际上是运行完整的回归测试套件。当然理想的情况是slow
build基本上不出错，因为*逻辑*用单元测试都覆盖到了，功能测试只是在描述*表现形式*。那么因为slow
build基本上不出错，就没有价值每次都去运行它，让它在后台慢慢的跑着，过一段时间（半天或者两小时）去关注它一下，没问题就好，偶尔出了问题就马上
解决并且加上对应的单元测试。这样你既节约了时间又不会严重降低对质量的保障力度。<br><br>
实际上的情况可能比较难这样理想，但是和所有好的环境一样，这个环境不是说一下子规划好就万事大吉的。你可能大概的分一分，然后不断的维护，在两组
build之间交换测试案例，一些覆盖到大量功能的、经常出错的案例也许要换到fast
build的冒烟套件里面，一些看起来永远不会出错的案例也许可以换到slow build去。一直琢磨这个事，它才会变得越来越好。<br><br>  （题外话：最近我觉得稍微大一点的项目应该有比较专注的build master，developers往往并不是特别认真的考虑build和CI的持续改进。）</blockquote>
<p>而胡凯则提出了一些基于CC采用分布式的解决思路：</p>
<blockquote>CruiseControl是支持一个叫做Distribute的Contrib，它的Idea是：因为
CruisControl支持叫做Composite的build方式，那么你可以起多个build
server一起来build同一个项目，当且仅当所有的子build通过，整个build才算成功。<br><br>  对于每个build server，你是在单线程测试，对于整个项目，你却是并发测试，因为有多个server同时在跑测试。</blockquote>
<p>但是他也说到CC毕竟是开源的东西，配置起来十分麻烦，于是最后也提出了采用Cruise的方案^_^:</p>
<blockquote>或者你也可以尝试一下ThoughtWorks新发布的Cruise, 基本的理念很相似， 都是把测试分布到不同的机器上执行。<br><br> 在试用期内可以同时跑6个Agent.你可以在每个Agent上执行不同的Target比如<br><br>  Agent1 : ant ft.suite.1<br> Agent2 : ant ft.suite.2<br> Agent3 : ant ft.suite.3<br><br>  你可以拿来玩儿下，根Open Source的那个比起来，应该容易设置很多。<br><br>  缺点是：<br>
<ul><li>你必须使用 hg或者svn 作为 SCM</li><li>试用期过后，你只有2个免费的Agent</li></ul>
</blockquote>
<p>另外，糖醋鼻子还提到了分支式开发，大家围绕这个还展开了激烈的讨论，不过我考虑到分支式开发对我们的利可能要远小于弊，最终还是放弃了这个方案。</p>
<p>在吸取了两方面的建议之后，经过一番思考，决定开始两方面的准备，一方面，对测试用例的分级方面做了一些工作，重构了一部分用例的结构。另一方面我
去调研分布式构建的实现手法。CC的配置果然非常麻烦，调研期间发现了有RemoteAnt这个东西，试了一下基本满足我们的需求，考虑到一个Agent
不用做的太过重型，于是就采用了这个方法。在分布式的技术调研已经完成的情况下，测试分级要不要做成了一个问题，但考虑到目前需求只作了1/3，如果这个
都抗不住要分级的话，后面的工作就没法做了，所以分级的事情，虽然做了，但是也暂缓实行。</p>
<p>现在实践已经采用，会不会产生新的问题呢？前文说过“兴一利必也生一弊”，这个事情是肯定的。那么问题就来了，既然弊端肯定会滋生，我们怎么知道作出的决策是正确的呢？</p>
<p>其实，倒回去看这一路走来的过程，除了一个可以运行的过程以外，还有一个很重要的收获，那就是：如何进行决策。而所谓决策，并不是在黑白分明的事情
之间做出选择，而是在都有理的事情中做出选择。就像我们都知道做软件设计的时候，设计是没有好坏之分的，只有适不适应你的具体情况之别。所以当我们面临几
套解决方案的时候，就好象面对几套设计方案一样，真的是很难选择。如何做？各自就有各自的思路了。像我们就吸收了敏捷开发的思想中所强调得不做过度设计。
选择立杆见影的改进去做。同时，像前文所说，抱着拥抱变化的态度，相信兴一利必生一弊并不是坏事。相反，他可以从一定程度上，带领我们找到真正的问题。</p><p><strong>作者简介</strong>：仝键，网名咖啡屋的鼠标，06年大学毕业，普通程序员，专注于Java、Flex方面的开发、Agile等软件开发方法论的学习。爱好参加社区活动。</p></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/11175037200882494034184</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/11175037200882494034184</guid>
    <pubDate>Wed, 24 Sep 2008 09:40:34 +0800</pubDate>
    <dcterms:modified>2008-09-24T09:40:34+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Flex中的控制反转和依赖注入]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/1117503720088230540435</link>
    <description><![CDATA[<div><a href="http://www.ericfeminella.com/blog/2008/09/21/dependency-injection-iocdi-in-flex/" target="_blank">原文</a>来自<a href="http://www.ericfeminella.com/" target="_blank">ericfeminella.com</a><br><p>Within the vast catalog of Design Patterns available to software
developers today, one of the most important to consider when designing
an enterprise class RIA is the <a href="http://en.wikipedia.org/wiki/Dependency_injection" target="_blank">Dependency Injection Pattern</a>.</p>
<p>Dependency Injection, a term originally coined by <a href="http://martinfowler.com/" target="_blank">Martin Fowler</a> in his well known article <a href="http://martinfowler.com/articles/injection.html" target="_blank"><em>Inversion of Control Containers and the Dependency Injection Pattern</em></a>, is a more specific term for what is otherwise known as <a href="http://en.wikipedia.org/wiki/Inversion_of_control" target="_blank">Inversion of Control</a> or IoC. </p>
<p>Fowler’s assessment of Inversion of Control containers concluded
that the name itself - Inversion of Control - was too generic, thus as
a result from his discussions with various IoC advocates they settled
on the more specific term Dependency Injection, also known as <em>DI</em>
for short. The terms Inversion of Control (IoC) and Dependency
Injection (DI) are commonly used interchangeably to describe the same
underlying design principle of separating configuration from
implementation.</p>
<p>There are three basic forms of Dependency Injection, which are
generally referred to as type 1 IoC (Interface Injection), type 2 IoC
(Setter Injection) and type 3 IoC (Constructor Injection). Before
diving into the specifics of how to implement the various forms of DI,
I will first discuss what Dependency Injection is on a conceptual level
as well as what each specific form means. The examples outlined here
are in ActionScript 3, however it is important to keep in mind that
like most Design Patterns Dependency Injection applies to any language
which supports an Object Oriented Model.</p>
<p>At the most basic level Dependency Injection can be explained as a
way of decoupling classes from their dependencies by injecting the
dependencies into them rather than having the classes directly
reference specific implementations. A class which directly references
other classes is coupled to those classes - these are the dependencies.
However a class which does not reference any other classes would
probably not be very useful. At some point the dependencies need to be
made. Dependency Injection is a solution to how those dependencies are
made, and the manner by which they are provided.</p>
<p>For example, consider the following class which illustrates a typical example of a class’s dependency on another class:</p>
<div  style="white-space: nowrap;">
<p><span >public</span> <span >class</span> ConfigurationManager<br>
<span >{</span><br>
&nbsp; &nbsp; <span >//defines the configuration to use</span><br>
&nbsp; &nbsp; <span >private</span> <span >var</span> config:XMLConfiguration;<br>
&nbsp; &nbsp; <br>
&nbsp; &nbsp; <span >public</span> <span >function</span> ConfigurationManager<span >(</span><span >)</span><br>
&nbsp; &nbsp; <span >{</span><br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;config = <span >new</span> XMLConfiguration<span >(</span><span >)</span>;<br>
&nbsp; &nbsp; <span >}</span></p>
<p>&nbsp; &nbsp; <span >public</span> <span >function</span> getLogLevel<span >(</span><span >)</span> : <span >String</span><br>
&nbsp; &nbsp; <span >{</span><br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span >return</span> config.<span >getConfig</span><span >(</span><span >"logLevel"</span><span >)</span>;<br>
&nbsp; &nbsp; <span >}</span><br>
<span >}</span></p></div>
<p>From looking at the code above the dependencies are pretty obvious;
the ConfigurationManager class is dependent on the XMLConfiguration
class. Now this type of dependency is quite typical so at this point
you may be asking what is wrong with doing this? </p>
<p>The first problem is that the config property is defined as a concrete implementation: </p>
<div  style="white-space: nowrap;">
<p><span >private</span> <span >var</span> config:XMLConfiguration</p></div>
<p>This violates a fundamental OO principle: </p>
<blockquote><p>Program to interfaces, not implementations.</p></blockquote>
<p>More importantly and perhaps pertinent to the topic at hand is that
it also isn’t very hard to imagine that at some point we may want to
load a configuration from some other means, such as a properties file,
a remote service and so on. In order to do so we would need to modify
the class, and from this we can deduce that the class does not scale
very well. </p>
<p>So we could begin improving our current implementation by simply
refactoring the ConfigurationManager class to define the config
property as an abstraction, say IConfiguration:</p>
<div  style="white-space: nowrap;">
<p><span >public</span> <span >interface</span> IConfiguration<br>
<span >{</span><br>
&nbsp; &nbsp; <span >function</span> getConfig<span >(</span><span >name</span>:<span >String</span><span >)</span> : *;<br>
<span >}</span></p>
<p><span >public</span> <span >class</span> ConfigurationManager<br>
<span >{</span><br>
&nbsp; &nbsp; <span >//define the configuration as an abstraction </span><br>
&nbsp; &nbsp; <span >private</span> <span >var</span> config:IConfiguration;<br>
&nbsp; &nbsp; <br>
&nbsp; &nbsp; <span >public</span> <span >function</span> ConfigurationManager<span >(</span><span >)</span><br>
&nbsp; &nbsp; <span >{</span><br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;config = <span >new</span> XMLConfiguration<span >(</span><span >)</span>;<br>
&nbsp; &nbsp; <span >}</span></p>
<p>&nbsp; &nbsp; <span >public</span> <span >function</span> getLogLevel<span >(</span><span >)</span> : <span >Array</span><br>
&nbsp; &nbsp; <span >{</span><br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span >return</span> config.<span >getConfig</span><span >(</span><span >"logLevel"</span><span >)</span>;<br>
&nbsp; &nbsp; <span >}</span><br>
<span >}</span></p></div>
<p>As you can see this is certainly a step in the right direction,
however the underlying problem still remains; we are still
instantiating an instance of XMLConfiguration directly in the
ConfigurationManager - and that is exactly what Dependency Injection is
all about: providing a solution to the recurring problem of managing
dependencies between classes, and how those dependencies are provided.</p>
<p>When implementing the Dependency Injection Pattern in an application
you do so by creating a context (configuration) which defines all
dependencies in an application as well as an Assembler which is
responsible for assembling the mappings and associations between
objects and their dependencies. This is done by utilizing any
combination of the three forms of DI; Interface Injection, Setter
Injection and Constructor Injection. Below is a brief description of
each form:</p>
<p><b>Interface Injection</b><br>
Interface Injection is the process by which all dependencies are
injected into an object via an interface. For example, the
ConfigurationManager example above could implement an interface which
defines the operations needed to inject the appropriate Configuration
implementation.</p>
<p><b>Setter Injection</b><br>
Setter injection as you may have guessed is the process of injecting
dependencies via public setters; both explicit or implicit. Using
Setter Injection the ConfigurationManager could provide public setters
from which an Assembler could inject the appropriate Configuration
implementation.</p>
<p><b>Constructor Injection</b><br>
Again as you may have guessed Constructor Injection is the process of
injecting dependencies via arguments in the class constructor. Using
Constructor Injection the concrete Configuration could just as easily
be injected.</p>
<p>Both Constructor and Setter Injection are by far the preferred forms
of Dependency Injection. Interface Injection has some major drawbacks
as it somewhat leads to convoluted code since multiple additional
interfaces need to be defined and implemented. The fact that “special”
types need to be created and implemented in order to facilitate DI
using Interface Injection greatly limits the potential for its use.</p>
<p>There are numerous frameworks for various platforms which provide
out of the box Dependency Injection implementations for all three forms
of DI. All of these frameworks handle the wiring necessary for easily
implementing Dependency Injection in an application, the most notable
being the <a href="http://www.springframework.org/" target="_blank">Spring Framework</a>
for Java/J2EE. There are also quite a few DI solutions for Flex and
ActionScript applications as well. Optionally you could choose to roll
your own however I would first suggest investigating some of the
frameworks which are currently available as they more than likely
provide what you need. The <a href="http://sourceforge.net/projects/prana/" target="_blank">Prana Framework</a> by <a href="http://www.herrodius.com/blog/" target="_blank">Christophe Herreman</a> is a good choice as it is one of the most prevalent DI solution available at the moment for Flex. </p>
<p>Using the ConfgurationManager example from above I have provided a basic <a href="http://code.ericfeminella.com/examples/PatternsDependencyInjection.zip">example</a>
application which demonstrates how to implement Dependency Injection
utilizing the Prana framework. The example application uses constructor
injection to provide a concrete Configuration to the
ConfigurationManager, however I encourage you to experiment with the
other mechanisms of injection as well. The example is intentionally
kept very simple in that it is only intended to convey the basic
concepts of DI and how to use it in Flex with Prana, from this you
should have a good understanding of how to implement DI in a larger
context.
</p><br></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/1117503720088230540435</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/1117503720088230540435</guid>
    <pubDate>Tue, 23 Sep 2008 12:05:40 +0800</pubDate>
    <dcterms:modified>2008-09-23T12:05:40+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[养成编程的好习惯：AS3声明变量时的一个小提示]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/11175037200882210188938</link>
    <description><![CDATA[<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private function myFun1():void<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; var myArr1:Array = new Array("1","2","3","4","5");<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; var myArr2:Array = new Array("6","7","8","9","10");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for each(<span style="color: rgb(255, 0, 0);">var str:String </span>in myArr1)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; trace(str);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for each(<span style="color: rgb(255, 0, 0);">var str:String</span> in myArr2)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; trace(str);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>注意上面的两个变量，如果这样写的话，编译器会发出警告："3596:变量重复定义"。<br>所以，我们这样写：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private function myFun2():void<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; var myArr1:Array = new Array("1","2","3","4","5");<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; var myArr2:Array = new Array("6","7","8","9","10");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<span style="color: rgb(255, 0, 0);"> var str:String = "";</span><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for each(<span style="color: rgb(255, 0, 0);">str</span> in myArr1)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; trace(str);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for each(<span style="color: rgb(255, 0, 0);">str </span>in myArr2)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; trace(str);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>可以在Flex SDK源文件中看到很多这样的写法：<br>例如：Grid.as中的measure()方法：<br>override protected function measure():void<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 1. Determine the number of grid columns,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // taking into account rowSpan and colSpan<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var numGridRows:int = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var numGridColumns:int = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var columnOccupiedUntilRow:Array = [];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: rgb(255, 102, 0);">var gridRow:GridRow;</span><br style="color: rgb(255, 102, 0);"><span style="color: rgb(255, 102, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var gridItem:GridItem;</span><br style="color: rgb(255, 102, 0);"><span style="color: rgb(255, 102, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var i:int;</span><br style="color: rgb(255, 102, 0);"><span style="color: rgb(255, 102, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var j:int;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var colIndex:int;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var rowList:Array = []; // GridRows<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (var index:int = 0; index &lt; numChildren; index++)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: rgb(255, 102, 0);">gridRow = GridRow(getChildAt(index));</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (gridRow.includeInLayout)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rowList.push(gridRow);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; numGridRows++;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; numGridRows; i++)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; colIndex = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: rgb(255, 102, 0);">gridRow = rowList[i];</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Cache the number of children as a property on the gridRow<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gridRow.numGridItems = gridRow.numChildren;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ………<br></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/11175037200882210188938</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/11175037200882210188938</guid>
    <pubDate>Mon, 22 Sep 2008 10:18:08 +0800</pubDate>
    <dcterms:modified>2008-09-22T10:18:08+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Optics Express——光学快递]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/11175037200881873943538</link>
    <description><![CDATA[<div>http://www.opticsexpress.org/<br>Optics Express 是由美国光学协会发布， Sydney大学的Martijn de Sterke编辑的电子版光学期刊。<br>更多信息可以看这里<a href="http://www.opticsexpress.org/journal/oe/about.cfm" target="_blank">http://www.opticsexpress.org/journal/oe/about.cfm</a></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/11175037200881873943538</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/11175037200881873943538</guid>
    <pubDate>Thu, 18 Sep 2008 19:39:43 +0800</pubDate>
    <dcterms:modified>2008-09-19T13:58:54+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[离开公司时留给公司的十句话（转）]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/1117503720088171138012</link>
    <description><![CDATA[<div><a href="http://topic.csdn.net/u/20080822/16/108fe45c-e87e-4988-a8cf-16b1d224dee5.html" target="_blank">原文</a>来自<a href="http://www.csdn.net/" target="_blank">CSDN</a><br>一项目计划： <br>  1.项目计划并不是一边将自己所熟悉的工作内容留给自己一边不停的说这个工作量太大，让MM来协助，你要这样的话我建议你当老总找个秘书。 <br>  2.开会： <br> &nbsp;  开会的目的是解决问题，不是休息，不是一个会可以开它半天，要讲究效率；开会时在讨论大家所关心的问题，而不是几个组员的问题，如果几个人有问题可以会后来解决，而 <br>  <br> 不是让大家等你们，直到你们解决完问题，才让大家散会。 <br>  <br> 二.项目管理： <br>  <br> 1.负起责任: <br> &nbsp; 让你管项目，你就得负起这个责任，不是让你的其他组员写代码而你在一边喝茶，老总问你怎么样了你只说差不多，可以了，也不是等到项目结束时你还没有将其他组员写的代 <br>  <br> 码合起来，而让他们陪着你加班。也不是你在老板面前一直说好了，而你所负责的代码直到两个项目完成时还未修改完，等到项目实施差不多时客户反馈的问题还是你的。 <br>  <br> 2.承担责任: <br> &nbsp; 让你管项目，你就承担起这个责任，不是在老总面前说进展顺利，而客户将问题反馈时，你说你不是很清楚，这些代码不是我写的，是mm是写的，将责任推卸给他人。 <br>  <br> 3.人员管理: <br> &nbsp;  不管出于什么目的千万不要在项目开始时让你的组员就写操作手册，那不仅是对软件开发过程的误解，而且是对组员的最大不尊重。 <br> 4.当你不了解的时候千万别乱说： <br> &nbsp; &nbsp; 我不知道几个写代码的同事对设计模式有多少了解，如果你了解了你就不会说别人代码乱（当然我承认我对设计模式理解不透），不要在一个工程下建立很多个文件夹，然后 <br>  <br> 给每个数据表写一个CS，然后说这是你的所谓的三层架构，CS是对象的实例，不是代码的分离器，不要为了三层而三层，思路开阔点，不要老师教你一你就是一，先将自己的事做 <br>  <br> 好，这样你会赢得更多的尊重。 <br> 三.项目实施： <br>  1.编码: <br> &nbsp;  编码标志着项目的开始，在编码之前请确定好你的数据库建设是否完整，没有确定之前请不要开始操作数据库，数据库是基础，就像盖楼时的地基，如果地基没有建立好你就去 <br>  <br> 盖楼，然后在盖楼中的过程中去修补你的地基的大小，我想这样即使能盖起一栋大楼，但是他的质量会打折扣的。这样建设起来的系统最终是用户不停的给你反馈问题，你也不停 <br>  <br> 的在修改他们。 <br> 2. 客户反馈： <br> &nbsp; 每个组员都有在客户那里实施项目的经历，而这种实地的实施恰恰是在客户那里解决问题，这是难得的获取新的需求的最好机会，所以每个个实施的员工应该带回来一个客户问 <br>  <br> 题反馈的文档，这些文档应该大家聚在一起探讨最好的解决办法和系统中新等等创新点，千万不要只是将问题修改了事（我到现在没看到公司其他员工写回来这样的文档，更不用 <br>  <br> 说讨论了。即使我写回来的几个项目反馈也没没有进行讨论，这点真的让我很吃惊）。 <br> 四.人际关系： <br>  1.同事关系： 同事也是一个团体，可以说是一个冲锋在前线的的战斗队伍，大家要讲的就是以团队的力量去取胜，只有大家密切合作才能取的胜利，同事之间的关系应该是最简 <br>  <br> 单的，而且是最有战斗力的，不要讲太多的关系，关系越简单越有战斗力，希望同事不要把政府的那一套带进团队的合作里，特别是软件行业里，如果你非要讲究那些东西的话我 <br>  <br> 建议你去政府当官，那里才有你的前途，如果你在公司而且是在一个开发团队里的话你绝对是一个祸害。 <br>  2.个人修养： <br> &nbsp; 大家都是二十几岁的小伙子，真是年轻气盛的时候，而且大家都是受过高等教育的，所以在年轻气盛的时候千万不要学那些泼妇行为，几个人一起说他不是，转过去又说另外一 <br>  <br> 个的不是，如果你乐此不疲的话，我真为你担心。注重个人修养。 <br> 五 个人发展: <br> &nbsp; 曾经看过这样一个故事，说一只老鼠跳进一个米缸，发现有很多米，结果就放心的吃起来，越吃越胖，没想到那个米会完，知道有一天他吃完米想跳出来的时候，发现缸太深了 <br>  <br> ，他肥胖的身体已经跳不出来了。希望每个人都不要成为米缸中的老鼠，继续奋斗，这样蛋糕才能越大，你吃到的也越多。上次去全球遥感大会时给我上了一堂生动的课，因为那 <br>  <br> 里的一家参展厂商给我留下了很深的影响，有个女的用英语在那里不停的在跟不同的客户去探讨....... <br>  <br> &nbsp; &nbsp; &nbsp; &nbsp; 祝大家前程似锦~~！ </div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/1117503720088171138012</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/1117503720088171138012</guid>
    <pubDate>Wed, 17 Sep 2008 23:38:00 +0800</pubDate>
    <dcterms:modified>2008-09-17T23:38:00+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[INTEL 865PERL 板载设备驱动下载]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/1117503720088175217718</link>
    <description><![CDATA[<div>这些是在INTEL中文网上找到针对windows XP的相关下载。我主要用到了"<font size="2" face="Arial,helvetica"><a href="http://downloadcenter.intel.com/Detail_Desc.aspx?agr=Y&amp;ProductID=949&amp;DwnldID=6816&amp;strOSs=44&amp;OSFullName=Windows%20XP%20Professional&amp;lang=zho">音频：ADI* 1985 驱动程序</a></font><font size="1" face="Arial,helvetica"> </font>"。<br>http://downloadcenter.intel.com/filter_results.aspx?strTypes=all&amp;ProductID=949&amp;OSFullName=Windows+XP+Professional&amp;lang=zho&amp;strOSs=44&amp;submit=%E6%89%A7%E8%A1%8C%EF%BC%81<br><br><br></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/1117503720088175217718</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/1117503720088175217718</guid>
    <pubDate>Wed, 17 Sep 2008 17:02:17 +0800</pubDate>
    <dcterms:modified>2008-09-17T17:02:17+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[微软对联软件]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/11175037200881614615713</link>
    <description><![CDATA[<div>软件地址：ttp://duilian.msra.cn/app/couplet.aspx<br>呵呵，挺有趣。<br>我在上联输入<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 吃饭吃饭再吃饭<br>下联好多：<br><table border="0"><tbody><tr><tr><td>
                                                                            <br></td>
                                                                            <td colspan="2">
                                                                                <div >
                                                                                <table ><tbody ><tr style="cursor: pointer; color: Black;" ><td style="cursor: pointer; color: Black;" ><br></td><td style="cursor: pointer; color: Black;" >上天上天重上天</td></tr><tr ><td ><br></td><td style="cursor: pointer; color: Black;" >上天上天又上天</td></tr><tr ><td ><br></td><td style="cursor: pointer; color: Black;" >做人做人重做人</td></tr><tr ><td ><br></td><td style="cursor: pointer; color: Black;" >睡觉睡觉一睡觉</td></tr><tr ><td ><br></td><td style="cursor: pointer; color: Black;" >睡觉睡觉不睡觉</td></tr><tr ><td ><br></td><td style="cursor: pointer; color: Black;" >上天上天已上天</td></tr><tr ><td ><br></td><td style="cursor: pointer; color: Black;" >睡觉睡觉还睡觉</td></tr><tr ><td ><br></td><td style="cursor: pointer; color: Black;" >说话说话一说话</td></tr><tr ><td ><br></td><td >说话说话更说话</td></tr><tr ><td ><br></td><td >说话说话多说话</td></tr><tr ></tr><tr ><td ><br></td><td style="cursor: pointer; color: Black;" >睡觉睡觉重睡觉</td></tr><tr ><td ><br></td><td >说话说话重说话</td></tr><tr ><td ><br></td><td >做人做人难做人</td></tr><tr ><td ><br></td><td >说话说话不说话</td></tr><tr ><td ><br></td><td >度日度日空度日</td></tr><tr ><td ><br></td><td >睡觉睡觉更睡觉</td></tr><tr ><td ><br></td><td >度日度日一度日</td></tr><tr ><td ><br></td><td >用餐用餐先用餐</td></tr><tr ><td ><br></td><td >用餐用餐曾用餐</td></tr><tr ><td ><br></td><td >用餐用餐可用餐</td></tr><tr ></tr><tr ><td ><br></td><td >用餐用餐常用餐</td></tr><tr ><td ><br></td><td >用餐用餐还用餐</td></tr><tr ><td ><br></td><td >拉车拉车还拉车</td></tr><tr ><td ><br></td><td >用餐用餐已用餐</td></tr><tr ><td ><br></td><td >拉车拉车曾拉车</td></tr><tr ><td ><br></td><td >拉车拉车先拉车</td></tr><tr ><td ><br></td><td >拉车拉车多拉车</td></tr><tr ><td ><br></td><td >出门出门难出门</td></tr><tr ><td ><br></td><td >拉车拉车已拉车</td></tr><tr ><td ><br></td><td >出门出门先出门</td></tr></tbody></table></div></td></tr></tr></tbody></table><br></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/11175037200881614615713</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/11175037200881614615713</guid>
    <pubDate>Tue, 16 Sep 2008 13:46:15 +0800</pubDate>
    <dcterms:modified>2008-09-16T13:46:15+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[命运]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/11175037200881573262</link>
    <description><![CDATA[<div>在命运降临的伟大瞬间，市民的一切美德——小心、顺从、勤勉、谨慎，都无济于事，它始终只要求天才人物，并且将他造就成不朽的形象。命运鄙视地把畏首畏尾的人拒之门外。命运——这世上的另一位神，只愿意用热烈的双臂把勇敢者高高举起，送上英雄们的天堂。</div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/11175037200881573262</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/11175037200881573262</guid>
    <pubDate>Mon, 15 Sep 2008 19:32:06 +0800</pubDate>
    <dcterms:modified>2008-09-15T19:32:06+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[FMS 装错版本了怎么办]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/111750372008810114534183</link>
    <description><![CDATA[<div>在FMS的示例程序 vod的readme中发现下面这段话。<br>The vod (video on demand) service is an Adobe-built application that lets you stream<br>recorded media to users without writing any code. Flash Media Streaming Server only <br>runs Adobe-built applications, also called "signed" applications.<br>Flash Media Interactive Server and Flash Media Development Server support unsigned (user-created)<br>applications. If you're using one of these server editions, you can modify the vod service <br>source code to create your own applications. <br><br>对developer来说 Flash Media Streaming Server(FMSS)&nbsp; 与 Flash Media Interactive Server(FMIS)，Flash Media Development Server(FMDS)是不同的。 如果我们用FMSS则我们写了main.asc后直接放到 application 目录下是无法加载执行的。application根本不会被加载进去。所以，得装FMIS或者FMDS。<br><br>那么，如果装错了我们需要卸载FMSS，然后重装FMIS吗？<br>不，不需要，仅仅找一个FMIS的序列号，然后覆盖安装目录下conf/fms.ini中的FMSS序列号，然后重启FMS 服务即可由FMSS切换到FMIS。<br></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/111750372008810114534183</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/111750372008810114534183</guid>
    <pubDate>Wed, 10 Sep 2008 11:45:34 +0800</pubDate>
    <dcterms:modified>2008-09-18T10:12:42+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[网站体系架构的演变]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/1117503720088992444862</link>
    <description><![CDATA[<div><a href="http://blog.eingzone.com/?p=72" target="_blank">原文</a>来自<a href="http://blog.eingzone.com/" target="_blank">赛兜</a><br><p ><span style="font-family: 宋体;">之前也有一些介绍大型网站架构演变的文章，例如</span><span lang="EN-US">LiveJournal</span><span style="font-family: 宋体;">的、</span><span lang="EN-US">ebay</span><span style="font-family: 宋体;">的，都是非常值得参考的，不过感觉他们讲的更多的是每次演变的结果，而没有很详细的讲为什么需要做这样的演变，再加上近来感觉有不少同学都很难明白为什么一个网站需要那么复杂的技术，于是有了写这篇文章的想法，在这篇文章中</span> <span style="font-family: 宋体;">将阐述一个普通的网站发展成大型网站过程中的一种较为典型的架构演变历程和所需掌握的知识体系，希望能给想从事互联网行业的同学一点初步的概念，</span><span lang="EN-US"> <img src="http://blog.eingzone.com/wp-includes/images/smilies/icon_smile.gif" alt=":)" > </span><span style="font-family: 宋体;">，文中的不对之处也请各位多给点建议，让本文真正起到抛砖引玉的效果。</span><span lang="EN-US"><br>
<br>
</span></p>
<p ><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;"><span style="font-family: 宋体;">架构演变第一步：物理分离</span><span lang="EN-US">webserver</span><span style="font-family: 宋体;">和数据库</span></span></span></strong></p>
<p ><span style="font-family: 宋体;">最开始，由于某些想法，于是在互联网上搭建了一个网站，这个时候甚至有可能主机都是租借的，但由于这篇文章我们只关注架构的演变历程，因此就假设这个时候</span> <span style="font-family: 宋体;">已
经是托管了一台主机，并且有一定的带宽了，这个时候由于网站具备了一定的特色，吸引了
部分人访问，逐渐你发现系统的压力越来越高，响应速度越来越慢，而这个时候比较明显的是数据库和应用互相影响，应用出问题了，数据库也很容易出现问题，而
数据库出问题的时候，应用也容易出问题，于是进入了第一步演变阶段：将应用和数据库从物理上分离，变成了两台机器，这个时候技术上没有什么新的要求，但你
发现确实起到效果了，系统又恢复到以前的响应速度了，并且支撑住了更高的流量，并且不会因为数据库和应用形成互相的影响。</span></p>
<p ><span style="font-family: 宋体;">看看这一步完成后系统的图示：</span></p>
<p ><span lang="EN-US"><img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/1.PNG" alt="" width="195" height="99"><br>
</span></p>
<p ><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span></p>
<p ><span style="font-family: 宋体;">这一步架构演变对技术上的知识体系基本没有要求。</span><span lang="EN-US"><br>
<br>
</span></p>
<p ><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;">架构演变第二步：增加页面缓存</span></span></strong></p>
<p ><span style="font-family: 宋体;">好景不长，随着访问的人越来越多，你发现响应速度又开始变慢了，查找原因，发现是访问数据库的操作太多，导致数据连接竞争激烈，所以响应变慢，但数据库连</span> <span style="font-family: 宋体;">接又不能开太多，否则数据库机器压力会很高，因此考虑采用缓存机制来减少数据库连接资源的竞争和对数据库读的压力，这个时候首先也许会选择采用</span><span lang="EN-US">squid </span><span style="font-family: 宋体;">等类似的机制来将系统中相对静态的页面（例如一两天才会有更新的页面）进行缓存（当然，也可以采用将页面静态化的方案），这样程序上可以不做修改，就能够</span> <span style="font-family: 宋体;">很好的减少对</span><span lang="EN-US">webserver</span><span style="font-family: 宋体;">的压力以及减少数据库连接资源的竞争，</span><span lang="EN-US">OK</span><span style="font-family: 宋体;">，于是开始采用</span><span lang="EN-US">squid</span><span style="font-family: 宋体;">来做相对静态的页面的缓存。</span></p>
<p ><span style="font-family: 宋体;">看看这一步完成后系统的图示：</span></p>
<p ><span lang="EN-US"><img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/2.PNG" alt="" width="195" height="156"><br>
</span></p>
<p ><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span></p>
<p ><span style="font-family: 宋体;">前端页面缓存技术，例如</span><span lang="EN-US">squid</span><span style="font-family: 宋体;">，如想用好的话还得深入掌握下</span><span lang="EN-US">squid</span><span style="font-family: 宋体;">的实现方式以及缓存的失效算法等。</span></p>
<p ><span lang="EN-US"> </span></p>
<p ><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;">架构演变第三步：增加页面片段缓存</span></span></strong></p>
<p ><span style="font-family: 宋体;">增加了</span><span lang="EN-US">squid</span><span style="font-family: 宋体;">做缓存后，整体系统的速度确实是提升了，</span><span lang="EN-US">webserver</span><span style="font-family: 宋体;">的压力也开始下降了，但随着访问量的增加，发现系统又开始变的有些慢了，在尝</span> <span style="font-family: 宋体;">到了</span><span lang="EN-US">squid</span><span style="font-family: 宋体;">之类的动态缓存带来的好处后，开始想能不能让现在那些动态页面里相对静态的部分也缓存起来呢，因此考虑采用类似</span><span lang="EN-US">ESI</span><span style="font-family: 宋体;">之类的页面片段缓存策略，</span><span lang="EN-US">OK</span><span style="font-family: 宋体;">，于是开始采用</span><span lang="EN-US">ESI</span><span style="font-family: 宋体;">来做动态页面中相对静态的片段部分的缓存。</span></p>
<p ><span style="font-family: 宋体;">看看这一步完成后系统的图示：</span></p>
<p ><span lang="EN-US"><img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/3.PNG" alt="" width="337" height="235"><br>
</span></p>
<p ><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span></p>
<p ><span style="font-family: 宋体;">页面片段缓存技术，例如</span><span lang="EN-US">ESI</span><span style="font-family: 宋体;">等，想用好的话同样需要掌握</span><span lang="EN-US">ESI</span><span style="font-family: 宋体;">的实现方式等；</span></p>
<p ><span lang="EN-US"> </span></p>
<p ><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;">架构演变第四步：数据缓存</span></span></strong></p>
<p ><span style="font-family: 宋体;">在采用</span><span lang="EN-US">ESI</span><span style="font-family: 宋体;">之类的技术再次提高了系统的缓存效果后，系统的压力确实进一步降低了，但同样，随着访问量的增加，系统还是开始变慢，经过查找，可能会发现系</span> <span style="font-family: 宋体;">统中存在一些重复获取数据信息的地方，像获取用户信息等，这个时候开始考虑是不是可以将这些数据信息也缓存起来呢，于是将这些数据缓存到本地内存，改变完毕后，完全符合预期，系统的响应速度又恢复了，数据库的压力也再度降低了不少。</span></p>
<p ><span style="font-family: 宋体;">看看这一步完成后系统的图示：</span></p>
<p ><span lang="EN-US"><img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/4.PNG" alt="" width="341" height="258"><br>
</span></p>
<p ><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span></p>
<p ><span style="font-family: 宋体;">缓存技术，包括像</span><span lang="EN-US">Map</span><span style="font-family: 宋体;">数据结构、缓存算法、所选用的框架本身的实现机制等。</span></p>
<p ><span lang="EN-US"> </span></p>
<p ><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;"><span style="font-family: 宋体;">架构演变第五步：</span> <span style="font-family: 宋体;">增加</span><span lang="EN-US">webserver</span></span></span></strong></p>
<p ><span style="font-family: 宋体;">好景不长，发现随着系统访问量的再度增加，</span><span lang="EN-US">webserver</span><span style="font-family: 宋体;">机器的压力在高峰期会上升到比较高，这个时候开始考虑增加一台</span><span lang="EN-US">webserver</span><span style="font-family: 宋体;">，这也是为了同时解决可用性的问题，避免单台的</span><span lang="EN-US">webserver down</span><span style="font-family: 宋体;">机的话就没法使用了，在做了这些考虑后，决定增加一台</span><span lang="EN-US">webserver</span><span style="font-family: 宋体;">，增加一台</span><span lang="EN-US">webserver</span><span style="font-family: 宋体;">时，会碰到一些问题，典型的有：</span><span lang="EN-US"><br>
1</span><span style="font-family: 宋体;">、如何让访问分配到这两台机器上，这个时候通常会考虑的方案是</span><span lang="EN-US">Apache</span><span style="font-family: 宋体;">自带的负载均衡方案，或</span><span lang="EN-US">LVS</span><span style="font-family: 宋体;">这类的软件负载均衡方案；</span><span lang="EN-US"><br>
2</span><span style="font-family: 宋体;">、如何保持状态信息的同步，例如用户</span><span lang="EN-US">session</span><span style="font-family: 宋体;">等，这个时候会考虑的方案有写入数据库、写入存储、</span><span lang="EN-US">cookie</span><span style="font-family: 宋体;">或同步</span><span lang="EN-US">session</span><span style="font-family: 宋体;">信息等机制等；</span><span lang="EN-US"><br>
3</span><span style="font-family: 宋体;">、如何保持数据缓存信息的同步，例如之前缓存的用户数据等，这个时候通常会考虑的机制有缓存同步或分布式缓存；</span><span lang="EN-US"><br>
4</span><span style="font-family: 宋体;">、如何让上传文件这些类似的功能继续正常，这个时候通常会考虑的机制是使用共享文件系统或存储等；</span><span lang="EN-US"><br>
</span><span style="font-family: 宋体;">在解决了这些问题后，终于是把</span><span lang="EN-US">webserver</span><span style="font-family: 宋体;">增加为了两台，系统终于是又恢复到了以往的速度。</span></p>
<p ><span style="font-family: 宋体;">看看这一步完成后系统的图示：</span></p>
<p ><span lang="EN-US"><img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/5.PNG" alt="" width="341" height="244"><br>
</span></p>
<p ><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span></p>
<p ><span style="font-family: 宋体;">负载均衡技术（包括但不限于硬件负载均衡、软件负载均衡、负载算法、</span><span lang="EN-US">linux</span><span style="font-family: 宋体;">转发协议、所选用的技术的实现细节等）、主备技术（包括但不限于</span><span lang="EN-US">ARP</span><span style="font-family: 宋体;">欺骗、</span><span lang="EN-US">linux heart-beat</span><span style="font-family: 宋体;">等）、状态信息或缓存同步技术（包括但不限于</span><span lang="EN-US">Cookie</span><span style="font-family: 宋体;">技术、</span><span lang="EN-US">UDP</span><span style="font-family: 宋体;">协议、状态信息广播、所选用的缓存同步技术的实现细节等）、共享文件技术（包括但不限于</span><span lang="EN-US">NFS</span><span style="font-family: 宋体;">等）、存储技术（包括但不限于存储设备等）。</span></p>
<p ><span lang="EN-US"> </span></p>
<p ><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;">架构演变第六步：分库</span></span></strong></p>
<p ><span style="font-family: 宋体;">享受了一段时间的系统访问量高速增长的幸福后，发现系统又开始变慢了，这次又是什么状况呢，经过查找，发现数据库写入、更新的这些操作的部分数据库连接的</span> <span style="font-family: 宋体;">资
源竞争非常激烈，导致了系统变慢，这下怎么办呢，此时可选的方案有数据库集群和分库策
略，集群方面像有些数据库支持的并不是很好，因此分库会成为比较普遍的策略，分库也就意味着要对原有程序进行修改，一通修改实现分库后，不错，目标达到
了，系统恢复甚至速度比以前还快了。</span></p>
<p ><span style="font-family: 宋体;">看看这一步完成后系统的图示：</span></p>
<p ><span lang="EN-US"><img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/6.PNG" alt="" width="341" height="243"><br>
</span></p>
<p ><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span></p>
<p ><span style="font-family: 宋体;">这一步更多的是需要从业务上做合理的划分，以实现分库，具体技术细节上没有其他的要求；</span></p>
<p ><span style="font-family: 宋体;">但同时随着数据量的增大和分库的进行，在数据库的设计、调优以及维护上需要做的更好，因此对这些方面的技术还是提出了很高的要求的。</span></p>
<p ><span lang="EN-US"> </span></p>
<p ><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;"><span style="font-family: 宋体;">架构演变第七步：分表、</span><span lang="EN-US">DAL</span><span style="font-family: 宋体;">和分布式缓存</span></span></span></strong><span lang="EN-US"><br>
</span><span style="font-family: 宋体;">随着系统的不断运行，数据量开始大幅度增长，这个时候发现分库后查询仍然会有些慢，于是按照分库的思想开始做分表的工作，当然，这不可避免的会需要对程序</span> <span style="font-family: 宋体;">进行一些修改，也许在这个时候就会发现应用自己要关心分库分表的规则等，还是有些复杂的，于是萌生能否增加一个通用的框架来实现分库分表的数据访问，这个在</span><span lang="EN-US">ebay</span><span style="font-family: 宋体;">的架构中对应的就是</span><span lang="EN-US">DAL</span><span style="font-family: 宋体;">，这个演变的过程相对而言需要花费较长的时间，当然，也有可能这个通用的框架会等到分表做完后才开始做，同时，在这个阶段可</span> <span style="font-family: 宋体;">能会发现之前的缓存同步方案出现问题，因为数据量太大，导致现在不太可能将缓存存在本地，然后同步的方式，需要采用分布式缓存方案了，于是，又是一通考察和折磨，终于是将大量的数据缓存转移到分布式缓存上了。</span></p>
<p ><span style="font-family: 宋体;">看看这一步完成后系统的图示：</span></p>
<p ><span lang="EN-US"><img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/7.PNG" alt="" width="342" height="439"><br>
</span></p>
<p ><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span></p>
<p ><span style="font-family: 宋体;">分表更多的同样是业务上的划分，技术上涉及到的会有动态</span><span lang="EN-US">hash</span><span style="font-family: 宋体;">算法、</span><span lang="EN-US">consistent hash</span><span style="font-family: 宋体;">算法等；</span></p>
<p ><span lang="EN-US">DAL</span><span style="font-family: 宋体;">涉及到比较多的复杂技术，例如数据库连接的管理（超时、异常）、数据库操作的控制（超时、异常）、分库分表规则的封装等；</span></p>
<p ><span lang="EN-US"> </span></p>
<p ><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;"><span style="font-family: 宋体;">架构演变第八步：增加更多的</span><span lang="EN-US">webserver</span></span></span></strong></p>
<p ><span style="font-family: 宋体;">在做完分库分表这些工作后，数据库上的压力已经降到比较低了，又开始过着每天看着访问量暴增的幸福生活了，突然有一天，发现系统的访问又开始有变慢的趋势</span> <span style="font-family: 宋体;">了，这个时候首先查看数据库，压力一切正常，之后查看</span><span lang="EN-US">webserver</span><span style="font-family: 宋体;">，发现</span><span lang="EN-US">apache</span><span style="font-family: 宋体;">阻塞了很多的请求，而应用服务器对每个请求也是比较快的，看来</span> <span style="font-family: 宋体;">是请求数太高导致需要排队等待，响应速度变慢，这还好办，一般来说，这个时候也会有些钱了，于是添加一些</span><span lang="EN-US">webserver</span><span style="font-family: 宋体;">服务器，在这个添加</span><span lang="EN-US"> webserver</span><span style="font-family: 宋体;">服务器的过程，有可能会出现几种挑战：</span><span lang="EN-US"><br>
1</span><span style="font-family: 宋体;">、</span><span lang="EN-US">Apache</span><span style="font-family: 宋体;">的软负载或</span><span lang="EN-US">LVS</span><span style="font-family: 宋体;">软负载等无法承担巨大的</span><span lang="EN-US">web</span><span style="font-family: 宋体;">访问量（请求连接数、网络流量等）的调度了，这个时候如果经费允许的话，会采取的方案是购</span> <span style="font-family: 宋体;">买硬件负载，例如</span><span lang="EN-US">F5</span><span style="font-family: 宋体;">、</span><span lang="EN-US">Netsclar</span><span style="font-family: 宋体;">、</span><span lang="EN-US">Athelon</span><span style="font-family: 宋体;">之类的，如经费不允许的话，会采取的方案是将应用从逻辑上做一定的分类，然后分散到不同的软负载集群中；</span><span lang="EN-US"><br>
2</span><span style="font-family: 宋体;">、原有的一些状态信息同步、文件共享等方案可能会出现瓶颈，需要进行改进，也许这个时候会根据情况编写符合网站业务需求的分布式文件系统等；</span><span lang="EN-US"><br>
</span><span style="font-family: 宋体;">在做完这些工作后，开始进入一个看似完美的无限伸缩的时代，当网站流量增加时，应对的解决方案就是不断的添加</span><span lang="EN-US">webserver</span><span style="font-family: 宋体;">。</span></p>
<p ><span style="font-family: 宋体;">看看这一步完成后系统的图示：</span></p>
<p ><span lang="EN-US"><img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/8.PNG" alt="" width="466" height="441"><br>
</span></p>
<p ><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span></p>
<p ><span style="font-family: 宋体;">到了这一步，随着机器数的不断增长、数据量的不断增长和对系统可用性的要求越来越高，这个时候要求对所采用的技术都要有更为深入的理解，并需要根据网站的需求来做更加定制性质的产品。</span></p>
<p ><span lang="EN-US"> </span></p>
<p ><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;">架构演变第九步：数据读写分离和廉价存储方案</span></span></strong></p>
<p ><span style="font-family: 宋体;">突然有一天，发现这个完美的时代也要结束了，数据库的噩梦又一次出现在眼前了，由于添加的</span><span lang="EN-US">webserver</span><span style="font-family: 宋体;">太多了，导致数据库连接的资源还是不够用，而这个时候又已经分库分表了，开始分析数据库的压力状况，可能会发现数据库的读写比很高，这个时候通常会想到数据读写分离的方案，当然，这个方案要实现并不</span> <span style="font-family: 宋体;">容易，另外，可能会发现一些数据存储在数据库上有些浪费，或者说过于占用数据库资源，因此在这个阶段可能会形成的架构演变是实现数据读写分离，同时编写一些更为廉价的存储方案，例如</span><span lang="EN-US">BigTable</span><span style="font-family: 宋体;">这种。</span></p>
<p ><span style="font-family: 宋体;">看看这一步完成后系统的图示：</span></p>
<p ><span lang="EN-US"><img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/9.PNG" alt="" width="555" height="398"><br>
</span></p>
<p ><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span></p>
<p ><span style="font-family: 宋体;">数据读写分离要求对数据库的复制、</span><span lang="EN-US">standby</span><span style="font-family: 宋体;">等策略有深入的掌握和理解，同时会要求具备自行实现的技术；</span></p>
<p ><span style="font-family: 宋体;">廉价存储方案要求对</span><span lang="EN-US">OS</span><span style="font-family: 宋体;">的文件存储有深入的掌握和理解，同时要求对采用的语言在文件这块的实现有深入的掌握。</span></p>
<p ><span lang="EN-US"> </span></p>
<p ><strong><span style="font-family: 宋体;"><span style="font-size: 14pt;">架构演变第十步：进入大型分布式应用时代和廉价服务器群梦想时代</span></span></strong></p>
<p ><span style="font-family: 宋体;">经过上面这个漫长而痛苦的过程，终于是再度迎来了完美的时代，不断的增加</span><span lang="EN-US">webserver</span><span style="font-family: 宋体;">就可以支撑越来越高的访问量了，对于大型网站而言，人气的重要毋</span> <span style="font-family: 宋体;">庸置疑，随着人气的越来越高，各种各样的功能需求也开始爆发性的增长，这个时候突然发现，原来部署在</span><span lang="EN-US">webserver</span><span style="font-family: 宋体;">上的那个</span><span lang="EN-US">web</span><span style="font-family: 宋体;">应用已经非常庞大</span> <span style="font-family: 宋体;">了，当多个团队都开始对其进行改动时，可真是相当的不方便，复用性也相当糟糕，基本是每个团队都做了或多或少重复的事情，而且部署和维护也是相当的麻烦，</span> <span style="font-family: 宋体;">因为庞大的应用包在</span><span lang="EN-US">N</span><span style="font-family: 宋体;">台机器上复制、启动都需要耗费不少的时间，出问题的时候也不是很好查，另外一个更糟糕的状况是很有可能会出现某个应用上的</span><span lang="EN-US">bug</span><span style="font-family: 宋体;">就导</span> <span style="font-family: 宋体;">致了全站都不可用，还有其他的像调优不好操作（因为机器上部署的应用什么都要做，根本就无法进行针对性的调优）等因素，根据这样的分析，开始痛下决心，将</span> <span style="font-family: 宋体;">系统根据职责进行拆分，于是一个大型的分布式应用就诞生了，通常，这个步骤需要耗费相当长的时间，因为会碰到很多的挑战：</span><span lang="EN-US"><br>
1</span><span style="font-family: 宋体;">、拆成分布式后需要提供一个高性能、稳定的通信框架，并且需要支持多种不同的通信和远程调用方式；</span><span lang="EN-US"><br>
2</span><span style="font-family: 宋体;">、将一个庞大的应用拆分需要耗费很长的时间，需要进行业务的整理和系统依赖关系的控制等；</span><span lang="EN-US"><br>
3</span><span style="font-family: 宋体;">、如何运维（依赖管理、运行状况管理、错误追踪、调优、监控和报警等）好这个庞大的分布式应用。</span><span lang="EN-US"><br>
</span><span style="font-family: 宋体;">经过这一步，差不多系统的架构进入相对稳定的阶段，同时也能开始采用大量的廉价机器来支撑着巨大的访问量和数据量，结合这套架构以及这么多次演变过程吸取的经验来采用其他各种各样的方法来支撑着越来越高的访问量。</span></p>
<p ><span style="font-family: 宋体;">看看这一步完成后系统的图示：</span></p>
<p ><span lang="EN-US"><img src="http://www.blogjava.net/images/blogjava_net/bluedavy/arch/10.PNG" alt="" width="554" height="431"><br>
</span></p>
<p ><span style="font-family: 宋体;">这一步涉及到了这些知识体系：</span></p>
<p ><span style="font-family: 宋体;">这一步涉及的知识体系非常的多，要求对通信、远程调用、消息机制等有深入的理解和掌握，要求的都是从理论、硬件级、操作系统级以及所采用的语言的实现都有清楚的理解。</span></p>
<p ><span style="font-family: 宋体;">运维这块涉及的知识体系也非常的多，多数情况下需要掌握分布式并行计算、报表、监控技术以及规则策略等等。</span><span lang="EN-US"></span></p>
<p ><span lang="EN-US"></span><span style="font-family: 宋体;">说起来确实不怎么费力，整个网站架构的经典演变过程都和上面比较的类似，当然，每步采取的方案，演变的步骤有可能有不同，另外，由于网站的业务不同，会有不同的专业技术的需求，这篇</span><span lang="EN-US">blog</span><span style="font-family: 宋体;">更多的是从架构的角度来讲解演变的过程，当然，其中还有很多的技术也未在此提及，像数据库集群、数据挖掘、搜索等，但在真实的演变过程中还会借助像提升硬件配置、网络环境、改造操作系统、</span><span lang="EN-US">CDN</span><span style="font-family: 宋体;">镜像等来支撑更大的流量，因此在真实的发展过程中还会有很多的不同，另外一个大型网站要做到的远远不仅仅上面这些，还有像安全、运维、运营、服务、存储等，要做好一个大型的网站真的很不容易，写这篇文章更多的是希望能够引出更多大型网站架构演变的介绍，</span><span lang="EN-US"> <img src="http://blog.eingzone.com/wp-includes/images/smilies/icon_smile.gif" alt=":)" > </span><span style="font-family: 宋体;">。</span></p>
<p>ps:最后附上几篇LiveJournal架构演变的文章：<br>
从LiveJournal后台发展看大规模网站性能优化方法<br>
http://blog.zhangjianfeng.com/article/743<br>
另外从这里：http://www.danga.com/words/大家可以找到更多关于现在LiveJournal网站架构的介绍。</p><br></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/1117503720088992444862</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/1117503720088992444862</guid>
    <pubDate>Tue, 9 Sep 2008 09:24:44 +0800</pubDate>
    <dcterms:modified>2008-09-09T09:24:44+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[使用Flex Profiler 3.x]]></title>	
    <link>http://hydra1983.blog.163.com/blog/static/11175037200888947354</link>
    <description><![CDATA[<div><a href="http://blogs.adobe.com/aharui/2008/09/using_the_flex_builder_3x_prof.html" target="_blank">原文</a>来自<a href="http://blogs.adobe.com/aharui/" accesskey="1">Alex’s Flex Closet</a><br>Alex 在这里详细讲解了如何使用 Flex Profiler 来诊断内存泄漏的问题。虽然在网上搜索了很多有关profiler的问题，但是大多讲的是Flex Profiler的用途，或者简单介绍了一下用法。如何诊断实际程序中的问题确是很少提到。感谢Alex~<br><br><div >
                              <p>I've been
getting lots of questions about memory leaks lately. I finally found
some time to put my techniques for analyzing memory leaks into writing.</p>

<p>Instead of using PowerPoint, I actually created a SWF so you can use
the SWF to both view the presentation and learn how to use the
Profiler. I cover the differences between profiler memory,
System.totalMemory and process memory and show how I analyze the two
most common memory leak scenarios.</p>

<p><a href="http://blogs.adobe.com/aharui/profiler/ProfilerScenarios.swf">Run Presentation</a></p>

<p>As usual, caveats apply.</p>

<p>The SWF also demonstrates an approach to another topic I've heard
about often, and that is how to do XML-driven or data-driven UI. The
presentation in this SWF is controlled by an XML file. A single engine
parses the XML and creates the UI widgets as dictated by the XML. To
change the presentation, all I have to do is change the XML. I can also
add new widgets easily. Source is available here:</p>

<p><a href="http://blogs.adobe.com/aharui/profiler/ProfilerScenarios.zip">Download FlexBuilder Project</a></p>

<p>The SWF also demonstrates a technique for improving startup time.
Because our blog system is painful to use, I don't like uploading more
than one or two files per blog post, but this presentation had more
than a dozen images. So, instead of loading images externally, I
embedded them into the SWF, but normally, that delays startup by the
download time of all of those images. To get around that, I pack all
the images into frame 3 of the SWF so that Flex can get up and running
while the images download at the end of the SWF. I can get away with
that because the images are not needed right away. </p>

<p>Hope this helps.</p>
                           </div><br></div>]]></description>
	    <author><![CDATA[hydra1983]]></author>
	    <comments>http://hydra1983.blog.163.com/blog/static/11175037200888947354</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://hydra1983.blog.163.com/blog/static/11175037200888947354</guid>
    <pubDate>Mon, 8 Sep 2008 09:47:03 +0800</pubDate>
    <dcterms:modified>2008-09-08T09:47:03+08:00</dcterms:modified>
  </item>    
 </channel>
</rss>