树结构在计算表达式解析上的应用(设计统计组件)
前言大部分公司都存在数据统计的业务逻辑,而随着业务的不断发展,数据量的增加,统计指标的增加导致原先的统计代码的复杂度也会迅速上升。如果没有良好的组织和维护,往往会出现修改难(代码间耦合严重),项目中有大量重复代码,比如很多个地方都需要某个统计数据,开发人员直接复制粘贴代码,还有就是性能N+1问题。所以在编写这种统计逻辑时,应考虑以下几点:
基础数据如何获取(从数据库读取,从缓存中读取,从外部系统获取)
多个数据源如何组织计算(比如计算某个员工的绩效排名,最终的得分一定是多个维度的)
天然要求考虑性能问题,避免N+1查询
统计逻辑应独立,可组合,可复用(比如销售的订单金额这一指标在多个统计项中都要使用,那就应尽量复用统一)
这里我们尝试设计一个统计框架
模块儿区分其实统计指标数据粗略可分为两种
基础指标
计算指标
我们统一称呼 指标 为 Field
基础指标基础指标就是数据源是独立的,比如获取当前销售部门下在职销售的本月订单金额。这个信息来源于Order表。能直接获取到的而不设计比较,计算,条件判断等。
select sales_id, sum(amount) from orde ...
利用 Delegated Types 与 Self Joins 设计高扩展性系统
前言
如何设计一套类似Confluence、语雀、Notion这类CMS系统,在一个容器内,里面含有大量的不同形式的内容,同时多种内容又有很多类似的操作:移动、复制、删除、支持评论等。一个文档下可以写文本,也可以再次建立子文档,文本评论也可以建立子评论。一篇文档能够清晰的查看操作历史、变化内容。同时一个容器内可能还会新增一些不同的内容,又同时也要支持上述的操作。
https://dev.37signals.com/the-rails-delegated-type-pattern/ 文章中探讨了37Signals团队如何设计系统架构,保证高维护性和高扩展性。其核心概念就是Recording、Recordable和Event。本质上,他们利用了Delegated Types + Self Joins模式设计架构,来最大程度上支持高扩展性和可维护性。
参考资料:
Active Record Associations — Ruby on Rails Guides
https://api.rubyonrails.org/classes/ActiveRecord/DelegatedType.h ...
kamal 部署加速
国内墙的原因,导致在使用kamal部署到服务器上慢的要死,最近折腾了一下,在不适用代理情况下,第一次部署在两分钟内,之后更新就在三十秒左右。
举例项目脚手架生成的最基本项目
-> ruby -v
ruby 3.4.6(2025-09-16 revision dbd83256b1) +PRISM [x86_64-linux]
-> rails -v
Rails 8.1.1
-> rails new demo --css tailwind -d postgresql
dockerfile syntax 卡住# syntax=docker.m.daocloud.io/docker/dockerfile:1
# check=error=true
实际测试下来比较稳定,偶尔会卡住
docker login 卡住dockerHub 登录一直卡住
我换成腾讯云docker个人仓库,我看免费有十个,个人完全够用了,需要提前绑定密码,账号就是腾讯云用户Id
# Where you keep your container images.
registry:
# Alternatives: ...
Vue 组件间通信方案:实现 Drawer 单例模式
需求背景在 List 列表页面中:
每行数据的操作栏有一个按钮
点击按钮会打开对应的 Drawer(抽屉)组件
Drawer 是独立组件,每行数据对应一个 Drawer 实例
核心需求:当打开新的 Drawer 时,自动关闭之前打开的 Drawer
解决方案对比方案1:父子组件通信实现思路:
在父组件中维护当前活跃的 Drawer ID
子组件打开时通知父组件更新状态
父组件通过 props 或事件通知其他子组件关闭
代码示例:
// 父组件
data() {
return {
activeDrawerId: null
}
},
methods: {
setActiveDrawer(id) {
this.activeDrawerId = id
}
}
// 子组件
props: ['activeId', 'drawerId'],
watch: {
activeId(newVal) {
if (newVal !== this.drawe ...
Rails层级设计演化
Rails层级设计演化
相关资料
37signal - 层级设计
37signal - concern设计
层级设计翻译
concern设计翻译
gitlab-ddd应用
面向资源编程
最初的样子我们都知道rails初始化项目,在层级拆分上只有两层
controller
model
controller负责接收请求,model负责实现存储,那业务逻辑在哪里实现?
可能为了model的干净,将业务逻辑写到controller中。也有可能为了代码复用,将业务逻辑写在model中。但不管选择哪种方式,如果不进行谨慎的管理,随着业务的不断迭代,你的controller或者model也会逐渐的臃肿,变得难以维护。自然而然的大家决定抽离出业务层,比如:Service,Command等等
引入Service/Command比如我有一个报价单模型,我可能有类似的结构
# controller
class QuotationController < ApplicationController
end
# Command
class QuotationCommand
def cr ...
警惕AI
警惕AI 2022年年底时,Chatgpt横空出世,让每个使用过它的人发出赞叹,大家都在提问各种问题,程序员可能是最早一匹去接触与尝试的群体了。大家都想看看这个小玩意儿能迸发出多大的力量,要是能帮我干活儿就好了。给我写代码!!!
但那时AI还像个小孩子,对于简单的问题能快速回答,但稍微复杂的问题,我们称之为一本正经的胡说八道的人工智障。但这并不影响我们非常看好它。再后来Github推出copilot以及一大堆AI提示工具,你第一句代码还没写完,AI就已经提示出你下一句话可能是什么。如果不对,你可以继续写原本的代码,它会根据新增的信息再去调整与生成。这用起来很方便,目前为止你的副驾驶有一位很棒的伙伴。
再后来的cursor,你更多的是像产品经理一样提出你的需求,它会尝试着自己去考虑所有的问题,并进行代码编写,很多简单的需求,或从零到一的小项目,几分钟后运行的结果如你想象一致,而这在过去可能会花上你半天甚至更长的时间。当然遇到大型,复杂项目它仍然会有各种问题,你知道它无法代替你,因为里面有很多内容是AI不清楚的,如架构,特定用法,DSL等等。但它已经足够棒了,如 ...
Ruby元编程实战
本文主要介绍一些元编程的使用技巧
Hash映射对象将Hash转成对象,键值对转成对象的方法,灵活的通过函数调用来获取值信息
module ActsAsField
def self.included(base_class)
base_class.instance_variable_set(:@all_fields, [])
# 一个常见的技巧,通过钩子函数,当模块引入时动态扩展
base_class.include Instance_Methods
base_class.extend Class_Methods
end
module Class_Methods
# 声明变量信息,并自动生成实例方法
def field(name, path)
instance_variable_get(:@all_fields) << name.to_sym
define_method(name.to_sym) do
case path
when String
...
RSpec 测试示例与技巧说明
RSpec 测试示例与技巧说明本文档整理了多个 RSpec 测试示例,并详细说明了每个示例中使用的技巧和代码示例。这些示例涵盖了常见的测试场景,包括基本断言、异常处理、状态变化、依赖注入、以及使用 spy 和 double 进行测试。
目录
基本断言
异常处理
状态变化
依赖注入与 double
使用 spy 进行测试
模拟日期和时间
基本断言示例代码RSpec.describe 'Assertion' do
describe 'expect equality' do
it do
foo = 1
expect(foo).to eq(1)
end
it do
foo = [1, 2, 3]
expect(foo).not_to equal([1, 2, 3])
end
end
describe 'expect Truthiness' do
it { expect(1 + 1 == 2).to be true }
end
describe 'match a ...
位运算 & (与)实际应用
疑问?
在linux系统中,我们经常使用chmod进行文件权限修改(读,写,执行)
比如我要对some.sh赋予权限: chmod u=rwx,g=rx,o=x some.sh
u=rwx:
u 表示文件所有者(user)。
rwx 表示读(r)、写(w)和执行(x)权限。
这意味着文件所有者将拥有读、写和执行权限。
g=rx:
g 表示文件所属组(group)。
rx 表示读(r)和执行(x)权限。
这意味着文件所属组将拥有读和执行权限,但没有写权限。
o=x:
o 表示其他用户(others)。
x 表示执行权限。
这意味着其他用户将只有执行权限,没有读和写权限。
可以看到我们分别对文件所属人,文件所属组,其他用户赋予了读,写,执行的权限,那这些信息实际存储是什么样子的呢?难道是一个数组?
u: [r, w, x], g: [r, x], o: [x]
这种看起来最直观,但有没有更优雅的方式,比如用一个数字就能表示所有的权限信息,u: 7, g: 5, o: 1,经常用这个命令的人知道,上述的写法可以使用chmod 751 some.sh直接表示
那为什么我通 ...
Zed动态查询
尝试过nvim的人应该都对telescope这种文件查询风格很喜欢,当在输入时能自动进行重新查询,并通过上下键进行翻阅
我目前在使用另一款编辑器Zed,它目前内置的查询并无法做到类似的操作。但通过内置的Terminal+fzf+bat+rg也能做到类似的效果
fish function
function search_and_edit
# 使用rg进行文件搜索,并使用fzf进行预览
set -l selected_file (rg --column --hidden --line-number --no-heading --color=always --smart-case --glob '!**/.git/' --glob '!**/node_modules/' . | fzf --ansi --delimiter : --preview 'bat --style=numbers,changes,header --color=always --highlight-line {2} {1}' --preview-windo ...

