####OOCamp Day1

  • Tasking 做tasking的标准是,这个task具备可测试性
  • 封装 对一个类的属性的读取,修改都在该类的上下文,那么这个类就没有封装泄露。 tell, don’t ask

####OOCamp Day2 使用自定义对象而不是java原生对象,更加容易适应需求变化

####OOCamp Day3

  • 什么是重构? 不改变功能的情况下改变代码的架构,重构的时候可以随时停止
  • 如何识别bad smell? 如果有一个子类,没有比父类更多的状态,那么这其实一个strategy模式
  • 如何证明代码被改进了? 把一个badsmell经过重构变成了一个pattern,或者bad smell消失了,那么代码就是被改进了。
  • 什么是Pattern? Pattern是一类问题及该类问题的解决方案。使用Pattern很容易,关键是正确地识别出问题, 而问题一般都表现为一个bad smell。例如下面几个problem以及解决这些bad smell所使用pattern:
    class explosion Decorator
    object creation is dependent on outside Factory

####OOCamp Day4
重构

  • 重构技巧:copy & paste => extract method & inline method
  • 代码中,什么是其组成的最小单元? 功能
  • 要有足够的bad smell支撑你来做重构

####OOCamp Day5 一个很难发现的bad smell: 上下文分散, Pattern:Strategy,把业务逻辑放到更加集中的类里

####OOCamp Day6 架构:

  • 什么是架构?
    软件架构回答了以下两个问题:
    1. 系统中有哪些组件
    2. 组件之间如何交互
  • 架构只有有了应用场景,才是有意义的

  • 五种常用的架构:
    单体: Singleton,最简单的架构
    黑板:模块之间的地位平等, 广播消息
    分层:上层把下层当做抽象机器, 拒绝跨层. 大多数问题都可以通过引入一个分层来解决, 但这通常都会带来新的问题.
    数据流:过滤器
    微核:分成平台和核. 带来的问题是隐性知识增多,一个典型的例子就是spring.

DRY:
DRY的代价是耦合, 绝大部分是值得的, 有些时候,需要故意引入重复来消除耦合.
DRY隐含了知识管理成本
note: 没有任何好的软件实践是不需要代价的.

Mock:
当我们提起Mock时,实际上在不同的上下文中,有着不同的含义。
如果你想测试的代码依赖一个尚未实现的外部接口,你需要“mock”这个外部接口,让其按照约定的行为工作, 然后测试你的程序,这时候,“mock”是一种技术。如果你写了了一个实现了这个外部接口的‘mock’ class,在这个class中返回假的数据以支撑你的测试,这时候,“mock”是一种“mock framework”。

当然,在实际开发过程中,你一般不需要自行实现一个“mock framework”,有太多的mock framework供你选择, easymock,jmock, mockito等等。

几种常见的mock手段:
fake, stub, dummy, mock

Q:什么时候决定了当前在用mock?
A:call verify, 在此之前,都是在stub.

State based testing:
内容实现不稳定时,采用基于状态的测试, 用stub即可。
Interaction based testing:
在明确系统的行为边界时,需采用基于交互的测试,需要使用mock来验证代码的行为。

Git save snapshot in each commit rather than store the delta

##Local operations:## Three states:
###modified modified but not adding to git local database Working directory

###staged modified and ready to add to git local database Staging area

###commited data safely stored in local database Git repository

##Git config you can put git config file in the following places:

  • /etc/gitconfig
  • ~/.gitconfig
  • /.git/config

you can show your git configs by

  • git config –list

##Open Class## 给予了你为class增加方法的能力,但是也如同打开了潘多拉魔盒,一旦通过Open Class增加了class方法导致重名问题,将很难定位。

##Instance variable## 和Java不同,Ruby中的instance_variable 与class之间没有直接联系,你可以从一个class创建不同实例,并且各自拥有不同的instance variable. (What’s the purpose?)

##Method## Ruby中,method保存在class中

##Object## 一个object是一组instance variable以及这个object所属的class的引用.

##Class## Ruby中,所有的class都是类Class的instance object. class是一个Class的实例、一组instance method、一个到super class的引用.

##Differences between Class and Module## Module is meant to be included (or mixined). Module can be used as namespace. Class is meant to be initlized or inherinted.

##Dynamic Methods## ruby中,可以在class定义时通过define_methods动态地定义方法, 如下代码动态地为class Computer添加了三个方法 mouse, cpu, keyboard:

class Computer
	def initialize(computer_id, data_source)
	  @id = computer_id
	  @data_source = data_source
	end

  def self.define_component(name) 
	define_method(name) {
  		info = @data_source.send "get_#{name}_info", @id
	    price = @data_source.send "get_#{name}_price", @id 
      "#{name.to_s.capitalize}: #{info} ($#{price})" 
	}
  end

  define_component :mouse
  define_component :cpu
  define_component :keyboard
end

##Method Missing## ruby中,当尝试对receiver调用一个不存在的方法时,该receiver的method_missing方法会被调用,利用这一特性,可以通过重载 method_missing实现动态定义属性、方法效果, 通过method missing机制定义出来的方法被称为Ghost Method。 例如:

class Computer
  def initialize(computer_id, data_source)
    @id = computer_id
    @data_source = data_source
  end

  def method_missing(name, *args)
    info = @data_source.send("get_#{name}_info", args[0])
    price = @data_source.send("get_#{name}_price", args[0])
    "#{name.to_s.capitalize}: #{info} ($#{price})"
  end
  
  #重写respond_to会使利用method_missing实现的动态方法与实际定义的方法无异
  def respond_to?(method)
    @data_source.respond_to?("get_#{method}_info") || super
  end
end

这些通过method_missing机制创建出来的methods被称为ghost method.

##Flat Scope## 在ruby中,classmodule,def被称为scope gate,当程序遇到这几个关键字时,程序的scope就会发生变化,如果需要在scope之间共享变量,则可以使用Class.new代替classmodule, Module#define_method代替def,如:

my_var = 12
MyClass = Class.new do
  # my_var is visiable here
  ...
  define_method :my_method do
    # my_var is visiable here
  end
end

##Object#instance_eval()## 改变self的值为指定实例,同时改变“current class”为当前实例的eigenclass, 在此实例上下文中执行一个block

##Module#class_eval() or Module#module_eval()## 改变self的值为指定实例,同时改变“current class”为当前方法的receiver,在此实例上下文中执行一个block

##Deferred Evaluation## 定义一个block,proc,lambda,然后在其他地方调用此block,proc,lambda,这就叫做Deferred Evaluation

##Singleton Method## 单独给一个object instance定义的method,称之为singleton method

class methods可以认为是一个class对象的singleton method

##Class Macro## class macro看起来像是关键字,但是实际上就是普通的方法,但是这些方法常在声明定义class中使用。

##Eignclass## 对象除了有一个其被创建时声明的那个class外,还会有它自己的一个不可见的,特殊的class,这个class被叫做eigenclass,也被称为singleton class。一个对象的singleton method就存在于这个对象的eignclass上,eignclass的superclass是这个对象的对外呈现的那个class(参考下面的示例代码)。

class Duck
	#code omited
end
#Duck就是a_duck对外呈现的class
a_duck = Duck.new

通过下面的语法,你可以进入到一个对象的eignclass内部

class << obj
  # you are in the eigen class scope.
end

或者可以通过下面的语法获取对eignclass的引用

metaclass = class << matz; self; end

###Scope changing class Person #self is the class object Person class « self #self is the eignclass of class object Person def species “Homo Sapien” end end end

Person.instance_eval do
  #method will be defined on eignclass	of class object `Person`
  #but self is the class object `Person`
  def species
	"Homo Sapien"
  end
   
  self.name #=> "Person"
end

###给对象的eignclass增加singleton方法:

#给对象增加singleton方法
matz = Object.new
def matz.speak
  "Place your burden to machine's shoulders"
end

#给类增加singleton方法(class methods)
class Person
end

def Person.speak 
  "Place your burden to machine's shoulders"
end

