Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

高阶的编程模型 #172

Open
EthanLin-TWer opened this issue May 23, 2017 · 9 comments
Open

高阶的编程模型 #172

EthanLin-TWer opened this issue May 23, 2017 · 9 comments

Comments

@EthanLin-TWer
Copy link
Owner

EthanLin-TWer commented May 23, 2017

通过一系列「优雅的 Mac」的讨论,我提到这些快捷的本质是为你更快地处理尽可能多的「背景事务」,以使你能够专注在「更重要的事情」上。更重要的事情是什么呢?产出价值。产出代码。这里,我们暂且假定
代码=价值,那么有两个推论:

  1. 如果「价值」本身有问题,那么整个所谓效率体系,都没意义,因为没有产出有用的价值。这个问题,我会在效率集里讨论
  2. 如果你不产出代码,那么你没必要节约其他部分的时间,因为你就没要完成的东西啊

更遑论,产出的代码本身不一定就100%达到了你要的价值。在业务代码的上下文下,你产出了代码,解决了问题,就是为公司产出了价值。在自己做产品时,写的代码有没有价值,就难说了。因此,更快的产出,才能支持更快的验证、反馈,甚至抛弃,才能作为整个敏捷体系的支撑。代码产出越慢,价值反馈越慢,你能试错的机会越少,机会成本越高。

骨架代码

这个 issue 要谈的是「产出代码」这个事情本身。我发现,即便是在产出代码,你在写的很大一部分代码也不一定是产生了直接价值的代码,比如框架代码,比如基本的控制结构。我把你要写的代码想像成一篇文章,这篇文章应该是有它更高层次的结构的。并且,这个结构与你所写文章的类型——理解为你所用的框架——有直接的关系。打个地方:

  1. 一个 React+ES6 的组件,首先一定是一个类,它必须有一个 render 方法,可能有若干生命周期方法。这些是它的结构、骨架,有了骨架,你再往里填东西就是了
  2. 一个 Java 服务, 首先它也一定是一个类,必然是这样的结构: class MyClass { ... }。里面可能有若干方法。这些是它的结构、骨架,有了骨架,再往方法里填东西就是了
  3. 一个用 chai+mocha 写成的 JS 单元测试。首先它一定具有 describe('', () => { it('', () => {}) }) 这样 的骨架,一个测试里,一定有 given(准备数据)、when(调用方法)、then(验证返回)三个部分。有了骨架,你再往方法里填东西就是了

可以看到,这些代码,都不一定是有价值的代码。你所写真正的代码,应该是那些骨架里的函数、方法里的那些代码。骨架代码,生成就行了。这是我要提的第一个点,骨架代码生成。说白了,就是这样一个 API:

generateSkeletonCode(...techStack)

基本控制结构

好,我们真正要写的就是那些骨架里的函数方法代码。但是莫急!这些函数里面,依然不需要你去写的所有的代码,我们还有更为基本的组件。那,就是我们经典的三大编程结构statementif-elsewhile。顺序结构、条件结构、循环结构。各种结构有变体,不妨碍使用,而且为了减少记忆负担,尽量只用一种可应对万能情况的结构。

细细拆分下来,顺序结构里面,一般是 变量计算API 调用赋值 等,本质都是通过计算和请求获得可供下步计算或返回的 数据;循环结构,其实在 JS 这种特定语言里,又可以使用函数式编程来代替。所以,我们在实现函数或代码的时候,可用的编程结构分列如下:

  • 顺序结构 statement
    • 变量计算。通常无特定模块,手敲即可
    • API 调用。这个又是一个子模块,它又根据你所用的技术栈不同而有不同的语法(如你用 $.ajax()fetch() 不同的 API 语法不同,你用 HTTP 请求与用 FTP 请求需要的协议参数又可能不同),但它又有共通的接口,如都需要你传入 urlsettings(optional)、回调等。其实又有一个编程结构的 API: generateAPICode(...techStack, url, settings, params, successCallback, errorCallback)
    • 赋值。上两步都是为了取得数据供后续计算,那么数据就得保存起来,会发生一次赋值操作。这个在 Intellij 里已经有后向声明这样的特性支持
  • 条件结构 if-else switchgenerateConditionComponent(condition, ...opeartions)。这个 Intellij 里也已有 if 这样的 live template
  • 循环结构 whilegenerateLoopComponent(startCondition, stopCondition, accumulateCondition, operations)。对于数组来说,这样的循环则可进一步简化为高阶函数式编程,现已有完美支持:array.map()array.filter()array.reduce()array.find()array.any()

理解了这些,其实编程产生的直接价值,真正需要你的东西,除了把代码写好让人容易理解到极致之外,就只是输入数据了。我们的工作,其实就是运用调配这些框架代码、编程结构,从原始的输入数据处,产生正确的输出。如是而已。中间调配过程,能越快完成越好。

实践落地

说了那么多,怎么落地呢!?

Mindset

思维转换。比如要 TDD,就要先把思维切换到 任务分解、快速反馈验证 这样的工作论上来;这种编程模型,本质是把代码做从上至下的组件划分,从框架性的最高层组件,到下面的结构组件,通过分离组件模板代码和真正需要我们编写的代码,尽量剔除无用的工作。新的思维模型会出来,正是因为以往直白的直觉思维,已经无法高效应对更复杂的问题。因此,尝试、辩证、质询看待一种新的思维方式,才是成长式的思维嘛。

真的要落地了

  • IDE 支持:WebStorm 插件?
  • 没了?

自己撸一个。核心代码尽量做成可复用的 API,这样不同的编辑器插件只需依照不同的模板集成就行了。就像 JUnit 5 分离出一个 jupital-core 的核心包出来一样,以后即可适应 gradle runner, maven runner, Intellij plugin, Eclipse plugin 等等不同的三方插件了。

API

举个非常简单的🌰:

1  import React from 'react'
2  
3  class **TodoApp** extends React.Component {
4    static propTypes = {
5      **todos**: React.PropTypes.string
6    }
7 
8    render() {
9      return (
10       **<ul>**
11       **{ todos.map(todo => <li>{ todo.name }</li>) }**
12       **</ul>**
13     )
14   }
15 }
16 

这个16行的 React 类里,其实真正需要我们写的,只有打了星号的部分,仅3行 + 2个变量名,也就是 类名、传入参数、组件 render 方法真正要做的事,其他的什么 class xxx extends React.Componentrender() 等都是 ES6+React这个技术栈本身所需要的骨架结构,完全可以一键生成;map 是实现过程中使用到的循环结构;html 这些,甚至可以用 emmet 这样的工具插件来完成。emmet 这个工具其实也是一样的思想,HTML 的标签都是模板,尽量生成就好,手撸个啥,HTML 页面真正需要你写的,就是把传入的数据展示出来,如是而已。

实际产出 / (实际产出 + 框架代码 + 基本编程结构) 这个公式来看,写一个16行的类,不产生直接价值、可通过模板生成的代码有75%。

好在,在 React 上,现在真的有 Intellij 插件完成这个事情了。剩下我们自己真正做的,真的就只有对输入的处理逻辑,这是我们最应该专注的地方。

@jkvim
Copy link

jkvim commented May 23, 2017

嗯嗯,写的代码越多,发现要重复的地方越多,例如 import { xx } from 'xx', 或者每次写一个新的组件的时候都需要 import React from 'react', 等等。现在的编辑器应该都支持 code snippet 的功能了,我在 vim 上也有用过,一些 IDE 支持在新建某种类型的文件时候,生成对应 template 代码。为了帮助大家快速启动项目,也有一些脚手架工具,例如 create-react-app, 帮助我们生成基本的框架。一些成熟的框架,会通过提供可配置的功能,帮助我们快速完成功能,而不需要写一堆 bolierplate code。

“我们的工作,其实就是运用调配这些框架代码、编程结构,从原始的输入数据处,产生正确的输出。” -- 通过对代码逻辑的归类和总结,得到的这个结论倒是没有想到过,棒棒的

@EthanLin-TWer
Copy link
Owner Author

EthanLin-TWer commented May 23, 2017

@jkvim 哎,你说我怎么就忘了 create-react-app~ 对,这是快速启动项目的脚手架,也应该补充到 issue 里去。

这个插件可以生成 React 相关的 template 代码:https://github.com/Minwe/jetbrains-react 。我去搜搜有没有 redux 的。。。

@jkvim
Copy link

jkvim commented May 23, 2017

哈哈 感觉更高层次的工作,是以代码为数据生成代码,如模板引擎,编译器,解释器等

@EthanLin-TWer
Copy link
Owner Author

补一个:还有项目本身相关的编程结构,比如数据库存取、API 请求发送、以及特定技术栈在项目上的定制等。需要了解项目时留意。大坑。

@EthanLin-TWer
Copy link
Owner Author

image

@JimmyLv
Copy link

JimmyLv commented Jun 17, 2017

SICP 只看过两章的人都觉得,受益匪浅

@kenpusney
Copy link

@JimmyLv
...前两章其实也就是本科都教过的内容啊,重点在第四章后面,那些才是“computation”。

@EthanLin-TWer
Copy link
Owner Author

@kenpusney 毕业论文想研究 Java 反射。结果发现它里面有一章元编程,并且我根本看不懂

@JimmyLv
Copy link

JimmyLv commented Jul 4, 2017

@kenpusney 原谅我本科没学过,😂

@EthanLin-TWer EthanLin-TWer removed this from the Iteration 5: Supreme❗ milestone Aug 10, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants