ML到对象映射器中
从更广泛的意义上来说,意外的复杂性是开发人员添加到他们代码中的复杂性,这对于代码的工作是不必要的。这可能包括过度工程化、过度使用设计模式、糟糕的工具、框架和范例选择、以难以阅读的方式编写代码片段。例如,如果你可以用一用微服务来做(并且必须决定粒度,协调它们,等等。)或消息驱动架构(设置代理及其队列的各种配置)不必要地增加了软件的复杂性,因此是意外的复杂性。如果您想解析xml并将其转换成对象,与XML到对象映射器(例如JAXB)相比,使用SAX会增加很多意外的复杂性,在XML到对象映射器中,您只需添加一些注释(希望如此)。如果你的逻辑可以用几个lambda表达式来表达,但是你用If子句做了几个嵌套的for循环,那么这就是意外的复杂性。至少对我来说,意外的复杂性是指除了不知道更好之外,在没有充分理由的情况下,很难阅读、维护和部署。
另一方面,本质的复杂性来自于你试图用你的软件建模的世界。这是关于上的复杂性可能并且确实会使你的代码更难阅读和维护。这使它看起来像“遗留”代码也应该是这样。意想不到的API调用,你在实际使用半年后发现的一些奇怪的边缘情况下存在的类,你认为你可以删除的if和for——这些是真正软件的标志。
(我知道另一种关于偶然复杂性的观点——它仍然增加价值,但不是你正在解决的问题。这是一个很长的讨论,但是我认为任何本质上复杂并且需要完成的事情(例如滚动更新)都是本质上的复杂,也就是说,你不能没有它。)
如果您正在建模的业务流程有很多分支甚至循环,并且无法优化,那么处理该业务流程的代码就必须是“有毛的”。当你不得不在一个可能失去连接或连接不良的设备上运行你的软件,而这个设备随时都可能重启,那么重试、重新应用离线步骤等代码是必要的,即使它很庞大,很难遵循。
但就这样吗?是不是我们对我们的本质复杂性无能为力,只能把丑陋的代码留在那里,耸耸肩说“嗯,我知道这不好,伙计,但你能做什么——本质复杂性”。
嗯,我们不能摆脱它。但是我们可以让它稍微友好一点。我有两个具体的方法。
记录需要复杂性的场景。要么直接在代码中,要么在代码中链接。大多数看起来“WTF”的代码看起来完过解释背后的业务原因,确保所有奇怪的代码对每个人都有意义,那么我们就解决了部分问题。
但那只是表面。当谈到本质复杂性时,我们真的能遵循“保持简单,愚蠢”(KISS)原则吗?是的,在某种程度上。你不能把复杂变得简单,但你可以用更简单的方式呈现。我们想要实现的是降低感知的复杂性,使其更容易理解和推理。
首先要寻找的是你在基本复杂性周围引入的任何偶然的复杂性。通常情况下,本质复杂性使得意外复杂性更有可能出现,这可能是因为开发人员的所有注意力都集中在掌握他正在工作的场景的每个方面,而忘记了良好的实践。但是消除这一点也是不够的。
具有讽刺意味的是,这正是通用(设计)模式和特定框架派上用场的地方。您需要表示应用程序状态的复杂序列?使用有限状态机实现,而不是零零散散的。你需要表现一个复杂的业务流程?使用业务流程管理框架,而不仅仅是流程控制结构。您的类中有很多依赖项(即使您的类设计和打包得很好)?使用依赖注入框架。或者在很多情况下——只是重构,我知道而易见的事情,但我们都见过复杂的方法,只是做了很多事情,并没有遵循这种方法。因为它是随着时间增长的,所以没有人意识到它已经变得那么大了。
但是除了几个例子之外,
如果您在集群中运行RabbitMQ,很有可ndling
配置。它有三个值:ignore、pause_minority和autoheal。上面链接的分区指南也解释了这一点(“我应该选择哪种模式?”).请注意,无论您选择什么,都会遇到问题,您必须恢复连接。举pause_minority然后手动重新连接可能更好。
幸运的是,检测分区相当简单。如果没有分区,则status命令有一个空的“partitions”元素,如果有分区,则有一个非空的partitions元素,或者根本没有这样的元素。这一行做了检测:
1
|
clusterOK=$( sudo rabbitmqctl cluster_status | grep "{partitions,\[\]}" | wc -l) |
例如,您可能希望安排脚本每分钟运行一次。如何处理结果取决于您使用的工具(Nagios、CloudWatch等)。对于Nagios有如果是AWS CloudWatch,您可以执行以下操作:
1
2
3
4
5
6
|
if [ "$clusterOK" - eq "0" ]; then echo "RabbitMQ cluster is partitioned" aws cloudwatch put-metric-data --metric-name $METRIC_NAME --namespace $NAMESPACE --value 1 --dimensions Stack=$STACKNAME --region $REGION else aws cloudwatch put-metric-data --metric-name $METRIC_NAME --namespace $NAMESPACE --value 0 --dimensions Stack=$STACKNAME --region $REGION fi |
当分区发生时,重要的事情是得到通知。之后,它取决于特定的应用、问题、队列配置(持久、镜像等)。)
我不能给出一个普遍规律。降低感知的复杂性(显然)高度依赖于降低它的人的感知。但是作为一个简单的建议——始终考虑如何围绕应用程序固有的基本复杂性重新排列代码,使其看起来不那么复杂。