用费曼技巧学编程,香不香?

引子

 有一本讲诺贝尔奖得到者,物理学家费曼的书,叫作《发现的乐趣》,书中写到一个费曼小时候的故事:java

 “咱们家有《大不列颠百科全书》,我仍是小孩子的时候,父亲就经常让我坐在他腿上,给我读些《大不列颠百科全书》。好比说,咱们读关于恐龙的部分,书上可能讲雷龙或其余什么龙,书上会说:“这家伙有 25 英尺高,脑壳宽 6 英尺。” 程序员

这时父亲就停下来,说:“咱们来看看这句话什么意思。这句话的意思是:假如它站在咱们家的前院里,它是那么高,高到足以把头从窗户伸进来。不过呢,它也可能遇到点麻烦,由于它的脑壳比窗户稍微宽了些,要是它伸进头来,会挤破窗户。 编程

费曼说:凡是咱们读到的东西,咱们都尽可能把它转化成某种现实,从这里我学到一个本领——凡我所读的内容,我总设法经过某种转换,弄明白它究竟什么意思,它到底在说什么。框架

 

费曼技巧

 

费曼技巧,或者说费曼学习法是一种以教促学的方法,一共有四步(已经知道的能够无视,直接跳过): 编程语言

(1) 选择新概念/新知识, 本身先去学习它。 微服务

(2) 伪装当一个老师,去教授别人 学习

想象你面对一群小白,怎么把这个概念讲给他们听,让他们理解呢? this

把你讲解的思路也写到纸上,若是实在不想写,能够说出来。 spa

很是重要!!!不要让你的思路停留在大脑中,由于大脑中对于知识点之间的关联会有些想固然的、错误的假设,说出来或者写出来能找到这些“盲点”!!线程

 

(3) 若是你在教授的过程当中遇到了麻烦,卡了壳,返回去学习。 

从新去看书,搜相关资料,问别人,倒逼本身把这个概念搞清楚, 而后回到第二步,继续给小白讲授。

 

(4) 简化你的语言。 

目标是用你本身的语言,非专业的词汇去解释这个概念。尽可能作到简单直白,或者找到比喻来表达。 

很是简单的过程,对吧? 

 

实战演练

咱们来用个例子来演练一下,有请码农翻身头号主人公张大胖出场。 

张大胖正在学习Java,这一天他遇到了一个新的概念:“动态代理”  (注意是学习这个概念,不是具体实现), 很是抽象,在平常编程中几乎不会直接使用,理解起来有难度。

 

第一步,自学

 张大胖看了动态代理的介绍,书上列举出一堆烦人的代码来展现这个东西是怎么使用的,好比有个接口(IHelloWorld)及其实现类(HelloWorld), 而后有个InvocationHandler的实现,最后用Proxy.newProxyInstance(....)建立一个新的类出来,这些都是什么鬼?啰里啰唆的。

 

第二步,张大胖尝试教一下小白(固然这里的小白至少得懂点儿Java)

 

张大胖:动态代理嘛,很简单,就是给定一个接口和实现类,再加上一个InvocationHandler , 动态代理这个技术能够在运行时建立一个新的代理类出来。 

小白:张老师, 新的代理类有什么用? 

张大胖:举个例子,有个叫IHelloWorld接口及其实现类HelloWorld,它有一个叫sayHello()的方法。能够在sayHello()以前和以后,额外加一些日志的输出。 

(在讲解一个概念的时候,举例和类比很重要,人类习惯于经过例子来学习,从具体走向抽象) 

小白:那我直接写一个新的类,好比HelloWorldEx,把日志输出添加到其中不就好了,为何还要用Proxy.newProxyInstance(......)这么麻烦的方法?

public class HelloWorldEx implements IHelloWorld{
    IHelloWorld hw;
    public HelloWorldEx(IHelloWorld hw){
        this.hw = hw;
    }    
    public void sayHello(){        
        Logger.startLog();
        hw.sayHello();
        Logger.endLog();
    }
}

  

