<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>oreilly on 元闰子的邀请</title>
    <link>https://yrunz.com/tags/oreilly/</link>
    <description>Recent content in oreilly on 元闰子的邀请</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Sun, 09 Mar 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://yrunz.com/tags/oreilly/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>走技术路线需要些什么？</title>
      <link>https://yrunz.com/p/%E8%B5%B0%E6%8A%80%E6%9C%AF%E8%B7%AF%E7%BA%BF%E9%9C%80%E8%A6%81%E4%BA%9B%E4%BB%80%E4%B9%88/</link>
      <pubDate>Sun, 09 Mar 2025 00:00:00 +0000</pubDate>
      
      <guid>https://yrunz.com/p/%E8%B5%B0%E6%8A%80%E6%9C%AF%E8%B7%AF%E7%BA%BF%E9%9C%80%E8%A6%81%E4%BA%9B%E4%BB%80%E4%B9%88/</guid>
      <description>荐语 本文要介绍的是O&amp;rsquo;Reilly在2022年出版的书籍，《The Staff Engineer&amp;rsquo;s Path》。
书中主要介绍走技术路线的工程师，或者说技术专家（Staff Engineer），需要具备哪些能力他们不仅仅要会写代码、做系统设计这么简单，技术能力只是基础，还要具备大局观、执行力和影响力。
如果你想走技术路线，那么本书值得一读。
前言 程序员的发展，总会遇到一个分叉路口，走技术路线，或者管理路线。
程序员总有股技术情怀，相信很多人最初都有坚定走技术路线的想法，但走着走着，最后都走上管理路线。
一方面，管理路线是清晰的，且有着大量成功的案例。对于沟通能力强、临危不乱、善于帮助周边同事成长的人来说，似乎成为管理者是一个常见，也是默认的职业发展规划。
另一方面，走技术路线，在很多人的理解里，就是不断提升技术能力。但是，这样走了一段路后，很可能就会遇到了向上发展的瓶颈，而转向管理路线。于是就有了所谓“不能一直搞技术”的结论。
然而，走技术路线遇到发展瓶颈的原因，并非是“不能一直搞技术”，而是“不能只搞技术！”
要走好技术路线，成为一名技术专家，拥有扎实的技术功底只是基础。除此之外，还需要具备全面的大局观、强大的执行力、良好的影响力三大能力支柱。
下面，我们将从技术专家的角色定位讲起，随后介绍这三大能力支柱，让你对“技术路线”有更深刻的理解。
技术专家是个什么角色？ 提到技术专家的角色定位，我们可能首先会想到“关键方案设计和开发”、“疑难问题解决”、“技术决策”，但还不止这些。
不是Manager，但也是个Leader 首先，技术专家也是一个Leader。
在技术路线上，深入技术领域只能让你走到高级工程师这一步，要想成为技术专家，主导更大的项目，你需要与更多的人沟通协作、说服他们接受你的方案、成为他们的榜样。
所以，技术专家不可避免地要成为一个Leader。
与Manager不同，技术专家通常没有直接下属，不负责人员管理，但他们同样需要在技术决策、设计和代码review等方面表现出领导力。
是个技术牛人 技术专家是一个高度专业化的角色。
你提出的设计和代码review意见，要有指导意义，能够让产品的代码和架构变得更好；做技术决策时，要理解各类因素的权衡，必要时能够深入代码细节，提出正确的问题。
所以，技术专家必须要有扎实的技术基础。
但这并不意味着技术专家要写大量的代码。为了高效地解决问题，很多时候，他们负责方案设计、指导中高级工程师完成编码，可能更有意义，这也是给其他人更多的成长机会。
牢记一点，技术专家最重要的是解决问题，而不是如何解决，代码、文档，都是一种方式。
了解了技术专家的角色定位，接下来本文将介绍技术专家所需要的，除技术基础之外的，三大能力支柱：大局观、执行力、影响力。
大局观 一个不断发展的组织，总会进行各种各样的决策：选择什么技术、打造什么产品、继续投资或者否决它。一个好的决策需要有详细、准确、全局的上下文知识来支撑。
一名技术专家很可能只是负责组织下某个产品或特性的技术方案，因此，很容易陷入局部最优的困境。
为保证能做出前瞻性的决策，技术专家需要成为一个纵观全局的人。而建立下面的这三张地图，也许能够帮你构筑大局观。
定位图（Locator Map）：广阔的视角 要避免局部最大化，需要建立一张定位图（Locator Map）以获得更广阔的视角：
 认清组织目标，找到真正重要的是什么。程序员很容易陷入唯技术论，技术专家要避免这一点。技术只是达成目标的手段，最重要的是搞清楚目标，是组织的目标，不是某个特性或小团队的目标。 理解客户的真正痛点。产品是为用户服务的，就算你的产品能够提升XX百倍性能，没有用户用，一样是没有价值。 了解领域行业动态。你正在解决的问题，很可能业界已经有人解决过。时刻了解你所在行业的动态，才能更高效地解决问题，更好地实现创新。  地形图（Topographical Map）：正确的导航 即使你有很强的技术能力，也可能会遇到好想法得不到重视、风险/困难无法提前识别、项目进展难以推动的情况。这时，你需要建立一张地形图（Topographical Map），帮助你实现技术落地、项目成功：
 理清组织结构，建立良好关系。了解你所在组织的结构，理清每个子团队所负责的业务以及关键角色，并于他们建立良好的关系。没错，技术专家也需要懂得“搞政治”，这样才能更好地开展工作。 了解组织文化。你的组织是倡导口头汇报还是书面汇报？鼓励快速试错还是深思熟虑后的变革？了解并融入你所在组织的文化，金子才能更好地发光。 保持地形图更新。为了更好地支撑商业成功，组织结构和人员的变化很正常，时刻更新你的地形图。  藏宝图（Treasure Map）：长远的目标 最后，你需要一张藏宝图（Treasure Map），找到自己的长远目标（通常是组织目标或者能够支撑组织目标的达成），并为之奋斗。
