読み込んでいます...
2010年01月31日

今天在微软年终Party中分享了敏捷开发的观点,让我真正的开始反思敏捷开发这个词,原来我一直都不知道自己的公司是在进行敏捷开发,不知道是喜是悲。也从这一段时间的开发过程中知道,其实敏捷并不是万能的,项目的速度和质量最重要的还是靠整个团队的协作。有人曾经说微软的敏捷做的不好,其实仔细想想自己的敏捷实践其实更烂,因为敏捷有几点是需要关注的。

  • 合格的自觉的编码规范。
  • TDD,先写单元测试再编码。
  • 客户参与项目。
  • 团队的平等性。

其实要做到上面的很难,无论是大公司还是小公司,其中最有趣的一点是,敏捷的团队要保持创新力和持久力,每周不能工作超过40小时,相比起来,不加班已经够幸运了,更不要说那种没有理由的或者瞎编理由让你加班的了。

所以,要知道敏捷并不是万能的,实践敏捷之前,还要考虑自己的团队能不能敏捷起来。另外要提醒一点的是,如果不能真正保证自己能实践的成功,就不要在实践之前鄙视某些其他的公司,其实以五十步笑百步才是最让人鄙视的,谦虚一点也没什么不好的。

2010年01月26日

本来想写这样一篇文章很久了,虽然也有时间去写,但是这样的貌似纯理论的东西感觉还是很难下笔,今天晚上想着还是写下来好,以后自己看也是一个值得回忆的技术过程。因为我自己使用命令行比较多,所以对我来说,任何机器首先最重要的是命令行环境了,在Windows下面,使用cmd和一些alias工具去使用命令行,在Mac或者Linux下面,命令行更是鼓励的一种方式,可见命令行虽然在历史上很久了,但还是非常重要的。

其实我原来一直都是在微软的.net平台下进行开发的,C#固然强大,但是帮你做的事情太多了,你不需要关心内存泄露,也不需要关心垃圾释放,也不需要关心指针问题,更不用关心自动化等等了。当然,好是很好,但是对程序员的自身提高还是有一定阻碍的,特别是对那些从C#入门的开发人员来说更是这样,所以就会很难理解命令行和自动化为什么好了。当有一个新语言或者新的东西发布的时候,如Chrome插件,iPhone开发等等,很多依赖平台或者IDE很强的人就茫然了,无从下手了。

但是很多人让他们去写这样的东西,用记事本什么的,也可以写出来,但是效率那就是很低的了,这也就是对命令行等等不太熟练造成的,为什么国外的很多程序员很厉害,因为他们基础很好,高层的自然就好了,当遇到问题的时候,自然就会找到简单的,高效的方式去解决。

说了这么多废话,还是举例最快了。例如当我们进行软件开发的时候,我们大部分的流程是这样的。

这个过程貌似是传统的软件开发过程,比如有人做数据库,有人写后端逻辑,进行性能优化,有人做中层开发,封装后端的复杂的逻辑,然后有人做前端开发,调用中层开发的封装的逻辑。当然,任何一个步骤都是复杂和难以控制的,前端要考虑用户体验,UI,UE等等,中层要考虑类的封装和设计,考虑到扩展性和实用性,后端要考虑到性能处理等,DBA数据库开发要考虑到数据读取,IO优化,索引等等,既然各个步骤都是复杂的,但是是什么让我们的过程更加复杂呢,那就是teamwork。

在teamwork中,各个成员依赖于不同的成员,也可以说依赖于不同的成员的结果,例如使用其他成员的代码或者库,这就考虑到协同的问题,所以这就是为什么会有版本控制和流程控制了。当然,当只有一个项目的时候,这虽然也很麻烦,但是还算是比较好解决,但是当项目越来越大,产品线越来越长的时候,一些问题就突出的显现出来了。

举例说明,假设,微软的Windows和SQL Server都要读取XML,但是都使用相同或差不多的逻辑,但是每个团队都有自己的方法,当过了5年或10年,出了BUG,有人修改了SQL Server里的XML读取的方法,但是忘记更改Windows里的,但是Windows团队以为改了Windows里的库,就发布了,但用户一旦一使用,发现出现了崩溃的情况,这是非常正常的,也是无论在大公司还是小公司都会发生的情况,这个时候用命令行可以优化整个过程。

