不平凡軟件,始于2014

首頁(yè) | 加入收藏 | 設(shè)為首頁(yè)

15565077981

您當(dāng)前的位置:首頁(yè) >  軟件開(kāi)發(fā)知識(shí)>詳細(xì)

企業(yè)級(jí)軟件開(kāi)發(fā)架構(gòu)心得

發(fā)布者: 鄭州軟件開(kāi)發(fā) 07-24
什么是架構(gòu)

軟件架構(gòu)絕對(duì)不只是框架的堆砌,在我看來(lái),架構(gòu)是為了方便軟件維護(hù)、擴(kuò)展、安全性、切入性(我也不知道有沒(méi)有人提出過(guò)這個(gè)關(guān)鍵字,因?yàn)榈拇_很少看見(jiàn),簡(jiǎn)單來(lái)說(shuō):我這里說(shuō)的切入性就是指一個(gè)以前沒(méi)有接觸過(guò)這個(gè)項(xiàng)目的人,能快速加入到這個(gè)項(xiàng)目中,對(duì)項(xiàng)目進(jìn)行維護(hù)、修改和擴(kuò)展)
維護(hù)性

一個(gè)好的軟件(不一定是成功的軟件,這里說(shuō)的好只是程序員認(rèn)為的代碼方面)肯定是能方便維護(hù)的,出了問(wèn)題能快速定位,需要修改時(shí)能快速修改,并且在一定程度上不會(huì)說(shuō)一修改就一堆bug,這就是我認(rèn)為的可維護(hù)性,當(dāng)然后面要說(shuō)到的切入性其實(shí)也算是維護(hù)性,不過(guò)為什么單獨(dú)放出來(lái)在切入性時(shí)我會(huì)詳細(xì)說(shuō)明。至于怎么樣才能使一個(gè)軟件維護(hù)方便,我覺(jué)得有以下幾點(diǎn):

1.代碼規(guī)范

一份代碼如果沒(méi)有遵循任何規(guī)范,那么我相信它的可維護(hù)性是很差的,就算是你一個(gè)人做出來(lái)的,估計(jì)過(guò)了幾個(gè)月去修改的時(shí)候也會(huì)冒出一句這TM是什么鬼

2.框架穩(wěn)定性

很多時(shí)候很多開(kāi)源框架剛出來(lái)的時(shí)候,也許功能十分強(qiáng)大,但是畢竟剛出來(lái),沒(méi)有經(jīng)過(guò)充分的測(cè)試,所以還是會(huì)或多或少存在一個(gè)不穩(wěn)定因子,所以建議在選擇框架時(shí)盡量選擇成熟穩(wěn)定的框架,哪怕功能和性能的確比不上剛出來(lái)的框架。當(dāng)然這也不是說(shuō)完全不用剛出來(lái)的框架,畢竟都不用,那么它也永遠(yuǎn)成熟不了,至于到底用不用和怎么用,本文的框架選擇和使用篇也會(huì)詳細(xì)分析說(shuō)明

3.封裝

本來(lái)想說(shuō)AOP的,但是個(gè)人覺(jué)得很多專業(yè)性的名詞也比不上一些通俗的形容,畢竟本文主要的目的是讓人理解,不是提出理論。封裝這個(gè)在Android中是經(jīng)常使用的,簡(jiǎn)單來(lái)說(shuō)就是把一些常用的、通用的東西進(jìn)行一個(gè)封裝,通過(guò)統(tǒng)一入口進(jìn)行調(diào)用,這樣出問(wèn)題就只需要修改一個(gè)地方,就能全部修改過(guò)來(lái)。同時(shí)封裝也要注意一些常見(jiàn)的坑,比如我曾經(jīng)就踩過(guò)的context坑,當(dāng)時(shí)封裝了一個(gè)UIUtils(主要是針對(duì)UI相關(guān)的工具類),因?yàn)楹芏喾椒ǘ家褂胏ontext,所以直接application傳進(jìn)去,保存了,所有方法都不用傳context,但是這樣卻出了一個(gè)bug,那就是有些操作用application的context是有問(wèn)題的。當(dāng)然這種還比較好處理,但是如果因?yàn)榉庋b導(dǎo)致內(nèi)存泄露,這就難以查找了,比如你傳入了一個(gè)activity的context,但是activity已經(jīng)關(guān)閉了,但是因?yàn)槟惴庋b的方法里面還在繼續(xù)使用這個(gè)context,所以activity的內(nèi)存也是不會(huì)釋放的,所以封裝的時(shí)候也一定要注意,不要給自己挖坑

