??xml version="1.0" encoding="utf-8" standalone="yes"?>国产综合成人久久大片91,久久乐国产精品亚洲综合,97精品久久天干天天天按摩http://m.shnenglu.com/qzb2006e/category/2343.htmlzh-cnFri, 10 Oct 2008 05:22:08 GMTFri, 10 Oct 2008 05:22:08 GMT60关于javascript callbackhttp://m.shnenglu.com/qzb2006e/archive/2008/10/09/63532.htmllittlegailittlegaiThu, 09 Oct 2008 04:29:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2008/10/09/63532.htmlhttp://m.shnenglu.com/qzb2006e/comments/63532.htmlhttp://m.shnenglu.com/qzb2006e/archive/2008/10/09/63532.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/63532.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/63532.htmlPage.Request.Form["__CALLBACKID"]
Page.Request.Form["__CALLBACKPARAM"]



littlegai 2008-10-09 12:29 发表评论
]]>
关于HttpApplicationhttp://m.shnenglu.com/qzb2006e/archive/2008/09/19/62257.htmllittlegailittlegaiFri, 19 Sep 2008 03:00:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2008/09/19/62257.htmlhttp://m.shnenglu.com/qzb2006e/comments/62257.htmlhttp://m.shnenglu.com/qzb2006e/archive/2008/09/19/62257.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/62257.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/62257.htmlSession_End
Application_End
h面
Application_Start
Application_BeginRequest
Application_AuthenticateRequest
Session_Start
再次h
Application_BeginRequest
Application_AuthenticateRequest


littlegai 2008-09-19 11:00 发表评论
]]>
如果sharepoint 不能卸蝲http://m.shnenglu.com/qzb2006e/archive/2008/08/16/59009.htmllittlegailittlegaiSat, 16 Aug 2008 00:56:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2008/08/16/59009.htmlhttp://m.shnenglu.com/qzb2006e/comments/59009.htmlhttp://m.shnenglu.com/qzb2006e/archive/2008/08/16/59009.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/59009.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/59009.html

littlegai 2008-08-16 08:56 发表评论
]]>
修复Visual Studiohttp://m.shnenglu.com/qzb2006e/archive/2008/07/24/57007.htmllittlegailittlegaiWed, 23 Jul 2008 16:06:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2008/07/24/57007.htmlhttp://m.shnenglu.com/qzb2006e/comments/57007.htmlhttp://m.shnenglu.com/qzb2006e/archive/2008/07/24/57007.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/57007.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/57007.html有时候在dWeb引用的时候,会告诉你没有安装有关lgQ需要重装Visual StudioQ主要是因ؓ所安装的扩展包Z问题Q这时候可以用
devenv /resetskippkgs
修复


littlegai 2008-07-24 00:06 发表评论
]]>
Nebula Tips (1)http://m.shnenglu.com/qzb2006e/archive/2008/07/19/56635.htmllittlegailittlegaiSat, 19 Jul 2008 13:27:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2008/07/19/56635.htmlhttp://m.shnenglu.com/qzb2006e/comments/56635.htmlhttp://m.shnenglu.com/qzb2006e/archive/2008/07/19/56635.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/56635.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/56635.html其中QNebula2.sln是源代码
tutorials.sln是那些小例子
打开tutorials.slnQ我用的是VS2008)Q找C要运行的那个目Q可以在SDK扑֯应的例子Q,讄一下包含\径和?lib)路径Q就可以~译了,通常~译q程会很利Q但是我q里q行的时候,出现?Q?br>
nD3D9Shader:failed to load fx file 'h:/games/Nebula2SDK/data/shaders/fixed/shape.fx' with:
memory(34,9):ID3DXEffectCompiler:Error in type checking
memory(55,9):ID3DXEffectCompiler:Error in type checking
memory(67,9):ID3DXEffectCompiler:Error in type checking
ID3DXEffectCompiler:There was an error initializing the compiler
在http://nebuladevice.cubik.org/forum/index.php?topic=41.msg401#msg401可以扑ֈ解决办法Q其中有效的一条是在nd3d9shader_main.cc
中设|编译标识ؓ
D3DXSHADER_USE_LEGACY_D3DX9_31_DLL
扑ֈҎbool nD3D9Shader::LoadResource()
/**
    Load D3DX effects file.
*/
bool
nD3D9Shader::LoadResource()
{
    n_assert(
!this->IsLoaded());
    n_assert(
0 == this->effect);

    HRESULT hr;
    IDirect3DDevice9
* d3d9Dev = this->refGfxServer->d3d9Device;
    n_assert(d3d9Dev);

    
// mangle path name
    nString filename = this->GetFilename();
    nString mangledPath 
= nFileServer2::Instance()->ManglePath(filename.Get());

    
//load fx file
    nFile* file = nFileServer2::Instance()->NewFileObject();

    
// open the file
    if (!file->Open(mangledPath.Get(), "r"))
    {
        n_error(
"nD3D9Shader: could not load shader file '%s'!", mangledPath.Get());
        
return false;
    }

    
// get size of file
    int fileSize = file->GetSize();

    
// allocate data for file and read it
    void* buffer = n_malloc(fileSize);
    n_assert(buffer);
    file
->Read(buffer, fileSize);
    file
->Close();
    file
->Release();

    ID3DXBuffer
* errorBuffer = 0;
    
#if N_D3D9_DEBUG
        DWORD compileFlags 
= D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
    
#else
        DWORD compileFlags 
= D3DXSHADER_USE_LEGACY_D3DX9_31_DLL;
    
#endif

    
// create include file handler
    nString shaderPath(mangledPath.Get());
    nD3D9ShaderInclude includeHandler(shaderPath.ExtractDirName());

    
// get global effect pool from gfx server
    ID3DXEffectPool* effectPool = this->refGfxServer->GetEffectPool();
    n_assert(effectPool);

    
// create effect
    hr = D3DXCreateEffect(
            d3d9Dev,            
// pDevice
            buffer,             // pFileData
            fileSize,           // DataSize
            NULL,               // pDefines
            &includeHandler,    // pInclude
            compileFlags,       // Flags
            effectPool,         // pPool
            &(this->effect),    // ppEffect
            &errorBuffer);      // ppCompilationErrors
    n_free(buffer);

    
if (FAILED(hr))
    {
        n_error(
"nD3D9Shader: failed to load fx file '%s' with:\n\n%s\n",
                mangledPath.Get(),
                errorBuffer 
? errorBuffer->GetBufferPointer() : "No D3DX error message.");
        
if (errorBuffer)
        {
            errorBuffer
->Release();
        }
        
return false;
    }
    n_assert(
this->effect);

    
// success
    this->hasBeenValidated = false;
    
this->didNotValidate = false;
    
this->SetState(Valid);

    
// validate the effect
    this->ValidateEffect();

    
return true;
}
注意按照U色的地方进行修改即可,然后回看到q行l果Q?br>





littlegai 2008-07-19 21:27 发表评论
]]>
javascript学习http://m.shnenglu.com/qzb2006e/archive/2008/04/23/47877.htmllittlegailittlegaiWed, 23 Apr 2008 03:17:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2008/04/23/47877.htmlhttp://m.shnenglu.com/qzb2006e/comments/47877.htmlhttp://m.shnenglu.com/qzb2006e/archive/2008/04/23/47877.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/47877.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/47877.html1?span style="font-family: "Times New Roman"; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">  Html标签如果环绕javascript代码Q则会作用于它的输出

如:

<html>

<head>

<script type="text/javascript">

function sayhello()

{

document.write("hello");

}

</script>

</head>

<body>

<font size="100">

<script language="javascript">

sayhello();

</script>

</font>

</body>

</html>

 

2?span style="font-family: "Times New Roman"; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">  <script language=”javascript”></script>不是W3C标准

W3C标准是:

<script type=”text/javascript”></script>

但是有些览器不支持type方式声明javascript脚本Q所以你最好两个都用,如下面Q?/span>

<script language=”javascript” type=”text/javascript”></script>

 

3?span style="font-family: "Times New Roman"; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">  有些览器在执行脚本的过E中产生输出Q但有些不能

<body>

<h1>Ready start</h1>

<script type="text/javascript">

      alert("First Script Ran");

</script>

<h2>Running...</h2>

<script type="text/javascript">

      alert("Second Script Ran");

</script>

<h2>Keep running</h2>

<script type="text/javascript">

      alert("Third Script Ran");

</script>

<h1>Stop!</h1>

</body>

 

4?span style="font-family: "Times New Roman"; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">  大多数浏览器喜欢把它们不支持的标{中的内容直接显C出来,如果你碰C个浏览器恰好不支?/span>javascriptQ你应该Q?/span>

<script type="text/javascript">

<!--

 

  put your JavaScript here

 

//-->

</script>

但是如果你所写的是严格的XHTMLQ注释标记就不大合适了Q你最好:

<script type="text/javascript">
<![CDATA[
   ..script here ..
]]>
</script>

 

5?span style="font-family: "Times New Roman"; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">  如果览器不支持javascript或?/span>javascript被关闭了Q最好写一D?/span>noscriptQ就像这P

<noscript>
      <em>Either your browser does not support JavaScript or it
         is currently disabled.</em>
</noscript>

一个很有意思的用法是Q如果浏览器不支?/span>javascriptQ就让他们蟩转到一个错误页面,如下Q?/span>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<title>noscript Redirect Demo</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
<!--  warning example does not validate -->
<noscript>
      <meta http-equiv="Refresh" content="0;URL=/errors/noscript.html" />
</noscript>
</head>
<body>
<script type="text/javascript">
<!--
 document.write("Congratulations! If you see this you have JavaScript.");
//-->
</script>
<noscript>
   <h2>Error: JavaScript required</h2>
   <p>Read how to <a href="/errors/noscript.html">rectify this problem</a>.</p>
</noscript>
</body>
</html>
 

6?span style="font-family: "Times New Roman"; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">  事g响应斚wQ?/span>html是不区分大小写的Q?/span>onclick,OnClick,onCliCk效果相同Q但是在XHTML中,只接受小写?/span>

大多数浏览器支持在地址栏中输入?strong>javascript: alert('hello')的代码来q行javascript?/strong>当然Q也可以以超链接的Ş式:<a href="javascript: alert('hello I am a pseudo-URL script');">Click to invoke</a>


littlegai 2008-04-23 11:17 发表评论
]]>
Direct Show W记http://m.shnenglu.com/qzb2006e/archive/2008/02/22/43108.htmllittlegailittlegaiFri, 22 Feb 2008 14:10:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2008/02/22/43108.htmlhttp://m.shnenglu.com/qzb2006e/comments/43108.htmlhttp://m.shnenglu.com/qzb2006e/archive/2008/02/22/43108.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/43108.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/43108.html一?总览Q?/b>

Graph、Filter、Pin、Simple

GraphQ可以理解ؓ媒体处理的流E图?

FilterQ可以理解ؓ媒体处理程图中的一个步骤?

PinQ可以理解ؓ媒体处理各个步骤之间的数据流节点?

SimpleQ可以理解ؓ各个形态的数据?

Filter的分c:

· source filter:数据从源(比如媒体文gQ引入Graph?

· transform filterQ数据流入、改变、流出?

· Renderer filtersQ把最l结果展现给用户?

· splitter filterQ比如把一个媒体流分解频和音频?

· mux filterQ和splitter filter相反?

1. Graph Manager

主要对处于同一个Graph的Filter(s)q行l一的管理?

比如Q?

· 各个Filter的状态切?/i>

· 建立同步旉

· 事g回发

· 创徏

Z么要l一理状态切换?

因ؓ处于同一Graph中的各个Filter的状态切换往往需要遵循严格的先后序。所以一般通过发送命令给Graph Manager的方式进行各Filter的状态变更?

Z么要建立同步旉Q?

比如声像需要同步?

2. Media Types

l构?a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/am_media_typestructure.htm">AM_MEDIA_TYPE定义了媒体类型?

主要包含如下l构Q?

· Major type: ׃个GUID来表C。通常包含韌频、未知流、MIDI{等?

· Subtype: ׃个GUID来表C。Major type频,则子cd可以包括RGB-24, RGB-32, UYVY

· Format block: 说明囑Ş寸、率等信息。如果Major type频,sub type为RGB-24Q则Format block的信息会被自动L识?

3. Sample?/b>Allocator

需要注意的是,各个filter之间q不直接传送它们各自进行处理的数据的指针。它们通过一个暴?a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/imemallocatorinterface.htm">IMemAllocator接口的Comlg来分配内存。填充了数据的内存被装到Sample里面。各个Filter真正使用的是Sample。Sample通常包含Q?

· 内存指针

· 旉?

· 标识

· 媒体cdQ可选)

q里当一个Filter使用Sample的时候,它同时掌握这个Sample的引用计敎ͼq样有效杜l了资源争用现象的发生?

4. Filter Graph中的g

g被封装到Filter中,M与硬件的交互都{化ؓ与Filter的交互?

二?Graph-Building lg

Filter Graph Manager.

Capture Graph BuilderQ设计的初衷是视频捕?但是可以衍生很多用途?

Filter Mapper and System Device EnumeratorQ枚丑֏用的filter.

DVD Graph Builder

Video Control

1. 拼接

1) 如果在Graph里面有一个没有输入的FilterQ那么Graph在完成自q时候,׃考虑q个Filter。如果有一个已有的Filter的流出恰好与q个没有输入的Filter的流入相匚wQ则这两个Filterq接?

2) Graph在完成自qq程中也会查找所有注册过的Filter与当前非l点Filter的流行匹配。注册的Filter会有一个权|作ؓGraphq行q接试的优先依据?

步骤Q?

1) 使用IStreamBuilderQ如果pin实现了这个接口,但大多数情况没有Q。(否则2Q?

2) 查找被缓存的Filter。(否则3Q?

3) 查找Graph现有的Filter。(否则4Q?

4) 查找所有注册了的Filter?

2. 关键Ҏ

IFilterGraph::ConnectDirect:直接q接两个FilterQ如不成功,q回p|?

IGraphBuilder::ConnectQ连接两个FilterQ如果可能,直接q接Q否则通过中间Filter(s)q行q接?

IGraphBuilder::RenderQ你自己建立了一pd从源开始的FilterQ基于这些Filter(s)完成Graph?

IGraphBuilder::RenderFileQ从一个文件开始完成Graph.

IFilterGraph::AddFilter:向Graph中添加一个Filter

通过q些ҎQ你可以Q?

1?由Graph Manager建立整个Graph。(通过RenderFileQ?

2?由Graph Manager建立部分Graph。(比如你想自己写一个AVI文gQ当然也可以通过Render来生成预览)

3?完全手动建立整个Graph。(需要自己AddFilterQ还需要自己ConnectQ?b>

三?Direct Show 数据概q?/b>

1. 关键接口Q方法)

IMediaSampleQ对Filter之间使用的内存的装?

IMemAllocator::GetBufferQ从allocator获取BufferQ即ImediaSimple的实现对象)

摘要Q?

׃Render会按照时间戳来Render数据Q所以它会一直占用它的上一UFilter入的SimpleQ直到时间戳所标识的时间到达。所以当上一UFilter用完了allocator的Simple池中的SimpleӞ会阻塞而不处理Q进而反向媄响到更上一U的FiltersQ从而它们变ؓ{待的状态。同时由于时间戳对于Render的时间上的要求,所有上URender都必dSimple的时间戳标识的时间到达之前处理完自己对于该Simple的动作?

2. TransportQ传送)

· Push ModelQ推送模型)Q上层filterQpin-outQ将处理好的数据推送给下层filter(pin-in)。下层filter在需要数据的时候通过IMemInputPin::Receive来获取数据?

· Pull ModelQ抓取模型)Q下层filter(pin-in)在需要数据的时候,通过IAsyncReader异步向上层filterh数据。(通常用于视频文g的回放)

3. Samples and Allocators

1) 引用计数

上层Filter(pin-out)通过IMemAllocator::GetBuffer向Allocator甌SimpleQ如果此时没有Simple的引用计Cؓ0Q则说明Allocator的Simple池中没有可用的SimpleQ则GetBuffer的调用会被阻塞。一旦Simple池中出现可用的SimpleQ则先前d的GetBuffer放行Qƈ获取一个引用计数变?的Simple。此Simple处理后,传递给下层Filter(pin-in)Q下层Filter如果在ReceiveҎ中处理SimpleQ则它与上层Filter的处理处于同一U程中,Simple的引用计C会变化,如果下层Filter需要通过创徏U程异步使用上层推入的Simpleq行处理Q则该Simple的引用计C?Q变?.之后如果上层Filter的推送线E结束,则Simple的引用计数减1Q变?.

2) 提交和撤销Allocator

IMemAllocator::Commit,在被调用之前Q所有的GetBuffer无效Q?

调用IMemAllocator::Decommit之后Q所有的GetBuffer调用无效.

4. Filter 状态变?/b>

Filter状态的变化由Graph Managerq行控制?