人们很容易过度关注短期目标，比如，当前版本发布的功能、某个用户对产品的差评等。寻求短期成功可能会限制你的发展。
要从更宏观的角度思考：
你想要达到什么目标？
你为什么要做这些事情？
这些事情能支撑你的目标达成吗？
本周的工作是否偏离了你的目标？
你是否还在不断接近你的目标？
执行力 技术专家需要很强的自驱力，要学会自己给自己安排任务，主动、提前为组织出谋划策，而不是等待被安排。
所以，技术专家通常会参与多个项目，处理很多事情。但人的精力总是有限的，学会时间和价值管理很重要。
可以尝试按照以下几个维度，为你所参与的项目/事宜进行打分，在有限的时间内完成最有价值的事情：
 能量（Energy）：这件事情将会耗费你多大的精力。 生活质量（Quantity of Life）：如果你的工作恰好是你的兴趣，那么你每天的生活质量将会非常的高。但这种机会是可遇不可求的，很多时候工作会降低你的幸福感。 信誉（Credibility）：信誉是领导力的一种体现，主导重要的项目、解决关键的难题，都能帮你提升在组织里的信誉。 社交资本（Social capital）：花时间与他人相处、与他们一起工作，建立良好的社交关系，互为战友。 技能（Skills）：技能是一种需要反复练习才能长久拥有的东西，你的工作内容一定程度上决定了你拥有哪些技能。  如何进行事情的优先级排序，一方面是要契合组织的目标，另一方面，也是你自己的职业规划。</description>
    </item>
    
    <item>
      <title>快速了解生成式AI</title>
      <link>https://yrunz.com/p/%E5%BF%AB%E9%80%9F%E4%BA%86%E8%A7%A3%E7%94%9F%E6%88%90%E5%BC%8Fai/</link>
      <pubDate>Sun, 19 Jan 2025 00:00:00 +0000</pubDate>
      
      <guid>https://yrunz.com/p/%E5%BF%AB%E9%80%9F%E4%BA%86%E8%A7%A3%E7%94%9F%E6%88%90%E5%BC%8Fai/</guid>
      <description>荐语 本文要介绍的是，O&amp;rsquo;Reilly在2024年出版的书籍，《Generative AI in Action》，作者是来自微软的Amit Bahree。
