[轉]3天搞定的小型B/S內部管理類軟件定制開發項目【軟件開發實戰10步驟詳解】


 

 

   十一休假,杭州西湖邊逛了一圈只能用人山人海來形容,浙大紫金港校區也逛了一圈風景如畫,建設得真不錯很棒,假期就去了這2個地方,然后在家里陪老婆、看孩子、洗尿布、打了幾局星際爭霸,在網上接了一個B/S架構的內部管理類定制軟件、淘寶上收了600元辛苦費后就開始行動了、現在把整個開發過程講解分享如下文。

 

客戶需求

   一個簡單的項目管理信息的,添加、刪除、編輯、查詢等功能的實現,把大的框架做好就可以,細節他會自己完善好,想想也很簡單的一樣,本以為1天時間就足可以搞定了,結果足足干了3天才算竣工,由於客戶也是軟件開發人員,溝通起來也比較順暢一些,否則可能不止需要3天了。

 

   項目雖然很小,但是由於跟我的主營方向是一致的,同時也想鍛煉一下做項目的成熟程度有多高、有多快,所以也沒嫌棄錢多錢少,開開心心就把這個項目開始啟動了。項目雖然小但五臟俱全來形容了這個活兒了。

   很多必要的功能雖然在需求里沒有提到,但是都是需要做好的,例如:

         01:系統的登錄功能、這個是必然要有的。

         02:記住密碼功能,而且是需要有加密功能的。

         03:退出系統的功能,總需要能安全退出系統的吧。

         04:用戶管理功能,例如哪些用戶才能登錄到系統里來?

         05:用戶修改密碼功能,停用功能,設置密碼功能等。

         06:用戶可以訪問那些菜單等?

         07:用戶有哪些操作權限等?

         08:角色管理功能,用戶角色關系功能,角色的權限功能。

         09:友善的菜單導航功能。

         10:沒有權限的友善提示功能。

         11:附件的管理、上傳、下載、刪除等等。

         12:查詢分頁功能等等,雖然都沒提出,但是這些功能都需要做好的。

 

 

整體開發思路

 

數據庫分2個設計:業務數據 + 權限數據,互相不干擾,相互比較獨立一些。

整個系統分3個種干系人: 開發人員 + 系統管理員 + 操作人員,他們對系統各自的期望值及操作的內容如下圖。

為了快速搞定項目,畢竟項目的預算很有限,所有有些功能模塊能不開發就不開發,那我們就用現成的成熟組件,通用權限管理系統,做為用戶賬戶管理、權限管理

菜單管理的核心組件,這樣可以大大的提高工作效率,可以靈活配置管理這個小型B/S項目信息管理系統了。

 

 

項目的具體開發制作步驟

 

步驟1:項目雖然很小,但是還是按規范的軟件開發步驟比較好,我們還是本着先有設計后有開發的思路,先不急着寫代碼,我們先把數據庫結構設計好,本系統應該只設計一個表就可以了,我們先要想好哪些數據用什么格式保存,都需要哪些字段來表示各種屬性,效果圖如下,我們用了數據庫建模工具PowerDesigner,來設計我們的業務模型中的數據模型吧,這就是所謂的開發上的領域模型吧,其實這個設計還是蠻關鍵的,設計亂了后面都會亂套了。

 

步驟2:通過用設計好的模型,我們先手工建立相應的數據庫及數據表。

 

步驟3:下圖是已經建立好的數據的效果圖,Project是業務數據庫、Project表是項目信息表,后面的Base_Sequence 用於產生序列及唯一排序號、Base_Comment 用於修改記錄保存功能,這些不用重復設計,直接從UserCenterV30數據中心里復制過來結構就可以了,為了在軟件里顯示一些數據出來,可以通過手工方式先錄入一些演示數據,這樣成就感會更多一些、信心也更足一些,因為很快就可以在軟件里顯示數據出來了。

 

步驟4:生成好相應的數據表后,可以用代碼生成器生成一些沒有多少商業邏輯的代碼了,所謂的添加、刪除、修改、查詢的代碼都不用寫了,直接用代碼生成器生成好就可以了,雖然這個技術不怎么先進,但是省事省心,對技術的要求也很低,生成好的代碼也比較規范一些,而且還支持多種數據庫,還是蠻好的,若生成好后,數據庫結構有變化了,也沒關系,重新生成一下就可以了,生成代碼1分鍾足夠了,頂多是命名空間可能需要整理一些就可以了,屬於是很經得起折騰的做法了。

 

