
获得徽章 0
- 《设计模式之美》11月day19
设计原则
在专栏的最开始,我们总结了一套评判代码质量的标准,比如可读性、可维护性、可扩展性、复用性等,这是从代码整体质量的角度来评判的。但是,落实到具体的细节,我们往往从是否符合设计原则,来对代码设计进行评判。比如,我们说这段代码的可扩展性比较差,主要原因是违背了开闭原则。这也就是说,相对于可读性、可维护性、可扩展性等代码整体质量的评判标准,设计原则更加具体,能够更加明确地指出代码存在的问题。
在专栏中,我们重点讲解了一些经典的设计原则,大部分都耳熟能详。它们分别是 SOLID 原则、DRY 原则、KISS 原则、YAGNI 原则、LOD 原则。这些原则的定义描述都很简单,看似都很好理解,但也都比较抽象,比较难落地指导具体的编程。所以,学习的重点是透彻理解它们的设计初衷,掌握它们能解决哪些编程问题,有哪些常用的应用场景。
SOLID 原则并非一个原则。它包含:单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)、依赖倒置原则(DIP)。其中,里氏替换和接口隔离这两个设计原则并不那么常用,稍微了解就可以了。我们重点学习了单一职责、开闭、依赖倒置这三个原则。展开赞过评论2 - 《Java并发编程实战》11月day18
解决并发编程里的分工问题,最好的办法是和现实世界做对比。对比现实世界构建编程领域的模型,能够让模型更容易理解。上一篇我们介绍的 Thread-Per-Message 模式,类似于现实世界里的委托他人办理,而今天介绍的 Worker Thread 模式则类似于车间里工人的工作模式。如果你在设计阶段,发现对业务模型建模之后,模型非常类似于车间的工作模式,那基本上就能确定可以在实现阶段采用 Worker Thread 模式来实现。
Worker Thread 模式和 Thread-Per-Message 模式的区别有哪些呢?从现实世界的角度看,你委托代办人做事,往往是和代办人直接沟通的;对应到编程领域,其实现也是主线程直接创建了一个子线程,主子线程之间是可以直接通信的。而车间工人的工作方式则是完全围绕任务展开的,一个具体的任务被哪个工人执行,预先是无法知道的;对应到编程领域,则是主线程提交任务到线程池,但主线程并不关心任务被哪个线程执行。
Worker Thread 模式能避免线程频繁创建、销毁的问题,而且能够限制线程的最大数量。Java 语言里可以直接使用线程池来实现 Worker Thread 模式,线程池是一个非常基础和优秀的工具类,甚至有些大厂的编码规范都不允许用 new Thread() 来创建线程的,必须使用线程池。
不过使用线程池还是需要格外谨慎的,除了今天重点讲到的如何正确创建线程池、如何避免线程死锁问题,还需要注意前面我们曾经提到的 ThreadLocal 内存泄露问题。同时对于提交到线程池的任务,还要做好异常处理,避免异常的任务从眼前溜走,从业务的角度看,有时没有发现异常的任务后果往往都很严重。展开评论点赞 - 《超级访谈:对话玉伯》11月day17
玉伯:做基础技术的同学,往往做着做着,想去做业务。做业务支撑的同学,往往做着做着,会想去做基础技术。这就是一个围城,城外的人想进去,城里的人想出来。
回到一线同学,这个围城带来的困惑非常常见。技术人对自身价值认知的不同,到现在为止都是一个普遍存在的问题。但这个问题很难解,靠沟通是解不掉的。体验技术部的做法是,尝试每隔半年,如果有做业务支撑的同学想去做基础技术,且也有这个能力的话,那就调整一下。反之也一样,让想做基础技术的同学,能选择去做做业务。
调整完成后,往往能让同学有完全不一样的感受。比如调整去做基础技术的,会刚开始很兴奋,但很快会发现,做基础技术也有一堆 bug 要改,也有各种项目排期,跟在业务线接需求是一样的。
这就是个围城。做基础技术的,也有很多同学觉得基础技术很难拿 3.75 绩效,基础技术很多是长周期,有同学就等不及,觉得做业务更容易拿到结果,公司很多奖项、聚光灯都是放在业务上的。每个基础技术方向,往往要做到一定阶段才会被看见,大部分情况下会在边缘,别人看不见,各有各的难处。
调完之后,最大的一个好处,是可以让做基础技术的和做业务支撑的同学,能彼此互相理解了,能真正感受到,原来都挺难。有些同学,能在调岗后,更善于去观察别人,同时开始更了解自己,知道自己原来更适合做业务,或者更适合做基础技术,自己的心就能安定了。心的安定,需要亲身去试试,很难通过沟通来解决。展开赞过评论1 - 《超级访谈:对话玉伯》11月day16
玉伯:行业也没什么标准,只能说我的经验。去看一些中后台的操作页面,会发现其实很多时候,好用并不取决于长得是否好看,好用更多取决于产品的操作交互是否贴合业务场景。
分享个 Ant Design 在设计过程中的一个坑。我们内部有一个客户服务系统,Ant Design 在早期追求排版布局的美观好看。为了好看、有呼吸感,排版会比较大气,错落有致。但这种设计,对整个客服系统来说,就很痛苦了。后来我们才理解,一个好的客服操作页面,需要页面信息密度足够高,方便客服人员在一个页面里就能找到各种信息并做快速操作。这种情况下,别看页面上密密麻麻的,密密麻麻才好用,宽松排版虽然好看,但并不好用。
业界去讲体验不好的案例时,经常用的一个比喻是说飞机操作仪表盘是不好的体验,因为上面有非常多的按键,很不好用。但我要对这个说法打个问号,这很可能只是业界的一个谬误。如果真把飞机的操作盘简化成 iPhone 一样,那飞机可能就要失事了。要回到专业领域去思考,比如去调研真正在飞机控制室里的飞行员是怎么想的。我找过很多文章,到现在为止都没有看见真正从事飞机行业的人出来说话,都是一帮搞互联网行业的用户体验设计师在那里拿它举反例。
所以从好看到好用,我目前更多在做的事情是,让特定领域的设计师深入业务。目前语雀的 UED 在语雀团队,设计师必须懂业务,得去研究用户的场景是什么、用户的高频操作是什么,然后再回到设计上,考虑怎样做到体验最好。在这个过程中,大家在保证操作效率和好用的基础上,同样要保证好看,这个好看是指多数人默认的好看,不是设计师一人觉得的好看。通常好看是更容易做到的,好用是更难做到的。
在前端这块我们提过产品工程师的概念,在设计这块,我们也提过一个概念,叫产品设计师。我不大想提体验设计师的概念,我们更多倡导产品设计师。最终前端和设计,都要落回到产品上。做设计也好,做前端实现也好,有时候体验好了,产品也不一定好用,这是两回事。展开赞过13 - 《超级访谈:对话玉伯》11月day15
玉伯:前端的核心价值,可以等同为一个问题:“公司为什么需要前端团队?前端团队因何而存在?” 我找到的答案有三点。
第一点,前端可以为公司降本增效,这是一个基本盘的价值。一个公司要做互联网产品,可以采用外包的方式,也可以采用自建团队的方式。为什么阿里等互联网公司采用了自建技术团队,核心原因是,自建技术团队,可以让产品研发更快,质量有保证,整体可持续发展。
组织设计上,技术团队经常会集中在一起,前端团队往往也会集中在一起。集中可以带来效率提升。假设一个业务需要 30 个前端来支撑,放到我这里,可能只需要 20 人就能满足业务需求。因为集中化管理,可以复用专业经验,我们知道如何更高效更专业地支撑业务。前端团队放在一起,在判断需求的优先级时,全局取舍会更自然发生。当前端分散在各个业务时,好处是能形成自闭环,但会带来一个常见问题:零散前端往往会被迫接好多需求。一旦前端是集中的,同时前端人员整体又紧缺时,面对业务需求,前端往往就不会再无条件接需求了。在需求的取舍过程中,就砍掉了很多没必要做的需求。砍需求往往是对业务的最大提效,不做一些需求,反而能提升需求质量,最终让业务做对需求。
但如果自己就是业务方,独立负责一块业务,很多 Leader 肯定就会想自己闭环最好,不然还得等排期。还不如自己直接招几个人,这样更高效,这是人性。但实际上,需要大家更客观去看。早期自闭环,可以让业务从 0-1 更高效。发展到一定阶段后,特别是各个业务板块需要互相关联时,集中化的技术支撑,往往能复用专业能力,整体业务效能会更高。
我现在更能理解一句话:分工是整个社会效能提升的关键。工业社会的分工极大提高了社会运转效率。以前农业社会衣食住行所需要的东西都可以自己生产,这叫做自闭环,效率是极低的。正是因为有了社会分工,整个人类社会才飞速发展。
降本是最近几年才凸显。现在不少公司开始提经营责任制,各个 Leader 会更意识到要省钱。举个例子,设计师对业务来说很重要,但业务如果自己去招一个创意设计师,往往不如用设计大团队提供的创意同学,这样会更省钱。统一的设计或前端部门,可以整体统筹,议价能力也更强,可以非常实在地降低成本。
简言之,前端团队的存在,是因为技术专业分工能带来整体效能的提升。同时前端团队往往会是一个整体,集中化可以降低公司的整体成本。展开赞过12 - 《数据结构与算法之美》11月day14
短网址服务的两种实现方法。
第一种实现思路是通过哈希算法生成短网址。我们采用计算速度快、冲突概率小的 MurmurHash 算法,并将计算得到的 10 进制数,转化成 62 进制表示法,进一步缩短短网址的长度。对于哈希算法的哈希冲突问题,我们通过给原始网址添加特殊前缀字符,重新计算哈希值的方法来解决。
第二种实现思路是通过 ID 生成器来生成短网址。我们维护一个 ID 自增的 ID 生成器,给每个原始网址分配一个 ID 号码,并且同样转成 62 进制表示法,拼接到短网址服务的域名之后,形成最终的短网址。
课后思考展开赞过评论2 - 《Rust语言从入门到实践》11月day11
在同一时刻,同一个所有权变量的不可变引用和可变引用两者不能同时存在,不可变引用可以同时存在多个。可变引用具有排它性,只能同时存在一个。
借用结束后,原本的所有权变量会重新恢复可读可写的状态。不可变引用可以被任意复制多份,但是可变引用不能被复制,只能转移,这也体现了可变引用具有一定的所有权特征。所有权和引用模型是 Rust 语言编写高可靠和高性能代码的基础,理解这些模型有助于优化程序的效率,提高代码质量。
本文通过探索性的方式尝试遍历不可变引用与可变引用的各种形式和可能的组合,由此揭开了 Rust 中引用的各种性质以及同所有权的关系,并总结出了多条相关规则。看起来略显繁琐,但每个示例其实非常简单,理解起来并不困难。请一定记住,不要死记硬背那些条条框框,请你亲自敲上面的代码示例,编译并运行它,在实践中去理解它们。久而久之,就会形成一种思维习惯,觉得 Rust 中的这种设计是理所当然的了。展开赞过13 - 《B端体验设计入门课》11月day10
小白选手,怎么快速出效果?
如果你刚刚进入 B 端行业,完全没有做过大屏,也不会一些复杂的 3D 软件,那一定会感觉很困难。因为不会 3D 软件,连大屏的效果图都没有办法做出来,研发更不知道该怎么做效果。一些团队会选择找外包团队直接制作,我们也有过类似的阶段,但是这个费用非常高,有些大概要几十万。
所以,小白要面临的问题就是:怎么才能用更低的预算,更快地做出优秀的效果呢?
其实市面上已经有很多公司识别到了这个需求。这些公司基于自己的技术能力与相关案例,总结出了很多的案例和模板,也做出了 Web 端的 B 端 SaaS 产品帮助你解决这个需求。其中阿里也做出来一个不错的平台,叫做 ThingJS,里面基于制造业、智慧城市等等这些场景提供了一些比较基础的模板。如果你的要求不是特别高,场景也比较通用,那么这样的模板就是最佳的选择,既可以做出不错的效果,成本也会低很多。
会一些 3D 软件,怎么做得更好?
单一的内容对于 B 端来说意义不大,那和大屏互动呢?在大屏设计这节课中,我分享过如何做出更有价值感的大屏,如果你已经掌握了一些 3D 软件,那么结合 C4D 和 Octane render 就可以和研发配合输出一些更好的效果了。展开赞过评论1 - 《左耳听风》11月day9
流量调度的主要功能
对于一个流量调度系统来说,其应该具有的主要功能是:
依据系统运行的情况,自动地进行流量调度,在无需人工干预的情况下,提升整个系统的稳定性;
让系统应对爆品等突发事件时,在弹性计算扩缩容的较长时间窗口内或底层资源消耗殆尽的情况下,保护系统平稳运行。
这还是为了提高系统架构的稳定性和高可用性。
此外,这个流量调度系统还可以完成以下几方面的事情。
服务流控。服务发现、服务路由、服务降级、服务熔断、服务保护等。
流量控制。负载均衡、流量分配、流量控制、异地灾备(多活)等。
流量管理。协议转换、请求校验、数据缓存、数据计算等。
所有的这些都应该是一个 API Gateway 应该做的事。展开评论点赞 - 《手把手教你搭建系统》11月day8
一般来讲,处理 EE 问题常见的方法有下面这五种。
探索性推荐:在推荐用户可能喜欢的内容的同时,探索一些用户可能没有想到或者没有接触过的新内容。可以通过增加一些随机性和多样性等手段来实现探索性推荐,从而平衡探索和利用之间的关系。
引入领域知识:借鉴领域知识,为推荐系统提供更准确的信息,帮助系统更好地利用已有的信息,从而减少探索的需求。
利用深度学习等技术提高模型准确性和效率:深度学习技术可以帮助推荐系统更好地理解用户、内容和交互等特征,提高模型的准确性和效率。
整合多种算法:将不同算法的结果进行融合,从而得到更全面和准确的推荐结果。
动态调整推荐策略:根据用户反馈和平台目标不断修改推荐算法,动态调整推荐策略和探索率,从而达到更好地探索和利用平衡点。
总之,处理推荐系统中的 EE 问题需要综合考虑多种因素,并结合具体业务需求和算法模型,采取合适的探索策略,从而找到最好的平衡点,提高推荐的准确性和效率。
如果召回集已经产生了不好的效果,我们利用排序后的其他手段也可以解决。最主要的方式就是在这个阶段加入一些全新且多样化的内容,然后再穿插到最后的推荐列表中。展开赞过评论3