例如当Windows团队和SQL Server团队的发现都写了一个相同功能的类的时候,可以将这个代码放到一个公共库里面去,然后每次使用命令行,在编译的时候自动拷贝最新的库,以保证代码的正确性和兼容性。这样就会有几个好处。

  • 代码维护简单:只在一个地方。
  • 应用程序最新:每天build的程序都是最新的,每个团队成员都是使用的最新的库,不会有错误。
  • 更改维护简单:更改一个地方,所有的代码都会更改为使用最新的代码,而不会这个程序是0.1版本,另一个是0.2,再一个是0.3。
  • 跨应用程序维护:所有的应用程序都可以使用这个库,例如Expression或者VS就同样可以使用这个类。

其实将上面的需求联系到我的实际,就是我在平常的工作中会开发好多东西,例如Firefox插件,Chrome插件和一些Widget,但是这些东西的开发都是大同小异的,都是用HTML和JavaScript,这个时候,就要考虑这样的需求了,是不是所有的软件都可以公用一些东西?如下。

例如我有一些库,而且都可以使用到Firefox,Chrome和Widget里,怎么办,难道我每次都要自己手动从库中拷贝吗?那么如果是这样的话肯定会遇到这样的问题。

  • Boss:Hey GuoJing,你这个可以运行吗。
  • GuoJing:当然可以,只要XXX就可以运行了。
  • Boss:哦,不错,不过另一个好像不工作,这两个代码应该是差不多的。
  • GuoJing:额,寒,我记得我上次拷贝过来了,忘记了,这次再拷一下就行了。
  • Boss:我们不能这样,我们要有一个自动化的系统。

这样的事情会经常发生,有些是显性的,例如你项目不能用了,不能工作了,有些却是隐性的,例如发布了1年之后才发现这个严重的BUG,那就真的就是一场灾难了。

所以命令行和自动化系统能帮我们自动的处理这些烦人的问题,我可以这样做。当需要打包或编译一个项目的时候,自动化的拷贝其他的项目的依赖库到我的应用中,如果其他项目需要编译,那么就先编译其他的项目,然后将最新的依赖库拷贝到我的应用中,如果依赖的库有问题无法编译,自动的通知负责人告知相应的BUG。也就是说,你的一个命令,会做很多的事情,而这么多的事情,仅仅只是一个命令而已。

命令行还有一个显著的特点就是,当你写对了一次,就不会再错了。这样就能保证我们系统的健康性和完整性还有一定的可重用性。

当然,这也可以不需要使用命令行,但是命令行是最简单,最轻便,成本最低的一种方式,如果一个团队的人都熟练使用相应的命令的话,效率会提升不只一倍。

其实,我们使用命令行和自动化的最主要的原因,不是为了耍酷或者说自己是一个真正的程序员,而是在项目中,更多的考虑重用,简单,依赖,可持续性的问题,对于小的公司,小的项目,可能这样的需求不是很高,甚至一个产品都不怎么测试的就发布了,但是对于大一点的公司和项目,自动化的处理,测试,编译,运行和发布都是非常重要的,这也是为什么微软会有用WTT自动化测试和Daily Build了,也是为了保证项目的完整性,健壮性和可持续性(例如微软的有些项目每天都会用很多机器自动的编译,然后自动的测试,自动的将结果发送到每个团队成员邮箱中,这样每个人都会知道哪里的问题,而不是打电话说,喂,好像你那里有问题,我们什么时候看看吧)。

命令行和自动化,其实就是为了简单,自动,高效。虽然一些小公司不太需要这样的概念,甚至可以说我的成本弄不起,但是为了将来的发展,和一个企业的习惯,尝试一下也不是不可以的。:)

311路过 4评论 软件开发 阅读全文..
2009年12月7日

第一就是关于内存的速度的,其实不难,但是开发的时候想到的很少,能想到的优化的就是高人,我也是路过看到不错,觉得很有用,就贴过来了。

