App架构设计经验谈:展示层的设计

原创文章,转载请注明:转载自Keegan小钢
并标明原文链接:http://keeganlee.me/post/architecture/20160222
微信订阅号:keeganlee_me
写于2016-02-22


App架构设计经验谈:接口的设计
App架构设计经验谈:技术选型
App架构设计经验谈:数据层的设计
App架构设计经验谈:业务层的设计
App架构设计经验谈:展示层的设计


三层架构中,数据层业务层都已经做过了简单的分享,最后,就剩下展示层了。本篇就给各位分享下我在展示层设计方面的一些经验心得。

展示层是三层架构中最复杂的一层了,需要考虑的包括但不限于界面布局、屏幕适配、文字大小、颜色、图片资源、提示信息、动画等等。展示层也是变化最频繁的一个层面,每天改得最多的就是界面了。因此,展示层也是最容易变得混乱不堪的一个层面。一个良好的展示层,应该有较好的可读性、健壮性、维护性、扩展性。

三原则

我在Android项目重构之路:界面篇中提到过三个原则,要设计好展示层,至少需要遵循好这三条基本的原则:

  1. 保持规范性:定义好开发规范,包括书写规范、命名规范、注释规范等,并按照规范严格执行;
  2. 保持单一性:布局就只做布局,内容就只做内容,各自分离好,每个方法、每个类,也只做一件事情;
  3. 保持简洁性:保持代码和结构的简洁,每个方法,每个类,每个包,每个文件,都不要塞太多代码或资源,感觉多了就应该拆分。

关于这三个原则详细的解说,界面篇已经讲过的,我这里就不再重复。在此,我只做些补充。

关于规范,Android方面,我已经分享过一套Android技术积累:开发规范,主要分为书写规范、命名规范、注释规范三部分。iOS方面,苹果已经有一套Coding Guidelines,主要属于命名方面的规范。当我们制定自己的开发规范时,首先就要遵守苹果的这份规范,在此基础上再加上自己的规范。

最重要的不是开发规范的制定,而是开发规范的执行。如果没有按照开发规范去执行,那开发规范就等于形同虚设,那代码混乱的问题依然得不到解决。

另外,Android系统本身已经对资源进行了很好的分离,字符串、颜色值、尺寸大小、图片、动画等等都用不同的xml文件定义。而iOS系统在这方面就逊色很多,只能自己实现,其中一种实现方案就是通过plist文件的方式实现和Android一样的机制。

工程结构

工程结构其实就是模块的划分,无非分为两类:按业务划分或按组件划分。

比如一个电商App,可能会有首页、附近、分类、我的四大模块,工程结构也根据这四大模块进行划分,Android可能就分为了四个模块包:

  • com.domain.home 首页
  • com.domain.nearby 附近
  • com.domain.category 分类
  • com.domain.user 我的

同样的,iOS则分为四个分组:home、nearby、category、user。

之后,每个模块下相应的页面就放入相应的模块。那么,问题来了,商品详情页应该属于哪个模块呢?首页会跳转到商品详情页,附近也会跳转到商品详情页,分类也会跳转到商品详情页,用户查看订单时也能跳转到商品详情页。有些页面,并不能很明显的区分出属于哪个模块的。我接手过的,按业务划分的二手项目中(即不是由我搭建的项目),我要找一个页面时,我认为应该属于A模块的,但在A模块却找不到,问了同事才知道在B模块。类似的情况出现过很多次,而且不止出现在我身上,对业务不熟悉的开发人员都会出现这个问题。而且,对业务不熟悉的开发人员开发新的页面或功能时,如果对业务理解不深,划分出错,那也将成为问题,其他人员要找该页面时更难找到了。

因此,我更喜欢按组件划分的工程结构,因为组件每个人都懂,不管对业务熟不熟悉,查找起来都明显方便很多。Android按组件划分大致如下:

  • com.domain.activities 存放所有的Activity
  • com.domain.fragments 存放所有的Fragment
  • com.domain.adapters 存放所有的Adapter
  • com.domain.services 存放所有的Service
  • com.domain.views 存放所有的自定义View
  • com.domain.utils 存放所有的工具类

iOS的分组则大致如下:

  • controllers 存放所有ViewController
  • cells 存放所有Cell,包括TableViewCell和CollectionViewCell
  • views 存放所有自定义控件或对系统控件的扩展
  • utils 存放所有的工具类

基类的定义

Android的Activity、Fragment、Adapter,iOS的ViewController,分别定义一个基类,将大部分通用的变量和方法定义和封装好,将减少很多工作量,而且有了统一的设置,也会减少代码的混乱。比如我在Android项目重构之路:实现篇中提到的KBaseActivity和KBaseAdapter的实现就是例子,当然还可以抽离出更多变量和方法。

每个Activity的onCreate()方法,一般分为三步:

  1. 变量的初始化;
  2. View的初始化;
  3. 加载数据。

因此,其实可以将onCreate()方法拆分成三个方法:

  1. initVariables()
  2. initViews()
  3. loadData()

在基类中将这三个方法定义为抽象方法,由子类去实现,这样,子类就不需要实现onCreate()方法了,只要实现更细化的上述三个方法即可。

iOS的ViewController也是同样的方式,这里就不重复了。

写在最后

自此,该系列的文章暂时就完结了,方法论比较多,很少涉及到具体的实现。因为具体实现的方案很多,而且还要结合实际项目,无法说哪个方案好哪个方案差。但方法论大部分是想通的,所以,本系列主要讲方法论。


扫描以下二维码即可关注订阅号。

Comments
Write a Comment
  • 风过无痕_haha reply

    嗯。

  • 有态度网友06MY6Y reply

    不错,学习了!

  • 齐晶 reply

    大侠!下次是否把生产环境中的架构分享之呢??

  • 齐晶 reply

    框架源码

  • 齐晶 reply

    大侠!下次是否把生产环境中的架构源码共享之呢??

  • 齐晶 reply

    大侠!下次是否把生产环境下的框架源码分享之呢?? 谢谢!

  • 地瓜超人闯天涯 reply

    我们项目现在遇到个情况:<br>core<br>module1<br>module2<br>core可以引用module1<br>core可以引用module2<br>但是不知道怎么<br>module1可以引用core<br>如何避免相互引用<br>还是要细粒度的再进行拆分

  • 有态度网友06MY5Z reply

    出现相互引用,那就是设计上的问题啦,将module1依赖于core的部分抽离到core就可以啦

  • 地瓜超人闯天涯 reply

    是的,我感觉和设计有关系。谢谢你。

  • 伪虾 reply

    初学者受益匪浅,谢谢你

  • 姚述智 reply

    感谢分享,受教了。

  • 有态度网友06MY7C reply
  • 有态度网友06MY5Z reply

    项目大了一般都是功能和分层结合的划分方式,而不是单一的采用功能划分或分层划分。另外,模块分得太多太细并不是好事。可以在大模块里再细分小模块,但不推荐从顶层就分太多。

  • 反革命攻城狮CasaTa reply

    大家可以去参照casatwy.com的架构谈文章,比这里出的早,而且这里的思想其实都在casatwy.com找得到,最重要的是,写得比这里好。

  • 有态度网友06MY8k reply

    呵呵

  • 飞宇青玄 reply

    我怎么感觉这些都是包建强《App研发录》里面的内容?

  • 有态度网友06MY5Z reply

    不想解释了,自己去比对。已经跟Casa撕逼过一次,不想再引发出和包大人的撕逼。

  • 有态度网友06MY8M reply

    傻逼

  • 有态度网友06MY6I reply

    对,这些思想都是包建强发明的,让他赶紧申请专利去。任何一个搞了几年的移动开发的,框架慢慢重构,这些东西谁不会?很多人只是没时间写出来而已。搞得好像他写了这些东西出来,别人在写就是抄袭了。没见过这么自以为是的人啊,长见识了。

  • Monad reply

    2B

  • 有态度网友06MY5V reply

    想请教一下,项目大了,在api层是不是要定义多个类似Api的接口,然后再定义多个ApiImpl,同理,core层的AppAction是不是也要定义多个呢?

  • 有态度网友06MYar reply

    谢谢分享

  • 有态度网友06PgWD reply

    项目目录按照组件划分的话,会造成一个困扰,因为开发任务都是根据业务划分的,如果按上面的方式,我们会在开发中不停的切换目录,很多时间会浪费在目录切换上

  • 美一分 reply

    对于移动应用来说,按组件划分会好些,移动应用的组件类型是有限的,而业务是不断变化的,而且对于同一个组件包下,不同业务的组件是可以通过规范的命名以及注释来区分的;如果一个应用业务量很大,那一定意味着有些业务是可以直接提炼成module的单独开发的,这样每一个module中的具体业务量并不会很多,按照组件分包,配合规范的命名,清新自然,查找文件,那怕对于业务一定都不了解的新人,只要知道移动开发的几大组件和常用控件,都可以很快能够理解。

  • 有态度网友06MY7C reply