![64b5d7221e94c5647c674dafb385b279.png](https://i-blog.csdnimg.cn/blog_migrate/a537f632d13058a37be8ef190b27a67a.jpeg)
欢迎来到真实的世界
无数的框架,让开发人员疲于学习.
你如果是开发过的客户端程序员, 或者说前端程序员. 你一定听说过MVC MVVM redux vue react ....其中的一种或者几种开发模式或者框架. 这些模式或者框架总是需要你花费很多时间去学习. 因为他们制定了一堆的规则, 还有各种名词, 还有各种限制. 这种成本在你入门时总是要付出.
为什么总是有人搞成很多框架, 然后还在不停的有新框架的新版本出来.很多老人表示"真的学不动了" . 特别是你更换平台,或者给多平台开发的时候.总是重新搞一套新框架. 这些事情不断地重复下.你应该会想到为啥?这是为啥? 为啥用户看到的东西并没有不同为啥需要几套不同的东西在做. 难道不应该有相同的东西在其中么?
![f27b3475bf1aefc08cc61f421be3fb33.png](https://i-blog.csdnimg.cn/blog_migrate/9d2b8e2afaf187da046be4426cc4ffd4.jpeg)
老娘真的学不动了!!
告诉你个惊天秘密,这些框架都有一个内在逻辑!
这些框架的共同性是什么? 他们应该在表达一件一样的事情. 应该有一个共同的逻辑,或者目的在里边. 笔者在开发过游戏, web, windows客户端,android ...等等项目后发现了一个惊天秘密!! 他们有个共同逻辑!!!
![5e3b876417d4aff8112141f8a755736c.png](https://i-blog.csdnimg.cn/blog_migrate/c79aaffc6dddcfd1c29ca2ed56c61d50.jpeg)
一个惊天大秘密
那就是所有的框架作者都在做的事情内在逻辑就是: "把UI部分和逻辑部分分开" 只要这么一个法则就可以使你摆脱所有的框架束缚, 即便使用新的平台,新的语言你都可以写出非常优雅的客户端程序. 即使你再使用其他框架,对其中的逻辑也会豁然开朗,知道如何灵活运用.
一个以此为指导的框架实现XFrame
https://github.com/fengshihao/XFrame 先别着急最后才看这个项目, 继续往下读.
要说明这个共同逻辑就要回到客户端程序刚开始的时候. 在计算机的洪荒时代,图形界面还没有的时候,计算机程序都是命令行形式的. 由用户一个字母一个字母的敲出相应命令来告诉程序,自己想要做什么的. 所以可以得到一个结论, 客户端程序是可以摆脱UI单独运行的.
![30c3a739364d3e0fd7c0d8cdce40c754.png](https://i-blog.csdnimg.cn/blog_migrate/0facbc7db6fd8309184211c8592e36a4.jpeg)
客户端程序刚开始是没有UI的
为什么要分开UI和逻辑代码? 因为他们本来就不是一起的.
即便到了今天无论多复杂程序都可以设计成是无UI运行的. 比如git, 或者无头浏览器(一种没有UI在服务器端用来分析动态网页用的浏览器).
![c7f8d9788aabc3d2577f299f41e88ff0.png](https://i-blog.csdnimg.cn/blog_migrate/31fcd32258e36d71c2100b318d909169.jpeg)
命令行下的git显示commit信息
没有界面,只用命令行,用户依然可以完成所有的工作,只是比较麻烦. 所以当图形界面操作系统诞生后,迅速的占领了市场. 随之带来的是客户端程序的复杂性增长. 特别是现在的开发者,都是从UI开始学起的.导致一个错误的直觉在刚开始就深植开发者心中, 就是UI是App的根本. 并且刚开是程序设计的时候就混入了太多的UI代码. 导致后续的开发特别的麻烦.
如何分开UI和逻辑代码?
正如上边说的. 刚开始设计程序的时候就把程序设计成无UI的, 或者说设计成命令行的. 命令行其实距离我们写程序时的API调用只差一点点了. 所以干脆刚开始就把程序设计成一堆API. 复杂的程序就是几组API. 每个API有不同的参数.
举个简单的例子,比如用户登录在没有UI的时候API调用就是这样的
![2f17ab2f0f388fd24bdfaf8ad5f9fc10.png](https://i-blog.csdnimg.cn/blog_migrate/e4eee5eb5eb0f4cfa5a413f4c8ba439a.jpeg)
无UI登录接口
用户在命令行使用这个app的时候就是 输入类似这样的命令行
login xxx yyy
然后程序会打印登录进程, 然后最终显示成功,或者失败, 然后才可以进行之后的操作. 程序执行的过程中都是阻塞的,用户不能做其他操作.
很显然的一个问题, 当有UI的时候,我们不能让ui阻塞, 得让UI不断地更新程序的运行状态. 这里我们采用观察者模式. 让UI实现一个接口, 这个接口是程序逻辑发生响应事件时回调给UI的. 接口看起来是这样的
![5232d7d935a9d7461c477091cd1b36cc.png](https://i-blog.csdnimg.cn/blog_migrate/d1693665c2a9a01f8a1333d122b0471a.jpeg)
逻辑部分实现第一个接口, UI部分实现第二个接口
有人说这个例子很简单,为啥不用Rx编程. 或者加一个回调函数就解决的问题. 为啥还要定义两个接口这么麻烦. 因为复杂的情况下rx 或者回调函数不能满足需求.
1 有的时候一个API调用会引起多个回调 ,比如下载,会有进度的回调, 成功回调, 失败的回调.
2 接收同一个回调事件的UI元素是多个, 比如一个页面同一个资源,上有两个下载入口(这种情况很常见), 点击一个开始下载后,下载入口就要disable ,然后开始显示下载进度, 然后成功后再把两个入口改为"已下载".
![57592bae9d7953aff91c78c6728b89f9.png](https://i-blog.csdnimg.cn/blog_migrate/77896818678d30f7978f1f5fd0d279d2.jpeg)
同一个逻辑层的事件多个UI响应
一些UI和逻辑分离的细节
记住最重要的原则: UI 和逻辑分离. 然后考虑每一部分代码是否违反这个原则. 下边的细则都可以推导出来. 关键这些东西都不依赖平台,不依赖语言, 非常容易在各个平台实现. 不需要多少代码. 可以做到无框架客户端开发了.
- UI的部分包括: view的显示,隐藏, 布局, 动画, 字体...
- 逻辑部分包括: 所有的IO请求, 网络请求, 数据库访问, 逻辑计算, 状态记录...
- 逻辑实现给用户调用的API 接口, 这些接口都要在UI线程调用.
- UI实现逻辑层的事件回调, 这些回调接口都在UI线程调用.
- UI依赖逻辑层代码, 但是逻辑层代码不依赖UI层代码. 这些可以通过自动检测做到. 把他们放到不同的文件夹下,所有UI代码放入ui文件夹, 所有的非UI代码放到logic文件夹下.
- 两层都会有些纯数据的model, 比如有个User的Model类, 里边有用户名, 头像.... 通常很多开发把逻辑的Model直接给UI使用, 这样是不对的. 不要复用逻辑的Model. 应为两边不是一样的目的, 比如有选中态,这个数据,只在UI这层有用, UI和逻辑需要靠Id来建立两个model的映射. 这点很重要.
因为UI和逻辑都是接口的实现, 所以会带来自然而然的好处.
- 两边都可以很好的被测试, 因为都是接口很容易mock假数据,假case来测试
- 很容实现面向切面编程, 比如在 逻辑API外加一层统计执行时间的代码, 如果超过16ms就报警告,这样很容易发现执行慢的API
- 回调接口包一层做线程检测, 保证所有的UI操作都在UI线程执行,
一个以此为指导的框架实现XFrame
XFrame 是为了详细说明上述内容该如何实现做的一个开源项目 https://github.com/fengshihao/XFrame
初衷是传播一种客户端编程的理念. XFrame是这个这种理念的Android上的实现.
为什么不给开发一个框架, 而是强调一个理念. 是因为框架是死的, 细节繁琐不适合人类记忆. 人类大脑适合思考,总结,抽象.
XFrame的代码就是用来表达这个理念的, 希望开发能从中能抽象出 UI代码和Logic代码分开 这么个思想. 如果只是口头介绍或者举例说明这个理念,仍然不够详细,让人不知道如何理解.