另一个就是《算法导论》了,国外的教材,也是MIT的标准教材,很好很强大,昨天看到了堆排序和快速排序(100页),用了好多张纸证明线性比较排序的上界和下界,堆排序和快速排序的最好的速度是nlogn,从数学角度上证明了线性比较排序(如判断a[1]>a[0])的最快就是nlogn,也就是说只要你是比较的,而且还是线性的,nlogn就是最快的了。

数学公式太复杂,什么期望啊,概率啊,极限啊,记的不是很清楚,让我自己推倒也没这个能力,不过倒是让我知道了,以后别想线性快速的排序还能超过nlogn了。:)

2009年11月18日

今天在看厕所专刊(编程珠玑)的时候看到了粗略估算,有点感悟,所以写下关于粗略估算的笔记。

粗略估算在工程角度来说是非常重要的,对于个人的能力评估也是很重要的,粗略估算不是说和仔细的数学的计算正确结果相悖,而是在某些情况下,在得到正确的结果之前,能够给我们一个很准确的方向,例如下面这道题。

题目:从N个数中取M个最大值。N是无序的,不连续的。

当然,在做上面这道题的时候,大家都可以很容易的做出来,例如快速排序,取前M个数,用二叉排序树,后序遍历M个数,堆排序,等等,不是很复杂。当然,这个题还可以变形一下,如下。

题目:从100万个数中取最大的10个数。

好吧,我想大部分的人都会犯这样一个错误,100万?这么大,那么我怎么组织空间才能性能最好,速度最快呢?其实,这个肯定是有一定问题的,100万,不是小数目,但是我们不妨计算一下,在各个系统中占用的内存最坏是多少,我们可以大约估算一下,在16位的机器里,一个指针和一个整数大约占4个字节,32位,那么就是8字节,那么64位就是16字节。那么100万个32位的整数和指针,大约会占用8M的内存,也就是说,在现在的计算机里,就算你将100万个数全部放到内存中,也才8M,那么,最坏最坏才8M,你就可以为你的程序计算出最坏的情况,比如这个程序需要10M内存,CPUx%以及进程数n,那么最后的程序应该在这个预期之内或更好。为了追求速度,可以牺牲一点空间,可以全部读入,如果要求空间有限,那就要优化一下,只用4M或2M内存或者更少。

当然这个题目你可以进行插入排序维护M个节点,这样你可以节约很多空间,只要维护N个字节即可,但是维护节点的性能上也会有很大的损失,100万个数字要维护线性次数,也不是一个小数目,如果你内存需求不是很高,可以一次读入,也会很快。

所以估算能力也是非常重要的,例如我们项目需要写一个程序,需要算法若干,功能若干,我们可以大概的估算一下我们所需要的内存是多少,例如10M,估算一下CPU使用率,大概不会超过5%,估算一下时间,如发送一个报告或者查找一个文件需要0.1秒,发送100个报告大概需要10秒。那么整个系统自动化跑下来可能总共花20M内存,2分钟,线程2个,嗯,是不错的结果。然后在开发过程中,如果大约估算是这个估算结果以内的话,我们可以说程序达到了一个预期的目的,如果再次优化的优先级不高(因为在估算内,肯定是与客户交流过),已经是不错的程序了。当然,程序还是会有很多优化手段的,这里不再做过多的说明了,毕竟任何程序都是可以优化的。

Little定律

编程珠玑里面降到了Little定律,我觉得是非常有必要再拿出来一说的。Little定律指出“系统中物体的平均数量等于物体离开系统的平均速率和每个物体在系统中停留的平均时间的乘积”,所以我们也可以看到这个例子,“这个地方可以容纳约60个人,每个人在这里面逗留的时间大约是3小时,所以我们可以看到进入这个地方的速率大约是每小时20人,现在前面的队伍中还有20人,所以我们估计还需要等待1个多小时”。

同样的我们可以计算一下我有100瓶矿泉水,我每天喝掉2瓶并买入2瓶,那么每瓶矿泉水保存的时间是多少天?可以估算一下100/2就是50天,平均情况下,每瓶矿泉水都可以保存50天(100=2*x=>x=50)。所以Litte法则也可以简单的说成“队列中物体的平均数量为进入速率与平与停留时间的乘积”。

在计算机系统中,这个定律也是有一定的估算作用的,例如在一个系统队列中,平均每秒处理n个数据,这个数据会在队列中停留t时间,而系统的响应时间为r,而整个系统队列中的总数为x,我们就可以得到一个简单的式子,那就是(根据Little定律得到)x=n*(t+r),即进入队列平均数量为进入的速率与平均停留时间的乘积,而这个估算是相当精确的。

所以在程序开发中,能够写出好的程序是第一步(得到正确的结果和不错的速度),第二步就是在一定的情况下的在一定的成本和需求下进行优化(如1天内速度从50秒达到10秒,虽然可以优化到5秒,但是不是非常必要的,因为10秒对客户已经足够友好)。虽然以上两点已经足够,但是在程序开发之初,我们能够通过粗略估算计算出程序的性能为10秒的话,我们可以在设计之初就能够判断我们的设计是否正确,而不是在后期去进行优化,当第一个版本的程序已经能够满足客户需求的时候,我们就不需要额外的成本再去优化以达到某种程序的性能要求了。(不过通常优化的速度越快越好:))

2009年09月11日

问题:

给定一个盛有一些黑色豆子和一些白色豆子的咖啡罐以及一大堆额外的黑色豆子,重复以下过程,直至罐中仅剩一颗豆子为止。

从罐中随机选取两颗豆子,如果颜色相同,就将它们都扔掉并且放入一个额外的黑色豆子,如果颜色不同,就将白色的豆子放回罐中,而将黑色的豆子扔掉。

证明该过程会终止。最后留在罐中的豆子颜色与最初的罐中的白色豆子和黑色豆子的数量有什么数学关系。

思考:留在后面。

抽象:

1.用链表,但是不适合随机查找,不适合用数组。(C#可以用List)

2.黑白豆子用0,1表示。

3.随机数,两次随机拿一个豆子,就是两次随机。

技巧:留在后面。

明确了问题和抽象之后,我们可以编写一下代码来实现这个咖啡豆问题。如果你懒得看代码直接看后面的思考和技巧。

//定义一个List泛型对象
private static List<int> box;

static void Main(string[] args)
{
    
//初始化4个黑豆子和4个白豆子,找规律
    TestMain(4, 4);
    
    Console.ReadKey();
}

static void TestMain(int blackNumber,int whiteNumber)
{
   
//初始化“咖啡罐”
    box = new List<int>();
    SetBox(blackNumber,whiteNumber);
   
//如果“咖啡罐”里面的咖啡豆不等于1
    while (box.Count != 1)
    {
       
//拿咖啡豆
        GetCoffee();
    }

    Console.WriteLine(GetStyle(box[0]));
    box
= null;
}

上面我们写一个主函数,这个代码比较简单,虚拟了拿咖啡豆的过程,如果咖啡豆的数量不等于1的话,我们就继续拿,这里用了SetBox方法初始化咖啡罐,代码如下。

//0 黑色咖啡豆
//1 白色咖啡豆
static void SetBox(int blackNumber, int whiteNumber)
{
    Console.WriteLine(
"Black " + blackNumber + " White " + whiteNumber);
    
//添加黑色豆子
    for (int i = 0; i < blackNumber; i++)
    {
        box.Add(
0);
    }

    //添加白色豆子
    for (int i = 0; i < whiteNumber; i++)
    {
        box.Add(
1);
    }
}

这里最主要的方法就在GetCoffee方法,这个是我们的核心方法,在明确了问题和抽象之后我们可以写如下代码,代码并不复杂。

static void GetCoffee()
{
    
//拿出的咖啡豆的颜色初始化
    int fCoffee = 0;
    
int sCoffee = 0;
    
    
//随机数
    Random random = new Random();

    //随机数的最大值
    int max = 0;
    
    
//随机数的最大值等于咖啡罐中的咖啡豆的数量
    max = box.Count;

    //随机生成两个index
    int fIndex = random.Next(0,max);
    
int sIndex = random.Next(0,max);

    //如果不是同一个index
    
//这里如果是同一个再执行的话肯定是有错误的
    if (fIndex != sIndex)
    {

        //分别获取咖啡豆的颜色
        fCoffee = box[fIndex];
        sCoffee
= box[sIndex];

        //如果颜色相同
        if (fCoffee == sCoffee)
        {
            
//丢掉一个咖啡豆
            box.RemoveAt(fIndex);
            
//这里链表或List的长度变短,要检查是否只剩一个了
            if (box.Count != 1)
            {
                
//如果还有,后面的索引减少一个
                if(sIndex!=0)
                {
                    sIndex
;
                }
                
//移除咖啡豆
                box.RemoveAt(sIndex);
                
//添加一个黑色豆子
                box.Add(0);
            }
            
else
            {
                
//添加黑色豆子
                box[0] = 0;
            }
        }
        
else
        {
            
//颜色不相同检查是否为白色
            
//如果不是白色的话就丢掉
            if (!IsWhiteCoffee(box[fIndex]))
            {
                box.RemoveAt(fIndex);
            }

            if (!IsWhiteCoffee(box[sIndex]))
            {
                box.RemoveAt(sIndex);
            }
        }
    }
}

嗯,上面的逻辑比较复杂,其实也比较简单了,注释都写在上面了,读者可以自行查看,这里IsWhiteCoffee函数很简单,代码如下。

static bool IsWhiteCoffee(int color)
{
    
return color==1;
}

嗯,整个问题来说不难,不过这里有两个陷阱。

  1. 两个相同颜色的咖啡豆。
  2. 随机拿取

两个相同颜色的咖啡豆这个地方,值得注意的是,如果你的“咖啡罐”中本来就只有2个白色豆子,那么你拿出来的就是2个相同颜色的豆子,那么如果你先Remove链表里的一个元素,那么第二个再Remove的话,那么索引就超出范围了,这就会有异常。而且题目也没说这个咖啡罐里面一定两种颜色都用,说不定都是白色的咖啡豆呢。

第二个随机拿取这里就比较有意思了,具体分析一下。

思考:

其实在做题的时候我们应该先思考,这也就是为什么这个题目还小有意思,大部分的人都会一上来就看题目然后写代码,最后看看结论比较的对不对,这不是一个好习惯。OK,我们来想想这个问题,恩,如果两个颜色不同,就丢掉黑色的,如果两个颜色相同,就都丢掉。仔细想想,仔细想想,恩,对,也就是说,无论我们怎么拿豆子,白色的豆子的取出的过程都是,2个,0个,2个,0个

也就是说,白色的豆子为偶数个的时候,留下的一定是黑色,而白色豆子为奇数的时候,留下的一定是白色!所以,随机不随机根本没有必要,就算你从第0个开始,顺序的拿两个豆子又怎样了呢?一样是这个结果,所以根本不用随机拿取。

技巧:

嗯,思考了之后,这个问题就太简单了,根本就不用浪费那么多时间写代码了,我们可以把随机过程改成顺序过程,或者直接干脆判断白色豆子的奇偶性,如果白色豆子为奇数,返回白色,否则为黑色。恩,改成一行代码了,简单吗?

总结:

所以说,写代码的时候,应该先思考,再写,否则会浪费很多精力,就算我们的程序的每个函数的性能都是O(1),还是不及一行代码来的快,毕竟程序,本来就是数学的程序。:)

详细数学推导过程请看我一个朋友的日志。

2009年08月3日

用电脑用多了,才发现命令行才是最高效的操作,在Windows下面的时候,也使用自己配置的命令行工具进行配置。最近安装了Ubuntu,发现Linux与Windows来说,命令行更加简单和可扩展了。不过其实和Windows下面的alias工具差不多,如果在Windows下面使用了alias工具,工作效率也和Linux命令行差不多啦。下面是我用命令行的一个截图。

我知道也相信很多人不喜欢使用命令行,不过我觉得这是个人爱好问题,无所谓是否非要使用命令行。不过我相信如果没有使用甚至是接触过命令行的人,肯定也不会特别专业,因为这里不是说非要使用命令行,而是很多东西如果你不使用命令行根本就不知道。比如在文件中查找字符串,大部分人都会使用查找替换,其实一句命令行就可以搞定了,这样就能够提高很多效率。

当然,这还是个人喜好问题了,像我用SVN的时候就更喜欢命令行一些,否则你真不知道哪个文件有没有check in,哪些文件是否还是“?”状态。用“乌龟”SVN是很方便,用手框一下就可以了。可命令行的话我直接输入sc就搞定了,而且还知道文件为什么冲突,哪个地方,什么时候冲突,而不会做删除原来的文件,再手动添加到服务器上这样麻烦的事情了。

用了几天的Ubuntu,感觉这个系统还不错,不过很多东西其实也很烂,和Windows比,我还是觉得没有Windows好用,比如这篇文章的截图就是用Ubuntu截的,对我来说我却觉得很不好,锯齿这么多。。哎。。Linux真的还是有很多路要走的。不过字体要比Windows好看多了,看上去也舒服多了。。。

246路过 0评论 软件开发 阅读全文..
2009年05月27日

今天在老赵的Twitter上看到了他的一篇文章的连接,是一道简单的题,不过您做对了吗,看上去很有挑战性,所以就尝试做了一下,发现其实难度不难,在思想上还是比原来有了很大的进步,至少在数据结构上面的思考方式还不错,O(∩_∩)O~,但是还有一点点不太好的地方,当然和我懒有关了,当然,在一些代码量比较多的地方,也没有标准答案了,好,我们来看题。

题目是这样的(Reverse),有一个数组,假设是[1,2,3,4,5,6],我可以指定反序的索引,比如1,4,那么这里输出就是[1,5,4,3,2,6],不知道你看明白了没,输入的索引1和4,那就2,5交换,3,4交换得到最终的数组,是不是很简单呢,不过做的方法有很多种,不知道你是怎么做的,for循环?压栈还是递归?不知道,但是肯定有如下几种方法,比如,先计算长度啊,计算偏移量,一搞,反正怎么循环一套就出来了,还有的时候有点小错误,还有人用新数组,分别一个一个的套进去,然后怎么一弄,遍历一下就完成了,还有人干脆用了压栈等复杂的数据结构。

不管怎样,貌似作出来的都是不错的,但是咱们程序员要提高啊,不能老做IT民工,其实有一种很简单的做法,就是开始索引和结束索引的大小,开始索引一开始是小于结束索引的,然后可以直接替换开始索引和结束索引的数组的元素,然后各自加贺减,最后开始索引大于结束索引的时候就可以退出了,是不是很简单,OK,代码可以编写如下。

if (endIndex != startIndex)
{
    while (startIndex <= endIndex)
    {
        temp = lists[startIndex];
        lists[startIndex] = lists[endIndex];
        lists[endIndex] = temp;
        startIndex++;
        endIndex–;
    }
}

其实,这里另一个重点是捕获异常,按照老赵的说法是抛出一个新的异常,所以代码可以编写如下。

static int[] Reverse(int[] list, int startIndex, int endIndex)
{
    int[] lists = list;
    int temp;

    if (startIndex < 0) //这里不止这两种情况了
    {
    throw new Exception("开始索引小于数组最小值", null as Exception);
    }

    if (endIndex > lists.Length)
    {
    throw new Exception("开始索引大于数组最大值", null as Exception);
    }

    if (endIndex != startIndex)
    {
        while (startIndex <= endIndex)
        {
                temp = lists[startIndex];
                lists[startIndex] = lists[endIndex];
                lists[endIndex] = temp;
                startIndex++;
                endIndex–;
        }
    }

    return lists;
}

其实,这样做也不错,不过我个人觉得有的时候在一个地方统一判断是否抛出异常的话,会更好,这样也比较容易维护,也省事,编写一个类,然后判断是否是我们需要抛出的异常,如果是,咱就抛出,不是,就算了。代码可以实现如下。

internal static class CriticalExceptions
{
    internal static bool IsCriticalException(Exception ex)
    {
        return ex is NullReferenceException ||
           ex is StackOverflowException ||
           ex is OutOfMemoryException ||
           ex is System.Threading.ThreadAbortException ||
           ex is System.Runtime.InteropServices.SEHException ||
           ex is System.Security.SecurityException;
    }
}

当然,这里没有绝对的好和不好,好不好都要看具体的应用中的设计了,在早期,代码的编写质量是很重要的,中期了,咱就看结构了。OK。可惜TOM说我数据结构和设计都不行啊。。哭。。~

2009年04月16日

Captain的朋友最近需要这样一个工具,是SEO工具,需要在百度刷网站,其具体思路很简单,打开百度,输入关键字,找到网站,点击,OK,应该增加了一点点Rank,可怜的我被Captain脱下水,赞助我那么大的空间我又不好意思拒绝,OK,就这样上了贼船了,给他朋友写一个SEO工具。

用了好几个小时去写这个工具,整体来说基本上完成了,现在在测试阶段了,测试不同的系统,不同的浏览器下面会产生什么效果。而且在现在的情况下,还暂时不能够自动更换IP,不过现在也已经有这样的TOOL了,所以要完成也不是很难的,但是要花时间。今天很闲,但是明天就不闲了。

暂时的功能包括单个网站点击和多个网站顺序刷新。单个网站很好理解了,比如我搜索关键字blog,然后找到我的博客,然后点击,增加一个点击,多个网站,就是写一个配置文件,按照顺序的刷新,不过我自己不用这个工具,纯属写给别人。第一个Beta版本在下面了。

现在也有几个这样的工具,不过不是很好用,很多错误,我这个错误倒不知道,还在测试中,但是有一点比别人好,就是可以自动翻页,例如我的blog关键字的网站排名在40页,你可以选择找40页去点,每次都会去找40页,不用当排名更改了之后再更改页数之类的,自动的就可以了,这是我自己觉得还行的地方,因为我自己刷自己做测试的时候,感觉还行。

当然,如果你对这个小工具感兴趣的话,可以去这里看看,不过暂时不提供免费下载,只有内部给朋友用和购买两种方式,如果你不想买,可以做朋友,呵呵,因为我也不怎么想卖,除非你价钱好的话,呵呵。

现在好像不支持Win7+IE8,可能是系统的原因,测试计划大概是XP SP3和Vista SP1。

270路过 4评论 软件开发 阅读全文..

今天早上上班,看到几个同事在磨磨叽叽的在自己的代码前做什么事情,我很好奇于是上去问了一下,原来是同事最近在用ReSharper改善自己的代码,于是我让同事传给我这个小工具,使用了一下,不看不知道,一看吓一跳啊,原来自己的代码中有这么多不好的代码,例如重复使用的变量名,乱用public,private和protected,还有一些申明了但是没使用的一些变量。虽然这些都是细节,但是细节往往反映了一个开发人员的能力啊。。

例如上面的图中,我们申明了一个变量,但是在整个解决方案中都没有使用这个变量,那么ReSharper就会将这个变量显示为灰色,并提醒你错误信息(在右侧的侧边栏)。然后也会给你一些解决方法,例如上面的“移除无用的字段”。

ReSharper还能够帮助我们用更好的方式去初始化一个类的对象,当我们的对象能够隱式的释放资源的时候,或者有一些默认的构造函数能够直接进行变量的申明和初始化的时候,ReCharp会提醒我们这里可以简化或者可以隱式的释放资源,这样就提高了我们的代码的构造,让代码看上去更清晰,也避免了一些潜在的风险。

上述代码在更改后更改成为了最新的简单的代码。

除此之外,ReSharper还会告诉我们哪些变量应该申明为public,哪些变量应该申明为private或者protected,还有,ReSharper还能够告诉我们这个方法在主函数中并没有初始化,那么在这里可以作为静态函数而存在,那么我们可以改为静态函数,这样就能够让代码具有更高的复用性。

ReSharper是个不错的东西,能够让我们的编程习惯和风格更加优秀,当然,好的工具比不过好的意识,意识才是最重要的,在我们平时写代码的时候,应该更加注意自身的修养。由于是嵌入式的,使用VS开发的朋友能够很好的与ReSharper进行整合。想要下载的朋友可以在下面下载。

到这里下载

391路过 4评论 软件开发 阅读全文..