书中主要介绍了生成式AI的相关知识，涉及LLM、提示工程、模型微调、RAG、向量数据库等内容，作者给出了大量的代码示例，通过实战的方式带读者入门生成式AI。
生成式AI领域发展迅速，虽然本书是在2024年11月出版，但现在看来，书中介绍的技术已经算是“老旧”的了。不过，跟着作者的思路，读者能够快速理清整个生成式AI的技术脉络，有助于后续展开更深入的了解。
生成式AI概述 随着大模型LLM的大热，生成式AI（Generative AI，GenAI）近年来获得了越来越多的关注和普及。如下图所示，生成式AI是AI的一个子领域，演变自深度学习。
传统的机器学习基于统计学对数据进行预测；
深度学习基于神经网络模拟人脑行为，去执行复杂的任务；
而生成式AI则可以从数据中创作，就像我们人类一样。
如下列出了生成式AI与传统AI的一些区别：
    传统AI 生成式AI     用途 专注预测和分类任务 从原始数据中创造不存在的内容   硬件 所需算力较少，能够在各种硬件上运行 需要大量算力，通常运行在大规模的计算集群上。   训练数据 较小的标记数据集 大型的原始数据集   模型复杂度 百万级以下的参数数量 亿级以上的参数数量    很多人会错误地把ChatGPT与生成式AI划上等号，实际上，ChatGPT只是生成式AI最简单的应用。生成式AI能做的很多，个人层面，常见的如文字、图像、视频、代码、音乐的生成；企业层面，常见的如个性化营销、消费者服务、风险管控、合同管理等。
总而言之，生成式AI能够弥补传统AI的局限性，帮助用户和企业构建更加智能的应用。
在生成式AI领域中，大语言模型（LLM）作为大脑，能够生成出符合用户需求的内容，下文将简单介绍其原理。
大语言模型 大语言模型（Large Language Models，LLM）是生成式AI的基础，它由基础模型（Foundational model，FM）发展而来，后者在2021年被首次提出。
过去的AI模型通常只能应用于特定的任务，而FM则在此基础上做了泛化性优化，通过大数据量的训练得到了更强的适应性。
早期最具代表性的FM为Google开发的BERT模型，它被广泛应用于自然语言理解（NLU）任务，比如文本分类、命名实体识别等。
LLM是适用于自然语言处理（NLP）和生成（NLG）任务的基础模型，它的模型规模更大，包括参数数量、训练数据集大小、算力资源。
通常，LLM都会在名称上带上参数规模，比如Meta的Llama 2-70B，其中7B表示参数规模为700亿。
一般来说，模型参数越多，性能就越好，最近国产大模型DeepSeek V3甚至已经达到了671B规模。
当然，模型规模越大，就要消耗越多的算力资源，也就意味着更高的经济成本。因此，在一些任务较为简单或明确的场景，用户可能会偏向使用成本效率更优的小语言模型（Small language model，SLM），比如微软最近推出的Phi-4模型，它的参数规模只有14B，但得益于多方面的技术进步，它在数学推理方面超越了同类和更大规模的模型。
LLM的本质是利用当前上下文去猜测下文，但它并不像人类一样能够直接读懂自然语言。因此，必须把输入文本（Prompt）先分块（token），这样才能得到更好的泛化性，接着把它们转换成能理解的格式（Embedding），最后通过特定的算法（Transformer）去猜测出下文。
Token序列 当前，几乎所有的LLM都是基于token的架构，它是LLM处理文本的基本单位。
有多种将文本划分成token序列的方法，常见的如按字划分、按词划分、按句划分等。
划分的粒度越细，模型的泛化性也会更好，但token数量会更多，所需计算资源更大；
划分的粒度越粗，token保留的语义和上下文也就更多，数量也会更少，但遇到陌生词或多义词可能无法处理，依赖构建好的词典。</description>
    </item>
    
    <item>
      <title>深入理解单元测试</title>
      <link>https://yrunz.com/p/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/</link>
      <pubDate>Sun, 08 Sep 2024 00:00:00 +0000</pubDate>
      
      <guid>https://yrunz.com/p/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/</guid>
      <description>荐语 本文要介绍的是 2020 年 O&amp;rsquo;Reilly 出版的书籍 Unit Testing Principles, Practices, and Patterns，一本在豆瓣评分高达 9.9 的好书。