所有的状态变化都是自低(Render FilterQ向上(Source FilterQ进行的。比如暂停的时候,Render Filter会首先暂停,q时候Render之上的Filter中都会存有未能推送的SimpleQ此时相当于在各个Filter之前都堆U了一些等待处理的数据。沿着Render向上的Filter逐个暂停Q直到Source。当状态从暂停变化为开始的时候,Render会首先变化ؓ开始状态,处理在它之前堆积的数据,qN些被占用的Simple。然后逐步向上直到Source,Source在能够获取Simple之后Q数据l流入GraphQ整个Graphq入开始状态?/p>

littlegai 2008-02-22 22:10 发表评论
]]>
重构--重构关系型数据库Q?Q?/title><link>http://m.shnenglu.com/qzb2006e/archive/2007/08/10/29529.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Fri, 10 Aug 2007 14:47:00 GMT</pubDate><guid>http://m.shnenglu.com/qzb2006e/archive/2007/08/10/29529.html</guid><wfw:comment>http://m.shnenglu.com/qzb2006e/comments/29529.html</wfw:comment><comments>http://m.shnenglu.com/qzb2006e/archive/2007/08/10/29529.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/qzb2006e/comments/commentRss/29529.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/qzb2006e/services/trackbacks/29529.html</trackback:ping><description><![CDATA[<p>1、数据库与面向对象编E语a的不?br>关系数据库的xҎ数据l构的声明。这L话一些封装手D就不可用了。没有封装,数据讉K׃会被明显的约束?br>表是通过外键兌的。这同样不能够被装?br>存在于数据库中的数据是持久化的,q且存活得比E序要长。数据库的结构一旦发生变化,数据pq行q徙?/p> <p>如果pȝ被多ơ安装,那么׃有不同的数据库。那么如果数据库l构发生变化Q这个变化同栯作用于每一份安装?/p> <p>不同的用户可以同时访问数据,但是他们可以每h拥有一份程序的拯?br><br>cd以承,但数据不行?br>源代码可以在本地q行l护和测试,之后发布到源代码理服务器中。版本冲H可以被识别刎ͼ然后通过一些强有力的工具可以帮助解册些问题。在大多数项目中Q同一个数据库往往为多个开发h员服务?br>l护源代码可以用工兗数据库的结构和数据则只能够׃h花更多的_֊ȝ护?br>讉K数据库所p的时间比赯问访问内存中对象的时间来要多上好几倍?/p> <p>关系型数据库中的数据l构是浅层结构,然而当它们变成对象处于面向对象的系l中Ӟ他们的含义变得更加深入,他们的关pd得更加错l复杂?/p> <p>2E序与数据库打交道时产生的一些问?/p> <p>当程序与数据库交互时Q会产生q样一些问题:</p> <p>E序与数据库之间的关联往往不是cd安全的(惌JDBCQ。编译器无法评估E序与数据库是否l构性兼宏V某些映类和持久层把这些问题拿C一边,却没有解军_们。类型安全性将会在影射cL持久层中失去Q而不是其他的地方?/p> <p>数据库将?#8220;隐藏”一些对象。这U情况发生在对象被写入数据库或者在d出来的地斏V因此对象可以被E序的两个部分交换用,而不需要显式得暴露于接口中?/p> <p>大多数情况下往往采用表和对象一一对应的模式。这往往在强调数据的应用E序中是错误的做法。特别是当需要从数据库读取对象时Q可能会需要多个表的极联,或者ؓ了满x据展C的需要,建立一些视图。结果,当数据库发生变化Ӟ很难扑ֈ一个合适的途径来决定那些类也要跟着修改。反q来_通常无法明确cȝ那些变化会媄响到查询和视图?/p> <p>q有一些琐的问题。数据库中的数据cd与程序语a中的基本数据cd之间的映会造成一些困难。比如时间戳的尺度,采用点数尺度或采用string或变长字W串集合׃有相当大的差别?/p> <p>在面向对象的pȝ当中Q关联关pȝ建模是基于概늚Q例如,账目和收支有养I。在关系数据库中Q一对多关系和多对一关系都是适用的。所以也无法找C套确定的Ҏ来实施重构?/p> <p>因此我们在重构的时候需要着重考虑q样三个地方Q?/p> <p>1Q有x据库l构、数据库模型的重构;</p> <p>2Q不同版本的数据库之间的数据q移Q?/p> <p>3Q有x据库讉K代码的重构?/p> <p>3重构关系数据库的数据库结?/p> <p>在实践中Q往往有一定数量的数据库模式^行存在。至有两个模式Q一个ؓ开发者所使用Q开发数据库Q一个ؓ用户所使用Q品数据库Q?/p> <p>因此开发者L可以试着修改数据库而不L扰用戗只有当数据库被d的测试完成,q且适合于构Z其上的系l,q样才会数据库、程序作Z个稳定版本提交给用户?/p> <p>此外Q每一个开发者应当拥有自q数据库实例,q样他们才能够独立的试他们对于数据库的一些变动而不会媄响到开发团队的其他人员。这些不同版本数据库实例的存在得数据的q移变成了一个关键话题。在下面的部分,我们会讨论q个话题?/p> <p>“逐步q化”q样一个核心的原理不论在程序重构中q是数据l构的重构中都在重演着Q老的l构q不会马上被新的所取代。新旧数据库l构往往会ƈ存一D|间。老的数据库结构会被标Cؓ“q期”以让那些新编写的E序不去讉K它。然后已有的E序会被修改Q一步又一步的向新数据库过渡。一旦这个过E结束,老的数据l构q完成了它的命,他会被终l然后删除。图5-1C出了表“Customer”的变革。一开始的时候,姓和名是作ؓ一个字D存储的Q他们合UC“Name”。现在姓和名会被存放在两个字D中Q最后Name字段被取代q被删除?/p> <p><a href="http://m.shnenglu.com/images/cppblog_com/qzb2006e/WindowsLiveWriter/fa5a4f2dd143_13D19/dbrefactor.jpg" atomicselection="true"><img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=190 alt=dbrefactor src="http://m.shnenglu.com/images/cppblog_com/qzb2006e/WindowsLiveWriter/fa5a4f2dd143_13D19/dbrefactor_thumb.jpg" width=724 border=0></a> </p> <p>在中间的状态,表Customer包含冗余字段Name。程序或触发器需要保障它们之间的一致性?/p> <p>在Java中,你可以把那些q时的程序标C“已过?#8221;。但是在大多数数据库和其他程序开发语a中没有提供相关的功能?/p> <p>在关pL据库中,字段、表、视囄x个数据库的结构都有可能需要被标记?#8220;q时”Q当Ӟq视具体的重构过E而定。我们往往通过讉K层面的限制或提示来体现这些独立的“已过?#8221;标注。比如我们用O/R mapping工具来生成这些数据的映射c,那么对于q些cLҎ我们可以用“已过?#8221;q行标记了。当Ӟ前提是你许Z会通过其他的手D|直接讉K数据库。如果确实这P在你的下一个版本中使用q种方式标记“q时”的数据库l构也就_了?/p> <p>如果你无法保证对于数据库的访问只是通过O/R mapping的映类Q那么就和你的开发团队订立协议吧。列一张表Q在q个表列丑֛为重构而过时的那些东西。当然所有的开发者都要同意这个表上列丄重构l果Qƈ且能够去贯彻它?/p> <p><a href="http://m.shnenglu.com/images/cppblog_com/qzb2006e/WindowsLiveWriter/fa5a4f2dd143_13D19/dbrefactor2.jpg" atomicselection="true"><img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=323 alt=dbrefactor2 src="http://m.shnenglu.com/images/cppblog_com/qzb2006e/WindowsLiveWriter/fa5a4f2dd143_13D19/dbrefactor2_thumb.jpg" width=726 border=0></a> </p> <p> </p> <p>Ambler在他的网站上攉了很多数据库中会被频J用到的重构Ҏ。这些重构方法ؓ数据库重构提供了一些依据?/p> <p>Ambler的重构方法的目的在于为数据库的结构带来改观。因而只是独立的d一列ƈ不能l成一ơ重构。独立的d一列不能够l数据库l构带来M的改观?/p> <p>有这样几UŞ式的重构Q重构而提升数据的质量Q重构而优化数据的l构Q重构而提高数据的性能Q重构而整合数据;重构而优化数据库框架?/p> <img src ="http://m.shnenglu.com/qzb2006e/aggbug/29529.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/qzb2006e/" target="_blank">littlegai</a> 2007-08-10 22:47 <a href="http://m.shnenglu.com/qzb2006e/archive/2007/08/10/29529.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重构--改善既有代码的设计读书笔?W四?1) http://m.shnenglu.com/qzb2006e/archive/2007/08/06/29242.htmllittlegailittlegaiMon, 06 Aug 2007 13:50:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2007/08/06/29242.htmlhttp://m.shnenglu.com/qzb2006e/comments/29242.htmlhttp://m.shnenglu.com/qzb2006e/archive/2007/08/06/29242.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/29242.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/29242.html单元试
~写单元试的目的是Z提高wؓ一个程序员的生产性能。至于让质保部门开心,那只是附带效果而以。单元测试是高度本地?/span>的东西,每个test class只对单一packageq作。它能够试其他packages的接口,除此之外它将假设其他package一切正常?br>功能试
用来保证软g能够正常q作。他们只负责向客h供质量保证,q不兛_E序员的生力。它们应该由一个喜Ƣ寻找臭虫的个别团队来开发。这个团队应该用重量工具和技术来帮助自己开发良好的功能试?br>一般而言Q功能测试尽可能把整个系l当作一个黑。面对一个GUI待测pȝQ它们通过GUI来操作那个系l。而对文g更新E序或数据库更新E序Q功能测试只观察待定输入所D的数据变化?br>一旦功能测试者或最l用h到Y件中的一个bugQ要除掉它至需要做两g事。当然你必须修改代码Q才得以排除错误Q但你还应该d一?span style="BACKGROUND-COLOR: yellow">单元试
Q让?span style="BACKGROUND-COLOR: yellow">揭发q只臭虫?br>4.3d更多的测?br>观察class该做的所有事情,然后针对M一功能的M一U可能失败的情况Q进行测试。这不同于某些程序员提倡的“试所有public函数”。记住,试应该是一U?span style="BACKGROUND-COLOR: yellow">风险驱动行ؓQ测试的目的是希望找出现在或未来可能出现的错误。所以我不会L试那些仅仅读或写一个值域的访问函敎ͼ因ؓ它们太简单了Q不大可能出错。这一点很重要Q因Z如果撰写q多试Q结果往往试量反而不够。测试的要诀是:试你最担心出错的部分,q样你就能从试工作中得到最大收益?br>考虑可能出错的边界条Ӟ把测试火力集中在那儿?br>L边界条gQ也包括LҎ的、可能导致测试失败的情况。对于文件相x试,I文件是个不错的边界条g。当事情被大家认为应该会出错Ӟ别忘了检查彼时是否有异常如预期般的被抛出?
不要因ؓ“试无法捕捉所有臭?#8221;Q就不撰写测试代码,因ؓ试的确可以捕捉大多数臭虫?br>对象技术有个微妙处Q承和多态会让测试变得比较困难,因ؓ有许多l合需要测试。如果你有三个彼此合作的abstract class有三个subclassQ那么你d有九个可供选择的classesQ和27U组合。我q不L试着试所有可能组合,但我会尽量测?span style="BACKGROUND-COLOR: yellow">每一?/span>classesQ这可以大大减少各种l合所造成的风险。如果这些classes之间彼此有合理的独立性,我很可能不会试所有组合。是的,我L可能遗漏些什么,但我觉得“花合理时间抓出大多数臭虫”要好q?#8220;I尽一生抓出所有臭?#8221;?br>试代码和品代码之间有个区别:你可以放心的拯、编辑测试代码?

littlegai 2007-08-06 21:50 发表评论
]]>
重构--改善既有代码的设计读书笔?W三?6)http://m.shnenglu.com/qzb2006e/archive/2007/07/30/28662.htmllittlegailittlegaiMon, 30 Jul 2007 14:11:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2007/07/30/28662.htmlhttp://m.shnenglu.com/qzb2006e/comments/28662.htmlhttp://m.shnenglu.com/qzb2006e/archive/2007/07/30/28662.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/28662.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/28662.html3.10Switch Statement
面向对象的一个最明显特征是Q少用switch或case语句。从本质上讲Qswitch语句的问题在于重复。通常用多态来解决Switch 语句带来的坏味道。switch语句常常Ҏtype codeq行选择Q你要的是与该type code相关的函数或class。所以你应该使用Extract Methodswitch语句提炼C个独立的函数中,再以Move Method他搬移到需要多态的那个class里头。此时你必须军_是否使用Replace Type Code with Subclass或Replace Type Code with State/Strategy。一旦这样完成承结构之后,你就可以Replace Conditional with Polymorphism了?br>如果你只是在单一函数中有些选择事例Q而你q不x动它们,那么“多?#8221;有Ҏ鸡用牛刀了。这U情况下Replace Parameter with Explicit Method是个不错的选择。如果你的选择条g之一是null,可以试试Introduce Null Object?br>3.11Parallel Inheritance Hierarchies(ql承关系)
在这U情况下Q每当你为某个class增加一个subclassQ必M为另外一个class相应增加一个subclass。如果你发现某个l承体系的class名称前缀和另一个承体pȝclass名称前缀完全相同Q便是闻Cq种坏味道。消除这U重复性的一般策略是Q让一个承体pȝ实体(instance)指涉(参考、引用、refer to)另一个承体pȝ实体。如果再接再厉运用Move Method和Move FieldQ就可以指涉端的承实体消弭?/p>