步驟5:將生成好的代碼,復制到相應的位置上,適當的修正一下命名空間什么的,因為是一個很小的項目,根本不用分層啥的,分那么多層也是多余的,其實分目錄就足夠可以了,若很懶惰的話目錄都可以不用分了,分層其實更適合大型軟件項目,小項目以見效最快為主,沒必要搞個7-8個層,這里是是1個層也沒分,只是分了一些目錄,顯得思路更清晰一些。

 

步驟6:代碼生成器不能生成所有的代碼,有些代碼還是有商業邏輯的,需要人工編寫,其中ProjectManager.cs 中的代碼就是有具體商業邏輯的代碼,這部分代碼無法靠代碼生成器自動生成好,需要按自己的需要進行編寫的,這里有2個功能,一個是查詢功能的實現、另一個是更新數據時需要有修改記錄的功能,需要詳細記錄數據被變更的全過程,這些代碼都需要人工編寫好,頁面上會調用這些代碼。

 

步驟7:接下來該是規划整個系統的菜單的時候,需要好好規划一下軟件的菜單,到底需要有哪些菜單,都叫什么名字?當然這一步也可以在在最后做,我們同通用權限管理組件可以靈活規划整個系統的菜單,基本上想怎么設置就怎么設置,想怎么托摘、想怎么排序都可以,規划菜單時會很爽,當然不只是開發人員用起來爽、而且系統管理員今后維護時也會很爽,系統的整個菜單都可以靈活配置權限、可以靈活更改,而不是寫死的菜單,將來不依賴開發人員也可以靈活配置管理,靈活設置各種權限限制等等。

 

步驟8:接下來,需要把相應的添加、修改、查詢、刪除功能頁面做出來,可以考慮到今后可能會擴展很多模塊進來,所有目錄規划得合理一些,說不定還要做人事管理、考勤管理、薪資管理、工作日志管理等等很多模塊,其實都是大同小異而已,更多是技術是體現在細節功能及業務邏輯的深入程度上。

 

步驟9:菜單配置好,頁面制作好后,就可以實現登錄系統的頁面了,當然這個也是用了現成的通用權限管理系統的登錄頁面,只需要制作一個登錄界面,然后調用相應的登錄API就可以了,自然就可以達到離職人員不能登錄、沒有權限的用戶不能登錄、停用賬戶不能登錄,不能重復登錄、限制登錄的IP地址等等額外的其他功能都可以集成在里面了,開發人員也不用關心更多的細節,省心省事了。 

 

步驟10:登錄好后,通用權限管理系統的底層API,自然會顯示有權限的菜單,無權訪問的菜單也不會出來了,哪個用戶可以訪問哪個菜單等等,都可以通過通用權限管理工具靈活配置管理,當然那個工具是給系統管理員、開發人員、實施人員使用的,並不是為了給普通業務操作員使用定位的。軟件的最終運行效果就如下圖了,由於是系統管理登錄的所有菜單都能顯示了,當然這里還需要一個成熟穩定的分頁組件。

 

 

   底層代碼生成器生成的代碼,可能只占用這個系統的代碼的 1/3左右,但是編寫這些代碼的時間也省了,整個開發過程不是可以節省1/3了,而且是純體力勞動而已。整個權限管理等可能需要整個系統開發的1/3左右的精力,若這部分也不用開發了,又可以節省整個軟件項目開發的1/3時間。整個框架的穩定完善,也可以說是占用整個軟件開發項目的1/3時間是應該的,若是2手空空開始開發的話。

   那我們的項目采用了 代碼生成器 + 數據庫訪問組件 + 通用權限組件 + 成熟的B/S開發框架 足足可以節省一個管理軟件項目開發的 2/3 的開發時間,可以把精力全部放在另外的 1/3 的業務邏輯優化、界面細節優化上。

   這樣也大大的降低了軟件項目的開發的失敗風險,誰說你不會在前面的2/3時間上失敗呢?未必能走到后面的1/3時間上來啊,對吧。  

 

