0%

上周末在北京参加了 QCon 会议,是自己第一次参加,学到了很多东西,大大开拓了眼界,一直忙没来的及总结,这篇以及后面的几篇都是对这次会议上自己感兴趣的东西的总结,在这里分享一下。

上海贝尔的敏捷转型之旅

讲了 5 个转型故事,可能因为我也是处于相似的环境下,听得好累 :-)

  • 自上而下改革,领导更替,组织调整,意见分歧,传言惑众;
  • 高速中换轮胎,"黑暗"力量卷土重来,"敏捷不搞了";
  • 大师一席话胜读 10 年书,大师的话真的这么重要吗? 答案是的确重要;
  • 祝福的人少,挑刺的人多,自以为是的咨询师…

整个 session 最让我印象深刻的是,说中间换了个领导,然后让人觉得敏捷好像不搞了,然后自己怎么怎么跟领导谈,让领导支持,甚至是公司有的团队使用了 agile,却不让他写到案例中,要悄悄搞。

Read more »

align-regexp

相必大家都用过 C-M-\,一般都能满足需要,可是有时候需要按一行中的某些字符对齐,比如一些变态的语言或者编程规范规定赋值语句需要按 "=" 对齐,那怎么办?

align-regexp 使用起来只需要选中需要对齐的 region,然后执行,输入需要匹配的正则表达式即可。

比如如下代码:

1
2
3
int var = 2;
int variable_is_kinda_long = 3;
int var_is_less_long = 4;
Read more »

StackOverflow 上有人问除了 HIG 外使用 Objective-C 以及 Cocoa 还有什么好的工程实践,果然是抛砖引玉,很多好的 practices 和 tips 一一跃然纸上,摘抄一些:

1> 使用 properties,不用 "_" 前缀。

2> 把 private 方法的定义移到 .m 文件,如下:

1
2
3
4
5
6
7
8
#import "MyClass.h"

@interface MyClass ()
- (void) someMethod
- (void) someOtherMethod
@end

@implementation MyClass

Objective-C 的方法没有像 Java 那样的 private 或者 public 属性,如果需要设置方法为 private,一般采用 category 来对方法进行隐藏。

Read more »

之前学 elisp 的时候一直感觉思维转不过来很纠结,看了 The Nature of Lisp,原来正如 Code Complete - Laying the Foundation 章节讲的那样,我们认识新事物总是会借鉴思维里面已有的 Metaphor, 我只用过 C, C++, Java,Python, Objective-C, 也就意味着我基本只有这些语言的 metaphor,都跟 Lisp 差异很大,也难怪了。但也正因为如此,才需要不断的克服自身的排斥心理,去接触更多的新事物。

正如书中所云:

A software metaphor is more like a searchlight than a road map. It doesn’t tell you where to find the answer, it tells you how to look for it. A metaphor serves more as a heuristic than it does as an algorithm.

接触的新事物越多,积攒起来的 metaphor 就越多,“本能” 的触类旁通便也会越频繁,很多科学上的新发现都是把不相干的事物触类旁通的引用到自身领域而突然使人茅塞顿开的。

该文章从 XML 着手,对于这样一个函数

Read more »

对 TDD 不了解的同学可参考 Test-driven development

本文使用的 Objective-C 单元测试框架是 OCUnit ,最新的 Xcode 已经包含。

TDD 的步骤如下:

  1. 写一个测试某个功能的单元测试用例;
  2. 运行,测试失败;
  3. 编码实现功能;
  4. 运行单元测试,通过修改代码,直到测试成功;
  5. 重构代码;
  6. 重构单元测试用例;
  7. 重复 1。

其中 5、6 是可选步骤,有必要了才会进行,但是必须保证产品代码和单元测试用例不能同时被更改。

Read more »

上一篇提到过,第二级 alloc 在分配大于 128 bytes 的时候,直接使用第一级 alloc,如果小于 128 bytes 才采用内存池的方式进行内存分配。

分配过程是这样的,每次分配一大块内存,存到一个 free list 中,下次 client 若再有相同大小的内存要求,就直接从这个 free list 中划出,内存释放时,则直接回收到对应的 list 中。为了管理的方便,实际分配的大小都被调整为 8 的倍数,所以有 16 个 free lists,分别为 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128 bytes。例如需要 20 bytes,将会被自动调整为 24 bytes。free lists 的结构如下

1
2
3
4
5
6
7
8
9
10
11
enum {_ALIGN = 8};
enum {_MAX_BYTES = 128};
enum {_NFREELISTS = 16}; // _MAX_BYTES/_ALIGN

union _Obj {
union _Obj* _M_free_list_link;
char _M_client_data[1]; /* The client sees this. */
};

private:
static _Obj* __STL_VOLATILE _S_free_list[_NFREELISTS];

为了节省内存使用,使用 union 结构,这个设计很巧妙,每一个元素(内存区域对象)即可以当作下一个元素的指针,例如后面代码中的 result -> _M_free_list_link,也可以当作该元素的值,例如 *__my_free_list。整个 free lists 的结构便是一串使用后者的元素构成的节点,每个节点的值是使用前者构成的单向链表的首地址。

首先来看 allocate 的过程

Read more »

在分析了对象的构建和析构之后,我们接着看对象构建所基于的内存空间是如何分配和释放的。这一功能是由 stl_alloc 提供的。之前提到过 allocate,在 SGI STL 中是不使用的,因为其只是对 new 和 delete 进行了简单的封装,并且加上了这段代码

1
set_new_handler(0);

这个函数用来指定如果内存分配失败时的 callback 函数,定义如下

1
2
typedef void (*new_handler)();
new_handler set_new_handler(new_handler p) throw();

使用时参数传入 NULL(0) 则表示卸除 new_handler,也就意味着如果 ::operator new 分配内存失败,则会抛出 std::bad_alloc 类型的异常。

Read more »

在做单元测试过程中,经常需要对被测程序的一些函数实现 stub,下面三个文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// product.c
#include <stdio.h>
void lib_pro()
{
printf("I'm in lib\n");
}
// user.c
int main(int argc, char *argv[])
{
lib_pro();
return 0;
}
// stub.c
#include <stdio.h>
void lib_pro()
{
printf("I am in fake lib\n");
}

product.c 为产品代码提供 lib_pro 函数,user.c 为使用者,可以当作 UT 测试函数,stub.c 提供 lib_pro 函数的另一个定义。

通常,为了使用 stub,需要在测试时将 user.c 产生的 user.o 和 stub.c 产生的 stub.o 链接在一起,这样,每当要给某一个文件加 stub 时,都需要替换链接,有没有什么办法可以自动进行这一工作,如果有 stub,就链接 stub,如果没有,就链接产品代码。

当然有,

Read more »