4.耦合

針對(duì)耦合這個(gè)東西相信很多文章都說(shuō)過(guò)了,如何解耦合,不過(guò)個(gè)人感覺(jué)解耦合這個(gè)東西也要適度,不要因?yàn)榻鉀Q一點(diǎn)耦合,花了大量的代碼,浪費(fèi)了大量的性能,所以解耦合這個(gè)東西就一定要把握這個(gè)度,過(guò)度設(shè)計(jì)是有問(wèn)題的設(shè)計(jì),這點(diǎn)我是贊同的。同時(shí)很多時(shí)候封裝會(huì)導(dǎo)致一些耦合的問(wèn)題,比如我曾經(jīng)一個(gè)項(xiàng)目中就有個(gè)這個(gè)一個(gè)情況:

因?yàn)轫?xiàng)目中使用了滑動(dòng)選取身高的WheelView,因?yàn)楫?dāng)時(shí)是彈Dialog出來(lái)選擇的,所以當(dāng)時(shí)想也沒(méi)想就直接封裝了一個(gè)Dialog,后面又出來(lái)了一個(gè)選取年齡的,然后又封裝了一個(gè)Dialog,以至于到后面封裝的Dialog有7,8個(gè)了,但是有些界面因?yàn)檫x中后的處理有些不一樣,導(dǎo)致Dialog里面的代碼混亂,所以后面就直接簡(jiǎn)單的封裝了一個(gè)Dialog,傳入需要選中的數(shù)據(jù)集合和選中監(jiān)聽(tīng),這樣就用了一個(gè)Dialog就能處理多種數(shù)據(jù)的選擇,還能根據(jù)不同界面分別處理,當(dāng)然這樣也不是萬(wàn)金油,畢竟這樣每個(gè)界面都需要自己實(shí)現(xiàn)監(jiān)聽(tīng),所以很多時(shí)候有利就有弊,至于具體怎么取舍,就看利是否大于弊
擴(kuò)展性

擴(kuò)展性簡(jiǎn)單來(lái)說(shuō)就是當(dāng)程序需要新的功能時(shí),能否對(duì)其進(jìn)行擴(kuò)展以及擴(kuò)展的難度來(lái)判斷,如何提高擴(kuò)展性,我覺(jué)得有以下幾點(diǎn):

1.抽象接口

這點(diǎn)相信大家都經(jīng)常遇到,比如Android的點(diǎn)擊事件,你想要實(shí)現(xiàn)什么樣的點(diǎn)擊效果,自己實(shí)現(xiàn)一個(gè)點(diǎn)擊監(jiān)聽(tīng),然后設(shè)置給控件就可以了

2.元素重用

很多時(shí)候,很多功能模塊可能使用到相同或者類似的元素,如Android中的一些布局,這些如果抽取出公共部分在進(jìn)行擴(kuò)展的時(shí)候方便對(duì)其快速擴(kuò)展,當(dāng)然這個(gè)是項(xiàng)目一開(kāi)始并不能預(yù)見(jiàn)的,所以需要在開(kāi)發(fā)中不斷的去重構(gòu)

3.單一職責(zé)

