张志松
记录工作点滴,留下人生轨迹。(zezese@163.com)
posts - 68,  comments - 11,  trackbacks - 0
1.模块接口尽量简单,但是可扩展性要强。
2.减少模块间的依赖,越少依赖越好管理。
3.实现模块自我管理,尽量自己搞定一切。
posted @ 2011-09-08 10:19 张志松 阅读(360) | 评论 (1)编辑 收藏
这是敏捷方法论假设的一个前提:你已经很好的掌握了编程技术!
posted @ 2011-09-08 10:05 张志松 阅读(268) | 评论 (1)编辑 收藏
http://www.codeproject.com/KB/library/piarchitecture.aspx
posted @ 2011-08-21 10:31 张志松 阅读(622) | 评论 (0)编辑 收藏
Const WinHttpRequestOption_URL = 1
Const WinHttpRequestOption_URLCodePage = 2
Dim WinHttpReq
Set WinHttpReq = CreateObject("WinHttp.WinHttpRequest.5.1")
WinHttpReq.Option(WinHttpRequestOption_URLCodePage) = 936 ‘国标GB2312
WinHttpReq.Open "GET", "http://www.baidu.com/s?wd=嘟嘟牛"
MsgBox WinHttpReq.Option(WinHttpRequestOption_URL)
posted @ 2011-08-10 10:30 张志松 阅读(646) | 评论 (0)编辑 收藏
1.用结构体

实现:函数根据传入结构体的大小来判断到底传递了哪些参数。
优点:程序运行效率高。
缺点:不同的语言需要各自定义结构体,一旦需要扩展,每种语言都需要修改结构体的定义。
场合:同一个语言调用,频繁调用等。

2.用XML字符串

实现:函数根据解析传入XML字符串来判断递了哪些参数。
缺点:程序运行效率较低。
优点:不需要定义结构体,只要按照格式拼好字符串就行。
场合:跨语言调用,调用次数很少等。
posted @ 2011-07-29 16:31 张志松 阅读(688) | 评论 (0)编辑 收藏
1.单一职责原则
    一个类,最好只做一件事,只有一个引起它变化的原因。
    一个类只有一个引起它变化的原因,否则就应当考虑重构。
    单一职责原则,由引起变化的原因决定,而不由功能职责决定。虽然职常常是引起
变化的轴线,但是有时却未必,应该审时度势。
    测试驱动开发,有助于实现全理分离功能的设计。
    可以通过Facade模式或Proxy模式进行职责分离。
    一个类,应该仅有一个引起它变化的原因,不要将变化原因不同的职责封装在一起
,而应该隔离。
2.开闭原则
    对扩展开放,对修改关闭。
    实现开闭原则的关键是抽象化,并且从抽象化导出具体实现。
    开闭原则是面向对象设计的主要目标。
3.里氏代换原则
    在使用基类和抽象类的地方,都可以用其子类或实现了该接口的类替换。
    里氏代换原则是继承复用的基石。所有支持继承复用的语言都满足里氏代换原则
4.依赖倒转原则
    要依赖于抽象,不要依赖于具体。
    要针对抽象编程,不要针对实现编程。
    要针对抽象编程的意思是:应当使用抽象和接口进行变量的类型声明、参量的类型
声明、方法的返回类型声明,以及数据类型的转换等。
    不要针对实现编程的意思是:不应当使用具体类进行变量的类型声明、参量的类型
声明、方法的返回类型声明,以及数据类型转换等。
    要保证做到这点,一个具体的类应当只实现接口和抽象类中声明的方法,而不应当
给出多余的方法。这个比较难。一个具体类总有自己独有的方法。
    倒转依赖强调一个系统内的实体之间关系的灵活性。基本上,如果设计师希望遵守
开闭原则,那么依赖倒转原则便是达到要求的途径。
    里氏代换原则是是依赖倒转原则的基础。
    依赖倒转原则是面向对象设计的核心原则,设计模式的研究和应用是以依赖倒转原
则为指导原则的。
    依赖倒转原则是面向对象设计的主要机制。
5.接口隔离原则
    使用多个专门的接口比使用单一的总接口要好。
    一个类对另一个类的依赖性应当建立在最小的接口上。
    准确而恰当地划分角色以及角色对应的的接口,是面向对象设计的一个的组成部
    分。将没有关系的接口合并在一起,形成一个臃肿的大接口,是对角色和接口的
