Shao Fan

          關(guān)于JAVA與軟件工程
          posts - 31, comments - 71, trackbacks - 0, articles - 4
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          2006年3月2日

          目前開(kāi)發(fā)人員對(duì)系統(tǒng)開(kāi)發(fā)的一個(gè)共識(shí)是使用三層架構(gòu),分為表示層,業(yè)務(wù)層,和持久層。而這三層之間的依賴關(guān)系如何?比較常見(jiàn)的一種看法是

          表示層 --> 業(yè)務(wù)層 --> 持久層

          這表明了層與層之間的調(diào)用關(guān)系,表示層通過(guò)調(diào)用業(yè)務(wù)層來(lái)完成任務(wù),而業(yè)務(wù)層則調(diào)用持久層。從另一個(gè)角度來(lái)看,一種依賴關(guān)系是

          表示層 --> 領(lǐng)域模型(Domain Model) <-- 持久層

          表示層和持久層都應(yīng)該理解(recognize)領(lǐng)域模型。而領(lǐng)域模型則是業(yè)務(wù)層的一部分。業(yè)務(wù)層正是系統(tǒng)的價(jià)值所在。雖說(shuō)表示和持久也很重要,在某些系統(tǒng)中可以說(shuō)是很關(guān)鍵,但是它們的最終目的都是為業(yè)務(wù)服務(wù),所以業(yè)務(wù)層應(yīng)該是系統(tǒng)的核心

          基于以上的認(rèn)識(shí),在系統(tǒng)設(shè)計(jì)的時(shí)應(yīng)首先分析需求得到領(lǐng)域模型,找出系統(tǒng)中的實(shí)體、對(duì)象(靜態(tài)的一面),并明確大致的業(yè)務(wù)流程(動(dòng)態(tài)的一面)。 而另兩層應(yīng)盡最大努力為業(yè)務(wù)層服務(wù),且盡量減少業(yè)務(wù)層受另兩層的限制。


          各層的職責(zé):

          表示層:負(fù)責(zé)顯示信息,及從系統(tǒng)外部得到輸入。表示層的設(shè)計(jì)決定系統(tǒng)界面的可用性,及信息輸入和展示的可靠性。表示層只知道如何展示信息,及收集用戶輸入,并不知道該如何對(duì)這些輸入進(jìn)行處理來(lái)完成業(yè)務(wù)。

          業(yè)務(wù)層:完成業(yè)務(wù)邏輯。業(yè)務(wù)層設(shè)計(jì)決定客戶價(jià)值是否能夠得到實(shí)現(xiàn)。這是系統(tǒng)的關(guān)鍵。外在的表現(xiàn)是功能性。業(yè)務(wù)層設(shè)計(jì)和實(shí)現(xiàn)的失誤表現(xiàn)在用戶端即功能缺失,功能不可靠等。如果需要對(duì)業(yè)務(wù)層的業(yè)務(wù)規(guī)則進(jìn)行解耦,則可以使用規(guī)則引擎如Drools,把業(yè)務(wù)規(guī)則分離出來(lái)。但分離后的業(yè)務(wù)規(guī)則仍屬于業(yè)務(wù)層。業(yè)務(wù)層知道如何對(duì)用戶輸入進(jìn)行處理,能夠應(yīng)用業(yè)務(wù)規(guī)則完成用戶所需的業(yè)務(wù),但它不知道數(shù)據(jù)如何讀取和保存。

          持久層:負(fù)責(zé)用戶信息的持久化。持久層的失誤表現(xiàn)在外即數(shù)據(jù)處理(儲(chǔ)存,展示等)不可靠。持久層完全不知道業(yè)務(wù),只專(zhuān)注于數(shù)據(jù)存儲(chǔ)和讀取。所謂持久化并不一定是指數(shù)據(jù)庫(kù),任何方式的持久化(通過(guò)文件,網(wǎng)絡(luò)的持久化等)都應(yīng)由持久層完成。

          各層的設(shè)計(jì)都會(huì)直接影響系統(tǒng)性能。

          三層的體積大小和復(fù)雜度在不同的系統(tǒng)中可能會(huì)有很大的不同。比如說(shuō)GOOGLE的搜索引擎,它的界面很簡(jiǎn)單,可以想像表示層是比較容易實(shí)現(xiàn)的,而它的業(yè)務(wù)層,關(guān)系到處理關(guān)鍵字,分析搜索結(jié)果,決定排名等,而持久層則要負(fù)責(zé)處理超大量的數(shù)據(jù)。業(yè)務(wù)層和持久層則相當(dāng)復(fù)雜。而有的系統(tǒng)持久層會(huì)很小,比如殺毒軟件,媒體播放軟件等。業(yè)務(wù)層小而另兩層大的例子暫時(shí)還沒(méi)有想到:)


          posted @ 2007-09-08 19:45 shaofan 閱讀(5132) | 評(píng)論 (2)編輯 收藏

          help是一個(gè)內(nèi)置函數(shù),所謂內(nèi)置函數(shù),就是在Python中被自動(dòng)加載的函數(shù),任何時(shí)候都可以用。參數(shù)分兩種:

          • 如果傳一個(gè)字符串做參數(shù)的話,它會(huì)自動(dòng)搜索以這個(gè)字符串命名的模塊,方法,等。
          • 如果傳入的是一個(gè)對(duì)象,就會(huì)顯示這個(gè)對(duì)象的類(lèi)型的幫助。

          比如輸入help(’print’),它就會(huì)尋找以’print’為名的模塊,類(lèi),等,找不到就會(huì)看到提示信息。而print在python里是一個(gè)保留字,和pass,return同等,而非對(duì)象,所以help(print)也會(huì)出錯(cuò)((kkkkkkk))。

          舉個(gè)例子:

          1 help(’sys’) #會(huì)列出sys模塊的幫助
          2 = [1,2,3]
          3 help(a) #會(huì)顯示list的幫助
          4 help(a.append) #會(huì)顯示list的append方法的幫助

          python安裝自帶的library reference,2.1節(jié)是關(guān)于內(nèi)置函數(shù)的。

          Reference Manual的6.6節(jié)可以找到關(guān)于print的東東。

          posted @ 2007-06-05 06:28 shaofan 閱讀(2769) | 評(píng)論 (0)編輯 收藏

          Struts2默認(rèn)theme是xhtml,它用表格來(lái)對(duì)表單中的控件進(jìn)行排版。它也提供一個(gè)客戶端的js驗(yàn)證功能,但是它的js腳本卻有些問(wèn)題,在某些情況下,前次驗(yàn)證的提示信息無(wú)法被清除,提示信息會(huì)不斷的累積顯示在屏幕上。而按照設(shè)計(jì),每次提交表單時(shí)應(yīng)只顯示每次驗(yàn)證的出錯(cuò)信息。

          它的客戶端驗(yàn)證的流程大概是這樣,用戶提交表單時(shí),對(duì)各個(gè)控件的輸入按預(yù)先設(shè)置的規(guī)則進(jìn)行驗(yàn)證,如果有問(wèn)題,則清除表單里原有的出錯(cuò)提示信息,并寫(xiě)入新的提示。其設(shè)計(jì)的功能是把出錯(cuò)信息寫(xiě)表格里出錯(cuò)控件的上方,以便用戶看得更加清楚。問(wèn)題就出在其用來(lái)清除原出錯(cuò)信息的函數(shù),其代碼是這樣的(在struts.jar的template/xhtml目錄下可以找到):

           1 function clearErrorMessages(form) {
           2 
           3     var table = form.childNodes[1];
           4     iftypeof table == "undefined" ) {
           5         table = form.childNodes[0];
           6     }
           7 
           8     // clear out any rows with an "errorFor" attribute
           9     var rows = table.rows;
          10     var rowsToDelete = new Array();
          11     if (rows == null){
          12         return;
          13     }
          14 
          15     for(var i = 0; i < rows.length; i++) {
          16         var r = rows[i];
          17         if (r.getAttribute("errorFor")) {
          18             rowsToDelete.push(r);
          19         }
          20     }
          21 
          22     // now delete the rows
          23     for (var i = 0; i < rowsToDelete.length; i++) {
          24         var r = rowsToDelete[i];
          25         table.deleteRow(r.rowIndex);
          26         //table.removeChild(rowsToDelete[i]);
          27     }
          28 }


          看這個(gè)函數(shù)的前三行,它試圖取得form的第1個(gè)或第2個(gè)子節(jié)點(diǎn),并把它作為table來(lái)處理(看接下來(lái)的幾行)。要想清除表格里的錯(cuò)誤信息,首先要取得表格本身,這沒(méi)錯(cuò),但是如果第1個(gè)或第2個(gè)子節(jié)點(diǎn)不是table的話,腳本就會(huì)出錯(cuò),造成原出錯(cuò)信息無(wú)法清除,這樣每次提交后的提示信息就會(huì)累積在屏幕上。

          要解決這個(gè)問(wèn)題有兩個(gè)辦法:
          • 寫(xiě)代碼時(shí)要小心,保證form的第1或2個(gè)子節(jié)點(diǎn)是table,不要在生成table前加其他代碼。
          • 或,修改xhtml的validation.js,使它總能獲得正確的table元素,重新打包到struts.jar。
          剛看了一下Struts的JIRA,已經(jīng)有人報(bào)告了這個(gè)問(wèn)題(id WW-1802),而且這個(gè)bug在2.1版本中已經(jīng)解決了。

          posted @ 2007-06-03 17:56 shaofan 閱讀(2540) | 評(píng)論 (3)編輯 收藏

          假設(shè):用兩者寫(xiě)一個(gè)最小的WEB程序。
          過(guò)程可以參照:
          1.struts的就太多了,隨便哪個(gè)都可以
          2.python/django可以看limodou寫(xiě)的Django step by step

           

          Java/Struts/JSP  Python/Django
          開(kāi)發(fā)步驟 1.在web.xml里配置struts的servlet
          2.在struts-config.xml里配置URL和action的映射
          3.寫(xiě)action
          4.寫(xiě)JSP
          1.在urls.py里配置URL到方法的映射
          2.寫(xiě)相應(yīng)的方法
          3.寫(xiě)HTML模板
          調(diào)用過(guò)程 1.根據(jù)web.xml的映射調(diào)用struts的servlet controller
          2.servlet controller根據(jù)struts-config.xml的映射調(diào)用相應(yīng)的action
          3.action處理請(qǐng)求
          4.JSP渲染顯示
          1.根據(jù)urls.py的映射調(diào)用相應(yīng)的方法
          2.方法處理請(qǐng)求
          3.HTML渲染顯示


          相比之下前者用了兩層才把一個(gè)HTTP請(qǐng)求映射到實(shí)際處理的方法:第一次是servlet的映射,第二次是struts action的映射。
          而django則一次就從URL映射到相應(yīng)的方法了。

          另外一個(gè)比較顯著的區(qū)別,也是基于java和python的語(yǔ)言上的區(qū)別吧,java的所有方法必需包含在一個(gè)類(lèi)中,因此action mapping配置時(shí)是映射到類(lèi),而action在實(shí)現(xiàn)類(lèi)則應(yīng)實(shí)現(xiàn)事先約定的方法(通過(guò)繼承或?qū)崿F(xiàn)接口)。而django則直接得多,可以直接在配置里寫(xiě)明處理請(qǐng)求的方法名。


          posted @ 2007-04-06 19:11 shaofan 閱讀(4977) | 評(píng)論 (0)編輯 收藏

          DOM (Document Object Model)是一套語(yǔ)言無(wú)關(guān)的XML解析的接口定義。它定義了在XML解析中需要的類(lèi)型,方法,以及屬性,比如如何獲得一個(gè)XML標(biāo)簽,如何改變標(biāo)簽的內(nèi)容,如何改變它的屬性,等等。

          DOM只是一個(gè)定義,并不是具體的實(shí)現(xiàn),它的目的就是為了讓大家在各個(gè)平臺(tái)上都能用相同的方式來(lái)處理XML,這樣一來(lái),我只要了解DOM,基本上在各個(gè)平臺(tái)上都可以方便的處理XML,而不用重新學(xué)習(xí)了。比如說(shuō),Java, JavaScript, Python都有DOM的實(shí)現(xiàn),用它們來(lái)處理XML,方式基本上都是一樣的(當(dāng)然也有非DOM的XML解析方式)。在Java下,實(shí)現(xiàn)DOM的類(lèi)庫(kù)就有很多,比如JDom,Xerces, 用GOOGLE一搜就一大把。現(xiàn)在Java 5.0內(nèi)置的就是Xerces。而JavaScript本身就內(nèi)置了DOM的實(shí)現(xiàn)。Python也默認(rèn)安裝了DOM的庫(kù)。

          正因?yàn)镈OM致力于實(shí)現(xiàn)各個(gè)平臺(tái)上對(duì)XML一致的處理方式,它定義了一堆自己的接口。因此在用DOM的時(shí)候,會(huì)有很多非NATIVE的東東。比如說(shuō),返回節(jié)點(diǎn)的子節(jié)點(diǎn)的方法,childNodes,返回的類(lèi)型是NodeList。我第一次在Java上用,就以為是返回一個(gè)List,然后用get(n)方法來(lái)取得某元素。而實(shí)際上NodeList是用item(n)的方法來(lái)取得某元素的。這就讓我覺(jué)得很怪。而DOM正是用這種方式來(lái)獲得“語(yǔ)言無(wú)關(guān)”的能力的。

          DOM是用IDL(Interface Definition Language)來(lái)定義的。完整的定義可以在這里找到 http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html。IDL也很容易看懂。定義的1.1節(jié)列出了所有的接口。

          這些接口里,最重要而且常用的是Node,NodeList,Document,Element,Text,Attr這幾個(gè)。DOM把XML文檔看作一棵樹(shù),樹(shù)上的每個(gè)元素都是Node。每個(gè)Node都屬于某個(gè)類(lèi)型,比如Element,attribute,text等。這些類(lèi)型就表明這個(gè)節(jié)點(diǎn)在XML文檔里的類(lèi)型了。

          比如Node里有個(gè)屬性:

          ??readonly?attribute?unsigned? short ??nodeType;

          根據(jù)這個(gè)定義,對(duì)于取得的節(jié)點(diǎn),我們就可以通過(guò)讀取nodeType這個(gè)屬性來(lái)判斷這個(gè)節(jié)點(diǎn)的類(lèi)型。在Java里,所有的屬性都是用getter來(lái)取得的,因此對(duì)某節(jié)點(diǎn)n,就可以用n.getNodeType()取得它的類(lèi)型。Node接口里也定義了類(lèi)型常量:

          ??const?unsigned?short??????ELEMENT_NODE???????????????????=?1;
          ??const?unsigned?short??????ATTRIBUTE_NODE?????????????????=?2;
          ??const?unsigned?short??????TEXT_NODE??????????????????????=?3;
          ??const?unsigned?short??????CDATA_SECTION_NODE?????????????=?4;
          ??const?unsigned?short??????ENTITY_REFERENCE_NODE??????????=?5;
          ??const?unsigned?short??????ENTITY_NODE????????????????????=?6;
          ??const?unsigned?short??????PROCESSING_INSTRUCTION_NODE????=?7;
          ??const?unsigned?short??????COMMENT_NODE???????????????????=?8;
          ??const?unsigned?short??????DOCUMENT_NODE??????????????????=?9;
          ??const?unsigned?short??????DOCUMENT_TYPE_NODE?????????????=?10;
          ??const?unsigned?short??????DOCUMENT_FRAGMENT_NODE?????????=?11;
          ??const?unsigned?short??????NOTATION_NODE??????????????????=?12;

          用這些常量和和n.getNodeType()的結(jié)果比較,就可以知道它是不是某種類(lèi)型。

          Node接口中也定義了一些方法,比如:

          ?Node?????appendChild(in?Node?newChild)????raises(DOMException);

          表明appendChild方法需要一個(gè)Node類(lèi)型的參數(shù),返回一個(gè)Node。 具體的說(shuō)明可以點(diǎn)文檔上的鏈接進(jìn)去,也很容易看懂。

          Node接口里定義了操縱節(jié)點(diǎn)的方法,比如增加子節(jié)點(diǎn),返回父節(jié)點(diǎn),插入新節(jié)點(diǎn),返回節(jié)點(diǎn)類(lèi)型,等等。Document,Element等接口都繼承Node接口,因此在它們上面都可以使用操縱節(jié)點(diǎn)的方法。

          Document:代表整個(gè)XML文檔。所有DOM元素都不能用類(lèi)似Java里new的方式來(lái)生成,而是要通過(guò)調(diào)用Document里的相應(yīng)方法來(lái)生成。因此它提供了生成諸如Element, Attr, Text的方法。比如createElement, createTextNode, createComment等。它也提供了名為getElementsByTagName的方法,用來(lái)通過(guò)標(biāo)簽名稱(chēng)來(lái)取得其對(duì)象。比如getElementByTagName("ul")就可以獲得所有ul標(biāo)簽。它也提供一些文檔的屬性,比如xmlEncoding,inputEncoding等。它的一個(gè)屬性,documentElement代表文檔的根節(jié)點(diǎn)。所有對(duì)XML元素的操作,基本上都是從Document開(kāi)始的。

          Element:代表一個(gè)XML標(biāo)簽。它可以有屬性,子標(biāo)簽,等。比如<ul id="booklist"><li>hello</li></ul>。標(biāo)簽ul是一個(gè)Element,它有一個(gè)屬性叫id,屬性的值是booklist。它有一個(gè)子結(jié)點(diǎn)li。li也是一個(gè)標(biāo)簽,它也有個(gè)子節(jié)點(diǎn)hello,是一個(gè)Text類(lèi)型的節(jié)點(diǎn)。這個(gè)接口提供操縱其標(biāo)簽屬性的方法,比如getAttribute,setAttribute,removeAttribute等。它也提供了和Document中一樣的getElementsByTagName的方法,用來(lái)獲得在這個(gè)節(jié)點(diǎn)下的元素。

          Attr:代表標(biāo)簽中的屬性。比如上面的id。它也是一個(gè)Node。它有名字,值,也可以獲得它的所屬標(biāo)簽。

          Text:代表一段文字,比如上面的hello,它也一個(gè)Node,但比較特殊,它不是直接繼承Node,而是繼承CharacterData接口,后者繼承了Node。但是它不能有子節(jié)點(diǎn)。

          用JavaScript給一個(gè)例子。假設(shè)有一個(gè)HTML文檔:

          < html >< head >< title > Try?DOM </ title ></ head >< body >
          < ul >
          < li > hello </ li >
          < li > world </ li >
          </ ul >
          </ body ></ html >

          下面是增加一個(gè)li的JavaScript方法:

          ulList? = ?document.getElementsByTagName( " ul " );
          ul?????
          = ?ulList.item( 0 );
          txt????
          = ?document.createTextNode( " I?am?new?li " );
          li?????
          = ?document.createElement( " li " );
          li.appendChild(txt);
          ul.appendChild(li);

          用Java來(lái)寫(xiě),是這樣:

          NodeList?ulList? = ?document.getElementsByTagName( " ul " );
          Node??????? ul??????
          = ?ulList.item( 0 );
          Text????????? txt???? ?
          = ?document.createTextNode( " I?am?new?li " );
          Element??? li??? ????
          = ?document.createElement( " li " );
          li.appendChild(txt);
          ul.appendChild(li);

          可以看到處理方式和數(shù)據(jù)類(lèi)型都是一樣的。如果要了解更多,可以看看DOM的定義,都是IDL。

          posted @ 2007-04-01 18:45 shaofan 閱讀(857) | 評(píng)論 (0)編輯 收藏

          我的博客已搬家,請(qǐng)移步到 http://shao-fan.com/blog 閱讀最新內(nèi)容!


          Ubuntu/Debian中的update-alternative用來(lái)對(duì)系統(tǒng)中不同版本的同個(gè)軟件進(jìn)行管理。
          比如,系統(tǒng)中可能裝有GNU的Java編譯器,和SUN的Java編譯器。可以用update-alternatives來(lái)設(shè)置當(dāng)前使用它們中的哪一個(gè)。

          它的原理是在/usr/bin中建立一個(gè)link,指向/etc/alternatives中的一個(gè)文件,而些文件又是一個(gè)link,指向當(dāng)前使用的命令。比如java命令,查看如下:

           $ which java
          /usr/bin/java
          $ ls -l /usr/bin/java
          lrwxrwxrwx /usr/bin/java -> /etc/alternatives/java
          $ ls -l /etc/alternatives/java
          lrwxrwxrwx /etc/alternatives/java -> /usr/lib/j2re1.5-sun/bin/java
          $ ls -l /usr/lib/j2re1.5-sun/bin/java
          -rwxr-xr-x /usr/lib/j2re1.5-sun/bin/java

          參數(shù)--display可以某個(gè)軟件的當(dāng)前配置,如:

           $ /usr/sbin/update-alternatives --display java
          java - status is auto.
          link currently points to /usr/lib/j2re1.5-sun/bin/java
          /usr/lib/kaffe/bin/java - priority 300
          slave java.1.gz: /usr/share/man/man1/java.kaffe.1.gz
          /usr/lib/j2re1.5-sun/bin/java - priority 315
          slave java.1.gz: /usr/lib/j2re1.5-sun/man/man1/java.1.gz
          Current `best' version is /usr/lib/j2re1.5-sun/bin/java.

          status有auto和manual兩種。一旦用戶更改了系統(tǒng)的默認(rèn)設(shè)置,它就變?yōu)閙anual。在auto的狀態(tài)下,系統(tǒng)會(huì)根據(jù)幾套配置的priority來(lái)判斷當(dāng)前應(yīng)該使用哪套配置。

          每套配置可以設(shè)定多個(gè)link,它們被稱(chēng)為slave。上面的例子中,有兩套java的配置。一套是/usr/lib/kafe/bin/java,另一套是/usr/lib/j2re1.5-sun/bin/java,它們各有一個(gè)slave。在些例中這些slave設(shè)置的是java命令的 manual。當(dāng)更改了配置時(shí),用man命令查看的幫助也會(huì)相應(yīng)更改。

          參數(shù)--config可以用來(lái)更改當(dāng)前的配置。

           $ sudo /usr/sbin/update-alternatives --config java 
          There are 2 alternatives which provide `java'.
          Selection Alternative
          -----------------------------------------------
          1 /usr/lib/kaffe/bin/java
          *+ 2 /usr/lib/j2re1.5-sun/bin/java
          Press enter to keep the default*, or type selection number: 1
          Using `/usr/lib/kaffe/bin/java' to provide `java'.

          參數(shù)--install用來(lái)設(shè)置一套新的配置。具體參見(jiàn) http://blog.stevenkroon.com/2006/08/29/debian-update-alternatives/

          posted @ 2006-12-25 01:43 shaofan 閱讀(6310) | 評(píng)論 (1)編輯 收藏

          Web開(kāi)發(fā)真是越來(lái)越有意思了。現(xiàn)在居然可以在JavaScript里直接調(diào)用Java寫(xiě)的方法。大水牛Buffalo的最新版1.2.3發(fā)行離現(xiàn)在已有半年時(shí)間了,現(xiàn)在才注意到。在客戶端的代碼相當(dāng)簡(jiǎn)單:

          buffalo.remoteCall("userService.listAll",[],function(reply){
           //?不用擔(dān)心,reply.getResult會(huì)從聰明的判斷服務(wù)器端遠(yuǎn)程調(diào)用的結(jié)果類(lèi)型。
           var?userList?=?reply.getResult();?
           var?firstUserFamilyName?=?userList[0].name.familyName;
          });

          給Web程序加上Buffalo也相當(dāng)容易。只要下載幾個(gè)jar文件放到lib目錄下,外加幾個(gè)JS文件,然后在web.xml里加一個(gè)Servlet即可。用的時(shí)候是需要有個(gè)properties文件來(lái)定義哪些JAVA方法可以被JS調(diào)用。而服務(wù)器端的JAVA代碼不需要做任何改動(dòng)。

          暫時(shí)手頭上還想不起來(lái)哪些地方會(huì)用,但是這個(gè)東東可是我很久以前曾經(jīng)想過(guò)的,現(xiàn)在有人實(shí)現(xiàn)了,還是很激動(dòng)人心的啊。Buffalo的主頁(yè)是 http://www.amowa.net/buffalo/zh/index.html?。


          posted @ 2006-09-08 03:59 shaofan 閱讀(8926) | 評(píng)論 (6)編輯 收藏

          最近因?yàn)镚lobus的原因,不得不用Linux了。以前幾次想學(xué),都因?yàn)殡y得要領(lǐng)放棄了。這次裝了Ubuntu,又碰巧在它的論壇上看到一篇很不錯(cuò)的教程,終于有些“入門(mén)”的感覺(jué)了。看來(lái)找到合適的教程真的是很重要啊。這幾天用下來(lái),感覺(jué)還真的很不錯(cuò)。用Python寫(xiě)了個(gè)顯示目錄樹(shù)的小程序。也不知道有沒(méi)有現(xiàn)成的,反正很簡(jiǎn)單,剛好就練練手,功能也夠我自己用了:)

          下載Python腳本


          posted @ 2006-08-01 08:57 shaofan 閱讀(1503) | 評(píng)論 (0)編輯 收藏

          最近Firefox出了點(diǎn)問(wèn)題。我這里用http proxy上網(wǎng),連接設(shè)置里要設(shè)置相應(yīng)的proxy。但發(fā)現(xiàn)每次重啟ff,連接設(shè)置都被重置為“直接連接”。即使改回“通過(guò)proxy連接”,下次重啟又被重置了。

          馬上google一把,發(fā)現(xiàn)類(lèi)似的問(wèn)題大致有兩種解決辦法:
          1.進(jìn)入safe mode,會(huì)出現(xiàn)一個(gè)對(duì)話框,把三個(gè)選項(xiàng)都勾上,重啟。
          2.在地址欄輸入about:config,會(huì)出現(xiàn)所有的配置,把要改的改了即可。
          3.直接修改prefs.js文件。

          但這三個(gè)方法對(duì)偶的FF都不管用。

          最后的解決方法是,刪除
          C:\Documents and Settings\<user name>\Application Data\Mozilla\Firefox\Profiles\<xxxxxxxx.default>\
          下的user.js,然后再修改prefs.js。然后一切都正常了。

          原來(lái),ff最基本的配置文件是prefs.js。而user.js的優(yōu)先級(jí)應(yīng)該是比prefs.js高,因此每次重啟它都從user.js讀取配置。而通過(guò)正常途徑,如在選項(xiàng)菜單里改設(shè)置,無(wú)法在user.js里保存(不知道為什么)。所以就造成了每次重啟配置被重置的情況,其實(shí)就是設(shè)置無(wú)法被保存。把user.js刪掉以后,ff就從prefs.js里讀取配置了,而且新的設(shè)置也可以正常保存。

          不管是從選項(xiàng)菜單里修改配置,還是以上的第二種方法,最終的結(jié)果都是配置被保存在prefs.js文件里,效果都是一樣的。

          目前已知的會(huì)私自修改FF配置的軟件只有Hide IP Plantium,而以上情況正是在安裝Hide IP Plantium以后出現(xiàn)的。用的時(shí)候要注意。

          相關(guān)的討論在mozillazine里有很多。不得不承認(rèn),這類(lèi)的英文資源要比中文的多得多。看這里的詳細(xì)討論:
          http://forums.mozillazine.org/viewtopic.php?t=413875&postdays=0&postorder=asc&postsperpage=15&start=15

          posted @ 2006-07-24 18:21 shaofan 閱讀(4638) | 評(píng)論 (2)編輯 收藏

          1.理解頁(yè)面流(flow),理解幾種不同的定位方式:static, relative, absolute等
          Positioning and other definitions:http://css.maxdesign.com.au/floatutorial/definitions.htm ?

          2.HTML頁(yè)面表達(dá)內(nèi)容邏輯,把樣式控制寫(xiě)到CSS文件中

          3.浮動(dòng)(float)的DIV要配合width屬性來(lái)用

          4.怎樣控制層的位置:用float,padding,width,height這些屬性來(lái)控制
          Float Tutorial: http://css.maxdesign.com.au/floatutorial/index.htm

          5.設(shè)置可見(jiàn)的border或background-color來(lái)幫助排版

          6.出現(xiàn)內(nèi)層的DIV跑到外層之外的情況時(shí),可以在外層DIV的</DIV>前加上一個(gè)clear層來(lái)解決問(wèn)題。就是這樣:
          ?? <div class="container">
          ?? ?...
          ?? ?...
          ?? ?<div class="clear"></div>
          ? </div>

          ? css:
          ? .clear{
          ?? ?clear:both;
          ? }

          7.樣式表的選擇符(Selector):
          ?? Type/Class/ID等
          ? Selector Tutorial:http://css.maxdesign.com.au/selectutorial/index.htm

          8.關(guān)于表單的樣式設(shè)計(jì):
          讓我們更好的設(shè)計(jì)表單:淺議Web的表單設(shè)計(jì) http://tech.163.com/06/0529/04/2I8UPHTB0009158Q.html
          用CSS制作具有親和力的表單 作者:greengnn
          http://www.jluvip.com/blog/article.asp?id=192

          9.各種瀏覽器對(duì)各種標(biāo)簽用不同的方式渲染,如p, h1, ul等,它們會(huì)有不同的padding和margin,為了在各種瀏覽器下都正常的顯示,可以把它們清零,如:
          *{
          ?? ?padding:0;
          ?? ?margin:0;
          }

          10.使用list來(lái)顯示數(shù)據(jù)或菜單
          List Tutorial:
          http://css.maxdesign.com.au/listamatic/
          http://css.maxdesign.com.au/listamatic2/
          http://css.maxdesign.com.au/listutorial/

          11.關(guān)于各種標(biāo)準(zhǔn),布局,技巧等的網(wǎng)站:
          網(wǎng)頁(yè)設(shè)計(jì)師:http://www.w3cn.org/
          CSS教程:http://www.netvtm.com/w3s/css/
          網(wǎng)頁(yè)制作指導(dǎo) - 致力于網(wǎng)頁(yè)制作知識(shí)的普及:http://www.jianzhan8.cn/
          當(dāng)然還有必不可少的經(jīng)典論壇blueidea:http://www.blueidea.com/bbs/list.asp?GroupName=%CD%F8%D2%B3%B1%EA%D7%BC%BB%AF%D7%A8%C0%B8

          posted @ 2006-06-21 06:22 shaofan 閱讀(934) | 評(píng)論 (0)編輯 收藏

          如果你不幸裝了NetBeans并且啟用了外置的服務(wù)器,那么它會(huì)自動(dòng)在你的web server的web.xml里添加一個(gè)filter,名叫HttpMonitorFilter。你用NetBeans時(shí),它會(huì)過(guò)濾所有的http請(qǐng)求,這樣NetBeans就可以顯示所有的相關(guān)信息。但是如果不用NetBeans,比如我,用eclipse + Tomcat ,那就會(huì)得到這個(gè)異常:

          NotifyUtil::java.net.ConnectException:?Connection?refused:?connect
          ??at?java.net.PlainSocketImpl.socketConnect(Native?Method)
          ??at?java.net.PlainSocketImpl.doConnect(Unknown?Source)
          ??at?java.net.PlainSocketImpl.connectToAddress(Unknown?Source)
          ??at?java.net.PlainSocketImpl.connect(Unknown?Source)
          ??at?java.net.Socket.connect(Unknown?Source)
          ??at?java.net.Socket.connect(Unknown?Source)
          ??at?sun.net.NetworkClient.doConnect(Unknown?Source)
          ??at?sun.net.www.http.HttpClient.openServer(Unknown?Source)
          ??at?sun.net.www.http.HttpClient.openServer(Unknown?Source)
          ??at?sun.net.www.http.HttpClient.(Unknown?Source)
          ??at?sun.net.www.http.HttpClient.(Unknown?Source)
          ??at?sun.net.www.http.HttpClient.New(Unknown?Source)
          ??at?sun.net.www.http.HttpClient.New(Unknown?Source)
          ??at?sun.net.www.http.HttpClient.New(Unknown?Source)
          ??at?sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown?Source)
          ??at?sun.net.www.protocol.http.HttpURLConnection.connect(Unknown?Source)
          ??at?sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown?Source)
          ??at?org.netbeans.modules.web.monitor.server.NotifyUtil$RecordSender.run(NotifyUtil.java:237)



          解決方法是

          第一步. 刪除 Tomcat目錄中common\lib下的兩個(gè)和netbeans有關(guān)的jar文件(以org-netbeans開(kāi)頭的)

          第二步. 修改tomcat目錄下的conf\web.xml,刪除相關(guān)Filter的定義,就是這一段:

          ????<filter>
          ????????
          <filter-name>HTTPMonitorFilter</filter-name>
          ????????
          <filter-class>
          ????????????org.netbeans.modules.web.monitor.server.MonitorFilter
          ????????
          </filter-class>
          ????????
          <init-param>
          ????????????
          <param-name>netbeans.monitor.ide</param-name>
          ????????????
          <param-value>127.0.0.1:8082</param-value>
          ????????
          </init-param>
          ????
          </filter>
          ????
          <filter-mapping>
          ????????
          <filter-name>HTTPMonitorFilter</filter-name>
          ????????
          <url-pattern>/*</url-pattern>
          ????????
          <dispatcher>REQUEST</dispatcher>
          ????????
          <dispatcher>FORWARD</dispatcher>
          ????????
          <dispatcher>INCLUDE</dispatcher>
          ????????
          <dispatcher>ERROR</dispatcher>
          ????
          </filter-mapping>

          posted @ 2006-06-13 20:37 shaofan 閱讀(1048) | 評(píng)論 (0)編輯 收藏

          據(jù)英國(guó)的職位搜索引擎Workcircle的調(diào)查顯示,93%的IT經(jīng)理人和幾乎所有的CEO和CTO會(huì)在英格蘭隊(duì)比賽的那天請(qǐng)病假。相比之下,程序員的請(qǐng)假的比例要低得多,JAVA程序員為86%,而最可憐的是SQL程序員,只有14%。更搞笑的是WikiHow上還有一個(gè)“怎樣請(qǐng)病假”的教程。

          原文如下:

          Managers most likely to take a sickie to watch England play

          9 June 2006, Cambridge UK – UK job site, Workcircle ran a survey this week asking how likely jobseekers are to take a sick day to watch an England World Cup match.

          World cup surveyThe results show the deep divide between workers and management, just 14% of Engineers surveyed will take a sickie to watch a match, but a shocking 93% of managers will.

          And it gets worse the higher you get – all CEOs and CTOs surveyed will take a day off.

          As far as the developers go, Java programmers are the most patriotic – 86% would call in sick to watch a match, compared to 14% of hard-working SQL developers.

          So when the boss is in an unexplained long meeting during the World Cup, check if there’s an England match on!

          posted @ 2006-06-12 06:45 shaofan 閱讀(688) | 評(píng)論 (0)編輯 收藏

          適用于webwork 2.2.2,詳見(jiàn)隨包文檔。源文件下載:Hello.rar

          一共五步:

          1.建立web應(yīng)用程序的目錄結(jié)構(gòu)
          2.拷貝庫(kù)文件:ww安裝目錄下的lib\default中的所有jar,以及webwork-2.2.2.jar,復(fù)制到WEB-INF\lib下。
          3.生成配置文件:web.xml在WEB-INF下, xwork.xml在WEB-INF\classes下

          web.xml:
          <?xml?version="1.0"?encoding="ISO-8859-1"?>
          <!DOCTYPE?web-app?PUBLIC?"-//Sun?Microsystems,?Inc.//DTD?Web?Application?2.3//EN"?"http://java.sun.com/dtd/web-app_2_3.dtd">
          <web-app>

          ????
          <display-name>My?First?Hello?Webwork</display-name>

          ????
          <filter>
          ????????
          <filter-name>webwork</filter-name>
          ????????
          <filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class>
          ????
          </filter>

          ????
          <filter-mapping>
          ????????
          <filter-name>webwork</filter-name>
          ????????
          <url-pattern>/*</url-pattern>
          ????
          </filter-mapping>

          ????
          <welcome-file-list>
          ????????
          <welcome-file>index.jsp</welcome-file>
          ????
          </welcome-file-list>

          ????
          <taglib>
          ????????
          <taglib-uri>/webwork</taglib-uri>
          ????????
          <taglib-location>/WEB-INF/lib/webwork-2.2.2.jar</taglib-location>
          ????
          </taglib>
          </web-app>


          xwork.xml:
          <!DOCTYPE?xwork?PUBLIC?"-//OpenSymphony?Group//XWork?1.1.1//EN"?"http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">

          <xwork>
          ????
          <!--?Include?webwork?defaults?(from?WebWork?JAR).?-->
          ????
          <include?file="webwork-default.xml"?/>

          ????
          <!--?Configuration?for?the?default?package.?-->
          ????
          <package?name="default"?extends="webwork-default">
          ????
          </package>
          </xwork>


          4. 編寫(xiě)action和jsp
          5. 在xwork.xml中添加相應(yīng)配置,如在package之間加入:
          ????????<default-interceptor-ref?name="completeStack"/>
          ????????
          <action?name="helloww"?class="net.blogjava.shaofan.helloww.Hello">
          ????????????
          <result?name="success">greetings.jsp</result>
          ????????
          </action>


          下步計(jì)劃:
          * 了解package
          * ww的taglibs
          * 在action和jsp間傳遞數(shù)據(jù)的機(jī)制(struts中使用formbean,利用session,request等)

          posted @ 2006-06-04 09:13 shaofan 閱讀(2305) | 評(píng)論 (7)編輯 收藏

               摘要: 在這篇文章里,Nick Afshartous描述了一種把HTML的內(nèi)容轉(zhuǎn)換為PDF格式的方法。這種方法相當(dāng)有用,比如說(shuō),一個(gè)web程序可以在它的頁(yè)面上提供如“下載為 PDF”的功能。這種功能方便了打印和儲(chǔ)存,以供日后使用。Afshartous的轉(zhuǎn)換方法只使用開(kāi)源的組件。也有一些商業(yè)產(chǎn)業(yè)可供使用。因此,在這篇文章里描述的這種方法既在價(jià)格上可以承擔(dān),又能夠獲得所用組件的源碼。(1600字;2006年4月10日)   閱讀全文

          posted @ 2006-06-01 07:56 shaofan 閱讀(3549) | 評(píng)論 (10)編輯 收藏

               摘要: 在這篇文章里,Nick Afshartous描述了一種把HTML的內(nèi)容轉(zhuǎn)換為PDF格式的方法。這種方法相當(dāng)有用,比如說(shuō),一個(gè)web程序可以在它的頁(yè)面上提供如“下載為PDF”的功能。這種功能方便了打印和儲(chǔ)存,以供日后使用。Afshartous的轉(zhuǎn)換方法只使用開(kāi)源的組件。也有一些商業(yè)產(chǎn)業(yè)可供使用。因此,在這篇文章里描述的這種方法既在價(jià)格上可以承擔(dān),又能夠獲得所用組件的源碼。(1600字;2006年4月10日)
            閱讀全文

          posted @ 2006-05-30 06:15 shaofan 閱讀(5689) | 評(píng)論 (7)編輯 收藏

          天差點(diǎn)栽在JAVA路徑設(shè)置上。

          本來(lái)是想用ANT的。但是在命令行輸入ant,得到了這樣的提示:

          Usage: java [-options] class [args...]
          ?????????? (to execute a class)
          ?? or? java [-options] -jar jarfile [args...]
          ?????????? (to execute a jar file)

          ?? ??? ......
          ?? ??? ......

          奇怪。想來(lái)是剛重裝了系統(tǒng),JAVA_HOME沒(méi)有設(shè)好。于是檢查了一遍。問(wèn)題依舊。那是不是虛擬機(jī)的問(wèn)題?虛擬機(jī)缷掉重裝。折騰了半天,問(wèn)題還是沒(méi)有解決。

          逼得我只能靜下心來(lái)仔細(xì)想想問(wèn)題所在了。ant的命令執(zhí)行的是一個(gè)批處理文件,在這個(gè)批處理中它會(huì)調(diào)用java.exe來(lái)運(yùn)行ant。出現(xiàn)這樣的問(wèn)題,必定是java.exe的用法格式不對(duì)了。于是打開(kāi)ant.bat,發(fā)現(xiàn)它的執(zhí)行有幾個(gè)分支。在每個(gè)分支上加上一句echo b1, echo b2,再次運(yùn)行,確定是哪個(gè)分支被執(zhí)行。被運(yùn)行的語(yǔ)句分支就是這個(gè)了:

          :runAntWithClasspath
          "%_JAVACMD%" %ANT_OPTS% -classpath "%ANT_HOME%\lib\ant-launcher.jar" "-Dant.home=%ANT_HOME%" org.apache.tools.ant.launch.Launcher %ANT_ARGS% -cp "%CLASSPATH%" %ANT_CMD_LINE_ARGS%
          goto end

          OK。現(xiàn)在幾乎可以肯定是那一堆%%的變量里出了問(wèn)題。拿出我們程序員百試不爽的絕招的時(shí)候了:打印每個(gè)變量。哈哈,問(wèn)題出來(lái)了:

          "D:\lib\apache-ant-1.6.5\\lib\ant-launcher.jar"

          看到了嗎?"lib"前面居然是兩個(gè)反斜杠杠。OK。發(fā)現(xiàn)了問(wèn)題所在,現(xiàn)在是解決的時(shí)候了。打開(kāi)系統(tǒng)變量ANT_HOME,果然,它被設(shè)置為"D:\lib\apache-ant-1.6.5\"。把最后的反斜杠去掉。再試運(yùn)行ant,得到:

          Buildfile: build.xml does not exist!
          Build failed

          ant可以正常運(yùn)行,問(wèn)題解決了。

          這個(gè)小小的問(wèn)題前后用了我快一個(gè)小時(shí)的時(shí)間。但是最后真正發(fā)現(xiàn)并解決問(wèn)題的時(shí)間也不過(guò)十分鐘而已。看來(lái)還是太浮躁了。如果一開(kāi)始就用心去想,也不會(huì)有這么多的浪費(fèi)。想想,為什么那后面會(huì)多一個(gè)\,其實(shí)也很簡(jiǎn)單,從WINDOWS的地址欄直接拷貝的咯。Windows啊......我知道不能怪Windows,但總要找個(gè)出氣桶,對(duì)不對(duì)?

          自以為用了幾年JAVA已經(jīng)挺熟了,沒(méi)想到差點(diǎn)栽到最低級(jí)的失誤里了。反省反省。。。。。。

          posted @ 2006-05-29 07:28 shaofan 閱讀(2595) | 評(píng)論 (3)編輯 收藏

          Sun 的Java EE 5終于發(fā)布了(上一版本稱(chēng)作J2EE)!這一版本可說(shuō)是萬(wàn)眾矚目了,目前在SUN的站點(diǎn)上已經(jīng)提供下載。值得關(guān)注的特點(diǎn)是:

          "第一個(gè)商業(yè)的,比較完善的Java EE 5 實(shí)現(xiàn)

          簡(jiǎn)化開(kāi)發(fā)--對(duì)編程模式的重新組織
          支持EJB3.0--POJO
          支持Java Persistence API , ORM更簡(jiǎn)單
          JAX-WS 2.0 以及 JAXB 2.0 使得開(kāi)發(fā)web services 以及SOA應(yīng)用更加便捷
          JavaServer Faces 1.2--更簡(jiǎn)易開(kāi)發(fā)AJAX
          效率更高, 同時(shí)管理和部署功能更強(qiáng)大
          啟動(dòng)速度提高30%, 占用內(nèi)存減少30%.
          web services 效率提高至少5倍.
          web services 管理更強(qiáng)大
          整合了NetBeans以及支持Eclipse plug-in
          提供了整合NetBeans的可視化的SOA 開(kāi)發(fā)以及部署
          Sun's Java System Application Server PE 9.0是完全開(kāi)源的"

          ???????????????????????????????????????????????? ----摘自www.Matrix.org.cn

          它的結(jié)構(gòu)如下圖:


          Matrix上的相關(guān)文章:http://www.matrix.org.cn/resource/news/728_SUN+JavaEE5+SDK.html
          SUN網(wǎng)站上的下載地址:http://java.sun.com/javaee/downloads/index.jsp

          posted @ 2006-05-17 08:04 shaofan 閱讀(685) | 評(píng)論 (0)編輯 收藏

          Google好用嗎?大概很多人會(huì)說(shuō)"Yes"。

          但是老外Don Norman去從另一個(gè)角度說(shuō)明,Google的易用性只是一個(gè)假象。因?yàn)樗闹黜?yè)只放一個(gè)搜索框,要想使用Google的其他服務(wù),比如Google Map, Google Earth,卻要經(jīng)過(guò)很多次不同的點(diǎn)擊,給用戶造成很大的不便。相比之下,其他的比如Yahoo,MSN,大家認(rèn)為它們復(fù)雜,但實(shí)際上從他們的主頁(yè)訪問(wèn)他們提供的各種服務(wù)都很方便。

          要我說(shuō),就一個(gè)字:贊成。兩個(gè)字:非常贊成!

          全文請(qǐng)見(jiàn):

          英文原文:The truth about Google's so-called "simplicity" ? by Don Norman
          中文譯文:關(guān)于 Google 界面所謂的“簡(jiǎn)潔性”的真實(shí)情況? 翻譯:張亮

          posted @ 2006-05-14 06:24 shaofan 閱讀(511) | 評(píng)論 (0)編輯 收藏

          些天,不記得是用SOHU的郵箱注冊(cè)了哪個(gè)網(wǎng)站了,現(xiàn)在每天都收到大量的垃圾郵件。不知道別人怎么樣,反正我覺(jué)得SOHU的閃電郵件的反垃圾郵件功能基本是個(gè)擺設(shè)。而它的“垃圾郵件舉報(bào)”的功能似乎也沒(méi)什么作用。相比YAHOO和GOOGLE,這兩位業(yè)界大佬提供的郵箱的反垃圾能力則明顯要高一籌。

          我也常用YAHOO的郵箱來(lái)注冊(cè)網(wǎng)站BBS,它對(duì)垃圾郵件的識(shí)別率相當(dāng)高,我收到的大部分垃圾郵件它都可以準(zhǔn)確識(shí)別。此外,YAHOO還提供了“替身郵”的功能,就是可以注冊(cè)一堆虛擬的郵件地址,每個(gè)地址其實(shí)都是指向你原來(lái)的那個(gè)。用這些替身地址去注冊(cè)網(wǎng)站或者留言什么的,所有發(fā)到它的郵件都會(huì)自動(dòng)到達(dá)原來(lái)的郵箱。以后從這個(gè)地址來(lái)的垃圾郵件多了,就可以把這個(gè)替身地址刪掉,就再也不會(huì)收到從它發(fā)來(lái)的垃圾了。

          這是個(gè)好想法。以前我所想到的方法是,注冊(cè)一個(gè)郵箱,專(zhuān)門(mén)用來(lái)在注冊(cè)網(wǎng)站用。然后給它設(shè)置自動(dòng)轉(zhuǎn)發(fā),把郵件轉(zhuǎn)到我原來(lái)的郵箱地址。替身郵和這個(gè)想法真有異曲同工之妙。但是替身郵有個(gè)缺點(diǎn),一旦把替身地址刪掉,那些有用的郵件也收不到了。我所希望的是,能為這些替身地址增加“白名單”的功能,只收指定地址寄來(lái)的郵件。如果是這樣,那就完美了。

          另外,SOHU閃電郵件的“自動(dòng)轉(zhuǎn)發(fā)”居然不起作用?開(kāi)了好幾天了,一封都沒(méi)轉(zhuǎn)發(fā)過(guò),真是狂暈!!

          posted @ 2006-05-03 18:22 shaofan 閱讀(652) | 評(píng)論 (1)編輯 收藏

          兩周休假,不更新咯!休息一下!

          posted @ 2006-03-20 10:30 shaofan 閱讀(339) | 評(píng)論 (0)編輯 收藏

               摘要: 最近Business 2.0雜志發(fā)表了一篇文章,名為"Next net 25",介紹了五類(lèi)25家新銳網(wǎng)站。它們大多為web2.0網(wǎng)站,它們的發(fā)展正體現(xiàn)了當(dāng)今互聯(lián)網(wǎng)的動(dòng)向。有人敏銳地認(rèn)識(shí)到了這篇文章的特別之處,并把它和 94年的狀況進(jìn)行了對(duì)比。認(rèn)為web2.0開(kāi)始從少數(shù)人面前跳上了大眾舞臺(tái),而目前主流媒體也開(kāi)始注意并認(rèn)可這類(lèi)站點(diǎn)和服務(wù)了。  閱讀全文

          posted @ 2006-03-13 08:13 shaofan 閱讀(1701) | 評(píng)論 (3)編輯 收藏

          本文譯自Joel on Software,同時(shí)發(fā)表在其wiki上。關(guān)于作者本人,請(qǐng)看這里。由于Joel對(duì)于他人對(duì)其作品的轉(zhuǎn)載有較嚴(yán)限制,轉(zhuǎn)載及引用者請(qǐng)參閱其聲明:Linking, Quotation, and Reprinting。這是我翻譯的第一篇文章,有些地方我也不是很肯定,請(qǐng)多多指正!

          (第一稿)


          在飛機(jī)控制的設(shè)計(jì)中,糟糕的可用性會(huì)致使飛機(jī)發(fā)生CFIT:可控飛行撞地

          可能可用性在你的產(chǎn)品中不是那么關(guān)鍵。如果幸運(yùn)的話,你在可用性設(shè)計(jì)中的錯(cuò)誤可能只會(huì)使人失去四肢,或甚至只是拇指。沒(méi)什么更糟的了。

          事實(shí)上,如果極端幸運(yùn),那么糟糕的可用性設(shè)計(jì)除了會(huì)使人難受,沒(méi)有其他后果。用戶試著去做一些事情,或者失敗,或者掙扎著去用,很直接的后果就是他們會(huì)為此感到不悅。在將來(lái)的文章里,我會(huì)講講此事在心理上的原因,但現(xiàn)在,這樣說(shuō)就足夠了:使用戶不悅的原因,很可能并非完全如你所想。

          可用性,確實(shí)是一個(gè)“好”設(shè)計(jì)的核心。在將來(lái),我會(huì)花很多時(shí)間來(lái)講述這個(gè)問(wèn)題。

          好消息是:我可以很輕松地教你關(guān)于可用性設(shè)計(jì)的話題。讓我們開(kāi)始吧:

          當(dāng)一件東西能夠以被期待的方式運(yùn)行,那它就是易用的。

          就是這樣!這就是關(guān)于可用性的一切!像Hillel所說(shuō),其它的一切都是解說(shuō)詞。

          讓我們來(lái)看一個(gè)簡(jiǎn)單的例子。


          哪個(gè)更好用:Windows還是Mac?


          在為人們?cè)O(shè)計(jì)產(chǎn)品時(shí),有一個(gè)假想用戶是很有幫助的。所設(shè)想的用戶越是實(shí)際,提供的幫助越大。

          我的假想用戶就是彼特。

          有一天,彼特的朋友,吉娜叫他來(lái)幫忙。吉娜有一臺(tái)Macintosh的iBook,因?yàn)樗矚g白色的電腦。當(dāng)彼特坐下開(kāi)始試著用吉娜的Macintosh時(shí),他很快就感到有點(diǎn)沮喪了。“我討厭這些東西,”他說(shuō)。雖然最后成功地幫吉娜解決了問(wèn)題,他卻覺(jué)得高興不起來(lái)。“Macintosh的用戶界面真是笨拙至極。”

          笨拙?為什么會(huì)這樣說(shuō)呢?每個(gè)人都知道,Macintosh有著優(yōu)雅易用的用戶界面,對(duì)不對(duì)?難道它不是那種易用性的范例嗎?

          好吧。讓我們來(lái)看看。

          在Macintosh上,如果你想改變窗口的大小,你必須拖它的右下角。而在Windows上,在任何一個(gè)邊上拖動(dòng)鼠標(biāo),都可以改變窗口大小。當(dāng)彼特幫吉娜時(shí),他試著拖右側(cè)的邊來(lái)讓窗口變寬。結(jié)果,整個(gè)窗口都跟著動(dòng)了,而不是他想要的“改變大小”。

          在Windows上,當(dāng)出現(xiàn)一個(gè)消息框時(shí),你只要按tab鍵移動(dòng)焦點(diǎn)到所需的按鈕上,然后按一下空格鍵就可以按到那個(gè)按鈕。但在Mac上,空格鍵不起那樣的作用。當(dāng)彼特得到一個(gè)警告,他就試著像他過(guò)去六年里下意識(shí)的做的那樣,按空格鍵來(lái)關(guān)掉消息框。第一次,機(jī)器沒(méi)有任何反應(yīng),他以為是鍵盤(pán)有問(wèn)題,于是更大力地又按了一次。結(jié)果還是一樣。最后他只能用鼠標(biāo)了。這是另一個(gè)小小的挫折。

          彼特還習(xí)慣用Alt+F4來(lái)關(guān)閉窗口。在Mac上,這恰恰是用來(lái)調(diào)整聲音音量的。這次,彼特想點(diǎn)擊桌面上的IE圖標(biāo),而這個(gè)圖標(biāo)剛好被另一個(gè)窗口遮住了一部份。于是他按Alt+F4關(guān)閉窗口的同時(shí)立即雙擊圖標(biāo)所在的位置。結(jié)果是聲音音量變大了,而窗口并未被關(guān)掉。而他的雙擊點(diǎn)在了他想關(guān)掉的那個(gè)窗口的幫助按鈕上,把幫助窗口打開(kāi)了。好了,他現(xiàn)在需要關(guān)閉兩個(gè)窗口了。

          這也是一個(gè)小小的挫折吧,但是,這確實(shí)讓彼特更加郁悶了。這天結(jié)束的時(shí)候,彼特的脾氣很不好。他試著控制那些東西,卻都沒(méi)有反應(yīng)。空格鍵和Alt+F4都“不起作用”----就像它們壞了一樣。窗口也不聽(tīng)話,連調(diào)整大小都不行。真差勁。就算這些想法都是下意識(shí)的,這些“失去控制”的細(xì)微感受也最終使他感到不快。“我還是喜歡我自己的電腦”,彼特想,“它被我設(shè)置的完美無(wú)缺,總能按照我想的方式去運(yùn)行。而這些Mac真是難用。真是讓人不爽。如果Apple這些年多花些心思在MacOS上,而不是搞iPod那些那些玩意,他們的操作系統(tǒng)也不會(huì)這么糟糕了。”

          好了。我們比彼特清楚。他雖然有這些種種感受,但事實(shí)上對(duì)Mac用戶來(lái)說(shuō),Mac確實(shí)很好用。完全可以用任意鍵來(lái)關(guān)閉窗口。微軟的程序員很可能覺(jué)得,讓用戶拖動(dòng)任意邊都可以調(diào)整窗口大小的功能真的很不錯(cuò)。而Apple程序員很可能認(rèn)為,拖動(dòng)任意邊來(lái)移動(dòng)窗口位置的功能很有創(chuàng)意。

          那些盲目信仰某種OS的網(wǎng)站上的關(guān)于用戶界面的爭(zhēng)論,都沒(méi)有說(shuō)到點(diǎn)子上。Windows更好,是因?yàn)榻o你更多手段來(lái)調(diào)整窗口大小。那又怎樣?這并不是問(wèn)題所在。真正的問(wèn)題是,UI是否以用戶預(yù)期的方式來(lái)響應(yīng)他們的操作。如果不是,那么用戶就會(huì)覺(jué)得他們無(wú)法控制它,并覺(jué)得自己會(huì)難以達(dá)成目的。就是這樣了。當(dāng)一件東西能夠以被期待的方式運(yùn)行,那它就是易用的。你可以把這句話反著紋在你的額頭上,這樣你在鏡子里就可以看到它。

          如果你繼續(xù)關(guān)注將來(lái)的文章,那么你會(huì)發(fā)現(xiàn),我所告訴你的關(guān)于可用性設(shè)計(jì)的一切,都可以追溯到這個(gè)簡(jiǎn)單的法則。如果哪天外星人在你的花園里著陸,把你扔到了名叫Kij8zxwrk的星球,在那里你無(wú)法連接到地球的互聯(lián)網(wǎng),因?yàn)閿?shù)據(jù)包傳送到地球所花時(shí)間太長(zhǎng)導(dǎo)致TCP/IP無(wú)法正常工作,那么你所知道的東西也足以讓你找到一份相當(dāng)體面的可用性設(shè)計(jì)師的工作了。

          posted @ 2006-03-10 06:39 shaofan 閱讀(1855) | 評(píng)論 (5)編輯 收藏

          我有一個(gè)習(xí)慣,每次學(xué)門(mén)語(yǔ)言,總要自己寫(xiě)個(gè)List或Stack并加上Unit Test來(lái)試試。這次對(duì)Python也不例外。總體感覺(jué)有以下幾點(diǎn)

          1.這是我用過(guò)的唯一一個(gè)把代碼行的縮進(jìn)也做為語(yǔ)法的語(yǔ)言,就因?yàn)椴徽_的縮進(jìn),我的第一個(gè)Python程序讓我吃盡了苦頭。事情是這樣的,我運(yùn)行測(cè)試時(shí),報(bào)告每次都說(shuō)"Ran 0 test in 0.000s",找了半天,也找不出為什么只運(yùn)行了0個(gè)測(cè)試,一直以為是unittest包的用法有問(wèn)題,或我的語(yǔ)法有問(wèn)題,直到花了大半個(gè)小時(shí)翻書(shū),又對(duì)比其他的測(cè)試程序以后,才發(fā)現(xiàn),天啊,原來(lái)是因?yàn)樽詈笠恍械目s進(jìn)多縮了一層,被認(rèn)為與上一個(gè)方法同一個(gè)block。

          2.雖然在縮進(jìn)上吃了苦頭,但是代碼看起來(lái)確實(shí)相當(dāng)整潔清楚,感覺(jué)比java的動(dòng)不動(dòng)一堆大括號(hào)相比,實(shí)在多了。

          3.Python的每個(gè)module(可以看作與java的包類(lèi)似)都可以包含方法和類(lèi),而java的所有方法都要寫(xiě)在類(lèi)里,包里只有類(lèi),這點(diǎn)相當(dāng)不同。

          4.因?yàn)镻ython是用c實(shí)現(xiàn)的,它的命名比較簡(jiǎn)單,使用很多縮寫(xiě),與java的長(zhǎng)長(zhǎng)一串的命名是很強(qiáng)烈的對(duì)比

          5.Python是動(dòng)態(tài)類(lèi)型的語(yǔ)言,變量不需聲明類(lèi)型可以直接使用,雖然方便,但缺點(diǎn)也很明顯,那就是變量的類(lèi)型信息不見(jiàn)了,經(jīng)常搞不清楚方法的參數(shù)要傳入什么,返回什么,挺不習(xí)慣的。

          6.就因?yàn)槿鄙兕?lèi)型信息,Python的文檔也沒(méi)有Java的可讀性強(qiáng)。比如java的 String foo(int a)一看就知道傳入整形返回字符串,換成Python就變成了 foo(a),只能讀文檔才能搞清楚了。可能我還沒(méi)習(xí)慣的原因吧,感覺(jué)有時(shí)文檔對(duì)它們的類(lèi)型也說(shuō)的不太清楚。

          總體感覺(jué)Python一些風(fēng)格像C。寫(xiě)起代碼來(lái),感覺(jué)很快,很清楚,還是很不錯(cuò)的 I love the feeling :)


          看看我寫(xiě)的Stack

          posted @ 2006-03-09 20:31 shaofan 閱讀(1044) | 評(píng)論 (0)編輯 收藏

               摘要: 過(guò)去的一年,Mustang 沒(méi)能出來(lái),EJB3剛剛才提交最終草案,Ajax興起但是五花八門(mén)不知道應(yīng)該用誰(shuí),Aspectj 5出來(lái)了,但是缺乏驚喜。
          或許我們會(huì)說(shuō),過(guò)去的2005,Java界缺乏成績(jī),但是卻毫無(wú)疑問(wèn),Java遙遙領(lǐng)先于其他語(yǔ)言。從11月的語(yǔ)言排行榜Java遙遙領(lǐng)先,到今年的Java圖書(shū)銷(xiāo)售統(tǒng)計(jì)上,Java圖書(shū)銷(xiāo)售總數(shù)是C#的2倍,PHP的2.5倍,Perl的4倍,Ruby/Python的9倍.
          這足以讓我們對(duì)2006充滿想象。
          不過(guò),還是讓我們先回顧下2005吧....  閱讀全文

          posted @ 2006-03-07 09:56 shaofan 閱讀(501) | 評(píng)論 (0)編輯 收藏

               摘要: 總感覺(jué)只會(huì)JAVA似乎不夠,不記得是哪位先人說(shuō)的了,一個(gè)程序員起碼要精通兩門(mén)語(yǔ)言,所以這些天花了不少時(shí)間琢磨python,看了不少網(wǎng)站,查了不少資料,正想著把一些東西寫(xiě)下來(lái),以免日后忘了,也可以和大家分享.先寫(xiě)一些下載安裝和學(xué)習(xí)資源的東東.  閱讀全文

          posted @ 2006-03-05 09:30 shaofan 閱讀(5366) | 評(píng)論 (7)編輯 收藏

               摘要: Design by Contract (DbC)的概念已經(jīng)出現(xiàn)很長(zhǎng)時(shí)間了,最先是在Eiffel的一個(gè)特色,通過(guò)DbC來(lái)提高軟件質(zhì)量,目前很多語(yǔ)言也都有相應(yīng)的實(shí)現(xiàn),但是在GOOGLE上搜索中文網(wǎng)頁(yè),得到的資源并不是很多.直覺(jué)上來(lái)說(shuō),DbC確實(shí)是一個(gè)很好的想法,本著拓寬眼界的原則,就簡(jiǎn)單了解一下吧.  閱讀全文

          posted @ 2006-03-02 00:55 shaofan 閱讀(2070) | 評(píng)論 (4)編輯 收藏

          主站蜘蛛池模板: 拜泉县| 德令哈市| 安康市| 赞皇县| 广丰县| 民权县| 甘孜县| 仁布县| 广宗县| 托里县| 保亭| 昌江| 梁平县| 中山市| 高唐县| 汤原县| 唐河县| 松江区| 赤水市| 新民市| 乐业县| 铁岭市| 洱源县| 沾化县| 蒙山县| 镶黄旗| 安阳县| 新平| 绩溪县| 宜宾县| 盈江县| 甘德县| 大港区| 杭州市| 上栗县| 胶州市| 胶南市| 丰台区| 泽普县| 德昌县| 宁海县|