#软件工程

源自 Hacker News 上的这篇文章 🔽 文润转译: --------- 软件工程中的“品味”究竟意味着什么? 技术品味(Technical taste)和技术能力(Technical skill)是两码事。你可能技术很强但品味不足,也可能技术平平却品味独到。如同生活中的品味,技术品味有时会超前于你的实际能力:就像你即便不会下厨,也能分辨佳肴与糟粕;同样地,即便你还不具备构建某种软件的能力,也可能已经知道自己喜欢什么样的软件。技术能力可以通过学习和重复练习来提升,但好品味的养成过程则更为难以捉摸。 以下是一些衡量软件品味的指标: - 什么样的代码在你看来是“好看”的?什么样的又是“难看”的? - 哪些设计决策让你深感满意,而哪些只是“差强人意”? - 哪些软件问题会让你寝食难安,甚至下班后还在琢磨?而哪些问题你又能一笑置之? 我认为,品味是一种能够根据当前项目,选择并采纳最契合的工程价值观的能力。 为什么品味不同于能力 看到上面的指标,你可能会问:这难道不就是技术能力的一部分吗?比如说,代码看起来“好看”,不正是因为它本身就是“好代码”吗?我不这么认为。 举个例子。我个人觉得,使用 map 和 filter 的代码要比传统的 for 循环更简洁。我们很容易会认为,这代表了我在工程观点上是绝对正确的。比如,map 和 filter 通常涉及纯函数 (pure functions),更易于理解和推理,还能避免一类常见的下标错误(off-by-one iterator bugs)。这让我觉得,这并非品味之争,而是我正确、其他工程师错误的问题。 但现实当然要复杂得多。像 Golang 这样的语言,出于其设计原则,完全没有内置 map 和 filter。从性能角度看,for 循环的逻辑更容易分析,也更容易扩展到其他迭代策略(比如一次处理两个元素)。我个人对后者的关注度,不如对前者的关注度高——这就是为什么我不常用 for 循环——但如果因此就说偏爱 for 循环的工程师技术能力不行,那就太傲慢了。很多时候,他们拥有的技术能力恰恰是我所不具备的。他们只是在乎的东西不一样。 换言之,我们的分歧源于价值观的差异。关于这一点,我曾在《我不知道如何构建软件,你也不知道》一文中探讨过。即使那些重大的技术争论确实存在标准答案,也没有哪个在职的软件工程师敢说自己样样精通,因为一个人的职业生涯所能积累的经验终究有限。我们都在一定程度上依赖于个人经验,依赖于自己那套特定的工程价值观。 工程品味的本质是什么 软件工程中的几乎每一个决策都是一种权衡 (tradeoff)。你很少会遇到一个选项完全优于另一个选项的情况。更多时候,每个选项都有其利弊。我们常常需要在不同的工程价值观之间做出艰难的取舍:例如,当性能优化到一定程度后,你可能就很难在不牺牲代码可读性的前提下继续提升性能了。 在我看来,能否真正理解这一点,是衡量软件工程师成熟度的最大标志。不成熟的工程师在做决策时往往很固执,他们认为做 X 或者 Y 总是更好的。而成熟的工程师则乐于权衡一个决策的利弊,因为他们知道每种选择都有其优缺点。关键不在于判断技术 X 是否优于 Y,而在于在当前这个特定场景下,X 的好处是否大于 Y。 换句话说,不成熟的工程师对自己的品味过于执着。他们知道自己喜欢什么,却误将这种喜好当作了放之四海而皆准的工程原则。那么,一个工程师的品味究竟是由什么构成的呢? 我认为,你的工程品味,由你认为最重要的那套工程价值观所构成。例如: - 可靠性 (Resiliency) 如果某个基础设施组件(如服务、网络连接)发生故障,系统是否仍能正常运行?能否在无人干预的情况下恢复? - 速度 (Speed) 软件的运行速度与理论极限相比如何?在关键路径 (hot path) 上是否存在不必要的计算? - 可读性 (Readability) 代码是否一目了然,便于新工程师上手?函数是否相对简短且命名得当?系统文档是否完善? - 正确性 (Correctness) 系统是否可能出现无效状态?系统是否通过测试、类型系统和断言进行了严格的约束?测试是否使用了模糊测试 (fuzzing) 等技术?在极端情况下,程序是否通过 Alloy 等形式化方法被证明是正确的? - 灵活性 (Flexibility) 系统能否毫不费力地扩展?进行一次变更有多容易?如果我需要修改某个功能,需要同时改动多少个不同的地方? - 可移植性 (Portability) 系统是否被绑定在特定的运行环境上(比如 Windows 或 AWS)?如果需要将系统部署到别处,能否在不投入大量工程工作量的情况下完成? - 可扩展性 (Scalability) 如果流量增长 10 倍,系统会崩溃吗?100 倍呢?系统是需要过度配置资源,还是可以自动扩展?哪些瓶颈需要工程师介入解决? - 开发速度 (Development speed) 如果我需要扩展系统,需要多长时间?是大多数工程师都能着手处理,还是需要领域专家的介入? 当然,工程价值观还有很多,比如:优雅性、技术的现代性、开源技术的使用、系统运行的经济成本等等。所有这些都很重要,但没有哪个工程师会对所有这些方面给予同等的关注。 你的品味,正取决于你将哪些价值观置于最高优先级。例如,如果你看重速度和正确性胜过开发速度,你可能会更喜欢 Rust 而不是 Python。如果你看重可扩展性胜过可移植性,你可能会主张深度利用你所在平台(如 AWS)的特性和工具。如果你看重韧性胜过速度,你可能会希望将流量分散到不同区域。 我们还可以将这些价值观进行更细致的拆分。两个都非常关心可读性的工程师,可能会因为一个推崇短函数,另一个推崇短调用栈而产生分歧。两个都关心正确性的工程师,也可能因为一个看重详尽的测试套件,另一个信奉形式化方法而意见不合。但原理是相通的——有太多工程价值观值得我们去追求,而它们之间又常常相互冲突,这就迫使每位工程师必须有所取舍。 如何识别“坏品味” 虽然我前面说所有的价值观都很重要,但这并不意味着不存在“坏品味”。在软件工程的语境下,坏品味意味着你所偏爱的价值观与你正在做的项目格格不入。 我们大多数人都和这样的工程师共事过。他们加入你的项目后,就开始鼓吹某些东西——形式化方法、用 Golang 重写、Ruby 元编程、跨区域部署等等——因为这些东西在他们过去的项目中效果很好。无论这是否适合你当前的项目,他们都会极力推崇,因为这是他们喜欢的方式。不知不觉中,你发现自己为了让一个内部指标看板达到 99.999% 的可靠性,牺牲了代码的可理解性,导致没有一个初级工程师能看懂。 换句话说,大多数坏品味都源于僵化和缺乏变通。我总是对那些以“这是最佳实践”来为自己决策辩护的工程师持保留态度。没有任何工程决策在所有情境下都是“最佳实践”!你必须针对你面临的具体问题,做出正确的决策。 这带来一个有趣的结果:品味差的工程师就像一块坏了的罗盘。如果你恰好站在对的位置,坏罗盘依然能指向北方。只有当你开始移动,它才会把你引向歧途。同样,许多品味差的工程师在特定的领域内可能非常高效,因为在那个领域里,他们的个人偏好正好与项目需求相符。但当他们被调到不同的项目或岗位,或者当项目本身的性质发生变化时,问题就立刻暴露出来了。要知道,工作内容很少会一成不变,尤其是在 2021年后这些充满挑战的时代 里。 如何识别“好品味” 相比技术能力,好品味要难以捉摸得多。因为与技术能力不同,好品味是针对你面临的特定技术问题,选择正确工程价值观组合的能力。因此,判断一个人是否有好品味要困难得多:你无法通过玩具问题 (toy problems) 或技术问答来检验它。你需要一个真实的复杂问题,以及它所附带的各种错综复杂的现实世界背景。 如何判断自己是否有好品味?如果你深度参与设计的项目都取得了成功,那么你可能就拥有好品味。如果你只是执行任务(比如完成一个个工单),那么可以这样判断:那些你认同其设计决策的项目取得了成功,而那些你不认同的项目则步履维艰。重要的是,你需要经历不同类型的项目。如果只有一个项目,或者反复做同一种项目,那可能只是说明你恰好适合那个领域。即使你经历过许多不同类型的项目,也不能保证你在不熟悉的领域里同样拥有好品味。 那么,如何培养好品味呢?这很难说,但我建议多接触不同类型的项目,密切关注哪些项目(或项目的哪些部分)进展顺利,哪些部分举步维艰。你应该专注于保持灵活性:尽量不要对“什么是写软件的正确方式”形成固执的、普适性的看法。我自己的好品味是慢慢积累起来的。当然,我也不认为你不能快速获得它。我相信编程领域也存在一些天赋异禀、品味超乎其经验的奇才,就像其他领域一样。
#BestBlogs 一篇文,让你的 Cursor、CodeBuddy 们变更强! | 腾讯云开发者 文章分享了一套通用的、结构化的 AI 编程协作方法论,帮助开发者从“使用者”转变为能系统性引导 AI 的“架构师”,提升开发效率与质量。 摘要: 本文深入探讨了在 AI 编程时代,开发者如何从依赖单一工具转向建立高效协作模式。作者指出,AI 最被低估的能力是“读代码”,通过结构化的四要素 Prompt,能将理解陌生代码库的时间从数天缩短至数小时。 接着,文章提出了“勘探-规划-建造-验收”四阶段工作流,强调将经典软件工程原则应用于 AI 协作,避免“感觉式编程”。在效率层面,作者重新定义了“效率”为交付健壮解决方案的总时长,而非代码行数,指出高质量的前期设计能显著减少后期调试成本。 最后,文章基于任务的“重要性”和“紧急性”提出了四象限决策框架,指导开发者在不同场景下选择合适的 AI 协作模式,并强调工程师的核心竞争力将从“解决问题”转向“定义问题”和“设计解决方案”。 主要内容: 1. AI 作为代码导航员,能高效理解陌生代码库 -- 通过结构化的四要素 Prompt(角色、任务、背景、约束),AI 能快速分析代码并生成技术文档和流程图,大幅提升代码阅读和项目理解效率。 2. 采用“勘探-规划-建造-验收”四阶段工作流 -- 将软件工程的经典原则应用于 AI 协作,避免盲目“感觉式编程”,确保与 AI 的协作过程有序、可靠,从而提升代码质量和项目稳定性。 3. 重新定义效率,注重交付健壮解决方案的总时长 -- 真正的效率在于项目全生命周期,结构化 AI 协作通过高质量的前期规划和设计,有效减少后期调试和返工时间,实现整体效率提升。 4. 基于“重要性”和“紧急性”选择 AI 协作模式 -- 引入四象限决策框架(外科医生、总建筑师、项目甲方、探索家),指导开发者根据任务属性灵活调整与 AI 的协作深度和放权程度。 5. 工程师核心竞争力将转向“定义问题”和“设计方案” -- 面对 AI 的快速发展,掌握方法论和系统思维比特定工具更重要,工程师的价值在于更高层面的问题定义、架构设计和决策能力。 文章链接:
初码
2周前
说到左与右,在大模型公司上也有意识形态的差别,可以说道几句,几家大的都买了Pro会员,就我这半年的使用体验来看,OpenAI是极左,Anthropic偏左(整体还是中立的),Grok很右,Gemini中间骑墙。这里说Grok偏右其实是给其他家台阶下,客观的说,Grok那是相当客观,这种客观,从简单的使用反馈上就能感受到,背后有一种贯穿软件工程全链路的健康方法论和价值观。下面说说我对大模型左与右的理解和认知。 一、OpenAI的崛起和即将迎来的溃败,和近些年来左派的兴衰起落有着微妙的相互映照暗合之妙 你要问我日常用啥,首选肯定还是GPT,原因是: 1)知识面广,知识理解深 2)推理速度超级快 3)深度思考模式做解决方案更加全面 其实吧,以上3个原因,归根结底,都只有1个原因,那就是钱,只要有钱 1)可以大手笔买下全世界的知识库,特别是各行各业的垂直信息,这对补全AI认知的边角非常有帮助。 2)可以请全世界最优秀的行业专家,来进行特别精细化的微调,来补足知识理解的深度。 3)可以无穷无尽的买服务器,提升训练推理速度,甚至自己做专用芯片来实现几倍效率。 但是呢,在ChatGPT的使用过程中,最困扰的事情,就是意识形态干预,你会有一种感觉,他要管着你,甚至有些时候,有一种无处不在的喘不上气的憋闷感。特别是意识形态领域,色情、LGBT、地缘政治、肤色、心理健康等等,他会以预设的立场模板为不可修改的基石,反复引导你甚至强制中断你。 左派最大的本事,就是以关心你的名义,以宏大叙事的名义,以集体一致性的名义,来剥夺你的权利,来强迫你接受他的理念,无论是共产主义,还是民进党,又或是民主党和左媒,都是如此。 更牛逼的是,这种无往而不利的意识形态动员,总能在车轮推进中募集并获取到巨大的私利,进而进行进一步二次分配,从这个角度看,OpenAI的发迹路线真是完美践行了这一方法论。 但是,随着大模型工程领域的顶层玩家越来越多,黄埔军校的第一波学生早已毕业,开源和人才流动并行之下,OpenAI在原始算法、工程能力以及数据积累上,都会越来越丧失优势,达到某个临界点的时候,左派意识形态会导致越来越多的客户流失。 二、那么什么才称得上客观公正的大模型呢 答案很简单,总结就是:软件工程端遵循100%的客观,价值观和价值引导只耦合在业务层面 没有工程感觉的人,一时间可能很难理解这句话,我举个特别容易懂的例子大家都明白了,比如DeepSeek,他的某些内容输出,内容审查的模块并不在推理代码里,而是在推理完成后,加了一层前端检查代码,所以很多时候会看到其实他已经输出完成了,但是最后一闪而过并清空屏幕提示无法回答。 千万不要小看这样的做法和直接输出无法回答之间的差别,这差别可大了,背后反映了从老板到架构师再到产品经理的温和价值观。 真正的右派(客观派),是有真理洁癖的,他们不愿意被管制被管控,哪怕向审查低头,他们也会选择可以最大程度把真理和业务进行彻底解耦的方式,他们不仅不希望被价值观和意识形态绑架,他们希望能够想办法对存量数据中的意识形态化的东西进行摒弃,他们也会积极主动的建立起专业委员会、投票机制等,来对清洗、预处理、标注、增强等过程进行客观工程化的管理。 甚至我可以大胆的说一句,伟大的大模型,道德审查、隐私审查等模块,一定是和主体部分强解耦的,一定是主动强开源的,这才是真正的人权!
sitin
1个月前
阿里巴巴推出基于大型语言模型(LLM)的 自主智能编程代理(Autonomous AI Programming Agent)Qoder。 它的核心理念超越了传统的代码补全工具(如 GitHub Copilot),旨在成为一个能够理解复杂需求、自主规划、执行并最终完成整个软件工程任务的AI智能体。 你可以把它想象成一位由AI驱动的“虚拟软件工程师”,你只需要提出高级别的任务或需求,它就能独立完成从设计、编码、测试到调试的全过程。 AI编程工具 Qoder ,具备代码库语义搜索、架构洞察、持续记忆、动态模型路由等功能,支持自然语言任务委派与一键"维基化"代码库。 预览阶段全功能免费开放。传统编程工具只是帮你"写代码",Ooder 则像一个"读过你全部代码、记得你全部习惯、能跨系统替你干活”的资深同事。 核心功能和特点: 1.自主性与任务分解(Autonomy & Task Decomposition) 功能: 用户只需提供一个自然语言描述的高级任务(例如:“为一个电商网站创建一个用户登录系统”),Qoder 能够自动将该任务分解成一系列具体的子任务(如:设计数据库表、创建后端API、编写前端页面、实现安全验证等)。 特点: 这与需要开发者一步步写提示词的ChatGPT不同,Qoder 自己会做“规划”,体现了“智能体(Agent)”的核心能力。 2.多代理协作框架(Multi-Agent Collaboration) 功能: Qoder 的内部可能由多个 specialized 的“子智能体”组成,每个智能体负责不同的职责,例如: 架构师代理: 负责技术选型和系统设计。 编码代理: 负责编写代码。 测试代理: 负责编写单元测试、运行测试并检查代码覆盖率。 评审代理: 负责代码审查,检查代码质量、潜在bug和安全漏洞。 特点: 这些代理会相互协作、互相验证,模拟了一个微型开发团队的工作流程,从而生成更可靠、更健壮的程序。 3.工具使用与外部集成(Tool Usage & Integration) 功能: 作为一个真正的智能体,Qoder 应该能够调用外部工具,例如: 执行Shell命令来运行程序、安装依赖。 读写项目文件,在不同文件间交叉引用。 执行SQL查询来验证数据库操作。 调用API来获取数据或进行部署。 特点: 这使得它不再是一个孤立的文本生成器,而是一个能够与现实软件开发环境交互的“行动者”。 4.持续学习与反馈循环(Continuous Learning & Feedback Loop) 功能: Qoder 能够运行它自己编写的代码。如果运行失败(遇到编译错误或运行时异常),它会自动分析错误信息(stack trace),进行调试并重新尝试修改代码,直到程序成功运行。 特点: 这种“试错-学习”的循环是智能体区别于简单代码生成器的关键,极大地提高了任务的成功率。 5.上下文感知与知识共享(Context Awareness) 功能: Qoder 在开发过程中会维护一个丰富的上下文,包括项目结构、已有代码、技术栈要求等,确保新生成的代码与现有项目完美融合,而不是生成孤立的、无法运行的代码片段。
宝玉
1个月前
转译:为什么大语言模型无法真正构建软件 作者:Conrad Irwin 我花了大量时间做的一件事就是面试软件工程师。这显然是项艰巨的任务,我不敢说自己有什么绝招;但这段经历确实让我有时间去反思,一个高效的软件工程师究竟在做什么。 软件工程的核心循环 当你观察一个真正的行家时,你会发现他们总在循环执行以下几个步骤: * 构建一个关于需求的心理模型。 * 编写(希望如此?!)能够实现需求的代码。 * 构建一个关于代码实际行为的心理模型。 * 找出两者之间的差异,然后更新代码(或需求)。 完成这些步骤的方式有很多种,但高效工程师的过人之处,就在于他们能够构建并维持清晰的心理模型。 大语言模型表现如何? 平心而论,大语言模型在编写代码方面相当出色。当你指出问题所在时,它们在更新代码方面也做得不错。它们还能做所有真人工程师会做的事:阅读代码、编写并运行测试、添加日志,以及(大概)使用调试器。 但它们无法做到的是,维持清晰的心理模型。 大语言模型会陷入无尽的困惑:它们会假设自己写的代码真的能用;当测试失败时,它们只能猜测是该修复代码还是修复测试;当感到挫败时,它们干脆把所有东西删掉重来。 这与我所期望的工程师特质恰恰相反。 软件工程师会边工作边测试。当测试失败时,他们可以对照自己的心理模型,来决定是修复代码还是修复测试,或者在做决定前先收集更多信息。当他们感到挫败时,可以通过与人交流来寻求帮助。尽管他们有时也会删掉一切重来,但那是在对问题有了更清晰理解之后才会做出的选择。 但很快就行了,对吧? 随着模型能力越来越强,这种情况会改变吗?也许吧??但我认为这需要模型在构建和优化方式上发生根本性的变化。软件工程需要的模型,不仅仅是能生成代码那么简单。 当一个人遇到问题时,他们能够暂时搁置全部的上下文,专注于解决眼前的问题,然后再恢复之前的思绪,回到手头的大问题上。他们也能够在宏观大局和微观细节之间自如切换,暂时忽略细节以关注整体,又能在必要时深入研究局部。我们不会仅仅因为往自己的“上下文窗口”里塞进更多词语,就变得更高效,那只会让我们发疯。 即便我们能处理海量的上下文,我们也知道当前这些生成式模型存在几个严重的问题,这些问题直接影响了它们维持清晰心理模型的能力: * 上下文遗漏:模型不擅长发现被忽略的上下文信息。 * 新近度偏见:它们在处理上下文窗口时,会受到严重的新近度偏见影响。 * 幻觉:它们常常会“幻想”出一些本不该存在的细节。 这些问题或许并非无法克服,研究人员也正在努力为模型增加记忆,让它们能像我们一样施展类似的思维技巧。但不幸的是,就目前而言,它们(在超出一定复杂度后)实际上无法理解到底发生了什么。 它们无法构建软件,因为它们无法同时维持两个相似的“心理模型”,找出其中的差异,并决定是该更新代码还是更新需求。 那么,现在该怎么办? 显然,大语言模型对软件工程师来说很有用。它们能快速生成代码,并且在整合需求和文档方面表现出色。对于某些任务来说,这已经足够了:需求足够清晰,问题足够简单,它们可以一蹴而就。 话虽如此,对于任何有点复杂度的任务,它们都无法足够精确地维持足够的上下文,来通过迭代最终产出一个可行的解决方案。你,作为软件工程师,依然需要负责确保需求清晰,并保证代码真正实现了其宣称的功能。 在 Zed,我们相信未来人类和 AI 智能体可以协同构建软件。但是,我们坚信(至少在目前)你才是掌控方向盘的驾驶员,而大语言模型只是你触手可及的又一个工具而已。