忠忠的新百宝袋

做人要厚道

Archive for April, 2008

The Pragmatic Programmer

Posted by Kai on 27th April 2008

We want to see pride of ownership.”I wrote this, and I stand behind my work.” Your signature should come to be recognized as an indicator of quality. People should see your name on a piece of code and expect it to be solid, well written, tested, and documented. A really professional job. Written by a real professinal.

A pragmatic Programmer.

It took me a month to finish this book. I gotta say, this one deserves your time.

This book is the reason why I started learning Perl, Learn a text manipulation language, so said the pragmatic programmer.

Compared with lot technology books i’ve read, this one is just like talking about philosophy. Well, it’s right. We programmers consider too much about detailed techonlogy, other than how to be a reliable engineer.

pragmatic programmer

Posted in books, tech | No Comments »

学习Perl感慨设计模式的代价

Posted by Kai on 25th April 2008

这几天学了Perl,然后看懂了The Pragmatic Programer上从元数据生成结构代码那个题目的答案。有一些感慨。

我的程序使用C++,一共380行。见一个生成代码的小练习

书上的Perl答案,一共52行。短到以至于我可以把代码贴在这里。

论通用性,well,我有的通用性他的代码也有。OO不是复用的唯一手段。它甚至不是最容易最方便的手段。

我的解法是设计模式的初学者常犯的错误,把一个不需要使用设计模式的问题做的太复杂。

Perl程序使用模块来实现换语言,产生一种新语言的工作量和我的答案差不多。

learning perl

PS:Learning Perl(中文名:Perl语言入门)是很好的适合Perl入门的一本书,又称小骆驼书(因为比大骆驼书薄)。如果你是Perl初学者,选这本没错。但是如果你想精通Perl,去看大骆驼书。

Perl语法里面我最喜欢的是倒装语法。

open INFILE,”< filename.txt” or die “can not open file.”;(live or die语句)

print “I do” if &you_would_like_to;(条件倒装语句)

print “I have to do” unless &you_have_to.

这些句子在Perl里是合法的语句。酷吧!

Perl是至今为止我见过的最酷的语言。

Posted in books, tech | No Comments »

Eclipse ECIP Debugger blocked by Firewall

Posted by Kai on 23rd April 2008

我使用的Eclipse,3.3版本,Perl,5.10版本,ECIP0.66版本,PadWalker1.7版本,但是就是不能调试。今天搞了几个小时。

刚刚把防火墙关掉,发现一下子就可以调试了。又经过半个小时的折磨,在防火墙里面找到一个“Enable Secure Port Technology”的复选框,选上就没事了。

郁闷了一下午。差点就转到Python阵营去了。

weblog

Posted in perl, tech | No Comments »

超赞的电影:阳光小美女

Posted by Kai on 22nd April 2008

赞那,赞那,赞那,大赞那。

特别是最后奥莉弗的那段热舞秀,简直是点石成金之笔,化腐朽为神奇。

神作!

最后的音乐是You Can’t Touch This,很老也很俗的一首歌,不过配合当时的情况很适合。

little Miss sunshine

Posted in movie | No Comments »

毕设过程8——更好的光照

Posted by Kai on 18th April 2008

光照使用了负责的Phong模型(其实我认为Phong模型和Gouraud模型的差别是计算方法不是光照模型)。另外使用更另一种新的比较自然的颜色,得到的效果也提升了很多。

 

cadaver-Data(4-18-2008)_Time(16-7-25)_968

光照模型里带有高光参数,很多地方只是随便的设个参数,看这还可以就过了。

我考虑我的光线合成或者模糊运算的方法可能有错,因为在原本黄色的颜色上添加了一些白色的条条。

我还顺便添加了根据计算机的配置自动选择最合适的分辨率的功能,其实很简单,就是二分搜索到我需要的FPS为止,也好快,如果设FPS目标是10的话,大概1秒不到就能搞找到合适的分辨率。

Posted in c++, tech | No Comments »

C++的有趣而罕见的特性:局部类

Posted by Kai on 14th April 2008

昨天看《C++设计新思维》,看到C++有个很有趣但是很少有人用的新特性,局部类。

就是可以在函数里面定义一个类,这个类在函数外面无法访问到。

这样,配合模板就可以在常用的循环里面很方便的做出for_each循环的效果。

因为如果使用自己定义的数据结构,要使用for_each循环就得自己定义迭代子,而且在迭代器模式中,尽管有迭代子的帮助,共有的循环控制代码还是重复了。

比如:

iterator it = vector::begin();
while(it != vector::end())
{
    //do something
   it = it->next;
}

在这种模式下,对容器的遍历被抽象为迭代子的步进,但是如果需要多个处理,while循环还是要写很多次。

