书评:弗里德曼《自由选择》

政府在经济活动中应该扮演多大的作用一直都是颇具争议性的话题。弗里德曼在《自由选择》一书中充分阐释了他的理念:政府应该致力于充分支持经济自由,让市场发挥完全的作用。弗里德曼是自由主义的坚定支持者。在他看来,美国的经济奇迹建立在两个自由之上:政治自由和经济自由。前者由人权宣言和美国的宪政体系所保证,后者则由亚当斯密以来深入人心的经济学思想来维系。但是从大萧条开始,经济自由开始受到越来越多的威胁。

美国1930年代的经济大萧条是经济思想的一次大转折。普通民众和学界都开始认为大萧条是市场失灵的结果,于是凯恩斯主义开始逐渐兴起。以大萧条的政治氛围为契机,从经济领域开始,政府在普通民众的生活中开始发挥越来越大的作用。从经济安全到社会平等,从促进教育到保护消费者,从保护劳工到避免通货膨胀、促进就业,政府的影响越来越多的进入到人们的日常生活当中。

弗里德曼认为市场尤其是价格有三个主要作用。第一个作用是传递信息,当信息构成相互比较的时候人们得以据此作出选择,第二个作用是促使人们采取最高效的生产办法;第三个作用是收入分配。弗里德曼认为,这三个功能是相互联系的,人们有动力改进他们的生产方式,是因为这些造成的价格改变最终会影响他们的收入。共产主义政府所犯的错误在于试图将收入的分配和价格体系隔离开来,直接决定人们的收入分配,价格机制所传递出的信息被扭曲了,人们也就失去了改进工作和生产的动力。

国际贸易是一直一个广受政府干预的领域。几乎所有的经济学理论和经济学家都支持自由贸易,因为自由贸易使消费者获得更加廉价的产品,使生产者可以专注于更具有比较优势的行业。但是自由贸易也是都到政治影响最多的经济领域。人们以各种理由反对自由贸易,比如保护等行业但不具备产品竞争优势的劳工,对其他国家政府补贴行为的反击,出于国家安全的需要,出于保护新兴产业的需要等等。在弗里德曼看来,这些顾虑大都是特殊的利益群体自我保护的结构,自由贸易最终都还是有利于各方的。

1930年代的大萧条是人类历史上最令人瞩目的事件之一,它使得公众相信资本主义是不稳定的,为了避免危机再次发生,政府有必要介入经济活动。这场危机也同时在经济学专业领域上产生了深远影响:凯恩斯主义的兴起。弗里德曼认为,公众和学术界对自由市场观点的转移是源自对大萧条发生原因的误解:大萧条是政府的行动错位而不是市场的失灵造成的,而美联储系统等政府经济控制机构的崛起实际上是受益于当时的这种政治氛围。

伴随大萧条新政而来的是一系列的社会福利计划,比如社会保障计划、健康保险计划等等。在西欧,国家福利主义开始盛行,比如英国的全民健康保险计划。在美国,最大的福利计划则是社会保障计划。社会保障实际上用现在的征收的税收来给已经退休的老人养老,这种计划的问题在于它无法提供任何保障,因为谁也难以预料未来若干年退休之后社会保障资金的运转情况如何。

在做着看来,社会福利主义的兴起部分的源于对结果平等的追求。比如诸多的收入再分配计划。这种做法实际上会损害到经济和社会本身,因为这样一来大家努力进取的动力就变低了获得回报的很大一部分被拿走交税,而就算不努力工作所获得的支出也不会太差。而在那些努力宣扬其追求结果公平的国家里,最终这些用来保证结果公平的强制力都落入了那些追求自己特殊利益的人的手中。

与结果平等相对的是起点平等,其含义是只有一个人的才能才会决定他的机会,除此之外任何因素都不应该影响他获得的机会。然而起点公平本身就是一个复杂而难以实现的想法:究竟怎样才算起点公平呢?一个穷人的孩子和一个富人的孩子所可以得到的教育资源就是完全不一样的,这样难道不是一种不公平吗?弗里德曼认为,先天所继承和拥有的财富就如同一个人先天的禀赋一样,是自然的事情,不应该被嫉妒。他认为,起点公平是和自由相互关联的,如果对于平等的追求被置于自由之上了,那么它无疑将会损害自由,反之,自由将可以用来促进公平。

