外部性与程序设计

经济学里面有一个名为“外部性“的概念。外部性是指一个人或企业的行为对其他人或企业产生的影响。 外部性可以是正的,也可以是负的。比如,一个企业的生产活动可能会产生污染,这就是一种负的外部性,对周围的环境和居民造成了伤害。相反,一个企业的生产活动也可能带来正面的外部性,比如提高周围地区的就业机会或改善周围地区的基础设施。 外部性对于组织职责划分的启示 利用这个概念,我们可以用来分析组织的职责划分。 什么样的职责应该由下级组织负责?我们说,当某一件事没有产生外部性或产生了正的外部性,那么下级组织应该负责。此时如果上级组织非得介入,则反而会增加下级组织的沟通成本,降低效率。因为上级组织往往由于掌握不了足够的细节,而要求下级组织频繁的汇报信息。 但是,当某一件事产生了负的外部性,那么上级组织应该负责。此时,下级组织往往没有驱动力去解决这个问题,因为这会增加下级组织的成本,但是却不会增加下级组织的收益。 举个例子。比如,企业在生产过程中赚到了钱,顺便改善了周边的经济环境,创造了正的外部性,很高兴。但是对于产生污染这样的负外部性,企业就不太会在意,且没有驱动力去解决,因为这会增加企业的成本。这时,作为上级组织的政府就应该介入,协调企业和周围居民的矛盾,并负责督促企业处理污染,避免对周围环境和居民造成伤害。 外部性对于程序设计的启示 在了解了外部性及其应用之后,我发现它对程序设计也有很大的启发。 无外部性或负外部性与高内聚 其一是在类或模块的职责划分上。如果一个类或模块的行为不会对其他类或模块产生影响,那这个行为就应该让这个类或模块自己处理。我们常常说的内聚性就是这个道理。如果一个类可以基于自己管理的数据独立完成某个功能,那么这个功能就应该由这个类自己实现,而不是由调用它的类来插手。 当我们看到在某一个类的方法中直接修改另一个对象的内部状态时,就应该警惕,因为维护这个状态可能是另一个对象自己的职责。越俎代庖很可能破坏了另一个对象的内聚性,并增加了系统的耦合度。 而当一个类或者一个模块的行为对其他类或者模块产生了影响,就产生了外部性。 如果这种外部性是正的,那么我们可以说这个函数或者模块是“无害的”,无需处理,并应极力鼓励。比如,某一个类优化了内部的算法,使得整个系统的性能提高了,这就是一种正的外部性。我们应该经常鼓励这样的优化。 但是,如果这种外部性是负的,那么我们就需要特别警惕,并考虑如何处理这种负外部性。这样的负外部性常常隐藏较深难以发现。 负外部性与上层协调 举一个大家经常碰到的例子。在基于数据库的后端程序开发中,我们常常需要从数据库中读取数据构建领域对象。JPA 可以帮我们自动完成这个过程。但是,如果我们不注意,JPA 可能会产生一种负的外部性,即 N+1 问题。 N+1 问题是指,当我们从数据库中读取一个领域对象时,JPA 会自动为这个领域对象的每一个关联对象发送一个额外的查询。如果这个领域对象有 N 个关联对象,那么就会发送 N+1 个查询。这将导致性能问题。 JPA 默认在非所有者端默认使用一种叫做“惰性加载”的模式来处理关联对象。惰性加载是指,当我们从数据库中读取一个领域对象时,不会立即查询关联对象,而是等到我们真正需要使用关联对象时,再发送查询。大多时候,这种模式是有效的,因为我们可能并不需要使用所有的关联对象。但是,如果我们需要使用所有的关联对象,那么就会产生 N+1 问题。 这种负外部性很难在领域对象内部自己解决,因为它不知道调用者何时会访问到哪些关联对象。 为了解决这个问题,我们可以在对应的 repository 中显示地定义一个方法,用于一次性加载所有关联对象(或通过参数指定需要加载哪些关联对象)。这样,我们就可以在需要的时候,在调用方(上级组织)显式地加载所有关联对象。在实现时,我们可以使用 JPA 的 fetch join 特性,在查询领域对象时,同时查询关联对象。这样,就可以避免 N+1 问题。 下面是一个示例。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 @Entity public class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private Date orderDate; @OneToMany(mappedBy = "order", fetch = FetchType.LAZY) private List<OrderItem> items; } @Entity public class OrderItem { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String productName; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "order_id") private Order order; } @Repository public class OrderRepository { @PersistenceContext private EntityManager entityManager; public Optional<Order> findOrderByIDWithItems(Long id) { TypedQuery<Order> query = entityManager.createQuery( "SELECT o FROM Order o LEFT JOIN FETCH o.items WHERE o.id = :id", Order.class) .setParameter("id", id); List<Order> resultList = query.getResultList(); return resultList.isEmpty() ? Optional.empty() : Optional.of(resultList.get(0)); } } 上述代码 findOrderByIDWithItems 被设计为供上层调用,其实现过程中: SELECT o FROM Order o: 指定了我们要查询的主实体是 Order,并将其别名命名为 o。 LEFT JOIN FETCH o.items: 这是 fetch join 的关键部分。这里我们执行了一次 左连接 (LEFT JOIN) 来包括所有订单。这意味着当你遍历结果列表中的每个订单并访问其 items 集合时,不会触发额外的数据库查询,因为所有必要的数据都已经在初始查询中被加载了。 在发现 N+1 问题时,如果我们想在领域对象内部解决这个问题就很困难。此时应该改变思路,通过提供接口让上层组织中显式地调用,这个问题就迎刃而解了。 总结 外部性这一经济学概念在软件设计中也有鲜活的体现。通过识别和分析系统中的外部性,我们有以下启示: 无外部性或正外部性:类或者模块的行为对其他部分没有影响(无外部性)或产生积极影响(正外部性),则其职责应尽量内聚,由自己处理,并鼓励正外部性优化。 负外部性:行为对其他部分产生了负面影响,需要通过上层组织进行协调、解决。通过显式地提供清晰的接口,上层组织就可以灵活处理问题。

2024/11/23
articleCard.readMore

每日一思

2024-07-31: 最后一天 团队早会,轮到他更新昨日的工作内容。 如往常一样,他保持着端正的坐姿,双手放在桌子下面。转头面向电视会议屏幕,身体往前倾。 “嘿嘿嘿”,他短暂地停了约有 0.5 秒钟,咧着嘴,“嘿嘿嘿”。 “我昨天没什么更新,在整理交接的文档。”他停了约有 1 秒钟,“但我这边也没有人可以交接。” “我这边今天最后一天了,以后的测试就靠大家自己了。” 会议室很安静,一点声音也没有。一秒,两秒。 主持人终于切换到下一个人。 明天,他的座位就空了,每次早上一到办公室的时候都能见到的身影从明天开始就见不到了。 明天,他的座位就空了,经常下班还能瞥见到的忙碌的身影从明天开始就见不到了。 以后,非工作时间的会议也总是能保持准时参加的身影也见不到了。

2024/7/31
articleCard.readMore

每日一思

2024-07-25: T恤衫 打开衣柜,在叠起来的一摞 T 恤衫里面翻找,一件自己买的,一件公司文化衫,又一件公司文化衫,还有一件公司文化衫。 穿什么呢?抽出一件背过来叠起的黑色 T 恤,打开一看,是公司文化衫。这一件应该有三年以上了,前面印的 disruptive thinking 及机器人图案已经开裂并快要掉落下来了。 旧了。算了,换一件吧,我把它放了回去。正准备开始继续找,又犹豫了,还是这件吧,不知道还能穿几回! 穿上这件文化衫准备出门,在门口的镜子面前停了一下,衣服上面的图案的色彩还是鲜艳的。

2024/7/25
articleCard.readMore

每日一思

2024-07-17: 烦恼 周末,躺在沙发上看电视剧。时间过得飞快,一晃三个小时过去了。看电视当时的满足感随着节目的结束一起结束。 还有一件事情迟迟没有决定。电视剧转移了注意力,可以让人短暂地将它抛诸脑后。但是事情一直存在,短暂的回避之后,它又冒了出来。开始后悔,自责。 人的烦恼常常在于不能决定,反复纠结,迟迟没有行动。 做 A,没有照顾到 B。做 B,担心 C。做 C,又担心 D。似乎没有完美的方案。 那么,还要不要行动?如何行动? 2024-07-15: 晚餐 晚上,去吃饭。 走进餐厅,服务员将我们引导到了预先订好的包间。包间内,沿墙一圈贴着气球,有一个位置,上方贴着“happy birthday”字样气球。 一家人落座。她看看位置,对着我说,“来,你坐这里,气球正下方。” 刚一落座,蛋糕已送到,一个身穿蓝色制服送餐装的小姑娘提着蛋糕和一个方盒子进来。她打开蛋糕盒,点上蜡烛。接着打开方盒子,原来里面是音响和话筒。拿出话筒,她开始主持吹蜡烛吃蛋糕的仪式。 生日快乐的音乐响起,房间里面弥漫着温馨的空气。 还有唱歌的节目,欢快的声音响起。接着是跳舞,小姑娘示意大家一起来。平常几乎不参与这些活动的她,走过去,跟着小姑娘的手势和舞步动起来。她的动作偶尔慢半拍,但总能快速跟上小姑娘的节奏。 接着,有人提着一捧花送过来,红黄相间的玫瑰里面穿插着一些红色的纸牌。仔细一看原来是彩票。将彩票分给大家一起刮,这里有三十,这里有二十,这里还有三十,最后竟然刮出了 100 块钱。 大家开始吃饭,快吃完的时候,她说,还有一个礼物。递给我一个红色的盒子。我小心翼翼打开,里面有什么东西快速弹了出来。我赶紧关上盒子,结果还是有不少东西洒了出来。仔细一看,周围都是红红的百元纸币。 我还记得一件事。晚饭刚开始的时候,她转头向小孩说,“晚上要跟爸爸怎么说?”两岁半的小孩子,咧着嘴,歪着头,说,“爸爸生日快乐!”

