??xml version="1.0" encoding="utf-8" standalone="yes"?>久久99精品久久久久久,精品综合久久久久久888蜜芽,久久777国产线看观看精品http://www.shnenglu.com/wanghaiguang/category/19460.html逆水行舟Q不q则退zh-cnTue, 20 May 2014 16:44:51 GMTTue, 20 May 2014 16:44:51 GMT60E序员需要具备的基本技能(转蝲Q?/title><link>http://www.shnenglu.com/wanghaiguang/archive/2013/11/28/204491.html</link><dc:creator>王v?/dc:creator><author>王v?/author><pubDate>Thu, 28 Nov 2013 03:55:00 GMT</pubDate><guid>http://www.shnenglu.com/wanghaiguang/archive/2013/11/28/204491.html</guid><wfw:comment>http://www.shnenglu.com/wanghaiguang/comments/204491.html</wfw:comment><comments>http://www.shnenglu.com/wanghaiguang/archive/2013/11/28/204491.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/wanghaiguang/comments/commentRss/204491.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/wanghaiguang/services/trackbacks/204491.html</trackback:ping><description><![CDATA[<p style="margin: 0px 0px 10px; padding: 0px; color: #555555; font-family: Arial, Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 22px;">软g开发是一个跨度很大的技术工作,在语a斚wQ有CQC++QJavaQRuby{等{等Q在环境斚wQ又分嵌入式Q桌面系l,企业U,W(xu)EBQ基pȝQ或是科学研I。但是,不管是什么的情况QL有一些通用的基本职业技能?/p><p style="margin: 0px 0px 10px; padding: 0px; color: #555555; font-family: Arial, Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 22px;">q些最基本的职业技能通常军_了一个程序员的别,能否用好q些技能,直接关系CE序员的职业生(dng)。很多程序新手也是因为缺、达不到或是不熟(zhn)在q些基本技能,所以,他们需要有老手带,需要努力补齐这些技能。而高U程序员应该非常熟?zhn)q些基本技能,而且有能力胜dƈ带领其他l验不的程序员?/p><p style="margin: 0px 0px 10px; padding: 0px; color: #555555; font-family: Arial, Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 22px;">下面q些基本职业技术可以用来做为对一个程序员的评伎ͼ很明显,下面的这些技能都可以用来做面试。虽?dng)q有很多非技术的因素Q但对于评估一个程序员的技术能力来_(d)其应该是_的了?/p><p style="margin: 0px 0px 10px; padding: 0px; color: #555555; font-family: Arial, Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 22px;">下面是程序员所应该具备的基本职业技能:(x)</p><p style="margin: 0px 0px 10px; padding: 0px; color: #555555; font-family: Arial, Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 22px;"></p><table border="0" cellspacing="0" style="background-color: #ffffff; border: 2px solid #cccccc; border-collapse: collapse; margin: 5px 0px 10px; color: #555555; font-family: Arial, Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; font-size: 14px; line-height: 22px;"><tbody><tr><th width="20%" style="border: 1px solid #cccccc; padding: 3px 10px; vertical-align: top; background-color: #edeff0;">基本技?/th><th width="80%" style="border: 1px solid #cccccc; padding: 3px 10px; vertical-align: top; background-color: #edeff0;">技能描q?/th></tr><tr><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">阅读代码</td><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">q个技能需要程序员能够具备L已经存在的代码的能力Q这L(fng)能力可以让程序员分析E序的行为,了解E序Q这h能和开发团队一起工作,l承l护或是改进现有的程序?/td></tr><tr><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">~写E序</td><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">~写E序q不包括E序设计。不要以为编E是一件很单的事情Q很多程序员都认为编E只需要懂得程序语a的语法,q把设计实现可以了。但是这ȝ写程序还q远不够Q用什么样的编码风格成为编写程序员最需要具备的基本技能。能否用非常良好的~程风格直接军_了程序员的别?/td></tr><tr><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">软g设计</td><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">q一能力直接军_了需要吏用什么样的代码技术达到怎么L(fng)功能Q而系l架构设计直接决定了软g的质量、性能和可l护性。ƈ不是所有的E序在这一斚w都非怼UQ但每个E序员都需要或多或的明白和掌握这一基本技能?/td></tr><tr><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">熟?zhn)软g工程</td><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">每个E序员都应该明白软g工程是什么东西,都应该知道,需求分析,设计Q编码,试QRelease和维护这几个阶段。当?dng)几乎所有的人都知道q些东西Q但q不是每个h都很清楚q些东西。现在很多高U程序员都会(x)h“需求规D明书FS”?#8220;概要设计HLD”。另外,E序员还需要知道一些Y件开发的Ҏ(gu)论,比如Q敏捷开发或瀑布模型?/td></tr><tr><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">使用E序库或框架</td><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">一个程序员需要学?x)用已有的代码Q无论是标论的程序库Q或是第三方的,q是自己公司内部的,都需要学?x)做。比如:(x)C++中,需要学?x)用STLQMFCQATLQBOOSTQACEQCPPUNIT{等。用这些东西,可以让你的工作事半功倍?/td></tr><tr><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">E序调试</td><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">E序调试是分析BUG和解决问题最直接的能力。没有h能够保证E序写出来不用调试就可以q行正常Q也没有人可以保证程序永q不?x)出BUG。所以,熟练使用调试器是一个程序员需要具备的基本技能?/td></tr><tr><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">使用IDE</td><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">学会(x)使用IDE工具也会(x)让你的工作事半功倍。比如,VC++QEmacsQEclipse{等Qƈ要知道这些IDE的长处和短处?/td></tr><tr><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">使用版本控制</td><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">一定要学会(x)使用版本控制工具Q什么叫mainline/trunkQ什么叫tagQ什么叫branchQ怎么做patchQ怎么merge代码Q怎么reverseQ怎么利用版本控制工具l护不同版本的Y件。这是程序员需要明的的软g配置理中最重要的一块?/td></tr><tr><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">单元试</td><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">单元试是每个程序都需要做的。很多单元测试也是需要编码的。一定要学会(x)在xUnit框架下进行单元测试。比如JUnit, NUnit, CppUnit{等?/td></tr><tr><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">重构代码</td><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">每个E序员都需要有最基本的能力去重构目前已有的代码,使代码达到最优但却不能媄(jing)响Q何的已有的功能。有一本书叫《Y件的重构》,每个E序员都应该M下?/td></tr><tr><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">自动化编?/td><td style="border-style: solid; border-color: #cccccc; padding: 3px 10px; vertical-align: top;">E序员需要用一个脚本,其能自动化编E所有的工程和代码,q样Q整个开发团队可以不停地集成代码Q自动化试Q自动化部vQ以?qing)用一些工兯行静态代码分析或是自动化试?/td></tr></tbody></table><p style="margin: 0px 0px 10px; padding: 0px; color: #555555; font-family: Arial, Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 22px;">当然Q还有很多的基本技术也是非帔R要的Q比如,与h的沟通能力,语言的表达能力,写作能力Q团队协作能力,适应变化的能力,旉理能力Q多d处理能力Q自我学?fn)能力,故障处理能力Q等{,{等Q这里只是列举了和技术相关的能力Q这些是E序最最最基本的能力,只要是程序员必需要有的能力?br /><br />本文转自Q?a style="font-family: verdana, 'courier new'; line-height: 21px;">http://coolshell.cn/articles/428.html</a></p><img src ="http://www.shnenglu.com/wanghaiguang/aggbug/204491.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/wanghaiguang/" target="_blank">王v?/a> 2013-11-28 11:55 <a href="http://www.shnenglu.com/wanghaiguang/archive/2013/11/28/204491.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VS2010调试W记http://www.shnenglu.com/wanghaiguang/archive/2013/05/22/200536.html王v?/dc:creator>王v?/author>Wed, 22 May 2013 09:57:00 GMThttp://www.shnenglu.com/wanghaiguang/archive/2013/05/22/200536.htmlhttp://www.shnenglu.com/wanghaiguang/comments/200536.htmlhttp://www.shnenglu.com/wanghaiguang/archive/2013/05/22/200536.html#Feedback0http://www.shnenglu.com/wanghaiguang/comments/commentRss/200536.htmlhttp://www.shnenglu.com/wanghaiguang/services/trackbacks/200536.html1?/strong>今天调试一个demoQ发现如下错误?/span>

1>  pȝ找不到指定的文g?/span>
1>C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: The command "copy D:\WL_SDK_LAN_C++_20130521\demo\c++\Debug\Sample.exe D:\YuanTuo_1\wulianSDK\wulian_sdk_sample\SDK\Sample.exe
1>C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: :VCEnd" exited with code 1.

可以修改下面属性:(x)


 

2?/span>VS2010~译错误Q?/span>

fatal error C1189: #error : This file requires _WIN32_WINNT to be #defined at least to 0x

fatal error C1189: #error :  This file requires _WIN32_WINNT to be #defined at least to 0x0403. Value 0x0501 or higher is recommended.


下面是彻底解x法:(x)
在工E的stdafx.h中添加(如有cM语句Q需注释掉)
#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later.
#define WINVER 0x0501 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
#endif

#ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later.
#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
#endif

#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
#define _WIN32_WINDOWS 0x0501 // Change this to the appropriate value to target Windows Me or later.
#endif

#ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later.
#define _WIN32_IE 0x0601 // Change this to the appropriate value to target IE 5.0 or later.
#endif


]]>
从一道面试题来阐释一个普遍的认知误区Q{载)http://www.shnenglu.com/wanghaiguang/archive/2013/04/18/199537.html王v?/dc:creator>王v?/author>Thu, 18 Apr 2013 03:03:00 GMThttp://www.shnenglu.com/wanghaiguang/archive/2013/04/18/199537.htmlhttp://www.shnenglu.com/wanghaiguang/comments/199537.htmlhttp://www.shnenglu.com/wanghaiguang/archive/2013/04/18/199537.html#Feedback0http://www.shnenglu.com/wanghaiguang/comments/commentRss/199537.htmlhttp://www.shnenglu.com/wanghaiguang/services/trackbacks/199537.html   解释以下语句的含义:(x)
         1
?/span>new A;
         2
?/span>new A();    
   也许很多人包括我自己Q都可以马上l出W一U情늚{案Q在堆上?/span>Acd配内存,然后调用A的构造函数。这U说法被大家所熟知Q因为包括?/span>STL源码剖析》等大作在内也都是这么写的(但是你认U说法完全正吗Q?/span>其实不尽?dng){案后面揭晓)
    W二U情况,对象构造的时候初始化列表为空?x)和W一U有什么不同呢Q对于这U在实际工程中很用的情况Q我一时还真给不出切的答案?/span>
   |上搜了一下,看到CSDN里面q有专门针对q个问题的一个帖子(原帖链接 http://bbs.csdn.net/topics/320161716Q?/span>
   好像最l也没有可以信服的答案,认同度比较高的是q样的说法:(x)
加括可用没有参数的构造函敎ͼ不加括号调用默认构造函数或唯一的构造函敎ͼ看需?/span>Q?/span>peakflys注:(x)q种说法是错误的Q答案后面揭晓)
   既然没有特别靠谱的答案,不如自己动手扑և{案?/span>
   构造以下示例:(x)

/**
 *\brief example1 difference between new and new()
 *\author peakflys
 *\data 12:10:24 Monday, April 08, 2013
 
*/

class A
{
public:
    int a;
};

int main()
{
    A *pa = new A;
    A *paa = new A();
    return 0;
}

查看main函数的汇~代?/span>(~译器:(x)gcc (GCC) 4.4.6 20120305 (Red Hat 4.4.6-4) )

int main()
{
  4005c4:   55                      push   %rbp
  4005c5:   48 89 e5                mov    %rsp,%rbp
  4005c8:   48 83 ec 10             sub    $0x10,%rsp
    A *pa = new A;
  4005cc:   bf 04 00 00 00          mov    $0x4,%edi
  4005d1:   e8 f2 fe ff ff          callq  4004c8 <_Znwm@plt>         //调用new
  4005d6:   48 89 45 f0             mov    %rax,-0x10(%rbp)           //rax寄存器内容赋l指针pa(rax寄存器里是new调用产生的A对象堆内存地址)
    A *paa = new A();
  4005da:   bf 04 00 00 00          mov    $0x4,%edi
  4005df:   e8 e4 fe ff ff          callq  4004c8 <_Znwm@plt>         //调用new
  4005e4:   48 89 c2                mov    %rax,%rdx                      //rax的内Ҏ(gu)入rdxQ执行之后,rdx里存攄x通过new A()产生的内存地址
  4005e7:   c7 02 00 00 00 00       movl   $0x0,(%rdx)                 //把rdx内存指向的内容赋?|xA::a赋gؓ(f)0
  4005ed:   48 89 45 f8             mov    %rax,-0x8(%rbp)             //rax寄存器内容赋l指针paa(rax寄存器里是new()调用产生的A对象堆内存地址)
     return 0;
  4005f1:   b8 00 00 00 00          mov    $0x0,%eax
}
  4005f6:   c9                      leaveq 
  4005f7:   c3                      retq
    通过上面产生的汇~代?/span>(?/span>AT&T汇编不熟(zhn)的可以看注?/span>)可以很容易看出,new A()的执行,在调用完operator new分配内存后,马上Ҏ(gu)分配内存中的对象使用0值初始化Q?/span>new A 仅仅是调用了operator new分配内存Q?/span>
   是不是这样就可以下结?/span> new A()?/span>new A多了一步,卛_始化对象的步骤呢Q?/span>
   我们再看看下面这U情况:(x)

/**
 *\brief example2 difference between new and new()
 *\author peakflys
 *\data 12:23:20 Monday, April 08, 2013
 
*/

class A
{
public:
    A(){a = 10;}
    int a;
};

int main()
{
    A *pa = new A;
    A *paa = new A();
    return 0;
}

   q种情况是类昄提供含默认值的构造函数?/span>
   查看汇编实现如下Q?/span>

int main()
{
  4005c4:   55                      push   %rbp
  4005c5:   48 89 e5                mov    %rsp,%rbp
  4005c8:   53                      push   %rbx
  4005c9:   48 83 ec 18             sub    $0x18,%rsp
    A *pa = new A;
  4005cd:   bf 04 00 00 00          mov    $0x4,%edi
  4005d2:   e8 f1 fe ff ff          callq  4004c8 <_Znwm@plt>
  4005d7:   48 89 c3                mov    %rax,%rbx
  4005da:   48 89 d8                mov    %rbx,%rax
  4005dd:   48 89 c7                mov    %rax,%rdi
  4005e0:   e8 2d 00 00 00          callq  400612 <_ZN1AC1Ev>
  4005e5:   48 89 5d e0             mov    %rbx,-0x20(%rbp)
    A *paa = new A();
  4005e9:   bf 04 00 00 00          mov    $0x4,%edi
  4005ee:   e8 d5 fe ff ff          callq  4004c8 <_Znwm@plt>
  4005f3:   48 89 c3                mov    %rax,%rbx
  4005f6:   48 89 d8                mov    %rbx,%rax
  4005f9:   48 89 c7                mov    %rax,%rdi
  4005fc:   e8 11 00 00 00          callq  400612 <_ZN1AC1Ev>
  400601:   48 89 5d e8             mov    %rbx,-0x18(%rbp)
    return 0;
  400605:   b8 00 00 00 00          mov    $0x0,%eax
}
  40060a:   48 83 c4 18             add    $0x18,%rsp
  40060e:   5b                      pop    %rbx
  40060f:   c9                      leaveq 
  400610:   c3                      retq 

   上面的汇~代码就不在d注释了,因ؓ(f)两种操作产生的汇~代码是一L(fng)Q都是先调用operator new分配内存Q然后调用构造函数?/span>
   上面的情况在VS2010下验证是一L(fng)情况Q有兴趣的朋友可以自己去看,q里׃再脓(chung)?/span>VS2010下的汇编代码了?/span>
   通过上面的分析,对于
new A?/span> new A() 的区?/span>Q我们可以得Z面的l论Q?/span>
      
1、类体含有显C适合地默认构造函数时Q?/span>new A?/span>new A()的作用一_(d)都是首先调用operator new分配内存Q然后调用默认构造函数初始化对象?/span>
     2、类体无昄构造函数时Q?/span>new A()首先调用operator new来ؓ(f)对象分配内存Q然后用空值初始化对象成员变量Q?/span>new A仅仅是调?/span>operator new分配内存Q对象的成员变量是无意义的随机|  Q?/span>peakflys注:(x)对于基本数据cdQ如int{?/span> 适用此条Q?/span>
   注意刎ͼ现在很多书籍?/span>new操作W的说明都存在纰漏,例如?/span>STL源码剖析》中2.2.2节中有以下的描述Q?/span>


事实证明Q?/span>new Foo的操作是否有构造函数的调用是不定的,具体要看FoocM里是否有昄构造函数的出现?/span>

/*****************************************华丽分割U?/span>**************************************
补充Q刚才发玎ͼ?/span>C++PrimerW四?/span>5.11节中Q已l有了对?/span>new A()的说明:(x)

   We indicate that we want to value-initialize the newly allocated object by following the type nameby a pair of empty parentheses. The empty parentheses signal that we want initialization but arenot supplying a specific initial value. In the case of class types (such as string) that define their own constructors, requesting value-initialization is of no consequence: The object is initialized by running the default constructor whether we leave it apparently uninitialized orask for value-initialization. In the case of built-in types or types that do not define any constructors, the difference is significantQ?/span>

     int *pi = new int;         // pi points to an uninitialized int 

     int *pi = new int();       // pi points to an int value-initialized to 0 

In the first case, the int is uninitialized; in the second case, the int is initialized to zero.
   q里l出的解释和上面自己分析?/span>new A()的行为是一致的?br />
/***************************************再次华丽分割U?/span>************************************
鉴于上面的结论是通过GCC?/span>VS2010得出的,而且有朋友也提出同样的质疑,Z定q种l果是否是编译器相关的,刚才Ҏ(gu)查看了一?/span>C++的标准化文档?/span>
摘自Q?/span>ISO/IEC 14882:2003(E) 5.3.4 - 15
— If the new-initializer is omitted:
      — If T is a (possibly cv-qualified) non-POD class type (or array thereof), the object is default-initialized(8.5). If T is a const-qualified type, the underlying class type shall have a user-declared default constructor.
      — Otherwise, the object created has indeterminate value. If T is a const-qualified type, or a (possibly cv-qualified) POD class type (or array thereof) containing (directly or indirectly) a member of const-qualified type, the program is ill-formed;
— If the new-initializer is of the form (), the item is value-initialized (8.5);

所以可以确定,q种情况完全是编译器无关?/span>(当然那些不完全按照标准实现的~译器除?/span>)?/span>
但是通过上面标准化文档的描述Q我们可以看出文中对new A在无昄构造函数时的ȝq不是特别准,鉴于很多公司都有q道面试?/span>(撇去q些题目的实际考察意义不说)Q我们有必要再补充一下:(x) 对于new A: q样的语句,再调用完operator new分配内存之后Q如?/span>AcM内含?/span>PODcdQ则PODcd的成员变量处于未定义状态,如果含有?/span>PODcd则调用该cd的默认构造函数。?/span> new A()在这些情况下都会(x)初始化?/span>
   PSQ估计很多公司的正确{案“ 也不一定正吧?/span>

 

本文转自Q?/span>http://www.shnenglu.com/peakflys/archive/2013/04/08/199208.html

 



]]>
敏捷软g开?/title><link>http://www.shnenglu.com/wanghaiguang/archive/2013/04/17/199514.html</link><dc:creator>王v?/dc:creator><author>王v?/author><pubDate>Wed, 17 Apr 2013 09:13:00 GMT</pubDate><guid>http://www.shnenglu.com/wanghaiguang/archive/2013/04/17/199514.html</guid><wfw:comment>http://www.shnenglu.com/wanghaiguang/comments/199514.html</wfw:comment><comments>http://www.shnenglu.com/wanghaiguang/archive/2013/04/17/199514.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/wanghaiguang/comments/commentRss/199514.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/wanghaiguang/services/trackbacks/199514.html</trackback:ping><description><![CDATA[<span style="font-family: Verdana; font-size: 12pt;">来源于《敏捯Y件开?#8212;—原则、模式与实践?/span><br /><br /><span style="font-size: 12pt; line-height: 26px; text-indent: 28px; background-color: #ffffff; font-family: Verdana;">常见的设计的臭味——腐化软g的气?/span><span style="font-size: 12pt; line-height: 26px; text-indent: 28px; background-color: #ffffff; font-family: Verdana;">?/span><br /><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; margin: 0cm 0cm 0pt 21pt; text-indent: -21pt;"><span style="font-family: Verdana; font-size: 12pt;">l<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">         </span></span><span style="font-family: Verdana; font-size: 12pt;">僵化性(</span><span style="font-family: Verdana; font-size: 12pt;">Rigidity</span><span style="font-family: Verdana; font-size: 12pt;">Q:(x)很难对系l进行改动,因ؓ(f)每个改动都会(x)q许多对系l其他部分的其他改动?/span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; margin: 0cm 0cm 0pt 21pt; text-indent: -21pt;"><span style="font-family: Verdana; font-size: 12pt;">l<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">         </span></span><span style="font-family: Verdana; font-size: 12pt;">脆弱性(</span><span style="font-family: Verdana; font-size: 12pt;">Fragility</span><span style="font-family: Verdana; font-size: 12pt;">Q:(x)对系l的改动?x)导致系l中和改动的地方在概念上无关的许多地方出现问题?/span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; margin: 0cm 0cm 0pt 21pt; text-indent: -21pt;"><span style="font-family: Verdana; font-size: 12pt;">l<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">         </span></span><span style="font-family: Verdana; font-size: 12pt;">牢固性(</span><span style="font-family: Verdana; font-size: 12pt;">Immobility</span><span style="font-family: Verdana; font-size: 12pt;">Q:(x)很难解开pȝ的纠l,使之成ؓ(f)一些可在其他系l中重用的组件?/span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; margin: 0cm 0cm 0pt 21pt; text-indent: -21pt;"><span style="font-family: Verdana; font-size: 12pt;">l<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">         </span></span><span style="font-family: Verdana; font-size: 12pt;">_滞性(</span><span style="font-family: Verdana; font-size: 12pt;">Viscosity</span><span style="font-family: Verdana; font-size: 12pt;">Q:(x)做正的事情比做错误的事情要困难?/span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; margin: 0cm 0cm 0pt 21pt; text-indent: -21pt;"><span style="font-family: Verdana; font-size: 12pt;">l<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">         </span></span><span style="font-family: Verdana; font-size: 12pt;">不必要的复杂性(</span><span style="font-family: Verdana; font-size: 12pt;">Needless Complexity</span><span style="font-family: Verdana; font-size: 12pt;">Q:(x)设计中包含有不具M直接好处的基l构?/span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; margin: 0cm 0cm 0pt 21pt; text-indent: -21pt;"><span style="font-family: Verdana; font-size: 12pt;">l<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">         </span></span><span style="font-family: Verdana; font-size: 12pt;">不必要的重复Q?/span><span style="font-family: Verdana; font-size: 12pt;">Needless Repetition</span><span style="font-family: Verdana; font-size: 12pt;">Q:(x)设计中包含有重复的结构,而该重复的结构本可以使用单一的抽象进行统一?/span></p><p style="background-color: #ffffff; margin: 0cm 0cm 0pt 21pt; text-indent: -21pt;"><span style="color: #333333; font-family: Verdana; line-height: 26px; font-size: 12pt;">l<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">         </span></span><span style="color: #333333; font-family: Verdana; line-height: 26px; font-size: 12pt;">晦ӆ性(</span><font color="#333333" face="Arial"><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">Opacity</span></font><font color="#333333" face="宋体"><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">Q:(x)很难阅读、理解。没有很好的表现出意图?br /><br /></span></font><span style="font-size: medium; line-height: 26px; text-indent: 28px; font-family: Verdana;">敏捷设计是一个过E,不是一个事件。它是一个持l的应用原则、模式以?qing)实跉|改进软g的结构和可读性的q程。它致力于保持系l设计在M旉都尽可能得简单、干净以及(qing)富有表现?/span><span style="font-size: medium; line-height: 26px; text-indent: 28px; font-family: Verdana;">?/span><br /><br /></p><div><span style="line-height: 26px; font-size: 12pt; font-family: Verdana;"><strong>敏捷软g开发宣aQ?/strong></span><span style="line-height: 26px;"><strong><br /><br /></strong></span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">我们正在通过亲n实践以及(qing)帮助他h实践Q揭C更好的软g开发方法。通过q项工作Q我们认为:(x)</span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;"><strong>个体和交?胜过 q程和工?/strong></span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;"><strong>可以工作的Y?胜过 面面俱到的文?/strong></span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;"><strong>客户合作 胜过 合同谈判</strong></span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;"><strong>响应变化 胜过 遵@计划</strong></span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">虽然右项也具有h(hun)|但我们认为左具有更大的价倹{?/span></div><div><span style="font-family: 宋体; font-size: medium; line-height: 26px; text-indent: 28px; background-color: #ffffff;">敏捷开发强调以Zؓ(f)中心Q而不是以q程Z心,?yu)可能的沟通(与客P与团队成员)Q尽可能C最单的设计解决问题Q从而能够拥抱变化)?/span><span style="line-height: 26px;"><br /></span></div><br /><div><span style="line-height: 26px; font-size: 12pt; font-family: Verdana;"><strong>敏捷宣言遵@的原?/strong></span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">我们遵@以下原则Q?/span></div><p> </p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong style="font-family: Verdana; font-size: 12pt;">1。我们最优先要做的是通过早的、持l的交付有h(hun)值的软g来客户满意?/strong></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">   规划q代故事时必L照优先安排Qؓ(f)客户先提供最有h(hun)值的功能。通过频繁q代能与客户形成早期的良好合作,?qing)时反馈提高产品质量。敏捷小l关注完成和?付具有用户h(hun)值的功能Q而不是孤立的d。以前我们都用需求规D明书或者用例来~写详细的需求,敏捷使用用户故事来罗列需求。用h事是一U表C需求的 轻量U技术,它没?/span></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">固定的Ş式和强制性的语法。但是有一些固定的形式可以用来参考还是比较有益的。敏捷估中使用了这个模板:(x)“作ؓ(f)【用L(fng)cd】,我希 望可以【能力】以ѝ业务h(hun)倹{?#8220;。用基于用h事的需求分析方法时Q仍可能需要原型和~写文档Q只是工作重Ҏ(gu)多的转移C口头交流?/span></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"> </p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong style="font-family: Verdana; font-size: 12pt;">2。即使到了开发的后期Q也Ƣ迎改变需求。敏捯E利用变化来为客户创造竞争优ѝ?/strong></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">  敏捷q程参与者不怕变化,他们认ؓ(f)改变需求是好事情,因ؓ(f)q些改变意味着我们更了解市场需求?/span><br />  <br /><strong style="font-family: Verdana; font-size: 12pt;">3。经常性的交付可以工作的YӞ交付的间隔可以从几周到几个月Q交付的旉间隔短好?/strong></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">   q代是受实践框限制的Q意味着即攑ּ一些功能也必须按时l束q代。只要我们可以保证交付的软g可以很好的工作,那么交付旉短Q我们和客户协作p 紧密Q对产品质量更有益。虽然我们多ơP代,但ƈ不是每次q代的结果都需要交付给用户Q敏捷开发的目标是让他们可以交付。这意味着开发小l在每次q代?都会(x)增加一些功能,增加的每个功能都是经q编码、测试,辑ֈ了可发布的质量标准的?/span><br /><span style="font-family: Verdana; font-size: 12pt;">  另外敏捷开发项目中对开发阶D|有什么重要的分割Q没有先期的需求阶D,然后是分析阶D,架构设计阶段Q编码测试阶D늭Q在目真正开始后Q每ơP代中都会(x)同时q?/span></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">行所有的上述阶段工作?/span><br /> <br /><strong style="font-family: Verdana; font-size: 12pt;">4。在整个目开发期_(d)业务人员和开发h员必d天都在一起工作?/strong></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">  软g目不会(x)依照之前讑֮的计划原路执行,中间对业务的理解、Y件的解决Ҏ(gu)肯定?x)存在偏差,所以客戗需求h员、开发h员以?qing)涉众之间必进行有意义的、频J?nbsp;</span></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">的交互,q样可以在早期?qing)时的发现ƈ解决问题?/span><br /> <br /><strong style="font-family: Verdana; font-size: 12pt;">5。围l被Ȁpv来的Z来构建项目。给他们提供所需要的环境和支持,q且信Q他们能够完成工作?/strong></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">  业务和技术是引v不确定的二个主要斚wQh是第三个斚w。而业务和技术又必须׃h来执行,所以能够激׃h来解册些问题是解决不确定性的关键。只要个人的目标和团</span></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">队的目标一_(d)我们需要鼓舞v每个人的U极性,以个Zؓ(f)中心构徏目Q提供所需的环境、支持与信Q?/span></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"> </p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong style="font-family: Verdana; font-size: 12pt;">6。在团队内部Q最h效果q且富有效率的传递信息的Ҏ(gu)Q就是面寚w的交谈?/strong></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">  在十几或者二十几个hl成的大团队中,文档是一U比较合适的传递知识和交流的途径。而敏捷团队一般不?x)很多hQ大团队实施敏捷时也?x)分成多个小的敏捷团队)Q所?/span></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">大量的文档交其实ƈ不是很经的做法。此旉寚w的交谈反而更快速有效?/span><br /> <br /><strong style="font-family: Verdana; font-size: 12pt;">7、可工作的Y件是首要q度度量标准?/strong></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">   一般的工作都比较容易衡量Q务进展,比如让你Lq?吨的矛_Q我只要ȝ一下你已经搬运的石头重量就知道你完成多了。而对于Y件来_(d)在Y件没有编 码、测试完</span></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">成之前,我们都不能因Z码编写了多少行,试用例跑了多少个就d量这个功能是否完成了。衡量这个功能是否完成的首要标准是q个功能可以?作了Q对用户来说已经?/span></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">以应用了?/span></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"> </p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong style="font-family: Verdana; font-size: 12pt;">8。敏捯E提可持l的开发速度。责Mh、开发者和用户应该能够保持一个长期的、恒定的开发速度?/strong></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">   很多人都认ؓ(f)软g开发中加班是很正常的,不加班反而不正常Q我Ҏ(gu)有点不理解,q个可能是国情所致吧。敏捯E希望能够可持箋的进行开发,开发速度不会(x) 随着q代的Q务不同而不同,不欣赏所谓的gg能完成的态度Q开发工作不应该是突击行为。我们不能指望说H击q个目后就可以L了,因ؓ(f)完成一个项?后会(x)接踵而来下一个项目,而只要还是拼拼的态度Q下一个项目依旧会(x)让你的组员再ơ突凅R这时不知道有h?x)不会(x)说Q那我们׃直加班,也是“持箋的开发??#8221;啊,q时可要注意了,持箋加班?/span></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">慧导致h疲劳、厌倦,保持长期恒定的速度也只是一U理惌已?/span><br /> <br /><strong style="font-family: Verdana; font-size: 12pt;">9。不断地x优秀的技能和好的设计?x)增强敏捯力?/strong></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">  敏捷q程有很多好的技术实践可以加Z品敏捯力,很多原则、模式和实践也可以增强敏捷开发能力?《敏捯Y件开发-原则、模式与实践》一书中介绍了很多设计,感兴的可以Ml看看?/span><br /> <br /><strong style="font-family: Verdana; font-size: 12pt;">10。简?---使未完成的工作最大化的艺?---是根本的?/strong></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">   我们不可能预期后面需求会(x)如何变化Q所以不可能一开始就构徏一个完的架构来适应以后的所有变化。敏捷团队不?x)去构徏明天的YӞ而把注意力放在如何?q最单的Ҏ(gu)完成现在需要解决的问题。这时有Z(x)_(d)我已l预计到了肯定存在哪些需求扩展点Q我们在一开始是否需要考虑呢?q时团队需要根据自q理解 d定是否考虑Q如果深信在明天发生了这个问题也可以L处理的话Q那么就最好先不考虑?/span><br /> <br /><strong style="font-family: Verdana; font-size: 12pt;">11。最好的构架、需求和设计与自l织的团队?/strong></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">        敏捷中有很多U实践,大家都知道,q代式开发是主要的实跉|法,而自l织团队也是主要的实践之一。在自组l团队中Q管理者不再发h令,而是让团队自w寻找最佳的工作方式来完成工作。要形成一个自l织团队其实比较难。CSDN采访Mishkin Berteig中说?自组l团队的W一个要素就是必L一个团队,而不仅仅是一h。一h是一帮在一起工作的人,他们彼此之间q没有太多的沟通,他们也ƈ不视彼此Z体。项目一开始,我们׃(x)l徏“团队”Q但很多时候由构架师、需求h员、开发h员和试人员l成的是一h而已。他q认为,团队的Ş成必ȝ历几个时期。在 l历了初期的合后,成员才会(x)开始对团队共同的工作理念与文化形成一个基本的认识和理解。团队内?x)逐渐形成规矩Q而且q些规矩是不a而喻的。比如,每个?都知道上午九(ji)Ҏ(gu)上班Q都?x)主动询问别人是否需要帮助,也都?x)去d和别人探讨问题。如果团队成员之间能够达成这L(fng)默契Q那么这个团队将成ؓ(f)一个真正高 效的工作团队。在q样团队中,成员之间怺理解Q工作效率非帔R。在自组l团队中Q团队成员不需要遵从别人的详细指o(h)。他们需要更高层ơ的指导Q这U指 导更像是一个目标,一个致力于开发出更好的Y件的目标。MQ自l织团队是一个自动自发、有着共同目标和工作文化的团队Q这L(fng)团队L在向它的l织做出 承诺。但是,实现q些承诺对于自组l团队来说非帔R要。否则,一旦出现问题,团队成员之间׃(x)出现信Q危机?/span></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br /><span style="font-family: Verdana; font-size: 12pt;">  虽然敏捷开发小l是以小lؓ(f)整体 来工作的Q但是还是有必要指明一些承担一定Q务的角色。第一个角色是产品所有者(Product OwnerQ。品所有者的主要职责包括Q确认小l所有成员都在追求一个共同的目前景Q确定功能的优先U以便L在处理最h价值的功能Q以?qing)作出决?使得寚w目的投入可以产生良好的回报。可以对应ؓ(f)以前开发中?#8220;产品l理”。另一角色是开发团队(developerQ,q里的开发h员包括了架构师、设计师、程序员、需求h员、测试h员、文档编写者等Q有时品所有者也可以被看作是</span></p><p style="color: #362e2b; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana; font-size: 12pt;">开发h员。还有一个重要角色就是项目经理(project managerQ。敏捷开发的目l理?x)更多的x领导而不是管理。在某些目中,目l理可能同时也是开发h员,数时候也?x)担M品所有者?/span><br />   <br /><strong style="font-family: Verdana; font-size: 12pt;">12。每隔一定时_(d)团队?x)在如何才能更有效地工作斚wq行反省Q然后相应地对自q行ؓ(f)q行调整?/strong></p><p style="background-color: #ffffff;"><font color="#362e2b" face="Arial"><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">  ׃很多不确定性因素会(x)D计划失效Q比如项目成员增减、技术应用效果、用户需求的改变、竞争者对我们的媄(jing)响等都会(x)让我们作Z同的反应。 敏捷不是Z预定义的工作方式Q而是Zl验性的方式Q对以上q些变化Q小l通过不断的反省调整来保持团队的敏h?/span></font><br /><br /></p><div><span style="line-height: 26px; font-size: 12pt; font-family: Verdana;"><strong>面向对象设计的原则:(x)</strong></span><span style="line-height: 26px;"><strong><br /><br /></strong></span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">SRP 单一职责原则</span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;"> </span><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">׃个类而言Q应该仅有一个引起它变化的原因?/span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;"></span></div><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; margin: 0cm 0cm 0pt 21pt; text-indent: -21pt;"><span style="font-family: Verdana; font-size: 12pt;">l<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">         </span></span><strong><span style="font-family: Verdana; font-size: 12pt;">单一职责原则</span></strong><span style="font-family: Verdana; font-size: 12pt;">Q?/span><span style="font-family: Verdana; font-size: 12pt;">The Single Responsibility Principle</span><span style="font-family: Verdana; font-size: 12pt;">Q简U?/span><span style="font-family: Verdana; font-size: 12pt;">SRP</span><span style="font-family: Verdana; font-size: 12pt;">Q:(x)׃个类而言Q应该仅有一个引起它变化的原?/span><span style="font-family: 宋体; font-size: 12pt;">。在</span><span style="font-size: 12pt;">SRP</span><span style="font-family: 宋体; font-size: 12pt;">中,我们把职责定义ؓ(f)“变化的原因(Q?#8221;。如果你能够惛_多于一个的动机L变一个类Q那么这个类具有多于一个的职责。Y件设计真正要做的许多内容Q就是发现职</span><span style="font-family: 宋体; font-size: 12pt;">责ƈ把那些职责相互分R?/span><span style="font-family: 宋体; font-size: 12pt;">事实上,</span><span style="font-family: 宋体; font-size: 12pt;">我们要的其余原则都?x)以q样或那L(fng)方式回到q个问题上?/span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; margin: 0cm 0cm 0pt 21pt; text-indent: -21pt;"><span style="font-family: Verdana; font-size: 12pt;">l<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">         </span></span><strong><span style="font-family: Verdana; font-size: 12pt;">开攑ְ闭原?/span></strong><span style="font-family: Verdana; font-size: 12pt;">Q?/span><span style="font-family: Verdana; font-size: 12pt;">The Open-Close Principle</span><span style="font-family: Verdana; font-size: 12pt;">Q简U?/span><span style="font-family: Verdana; font-size: 12pt;">OCP</span><span style="font-family: Verdana; font-size: 12pt;">Q:(x)软g实体Q类、模块、函数等{)应该是可以扩展的Q但是不可以修改?/span><span style="font-family: Verdana; font-size: 12pt;">。遵循开攑ְ闭原则设计出的模块具有两个主要的特征。它们是Q(</span><span style="font-family: Verdana; font-size: 12pt;">1</span><span style="font-family: Verdana; font-size: 12pt;">Q、对于扩展是开攄。这意味着模块的行为是可以扩展的。当应用的需求改变时Q我们可以对模块q行扩展Q其具有满那些改变的新行为。换句话_(d)我们可以改变模块的功能。(</span><span style="font-family: Verdana; font-size: 12pt;">2</span><span style="font-family: Verdana; font-size: 12pt;">Q、对模块行ؓ(f)q行扩展Ӟ不必改动模块的源代码或者二q制代码。模块的二进制可执行版本Q无论是可链接的库?/span><span style="font-family: Verdana; font-size: 12pt;">DLL</span><span style="font-family: Verdana; font-size: 12pt;">或?/span><span style="font-family: Verdana; font-size: 12pt;">Java</span><span style="font-family: Verdana; font-size: 12pt;">?/span><span style="font-family: Verdana; font-size: 12pt;">.jar</span><span style="font-family: Verdana; font-size: 12pt;">文gQ都无需改动?/span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; margin: 0cm 0cm 0pt 21pt; text-indent: -21pt;"><span style="font-family: Verdana; font-size: 12pt;">l<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">         </span></span><strong style="font-family: Verdana; font-size: 12pt;">Liskov</strong><strong style="font-size: 12pt;"><span style="font-family: 宋体;">替换原则</span></strong><span style="font-family: 宋体; font-size: 12pt;">Q?/span><span style="font-size: 12pt;">The Liskov Substitution Principle</span><span style="font-family: 宋体; font-size: 12pt;">Q简U?/span><span style="font-size: 12pt;">LSP</span><span style="font-family: 宋体; font-size: 12pt;">Q:(x)子类型必能够替换掉它们的基cd?/span><span style="font-size: 12pt;">OCP</span><span style="font-family: 宋体; font-size: 12pt;">原则?/span><span style="font-size: 12pt;">OOD</span><span style="font-family: 宋体; font-size: 12pt;">中很多说法的核心</span><span style="font-family: 宋体; font-size: 12pt;">?/span><span style="font-size: 12pt;">LSP</span><span style="font-family: 宋体; font-size: 12pt;">是</span><span style="font-size: 12pt;">O</span><span style="font-size: 12pt;">CP</span><span style="font-family: 宋体; font-size: 12pt;">成ؓ(f)可能的主要原则之一。正式子cd的可替换性才使得使用基类cd的模块在无需修改的情况下可以扩展。这U可替换性必L开发h员可以隐式依赖的东西?/span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; margin: 0cm 0cm 0pt 21pt; text-indent: -21pt;"><span style="font-family: Verdana; font-size: 12pt;">l<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">         </span></span><strong><span style="font-family: Verdana; font-size: 12pt;">依赖倒置原则</span></strong><span style="font-family: Verdana; font-size: 12pt;">Q?/span><span style="font-family: Verdana; font-size: 12pt;">The Dependency Inversion Principle</span><span style="font-family: Verdana; font-size: 12pt;">Q简U?/span><span style="font-family: Verdana; font-size: 12pt;">DIP</span><span style="font-family: Verdana; font-size: 12pt;">Q:(x)Q?/span><span style="font-family: Verdana; font-size: 12pt;">1</span><span style="font-family: Verdana; font-size: 12pt;">Q、高层模块不应该依赖于底层模块。二者都应该依赖于抽?/span><span style="font-family: Verdana; font-size: 12pt;">。(</span><span style="font-family: Verdana; font-size: 12pt;">2</span><span style="font-family: Verdana; font-size: 12pt;">Q、抽象不应该依赖于细节。细节应该依赖于抽象。用传l的q程化设计所创徏出来的依赖关pȝ构,{略是依赖于l节的。面向对象的E序设计倒置了依赖关pȝ构,使得l节和策略都依赖于抽象,q且常常是客h有服务接口。事实上Q这U依赖关pL式好的面向对象设计的标志所在?/span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; margin: 0cm 0cm 0pt 21pt; text-indent: -21pt;"><span style="font-family: Verdana; font-size: 12pt;">l<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">         </span></span><strong><span style="font-family: Verdana; font-size: 12pt;">接口隔离原则</span></strong><span style="font-family: Verdana; font-size: 12pt;">Q?/span><span style="font-family: Verdana; font-size: 12pt;">The Interface Segregation Interface</span><span style="font-family: Verdana; font-size: 12pt;">Q简U?/span><span style="font-family: Verdana; font-size: 12pt;">ISP</span><span style="font-family: Verdana; font-size: 12pt;">Q:(x)不应该强q客户依赖它们不用的Ҏ(gu)</span><span style="font-family: Verdana; font-size: 12pt;">。如果强q客L(fng)序依赖于那些它们不适用</span><span style="font-family: Verdana; font-size: 12pt;">的方法,那么q些客户E序面临着׃q些未用方法的改变所带来的变更。这无意中D了所有客L(fng)序之间的耦合。我们希望尽可能地避免这U耦合Q因此我们希望分L口?/span></p><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;"></span></div><div>      <span style="line-height: 26px; font-family: Verdana; font-size: 12pt;"><strong>REP 重用发布{h(hun)原则</strong></span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;"> </span>      <span style="font-family: Verdana; font-size: 12pt; line-height: 26px;">重用的粒度就是发布的_度</span></div><div>    <strong>  <span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">CCP q闭原则</span></strong></div><div>      <span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">包中的所有类对于同一cL质的变化应该是共同闭的。一个变化若对一个包产生影响Q则对该包中的所有类产生影响Q而对于其他的包不造成M影响?/span></div><div>     <strong> <span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">CRP 共同重用原则</span></strong></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;"> </span>     <span style="font-family: Verdana; font-size: 12pt; line-height: 26px;">一个包中的所有类应该是共同重用的。如果重用了包中的一个类Q那么就要重用包中所有类?/span></div><div>      <span style="line-height: 26px; font-family: Verdana; font-size: 12pt;"><strong>ADP 无环依赖原则</strong></span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;"> </span>     <span style="font-family: Verdana; font-size: 12pt; line-height: 26px;">在包的依赖关pd中不允许存在环?/span></div><div>      <span style="line-height: 26px; font-family: Verdana; font-size: 12pt;"><strong>SDP E_依赖原则</strong></span></div><div>      <span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">朝着E_的方向进行依赖?/span></div><div>     <strong> <span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">SAP E_抽象原则</span></strong></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;"> </span>     <span style="font-family: Verdana; font-size: 12pt; line-height: 26px;">包的抽象E度应该和其E_E度一致?/span></div><div><span style="line-height: 26px;"><br /></span></div><div><span style="line-height: 26px; font-size: 12pt; font-family: Verdana;"><strong>极限~程实践</strong></span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">完整团队</span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">XP目的所有参与者(开发h员、业务分析师、测试h员等{)一起工作在一个开攄场所中,他们是同一个团队的成员?/span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">计划游戏</span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">计划是持l的Q@序渐q的。每2周,开发h员就Z2周估候选特性的成本Q而客户则Ҏ(gu)成本和商务h(hun)值来选择要实现的Ҏ(gu)?/span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">客户试</span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">作ؓ(f)选择每个所期望的特性的一部分Q客户定义出自动验收试来表明该Ҏ(gu)可以工作?/span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">单设?/span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">团队保持设计恰好和当前的pȝ功能相匹配,它通过了所有的试Q不包含M重复Q表辑և了编写者想表达的所有东西,q且包含可能少的代码?/span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">l对~程</span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">所有的产品软g都是׃个程序员Qƈ排坐在一起在同一台电(sh)脑上构徏的?/span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">试驱动开?/span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">E序员以非常短的循环周期工作Q他们先增加一个失败的试Q然后之通过?/span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">改进设计</span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">随时改进p糕的代码。保持代码尽可能的干净Q具有表辑֊?/span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">持箋集成</span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">团队L使系l完整地被集成?/span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">集体代码所有权</span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">Ml对的程序员都可以在M时候改qQ何代码?/span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">~码标准</span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">pȝ中所有的代码看v来就好像是被单独一?-非常值得胜Q?-人编写的?/span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">隐喻</span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">团队提出一个程序工作原理的公共景像?/span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">可持l的速度</span></div><div><span style="line-height: 26px; font-family: Verdana; font-size: 12pt;">团队只有持久才有莯的希望,他们以能够长期维持的速度努力工作Q他们保存精力,他们把项目看作是马拉N袍,而不是全速短跑?/span></div><br /><p> </p><h1><span style="font-size: 12pt; font-family: Verdana;">试驱动开?/span></h1><p style="color: #333333; text-indent: 21pt;"><span style="font-family: Verdana; font-size: 12pt;">极限~程Q?/span><span style="font-family: Verdana; font-size: 12pt;">eXtreme Programming</span><span style="font-family: Verdana; font-size: 12pt;">Q简U?/span><span style="font-family: Verdana; font-size: 12pt;">XP</span><span style="font-family: Verdana; font-size: 12pt;">Q是敏捷Ҏ(gu)中最著名的一个。它׃pd单却怺依赖的时间组成。这些实늻合在一起Ş成了一个胜于部分结合的整体。其中一个非帔R要的Q当前也受到格外重视的实践就?/span><span style="font-family: Verdana; font-size: 12pt;">TDD</span><span style="font-family: Verdana; font-size: 12pt;">Q测试驱动的开发方法)?/span></p><p style="color: #333333; text-indent: 21pt;"><span style="font-family: Verdana; font-size: 12pt;">在测试驱动的开发方法中Q编写所有的代码的目的都是ؓ(f)了p|的单元测试能够通过。首先编写一个单元测试,׃它要试的功能还不在Q所以它?x)运行失败。然后编写代码ɋ试通过?/span></p><p style="color: #333333; text-indent: 21pt;"><span style="font-family: Verdana; font-size: 12pt;">~写试用例和代码之间的更P速度是很快的Q基本上几分钟左叟뀂测试用例和代码共同演化Q其中测试用例@序渐q地对代码的~写q行指导。作为结果,一个非常完整的试用例集和代码一起发展v来?/span></p><p style="color: #333333; text-indent: 21pt;"><span style="font-family: Verdana; font-size: 12pt;">试_略的可以分为单元测试和验收试。单元测试是用来验证pȝ中个别机制的白盒试?/span></p><p style="color: #333333; text-indent: 21pt;"><span style="font-family: Verdana; font-size: 12pt;">单元试用来验证pȝ的小的组成单元应该按照所期望的方式工作,但是它们没有验证pȝ作ؓ(f)一个整体时工作的正性。所以,单元试是必要的Q但是不够充分?/span></p><p style="color: #333333; text-indent: 21pt;"><span style="font-family: Verdana; font-size: 12pt;">验收试是用来验证系l满_户需求的黑盒试。验收测试由不了解系l内部机制的人编写。验收测试是E序Q因此是可运行的。通常通过使用专门为应用程序的客户创徏的脚本语a来编写验收测试。正如单元测试作为可~译、运行的有关pȝ内部l构的文档那P验收试是有关系l特性的可编译、执行的文档?/span></p><p style="color: #333333; text-indent: 21pt;"><span style="font-family: Verdana; font-size: 12pt;">~写代码前就~写单元试?x)带来四个很明显的好处?x)</span></p><p style="color: #333333; text-indent: 21pt;"><span style="font-family: Verdana; font-size: 12pt;">1</span><span style="font-family: Verdana; font-size: 12pt;">、首先编写测试得程序中的每一功能都有测试来验证它的操作的正性。这可以给以后的开发提供支_(d)使我们可以更自由地对E序q行更改Q因为测试可以告诉我们程序仍然具有正的行ؓ(f)?/span></p><p style="color: #333333; text-indent: 21pt;"><span style="font-family: Verdana; font-size: 12pt;">2</span><span style="font-family: Verdana; font-size: 12pt;">、首先编写测试迫使我们必ME序调用者的有利视角去观察我们将要编写的E序。这P我们׃(x)在关注程序的功能的同Ӟ直接x它的接口Q我们也可以设计出便于调用的Y件?/span></p><p style="color: #333333; text-indent: 21pt;"><span style="font-family: Verdana; font-size: 12pt;">3</span><span style="font-family: Verdana; font-size: 12pt;">、首先编写测试迫使我们把E序设计为可试的。ؓ(f)了把E序设计为易于调用和可测试的Q程序必d它周边环境解耦。这样首先编写测试迫使我们解除Y件中的耦合。面向对象设计的原则在进行这U解除耦合斚wh巨大的帮助作用?/span></p><p style="color: #333333; text-indent: 21pt;"><span style="font-family: Verdana; font-size: 12pt;">4</span><span style="font-family: Verdana; font-size: 12pt;">、首先编写测试的另一个重要效果是Q测试可以作ZU无L(fng)文档形式。测试就像一套范例,它帮助其他程序员了解如何使用代码。这份文档是可编译、可q行的。它保持最新。它不会(x)撒谎?/span></p><p style="color: #333333; text-indent: 21pt;"><span style="font-family: Verdana; font-size: 12pt;">首先~写验收试的行为对于系l的架构斚whp的媄(jing)响。ؓ(f)了ɾpȝh可测试性,必要在很高的pȝ架构层面对系l进行解耦合</span><span style="font-family: Verdana; font-size: 12pt;">。正如单元测试可以促使你在小的方面可以做Z良的设计决策一P验收试可以促你在大的斚w做出优良的系l架构决{?br /><br /></span><span lang="EN-US" style="color: #000000; font-family: Arial; font-size: medium; line-height: 26px; text-indent: 0px; background-color: #ffffff;"> </span><span style="color: #000000; font-size: medium; line-height: 26px; text-indent: 0px; background-color: #ffffff; font-family: 宋体;">软g大师?/span><span lang="EN-US" style="color: #000000; font-family: Arial; font-size: medium; line-height: 26px; text-indent: 0px; background-color: #ffffff;">C++</span><span style="color: #000000; font-size: medium; line-height: 26px; text-indent: 0px; background-color: #ffffff; font-family: 宋体;">之父</span><span lang="EN-US" style="color: #000000; font-family: Arial; font-size: medium; line-height: 26px; text-indent: 0px; background-color: #ffffff;">Bjarne Stroustrup</span><span style="color: #000000; font-size: medium; line-height: 26px; text-indent: 0px; background-color: #ffffff; font-family: 宋体;">曄说过Q设计和~程都是人的zd。忘Cq一点,会(x)失去一?/span><span style="color: #000000; font-size: medium; line-height: 26px; text-indent: 0px; background-color: #ffffff; font-family: 宋体;">。敏捯Y件开发方法正是认识到软g开发的q一本质特征而提出的革新性开发方法。用敏捷开发方法会(x)l我们带来巨大的好处。当然要完全做到也是很困隄。这不仅需要对敏捷的深ȝ解,更需要敏捷团队成员的共同努力?/span><br /><span style="font-family: Verdana; font-size: 12pt;"><br /></span></p><span style="font-family: Verdana; font-size: 12pt;">本文参考:(x)</span><a style="font-family: verdana, 'ms song', Arial, Helvetica, sans-serif; line-height: 21px;"><span style="font-family: Verdana; font-size: 12pt;">http://blog.csdn.net/open2job/article/details/6335000</span></a><p> </p><p> </p><img src ="http://www.shnenglu.com/wanghaiguang/aggbug/199514.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/wanghaiguang/" target="_blank">王v?/a> 2013-04-17 17:13 <a href="http://www.shnenglu.com/wanghaiguang/archive/2013/04/17/199514.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Q{载)架构师不可不知的十大可扩展架?/title><link>http://www.shnenglu.com/wanghaiguang/archive/2013/01/07/197080.html</link><dc:creator>王v?/dc:creator><author>王v?/author><pubDate>Mon, 07 Jan 2013 08:49:00 GMT</pubDate><guid>http://www.shnenglu.com/wanghaiguang/archive/2013/01/07/197080.html</guid><wfw:comment>http://www.shnenglu.com/wanghaiguang/comments/197080.html</wfw:comment><comments>http://www.shnenglu.com/wanghaiguang/archive/2013/01/07/197080.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/wanghaiguang/comments/commentRss/197080.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/wanghaiguang/services/trackbacks/197080.html</trackback:ping><description><![CDATA[<p style="box-sizing: border-box; font-size: 13px; margin-right: 0px; margin-left: 0px; padding: 5px 0px; color: #585858; font-family: verdana, helvetica, arial, sans-serif; line-height: 23.383333206176758px; text-align: justify; background-color: #ffffff;">转自Q?a style="box-sizing: border-box; color: #3468a4;">http://www.itivy.com/ivy/archive/2011/11/24/something-that-architecture-must-be-aware-of.html<br style="box-sizing: border-box;" /></a><br style="box-sizing: border-box;" />对于大多数架构师而言Q?#8220;可扩展?#8221;在Y件架构方面是最虚无~缈的说法。这毫不奇怪,因ؓ(f)可扩展性正是如今Y件设计领域最值得优先考虑的要素。然 而,计算机科学家们还无法了解一套单独的架构如何才能扩展臛_cd用环境当中。相反,我们在数量繁多的Ҏ(gu)中所设计出的可扩展性架构,往往以业界较为通用 的已知可扩展模式?qing)个人偏好?f)标准。简单来Ԍ打造一套具备可扩展性的pȝ已经变得更像是一门艺术而不单单是技术?/p><p style="box-sizing: border-box; font-size: 13px; margin-right: 0px; margin-left: 0px; padding: 5px 0px; color: #585858; font-family: verdana, helvetica, arial, sans-serif; line-height: 23.383333206176758px; text-align: justify; background-color: #ffffff;">我们常常?x)通过观摩C体会(x)q学?fn)艺术的_NQ而可扩展性也应该遵@同样的\U!</p><p style="box-sizing: border-box; font-size: 13px; margin-right: 0px; margin-left: 0px; padding: 5px 0px; color: #585858; font-family: verdana, helvetica, arial, sans-serif; line-height: 23.383333206176758px; text-align: justify; background-color: #ffffff;">在这文章中Q我列出数ƾؓ(f)大家所耳熟能详的可扩展性架构。通常情况下,架构师们完全可以借鉴已知的可扩展架构模式Q进而创造出新的可扩展架构?/p><ol style="box-sizing: border-box; font-size: 13px; padding: 0px; margin: 0px; color: #585858; font-family: verdana, helvetica, arial, sans-serif; line-height: 23.383333206176758px; text-align: justify; background-color: #ffffff;"><li value="1" style="font-size: 12px; box-sizing: border-box; list-style: url(http://www.itivy.com/Skins/gazetteer/li.gif); margin-left: 18px;">LB (负蝲q? + 无共享单?nbsp;- 该模型中包含一pd单元Q各单元彼此间不׃nM内容Q且一致指向一个将输入文讯按一定条件发往单元处的负蝲q器(q构成一个@ 环,以负载等情况为基Q。每个单元可以是一个单独的节点或是紧密耦合的节Ҏ(gu)构成的集。用户可以用DNS循环、硬件负载^衡器或者Y件负载^衡器?成负载^衡效果。创Z套负载均衡的层次l构Qƈ在其中结合前面提到的各种负蝲q器也是可行的。在由Michael Stonebraker撰写的?nbsp;<a target="_blank" style="box-sizing: border-box; color: #dc8e38; background-color: transparent; text-decoration: initial;">无共享体pL构实?nbsp;</a>》一文中Q专门讨Z此类架构?br style="box-sizing: border-box;" /> </li><li value="2" style="font-size: 12px; box-sizing: border-box; list-style: url(http://www.itivy.com/Skins/gazetteer/li.gif); margin-left: 18px;">LB + 无状态节?nbsp;+ 可扩展存?nbsp;- 传统?nbsp;<a target="_blank" style="box-sizing: border-box; color: #dc8e38; background-color: transparent; text-decoration: initial;">三层式Web架构 </a>使用的就是这U模型。该模型包括C与可扩展存储交互的无状态节点以?qing)一个分布于节点间负载中的负载^衡器。在q一模型中,存储通常作ؓ(f)限制因素存在Q但NoSQL存储则可以利用这套模型创建出具备相当可扩展性的pȝ?br style="box-sizing: border-box;" /> </li><li value="3" style="font-size: 12px; box-sizing: border-box; list-style: url(http://www.itivy.com/Skins/gazetteer/li.gif); margin-left: 18px;">点对Ҏ(gu)?nbsp;(分布式Hash列表 (UDHT)以及(qing)内容d|络(UCAN)) -q套模型提供了一些传l的 可扩展算法,q些法的各个方面几乎全部按Ҏ(gu)q行了等比例增加。D例来_(d)像Chord、PastryQ特指免费版Q以?qing)CAN都属于此cR而以 CassandraZ表的、基于P2P架构的几ƾNoSQLpȝ也是其中的成员。?nbsp;<a target="_blank" style="box-sizing: border-box; color: #dc8e38; background-color: transparent; text-decoration: initial;">展望P2Ppȝ中的数据 </a>》一文就深入探讨了这cL型的各种l节?br style="box-sizing: border-box;" /> </li><li value="4" style="font-size: 12px; box-sizing: border-box; list-style: url(http://www.itivy.com/Skins/gazetteer/li.gif); margin-left: 18px;">分布式队?nbsp;– q种模型以将队列实施Q即先进先出交付机制Q作为网l服务处理ؓ(f)基础。该模型通过JMS队列而广泛得到采用。一般会(x)遵@q种做法的有d队列以及(qing)通过保持队列分体系实现扩展性的d队列版本Q后者在负蝲无法?qing)时处理Ӟd?x)由低层面向高U层面传递?br style="box-sizing: border-box;" /> </li><li value="5" style="font-size: 12px; box-sizing: border-box; list-style: url(http://www.itivy.com/Skins/gazetteer/li.gif); margin-left: 18px;">发布/订阅模式 - 一般用于通过|络向彼此发布订阅讯息。?nbsp;<a target="_blank" style="box-sizing: border-box; color: #dc8e38; background-color: transparent; text-decoration: initial;">发布与订阅的多面?nbsp;</a>》这一l典论文中详l的介绍q一模型Q该模型斚w最典型的例子即 <a target="_blank" style="box-sizing: border-box; color: #dc8e38; background-color: transparent; text-decoration: initial;">NaradaBroker</a>?nbsp;<a target="_blank" style="box-sizing: border-box; color: #dc8e38; background-color: transparent; text-decoration: initial;">EventJava </a>?br style="box-sizing: border-box;" /> </li><li value="6" style="font-size: 12px; box-sizing: border-box; list-style: url(http://www.itivy.com/Skins/gazetteer/li.gif); margin-left: 18px;">道消息与自然灵感式模型 - q种模型源自日常生活中小道消息的传播途径Q也是每个节点随机选择后箋节点以交 换信息。正如现实生zM的实际反馈,q种八卦型算法在信息传播斚w出奇地迅速。该模型的另一大分支则是受到生物学影响的启发式法。自然世界中存在着大量 协调?qing)扩展方面极为卓的固有法。D例来_(d)蚂蚁、hcM?qing)蜜蜂等{,都能够以最z的交流方式协调好扩展性方面的需要。模型中的算法正是借鉴了这些实 际存在的现象。在论文?nbsp;<a target="_blank" style="box-sizing: border-box; color: #dc8e38; background-color: transparent; text-decoration: initial;">从流行病的蔓延到分布式计?nbsp;</a>》中对这U模型有着详尽的叙q?br style="box-sizing: border-box;" /> </li><li value="7" style="font-size: 12px; box-sizing: border-box; list-style: url(http://www.itivy.com/Skins/gazetteer/li.gif); margin-left: 18px;">地图~小/数据?nbsp;- q一概念首先p歌公司提出,地图~小为工作的描述?qing)执行提供了一套可扩展的模式。虽然内?单,但它仍然成ؓ(f)联机分析处理斚w的首要处理模式。数据流则是一U更先进的方式,用来表达执行信息Q而像Dryad?qing)Pigq样的项目ؓ(f)数据的执行?供了可扩展的框架。论文?nbsp;<a target="_blank" style="box-sizing: border-box; color: #dc8e38; background-color: transparent; text-decoration: initial;">地图~小Q大型集上的简化数据处?nbsp;</a>》中讄了专门的主题Q详l讨一内容。Apache的Hadoop是q种模型的代表性品?br style="box-sizing: border-box;" /> </li><li value="8" style="font-size: 12px; box-sizing: border-box; list-style: url(http://www.itivy.com/Skins/gazetteer/li.gif); margin-left: 18px;">责Q?wi)Ş?nbsp;- q种模型打破了递归问题的束~,整个流E以?wi)状形式加以处理Q每个父节点工作下放至子节炏V这U模型扩展性强Qƈ已经被应用于数款可扩展性架构当中?br style="box-sizing: border-box;" /> </li><li value="9" style="font-size: 12px; box-sizing: border-box; list-style: url(http://www.itivy.com/Skins/gazetteer/li.gif); margin-left: 18px;">处?nbsp;- q种模型被用于处理源源不断的数据及(qing)数据。这U处理方式通过|络中的处理节点获得支持Q例如Aurora、Twitter Strom以及(qing)Apache S4{)?br style="box-sizing: border-box;" /> </li><li value="10" style="font-size: 12px; box-sizing: border-box; list-style: url(http://www.itivy.com/Skins/gazetteer/li.gif); margin-left: 18px;">可扩展存?nbsp;– 该模型的应用范围从数据库、NoSQL存储、服务注册到文gpȝ都有体现?nbsp;<a target="_blank" style="box-sizing: border-box; color: #dc8e38; background-color: transparent; text-decoration: initial;">链接中的q篇文章 </a>以可扩展性ؓ(f)切入点对其进行了深入讨论?/li></ol><p style="box-sizing: border-box; font-size: 13px; margin-right: 0px; margin-left: 0px; padding: 5px 0px; color: #585858; font-family: verdana, helvetica, arial, sans-serif; line-height: 23.383333206176758px; text-align: justify; background-color: #ffffff;">lg所qͼ可扩展性的实现只有三种方式Q即Q分布、缓存及(qing)异步处理。前文所提到的各U架构事实上都是把这三种方式q行不同l合q加以实施。而另一?面,不利于可扩展性的因素Q除了糟p的~码本nQ全局性协调也起到了重要的影响。简单来_(d)M一U全局性协调都?x)限制系l的可扩展性。本文中所提到的各 U架构也只是在做好了本地性协调,而非全局性协调?/p><p style="box-sizing: border-box; font-size: 13px; margin-right: 0px; margin-left: 0px; padding: 5px 0px; color: #585858; font-family: verdana, helvetica, arial, sans-serif; line-height: 23.383333206176758px; text-align: justify; background-color: #ffffff;">然而,它们有机地l合h以创Z套极具可扩展性的架构可不像说h那么Ҏ(gu)Q除非我们能扑ֈ一U全新的扩展模式。不q经验告诉我们,比v搞一套全新的架构Q采用ؓ(f)我们所熟知且更易驾驭的可扩展性解x案永q是更好的选择?/p><img src ="http://www.shnenglu.com/wanghaiguang/aggbug/197080.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/wanghaiguang/" target="_blank">王v?/a> 2013-01-07 16:49 <a href="http://www.shnenglu.com/wanghaiguang/archive/2013/01/07/197080.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Q{载)怎样量化评h(hun)搜烦(ch)引擎的结果质?/title><link>http://www.shnenglu.com/wanghaiguang/archive/2013/01/07/197078.html</link><dc:creator>王v?/dc:creator><author>王v?/author><pubDate>Mon, 07 Jan 2013 08:46:00 GMT</pubDate><guid>http://www.shnenglu.com/wanghaiguang/archive/2013/01/07/197078.html</guid><wfw:comment>http://www.shnenglu.com/wanghaiguang/comments/197078.html</wfw:comment><comments>http://www.shnenglu.com/wanghaiguang/archive/2013/01/07/197078.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/wanghaiguang/comments/commentRss/197078.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/wanghaiguang/services/trackbacks/197078.html</trackback:ping><description><![CDATA[<h2>转自Q?a style="box-sizing: border-box; color: #3468a4;">http://www.infoq.com/cn/articles/cyw-evaluate-seachengine-result-quality</a><br style="box-sizing: border-box;" /><br style="box-sizing: border-box;" />前言</h2><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">搜烦(ch)质量评估是搜索技术研I的基础性工作,也是核心工作之一。评PMetricsQ在搜烦(ch)技术研发中扮演着重要角色Q以至于M一U新Ҏ(gu)与他们的评h(hun)方式是融Z体的?/p><div style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><br style="box-sizing: border-box;" />搜烦(ch)引擎l果的好坏与否,体现在业界所U的在相x(RelevanceQ上。相x的定义包括狭义和广义两斚wQ狭义的解释是:(x)(g)索结果和用户查询的相关程度。而从q义的层面,相关性可以理解ؓ(f)为用h询的l合满意度。直观的来看Q从用户q入搜烦(ch)框的那一刻vQ到需求获得满ؓ(f)止,q之间经历的q程顺畅,便P搜烦(ch)相关性就好。本文ȝ业界常用的相x评h标和量化评h(hun)Ҏ(gu)。供Ҏ(gu)感兴的朋友参考?/div><h2>Cranfield评h(hun)体系</h2><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">A Cranfield-like approachq个名称来源于英国Cranfield UniversityQ因为在二十世纪五十q代该大学首先提Zq样一套评L(fng)l:(x)由查询样例集、正答案集、评指标构成的完整评测Ҏ(gu)Qƈ从此立?#8220;评h(hun)”在信息检索研I中的核心地位?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">Cranfield评h(hun)体系׃个环节组成:(x)</p><ol style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><li style="font-size: 12px; box-sizing: border-box;">抽取代表性的查询词,l成一个规模适当的集?/li><li style="font-size: 12px; box-sizing: border-box;">针对查询样例集合Q从(g)索系l的语料库中L对应的结果,q行标注Q通常人工q行Q?/li><li style="font-size: 12px; box-sizing: border-box;">查询词和带有标注信息的语料库输入检索系l,对系l反馈的(g)索结果,使用预定义好的评仯公式,用数值化的方法来评h(hun)(g)索系l结果和标注的理想结果的接近E度</li></ol><h2>查询词集合的选取</h2><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">Cranfield评h(hun)pȝ在各大搜索引擎公司内有广泛的应用。具体应用时Q首先需要解决的问题是构造一个测试用查询词集合?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">按照Andrei BroderQ曾在AltaVista/IBM/Yahoo任职Q的研究Q查询词可分?c:(x)dcL询(NavigationalQ、信息类查询(Informational)、事务类查询(Transactional)。对应的比例分别?/p><pre style="box-sizing: border-box; overflow: auto; width: 964.25px; padding: 0px 0px 5px; font-size: 12px; line-height: 15px; font-family: 'Courier New', Courier; color: #222222; margin-top: 0px; margin-bottom: 0px; background-color: #fafafa; border: 2px solid #efefef;">Navigational Q?12.3% Informational Q?62.0% Transactional Q?25.7% </pre><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">Z使得评估W合U上实际情况Q通常查询词集合也?x)按比例q行选取。通常从线上用L(fng)Query Log文g中自动抽取?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">另外查询集合的构造时Q除了上q查询类型外Q还可以考虑Query的频ơ,对热门queryQ高频查询)、长queryQ中低频Q分别占特定的比例?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">另外Q在抽取QueryӞ往往Query的长短也是一个待考虑的因素。因为短queryQ单term的查询)和长QueryQ多Term的查询)排序法往往?x)有一些不同?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">构成查询集合后,使用q些查询词,在不同系l(例如Ҏ(gu)癑ֺ和GoogleQ或不同技术间Q新旧两套Ranking法的环境)q行搜烦(ch)Qƈ对结果进行评分,以决定优劣?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">附图Q对同一QueryQ?#8220;C会(x)保险?#8221;Q各大搜索引擎的l果C意图。下面具体谈谈评分的Ҏ(gu)?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; overflow-x: auto; width: 964.25px; overflow-y: hidden; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><img border="0" _href="img://image1.jpg" _p="true" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image1.jpg" alt="" style="box-sizing: border-box; border: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" /></p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; overflow-x: auto; width: 964.25px; overflow-y: hidden; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><img border="0" _href="img://image1.jpg" _p="true" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image2.jpg" alt="" style="box-sizing: border-box; border: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" /></p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; overflow-x: auto; width: 964.25px; overflow-y: hidden; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><img border="0" _href="img://image1.jpg" _p="true" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image3.jpg" alt="" style="box-sizing: border-box; border: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" /></p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; overflow-x: auto; width: 964.25px; overflow-y: hidden; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><img border="0" _href="img://image1.jpg" _p="true" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image4.jpg" alt="" style="box-sizing: border-box; border: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" /></p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; overflow-x: auto; width: 964.25px; overflow-y: hidden; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><img border="0" _href="img://image1.jpg" _p="true" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image5.jpg" alt="" style="box-sizing: border-box; border: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" /></p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; overflow-x: auto; width: 964.25px; overflow-y: hidden; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><img border="0" _href="img://image1.jpg" _p="true" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image6.jpg" alt="" style="box-sizing: border-box; border: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" /></p><h2>Precision-recallQ准率-召回率方法)</h2><h3>计算Ҏ(gu)</h3><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">信息(g)索领域最qؓ(f)人知的评h标ؓ(f)Precision-RecallQ准率-召回率)Ҏ(gu)。该Ҏ(gu)从提今已l历半个世纪Q至今在很多搜烦(ch)引擎公司的效果评C使用?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">֐思义Q这个方法由准确率和召回率这两个怺兌的统计量构成Q召回率QRecallQ衡量一个查询搜索到所有相x档的能力Q而准率QPrecisionQ衡量搜索系l排除不相关文档的能力。(通俗的解释一下:(x)准确率就是算一你查询得到的结果中有多是靠谱的;而召回率表示所有靠ql果中,有多被你给扑֛来了Q。这两项是评h索效果的最基础指标Q其具体的计方法如下?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">Precision-recallҎ(gu)假定对一个给定的查询Q对应一个被(g)索的文档集合和一个不相关的文档集合。这里相x被假设Z元的Q用数学形式化方法来描述Q则是:(x)</p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">A表示相关文档集合</p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><span style="box-sizing: border-box; text-decoration: overline;">A</span>表示不相关集?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">B表示被检索到的文档集?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><span style="box-sizing: border-box; text-decoration: overline;">B</span>表示未被(g)索到的文档集?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">则单ơ查询的准确率和召回率可以用下述公式来表达:(x)</p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; overflow-x: auto; width: 964.25px; overflow-y: hidden; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><img alt="" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image7.jpg" _href="img://image7.jpg" _p="true" style="box-sizing: border-box; border: 0px;" /></p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">Q运符∩ 表示两个集合的交集。|x|W号表示集合x中的元素数量Q?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">从上面的定义不难看出Q召回率和准率的取D围均在[0,1]之间。那么不难想象,如果q个pȝ扑֛的相兌多,那么召回率越高,如果相关l果全部都给召回了,那么recall此时q?.0?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"></p><table cellspacing="0" cellpadding="0" border="1" style="box-sizing: border-box; color: #000000; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 19px; text-align: start; background-color: #ffffff;"><tbody style="box-sizing: border-box;"><tr style="box-sizing: border-box;"><td width="156" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"> </td><td width="156" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">相关?/p></td><td width="156" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">不相?/p></td></tr><tr style="box-sizing: border-box;"><td width="156" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">被检索到</p></td><td width="156" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">A∩ B</p></td><td width="156" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;"><span style="box-sizing: border-box; text-decoration: overline;">A</span>∩ B</p></td></tr><tr style="box-sizing: border-box;"><td width="156" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">未被(g)索到</p></td><td width="156" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">A∩<span style="box-sizing: border-box; text-decoration: overline;">B</span></p></td><td width="156" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;"><span style="box-sizing: border-box; text-decoration: overline;">A</span>∩<span style="box-sizing: border-box; text-decoration: overline;">B</span></p></td></tr></tbody></table><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"></p><h3>Precision-Recall曲线</h3><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">召回率和准确率分别反映了(g)索系l的两个最重要的侧面,而这两个侧面又相互制U。因为大规模数据集合中,如果期望(g)索到更多相关的文档,必然需?#8220;攑֮”(g)索标准,因此?x)导致一些不相关l果淯来,从而准确率受到媄(jing)响。类似的Q期望提高准率Q将不相x档尽量去除时Q务必要执行?#8220;严格”的检索策略,q样也会(x)使一些相关的文档被排除在外,使召回率下降?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">所以ؓ(f)了更清晰的描qC者间的关p,通常我们Precison-Recall用曲U的方式l制出来Q可以简UCؓ(f)P-R diagram。常见的形式如下图所C。(通常曲线是一个逐步向下的走势,即随着Recall的提高,Precision逐步降低Q?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; overflow-x: auto; width: 964.25px; overflow-y: hidden; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><img border="0" _href="img://image1.jpg" _p="true" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image8.jpg" alt="" style="box-sizing: border-box; border: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" /></p><h3>P-R的其它Ş?/h3><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">一些特定搜索应用,?x)更x搜烦(ch)l果中错误的l果。例如,搜烦(ch)引擎的反作弊pȝQAnti-Spam SystemQ会(x)更关注检索结果中混入了多条作弊l果。学术界把这些错误结果称作假x(F(tun)alse PositiveQ结果,对这些应用,通常选择用虚报率QF(tun)alloutQ来l计Q?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; overflow-x: auto; width: 964.25px; overflow-y: hidden; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><img alt="" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image9.jpg" _href="img://image9.jpg" _p="true" style="box-sizing: border-box; border: 0px;" /></p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">Fallout和Presion本质是完全相同的。只是分别从正反两方面来计算。实际上是P-R的一个变U?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">再回C图,Presion-Recall是一个曲U,用来比较两个Ҏ(gu)的效果往往不够直观Q能不能对两者进行综合,直接反映C个数g呢?为此IR学术界提ZF值度量(F(tun) -MeasureQ的Ҏ(gu)。F-Measure通过Presion和Recall的调和^均数来计,公式为:(x)</p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; overflow-x: auto; width: 964.25px; overflow-y: hidden; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><img border="0" _href="img://image1.jpg" _p="true" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image10.jpg" alt="" style="box-sizing: border-box; border: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" /></p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">其中参数λε(0,1)调节pȝ对Precision和Recall的^衡程度。(通常?#955;=0.5Q此?nbsp;<img border="0" _href="img://image1.jpg" _p="true" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image11-1.jpg" alt="" style="box-sizing: border-box; border: 0px;" />Q?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">q里使用调和q_数而不是通常的几何^均或术q_Q原因是调和q_数强调较?yu)数值的重要性,能敏感的反映数字的变化Q因此更适合用来反映(g)索效果?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">使用F Measure的好处是只需要一个单一的数字就可以ȝpȝ的检索效果,便于比较不同搜烦(ch)pȝ的整体效果?/p><h2>P@NҎ(gu)</h2><h3>点击因素</h3><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">传统的Precision-Recallq不完全适用Ҏ(gu)索引擎的评估Q原因是搜烦(ch)引擎用户的点?yn)L式有其特D性,包括Q?/p><pre style="box-sizing: border-box; overflow: auto; width: 964.25px; padding: 0px 0px 5px; font-size: 12px; line-height: 15px; font-family: 'Courier New', Courier; color: #222222; margin-top: 0px; margin-bottom: 0px; background-color: #fafafa; border: 2px solid #efefef;">A 60-65%的查询点M名列搜烦(ch)l果?0条的|页Q? B 20-25%的h?x)考虑点击名列11?0的网; C 仅有3-4%的会(x)点击名列搜烦(ch)l果中列W?1到第30名的|页 </pre><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">也就是说Q绝大部分用h不愿意翻去看搜索引擎给出的后面的结果?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">而即使在搜烦(ch)l果的首(通常列出的是?0条结果)Q用L(fng)点击行ؓ(f)也很有意思,我们通过下面的Google点击热图QHeat MapQ来观察Q这个热囑֜二维搜烦(ch)l果上通过光谱来Ş象的表达不同位置用户的点ȝ度。颜色约靠近U色表示点击强度高Q:(x)</p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; overflow-x: auto; width: 964.25px; overflow-y: hidden; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><img border="0" _href="img://image1.jpg" _p="true" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image12.jpg" alt="" style="box-sizing: border-box; border: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" /></p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">从图中可以看出,搜烦(ch)l果的前3条吸引了大量的点击,属于热度最高的部分。也是_(d)Ҏ(gu)苏引擎来_(d)最前的几条l果是最关键的,军_了用L(fng)满意E度?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; overflow-x: auto; width: 964.25px; overflow-y: hidden; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><img border="0" _href="img://image1.jpg" _p="true" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image13.jpg" alt="" style="box-sizing: border-box; border: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" /></p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">康乃?yu)(dng)大学的研究人员通过eye tracking实验获得了更为精的Google搜烦(ch)l果的用戯为分析图。从q张图中可以看出Q第一条结果获得了56.38%的搜索流量,W二条和W三条结果的排名依次降低Q但q低于排名第一的结果。前三条l果的点?yn)L例大Uؓ(f)11:3:2 。而前三条l果的ȝd乎分了搜烦(ch)量?0%?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">另外的一些有的l论是,点击量ƈ不是按照序依次递减的。排名第七位获得的点?yn)L最的Q原因可能在于用户在览q程中下拉页面到底部Q这时候就只显C最后三位排名网站,W七名便Ҏ(gu)被忽略。而首屏最后一个结果获得的注意力(2.55Q是大于倒数W二位的(1.45)Q原因是用户在翻前Q对最后一条结果印象相对较深。搜索结果页面第二页排名W一的网(xL?1位的l果Q所获得的点d有首|名第十网站的40%Q与首页的第一条结果相比,更是只有?/60?/100的点击量?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">因此在量化评估搜索引擎的效果Ӟ往往需要根据以上搜索用L(fng)行ؓ(f)特点Q进行针Ҏ(gu)的设计?/p><h3>P@N的计方?/h3><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">P@N本n是Precision@N的简Uͼ指的是对特定的查询,考虑位置因素Q检前N条结果的准确率。例如对单次搜烦(ch)的结果中?,如果?ؓ(f)相关文档Q则P@5 = 4/5 = 0.8 ?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">试通常?x)用一个查询集合(按照前文所q方法构造)Q包含若q条不同的查询词Q在实际使用P@Nq行评估Ӟ通常使用所有查询的P@N数据Q计算术^均|用来评判该系l的整体搜烦(ch)l果质量?/p><h3>N的选取</h3><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">对用h_(d)通常只关注搜索结果最前若q条l果Q因此通常搜烦(ch)引擎的效果评估只x?、或者前3l果Q所以我们常用的N取gؓ(f)P@3或P@5{?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">对一些特定类型的查询应用Q如dcȝ查询QNavigational SearchQ,׃目标l果极ؓ(f)明确Q因此在评估Ӟ?x)选择N=1Q即使用P@1Q。D个例子来_(d)搜烦(ch)“新浪|?#8221;、或“新浪首页”Q如果首条结果不?新浪|(urlQ?a style="box-sizing: border-box; color: #0b59b2;">www.sina.com.cn</a>Q,则直接判该次查询_ֺ不满需求,即P@1=0</p><h2>MRR</h2><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">上述的P@NҎ(gu)Q易于计和理解。但l心的读者一定会(x)发现问题Q就是在前Nl果中,排序W?位和WN位的l果Q对准确率的影响是一L(fng)。但实际情况是,搜烦(ch)引擎的评h和排序位|极为相关的。即排第一的结果错误,和第10位的l果错误Q其严重E度有天壤之别。因此在评h(hun)pȝ中,需要引入位|这个因素?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">MRR是^均排序倒数QMean Reciprocal RankQ的UͼMRRҎ(gu)主要用于dcL索(Navigational SearchQ或问答cL索(Question AnsweringQ,q些(g)索方法只需要一个相x档,对召回率不敏感,而是更关注搜索引擎检索到的相x档是否排在结果列表的前面。MRRҎ(gu)首先计算每一个查询的W一个相x档位|的倒数Q然后将所有倒数值求q_。例如一个包含三个查询词的测试集Q前5l果分别为:(x)</p><pre style="box-sizing: border-box; overflow: auto; width: 964.25px; padding: 0px 0px 5px; font-size: 12px; line-height: 15px; font-family: 'Courier New', Courier; color: #222222; margin-top: 0px; margin-bottom: 0px; background-color: #fafafa; border: 2px solid #efefef;">查询一l果Q?.AN 2.AR 3.AN 4.AN 5.AR 查询二结果:(x)1.AN 2.AR 3.AR 4.AR 5.AN 查询三结果:(x)1.AR 2.AN 3.AN 4.AN 5.AR </pre><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">其中AN表示不相关结果,AR表示相关l果。那么第一个查询的排序倒数QReciprocal RankQRR<sub style="box-sizing: border-box;">1</sub> = 1/2=0.5 Q第二个l果RR<sub style="box-sizing: border-box;">2</sub> = 1/2 = 0.5 Q?注意倒数的g变,即查询二获得的相关l果更多。同理,RR<sub style="box-sizing: border-box;">3</sub>= 1/1 = 1?对于q个试集合Q最lMRR=QRR<sub style="box-sizing: border-box;">1</sub>+RR<sub style="box-sizing: border-box;">2</sub>+RR<sub style="box-sizing: border-box;">3</sub>Q? 3 = 0.67</p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">然而对大部分检索应用来_(d)只有一条结果无法满需求,对这U情况,需要更合适的Ҏ(gu)来计效果,其中最常用的是下述MAPҎ(gu)?/p><h2>MAP</h2><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">MAPҎ(gu)是Mean Average PrecisonQ即q_准确率法的简U。其定义是求每个相关文档(g)索出后的准确率的q_|即Average PrecisionQ的术q_|MeanQ。这里对准确率求了两ơ^均,因此UCؓ(f)Mean Average Precision。(注:(x)没叫Average Average Precision一是因为难听,二是因ؓ(f)无法区分两次q_的意义)</p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">MAP 是反映系l在全部相关文档上性能的单值指标。系l检索出来的相关文档靠?rank 高)QMAP应该越高。如果系l没有返回相x档,则准率默认??/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">例如Q假设有两个主题Q?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">主题1?个相关网,主题2?个相关网c(din)?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">某系l对于主?(g)索出4个相关网,其rank分别?, 2, 4, 7Q?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">对于主题2(g)索出3个相关网,其rank分别?,3,5?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">对于主题1Q^均准率MAP计算公式为:(x)</p><pre style="box-sizing: border-box; overflow: auto; width: 964.25px; padding: 0px 0px 5px; font-size: 12px; line-height: 15px; font-family: 'Courier New', Courier; color: #222222; margin-top: 0px; margin-bottom: 0px; background-color: #fafafa; border: 2px solid #efefef;">(1/1+2/2+3/4+4/7)/4=0.83?</pre><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">对于主题2Q^均准率MAP计算公式为:(x)</p><pre style="box-sizing: border-box; overflow: auto; width: 964.25px; padding: 0px 0px 5px; font-size: 12px; line-height: 15px; font-family: 'Courier New', Courier; color: #222222; margin-top: 0px; margin-bottom: 0px; background-color: #fafafa; border: 2px solid #efefef;">(1/1+2/3+3/5+0+0)/5=0.45?</pre><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">则MAP= (0.83+0.45)/2=0.64?#8221;</p><h2>DCGҎ(gu)</h2><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">DCG是英文Discounted cumulative gain的简Uͼ中文可翻译ؓ(f)“折扣增益?#8221;。DCGҎ(gu)的基本思想是:(x)</p><ol style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><li style="font-size: 12px; box-sizing: border-box;">每条l果的相x分{来衡?/li><li style="font-size: 12px; box-sizing: border-box;">考虑l果所在的位置Q位|越靠前的则重要E度高</li><li style="font-size: 12px; box-sizing: border-box;">{高(卛_l果Q的l果位置靠前则值应该越高,否则l予惩罚</li></ol><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">我们首先来看W一条:(x)相关性分U。这里比计算Precision时简单统?#8220;准确”?#8220;不准?#8221;要更为精l。我们可以将l果l分为多个等U。比如常用的3U:(x)GoodQ好Q、FairQ一般)、BadQ差Q。对应的分值rel为:(x)Good:3 / Fair:2 / Bad:1 。一些更为细致的评估使用5U分cLQVery GoodQ明昑֥Q、GoodQ好Q、FairQ一般)、BadQ差Q、Very BadQ明昑ַQ,可以对应分值rel讄为:(x)Very Good:2 / Good:1 / Fair:0 / Bad:-1 / Very Bad: -2</p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">评判l果的标准可以根据具体的应用来确定,Very Good通常是指l果的主题完全相养Iq且|页内容丰富、质量很高。而具体到每条</p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; overflow-x: auto; width: 964.25px; overflow-y: hidden; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><img border="0" _href="img://image1.jpg" _p="true" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image14.jpg" alt="" style="box-sizing: border-box; border: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" /></p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">DCG的计公式ƈ不唯一Q理Z只要求对数折扣因子的qx性。我个h认ؓ(f)下面的DCG公式更合理,了相x,W??条结果的折扣pL也更合理Q?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; overflow-x: auto; width: 964.25px; overflow-y: hidden; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><img border="0" _href="img://image1.jpg" _p="true" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image15.jpg" alt="" style="box-sizing: border-box; border: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" /></p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">此时DCG?个位|上l果的折扣因子(Discount factorQ数gؓ(f)Q?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"></p><table cellspacing="0" cellpadding="0" border="1" style="box-sizing: border-box; color: #000000; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; font-size: 13px; line-height: 19px; text-align: start; background-color: #ffffff;"><tbody style="box-sizing: border-box;"><tr style="box-sizing: border-box;"><td width="189" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">i</p></td><td width="189" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">log<sub style="box-sizing: border-box;">2</sub> (i+1)</p></td><td width="189" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">1/log<sub style="box-sizing: border-box;">2</sub> (i+1)</p></td></tr><tr style="box-sizing: border-box;"><td width="189" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">1</p></td><td width="189" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">1</p></td><td width="189" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">1</p></td></tr><tr style="box-sizing: border-box;"><td width="189" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">2</p></td><td width="189" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">1.59</p></td><td width="189" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">0.63</p></td></tr><tr style="box-sizing: border-box;"><td width="189" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">3</p></td><td width="189" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">2</p></td><td width="189" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">0.5</p></td></tr><tr style="box-sizing: border-box;"><td width="189" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">4</p></td><td width="189" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">2.32</p></td><td width="189" valign="top" style="font-family: Verdana, Helvetica, Arial; word-break: break-all; font-size: small; box-sizing: border-box;"><p align="center" style="box-sizing: border-box;">0.43</p></td></tr></tbody></table><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"></p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">取以2为底的logg来自于经验公式,q不存在理论上的依据。实际上QLog的基数可以根据^滑的需求进行修改,当加大数值时Q例如用log<sub style="box-sizing: border-box;">5</sub> 代替log<sub style="box-sizing: border-box;">2</sub>Q,折扣因子降低更ؓ(f)q速,此时了前面结果的权重?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">Z便于不同cd的queryl果之间横向比较Q以DCG为基Q一些评L(fng)l还对DCGq行了归一Q这些方法统UCؓ(f)nDCGQ即 normalize DCGQ。最常用的计方法是通过除以每一个查询的理想值iDCGQideal DCGQ来q行归一Q公式ؓ(f)Q?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; overflow-x: auto; width: 964.25px; overflow-y: hidden; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><img border="0" _href="img://image1.jpg" _p="true" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image16.jpg" alt="" style="box-sizing: border-box; border: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" /></p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">求nDCG需要标定出理想情况的iDCGQ实际操作的时候是异常困难的,因ؓ(f)每个人对“最好的l果”理解往往各不相同Q从量数据里选出最优结果是很困隄dQ但是比较两l结果哪个更好通常更容易,所以实践应用中Q通常选择l果Ҏ(gu)的方法进行评估?/p><h2>怎样实现自动化的评估Q?/h2><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">以上所介绍的搜索引擎量化评估指标,在Cranfield评估框架QCranfield Evaluation FrameworkQ中被广泛用。业界知名的TRECQ文本信息检索会(x)议)׃直基于此cL法组l信息检索评和技术交。除了TREC外,一些针对不同应用设计的Cranfield评测论坛也在q行q行Q如 NTCIR、IREX{)?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">但Cranfield评估框架存在的问题是查询样例集合的标注上。利用手工标注答案的方式q行|络信息(g)索的评h(hun)是一个既耗费人力、又耗费旉的过E,只有数大公司能够用。ƈ且由于搜索引擎算法改q、运营维护的需要,(g)索效果评价反馈的旉需要尽量羃短,因此自动化的评测Ҏ(gu)Ҏ(gu)高评估效率十分重要。最常用的自动评估方法是A/B testingpȝ?/p><h3>A/B Testing</h3><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; overflow-x: auto; width: 964.25px; overflow-y: hidden; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><img border="0" _href="img://image1.jpg" _p="true" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image17.jpg" alt="" style="box-sizing: border-box; border: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" /></p><p align="center" style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><strong style="box-sizing: border-box;">A/B Testingpȝ</strong></p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">A/B testingpȝ在用h索时Q由pȝ来自动决定用L(fng)分组PBucket idQ,通过自动抽取量导入不同分支Q得相应分l的用户看到的是不同产品版本Q或不同搜烦(ch)引擎Q提供的l果。用户在不同版本产品下的行ؓ(f)被记录下来Q这些行为数据通过数据分析形成一pd指标Q而通过q些指标的比较,最后就形成了各版本之间C孰劣的结论?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">在指标计时Q又可细分ؓ(f)两种Ҏ(gu)Q一U是Z专家评分的方法;一U是Z点击l计的方法?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">专家评分的方法通常由搜索核心技术研发和产品人员来进行,Ҏ(gu)预先讑֮的标准对A、B两套环境的结果给予评分,获取每个Query的结果对比,q根据nDCG{方法计整体质量?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">点击评分有更高的自动化程度,q里使用了一个假设:(x)同样的排序位|,点击数量多的l果质量优于点击数量的l果。(即A2表示A试环境W?条结果,如果A2 > B2Q则表示A2质量更好Q。通俗的说Q相信群众(因ؓ(f)众的眼睛是雪亮的)。在q个假设前提下,我们可以A/B环境前N条结果的点击率自动映ؓ(f)评分Q通过l计大量的Query点击l果Q可以获得可靠的评分Ҏ(gu)?/p><h3>Interleaving Testing</h3><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">另外2003q由Thorsten Joachims {h提出的Interleaving testingҎ(gu)也被q泛使用。该Ҏ(gu)设计了一个元搜烦(ch)引擎Q用戯入查询词后,查询词在几个著名搜索引擎中的查询结果随机؜合反馈给用户Qƈ攉随后用户的结果点击行Z息.Ҏ(gu)用户不同的点d֐性,可以判断搜索引擎返回结果的优劣Q?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">如下图所C,算法A和B的结果交叉放|,q分量q行试Q记录用L(fng)M息。根据点d布来判断A和B环境的优劣?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; overflow-x: auto; width: 964.25px; overflow-y: hidden; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><img border="0" _href="img://image1.jpg" _p="true" src="http://www.infoq.com/resource/articles/cyw-evaluate-seachengine-result-quality/zh/resources/image18.jpg" alt="" style="box-sizing: border-box; border: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" /></p><p align="center" style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;"><strong style="box-sizing: border-box;">Interleaving Testing评估Ҏ(gu)</strong></p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">Joachims同时证明了Interleaving Testing评h(hun)Ҏ(gu)与传lCranfield评h(hun)Ҏ(gu)的结果具有较高的相关性。由于记录用户选择(g)索结果的行ؓ(f)是一个不耗费人力的过E,因此可以便捷的实现自动化的搜索效果评估?/p><h2>ȝ</h2><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">没有评估没有进?#8212;—Ҏ(gu)索效果的量化评测Q目的是准确的找出现有搜索系l的不Q没有哪个搜索系l是完美的)Q进而一步一个脚印对法、系l进行改q。本文ؓ(f)大家ȝ了常用的评h(hun)框架和评h标。这些技术像一把把子Q度量着搜烦(ch)技术每一ơ前q的距离?/p><hr style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;" /><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">感谢<a style="box-sizing: border-box; color: #0b59b2;">张凯?/a>?本文的审校?/p><p style="box-sizing: border-box; color: #4b4b4b; font-size: 13px; font-family: Lucida, 'Lucida Grande', Tahoma, sans-serif; line-height: 19px; background-color: #ffffff;">lInfoQ中文站投E或者参与内容翻译工作,请邮件至<a href="mailto:editors@cn.infoq.com" style="box-sizing: border-box; color: #0b59b2;">editors@cn.infoq.com</a>。也Ƣ迎大家加入?a target="_blank" style="box-sizing: border-box; color: #0b59b2;">InfoQ中文站用戯论组</a>中与我们的编辑和其他读?朋友交流?/p><div></div><img src ="http://www.shnenglu.com/wanghaiguang/aggbug/197078.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/wanghaiguang/" target="_blank">王v?/a> 2013-01-07 16:46 <a href="http://www.shnenglu.com/wanghaiguang/archive/2013/01/07/197078.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HOOK介绍http://www.shnenglu.com/wanghaiguang/archive/2012/11/05/194544.html王v?/dc:creator>王v?/author>Mon, 05 Nov 2012 03:27:00 GMThttp://www.shnenglu.com/wanghaiguang/archive/2012/11/05/194544.htmlhttp://www.shnenglu.com/wanghaiguang/comments/194544.htmlhttp://www.shnenglu.com/wanghaiguang/archive/2012/11/05/194544.html#Feedback0http://www.shnenglu.com/wanghaiguang/comments/commentRss/194544.htmlhttp://www.shnenglu.com/wanghaiguang/services/trackbacks/194544.html一、基本概念:(x)

钩子(Hook)Q是Windows消息处理机制的一个^?应用E序可以在上面设|子E以监视指定H口的某U消息,而且所监视的窗口可以是其他q程所创徏的。当消息到达后,在目标窗口处理函C前处理它。钩子机制允许应用程序截获处理window消息或特定事件?/span>

钩子实际上是一个处理消息的E序D,通过pȝ调用Q把它挂入系l。每当特定的消息发出Q在没有到达目的H口前,钩子E序先捕获该消息,亦即钩子函数先得到控制权。这旉子函数即可以加工处理Q改变)该消息,也可以不作处理而l传递该消息Q还可以强制l束消息的传递?/span>

二、运行机Ӟ(x)

1、钩子链表和钩子子程Q?/span>

每一个Hook都有一个与之相兌的指针列表,UC为钩子链表,ql来l护。这个列表的指针指向指定的,应用E序定义的,被Hook子程调用的回调函敎ͼ也就是该钩子的各个处理子E。当与指定的Hookcd兌的消息发生时Q系l就把这个消息传递到Hook子程。一些Hook子程可以只监视消息,或者修Ҏ(gu)息,或者停止消息的前进Q避免这些消息传递到下一个Hook子程或者目的窗口。最q安装的钩子攑֜铄开始,而最早安装的钩子攑֜最后,也就是后加入的先获得控制权?/span>

Windows q不要求钩子子程的卸载顺序一定得和安装顺序相反。每当有一个钩子被卸蝲QW(xu)indows 侉K攑օ占用的内存,q更新整个Hook链表。如果程序安装了钩子Q但是在未卸蝲钩子之前q束了Q那么系l会(x)自动为它做卸载钩子的操作?/span>

钩子子程是一个应用程序定义的回调函数(CALLBACK Function),不能定义成某个类的成员函敎ͼ只能定义为普通的C函数。用以监视系l或某一特定cd的事Ӟq些事g可以是与某一特定U程兌的,也可以是pȝ中所有线E的事g?/span>

钩子子程必须按照以下的语法:(x)
1 LRESULT CALLBACK HookProc
2 (
3      int nCode, 
4          WPARAM wParam, 
5          LPARAM lParam
6 );
HookProc是应用程序定义的名字?/span>
nCode参数是Hook代码QHook子程使用q个参数来确定Q务。这个参数的g赖于HookcdQ每一UHook都有自己的Hook代码特征字符集?/span>
wParam和lParam参数的g赖于Hook代码Q但是它们的典型值是包含了关于发送或者接收消息的信息?/span>

2、钩子的安装与释放:(x)

使用API函数SetWindowsHookEx()把一个应用程序定义的钩子子程安装到钩子链表中。SetWindowsHookEx函数L在Hook铄开头安装Hook子程。当指定cd的Hook监视的事件发生时Q系l就调用与这个Hook兌的Hook铄开头的Hook子程。每一个Hook链中的Hook子程都决定是否把q个事g传递到下一个Hook子程。Hook子程传递事件到下一个Hook子程需要调用CallNextHookEx函数?/span> 
 1 HHOOK SetWindowsHookEx( 
 2      int idHook,      // 钩子的类型,卛_处理的消息类?/span>
 3      HOOKPROC lpfn,   // 钩子子程的地址指针。如果dwThreadId参数?
 4                                              // 或是一个由别的q程创徏的线E的标识Q?br /> 5                                              // lpfn必须指向DLL中的钩子子程?br /> 6                                              // 除此以外Qlpfn可以指向当前q程的一D钩子子E代码?br /> 7                                              // 钩子函数的入口地址Q当钩子钩到M消息后便调用q个函数?/span>
 8      HINSTANCE hMod,  // 应用E序实例的句柄。标识包含lpfn所指的子程?/span>DLL?/span>
10                                              // 如果dwThreadId 标识当前q程创徏的一个线E,
11                                              // 而且子程代码位于当前q程QhMod必须为NULL?br />12                                              // 可以很简单的讑֮其ؓ(f)本应用程序的实例句柄?/span>
13      DWORD dwThreadId // 与安装的钩子子程相关联的U程的标识符?br />14                                              // 如果?Q钩子子E与所有的U程兌Q即为全局钩子?/span>
15                  ); 
  
函数成功则返回钩子子E的句柄Q失败返回NULL?/span>

以上所说的钩子子程与线E相兌是指在一钩子链表中发l该U程的消息同时发送给钩子子程Q且被钩子子E先处理?/span>

在钩子子E中调用得到控制权的钩子函数在完成对消息的处理后Q如果想要该消息l箋传递,那么它必调用另外一个SDK中的API函数CallNextHookEx来传递它Q以执行钩子链表所指的下一个钩子子E。这个函数成功时q回钩子链中下一个钩子过E的q回|q回值的cd依赖于钩子的cd。这个函数的原型如下Q?br />
1 LRESULT CallNextHookEx
2             (
3                 HHOOK hhk;
4                 int nCode;
5                 WPARAM wParam;
6                 LPARAM lParam;
7              );
hhk为当前钩子的句柄Q由SetWindowsHookEx()函数q回?/span>
NCodeZl钩子过E的事g代码?/span>
wParam和lParam 分别是传l钩子子E的wParam|其具体含义与钩子cd有关?/span>
  
钩子函数也可以通过直接q回TRUE来丢弃该消息QƈL该消息的传递。否则的话,其他安装了钩子的应用E序不?x)接收到钩子的通知而且q有可能产生不正的l果?/span>

钩子在用完之后需要用UnHookWindowsHookEx()卸蝲Q否则会(x)造成ȝ(ch)。释N子比较简单,UnHookWindowsHookEx()只有一个参数。函数原型如下:(x)
1 UnHookWindowsHookEx
2 (
3     HHOOK hhk;
4 );
函数成功q回TRUEQ否则返回FALSE?/span>

3、一些运行机Ӟ(x)

在Win16环境中,DLL的全局数据Ҏ(gu)个蝲入它的进E来说都是相同的Q而在Win32环境中,情况却发生了变化QDLL函数中的代码所创徏的Q何对象(包括变量Q都归调用它的线E或q程所有。当q程在蝲入DLLӞ操作pȝ自动把DLL地址映射到该q程的私有空_(d)也就是进E的虚拟地址I间Q而且也复制该DLL的全局数据的一份拷贝到该进E空间。也是说每个进E所拥有的相同的DLL的全局数据Q它们的名称相同Q但其值却q不一定是相同的,而且是互不干涉的?/span>

因此Q在Win32环境下要惛_多个q程中共享数据,必进行必要的讄。在讉K同一个Dll的各q程之间׃n存储器是通过存储器映文件技术实现的。也可以把这些需要共享的数据分离出来Q放|在一个独立的数据D里Qƈ把该D늚属性设|ؓ(f)׃n。必ȝq些变量赋初|否则~译器会(x)把没有赋初始值的变量攑֜一个叫未被初始化的数据D中?/span>

#pragma data_seg预处理指令用于设|共享数据段。例如:(x)
1 #pragma data_seg("SharedDataName")
2 HHOOK hHook=NULL;
3 #pragma data_seg()
?pragma data_seg("SharedDataName")?pragma data_seg()之间的所有变?被讉K该Dll的所有进E看到和׃n?/span>

当进E隐式或昑ּ调用一个动态库里的函数Ӟpȝ都要把这个动态库映射到这个进E的虚拟地址I间?以下U?地址I间")。这使得DLL成ؓ(f)q程的一部分Q以q个q程的n份执行,使用q个q程的堆栈?/span>

4、系l钩子与U程钩子Q?/span>

SetWindowsHookEx()函数的最后一个参数决定了此钩子是pȝ钩子q是U程钩子?/span>
    
U程勑֭用于监视指定U程的事件消息。线E勾子一般在当前U程或者当前线E派生的U程内?/span>
    
pȝ勑֭监视pȝ中的所有线E的事g消息。因为系l勾子会(x)影响pȝ中所有的应用E序Q所以勾子函数必L在独立的动态链接库(DLL) 中。系l自动将包含"钩子回调函数"的DLL映射到受钩子函数影响的所有进E的地址I间中,卛_q个DLL注入了那些进E?/span>

几点说明Q?/span>
Q?Q如果对于同一事gQ如鼠标消息Q既安装了线E勾子又安装了系l勾子,那么pȝ?x)自动先调用U程勑֭Q然后调用系l勾子?

Q?Q对同一事g消息可安装多个勾子处理过E,q些勑֭处理q程形成了勾子链。当前勾子处理结束后应把勑֭信息传递给下一个勾子函数?

Q?Q勾子特别是pȝ勑֭?x)消耗消息处理时_(d)降低pȝ性能。只有在必要的时候才安装勑֭Q在使用完毕后要?qing)时卸蝲?/span>

三、钩子类?/span>

每一U类型的Hook可以使应用程序能够监视不同类型的pȝ消息处理机制。下面描q所有可以利用的Hookcd?/span>

1、WH_CALLWNDPROC和W(xu)H_CALLWNDPROCRET Hooks

WH_CALLWNDPROC和W(xu)H_CALLWNDPROCRET Hooks使你可以监视发送到H口q程的消息。系l在消息发送到接收H口q程之前WH_CALLWNDPROCHook子程Qƈ且在H口q程处理完消息之后调用WH_CALLWNDPROCRET Hook子程?/span>

WH_CALLWNDPROCRET Hook传递指针到CWPRETSTRUCTl构Q再传递到Hook子程。CWPRETSTRUCTl构包含了来自处理消息的H口q程的返回|同样也包括了与这个消息关联的消息参数?/span>

2、WH_CBT Hook

在以下事件之前,pȝ都会(x)调用WH_CBT Hook子程Q这些事件包括:(x)
1. Ȁz,建立Q销毁,最化Q最大化Q移动,改变寸{窗口事Ӟ
2. 完成pȝ指o(h)Q?/span>
3. 来自pȝ消息队列中的Ud鼠标Q键盘事Ӟ
4. 讄输入焦点事gQ?/span>
5. 同步pȝ消息队列事g?/span>
    
Hook子程的返回值确定系l是否允许或者防止这些操作中的一个?/span>

3、WH_DEBUG Hook

在系l调用系l中与其他Hook兌的Hook子程之前Q系l会(x)调用WH_DEBUG Hook子程。你可以使用q个Hook来决定是否允许系l调用与其他Hook兌的Hook子程?/span>

4、WH_FOREGROUNDIDLE Hook

当应用程序的前台U程处于I闲状态时Q可以用WH_FOREGROUNDIDLE Hook执行低优先的Q务。当应用E序的前台线E大概要变成I闲状态时Q系l就?x)调用WH_FOREGROUNDIDLE Hook子程?/span>

5、WH_GETMESSAGE Hook

应用E序使用WH_GETMESSAGE Hook来监视从GetMessage or PeekMessage函数q回的消息。你可以使用WH_GETMESSAGE Hookȝ视鼠标和键盘输入Q以?qing)其他发送到消息队列中的消息?/span>

6、WH_JOURNALPLAYBACK Hook

WH_JOURNALPLAYBACK Hook使应用程序可以插入消息到pȝ消息队列。可以用这个Hook回放通过使用WH_JOURNALRECORD Hook记录下来的连l的鼠标和键盘事件。只要WH_JOURNALPLAYBACK Hook已经安装Q正常的鼠标和键盘事件就是无效的。WH_JOURNALPLAYBACK Hook是全局HookQ它不能象线E特定Hook一样用。WH_JOURNALPLAYBACK Hookq回时|q个值告诉系l在处理来自回放Hook当前消息之前需要等待多长时_(d)毫秒Q。这׃Hook可以控制实时事g的回放。WH_JOURNALPLAYBACK是system-wide local hooksQ它們不會被注射CQ何行E位址I間?/span>

7、WH_JOURNALRECORD Hook

WH_JOURNALRECORD Hook用来监视和记录输入事件。典型的Q可以用这个Hook记录q箋的鼠标和键盘事gQ然后通过使用WH_JOURNALPLAYBACK Hook来回放。WH_JOURNALRECORD Hook是全局HookQ它不能象线E特定Hook一样用。WH_JOURNALRECORD是system-wide local hooksQ它們不會被注射CQ何行E位址I間?/span>

8、WH_KEYBOARD Hook

在应用程序中QW(xu)H_KEYBOARD Hook用来监视WM_KEYDOWN and WM_KEYUP消息Q这些消息通过GetMessage or PeekMessage functionq回。可以用这个Hook来监视输入到消息队列中的键盘消息?/span>

9、WH_KEYBOARD_LL Hook

WH_KEYBOARD_LL Hook监视输入到线E消息队列中的键盘消息?/span>

10、WH_MOUSE Hook

WH_MOUSE Hook监视从GetMessage 或?PeekMessage 函数q回的鼠标消息。用这个Hook监视输入到消息队列中的鼠标消息?/span>

11、WH_MOUSE_LL Hook

WH_MOUSE_LL Hook监视输入到线E消息队列中的鼠标消息?/span>

12、WH_MSGFILTER ?WH_SYSMSGFILTER Hooks

WH_MSGFILTER ?WH_SYSMSGFILTER Hooks使我们可以监视菜单,滚动条,消息框,对话框消息ƈ且发现用户用ALT+TAB or ALT+ESC l合键切换窗口。WH_MSGFILTER Hook只能监视传递到菜单Q滚动条Q消息框的消息,以及(qing)传递到通过安装了Hook子程的应用程序徏立的对话框的消息。WH_SYSMSGFILTER Hook监视所有应用程序消息?/span>
    
WH_MSGFILTER ?WH_SYSMSGFILTER Hooks使我们可以在模式循环期间qo(h)消息Q这{h(hun)于在L息@环中qo(h)消息?/span>
    
通过调用CallMsgFilter function可以直接的调用WH_MSGFILTER Hook。通过使用q个函数Q应用程序能够在模式循环期间使用相同的代码去qo(h)消息Q如同在L息@环里一栗?/span>

13、WH_SHELL Hook

外壳应用E序可以使用WH_SHELL HookL攉要的通知。当外壳应用E序是激zȝq且当顶层窗口徏立或者销毁时Q系l调用WH_SHELL Hook子程?/span>
WH_SHELL 共有Q钟情況Q?/span>
1. 只要有个top-level、unowned H口被生、v作用、或是被摧毁Q?/span>
2. 当Taskbar需要重L个按钮;
3. 当系l需要显C关于Taskbar的一个程序的最化形式Q?/span>
4. 当目前的键盘布局状态改变;
5. 当用者按Ctrl+EscL行Task ManagerQ或相同U别的程序)?/span>

    按照惯例Q外壛_用程序都不接收WH_SHELL消息。所以,在应用程序能够接收WH_SHELL消息之前Q应用程序必调用SystemParametersInfo function注册它自己?/span>

以上转自Q?a >http://www.microsoft.com/china/community/program/originalarticles/techdoc/hook.mspx
以下转自Q?/span>http://topic.csdn.net/t/20030513/03/1774836.html

CallNextHookEx 作用

Hook   串鏈QHook   ChainsQ?
當許多程式都安裝了某E型態的hook   時,會形成一個filter-function   chain。一旦特?的event   發生QW(xu)indows   會呼叫該型態中最新掛上的hook   filter   function。舉個例Q如?E式A   掛上了一個system-wide   WH_KEYBOARD   hookQ每當有M埯R取得鍵盤訊 息,W(xu)indows   會呼叫這個filter   function。如果程式B   也掛上了一個system-wide WH_KEYBOARD   hookQ那麼當event   發生QW(xu)indows   不再呼叫E式A   的filter   functionQ?改呼叫程式B的filter   function。這也意味每一個filter   function   有Kȝ保先前掛上的filter Windows   95   E式a計指南QWindows   95   :   A   Developer’s   GuideQ?394 function   被呼叫(也就是維護串鏈的完整性)?SetWindowsHookEx   函式會將新掛上的hook   filter   function   的代傳回。Q何程式只要掛 上一個新的filter   function   必須儲存這個代|通常存放在全域變怸Q:(x)
static   HHOOK   g_hhook   =   NULL;
.   .   .
g_hhook   =   SetWindowsHookEx(WH_KEYBOARD,   Example_kybdHook,   hinst,   NULL);
.   .   .
如果有錯誤發生,SetWindowsHookEx   函式會傳回NULL?
如果你希望hook   chain   中的其它filter   functions   也能夠執行,你可以在你的filter   function 中呼叫CallNextHookEx   函式Q或a׃已經在先前的Example_KybdHook   函式片段中注?CQ?nbsp;

LRESULT   CallNextHookEx(HHOOK   hhook,   int   nCode,   WPARAM   wParam,   LPARAM   lParam);
這個函式會呼叫filter-function   chain   的下一個filter   functionQ並傛_相同的nCode?wParam   和lParam。下一個filter   function   i束之前Q應該也遵@這個規則去呼叫 CallNextHookEx   函式Q並再次hook   代碼Q通常那是被放在全域變怸Q傳入?CallNextHookEx   函式利用這個hook   代碼Q走a整個串鏈,決定哪一個filter   function   ?
下一個呼叫目標。如果CallNextHookEx   函式發現已經沒有下一個filter   function   可以呼叫 Q走C鏈盡頭了Q,它會傛_0Q否則它?yu)傳回「下一個filter   function   埯後的傛_倹{?nbsp;

你可能會在許多文Ӟ包括SDK   文gQ中發現一個有關CallNextHookEx   函式的過氣警告:(x)「如 果nCode   於0Q則hook   函式應該不做M處理Q直接將它交iCallNextHookEx   函式Q並傛_ CallNextHookEx   函式的回q倹{。這並不是真的Q而且自Windows   3.0   以來Q那時還在用舊版的 SetWindowsHook   函式Q就已經不是真的了!撰寫E式時,你可以完全不理會這項警告?
W6章訊息攔截(HooksQ?395

有些時候你可能不希望呼叫其他的filter   functionsQ這種情況下你只要不在你的filter function   中呼叫CallNextHookEx   函式卛_。只要不CallNextHookEx   函式攑ֈ你的filter
function   中,你就不會呼叫其他的filter   functionsQ而你也因此可以指定你自己的傳回倹{?不幸的是Q這裡埋伏著一個陷阱:(x)另一個執行緒可能也為你安裝了一個hookQ新的filter
function   於是比你的filter   function   更早被喚P而它可能不呼叫你的filter   functionQ完?了!這個問沒有一般性的解決Ҏ(gu)Q如果你先將自己的hook   協RQ然後再重新掛上Q?那麼你的filter   function   成為最新的一個,會最先被呼叫。沒錯,但你不能夠保證其?Z會依樣畫葫蘆。簡a之,hooks   是一個合作機Ӟ沒有M保障?



]]>微Y研究院Detour开发包之API拦截技?/title><link>http://www.shnenglu.com/wanghaiguang/archive/2012/11/02/194179.html</link><dc:creator>王v?/dc:creator><author>王v?/author><pubDate>Fri, 02 Nov 2012 06:32:00 GMT</pubDate><guid>http://www.shnenglu.com/wanghaiguang/archive/2012/11/02/194179.html</guid><wfw:comment>http://www.shnenglu.com/wanghaiguang/comments/194179.html</wfw:comment><comments>http://www.shnenglu.com/wanghaiguang/archive/2012/11/02/194179.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/wanghaiguang/comments/commentRss/194179.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/wanghaiguang/services/trackbacks/194179.html</trackback:ping><description><![CDATA[<div class="uscogy4" id="cnblogs_post_body"> <p><span style="font-family: Verdana; font-size: 12pt">我们截获函数执行最直接的目的就是ؓ(f)函数增添功能Q修改返回|或者ؓ(f)调试以及(qing)性能试加入附加的代码,或者截获函数的输入输出作研IӞ破解使用。通过?问源代码Q我们可以轻而易丄使用重徏QRebuildingQ操作系l或者应用程序的Ҏ(gu)在它们中间插入新的功能或者做功能扩展。然而,在今天这个商?化的开发世界里Q以?qing)在只有二进制代码发布的pȝ中,研究人员几乎没有Z(x)可以得到源代码。本文主要讨论Detour在Windows二进制PE文g基础 上的API截获技术。对于Linuxq_Q作qg事情会(x)非常的简单,׃最初的操作pȝ设计者引入了LD_PRELOAD。如果你讄  LD_PRELOAD=mylib.so Q那么应用程序在载入 dllӞ?x)先查看mylib.so的符可Q在relocation 的时候会(x)优先 使用mylib.so 里的 symbol 。假如你在mylib.so里有个printf() Q那么这个printf׃(x)替代libc?printf?而在mylib.so里的q个printf可以直接讉K libc.so里的printf函数指针来获得真正的 printf的入口地 址?q样Q所有的dll的API HOOK在loader加蝲dll的时候就已经完成Q非常自?dng)和^台相关的部分全部交给loaderd理?/span><br /><span style="font-family: Verdana; font-size: 12pt">一?nbsp; Detour开发库Q?/span><br /><span style="font-family: Verdana; font-size: 12pt">?nbsp; ?/span><br /><span style="font-family: Verdana; font-size: 12pt">Detours是一个在x86q_上截获Q意Win32函数调用的工具库。中断代码可以在q行时动态加载。Detours使用一个无条g转移指o(h)来替换目 标函数的最初几条指令,控制流转移C个用h供的截获函数。而目标函C的一些指令被保存在一个被UCؓ(f)“trampoline” Q译注:(x)英文意ؓ(f)y?床,杂技Q的函数中,在这里我觉得译成目标函数的部分克隆/拯比较贴切。这些指令包括目标函C被替换的代码以及(qing)一个重新蟩转到目标函数的无条g?支。而截获函数可以替换目标函敎ͼ或者通过执行“trampoline”函数的时候将目标函数作ؓ(f)子程序来调用的办法来扩展功能?/span><br /><span style="font-family: Verdana; font-size: 12pt">Detours是执行时被插入的。内存中的目标函数的代码不是在硬盘上被修改的Q因而可以在一个很好的_度上得截获二q制函数的执行变得更Ҏ(gu)。例如, 一个应用程序执行时加蝲的DLL中的函数q程可以被插入一D|获代码(detouredQ,与此同时Q这个DLLq可以被其他应用E序按正常情冉|行(?注:(x)也就是按照不被截L(fng)方式执行Q因为DLL二进制文件没有被修改Q所以发生截h不会(x)影响其他q程I间加蝲q个DLLQ。不同于DLL的重新链接或?静态重定向QDetours库中使用的这U中断技术确保不?x)?jing)响到应用E序中的Ҏ(gu)或者系l代码对目标函数的定位?/span><br /><span style="font-family: Verdana; font-size: 12pt">如果其他Zؓ(f)了调试或者在内部使用其他pȝ(g)手D而试图修改二q制代码QDetours是一个可以普遍用的开发包。据我所知,Detours是第一 个可以在Lq_上将未修改的目标代码作ؓ(f)一个可以通过“trampoline”调用的子E序来保留的开发包。而以前的pȝ在逻辑上预先将截获代码攑ֈ?标代码中Q而不是将原始的目标代码做Z个普通的子程序来调用。我们独特的“trampoline”设计对于扩展现有的Y件的二进制代码是臛_重要的?/span><br /><span style="font-family: Verdana; font-size: 12pt">Z使用基本的函数截获功能的目的QDetours同样提供了编辑Q何DLL导入表的功能Q达到向存在的二q制代码中添加Q意数据节表的目的Q向一个新q?E或者一个已l运行着的进E中注入一个DLL。一旦向一个进E注入了DLLQ这个动态库可以截获Q何Win32函数Q不论它是在应用E序中或者在pȝ?中?/span><br /><span style="font-family: Verdana; font-size: 12pt">?nbsp; 基本原理</span><br /><span style="font-family: Verdana; font-size: 12pt">1Q?nbsp; WIN32q程的内存管?</span><br /><span style="font-family: Verdana; font-size: 12pt">众所周知QW(xu)INDOWS NT实现了虚拟存储器Q每一WIN32q程拥有4GB的虚存空_(d) 关于WIN32q程的虚存结构及(qing)其操作的具体l节请参阅WIN32 API手册Q?以下仅指ZDetours相关的几点:(x) </span><br /><span style="font-family: Verdana; font-size: 12pt">(1) q程要执行的指o(h)也放在虚存空间中 </span><br /><span style="font-family: Verdana; font-size: 12pt">(2) 可以使用QueryProtectEx函数把存放指令的面的权限更改ؓ(f)可读可写可执行,再改写其内容Q从而修Ҏ(gu)在运行的E序 </span><br /><span style="font-family: Verdana; font-size: 12pt">(3) 可以使用VirtualAllocEx从一个进Eؓ(f)另一正运行的q程分配虚存Q再使用 QueryProtectEx函数把页面的权限更改为可d写可执行Qƈ把要执行的指令以二进制机器码的Ş式写入,从而ؓ(f)一个正在运行的q程注入L的代??/span><br /><span style="font-family: Verdana; font-size: 12pt">2Q?拦截WIN32 API的原?</span><br /><span style="font-family: Verdana; font-size: 12pt">Detours定义了三个概念:(x)</span><br /><span style="font-family: Verdana; font-size: 12pt">    (1) Target函数Q要拦截的函敎ͼ通常为Windows的API?/span><br /><span style="font-family: Verdana; font-size: 12pt">(2) Trampoline函数QTarget函数的部分复制品。因为Detours会(x)改写Target函数Q所以先把Target函数的前5个字节复制保存好Q一斚w仍然保存Target函数的过E调用语义,另一斚w便于以后的恢复?/span><br /><span style="font-family: Verdana; font-size: 12pt">(3) Detour 函数Q用来替代Target函数的函数?</span><br /><span style="font-family: Verdana; font-size: 12pt">Detours在Target函数的开头加入JMP Address_of_ Detour_ Function指o(h)Q共5个字节)把对Target函数 的调用引导到自己的Detour函数Q?把Target函数的开头的5个字节加上JMP Address_of_ Target _ Function+ 5?0个字节作为Trampoline函数。请参考下面的?和图2?/span><br /><span style="font-family: Verdana; font-size: 12pt">(?QDetour函数的过E?</span><br /><a ></a> <img border="0" alt="" src="http://www.shnenglu.com/images/cppblog_com/wanghaiguang/crack_01_thumb.jpg" width="620" longdesc="" height="460" /><br /><span style="font-family: Verdana; font-size: 12pt">Q图2Q?Detour函数的调用过E)</span><br /><a ></a> <img border="0" alt="" src="http://www.shnenglu.com/images/cppblog_com/wanghaiguang/crack_02_thumb.jpg" longdesc="" /><br /><span style="font-family: Verdana; font-size: 12pt">说明Q?/span><br /><span style="font-family: Verdana; font-size: 12pt">?nbsp; 目标函数Q?/span><br /><span style="font-family: Verdana; font-size: 12pt">目标函数的函CQ二q制Q至有5个字节以上。按照微软的说明文档Trampoline函数的函C是拷贝前5个字节加一个无条g跌{指o(h)的话Q如果没 有特D处理不可分割指令的话)Q那么前5个字节必L完整指o(h)Q也是不能W?个字节和W?个字节是一条不可分割的指o(h)Q否则会(x)造成Trampoline 函数执行错误Q一条完整的指o(h)被硬性分割开来,造成E序崩溃。对于第5字节和第6个字节是不可分割指o(h)需要调整拷贝到杂技函数(Trampoline)?字节个数Q这个值可以查看目标函数的汇编代码得到。此函数是目标函数的修改版本Q不能在Detour函数中直接调用,需要通过对Trampoline函数 的调用来辑ֈ间接调用?/span><br /><span style="font-family: Verdana; font-size: 12pt">?nbsp; Trampoline函数Q?/span><br /><span style="font-family: Verdana; font-size: 12pt">此函数默认分配了32个字节,函数的内容就是拷贝的目标函数的前5个字节,加上一个JMP Address_of_ Target _ Function+5指o(h),?0个字节?/span><br /><span style="font-family: Verdana; font-size: 12pt">此函C供?zhn)的Detour函数调用Q执行完?个字节的指o(h)后再l对跌{到目标函数的W?个字节l执行原功能函数?/span><br /><span style="font-family: Verdana; font-size: 12pt">?nbsp; Detour函数Q?/span><br /><span style="font-family: Verdana; font-size: 12pt">此函数是用户需要的截获API的一个模拟版本,调用方式Q参C数必d目标函数怸致。如目标函数是__stdcallQ则Detour函数声明也必?是__stdcall,参数个数和类型也必须相同Q否则会(x)造成E序崩溃。此函数在程序调用目标函数的W一条指令的时候就?x)被调用Q无条g跌{q来的)Q如 果在此函C想l调用目标函敎ͼ必须调用Trampoline函数QTrampoline函数在执行完目标函数的前5个字节的指o(h)后会(x)无条件蟩转到目标 函数?个字节后l箋执行Q,不能再直接调用目标函敎ͼ否则进入无I递归Q目标函数蟩转到Detour函数QDetour函数又蟩转到目标函数的递归Q?因ؓ(f)目标函数在内存中的前5个字节已l被修改成绝对蟩转)。通过对Trampoline函数的调用后可以获取目标函数的执行结果,此特性对分析目标函数?常有用,而且可以目标函数的输出l果q行修改后再传回l应用程序?/span><br /><span style="font-family: Verdana; font-size: 12pt">Detour提供了向q行中的应用E序注入Detour函数和在二进制文件基上注入Detour函数两种方式。本章主要讨论第二种工作方式。通过 Detours提供的开发包可以在二q制EXE文g中添加一个名UCؓ(f)Detour的节表,如下?所C,主要目的是实现PE加蝲器加载应用程序的时候会(x)?动加载?zhn)~写的Detours DLLQ在Detours Dll中的DLLMain中完成对目标函数的Detour?/span><br /><span style="font-family: Verdana; font-size: 12pt">Q图3Q?/span><br /><a ></a> <img border="0" alt="" src="http://www.shnenglu.com/images/cppblog_com/wanghaiguang/crack_03_thumb.jpg" width="506" longdesc="" height="299" /><br /><span style="font-family: Verdana; font-size: 12pt">二?nbsp; Detours提供的截获API的相x?/span><br /><span style="font-family: Verdana; font-size: 12pt">Detours的提供的API 接口可以作ؓ(f)一个共享DLLl外部程序调用,也可以作Z个静态Lib链接到?zhn)的程序内部?/span><br /><span style="font-family: Verdana; font-size: 12pt">Trampoline函数可以动态或者静态的创徏Q如果目标函数本w是一个链接符P使用静态的trampoline函数非常简单。如果目标函C能在链接时可见,那么可以使用动态trampoline函数?/span><br /><span style="font-family: Verdana; font-size: 12pt">?nbsp; 要用静态的trampoline函数来截L(fng)标函敎ͼ应用E序生成trampoline的时候必M?/span><br /><span style="font-family: Verdana; font-size: 12pt">DETOUR_TRAMPOLINE宏。DETOUR_TRAMPOLINE有两个输入参敎ͼ(x)trampoline的原型和目标函数的名字?/span><br /><span style="font-family: Verdana; font-size: 12pt">注意Q对于正的截获模型Q包括目标函敎ͼtrampoline函数Q以?qing)截获函数都必须是完全一致的调用形式Q包括参数格式和调用U定。当通过 trampoline函数调用目标函数的时候拷贝正参数是截获函数的责仅R由于目标函C仅是截获函数的一个可调用分支Q截获函数可以调?trampoline函数也可以不调用Q,q种责Q几乎是一U下意识的行为?/span><br /><span style="font-family: Verdana; font-size: 12pt">使用相同的调用约定可以确保寄存器中的D正确的保存,q且保证调用堆栈在截获函数调用目标函数的时候能正确的徏立和销毁?/span><br /><span style="font-family: Verdana; font-size: 12pt">可以使用DetourFunctionWithTrampoline函数来截L(fng)标函数。这个函数有两个参数Qtrampoline函数以及(qing)截获函数的指针。因为目标函数已l被加到trampoline函数中,所有不需要在参数中特别指定?/span><br /><span style="font-family: Verdana; font-size: 12pt">?nbsp; 我们可以使用DetourFunction函数来创Z个动态的trampoline函数Q它包括两个参数Q一个指向目标函数的指针和一个截获函数的指针。DetourFunction分配一个新的trampoline函数q将适当的截获代码插入到目标函数中去?/span><br /><span style="font-family: Verdana; font-size: 12pt">当目标函C是很Ҏ(gu)使用的时候,DetourFindFunction函数可以扑ֈ那个函数Q不它是DLL中导出的函数Q或者是可以通过二进制目标函数的调试W号扑ֈ?/span><br /><span style="font-family: Verdana; font-size: 12pt">DetourFindFunction接受两个参数Q库的名字和函数的名字。如果DetourFindFunction函数扑ֈ了指定的函数Q返回该函数 的指针,否则返回一个NULL指针。DetourFindFunction?x)首先用Win32函数LoadLibrary ?GetProcAddress来定位函敎ͼ如果函数没有在DLL的导中找刎ͼDetourFindFunction用ImageHlp库来搜烦(ch)?效的调试W号Q译注:(x)q里的调试符h指Windows本n提供的调试符P需要单独安装,具体信息请参考Windows的用戯断支持信息)?DetourFindFunctionq回的函数指针可以用来传递给DetourFunction以生成一个动态的trampoline函数?/span><br /><span style="font-family: Verdana; font-size: 12pt">我们可以调用DetourRemoveTrampoline来去掉对一个目标函数的截获?/span><br /><span style="font-family: Verdana; font-size: 12pt">注意Q因为Detours中的函数?x)修改应用程序的地址I间Q请保当加入截获函数或者去掉截获函数的时候没有其他线E在q程I间中执行,q是E序员的责Q。一个简单的Ҏ(gu)保证q个时候是单线E执行就是在加蝲Detours库的时候在DllMain中呼叫函数?/span><br /><span style="font-family: Verdana; font-size: 12pt">三?nbsp; 使用Detours实现对API的截L(fng)两种Ҏ(gu)</span><br /><span style="font-family: Verdana; font-size: 12pt">建立一个MFC对话框工E,在对话框的OK按钮的单M件中加入对MessageBoxA函数的调用,~译后的E序名称MessageBoxApp,效果如图?/span><br /><a ></a> <img border="0" alt="" src="http://www.shnenglu.com/images/cppblog_com/wanghaiguang/crack_04_thumb.jpg" longdesc="" /><br /><span style="font-family: Verdana; font-size: 12pt">(?)</span><br /><span style="font-family: Verdana; font-size: 12pt">?nbsp; 静态方?/span><br /><span style="font-family: Verdana; font-size: 12pt">建立一个Dll工程Q名UCؓ(f)ApiHookQ这里以Visual C++6.0开发环境,以截获ASCII版本的MessageBoxA函数来说明。在Dll的工E加入:(x)</span><br /><span style="font-family: Verdana; font-size: 12pt">DETOUR_TRAMPOLINE(int WINAPI Real_Messagebox(HWND hWnd ,</span><br /><span style="font-family: Verdana; font-size: 12pt">    LPCSTR lpText,</span><br /><span style="font-family: Verdana; font-size: 12pt">    LPCSTR lpCaption,</span><br /><span style="font-family: Verdana; font-size: 12pt">UINT uType), ::MessageBoxA);</span><br /><span style="font-family: Verdana; font-size: 12pt">生成一个静态的MessageBoxA的Trampoline函数Q在Dll工程中加入目标函数的Detour函数Q?/span><br /><span style="font-family: Verdana; font-size: 12pt">int WINAPI MessageBox_Mine( HWND hWnd ,</span><br /><span style="font-family: Verdana; font-size: 12pt">    LPCSTR lpText,</span><br /><span style="font-family: Verdana; font-size: 12pt">    LPCSTR lpCaption,</span><br /><span style="font-family: Verdana; font-size: 12pt">    UINT uType)</span><br /><span style="font-family: Verdana; font-size: 12pt">{</span><br /><span style="font-family: Verdana; font-size: 12pt">  CString tmp= lpText;</span><br /><span style="font-family: Verdana; font-size: 12pt">  tmp+=” 被Detour截获”;</span><br /><span style="font-family: Verdana; font-size: 12pt">  return Real_Messagebox(hWnd,tmp,lpCaption,uType);</span><br /><span style="font-family: Verdana; font-size: 12pt">//  return ::MessageBoxA(hWnd,tmp,lpCaption,uType);  //Error </span><br /><span style="font-family: Verdana; font-size: 12pt">}</span><br /><span style="font-family: Verdana; font-size: 12pt">在Dll入口函数中的加蝲Dll事g中加入:(x)</span><br /><span style="font-family: Verdana; font-size: 12pt">DetourFunctionWithTrampoline((PBYTE)Real_Messagebox, (PBYTE)MessageBox_Mine);</span><br /><span style="font-family: Verdana; font-size: 12pt">在Dll入口函数中的卸蝲Dll事g中加入:(x)</span><br /><span style="font-family: Verdana; font-size: 12pt">DetourRemove((PBYTE)Real_Messagebox, (PBYTE)MessageBox_Mine);</span><br /><span style="font-family: Verdana; font-size: 12pt">?nbsp; 动态方?/span><br /><span style="font-family: Verdana; font-size: 12pt">建立一个Dll工程Q名UCؓ(f)ApiHookQ这里以Visual C++6.0开发环境,以截获ASCII版本的MessageBoxA函数来说明。在Dll的工E加入:(x)</span><br /><span style="font-family: Verdana; font-size: 12pt">//声明MessageBoxA一L(fng)函数原型</span><br /><span style="font-family: Verdana; font-size: 12pt">typedef int  (WINAPI * MessageBoxSys)( HWND hWnd ,</span><br /><span style="font-family: Verdana; font-size: 12pt">    LPCSTR lpText,</span><br /><span style="font-family: Verdana; font-size: 12pt">    LPCSTR lpCaption,</span><br /><span style="font-family: Verdana; font-size: 12pt">    UINT uType);</span><br /><span style="font-family: Verdana; font-size: 12pt">//目标函数指针</span><br /><span style="font-family: Verdana; font-size: 12pt">MessageBoxSys SystemMessageBox=NULL;</span><br /><span style="font-family: Verdana; font-size: 12pt">//Trampoline函数指针</span><br /><span style="font-family: Verdana; font-size: 12pt">MessageBoxSys Real_MessageBox=NULL;</span><br /><span style="font-family: Verdana; font-size: 12pt">在Dll工程中加入目标函数的Detour函数Q?/span><br /><span style="font-family: Verdana; font-size: 12pt">int WINAPI MessageBox_Mine( HWND hWnd ,</span><br /><span style="font-family: Verdana; font-size: 12pt">    LPCSTR lpText,</span><br /><span style="font-family: Verdana; font-size: 12pt">    LPCSTR lpCaption,</span><br /><span style="font-family: Verdana; font-size: 12pt">    UINT uType)</span><br /><span style="font-family: Verdana; font-size: 12pt">{</span><br /><span style="font-family: Verdana; font-size: 12pt">  CString tmp= lpText;</span><br /><span style="font-family: Verdana; font-size: 12pt">  tmp+=” 被Detour截获”;</span><br /><span style="font-family: Verdana; font-size: 12pt">  return Real_Messagebox(hWnd,tmp,lpCaption,uType);</span><br /><span style="font-family: Verdana; font-size: 12pt">//  return ::MessageBoxA(hWnd,tmp,lpCaption,uType);  //Error </span><br /><span style="font-family: Verdana; font-size: 12pt">}</span><br /><span style="font-family: Verdana; font-size: 12pt">在Dll入口函数中的加蝲Dll事g中加入:(x)</span><br /><span style="font-family: Verdana; font-size: 12pt">  SystemMessageBox=(MessageBoxSys)DetourFindFunction("user32.dll","MessageBoxA");</span><br /><span style="font-family: Verdana; font-size: 12pt">  if(SystemMessageBox==NULL)</span><br /><span style="font-family: Verdana; font-size: 12pt">  {</span><br /><span style="font-family: Verdana; font-size: 12pt">    return FASLE;</span><br /><span style="font-family: Verdana; font-size: 12pt">  }</span><br /><span style="font-family: Verdana; font-size: 12pt">  Real_MessageBox=(MessageBoxSys)DetourFunction((PBYTE)SystemMessageBox, (PBYTE)MessageBox_Mine);</span><br /><span style="font-family: Verdana; font-size: 12pt">在Dll入口函数中的卸蝲Dll事g中加入:(x)</span><br /><span style="font-family: Verdana; font-size: 12pt">DetourRemove((PBYTE)Real_Messagebox, (PBYTE)MessageBox_Mine);</span><br /><span style="font-family: Verdana; font-size: 12pt">?nbsp; 重写二进制可执行文g</span><br /><span style="font-family: Verdana; font-size: 12pt">使用Detours自带的SetDll.exe重写二进制可执行文gQ可以在需要截L(fng)E序中加入一个新的Detours的PE节表。对于本文就是新Z个批处理文g调用SetDll.exe?/span><br /><span style="font-family: Verdana; font-size: 12pt">@echo off</span><br /><span style="font-family: Verdana; font-size: 12pt">if not exist MessageBoxApp.exe (</span><br /><span style="font-family: Verdana; font-size: 12pt">echo 请将文g解压到MessageBoxApp.exe的安装目? 然后执行补丁E序</span><br /><span style="font-family: Verdana; font-size: 12pt">) else (</span><br /><span style="font-family: Verdana; font-size: 12pt">setdll /d:ApiHook.dll MessageBoxApp.exe</span><br /><span style="font-family: Verdana; font-size: 12pt">)</span><br /><span style="font-family: Verdana; font-size: 12pt">Pause</span><br /><span style="font-family: Verdana; font-size: 12pt">调用后用depends.exeQ微软VC6.0开发包的工具之一Q观察MessageBoxApp.exe前后变化Q?可以看到Setdll已经重写MessageBoxApp.exe</span><br /><span style="font-family: Verdana; font-size: 12pt">成功Q加入了对ApiHook.dll的依赖关pR?/span><br /><a ></a> <img border="0" alt="" src="http://www.shnenglu.com/images/cppblog_com/wanghaiguang/crack_05_thumb.jpg" width="872" longdesc="" height="220" /><br /><span style="font-family: Verdana; font-size: 12pt">      Q执行SetDll.exe前)                                                       (执行SetDll.exe?</span><br /><span style="font-family: Verdana; font-size: 12pt">执行SetDll.exe重写后的MessageBoxApp.exeQ点ȝ定后可以看到l果如下Q?/span><br /><span style="font-family: Verdana; font-size: 12pt">xQMessageBoxApp.exe对MessageBoxA函数的调用已l被截获Q弹出的对话框内容已l明显说明这一炏V?/span><br /><img border="0" alt="" src="http://www.shnenglu.com/images/cppblog_com/wanghaiguang/crack_06_thumb.jpg" width="407" longdesc="" height="263" /><br /><br /><span style="font-family: Verdana; font-size: 12pt">本文转自Q?/span><a ><span style="font-family: Verdana; font-size: 12pt">http://www.cnblogs.com/flying_bat/archive/2008/04/18/1159996.html</span></a></p></div><img src ="http://www.shnenglu.com/wanghaiguang/aggbug/194179.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/wanghaiguang/" target="_blank">王v?/a> 2012-11-02 14:32 <a href="http://www.shnenglu.com/wanghaiguang/archive/2012/11/02/194179.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>? 数学之美W记http://www.shnenglu.com/wanghaiguang/archive/2012/09/21/191509.html王v?/dc:creator>王v?/author>Fri, 21 Sep 2012 09:50:00 GMThttp://www.shnenglu.com/wanghaiguang/archive/2012/09/21/191509.htmlhttp://www.shnenglu.com/wanghaiguang/comments/191509.htmlhttp://www.shnenglu.com/wanghaiguang/archive/2012/09/21/191509.html#Feedback0http://www.shnenglu.com/wanghaiguang/comments/commentRss/191509.htmlhttp://www.shnenglu.com/wanghaiguang/services/trackbacks/191509.html 半个月前在豆瓣上看到了一本新书《数学之》,评h(hun)很高。而因为在半年前看了《什么是数学》就Ҏ(gu)学生浓厚兴,但苦于水q不的我便立马C一本,希望能对数学多一些了解,q认真阅读v来?
        令我意外q欣喜的是,q本书里边的数学内容q不晦ӆ难懂Q而且作者ؓ(f)了讲q数学之而搭配的一些工E实例都是和我学?fn)ƈ感兴的模式识别Q目标分cȝ关算法相兌的。这让我觉得捡到了意外的宝藏?
        书中每一个章节都或多或少是作者亲w经历过的,比如世界U教授的故事,或者Google的搜索引擎原理,又或者是Google的云计算{。作者用其行云流水般的语a各个知识点像讲故事一h的叙述出来?
        q本书着实让我印象深刻,所以我把笔记分享出来,希望更多和我学习(fn)研究领域一L(fng)Z(x)喜欢q亲自阅读这本书Qƈ能支持作者。毕竟国内这U书实在是太了Q也希望能有更多领域内的大牛能再写出一些这U书c来让我们共同提高?
1.    因ؓ(f)需要传播信息量的增加,不同的声韛_ƈ不能完全表达信息Q语a便生了?
2.    当文字增加到没有完全C所有文字时Q聚cd归类开始了。例如日代表太阳或者代表一天?
3.    聚类?x)带来歧义性,但上下文可以消除歧义。信息冗余是信息安全的保障。例如罗塞塔石碑上同一信息重复三次?
4.    最短编码原理即常用信息短编码,生僻信息长编码?
5.    因ؓ(f)文字只是信息的蝲体而非信息本nQ所以翻译是可以实现的?
6.    2012Q其实是玛雅文明采用二十q制Q即四百q是一个太阳纪Q?012q恰巧是当前太阳U的最后一q_(d)2013q是新的太阳U的开始,故被误传Z界末日?
7.    字母可以看ؓ(f)是一l编码,而汉字可以看Zl编码?
8.    Zl计的自然语a处理Ҏ(gu)Q在数学模型上和通信是相通的Q甚x相同的?
9.    让计机处理自然语言的基本问题就是ؓ(f)自然语言q种上下文相关的Ҏ(gu)徏立数学模型,即统计语a模型QStatistical Language ModalQ?
10.    Ҏ(gu)大数定理QLaw of Large NumbersQ,只要l计量够,相对频度q于概率?
11.    二元模型。对于p(w1,w2,…,wn)=p(w1)p(w2|w1)p(w3|w1,w2)…p(wn|w1,w2,…,wn-1)的展开问题Q因为p(w3|w1,w2)难计,p(wn|w1,w2,…,wn-1)更难计算Q马?dng)科夫给Z一个偷懒但是颇为有效的Ҏ(gu)Q也是每当遇到q种情况Ӟ假设Q意wi出现的概率只与它前面的wi-1有关Q即p(s)=p(w1)p(w2|w1)p(w3|w2)…p(wi|wi-1)…p(wn|wn-1)。现在这个概率就变的单了。对应的语言模型?元模型(Bigram ModelQ?
12.    *N元模型。wi只与前一个wi-1有关q似的过头了Q所以N-1阉?dng)科夫假设?f)p(wi|w1,w2,…,wi-1)=p(wi|wi-N+1,wi-N+2,…,wi-1)Q对应的语言模型成ؓ(f)N元模型(N-Gram ModelQ。一元模型就是上下文无关模型Q实际应用中更多实用的是三元模型。Google的罗塞塔译pȝ和语a搜烦(ch)pȝ实用的是四元模型Q存储于500C上的Google服务器中?
13.    *卡兹退避法QKatz backoffQ,对于频率过一定阈值的词,它们的概率估计就是它们在语料库中的相寚w度,对于频率于q个阈值的词,它们的概率估计就于他们的相寚w度,出现ơ数少Q频率下调越多。对于未看见的词Q也l予一个比较小的概率(即下调得到的频率dQ,q样所有词的概率估计都qx了。这是卡兹退避法QKatz backoffQ?
14.    训练数据通常是越多越好,通过qxq渡的方法可以解决零概率和很概率的问题Q毕竟在数据量多的时候概率模型的参数可以估计的比较准?
15.    利用l计语言模型q行分词Q即最好的分词Ҏ(gu)应该保证分完词后q个句子出现的概率最大。根据不同应用,汉语分词的颗_度大小应该不同?
16.    W合马尔U夫假设Q各个状态st的概率分布只与它前一个状态st-1有关Q的随即q程x为马?dng)科夫过E,也称为马?dng)科夫链?
17.    隐含马尔U夫模型是马?dng)科夫链的扩展,L时刻t的状态st是不可见的,所以观察者没法通过观察C个状态序列s1,s2,s3,…,sT来推{UL率等参数。但是隐马尔U夫模型在每个时刻t?x)输Z个符号otQ而且ot和st相关且仅和ot相关。这个被UCؓ(f)独立输出假设。其中隐含的状态s1,s2,s3,…是一个典型的马尔U夫链?
18.    隐含马尔U夫模型是机器学?fn)主要工具之一Q和几乎所有机器学?fn)的模型工具一P它需要一个训l算法(鲍姆-韦尔奇算法)和用时的解码算法(l特比算法)。掌握了q两cȝ法,基本上可以使用隐含马尔U夫模型q个工具了?
19.    鲍姆-韦尔奇算法(Baum-Welch AlgorithmQ,首先扑ֈ一l能够生输出序列O的模型参敎ͼq个初始模型成ؓ(f)Mtheta0Q需要在此基上找C个更好的模型Q假定不但可以算个模型生O的概率P(O|Mtheta0)Q而且能够扑ֈq个模型产生O的所有可能的路径以及(qing)q些路径的概率。ƈ出一l新的模型参数theta1Q从Mtheta0到Mtheta1的过E称ZơP代。接下来从Mtheta1出发L更好的模型Mtheta2Qƈ一直找下去Q直到模型的质量没有明显提高为止。这样一直估计(ExpectationQ新的模型参敎ͼ使得输出的概率达到最大化QMaximizationQ的q程被称为期望值最大化QExpectation-MaximizationQ简UEMq程。EMq程能保证一定能收敛C个局部最优点Q但不能保证扑ֈ全局最优点。因此,在一些自然语a处理的应用中Q这U无监督的鲍?韦尔奇算法训l处的模型比有监督的训练得到的模型效果略差?
20.    熵,信息늚定义为H(X)=-SumP(x)logP(x)Q变量的不确定性越大,熵也大?
21.    一个事物内部会(x)存在随机性,也就是不定性,假定为UQ而从外部消除q个不确定性唯一的办法是引入信息IQ而需要引入的信息量取决于q个不确定性的大小Q即I>U才行。当I<UӞq些信息可以消除一部分不确定性,U'=U-I。反之,如果没有信息QQ何公C或者数字的游戏都无法排除不定性?
22.    信息的作用在于消除不定性?
23.    互信息,对两个随Z件相x的量化度量Q即随机事gX的不定性或者说熵H(X)Q在知道随机事gY条g下的不确定性,或者说条g熵H(X|Y)之间的差异,即I(X;Y)=H(X)-H(X|Y)。所谓两个事件相x的量化度量Q即在了解了其中一个Y的前提下Q对消除另一个X不确定性所提供的信息量?
24.    相对熵(Kullback-Leibler DivergenceQ也叫交叉熵Q对两个完全相同的函敎ͼ他们的相对熵为零Q相对熵大Q两个函数差异越大,反之Q相对熵小Q两个函数差异越;对于概率分布或者概率密度函敎ͼ如果取值均大于Ӟ相对熵可以度量两个随机分布的差异性?
25.    弗里德里?#183;N克QF(tun)rederek JelinekQ是自然语言处理真谛的先p?
26.    技术分为术和道两种Q具体的做事Ҏ(gu)是术Q做事的原理和原则是道。术?x)从独门l技到普?qing)再到落伍,q求术的Z(x)很辛苦,只有掌握了道的本质和_N才能永远游刃有余?
27.    真理在Ş式上从来是简单的Q而不是复杂和含؜的?
28.    搜烦(ch)引擎不过是一张大表,表的每一行对应一个关键字Q而每一个关键字后面跟着一l数字,是包含该关键词的文献序号。但当烦(ch)引变的非常大的时候,q些索引需要通过分布式的方式存储C同的服务器上?
29.    |络爬虫QWeb CrawlersQ,图论的遍历算法和搜烦(ch)引擎的关pR互联网虽然复杂Q但是说I了其实是一张大?#8230;…可以把每一个网当做一个节点,把那些超链接当做q接|页的弧。有了超链接Q可以从M一个网出发,用图的遍历算法,自动讉K到每一个网ƈ且把他们存储h。完成这个功能的E序叫网l爬虫?
30.    哥尼斯堡七桥Q如果一个图能从一个顶点出发,每条边不重复的遍历一遍回到这个顶点,那么每一个顶点的度必Mؓ(f)偶数?
31.    构徏|络爬虫的工E要点:(x)1.用BFSQ广度优先搜索)q是DFSQ深度优先搜索)Q一般是先下载完一个网站,再进入下一个网站,即BFS的成分多一些?.面的分析和URL的提取,如果有些|页明明存在Q但搜烦(ch)引擎q没有收录,可能的原因之一是网l爬虫中的解析程序没能成功解析网中不规范的脚本E序?.记录哪些|页已经下蝲q的URL表,可以用哈希表。最l,好的Ҏ(gu)一般都采用了这样两个技术:(x)首先明确每台下蝲服务器的分工Q也是在调度时Q一看到某个URLq道要交给哪台服务器去下蝲Q这样就避免了很多服务器对同一个URL做出是否需要下载的判断。然后,在明分工的基础上,判断URL是否下蝲可以批处理了,比如每次向哈希表Q一l独立的服务器)发送一大批询问Q或者每ơ更C大批哈希表的内容Q这样通信的次数就大大减少了?
32.    PageRank衡量|页质量的核心思想Q在互联|上Q如果一个网被很多其他|页所链接Q说明它受到普遍的承认和信赖Q那么它的排名就高。同Ӟ对于来自不同|页的链接区别对待,因ؓ(f)|页排名高的那些|页的链接更可靠Q于是要l这些链接比较大的权重?
33.    TF-IDF(Term Frequency / Inverse Document Frequency) Q关键词频率-逆文本频率|其中QTF为某个网上出现关键词的频率QIDF为假定一个关键词w在Dw个网中出现q,那么Dw大Qw的权重越,反之亦然Q公式ؓ(f)log(D/Dw)?.一个词预测主题的能力越强,权重大Q反之,权重小?.停止词的权重为零?
34.    动态规划(Dynamic ProgrammingQ的原理Q将一个寻扑օE最优的问题分解成一个个L局部最优的问题?
35.    一个好的算法应该像L器中最有名的AK-47冲锋枪那P(x)单、有效、可靠性好而且Ҏ(gu)LQ易操作Q而不应该故弄玄虚。选择单方案可以容易解释每个步骤和Ҏ(gu)背后的道理,q样不仅便于出问题时的查错,也容易找C后改q的目标?
36.    在实际的分类中,可以先进行奇异值分解(得到分类l果略显_糙但能较快得到l果Q,在粗分类l果的基上,利用计算向量余u的方法(对范围内的分cd两两计算Q,在粗分类l果的基上,q行几次q代Q得到比较精的l果?
37.    奇异值分解(Singular Value DecompositionQ,在需要用一个大矩阵A(ch)来描q成千上万文章和几十上百万词的关联性时Q计量非常大,可以A奇异值分解ؓ(f)X、B和Y三个矩阵QAmn=Xmm*Bmn*YnnQX表示词和词类的相x,Y表示文本和主题的相关性,B表示词类和主题的相关性,其中B对角U上的元素很多值相对其他的非常,或者ؓ(f)Ӟ可以省略。对兌矩阵A(ch)q行一ơ奇异值分解,可以同时完成近义词分类和文章的分类Q同时能得到每个主题和每个词义类之间的相x,q个l果非常漂亮?
38.    信息指纹。如果能够找CU函敎ͼ?000亿网址随即地映到128位二q制Q也是16字节的整数空_(d)qq?6字节的随机数做该|址的信息指UV信息指U可以理解ؓ(f)一D信息映到一个多l二q制I间中的一个点Q只要这个随卛_数做的好Q那么不同信息对应的点不?x)重合,因此q个二进制的数字变成了原来信息所h的独一无二的指UV?
39.    判断两个集合是否相同Q最W的Ҏ(gu)是这个集合中的元素一一比较Q复杂度O(squareN)Q稍好的是将元素排序后顺序比较,复杂度O(NlogN)Q最完美的方法是计算q两个集合的指纹Q然后直接进行比较,计算复杂度O(N)?
40.    伪随机数产生器算法(Pseudo-Random Number GeneratorQPRNGQ,q是产生信息指纹的关键算法,通过他可以将L长的整数转换成特定长度的伪随机数。最早的PRNG是将一个数的^Ҏ(gu)头去֏中间Q当然这U方法不是很随即Q现在常用的是梅旋转算法(Mersenne TwisterQ?
41.    在互联网上加密要使用Z加密的伪随机C生器QCryptography Secure Pseudo-Random Number GeneratorQCSPRNGQ,常用的算法有MD5或者SHA-1{标准,可以不定长的信息变成定长的128位或?60位二q制随机数?
42.    最大熵模型QMaximum EntropyQ的原理是保留全部的不定性,风险降到最。最大熵原理指出Q需要对一个随Z件的概率分布q行预测Ӟ我们的预应当满_部已知的条gQ而对未知的情况不要做M主观假设。在q种情况下,概率分布最均匀Q预的风险最。I.Csiszar证明Q对M一l不自相矛盾的信息,q个最大熵模型不仅存在Q而且是唯一的,此外Q他们都有同一个非常简单的形式-指数函数?
43.    通用q代法QGeneralized Iterative ScalingQGISQ是最原始的最大熵模型的训l方法?.假定W零ơP代的初始模型为等概率的均匀分布?.用第NơP代的模型来估每U信息特征在训练数据中的分布。如果超q了实际的,把相应的模型参数变,反之变大?.重复步骤2直至收敛。这是一U典型的期望值最大化QExpectation MaximizationQEMQ算法。IIS(Improved Iterative Scaling)比GIS~短了一C个数量?
44.    布隆qo(h)器实际上是一个很长的二进制向量和一pd随机映射的函数?
45.    贝叶斯网l从数学的层面讲是一个加权的有向图,是马?dng)科夫链的扩展,而从知识论的层面看,贝叶斯网l克服了马尔U夫那种机械的线性的U束Q它可以把Q何有兌的事件统一到它的框架下面。在|络中,假定马尔U夫假设成立Q即每一个状态只与和它直接相q的状态有养I而和他间接相q的状态没有直接关p,那么它就是贝叶斯|络。在|络中每个节Ҏ(gu)率的计算Q都可以用贝叶斯公式来进行,贝叶斯网l也因此得名。由于网l的每个弧都有一个可信度Q贝叶斯|络也被UC信念|络QBelief NetworksQ?
46.    条g随机场是计算联合概率分布的有效模型。在一个隐含马?dng)科夫模型中Q以x1,x2,...,xn表示观测值序列,以y1,y2,...,yn表示隐含的状态序列,那么xi只取决于产生它们的状态yi,和前后的状态yi-1和yi+1都无兟뀂显然很多应用里观察值xi可能和前后的状态都有关Q如果把xi和yi-1,yi,yi+1都考虑q来Q这L(fng)模型是条g随机场。它是一U特D的概率图模型(Probablistic Graph ModelQ,它的Ҏ(gu)性在于,变量之间要遵守马?dng)科夫假设,x个状态的转移概率只取决于盔R的状态,q一点和另一U概率图模型贝叶斯网l相同,它们的不同之处在于条仉机场是无向图Q而贝叶斯|络是有向图?
47.    l特比算法(Viterbi AlgoritmQ是一个特D但应用最q的动态规划算法,利用动态规划,可以解决M一个图中的最短\径问题。它之所以重要,是因为凡是用隐含马?dng)科夫模型描q的问题都可以用它来解码?.从点S出发Q对于第一个状态x1的各个节点,不妨假定有n1个,计算出SC们的距离d(S,x1i)Q其中x1i代表L状?的节炏V因为只有一步,所以这些距都是SC们各自的最短距R?.对于W二个状态x2的所有节点,要计出从SC们的最短距Rd(S,x2i)=min_I=1,n1_d(S,x1j)+d(x1j,x2i)Q由于j有n1U可能性,需要一一计算Q然后找到最倹{这样对于第二个状态的每个节点Q需要n1ơ乘法计。假定这个状态有n2个节点,把Sq些节点的距都一遍,有O(n1*n2)ơ运?.按照上述Ҏ(gu)从第二个状态走到第三个状态一直走到最后一个状态,q样得到整个网l从头到最短\径?
48.    扩频传输QSpread-Spectrum TransmissionQ和固定频率的传输相比,有三Ҏ(gu)昄好处Q?.抗干扰能力强?.信号能量非常低,很难获取?.扩频传输利用带宽更充分?
49.    Google针对云计给出的解决工具是MapReduceQ其Ҏ(gu)原理是计算机算法上常见的分ȝ法(Divide-and-ConquerQ。将一个大d拆分成小的子dQƈ完成子Q务的计算Q这个过E叫MapQ将中间l果合ƈ成最l结果,q个q程叫Reduce?
50.    逻辑回归模型QLogistic RegressionQ是一个事件出现的概率适应C条逻辑曲线QLogistic CurveQ上。典型的逻辑回归函数Qf(z)=e`z/e`z+1=1/1+e`-z。逻辑曲线是一条S型曲U,其特Ҏ(gu)开始变化快Q逐渐减慢Q最后饱和。逻辑自回归的好处是它的变量范围从负无I到正无IP而值域范围限制?-1之间。因为值域的范围在0-1之间Q这样逻辑回归函数可以和一个概率分别联pv来了。因变量范围在负无穷到正无穷之间Q它?yu)可以把信号l合hQ不论组合成多大或者多的|最后依然能得到一个概率分布?
51.    期望最大化法QExpectation Maximization AlgorithmQ,Ҏ(gu)现有的模型,计算各个观测数据输入到模型中的计结果,q个q程UCؓ(f)期望D过E(ExpectationQ,或Eq程Q接下来Q重新计模型参敎ͼ以最大化期望|q个q程UCؓ(f)最大化的过E(MaximizationQ,或Mq程。这一cȝ法都UCؓ(f)EM法Q比如隐含马?dng)科夫模型的训练?gu)Baum-Welch法Q以?qing)最大熵模型的训l方法GIS法?br />
本文转自Q?a href="http://www.shnenglu.com/humanchao">http://www.shnenglu.com/humanchao


]]>如何写好UIE序 http://www.shnenglu.com/wanghaiguang/archive/2012/09/05/189522.html王v?/dc:creator>王v?/author>Wed, 05 Sep 2012 02:45:00 GMThttp://www.shnenglu.com/wanghaiguang/archive/2012/09/05/189522.htmlhttp://www.shnenglu.com/wanghaiguang/comments/189522.htmlhttp://www.shnenglu.com/wanghaiguang/archive/2012/09/05/189522.html#Feedback0http://www.shnenglu.com/wanghaiguang/comments/commentRss/189522.htmlhttp://www.shnenglu.com/wanghaiguang/services/trackbacks/189522.html在Windowsq_做开发肯定会(x)接触到UIE序的编写,以MFC的UI开发ؓ(f)例,可以开发单文档Q多文档Q对话框{Ş式的应用。写一个UIE序Ҏ(gu)Q写好却不是一件简单的事情。在整个代码l构的清晰性与可维护性方面需要多加注意。写好UIE序需求注意以下几点:(x)

 

1、围l数据编E与不是围绕UI~程

 

当我们拿到需求最先接触到的就是UI的设计,也许是美工画的,也许是设计草图。工E师在具体设计的时候容易受UI的媄(jing)响,或者干脆从UI开始编E?/span>

 

q是一个错误的~程?fn)惯Q无论UI如何展现与交互,最l都应该围绕数据~程。拿到需求后Q应该先思考和推敲数据的设计与{QUI不过是数据的一U展现Ş式而已?/span>

 

2、做好UI与逻辑的解?/span>

 

UI的编E会(x)涉及(qing)到许多控件的操作Q消息的处理Q不知不觉,一个UIcȝ代码?x)越写越大,以至于一D|间以后,览和梳理都?x)变得不太方ѝ?/span>

 

在UIc里Q除了与UI本n的操作有关的代码以外QQ何逻辑代码都应该与此解耦,q根据具体情况进行封装调用。如果一个控件关联了太多数据操作Q应该把q些操作装到控件的l承cMQ把一cM码进行集中管理和l护?/span>

 

上述问题Q在E序写作的初期还不太明显Q随着代码逐渐膨胀Q会(x)会(x)让人难以忍受?/span>

 

3、数据单向依赖,单向更新

 

UI围绕的数据进行展C更新Q在q个q程中,所以对数据的操作应该进行封装,而不是散落在UIE序在各个角落,数据的更新、获取和UI传递消息时Q应该单向操作,如果出现循环处理的情况,在以后维护调试的BUG的过E中?x)变得比较困难,Dl护效率下降?/span>

 

本文来自CSDN博客Q{载请标明出处Q?/span>http://www.shnenglu.com/humanchao



]]>
优秀E序员的特征 http://www.shnenglu.com/wanghaiguang/archive/2012/07/17/183832.html王v?/dc:creator>王v?/author>Tue, 17 Jul 2012 00:13:00 GMThttp://www.shnenglu.com/wanghaiguang/archive/2012/07/17/183832.htmlhttp://www.shnenglu.com/wanghaiguang/comments/183832.htmlhttp://www.shnenglu.com/wanghaiguang/archive/2012/07/17/183832.html#Feedback1http://www.shnenglu.com/wanghaiguang/comments/commentRss/183832.htmlhttp://www.shnenglu.com/wanghaiguang/services/trackbacks/183832.html什么样的程序员U得上优UQ根据我所看到Q有如下体会(x)Q?

1、不愿意就的h

E序设计工作是一地地道道的脑力力_Q把工作做得很好和做的很差往往只在工作中的一个小的l节Q我发现我n边优U的程序员都不太喜Ƣ将,始终把自q计算机和自己的开发环境调整到最佳状态,原来带我的老员工甚至会(x)自己写一些小工具Q来提高工作效率?/span>

2、不喜欢蛮干

脑力力_与体力劳动不同,很多时候很N过单的量的U篏辑ֈ目的Q尤其是处理一些难题的时候。一味的蛮干Q加班几乎天生与高手无缘。没有思\的时候,换个环境Q也许答案就在明天上班的路上惌v?/span>

3、愿意思考、专注改q?/strong>

E序员与其他力_者相|熟练了以后都?x)Ş成惯性思维Q会(x)不自觉的用自׃(fn)惯的方式解决问题Q但问题的Ş式与本质M(x)变化Q只有不断的改进才能使工作效率不断提高。而把脑力力_变成体力力_的现象在实际工作中比比皆是?/span>

4、良好的基础和不断的学习(fn)

良好的基与不断的学习(fn)是天生的一对孪生兄弟,因ؓ(f)基础好所以学的快Q因为学得快Q所以基本功好。良好学?fn)?fn)惯不是不停的单追t新技术,一斚w是了解新技术,另一斚w需要不断的弥补思维盲区Q学?fn)可以有很多U状态,有一U是M而知一Q技也,有一U是M而知三,术也Q有一U是M而知十,道也?/span>

5、直接切入问题的能力

在解决一个问题的时候,有些人L能够直接切入问题核心Q而有些hL喜欢x边缘问题。直入主题是一U核心能力,需要思考,实践Q改q,U篏Q提高,周而复使,螺旋上升。另外我觉得q与思维方式与知识面关系很大Q多涉猎一些领域没有坏处?/span>

***p***Q呵呵,对,q是pQ流利的听说d?/span>


本文来自CSDN博客Q{载请标明出处Q?/span>http://www.shnenglu.com/humanchao



]]>断言式编E?/title><link>http://www.shnenglu.com/wanghaiguang/archive/2012/04/12/171069.html</link><dc:creator>王v?/dc:creator><author>王v?/author><pubDate>Thu, 12 Apr 2012 04:58:00 GMT</pubDate><guid>http://www.shnenglu.com/wanghaiguang/archive/2012/04/12/171069.html</guid><wfw:comment>http://www.shnenglu.com/wanghaiguang/comments/171069.html</wfw:comment><comments>http://www.shnenglu.com/wanghaiguang/archive/2012/04/12/171069.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/wanghaiguang/comments/commentRss/171069.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/wanghaiguang/services/trackbacks/171069.html</trackback:ping><description><![CDATA[<span style="font-size: 14pt">本文转自Q?a href="http://www.shnenglu.com/humanchao/archive/2008/08/19/59309.html">http://www.shnenglu.com/humanchao/archive/2008/08/19/59309.html</a><br /><br />我们先看一个函敎ͼ(x)函数的功能完?~10的加法?br /><br /> <div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff">int</span><span style="color: #000000"> Add1to10(</span><span style="color: #0000ff">int</span><span style="color: #000000"> a, </span><span style="color: #0000ff">int</span><span style="color: #000000"> b)<br />{<br />   </span><span style="color: #0000ff">return</span><span style="color: #000000"> a </span><span style="color: #000000">+</span><span style="color: #000000">b;<br />}<br /></span></div><br />但是一般我们还需要加上几条代码:(x)<br /><br /> <div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff">int</span><span style="color: #000000"> Add1to10(</span><span style="color: #0000ff">int</span><span style="color: #000000"> a, </span><span style="color: #0000ff">int</span><span style="color: #000000"> b)<br />{<br />    assert(a </span><span style="color: #000000">>=</span><span style="color: #000000"> </span><span style="color: #000000">1</span><span style="color: #000000"> </span><span style="color: #000000">&&</span><span style="color: #000000"> a </span><span style="color: #000000"><=</span><span style="color: #000000"> </span><span style="color: #000000">10</span><span style="color: #000000">);<br />    assert(b </span><span style="color: #000000">>=</span><span style="color: #000000"> </span><span style="color: #000000">1</span><span style="color: #000000"> </span><span style="color: #000000">&&</span><span style="color: #000000"> b </span><span style="color: #000000"><</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000">10</span><span style="color: #000000">);<br /><br />    </span><span style="color: #0000ff">if</span><span style="color: #000000"> ( a </span><span style="color: #000000"><</span><span style="color: #000000"> </span><span style="color: #000000">1</span><span style="color: #000000"> </span><span style="color: #000000">||</span><span style="color: #000000"> a </span><span style="color: #000000">></span><span style="color: #000000"> </span><span style="color: #000000">10</span><span style="color: #000000"> </span><span style="color: #000000">||</span><span style="color: #000000"> b </span><span style="color: #000000"><</span><span style="color: #000000"> </span><span style="color: #000000">1</span><span style="color: #000000"> </span><span style="color: #000000">||</span><span style="color: #000000"> b </span><span style="color: #000000">></span><span style="color: #000000"> </span><span style="color: #000000">10</span><span style="color: #000000">)<br />        </span><span style="color: #0000ff">return</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">;<br /><br />    </span><span style="color: #0000ff">return</span><span style="color: #000000"> a </span><span style="color: #000000">+</span><span style="color: #000000">b;<br />}</span></div><br />加上上面几条代码的作用是(g)查函数的输入参数Q当参数不正的时候不光要在返回g得到体现Q而且?x)触发assert断言Q提醒我们参数有误?br /><br />断言式编E体C个编E的思想Q在我们的程序执行偏预想的路线时给出提醒。当E序执行偏离预想的\U时一般会(x)出现两种可能Q即断言以上的程序没有理解下面程序的调用条g、或断言以下的程序需要接受更为宽泛输入条件。以下分别讨ZҎ(gu)法:(x)<br /><br />1、如果函数的输入参数是我们编E的一个疏漏,我们认ؓ(f)Ҏ(gu)׃应该出现或生这L(fng)|那我们应该修改调用函数处的代码,避免非预想的值出现?br /><br />2、如果无法避免出现或者生一个非法输入|那我们要么在函数调用处加入判断,产生W合条g的值时调用函数Q不W合参数条gelse处理Q要么修改函敎ͼ使函数可以接受更为宽泛输入条Ӟq调整断a内容和参数判断逻辑?br /><br />断言不仅可以出现在函数的参数(g)查的场合Q也可以出现在其他的上下文调用的场合。而且它还?x)随着E序的开发进E逐渐的增加、删除和调整。它可以验证E序是按照我们预想的思\在执行,当出现意外时?qing)时的给出提醒,提醒我们修正E序或者自q思\?/span> <img src ="http://www.shnenglu.com/wanghaiguang/aggbug/171069.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/wanghaiguang/" target="_blank">王v?/a> 2012-04-12 12:58 <a href="http://www.shnenglu.com/wanghaiguang/archive/2012/04/12/171069.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]写好代码?0个秘?http://www.shnenglu.com/wanghaiguang/archive/2012/04/09/170576.html王v?/dc:creator>王v?/author>Mon, 09 Apr 2012 05:36:00 GMThttp://www.shnenglu.com/wanghaiguang/archive/2012/04/09/170576.htmlhttp://www.shnenglu.com/wanghaiguang/comments/170576.htmlhttp://www.shnenglu.com/wanghaiguang/archive/2012/04/09/170576.html#Feedback0http://www.shnenglu.com/wanghaiguang/comments/commentRss/170576.htmlhttp://www.shnenglu.com/wanghaiguang/services/trackbacks/170576.html[转]写好代码?0个秘?收藏
作者:(x)飞哥 Q百度)

先给大家看一D|说是史上最强的E序Q?br />e100 33 f6 bf 0 20 b5 10 f3 a5 8c c8 5 0 2 50 68 13 1 cb e 1f be a1 1 bf 0 1
e11b 6 57 b8 11 1 bb 21 13 89 7 4b 4b 48 79 f9 ad 86 e0 8b c8 bd ff ff e8 20
e134 0 3d 0 1 74 1a 7f 3 aa eb f3 2d ff 0 50 e8 f 0 5a f7 d8 8b d8 26 8a 1 aa
e14f 4a 75 f9 eb de cb 57 bb 21 13 8b c1 40 f7 27 f7 f5 8b fb ba 11 1 4f 4f 4a
e168 39 5 7f f9 52 8b c5 f7 25 f7 37 2b c8 95 f7 65 2 f7 37 95 2b e8 fe e fe
e181 10 79 6 c6 6 fe 10 7 46 d0 14 d1 d1 d1 e5 79 ec 5a b8 11 1 ff 7 4b 4b 48
e19b 3b d0 75 f7 5f c3 83 f7 83 a6 5d 59 82 cd b2 8 42 46 9 57 a9 c5 ca aa 1b
.............................................................................


q段E序?997q世界程序设计大赛的一{奖作品的部分代码(完整的代码下载,把代码复制粘贴到cmd的debug命o(h)中,回R看到效果Q。这个程序运行后是一?D的且伴随着音乐的动甅R震撼吧Q?br />是不是从事Y件开发的人员都希望成L(fng)武林高手呢?然而真要是用这L(fng)高手来设计、编写我们的产品代码Q恐怕某一天,我们什么都不用q了Q只能h手一本机器代码,一句一句进行翻译了Q那么对于Y件品开发而言Q如何写好代码呢Q一的软g产品的代码具备哪些特征呢Q?/p>


 

一代码的特征


1、稳定可靠(RobustnessQ?
代码写出来以后,一定要能够q行得非常好Q非常稳定可靠。在C的IT行业QY件品都是是24*7Q即要保证系l一?4时Q一星期7天中都可以无间断的正常运行。比如我们百度的搜烦(ch)引擎pȝQ比如我们的通信pȝQ等{。到了品开发后期,大部分的成本都将投入C品稳定性的提高?

2、可l护且简z(Maintainable and Simple CodeQ?br />在写代码Ӟ首先要考虑的是Q写出来的代码不但要自己可以LQ而且我们的同事、测试工E师都可能要修改q些代码Q对其进行增减。如果代码很复杂Q不Ҏ(gu)LQ如E序中的递归一大堆、程序不知何时或从何地蟩出,则会(x)使程序的可维护性和z性降低。所以必要的注释、统一的编E规范等都是非常重要的?

3、高效(F(tun)astQ?br />在Y件行业中效率是非帔R要的Q比如搜索引擎。有些Y件的搜烦(ch)效率׃高,搜烦(ch)q程特别~慢Q让人难以接受。当然这里面有一个带宽的问题Q但是程序效率不高也是一个重要的原因。而实际上E序的效率提高,有时候很单,q没有什么神U之处,如用数l烦(ch)引时候,可以用指针方式而不使用数组下标Q数l的I间定义应该定义?的Nơ幂{等?

4、简短(SmallQ?br />q方面大家的感受可能不是很深Q但是我的感受是很深的。配|过PSTNE控交换机、\由器、VoIP|关讑֤的h都知道,q些讑֤的Y仉是从PC机通过|口或串口下载到q些讑֤的Flash上(cMPC机的BIOSQ再通过讑֤上的CPU启动。如果程序写的很|嗦Q随着Ҏ(gu)不断增加,E序规模变大的巨大QFlashI间告急、内存告急、下载升U变的不可忍受,{等Q带来的是成本不断增加Q利润不断下降?

5、共享性(ReusableQ?br />如果做大型品开发,E序的共享性也是非帔R要的。我们品有那么多开发h员,如果每一个h都自己定义字W串、链表等数据l构Q那么开发效率就?x)降低,我们的品恐怕到今天也不能出台。我所说的“׃n”不是指将别h的代码复制到自己的代码中Q而是指直接调用别人的代码Q拿来即可用。这一斚w可以减少代码的冗余性,另一斚w可以增强代码的可l护性。如果别人的代码里有BugQ只需修改他的代码Q而调用此代码的程序不用进行Q何修改就可以辑ֈ同步。这同时要求我们在设计的时候,如何考虑pȝ的内聚和耦合的问题?

6、可试性(TestableQ?br />我们的品开发里Q除了Y件开发h员,q有一部分工程师负责Y件测试。Y件测试h员会(x)开发代码拿来,一行一行地q行Q看E序q行是否有错。如果Y件开发h员的代码不可试Q那试工程师就没有办法q行工作。因此可试性在大型软g开发里是很重要的一炏V可试性有时候与可维护性是遥相呼应的,一个具有好的可试性和可维护性的代码Q测试h员可以根据开发提供的l护手册、debug信息手册{就可以判断出程序出错在哪个模块?

7、可UL性(PortableQ?br />可移植性是指程序写出来以后Q不仅在windows 2000里可以运行,在NT/9X下可以运行,而且在Linux甚至Macintosh{系l下都可以运行。所有这些特性都是一代码所具备的特性。但是其中有些特性是?x)有冲突的。比如高效性,E序写的效率很高Q就可能变得很复杂,牺牲的就是简z。好的代码要在这些特性中取得q?

 

写好代码?0个秘?br />

1、百家之长归我所有(F(tun)ollow Basic Coding StyleQ?br />其实写代码的方式有很多,每个人都有自q风格Q但是众多的风格中L一些共性的、基本的写代码的风格Q如为程序写注释、代码对齐,{等。是不是~程规范Q对是~程规范?

2、取个好名字QUse Naming ConventionsQ?br />取个好的函数名、变量名Q最好按照一定的规则起名。还是编E规范?

3、凌波微步,未必摔跤QEvil goto's?Maybe Not...Q?br />q里我用“凌L微步”来Ş容goto语句。通常Qgoto语句使程序蟩来蟩去,不容易读Q而且不能优化Q但是在某种情况下,goto语句反而可以增强程序的可读性。Just go aheadQnot go back?

4、先发制人,后发制于人(Practic Defensive CodingQ?br />Defensive Coding指一些可能会(x)出错的情况,如变量的初始化等Q要考虑到出现错误情况下的处理策略。测试时要多q行几个U程。有些程序在一个线城下q行是正常的Q但是在多个U程q行q行时就?x)出现问题;而有些程序在一个CPU下运行几个线E是正常的,但是在多个CPU下运行时׃(x)出现问题Q因为单CPUq行U程只是狭义的ƈ行,多CPU一赯行程序,才是真正的ƈ行运?

5、见招拆招,滴水不漏QHandle The Error CasesQThey Will OccurQ)
q里的Error CaseQ错误情况)Q是指那些不易重视的错误。如果不对Error Caseq行处理Q程序在多数情况下不?x)出错,但是一旦出现异常,E序׃(x)崩溃?6、熟?fn)剑法刀术,所向无敌(Learn Win32 API SeriouslyQ?br />?#8220;剑法刀?#8221;来Ş容一些API是因为它们都是经q了很多优秀开发h员的不断开发、测试,其效率很高,而且z易懂,希望大家能掌握它Q熟(zhn)它Q用它。是不是象我们的ULIB?

7、双手互搏,无坚不摧QTest,but don't stop thereQ?br />q里的测试不是指别h来测试你的代码,而是指自己去试。因Z是写代码的原作者,对代码的了解最深,别h不可能比你更了解Q所以你自己在测试时Q可以很好地L试哪些边界条Ӟ以及(qing)一些意向不到的情况?

8、活用断aQUse,don't abuse,assertionsQ?br />断言QassertionQ是个很好的调试工具和方法,希望大家能多用断aQ但是ƈ不是所有的情况下都可以用到断言。有些情况用断a反而不合适?

9、草木皆兵,不可大意QAvoid AssumptionsQ?br />是指在写代码Ӟ要小心一些输入的情况Q比如输入文件、TCP的sockets、函数的参数{等Q不要认Z用我们的API的用户都知道什么是正确的、什么是错的Q也是说一定要考虑到对外接口的出错处理问题?

10、最高境界、无招胜有招QStop writing so much codeQ?br />意思就是说量避免写太多的代码Q写的越多,出错的机?x)也多。最好能重用别h开攄接口函数或直接调用别人的api?

 

本文来自CSDN博客Q{载请标明出处Q?a href="http://www.shnenglu.com/humanchao/archive/2010/08/05/122334.html">http://www.shnenglu.com/humanchao/archive/2010/08/05/122334.html



]]>
转蝲Q如何查询端口被占用的程?/title><link>http://www.shnenglu.com/wanghaiguang/archive/2012/02/22/166251.html</link><dc:creator>王v?/dc:creator><author>王v?/author><pubDate>Wed, 22 Feb 2012 09:06:00 GMT</pubDate><guid>http://www.shnenglu.com/wanghaiguang/archive/2012/02/22/166251.html</guid><wfw:comment>http://www.shnenglu.com/wanghaiguang/comments/166251.html</wfw:comment><comments>http://www.shnenglu.com/wanghaiguang/archive/2012/02/22/166251.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/wanghaiguang/comments/commentRss/166251.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/wanghaiguang/services/trackbacks/166251.html</trackback:ping><description><![CDATA[<p>大家在启动服务器Ӟ有时正常启动有时又启动不了是怎么回事呢?Q那Z么关掉迅L(fng)软g又好了呢?Q现在就来给大家讲解一下,</p> <p><a target="_blank"><img alt="如何查询端口被占用的E序 - kakis - Kakis" src="http://img.blog.163.com/photo/Tl2tguIIMavHqSmPIqmjUg==/1422293057320130173.jpg" __1329901352878__="ev_7614859533" /></a></p> <p>转自Q?a ><font color="#3468a4">http://yinkai210.blog.163.com/blog/static/287483452009050256466/</font></a><br /><br />q些端口如果被其他程序占用就不能正常启动Q比如有时启动时?x)提CWEB启动p|Q其实就?0端口被占用了Q而迅L(fng)下蝲软g恰恰是占用?0端口Q关掉就行了。但有时q雷{都没有开也启动不了,那就是别的东西占用了Q那怎么办呢Q我来叫你查看端口ƈx的方法?br />1.在开?-q行   里面输入cmd点回车,?x)出现运行窗口?br />2.在提C符后输入netstat -ano回RQ找到tcp 80端口对应的pidQ比?484.<br />3.ctrl+alt+del打开d理器,选进E,q里有很多正在运行的E序怎么找?别急点上面?nbsp;  查看--选择?-在PIDQ进E标C符Q前面打钩。好了,下面的进E前面都有了PIDL(fng)。这时上一步找到的PID有用了Q找?484Q比如PEER.EXE什么的Q结束进E吧。这时再开服务器,看WEB可以启动了!</p> <p><font color="#ff0000"><strong>如上面的不清楚还有简明的Q?/strong></font></p> <p><font color="#ff0000"><strong>假如我们需要确定谁占用了我们的80端口</strong></font></p> <p><font color="#ff0000"><strong>1、Windowsq_<br />在windows命o(h)行窗口下执行Q?br />C:\>netstat -aon|findstr "80" <br />TCP     127.0.0.1:80         0.0.0.0:0               LISTENING       2448<br />看到了吗Q端口被q程号ؓ(f)2448的进E占用,l箋执行下面命o(h)Q?br />C:\>tasklist|findstr "2448" <br />thread.exe                     2016 Console                 0     16,064 K<br />很清楚吧Qthread占用了你的端?Kill it<br />如果W二步查不到Q那开d理器,看哪个进E是2448Q然后杀之即可?/strong></font></p> <p><font color="#ff0000"><strong>如果需要查看其他端口。把 80 Ҏ(gu)卛_<br /><br /></strong></font><a style="color: #333333; text-decoration: none; font-family: 'Microsoft YaHei'; font-size: 20px; line-height: 30px; background-color: #ffffff;">Linux查看端口使用状态、关闭端口方?br /></a>转自Q?a >http://blog.csdn.net/wudiyi815/article/details/7473097</a><br /><span style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;">前提Q首先你必须知道Q端口不是独立存在的Q它是依附于q程的。某个进E开启,那么它对应的端口开启了Q进E关闭,则该端口也就关闭了。下ơ若某个q程再次开启,则相应的端口也再ơ开启。而不要纯_的理解为关闭掉某个端口Q不q可以禁用某个端口?/span><br style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;" /><br style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;">1. 可以通过"netstat -anp" 来查看哪些端口被打开?/span><br style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;">Q注Q加参数'-n'?x)将应用E序转ؓ(f)端口昄Q即数字格式的地址Q如Qnfs->2049, ftp->21Q因此可以开启两个终端,一一对应一下程序所对应的端口号Q?/span><br style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;">2. 然后可以通过"lsof -i:$PORT"查看应用该端口的E序Q?PORT指对应的端口P。或者你也可以查看文?etc/servicesQ从里面可以扑և端口所对应的服务?/span><br style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;">Q注Q有些端口通过netstat查不出来Q更可靠的方法是"sudo nmap -sT -O localhost"Q?/span><br style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;">3. 若要关闭某个端口Q则可以Q?/span><br style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;">1)通过iptables工具该端口掉Q如Q?/span><br style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;"> "sudo iptables -A INPUT -p tcp --dport $PORT -j DROP"</span><br style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;"> "sudo iptables -A OUTPUT -p tcp --dport $PORT -j DROP"    </span><br style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;">2)或者关掉对应的应用E序Q则端口p然关闭了Q如Q?/span><br style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;"> "kill -9 PID" (PIDQ进E号)</span><br style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;">  如:(x)    通过"netstat -anp | grep ssh"</span><br style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;">  有显C:(x)    tcp 0 127.0.0.1:2121 0.0.0.0:* LISTEN 7546/ssh</span><br style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;">  则:(x)    "kill -9 7546"</span><br style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;" /><br style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;">Q可通过"chkconfig"查看pȝ服务的开启状态)</span><br /><font color="#ff0000"><strong><br /></strong></font></p><img src ="http://www.shnenglu.com/wanghaiguang/aggbug/166251.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/wanghaiguang/" target="_blank">王v?/a> 2012-02-22 17:06 <a href="http://www.shnenglu.com/wanghaiguang/archive/2012/02/22/166251.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.wkbxdlr.cn" target="_blank">ƷþþþþþþĻ</a>| <a href="http://www.rszgrh2.cn" target="_blank">þþƷ˘AV</a>| <a href="http://www.cbsfq.cn" target="_blank">Ⱦþۺ</a>| <a href="http://www.cqtqtz.cn" target="_blank">þþþþëƬѲ</a>| <a href="http://www.xyq123.cn" target="_blank">þþþžоƷ</a>| <a href="http://www.igdl.cn" target="_blank">˼˼þ99ѾƷ6</a>| <a href="http://www.xqt007.cn" target="_blank">þۺav</a>| <a href="http://www.fayongshicai.cn" target="_blank">99þ99þþƷ</a>| <a href="http://www.jdjx168.cn" target="_blank">99þ99þþƷƬ</a>| <a href="http://www.seo9968.cn" target="_blank">պӰԺþ</a>| <a href="http://www.akeyu.cn" target="_blank">þþƷۺɫ</a>| <a href="http://www.vqzt.cn" target="_blank">鶹þþ9ԴƬ</a>| <a href="http://www.shoescaps.cn" target="_blank">þþƷaĻ</a>| <a href="http://www.yghzby.cn" target="_blank">þ99ֻоƷ</a>| <a href="http://www.ltbhs.com.cn" target="_blank">þ96Ʒþþ</a>| <a href="http://www.xcvcd.cn" target="_blank">Ļav鲻þ</a>| <a href="http://www.smash6.cn" target="_blank">þøŮ߳MBA</a>| <a href="http://www.facai365.cn" target="_blank">91鶹Ʒ91þþþþ </a>| <a href="http://www.ssxgsl.cn" target="_blank">˾þۺϾƷAVר </a>| <a href="http://www.taoke140.cn" target="_blank">ƷþþĻһ </a>| <a href="http://www.zuiaimama.cn" target="_blank">һŮȫƾþƬ </a>| <a href="http://www.xinanyue.cn" target="_blank">þõӰ2021</a>| <a href="http://www.hanshigu.cn" target="_blank">ٸۺϾþĻ</a>| <a href="http://www.101922.cn" target="_blank">ۺϾþĻӰ</a>| <a href="http://www.hoay.com.cn" target="_blank">þݺҹҹվ</a>| <a href="http://www.0558pet.cn" target="_blank">ھƷþþþþҰ</a>| <a href="http://www.csrencaiwd.cn" target="_blank">˾þһ</a>| <a href="http://www.sxxnjy.cn" target="_blank">һaƬþëƬ</a>| <a href="http://www.gvyf.cn" target="_blank">þݺҹҹվ</a>| <a href="http://www.silverprice.net.cn" target="_blank">޹㽶ˬAVƬþ</a>| <a href="http://www.pcb0.cn" target="_blank">þ99Ʒþ99</a>| <a href="http://www.jnyadz.cn" target="_blank">ɫۺϾþ</a>| <a href="http://www.nxxdz.cn" target="_blank">պAvĻþþ޸ </a>| <a href="http://www.h3cedu.cn" target="_blank">91þùۺϾƷ</a>| <a href="http://www.take-art.cn" target="_blank">þ99Ʒþþþþˮ </a>| <a href="http://www.ailazi.com.cn" target="_blank">ƷŮþþm</a>| <a href="http://www.okfupo.cn" target="_blank">þwww˳ɿƬ</a>| <a href="http://www.t0oal.cn" target="_blank">ŮƷþþþ</a>| <a href="http://www.n24657.cn" target="_blank">˾þۺ</a>| <a href="http://www.haihuasuye.cn" target="_blank">˾þô߽ۺվ</a>| <a href="http://www.kou365.cn" target="_blank">þseֻоƷ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>