现有的一个方法是使用std::for_each模板,通过

std::for_each(vector::begin(), vector::end(), DoSomethingClass());

这样需要建立一个DoSomethingClass的类。

可惜C++不像Java和C#一样有匿名类的机制,那么一般的解决方法就是在外部建立一个DoSomethingClass的类。然而这样处理就向外界暴露了这个类,使得程序接口更加复杂。

在我的程序中,有这样一个功能:

for(int x = 0 ; x < x_Max; ++x)
{
    for(int y = 0 ; y < y_Max; ++y)
    {
        for(int z = 0 ; z < z_Max; ++z)
        {
            DoSomeThing();
        }
    }
    ShowProceedBar();
}
Refrush();

在好几个函数中我都有这种循环,唯一的区别就是DoSomeThingA(), DoSomeThingB(),…,这样三重循环的代码就被重复了好几次。重复是代码罪恶的源头。

而对于一个三重循环,要实现stl的iterator接口可能有点复杂。

现在可以用一个漂亮的解决方法。

首先建立一个模板函数:

template<typename Functor>
void DoEach(Functor func)
{
    for(int x = 0 ; x < x_Max; ++x)
    {
        for(int y = 0 ; y < y_Max; ++y)
        {
            for(int z = 0 ; z < z_Max; ++z)
            {
                func();
            }
        }
        ShowProceedBar();
    }
    Refrush();
}

然后根据我的需要,在原来的诸多函数的基础上,比如说:

void DoA( for…for…for (…DoSomeThingA())… );
void DoB( for…for…for (…DoSomeThingB())… );
void DoC( for…for…for (…DoSomeThingC())… );
void DoD( for…for…for (…DoSomeThingD())… );

在DoX()函数里面建立局部类,把原来的操作代码封装到局部类的operator()的定义里面去。因为局部类只在函数内部有效,所以不用担心名字冲突的问题。像这样:

void DoA()
{
    class Func
    {
    public:
        void operator()()
            {
                DoSomeThingA();
            }
    };
    DoEach(Func());
}

void DoB()
{
    class Func
    {
    public:
        void operator()()
            {
                DoSomeThingB();
            }
    };
    DoEach(Func());
}

因为class定义是在编译时处理,所以DoX在运行时实际的代码只有

void DoA()
{
    DoEach(Func());
}
void DoB()
{
    DoEach(Func());
}

 

相当于在外部定义了DoX_Functor。但是,得益于局部类的名称局部性控制,使得对与调用DoX函数的外部代码,DoX_Functor完全透明。

新的代码比原来的代码优雅,因为邪恶的重复循环代码只有一处。另外,对于DoX系列函数的调用者,什么都没有改变。可以认为我只是在函数内部做了调整,以达到减少重复的目的。实际上,在我的程序里,DoEach模板是私有成员模板函数,类的接口没有变化。

———————————————————————————–

刚刚在修改我的程序的时候发现了更酷更漂亮的做法,那就是搭配使用宏,来简化一些琐碎的工作。

#define For__Each(code); class Func \
        { \
        public: \
                void operator()() \
                { \
                        code \
                } \
        }; \
        DoEach(Func());

然后在DoA里面,只要写
void DoA()
{
        For__Each(
                DoSomeThingA();
        );
}
就可以了。

Posted in c++, tech | 1 Comment »

一个生成代码的小练习

Posted by Kai on 11th April 2008

在《程序员修炼之道》里面看到了这个题目:

Exercises 13:

Generating code from a language-neutral representation. In the input file, lines starting with ‘M’ flag the start of a message definition, ‘F’ lines define fields, and ‘E’ is the end of the message.

# Add a Product
# to the ‘no-order’ list
M AddProduct
F id    int
F name    char[30]
F order_code int
E

Generate C:

typedef struct {
    int    id;
    char    name[30];
    int    order_code;
} AddProductMsg;

Generate Pascal:

{ Add a Product }
{ to the ‘no-order’ list }
AddProductMsg = packed record
    id:        LongInt;
    name:        array [0..29] of char;
    order_code:        LongInt;
end;

今天我花了接近3个小时做这个程序,顺便练习一下最近学的设计模式。

下面是我的类图:

TargetFamily

这是输出用的类,其中使用了模板方法,工厂方法模式。

TypeFamily

这是字段的类型类,因为数组类型和原子类型输出不同,所以分开,这里也许应该用访问者模式。

CallSequence

这是调用顺序图,Type和Meta都必须通过工厂TypeResolver和MetaResolver产生实例,Type的虚礼析构函数向堆中释放自身。

其中我不满意的地方有:

1. 使用了protected访问控制,在Type的构造函数里面。protected是丑陋的。

