一个程序员花了一年写交友软件,上周开源了匹配引擎。他最纠结的设计选择是:匹配器完全无法读取照片。不是"忽略",不是"降低权重",是物理上无法访问——TypeScript编译会直接报错。
核心代码长这样:
![]()
rank函数接收两个Profile参数,返回匹配分数。Profile类型包含:五个文字问答、一段30秒语音转录文字、交友意图(朋友/恋人/社群)、基础元数据(年龄段、城市、语言)。整个类型定义里,没有照片字段。
![]()
照片数据存在另一张表,走独立的读取路径,被mutualVibe布尔值控制。rank函数没有引用那张表,正常应用架构下也拿不到。约束由编译器强制执行。
为什么不用功能开关,而是做到类型层面?作者给了三个理由。
第一,开关会被后来人翻转。某个疲惫的晚上,未来的工程师看着 engagement 仪表盘,会提议加个"辅助信号"A/B测试。他是对的,指标会涨。但他错了,测的根本不是当初说好的东西。开关活不过这场对话,类型签名可以。
第二,约束应该活在产物里,而不是文档里。README写"请勿用照片排序"是备忘录,类型里没有照片字段是编译错误。银行不会用备忘录来保证数据一致性。
![]()
第三,公开可验证。仓库是开源的,看入口类型,60秒就能确认,不用信作者任何一句话。
代价也不小。数据模型最烧钱:照片实体必须有自己的服务、访问控制、读取路径。图片上传管道永不返回匹配服务。"给我看脸"是独立请求,服务端用双用户ID键控的mutualVibe行来把关。这不是一个下午能重构完的。
其次是决定Profile该放什么,才能让排序还能跑。作者试了很多方案,现在的形状(五段问答+语音转文字+意图元数据)是能产生"经得起人工检查"的匹配的最小集合。大半年的时间,就花在把它压缩到这个程度。
第三个代价更软性。有一类用户,在现有应用上主要靠脸筛选。他们会看这款产品的简介,然后关掉页面。作者接受这个流失。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.