污染。
6.合成/聚合复用原则
    意思:在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的
对象通过向这些对象的委派达到复用已有功能的目的。
    要尽量使用合成/聚合,尽量不使用继承。
7.迪米特法则
    又叫做最少知识原则,就是说,一个对象应当对其他对象有尽可能少的了解。
    优先考虑将一个类设置成不变类。
    尽量降低一个类的访问权限。
    谨慎使用序列化。
    尽量降低成员的访问权限。
posted @ 2011-07-14 21:07 张志松 阅读(321) | 评论 (0)编辑 收藏

   这里介绍一个办法来实现基于MFC应用程序的模块化,至于为什么要模块化,模块化有哪些优点哪些缺点这里不做讨论。

假设有这样一个工程,有主程序Main.exe和两个DLL模块Module1.dll以及Module2.dll组成,所有的模块都动态链接到MFC动态库(静态链接到MFC动态库的情况会有些区别)。


一、首先要建立先定义好一组接口,用来实现主程序和DLL模块双向交换。

 

1、主程序Main.exe要提供一个接口IAppDLL模块,使得DLL模块可以使用主程序的一些功能,比如写日志等。

class IApp

{

public:

   virtual Long GetVer() = 0;  //接口版本号
   virtual ILogGetLog() = 0; //
返回日志接口指针

    //这里可以扩展其他的虚函数,但是新的虚函数定义一定要放在原有接口的最后面,这和虚函数表有关。

    //这样就达到了可扩展性。

};

 

2、模块Module1.dll以及Module2.dll也要分别提供一个或多个接口给主程序Main.exe调用。

分别为:

class IModule1

{

public:

    virtual void SetApp(IApplpApp) = 0; //把主程序的接口传给DLL

    virtual void DoSomething() = 0;//做一些处理

    //这里一样支持可扩展

};

 

class IModule2

{
public:

    virtual void SetApp(IApplpApp) = 0; //把主程序的接口传给DLL

    virtual void ShowDlg() = 0;//显示对话框

//这里一样支持可扩展

};

 

二、建立各自的MFC工程并实现相应的接口

 

1、建立主程序MFC工程Main.exe,动态链接到MFC动态库,然后实现IApp,ILog等接口。

 

2建立MFC工程Module1.dll,可以是规则DLL,也可以是非规则DLL,但是要求动态链接到MFC动态库。

   规则DLL与非规则DLL在资源使用,窗口管理等方面有些区别,一般建议使用非规则DLL

   Module1.dll不直接导出类,而是导出一些函数来创建对应的接口,比如导出函数CreateModule1Instance()用来创建IModule1实例,以此类推。这是为了把创建实例的代码放在DLL中,也是为了支持将来升级扩展。因为后续版本的Module1.dll所实例化的对象占用的内存大小可能不一样的,如果把实例化代码放在Exe中,则需要重新编译Exe

 

3Module2.dll实现同上。

 

三、扩展升级

 

1不修改接口的扩展

比如要修改IModule1DoSomething函数所实现的功能,那就只需要修改并升级Module1.dll即可。

 

2、需要修改接口的扩展

 

修改IModule2接口(有可能也需要修改IApp接口):

class IModule2

{

public:

    virtual void SetApp(IApplpApp) = 0;

    virtual void ShowDlg() = 0;

    virtual void DoSomething() = 0;//增加的函数

};

       这样需要修改Module2.dll和主程序Main.exe的代码来实现新功能。但是修改后Module2.dll一样支持老版本的Main.exe,因此也就只需要维护一个版本的Module2.dll即可。

 

四、一些应用场合

 

1 不用的客户使用不同的模块,从而实现业务逻辑的不同。(比如使用不同的数据库。)

 

2 主程序需求相对稳定,但是某个模块功能经常需要升级。(需求特别紧急的情况下,其好处更是明显,目前笔者的产品就是这样的。)


posted @ 2011-07-13 18:00 张志松 阅读(1592) | 评论 (0)编辑 收藏
   #include <msado15.h>