2024/7/15
articleCard.readMore

每日一思

2024-07-13: 做事 小 A 在实现一个需求的时候,发现接口文档中的设计不太合理,返回的数据结构不是平台标准的结构。 如果完全按照文档完成,则需要引入没必要的定制,徒增了复杂性。于是,小 A 按照平台标准结构进行实现。 需求实现完成之后,小 A 在预定时间之前,提前将接口调用方式发送给下游。 下游在集成的时候,发现与文档对不上,提出质疑。小 A 与下游沟通,坚持采用平台标准的结构。 小 A 强调说,之前的文档只是一个设计文档,而不是最终的接口文档。最终的接口文档必须是双方根据实际情况进行实现,双方协调,集成之后,才最终确定的。 朱熹说,大凡做事底人,多是先其大纲,其他节目可因则因。 2024-07-12: 数据开发的反直觉性:字段重命名 小 A 觉得从上游数据源接入的数据字段命名不太合理,于是根据自己的理解将字段名重新映射为了一个新的名字。 数据 etl 基于这个新名字开发完了。 客户想要验证这个 etl 的正确性,于是从源系统中提取出明细数据让小 A 进行核对。 小 A 拿到数据之后,也自己提取了一份明细数据。两边一对比,小 A 就后悔了,因为客户提的明细数据的字段名全部是源系统的字段名,而小 A 则使用的是映射之后的名字。小 A 不得不重新做一次映射。 小 A 发现数据对不上,于是找到上游系统提数的人沟通。小 A 把自己的实现口径展示给对方看,对方看后,问道:“这个字段是什么?对应源系统的什么字段?”于是,小 A 又不得不去解释字段与原字段的对应关系。 小 A 感叹:这字段名映射,真不值! 2024-07-10: 团队会议 早上项目团队站立会议。由于团队分散在各地,会议在线上进行。由团队成员轮流组织,今天轮到一位小伙伴,他在团队中已经工作了几个月了。 打开项目看板,他开始组织大家更新自己的工作。 站会按照角色及人员的顺序进行。点击人员列表,他开始找人。 “A 来更新一下吧”,他说道。等了一会,没人回应。会议室陷入了安静。“A 下项目了”,终于有人接着补充道。 鼠标移动到 B 旁边,停下来,犹豫着要不要往前。时间过去了约有 10 秒钟,终于跳过了 B。B 是一个非当前角色的人。接着,他找到了正确的人,会议继续。 2024-07-09: 简单架构 有一个项目,其数据接入流程为:上游发送数据到 kafka -> 下游 flink 程序将 kafka 消息转换为标准的 debezium 格式 -> 另一个 flink 程序将数据写入到大数据平台以 iceberg 格式进行存储 -> 另一个 spark 批处理程序定时将 iceberg 中的数据增量写入到 hive 表 问题:中间过程太多,流程太长,涉及技术组件也多;为保证上述流程可稳定工作,还需要额外的 iceberg 表小文件优化程序;iceberg 表中的数据没有使用,无必要且存在浪费 优化:直接使用一个 spark 程序消费 kafka 数据写入 hive 表。 2024-07-08: 堵车 早上 8 点 10 分,还是按照以往的时间出门。昨晚下了雨,路上湿漉漉的。 拐过一个路口,来到了另一条路,通过这条路可以上主路。 刚一进这条路就发现已经堵得水泄不通了。车子只能慢慢蠕行,每次挪动不到一个车位的距离,挪动之后就得停下来等。 经过无数次挪动之后,看到了一点进度,到了一家吃串串的餐饮店。我感觉不太对,虽然以前这条路也堵,但是今天也太离谱了。以往三分钟的路今天竟然走了十五分钟! 没办法,到这里也只能硬着头皮继续往前挪了。经历了差不多半小时,终于才上了主路。 上主路的路口,有一个交警正在指挥交通。

2024/7/8
articleCard.readMore

每日一思

2024-07-07: 喂饭 家里小孩快两岁半了,自己吃饭还吃不好,主要靠姥姥喂。 我在椅子上坐着,姥姥端着饭跟在小孩后面。 姥姥装满一大勺饭喂过去,小孩张着大口,一口吃了下去。我说:“耶,这一大口吃的好。” 姥姥一边喂,一边跟我说道,“看,饭都冰冷了。每次都得饭冰冷了才肯吃。” 停了一下,用勺子翻了翻碗里的饭,又说道,“现在开始想吃肉了,要把肉末混在饭里面才肯吃。只有菜,就不吃,吐出来。嚼两口,说没味道。每次还要把肉放在上面,露出来,给他看到,才吃得好。” 我笑了笑。这才发现,姥姥已经是喂饭的专家了。 2024-07-05: 动机转移 当我工作到很晚,为了解决一个疑难问题时,我不认为这是在加班,而其实这是我在提升自己。 当我跑步累到时候完全不想动时,我不认为这是在挑战自己的体力,而其实我是在用跑步刺激自己思考昨天没有解决的问题。 当我持续在读书时,我不认为是想要学到多少新知识,而是想找一个智者对话,了解一些思考问题的全新的角度。 当我坚持写下这一行行文字时,我不认为这是在与自己较劲,而是希望借此机会回顾一下今天,让它在转瞬即逝的生命里留下一点点痕迹。 你行为的意义在于你如何看待你的行为。在心理学中,这被称为“动机转移”。那么,你想如何转移你的动机? 2024-07-04: 和平 1 月 20 日,老李在公司上班,接到公司的全体会议邀请。会议时间在中午,公司领导层用了一小时提醒说,当前形势严峻,可能要裁员。 2 月 15 日,老李在公司上班,接到公司的全体会议邀请。会议时间提前了一点,在上午快下班的时候。公司领导层用半小时公布了裁员计划,10%。 4 月 10 日,老李在公司上班,接到公司的全体会议邀请。会议时间在早上 9 点到 9 点半,这个点,老李还在与客户的会上。 事后,老李从参与会议的同事嘴里了解到,公司发现财务状态不见起色,可能需要继续裁员。 5 月 5 日,公司发布组织架构调整计划,目标是更加面向市场,提高盈利能力。 6 月 10 日,公司发布进一步组织架构精简的计划。 在世界的那边,俄乌战争在继续,中东的硝烟似乎越来越浓。 2024-07-03: 意义 威尔一直坚持跑步,持续了很长时间。盯着满满一屏幕的打卡记录,心里非常满意。 然而,坚持是不容易的,某一天,一个声音在脑中响起,跑步还是挺累的,歇一歇吧。威尔把这个念头告诉他的朋友。朋友反问威尔:“威尔,你想想,你是想要怎样的生活?你想去当健身教练吗?” 威尔愣住了,他确实没有兴趣当健身教练。那坚持跑步是为了什么呢?身体健康?不跑步似乎也不怎么损害健康。 威尔停止了坚持很久的跑步。生活进入舒适循环。他在闲暇时可以无忧无虑躺在沙发上刷手机几个小时。 然而,一段时间之后,威尔发现以前自己的状态没了。肌肉变松弛了,思维似乎也没那么敏捷了。 威尔发现不对。坚持的意义是什么?可能是让自己一直保持一种让自己满意的状态。 威尔又开始了。

2024/7/3
articleCard.readMore

每日一思

2023-12-30: 他不害羞 电梯里,他睁着大眼睛,抬起头,目不转睛地望着旁边的阿姨,一直望着阿姨,一直望着阿姨。我们都看着他,忍不住笑。他突然开始朝着阿姨笑,没有发出声音。阿姨也看向他,看他望了很久,也开始对他笑,“小朋友真可爱!” 电梯里,几位叔叔阿姨一起同行。电梯门开了,叔叔出电梯了。“叔叔拜拜,叔叔拜拜!”他对着电梯门大声说。电梯门又开了。“阿姨拜拜,阿姨拜拜!”电梯里面进来一个人,阿姨没有下电梯。姥姥说,“阿姨还没到。” 电梯门开了,我们到了。我们走出电梯。“叔叔拜拜,阿姨拜拜,爷爷奶奶拜拜!”

2023/12/30
articleCard.readMore

每日一思

2023-12-24: 童言 “小鸡怎么叫?”“小鸡叽jī叽jī叽jī。” “小狗怎么叫?”“汪wàng汪wàng” “大公鸡怎么叫?”“咯gé咯gē咯gé。” “母鸡怎么叫?”“母鸡咯gé咯gē哒dà。” “关guán门啦。”在看了很多遍小兔子乖乖的视频之后,他经常这样说。 有一次,家里人围坐在一起教他说话,一个人说,“妈妈好棒”,另一个人说,“妈妈好笨”,到他嘴里,最终变成了“妈妈好beng!”

2023/12/24
articleCard.readMore

成长

他没有做过数据开发,但是对新技术很有兴趣。项目刚开始,正是需要有能力的开发人员加入的时候,他加入了团队。 将数据实时接入数据平台可以提升数据导入性能。当前已经有一个实现,但是性能问题很突出。在数据量激增时,延迟会变得很高。他接受了这个挑战。 “搭建一套环境,重现这个性能问题,应该就能解决。”团队初步确定了思路。数据开发用到了很多技术,Oracle、OGG、Kafka、StreamSet、Kudu等等,对于他而言,都是全新的。 接下来几个晚上,他放弃了很多休息时间,学习,学习,学习… 环境终于搭建好。他构造了一个测试场景:生成数据,导入各个模块,搜集性能数据。问题重现了出来。他开始研究各个模块的实现原理,并着手调整各个模块的配置,快速的反馈让他很容易验证配置修改的效果。终于找到了症结:之前的配置没对,不能将系统性能发挥出来! 实时数据接入问题解决之后,他开始转到业务开发。这是一个全新的领域,涉及上游十个以上的复杂系统,数百张数据库表,成千上万个字段。 接下来几周,他放弃了很多休息时间,学习,学习,学习… 团队通过内部分享来检验大家的学习成果,他欣然参与到每天的业务分享中来。 数据建模是一个新的领域,开发工具和编码语言也是新的。他领取了一个相对容易的任务,开始工作。经过几天紧张的适应期之后,他顺利搞定了这个任务。 感觉还不太过瘾,他想要领取一个复杂的任务。他拿到了一个预估需要2到3周才能做完的任务。抽取模型,复用已有模型,简化代码,重新实现,代码重构,数据验证。他投入到这些新的复杂的开发过程中去。他经常一坐下,便是一上午或者一下午不起身。键盘声有节奏地响起,他一会注视屏幕的左边,一会儿又切换到右边。很少看到他上厕所。 经过两周以上紧张的工作,他搞定了这个复杂的任务。 下个月上线,团队准备发布之前的实时数据接入功能。在运行一段时间之后,发现另一个问题:某一个组件会不定时的重启,当数据量激增时,这个重启操作将导致延迟增加20分钟以上,这无法接受。 他主动调查这个问题。 离上线时间越来越近,这个问题必须要尽快解决。 他下载了这个开源组件的代码,并搭建了一套编译环境,根据日志中的报错信息,找到相关代码。他仔细阅读研究这部分代码。代码用了一种异步的方式实现,包含了大量的细节,不易理解。他利用了很多休息时间,学习,学习,学习… 他发现之前的代码实现上有一个小的缺陷。在服务器压力上升时,客户端不仅没有及时停止发送请求,反而发送了更大量的请求。这进一步加剧了服务器压力。最终服务器丢弃了更多的请求,导致客户端超时重启。 找到问题根源之后,他提出一个方案:可以在发生超时时,先等待一段小的时间,然后再发起请求。这可以降低服务器压力,从而让系统在负载较高时也不至于失败。 他实现了这个方案,并验证确实有效。 “你们真是厉害,开源项目的问题也一起改了。要是别的合作商,肯定不会管这个。”在看到他顺利解决了这个问题之后,客户这样说。 他很喜欢徒步,经常在结束了一周紧张的工作之后,参与到一些周末徒步活动中。每次周末回来,他的精神状态都不错。 他也喜欢看书,火车上是他读书的理想场所。每次在火车上同行,总是看到他捧着一本书津津有味的读起来。他也经常分享看过的书。有一本毛主席的警卫写的毛主席回忆录,是他极力推荐给我的。

2023/12/24
articleCard.readMore

平淡与不平淡

早上送完人回到家,快两岁的小孩子已经起床穿好了衣裳,家里人正在准备早餐。 “要吃饼饼”,小孩子指着一袋子蛋卷说。看看给他准备的牛奶马上就要好了,就对他说,“我们先喝牛牛好不好,喝完牛牛再吃饼饼”。小孩子一改以往得不到就吵闹的样子,嘴上说着“喝完牛牛再吃饼饼”,往摇奶器那边走过去。 安安静静地喝完了牛奶,热好的烧麦和煮好的鸡蛋已经上桌。我叫上小孩子,“要不要吃包包?” 小孩子走过来,“包包好吃。” 我一边吃烧麦,一边喂给他。小孩子一改以往吃东西乱吐的习惯,开始大口吃起来。 吃完了大半个烧麦,我剥开一个鸡蛋,问他吃不吃。小孩子笑一笑看着我,“蛋波波好吃”。先喂他吃一口蛋白,再挑出一瓣蛋黄给到他。小孩子一改以往吃东西落满地食物的习惯,今天照单全收了,地板上甚至很难找到掉下来的残渣。 吃过饭就和姥姥出门了,回来已经11点。姥姥买回来一袋水果,说,“椪柑应该还好吃。” 我剥开一个准备尝一尝,小孩子也凑过来想要吃。我剥开一瓣给到他,他还是像以往一样想要双手拿一大把。我对他说,“水果一次只能吃一瓣,吃完才能吃下一瓣”。他重复我的话,然后把多余的给我,开始吃起来。吃出了一个桔子核,小孩子一改往日随地就吐的习惯,说,“桔子核要丢垃圾桶”,然后跑到垃圾桶旁边把桔子核丢了进去。 早上的时光还剩一点,小孩子玩起了识字挂图,开始点按里面的人物。“科学家,画家,服务员,老师…”,识字挂图开始发出声音。我走过去问他科学家在哪里,“在这里啊”,他说着并把手指向科学家。我又问了画家在哪里,他竟然也指对了!我满脸的惊诧。 玩了大约20分钟的识字挂图,他又去找其他的玩。这时姥姥出门丢垃圾回来,小孩子就跟着姥姥进了卧室。我在沙发上休息。过了一会儿,姥姥也到沙发上休息。突然我一晃神,怎么这么久没有听到小孩子的声音了。赶紧走过去想看看小孩子在干啥。一过去就发现,原来小孩子把房门钥匙拔下来了,正在想办法把钥匙插回去。他身高还不够,尝试了好几次都插不进去。有几次眼看要插进去了,最后还是滑到了其他地方。小孩子一点声音也没有发出,努力地尝试要把钥匙插回去,努力地尝试要把钥匙插回去。 到了午饭点,小孩子还没有插好钥匙。“快过来吃莽莽,吃完莽莽再来插钥匙好不好?” 小孩子犹豫了一会儿,就过来开始吃午饭。午饭依然很顺利地就吃了一小碗。 吃完午饭,是小孩子午睡的时间点了。我坐在椅子上,闭目养神,跟他说,“睡觉觉好舒服,睡好觉觉精神好好。你想不想睡觉啊?”小孩子起初还有点抗拒,等了一会,看我想要休息的样子,他也跑去找到姥姥,说要睡觉。然后要姥姥帮助脱下鞋子和袜子。脱下鞋袜之后,他就开始自己哼着歌,“嗯…嗯…嗯…嗯…”,这稚嫩的声音混合着姥姥的“哦…哦…哦…”,组成了一首绝佳的催眠曲。时间也就过去了几分钟,他就进入了梦乡。 不知道他的梦乡甜不甜,反正我今天已经感动到不写完上面这些文字就睡不着觉了。 转念一想,带小孩其实跟项目交付很像。有些项目交付,在表面上看,也许就只是如同今天小孩的表现一样,平平淡淡,普普通通。但是在这背后,十里地开外,也许就是波涛汹涌的洪水。如果不是身在团队中间,怎能知道这平淡和普通其实是由于团队建立起了一座阻挡洪水的高高的堤坝?

2023/12/17
articleCard.readMore

每日一思

2023-12-17: 传承 “搞破坏,搞破坏不乖”,在跟他说过这些之后,这几句成了他这几天的口头禅。 “瞎搞”,偶尔也能从他嘴里冒出来。 很久以前,每次在他准备打开平板电脑的时候,都会跟他说,“这个搞不得”。现在,当他发现平板电脑在旁边,想去玩一玩的时候,只要我在旁边,他都会重复之前说过的话:“这个搞不得”。 “拉粑粑要跟妈妈说”,虽然他现在还是每次拉完粑粑都不说,但是每当我们问起他为什么不说的时候,他总是重复着上面这句之前跟他说过的话。 传承,是个很奇妙的过程。 2023-12-16: 他其实学会了 和家里人一起在公园游玩,小孩子推着他自己的婴儿车往前走,这是他一直很喜欢的事情。 突然,地上有一个坑,挡住了婴儿车的轮子,推不动了。他望着姥姥说,“姥姥帮忙,姥姥帮忙!” 姥姥一脸惊诧,“哎呀呀,姥姥帮忙?真能干啊,什么时候学会叫姥姥帮忙了?什么时候学会的啊?这没人 … 2023-12-14: 又好气又好笑 家里小孩很喜欢吃蛋卷,但是有个坏毛病是喜欢每次拿一大卷,在吃的时候又总是免不了残渣掉满地。 一天中午,我特意把蛋卷掰成了一小块,递给他,小伙子用充满稚气的话说,“好大坨!” 小孩妈妈在旁边捂着嘴,禁不住地笑出声来,“哈哈哈,哈哈哈,好大坨!” 从此,小伙子记住了,“好大坨”这个词很好笑。后来很多次,他玩着玩着就突然冒出来一句:“好大坨”。 2023-12-12: 难得的安静 早上送完人回到家,小孩子已经起床穿好了衣裳,家里人正在准备早餐。 “要吃饼饼”,小孩子指着一袋子蛋卷说。看看给他准备的牛奶马上就要好了,就对他说,“我们先喝牛牛好不好,喝完牛牛再吃饼饼”。小孩子一改以往得不到就吵闹的样子,嘴上说着“喝完牛牛再吃饼饼”,往摇奶器那边走过 … 2023-12-11: 他也要做决定 今天天气不错,一阵微风吹散了笼罩城市多日的雾霾,太阳也从云层中探出头,把光明撒向大地。 去晒个太阳吧,这是个好主意。午饭之后,待孩子睡了一个午觉起来,家里人就开始收拾东西,尿不湿、水、各类纸巾、零食等等。我还特意剥了一个特别难剥的柚子。 好了,一切收拾妥当,准备出发。 小孩子快两岁了,跟着我们迈着小步子朝电梯走去。到停车场了,准备上车。爸妈把门拉开,示意小孩上车。“不上车,不上车,不坐车车,不坐车车”,小孩突然开始吵闹起来,一靠近车子就把身子往外面扭。咦?这是怎么回事,以前坐车都好好的,怎么今天突然不愿意坐车呢? 爸妈开始哄孩子,“乖,快上车我们去晒太阳,外面天气好好哦”,劝了好半天,小孩就是无动于衷。 等了好一会儿,小孩还是不愿意上车。实在没办法,大家只好收拾东西折回家去。 到了两岁的年纪,小孩子也想要自己做决定了。

2023/12/11
articleCard.readMore

每日一思

2023-12-10: 城里人去住别墅 卧室外面是一个十来平的小院子,一张长方形的石桌子摆在一边,桌子旁立着四张方形石凳。桌子和凳子不少地方都露出了石头原本的颜色和样貌。 深秋时节,金黄色的银杏叶飘落,零星的洒落在院子里。拾起一片,满片树叶都是黄色,像是已经熟透了,有的地方甚至有点泛白。叶子上面的脉络,清晰可见。 邻居院子突然传来几声清脆的交谈声,有两个人,说的是无聊的琐事,但清脆的声音在安静的环境中显得特别清晰且响亮。可惜和他们隔着一堵墙,我踮起脚也只能看到他们的头顶,否则真想和他们打声招呼,问问看是否吃过了早餐。 这里也能听到鸟叫,偶尔还有几只小鸟悄没声地飞到院子里,在草丛里面翻找着食物。 不禁开始怀念起小时候在农村家里的样子,也是安静的早晨,新鲜的空气,唧唧乱叫的小鸟,和清脆的人声。

2023/12/10
articleCard.readMore

每日一思

2023-09-30: 中秋节的月亮 10小时自驾,在一轮满月的陪伴下到家,终于见到一个月未见的小孩。平常的他10点睡觉,但今天,快到11点了,他还没有睡。 开门就发现,他满脸堆笑的站在门口,“哦!哦!哦!”高兴地拍手。 妈妈上前去,想要抱起,小孩有点不知所措,竟然推开妈妈的手,想要保持一点距离。大概在快速成长的小孩眼里,一个月已经是很长很长的时间了。 最终他还是投入了妈妈的怀抱。妈妈仔细端详起来,“长高了一点,越来越瘦了”。 小孩还是那么活泼,感觉有无穷的精力,在屋子里跑来跑去。现在正是语言爆发期,大人说什么,简单的,他也能跟着说。“好多大车车”,“骨头”,“鸡肉”,“丢到垃圾桶”,这些都是他新学到的几句话。 今天晚上,小孩兴奋了很久,12点才有睡意。 2023-09-29: 你看到的是什么 客户下班时间有事找到你,你会觉得这是一个新机会,还是烦人的加班工作? 碰到一个很复杂的技术问题,你会觉得这是一个提升的机会,还是一个巨大的风险? 梭罗说,我并不是说约翰或者乔纳森能够彻底明白这个道理;但正因为他们不明白,所以早晨只是时间的流逝,而不是真正的破晓。导致我们闭上双眼的阳光,对我们来说就是黑暗。只有在我们醒着时,天才是真正的破晓。日出未必意味着光明。太阳也无非是一颗晨星而已。 世界是什么样,那取决于你看世界是什么眼光。 2023-09-27: 正义的原则 作为20世纪最有名的政治理论家,罗尔斯,针对当下流行的功利主义正义观提出了批评,并提出了正义二原则来促进更大程度的自由和平等。 罗尔斯认为存在两类基本善(基本善是指经由社会合作产生并用于可分配的所有东西,比如财富、收入、人的自由、权利、机会、自尊等):一类“基本善”,如言论自由、人的自尊等,可以被平等分配;另一类“基本善”,如出身、天赋、收入、财富、机会、权力等,无法被平等分配。 如何解决这两类基本善的公平分配问题?罗尔斯提出了两个原则,即正义二原则: 第一原则是最大的平等自由原则:每个人对与其他人所拥有的最广泛的基本自由体系相容的类似自由体系都应有一种平等的权利。 第二原则包括差异原则和公平的机会平等原则:社会的和经济的不平等应这样安排,使它们 适合于最不利者的最大利益,并与正义的储蓄原则相一致(差异原则); 在公平的机会平等的条件下,使所有的职务和地位向所有的人开放(公平的机会平等原则)。 其中:第一原则优先于第二原则,即第一类基本善应该被公平分配;第二原则中,公平的机会平等原则优先于差异原则,即在出现第二类基本善的分配问题时,对所有人公平优于向弱者倾斜。 2023-09-26: 流水 最近做了一个明智的决定,那就是设置了短视频的每日使用时长。达到设置的时长之后,就需要输入密码才能继续使用,而我特意设置了一个随机的记不住的密码。 每次短视频提醒我的时候,我就知道:今天时间已到,需要安排其他事情了。于是,果断关闭它。 突然发现周末的时间变多了,可以做一些其他的事情。散步,做一餐饭,运动一下,打扫一下家里的卫生,把早该清洗的家具清洗一下,上网查一查东西要买哪一个品牌。生活一下子变得更充实了。 短视频就像流水,你坐在船上,水载着你自动往低处流去。如果你不主动停下,水就载着你越走越远。 2023-09-25: 用户体验 开火1:按压燃气灶开关,扭动,电池打火装置啪啪啪响起来;此时不能松手,需一直按着开关,否则将因为刚开始时燃气浓度太低而熄火;直到火势稳定,放手。 开火2:按压燃气灶开关,扭动,松手,火随之打着;为避免熄火,燃气灶自动保持啪啪啪打火,直到火势稳定。 煮蛋1:打着火,放入水和鸡蛋,记下开始时间,并计算煮好的时间;去忙其他事;时间到了,进厨房关火,捞出鸡蛋;再忙也不能忘记,否则,鸡蛋煮过了,或者,锅烧坏了。 煮蛋2:打着火,放入水和鸡蛋,设置13分钟定时关火;安心做其他事;其他事做完,回厨房,捞出煮到恰好的鸡蛋。 油烟机操作1:根据火势大小及油烟强度,判断吸力档位,然后,按动烟机上面的按键;炒菜完,不能忘关烟机,否则,它一直工作并发出呼呼呼的噪音;不能关太早,否则,空气中油烟未完全消除,余味绕梁。 油烟机操作2:无。(自动与燃气灶联动,开机、调节大小随火势自动变化;炒菜完毕自动延迟关闭)

2023/9/25
articleCard.readMore

每日一思

2023-09-24: 感染力 她双手分别拿起一块鹅卵石,快速碰在一起,“铿”,声音不大,但在偌大的掉一根针都能听到的大厅里,这清脆的声音可以清晰地传入耳中。 紧跟着这一声“铿”,后排的三位伴奏者也同时敲下手里面的鹅卵石,三声“铿”分秒不差地重叠在一起,合并为更沉闷的一声“铿”传入耳中。 随着节奏往前推进,她一边敲击鹅卵石,一边轻声走向后面摆好的鼓阵。“铿铿”声瞬间切换为“咚咚咚咚”密集的鼓点,时而大时而小,时而密集时而稀疏,有时候是敲在鼓边的更清脆的“咚”,有时候是敲在鼓心的大声的沉闷的“咚”。这声音快起来的时候,她挥舞的鼓锤变成了看不清的残影;这声音慢起来的时候,她舞动的手臂像是在跳优雅而浪漫的古典舞。 谁说鼓只能拿来敲?只见她双手在鼓面上面划着圆圈摩挲,顿时响起一阵阵沙沙声,伴奏的三人也随之摩挲起来,一阵阵“沙沙沙沙”声此起彼伏。一会儿呼呼的风声响起,一会儿滔滔的水声响起,一会儿又“啪啪”的海水拍击礁石声响起,这声音哪里是来自她们手里的乐器?这声音分明是来自大自然! 一曲终了,她移步另一处鼓阵,这鼓锤再次与她手臂融为一体,一阵密集的鼓声之间,竟然出现了一声清脆的木棒碰到金属的声音。哦,这是旁边的金属架。开始是一声,后面越来越多,鼓声则越来越少。再后来,竟然全部是鼓锤敲击金属架的声音。随着她缓慢移步,旁边的鼓架、放乐器的桌面、桌子的桌角、地面全都变成了她的乐器。“铿铿”、“锵锵”、“砰砰”、“哐哐”、“啪啪”这不同质地的敲击声和谐地有节奏地发出,组成了一曲错落有致的壮丽乐章。 2023-09-23: 语言的能指和所指 著名的语言学家索绪尔在分析了语言的结构之后,发现我们所说的每一个语词都存在能指和所指两个概念。 能指是指一个语词的符号,而所指是指该符号所表达的概念和意义。能指是人们想要表达其所指时赋予的一个符号。 所指优先于能指而出现。比如,苹果作为一种球形的红色水果,在没有人类语言之前也是一直都存在的,人们为了表达这种水果,于是设计了一个符号“苹果”。 区分了能指和所指之后,就能理解,当我们想要表达某一个意思(所指)时,我们通过说出来一系列符号(能指)来实现。但是,听众却只能通过这些能指来理解我们的所指。于是,误解便经常产生。 如何消除误解?结合语音和表情,我们就能更多的获得对方的所指,这即是我们所推崇的当面沟通。 在软件开发领域,我们用变量名、函数名、类名、包名等编程语言元素来表达我们的所指。由于这些名字同样是自然语言,只是一种能指符号,其背后的所指常常因人而异。这就不难理解为什么我们读他人的代码会比较困难。 如何缓解?这可能需要我们每一个人在编写代码时都需要尽可能用清晰易懂的、没有歧义的语词。 2023-09-22: 理解就是视域融合 人是历史的人,每个人都身处不同的历史阶段下。人同时也是社会的人,每个人都在他的社会圈子中的活动。所以,人的认知范围受限于这个历史阶段和社会圈子,这个有限的范围就是人的视域。 一个人与另一个人沟通,需要彼此相互理解,理解的过程就是视域融合的过程。如果两者的视域完全没有交集,则无法相互理解。如果两者视域接近,则很容易相互理解。 视域的融合就如同可乐和雪碧的融合。当你作为可乐与另一个作为雪碧的人交流时,他的雪碧就会融入你的可乐,从而改变你的颜色和味道。同时,你的可乐也会融入他的雪碧,他的颜色与味道也因你而改变。 理解是两个人的双向奔赴,相互找到可融合的点,求同存异。理解也是无法相融的视域发生碰撞的点,碰撞激起的火花带来创新。 2023-09-21: 交往理性 在物质生活高度发达的今天,普世的教育是对科技的崇尚,认为脱胎于科技的工具就是人类之光。但是过于崇尚科技和工具,就容易忽略一个问题:科技的最终目的是服务于人并提升人类整体的幸福感。 在资本主义社会里,企业执着于创造利润,人不仅没有得到应有的服务,反而不得不面对越来越长的工作时间,越来越大的工作强度以及越来越低下的生活品质。如此一来,我们发展科技的作用是什么? 德国当代哲学家哈贝马斯提出的交往理性正是针对当今社会的工具理性中的问题而提出。工具理性的社会里,人由于使用工具产生了莫名的优越感,人与人之间的情感变得冰冷。交往理性呼吁人们关注和回归人与人之间的交往过程,提醒人们保持谦逊,用相互可以理解的方式沟通,求同存异,从而营造一个和谐共处的环境。 敏捷宣言中有一句话是个体和互动高于流程和工具。可以发现,敏捷宣言与交往理性所推崇的价值观是一致的。在软件开发活动中,我们只有把人的位置放在工具之上才能帮助我们构建更高质量、更人性化的软件工具。 2023-09-20: 知觉 我们很熟悉感觉,即用身体器官去感受世界而觉察到一些东西。它包括视觉、听觉、触觉、嗅觉等等。 知觉是什么?在梅洛庞蒂看来,从身体到心灵之间的桥梁就是知觉,知觉是基于心灵的认知的感觉,它把身体和心灵给紧密联系起来。 试想,如果我们在感觉之前,没有任何的感受经验,对将要感受的外物也没有任何的认知,那我们会如何对待接下来的感受?大概就如同婴儿,只剩下一些模糊不清的本能反应。 如果我们没有感受,而只有心灵,如同笛卡尔所说“我思故我在”,那我们可能根本无法成长起来,因为婴儿最开始的成长就是不断感受世界。即便成长起来了,没有身体的心灵也将如果植物人一样没有任何依附。 所以,心灵和身体是和谐的,不可分割的,知觉就是建立它们之间联系的桥梁。我们依靠心灵的思考,结合从感觉中获取的信息,而与世界进行交互。 2023-09-19: 匠艺与匠人 我们常常听说软件匠艺,字面意思是指把软件做成艺术品,这应该是每一个做软件开发的人的追求。 我对此的理解是,要做软件匠艺先做软件匠人。 什么是匠人,最初的匠人是指精益求精的手工艺人。在软件开发领域同样需要精益求精的精神。 如果你舍得多花五分钟把代码格式调整好,那你就在精益求精的路上往前走了一步。 如果你舍得在写代码之前仔细思考如何用一个更好的模型来抽象当前的问题,那你就在精益求精的路上又往前走了一步。 如果你不惜多花费一点时间从软件的用户、代码(api)的用户角度思考如何设计一个易用且好理解的接口,那你再次往前走了一步。 如果你对做好的功能建立了良好的易维护的测试,那你离匠人就更近了,你的软件就离匠艺更近了。 好的软件的背后是好的软件开发人员,是对好的极致追求。 2023-09-18: 逛超市 周末,午饭后,躺在沙发上休息了一阵子。我叫上她一起出去走走,消消食。去超市吧,顺便买点东西回来。 下楼,穿过地铁通道,往超市方向走去。她走得很快,我不得不叫住她,“你走太快了,能慢一点吗?” 她也突然意识到这一点,才放慢脚步。但是,走了几步,竟然又开始恢复到之前的速度。 到超市了。如何逛?我说,“我们要走一走每一个货架,看看以前都遗漏了什么”。于是我拉着她沿着货架左拐右拐,像是寻宝一般。超市的东西还真是多种多样,想得到的想不到的东西都有,包括各类睡衣、婴儿车、鞋子、毯子、玩具等等。食品区东西更是丰富,诱人的果脯,新鲜的水果和牛奶,各类糕点,各类干粮,卤的炸的,不管是颜色还是香气都肆无忌惮地诱惑着你。逛完之后,不禁感叹,人类的物质竟然丰富到这样的程度了吗? 我还在寻宝,但是她对此似乎没什么兴趣,望着一处搭建好到帐篷发呆。我叫她,这才反应过来,继续一同往前走去。 你越慢,时间越慢,你越快,时间越快。然而,生命的时间是有限的,究竟是要快一点还是慢一点?

2023/9/18
articleCard.readMore

每日一思

2023-09-16: 没有成行的钓鱼 有一个漂亮的湖,湖水里经常有会飞的野鸭子出没,你明明看到在某一处有一只野鸭子,一转眼它已不见了身影。你开始睁大眼睛四处找寻,过来好一会儿,终于在几十米开外的地方突然发现有一个鸭子头从水里钻出来。 湖边是绿油油的草坪,这里几乎没有人,你可以肆意的进去踩一踩松软的草坪,甚至坐一坐,或者打个滚,丝毫不会影响小草的生长。 湖边的树木也是经过精心设计的艺术,一大株一小株相间排列,品种各样。小鸟禁不住诱惑,高兴地在树丛间飞来飞去,叽叽喳喳似乎在向同伴述说自己的意外发现。 有一次,我和家里人在湖边散步,看到有几个年长的人在钓鱼。他们不紧不慢,悠闲的坐在湖边,水里面的线很长时间也没有动一下。但是他们不在乎,好像只是在等着那些愿意上钩的鱼儿。这让我想起了儿时钓鱼的场景,那会儿钓鱼可是我们几个小朋友最大的爱好。 我说,我也要找个机会来钓鱼。 第二次,看到类似这样的场景,我说,一定要找个机会来钓鱼。 第三次,我也这么说过。 现在,时间已经过去了一年有余,钓鱼终也没有成行。也许再也不愿意花几个小时安安静静坐在湖边了。 2023-09-15: 一个管理命令行工具的工具 开发人员在开发阶段常常需要执行很多自动化的shell命令,以帮助完成测试和调试工作。 虽然执行命令已经很快了,但还是免不了需要手动输入命令名称以及命令参数。特别是在命令和参数非常多的时候,记忆负担变得更重了。 我们实现的开发工作台(data-workbench.com)引入了这样一些方法来解决这个问题: 提供一种方式将这些常用的命令分组并添加描述 提供多种访问和执行这些命令的入口,如网页版搜索、ide插件版快捷键等功能 在上述这些入口中,提供自动参数校验,参数历史记录等便于使用的功能 有了这些功能,不仅记忆负担大大降低,而且方便了团队里面大家共享这些命令行工具。团队效率得到极大提升。 2023-09-14: 一个开发者工具的出现 为了能及时获得开发反馈,我们开发了一个工具,将easysql编写的etl转换为impala可执行的sql代码。它给我们带来了极大的便利,定位olap引擎的impala可以非常及时的告诉我们代码是否有问题。 但是,改进似乎是没有尽头的。工具虽然好用,但是是以命令行的形式调用的。于是,为了能获得这样的开发反馈,总是需要手动的执行命令,拷贝代码,然后粘贴到impala的sql执行工具中执行一下。每改一行代码都需要重复这个工作。总是感觉很繁琐。 然后,我们又在酝酿下一次工具的迭代升级。思路非常简单,把之前需要手动完成的操作进一步自动化,使得开发者可以一键获取反馈,或者更进一步,自动在后台给我们提供开发反馈。 道家说,道生一,一生二,二生三,三生万物。回过头来看这样的工具演进路线,一个之前完全不存在的工具,似乎正在变得越来越丰富和完善。这可能是软件的发展之道。 2023-09-13: etl代码静态检查 作为数据开发的专用dsl–sql,它与其他编程语言存在着一个显著差异:其正确性严重依赖于外部环境。这带来了一些问题: 无法在编码时静态检查字段有没有写错。一个字段在当前没有,不代表后续建表的时候不会重新加上;一个当前已存在的字段也可能在运行时被删除了。 无法检查潜在的类型转换问题。比如,当你在按照数字类型处理数据时,如果实际上该类型为字符串,就可能由于类型隐式转换导致大量空置。 这些基本的错误常常在代码执行时才暴露出来,反馈循环太长,开发人员因此效率低下。 因此,数据开发迫切需要一个能实时连接元数据库进行静态代码检查的集成开发环境。目前有很多数据库专用开发工具可以给到这样的开发体验,比如Oracle提供的sql developer。但支持spark或hive这类大数据引擎的目前还比较少。 一个简单的实现思路是: 将sql代码转换为基于cte的一条查询语句 在最后添加一个用于输出结果的占位语句,如select 1 在查询引擎上面执行这个查询,并分析报错结果,然后映射回对应的代码行 2023-09-12: 想念 一位很久没有打电话问候的奶奶,突然入梦,慈祥的脸上还是洋溢着那般笑容。 她不愿意到城市里面和我们一起生活,一个人在农村老家待得自在。 上次回去,家里显得空空的,大大的堂屋里面只有一张陈旧的小桌子和两张长条凳。但是,她一个人在家,也要收拾得干干净净,桌凳上、地上、墙壁上没有一点灰尘。 上次回家带上一岁儿子一起,一开始,小孙子还认生,不愿意跟太奶奶亲近。太奶奶很想和小孙子抱一抱,张开双臂,嘴里温和的念叨着要抱一抱,还比着手势。小孩子纠结了好一会儿,最后笑着投入太奶奶的怀抱。 在老家,有人气的家里就会受燕子的青睐,上次回去,墙壁上又筑好了两个燕子巢。 2023-09-11: 影响 跑步,总是能碰到跑在我前面的。遇到实力差不多的,总是忍不住想要跟上去,从而不自觉地加快脚步。 图书馆,看到满座都是捧起书津津有味吸取知识精华的人,总是忍不住也伸手拿起一本,沉下心来,享受阅读的乐趣。 景区,附近一个停车的地方,一位当地的老乡说,这是他们自己家修的,不收费。附近的几处停车的地方也没有收费。 景区,你随手捡起地上的塑料垃圾,准备收集起来处理掉,避免污染环境。旁边也有人效仿你开始捡起其他的垃圾。 泰戈尔说:把自己活成一道光,因为你不知道,谁会借着你的光,走出了黑暗;请保持心中的善良,因为你不知道,谁会借着你的善良,走出了绝望。 这就是影响的力量!

2023/9/11
articleCard.readMore

每日一思

2023-09-10: 这味道,停不下来 一锅香气四溢的辣子红油汤上桌,每人一个浅腹平底碗,装满调料。 服务员过来打汤,将一半敞口,一半过滤网的汤匙浸入辣子红油汤锅,旋转勺子底部撇开部分红油,舀起一大勺汤,过滤,倒入调料碗。 夹起一只美蛙,放入调料碗中,来回旋转几次,彻底浸入调料汁。拆下一块肉,送入口中。一辣一麻一香,以肉的位置为中心,瞬间四溢到周围的味蕾。活动牙齿,咀嚼一下,鲜嫩的蛙肉一下子散开。散开的每一小块都味道十足,带着劲道的汤汁无情地席卷整个口腔。 辣,刺激着口腔发痛;麻,让每一个口腔细胞都开始跳舞;香,带着令人幸福爽快的小分子穿越口腔和鼻腔直达脑门。 十足的辣让人想赶紧把食物咽下去,十足的麻和香又让人想把食物一直留在口中。于是,在辣味还未来得及传递到大脑时,赶紧咀嚼几次,得到美味的享受之后,辣味也快速到来,赶紧吞咽下肚。然而,大脑哪里能抵抗这种美味,立即指挥手开始拆下一块肉送入口中。 哪管他会不会长肉!哪管他是不是健康!这味道,停不下来! 2023-09-09: 宗教与诗 在很多西方人看来,每个人都应该信仰一种宗教。但是中国却很特别,一个具有数千年历史的文明古国竟然没有一个广泛信仰的宗教。 中国人如何处世?引导中国人一直向前的可能是诗。从最早的六经,到唐朝的绝句,到宋朝的词,到元朝的曲,再到现代的白话诗。 诗中的故事和情感,感动着一代又一代的人。诗中的哲学和世界观,引导着一代又一代的人。在彷徨时,诗给人以一束穿透迷雾的光;在失意时,诗给人以一种从容向前的动力;在成功时,诗警醒人前路依然不平坦。 宗教,虽然充满理性和逻辑,但总少不了神秘主义色彩。相比起来,诗是作者的想象,是脱离现实而高于现实的,这是读者在读诗之前就知道的。同时,诗中有大量的留白,需要读者去填补和想象;诗中有很多道理,需要读者结合自己的经历去体悟。 这可能就是为什么中国人的哲学既是出世的也是入世的,既追求内圣也追求外王。 2023-09-08: 负能量 小a上项目半天,说,我感觉很懵,别的团队上新人会有技术的业务的各类onboarding,这边都没有。 公司人员缩减,小a说,这两天上班心都悬着,别什么时候被约谈了。 小a遇到了一种新的语法规则,说,这个怎么这么奇怪,完全反人类,我是怎么都理解不了。 小a碰到一个不熟悉的工具,说,这个怎么这么难用,感觉很难理解,看不懂。 2023-09-07: 道德的本源 道德是一个非常抽象的概念。根据当今时代的理解,道德是社会意识形态之一,是人们共同生活及其行为的准则和规范,通过社会的或一定阶级舆论对社会生活起约束作用。(百度百科) 为什么道德是规则和意识形态?要追寻其最初的本义,需要回归老子的道德经。 经上说,“道生一,一生二,二生三,三生万物”。从这里来看,道是万物之源,并且,万物在生成过程之中,也都有“道”在其中。但是初始的“道”不同于万物之“道”,因此,“道可道,非常道”。 什么是德?在万物之中的“道”就是“德”, “德”的含义是“能力”或“品德”,它可以解释为万物本有的品质。“万物莫不尊道而贵德”, “道”是万物的由来,“德”则是万物本性的依据。 当今我们所指的道德更近似道家的“德”,即人的本性,本性具象化就是一些规律,延伸出来就是规则。 2023-09-06: 他乡遇故知 想象一下,你在一个陌生的城市,正在为生计做着事,突然一抬头,发现一个多年未见的朋友,恰好,他也看见你。 “xxx”!“xxx”!你们兴奋而又惊讶地相互叫出名字。 相约去大餐一顿。饭间,以前一起经历的往事,搞笑的尴尬的,变成现在的笑谈… 人类的情感就是这么奇妙,一次偶然的遇见,一段尘封的往事,就足以令人潸然泪下。 2023-09-05: 稳妥的技术路线 今天被一个hive分区问题给坑了。 问题表现非常奇怪,使用create table as select *…创建的表居然与原表数据量不一致! 调查了很久,发现了一些端倪: 原表为分区表,采用insert overwrite以动态分区的形式创建 查看底层文件系统发现,原表有一些分区列值为空的分区,以及分区列值为 hive__default 的分区 直接查询原表按照分区统计数量,不会出现上述不合法的分区 对新表(未分区表)按照原表的分区字段统计数量,出现了值为空及 hive__default 的数据 通过这些现象,可以了解到,可能由于之前某一次运行etl产生了一些脏数据。由于insert overwrite在动态分区场景下不会覆盖没有出现过数据的分区,所以之前的脏数据也一直被保留了下来。 在技术选择上,我一直推荐采用保守而稳妥的策略。事实上由于软件已经过于复杂了,如果再引入没必要的复杂度,那就很容易导致问题。比如,避免上述问题的一种稳妥的策略是,先truncate或drop table清除所有数据,然后再写入新数据。 一些其他常见的稳妥技术选择包括: 采用最简单和通用的语法,避免采用过于风格化的编程语言语法(如Scala过于复杂的类型推导) 采用最成熟的api,比如写在库或工具的上手文档中的那些api 保持实现的幂等性(类似纯函数),尽量隔离副作用 … 2023-09-04: 成就自己与成就他人 儒家之仁有两层意义。 一是忠,即:己欲立而立人,己欲达而达人(《论语 雍也》)。 二是恕,即:己所不欲,勿施于人。 第一点的忠,并不是愚忠(别人叫你干什么就干什么)。而是指,自己想要成功,就需要真心实意帮助别人成功。 当今社会很多人为了自己的成功不择手段,损害他人利益,这显然不是一种可持久的方式。对己难以保持平和,对人难以受到信任。 事实恰好在于,如果帮助他人成功了,自己往往也会成功。这就是:成就他人即成就自己。

2023/9/4
articleCard.readMore

每日一思

2023-09-03: 生命不能承受之重 汽车突然刹停,“嘭”,一个响亮的声音传入车厢里的几人耳中。 “哇!”接着传来小孩的哭声。“遭了,这下遭了!”后排的人嘴里说着话,赶紧抱起摔倒的小孩。 大家开始检查小孩的伤势,鼻子旁边有擦伤,在流血,另一只鼻子也隐隐流出血来。 事发之前,小孩站在后排中间座椅上,刹车时,被惯性带着往前倾倒。由于正对着空调出风口,直直的撞了上去。 这是多幸运?只是一点擦伤!如果没有这么幸运,那可能就是生命不能承受之重! 2023-09-02: 代码行数的错觉 最近进行的是一个数据开发重构项目,最重要任务之一是改善先前代码的质量。 经过几周时间的分析和实践,我们发现核心问题是代码重复。 团队随处能看到一大段一大段的重复代码,一个800行的sql代码消除重复之后可能只有不到200行。 消除重复带来的益处非常明显: 原来的数据计算逻辑清晰地呈现了出来,代码更容易理解,调查问题更快了 不少隐藏的bug被发现并修复 取数逻辑的一致性得到更好的保证 代码行数一直是程序员工作量的一个参考指标,不少企业甚至为每个员工设定一个代码行数的目标。因此,很多开发人员为了达成这个所谓的目标胡乱复制粘贴代码,最终导致了低下的项目质量。 这其实是关于代码行数的错觉。 事实上,在代码量指标上,不仅不应该求多,反而应该求少。能完成同样功能的代码,当然是越少越容易维护。 2023-09-01: 数据流水线自动生成 在很多数据项目中,数据流水线的配置都是靠团队手工完成。这带来了很大的工作量(特别是在开发阶段),而且容易出错。 事实上,数据流水线完全可根据etl血缘关系自动生成出来。 我们在团队中这样做: 采用airflow这样的可通过代码定义流水线的调度工具 自动解析etl文件中的依赖表,并找到对应的etl文件 根据以上依赖关系自动生成etl依赖图 将此依赖图转化为流水线代码 自动化数据流水线的生成和管理给我们带来了极大的便利,节省了团队大量的时间。团队变得更高效和敏捷了。 2023-08-31: 核污染水的数据与逻辑 日本核污染水排海事件正在成为国际关注的焦点。关于这件事有很多说法,比如日本自私论,美国阴谋论,中国过分反应论等等。 日本举出了很多数据说明核污染水无害。然而中国的逻辑很简单,如果无害就没必要排海,如果有害就更不应该排海。 在这件事上,我们的态度应该是保守的,因为它关乎全人类的健康。同时,在这件事上,过分相信数据那是极危险的,因为数据极容易作假,特别是这样复杂的专业领域,漏报一项数据就可能让性质完全不一样。 这件事上更应该相信的是简单的逻辑,中国的逻辑就是简单而显然的。 在关乎健康的重大问题上,中国是偏保守的,这让我们很放心,感觉更安全。为什么要拿安全去冒险?钱是可以赚的,安全问题发生了,就无法回头了。 2023-08-30: 无处藏身的bug 业务应用开发中大家常常遇到bug,有些bug隐藏很深,甚至连专业的qa都没法发现。比如某些并发场景下出现的bug,某些极少出现的边界场景、需求未定义的场景下的bug等等。 但是在数据开发中,这些bug往往无处遁形。究其原因,有: 数据开发通常要并行处理大量数据,并发问题极易在开发阶段就暴露出来 数据开发通常要处理生产系统积累的全部数据,其背后覆盖了几乎所有业务场景 数据开发以专用的sql语言为主要开发语言,如果代码本身有问题,从结果上很容易发现(比如结果集数据量不对,统计上不符合业务直觉等等) 因此,数据开发人员在编写代码时应当极为谨慎,因为bug很容易暴露出来,而出现bug后也得由自己处理,总也跑不掉。 2023-08-29: 自动化一切 如何让团队变得更敏捷,也许应该从自动化一切开始。 自动化大部分工作之后,团队的各类开发规范就不至于只停留在纸面上,而是通过工具自动化得到保证。团队也不会因为一些低级错误而耗费大量的时间。有了自动化加持,团队可以集中精力解决重要问题,从而实现效率更高、质量更好。 就像先进机器是工业化时代的生产力一样,自动化工具就是敏捷团队的生产力。 如何推进团队工作自动化?要点在于在团队内部建立这样的意识,当每个团队成员在完成开发任务的时候都想着是不是可以把一些工作自动化的时候,团队的自动化水平就会越来越高。 自动化一切要求团队成员具备很强的技术基础,不过,这正好是技术人员努力前进的方向。 2023-08-28: 诱惑 小孩到了一岁半的年纪,吃饭慢慢变成一件令人头疼的事情。 勺子自己拿不太稳,同时专注力也不够,吃两口之后就动来动去,上蹿下跳。 家里人没办法只能喂饭,喂一口,又跑了,得跟着追。有时候喂快了没吃完,或者他只是单纯抗拒食物,到嘴里面了,也直接吐出来,吐一地。 最近发现一个特别有效 …

2023/8/28
articleCard.readMore

每日一思

2023-08-27: 积木与故事 家里小孩有一个积木桌,搭配有很多积木小方块。小孩年纪还十分小,这些小方块也都是随意的搭配,没有成套。 这正好给人充分发挥创造力的空间。 那我们就来设计一个理想中的院子吧。将高度相同的小方块连续排列,围成一个方形,就是院子的围墙。围墙上面留一个小口子,口子两边凸出一块,就变成门。院子里面再围一圈高一点的小方块,就是院子里面的房间。房间紧挨着再来一圈相同高度的方块,就构成了另一个房间。房间里面平铺几块低一些的小方块,这是床。类似的还可以做出厨房和卫生间以及院子里的茶座。 在院子搭建完毕之后,拿着成型的院子给家里人讲一个故事:这是妈妈,妈妈早上起床了,到卫生间洗漱,顺便上了一个厕所,然后到厨房找了早餐吃了,然后泡茶并在茶座上和家里人愉快地聊天。。。 《人类简史》中说,人类和黑猩猩之间真正不同的地方就在于那些虚构的故事,它像胶水一样把千千万万的个人、家庭和群体结合在一起。这种胶水,让我们成了万物的主宰。 比如小小的积木就可以让我们虚构一个故事,如果这个虚构的故事能被大家所接受,那它就可以把大家紧密地结合在一起。 2023-08-26: 从拥堵中寻找顺畅 上班路上有一个左转路口,之前一直非常拥堵,一般需要超过10分钟才能过去。最近这个路口却突然变得通畅起来,常常只用一个红绿灯就过去了。 观察发现是由于红绿灯设置更合理了。 这个路口是进出城市环线的路口,工作日的时候进环线和出环线的车都非常多。之前出环路后的直线路段第一个红绿灯的直行绿灯时间设置比较长,左转时间则非常短。为什么左转时间短呢?是为了支持更多的对向直行上环路的车。这就导致一个问题,下环路后直行左转和上环路的车都堵得厉害。 在车流并没有变少的情况下,现在的红绿灯设置为什么可以改善执行左转的拥堵呢? 很简单,只需要增加左转时间即可。因为原来对向直行本来就堵,在一定范围内,无论增加或减少时间都不会有任何改善。既然如此,最优解就是找到对向直行的最短绿灯的时间即可。这时,上环路的拥堵依然存在,下环路的拥堵却显著减少了。 很多事情虽然看起来已经最优,但在全局视角下,往往还有提升的空间。如果你找到了这样的方法,那就是从拥堵中寻找到了顺畅。 2023-08-25: 滴滴打车意外打到了一辆model 3 滴滴打车意外打到了一辆model 3,我靠近车门,准备拉开门上车,发现门把手嵌入到车门里面,不知道如何打开。我敲一敲车窗,司机师傅告诉我说要按一下门把手一边,另一边就会翘起,然后就可以开门了。上车之后,座位怎么坐都不太舒服,仔细感受之后发现坐垫太短且地台太高,腿一大截没有被支撑到。而且后面座位也显得有点紧张,活动空间有限。车辆行驶过程中,周边环境及车辆会跟随显示,非常清晰和准确,司机可以清楚的看到周围的情况。 更多能打到的车是比亚迪汉,靠近车门,门把手自动弹出来,我拉开门上车,一气呵成。进入车内,座位坐起来相当舒服,不管是地台高度还是坐垫长度都非常适当,活动空间也非常宽敞。座位皮质显得很高档,不管是触感还是观感都有一种高级和精致的感觉。当然这辆车虽然有大屏幕,但看起来只像是摆设,司机师傅只是用来显示空调信息。 2023-08-24: spark同时读写某一张表 spark无疑是一个优秀的计算引擎,但却在支持同时读写某一张表时略显不足。 一个简单的示例为:insert overwrite a select * from a 事实上,如果我们碰到了这样的场景,spark直接报错:cannot overwrite a path that is also being read from. 如何解决?一个很简单的方案是,先写入一个临时目录,然后再修改一下目录名。 用sql表达,即: insert overwrite a_tmp select * from a drop table a alter table a_tmp rename to a 2023-08-23: 分解复杂数据问题 数据开发常常碰到数千行的sql代码,如何看待和优化这些代码呢? 可以将问题按照业务和技术复杂性进行分解。 识别复杂代码中涉及的大表连接场景,这通常很慢而且难以优化。 针对大表连接场景,识别是否可以将更多数据筛选条件下推到连接之前;识别是否可以在连接条件中利用分区键;识别是否可以优化为小表连接大表等。这些场景下有很多成熟的优化方案。 将大表连接代码隔离出来,单独处理。即拆分为简单代码大数据量代码段及复杂代码小数据量代码段两部分。第一部分主要进行技术优化,第二部分主要进行业务逻辑优化。此即为关注点分离的模式。 2023-08-22: 困局 地上一滩水,小蚂蚁在水边爬,恶作剧的人用手划过这滩水,圈出一个水圈,将小蚂蚁困在圈子里面。 小蚂蚁在水圈里面来回爬,想要找到一个出路,它一直尝试一直尝试,把能尝试的路径都试过了,始终都没有找到出路。 随着这滩水越积越多,水圈慢慢变小,慢慢变小。。。 2023-08-21: 推荐反被推荐误 下火车了,赶紧用滴滴订一个车,滴滴推荐了几个上车点,随意选一个,然后开始往上车点赶。到了上车点,是一个停车场,人真多,嘈杂的打电话声音夹杂着汽车的哄哄声,在夏天的潮湿而又闷热的空气中乱作一团。汽车排着长队一个车位一个车位往前挪,刺耳的喇叭声不绝于耳。等了20分钟终于上车。 这是很多人在火车站打滴滴车的日常。 这次到站了,由于我实在无法忍受在热浪中等待20分钟之久,就选择了一个自己定位的上车点。没想到一切竟出奇的顺利,快速的叫到了车,师傅快速到了上车点,我也快速的上了车。由于上车点在马路旁,人流量不大,车也没有排长队。体验一下子提升n个档次。 为什么滴滴推荐的上车点体验如此差,而自己选择的却还不错? 本来是一个不错的地点,但正是由于将少量资源推荐给了大多数人,这个不错的地点就变成了很差的地点。推荐反被推荐误!

2023/8/21
articleCard.readMore

每日一思

2023-08-20: 在紧张中创造 反思一下个人的内容产出频率,我注意到一个很有意思的现象:往往工作最紧张、压力最大的那一个阶段,产出却是最多的。 为何?紧张的时期,大脑一直处于思考的状态,所以新的想法就很多;当渐渐进入到一个平稳的时期,创造力似乎就渐渐离我远去。 为什么春秋战国时期有百家争鸣,各类新思潮层出不穷?大概是因为那个时代是一个局势紧张的时代,各诸侯国之间战事不断,不仅要求发展还求如何得人心。 古希腊半岛位于各个文明圈的中央,也正是由于和周围的城邦不断的进行交流和碰撞才产生了西方哲学的萌芽。 所以,站在人类的历史长河看,有竞争的乱世也并不是一件坏事,因为它常常是破旧立新产生突破的时代。 2023-08-19: 记忆里的人 在记忆里她一直是一位很慈祥的母亲。 她很会做饭,曾经在一个山清水秀的煤矿厂里给厂子里面的人做饭;数次春节到她们家,也总是能有一大桌子菜等着大饱口福。 她也很慷慨,每次春节到她们家总少不了一个大红包;平时去也是各类零食水果从不间断。 她勤劳且持家,每次去她们家总是能看到干净整洁的房间;只要她在,总是在忙里忙外收拾这准备那。 很多年没常见面了,以后回去也见不到了。 2023-08-18: 半梦半醒 我左手抱着小孩,有一种沉甸甸的感觉。他今天很安静,没有吵闹。客厅的墙、过道、地板看起来都非常的清晰。我没有戴眼镜。家里人都正常在家休息,有的在沙发上半躺着,有的在房间其他角落走动。 我能清晰的知道这不是现实。但眼前的事物是那么的清晰和真实,即便在我的身体自然移动时,这些事物也可以正常地跟随切换。 我想挑战一下这自动在脑海里出现的场景,看看它的能力极限在哪里。 走进房间的过道,进入一间卧室。没错,是我们家的卧室!床和柜子的摆放都是没问题的。甚至连门上面的贴画上面的字都清晰映入眼帘。 穿出过道,进入了一个黑黢黢的拐角处,朝房间里面望去。这好像是好几年前的住过的房间。床和家具是深色木质的,被子铺在床上。看起来是被人直接在床上面躺过而没有将被子展平,有很多褶皱。衣柜的一边柜门贴着一张四方形的福字贴,里面有老婆很久以前写的八个字,字非常清晰。和我有关,读后感觉很感动。这个场景渐渐勾起了我更多的回忆。。。 2023-08-17: 程序员终极提效工具 最近的数据开发项目中,我们引入了一个etl代码编译解析工具,它可以自动分析代码为语法树,并从中提取代码相关信息。 然后,我发现有很多日常开发需要手工完成的事情都可以用它来自动完成,比如: 自动生成建表语句 自动生成数据血缘分析图 自动提取输入表、输出表,辅助生成输入输出处理代码 自动代码格式化 自动重构 自动提示待重构的代码 -… 有了语言级的信息支持,有一种思路一下子被打开的感觉。随着一个一个工具的实现,工作效率也是蹭蹭蹭往上涨。 程序员的终极提效工具是什么?除却GPT这种自动写代码的黑科技之外,那可能就是编程语言级的自动分析优化和代码生成了。 回想很多语言提出的元编程思想(比如rust),其实与这里的解法一致,不过它们大多由官方提供了支持。 2023-08-16: 当学习成为负担 最近团队在专业业务领域知识积累不太够,于是我们组织大家一起学习。 由于学习通常在工作时间之外,这势必会占用一些工作之外的其他时间。 这就导致了一个矛盾,团队成员可能不得不放弃一些个人安排,投入更多时间到学习中。 看起来学习成为了团队的一种负担。 但是,学习真的是负担吗? 回顾一下之前的学习过程就可以知道,学习常常能给人一种充实感。学到新知识了,我们会感觉获得更多能力了,变得更强大了。所以,学习常常是获得快乐的一种方式,而不是负担。 为什么会有人觉得是负担?可能是当代学以致用的观念胜过了学以致知。当我们将自己定位为一个学习的人,成长的人,坚持终身学习,把学习作为人生的一种状态,它也就不是负担了。 所以,是不是负担,关键在于个人的心态。 2023-08-15: 二级混沌系统 准确的预测可以帮我们更好的计划。比如,预测明天的天气,可以帮助我们计划旅游目的地;预测将来的行业趋势,可以帮助我们更好的选择职业。 随着科技的进步,越来越多的系统的原理被揭示出来,变得可以被准确预测。 然而有一类系统不可被准确预测,那就是二级混沌系统。 比如股市的预测,如果有一个方法宣称它可以准确预测股票的走势,那大家就可以完全根据它的预测结果进行股票交易。其结果反而将推翻之前的预测。 在这类系统中,预测会受到本身预测结果的影响,因而不可能准确预测。这就是二级混沌系统。 类似的系统还有很多,比如物理学中的测不准原理,政治预测,地图上的拥堵预测等等。 当下流行一句话,我预判了你的预判,这是指人思维也具有这样的特性。 在这样的系统中,一个科学的做法是什么?可能是要有多种完全不同的预测方法,然后不同的人选择不同的方法来做预测。这样一来,就有可能大家共赢。 2023-08-14: 动态的制度 在一个组织中,一项制度的确定一定是为了解决某一类问题,其初衷通常是好的。其操作过程也常常是因为得到大多数人的支持而形成。但制度常常解决某些问题却引出来另一些问题,这就是上面的政策引出来的下面的对策。 所以,制度的出台应该着眼于解决现实问题。但制度却不应该是死的制度,应该根据情况随时调整。对待调整的制度的态度应不亚于最初制定制度的态度,否则制度往往流于形式或导致更严重的问题。 钱穆在《中国历代政治得失》中说,应该用制度迁就现实,而不是现实迁就制度。直接生搬硬套拿来的制度不一定是好的制度,因为它没有着眼于具体的现实问题。而从汉唐一成不变的制度最终导致没落,又可说明制度需常改常新。

2023/8/14
articleCard.readMore

每日一思

2023-08-13: 会计准则与领域词典 财务是一个很有意思的部门,它的职责是记录和管理企业内部的各类经济事务。由于企业内部几乎所有活动都要和钱相关,因此也都需要和财务相关。故而,企业几乎所有业务活动所涉及的(高层次)知识都将流入财务系统,财务系统事实上成了企业内部的知识中心。 这对于软件开发有什么启示? 领域驱动设计建议我们逐步构建一个领域词典,以便于让大家对于系统的理解达成一致。如何构建这个词典? 企业财务管理需要符合国家会计准则,而国家会计准则则对于社会上的各类企业业务做了较为明确的高层次划分及规范制定。比如,会计科目中关于原材料采购业务定义了这几类相关科目:银行存款/应付账款/应交税费用于钱款流转事务,在途物资/原材料用于物品运输与仓储事务,生产成本/制造费用/管理费用则用于和原材料相关的各类生产消耗事务。从这里所涉及到的一些术语可以了解到会计准则中的知识几乎覆盖了企业所有核心业务过程。 基于以上分析,领域词典是不是可以基于标准的会计准则中的知识来定义? 会计准则作为一个国家颁布的企业经济行为标准,经过了社会广泛调研,可以覆盖绝大多数的关键场景,并且相关的解释和研究非常丰富,实在是不可多得的材料。 虽如此,会计准则之于领域词典也有局限。因为会计准则中的知识是仅停留在高层次,其应用范围也将限于高层次(比如架构、系统对接接口等),细节或较低层次的内容则还是应该根据具体系统相关的业务确定。 2023-08-12: on中的条件和where中的条件 sql语言的表达能力非常强,但在某些场景下看起来功能相同的代码却有着非常细微的差别,稍不留神可能就被坑了几个小时的调试时间。 比如,某一个条件写在表的连接条件中和写在连接后的where条件中有什么区别? 示例如下: 写在on:select * from a left join b on a.id=b.id and a.cond=1 写在where:select * from a left join b on a.id=b.id where a.cond=1 思考一下,第一个的结果集里面会出现a.cond!=1的数据吗? 2023-08-11: 用编程语言的性能提升你的效率 最近项目中需要搜集一个公开产品的文档,以便快速为团队补充相关知识。通过实现一个简单的爬虫,解析网页,获取信息就可以支持。 第一个版本,我采用了最近用得最多的python实现。代码很快写完,但是一运行就发现了一个较大的问题,网页解析太慢了!一个20MB的网页需要解析十分钟,而这样的网页总共有好几百个。没想到,本来以为可以快速完成的任务,结果输在了程序性能上!在Python这条路上折腾好长时间,无果。 由于nodejs天生就对网页解析和元素查找很擅长,所以,考虑改为nodejs实现。于是,花了一小时左右,程序搞定。上真实网页一测,性能简直不要太好,20MB的网页解析只用了不到5秒。于是这个任务在采用nodejs重新实现之后,顺利地在两小时内完成了。 我们在开发程序的时候,一般都先入为主采用自己最擅长的开发语言,希望通过熟练度来提升效率。但是每一种开发语言都有其擅长和不擅长的领域。了解这些,就可能可以通过编程语言的性能带来颠覆式的效率提升。 2023-08-09: 基于代码复用的数据工程 业界普遍采用以sql为主的数据开发语言进行数据开发,依靠数仓分层来避免重复计算,这一复用方式可以称之为数据复用。但数据复用的灵活性较差,可能会形成一个非常复杂的数据任务流水线,并且,当我们想独立运行某一个etl的时候,我们不得不执行所有依赖的任务。 基于代码复用的数据工程是指采用复用代码的方式进行数据工程中的复用。它采用以计算资源换取维护成本的方式帮我们节省开支。在大量数据量没那么大的场景下更适用。 目前很多框架可以支持这一使用方式,比如dbt,easysql都有相应的支持。 2023-08-08: 终点却是过程 人们常常奔着一个目标往前冲,甚至能不分昼夜,不顾身体。 但是等目标按照预期实现了之后,却觉得心里一下子空虚起来,不知道该干什么了。 有多少软件功能在实现之后就成了它的坟墓?无人问津的程度甚至不如当初开发阶段的测试使用频率。 也许有时候终点恰恰是过程,是奋力向上的有着充实感受的过程。而目的的意义在于为我们提供一个参与这个过程的机会。

2023/8/8
articleCard.readMore