张大胖没法回答这个问题,卡壳了! 

第三步,回过头去看书,学习。

书中也没有解释,唉! 

仔细想想,手动写一个类HelloWorldEx和用Proxy.newProxyInstance来建立,区别究竟是什么? 

实现的功能是相同的,可是HelloWorldEx须要事先写好,编译后不能改了,至关于写死了!若是我想对Order类,Employee类,Department类,也想加点儿日志,还得写个OrderEx,EmployeeEx,DepartmentEx的类,太麻烦了! 

而Proxy.newProxyInstance这种方法,能够在程序运行的时候为任意类动态地建立加强的类。 

事先写死的叫作静态代理,Proxy.newProxyInstance这种方式叫作动态代理,更加灵活。 

张大胖以为这么解释就通了。 

小白:为何要建立新的代理类,那个Proxy.newProxyInstance不能直接修改老的HelloWorld类吗? 

张大胖再度卡壳,上网搜索,找到了答案,和Python,Ruby等方法不一样,Java本质是一个静态类型的语言,class一旦被装入JVM,是不能修改,添加,删除方法的,既然老的class不能修改,只能经过代理的方式来建立新的类了。 

小白:懂了,这个技术主要用在什么地方啊? 难道只是加个日志? 

张大胖第三次卡壳,只好再次搜索。 

原来动态代理使用得最多的是AOP,AOP中常常会以声明的方式提出这样的要求: 

某个包下全部add开头的方法,在执行以前都要调用Logger.startLog()方法,在执行以后都要调用Logger.endLog()方法。 

或者对于全部以Service结尾的类,全部的方法执行以前都要调用tx.begin(),执行以后都要调用tx.commit(), 若是抛出异常的话调用tx.rollback()。

 

到此为止,张大胖能够这样来给小白讲述了: 

你不是用过Spring AOP吗?AOP中常常有这样的需求......  ,Spring想添加这些日志和事务的功能,可是却没有办法去修改用户的类,它是框架啊,一是不知道用户类的源码,二是Java不容许再修改装载入JVM的class。 

没办法,Spring只好在运行时找到用户的类,而后操做字节码动态建立一个新类,新类会对原有的类进行加强,添加日志,事务这些功能,注意啊,这些都是在内存中动态建立的。 

这个技术就是Java的动态代理,不过它有个前提要求,就是用户的类须要实现接口才行。我用一个简单的例子给你说下,你就明白细节了......

 

第四步,简化,比喻

上面的讲解从文字上来讲仍是很是啰嗦的,用了很大篇幅来说解“为何”,由于理解了why ,剩下的就是细节了。  

若是你完全理解了之后,动态代理的技术细节会在大脑中会创建这么一幅图景:

 

$HelloWorld100就是那个代理类,它和HelloWorld都实现了IHelloWorld这个接口。 

若是必定要用个比喻来讲,它们俩就是“兄弟关系”,CgLib提供了另一种对现有类加强的办法,动态生成的类继承了现有的类,二者是“父子关系”。

  

小结

 怎么样?用这种(伪装)教授别人,层层递进、自我逼问的方法是否是颇有效果?收益很大?  

用这种办法,实际上就是逼着你把大脑中的盲点和一些想固然的假设给暴露出来,效果要比单纯地阅读和记忆好得多,赶忙在学习中试一下吧!

  

更多精彩文章,尽在码农翻身

 

我是一个线程

TCP/IP之大明邮差

一个故事讲完Https

CPU 阿甘

Javascript: 一个屌丝的逆袭

微服务把我坑了

如何下降程序员的工资?

程序员,你得选准跑路的时间!

两年,我学会了全部的编程语言!

一直CRUD,一直996,我烦透了,我要转型

字节码万岁!

上帝托梦给我说:一切皆文件

Node.js :我只须要一个店小二

相关文章
相关标签/搜索