開發總結

 

  目前3天內搞定一個獨立的內部管理系統,而且五臟俱全的是我從業10年左右的最快記錄,當然若第二次做類似的東西,可能有希望2天內可以搞定了。

 

  經過多年的積累,手上才會有一個運行穩定、可以靈活配置的B/S開發架構,雖然看看都很簡單,但是最起碼不斷完善幾年后,才會達到銅牆鐵壁的程度,我們經常會發現,開發一個小小的軟件,往往1個月也開發不完,很可能是由於沒有穩定的B/S開發架構導致的,這個架構也不是說技術,就是一個美觀的整體效果良好的運行穩定的B/S系統吧,從頭開發的B/S架構,由於需要調整很多細節環節、特別是頁面、菜單的美觀設計等上會耗費很多精力。

   有時候界面設計良好、程序思路嚴謹、用戶交互效果好的B/S空框架也能賣出幾萬元,以前不能理解,現在是徹底能體會了,穩定的B/S架構的確可以值一些錢,因為是經過精雕細刻后才能形成最后的勞動成果的。

 

   軟件的大體效果做到這里,大概花費了3天時間、接下來可能要花費的時間會更多,應該不止3天了,可能是30天,因為很多業務上的細節會耗費很多時間來調整,例如新增頁面的先后輸入的內容,頁面輸入的檢查、頁面的美觀設計、光標的順序優化、回車優化,輸入內容的完善補充等等,查詢頁面的排序順序優化、查詢內容的先后順序排版、表格中各列的寬度調整,一些提醒顏色的優化等等會有很多細節問題上還要耗費很久時間的, 做軟件其實就是做細節,你需要有一個良好的B/S開發框架,否則全部自己弄,不知道什么時候才能弄好,有個良好的框架、再有良好的例子程序,整個管理系統,就是一個量的問題了,其次就是很多細節的優化上,會花費很多時間。

   

    有良好的穩定的B/S開發框架,前期工作只用了3天,若沒有這個,從頭開始做,可能30天也做不完,更不會把大多精力都花費在業務邏輯的細節優化上,可能更多的精力都耗費在B/S系統架構的穩定、優化上了,那這個軟件的質量就更沒保障了。

 

    有了穩定的B/S開發框架后,才好進行大規模生產、大量招聘人員做開發工作,若這些都沒有,招聘來一大堆開發人員,那很可能局面就亂套了,大家就容易亂來了。

 

    ProjectManager.cs手工編寫的商業邏輯代碼如下:

代碼 

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->//------------------------------------------------------------
// All Rights Reserved , Copyright (C) 2010 , Jirisoft , Ltd .
//------------------------------------------------------------

using System;
using System.Data;
using System.Data.Common;
using System.Collections.Generic;

namespace Project
{
    using DotNet.DbUtilities;
    using DotNet.Manager;
    using DotNet.Utilities;
    using DotNet.Business;

