<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 193,  comments - 520,  trackbacks - 0
     

    原文地址:http://www.tkk7.com/RongHao/archive/2007/10/30/157009.html

    對于當(dāng)前的工作流應(yīng)用來說,人工節(jié)點無疑扮演著一個非常重要的角色。因為無論是傳統(tǒng)的協(xié)同辦公系統(tǒng)還是越來越多的企業(yè)應(yīng)用,都需要有人參與到具體的流程中來。這篇文章著重分析工作流應(yīng)用中人工節(jié)點所涉及到的參與者模式以及與此關(guān)聯(lián)的工作項模式,最后會提供部分的解決方案作為參考。

    先簡單說說什么是人工節(jié)點。

    人工節(jié)點的概念是與自動節(jié)點相對的。顧名思義,人工節(jié)點就是需要有人參與的節(jié)點,在實際流程中,它體現(xiàn)在產(chǎn)生由人完成的工作項以及由人決定一些決策變量,這些決策變量會對流程的運行產(chǎn)生影響(例如分支的選擇等等)。自動節(jié)點則是由工作流引擎自己調(diào)用完成,不需要人的參與,通常是執(zhí)行定制的業(yè)務(wù)操作。相比較而言,人工節(jié)點更多的應(yīng)用在管理流程里,而自動節(jié)點更多的則是應(yīng)用在企業(yè)業(yè)務(wù)流程里。

    人工節(jié)點的職責(zé)有三個:第一是決定該節(jié)點的參與者;第二是根據(jù)參與者生成需要人來處理的工作項;最后是當(dāng)工作項被參與者處理完畢時,它將繼續(xù)觸發(fā)流程的流轉(zhuǎn)。參與者處理工作項時可以處理相應(yīng)的業(yè)務(wù)和設(shè)置流程決策變量。

    下面我們就按照這三個職責(zé)分別對人工節(jié)點所涉及到的參與者模式和工作項模式進(jìn)行分析。

    1、  決定參與者模式

    換句話說就是決定該節(jié)點的參與者,這里有兩種模式:引擎自動獲取和最終用戶指定。
     

    11引擎自動獲取

    所謂引擎自動獲取就是由引擎在運行期計算實際的節(jié)點參與者,不需要最終用戶的參與。這個計算基于流程定義時對該節(jié)點參與者的定義。

    (1)    直接指定人員、部門或角色

    這種情況最簡單,也最直接,用戶定義節(jié)點時直接在組織用戶樹里選定人員、部門或角色,然后在運行期根據(jù)定義執(zhí)行與或者是或的運算。大多數(shù)的工作流引擎都支持這種模式。但很明顯它也存在著很大的局限性,它是靜態(tài)的,一旦流程定義完畢參與者也就跟著固定下來,運行期的任何變化都不會對參與者造成影響,一個很簡單的需求,請假流程,節(jié)點的參與者需要是當(dāng)前申請者的部門領(lǐng)導(dǎo),因為申請者在定義期是不確定的,所以根本無法指定節(jié)點的參與者,所以這種模式遠(yuǎn)遠(yuǎn)滿足不了用戶稍微復(fù)雜一點的需求。

    (2)    調(diào)用用戶定制的計算參與者代碼

    這種情況通常是由引擎提供一個接口或是父類,用戶需要實現(xiàn)或是繼承這個接口或父類,然后實現(xiàn)相應(yīng)的方法。這個方法通常會傳遞進(jìn)一個執(zhí)行上下文的參數(shù),用戶代碼通過這個上下文可以訪問到當(dāng)前流程實例的信息,例如當(dāng)前節(jié)點狀態(tài),工作流變量等等,然后用戶可以根據(jù)實際業(yè)務(wù)和當(dāng)前流程實例信息進(jìn)行邏輯計算,最后返回一個參與者的ID集合。對于上一個模式里提到的計算當(dāng)前申請者部門領(lǐng)導(dǎo)的例子,這個模式實現(xiàn)起來非常簡單,首先獲得當(dāng)前申請者ID,然后在根據(jù)這個ID找出該申請者部門再找出該部門領(lǐng)導(dǎo)即可。

    實際流程運行到該節(jié)點就會調(diào)用用戶自己定制的計算參與者的代碼,方法返回的參與者ID即作為該節(jié)點的實際參與者。

    這種模式對于工作流引擎的實現(xiàn)而言最為簡單,因為它把最大的復(fù)雜性都拋給了用戶,由用戶代碼來計算實際的參與者。實際上很多開源的工作流引擎采用的都是這種方式,例如JBPM。但是這種方式給用戶帶來最大靈活性的同時也帶來了復(fù)雜和煩瑣。特別是當(dāng)面對一個數(shù)量巨大的流程需求時,為每一個流程的每一個人工節(jié)點都定義一個參與者計算類是讓人頭疼的。再加上現(xiàn)在強調(diào)業(yè)務(wù)的敏捷,業(yè)務(wù)里的改變要迅速反饋到流程的定義里,讓最終用戶來編寫或修改這個參與者計算類不現(xiàn)實也不可能。補充一下,這也是用戶在考慮采用開源的工作流引擎還是商業(yè)工作流引擎時需要著重考慮的一個方面。

    (3)    指定前續(xù)節(jié)點的參與者

    實際上是用戶在節(jié)點定義時指定參與者為前續(xù)某個節(jié)點的參與者,當(dāng)流程運行到該節(jié)點,引擎會自動獲取所指定的前續(xù)節(jié)點的參與者作為該節(jié)點的實際參與者。

    這個模式實現(xiàn)起來并不困難,大多數(shù)商業(yè)工作流引擎都對該模式進(jìn)行了支持。它能夠滿足用戶的部分特定需求。

    (4)    更為復(fù)雜的情況

    用戶的需求永遠(yuǎn)是復(fù)雜的,引擎所要做得就是盡量降低這種復(fù)雜性,流程的變化要能夠迅速跟上業(yè)務(wù)的變化。考慮下面兩種稍微復(fù)雜一點但是又很常見的需求。需求一:參與者為當(dāng)前申請者的部門領(lǐng)導(dǎo)且職位為副總;需求二:參與者需要是測試部的所有女同事。這兩種需求模式13都不能滿足,2可以,但是正如提到的那樣,模式2可能會非常的煩瑣,不能適應(yīng)業(yè)務(wù)的敏捷。其實這里的復(fù)雜性主要體現(xiàn)在:1、這里的參與者可能是運行期決定的;2、參與者的限制條件可能非常多,而這些條件不是簡單的部門、角色或職位所能描述的。

    對于一般的工作流引擎而言,它們都會選擇模式2的實現(xiàn),讓用戶自己實現(xiàn)邏輯。實際在后面的部分解決方案里,我們會看到更為好一點的實現(xiàn)方式。

     

    1.2最終用戶指定

       運行期由最終用戶來決定節(jié)點的參與者。這也是中國國情所獨有的特色。這種模式最為常見的就是用戶提交工作項時的提交頁面,用戶在該頁面上選定下一節(jié)點(多數(shù)分支用戶選定時)和下一節(jié)點的參與者。這種模式本身并不困難,問題在于在提交頁面需要給用戶提供一個參與者的選擇范圍,讓用戶進(jìn)行選擇。而關(guān)于這個選擇范圍,則又回到前面所提到的引擎自動獲取的模式,這個范圍同樣是需要引擎計算的。于是又回到了剛剛討論過的四種模式。

     

    2、參與者執(zhí)行模式

       現(xiàn)在,已經(jīng)獲得了節(jié)點的參與者。引擎下一步將會根據(jù)這個參與者生成工作項,注意,這里的參與者可能是一個人,也可能會是一個人員范圍(即多個人)。于是就產(chǎn)生了參與者的執(zhí)行模式,也可以理解為工作項的生成模式。

    2.1競爭參與

    當(dāng)有多個參與者參與這個節(jié)點時就會產(chǎn)生競爭參與這個模式。同樣一個工作,A可以完成,B也可以完成,于是就產(chǎn)生競爭,誰先開始這項工作,就由誰負(fù)責(zé)完成該工作。

    2.2順序參與

       多個參與者按照指定的順序完成該工作項。A完成之后由B完成,B完成之后再交給C完成。

    2.3同時參與

       多個參與者同時對工作進(jìn)行處理,所有參與者均完成后,流程繼續(xù)向后流轉(zhuǎn)。這個模式其實比較復(fù)雜,因為這里同時涉及到一個完成規(guī)則:是所有參與者均完成工作項后流程流轉(zhuǎn),還是有其他規(guī)則?例如完成2個工作項即可流轉(zhuǎn),完成80%的工作項即可流轉(zhuǎn)。稍候會討論到。

    2.4負(fù)載均衡

       這也是一個常見的需求。這項工作AB都可以完成,但是A目前有10個待辦工作項,B只有2個待辦工作項。于是用戶期望該工作交由B來完成。這里需要實現(xiàn)一個簡單的負(fù)載均衡。其實這種情況只是智能決策的一種最簡單的情況,所謂智能決策是指系統(tǒng)能夠根據(jù)一定的指標(biāo)(由數(shù)據(jù)分析,例如人員的處理效率,工作負(fù)載等等)和規(guī)則來決定該節(jié)點的參與者。

    3、工作項完成模式

    這個模式在參與者執(zhí)行模式為同時參與時有效。在說到這個模式之前,先簡單說說工作項可能存在的幾種特殊狀態(tài),這些狀態(tài)包括掛起、人工終止和委派。掛起就是工作項暫時停止執(zhí)行,掛起會影響到流程的流轉(zhuǎn),會導(dǎo)致流程的掛起。人工終止則是人工手動改變該工作項的狀態(tài),使該工作項終止執(zhí)行,這個人通常會是管理員。人工終止也會對流程流轉(zhuǎn)產(chǎn)生影響,當(dāng)除去該工作項之外的所有工作項都完成時,人工終止該工作項會觸發(fā)流程的流轉(zhuǎn)。委派就是將該工作項委派給他人完成,同時該工作項也就結(jié)束了。人工終止和委派是工作項結(jié)束的特殊狀態(tài)。
     

    3.1全部完成

    當(dāng)所有工作項都結(jié)束時觸發(fā)節(jié)點的結(jié)束和流程的流轉(zhuǎn)。

    3.2完成規(guī)定的個數(shù)

    節(jié)點定義時指定工作項必須完成的個數(shù),當(dāng)完成的工作項達(dá)到這個指定的個數(shù)時觸發(fā)節(jié)點的結(jié)束和流程的流轉(zhuǎn)。 

    3.3完成規(guī)定的百分比

    節(jié)點定義時指定工作項必須完成的百分比,當(dāng)完成的工作項占所有工作項的比例達(dá)到這個指定的百分比時觸發(fā)節(jié)點的結(jié)束和流程的流轉(zhuǎn)。
     

    其實這里很明顯的可以看出不管是所謂的參與者執(zhí)行模式還是工作項完成模式不過都是一定的規(guī)則,既然是一定的規(guī)則那必然就限定了應(yīng)用的靈活性,用戶能否自定義規(guī)則?根據(jù)業(yè)務(wù)靈活地修改規(guī)則?規(guī)則引擎+DSL應(yīng)該是一個不錯的選擇。

    posted @ 2007-10-30 18:06 ronghao 閱讀(3670) | 評論 (3)編輯 收藏
    周末參加了清華大學(xué)信息系統(tǒng)與工程研究所組織的一次工作流研討會。
    會上清華大學(xué)的研究人員介紹了他們對工作流研究的一些成果。其中主要關(guān)注了數(shù)據(jù)挖掘和分析。
    關(guān)于數(shù)據(jù)挖掘,有兩個方面。第一個方面是當(dāng)企業(yè)沒有應(yīng)用工作流時,對企業(yè)日常數(shù)據(jù)進(jìn)行挖掘,分析數(shù)據(jù)
    之間的關(guān)聯(lián)和邏輯,得出一套基本的企業(yè)應(yīng)用業(yè)務(wù)流程,為將來應(yīng)用工作流做出準(zhǔn)備;第二個方面是當(dāng)企業(yè)
    已有工作流應(yīng)用時,對相關(guān)流程數(shù)據(jù)進(jìn)行挖掘,根據(jù)數(shù)據(jù)描繪出正在運行的流程,很顯然,這個方面與流程
    仿真有關(guān)。
    關(guān)于數(shù)據(jù)分析,則主要是對流程數(shù)據(jù)進(jìn)行分析,這個涉及的內(nèi)容就比較多,包括流程的運行效率,人員效率
    分析,統(tǒng)計等等。其中有一個非常有趣的例子:貪官A試圖逃跑,逃跑前是有一定前兆的,比如向國外轉(zhuǎn)移
    賬款,給小蜜頻繁打電話,工作效率降低等等。于是數(shù)據(jù)分析就可以起作用,對A最近的所有數(shù)據(jù)進(jìn)行分析,
    得出他將要逃跑的結(jié)論。而來自有生博大的趙斌,談?wù)摰剿麄円呀?jīng)實施的項目中,涉及到對一些電子公文
    流程中的辦文統(tǒng)計,并依據(jù)“指標(biāo)”進(jìn)行工作量和效率的分析。
    這其實也反映出我們工作流軟件中缺失的部分:數(shù)據(jù)分析-數(shù)據(jù)統(tǒng)計-優(yōu)化流程。而這也正是BPM的重要功能之一。也是未來發(fā)展的趨勢。功能缺失最重要的原因在于實際上我們的軟件沒有研發(fā)只有開發(fā)。具體他們略微談到了他們一些實現(xiàn)的方式,非常的理論,涉及到算法,數(shù)據(jù)結(jié)構(gòu)等等。我們軟件開發(fā)最主要的是滿足用戶的各種業(yè)務(wù)需求,比如說回退、收回、會簽等等,這也是現(xiàn)實情況所決定的,開發(fā)團(tuán)隊的人員通常都不是很多,并且這種分析挖掘需要的人員無疑需要很高的理論水準(zhǔn),這個本科往往是達(dá)不到的(不得不承認(rèn)研究生和博士就是比本科要優(yōu)秀),博士碩士的研發(fā)團(tuán)隊的開發(fā)成本會非常的高,并且實際產(chǎn)生的利潤很難評價,對于不大的公司來講這個是很難接受的。于是就造成了這種狀況:軟件研發(fā)缺失掉了。
    依托高校是個不錯的想法,但是依托高校不等于說你把辦公地點搬到清華大學(xué)門口就是依托高校了,也有這種依托,那是買煎餅的。
    posted @ 2007-10-29 11:57 ronghao 閱讀(1429) | 評論 (6)編輯 收藏
    問題背景:我們是一家工作流公司,客戶采購我們的產(chǎn)品后,將其嵌入其項目中。我們的工作流采用的是   spring+hibernate的方式,客戶項目則是jdbc直接進(jìn)行數(shù)據(jù)庫操作。
    問題:客戶在其數(shù)據(jù)庫操作過程中需要調(diào)用我們的工作流接口,這樣就需要將我們的工作流操作與他們的業(yè)  務(wù)操作置于同一個事務(wù)中。我們的服務(wù)采用的都是spring的聲明式事務(wù),而客戶采用的是對         connection進(jìn)行事務(wù)處理。如何保證事務(wù)的一致性?
    想到的解決方案一:使用jta事務(wù),用tomcat+jotm提供事務(wù)管理器。為什么一開始就想到要使用jta事務(wù)??實際上我們和客戶都是使用的同一個數(shù)據(jù)庫,為了方便,各自使用了不同的數(shù)據(jù)庫連接方式,使用jta的話確實有bt的意思在里面。但是事實上是我們的第一反應(yīng)都是jta。最后沒有采用該方法的原因也很簡單:我沒有將jotm配置成功!汗一個。
    想到的解決方案二:將客戶的這些特定代碼用spring管理起來。因為要修改客戶部分代碼,這個方案遭到了客戶的強烈反對。于是放棄。
    想到的解決方案三:客戶數(shù)據(jù)庫操作與我們的服務(wù)使用同一個數(shù)據(jù)庫連接。然后編程處理事務(wù)。存在兩種方式:一種是把客戶的連接傳給我們,另一種則是把我們的連接傳給客戶。第一種方式對我們的影響太大,所以最后決定采用后一種方式:從hibernate session中獲取connection然后傳遞給客戶。接下來查看一下HibernateTemplate的execute()方法,思路就很簡單了:獲取定義的sessionFactory-->創(chuàng)建一個新的session并打開-->將session與當(dāng)前線程綁定-->給客戶代碼返回connection-->打開事務(wù)-->客戶使用我們傳遞的connection進(jìn)行數(shù)據(jù)庫操作-->我們不帶聲明事務(wù)的服務(wù)操作-->提交事務(wù)-->解除綁定。
    實際要注意的地方是:1、將session與當(dāng)前線程綁定使用的TransactionSynchronizationManager.bindResource()方法,這樣在HibernateTemplate里才能找到session;
                        2、我們的服務(wù)一定要把聲明式事務(wù)徹底干掉,否則會有commit;
                        3、我們服務(wù)調(diào)用完畢后一定要flush session,否則客戶代碼不會感知數(shù)據(jù)庫里的數(shù)據(jù)變化。
    最終解決:使用了spring里常用的模板和回調(diào)。代碼如下:
    public class TransactionTemplate {

        
    protected final Log logger = LogFactory.getLog(TransactionTemplate.class);

        
    private FlushMode flushMode = FlushMode.ALWAYS;

        
    public Object execute(TransactionCallback callback) {
            
    //首先獲取sessionFactory
            SessionFactory sessionFactory = (SessionFactory) Framework.getEngine()
                    .getContainer().getComponent(
    "sessionFactory");
            
    //創(chuàng)建一個新的session并打開
            logger.debug("Opening single Hibernate Session in TransactionTemplate");
            Session session 
    = getSession(sessionFactory);
            
    //將session與當(dāng)前線程綁定
            TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
            
    //獲取數(shù)據(jù)庫連接
            Connection conn = session.connection();
            Object result 
    = null;
            Transaction transaction 
    = null;
            
    try {
                
    //開始處理事務(wù)
                transaction = session.beginTransaction();
                
    try {
                    result 
    = callback.doInTransaction(conn);
                }
                
    catch (RuntimeException ex) {
                    doRollback(session, transaction);
                    
    throw ex;
                }
                
    catch (Error err) {
                    doRollback(session, transaction);
                    
    throw err;
                }
                
    //如果數(shù)據(jù)庫操作過程中沒有發(fā)生異常則提交事務(wù)
                transaction.commit();
            } 
    catch (WorkflowException e) {
                logger.error(
    "數(shù)據(jù)庫操作失敗,事務(wù)回滾也失敗!");
                
    throw e;
            } 
    catch (RuntimeException ex) {
                logger.error(
    "數(shù)據(jù)庫操作失敗,事務(wù)被回滾!");
                
    throw ex;
            } 
    catch (Error err) {
                logger.error(
    "數(shù)據(jù)庫操作失敗,事務(wù)被回滾!");
                
    throw err;
            } 
    finally {
                
    // 將session與當(dāng)前線程解除綁定
                TransactionSynchronizationManager.unbindResource(sessionFactory);
                doClose(session);
            }
            
    return result;
        }

        
    protected Session getSession(SessionFactory sessionFactory) {
            Session session 
    = SessionFactoryUtils.getSession(sessionFactory, true);
            FlushMode flushMode 
    = getFlushMode();
            
    if (flushMode != null) {
                session.setFlushMode(flushMode);
            }
            
    return session;
        }

        
    private void doRollback(Session session, Transaction transaction) {
            logger.debug(
    "數(shù)據(jù)庫操作異常,開始回滾事務(wù)");
            
    try {
                transaction.rollback();
                logger.debug(
    "回滾事務(wù)成功!");
            }
            
    catch (Exception e) {
                logger.error(
    "回滾事務(wù)失敗!");
                
    throw new WorkflowException("回滾事務(wù)失敗!");
            } 
    finally {
                session.clear();
            }
        }

        
    private void doClose(Session session) {
            logger.debug(
    "開始關(guān)閉連接");
            
    try {
                session.close();
            }
            
    catch (Exception e) {
                logger.error(
    "關(guān)閉連接失敗!");
                
    throw new WorkflowException("關(guān)閉連接失敗!");
            }
        }

        
    public FlushMode getFlushMode() {
            
    return flushMode;
        }

        
    public void setFlushMode(FlushMode flushMode) {
            
    this.flushMode = flushMode;
        }
    }

    public interface TransactionCallback {

        Object doInTransaction(Connection conn);
    }
    調(diào)用偽代碼:
        public void methodA(){
            TransactionTemplate transactionTemplate
    =new TransactionTemplate();
            transactionTemplate.execute(
    new TransactionCallback(){
                
    public Object doInTransaction(Connection conn) {
                    
    //客戶代碼
                    client.method1("1");
                    
    //我們代碼 直接使用
                    our.method2();
                    
    //客戶代碼
                    client.method3("l");
                    
    return null;  
                }
            });
        }


    posted @ 2007-10-09 15:11 ronghao 閱讀(7742) | 評論 (5)編輯 收藏
    基于職責(zé)設(shè)計對象
    最關(guān)鍵的軟件開發(fā)工具是受過良好設(shè)計原則訓(xùn)練的思維,而不是UML或其他任何技術(shù)。

    RDD是思考OO軟件設(shè)計的一般性隱喻。把軟件對象想象成具有某種職責(zé)的人,他要與其他人協(xié)作以完成工作。RDD使我們把OO設(shè)計看作是有職責(zé)對象進(jìn)行協(xié)作的共同體。

    分配職責(zé)的基本模式是GRASP。

    創(chuàng)建者模式
      問題:誰創(chuàng)建類A的實例?
      建議:如果以下條件為真時(越多越好),將創(chuàng)建類A實例的職責(zé)分配給類B:
            1、B“包含”或組成聚集了A。
            2、B記錄A。
            3、B緊密的使用A。
            4、B具有A的初始化數(shù)據(jù)。
            首選聚集或包含A的類B。
      注意:A和B指的都是軟件對象而不是領(lǐng)域模型對象。
      禁忌:對象的創(chuàng)建常常具有相當(dāng)?shù)膹?fù)雜性。在一些情況下,更適合使用工廠。

    信息專家模式
      問題:給對象分配職責(zé)的基本原則是什么?
      建議:把職責(zé)分配給具有完成該職責(zé)所需信息的那個類。把職責(zé)和數(shù)據(jù)置于一處,把服務(wù)與其屬性置于一處。
      禁忌:相比較而言系統(tǒng)關(guān)注更為重要,設(shè)計要分離主要的系統(tǒng)關(guān)注。例如:領(lǐng)域?qū)ο蠹尤氤志没壿嫵蔀槌溲P停@就把應(yīng)用邏輯與數(shù)據(jù)庫邏輯混合起來了(不良設(shè)計)。

    低耦合模式
      問題:如何減少因變化產(chǎn)生的影響?(高耦合并不是問題所在,問題是與某些方面不穩(wěn)定的元素之間的高耦合)
      建議:分配職責(zé)以使(不必要的)耦合保持在較低的水平。(信息專家模式支持低耦合)

    控制器模式
      問題:在UI層之上首先接受和協(xié)調(diào)系統(tǒng)操作的對象是什么?
      建議:把職責(zé)分配給能代表下列選擇之一的對象:
            1、代表全部“系統(tǒng)”、“根對象”、運行軟件的設(shè)備或主要的子系統(tǒng)(外觀控制器的變體)。
            2、代表發(fā)送系統(tǒng)操作的用例場景(用例或會話控制器)。

    高內(nèi)聚模式
      問題:怎樣使對象保持有內(nèi)聚、可理解和可管理,同時具有支持低耦合的附加作用?
      建議:職責(zé)分配應(yīng)保持高內(nèi)聚。委派職責(zé)。內(nèi)聚性低的類通常表示大粒度的抽象,或承擔(dān)了本該委托給其他對象的職責(zé)。

    多態(tài)模式
      問題:如何處理基于類型的選擇?如何創(chuàng)建可插拔的軟件構(gòu)件?
      建議:當(dāng)相關(guān)選擇或行為隨類型(類)有所不同時,使用多態(tài)為變化的行為類型分配職責(zé)。不要測試對象的類型,也不要使用條件邏輯來執(zhí)行基于類型的不同選擇。
      經(jīng)驗:如果有一個具有抽象超類C1的類層次結(jié)構(gòu),可以考慮對應(yīng)于C1中的公共方法特征標(biāo)記來定義接口I1,然后聲明C1來實現(xiàn)接口I1。

    純虛構(gòu)模式
      問題:當(dāng)并不想違背高內(nèi)聚和低耦合或其他目標(biāo),但基于專家模式的方案又不合適時,哪些對象應(yīng)承擔(dān)這一職責(zé)?
      建議:人為制造類,由該類來承擔(dān)一組高內(nèi)聚的職責(zé)。該類并不代表問題領(lǐng)域的概念-是虛構(gòu)的事物。例如DAO
      純虛構(gòu)通常基于相關(guān)的功能性進(jìn)行劃分,因此這是一種以功能為中心的對象。

    間接性模式
      問題:為了避免兩個或多個事物之間的直接耦合,應(yīng)該如何分配職責(zé)?
      建議:將職責(zé)分配給中介對象。例如,Adapter
      間接性的動機通常是為了低耦合,并且大多數(shù)間接性中介都是純虛構(gòu)的。

    防止變異模式
      問題:如何設(shè)計對象、子系統(tǒng)和系統(tǒng),使其內(nèi)部的變化或不穩(wěn)定性不會對其他元素產(chǎn)生不良影響?
      建議:創(chuàng)建穩(wěn)定的接口。
      不要和陌生人講話:約束了應(yīng)該在方法里給哪些對象發(fā)送消息。它要求在方法里,只應(yīng)給以下對象發(fā)送消息:
      1、this對象(自身)
      2、方法的參數(shù)
      3、this的屬性
      4、作為this屬性的集合中的元素
      5、在方法中創(chuàng)建的對象
      典型違反該原則的例子: F f=foo.getA().getB().getC().getD().getE().getF();

    命令-查詢分離原則:
      執(zhí)行動作(更新、調(diào)整,等等)的命令方法,這種方法通常具有改變對象狀態(tài)等副作用,并且是void的(沒有返回值)。
      向調(diào)用者返回數(shù)據(jù)的查詢,這種方法沒有副作用,不會永久性地改變?nèi)魏螌ο蟮臓顟B(tài)。
    關(guān)鍵在于:一個方法不應(yīng)該同時屬于以上兩種類型。
     
    在繪制交互圖時考慮和決定職責(zé)分配。然后在類圖的方法分欄里概括職責(zé)分配結(jié)果,方法是職責(zé)的具體實現(xiàn)。
    posted @ 2007-09-04 17:38 ronghao 閱讀(1295) | 評論 (0)編輯 收藏
    在迭代開發(fā)中,我們并非一次就實現(xiàn)所有需求。

    在多個迭代里對同一用例進(jìn)行增量式開發(fā)。

    細(xì)化階段:構(gòu)建核心架構(gòu),解決高風(fēng)險元素,定義大部分需求,以及預(yù)計總體進(jìn)度和資源。(包括了三到四次的細(xì)化迭代)
    關(guān)鍵思想和最佳實踐:
     實行短時間定量、風(fēng)險驅(qū)動的迭代
     及早開始編程
     對架構(gòu)的核心和風(fēng)險部分進(jìn)行適應(yīng)性設(shè)計、實現(xiàn)和測試
     盡早、頻繁、實際的測試
     基于來自測試、用戶、開發(fā)者的反饋進(jìn)行調(diào)整
     通過一系列討論會,詳細(xì)編寫大部分用例和其他需求,每個細(xì)化迭代進(jìn)行一次
    制品:領(lǐng)域模型、設(shè)計模型、軟件架構(gòu)文檔、數(shù)據(jù)模型、用例、用戶界面原型。

    領(lǐng)域模型
    領(lǐng)域模型是對領(lǐng)域內(nèi)的概念類或現(xiàn)實世界中對象的可視化表示。
    應(yīng)用UML表示法,領(lǐng)域模型被描述為一組沒有定義操作的類圖,反映屬性和關(guān)聯(lián)。(一定注意,它不是軟件對象!是概念對象!)
    準(zhǔn)則:
      使用領(lǐng)域術(shù)語
      認(rèn)真汲取領(lǐng)域?qū)<宜褂玫暮诵脑~匯和概念
      如果某概念類不是現(xiàn)實世界中的數(shù)字或文本,那么她可能是概念類而不是屬性
      需要描述類:1、需要有關(guān)商品或服務(wù)的描述,獨立于任何商品或服務(wù)的現(xiàn)有實例;2、減少冗余或重復(fù)信                 息
      避免加入大量關(guān)聯(lián),添加關(guān)聯(lián)是為了突出對重要關(guān)系的大致理解,而非記錄對象或數(shù)據(jù)的結(jié)構(gòu)
      通過關(guān)聯(lián)而不是屬性來表示概念類之間的關(guān)系,領(lǐng)域模型中屬性的類型應(yīng)該是數(shù)據(jù)類型(基本類型)
      對數(shù)量和單位建模
    每次迭代的領(lǐng)域建模不超過幾個小時。

    系統(tǒng)順序圖
    系統(tǒng)順序圖(SSD)是為闡述與所討論系統(tǒng)相關(guān)的輸入和輸出事件而快速、簡單地創(chuàng)建的制品。是操作契約和對象設(shè)計的輸入。
    SSD展示了直接與系統(tǒng)交互的外部參與者、系統(tǒng)(作為黑盒)以及由參與者發(fā)起的系統(tǒng)事件。這些事件是通過用例文本總結(jié)出來的。
    應(yīng)為每一個用例的主成功場景,以及頻繁發(fā)生的或者復(fù)雜的替代場景繪制SSD。
    基本上軟件系統(tǒng)要對三種事件進(jìn)行響應(yīng):來自于參與者的外部事件,時間事件,錯誤和異常(通常源于外部)。
    系統(tǒng)事件應(yīng)該在意圖的抽象級別而非物理的輸入設(shè)備級別來表達(dá)。

    操作契約
    操作契約使用前置和后置條件的形式,描述領(lǐng)域模型里對象的詳細(xì)變化。其中的關(guān)鍵元素是后置條件。
    為系統(tǒng)操作定義操作契約。系統(tǒng)操作在繪制SSD草圖時確定。
    后置條件描述了領(lǐng)域模型內(nèi)對象狀態(tài)的變化。可分為三種類型:創(chuàng)建或刪除實例,屬性值的變化,形成和消除關(guān)聯(lián)。注意,它描述的是所需的變化,而不是這些變化是如何完成的。以說明性的、被動式的過去時態(tài)編寫后置條件。(例如,創(chuàng)建了xx,而不是創(chuàng)建xx)

    邏輯架構(gòu)和UML包圖
    邏輯架構(gòu)是軟件類的宏觀組織結(jié)構(gòu),它將軟件類組織為包(或命名空間)、子系統(tǒng)和層等。
    UML包圖常用于描述系統(tǒng)的邏輯架構(gòu)--層、子系統(tǒng)、包等。
    將系統(tǒng)的大型邏輯結(jié)構(gòu)組織為獨立的、職責(zé)相關(guān)的離散層,具有清晰、內(nèi)聚的關(guān)注分離。
    協(xié)作和耦合是從較高層到較低層進(jìn)行的,要避免從較低層到較高層的耦合。較低層包含可復(fù)用功能。
    可以將應(yīng)用邏輯層更準(zhǔn)確地稱為架構(gòu)的領(lǐng)域?qū)樱窗I(lǐng)域?qū)ο螅ㄗ⒁忸I(lǐng)域模型與領(lǐng)域?qū)ο笫遣煌膬蓚€概念),處理應(yīng)用邏輯的層。
    領(lǐng)域?qū)邮擒浖囊徊糠郑I(lǐng)域模型是概念角度分析的一部分。
    從UI層發(fā)送到領(lǐng)域?qū)拥南⑹荢SD中所描述的消息。

    輕量級繪圖然后編碼。
    posted @ 2007-09-03 17:50 ronghao 閱讀(2129) | 評論 (1)編輯 收藏
    僅列出標(biāo)題
    共39頁: First 上一頁 18 19 20 21 22 23 24 25 26 下一頁 Last 
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    關(guān)注工作流和企業(yè)業(yè)務(wù)流程改進(jìn)。現(xiàn)就職于ThoughtWorks。新浪微博:http://weibo.com/ronghao100

    常用鏈接

    留言簿(38)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    常去的網(wǎng)站

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 久久久精品视频免费观看| 久久久久亚洲AV综合波多野结衣| 久久久免费观成人影院| 67194在线午夜亚洲| 久久91亚洲精品中文字幕| 亚洲国产精品毛片av不卡在线| 人与禽交免费网站视频| a毛片在线免费观看| 一级毛片免费观看不收费| 亚洲人成色在线观看| 亚洲国产精品网站久久| 亚洲va国产va天堂va久久| 亚洲视频一区二区| 国产成人无码免费视频97| 成年18网站免费视频网站| 91免费人成网站在线观看18| 3344在线看片免费| 在线观看人成视频免费无遮挡 | 亚洲精品偷拍视频免费观看| 亚洲高清乱码午夜电影网| 亚洲三级在线视频| 亚洲妇女水蜜桃av网网站| 亚洲国产成人精品不卡青青草原| 亚洲综合国产一区二区三区| 亚洲AⅤ视频一区二区三区| 日本大片在线看黄a∨免费| 插B内射18免费视频| 九九九精品成人免费视频| 免费看成人AA片无码视频羞羞网| 国产精品久久久久久久久免费| 18禁美女裸体免费网站| 亚洲一级免费毛片| 亚洲三级高清免费| 黄页网站在线看免费| 午夜亚洲国产理论片二级港台二级 | 丝袜捆绑调教视频免费区| 国产精品亚洲色图| 国产精品亚洲AV三区| 日本亚洲色大成网站www久久| 久久精品国产99国产精品亚洲| 亚洲色四在线视频观看|