這個(gè)其實(shí)就是面向?qū)ο蟮膯我宦氊?zé),比如前面提到的Dialog,一開(kāi)始只有選擇身高的功能,看起來(lái)是單一職責(zé),但是其實(shí)相關(guān)處理也包含在其中,所以那個(gè)Dialog類本身職責(zé)已經(jīng)不單純,當(dāng)然如果一直只有這一個(gè),這樣做沒(méi)有任何問(wèn)題,也能看做單一職責(zé),但是如果有多個(gè)選擇和處理的時(shí)候,就必須對(duì)其重構(gòu)了

4.替換性

替換性包含里氏代換但是也不僅僅是里氏代換,比如常見(jiàn)的Android布局不同,但是其顯示內(nèi)容大致相同,這樣寫布局的時(shí)候就可以對(duì)相同內(nèi)容的控件指定相同的id,這樣就算替換布局,也不用重寫ViewHolder,當(dāng)然對(duì)于Adapter也僅僅只需要替換相應(yīng)的布局就ok

5.耦合

這個(gè)和維護(hù)的耦合相同,畢竟很多地方本來(lái)就存在交叉,所以就沒(méi)有必要再說(shuō)了
安全性

個(gè)人覺(jué)得數(shù)據(jù)安全性并不僅僅是數(shù)據(jù)安全,還有程序的一些操作安全性(簡(jiǎn)單來(lái)說(shuō)就是避免程序出現(xiàn)一些非崩潰性異常)

1.數(shù)據(jù)安全性

數(shù)據(jù)安全就包括數(shù)據(jù)抓取、數(shù)據(jù)攔截以及數(shù)據(jù)修改。當(dāng)然這些并不能完全避免,只能是由我們寫出盡量安全的代碼,比如關(guān)鍵數(shù)據(jù)使用HTTPS以及對(duì)數(shù)據(jù)進(jìn)行md5驗(yàn)證完整性,對(duì)于數(shù)據(jù)修改,可以通過(guò)多文件多地址保存文件修改記錄,來(lái)確定保存的數(shù)據(jù)是否被修改,畢竟Android只要獲取root權(quán)限,就能對(duì)很多文件進(jìn)行修改了

2.操作安全性

簡(jiǎn)單來(lái)說(shuō)經(jīng)常遇到的一個(gè)問(wèn)題,比如按鈕的點(diǎn)擊事件,有可能這個(gè)點(diǎn)擊事件是請(qǐng)求網(wǎng)絡(luò)或者打開(kāi)Activity,這樣就會(huì)存在事件還未處理完成再次收到事件,只要你一直猛點(diǎn),肯定可以的,所以這樣就需要我們對(duì)控件事件進(jìn)行一些封裝,比如打開(kāi)界面的,可以在點(diǎn)擊后禁用按鈕,界面打開(kāi)完成后才啟用,請(qǐng)求網(wǎng)絡(luò)的可以在開(kāi)始就禁用按鈕,請(qǐng)求結(jié)果反饋了才啟用(不管是請(qǐng)求成功或者失?。?/span>
切入性

切入性就是當(dāng)另外一個(gè)從未接觸過(guò)此項(xiàng)目的人,能快速進(jìn)入這個(gè)項(xiàng)目進(jìn)行開(kāi)發(fā),當(dāng)然想要切入性好,前面的維護(hù)和擴(kuò)展是必須要滿足的,下面我就說(shuō)說(shuō)我認(rèn)為能增加切入性的一些點(diǎn)

1.文檔

開(kāi)發(fā)都不喜歡寫文檔,這是肯定的,但是每當(dāng)我們?nèi)ソ邮忠粋€(gè)項(xiàng)目的時(shí)候,發(fā)現(xiàn)沒(méi)有文檔估計(jì)就要開(kāi)始罵娘了,所以文檔不僅要寫,還要寫的規(guī)范。我認(rèn)為開(kāi)發(fā)中必須要有的幾個(gè)文檔:代碼規(guī)范文檔(比如包名規(guī)范,文件命名規(guī)范,id命名規(guī)范等等,具體依據(jù)項(xiàng)目情況而定)、接口文檔

2.注釋

每個(gè)類必須要有注釋,方法也要有注釋,同時(shí)也要標(biāo)注好方法最后修改人是誰(shuí),這樣出現(xiàn)疑問(wèn)或者問(wèn)題別人就知道該去找誰(shuí)了,當(dāng)然有些方法是不需要有注釋的,比如重寫父類的方法,只是如果方法內(nèi)邏輯很復(fù)雜,可以在方法中添加一些對(duì)邏輯的說(shuō)明。當(dāng)然注釋也不是越多越好,具體注釋該怎么寫,Google最清楚,不能Google百度也行

3.包名

什么類放什么包簡(jiǎn)單,但是一但一個(gè)包中的類太多,也是非常不方便,所以正確的分包也是非常重要的,目前常見(jiàn)的Android分包包括針對(duì)功能分包(不是指程序功能,而是指UI,http,bean這些功能),還有就是模塊分包(這就是程序的功能了,比如login,user等),當(dāng)然具體怎么分包需要團(tuán)隊(duì)協(xié)商,防止一個(gè)包中類太多,而我現(xiàn)在一個(gè)程序很大的情況下,采用的分包是先功能分包,再模塊分包,比如:
wang.raye.demo
|-activity
| |-user
| |-login
|-fragment
| |–user
| |–login

這樣能減少每個(gè)包的類數(shù)量,當(dāng)然如果項(xiàng)目本身并不是很大,可以完全不用這種分包模式,畢竟如果只是小項(xiàng)目,這樣會(huì)使項(xiàng)目變得更加難以閱讀
MVC 還是 MVP

現(xiàn)在針對(duì)移動(dòng)端開(kāi)發(fā),衍生了很多種架構(gòu),如MVC、MVP、MVVP,當(dāng)然這里著重分析MVC和MVP,畢竟MVVP我也只是了解過(guò)一下,沒(méi)有詳細(xì)接觸,至于什么是MVC和MVP我也不想做過(guò)多描述,這類的文章實(shí)在太多,這里主要分析一下什么情況下用MVC和MVP

MVC

MVC是以XML布局為V(視圖),Activity或Fragment為C(控制器),數(shù)據(jù)實(shí)體為M(模型),但是因?yàn)閄ML的局限性,所以其實(shí)我們還是需要在Activity或Fragment中對(duì)視圖進(jìn)行操作,所以這也就是為什么那么多人抵制MVC的原因,因?yàn)檫@也算不上完整的MVC

優(yōu)點(diǎn):開(kāi)發(fā)迅速,結(jié)構(gòu)易理解
缺點(diǎn):當(dāng)一個(gè)界面業(yè)務(wù)邏輯一多,不方便維護(hù)

MVP

MVP是為XML配合Activity或Fragment為V(視圖),同時(shí)抽象出接口,界面相關(guān)業(yè)務(wù)抽離出來(lái)的P(Presenter)同時(shí)通過(guò)視圖接口來(lái)更新UI,數(shù)據(jù)實(shí)體為M(模型)

優(yōu)點(diǎn):業(yè)務(wù)發(fā)生變化時(shí)易修改,同時(shí)能減少修改過(guò)程中引發(fā)bug,也能將多人協(xié)同開(kāi)發(fā)充分調(diào)用起來(lái)(并不是針對(duì)一個(gè)人負(fù)責(zé)一個(gè)模塊的模式,而是多人協(xié)同開(kāi)發(fā)一個(gè)模塊)
缺點(diǎn):開(kāi)發(fā)速度會(huì)有所降低

所以對(duì)比2種架構(gòu),發(fā)現(xiàn)MVC適合不需要太多業(yè)務(wù)邏輯和功能性少的APP,比如數(shù)據(jù)展示類應(yīng)用,MVP適合每個(gè)界面有復(fù)雜邏輯以及大型多人開(kāi)發(fā)的APP
框架選擇及使用 如何選擇框架

