关于编程的思考

一、背景:

看了《SICP》 前面三章。然后休息了一阵子。首先对抽象的重要意义前三章讲得很好,也有了更深刻的体会。

回顾了Sinatra、Rails、Roda 三个框架的颗粒度,和我在他们之间的思考和徘徊

二、关于编程的思考

1.一切的问题在于编程的一半是人

程序,一方面交给计算机执行,一方面交给人来阅读。

人们编写程序主要目的其实是为了给人阅读,其次的目的是给机器执行。

编程的一半的意义是跟人相关。

人通过书写程序来表达一种思想。编程行为本身是一种表达。创造。所以很多大家都再说,与其说编程像是工程科学,他其实更像艺术。

同样,人也是程序生命周期的一部分。一个程序没有人维护就等同于死掉了。只有人会不断的更新程序,程序也就有了新的生命一样可以持续被改进。

2.抽象的高度自由和人

只要你愿意,你可以在程序的任何维度上面进行抽象。显然不同人有不同的选择。就像一千个人心中有一千个哈姆雷特。不同人的理解和表达,也不见得不容易被别人理解。

你依然可以书写作品被别人理解,交流你的观点。

程序抽象的好坏,其实就是表达的好坏。衡量人的部分就在这里得以体现。

3.抽象和DRY是一切的基础是圣剑的双刃

编程的过程中,可能用到数学、算法理论、机器原理……这些都是认知层面上的东西。

但是只要开始写程序就是表达层面上的东西。

凌驾于任何思想之上的,或者说是一切编程理论的根基,只有两个:

1)抽象 2) DRY

抽象是用来在程序中建立起结构的。

DRY是用来在工程中建立起结构的。

3.1 抽象

抽象就是起名字,通过函数、类封封装,底层就是一个指针的名字。《SICP》中有精彩的描述。抽象建立起抽象层。

有了抽象层,我们就可以像垒砖一样,一层一层构建起复杂的程序。就像一个一个基石可以堆砌成宏伟的金字塔。

“lambda演算”已经揭示了计算是一切的起源。同样和基于状态的图灵机互为等价模型。

抽象是为了屏蔽细节。我不用关心了。

抽象是为了产生新东西。如果没有新东西,不叫抽象。

3.2 DRY

DRY是工程层面上的,或者实现层面上的。为了增加可读性,DRY往往是依托在抽象上而生的。

一切的设计模式、编程原则、如何写出更好的程序的所有实践经验,归根结底逃不出DRY原则。

就是为了更少的重复。更少的改动。最大可能性的不变代码但是可以应对变化本身。

4.如何使用圣剑

圣剑可以斩断一切问题,圣剑有双刃——抽象和DRY

为了不被圣剑反噬。我们必须知道如何控制自己的武器。

1) 抽象

不做没有产生实际价值的抽象。

我为什么喜欢微框架,而且很认可这条路。是因为客观上在你做这件事情开始,抽象并未真正的产生。

大多数你可以使用的框架,他们能解决你的问题,仅仅是一个巧合。

当我们解决的是一个特殊的问题的时候,尤其如此。就像LISP它最终会进化为独一无二解决这个问题的语言。

我们自己的程序也是在走这条路。

所以我们的抽象,应该逐渐的逼近我们的问题而产生。

微框架提供了比较少的负担。

2)DRY

要去除产生的重复。才叫DRY。

如果在我们的发展过程中,从未重复,那何谈DRY呢?

DRY是伴随着问题的产生,持续发生变化的。

微框架的理念把DRY的权利留给你来做。

3)Rails VS Sinatra

正是由于上面两种思考,我反而是反对 Rails。

我非常认可Rails的存在,它积累和凝结了社区的智慧,沉淀了大量实践。挺好,只是我不会去用。

我鼓励Sinatra,因为你要做的东西,和Rails的方向可能是南辕北辙。尤其是新东西。

为什么你要接受你的代码里(框架也是代码的一部分)存在大量的冗余,那些你不理解,你无法控制的各种抽象,各种轮子。

站在我的角度,我们应该细颗粒度控制我们的项目。抽象我们自己的抽象。我们的抽象、DRY做到了自己服务,才会获得真正的自由。

三、反省一个脚手架

sinatra-app-template 是我自己想写的一个框架的雏形。

随着我对编程理解不断的变化,它也在不断地变化。

1) v1.0.0

这时候我想把框架做成一个无所不包的脚手架。包含像Rails一样的特性。最后我设想这里就像一个平台,可以融合很多的rack应用。

反思:

这就是一个错误的、冗余的设计。因为你过度自信了事情的发展方向。 而这种冗余的模板,会带来一大堆没必要的东西。

所以这是一个非常失败的设计。这也是某种很自然的第一直觉。

2)v2.0.0

产生了DRY思想的萌芽。产生了聚合,分职能的规划。对应用的理解出现了bases可继承类。

反省: 一切都恰如其分。但是实际上发展的太复杂了。目录超过了10个。 这是在制造问题,尤其是他们的引用关系。

他们真的有那么多,一切都非常必要么?

很多工作是无用功罢了

3)v3.0.1

我不再觉得我们需要很多app、rack包含在这里。

程序他应该是简单的、纯粹的、组织明确的。

于是程序变成 core+应用本身

一切只为一个应用而生,所有问题根据路由解决。

如果路由无法解决,那你应该新建一个应用产生服务。

这里逐渐提取了config、main_app、core的概念。

反思:

但是依然复杂。复杂在一切设定。复杂在太多的重复、无用的抽象。

比如 class BaseApp 是一个无用的抽象。他没有产生价值。

一个抽象,必须要屏蔽细节。而BaseApp没有真的屏蔽细节,他只是在假装看起来很简单。但是当你要修改的时候,还要跨越2个源码文件查看修改。这个抽象——没有带来新东西。所以这是失败的抽象。

没有带来新东西的抽象——是失败的抽象。

比如 config/boot.rb 处处在声明它。这是个靠声明拖动起来的框架,如果你丢了一个声明。一切无法运行。

这是一个存在大量无用重复代码的模板。

DRY应该切实的消除大量的重复 —— 实实在在的消灭重复


4)v4.0.0

伴随这次思考,应该会更加简单。

只保留有需要的。

开放可以修改的。

减少无用的。

我们应该跳出各种技能、最佳时间、编程最佳思想……枷锁的束缚。

那些只是前人工作经验的总结罢了。

我们要做的是思考和审视我们自己在做的事情。不断地评估他的合理性、抽象、和是否做到了DRY。仅此而已罢了,事情非常简单。

只不过为了这个目标,我们要使用各种办法表达,直到达到我们的目的。

一切就为了做好这件事本身 —— 纯粹的思考。

Mark24

Everything can Mix.