coerced value(强制转换的值、静默转换)与typed ok=False result(类型化的失败结果)对比

coerced value(强制转换的值、静默转换)与typed ok=False result(类型化的失败结果)对比 Repo-wide silent-fallback audit✅ done: six defects fixed — resume match persisted an LLM failure asmatch_score0.0statusdone(overwrote a real score with “terrible fit”); interview prep persisted two failed generations as “ready: 0 questions”; thejob.discoveredconsumer ACKed messages whose upsert had failed (jobs silently lost between “42 found” and the library); the request-context middleware swallowed unreadable tokens with no log or metric; all 7 ReAct tools returned error JSON with no metric; the frontend collapsed analysis-fetch 5xx into “never analyzed” and a failed discovery-config fetch into “you have none”. Audited and deliberately left alone:scraper.py(typedokFalseresult, not a coerced value),analyzer_graph(already tri-state instrumented), Temporal activity/workflow error paths (recorded on the run row and re-raised)它使用类型化的 okFalse 结果来表示失败是什么意思文章目录coerced value强制转换的值与typed okFalse result类型化的失败结果对比❌ 不好的做法coerced value强制转换的值✅ 好的做法typed okFalse result类型化的失败结果为什么这样更好1. 调用方**被迫处理失败情况**2. 成功和失败**不会混淆**一句话总结coerced value强制转换的值与typed okFalse result类型化的失败结果对比这是指scraper.py这个模块在表示成功/失败时采用了一种显式的、类型安全的方式来返回结果而不是把错误悄悄转换成一个看似正常的值。让我对比一下两种做法你就能理解了❌ 不好的做法coerced value强制转换的值假设一个爬虫函数要返回抓取到的数据# 不好失败时返回一个看起来正常的默认值defscrape(url):try:datafetch(url)return{items:data,ok:True}exceptException:# 把失败伪装成成功但没数据return{items:[],ok:True}# ← 问题调用方以为成功了只是没数据或者更常见的defget_match_score(resume,job):try:scorellm.analyze(resume,job)returnscore# 比如返回 85.0exceptException:return0.0# ← 问题调用方无法区分真的是0分还是调用失败了这就是 commit 里说的coerced value——把失败强行转换成了一个正常的数值0.0、空列表等调用方完全无法区分真的就是这个结果还是出错了。✅ 好的做法typedokFalseresult类型化的失败结果scraper.py的做法是定义一个明确的结果类型成功和失败是不同的结构fromdataclassesimportdataclassfromtypingimportOptional,ListdataclassclassScrapeSuccess:ok:True# 类型标注为字面量 Trueitems:List[str]# 只有成功时才有数据dataclassclassScrapeFailure:ok:False# 类型标注为字面量 Falseerror:str# 错误原因status_code:Optional[int]# HTTP 状态码等ScrapeResultScrapeSuccess|ScrapeFailure# 联合类型defscrape(url:str)-ScrapeResult:try:datafetch(url)returnScrapeSuccess(okTrue,itemsdata)exceptExceptionase:returnScrapeFailure(okFalse,errorstr(e),status_code500)为什么这样更好1. 调用方被迫处理失败情况resultscrape(https://example.com)ifresult.ok:# 这里 result 的类型自动收窄为 ScrapeSuccess# 可以安全地访问 result.itemsprint(f抓到了{len(result.items)}条数据)else:# 这里 result 的类型自动收窄为 ScrapeFailure# 可以访问 result.errorprint(f抓取失败:{result.error})如果你忘了检查ok类型检查器如 mypy会报错提醒你可能遗漏了错误处理。2. 成功和失败不会混淆场景coerced value 方式typedokFalse方式成功抓到 5 条{items: 5条}ScrapeSuccess(items5条)成功没数据{items: []}ScrapeSuccess(items[])失败{items: []}← 和成功但没数据一样ScrapeFailure(error超时)← 明确不同一句话总结“typedokFalseresult”就是用明确的类型定义来区分成功和失败两种结果让调用方在代码层面不可能把失败误认为成功。而 “coerced value” 则是把失败硬塞进成功的格式里让调用方根本分不清。这也是为什么审计人员确认scraper.py不需要修改——它从一开始就正确地处理了失败情况。