一些突发奇想
上下文
任何概念与定义都必须基于一个特定的上下文(环境)否则会失去意义,也就是语境与限定。上下文概念是一个使用范围非常广泛的概念,可以出现在除编程以外的很多领域,例如在辩论与讨论中双方可能交锋的不是论点而是上下文,目的是将自己的上下文另对方信服或根据优势。在编程领域实际上有很多实例比如Spring ApplicationContext,多线程上下文切换、C# UI线程SynchronizationContext等等。
当然上述只是概念,如果谈论我对上下文的理解,狭义上来讲是某个概念所必须的数据类,广义上来讲是一种界定。狭义上的理解比较好解释,广义上来讲可能不是以context的形式出现,可以是单体应用的一个文件夹、一个项目,或者是一个微服务。
说起上下文,每当我需要解决一个问题,我的编程习惯是新建个名称为 DefaultContext 的类,当然这个名称会根据以后需要更改,但是有这样的一个类会让我感到安心,因为我的一些内部运转可以交给这个类解决,顺理成章。所以有新建类而不知道如何起名或不知道如何给自己代码安排职责时,或许可以考虑这一点。
如果真的想要构建属于自己的上下文,使用IoC似乎是一个更加有趣的选择。因为使用IoC更加方便、快捷且透明,而且很多框架(例如Spring)已经将这些工具内置功能也更加强大(不需要你去维护不用担心bug),有时候我会在每一个工程中创建一个IoC,这样集中创建、销毁实例会更加方便,划分访问域也使得实例的使用更加安全。
闲聊一下:说起上下文想起 Spring 和 SpringMVC 的子父 context 的问题,因为SpringMVC 基于 Spring,因此SpringMVC 可以访问 Spring 的 context 但反过来不行。这种设计初衷是好的,但实际使用的时候似乎麻烦不少,当时我记得使用 hibernate 的时候要配置一个安全属性(大概是这个)它是要放在 Spring 的 context 下,当时并不知情所以耽搁了不少时间。后来 SpringBoot 就直接一个 context 了(不过 SpringBoot 可能初衷就是一个单体,所以只存在一个 context 情有可原)
分层架构
分层架构应该是我用的最多的一种架构,虽然用的多但也不见得对它认知的有多深刻,现在微服务兴起刮起了抛弃这种“上古遗物”的风潮,有很多程序员似乎也要被这股风刮飞了去,谈及架构一定提及那些服务、治理、路由等等。但我一直相信大道至简,看似简单的东西一定有其深刻的内涵,这里我也谈一下自己对分层架构的看法
① 如果你的业务场景可以总体归纳为一类有序的序列,则可能适合使用分层架构。这里的意思如果从另一个角度理解就是业务按照流程划分,同时层级保持单向依赖,尽可能不跨层调用。分层架构也有规范的意思,因为编写代码时最常见的就是循环依赖,进行分层保持单向也潜意识避免这种错误。分层架构的这几点也是它使用广泛的原因之一,因为人较为容易理解有序的序列,同时也习惯将一个复杂事物模块化并按照一定顺序组合,因此分层架构正好符合这些特点。
② 如果将分层架构图旋转180度的话,我认为一个良好的分层架构图很像一个继承关系良好的类图。这对我有一些启发。对于某些业务场景难以进行划分层级的时候,我会去参考一些相似业务的开源项目代码的类图(UML图),说不定有意外收获。有时去看一些知名项目的分层架构图,也能从中间接学习到一些关于继承、组合、依赖相关的知识。
闲聊一下:如果是C#程序员聊起分层架构一定会想起宠物商店(PetShop)这个例子,不过部分程序员对它的印象并不是很好,但如果去搜索 PetShop4.0 的架构图的话还是值得学习的。不管 PetShop 是否存在一定的问题,起码很多程序员以此为蓝本进行构建,这已经说明它的意义,否则很多程序员可能根本就无从下手。回到分层架构的话题中,我个人认为分层架构中每一层之间如果只是靠引用(函数调用/dll引用等等)维持联系有一些羸弱,或者说已经不太适应现代应用的设计,如果改为总线(像guava的EventBus)、消息中间件的话似乎可以一试,不过这又有点像以太网的那种网络拓谱图的感觉了。
操作系统与分布式
现在公司似乎非常喜欢面试一些关于分布式相关的知识点,包括框架、原理、源码等等。大多数面试题主要围绕概念或理论性质进行提问,换言之考察的是面试者知识的广度。现如今这些资料已经是比较完备了只要用心准备也应该会回答上一些内容,因此想要在面试上其他人与众不同展示一些不同的东西,就要在这些知识点本身基础上进行一些延拓或者一些深度,这里想要讨论一下自己的想法。
① 单核CPU/多核CPU 与 单体应用/微服务。如果对现在流行的关于单体应用与微服务相关讨论的感兴趣不妨可以参考单核CPU向多核CPU发展史相关的资料或书籍。虽然CPU演进和软件架构有不同之处但是了解一下其演进过程中的取舍说不定对软件架构有更深一步的思考。
② CPU缓存架构与分布式缓存。如果简单介绍一下CPU缓存架构的话是用buffer去写用queue去读。当然这只是简单的描述,如果细致去了解CPU的缓存架构的话会发现很多分布式的知识点其实是它的部分组成。如果对缓存这方面感兴趣不妨就先研究CPU的缓存架构。这篇文章《探索CPU的缓存架构,及引申到缓存系统的设计》可以一读。
③ MESI协议 与 分布式缓存一致性。如果对分布式缓存一致性算法不怎么理解的话倒是可以先去看一下MESI协议的内容,这个协议理解起来难度不是特别大,是一个不错的切入点(《大话处理器》这部分内容讲解的确实不错可以一看)。
④ 全局时钟同步问题。这里的时钟同步涉及到的是不同服务器的关键操作时间点的同步性问题,这样说可能有点片面,可以阅读一下这篇文章《浅析时钟向量算法》讲的比较通俗了。这个算法属于一致性算法,其他一致性算法感兴趣可以去搜搜看,说起一致性就会想起CAP理论了,这个也是一个很有趣的话题不妨多搜搜这些关键字面试中说不定就有收获。
闲聊几句:说起操作系统立刻想起一本经典书籍《深入理解计算机系统》,不过阅读感觉这本书更加适合那些面向基础层的程序员(C/C++)阅读这本书常常有种“我理解了这个知识点但它似乎不是我想要的”感觉。其实相对于这本书,我更喜欢《计算机体系结构:量化研究方法》这本书。虽然我只读了前两章,但感觉这本书受众面很广,实际上的确如此。如果你是嵌入式相关的专业书中有提及cortex架构(面试中提到大概率会让面试官眼前一亮)对于软件开发的同学这本书更不用说,它涉及到缓存、并发等等你感兴趣的东西。虽然有点安利嫌疑但是不妨试读前两章看看它是否适合你。
位操作
其实位操作没有想象中的枯燥,我在这里试举几例。① 使用位移操作(左移/右移)模拟队列操作。如果你的数据可以用位替代或者可以通过位转换这个操作确实可以帮助你省去一些麻烦,不妨试试 ② 布隆过滤器。虽然有一定误判率但是因为速度快可以做前置检查,也有一些改进版的布隆过滤器改进其弱点,一些第三方库亦有支持。
Ps:一些问题使用位运算会有奇效,可以试试(搜索Matrix67的《位运算简介及实用技巧》或位运算应用说不定会有惊喜)。不过还是要明确的是,位操作等相关的操作时我一般持有保守态度,因为很多支持这种编程风格的程序员有两个理由 ①简洁 ②高效。但是个人认为团队编程需要的是共识,共识之一包括编程风格,如果这种编程风格带来部分队员的理解难度,则需要慎重考虑,同时高效的问题在没有发生量变情况下也难以衡量,如果仅仅是几个操作就谈及效率,有点过于苛刻了。
阅读源码
似乎很少有人提到bookmark(书签)工具,对我而言她有时可以代替注释/断点帮助我理清思路。在Visual Studio 中书签默认就放在工具栏的一侧,可惜很多人(包括以前的我)对她视而不见。真心推荐这个工具。Ps:书签工具在IDEA中倒是很不起眼,而且不太好用。