CComPtr<_ADOConnection> pADOConnection;
//创建连接对象
HRESULT hr = pADOConnection.CoCreateInstance(L"ADODB.Connection");
if (FAILED(hr))
{  
MessageBox(_T("无法创建ADO对象!"));
return ;
}
//设置游标
pADOConnection->put_CursorLocation(adUseClientBatch);
CString strCon("DSN=netbar;");
//打开数据库连接
hr = pADOConnection->Open(strCon.AllocSysString());
CComVariant v;
CComPtr<_ADORecordset> pRst;
CString strSQL("SELECT * FROM activemember");
//查询返回记录集
hr = pADOConnection->Execute(strSQL.AllocSysString(), &v, 0, &pRst);
long count = 0;
pRst->get_RecordCount(&count);
//移到第一个跳记录
pRst->MoveFirst();
CComPtr<ADOFields> pADOFields;
//读取所有的字段
pRst->get_Fields(&pADOFields);
CComVariant vFieldsName("memberId"); //可以是字段名称也可以是编号
CComPtr<ADOField> pADOField;
//获取指定的字段
pADOFields->get_Item(vFieldsName, &pADOField);
pADOField->get_Value(&v);
pRst->Close();
//关闭数据库连接
pADOConnection->Close();
posted @ 2011-06-23 15:17 张志松 阅读(493) | 评论 (0)编辑 收藏
1、包含头文件
#include <MsXml2.h>
#include <comutil.h>
#pragma comment(lib, "comsuppw.lib")

2、例子代码
CComPtr<IXMLDOMDocument> pDoc;
HRESULT hr = pDoc.CoCreateInstance(__uuidof(DOMDocument30));
if (FAILED(hr))
{  
MessageBox(_T("无法创建DOMDocument对象!"));
return ;
}
CString strXML;
strXML = "<t publishid=\"14\" gender=\"2\" starttime=\"2011-06-22 16:50:42\" endtime=\"2011-06-30 16:50:42\" tipsshowtype=\"0\" onlineminites=\"0\" hideseconds=\"5\" url=\"http://192.168.10.93:8080/dodonew/front/resource/hometemplate/showtips3.htm?publishId=14\" />";
VARIANT_BOOL bRet = VARIANT_FALSE;
//加载文件或XML文本
//pDoc->load()
pDoc->loadXML(strXML.AllocSysString(), &bRet);
if (!bRet)
{
return;
}
CString strNode(_T("//t"));
IXMLDOMNode* pNode = NULL;
pDoc->selectSingleNode(strNode.AllocSysString(), &pNode);
long count = 0;
//节点属性,放在链表中
IXMLDOMNamedNodeMap* pAttrMap = NULL;
pNode->get_attributes(&pAttrMap);
pAttrMap->get_length(&count);
for (long i = 0; i < count; i++)
{
IXMLDOMNode* pAttrItem = NULL;
pAttrMap->get_item(i, &pAttrItem);
//取得节点的值
_variant_t variantValue;
pAttrItem->get_nodeTypedValue(&variantValue);
_bstr_t bstrValue = variantValue;
CString strValue = bstrValue;
TRACE("%s\n", strValue);
}
//子节点, 放在链表中
IXMLDOMNodeList* pNodeList = NULL;
pNode->get_childNodes(&pNodeList);
pNodeList->get_length(&count);
for (long i = 0; i < count; i++)
{
IXMLDOMNode* pChildNode = NULL;
pNodeList->get_item(i, &pChildNode);
_variant_t variantValue;
pChildNode->get_nodeTypedValue(&variantValue);
_bstr_t bstrValue = variantValue;
CString strValue = bstrValue;
TRACE("%s\n", strValue);
}
posted @ 2011-06-22 22:48 张志松 阅读(865) | 评论 (0)编辑 收藏
选用map还是hash_map,关键是看关键字查询操作次数,以及你所需要保证的是查询总体时间还是单个查询的时间。如果是要很多次操作,要求其整体效率,那么使用hash_map,平均处理时间短。如果是少数次的操作,使用 hash_map可能造成不确定的O(N),那么使用平均处理时间相对较慢、单次处理时间恒定的map,考虑整体稳定性应该要高于整体效率,因为前提在操作次数较少。如果在一次流程中,使用hash_map的少数操作产生一个最坏情况O(N),那么hash_map的优势也因此丧尽了。
posted @ 2011-03-31 13:20 张志松 阅读(372) | 评论 (0)编辑 收藏
仅列出标题
共7页: 1 2 3 4 5 6 7 

<2024年12月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

常用链接

留言簿(2)

随笔分类

随笔档案

文章分类

文章档案

转载

搜索

  •  

最新评论

阅读排行榜

评论排行榜