3.12Lazy Class(冗赘c?
你所创徏的每一个classQ都得有人去理解它、维护它Q这些工作都是要花钱的。如果一个class的所得不值其whQ它应该消失。项目中l常会出现这L情况Q某个class原本对得赯qwhQ但重构使它wŞ~水Q不再做那么多工作;或开发者事前规划了某些变化Qƈd一个class来对付这些变化,但变化实际上没有发生。如果某些subclass没有做满_工作Q试试Collapse Hierarchy。对于几乎没用的lgQ你应该以inline class对付它们?br>Collapse Hierarchy(折叠l承体系)
superclass和subclass之间无太大区别?br>它们合Z体?br>动机
如果你曾l写q承体p,你就会知道,l承体系很容易变得过分复杂。所谓重构承体p,往往是将函数和值域在体pM上下Ud。完成这些动作后Q你很可能发现某个subclassq未带来该有的h|因此需要把classes合ƈ(折叠)h?br>作法Q?br>选择你想U除的classQ是superclassq是subclass?
使用pull up Field和pull up method或者push down method和push down fieldQ把惌U除的class内的所有行为和数据搬移到另一个class?br>每次Ud后,~译q测试?br>调整“卛_被移除的那个class”的所有引用点Qo它们改而引用合qӞ折叠Q后留下的class。这个动作将会媄响到变量的声明、参数的型别以及构造函数?br>U除我们的目标;此时它应该已l成Z个空cR?br>~译、测试?/p>

3.13Speculative Generality(夸夸其谈未来?
如果所有的装置都会被用刎ͼ那就值得处理q些非必要的事情Q如果用不到׃值得。用不上的装|只会挡你的路,所以,把它搬开吧?br>如果函数或class的唯一用户是test cases(试用例)Q这飘Z坏味道。如果你发现q样的函数或classQ请把它们连同其test case都删掉。但如果他们的用途是帮助test cases正当功能,当然必须刀下留人?br>3.14Temporary Field(令hqh的暂时值域)
有时你会看到q样的对象:其内某个instance变量仅ؓ某种特定情势而设。这L代码让h不易理解Q因Z通常认ؓ对象在所有时候都需要它的所有变量。在变量未被使用的情况下猜测起当初设|的目的Q会让你发疯?br>请用Extract Classl这个可怜的孤儿创造一个家Q然后把所有和q个变量相关的代码都放进q个新家?br>如果class中有一个复杂算法,需要好几个变量Q往往可能导致这U坏味道。由于实现者不希望传递一长串参数Q所以他把这些参数都放进值域中,但是q些值域只在使用该算法的时候才有效Q其他情况下只会让hqh。这个时候可以用Extract Class把这些变量和其相关的函数提炼C个独立的class中,提炼后的新对象是一个method object?br>3.15Message Chains(q渡耦合的消息链)
用户索求对象Q然后向求得的对象l烦求对象?br>q时候应该用Hide Delegate。应该先观察Message Chain最l得到的对象是用来干什么的Q看看能否以Extract Method把用该对象的代码提炼到一个独立函CQ再q用Move Method把这个函数推入Message Chain?br>Hide Delegate(隐藏委托关系)

 当类囑֦上所C时Q客L如果惌获得对应Person的ManagerQ需要如下过E:

Department department = person.Department;
            Manager manager 
= department.Manager;

通过重构QؓcPersond属性ManagerQ如Q?br>

 1 public class Person
 2     {
 3         private Department _department;
 4         public Department Department
 5         {
 6             get
 7             {
 8                 return _department;
 9             }
10             set
11             {
12                 _department = value;
13             }
14         }
15         public Manager Manger
16         {
17             get
18             {
19                 return _department.Manager;
20             }
21         }
22     }

q样客户端可以这样写Q?br>Manager manager = person.Manger;
当然如果person不属于Q何一个部门,那么E序׃出错。这里其实可以引入Null Object来解决问题?/p>

3.16Middle ManQ中间{手hQ?br>Z可能会过渡运用delegation。你也许会看到某个class所实现的接口有一半的函数都委托给其他classQ这样就使过渡运用。这时你应该使用Remove Middle ManQ直接和职责对象打交道。如果这?#8220;不干实事”的函数只有少数几个,可以q用inline Method把它们放q调用端。如果这些Middle Man q有其他的行为,你可以运用Replace Delegation with Inheritance把它们变成实责对象的subclassQ这样你既可以扩展原对象的行为,又不必负担那么多的委托动作?br>Remove Middle Man
q个重构q程和Hide Delegate刚好相反?br>Replace Delegation with Inheritance

q个重构q程是把关联关p{换ؓl承关系?br>?br>
转变?br>
3.17Inappropriate Intimacy
当两个类彼此关系紧密地时候,有可能是他们所包含的方法或值域处在错误的类中而导_此时应当通过Move Method或Move Field把它们移动到合适的位置。应当看一下两个类之间是否真的需要双向导航关p,如果不是Q让它们之间的关pd为单向导航关pR或者通过Extract Class把共同的函数或值域抽取出来Q让每一个Class直接去调用被抽取出来的类。另外如果是子类和父c过分耦合Q则可以通过承{换ؓ兌的手D|降低耦合性?br>3.18Alternative Classes with Different InterfacesQ异曲同工的c)
如果两个函数做同一件事Q却有着不同的签名式Q应当运用Rename MethodҎ它们的用途重新命名。请反复q用Move Method某些行为移入classesQ直C者的协议一致ؓ止。或许可以用Extract Superclass来解决问题?br>3.19Incomplete Library ClassQ不完美的程序库c)
当你面对的程序类库不够好( 或者不能满求)而你又不能直接改变它Ӟ可以采用Introduce Foreign Method Ҏ来修改其中一两个函数Q或者用Introduce Local Extension来添加行为?br>Introduce Foreign Method (162)
在client class建立一个函敎ͼq以一个server class实体作ؓW一个参数。书中的例子Q?br>
Introduce Local Extension(164)
q种重构方式实际上就是从已封装的cd中承你认ؓ功能不的那个类Q然后添加你惌实现的功能。当Ӟ有时候你x展的那个cȝ巧加上了关键字final(java) 或sealed(c#)Q这样就没办法了?br>3.20Data Class(U稚的数据类)
所谓Data Class是指Q它们拥有一些值域Q以及用于访问这些值域的函敎ͼ除此之外一无长物。早期的Data Class可能会包含public值域或容器类值域Q应当首先将它们装hQ用属性或特定ҎQ。尽量可能的把外界操U这些值域的方法搬Udc里面来Q那些不应该被其他classes修改的值域Q请q用Remove Setting Method?br>Remove Setting Method
卛_调设值函数或属性中的set让它变ؓ只读?br>3.21Refused Bequest
当子cM愿意l承父类的某些东西时Q徏议将l承修改为关联。不随便修改l承体系。这是一U很淡的坏味道?br>3.22Comments(q多的注?
注释本nq不是坏味道Q它可以帮助我们扑ֈ代码中的坏味道?br>如果你需要注释来解释一块代码做了什么,试试Extract MethodQ如果method已经提炼出来Q但q是需要注释来解释其行为,试试Rename MehtodQ如果你需要注释说明某pȝl的需求规|试试Introduce Assertion?br>当你感觉需要撰写注释,请先试重构Q试着让所有注释都变得多余?br>如果你不知道该做什么,q才是注释的良好q用时机。除了用来记q将来的打算之外Q注视还可以用来标注你ƈ无十x握的区域。你可以在注释里写下“Z么做某某?#8221;。这cM息可以帮助将来的修改者,其是那些健忘的家伙?br>Introduce Assertion
引入断言?br>某一D代码需要对E序状态作出某U假设。注意,你可以创q断言Q而不仅仅是依赖已有断a?br>

littlegai 2007-07-30 22:11 发表评论
]]>
重构--改善既有代码的设计读书笔?W三?5)http://m.shnenglu.com/qzb2006e/archive/2007/07/17/28155.htmllittlegailittlegaiTue, 17 Jul 2007 13:26:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2007/07/17/28155.htmlhttp://m.shnenglu.com/qzb2006e/comments/28155.htmlhttp://m.shnenglu.com/qzb2006e/archive/2007/07/17/28155.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/28155.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/28155.html3.5 Divergent Change ( 发散式变?
针对某一外界变化的所有相应修改,都只应该发生在单一class中,而这个新class内的所有内定w应该反映外界变化。ؓ此,你应该找出因为某特定原因而造成的所有变化,然后q用Extract Class他们提炼到另一个class中?br>3.6Shotgun Surgery(散弹式修?
如果每遇到某U变化,你都必须在许多不同的classes内作多小修改以响应之Q你所面的坏味道是散弹式修攏V?br>q种情况下,你应该用Move Method和Move Field把所有需要修改的代码放进同一个class。如果眼下没有合适的class可以安置q些代码Q就创造一个。通常你可以运用Inline Class把一pd相关行ؓ放进同一个class。这可能会造成量发散式变化,但你可以L处理它?/p>

InLine Class

场景Q你的某个class没有做太多事?没有承担_责Q)?br>class的所有特性搬Ud另一个class中,然后U除原class?br>作法
在移动的目的classw上声明所有被Ud的class的公共属性和Ҏ?如果“以一个独立接口表Csource class函数”更合适的话,应该在inlining之前使用Extract Interface)
修改所有source class引用点,改而引用吸收被Ud的class的目标class?source class声明为privateQ以斩断package之外的所有引用可能。同时ƈ修改source class的名Uͼq便可以使编译器帮助你捕获到所有对于source class的dangling reference(虚悬引用?
~译Q测?br>q用Move Method和Move FieldQ将source class的特性全部搬Ud目标class?br>3.7Feature Envy(依恋情结)
有一U经典的气味是:函数Ҏ个class的兴高q对自己所处之host class的兴。这U倾慕之情最通常的焦点便是数据。无数次l验里,我们看到某个函数Z计算某|从另一个对象那儿调用几乎半打的取值函数。疗法显而易见:把这个函数移臛_一个地炏V你应该使用Move MethodQ把它移到它该去的地斏V有时候函数只有一部分受这U依恋之苦,q时候你应该使用Extract Method把这一部分提炼到独立的函数中,再用Move Method带它d的梦中家园?br>往往一个函C用上CclassesҎ。那么它I竟该被|于何处呢?我们的原则是Q判断哪个class拥有最?#8220;被此函数使用”的数据,然后把q个函数和那些数据摆在一赗如果先以Extract Method这个函数分解ؓC较小函数q分别放|于不同地点Q上q步骤也比较容易完成了?br>3.8Data Clumps(数据泥团)
?#8220;Ll在一起出现的数据”放进属于它们自己的对象中。首先找些数据的值域形式出现点,q用Extract Class它们提炼到一个独立的对象中。然后运用Introduce Parameter Object ?Preserve Whole Object为参数过长的成员函数减肥?br>一个好的评判数据惔团的办法Q删除掉众多数据中的一W。其他数据如果不再有意义Q这是个明的信号Q你应该为它们生一个新对象?/p>

3.9Primitive Obsession(基本型别偏执)
对象技术的新手通常不愿意在Q务上q用对?-像是l合数值和币值的money class、含一个v始值和一个结束值得range class、电话号码或邮政~码(ZIP){等的特Dstrings。你可以q用Replace Data Value with Object原本单独存在的数值替换ؓ对象。如果欲替换之数值是type codeQ型别码)Q而它不媄响行为,你可以运用Replace Type Code with Class它换掉。如果你有相依于此type code的条件式Q可q用Replace Type Code with SubClass或Replace Type Code with State/Strategy 加以处理?br>如果你有一l应该L攑֜一L值域Q可q用Extract Class。如果你在参数列中看到基本型数据Q不妨试试Introduce Parameter Object。如果你发现自己正在从array中挑选数据,可运用Replace Array with Object?br>Replace Type Code with Class
在以C为基的编E语a中,type code(型别?或枚丑ր很常见。如果带着一个有意义的符号名Qtype code的可L还是不错的。问题在于,W号名终I只是个别名Q编译器看见的、进行型别检验的Q还是背后那个数倹{Q何接受type code作ؓ引数(argument)的函敎ͼ所期望的实际上是一个数|无法强制使用W号名。这会大大降低代码的可读性,从而成虫之源?br>如果把那L数D{换ؓ一个classQ编译器可以对q个classq行型别验。只要ؓq个class提供factory methodQ你可以始l保证只有合法的实体才会被创建出来,而且它们都回被传递给正确的宿d象?br>但是如果枚D被switch所使用Q你׃能简单地它替换为class。因为switch往往只会接受整型数据。所以应该首先对switchq用Replace Conditional with Polymorphism重构Q而在q之前,q要q行Replace Type Code with Subclasses或Replace Type Code with State/Strategy把type code处理掉?br>作法Q?br>1、ؓ type code建立一个class。其中包含相应的用于记录type code的值域Qƈ准备一lstatic变量保存允许被创建的实体Qƈ以一个static函数Ҏ原本的type code q回合适的实体?br>2、修改source class代码Q让他用上q新建的class?br>3、编译、测?br>4、对于source class中每一个用type code 的函敎ͼ相应建立一个函敎ͼ让新函数使用新的class。你需要徏?#8220;以新class实体变量”的函敎ͼ用以替换原先“直接以type code为引?#8221;的函数。你q需要徏立一?#8220;q回新class实体”的函敎ͼ用以替换原先一直返回type code的函数。徏立新函数前,你可以用Rename Method修改原函数名Uͼ明确指出那些函数仍然使用旧式的type code?br>5、逐一修改source class用户Q让它们使用新接口?br>6、每修改一个用P~译q测试?br>7、删除?#8220;type code”的接口,q删除保存旧type code的静态变量?br>8、编译测试?br>Replace Type Code with SubClass
我的理解Q?br>
在这里Roomcd含一个属性IsMeetingRoom。如果ؓtrueQ则q个戉K是一个会议室Q如果ؓfalseQ则q个戉K是一个普通的戉K。这里true和false可以理解Z个简单的“型别~码”。它可以重构Z面的形式Q?br>
更复杂的情况Q?br>
q样需要根据RoomType的实际数量分d多个子类来?/p>

作法Q?br>使用Self Encapsulate FieldҎ把type code自我装h。如果type code被传递给构造函敎ͼ你就需要将构造函数换成factory method.
为type code的每一个数值徏立一个相应的subclass。在每个subclass中覆写type code的取值函?getter)Q其返回相应的type code倹{?br>每徏立一个新的subclass,~译q测试?br>从superclass中删除掉保存type code的值域。将type code讉K函数声明为抽象函数?br>~译Q测试?br>Replace Type Code with State/Strategy
你有一个type codeQ它会媄响class的行为,但你无法使用subclassing?br>以state object(专门用来描述状态的对象)取代type code?br>之所以无法subclassing是因为Type Code会在对象生命周期q程中发生变化?br>如果你打再完成本项重构之后再以Replace Conditional with Polymorphism(用多态替换条件判?化一个算法,那么选择Strategy模式比较合适;如果你打搬UM状态有关的数据Q而且你把新徏对象视ؓ一U变q状态,应该用State模式?br>
Replace Array with Object
你有一个数l?array)Q其中的元素各自代表不同的东ѝ?br>以对象替换数l,对于数组中的每个元素Q以一个值域表示之?br>String[] row =new String[3];
row[0]="Liverpool";
row[1]="15";
转换?br>Performance row=new Performance();
row.setName("Liverpool");
row.setWins("15");
3.10Switch Statements

如果你只是在单一函数中有些选择事例Q而你q不x动它们,那么“多?#8221;有Ҏ鸡用牛刀了。这U情况下Replace Paremeter with Explicit Method是个不错的选择。如果你的选择条g之一是nullQ可以试试Introduce Null Object
Replace Paremeter with Explicit Method
此方法即是将包含多个switch分支的函数的各个分支独立成不同的函数。比如:
public static Object CreateObject(int typeOfObject)
{
      switch(typeOfObject)
      {
            case 1:return new A();
            case 2:return new B();
            case 3:return new C();
      }
}
转换为:
public static Object Create1()
{
      return new A();
}
public static Object Create2()
{
      return new B();
}
public static Object Create3()
{
      return new C();
}
思考:q样会削弱此函数的运行期Ҏ?br>Introduce Null Object
使用q种重构Ҏ的好处就是你不用在向一个对象发送消息的时候去验这个对象是否存在。因为对象确实存在,只不q有可能对你发送的消息做出“我是I?#8221;的回应?br>作法
为source class建立一个subclassQ其行为像source class的null版本。在source class和null class中都加上IsNull()函数Q前者的IsNull()应该q回falseQ后者的应该q回true.可以建立一个nullable接口Q将isnull函数攑֜其中Q让source class实现q个接口?br>另外可以创徏一个testing接口Q专门用来检验对象是否ؓnull.
~译?br>扑և所?#8220;索求source obejct却得C个null”的地斏V修改这些地方,使他们改而获得一个null object?br>扑և所?#8220;讲source object与null做比较的地方”。修改这些地方,使它们调用IsNull()函数?br>你可以在不该在出现null value的地Ҏ上一些断aQ确保null的确不再出现。这可能对你有所帮助?br>q出q样的程序点Q如果对象不是nullQ做A动作Q否则做B动作?br>对于每一个上q地点,在null class中覆写A动作Q其行为和B动作相同?br>使用上述的被覆写动作(A)Q然后删?#8220;对象是否{于null”的条件测试。编译ƈ试?br>其他Ҏ情况
使用本项重构Ӟ你可以有数种不同的null objectsQ例如你可以?#8220;没有֮”?#8220;不知名顾?#8221;q两U情冉|不同的。果真如此,你可以针对不同的情况建立不同的null class。有时候null objects 也可以携带数据,例如不知名顾客的使用记录{等?br>本质上讲Q这是一个比Null Object模式更大的模式:Special Case模式。所谓Special case class是某个class的特D情况,有着Ҏ的行为。因此表qC知名֮的UnKnownCustomer 和表C没有顾客的NoCustomer都是Customer的特例。你l常可以在表C数量的class中看到这L特例cR例如Java点数有“正无I大”?#8220;负无I大”?#8220;非数?#8221;{特例。special case class的h值是Q它们可以降低你的错误处理开销。例如Q点运决不会抛出异常。如果你对NaN作Q点运,l果也会是个NaN。这?#8220;null object”的访问函数通常会返回另一个null object是一L道理?/p>

littlegai 2007-07-17 21:26 发表评论
]]>
The C++ Standard Library : A Tutoral and Reference MW记之auto_ptrhttp://m.shnenglu.com/qzb2006e/archive/2007/07/12/27880.htmllittlegailittlegaiThu, 12 Jul 2007 14:46:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2007/07/12/27880.htmlhttp://m.shnenglu.com/qzb2006e/comments/27880.htmlhttp://m.shnenglu.com/qzb2006e/archive/2007/07/12/27880.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/27880.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/27880.html        auto_ptr的动?/span>
        通常,一个函C按照下面的流E进行操?
        1.获取资源.
        2.q行一些操?
        3.释放之前所获取的资?
        如果函数所获取的那些资源与本地对象l定,它们׃在函数结束的时候被自动释放?因ؓ本地对象的析构函C被调?但是如果资源被显式获?q且没有与Q何对象绑?它们必须也被昑ּ的释放掉.在用指针的时?资源通常是被昑ּ理?
        一U典型的像上面这样用资源的方式是使用new来创建和用delete来释?
        但是作释攄的delete操作往往被忽?特别是函数有q回值的时?.当然,出现异常的时?也同样会发生q种风险.因ؓ异常有可能马上停止你函数的执?而不去进行delete释放.l果是内存泄漏,或者说得宽泛一??资源泄漏".Z避免资源泄漏,通常需要函数能够捕h有的异常.随之而来的就?代码变得来复?冗长.
        伴随着q种情况的发?一U智能指针auto_ptr出现?在Q何时?一旦指针本w被销?它所指向的数据也会被销?此外,因ؓ指针是一个本地变?不管函数到底是因为正常结?q是因ؓ非正常结?auto_ptr所指向的数据都会被销?
        有了auto_ptr,delete语句和catch语句变得不那么必要?auto_ptr和普通指针的使用方式基本相同,即用L"*"表示它所指向的对?同样?->"来访问所指向对象的成员方?但是有关指针的运?比如指针的自?不被支持(q也许是一个优?因ؓ指针q算也许会造成一些麻?.
        注意auto_ptr<>不允怽使用指派的方式来声明它所指向的对?比如:
        下面的操作是不允许的:
        std::auto_ptr<ClassA> ptr2 = new ClassA; //ERROR
        而应该采用显式的构造函数来初始?
        std::auto_ptr<ClassA> ptr1(new ClassA);  //OK
        通过auto_ptr来{换所有权
        auto_ptr在语意上提供了对于所有全的严格约?q意味着因ؓ如果一个auto_ptr删除了它所指向的对?那么q个对象不会被其他M对象所拥有.两个或以上的auto_ptrl不能同时拥有一个对?不幸的是,q种情况是有可能出现?所以只能有E序员来保q种情况不会发生.
        那么在这U情况下,auto_ptr的拷贝构造函数如何工作呢?通常它会把一个对象的数据复制l另外一个对?但是在这?恰恰是这U行ZD两个auto_ptr拥有相同对象q种情况的出?解决Ҏ很简?但是却得Z一个重要结?auto_ptr的拷贝构造函数和指派操作促成了auto_ptr对于对象所有权的一ơ移?
        看一下下面的代码:
        //initialize an auto_ptr with a new object
        std::auto_ptr<ClassA> ptr1(new ClassA);
        //copy the auto_ptr
        //- transfers ownership from ptr1 to ptr2
        std::auto_ptr<ClassA> ptr2(ptr1);
        W一句中,ptr1拥有new所创徏的那个对?然后W二句把对于对象的所有权从ptr1转移l了ptr2.所以在W二句之?ptr2拥有new创徏的那个对象的所有权,而ptr1则自动失M对于那个对象的所有权.ClassA只会在ptr2被析构的时候被释放?
        同样,对于一ơ指z操作也是如?如下所C?
        //initialize an auto_ptr with a new object
        std::auto_ptr<ClassA> ptr1(new ClassA);
        std::auto_ptr<ClassA> ptr2; //create another auto_ptr
        ptr2 = ptr1;        //assign the auto_ptr
                                  //- transfers ownership from ptr1 to ptr2
        注意,随着所有权的移?之前失去对象所有权的那个auto_ptr变成了一个空指针.
        当然,q可以让q个失去所指的I指针重新指向一个对?像下面这?
        std::auto_ptr<ClassA> ptr;               //create an auto_ptr
        ptr = std::auto_ptr<ClassA>(new ClassA); //OK, delete old object and own new
        对于所指向的对象的所有权的变换ؓ我们提供了auto_ptr的一U潜在用?函数可以使用向其他的函数传递所有权.q包含两U情?
        1.传入函数的对象不再?卛_auto_ptr作ؓ参数传递的时?在这U情况下,被调用的函数得到了传入的auto_ptr所指向的那个对象的所有权.因此,如果函数不再对象的所有权转移出来,那么对象׃在函数的调用l束之后销?
         2.函数要向外传出对?当auto_ptr被返回的时?所有权p调用的函数{Uȝ调用?
         ׃auto_ptrL牉|到对象所有权变换的问?所以在使用的时候一定要注意你是否真的要转换q个所有权.
         你可能打通过引用传递auto_ptr(s).但是q样做有可能最l你都不清楚所有权的归属了.M,q不是一个好的决定或设计.
        从auto_ptr的概念出?你可能会觉得即是传递常指针的话,对象的归属也会改?如果q种情况可能发生,那将是非常危险的.因ؓZL不期待一个成?帔R"的东西发生改?q运的是,通过一些技术上的处?q样做是不可能的.?
       
 1 #include<iostream>
 2 using namespace std;
 3 int getValue(auto_ptr<int>);
 4 int main()
 5 {
 6     const auto_ptr<int> myAutoPtr=auto_ptr<int>(new int);
 7     *myAutoPtr=10;
 8     cout<<getValue(myAutoPtr)<<endl;
 9     
10 }
11 int getValue(auto_ptr<int> ptr)
12 {
13     return 10*(*ptr);
14 }
       上面首先定义了常量的auto_ptr,q就表明,q个auto_ptr不能自己所指对象的所有权传递给其他对象.因而调用函数getValue的时候如果传递了上面定义的auto_ptr,׃被编译器发现,q作为编译错误反馈回?
错误Q?passing ‘const std::auto_ptr<int>’ as ‘this’ argument of ‘std::auto_ptr<_Tp>::operator std::auto_ptr_ref<_Tp1>() [with _Tp1 = int, _Tp = int]’ discards qualifiers
auto_ptr(s)作ؓ成员变量
当然,如果在类中用auto_ptr的时?你同样也可以避免资源泄漏q种问题的发?如果你用auto_ptr取代通常的指针的?你将不再需要对那些对象q行手动的析构处?同时,auto_ptr也能够有效避免因为初始化异常而导致资源泄漏这U情늚发生.因ؓ析构L在构造之?所以如果在构造的时候发生异?你往往不能够及旉放资?q而导致资源泄漏情늚发生.
        但是,在n用了auto_ptr带来的诸多好处的同时,你在处理拯构造函数和重蝲赋值操作的时?要格外注意auto_ptr所有权变换的问?当然,避免q类问题的最好方法就是用常量指?
        有关auto_ptr(s)的滥?/span>
        auto_ptr能够满一些需?特别是容易发生资源泄漏的时?它总能够发挥好的效?但是在用它的时候仍焉要注?不要滥用.在用的时?要注意以下几?
        1.auto_ptr(s)不能够共享对于所指向对象的所有权.
        2auto_ptr(s)不提供对于数l的支持.因ؓ在释放资源的时?auto_ptr使用的是delete而不是delete[].当然,对于数组而言,STL也有相应的处理办?比如容器.
        3.auto_ptr(s)不是指针的全?注意它ƈ不能解决一切问?注意它的应用场景.
        4.auto_ptr(s)不能满容器中对象的操作要求.

       







       



littlegai 2007-07-12 22:46 发表评论
]]>
重构--改善既有代码的设计读书笔?W三?4)http://m.shnenglu.com/qzb2006e/archive/2007/07/10/27833.htmllittlegailittlegaiTue, 10 Jul 2007 14:16:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2007/07/10/27833.htmlhttp://m.shnenglu.com/qzb2006e/comments/27833.htmlhttp://m.shnenglu.com/qzb2006e/archive/2007/07/10/27833.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/27833.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/27833.html现在回到重构--改善既有代码的设计这本书?br>3.4Long Parameter ListQ过长参数列Q?br>如果“向既有对象发Z条请?#8221;可以取得原本位于参数列上的一份数据,那么你应该激z重构准则Replace Parameter with Method。上q的既有对象可能是函数所属class内的一个值域Q也可能是另一个参数。你q可以用 Preserve Whole Object来自同一对象的一堆数据收藏v来,q以该对象替换它们。如果某些数据缺乏合理的对象归属Q可使用Introduce Parameter Object为它们制造出一?#8220;参数对象”?/p>

Replace Parameter with Methods(以函数取代参?
对象调用某个函数Qƈ结果作为参敎ͼ传递给另外一个函数。而接受该参数的函C可以Q也有能力)调用前一个函数?br>动机
如果函数可以通过其它途径Q而非参数列)获得参数|那么它就不应该通过参数取得该倹{?br>~减参数列的办法之一是Q看?#8220;参数接受?#8221;是否可以通过“与调用端相同的计?#8221;来取得参数携带倹{如果调用端通过“其所属对象内部的另一个函?#8221;来计参敎ͼq在计算q程?#8220;未曾饮用调用端的其它参数”Q那么你应该将q个计算q程转移到被调用端内Q从而除去该参数。如果你所调用的函数隶属另一对象Q而该对象拥有一个reference指向调用端所属对象,前面所说的q些也同样适用?br>作法
1、如果有必要Q将参数的计过E提炼到一个独立函C?br>2、将函数本体?#8220;对该参数的引?#8221;替换为对“新函数的引用”?br>3、每ơ替换后Q修改ƈ试?br>4、全部替换完成后Q适用Remove Parameter该参数L?/p>


思考:
实从实践角度讲Q上面这U方法是一U很实用的重构方法。确实是~减了函数的参数个数Qƈ隐藏了一些中间结果。但是我认ؓQ在应用q个Ҏ的时候,q应当考虑q样两个问题Q?br>1、当中间函数Q方法)被隐藏的时候,以这个中间函数的q回gؓ参数的那个函数名q能够表q自q用途吗Q?br>2、被修改的那个函数所处的具体语境是什么。因为在面向对象~程的时代,单独去考虑一个函数的情况是很的。确保这个函数是否处在正的位置上(如是否处在正的cMQ是必要的?br>



此间存在一个重要的例外。有时候你明显不希望造成“被调用之对象”?#8220;较大对象”间的某种依存关系。这时候将数据从对象拆解出来单独作为参敎ͼ也很合情合理。但是请注意其所引发的代仗如果参数列太长或变化太频繁Q你需要重新考虑自己的依存结构了?

 Introduce Parameter ObjectQ引入参数对象)
某些参数L很自然的同时出现Q以一个对象取代这些参数?br>你常会看到特定的一l参数L一赯传递。可能有好几个函数都使用q一l参敎ͼq些函数可能隶属同一个classQ也可能隶属不同的classes。这样一l参数就是所谓的Data Clump(数据泥团)。我们可以运用一个对象包装所有这些数据,再以该对象取代它们?br>作法Q?br>1、新Z个classQ用以表Cx换的一l参数。将q个class设ؓ不可变的(不可被修改的Qimmutable)?br>2、编译?br>3、针对用该l参数的所有函敎ͼ实施Add ParameterQ以上述新徏class之实体对象作为新d敎ͼq将此一参数D为null?br>4、对于Data Clump(数据泥团)中的每一?在此均ؓ参数)Q从函数{֐式中U除之,q修改调用端和函数本体,令他们都改而通过“新徏的参数对?#8221; 取得该倹{?br>5、每除去一个参敎ͼ~译q测试?br>6、将原先的参数全部除M后,观察有无适当函数可以q用Move Method搬移到参数对象中?/p>


思考:
现在我有一个函数fQ函数定义如下:
public string f(int i,int j,string s)
{
   int newValue=i+j;
   string result=s+":"+newValue.ToString();
   return result;
}
现在我把q三个参数{化ؓcd象,cd定义为MyParameter
public class MyParameter
    {
        
int _i;

        
public int I
        {
            
get { return _i; }
            
set { _i = value; }
        }
        
int _j;

        
public int J
        {
            
get { return _j; }
            
set { _j = value; }
        }
        
string _s;

        
public string S
        {
            
get { return _s; }
            
set { _s = value; }
        }
        
public MyParameter(int i, int j, stirng s)
        {
            _i 
= i;
            _j 
= j;
            _s 
= s;
        }

    }

然后再我的代码中q样写:
f(new MyParameter(3,2,"Result"));

发现什么问题了吗?
1、好像参数ƈ没有减少Q只不过是移动到了构造函CQ?br>2、你从f参数中将会看不出f中到底需要什么东西(如果参数名称体现了参数的用途的话)?br>q说明:
1、虽然这是经典的重构ҎQ但是不能滥用,在用的时候要谨慎考虑场景是否合适?br>2、注意TDA原理Q不要刻意生太多的中间对象?br>3、参C能随便合q或隐去Q要特别注意领域模型Q要切合领域模型所表述的意图?br>我个为可以应用的场景Q?br>是文中所说的DataRangeQ即适合于被转换为参数对象的参数列具有通用的含义,q且概念层次比较低?/p>


 



littlegai 2007-07-10 22:16 发表评论
]]>
重构--改善既有代码的设计读书笔?W三?3)http://m.shnenglu.com/qzb2006e/archive/2007/07/08/27579.htmllittlegailittlegaiSun, 08 Jul 2007 12:31:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2007/07/08/27579.htmlhttp://m.shnenglu.com/qzb2006e/comments/27579.htmlhttp://m.shnenglu.com/qzb2006e/archive/2007/07/08/27579.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/27579.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/27579.html其实在看Martin Fowler的重构这本书的很长一D|间里Q我一直把它错当成了另外一本书的中文版Q那本书的名字就是:John.Wiley.and.Sons.Refactoring.in.Large.Software.Projects.Performing.Complex.Restructurings.Successfully.Jun.2006
以前曄看过q本书,目前q没有找C文版。相对于《重?-改善既有代码的设计》的侧重实践来说Q上面这本书理论性更Z些。看讲实늚书有个缺点,是你看了不上手做一做的话,{于白看Q而理论呢Q你可以C。所以下面穿插一些《Refactoring.in.Large.Software.Projects.Performing.Complex.Restructurings.Successfully》的理论Q有很多通过英文字面意思很隄解,q样我会在网上找些资料,然后抄记在下面:
设计原理
        正如代码?#8220;有味”一Pl构也会“有味”Q他们通常会由对于设计原理的违反而引赗因此设计原理会为我们提供一些有价值的东西q而帮助我们ؓ设计d狐臭。在我们从设计中扑ևq反q些设计原理的地方的同时,我们也有了自qx来改善我们的设计。。下表列Z当前行的设计原理:

1?span style="BACKGROUND-COLOR: yellow">DRY(Don't Repeat Yourself)Q不要写重复的代码。也可以叫做“一ơ且仅一?Once and Only Once)”原理?br>2?span style="BACKGROUND-COLOR: yellow">SCP(Speaking Code Principle)Q代码应该清楚地表明它自q意图。代码中出现注释Q说明代码不能清楚地表现自己的意图?br>3?span style="BACKGROUND-COLOR: yellow">OCP(Open Closed Principle)Q一个设计单元应该向修改开放。这U修改不应该D调用Ҏ效。承是一U能够让你达到此目的的方法。子cd以进行一些调_而超cM持不变?br>4?span style="BACKGROUND-COLOR: yellow">LSP(Liskov Substitution Principle)Q个软g实体如果使用的是一个基cȝ话,那么一定适用于其子类Q而且它根本不能察觉出基类对象和子cd象的区别。反q来代换是不成立?br>5?span style="BACKGROUND-COLOR: yellow">DIP(Dependency Inversion Principle)Q等U高的概念不应该依赖于等U低的概念(或实玎ͼ。对于从属关pL说刚好相反。因为等U高的概忉|LU低的概忉|说变动的可能性要?br>6?span style="BACKGROUND-COLOR: yellow">ISP(Interface Segregation Principle)Q接口隔d理。接口应该尽量的。他们应该仅包含很少的方法,但是q些被放|在同一个接口中的方法应该是紧密相关的?br>7?span style="BACKGROUND-COLOR: yellow">REP(Reuse/Release Equivalency Principle)Q可重用的元素必然是已经被发布的元素?/p> 8?span style="BACKGROUND-COLOR: yellow">CRP(Common Closure Principle)Q?font style="FONT-SIZE: 12pt" size=2>包中的所有类对于同一cL质的变化应该是共同闭的?/font> 一个变化若对一个包产生影响Q则对该报的所有类产生影响。而对其他的包不构成Q何媄响?br>9?span style="BACKGROUND-COLOR: yellow">ADPQAcyclicQ无环的QDependencies PrincipleQ:包之间的依赖关系应当是无环的?br>10?span style="BACKGROUND-COLOR: yellow">SDP(Stable Dependencies Principle)Q一个包应该依赖于至像它自己那L定的包?br>11?span style="BACKGROUND-COLOR: yellow">SAPQStable Abstractions PrincipleQ:稳定的包,其抽象程度越高。不E_的包通常是具体化的包?br>12?span style="BACKGROUND-COLOR: yellow">TDAQTell,Don't AskQ:不要向一个对象去甌另外一个对象,而应该告诉这个对象应该如何去做?br>13?span style="BACKGROUND-COLOR: yellow">SOC(Separation Of Concerns)Q不要在一个类中包含多个关注点。这通常也被叫做“责Q单一原理”?br>cdpd中的“狐臭”
两个或多个类之间的关p通常包含“使用”?#8220;l承”两种。如果我们想在一个系l中扑և“使用”关系Q我们应该看一?#8220;静?#8221;关系图。在pȝq行时呈现出来的“使用”关系构成了对象之间的动态关pd?br>一、无用类

Refactoring.in.Large.Software.Projects.Performing.Complex.Restructurings.Successfully
那些不再使用的类会因为具有一些显而易见的无用功能而增加系l的负担。这些负担包括:E序开发者需要花费大量的旉来分辨出一个正的c,构徏pȝ的时间变得更长,pȝ变得更加难以理解?br>相对于完全无用的c,更多的情况下你会遇到包含部分无用代码的类。这是因Z个类中包含了太多的功能,而在真正使用的时候,那些功能又被抛弃掉了。我们可以在重构的时候依据这些功能把c进行拆分,通过拆分我们会首先得到无用类。然后进一步对它进行处理?br>不仅仅单单一个类会成为无用类Q有的时候,处在同一个关pd中的c都回成为无用类(s)?br>无用c通常因ؓ两种原因而出玎ͼ
Q、技术上提供覆盖面尽可能q的支持Q一个开发者推一个类可能最l会被用刎ͼ即没有q象表明现实中有与之对应的需求?br>Q、重构:通过对系l的修改Q以前需要用到的c,现在变得陈旧q期了?br>二、树型依赖关p?br>
Refactoring.in.Large.Software.Projects.Performing.Complex.Restructurings.Successfully
树型依赖关系图体C对于pȝ的一U分解。树中的每一个类都确定的被另外一个类使用?br>鉴于在面向对象的应用E序中,功能分解本n通常会被看作是一U?#8220;狐臭”Q一U树型依赖结构像重复代码一样也应该被看作是一U?#8220;狐臭”。在?-6中,cProtocol除了被类Data Storage使用外,不再被别的地方用。重用没有发生?br>三、静态环状依赖关p?br>
Refactoring.in.Large.Software.Projects.Performing.Complex.Restructurings.Successfully
两个cd此用对Ҏ最单的环状依赖关系。环状依赖关pM也可以包含多个类?br>环状依赖关系会环本w变得更加臃ѝ环所h的消极媄响包括:
a、不可理解性:q些cM能够被一个又一个的单独理解Q因为它们彼此依靠对Ҏ实现功能。又或者是Q一个类需要从多个cM选择一个作为理解他们本w的前提?br>b、可l护性:环状依赖可能包含严重的ƈ且不可预的递推关系Q进而导致修改包含它的系l变得非常困难?br>c、可计划性:对环的修改到底会造成什么媄响是很难预期的。估到底需要多的工作来完成这个修改会是一件很困难的事?br>d、设计的清洁性:因ؓ处在环中的那些类会直接或间接的访问到处在环中的Q意一个类Q因此,从理ZԌcM的这U关pd随意了。如果在q个环中又恰好把一个方法放到错误的cMQ会D理解q种设计变得更加困难?br>e、重用性:q些cdd旉用。如果在一个给定的语境中,只有其中的一个类所提供的功能被xQ因为处在环中,q个cM能被单的剥离q用?br>f、可试性:q些cdM赯试。这增加了测试的要求以及堪错的难度。如果想要独立的试其中的一个类Q就必须使用“伪对?#8221;?br>g、异常处理:通常异常会在环中?#8220;堆积”。如果环中的一个方法抛Z异常Q他会潜在得影响环中的其他方法?br>h、依赖引入问题:每一个处于环中的cd时又依赖于另一个处于环中的cd在环外的依赖关系?br>昄Q环中的最大长度越大,代码?#8220;狐臭”呛_浓。然而,在有些地方,只包含两个类的环却是一U被推崇的设计方案,被应用于很多设计模式中(如P代器模式Q?br>四、显式依?br>面向对象支持装原理以及信息隐藏原理Q内部的实现被隐藏于接口之中。客L的代码无ȝ道Q何有关于API的实现。另外,接口与实现类之间存在一?#8220;裂痕”。很多开发者相信封装和信息隐藏只会在成员变量被定义?#8220;U有”的时候才会有效。这当然不是事实Q在很多pȝ中都是支?#8220;属?#8221;的,q且属性可以被l承。然而,有这样一个事实,在一个系l中Q显式依赖关pd是无法隐藏的。一个具有公׃赖关pȝpȝ在被修改的时候,M产生q样那样的问题,反之Q私有的局部的依赖关系只会有小范围的媄响?br>TDA(Tell,don't ask)原理指出了一条正的途径Q理x况下Q客L告诉对象自己打算做什么。既不要通过已有对象获取一个新的对象,更不要用那个新的对象q行一些操作?br>下面看一个例子。在q个例子中,“订单”有很多的状态。我们可以简单的以打开的订单和关闭的订单来单的区分一下。打开的订单就是客h回款的订单。现在我们要写一些代码,来计所有打开的订单的总额?br>如果我们使用一个方法calculateValueOpenOrders(注意Q这个方法是写在调用方的Q我们的调用方的cd定ؓFooQ,而方法体如下。可以看个方法违反了TDA原理Q?br>

public float calculateValueOpenOrders(ListOfOrders orders) 
{
    
float totalValue = 0.0f;
    
for (int i=0; i<orders.getNumber(); i++
    {
        Order a 
= orders.getOrder(i);
        
if (a.isOpen) 
        {
            totalValue 
+= a.getValue();
        }
    }
    
return totalValue;
}
原因是客户端的Foo直接使用Orders来获取其中的一些信息,而不是告诉Orders我要做什么?br>
Refactoring.in.Large.Software.Projects.Performing.Complex.Restructurings.Successfully
现在我们做一下修改,把打开的订单的金额计算Ud到订单内部进行。如果订单是打开的,q回本订单的金额Q反之,q回0?br>
public class ListOfOrders 
{
    
public float calculateValueOpenOrders() 
    {
        
float totalValue = 0.0f;
        
for (int i=0; i<getNumber(); i++
        {
            Order a 
= getOrder(i);
            totalValue 
+= a.getOpenValue();
        }
        
return totalValue;
    }
}
     
public class Order 
{
    
public float getOpenValue() 
    {
        
if (isOpen()) 
        {
            
return getValue();
        }
        
else 
        {
            
return 0;
        }
    }
}
我们可能会因为所有Order都要q回打开的订单的金额而感觉不爽。如果你打算多次使用TDA原理Q你可能通过增加一个方?#8220;addOpenValue”来增加类order的柔性。但是,同时q也意味着cOrder会知道另外的一些Order的存在。在q种情况下,我们可能会违反SOCQ即单一职责原理Q。我们不应该忽略q样一点:在用一些设计原理的时候,q要兼顾pȝ的^衡性。在q个例子中,q个Ҏ是否应该加入取决于它是否真的与这个类?#8220;领域模型”所匚w?br>新的实现方式不仅仅代码更加短,而且q包括如下的优点Q?br>功能有了正确的归属。在大多数情况下Q上面第一D代码中的方法calculateValueOpenOrders通常是被攑ֈUIcM或者是一些HelpercMQ而这些类通常有一些奇异的名字Q比如OpenOrders CalculatorQ。这对于q个Ҏ来说Q不是一个正的归属?br>TDA原理保cȝ使用应该局部化Q而不要散步到pȝ的各个角落。因此可以简化一些优化方案的实现?br>

littlegai 2007-07-08 20:31 发表评论
]]>
The C++ Standard Library : A Tutoral and Reference MW记之错误和异常处理http://m.shnenglu.com/qzb2006e/archive/2007/06/26/26943.htmllittlegailittlegaiTue, 26 Jun 2007 14:18:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2007/06/26/26943.htmlhttp://m.shnenglu.com/qzb2006e/comments/26943.htmlhttp://m.shnenglu.com/qzb2006e/archive/2007/06/26/26943.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/26943.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/26943.html有三U标准异常类:
1.语言支持型异?Exceptions for language support )
比如:
用new创徏对象p|的时?会抛出bad_alloc异常;
dynamic_castp|会抛出bad_cast异常;
函数抛出不可控异常的时候会抛出bad_exception异常或调用unexpected函数.

#include <iostream>
class E1
{

};
class E2
{
};
void f_throwE1() throw(E1)
{
    
throw E1();
}
void f_throwE2() throw(E1)
{
    
throw E2();
}
void f_throwE2AsBadException() throw (E1,std::bad_exception)
{
    
throw E2();
}
int main()
{
    
try
    {

        f_throwE1(); 
//1:抛出可控异常
        f_throwE2(); //2:抛出不可控异?执行unexpected函数
        f_throwE2AsBadException(); //3:抛出不可控异?被认为是bad_exception
    }
    
catch(const E1 &e1)
    {
        std::cout
<<"E1 error occured"<<std::endl;    
    }
    
catch(const std::bad_exception &e2)
    {
        std::cout
<<"bad_exception occured"<<std::endl;
    }
    
catch(const E2 &e2)
    {
        std::cout<<"E2 error occured"<<std::endl;
    }
    catch(...)
    {
        std::cout<<"unknown exception occured"<<std::endl;
    }
}
上面的程序中,执行1,会生如下的l果:
E1 error occured
执行2,q没有被作ؓcdE2的异常所捕获.而是出现了如下提C?
terminate called after throwing an instance of 'E2'
忽略
现在执行3.l果q没有捕获到std::bad_exception异常.而是仍然出现了这L错误提示:
terminate called after throwing an instance of 'E2'
忽略
同样的的例子,上面是在linux下执行的情况.下面换做vs2003的vc7.执行3,l果?
unknown exception occured
即也没有捕获到std::bad_exception,但是被更加通用?..所捕获?q是~译器情늚不同.
2.c++标准库的异常(Exceptions for the C++ standard library)
c++标准库的异常c通常从logic_errorcȝ?逻辑错误从理Z来说,臛_应该被程序所避免,例如通过对于函数参数q行额外的测?c++提供了诸如invalid_argument,length error,out_of_range,domain_error{异常类.
3.在程序域之外的异?Exceptions for errors outside the scope of a program)
此类异常通常难于避免.
异常cȝ头文?br>异常的基cdbad_exceptionc被定义?lt;exception>?
cbad_alloc?lt;new>中被声明;
bad_cast和bad_typeid?lt;typeinfo>中被声明;
ios_base::failure?lt;ios>中被声明;
所有其他的c都被定义在<stdexcept>?
异常cȝ成员
在异常类中除cd信息之外,唯一可以获取的信息来自于函数what():
namespace std {
    class exception {
      public:
            virtual const char* what() const throw();
            ...
      };
}

使用what来获取信?
try {
    ...
}
catch (const exception& error) {
    //print implementation-defined error message
    cerr << error.what() << endl;
    ...
}
可以以下面的方式创徏标准异常:
string s;
...
throw out_of_range(s);

或?br>throw out_of_range("out_of_range exception (somewhere, somehow)");
从标准异常类l承
例如:
#include <exception>
#include 
<iostream>
class MyException:public std::exception
{
private:
    
char* errorMessage;
public:
    MyException(
const char* errMsg)
    {
        errorMessage
=new char[strlen(errMsg)];
        strcpy(errorMessage,errMsg);
    }
    
~MyException() throw()
    {
        
if(errorMessage)
        {
            delete[] errorMessage;
            errorMessage
=NULL;
        }
    }
    
virtual const char* what() const throw()
    {
        
return errorMessage;
    }

};
int main()
{
    
try
    {
        
throw MyException("Error Occured!!");
    }
    
catch(const std::exception &e)
    {
        std::cout
<<e.what()<<std::endl;
    }

}








littlegai 2007-06-26 22:18 发表评论
]]>
The C++ Standard Library : A Tutoral and Reference MW记之命名空?2)http://m.shnenglu.com/qzb2006e/archive/2007/06/25/26935.htmllittlegailittlegaiMon, 25 Jun 2007 13:18:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2007/06/25/26935.htmlhttp://m.shnenglu.com/qzb2006e/comments/26935.htmlhttp://m.shnenglu.com/qzb2006e/archive/2007/06/25/26935.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/26935.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/26935.html命名I间是ؓ了应对命名冲H这U情늚出现而生的 .命名I间是可扩展?你可以用相同的命名I间来定义你的那些在物理上处于不同位|的lg.一个典型的例子是namespace std.
你可以有三种选择来用std命名I间.
1.使用std::作ؓ前缀.
?
std::cout << std::hex << 3.4 << std::endl;
2.使用using q行预定?br>using std::cout;
using std::endl;
然后q样使用:
cout << std::hex << 3.4 << endl;
3.直接使用using.
using namespace std;
cout << hex << 3.4 << endl;
不要在代码上下文不明的地方使用q种用法( 如头文g?.
c++标准中对?span style="font-weight: bold; font-size: 14pt;">头文?/span>引入使用了一U新的写??
#include <iostream>
q实际上是引入了c++的标准模板库的iostream.h文g.
而对于旧的c语言的头文g,可以使用q种方式引入:
#include <cstdlib> //相当?lt;stdlib.h>                 
#include <cstring> //相当?lt;string.h>
有意思的?如果在引入头文g的时候这样写,可以把c风格的函数加上std命名I间来?
?
#include <cstring>
#include
<cstdio>
int main()
{
    std::printf(
"%d",std::strlen("hello world!"));
}

当然,仍然可采用兼容于c风格的头文g引入方式:
#include <stdlib.h>







littlegai 2007-06-25 21:18 发表评论
]]>
重构--改善既有代码的设计读书笔?W二?3)http://m.shnenglu.com/qzb2006e/archive/2007/06/24/26856.htmllittlegailittlegaiSun, 24 Jun 2007 13:35:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2007/06/24/26856.htmlhttp://m.shnenglu.com/qzb2006e/comments/26856.htmlhttp://m.shnenglu.com/qzb2006e/archive/2007/06/24/26856.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/26856.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/26856.html难以通过重构手法完成的设计改?/strong>
比如说在一个项目中Q我们很难(但还是有可能Q将“无安全需求情况下构造v来的pȝ”重构?#8220;安全性良好的pȝ”?br>q种情况下我的办法就?#8220;?span style="BACKGROUND-COLOR: yellow">惌重构的情?#8221;。考虑候选设计方案时Q我会问自己Q将某个设计重构为另一个设计的隑ֺ有多大? 如果看上d单,我就不用担心选择是否得当Q于是我׃选择最单的设计Q哪怕它不能覆盖所有潜在需求也没关pR但如果预先看不出简单的重构办法Q我׃在设计上投入更多力气?br>何时不该重构Q?br>重写Q而非重构Q的一个清楚的讯号是Q现有代?span style="BACKGROUND-COLOR: yellow">Ҏ不能正常工作。你可能只是试着做点试Q然后就发现代码中满是错误,Ҏ无法E_q作。记住,重构之前Q代码必v码能够在大部?/span>情况?span style="BACKGROUND-COLOR: yellow">正常q作?br>另外Q如果项目自己已q?span style="BACKGROUND-COLOR: yellow">最后期?/span>Q你也应?span style="BACKGROUND-COLOR: yellow">避免重构。在此时机,从重构过E中赢得的生产力只有在最后期限过后才能体现出来,而那个时候已l时不我予?br>Wrad Cunningharn的看法:未完成的重构工作?#8220;债务”。过于复杂的代码所造成的维护和扩展的额外开销Q就?span style="BACKGROUND-COLOR: yellow">利息。你可以承受一定程度的利息Q但如果利息太高你就会被压垮。把债务理?/span>是很重要的,你应该通过重构来偿q部分债务?br>重构与设?br>Alistair CockburnQ有了设计,我可以思考更快,但是其中充满漏z?br>有一U观点认为:重构可以成ؓ“预先设计”的替代品。这意思是你根本不必做M设计Q只按照最初想法开始编码,让代码有效运作,然后再将它重构成型。极限编E的支持者极力提倡这U办法?br>但这不是最有效的途径。极限编E的爱好者们也会q行预先设计。他们会使用CRC?/span>或类似的东西来检验各U不同的xQ然后才得到W一个可被接受的解决ҎQ然后才开始编码,然后才能重构。关键在于:重构改变?/span>“预先设计”的角艌Ӏ如果没有重构,必M?#8220;预先设计”的正无误,q个压力太大了?br>

什么是CRC?
CRC(Class-Responsibility-Collaborator)卡徏模是一U简单且有效的面向对象的分析技术。在一个OO(面向对象)开发项目中Q包括用戗分析员和开发者在建模和设计过E中l常应用CRC卡徏模,使整个开发团队普遍的理解形成一致?br>它由三部分组成:
1. c?Class)
2. 职责(Responsibility)
3. 协作(Collaborator)
一个类代表许多cM的对象。而对象是pȝ模型化中x的事物。他们可以是一个h、地斏V事情、或M对系l有重要性的概念。类名在CRC卡的剙?br>职责是类需要知道或做的M事物。这些职责是c自w所知的知识Q或cd执行时所知的知识?br>协作是指取消息,或协助执行活动的其他cR在特定情Ş下,与指定的cL一个设惛_同完成一?或许?步骤。协作的c顺着CRC卡的双排列?br>
(上图http://book.csdn.net/bookfiles/116/1001163602.shtml)



在可以重构的前提下,你只需要得C?span style="BACKGROUND-COLOR: yellow">_合理
的解x案就够了?br>如果你在预先设计时在所有有可能出现变化的地斚w建立LzL,却在最后发现这些灵zL都毫无必要Q这才是最大的p|。你知道Q这其中肯定有些灉|性的派不上用场Q但你却无法预测到底哪些z不上用场?br>而有了重构,则只需要考虑Q把一个简单的解决Ҏ重构成这个灵zȝ解决Ҏ有多大难度?如果{案?#8220;相当Ҏ”Q那么你只需实现目前?span style="BACKGROUND-COLOR: yellow">单方?/span>可以了?br>重构与性能
虽然重构必然会软gq行更慢Q但它也使Y件的性能优化更易q行。除了对性能有严D求的实时pȝQ其他Q

 

何情况下“~写快速Y?#8221;的秘密就是:首先写出可调软gQ然?span style="BACKGROUND-COLOR: yellow">调整它以求获得够速度?br>~写快速Y件的ҎQ?br>1、时间预法?br>为每个组件分配资源(包括旉资源和执行轨q)Q每个组件绝对不能超q自q预算Q就拥?#8220;可在不同lg之间调度预配旉”的机制也不行。例如心律调节器Q在q样的系l中Q迟来的数据是错误的数据?br>2、持l关切法?br>要求E序员在M旉做Q何事Ӟ都要设法保持pȝ的高性能?br>q种方式通常不会起太大作用。Q何修改如果ؓ了提高性能Q通常会ɽE序难以l护Q因而减~开发速度。性能一旦被分散到程序各个角落,每次改善都只不过是从“对程序行为的一?span style="BACKGROUND-COLOR: yellow">狭隘视角”出发而已?br>3、利?0%l计数据
90%的优化都是白费劲Q因为难得被执行?br>所以以一U?#8220;良好?span style="BACKGROUND-COLOR: yellow">分解方式”来徏造自qE序Q不Ҏ能投以M兛_Q直臌入性能优化阶段?br>优化的过E:量-->优化-->~译-->试-->再次量.
使用性能热点量工具“发现热点、去除热?#8221;Q直到获得客h意的性能?br>McConnell提供了关于这Ҏ术的更多信息?/p>

 很想了解相关技?但是没有扑ֈ具体资料.倒是有两个开源项?/p> p-unit?strong>junitperf
http://www.javapronews.com/javapronews-47-20030721ContinuousPerformanceTestingwithJUnitPerf.html



littlegai 2007-06-24 21:35 发表评论
]]>
The C++ Standard Library : A Tutoral and Reference MW记?W二章扫?/title><link>http://m.shnenglu.com/qzb2006e/archive/2007/06/20/26729.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Wed, 20 Jun 2007 14:50:00 GMT</pubDate><guid>http://m.shnenglu.com/qzb2006e/archive/2007/06/20/26729.html</guid><wfw:comment>http://m.shnenglu.com/qzb2006e/comments/26729.html</wfw:comment><comments>http://m.shnenglu.com/qzb2006e/archive/2007/06/20/26729.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/qzb2006e/comments/commentRss/26729.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/qzb2006e/services/trackbacks/26729.html</trackback:ping><description><![CDATA[<span style="font-weight: bold;">静态常量的初始?/span><br>书中?现在可以在类l构中初始化整型的静态成员了(N以前不可?).我想书中大概是这个意?<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">class</span><span style="color: #000000;"> MyClass<br>{<br></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br></span><span style="color: #0000ff;">static</span><span style="color: #000000;"> </span><span style="color: #0000ff;">const</span><span style="color: #000000;"> </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> num</span><span style="color: #000000;">=</span><span style="color: #000000;">100</span><span style="color: #000000;">;<br></span><span style="color: #0000ff;">int</span><span style="color: #000000;"> values[num];<br>};<br></span><span style="color: #0000ff;">int</span><span style="color: #000000;"> main()<br>{<br>std::cout</span><span style="color: #000000;"><<</span><span style="color: #000000;">MyClass::num;<br>}</span></div> <span style="font-weight: bold;">main的声?/span><br>在c++标准中只有两Umain函数的写法会被接?<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<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;"> main()<br>{<br>    <img src="http://m.shnenglu.com/Images/dot.gif"><br>}<br></span></div> <br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<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;"> main (</span><span style="color: #0000ff;">int</span><span style="color: #000000;"> argc, </span><span style="color: #0000ff;">char</span><span style="color: #000000;">*</span><span style="color: #000000;"> argv[])<br>{<br>    <img src="http://m.shnenglu.com/Images/dot.gif"><br>}<br></span></div> 与C语言不同,C++在main中没有返回值的情况?会隐式的q回0.但这U情?~译器在~译的时?会给你警?<br><span style="font-weight: bold;">复杂度问题和大写的O标志<br></span>大写的O标志是用来考量一个算法的旉复杂度的.如果q算的时间与q算元素的个数接q于正比,那么旉复杂度就是O(n).当然除此之外,q有q的时间复杂度.q里的是,c++ 中的数学库中一些算法的实现都仔l考虑了时间复杂度的问?<br><br><span style="font-weight: bold;"></span><img src ="http://m.shnenglu.com/qzb2006e/aggbug/26729.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/qzb2006e/" target="_blank">littlegai</a> 2007-06-20 22:50 <a href="http://m.shnenglu.com/qzb2006e/archive/2007/06/20/26729.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重构--改善既有代码的设计读书笔?W一?2)http://m.shnenglu.com/qzb2006e/archive/2007/06/20/26656.htmllittlegailittlegaiWed, 20 Jun 2007 13:42:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2007/06/20/26656.htmlhttp://m.shnenglu.com/qzb2006e/comments/26656.htmlhttp://m.shnenglu.com/qzb2006e/archive/2007/06/20/26656.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/26656.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/26656.htmlq用多?polymorphism)取代与h格相关的条g逻辑
在另一个对象的属性基上运行switch语句Qƈ不是什么好L。如果不得不使用Q也应该在对象自q数据上而不是在别h的数据上使用。选择对象之间的传递关pȝ时候,应当考虑选择稳定的对象的属性传递给易变的对象(如书中的租期长度来自RentalQ稳定,不易变)传递给MovieQ不E_Q易变)Q?br>对于cA和类BQ如果A中存在因B而变化的属性或Ҏ体,则将它们Ud到B中,A中只保留Ud后B暴露lA的接口(或方法)?br>l于.......我们来到l承(inheritance)
此部分包含的重构ҎQ?br>Self Encapsulate FieldQ自装域?br>Move MethodQ移动方法?br>Replace Conditional with PolymorphismQ用多态替换条仉择?br>Replace Type Code with State/StrategyQ在q个Ҏ中用了上面三个Ҏ作ؓ步骤。即用状态、策略替换代码,与cd怾的行为搬Ud模式内。在使用它的时候,多用对于以cd怾的行行Self Encapsulate Field作ؓW一步骤。从而确保Q何时候都通过getter和setter两个函数来运行这些行为。第二步通常采用Move MethodҎQ即把代码从类的宿M搬移到子cM厅R第三步采用Replace Conditional with PolymorphismҎQ将switchQif{条件分支语句{变ؓ多态Ş式?br>下面是一个小实验Q?br>一、重构之前的代码Q?br>

public class ClassA {
    
public int getValue(TheType type)
    {
        
switch(type)
        {
        
case SmallValue:return 100;
        
case MidValue:return 200;
        
case BigValue:return 300;
        
default:return 0;
        
        }
    }
    
    
public static void main(String args[])
    {
        ClassA instanceA
=new ClassA();
        System.out.println(
"theValueIs:"+instanceA.getValue(TheType.SmallValue));
    }
}

应用Self Encapsulate Field之后的效果:

public class ClassAModified {

    
/**
     * 
@param args
     
*/
    
public TheValue _theValue;
    
public int getValue(TheType type)
    {
        
switch(type)
        {
        
case SmallValue:return 100;
        
case MidValue:return 200;
        
case BigValue:return 300;
        
default:return 0;
        
        }
    }

        
    
public TheValue get_theValue() {
        
return _theValue;
    }

    
public void set_theValue(TheType type) {
            }
        
}
public class TheValue
    {
    
    }
        

应用Move Method之后的效果:

public class ClassAModified {

    
/**
     * @param args
     
*/
    
public TheValue _theValue;
    
public int getValue(TheType type)
    {
        
return _theValue.getValue(type);
    }

    
public static void main(String[] args) {
        
// TODO Auto-generated method stub

    }
    
    
public TheValue get_theValue() {
        
return _theValue;
    }

    
public void set_theValue(TheType type) {
        _theValue
=new TheValue();
    }
    
public class TheValue
    {
        
public int getValue(TheType type)
        {
            
switch(type)
            {
            
case SmallValue:return 100;
            
case MidValue:return 200;
            
case BigValue:return 300;
            
default:return 0;
            
            }
        }
    }
    

}

 应用Replace Conditional with Polymorphism之后的效果:

public class ClassAModified {

    
/**
     * @param args
     
*/
    
public TheValue _theValue;
    
public int getValue(TheType type)
    {
        
return _theValue.getValue();
    }

    
public static void main(String[] args) {
        
// TODO Auto-generated method stub

    }
    
    
public TheValue get_theValue() {
        
return _theValue;
    }

    
public void set_theValue(TheType type) {
        
switch(type)
        {
            
case SmallValue:_theValue= new SmallValue();
            
case MidValue:_theValue= new MidValue();
            
case BigValue:_theValue= new BigValue();
            
default:_theValue=new TheValue();
        
        }
    }
    
public class TheValue
    {
        
public int getValue()
        {
            
return 0;
        }
    }
    
public class SmallValue extends TheValue
    {
        
public int getValue()
        {
            
return 100;
        }
    }
    
public class MidValue extends TheValue
    {
        
public int getValue()
        {
            
return 200;
        }
    }
    
public class BigValue extends TheValue
    {
        
public int getValue()
        {
            
return 300;
        }
    }

}

l语
重构的节奏:试、小修改、测试、小修改、测试、小修改。。?br>正是q种节奏让重构得以快速而安全的前进?br> 


 



littlegai 2007-06-20 21:42 发表评论
]]>
数据l构MW记Q用栈替代递归Q?/title><link>http://m.shnenglu.com/qzb2006e/archive/2007/06/17/26499.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Sun, 17 Jun 2007 09:19:00 GMT</pubDate><guid>http://m.shnenglu.com/qzb2006e/archive/2007/06/17/26499.html</guid><wfw:comment>http://m.shnenglu.com/qzb2006e/comments/26499.html</wfw:comment><comments>http://m.shnenglu.com/qzb2006e/archive/2007/06/17/26499.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/qzb2006e/comments/commentRss/26499.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/qzb2006e/services/trackbacks/26499.html</trackback:ping><description><![CDATA[        数据l构上面在讲到栈的时候,Z提了一下递归。实际上递归是用栈来实现的。在很多法书上Q对于一些用递归方式写成的算法,相应的也l出了栈的算法。这里我要把fibonacci数列分别用递归和栈的方式写出来Q由于我以前的算法教材丢׃Q而数据结构中也没有给出相应的伪码Q所以只有自׃头写起了?br>        首先是fibonacci的递归写法Q不是很标准Q但是很亲切Q:<br> <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> fib(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> value)<br>{<br>    </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">value)<br>        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>    </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br>        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">value)<br>            </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br>        </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br>        {<br>            </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> fib(value</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">fib(value</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">);<br>        }<br>}</span></div>         接下来要把这个算法{换ؓ使用栈的写法?br>        首先q行一下分析。递归是逆向求结果的Q对于不能求出结果的函数Q先运行场景压栈,然后递归调用自己Q如果仍然不能出l果Q就再将q行场景压栈Q一直到函数可以q回l果为止。此时依ơ将q行场景ҎQ完成运行场景,取得q回|再弹?.....印象中的递归调用q程是如此。如果我们要自己写递归求fibonacci数列Q就要自己手动用E序来模拟这个过E。我首先准备一个栈来存攄果序列。在q个l果序列里面Q保证第一个结果和W二个结果L可以直接求得的数倹{因为只需要n-1和n-2便能求出fib(n)Q所以我们在法中要把多余的n-3弹出Q这h内的元素个数在每一ơ调用的q程中逐渐减少Q一直到里面只剩下一个元素,在这个时候,刚才弹出的两个元素之和就是我们要求的fibonacci(n)?br>        下面是算法:<br> <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> fibByStack(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> value)<br>{<br>    </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> currentValue;<br>    currentValue</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">value;<br>    </span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(currentValue</span><span style="COLOR: #000000">>=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br>    {<br>        fibStack.push(currentValue);<br>        currentValue</span><span style="COLOR: #000000">--</span><span style="COLOR: #000000">;<br>    }<br>    fibStack.pop();<br>    fibStack.pop();<br>    //1?是n=1和n=0时的|Z压入的是“l果”Q我头两个元素弹出再压入这两个?br>    fibStack.push(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br>    fibStack.push(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br>    </span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">)<br>    {<br>        </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> topValue1,topValue2<br>        topValue1</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">fibStack.top();<br>        fibStack.pop();<br>        topValue2</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">fibStack.top();        <br>        fibStack.pop();<br>        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">fibStack.size())<br>            </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> topValue1</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">topValue2;<br>        fibStack.pop();        <br>        fibStack.push(topValue1</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">topValue2);<br>        fibStack.push(topValue2);<br>    }<br>}</span></div> <img src ="http://m.shnenglu.com/qzb2006e/aggbug/26499.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/qzb2006e/" target="_blank">littlegai</a> 2007-06-17 17:19 <a href="http://m.shnenglu.com/qzb2006e/archive/2007/06/17/26499.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The C++ Standard Library : A Tutoral and Reference MW记?cd转换(1)http://m.shnenglu.com/qzb2006e/archive/2007/06/17/26347.htmllittlegailittlegaiSun, 17 Jun 2007 06:56:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2007/06/17/26347.htmlhttp://m.shnenglu.com/qzb2006e/comments/26347.htmlhttp://m.shnenglu.com/qzb2006e/archive/2007/06/17/26347.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/26347.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/26347.html书上的例子中的类名叫做Stack,q样L觉有些误?因ؓ栈这个概念已l在我们的脑中先入Z?Ҏ形成思维定式.那么我写一个和其他M概念都无关的例子:
class MyClass
{    
    
private:
    
int _number;
    
public:
    MyClass(
int number)
    {
        _number
=number;
    }
};
上面的类很普?没什么特别的.我们可以q样创徏q个cȝ对象:
int main()
{
    MyClass instance
=5;
}
q就比较有意思了,c++q能q样?我以前的没有见q?那么explicit关键字的作用是不让你这样写,如果你这样写?~译器就会给你一个错误提C?现在攚w一下MyClass
class MyClass
{    
    
private:
    
int _number;
    
public:
    
explicit MyClass(int number)
    {
        _number
=number;
    }
};
main函数不变的情况下,~译器会q样提示?
Explicit.cpp: In function ‘int main()’:
Explicit.cpp:14: 错误Q?conversion from ‘int’ to non-scalar type ‘MyClass’ requested
q样,只能这样写?
MyClass instance(5);
好了,下面开始阅ȝ型{换的部分.
1 static_cast
q个操作W的执行q程可以被认为是:它创Z一个新的对?然后用要转换的值去初始化这个新对象.q个转换只有当一个类型{换被声明q才能执?
首先是一个简单的例子:
//一个简单的cd转换
   int valueToBeConverted=int();
   
using namespace std;
   cout
<<static_cast<float>(valueToBeConverted)<<"\n";
很像其他语言中的昑ּcd转换.那么对于我自qcd何进行{换呢?可以看一下下面的q个例子:
#include <iostream>

class MyClass2
{
   
public:
    
int IntMember1;
   MyClass2()
   {
      IntMember1
=1;
   }
};
class MyClass1
{
   
public:
   
int IntMember1;
   
virtual void  f()
   {
       std::cout
<<IntMember1<<"\n";
   }
   
explicit MyClass1(MyClass2 instance)
   {
       IntMember1
=instance.IntMember1;
   }
};
int main()
{
   MyClass2 mc2Instance;
   MyClass1 mc1Instance
=static_cast<MyClass1>(mc2Instance);
   mc1Instance.f();
}
注意看上面的_体字explicit.如果没有explict对于构造函数的修饰,那么万全可以单爽快的q么?
MyClass1 mc1Instance=mc2Instance;
换句话说,如果你想让别人写代码的时候不兛_cd,舒舒服服的写Z认ؓ不安全的代码,那么你就Lexplicit,如果你想让别人在写代码的时?让那些不安全的类型{换变得更?昄"一?那么你就按上面这样写.然后让编译器狠狠的给他们一个警?
2 dynamic_cast
This operator enables you to downcast a polymorphic type to its real static type. This is
the only cast that is checked at runtime. Thus, you could also use it to check the type of a
polymorphic value.

q个q算W能够让你把一个多态的cd转换成它的真实的静态类?q是唯一的在q行时进行检验的转换Ҏ.所以你同样需要在转换之前验多态值的cd.
首先dynamic_cast只能够用于指针或者引?否则~译器会告诉你类DL错误:
 无法?‘scInstance’ 从类?‘SubClass’ 动态{换到cd ‘class BaseClass’ (target is not pointer or reference)
q里使用书中的例?
 
class Car;         // 臛_拥有一个抽象函数的抽象c?/span>
   class Cabriolet : public Car {
       
   };
   
class Limousine : public Car {
       
   };
   
void f(Car* cp)
   {
       Cabriolet
* p = dynamic_cast<Cabriolet*>(cp);
       
if (p == NULL) {
           
//pqCabriolletcd
           
       }
   }

In this example, f() contains a special behavior for objects that have the real static type
Cabriolet. When the argument is a reference and the type conversion fails,
dynamic_cast throws a bad_cast exception (bad_cast is described on page 26).
Note that from a design point of view, it it always better to avoid such type-dependent
statements when you program with polymorphic types.
当参数是一个引用ƈ且类型{换失败的时?dynamic_cast会抛Z个bad_cast异常.值得注意的是,从设计的角度来说,通常在进行多态类型的E序~写?应该避免q样的类型依?
3 const_cast
This operator adds or removes the constness of a type. In addition, you can remove a
volatile qualification. Any other change of the type is not allowed.
q个操作W添加或除去一个类型的帔R?Ҏ?.另外,你可以除M个变量变化的能力.M对于q个cd变量的变化都不被允?
让常量可修改的例?
class MyClass
{
    
public:
        
int MemberValue;
        
void showValue()
        {
            cout
<<"My Value is"<<MemberValue<<"\n";
        }
        MyClass()
        {
            MemberValue
=1;
        }    
};
int main()
{
    
const MyClass myValue;
    MyClass 
*ptr=const_cast<MyClass*>(&myValue);
    ptr
->MemberValue=100;
    ptr
->showValue();
}
上面的例子只是将一个const变得可以修改?但是注意C中的q样一?
In addition, you can remove a
volatile qualification. Any other change of the type is not allowed.
gq可以将一个可变量转换为非可变?q里没有查到相关资料,也许书的后面会有相应解释,所以这里先放一?
4 reinterpret_cast
q个比较有趣,支持不兼容类型之间的转换.以下是例?
#include <iostream>
using namespace std;
class ClassA
{
    
public:
    
int Value1;
    
int Value2;
    
int Value3;
    
void showValue()
    {
        cout
<<Value1<<","<<Value2<<","<<Value3<<"\n";
    }
};
class ClassB
{
    
public:
    
int Value1;
    
int Value2;
    
int Value3;
    ClassB()
    {
        Value1
=1;
        Value2
=2;
        Value3
=3;
    }
};
int main()
{
    ClassB 
*b=new ClassB();
    ClassA 
*a=reinterpret_cast<ClassA*>(b);
    a
->showValue();
}
同样,q种转换对于非基本类型来?仍然只能支持指针和引?
q些q算W的优点是他们明确了类型{换的意图,q且能够让编译器获取更多的信息来了解q些cd转换的原?然后当这些{换操作越q他们的职能的时?~译器会报告错误.
另外需要注意的?q些cd转换都只能接受一个参?看下面的例子:
    static_cast<Fraction>(15,100)                   
上面不会产生你想要的l果.q里的逗号q不是用来连接两个参数的,而是作ؓ逗号q算W出?q里15会被舍弃,而采?00作ؓ参数构造Fraction.
所以还是需要采用下面的Ҏ才合?
    Fraction(15,100)                             







littlegai 2007-06-17 14:56 发表评论
]]>
重构--改善既有代码的设计读书笔?W一?1)http://m.shnenglu.com/qzb2006e/archive/2007/06/15/26400.htmllittlegailittlegaiFri, 15 Jun 2007 14:53:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2007/06/15/26400.htmlhttp://m.shnenglu.com/qzb2006e/comments/26400.htmlhttp://m.shnenglu.com/qzb2006e/archive/2007/06/15/26400.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/26400.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/26400.html        先看看书中有关重构的定义Q?br>        重构的定义:?span style="BACKGROUND-COLOR: yellow">不改?/span>代码外在行ؓ的前提下Q对代码做出修改Q以改进E序?span style="BACKGROUND-COLOR: yellow">内部l构。本质上_重构是在代码写好之后改q它的设计?br>        q个定义说得很清楚了Q基本上不需要进行Q何的说明。我们只要将它当作原则去늅好了?br>        然后书中讲了Q?br>        快速而随?quick and dirty)的设计一个简单的E序q没有错?br>        于是我就有这L问题了:
        什么规模的E序才值得重构Q?br>        然后书中l了我这样一个回{:
        如果你发现自己需要ؓE序d一个特性,而代码结构?span style="BACKGROUND-COLOR: yellow">无法很方?/span>的那么做Q那先重构那个E序QҎ的d比较Ҏq行Q然后添加特性?br>        重构之前要做q样一些准备:
        重构的第一?-Z码徏立测试环境?br>重构之前Q首先检查自己是否有一套可靠的试机制。这些测试必L自我查能力?br>        下面是一些摘录:
        首先在代码中扑և函数内的局部变量和参数。Q何不会修改的变量都可以被当成参数传入新的函数Q至于会被修改的变量需要格外小心。如果只有一个变量会被修改,可以把它当作q回倹{?br>在找Z个函数的逻辑泥潭q将之提l到另外一个函C的时候,要格外注意返回倹{如果你l常犯这L错误Q那么一定确保在修改前后函数的调用结果相一致?
        代码应该表现自己的目的,q一炚w帔R要?span style="BACKGROUND-COLOR: yellow">阅读代码的时候,我经常进行重?/span>。这P随着对程序的理解逐渐加深Q我也就不断地把q些理解嵌入代码中,q么一来才不会遗忘我曾l理解的东西?br>        几个重构的方法(下面的伪码是我自己写的)Q?br>        1、Extract Method Q提取方法)
        2、appending assignment ,operator+=Q?附添赋值动作)
        q两U重构方法结合的形式为:
        重构前:
        A=0;
        A++;
        if(expression)
          A++;
        重构后:
         A=0;
         A+=function1();
         TypeOfA function1()
         {
             if(expression)
               return 2;
             else
               return 1;
          }
         3、Replace Temp with QueryQ字面上用查询取代时变量)
         利用所谓的query method来取代时变量。由于class内的M函数都可以取用(调用Q所谓query methods,所以它能够促进比较q净的设计,而非冗长复杂的函数?br>          Replace Temp with Query的伪码例子:
          A=0;
          while(expression)
          {
             A++;
           }
          return "The Result is "+A;
          上面A是一个时变?所以可以用一个querymethod来取代:
           TypeA function1()
          {
             A=0;
             while(expression)
             {
                A++;
              }
             return A;
           }
q样ȝ序可以这样写:
           return "The Result is "+function1();
l箋摘抄Q?br>重构可能会存在另外一个问题,是性能。原本代码只执行一ơ@环,在重构以后可能要执行三次。如果@环中的语句耗时很多Q就可能大大降低E序的性能。单单ؓ了这个原因,许多E序员就不愿q行q个重构动作。但是请注意q里只是“可能”。除非进行评,否则无法定循环的执行时_也无法知道这个@环是否经怋用以至于影响pȝ的整体性能。重构时E序人员不必担心q些Q优化时才去担心它们Q但那时候你已经处于一个比较有利的位置Q有更多选择可以q行有效优化?br>使用Form Template MethodQ字面上建立模板ҎQ可以进一步减重复代码。这会在书后面的章节讲到?

littlegai 2007-06-15 22:53 发表评论
]]>
The C++ Standard Library : A Tutoral and Reference MW记之命名空?/title><link>http://m.shnenglu.com/qzb2006e/archive/2007/06/14/26279.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Thu, 14 Jun 2007 14:06:00 GMT</pubDate><guid>http://m.shnenglu.com/qzb2006e/archive/2007/06/14/26279.html</guid><wfw:comment>http://m.shnenglu.com/qzb2006e/comments/26279.html</wfw:comment><comments>http://m.shnenglu.com/qzb2006e/archive/2007/06/14/26279.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/qzb2006e/comments/commentRss/26279.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/qzb2006e/services/trackbacks/26279.html</trackback:ping><description><![CDATA[在这一部分之前,书中介绍了基本类型的昑ּ初始化以及简单的异常处理.<br>基本cd的显式初始化是比较简单的.是说你在定义一个整型变量的时?有两U不同的情况:<br>int i1;         // undefined value<br>int i2 = int(); // initialized with zero<br><br> 如果按照前一U?会作"值未定义;如果按照后一U?则自动被初始化ؓ0.q样也就保了你的类在初始化的时候有一个确定的初始?<br>至于异常的处理等问题,书中会在后面有比较详l的描述.q里可以看到比较有意思的一?是指定函数抛出的异常类?q于Java很像:<br>void f() throw(bad_alloc); <br>下面转入正题:命名I间.<br>有了命名I间,它将会取代函数和cM用于全局,q作为它所l领的那些类和函数的唯一标识存在.q样可以避免命名冲突情况的出?正如书中所?<br>Unlike classes, namespaces are open for definitions and extensions in different modules. Thus<br>you can use namespaces to define modules, libraries, or components even by using multiple<br>files. A namespace defines logical modules instead of physical modules (in UML and other<br>modeling notations, a module is also called a package).<br><br> 可以像这样定义一个命名空? <br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">namespace</span><span style="color: #000000;"> MyNameSpace<br>{<br>    </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> MyClass<br>    {<br>        </span><span style="color: #0000ff;">private</span><span style="color: #000000;">:<br>        </span><span style="color: #0000ff;">char</span><span style="color: #000000;"> </span><span style="color: #000000;">*</span><span style="color: #000000;"> _classInfo;<br>        </span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br>        </span><span style="color: #0000ff;">char</span><span style="color: #000000;">*</span><span style="color: #000000;"> getClassInfo()<br>        {<br>            </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> _classInfo;<br>        }<br>        MyClass(</span><span style="color: #0000ff;">const</span><span style="color: #000000;"> </span><span style="color: #0000ff;">char</span><span style="color: #000000;">*</span><span style="color: #000000;"> info)<br>        {<br>            _classInfo</span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> </span><span style="color: #0000ff;">char</span><span style="color: #000000;">[strlen(info)];<br>            strcpy(_classInfo,info);<br>        }<br>        </span><span style="color: #000000;">~</span><span style="color: #000000;">MyClass()<br>        {<br>            </span><span style="color: #0000ff;">if</span><span style="color: #000000;">(_classInfo)<br>            {<br>                std::cout</span><span style="color: #000000;"><<</span><span style="color: #000000;">"</span><span style="color: #000000;">free classinfo</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br>                delete[] _classInfo;<br>            }<br>        }<br>    };<br>    </span><span style="color: #0000ff;">void</span><span style="color: #000000;"> printMyClassInfo(MyClass </span><span style="color: #000000;">&</span><span style="color: #000000;">instance)<br>    {<br>        std::cout</span><span style="color: #000000;"><<</span><span style="color: #000000;">instance.getClassInfo();<br>    }<br>}</span></div> 从上面可以看?q个命名I间里面包括了一个类和一个函?cM包含了char*cd的成员变?函数printMyClassInfo 以一个MyClasscd的引用作为参?Z么要用引用呢?熟悉c++的h应当很清?我是通过实验才刚刚知道原?q个原因我将会在后面说明.<br>好现在来看一下调用过E?通常的调用过E是q样?<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<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;"> main()<br>{<br>    MyNameSpace::MyClass instance(</span><span style="color: #000000;">"</span><span style="color: #000000;">MyClass!\n</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>    MyNameSpace::printMyClassInfo(instance);<br>}</span></div> q没有Q何问?但有意思的?q可以这栯?<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<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;"> main()<br>{<br>    MyNameSpace::MyClass instance(</span><span style="color: #000000;">"</span><span style="color: #000000;">MyClass!\n</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>    printMyClassInfo(instance);<br>}</span></div> 看来c++中在使用一个命名空间的cL者函数的时?q个命名I间p"自动"引入?当寻扑և数printMyClassInfo的时候会在当前的上下文中q行L的同?q会C前用到过的命名空间中d?<br>当然,通常情况下我们喜Ƣ这样做:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">using</span><span style="color: #000000;"> </span><span style="color: #0000ff;">namespace</span><span style="color: #000000;"> MyNameSpace; <br></span><span style="color: #0000ff;">int</span><span style="color: #000000;"> main()<br>{<br>    MyClass instance(</span><span style="color: #000000;">"</span><span style="color: #000000;">MyClass!\n</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>    printMyClassInfo(instance);<br><br>}</span></div> 但是q不是在M情况下都鼓励using namespaceq种做法?在书中将得比较清?<br>Note that you should never use a using directive when the context is not clear (such as in header<br>files, modules, or libraries). The directive might change the scope of identifiers of a namespace,<br>so you might get different behavior than the one expected because you included or used your<br>code in another module. In fact, using directives in header files is really bad design.<br><br> 上面q段话强调了当上下文q不明确的情况下(比如在一个头文g,lg或者库里面),不要使用usingq种写法,q个指o会改变命名空间标识符的作用域,q样你就有可能引发和你预期不相同的行?因ؓ你会在另外一个组件中引用你的代码或用它.事实?using标识W写在头文g里面是一U相当不好的设计.<br>在这?我看了一下c++E序设计语言q本?发现命名I间除了像上面这样声明以?q可以像cM栯h?<br>在命名空间中q样定义<br>void printMyClassInfo(MyClass &); <br>然后在外面写函数的主?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">void</span><span style="color: #000000;"> MyNameSpace::printMyClassInfo(MyClass </span><span style="color: #000000;">&</span><span style="color: #000000;">instance)<br>{<br>    std::cout</span><span style="color: #000000;"><<</span><span style="color: #000000;">instance.getClassInfo();<br>}</span></div> 好了,写了q么?再来看看刚才留下来的那个问题.<br>其实很简?一个函数如果传递的是?那么׃在内存中产生一个一模一L"复本",而那个字W指针也会被复制一?当传送的Dq它的作用域的时?,׃被释放掉,而被复制?本体"在程序运行结束之?又会?释放一?.q样在运行的时?它会提示你这L错误: <br>*** glibc detected *** double free or corruption (fasttop): 0x0804a008 ***<br><br> 在我们的MyClasslcȝ析构?我们有一个输?所以这里就输出了两?<br>free classinfofree classinfo<br><br> <br><br><br> <img src ="http://m.shnenglu.com/qzb2006e/aggbug/26279.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/qzb2006e/" target="_blank">littlegai</a> 2007-06-14 22:06 <a href="http://m.shnenglu.com/qzb2006e/archive/2007/06/14/26279.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>富爸爸投资指南读书笔?/title><link>http://m.shnenglu.com/qzb2006e/archive/2007/06/13/26267.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Wed, 13 Jun 2007 11:42:00 GMT</pubDate><guid>http://m.shnenglu.com/qzb2006e/archive/2007/06/13/26267.html</guid><wfw:comment>http://m.shnenglu.com/qzb2006e/comments/26267.html</wfw:comment><comments>http://m.shnenglu.com/qzb2006e/archive/2007/06/13/26267.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/qzb2006e/comments/commentRss/26267.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/qzb2006e/services/trackbacks/26267.html</trackback:ping><description><![CDATA[<p>富爸爸研I过公司法和E法Qƈ扑ֈ了利用法律ؓ他赚很多qҎ?br>mortgage<br>KK: []<br>DJ: []<br>抉|hQ源于法语mortirQ法语意思是MQ因而抵DƑְ是直到死的一U契U?br>real estate<br>KK: []<br>DJ: []<br>不动产,q不?#8220;真正”的胦产,来自于西班牙语,意思是贉|的胦产?br>我们仅仅是在技术上控制了不动Q却q不能占有它Q政府占有这些胦产,向我们征收不动E?br>奥肖内西 华尔街股市投资经?br>What Works On Wall Street:A Guide to the Best Performing In-vestment Strategies of All Time<br>提出两种不同的决{方法:<br>l验型的分析Ҏ或称直觉式分析方法。该Ҏ以知识,l验和常识ؓ基础?br>定量分析法或U精统计法。这U方法以大量数据为基Q推论出各种关系?br>在多数情况下Q直觉分析法的投资者常常做出错误的军_Q或败给几乎U机械的Ҏ。即Qhcȝ推断力远于我们所惌的?/p> <p>企业取得?不动产组?购买抉|?贴现合同 投资研讨?|宾逊准?br>有些东西你的眼睛是看不到的,不动产就是不动Q股就是公司股,q些东西你能看到Q但是你看不Z么事重要的。决定某U东西是不是一好的投资的q有Q交易、胦务协议、市场、管理、风险因素、现金流、企业结构、税法和很多其他的事情?br>你ؓ什么要付这么高的利率?你认Z的投资回报是多少Q这Ҏ资于你的长期财务战略d吗?你打用多大比例计算修理费用Q你知道q个城市刚刚宣布要在那个地区修\以改善交通状况吗Q一条大道就要从你的房前I过Q你知道q些吗?我知道现在市场看好,但是你知道是什么在驱动市场Q商业经还是贪婪?你认U趋势会l持多久Q如果你的房子租不出去,你将怎么办?</p> <p>q不是现?<br>成ؓ-->?->拥有<br>大多Chq求做而不是追?#8220;成ؓ”<br>一个拥有失败者心态的人将一直失?br>不要在对方n上下功夫Q而要在你对对方的看法上下功夫<br>丹尼?格鲁?《情商?br>父母会说很多?#8220;应该”Q小孩说很多?#8220;感觉”<br>父母q不一定就是成qh<br>作ؓ一个成qh应当意识C必须d什么ƈ且去做,即你可能感觉上q不喜欢做这件事<br>我的富爸怸许我_<br>“我付不v?#8221;<br>“我做不到”<br>“做事要稳?#8221;<br>“别赔?#8221;<br>“如果你失败了q且再也M了nQ该怎么办? ”<br>他不许我说这些是因ؓ他坚信语a是hcL有媄响力的工P一个h所说的和所想的l将变ؓ现实?br>用圣l里面的话即使:<br>语言变肉,留在我们体内?/p> <img src ="http://m.shnenglu.com/qzb2006e/aggbug/26267.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/qzb2006e/" target="_blank">littlegai</a> 2007-06-13 19:42 <a href="http://m.shnenglu.com/qzb2006e/archive/2007/06/13/26267.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据l构MW记Q栈Q不只是C++的东西)http://m.shnenglu.com/qzb2006e/archive/2007/06/11/26104.htmllittlegailittlegaiMon, 11 Jun 2007 14:11:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2007/06/11/26104.htmlhttp://m.shnenglu.com/qzb2006e/comments/26104.htmlhttp://m.shnenglu.com/qzb2006e/archive/2007/06/11/26104.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/26104.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/26104.html
 1 #include <stack>
 2 #include <iostream>
 3 using namespace std;
 4 int _tmain(int argc, _TCHAR* argv[])
 5 {
 6     stack<int> binaryStack;
 7     int decimalValue;
 8     cout<<"please input decimal value:";
 9     cin>>decimalValue;
10     while(decimalValue)
11     {
12         binaryStack.push(decimalValue%2);
13         decimalValue=decimalValue/2;
14         
15     }
16     cout<<"\n"<<"the binary result is:";
17     while(!binaryStack.empty())
18     {
19         int result=(int)binaryStack.top();
20         binaryStack.pop();
21         cout<<result;
22     }
23     cout<<"\n";
24     return 0;
25 }
另外Z看了一下C#和JAVAQ当然也支持栈。但是这些东西在我^时用的时候却很少用到Q或者在用到的时候去“重复发明轮子?#8221;。作Z个经典的数据cdQ栈理应是被l大多数语言支持的(不知道PB怎样Q。所以在q里要树立一?#8220;重用轮子”的意识:
C#的十q制转二q制实现Q?br>
 1 class Class1
 2     {
 3         /// <summary>
 4         /// 应用E序的主入口炏V?br> 5         /// </summary>
 6         [STAThread]
 7         static void Main(string[] args)
 8         {
 9             //
10             // TODO: 在此处添加代码以启动应用E序
11             //
12             Stack binaryStack=new Stack();
13             Console.WriteLine("Please input decimal value:");
14             String sDecimal=Console.ReadLine();
15             int decimalValue=Int32.Parse(sDecimal);
16             while(decimalValue!=0)
17             {
18                 binaryStack.Push(decimalValue%2);
19                 decimalValue=decimalValue/2;
20             }
21             Console.WriteLine("The binary result is:");
22             while(binaryStack.Count!=0)
23             {
24                 Console.Write(binaryStack.Pop());
25             }
26             Console.WriteLine();
27         }
28     }

JAVA的十q制转二q制实现Q?br>
 1 import java.io.BufferedReader;
 2 import java.io.InputStreamReader;
 3 import java.util.Stack;
 4 public class hello1 {
 5     public static void main(String args[])
 6     {
 7         try {
 8             Stack<Integer> binaryStack=new Stack<Integer>();
 9             int decimalValue;
10             System.out.println("please input decimal value:");
11             BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(System.in));
12             decimalValue=Integer.parseInt(bufferedReader.readLine());
13             while(decimalValue!=0)
14             {
15                 binaryStack.push(decimalValue%2);
16                 decimalValue=decimalValue/2;
17             }
18             System.out.println("the binary result is:");
19             while(!binaryStack.empty())
20             {
21                 System.out.print(binaryStack.pop());
22             
23             }
24         } catch (Exception e) {
25             // TODO Auto-generated catch block
26             e.printStackTrace();
27         }
28         
29         
30     }
31     }
通过比较Q会发现C#不大?#8220;?#8221;的感觉,JAVA和C++更脓q于《数据结构》中对于数据cd“?#8221;的操作的定义。另外支持模板或者范型的特点让h用v来M感觉十分舒服。在q里提醒自己Q以后这三种语言?#8220;?#8221;可用了!

littlegai 2007-06-11 22:11 发表评论
]]>
数据l构MW记Q冒泡排?不要只注意最坏的情况Q?http://m.shnenglu.com/qzb2006e/archive/2007/06/10/26004.htmllittlegailittlegaiSun, 10 Jun 2007 14:34:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2007/06/10/26004.htmlhttp://m.shnenglu.com/qzb2006e/comments/26004.htmlhttp://m.shnenglu.com/qzb2006e/archive/2007/06/10/26004.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/26004.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/26004.html数据l构W一章讨Z一些有关算法的问题.在这一部分再次引入了那个经典的法--冒排序法?br>如果让我来描qC下这个算法的q程的话Q我会这hqͼ
从第一个元素开始和依次q行比较Q大的那个放在后面,一直到最后一个元素。这h后一个元素就会成为最大的那个Q除刚才产生的最大的那个元素外,再次从头开始比较,一直到W一个元素没得可比ؓ止?br>q是我的理解。进而通过q个理解Q我可以写出q个法来。这没有问题。但是当我看到原版的法的时候,我立卛_感觉出差别来了:

1 void bubble_sort(int a[],int n)
2 {
3      for(i=n-1,change=TRUE;i>1&&change;--i)
4      {
5          change=FALSE;
6          for(j=0;j<i;++j)
7              if(a[j]>a[j+1]{a[j]<-->a[j+1];change=TRUE;}
8      }
9 }
注意变量change。这里体现的思\是:如果在某一ơ比较过E中没有UdM元素Q那么就没有必要再从头比较一ơ了。因为实际上已经得到了一个排好序的数l?br>q样对于相当多的情况来讲Q减了很多的不必要操作Q自然^均时间复杂程度就降低了?br>因ؓ我往往只考虑到比较坏甚至极端的情况(比如完全逆序Q,所以自然就会忽略这些看上去不太坏,甚至是非常好的情况,q样一个直接的l果是让那些好的情况下的操作也变得J琐异常Q而仅仅是Z照顾那些比较难于出现的个别异常情况,现在xQ这样做不可取。日后应当注意?

littlegai 2007-06-10 22:34 发表评论
]]>
The C++ Standard Library : A Tutoral and Reference MW记?模板(1)http://m.shnenglu.com/qzb2006e/archive/2007/06/09/25936.htmllittlegailittlegaiSat, 09 Jun 2007 15:53:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2007/06/09/25936.htmlhttp://m.shnenglu.com/qzb2006e/comments/25936.htmlhttp://m.shnenglu.com/qzb2006e/archive/2007/06/09/25936.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/25936.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/25936.html与此相关的阅d实验q程都是在linux下进行的,所以这些读书笔C会在linux下完?q里不由得感叹一?-博客园的博客pȝ的通用性确实做得非常好,臛_我在fire fox下面下用没有感觉到M的差?
首先是模板Template.
template<class T> 
class MyClass
{
private:
T value;
public:
const T getValue()
{
return value;
}
void assign(const MyClass<T> &m)
{
value
=m.value;
}

MyClass(T theValue)
{
value
=theValue;
}

};

上面的MyClass是我的模板c?然后我按照如下的方式q行调用,是没有问题的:
MyClass<int> i1(1);
MyClass
<int> i2(2);
cout
<<"\n";
cout
<<i1.getValue()<<"\n";
cout
<<i2.getValue()<<"\n";
i1.assign(i2);
cout
<<i1.getValue()<<"\n";
exit(
0);
但是如果q样,׃出现问题.
MyClass<int> i1(1);
MyClass
<float> f3(3.9);
f3.assign(i1);
~译器会告诉?
TemplateExp.cpp: In function ‘int main()’:
TemplateExp.cpp:36: 错误Q??‘MyClass<float>::assign(MyClass<int>&)’ 的调用没有匹配的函数
TemplateExp.cpp:13: 附注Q?备选ؓQ?void MyClass<T>::assign(const MyClass<T>&) [with T = float]
因ؓ在编译器看来
void assign(const MyClass<int> &m)?br>void assign(const MyClass<float> &m)是不同的.
q样必assignq行修改.我在q里建立了一个新的函数assignX,如下:
template <class X>
void assignX(MyClass<X> &m)
{
value
=m.getValue();
}
在调用的时?q样写就没有问题?
MyClass<int> i1(1);
MyClass
<float> f3(3.9);
f3.assignX(i1);
cout
<<f3.getValue()<<"\n";
exit(
0);
有一炚w要注?在assignX?不能够只接用m.value而要使用m.getValue().正如书中所?
Note that the argument x of assign() now differs from the type of *this. Thus, you can't
access private and protected members of MyClass<> directly. Instead, you have to use
something like getValue() in this example.
׃cd不同?即MyClass<float>不同于MyClass<int>)所以就不能使用this.因而要另外建立一个获取值的函数.
实际上上面写的代码和书中q是有所不同?比较重要的区别是函数assign.
书中的参Cؓ:
template<class X>
assign(const MyClass<X>& x)
q样实际上是不能得到x.getValue()?~译器会l出q样的提C?
TemplateExp.cpp:36:   instantiated from here
TemplateExp.cpp:20: 错误Q?passing ‘const MyClass<int>’ as ‘this’ argument of ‘const T MyClass<T>::getValue() [with T = int]’ discards qualifiers
但是修改?br>
template<class X>
assign(MyClass<X>& x)
׃会有问题?br>


littlegai 2007-06-09 23:53 发表评论
]]>
Domain-Driven Design: Tackling Complexity in the Heart of Software 语句_摘.3. http://m.shnenglu.com/qzb2006e/archive/2006/08/31/11903.htmllittlegailittlegaiThu, 31 Aug 2006 15:22:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2006/08/31/11903.htmlhttp://m.shnenglu.com/qzb2006e/comments/11903.htmlhttp://m.shnenglu.com/qzb2006e/archive/2006/08/31/11903.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/11903.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/11903.html Chapter Three. Binding Model and Implementation
If the design, or some central part of it, does not map to the domain model, that model is of little value, and the correctness of the software is suspect. At the same time, complex mappings between models and design functions are difficult to understand and, in practice, impossible to maintain as the design changes. A deadly divide opens between analysis and design so that insight gained in each of those activities does not feed into the other.
        如果一U设?或者它的一些核心ƈ没有与域模型相关联,那么q个模型没有h|q且以此而开发出来的软g的正性也值得怀疑。同Ӟ模型与功能设计之间复杂的对应关系会变得难于理解,q且当设计变化的时候,它们很隄护。一U致命的分歧此在分析与设计之间出现Q以至于那些分析设计zd中所获得的见解不能彼此满?/span>

Design a portion of the software system to reflect the domain model in a very literal way, so that mapping is obvious. Revisit the model and modify it to be implemented more naturally in software, even as you seek to make it reflect deeper insight into the domain. Demand a single model that serves both purposes well, in addition to supporting a robust UBIQUITOUS LANGUAGE.

Draw from the model the terminology used in the design and the basic assignment of responsibilities. The code becomes an expression of the model, so a change to the code may be a change to the model. Its effect must ripple through the rest of the project's activities accordingly.

To tie the implementation slavishly to a model usually requires software development tools and languages that support a modeling paradigm, such as object-oriented programming.

        以书面的形式设计软gpȝ的一部分Q进而与域模型相映射Q这样双方的对应关系会变得明显。重新考虑q些模型q且通过修改让他们在软g当中昑־更加自然Q甚x当你在寻求一U方法,来让模型更加深刻的反映问题域的时候也要如此。追求尽可能单的模型Q让它能够满_斚w目的QY件方面和设计斚wQ)Q又能够支持_健全的通用语言?/span>

        从模型中提取那些在存在于设计中,以及存在于(域专家的?Q职责所包含的基本工作中的那些术语。代码会因此成ؓ对于模型的一U描qͼ所以对于代码的更改或许是源自于对于模型的更改。从而,它们的媄响将会L及到目其他部分的行为?br />        要牢固的把实现和模型l定在一P通常需要一些Y件设计工具以及支持模型范例的语言Q例如面向对象程序设计?br />       

If the people who write the code do not feel responsible for the model, or don't understand how to make the model work for an application, then the model has nothing to do with the software. If developers don't realize that changing code changes the model, then their refactoring will weaken the model rather than strengthen it. Meanwhile, when a modeler is separated from the implementation process, he or she never acquires, or quickly loses, a feel for the constraints of implementation. The basic constraint of MODEL-DRIVEN DESIGN—that the model supports an effective implementation and abstracts key domain knowledge—is half-gone, and the resulting models will be impractical. Finally, the knowledge and skills of experienced designers won't be transferred to other developers if the division of labor prevents the kind of collaboration that conveys the subtleties of coding a MODEL-DRIVEN DESIGN.
        如果写代码的那些人对于模型没有责L的话Q或者他们ƈ不能懂得如何让模型作用于应用Q那么模型对于Y件来讲毫无用处。如果开发h员不能够认识到对于代码的修改是对于模型的修改的话,它们的重构将会模型变得更糟Q而不是让它们更加健壮。同Ӟ当一个从事徏模的Z实现q程盔Rȝ时候,他(她)永远也不会获得,或者说会很快失d于实现的U束感。模型驱动设计的基本U束x--模型需要对那些有效的(E序Q实现提供支持,q且能够抽象关键的域知识--ȝ其一Q模型都会变得不切实际。最后,如果目中的分工L了能够微妙的改善模型驱动设计代码~写的那些协作,那么团队中经验丰富的设计人员的知识和技术将不能l的其他设计人员带来提高?br />

Any technical person contributing to the model must spend some time touching the code, whatever primary role he or she plays on the project. Anyone responsible for changing code must learn to express a model through the code. Every developer must be involved in some level of discussion about the model and have contact with domain experts. Those who contribute in different ways must consciously engage those who touch the code in a dynamic exchange of model ideas through the UBIQUITOUS LANGUAGE.
        M专注于模型的技术h员必花旉接触代码Q而不ZQ她Q在目中的首要角色是什么。Q何负责修改代码的人必d会通过代码来描q模型。每一个开发h员必M同程度的被纳入到Ҏ型的讨论以及和域专家的交中。那些上q工作之外所涉及的项目h员必自觉地让那些接触代码的人通过通用语言动态的交换对于模型的意见?/p>

littlegai 2006-08-31 23:22 发表评论
]]>
Domain-Driven Design: Tackling Complexity in the Heart of Software 语句_摘.2.http://m.shnenglu.com/qzb2006e/archive/2006/08/29/11834.htmllittlegailittlegaiTue, 29 Aug 2006 13:25:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2006/08/29/11834.htmlhttp://m.shnenglu.com/qzb2006e/comments/11834.htmlhttp://m.shnenglu.com/qzb2006e/archive/2006/08/29/11834.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/11834.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/11834.htmlChapter Two. Communication and the Use of Language

A project faces serious problems when its language is fractured. Domain experts use their

jargon while technical team members have their own language tuned for discussing the domain

in terms of design.

The terminology of day-to-day discussions is disconnected from the terminology embedded in

the code (ultimately the most important product of a software project). And even the same

person uses different language in speech and in writing, so that the most incisive

expressions of the domain often emerge in a transient form that is never captured in the

code or even in writing.

Translation blunts communication and makes knowledge crunching anemic.

Yet none of these dialects can be a common language because none serves all needs.

         当用于交的语言出现断层的时候,目会面一pd严重的问题。域专家们与技术团队自

说自话?br />        日常讨论所用的术语不再与代码(它们会成Y仉目的重要部分Q中的术语相联系。甚臛_

一个h会在交流中和在记录中所用的术语不相一_以至于问题域中那些重要的表达方式出现得如此短

暂进而它们无法被捕获到代码中去甚至无法被记录下来?/p>

Use the model as the backbone of a language. Commit the team to exercising that language

relentlessly in all communication within the team and in the code. Use the same language in

diagrams, writing, and especially speech.

Iron out difficulties by experimenting with alternative expressions, which reflect

alternative models. Then refactor the code, renaming classes, methods, and modules to

conform to the new model. Resolve confusion over terms in conversation, in just the way we

come to agree on the meaning of ordinary words.

Recognize that a change in the UBIQUITOUS LANGUAGE is a change to the model.

Domain experts should object to terms or structures that are awkward or inadequate to

convey domain understanding; developers should watch for ambiguity or inconsistency that

will trip up design.
        把模型作为通用语言的核心。推动整个团队在各种各样的交中以及在编码中严格的实践这U?/p>

语言。在图表、记录特别是谈话中统一交流方式?br />        通过选择性的表达方式Q即那些对应不同模型的表达方式来消除通用语言中的隄。然后重?/p>

代码Q重新命名那些类、方法模块,使它们和新的模型怸致。我们对那些常用词汇的理解渐渐的达成

一_q以此来解决交谈期间的那些؜淆?br />        要知道,对于通用语言的Q何变化都是对模型的变化?br />       域专家们应当U极反对那些尬的或者不能充分传辑֟概念的术语,开发者应当时时留意含义不

明确或者有矛盾的地方,q些地方会给设计埋下隐患?br />Play with the model as you talk about the system. Describe scenarios out loud using the

elements and interactions of the model, combining concepts in ways allowed by the model.

Find easier ways to say what you need to say, and then take those new ideas back down to

the diagrams and code.
        当你谈论pȝ的时候,多多使用模型。大声地使用模型所提供的那些元素和交互方式描述情节

Q以模型所接受的方式联l域中的概念。尽可能单的表达你所要表辄东西Q然后反q头来把q些?/p>

路{变ؓ图表和代码?br />



littlegai 2006-08-29 21:25 发表评论
]]>
Domain-Driven Design: Tackling Complexity in the Heart of Software 语句_摘.1.http://m.shnenglu.com/qzb2006e/archive/2006/08/21/11539.htmllittlegailittlegaiMon, 21 Aug 2006 12:50:00 GMThttp://m.shnenglu.com/qzb2006e/archive/2006/08/21/11539.htmlhttp://m.shnenglu.com/qzb2006e/comments/11539.htmlhttp://m.shnenglu.com/qzb2006e/archive/2006/08/21/11539.html#Feedback0http://m.shnenglu.com/qzb2006e/comments/commentRss/11539.htmlhttp://m.shnenglu.com/qzb2006e/services/trackbacks/11539.htmlA domain model is not a particular diagram; it is the idea that the diagram is intended to convey. It is not just the knowledge in a domain expert's head; it is a rigorously organized and selective abstraction of that knowledge. A diagram can represent and communicate a model, as can carefully written code, as can an English sentence.
域模型ƈ非一U特D的图,却是q种图所要传辄含义。它q不仅是域专家头脑中的知识,它是严格l织出来的,q且有选择的抽象的知识。一张图C可以展C及表达一U模型,同样的,一D仔l斟酌的代码可以Q一句英文也可以?br />In domain-driven design, three basic uses determine the choice of a model.
1.The model and the heart of the design shape each other.
2.The model is the backbone of a language used by all team members.
3.The model is distilled knowledge.
在DDD中,三种基本用途决定了模型的选择?br />1.模型和设计的核心交相辉映?br />2.模型是所有团队成员交方式的中心?br />3.模型是精化后的知识?img src ="http://m.shnenglu.com/qzb2006e/aggbug/11539.html" width = "1" height = "1" />

littlegai 2006-08-21 20:50 发表评论
]]>
91þó| þùƷþþ| ھƷþ| þĻר| ھƷþþþù| þúݺɫۺ| 99þۺϾƷ| þAëƬѹۿ| þþƷAVӰ| ŷþþþƷӰԺ| ղþǿѵĿ| 㽶þAһ| 2021ھƷþþþþӰԺ| þ߳ˮ| AVþþƷ | ƷþþþþþþþӰԺ| þþþ޾Ʒһ| ޹˾Ʒ91þþ| þˬһ | 97Ʒ97þþþþ | þˬƬav| avպƷþþþþa| ҹþþþþþþþ| þþƷݲݲ| þùһ| þþþþþþ˳| պƷþþþþ| þAV뾫Ʒɫҹ| ŷþۺ | Ʒþþþþ| Ʒۺþþþþ | ŷ츾XXXXԾþþ | ޹Ʒþһ| þ97㽶| 㽶97þ| ӰɫۺϾþ| Ůþþþþ| ŷҹƷþþþþ˳| þ| þþƷƷ| ˺ݺۺ88ۺϾþ|