天天看點

分享我的面向對象分析方法先分享一下我的面向對象分析方法案例分析:圖書管理系統需求用例場景描述結合面向對象分析思路和需求用例場景進行分析

找出最關鍵的一些業務場景;一般通過動詞來尋找,比如招聘系統中,一個應聘人投遞一個職位就是一次應聘,應聘就是一個業務場景;一個學生參加某門課的考試,那麼考試就是一個業務場景;一個學生去圖書館借書,那麼借書就是一個業務場景;

針對每個業務場景分析出有哪些場景參與者,哪些參與者以對象的形式參與,哪些參與者以服務的形式參與;為什麼要區分對象還是服務是因為有時候我們不關心參與者是哪個,而隻關心參與者是什麼。一般服務在系統中我們隻關心它是什麼服務,并且在系統中服務一般也隻有一個執行個體;而對象則不同,我們會關心對象是誰,即哪一個;

分析每個場景參與者對象的基本狀态特征;所謂的基本狀态特征是指對象與生俱來的,對象從一開始被建立出來之後就具有的狀态特征;最形象的例子就是人的身高體重,當人一出生便具有了身高和體重這兩個狀态特征;再比如一篇博文,它從被寫好之時起就具有了内容這個狀态特征,但是我們可以随便修改博文的内容;但是有些狀态特征是不能修改的,比如博文的建立時間一旦博文被建立之後便不能再被修改;需要注意的是我們不要把和對象關聯的一些關聯資訊也認為是對象的基本狀态特征。比如某人有一本英語六級考試證書,那麼人和證書之間的關系是擁有的關系,證書不是人固有的與生俱來的基本狀态特征,而是人參與了某次考試這個場景後得來的;後面我會提到這種關聯關系該如何去思考和了解!

分析每個場景參與者對象分别扮演什麼角色參與場景,整個場景的完整互動過程是怎樣的,對象在參與場景的過程中執行了哪些互動行為; 相信大家都明白這點非常重要,因為它涉及到對象之間如何互動,涉及到該如何分析哪個對象該具有哪個互動職責;進而最終決定了在代碼級别哪個類該具有哪些方法的問題。關于這方面思考的例子我會在下面進行介紹,這裡先說一下理論吧。我覺得要點是将整個業務場景中的每個互動行為通過四色原型的分析方法來了解。用一句話來概括四色原型就是:一個什麼什麼樣的人或組織或物品以某種角色在某個時刻或某段時間内參與某個活動。另外一個技巧就是,我們經常可以問自己,這個互動行為是“誰通知誰做什麼事情?“,行為的驅動者是誰?行為的執行者是誰?一般行為的驅動者就是通知方,行為的執行者就是被通知方,被通知方擁有”通知方要求做的事情“執行行為;另外,我覺得還需要說明的是,現實生活中的對象并不是說其扮演了某個角色後才具有角色所定義的行為的,而是本來就有的,隻不過是在扮演角色後表現出了該行為;是以對于現實生活中的對象,執行角色所定義的行為和扮演角色是同時發生的,沒有誰先誰後的說法;但是軟體中的對象則不同,因為軟體中的對象隻是現實生活中的對象的某一個我們所關心的方面,是以它的能力也有限。另外從設計實作的角度職責單一的角度來說,我們也不會将軟體中的對象設計的很複雜,包含很多職責,因為這樣會導緻對象難以維護,這樣做雖不違背分析原則,但違背設計原則。軟體中的對象我們往往是設計成當它扮演某個角色時,動态給對象注入角色所定義的互動行為,進而給對象賦予了參與場景互動的能力。是以簡單的說,軟體中的對象,平時隻具有基本的狀态特征和基本的非互動行為,而當它扮演某個角色時,則動态具有互動行為;

分析互動過程結束後分别會對每個場景參與者對象産生哪些基本狀态特征的改變;這個很好了解,當一個對象參與了某個互動活動後,一些基本狀态特征會發生改變,比如一個人參加一次100米跑步比賽後,心跳速度會加快;心跳速度就是人的基本體征;這個應該很好了解吧,不多舉例了。