作为一名软件开发工程师，你应该对单元测试（unit test）很熟悉，但单元测试的目的、Mock 的正确用法、单元测试和集成测试的区别等等，你真的懂吗？书中对这些内容都做了深入的介绍，并通过实际案例教你如何写出好的单元测试。读完这本书，你一定会有醍醐灌顶的感觉，原来单元测试要这么写！
书中的另一个重要观点认为，单元测试和代码架构是息息相关的，写不出好的单元测试，极有可能是代码架构设计得不好。为了写出好的单元测试，需要不断对代码架构的优化，它们相辅相成，从而让软件能够持续演进。
为什么要写单元测试？ 单元测试的目的 如今，在软件开发活动中，单元测试已经成为企业级软件不可或缺的一环，是代码门禁的必选项。
如果突然有人问你，“为什么要写单元测试？”，你很容易会想到这样的答案，1）为了找到代码中已有的 Bug；2）为了防止引入新的 Bug；3）让代码架构变得更好；甚至是 4）满足代码门禁中覆盖率的要求。
但这些都不是我们写单元测试的根本目的，它们只是“写单元测试”这一活动所带来的副产品。
书中认为，单元测试的目的是实现软件项目的可持续增长。
企业级软件应用通常都有着业务逻辑复杂度高和生命周期长的特点。随着产品的不断迭代，代码会变得越来越复杂乱，每次修改代码也会变得越来越难，这就是软件的熵增定律。而单元测试的目的就是降低熵增的加速度，使得重构代码或新增功能变得更加的容易。
单元测试也分好坏 代码并非资产，而是一种负债，单元测试代码也是如此。
然而，我们往往会将生产代码和测试代码区分对待，忽略了对测试代码的维护，久而久之，测试代码变得冗余、复杂，甚至出现误报的情况。这样的单元测试，只会让系统的演进更加难。
如何评判单元测试的好坏？最常用的方法是代码覆盖率，也即测试用例执行了多少源代码。其中，又可分为行覆盖率和分支覆盖率。
行覆盖率计算执行了多少代码行，比如下面的例子，return true 的代码行无法覆盖，因此代码行覆盖率为 4/5=80%：
// C# public static bool IsStringLong(string input) { if (input.Length &amp;gt; 5) // 无法执行  return true; return false; } public void Test() { bool result = IsStringLong(&amp;#34;abc&amp;#34;); Assert.Equal(false, result); } 但是，某些时候行覆盖率并不能放映真实的覆盖情况，比如将上述的 IsStringLong 使用三目运算符进行重构，行覆盖率 3/3=100% 了，但实际情况并未改善。</description>
    </item>
    
    <item>
      <title>深入理解Lambda架构</title>
      <link>https://yrunz.com/p/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3lambda%E6%9E%B6%E6%9E%84/</link>
      <pubDate>Sun, 21 Jul 2024 00:00:00 +0000</pubDate>
      
      <guid>https://yrunz.com/p/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3lambda%E6%9E%B6%E6%9E%84/</guid>
      <description>荐语 本文要介绍的是 2015 年 O&amp;rsquo;Reilly 出版的书籍 Big Data: Principles and best practices of scalable realtime data systems，书中主要介绍一种常见的大数据架构 —— Lambda 架构。Lambda 架构通过批处理和流处理相结合的方法，有效处理了大数据场景下的工作负载。相比以关系型数据库为核心的传统数据系统，它在可扩展性、容错性等方面有了更进一步的提升。
虽然 Lambda 架构是十年前被提出的数据架构，但 Lambda 架构的以不可变数据作为核心、历史和实时数据分层处理的架构思想仍值得我们学习。
传统数据系统的局限 考虑有这么一个系统，根据用户的浏览记录，统计用户访问网页的次数：
在上述系统中，每次用户浏览一个 url，应用就会向数据库更新一行数据。随着用户量的不断上升，并发量急剧上涨，数据库最先达到瓶颈，频繁出现更新超时的现象。针对这种情况，我们可以引入消息队列，将单次写改成批量写，以此降低数据库的并发数。
但这并不是长久之计，随着用户量的再次上涨，单实例的数据库还是会成为单点瓶颈。为此，可以对数据库进行水平扩展，分库分表，将原本集中在单个数据库实例上的请求，负载均衡到多个实例之上。
分库分表虽能消除数据库单点瓶颈，但也会带来其他的一些问题：
 应用逻辑更复杂。应用层需要根据数据的 key 找到其所在的数据库实例，以便进行数据更新。 维护成本更高。为了避免因数据库实例宕机导致的服务不可用，需要通过增加数据副本、缓冲队列等手段提升可用性。另外，随着数据量的增大，可能因数据库实例间负载不均衡，而产生对数据进行重分区的操作。这些都会导致维护成本的急剧增加。 容错性问题。一旦开发者在更新数据库时出现人为错误，比如在增加 pageviews 字段时多乘了 2，那么数据将难以恢复，因为很难溯源。  上述例子中，从简单的 CURD，到增加消息队列、分库分表、副本、重分区等，系统也越来越复杂。导致这一切的原因是，传统数据库系统并非为分布式而生，它无法很好地适用于大数据场景。
大数据技术的局限 那么，大数据技术就能解决这些问题吗？答案是，否！
像 Hadoop、MapReduce、HBase 等这类大数据技术，虽然能够天然就处理海量数据，但它们都有各种局限，比如，MapReduce 是批处理系统，计算时延高；HBase 键值查询快，但无法满足复杂的 SQL 查询场景。
为了找到解决方法，我们还需从大数据系统的本质入手。
大数据系统的本质 作者对数据系统进行了如下定义：
 A data system answers questions based on information that was acquired in the past up to the present.</description>
    </item>
    
    <item>
      <title>软件架构，一切尽在权衡</title>
      <link>https://yrunz.com/p/%E8%BD%AF%E4%BB%B6%E6%9E%B6%E6%9E%84%E4%B8%80%E5%88%87%E5%B0%BD%E5%9C%A8%E6%9D%83%E8%A1%A1/</link>
      <pubDate>Sun, 16 Jun 2024 00:00:00 +0000</pubDate>
      
      <guid>https://yrunz.com/p/%E8%BD%AF%E4%BB%B6%E6%9E%B6%E6%9E%84%E4%B8%80%E5%88%87%E5%B0%BD%E5%9C%A8%E6%9D%83%E8%A1%A1/</guid>
      <description>荐语 本文要介绍的是 2021 年 O&amp;rsquo;Reilly 出版的书籍 Software Architecture: The Hard Parts（后文简称 SAHP），某种程度上，它是 Fundamentals of Software Architecture（后文简称 FSA）的延续，两本书的主要作者相同。FSA 是基础篇，重点介绍了常见的 8 种架构模式；SAHP 是进阶篇，重点介绍了如何从单体架构演进到分布式架构。
软件架构，特别是分布式架构，是很复杂的。这世上不存在所谓的通用架构模式，针对特定的应用场景，架构师需要在数据一致性、可扩展性、性能等多个因素上进行权衡，这也是本书标题强调的 The Hard Parts。
FSA 里有一句名言，“Everything in software architecture is a trade-off.”。本书的重点就是要教会你，在单体架构演进到分布式架构的过程中，如何众多因素上进行权衡分析，以此来选择出一个符合实际业务场景的软件架构。
为什么叫 “The Hard Part”？ 书的名字叫 Software Architecture: The Hard Parts，其中，Hard 有两层含义。
第一，软件架构很难。设计软件架构需要考虑的因素很多，架构师也必然会遇到各式各样的难题，而且它们往往没有通用的解决方法。软件工程的问题，很多时候可以通过 Google 搜索来解决；而软件架构的问题，只能根据实际的业务场景，在众多的考虑因素上进行权衡。所以，在软件架构上，不要试图找到最好的设计，而是要努力实现最不糟糕的权衡组合。
 Don’t try to find the best design in software architecture; instead, strive for the least worst combination of trade-offs.
 第二，软件架构是稳定的。Hard 取自于硬件的英文单词 Hardware，相比软件 Software，硬件是更稳定的一个，它是软件的基础。同理，软件架构是一款软件的架子、基础，好的架构通常都是稳定的，不轻易随软件的变更而变化。</description>
    </item>
    
  </channel>
</rss>
