diff --git a/.DS_Store b/.DS_Store index 5693f8e..3cfdfa0 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.vscode/1.96.md b/.vscode/1.96.md new file mode 100644 index 0000000..894b632 --- /dev/null +++ b/.vscode/1.96.md @@ -0,0 +1,14 @@ +# 一个提高 App 运算性能的想法 + +想到了一个场景,大概是客户端、H5 网页端、Electron 桌面端都需要大量的 DB 操作、JS 执行大量数据的计算。这些常见的共同特点是计算特别大,耗费 CPU 算力。想到了 H5 网页、Electron 等都会使用 GPU 去渲染,那么这些复杂计算,能不能也利用 GPU 强大的算力去实现。 + + +考虑到某些机器上可能没有 GPU 能力,感觉可以做一个封装,内部根据当前内存情况、GPU 情况,派发任务到 GPU 还是普通的 JS 单线程的异步任务上,没有 GPU 则直接使用异步任务 + +由于我们的场景会存在很多的离线能力,所以这个时候很多的计算都需要本地完成,后续的 PC 收银参考客户端,做离线 DB 的操作、营销 JS 计算、很多运算都可以放 GPU + +比如,营销 JS 的计算代码,目前就在客户端(iOS、Android)存在,H5 JS 也存在,那么 PC 收银桌面端,也可以享用这个能力。 + +利用 CommonJS 规范,Webpack 打包出一个 distJS,多个端服用。内部判断当前设备支不支持 GPU,支持则在 GPU 上运算,不支持则在 CPU 上异步计算。 + +前端开源了 [gpu.js](https://github.com/gpujs/gpu.js],同样客户端也可以实现类似的设计。做到一个高性能计算的效果。 \ No newline at end of file diff --git a/Chapter1 - iOS/1.44.md b/Chapter1 - iOS/1.44.md index 82e5899..ca90742 100644 --- a/Chapter1 - iOS/1.44.md +++ b/Chapter1 - iOS/1.44.md @@ -1,15 +1,15 @@ # 一个 Hybrid SDK 设计与实现 -随着移动浪潮的兴起,各种 App 层出不穷,极速发展的业务拓展提升了团队对开发效率的要求,这个时候纯粹使用 Native 开发技术成本难免会更高一点。而 H5 的低成本、高效率、跨平台等特性马上被利用起来了,形成一种新的开发模式: Hybrid App - -作为一种混合开发的模式,Hybrid App 底层依赖于 Native 提供的容器(Webview),上层使用各种前端技术完成业务开发(现在三足鼎立的 Vue、React、Angular),底层透明化、上层多样化。这种场景非常有利于前端介入,非常适合业务的快速迭代。于是 Hybrid 火了。 - -大道理谁都懂,但是按照我知道的情况,还是有非常多的人和公司在 Hybrid 这一块并没有做的很好,所以我将我的经验做一个总结,希望可以帮助广大开发者的技术选型有所帮助 +> 随着移动浪潮的兴起,各种 App 层出不穷,极速发展的业务拓展提升了团队对开发效率的要求,这个时候纯粹使用 Native 开发技术成本难免会更高一点。而 H5 的低成本、高效率、跨平台等特性马上被利用起来了,形成一种新的开发模式: Hybrid App +> +> 作为一种混合开发的模式,Hybrid App 底层依赖于 Native 提供的容器(Webview),上层使用各种前端技术完成业务开发(现在三足鼎立的 Vue、React、Angular),底层透明化、上层多样化。这种场景非常有利于前端介入,非常适合业务的快速迭代。于是 Hybrid 火了。 +> +> 大道理谁都懂,但是按照我知道的情况,还是有非常多的人和公司在 Hybrid 这一块并没有做的很好,所以我将我的经验做一个总结,希望可以帮助广大开发者的技术选型有所帮助 -## Hybrid 的一个现状 +## 一、Hybrid 现状 可能早期都是 PC 端的网页开发,随着移动互联网的发展,iOS、Android 智能手机的普及,非常多的业务和场景都从 PC 端转移到移动端。开始有前端开发者为移动端开发网页。这样子早期资源打包到 Native App 中会造成应用包体积的增大。越来越多的业务开始用 H5 尝试,这样子难免会需要一个需要访问 Native 功能的地方,这样子可能早期就是懂点前端技术的 Native 开发者自己封装或者暴露 Native 能力给 JS 端,等业务较多的时候者样子很明显不现实,就需要专门的 Hybrid 团队做这个事情;量大了,就需要规矩,就需要规范。 @@ -27,12 +27,12 @@ Hybrid 在大量应用的时候就需要一定的规范,那么本文将讨论 -## Native 与前端分工 +## 二、Native 与前端分工 在做 Hybird 架构设计之前我们需要分清 Native 与前端的界限。首先 Native 提供的是宿主环境,要合理利用 Native 提供的能力,要实现通用的 Hybrid 架构,站在大前端的视觉,我觉得需要考虑以下核心设计问题。 -### 交互设计 +### 1. 交互设计 Hybrid 架构设计的第一要考虑的问题就是如何设计前端与 Native 的交互,如果这块设计不好会对后续的开发、前端框架的维护造成深远影响。并且这种影响是不可逆、积重难返。所以前期需要前端与 Native 好好配合、提供通用的接口。比如 @@ -43,14 +43,14 @@ Hybrid 架构设计的第一要考虑的问题就是如何设计前端与 Native -### 账号信息设计 +### 2. 账号信息设计 账号系统是重要且无法避免的,Native 需要设计良好安全的身份验证机制,保证这块对业务开发者足够透明,打通账户体系 -### Hybrid 开发调试 +### 3. Hybrid 开发调试 功能设计、编码完并不是真正结束,Native 与前端需要商量出一套可开发调试的模型,不然很多业务开发的工作难以继续。 @@ -67,7 +67,7 @@ Android 调试技巧: -## Hybrid 交互设计 +## 三、Hybrid 交互设计 Hybrid 交互无非是 Native 调用 H5 页面JS 方法,或者 H5 页面通过 JS 调 Native 提供的接口。2者通信的桥梁是 Webview。 业界主流的通信方法:1.桥接对象(时机问题,不太主张这种方式);2.自定义 Url scheme @@ -82,7 +82,7 @@ weixin:// 可以打开微信。 -### JS to Native +### 1. JS to Native Native 在每个版本都会提供一些 Api,前端会有一个对应的框架团队对其封装,释放业务接口。举例 @@ -116,7 +116,7 @@ SDGHybridReady(function(arg){ -### Api 交互 +### 2. Api 交互 调用 Native Api 接口的方式和使用传统的 Ajax 调用服务器,或者 Native 的网络请求提供的接口相似 ![Api交互](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/HybridApi.jpg) @@ -128,7 +128,7 @@ SDGHybridReady(function(arg){ -### 格式约定 +### 3. 格式约定 交互的第一步是设计数据格式。这里分为请求数据格式与响应数据格式,参考 Ajax 模型: ``` @@ -295,13 +295,13 @@ typedef NS_ENUM(NSInteger){ -## 常用交互 Api +## 四、常用交互 Api 良好的交互设计是第一步,在真实业务开发中有一些 Api 一定会由应用场景。 -### 跳转 +### 1. 跳转 跳转是 Hybrid 必用的 Api 之一,对前端来说有以下情况: - 页面内跳转,与 Hybrid 无关 - H5 跳转 Native 界面 @@ -361,8 +361,7 @@ back 与 forward 一致,可能会有 animatetype 参数决定页面切换的 - -## Header 组件的设计 +### 2. Header 组件的设计 Native 每次改动都比较“慢”,所以类似 Header 就很需要。 1. 主流容器都是这么做的,比如微信、手机百度、携程 @@ -590,8 +589,7 @@ define([], function () { - -## 请求类 +### 3. 请求类 虽然 get 类请求可以用 jsonp 方式绕过跨域问题,但是 post 请求是一个拦路虎。为了安全性问题服务器会设置 cors 仅仅针对几个域名,Hybrid 内嵌静态资源可能是通过本地 file 的方式读取,所以 cors 就行不通了。另外一个问题是防止爬虫获取数据,由于 Native 针对网络做了安全性设置(鉴权、防抓包等),所以 H5 的网络请求由 Native 完成。可能有些人说 H5 的网络请求让 Native 走就安全了吗?我可以继续爬取你的 Dom 节点啊。这个是针对反爬虫的手段一。想知道更多的反爬虫策略可以看看我这篇文章 [Web反爬虫方案](https://github.com/FantasticLBP/Anti-WebSpider) @@ -628,7 +626,7 @@ requestHybrid({ -## 常用 NativeUI 组件 +## 五、常用 NativeUI 组件 一般情况 Native 通常会提供常用的 UI,比如 加载层loading、消息框toast @@ -663,7 +661,7 @@ Native UI与前端UI不容易打通,所以在真实业务开发过程中,一 -## 账号系统的设计 +## 六、账号系统的设计 Webview 中跑的网页,账号登录与否由是否携带密钥 cookie 决定(不能保证密钥的有效性)。因为 Native 不关注业务实现,所以每次载入都有可能是登录成功跳转回来的结果,所以每次载入都需要关注密钥 cookie 变化,以做到登录态数据的一致性。 @@ -704,7 +702,7 @@ HybridUI.logout = function () { -## Hybrid 资源管理 +## 七、Hybrid 资源管理 Hybrid 的资源需要 `增量更新` 需要拆分方便,所以一个 Hybrid 资源结构类似于下面的样子 @@ -738,7 +736,7 @@ WebApp -## 增量更新 +## 八、增量更新 每次业务开发完毕后都需要在打包分发平台进行部署上线,之后会生成一个版本号。 @@ -760,9 +758,9 @@ WebApp -## 一些零散的解决方案 +## 九、体验优化 -1. 静态直出 +### 1. 静态直出 “直出”这个概念对前端同学来说,并不陌生。为了优化首屏体验,大部分主流的页面都会在服务器端拉取首屏数据后通过 NodeJs 进行渲染,然后生成一个包含了首屏数据的 Html 文件,这样子展示首屏的时候,就可以解决内容转菊花的问题了。 当然这种页面“直出”的方式也会带来一个问题,服务器需要拉取首屏数据,意味着服务端处理耗时增加。 @@ -771,18 +769,16 @@ WebApp 我们可以做一个类似的事情,自动同步最新的代码和数据,然后生成新的含首屏 Html,并发布到 CDN 上面去 - -2. 离线预推 +### 2. 离线预推 页面发布到 CDN 上面去后,那么 WebView 需要发起网络请求去拉取。当用户在弱网络或者网速比较差的环境下,这个加载时间会很长。于是我们通过离线预推的方式,把页面的资源提前拉取到本地,当用户加载资源的时候,相当于从本地加载,即使没有网络,也能展示首屏页面。这个也就是大家熟悉的离线包。 手 Q 使用 7Z 生成离线包, 同时离线包服务器将新的离线包跟业务对应的历史离线包进行 BsDiff 做二进制差分,生成增量包,进一步降低下载离线包时的带宽成本,下载所消耗的流量从一个完整的离线包(253KB)降低为一个增量包(3KB)。 - -https://mp.weixin.qq.com/s?__biz=MzUxMzcxMzE5Ng==&mid=2247488218&idx=1&sn=21afe07eb642162111ee210e4a040db2&chksm=f951a799ce262e8f6c1f5bb85e84c2db49ae4ca0acb6df40d9c172fc0baaba58937cf9f0afe4&scene=27#wechat_redirect +[手Q开源Hybrid框架VasSonic介绍,极致的页面加载速度优化](https://mp.weixin.qq.com/s?__biz=MzUxMzcxMzE5Ng==&mid=2247488218&idx=1&sn=21afe07eb642162111ee210e4a040db2&chksm=f951a799ce262e8f6c1f5bb85e84c2db49ae4ca0acb6df40d9c172fc0baaba58937cf9f0afe4&scene=27#wechat_redirect) -3. 拦截加载 +### 3. 拦截加载 事实上,在高度定制的 wap 页面场景下,我们对于 webview 中可能出现的页面类型会进行严格控制。可以通过内容的控制,避免 wap 页中出现外部页面的跳转,也可以通过 webview 的对应代理方法,禁掉我们不希望出现的跳转类型,或者同时使用,双重保护来确保当前 webview 容器中只会出现我们定制过的内容。既然 wap 页的类型是有限的,自然想到,同类型页面大都由前端采用模板生成,页面所使用的 html、css、js 的资源很可能是同一份,或者是有限的几份,把它们直接随客户端打包在本地也就变得可行。加载对应的 url 时,直接 load 本地的资源。 对于 webview 中的网络请求,其实也可以交由客户端接管,比如在你所采用的 Hybrid 框架中,为前端注册一个发起网络请求的接口。wap 页中的所有网络请求,都通过这个接口来发送。这样客户端可以做的事情就非常多了,举个例子,NSURLProtocol 无法拦截 WKWebview 发起的网络请求,采用 Hybrid 方式交由客户端来发送,便可以实现对应的拦截。 @@ -792,25 +788,46 @@ https://mp.weixin.qq.com/s?__biz=MzUxMzcxMzE5Ng==&mid=2247488218&idx=1&sn=21afe0 NSURLProtocol能够让你去重新定义苹果的URL加载系统(URL Loading System)的行为,URL Loading System里有许多类用于处理URL请求,比如NSURL,NSURLRequest,NSURLConnection和NSURLSession等。当URL Loading System使用NSURLRequest去获取资源的时候,它会创建一个NSURLProtocol子类的实例,你不应该直接实例化一个NSURLProtocol,NSURLProtocol看起来像是一个协议,但其实这是一个类,而且必须使用该类的子类,并且需要被注册。                                        -4. WKWebView 网络请求拦截 -方法一(Native 侧): -原生 WKWebView 在独立于 app 进程之外的进程中执行网络请求,请求数据不经过主进程,因此在 WKWebView 上直接使用 NSURLProtocol 是无法拦截请求的。 -但是由于 mPaas 的离线包机制强依赖网络拦截,所以基于此,mPaaS 利用了 WKWebview 的隐藏 api,去注册拦截网络请求去满足离线包的业务场景需求,参考代码如下: +### 4. WKWebView 网络请求拦截 -```Objective-c -[WKBrowsingContextController registerSchemeForCustomProtocol:@"https"] -``` -但是因为出于性能的原因,WKWebView 的网络请求在给主进程传递数据的时候会把请求的 body 去掉,导致拦截后请求的 body 参数丢失。 +- 方法一(Native 侧): + 原生 WKWebView 在独立于 app 进程之外的进程中执行网络请求,请求数据不经过主进程,因此在 WKWebView 上直接使用 NSURLProtocol 是无法拦截请求的。 -在离线包场景,由于页面的资源不需要 body 数据,所以离线包可以正常使用不受影响。但是在 H5 页面内的其他 post 请求会丢失 data 参数。 + 但是由于 mPaas 的离线包机制强依赖网络拦截,所以基于此,mPaaS 利用了 WKWebview 的隐藏 api,去注册拦截网络请求去满足离线包的业务场景需求,参考代码如下: -为了解决 post 参数丢失的问题,mPaas 通过在 js 注入代码,hook 了 js 上下文里的 XMLHTTPRequest 对象解决。 + ```Objective-c + [WKBrowsingContextController registerSchemeForCustomProtocol:@"https"] + ``` -通过在 JS 层把方法内容组装好,然后通过 WKWebView 的 messageHandler 机制把内容传到主进程,把对应 HTTPBody 然后存起来,随后通知 JS 端继续这个请求,网络请求到主进程后,在将 post 请求对应的 HttpBody 添加上,这样就完成了一次 post 请求的处理。整体流程可以参考如下: -![ajax-时序图](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2021-05-28-WKWebViewRequestHook) -通过上面的机制,既满足了离线包的资源拦截诉求,也解决了 post 请求 body 丢失的问题。但是在一些场景还是存在一些问题,需要开发者进行适配。 + 但是因为出于性能的原因,WKWebView 的网络请求在给主进程传递数据的时候会把请求的 body 去掉,导致拦截后请求的 body 参数丢失。 -方法二(JS 侧): -通过 AJAX 请求的 hook 方式,将网络请求的信息代理到客户端本地。能拿到 WKWebView 里面的 post 请求信息,剩下的就不是问题啦。 -AJAX hook 的实现可以看这个 [Repo](https://github.com/wendux/Ajax-hook). \ No newline at end of file + 在离线包场景,由于页面的资源不需要 body 数据,所以离线包可以正常使用不受影响。但是在 H5 页面内的其他 post 请求会丢失 data 参数。 + + 为了解决 post 参数丢失的问题,mPaas 通过在 js 注入代码,hook 了 js 上下文里的 XMLHTTPRequest 对象解决。 + + 通过在 JS 层把方法内容组装好,然后通过 WKWebView 的 messageHandler 机制把内容传到主进程,把对应 HTTPBody 然后存起来,随后通知 JS 端继续这个请求,网络请求到主进程后,在将 post 请求对应的 HttpBody 添加上,这样就完成了一次 post 请求的处理。整体流程可以参考如下: + ![ajax-时序图](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2021-05-28-WKWebViewRequestHook) + 通过上面的机制,既满足了离线包的资源拦截诉求,也解决了 post 请求 body 丢失的问题。但是在一些场景还是存在一些问题,需要开发者进行适配。 + +- 方法二(JS 侧): + 通过 AJAX 请求的 hook 方式,将网络请求的信息代理到客户端本地。能拿到 WKWebView 里面的 post 请求信息,剩下的就不是问题啦。 + AJAX hook 的实现可以看这个 [Repo](https://github.com/wendux/Ajax-hook). + + + + +## 十、离线包 + +传统的 H5 技术容易受到网络环境影响,因而降低 H5 页面的性能。通过使用离线包,可以解决该问题,同时保留 H5 的优点。 + +**离线包** 是将包括 HTML、JavaScript、CSS 等页面内静态资源打包到一个压缩包内。预先下载该离线包到本地,然后通过客户端打开,直接从本地加载离线包,从而最大程度地摆脱网络环境对 H5 页面的影响。 + +使用 H5 离线包可以给您带来以下优势: + +- **提升用户体验**:通过离线包的方式把页面内静态资源嵌入到应用中并发布,当用户第一次开启应用的时候,就无需依赖网络环境下载该资源,而是马上开始使用该应用。 +- **实现动态更新**:在推出新版本或是紧急发布的时候,您可以把修改的资源放入离线包,通过更新配置让应用自动下载更新。因此,您无需通过应用商店审核,就能让用户及早接收更新。 + +![离线包下载流程](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/Hybrid-OfflinePackageDownload.png) + +![离线包加载流程](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/Hybrid-OfflinePackageLoad.png) \ No newline at end of file diff --git a/Chapter1 - iOS/1.74.md b/Chapter1 - iOS/1.74.md index 71013c0..a27d258 100644 --- a/Chapter1 - iOS/1.74.md +++ b/Chapter1 - iOS/1.74.md @@ -4,11 +4,11 @@ App 的性能问题是影响用户体验的重要因素之一。性能问题主要包含:Crash、网络请求错误或者超时、UI 响应速度慢、主线程卡顿、CPU 和内存使用率高、耗电量大等等。大多数的问题原因在于开发者错误地使用了线程锁、系统函数、编程规范问题、数据结构等等。解决问题的关键在于尽早的发现和定位问题。 -xf 本篇文章着重总结了 APM 的原因以及如何收集数据。APM 数据收集后结合数据上报机制,按照一定策略上传数据到服务端。服务端消费这些信息并产出报告。请结合[姊妹篇](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.80.md), 总结了如何打造一款灵活可配置、功能强大的数据上报组件。 +本篇文章着重总结了 APM 的原因以及如何收集数据。APM 数据收集后结合数据上报机制,按照一定策略上传数据到服务端。服务端消费这些信息并产出报告。请结合[姊妹篇](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.80.md), 总结了如何打造一款灵活可配置、功能强大的数据上报组件。 ## 一、卡顿监控 -卡顿问题,就是在主线程上无法响应用户交互的问题。影响着用户的直接体验,所以针对 App 的卡顿监控是 APM 里面重要的一环。 +卡顿问题,程度较低就是掉帧,比如用户在滑动某个列表的时候会有不流畅的体验,但是应用程序还是可以相应的。严重些就是 ANR,就是短时间在主线程上无法响应用户交互的问题。影响着用户的直接体验,所以针对 App 的卡顿监控是 APM 里面重要的一环。 FPS(frame per second)每秒钟的帧刷新次数,iPhone 手机以 60 为最佳,iPad 某些型号是 120,也是作为卡顿监控的一项参考参数,为什么说是参考参数?因为它不准确。先说说怎么获取到 FPS。CADisplayLink 是一个系统定时器,会以帧刷新频率一样的速率来刷新视图。 `[CADisplayLink displayLinkWithTarget:self selector:@selector(###:)]`。至于为什么不准我们来看看下面的示例代码 @@ -2697,6 +2697,7 @@ CFNetwork 使用 CFReadStreamRef 来传递数据,使用回调函数的形式 } @end + ``` @implementation NetworkDelegateProxy @@ -2713,31 +2714,31 @@ CFNetwork 使用 CFReadStreamRef 来传递数据,使用回调函数的形式 }); return _sharedInstance; - } + } #pragma mark - public Method + (instancetype)setProxyForObject:(id)originalTarget withNewDelegate:(id)newDelegate - { + { NetworkDelegateProxy *instance = [NetworkDelegateProxy sharedInstance]; instance->_originalTarget = originalTarget; instance->_NewDelegate = newDelegate; return instance; - } + } - (void)forwardInvocation:(NSInvocation *)invocation - { + { if ([_originalTarget respondsToSelector:invocation.selector]) { [invocation invokeWithTarget:_originalTarget]; [((NSURLSessionAndConnectionImplementor *)_NewDelegate) invoke:invocation]; } - } + } - (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel - { + { return [_originalTarget methodSignatureForSelector:sel]; - } + } @end ``` @@ -5538,12 +5539,13 @@ parseJSError(line, column); }); return _sharedManager; } + ``` #pragma mark - public Method - (void)startMonitor - { + { APMMLog(@"crash monitor started"); #ifdef DEBUG @@ -5569,14 +5571,14 @@ parseJSError(line, column); } - (void)installKSCrash - { + { [[APMCrashInstallation sharedInstance] install]; [[APMCrashInstallation sharedInstance] sendAllReportsWithCompletion:nil]; [APMCrashInstallation sharedInstance].onCrash = onCrash; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ _isCanAddCrashCount = NO; }); - } + } ``` 在 `installKSCrash` 方法中调用了 `[[APMCrashInstallation sharedInstance] sendAllReportsWithCompletion: nil]`,内部实现如下 diff --git a/Chapter2 - Web FrontEnd/2.18.md b/Chapter2 - Web FrontEnd/2.18.md index 8fd50f2..9ef75fb 100644 --- a/Chapter2 - Web FrontEnd/2.18.md +++ b/Chapter2 - Web FrontEnd/2.18.md @@ -603,3 +603,8 @@ $ npm install $ node app.js ``` + +## 提问 +1. 反爬技术方案本身会不会对盲人等特殊群体的视障模式有影响? +https://medium.com/frochu/回歸初心-一探web-accessibility-baaa4d22f4a7 +alt diff --git a/Chapter3 - Server/3.10.md b/Chapter3 - Server/3.10.md new file mode 100644 index 0000000..4aea693 --- /dev/null +++ b/Chapter3 - Server/3.10.md @@ -0,0 +1,11 @@ +# 领域驱动设计与中后台、BFF的关系 + + +1. DDD 将业务拆分为多个领域,比如订单、商品...。每个域的服务是单独可以运行、维护的。比如订单域有10台机器,1台负载均衡,9台真正做事情的机器。有任务过来调度器进行任务派发。 +2. 客户端或者大前端都存在模块的概念。比如商品、订单,也是以 Pods 的形式去维护,每个领域的代码都单独可以运行、维护。模块之间不存在耦合关系,通过接口的形式去能力发现、能力调用。比如订单域通过某个接口访问某个商品详情的能力 +3. DDD 的最佳实践是不是微服务。比如订单服务所在的工程,可以单独运行、维护。 +4. 基于微服务,肯定需要一个 BFF 层,扮演业务编排、字段转换。比如订单域的模型有100个字段。但是订单的接口为客户端服务,客户端(通过接口找2018~2020年的、待付款的订单),BFF 层就去扮演数据组装、字段筛选的作用。 + + +- https://tech.meituan.com/2017/12/22/ddd-in-practice.html +- https://juejin.cn/post/6997250621627858957#heading-3 \ No newline at end of file diff --git a/Chapter3 - Server/chapter3.md b/Chapter3 - Server/chapter3.md index 34368a6..8e8457a 100644 --- a/Chapter3 - Server/chapter3.md +++ b/Chapter3 - Server/chapter3.md @@ -11,4 +11,5 @@ * [6、YAML](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter3%20-%20Server/3.6.md) * [7、Node单元测试](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter3%20-%20Server/3.7.md) * [8、数据安全(反爬虫)之「防重放」策略](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter3%20-%20Server/3.8.md) -* [9、爬取疫情数据并用 Markdown 预览](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter3%20-%20Server/3.9.md) \ No newline at end of file +* [9、爬取疫情数据并用 Markdown 预览](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter3%20-%20Server/3.9.md) +* [10、领域驱动设计与中后台、BFF的关系](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter3%20-%20Server/3.10.md) \ No newline at end of file diff --git a/Chapter7 - Geek Talk/7.22.md b/Chapter7 - Geek Talk/7.22.md new file mode 100644 index 0000000..f0b457b --- /dev/null +++ b/Chapter7 - Geek Talk/7.22.md @@ -0,0 +1,22 @@ +# 项目管理案例分析 + + + +## 库存扣减项目 + +**背景**:原定于17号上车,上车过程中代码合并 master 分支。iOS 和网关代码均无冲突。Android 发现订单列表接口被替换,和同学 A chechk 核实原因后是因为 App 订单管理能力补齐,替换了订单列表接口,而库存扣减项目测试过程中一直走的是老接口,发现问题后与测试沟通,对合并后的代码再进行一轮回归,延期至18号上车 + +**影响**:额外的近2天时间,导致其他项目进度滞后 + +**复盘总结:** + +因为过程中没有及时合并主分支代码,导致 QA 测试完成后,项目上车之际,合并 master 后发现很多主要逻辑以及接口被修改了。这时候不可能直接上车的,必须为新增的每一行代码回归,不然质量没法确保。 +这种情况,可与举个例子,比如你的 Native 工程或者前端工程的 Package.json 中版本没有锁死,在打包平台出的 SDKA 1.0.0 版本,测试完成后在出市场包或者 Web 部署 CDN 的时候,因为没锁死,恰好 SDKA 刚好有 1.0.1 可用,这样子造成的三方库引发的“新功能”或者某某不兼容,导致发生了线上问题。 + + +**改进点:** +- 开发过程中需要及时合并主分支,给 QA 的交付物保持最新 +- 后端接口改变,尽量做到向前兼容,避免影响线上服务 +- 后端接口做不到向前兼容,则新开接口,避免影响线上业务。接口改动尽量同步给相关使用方,正确评估影响面 + +这个问题本质上也就是多版本并行问题。属于很常见的项目问题,没有版本根本上解决,但是采取👆上面3个措施,相信情况会好很多。 \ No newline at end of file diff --git a/Chapter7 - Geek Talk/chapter7.md b/Chapter7 - Geek Talk/chapter7.md index 40712d7..4676b5c 100644 --- a/Chapter7 - Geek Talk/chapter7.md +++ b/Chapter7 - Geek Talk/chapter7.md @@ -21,4 +21,5 @@ * [17、一套开发规范](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter7%20-%20Geek%20Talk/7.18.md) * [18、云服务器靠谱推荐](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter7%20-%20Geek%20Talk/7.19.md) * [19、规范化团队 git 提交信息](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter7%20-%20Geek%20Talk/7.20.md) - * [20、如何画架构图](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter7%20-%20Geek%20Talk/7.21.md) \ No newline at end of file + * [20、如何画架构图](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter7%20-%20Geek%20Talk/7.21.md) + * [21、项目管理案例分析](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter7%20-%20Geek%20Talk/7.22.md) \ No newline at end of file diff --git a/Chapter9 - Ragdoll/Chapter9.md b/Chapter9 - Ragdoll/Chapter9.md index 52bea63..5b41e3b 100644 --- a/Chapter9 - Ragdoll/Chapter9.md +++ b/Chapter9 - Ragdoll/Chapter9.md @@ -1,7 +1,106 @@ # 第九部分 -第九部分主要记录布偶猫饮食、吃饭、健康、玩具、洗护、社会化等方面的经验和心得,还有一部分晒猫的原因。 +> 主要记录猫咪饮食、吃饭、健康、玩具、洗护、社会化等方面的经验和心得,还有一部分晒猫的原因。 + + +## 基础信息 + +坐标 :杭州 + +猫咪:养了4只吞金兽-布偶猫,每个猫咪都有 CFA 证书,有些猫咪小时候拿过比赛大奖,赛级布偶。 + +- Bella 是一只波斯系蓝双布偶,妹妹 +- Simba 是一只海双布偶,弟弟 +- PiPi 是一只海双布偶,弟弟 +- 碎星 是一只海双布偶,妹妹 + +环境:家里一周一次紫外臭氧灯消毒 + +洗护:克里斯汀森赛级洗护 + +饮食:生骨肉、羊奶 + + + + + +## 猫咪 + +
PiPi:
+ + + + + +
碎星:
+ + + + + +
Bella:
+ + + + + + + + + +
Simba:
+ + + + + +
小猫:
+ +(写入2021-0)4周前拍的 + + + + + + + + + + + + + +(写入2021-07-11)现在 + + + + + + + + + +更多: +其他更多的猫咪的美照,可以访问[这里](./assets) + + + + + +## 交流 + +如果你是一名铲屎官,想进群晒猫或者是交流猫咪养护经验 + +如果没有养猫,想云吸猫 + +如果打算养一只可爱、高颜值的布偶猫 + +可以联系我微信:704568245 + + + +## 目录 * [1、"CFA 证书" 不再那么神秘](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter9%20-%20Ragdoll/9.1.md) * [2、猫咪饮食](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter9%20-%20Ragdoll/9.2.md) diff --git a/SUMMARY.md b/SUMMARY.md index c4bcfaa..870d8e3 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -98,6 +98,7 @@ * [93、flutter 新功能引导](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.93.md) * [94、APM-Wake Up](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.94.md) * [95、从 flutter 和前端角度出发,聊聊单线程模型下如何保证 UI 流畅性](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.95.md) + * [96、一个提高 App 运算性能的想法](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.96.md) * [Chapter2 - Web FrontEnd](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter2%20-%20Web%20FrontEnd/chapter2.md) * [1、-last-child与-last-of-type你只是会用,有研究过区别吗?](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter2%20-%20Web%20FrontEnd/2.1.md) @@ -152,6 +153,7 @@ * [7、Node单元测试](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter3%20-%20Server/3.7.md) * [8、数据安全(反爬虫)之「防重放」策略](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter3%20-%20Server/3.8.md) * [9、爬取疫情数据并用 Markdown 预览](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter3%20-%20Server/3.9.md) + * [10、领域驱动设计与中后台、BFF的关系](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter3%20-%20Server/3.10.md) @@ -190,6 +192,7 @@ * [18、云服务器靠谱推荐](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter7%20-%20Geek%20Talk/7.19.md) * [19、规范化团队 git 提交信息](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter7%20-%20Geek%20Talk/7.20.md) * [20、如何画架构图](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter7%20-%20Geek%20Talk/7.21.md) + * [21、项目管理案例分析](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter7%20-%20Geek%20Talk/7.22.md) * [Chapter8 - Finance](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter8%20-%20Finance/chapter8.md) @@ -216,7 +219,3 @@ * [5、猫粮对你猫咪的牙齿做了什么?](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter9%20-%20Ragdoll/9.5.md) * [6、新猫到家的注意事项](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter9%20-%20Ragdoll/9.6.md) * [7、猫咪健康](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter9%20-%20Ragdoll/9.7.md) - - - - \ No newline at end of file diff --git a/assets/Hybrid-OfflinePackageDownload.png b/assets/Hybrid-OfflinePackageDownload.png new file mode 100644 index 0000000..2c0b3f0 Binary files /dev/null and b/assets/Hybrid-OfflinePackageDownload.png differ diff --git a/assets/Hybrid-OfflinePackageLoad.png b/assets/Hybrid-OfflinePackageLoad.png new file mode 100644 index 0000000..33bf25a Binary files /dev/null and b/assets/Hybrid-OfflinePackageLoad.png differ