政府干预经济自由的另一个领域在教育市场。作者认为政府设立的公立助学计划限制了家长们的选择自由。家长需要通过交税为公立学校出资,但是公立学校并不能满足所有家庭的教育需求。作者的建议是在初级和中级教育阶段设立凭单制,家长可以使用凭单来抵扣教育的费用,这样一来家长可以在公立教育和私立教育之间灵活选择。

第二个受政府干预的领域是消费者保护。近半个世纪以来,政府开始设立越来越多的消费者保护机构,比如州际商务委员会,消费品安全委员会,环境部等等。这些机构提供诸如帮助消费者鉴定产品质量以避免上当受骗的价值。但弗里德曼认为,这些政府结构的设置阻碍了市场的自由发展,如果允许市场自由竞争,那么这些问题都会随之解决。

第三个例子是劳动者保护。政府和劳工委员会通过设立基本工资,进行薪酬谈判等方式来保护劳工的利益。但在作者看来这实际上是难以实现的。市场的供需关系不会改变,人为设立的基本工资只会限制和降低劳动需求量,最终损害劳动者的利益。 比如工会谈判要求提高工资,这样一来势必会压缩企业的利润空间,从而导致企业降低劳工人数以控制人力成本。而一般认为的提供工资提升空间的公司利润部分实际上是资本的利得部分,如果一项投资的回报率降低,势必导致对该行业或企业投资的减少。初次之外,劳工委员会常常和政治影响力合作,通过政治影响来增加自己所在群体的特殊利益,又反过来对政治力量予以支持。在作者看来,这些都是政府不适当干预经济过程的后果。

在本书的最后,作者谈到了通货膨胀的现象和医治。作者认为通货膨胀完全是一种货币现象,其发生的根源在于政府滥发货币。通货膨胀实际上是政府获取资金而又不直接增加税收的一种隐蔽的手段,获取资金只需要开动印钞机即可,既增加支出而又不增加税收简直是一件大快人心的好事。但是实际上通货膨胀的成本最后还是会转嫁到普通民众身上。通货膨胀的另一大原因是政府错误地将控制就业作为基本目标。为了达到不切实际的就业率,政府只能通过增加支出来实现,因此必然导致货币超发发,通货膨胀。为了治疗通货膨胀,在抑制政府开支的同时,还必须忍耐高失业率这一副作用。

弗里德曼在这本书中所讨论的都是颇具争议性的话题,比如大萧条的成因,消费者保护,国家是否应该设立公共教育,控制通货膨胀和控制失业率之间的权衡等等。在这些争议当中,弗里德曼总是坚定地站在市场这一边,并且从理性的经济学的角度阐释选择自由市场的好处。这本书另一个具有启发性的地方在于,他使人们看到了在实际的经济决策当中不可忽视的政治因素–尽管他的本意是要尽力摒除这些政治因素。比如在国际贸易的争论当中,在利益受到短期损害的民众的选票和长期的不容易立即显现的贸易价值之间,政治家很可能选择前者以讨好民众包住选票。在自由主义和政府主义的光谱中间,我们已经看到了全世界各个不同国家的选择。这本书为我们观察这些国家的社会现状提供了一个好的切入点。

Book Review: Cloud Native Java

Cloud Native Java provides an overview of why people want to build cloud-native applications, and how to build them with Spring Boot and other frameworks.

A cloud-native application focus on the application logic that solves the business and product problems, without worrying about the underlying infrastructures setup and operation. Spring Boot is such a framework that provides a simple service bootstrapping process as it covers most of the complicated configuration process in order to bring up a service. It does not solve every engineering problem you will be facing, but it provides easy integrations with the best framework on the problem domains.