    /// <summary>
    /// ProjectManager
    /// 項目跟進表
    ///
    /// 修改紀錄
    ///
    ///        2010-09-28 版本:1.0 JiRiGaLa 創建主鍵。
    ///
    /// 版本:1.0
    ///
    /// <author>
    ///        <name>JiRiGaLa</name>
    ///        <date>2010-09-28</date>
    /// </author>
    /// </summary>
    public partial class ProjectManager : BaseManager, IBaseManager
    {
        public DataTable Search(string userId, string searchValue)
        {
            // 一、這里是開始進行動態SQL語句拼接,字段名、表明都進行了常量定義,表名字段名發生變化時,很容易就知道程序哪里都調用了這些。
            string sqlQuery = string.Empty;
            sqlQuery = " SELECT * "
                    + " FROM " + this.CurrentTableName
                    + " WHERE " + ProjectTable.FieldDeleteMark + " =  0 ";

            // 二、我們認為 userId 這個查詢條件是安全,不是人為輸入的參數,所以直接進行了SQL語句拼接
            if (!String.IsNullOrEmpty(userId))
            {
                sqlQuery += " AND " + ProjectTable.FieldCreateUserId + " = '" + userId + "'";
            }

            // 三、這里是進行參數化的准備,因為是多個不確定的查詢參數,所以用了List。
            List<DbParameter> dbParameters = new List<DbParameter>();

            // 四、這里看查詢條件是否為空
            searchValue = searchValue.Trim();
            if (!String.IsNullOrEmpty(searchValue))
            {
                // 五、這里是進行支持多種數據庫的參數化查詢
                sqlQuery += " AND (" + ProjectTable.FieldKeHuMingCheng + " LIKE " + DbHelper.GetParameter(ProjectTable.FieldKeHuMingCheng);
                sqlQuery += " OR " + ProjectTable.FieldKeHuXiangMuMingCheng + " LIKE " + DbHelper.GetParameter(ProjectTable.FieldKeHuXiangMuMingCheng);
                sqlQuery += " OR " + ProjectTable.FieldCreateUserRealname + " LIKE " + DbHelper.GetParameter(ProjectTable.FieldCreateUserRealname);
                sqlQuery += " OR " + ProjectTable.FieldDescription + " LIKE " + DbHelper.GetParameter(ProjectTable.FieldDescription) + ")";

                // 六、這里是判斷,用戶是否已經輸入了%
                if (searchValue.IndexOf("%") < 0)
                {
                    searchValue = "%" + searchValue + "%";
                }

                // 七、這里生成支持多數據庫的參數
                dbParameters.Add(DbHelper.MakeInParam(ProjectTable.FieldKeHuMingCheng, searchValue));
                dbParameters.Add(DbHelper.MakeInParam(ProjectTable.FieldKeHuXiangMuMingCheng, searchValue));
                dbParameters.Add(DbHelper.MakeInParam(ProjectTable.FieldCreateUserRealname, searchValue));
                dbParameters.Add(DbHelper.MakeInParam(ProjectTable.FieldDescription, searchValue));
            }
            sqlQuery += " ORDER BY " + ProjectTable.FieldSortCode + " DESC ";

            // 八、這里是將List轉換為數組,進行數據庫查詢
            return DbHelper.Fill(sqlQuery, dbParameters.ToArray());
        }
        
        /// <summary>
        /// 更新(帶有修改記錄功能)
        /// </summary>
        /// <param name="projectEntity">實體</param>
        /// <param name="changeLog">修改記錄</param>
        /// <returns>影響行數</returns>
        public int Update(ProjectEntity projectEntity, bool changeLog)
        {
            // 若不需要修改記錄
            if (!changeLog)
            {
                return this.UpdateEntity(projectEntity);
            }

            String changeMessage = String.Empty;

            // 獲取原來的數據
            ProjectEntity oldProjectEntity = this.GetEntity((int)projectEntity.Id);
            if (oldProjectEntity.KeHuXiangMuMingCheng != projectEntity.KeHuXiangMuMingCheng)
            {
                changeMessage += "客戶項目名稱被修改為:" + projectEntity.KeHuXiangMuMingCheng + " 原值:" + oldProjectEntity.KeHuXiangMuMingCheng + "<br>";
            }
            if (oldProjectEntity.KeHuMingCheng != projectEntity.KeHuMingCheng)
            {
                changeMessage += "客戶名稱被修改為:" + projectEntity.KeHuMingCheng + " 原值:" + oldProjectEntity.KeHuMingCheng + "<br>";
            }

            if (oldProjectEntity.KaiGaiRiQi != projectEntity.KaiGaiRiQi)
            {
                // changeMessage += "開改模日期被修改為:" + ((DateTime)projectEntity.KaiGaiRiQi).ToString(BaseSystemInfo.DateFormat) + " 原值:" + ((DateTime)oldProjectEntity.KaiGaiRiQi).ToString(BaseSystemInfo.DateFormat) + "<br>";
            }

            if (!String.IsNullOrEmpty(changeMessage))
            {
                BaseCommentManager commentManager = new BaseCommentManager(this.DbHelper, this.UserInfo);
                commentManager.Add("工程管理", projectEntity.Id.ToString(), projectEntity.KeHuXiangMuMingCheng, changeMessage, false, String.Empty, false, this.UserInfo.IPAddress);
            }

            return this.UpdateEntity(projectEntity);
        }
    }
}

引文鏈接:

3天搞定的小型B/S內部管理類軟件定制開發項目【軟件開發實戰10步驟詳解】


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM