android接口类命名规范_Android包命名规范

写在前面

最近在做一个Android小游戏,Activity略多,按view, com, core, dao, service, util等等来分层总感觉不舒服,出去翻了一会儿才发现这样划分包名已经不是主流做法了

一.PBL(Package By Layer)

按层分包组织class,也就是传统做法,分为view, com, core, dao等等包,把职能相同的class放在一起

在default package下写完整个项目的所有class也不是不可以,但太多不相关的class挤在一起,且不说可维护性什么的,单是自己看着也难受

src

└─net

└─ayqy

└─app_gowithme

SearchPlan.java

ShowDetail.java

ShowMap.java

ShowRoute.java

// 或者稍微好一点点的

src

└─net

└─ayqy

└─app_notepad

DAO.java

Dialog.java

MainActivity.java

myEditText.java

ShowList.java

P.S.windows下,tree /f可以生成上面的东西

笔者习惯的包命名方法(或者说是类组织方法)是按照class职能(所谓的PBL)来分,比如:

src

│ summary.txt

└─net

└─ayqy

└─app_rsshelper

│ MainActivity.java

│ SettingActivity.java

├─com

├─core

│ Consts.java

│ Urls.java

├─dao

├─service

│ HtmlFetcher.java

│ JsInvoker.java

│ MainServ.java

│ RssFetcher.java

├─util

│ HtmlHelper.java

│ InputStream2String.java

│ RssHelper.java

└─vo

RssItem.java

各层职能如下:

default package

View层,定义Activity只实现UI展示,以及跳转

com(component)

自定义组件,包括自定义View和View组合

core

核心类,定义配置数据以及常量

dao(data access object)

db操作类,包括dbHelper

service

每个Activity对应一个Service,负责实现该Activity的业务逻辑,此外Service依赖的其它与Activity密切相关的类(需要Activity的context,比如JsInvoker)也在这里定义

util

工具类,包括modelHelper(比如RssHelper)

vo(value object)

model,或者说是bean,只包含数据结构定义以及getter/setter(需要的话还可以有equals、compareTo等等,反正尽量保持model纯粹)

笔者先接触了JSP,所以一直认为这套分层方法挺好,在Android里就照搬过来了(甚至搬到了WinForm和WPF),所幸项目规模都很小,没觉得有什么不妥,因为没有第二个方案可选

PBL的缺点如下:

package内低内聚低模块化

通常同一个包下的各个class彼此不相关,也可能永远不会相关

package之间高耦合

通常在一个class里需要import来自不同package的一堆东西

码起来麻烦

实现一块功能需要编辑不同目录下的多个文件,经常用IDE开一堆标签页还都舍不得关闭,因为关了不好找

同样,删起来也麻烦,在几个包下找来找去,一不小心就出错

二.PBF(Package By Feature)

按功能(模块)分包组织class,按app功能分为login、feedback、settings、orders、shipping等等,例如:

// 医药app

src

└─com

└─domain

└─app

├─doctor

│ DoctorAction.java - an action or controller object

│ Doctor.java - a Model Object

│ DoctorDAO.java - Data Access Object

│ database items (SQL statements)

│ user interface items (perhaps a JSP, in the case of a web app)

│ ...不只能放java代码,只要是该功能相关的都应该放在这里

├─drug

├─patient

├─report

├─security

├─webmaster

└─util

简单地说,每块功能对应一个package,包名就是功能名,除了通用的类定义在util之类的package下之外,实现该功能的所有类都在该package下

好处很明显,如下:

package内高内聚,package间低耦合

哪块要添新功能,只改某一个package下的东西

按class职能分层(PBL)降低了代码耦合,但带来了package耦合,要添新功能,需要改model、dbHelper、view、service等等,需要改动好几个package下的代码,改动的地方越多,越容易产生新问题,不是吗?

按功能分包(PBF),featureA相关的所有东西都在featureA包,feature内高内聚高度模块化,不同feature之间低耦合,相关的东西都放在一起,还好找

package有私有作用域(package-private scope)

你负责开发这块功能,这个目录下所有东西都是你的

PBL的方式是把所有工具方法都放在util包下,小张开发新功能时候发现需要一个xxUtil,但它又不是通用的,那应该放在哪里?没办法,按照分层原则,我们还得放在util包下,好像不太合适,但放在其它包更不合适,功能越来越多,util类也越定义越多。后来小李负责开发一块功能时发现需要一个xxUtil,同样不通用,去util包一看,怎么已经有了,而且还没法复用,只好放弃xx这个名字,改为xxxUtil……因为PBL的package没有私有作用域,每一个包都是public(跨包方法调用是很平常的事情,每一个包对其它包来说都是可访问的)

如果是PBF,小张的xxUtil自然放在feautreA下,小李的xxUtil在featureB下,如果觉得util好像是通用的,就去util包看看要不要把工具方法添进xxUtil,class命名冲突没有了

PBF的package有私有作用域,featureA不应该访问featureB下的任何东西(如果非访问不可,那就说明接口定义有问题)

很容易删除功能

统计发现新功能没人用,这个版本那块功能得去掉

如果是PBL,得从功能入口到整个业务流程把受到牵连的所有能删的代码和class都揪出来删掉,一不小心就完蛋

如果是PBF,好说,先删掉对应包,再删掉功能入口(删掉包后入口肯定报错了),完事

高度抽象

解决问题的一般方法是从抽象到具体,PBF包名是对功能模块的抽象,包内的class是实现细节,符合从抽象到具体,而PBL弄反了

PBF从确定AppName开始,根据功能模块划分package,再考虑每块的具体实现细节,而PBL从一开始就要考虑要不要dao层,要不要com层等等

只通过class来分离逻辑代码

PBL既分离class又分离package,而PBF只通过class来分离逻辑代码

没有必要通过package分离,因为PBL中也可能出现尴尬的情况:

├─service

│ MainServ.java

按照PBL,service包下的所有东西都是Controller,应该不需要Serv后缀,但实际上通常为了码起来方便,直接import service包,Serv后缀是为了避免引入的class和当前包下的class命名冲突,当然,不用后缀也可以,得写清楚包路径,比如new net.ayqy.service.Main(),麻烦

而PBF就很方便,无需import,直接new MainServ()即可

package的大小有意义了

PBL中包的大小无限增长是合理的,因为功能越添越多

而PBF中包太大(包里class太多)表示这块需要重构(划分子包)

三.PBF具体实践(Google I/O 2015)

java

└─com

└─google

└─samples

└─apps

└─iosched

│ AppApplication.java 定义Application类

│ Config.java 定义配置数据(常量)

├─about

│ AboutActivity.java

├─appwidget

│ ScheduleWidgetProvider.java

│ ScheduleWidgetRemoteViewsService.java

├─debug

│ │ DebugAction.java

│ │ DebugActivity.java

│ │ DebugFragment.java

│ │

│ └─actions

│ DisplayUserDataDebugAction.java

│ ForceAppDataSyncNowAction.java

│ ForceSyncNowAction.java

│ ...

├─explore

│ │ ExploreIOActivity.java

│ │ ExploreIOFragment.java

│ │ ExploreModel.java

│ │ ...

│ │

│ └─data

│ ItemGroup.java

│ LiveStreamData.java

│ MessageData.java

│ ...

├─feedback

│ FeedbackApiHelper.java

│ FeedbackConstants.java

│ FeedbackHelper.java

│ ...

├─framework

│ FragmentListener.java

│ LoaderIdlingResource.java

│ Model.java

│ ...定义interface并实现

├─gcm

│ │ GCMCommand.java

│ │ GCMIntentService.java

│ │ GCMRedirectedBroadcastReceiver.java

│ │ ...

│ │

│ └─command

│ AnnouncementCommand.java

│ NotificationCommand.java

│ SyncCommand.java

│ ...

├─io

│ │ BlocksHandler.java

│ │ HandlerException.java

│ │ HashtagsHandler.java

│ │ ...处理model

│ │

│ ├─map

│ │ └─model

│ │ MapData.java

│ │ Marker.java

│ │ Tile.java

│ │

│ └─model

│ Block.java

│ DataManifest.java

│ Hashtag.java

│ ...

├─map

│ │ InlineInfoFragment.java

│ │ MapActivity.java

│ │ MapFragment.java

│ │ ...

│ │

│ └─util

│ CachedTileProvider.java

│ MarkerLoadingTask.java

│ MarkerModel.java

│ ...

├─model

│ ScheduleHelper.java

│ ScheduleItem.java

│ ScheduleItemHelper.java

│ ...定义model以及实现model相关操作

├─myschedule

│ MyScheduleActivity.java

│ MyScheduleAdapter.java

│ MyScheduleFragment.java

│ ...

├─provider

│ ScheduleContract.java

│ ScheduleContractHelper.java

│ ScheduleDatabase.java

│ ...实现ContentProvider

│ (也在此处定义provider依赖的其它类,比如db操作)

├─receiver

│ SessionAlarmReceiver.java

├─service

│ DataBootstrapService.java

│ SessionAlarmService.java

│ SessionCalendarService.java

├─session

│ SessionDetailActivity.java

│ SessionDetailConstants.java

│ SessionDetailFragment.java

│ ...

├─settings

│ ConfMessageCardUtils.java

│ SettingsActivity.java

│ SettingsUtils.java

├─social

│ SocialActivity.java

│ SocialFragment.java

│ SocialModel.java

├─sync

│ │ ConferenceDataHandler.java

│ │ RemoteConferenceDataFetcher.java

│ │ SyncAdapter.java

│ │ ...

│ │

│ └─userdata

│ │ AbstractUserDataSyncHelper.java

│ │ OnSuccessListener.java

│ │ UserAction.java

│ │ ...

│ │

│ ├─gms

│ │ DriveHelper.java

│ │ GMSUserDataSyncHelper.java

│ │

│ └─util

│ UserActionHelper.java

│ UserDataHelper.java

├─ui

│ │ BaseActivity.java

│ │ CheckableLinearLayout.java

│ │ SearchActivity.java

│ │ ...BaseActivity以及自定义UI组件

│ │

│ └─widget

│ AspectRatioView.java

│ BakedBezierInterpolator.java

│ BezelImageView.java

│ ...自定义小UI控件

├─util

│ AboutUtils.java

│ AccountUtils.java

│ AnalyticsHelper.java

│ ...工具类,提供静态方法

├─videolibrary

│ VideoLibraryActivity.java

│ VideoLibraryFilteredActivity.java

│ VideoLibraryFilteredFragment.java

│ ...

└─welcome

AccountFragment.java

AttendingFragment.java

ConductFragment.java

...

上面除了按feature命名的package外,也定义了类似于layer的package,如下:

framework

io

model

provider

receiver

service

ui

util

对比一下PBL的一般规范,如下:

PBL一般规范

Google I/O 2015

activities(页面用到的Activity类)

feature/

base(页面中每个Activity类共享的可以写成一个BaseActivity类)

ui

adapter(页面用到的Adapter类)

通用的在ui里,不通用的在feature/

tools(公共工具方法类)

util

bean/unity(元素类)

model

db(数据库操作类)

数据库操作在provider里,数据处理(比如json解析)在io里

view/ui(自定义的View类)

ui

service(Service服务)

service

broadcast(Broadcast服务)

feature/

三.总结

参考Google I/O 2015的代码结构,PBF具体可以这样做:

src

└─com

└─domain

└─app

│ Config.java 配置数据、常量

├─framework

│ 定义interface以及相关基类

├─io

│ 数据定义(model)、数据操作(比如json解析,但不包括db操作)

├─model

│ 定义model(数据结构以及getter/setter、compareTo、equals等等,不含复杂操作)

│ 以及modelHelper(提供便于操作model的api)

├─provider

│ 实现ContentProvider,及其依赖的db操作

├─receiver

│ 实现Receiver

├─service

│ 实现Service(比如IntentService),用于在独立线程中异步do stuff

├─ui

│ 实现BaseActivity,以及自定义view和widget,相关的Adapter也放这里

├─util

│ 实现工具类,提供静态方法

├─feature1

│ Item.java 定义model

│ ItemHelper.java 实现modelHelper

│ feature1Activity.java 定义UI

│ feature1DAO.java 私有db操作

│ feature1Utils.java 私有工具函数

│ ...其它私有class

├─...其它feature

当然,这样的代码组织方案不仅仅适用于Android,用着觉得好就好

参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值