分析如何記錄和跟蹤這一次互動行為,分析這次互動行為會産生哪些額外的資訊;這點估計大家平時很少思考,而這點我想也正是我的面向對象分析思路最具特色的地方吧!大家一定知道,一次對象的互動活動會産生一些與該互動活動相關的互動資訊。比如一次應聘活動會産生一些與該活動相關的資訊,如是否錄取,筆試成績,面試成績等;比如一次考試會産生考試成績這個資訊;一次借書會産生一個借閱資訊(包含:借書人、被借的書、借書時間,我們可能還會設計一個還書時間);并且,在很多情況下,這些互動資訊會在後續的其他互動場景中再被更新。比如,一次應聘一開始狀态可能是”新投遞“,表示應聘人剛剛投了履歷并選了某個職位,後來她去參加筆試或面試了,那麼這次應聘的狀态就變為了”已筆試“或”已面試“;在比如一個學生參加一次考試,剛開始還沒有成績,但後來老師批卷子後便有了考試成績。再比如一次借書後,如果這本書還沒被還,則還書時間為空,而一旦還書了之後,便有了還書時間;是以,我們從這些規律中可以發現,互動其實是一個過程,并且該過程一旦開始後就會産生一些相關的資訊,如應聘的狀态,考試的成績,借閱資訊的歸還時間,等等。通常我們會把互動過程本身所涉及的一切資訊以及互動過程所産生的所有附加資訊作為一個整體來進行考慮。是以,我覺得我們有必要設計一個對象,用來表示某一次互動的結果,這個結果包含互動過程本身所涉及的一切資訊以及互動過程所産生的所有附加資訊;大家想想,看到”應聘“這個單詞,你有時候會認為它是一個動詞,優勢後會認為它是一個名詞。在認為是動詞時,我們關注的是互動本身,活動本身,強調行為;而在認為是名詞時,我們關注的是應聘行為所産生的一切資訊;是以,看到這裡,我想大家應該心裡有個數了,就是在互動行為結束後,我們往往需要設計一個對象用來表示一次互動活動的相關資訊;這些資訊一方面展現了互動活動的參與者,(互動時間,互動地點,如果我們關心這些的話),另一方面展現了互動活動所産生的附加的資訊,如成績,應聘狀态,借書還書時間,等等。最後,需要強調的是這些資訊之是以設計為對象是因為這些資訊不是曆史,即不是不可改變的,相反,這些資訊會在後續的其他互動活動中被更新;是以,看到這裡,我想我們就不用在糾結對象在參加互動活動後所産生的一些與它關聯的資訊該如何存放這個問題了。

圖書館管理者掃描不同名稱的書本。大家都知道每本具體的書都有一個isbn,即international standard book number,國際标注書号。圖書館是根據isbn來管理書本的,同一個isbn的書會有很多不同的副本,每一個副本就是一本實實在在的書。是以,嚴格的說圖書館資料庫中儲存的是“書本的庫存資訊”。在圖書入庫的場景中,隻要是isbn相同,即書名相同的書隻會被掃描一次,然後管理者會輸入這種書總共有多少本,應該放在什麼地方等庫存資訊。當然這隻是我自己了解的業務場景,姑且不論對錯,咱們就先當這個了解是正确的吧。

借書人持圖書卡去圖書館,先找到幾本要借的書,然後跑到借書處借書;

圖書管理者掃描借書人的借書卡以及書本的條形碼,條形碼就是isbn;

借書人拿着書從圖書館離開;

借書人吃圖書卡去圖書館,到還書處還書;

圖書管理者掃描還書人的借書卡以及書本的條形碼,如果有需要罰款的,也在此時會計算出來;

還書人離開圖書館;

圖書館、書本;其中圖書館在整個圖書借閱系統中隻需要一個執行個體,我們也不關心是這個圖書館還是那個圖書館,是以我覺得可以把圖書館設計為一個服務。

書本的基本狀态特征:如書名、作者、出版社等資訊;

圖書館的基本狀态特征:沒有,一般情況下服務是無狀态的,服務隻提供服務行為;

很容易了解,圖書館本身就具有圖書入庫的行為。圖書入庫時,圖書館服務會生成并儲存一個書本的“庫存資訊”,該資訊包含了某個名稱的書本的數量、書架位置資訊。該庫存資訊中的count表示某個名稱的書有幾本。當在借書或還書的場景發生時,這個count就會改變; 代碼示例如下:

圖書入庫場景類的實作:

分享我的面向對象分析方法先分享一下我的面向對象分析方法案例分析:圖書管理系統需求用例場景描述結合面向對象分析思路和需求用例場景進行分析

    public class storebookcontext

    {

        private ilibraryservice library = null;

        private book book = null;

        public storebookcontext(ilibraryservice library, book book)

        {

            this.library = library;

            this.book = book;

        }

        public void interaction(int count, string location)

            library.storebook(book, count, location);

    }

分享我的面向對象分析方法先分享一下我的面向對象分析方法案例分析:圖書管理系統需求用例場景描述結合面向對象分析思路和需求用例場景進行分析

圖書館圖書入庫的方法: 

分享我的面向對象分析方法先分享一下我的面向對象分析方法案例分析:圖書管理系統需求用例場景描述結合面向對象分析思路和需求用例場景進行分析

public void storebook(book book, int count, string location)

{

    //圖書入庫時生成圖書的庫存資訊

    var bookstoreinfo = new bookstoreinfo(book, count);

    bookstoreinfo.location = location;

    bookstoreinforepository.add(bookstoreinfo);

}

分享我的面向對象分析方法先分享一下我的面向對象分析方法案例分析:圖書管理系統需求用例場景描述結合面向對象分析思路和需求用例場景進行分析

最後,互動之後,場景參與者的基本狀态特征是否發生變化?都沒有發生變化。

圖書館注冊帳号、圖書館、書本;圖書館是一個服務、書本也隻是一本普通的書,它沒有行為,它是被借的。需要着重分析的是圖書館注冊帳号這個參與者。先說一下我對:軟體使用者(即軟體的使用者)、注冊帳号、圖書卡、借書人這四個概念的了解。了解這些概念非常重要!首先,軟體使用者就是軟體的使用者,就是我們平時所說的使用者,這點沒什麼問題。圖書卡和注冊帳号的關系是什麼?我們都知道現實生活中,人持圖書卡去借書;而軟體中,人通過其注冊帳号登入,然後以該注冊帳号所代表的“人”做事情;是以,圖書卡是使用者用來借書的工具;同樣注冊帳号也是軟體使用者通過軟體進行借書的工具;使用者擁有圖書卡,使用者擁有注冊帳号。那麼借書人如何了解呢?我們平時所說的借書人其實就是一種角色,即使用者在通過借書卡參與借書的行為過程中,我們把正在執行該行為或已經執行了該行為的人叫做借書人。用更通用的表達方式就是,我們通常會給正在做某件事情或已經做了某件事情的參與者一個稱謂,如兇手、借書人、還書人、應聘人,等等;是以,有了這些了解之後,我們就知道借書人隻是一個角色,某個注冊帳号扮演了借書人這個角色後可以行駛借書的行為;

注冊帳号的基本狀态:圖書館注冊帳号有基本的狀态特征,比如:卡号,所有者姓名,是否鎖定,等等;

某個軟體的使用者,即軟體使用者通過某個已注冊帳号登入軟體系統,然後選擇了幾本想借的書之後點選“借書”按鈕,然後該按鈕觸發一個借書的場景,該場景建立時包含了部分的場景參與者,在借書這個例子中就是帳号和書,然後借書場景知道帳号應該扮演借書者這個角色。是以帳号在扮演了借書者這個角色後對每一本書行駛借書的互動行為。扮演了借書者角色的注冊帳号自動具有了借書的行為,在該行為的内部實作中,通知圖書館把書借出來。随後圖書館接到通知後,首先根據目前書本擷取書本的庫存資訊,如果目前庫存資訊是0本,說明這本書沒有庫存,就抛出異常通知軟體使用者這本書目前已經被借光了。如果還有庫存,則先更新庫存資訊,比如圖書的數量減1,然後根據目前借書人,書本,以及目前時間生成一個借書資訊對象,該對象還會包含一個圖書歸還時間的附加資訊。最後将該借書資訊對象儲存起來。代碼示例如下:

借書場景類的實作:

分享我的面向對象分析方法先分享一下我的面向對象分析方法案例分析:圖書管理系統需求用例場景描述結合面向對象分析思路和需求用例場景進行分析

    public class borrowbookscontext

        private libraryaccount account = null;

        private ienumerable<book> books = null;

        public borrowbookscontext(libraryaccount account, ienumerable<book> books)

            this.account = account;

            this.books = books;

        public void interaction()

            var borrower = account.actas<iborrower>();

            foreach (var book in books)

            {

                borrower.borrowbook(book);

            }

分享我的面向對象分析方法先分享一下我的面向對象分析方法案例分析:圖書管理系統需求用例場景描述結合面向對象分析思路和需求用例場景進行分析

借閱者的借書方法:

public void borrowbook(book book)

    //通知圖書館把書借給我

    library.lendbook(book, this);

圖書館借出書的方法: 

分享我的面向對象分析方法先分享一下我的面向對象分析方法案例分析:圖書管理系統需求用例場景描述結合面向對象分析思路和需求用例場景進行分析

public void lendbook(book book, iborrower borrower)

    //更新書本在圖書館的庫存資訊,如:數量資訊、所在書架位置資訊

    var bookstoreinfo = bookstoreinforepository.getbookstoreinfo(book.id);

    if (bookstoreinfo.count == 0)

        throw new exception(string.format("the count of book '{0}' in library is zero, so you cannot borrow it.", book.bookname));

    bookstoreinfo.decreasecount(); //數量減1

    bookstoreinfo.location = null; //位置清空

    //生成借書資訊并儲存到repository中

    borrowinforepository.add(new borrowinfo(book, borrower, datetime.now));

分享我的面向對象分析方法先分享一下我的面向對象分析方法案例分析:圖書管理系統需求用例場景描述結合面向對象分析思路和需求用例場景進行分析

有了借書場景的分析,那麼還書場景也很容易分析了,主要的過程是:注冊帳号扮演借閱者角色執行還書行為,執行過過程中通知圖書館接收某本要歸還的書,圖書館接到通知後首先調出與該書本對應的那一次借書資訊,然後更新其還書時間,最後更新圖書的庫存資訊。另外的基本和借書類似了,相信大家一看代碼都應該明白了,直接上代碼吧!

還書場景類:

分享我的面向對象分析方法先分享一下我的面向對象分析方法案例分析:圖書管理系統需求用例場景描述結合面向對象分析思路和需求用例場景進行分析

    public class returnbookscontext

        public returnbookscontext(libraryaccount account, ienumerable<book> books)

            var returnner = account.actas<iborrower>();

                returnner.returnbook(book);

分享我的面向對象分析方法先分享一下我的面向對象分析方法案例分析:圖書管理系統需求用例場景描述結合面向對象分析思路和需求用例場景進行分析

借書者的還書方法:

public void returnbook(book book)

    //通知圖書館接收我要歸還的書

    library.receivereturnedbook(book, this);

圖書館接收被還的書的方法:

分享我的面向對象分析方法先分享一下我的面向對象分析方法案例分析:圖書管理系統需求用例場景描述結合面向對象分析思路和需求用例場景進行分析

public void receivereturnedbook(book book, iborrower borrower)

    //設定借書資訊的還書時間

    var borrowedinfo = borrowinforepository.findnotreturnedborrowinfo(borrower.id, book.id);

    borrowedinfo.returntime = datetime.now;

    //這裡,真正的系統還會計算歸還時間是否超期,計算罰款之類的邏輯,因為我這個是一個示範的例子,是以不做這個處理了

    //這裡隻更新書本的數量資訊,因為還書時并不是馬上把書本放回書架的,是以此時書本的書架位置資訊還是保留為空

    //等到我們将這本書放到書架的某個位置時,才會更新其位置資訊

    bookstoreinfo.increasecount(); //數量加1

分享我的面向對象分析方法先分享一下我的面向對象分析方法案例分析:圖書管理系統需求用例場景描述結合面向對象分析思路和需求用例場景進行分析

好了,差不多就這樣吧,從整理思考到文章寫作完成,花了我不少心思和時間那,希望大家都能看明白!另外一個題外話,大家在看我的源代碼時,不要過分注重我的架構實作,而應該注重這種面向對象的分析思路,架構是偏設計的,是用來為了更友善的支援由這種分析思路而産生的代碼實作。我想你懂的,呵呵!