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

meta programing ruby读书笔记

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

In Melbourne

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

天气

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

Sky of Melbourne</img>

Social

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

VIM

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

MelbJS

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

prototype based 继承机制

与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”的继承机制。