从实践总结而来_编程精粹书评-查字典图书网
查字典图书网
当前位置: 查字典 > 图书网 > 编程 > 编程精粹 > 从实践总结而来
Wuqifu 编程精粹 的书评 发表时间:2012-05-30 20:05:10

从实践总结而来

原书写于1992年,内容基于作者在Microsoft工作期间编写C语言无错代码的经验之谈,这是一本从实践总结而来的编程书籍,章节不多,但很值得一读!可惜的是,本书出版于二十年前没能与时俱进推出后续更新版本。

看的是电子版,记录下读书笔记:
你必须养成经常询问怎样编写代码的习惯,本书就是长期坚持询问一些简单问题所得的结果。
我怎样才能自动检测出错误?
我怎样才能防止错误?
这种想法和习惯是帮助我编写无错代码呢还是妨碍了我编写无错代码?

编写直观的代码才是真正的聪明人。
重要的是养成好的习惯和正确的态度。
除非关系产品的成败,否则不要整理代码 --> 这点与现在主流的重构、敏捷开发方法论背道而驰。
不要实现没有战略意义的特征
错误既不会自己产生,也不会自己改正。
不能“以后”再修改错误,这是许多产品被取消的共同教训。
修改错误要治本,不要治表
不要实现没有战略意义的特征
不允许没有必要的灵活性
测试代码的责任不在测试员身上,而是程序员自己的责
决不允许同样错误出现两次
使程序在调用点明了易懂;要避免布尔参数
关心局部效率是不值得的。如果你很注重效率的话,请集中于全局效率和算法的效率上,这样你才会看到努力的效果。


编码检查表
─一 你是否将编译程序的警告都处理了?
── 你的代码是否未用Lint
─一 你的代码进行了单元测试吗?
─一 你是否逐步通过了每一条编码路径以观察数据流?
── 是否重构过了任何代码?如果是,修改处经过彻底测试了吗?
── 程序维护人员是否能够理解你的代码?

─一 是否用断言证实了函数参数的有效性?
─一 是否使用断言警告可能出现的非常情况?
─一 代码中是否有未定义的或者无意义的代码?
─一 你在代码中是否作过任何假设?
── 代码中是否有稀奇古怪的行为?
── 代码有不必要的灵活性吗?你能消除它们吗?
─一 函数是否小并容易测试?
─一 在调用点你的函数是出易读?
─一 你的函数是否有布尔量输入?

─一 此特征是否符合产品的市场策略?
─一 是否评审了你的接口,它能保证难于出现误操作吗?

── 错误无法消失,是否能找到错误的根源?
─一 是修改了错误的真正根源,还是仅仅修改了错误的症状?

书中出现的部分代码:
1, 用户自己定义宏ASSERT的方法:
#ifdef DEBUG
    void _Assert(char* , unsigned); /* 原型 */
#define ASSERT(f)
    if(f)
        NULL;
    else
        _Assert(__FILE__ , __LINE__)
#else
    #define ASSERT(f) NULL

_Assert在标准错误输出设备stderr上打印一条错误消息,然后中止:
#endif
void _Assert(char* strFile, unsigned uLine)
{
    fflush(stdout);
    fprintf(stderr, “nAssertion failed: %s, line %un”,strFile, uLine);
    fflush(stderr);
    abort();
}

2, 要使用断言对函数参数进行确认。
/* memcpy ─── 拷贝不重叠的内存块 */
void* memcpy(void* pvTo, void* pvFrom, size_t size)
{
    byte* pbTo = (byte*)pvTo;
    byte* pbFrom = (byte*)pvFrom;
    ASSERT(pvTo != NULL && pvFrom != NULL);
        /* 内存块重叠吗?如果重叠,就使用memmove */
    ASSERT(pbTo >= pbFrom + size || pbFrom >= pbTo + size);
    while(size-->0)
        *pbTo++ == *pbFrom++;
    return(pvTo);
}

3,/* UnsToStr—一将无符号值转换为字符串 */
void UnsToStr(unsigned u,char *str)
{
        char *strStart = str;
        do {
                *str++ = (u % 10) + '0';
        } while((u /= 10) > 0);
        *str = '';

        ReverseStr(strStart);
}

void UnsToStr(unsigned int u, const char *str)
{
        char strDigits[6];
        char *pch;
        /* u超出范围了吗?使用UlongToStr… */
        ASSERT(u <= 65536);
        pch = &strDigits[6];
        *pch = '';
        do {
                *--pch = u % 10 + '0';
        }while((u /= 10) > 0);

        strcpy(str,pch);
}

char* strcpy(char* pchTo, const char* pchFrom)
{
        char* pchStart = pchTo;
        while(*pchTo++ = *pchFrom++)
                NULL;
        Return(pchStart);
}

4,/* memset ─── 用“byte”的值填充内存 */
void* memset(void* pv, byte b, size_t size)
{
        byte* pb = (byte*)pv;
        while(size-- > 0)
                *pb++ = b;
        return(pv);
}

/* strdup ─── 为一个字符串建立副本 */
char* strdup(const char* str )
{
        char* strNew;
        strNew = (char*)malloc( strlen(str)+1 );
        strcpy( strNew, str );
        return( strNew );
}

char* CopySubStr(char *strTo, const char* strFrom, size_t size)
{
        char* strStart = strTo;
        ASSERT( strTo != NULL && strFrom != NULL );
        ASSERT( size <= strlen(strFrom) );
        while( size-- > 0 )
                strTo++ = strFrom++;
        *strTo = '';
        reurn (strStart);
}

char tolower(char ch)
{
        ASSERT( ch >= ‘A’ && ch <= ‘Z’);
        return( ch + ‘a’-‘A’);
}

void *memchr(void *pv, unsigned char ch, size_t size)
{
        unsigned char *pch = (unsigned char *)pv;
        while(size-- > 0)
        {
                if(*pcd == ch)
                        return(pch);
                pch++;
        }
        return(NULL);
}

展开全文
有用 3 无用 0

您对该书评有什么想说的?

发 表

推荐文章

猜你喜欢

附近的人在看

推荐阅读

拓展阅读

对“从实践总结而来”的回应

boiyee 2012-07-06 23:56:25

nod, 关心局部效率是不值得的