1.穩(wěn)定性

如果框架本身就不穩(wěn)定,那么導(dǎo)致的結(jié)果就是程序本身也會(huì)漏洞百出,所以選擇框架一定要選擇經(jīng)歷過(guò)考驗(yàn)的穩(wěn)定的框架

2.擴(kuò)展性

隨著程序功能的增加,以前的框架可能會(huì)出現(xiàn)功能不足的情況,但是因?yàn)檫@點(diǎn)是不可預(yù)見(jiàn)的,所以我們選擇框架時(shí)一定要了解好框架本身的擴(kuò)展性如何,或者對(duì)框架有較深的理解,能夠自己擴(kuò)展框架,當(dāng)然有些框架解決的問(wèn)題比較單一,一般也不用擔(dān)心過(guò)多的擴(kuò)展性,比如Butterknife或PreIOC這類單一性框架,但是有些框架經(jīng)常需要配合做一些操作,比如圖片加載框架,常見(jiàn)的一些就是清理圖片緩存、獲取圖片緩存大小、顯示圓角或者圓形圖片, 常用的圖片加載框架UniversalImageLoader都提供了相關(guān)的方法或接口來(lái)實(shí)現(xiàn)

3.封裝性

封裝性是指能否針對(duì)框架進(jìn)行二次封裝,以及封裝后的耦合度,詳細(xì)會(huì)在使用篇說(shuō)明
如何使用

選擇好了框架千萬(wàn)不要拿來(lái)就用,因?yàn)樵俸玫目蚣芤灿兴窒薜牡胤?,?dāng)然你也可以簡(jiǎn)單的在遇到這個(gè)框架不能實(shí)現(xiàn)的時(shí)候,添加另外一種框架,只是這樣項(xiàng)目會(huì)越來(lái)越大,對(duì)于APP來(lái)說(shuō)APK也越來(lái)越大,65535 的問(wèn)題也會(huì)提前出現(xiàn),所以為了方便以后有可能出現(xiàn)的切換框架,以及防止初期對(duì)框架使用不熟悉而引發(fā)出新的bug,在選擇好了框架后,一定要對(duì)框架進(jìn)行二次封裝,當(dāng)然有些框架是不需要二次封裝的,比如前面說(shuō)的單一性的框架Butterknife或PreIOC,但是像UniversalImageLoader、OKHttp等框架,必須要進(jìn)行二次封裝,至于封裝原則,則是封裝后,調(diào)用框架對(duì)于調(diào)用代碼來(lái)說(shuō)是透明的,簡(jiǎn)單來(lái)說(shuō),就是對(duì)于框架調(diào)用都通過(guò)一個(gè)統(tǒng)一的入口進(jìn)入,并且調(diào)用時(shí),不需要傳入任何跟框架相關(guān)的東西,如果必須要傳入接口,可以通過(guò)繼承框架來(lái)實(shí)現(xiàn)新的接口傳入,這樣在真正的使用框架的地方,沒(méi)有任何關(guān)于框架的引用

封裝的好處

之所以要這樣封裝,最大的好處就是一旦框架不能滿足需求時(shí),需要進(jìn)行框架更換時(shí),只需要換掉框架,同時(shí)修改統(tǒng)一入口處的代碼,就能快速的替換整個(gè)框架

以上就是我在Android APP架構(gòu)上面的一些心得,此文可能并沒(méi)有教你快速搭建一個(gè)框架,只是指明搭建框架時(shí)需要注意和搭建框架的一個(gè)方向,當(dāng)然軟件是死的人是活的,具體項(xiàng)目具體處理。
返回列表

上一篇

鄭州短視頻小程序開(kāi)發(fā)制作短視頻小程序

下一篇

軟件開(kāi)發(fā)項(xiàng)目的技術(shù)方案編寫格式

相關(guān)新聞

相關(guān)案例