##Class Extension Mixin

module M
  def included(clazz)
	clazz.extend ClassMethods
  end

  #定义在这个内部module里的方法会变成inclusor的class method
  module ClassMethods
	def a_class_method
    end
  end
end

第一次出国,所有的事儿都是新鲜的,难免有点忐忑,幸运的是,在机上邻座的是一个话多的澳洲土耳其裔姑娘,告诉我在澳洲如何入境,应该注意什么,该如何填写入境卡,到了墨尔本应该去哪些景点应该去。 到了墨尔本,Luke带我熟悉道路,去Yarra河旁边看风景,Tan带我去吃烤鸡,参加MelbourneJS组活动。Herry带我去吃越南餐,这里有全世界各地的食品,而我也尽量保持每天吃饭的不重样,来之前我妈对我吃不习惯的担心完全是多余的。

##天气## 墨尔本的天看起来很低,似乎站在楼顶就触手可及了,而且始终是那么的蓝。还有一个特点就是:有时候你可以在一天内有四个季节的体验。

Sky of Melbourne</img>

##Social## 个人的social技能还是不行,到了一个陌生的地方始终放不开觉,始终担心在某个方面冒犯了别人。本来海拔就低,来到这儿就像是到了巨人国,跟大多数人说话都得仰着头,有个UX竟然高达两米,没去打篮球真是可惜了了。相比之下,Tan就很值得我学习,与周围人都很聊得开,而且,在解决问题时,始终让人感觉很耐心,给新人以安全感。

##VIM## 从David教我VIM,到现在能够比较自如得使用,也就不到俩月。兴趣是最好的老师。

###MelbJS### Tan 带我去参加一次Melbourne JS的活动,来自不同公司的技术达人在一起分享工作中的心得,Melbourne的的开源氛围真得不错。

与Java,C#,Ruby中”class-based”继承机制不同,javascript是一种”prototype-based”的继承机制。 关于prototype-based和class-based的区别,我想通过一个例子来描述下:
你是一个陶艺师,我给你一个图纸,说:”照着这个图纸的样子帮我做5个罐子”,于是你照着图纸上描述的形状,颜色,材质做出5个,这就是class-based 的模式

我拿给你一个罐子,说:”照着这个样子帮我做个罐子”,于是你参照这个罐子的形状,颜色,材质做出5个,你就是采用了prototype-based 的模式。

####class based OO 我们再来看一段class-based 面向对象语言的代码示例:

class Animal
  private String name
  public Animal(String name)
  {
  this.name = name;
  }
  public void run(){
    ...
  }
}
  class Wolf extends Animal
{
  public void hunt ()
  {
    ...
  }
}

class Wolf继承自class Animal拥有了run技能,并且扩展了自己的hunt技能。

####prototype based OO 下面我们来看看一段prototype-based面向对象语言的代码示例:

    function Animal(name)
    {
      this.name = name;
      this.run = function () {
        console.log(this.name + " is runing")
      }
    }

    function Wolf(name)
    {
      this.name = name;
      this.hunt = function () {
        console.log(this.name + " is hunting")
      }
    }
    //继承的魔法在这里显现
    Wolf.prototype = new Animal();
    var someone = new Animal("Some one");
    var wolf = new Wolf("Wolf");
    someone.run();
    wolf.run();
    wolf.hunt();
    //should got exception here
    someone.hunt();

在这里,把function Wolf的prototype设置为一个Animal的实例,当尝试调用wolf上的run方法时,由于Wolf中没有run方法,于是javascript解释器会查找Wolf的prototype(一个Animal的实例)是否有run方法,如果有,则调用此方法,如果没有,则尝试调用此实例的prototype上的run方法,如此持续下去,直到找到这个run方法或者到达继承顶部 - Object.prototype。这就是基于”prototype-chain”的继承机制。

再附上同事Sheldon画的javascript中常见对象的关系图:
<img src=’http://winsonwq.github.com/ppt/resources/images/JavaScriptObjectsRelation.jpg’ width=’800’, heigth=’600’></img> 点击这里看大图.