业务逻辑-cdn持久化存储缓存以及更新cdn缓存这里以通过微信登录时缓存微信头像图片为例cdn缓存是什么:
cdn是网络上提供缓存服务的节点,用于减轻访问压力,并降低对第三方的依赖
比如用户在通过微信登录的时候会提供自己头像的url, 当我们不使用cdn缓存的时候,由于微信头像的url是不稳定的,当你的微信头像更换之后,原来的url会失效,最终导致网页根据该url解析的头像图片失效
而如果采用cdn缓存,会将当前url的图片缓存到cdn节点,之后网页头像图片的获取就从cdn来,哪怕原头像图片对应的微信url失效,网页头像依旧正常
接下来是更新cdn缓存和网页头像的一套业务逻辑模块,头像url分为以下三种:
userInfo.AvatarUrl为新头像:当前这次登录时获取到最新的微信头像
user.Avatar为网页头像:网页显示的头像
user.PermanentAvatar为获取cdn缓存的url
12345678910111213141516171819202122232425·········//在覆盖之前捕获之前存储的旧头像oldAvatarUrl := getUs...
目前网上检索到的关于Swift的REST API Call实现很多已经在swift6之后算是过时了的,Swift6强化了并发安全,以及URLsession API也相应增加了async版本(旧版本使用callback),更modern的方法是使用async/await以及Task来构建REST API Call
以下均使用URLsession进行REST API Call
在旧版Swift中, Get接口是这么call的
12345678910111213141516171819202122232425 func fetchPage(completion: @escaping (Result<PageData, Error>) -> Void) { let url = URL(string: "http://127.0.0.1:8080/community/page/get")! URLSession.shared.dataTask(with: url) { data, response, er...
用Swift写了一个从后端获取数据来展示话题和评论的Mac客户端, 用了MVVM模式
MVVM即Model、View和ViewModel
View层:
UI界面,对的,记住它就仅仅是个UI
ViewModel层:
View要用到的所有数据和方法,嗯,data和function,所以它在Swift中通常是个class
Mode层l:
底层数据和业务逻辑,在这个例子中包括向后端发出请求的底层方法,以及对应得到的json数据转换为的结构体
用ViewModel是为了视图和业务逻辑之间的解耦从我的项目文件结构中应该能更加清晰说明这个:
-CommentSystem
-PageModel.swift
-PageService.swift
-PageData.swift
-PageViewModel.swift
-PageView.swift
...
写这个项目的时候本来用来理清需求和思路, 后来稍微添了点就顺便出来一份规范点的易上手文档,仅供参考
存储技术文档后端项目:你可能需要的文档:
补充后端基础知识 https://youtu.be/XBu54nfzxAQ?si=0Ce6-dFM4nokSlwb
(JWT入门)Spring Boot 如何集成JWT实现Token验证https://cloud.tencent.com/developer/article/2245008
Spring Boot 零基础快速入门https://kucw.io/blog/springboot/1/
Spring Boot Restful API介绍https://kucw.io/blog/springboot/22/
spring与数据库的交互方式 https://dimitri.codes/difference-spring-data-jdbc-jpa/
要求:
系统需求: 支持 Markdown 文件的上传、元数据存储以及权限化的访问管理
用户与权限: 支持基础的JWT认证, 角色权限可以分成User/Admin
...
为防止init_commit的重复创建,应把init_commit写入.gitlet,一次创建,其他地方直接引用
sha接受byte数组,需要readContents先转化为 byte[]
暂存区分tobeadded和tobeDeleted两种
获取timeStamp:
123Date now = new Date();Date inittime = new Date(0);//the init time 'Thursday, 1 January 1970'
转换得到String类型的timeStamp
1234static String dateToTimeStamp(Date date) { DateFormat dateFormat = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy Z", Locale.US); return dateFormat.format(date); }
对于每个commit,其hashID通常这样...
祝生物钟倒转的三天新年快乐🎆
基于上次的状态机:
之前说过我当时写出这个状态机时,是从最初的if-else重构过来的。
所以当时新接触这个状态机时,我也尝试过从if-else的角度去反向理解这个教简单的状态机,然后误打误撞就发现这其实就是分层状态机(HFSM)的思想
事实上把陌生和友好两个状态合并起来就是对应着本的’false’,而逃跑状态则对应原本的’true’
或者换句话说: if-else本身就是一种广义上的二元状态机
同时,在我们的这个例子中,我们用抽象的思维看,其实’陌生和友好’本身也是一个二元的状态机,它作为一个状态机被封装成了大的if-else二元状态机下的一个状态。
也就是说:状态机中的状态可以是另一个状态机
这也就是分层状态机HFSM
我们把之前的FSM重构为HFSM,它总体上大致长这样
hfsm的运行逻辑是先进入父状态机,然后根据过渡条件选择对应的子状态机,再运行子状态机并进入子状态机下的状态。
各层级内需要做好抽象屏障,子状态机的状态不应与父状态机的状态存在任何通信。
以下是HFSM的一个通用模型
对于我们这个例子:
父状态机是‘逃跑-不逃跑’...
本篇基于Modo在写Flee On Sight时的感想对于较复杂的状态判断,有一种更好的方法为什么不用if-else ?:首先,对于大量子状态的判定会在这种boolean的判定中越来越冗长,如果是写了辅助方法来包装则会有层层嵌套的问题,而且对于几个不相关的子boolean强行包装成一个辅助boolean会导致可读性下降,最终整体的状态判定会很难维护
同时,最最危险的一点在于if-else的各种子状态判定一旦存在耦合,会变得非常非常麻烦举个例子,我们判断一只羊是否应该逃跑(记为isFleeing), 假设isFleeing这个boolean由两个子状态A和B来判定:
A 代表空间判定(包含视角判定,空间距离判定)
B 代表食物引诱判定(即羊不应在受吸引时逃跑)
或许这个时候你会想这么写
123if (A && B) { isFleeing = true;}
然而事实是B中实际上嵌套了A中的部分空间逻辑🤓,这意味着 A 与 B 并不是两个独立条件,这就非常头疼了
通常接下来你有两种常规的处理这玩意的思路:
第一种是打补丁:在A...