- “Domain Driven Rails”
- “I Heart Logs”
- “The Ruby On Rails Performance Apocrypha” - Nate Berkopec
what must be clear while upgrading application/dependencies?
Given
- new version
is compatiable with
old version - old version
is NOT compatiable with
new version
Then
- rollout(old -> new) or rollback(new -> old)
- case#1 new produce -> new consume OK
- case#2 new produce -> old consume ERROR
- case#3 old produce -> new consume OK
- case#4 old produce -> old consume OK
Review
- if retry could make case#2 work, then it’s ok and expected, otherwise we need to figure out how to do the upgrade carefully
- if cache object deserilization is included, better consider using a fresh new cache key(sth like version number) to make sure new version won’t load the outdated version of cache data
Continuous Conscious Self-Improvement
Blog content copied from Continuous Conscious Self-Improvement | zenspider.com | by ryan davis
- How do you develop software?
- Is it effective? (and how do you know that?)
- Are you focusing on improving yourself?
- Where are you at? Where do you want to be?
- Could you do better?
- Where could you put the least amount of effort to improve the worst?
- When do you do that?
- What would your teammates answer (about you)?
- What can you learn from them?
- What are you doing to get there?
Incident Review
今天因为我的失误导致了一次小故障,持续大概一小时才被发现,影响10多个用户,需要修几十条数据(粗略估计)
这是在公司因为我导致的第二次问题,有必要把反思记录一下
第1次问题(2022年底)
功能开发完成,QA内部测试完成,但是隔了有一段时间才真正在生产环境启用,导致功能开关的影响范围没有完全理清,和另一个功能开关的开启产生了干涉,问题持续了近10个小时才被发现,导致有几千条数据异常;最后只得花了很多精力从日志里捞数据,修数据,非常麻烦
当时反思有这几点原因:
- 功能内测结束后没有重置功能开关
- 打开功能开关之前没有检查功能开关的状态,没有考虑到功能之间可能产生干涉
- 一段时间内,同时在处理的事情有点多了(WIP数量有点多),精力太过分散,review不到位
- 对生产环境变更缺少敬畏心
第2次问题(2023-04-12)
有一个较大的任务,是给多个业务场景添加source_type
和source_id
, 以便于数据查询和统计;最近到了收尾阶段,有几个场景的改动在其他团队阻塞了近1个月,为了不完全被阻塞,leader和我先把后续的验证环节先做好了,准备内测
今天刚刚开启内测的开关,因为考虑不周,导致了空指针异常
直接原因是遗漏的几个场景没有部署,导致对应的source_type
和source_id
为空
根本原因是自己的疏忽,有这么几点
- 测试用例里,应该捕获到这个问题,但是实际上没有,这是偷懒导致的
- 在有几个场景被阻塞的前提下,为了不完全被阻塞,开始做其他的事前,没有想清楚哪些事是需要注意的,多想一步,就可以想得到之后的测试用例要着重关注它们
- 修改不熟悉的代码时,不够细心,最基本的为空的情况被自己遗漏了
- “后续的验证环节”这部分代码,不应该影响业务流程,这里最保险的方法是加上异常捕获(fail-safe);虽然捕获一个general的异常是糟糕的实践,但在这个场景下其实是很合适的,我因为心底拒绝这种实践,所以完全忽略了这种做法
- 开启开关后,对生产环境的监控疏忽了,竟然是近1个小时后才从告警群里发现有问题…
- 对生产环境变更缺少敬畏心
反思
- 无论业务是否关键,变更前都要想清楚怎么监控,怎么减少错误出现的可能;如果一定不能出错,fail-safe的做法就是必要的
- 对生产环境变更要有敬畏之心
- limit WIP, 把事情做好,不要一下给很多事开头,不停的在很多事之间切换
- 常识: 多想想如果为空会怎么样; 自信想了一下,没考虑到这个,和写代码的方式也有关,方法定义的方法调用的地方相隔太远,没有有意识的去专门检查,如果他们离得近,发现他们的概率会提升很多
- 如果想不清楚,就先不要开启,就先不要发布;和生产环境相关的变更,头脑不清楚的时候不要动
- 这两次问题影响范围不算太大,算是教训;如果不注意,以后犯更大错误的可能性更高;一定要多培养好习惯,发现和克服坏习惯
My understanding for IoC(Inversion of Control)
20230322 free chat sharing notes
Framework vs Library
- our code calls library code
- our code called by framework code
My understanding for IoC
IoC is we as programmers write codes that are called by
Frameworks
- control structures: Sequence, Selection & Iteration
- normally we write business logic as step1, step2, step3… using above control structures
- but we will notice bolier templates as we getting more and more familar with them, for examples:
- we always need to close an open file
- we always need to declare an empty array if we’re only interested in part of the elements in a list
- some code only differs in the middle part
Examples
- map/filter/reduce(pipelined list handling)
- list.filter {}.map {}
- list.filter {}.map {}.reduce {}
- ruby: partition/all?/any?/none?
- (1..6).partition { |v| v.even? } #=> [[2, 4, 6], [1, 3, 5]]
- dsl(describe what to do, not how to do it)
- framework
- rails
- event_sourcing
- lambda(ruby block / First-class Function)
Take aways
- find & use good abstraction(e.g.: use
map/filter/reduce
more) - learn more about the framework we’re using
References
- algorithm = logic + control.pdf
- Framework vs Library: Full Comparison - InterviewBit
- Generic Map, Filter and Reduce in Go | by Erik Engheim | ITNEXT
- Go filter/map - filter and map functions in Golang
- How to Read and Writes Files in Ruby
- Inversion Of Control - wiki.c2
- Inversion of control - Wikipedia
- Inversion of Control Containers and the Dependency Injection pattern
- module Enumerable - RDoc Documentation
Some common sense
最近这些简单的感悟和常识经常在脑袋里窜, 记下来供以后review
- 没有人阻止我去重看那些以前看不懂的东西(文章/书/电影/知识点…), 多看几次, 随着知识增长, 大概率会慢慢看懂并且学会的
- 没有人阻止我去练习那些不容易掌握的能力和技巧, 难是正常的, 刚开始不会也是正常的, 硕哥以前教过我: “我不会是因为我欠练”, 多多练习, 一定能提升熟练度, 慢慢掌握的
- 没有人阻止我做很多我认为正确的/有价值的事, 唯一的阻碍就是自己想偷懒, 问题在自己
- 守好自己的钱包, 在接受别人分享的”赚钱机会”时, 想想你是不是他爹? 凭什么他不自己闷声发财
- 重要的信息一定要确认来源, 多方验证, 要重视”验证码”的重要性
- 要多积累常识, 多思考”老生常谈”的含义, 做决定时多调用常识, 多多沟通
- 人给自己找理由实在太容易了, 不要怕麻烦, 如果自己思考不清楚, 应该向更厉害的人求助; 行动起来就会遇到问题, 遇到问题就解决问题, 坐在那里给自己找理由实在太容易了(还没做到…)
- 多想想怎么能把自己在做的事的价值描述清楚, 如果想不清楚, 说不清楚, 是不是说明在做的事没价值? 如果不是, 为什么说不清楚? 有什么是自己不敢面对的么?
Abstract Data Type Collection
“和任何编程概念一样,理解抽象数据类型的威力和用法的最好办法是仔细研究更多的例子和实现” — algs4 ch1.2
- Counter
- Interval1D
- Interval2D
- Date
- Transaction
- from_user
- to_user
- created_at
- amount
- currency
- souce_id
- source_type
- List
- Stack
- Queue
- Bag
- Tree
ref: Reading 10: Abstract Data Types
昨天复习优先队列的时候,才真正注意到 ADT 和 data structure 是两个不同的概念
比如优先队列(priority queue)是一种ADT, 所以他的实现可以有多种, 基于数组实现的而叉堆只是实现它的一种数据结构
比如栈(stack)是一种ADT, 基于数组实现的栈是一种数据结构, 基于链表实现的栈也是一种数据结构
(还是不够清晰,甚至感觉有错误…)
Find unused local variables in ruby project
Inspired by SublimeLinter plugin for ruby, using ruby -wc
1 | parallel "ruby -wc {}" ::: $(find . -name \*.rb) 1> /dev/null |
Known issue
it only detects local variables for “warning: assigned but unused variable - xxx”
not working for instance variables
probably work with unused-code/unused to detect other unused tokens
unused
1 | # https://github.com/universal-ctags/homebrew-universal-ctags |
Linus torvalds talking about good taste
“The mind behind Linux | Linus Torvalds”
Sometimes you can see a problem in a different way and rewrite it so that a special case goes away and becomes the normal case. And that’s good code.
To me , the sign of good people I really want to work with is that they have good taste.
This is a small example , Good Taste is much bigger than this.
Good taste is about really seeing the big patterns, and kind of instinctively and knowing what’s the right way to do things.