2. 使用了friend class机制,以让工厂类能够访问MetaStrut和AtomType,ArrayType。friend机制是丑陋的。如果我做另外一个什么DerivedType,我必须在这个DerivedType里面再声明friend class,这就使得不能完全解耦。

第一个,如果Type不允许实例化的话,我也可以把Type的函数做成纯虚函数,这样就不需要使用protected保护Type了。

第二个,我没想到好的解决办法。我不能让MetaStrut、AtomType和ArrayType可以在栈上被实例化。为了使用多态,简单工厂返回的是基类的指针,所以不可以使用栈对象。使用堆对象的话,又必须在析构函数里面调用delete this。从而就不能有栈对象的存在,为了防止其他函数使用建立栈对象,我就想到把构造函数设成Private。这样建立对象的唯一机会就是在简单工厂里面,可以保证都是堆对象。

一下是我的程序的输出:

/* Add a Product */
/* to the ‘no-order’ list */
typedef struct {
    int    id;
    char    name[30];
    int    order_code;
} AddProductMsg;

{ Add a Product }
{ to the ‘no-order’ list }
AddProductMsg = packed record
    id:        LongInt;
    name:        array [0..29] of char;
    order_code:        LongInt;
end;

// Add a Product
// to the ‘no-order’ list
class AddProductMsg
{
public:
    int    id;
    char    name[30];
    int    order_code;
};

PS:这次做程序的过程中,我使用了Refactor!Pro来重构代码,使用了Extract Method,感觉很不错,这次的代码我看着也觉得有点漂亮。可惜我的Refactor!Pro是体验版,还有10天就到期了。另外,我决定以后一定要学会用flex,自己处理字符串既费时又没有意义。

Posted in c++, tech | No Comments »

耳朵小恙

Posted by Kai on 11th April 2008

左边耳朵上星期感觉闷闷的,今天去医院检查,说是耳道被耳屎堵住了。于是医生用很专业的工具,在我左耳里面夹出来豌豆一样巨大的一块耳屎,超恐怖啊。

医生说,还好你耳道比较大,刚刚那个同学耳道小,夹的费劲死了。

另外,左耳被发现有中耳炎现象,郁闷。也不知是进水还是因为上次拔牙弄伤的。

还有,用棉签掏耳朵的时候一定要轻轻的掏,搞不好会把耳屎推进耳道深处,进而容易把耳道堵住。

Posted in Uncategorized | No Comments »

重构:改善及有代码的设计

Posted by Kai on 3rd April 2008

昨天看完了《重构》,来发点读后感。

我觉得《重构》一书写的最好的是第一章,所以如果有谁感兴趣又没有那么多时间,花上1个小时琢磨一下第一章也能有很大收获的。

后面的章节我觉得作者更多的是从理论上讲重构过程中的步骤,过于细节,没有必要。须知,现在如果工程里面做重构,大都会借助自动重构工具。而大部分读者是不会去做一个自动重构工具的,所以中间章节实用价值不大。最后几章对于看过《设计模式》的人来说,也无多大作用。如果没看过《设计模式》,我想可能会有点帮助。

正如作者说所,GoF的《设计模式》指出了编码的方向,而重构告诉程序员具体的实现方法。所以,如果不看《设计模式》相关的书,光看《重构》效用也很局限。

今天在网上找到了《重构》作者的网站,还有一个叫做重构的网站。Refacting

本想找个免费好用的C++自动重构工具,但是木有发现。有个叫做Refactor!Pro的Visual Studio插件挺不错,但是不免费,而且很贵,要99美刀。Refactor!Pro有体验版,可以免费用大概1个月左右。最新的版本是3.0,已经支持VS2008了,所以我今天试用了一下,感觉很不错,界面漂亮的像Visual Studio一样。

相比较C++程序员的苦恼,Java程序员就舒服的多了。免费IDE Eclipse里面就有现成的Refacting工具,而且功能很多很强大。据说是因为C++的语法太复杂了,不能想Java那么容易的解释,所以没有重构方面没有Java发展的快。

Posted in books, tech | No Comments »

关于重构:Java比C++幸福

Posted by Kai on 3rd April 2008

Eclipse里面,在使用Java的时候有一个好功能:Refactoring

Refacting for Java

而在C++项目里面,Refactoring菜单后面只有一个蹩脚的Rename

Refacting for C

真羡慕Java程序员。

找到一个重构的网站:http://www.refactoring.com/

这个网站是《重构》一书的作者Martin Fowler所主持的,可以说是重构领域的民间官方网站。

里面提到几个C++重构工具,但相比Java重构工具来,功能少多了。

是的,C++很复杂。

Posted in java, tech | No Comments »

 
FireStats icon Powered by FireStats