Spring Boot enables you to quickly build a REST application, you can have such an application up and running with half an hour. The easy to use reminds of some good frameworks in the Python web world like Falsk. You can easily equip your framework with different persistence solutions: SQL database like MySQL and PostgreSQL, NoSQL database like MongoDB, cache services like Redis. You can also build a data-driven application with the Spring message channel framework or integrating with messaging brokers like Kafka, RabbitMQ.

Spring makes such integration easy by providing you with the native abstraction frameworks to integrate with such systems, like Spring JPA for database access, Spring Data Cache for cache service access, and Spring Message Channel for streaming frameworks. These abstractions help you focus on the application logic without worrying about the underlying details.

Spring also utilize the well-built framework to solve the problems beyond the application logic. By integrating with OAuth, it provides robust authentication and authorization solution. By integrating with Eureka, it helps you solve the middle tier routing problems.

It is fair to say that this book is very comprehensive. It almost covers every aspect of the system that you need to build for a cloud application. The well-organized examples and annotations make this book a handbook for people who need to solve exactly the same problem.

It is a good guide book for people who try to understand how to build a Java application with Spring Boot on the cloud. It discusses some of the essential problems you need to consider and solve when building cloud native applications, and it demonstrated that these problems can be solved easily with spring boot. 

However, I don’t consider it as a good book for people who are exploring Spring Boot as an alternative solution for the engineering problems within a relatively established world.

The major issue is: the infrastructure components in such an organization mostly have already been built. The challenge for the engineers is to integrate the SpringBoot into the existing system.  For one example, OAthu is a good choice for authentication, but what if your company already have it’s own authentication system, for example, Django’s authentication framework where each client is viewed as a user?

I understand that it is very difficult to write such a book that fit for everyone’s use case. as every company is built differently, a solution works for one company might not work for another. And the most interesting challenge for the engineers is to solve the problem with a given context. 

The other problem of this book is that it lacks the in-depth discussions of the essential problems engineerings will be facing when building cloud-native applications. The discussion in this book is relatively superficial. For books that don’t provide the right solution, I expect them to provide inspiriation.

Overall, I recommend this book to people who are new to the industry and new to the Java web service programming world. For people who are looking for more in-depth solutions or discussions, this book is not a right choice.

Book Review: The Effective Engineer

The effective engineer raise a simple question: how does the engineer leverage his or her effort to make a disproportionate and meaningful impact? Before answering the question, we would want to know how to define and measure the effectiveness of an engineer and engineering activities. The author believes that leverage, the value or impact produced per time invested, is the best measurement for the effectiveness. In order to increase your effectiveness, you should focus on either get the same task done more quickly, or to increase the impact of your activities, or to shift to activities with higher leverage.

The foremost and fundamental part of becoming more effective is to adopt the right mindset. Including focusing on high-leverage activities, optimize for learning, and prioritize regularly in order to keep yourself focused.

The following sections of this book are essentially discussing the two major approaches of increasing your effectiveness. Part II of this book focused on execution: how do you get your work done more efficiently.

The first advise it offers it to improve the iteration speed: the faster you can iterate, the more output you could generate within a given time. Many factors could slow down the iteration speed: maybe your team works on a huge monolithic service without enough support on tooling and debugging, maybe your existing service requires constant operation support that your team gets distracted. To become more effective, you should constantly think about what makes you and your team’s iteration speed slow down.

Another advice is to measure what you want to improve. A common mistake people make during work is using the wrong metric to measure the problem. Selecting the wrong metric could be misleading.

Measuring the area you want to improve also help you better drive the work. Whether you are an individual contributor, a tech lead or an engineering manager, you must be in situations when you would like to bring some technical, product work to people’s attention so that you get their consensus on the priority of the work and support to work on it. In these situations, data and metrics are more compelling than words. So the best strategy is to measure the scope of your work: how many order we lost every day due to this issue, how many customers are being affected. You will be much better off with these measures.

The third advice is to validate your ideas early and often. I’ve got multiple opportunities to start new products from scratch. I find it is very useful to deliver the first version of the product as fast as you can, collect the requirements from your customers then try to improve on it. It is very hard to picture every detail of your product before you bring it to your customer. And I give this advice to every engineer working on some project.

The fourth advice is to improve your project estimation skill. Project estimation is hard, but it is important for the team to communicate the expectation to the stakeholders, and for the business to decide the priority of these works. We made many mistakes on effort estiamation, people either tend to underestimate or overestimate the difficulties of their task, and there is an anchor effect on people’s preference. For large project estimation, this becomes even challenging,  because we oftentimes underestimate the unknown parts, and they only start to materialize once the team starts to work on them. Of course, there are approaches to reduce the risk of inaccurate effort estimation, for example, ask the people that will work on the task to do the estimation, and timebox the investigation on the unknown part.

For tech leads and engineering manager who held the responsibilities of communicating the expectation and progress to the stakeholders, the effort estimation becomes even more critical. First of all, you should define a clear goal for your project. A clearly defined goal not only helps you better manage the expectations of the stakeholders but also provides with you a good approach to correctly scope the works and prioritize the tasks.  Secondly, you should build your project incrementally. Trying to achieve multiple goals in one project can significantly increase the risk your project get slipped, as the complexity of the project grows exponentially.

Part III of this focused on building long-term value: which is the more impactful work for the engineers comparing to other activities like delivery a feature.

The advice from this section includes balancing the quality with pragmatism. An essential topic for most the engineering team is how to improve the quality of the work, except for a few companies like Google, as they introduced such a good code review system to make sure the code is written in good quality. This is not the case for most other engineering teams. Introduce the code review process will be helpful. Another such topic is about tech debt. Tech debt will be accumulated as the team takes shortcuts on the development. It is totally okay to introduce tech debt on the code base, but the team should also have a pan to continuously repay the tech debt.

The next advice is to minimize the operational burden. You must always be aware of the tech decision you make: is it engineering infrastructure you build robust enough that you don’t need to worry about its operation support? Does the tools you provide enough visibilities with the clients to track out the failures easily? Another typical mistake we make is to introduce new technology without enough knowledge about its operational burden.

The last advice is to invest in your team’s growth.  Help the people around you be successful, building a better onboarding process, making hiring a priority of the team. All these works would lead to a better engineering culture.

This book is not only a good choice for engineers who want to become more effective but also a good guide for the engineering managers to materialize their ideas of building a better team: essentially only when your team member becomes effective, you will be effective.

《联邦党人文集》阅读笔记一

 

《联邦党人文集》是汉密尔顿、麦迪逊和杰伊,在1787年美国宪法草案颁布之后,为说服纽约州居民支持该草案而撰写的一系列说明性的文章。今天我们仍然阅读《联邦党人文集》,是因为它依然是对美国宪法立法者们立宪意图的最权威解读。

《联》一般可以分为五个部分。第一部分为前十四篇,主要阐释为何需要一个强大的联邦来保卫安全和保证繁荣;第二部分为十五至二十二篇,主要讨论当时联邦组成的弱点。第三部分为二十三至三十六篇,主要论证一个有活力的联邦需要哪些权力。第四部分为三十七至五十一篇,主要定义了新的联邦主义者。第五部分为五十二至八十三篇,主要描述联邦政府的机构设置。

在第一部分当中,作者意在说明分散的州政府的诸多缺点。首先是战争的危险。作者认为,正当的战争多半是因为国际条约没有得到有效履行。相对于十三个独立的小政府,成立一个联合的大政府更容易保证这些国际条约得到有效的正确的执行。而对于不义的战争,最好的策略是建立强大的军队使得敌国不敢冒犯,而一个强大的联邦政府比分散的小州政府更能够维持一只强大的军队。作者还认为,如果保持十三个州分别独立,他们会因为种种原因产生冲突并最终酿成战争。比如外国的干扰、州与州之间贸易的摩擦、领土的纠纷和军事不平等。而由于州与州之间的战争或者军事竞争,政府必然会扩大权力和军队力量,最终损害人民利益。成立联邦政府则可以有效避免这些危险,既可以有效评定叛乱,还有助于海上商业的发展和海军的建立,同时可以简化税收,降低联邦的运行成本。

第二部分主要是对当前联邦的弱点的描述。其中最主要的问题是,当时的联邦政府的立法基础是建立在州之上而非个人之上的,而联邦公约的执行毫无强制的手段。作者认为,解决这些问题的办法是让联邦政府的执法权建立在个人基础之上。关于这一点,反对者认为联邦政府将过于强大而侵犯人民权利。作者则反驳道,联邦政府之下有处理当地事务的州政府和地方政府,联邦政府并不直接与公民的日常生活发生联系,联邦政府想要直接获取他们手中的权利既困难也无此不必要。初立法权之外,作者认为联邦政府还缺乏管理商业的能力、招募军队的能力以及司法权力。

在第三部分当中,作者论证了为了建立一个有活力的联邦需要哪些权力。首先是征兵并维持常备军的权利。关于这一点反驳的意见认为,维持常备军将更容易使政府侵害公民权利。但作者认为,在紧急情况之下,零时征召军队是不可行的,而作为制衡的手段,只需要周期性的重新审定常备军的预算计划即可。其次是征税的权力,在此前的联邦政府设置当中,政府经费需要由各州缴付,联邦政府经常陷入经费不足的境地,直接征税的权利是联邦政府顺利运行的关键。

在整部《联》当中,第十篇是最重要的一篇。汉密尔顿在这篇文章里阐述了党争的不可避免以及控制他们影响的办法。汉密尔顿认为由于人与人天然在观念上不同、在财产上不均,人们必然会和他们最相近的人组成团体,有时候甚至不惜危害公众的利益,侵犯他人的权利,这样的党争是无法避免。

在所有党争当中,麦迪逊认为危害最大的是因为财产不均而起的。在当时的美国,有产阶级占少数,无财产者仍然占多数。麦迪逊担心,如果实现直接民主,这些多数无产者将会最终控制政府,并且通过各种手段,以牺牲其他富人和有产者利益为代价重新分配国家的财富,是为多数人的暴政。

麦迪逊认为解决这个问题的办法只有两个:消除其源头,或者控制其影响。消除源头或者需要完全剥夺人的自由,或者需要创立一个均富社会,二者都不可行。为了控制党争的影响,麦迪逊认为需要实行共和制而非直接民主制。共和制所选出来的代表更有可能是为了集体的利益,而不是个人的利益而制定决策。而大规模的共和制比小规模的共和制更能够有效控制党争。大规模的共和制意味着更多更优秀的的候选人,人们的利益更加多元而难以形成利益上的大多数。

至此,我们已经了解了《联》前三部分的主要内容,更多的内容将会出现在接下来的笔记当中。

《费城奇迹》书评

1787年5月25日到9月17日,联邦制宪会议在费城市的州议会大楼召开。费城会议是美国历史最重要的转折点之一。华盛顿汉密尔顿,麦迪逊,富兰克林等知名人物都参加了会议。这次会议通过的宪法将成为美国未来长久的繁荣的坚实基础。

美国宪法因为其伟大的设计成为历史长卷上的神来之笔。很多人将美国宪法的制定与独立战争联系在一起,误以为这部宪法是独立后的自然结果。实际上在联邦宪法制定之前,美国联邦一直以《联邦条例》为宪法而运行。《联邦条例》制定于1777年美国独立战争期间,是当时的美国各州为了争取更广泛的利益而达成的结盟协议。而联邦宪法的制定过程更是充满了波折。

《联邦条例》的制定是为了在各州的基础上建立一个统一的联盟,以在军事,外交,商业上争取更大的利益。联邦会议作为当时的联邦政府正是在这个条例的框架之下成立和运行的。

然而由于缺乏权力根基,《联邦条例》在各个领域的表现都差强人意。军事上,联邦陆军因为军费征收不力一度濒临解散。外交上,因为财力和权力有限,也一直未能达成有效的贸易协议。联邦在商业上的表现更为糟糕。因为缺乏征税能力,同时无法独立制定国际和洲际贸易的规则,联邦政府在促进易商上的努力也收效甚微。

《联邦条例》的失败是因为其所建立的权力基础不足。整体上她只是一种联盟性质的约定。联邦之内的各州拥有完全的主权,联邦会议的决议也必须要得到州政府的通过才得以推行。联邦的财政收入需要分摊到各州,但同时她又缺乏对各州的强制征税能力,所以即使各州拖欠费用联邦也无计可施。

正是看到了联邦的这些问题,汉密尔顿、华盛顿等人决定推动重新制宪,已建立一个更加强大的联邦政府。1787年,联邦会议决定修改条例,并邀请各州代表共同商讨修改方案。因此,在最初的计划当中,也许是为了获得更多州的支持,费城会议名义上并不是为了重制宪法而是为了改进联邦条例而召开的。

费城会议上一共出现了三套主要的制宪方案。包括更加激进,提议成立国家级联邦政府的弗吉尼亚方案,更加温和、提议在现有联邦条例框架上进行改进的新泽西方案,还有与当时英国制度颇为相似的汉密尔顿方案。其中汉密尔顿的方案因为与英国政体过于接近,并且需要州权作出更多让步而最终没有被接受。

佛吉尼亚方案主要由詹姆斯麦迪逊,即后来的美国第四人总统提出。弗吉尼亚方案提议设立一个强有力的两院制立法机构,即美国国会,国会上下两院,过会两院代表按照各州人口比例分配拟并选举。

在这里,我们需要了解的背景是,在当时美国联邦的十三个州当中,有人口和面积都巨大的弗吉尼亚州,佐治亚州,纽约州等,也有相对更小的新泽西州、罗德岛州等州。各州虽然人口和经济实力不同,但在联邦会议中都拥有同等的投票权。因此,弗吉尼亚方案中按照人口分配国会议员比例的方案可能会削弱小州在联邦中的权力。因此,新泽西州提出了一份反对弗吉尼亚州方案的新方案。

新泽西方案提议,各州在新的两院制立法部门拥有同等的投票权,这一提议与当时的《联邦条例》完全相同。新泽西提议一方面反映了各州希望以完全独立、平等的状态自愿结成联盟的心态,另一方面也反映了小州对于在新联邦中话语权降低的威胁的担忧。新泽西方案并未被会议认真考虑过,但是在制宪会议临近尾声的时候,小州的代表们以此为威胁阻止最后协议的达成。

在带领读者了解制宪会议的历史进程、并还原了州代表在制宪会议上的发言和背景之后,作者还试图让读者更为清楚的体会到制宪会议上最重大的争论:立法部门代表分配问题,的历史背景。因为对国会席位分派方案上的争论,制宪会议一读陷入僵局。这个时候,作者笔锋转移,带领读者对当时的美洲大陆进行了一次巡视。

这种巡视式的方式让我们更加了解费城制宪会议的历史背景,比如为何美国的人民如此真在意州权。在制宪会议陷入僵局的时候,康涅狄格妥协成为了最终的方案。这个方案主张,两院制国会当中,下院的代表名额按照每个州的人数分配,而上院代表队的名额平均分配,每州两名。这个妥协的方案平衡了大州和小州的利益,于是最终得以通过。

除了对于制宪会议的历史还原,《费城奇迹》这本书还刻画了会议上最令人瞩目的人物。包括沉默寡言的华盛顿将军,能言善辩的汉密尔顿等。其中又以对经验丰富,政治手腕高强的富兰克林博士的刻画最有趣味,比如作者还原了富兰克林在制宪会议陷入僵局时,为了鼓励大家放下成见放眼未来的而进行了轻松幽默而又发人深省的发言。正是这样的细节就让我们感到了他欢快而又充满智慧的个性。

作者在本书的最后几个章节还介绍了宪法批准的过程。因为根据新宪法的规定,比如得到13个州当中9个州的批准才能正式通过。这些情节同样精彩。

对于想要了解1787年制宪会议这段历史的读者,《费城奇迹》这本书是个不错的选择。作者在内容上的选取有度,重点还原了制宪会议上主要争论,而没有陷入到对于细枝末节的沉闷讨论。另一方面,对于会议上重要人物的刻画给阅读增添了趣味,也使读者通过靠近这些改变历史的人物更加体会到历史事件的发展过程。作者在记述会议进程期间还穿插了历史背景的介绍,以使得读者更容易理解为何当时的辩论如此重要。

《万历十五年》书评

按照作者黄仁宇的说法,万历十五年,即1587年,是历史上极为平常的一年。这一年‘四海升平,全年并无大事可叙’,‘实为平平淡淡的一年’。既然平淡,作者何以要单单将这一年抽出来叙述呢?要理解作者的做法需要从作者的大历史观说起。

黄仁宇的历史研究从大的时空范围着手,强调不通过历史人物的生涯探讨和单一历史事件来分析历史,而是通过对历史社会面貌进行整体的分析和把握,掌握历史社会的结构特征。

万历十五年是五百年明清史中极为平常的一年,这也正是作者选取这一年作为研究切片的原因之一:从宏观上看,明清社会的根本问题从未改变,从这极为平常的一年着手,也可看出不变的矛盾并理解明清社会走向衰落的根本原因。

黄仁宇在这本书中对万历朝的诸多人物做了群像式的描绘。在他看来,传统中国社会以道德代替法律,阻碍了技术的发展,最终导致中国社会从汉唐的先进走向明清的衰落。黄仁宇在描绘这些历史人物的时候,重点展示了他们在这种社会设定之下辗转腾挪。

比如张居正之后的第二任首辅申行时,一般认为他是个和事佬,老好人。作者却认为,他早已看出整个文官集团中,作为统治基础的道德要求和文关门本身的的私欲之间的相互抵触。

作者以阳和阴来说明道德与私欲的矛盾。道德礼法是阳,皇帝和百官需要通过各种象征性的仪式来维持人们对于道德的信任,从而达到上下一心的目的,bi并完成国家治理。但另一方面,大明王朝历经两百年,文官集团已经成为事实上的统治集团,文官们为了私欲进行各种争斗也是无可否认的事实。

万历皇帝了解到道德与私欲并存的过程正是从张居正死后大臣对他的弹劾开始的。万历皇帝发现这个曾经以道德教育自己,以简谱自居的首辅大臣其实私生活相当奢侈,他对于自己多年受到的要为明君的道德信条也终于坍塌。

万里皇帝还逐渐了解到,及时那些对张居正进行攻击的大臣,也并不是完全怀着纯正的目的,他们也是通过这种手段获取利益。作为皇帝表面上拥有无上的权力,但也不得不收到传统文化和文官集团的掣肘,而他并无能力改变这一局面,于是他选择了怠政的方式作为对文官集团的报复。

张居正死后被清算的原因在于他改革社会的同事,试图以权威压制私欲,最终在死后遭到反弹。申行时在了解这一问题之后调整方法,努力维持人们对于道德的信任的同事又不过分压制文官的私欲。

申行时的这种中庸和妥协的方法当然难免受到非议,人们会认为他不作为,对导致明朝覆亡的诸多隐患置之不顾。但作者却指出,在传统中国社会道德统治的设定之下,供申行时选择的空间不存在了。

另一个代表人是以清廉正直的名声享誉本朝的海瑞。他所提倡的社会治理的方法乃是以残酷的手段,如朱元璋时期的剥皮之刑,惩治道德败坏,贪污腐败者。立足点仍然是惩治私欲,维护道德。即使是万历皇帝也认为他的主张过于怪癖而认为他冥顽不化,最终海瑞落寞的死在任上。

军事领域的情形十分类似。明朝立国以来,为防止武将作乱,始终以文职为尊,打压排挤武将。戚继光所进行的军事改革也仅仅是局限在抗击倭寇的前线部队之中,而无法触动更大的军事集团。

思想界的代表人物李贽同样如此。李贽力图突破程朱理学的限制,提出人可以有私欲的观点。但是最终仍然不被认可,并在信仰程朱理学的士绅们的迫害之下入狱,最终自刎。

在作者看来,海瑞,戚继光,李贽都是因为受到传统文化的掣肘而得不到有意义的发展的人。

本书作者黄仁宇原本是国民党的军官,二战结束后进入美国密歇根大学跟随著名学者余英时学习历史,1964年获得密歇根大学历史学博士学位。本书1976年即已成稿,然而因为研究方法别出心裁,一直到1981年才在耶鲁大学出版社的支持下出版。

这本书原作为英文,后经作者翻译为中文,但行文乃仍然保留了许多英语文章的特色。

Building Microservices Note: Integration

What is Microservices Integration ?

How one microservice can talk with another? In general, the following technologies could be used: shared database, RPC, and REST. But how do we pick up the right one?

The following are general answers to the questions:

  • Avoid breaking changes.

When we add a change on the server side, the client side should not be impacted unless necessary.

  • Keep your APIs technology agnostic

This is to avoid integration technology that dictates what technology stacks we can use to implement the micro services.

  • Make your service simple for consumers

Make it easy for the consumers to user the services.

  • Hide internal implementation details

Don’t have the consumers bound to the internal implementation.

With this guideline, let’s take a look at available options.

Integration technology

Shared Database

The most common form of integration is database(DB) integration: if other services want to retrieve or update the information from another service, they reach into the database.

This integration pattern definitely breaks many of the guidelines we set put:

  • It allows the external parties to view and bind to internal implementation details.
  • The customers are tied to a specific technology choice. For instance, if we decided to use Postgres, the consumer has to find a way to integrate with Postgres.
  • It would be very difficult to change the logic, the logic of parsing the data must be spreader across all consumers.

So in sum, shared database is never a good choice for micro service integration.

Remote Procedure Call

Remote Procedure Call(RPC) refers to the technique of making a local call and having it execute on a remote service somewhere.

The common used PRC techniques includes SOAP, Thrift, Protocol Buffers. They support separate interface definition, and client/server stub generation based on the definition.

Some of the technique bind to a specific networking protocol, while some allows you to use different type of protocols. For example, gRPC utilizes Protocol Buffer and HTTP2.

Some RPC mechanism are heavily tied to a specific platform, but some other mechanisms for example Thrift and protocol buffer support multiple languages.

So, what’s the major downside of RPC calls? The problem is, Local Calls are not like Remote Calls. The consumers often forget about one thing: the network is not reliable. The client needs to keep in mind that the remote server could be down, be slow or the request could be lost and handle these situations properly.

REST

Representational State Transfer(REST) is another technique. The most important concept of REST is resources. The REST service creates different representations of this resource on request.

REST and HTTP

REST as a design pattern does not talk about underlying protocols, although it is most commonly used over HTTP. The major reason is HTTP itself defines some useful capabilities that works very well with REST style, for example, the HTTP verbs: GET, POST, and PUT, and HTTP error codes.

There are, of course, downside of REST over HTTP. For server to service communication, if extremely low latency or small message size is important, HTTP might not be a good choice, as the message header can be big. TCP/UDP might be a better choice in these case.

Data Interchange

REST support many formats of data interchange framework, the most comply used one are JSON and XML. Application data are converted into JSON/XML format, and then transmitted to the other service.

JSON V.S. XML

Both JSON and XML are human readable and machine readable.

  • XML supprots store the metadata information with the tag.

For example, the type of the field, while JSON has to encode these metadata as an object and associate it with the data.

  • XML supports link while JSON does not.

Xlink is used to create hyperlink in XML documents, with Xlink, the link content can be defined outside the linked files. While JSON is purely data based, and does not support anything similar. For python, the objects has to be concretely rendered in multiple places even though they share the same content.

  • JSON is significantly less verbose than XML.
  • JSON supports array.

This make it easy to be mapped to the data structure in the programming languages, for example, array, list, hash map etc. . For example, JSON is directly interchangeable with python dict. JSON objects can be easily parsed and manipulated in almost all programming languages.