iLeichun

当前位置:首页编程开发

用不同语言实现脸部辨识

分类:编程开发  来源:网络  时间:2012-4-11 20:50:49

脸部辨识是通过图像算法来判断人脸位置和大小的计算机技术。它指认面部特征,忽略其他图像噪音,譬如建筑物,树木和身体。现在大多数社交网络平台的相册都有这个功能,在你上载了一张照片后,它自动跑算法,在照片上标识出你的朋友。此文向你介绍用不同的插件和库来实现这个功能。

jQuery 脸部辨识

jQuery的插件在照片上标识脸部并给出他们的坐标和大小。这个插件是由六六(音译:Liuliu)结合HTML5 canvas开发的,所以只能在支持HTML5的客户端跑。有兴趣的话可以参见这个样例(见下图,不过要翻墙),整套算法代码可以在git hub下载。

 

用不同语言实现面部辨识
(jQuery 脸部辨识样例)

 

PHP 脸部辨识扩展

提供了用PHP实现的OpenCV (Open Source Computer Vision) 。它包含两个函数face_count() 和face_detect(). 第一个给了在一张图像上所标识的面部数量。第二个给了一个他们的坐标数列和总数量。你可以在XARG’s page.找到安装程序和使用手册,还有Demo。

脸部辨识API

这个API是由一个罗马尼亚人开发。这个使用还是很方便的。你的程序发给它API认证和要分析的图像URL,它返给你一个XML数据包含在图像上发现的所有脸部数据。这个包特别方便,是因为它可以直接分析URL而不是图像数据,所以你可以直接在服务器上抓链接然后进行分析。

Ruby

这个是跟使用OpenCV的Ruby包,和PHP的那段程序很像。你们可以在Ruby页面下载程序。

OpenCVDotNet

这个是为.NET framework开发的程序管理,通过他可以直接从C#里面叫OpenCV的函数。 它包括一个DLL (C++写的) 把OpenCV包在.NET的类里面,这样VB.NET, C++和C#都可以用。

关于译(作)者:
潘文佳:软件工程师。从事iPhone/iPad、Android手机应用开发。关注移动应用产品设计和市场展望

用户体验设计的五项原则

分类:编程开发  来源:网络  时间:2012-4-4 20:55:31

                                       阿里巴巴资深交互设计师 宋磊

如何设计出具有优秀用户体验的产品是交互设计师始终面临的一道难题,“好的产品设计一定是建立在对用户需求的深刻理解上”这句话被许多设计师视为设计的天条;至于在设计中如何发现并深刻理解用户的需求,并由此设计出具有优秀用户体验的产品,阿里巴巴的UED团队在多年的产品设计实践中总结出重要的五项原则。

1. 同理心:所谓的同理心通俗说法就是换位思考。设计师在设计产品时要能够做到换位思考,体会用户的立场和感受,并站在用户的角度思考和处理问题,把自己置身于相关的用户场景中,理解用户的行为特点和行为差异。

在我们阿里系网站,淘宝网站上面主要是C类用户,淘宝的很多设计师自己本身就是C类用户,他们会更加容易把握和理解C类用户的需求,以此来指导产品的设计。这一点对于我们B2B的设计师来说即是面临的困难也是一种机遇,因为B2B的设计师很难从自身获得足够的B类用户经验也就无法很好的把握和理解B类用户的需求,所以我们团队就更加强调设计师的同理心、换位思考能力。我们会要求设计师在平时多注意积累用户经验,熟练的使用自己的产品,模拟B类用户进行相关操作,也会经常让设计师走出去把用户请进来等各个渠道和用户研究的手段让设计师可以全方位深入的了解用户需求。使得我们的设计师可以很客观、深入和全面的了解用户以及相关需求,也就避免了依赖自身经验和主观臆断的闭门造车。

记得在我上大学学习《无障碍设计》课程的时候,为了体验和理解腿部残疾人士对于乘坐车辆的需求,我会把自己的腿绑在一起或者坐在轮椅上,真实体验腿部残疾人士上车时的场景。我想有过这种体验的设计师为腿部残疾人士设计产品的时候,肯定会在设计中充分考虑到残障人士的真实需求了。

同理心是用户体验设计的基础,只有这样设计师才会对用户需求把握的越透彻,设计出越贴心的产品。当我们的用户看到产品时会说:“这就是我想要的”,我想这应该就是最好的用户体验设计了。

同时需要说明的是同理心不是万能的,也不都是准确的,更灵活的运用和效果的产出,一方面需要设计师长期的产品设计经验的积累和对用户长期深入的接触和理解;另一方面需要设计师对用户数据和用户行为的分析再加上相关的用户研究的方法的使用。

2. 简洁就是好的:简洁不等于简单,它是在设计师深刻理解用户需求的基础上,根据用户的操作行为、信息架构等因素深思熟虑后的用户交互界面,界面不是产品功能的简单 “堆砌”和界面信息的杂乱“摆放”;是一个满足了用户特定需求、具有流畅操作、赏心悦目的界面。

记得在前几年很多网站的注册页面中,排列了许多需要用户填写的必填或者选填的表单,显得页面特别的繁琐和复杂,其实这些都不是用户想要的,用户需要一个页面上只有简单的一道两个必填的项目,可以让用户以最快的速度完成相关表单的填写,以便尽快的完成网站的注册的简洁页面。但是我们却基于保存用户资料数据、商业和运营的考量,设计出一个复杂的注册页面,强迫着用户做着对于用户来说没有意义的事情。

再看看现在网站的注册页面基本上只有很少的几个简单需要用户填写的注册信息,甚至有些网站为了让用户更加快捷的完成他的目标,取消了注册环节,真正的方便了用户。

简洁就是好的,本质上是让设计师了解一般用户在单个页面只会有一个主任务和主流程,因此不要用其它次要因素或是繁复的视觉元素来打扰他的视觉注意力,干扰他的判断,越简洁,用户的使用感受越佳,这样对于用户体验来说就是好的。

3. 把决定权还给用户:要让用户知道产品的决定权是在用户自己手中的,不要和用户抢夺控制权,要谨慎的帮助用户做一些决定,很多时候还是要让用户自己进行判断,并进行操作。

很多时候网站出于商业、营销等层面的考虑,会帮助用户做决定,会引导用户做一些他所不愿意或者反感的事情。这些举动严重干扰了用户的操作进度和用户目标的完成。

例如在SNS网站中,当用户编辑完一篇内容顺利发布后会出现发布成功页面,该页面自动跳转到已发文章列表页面。但是一些用户其实发完是想看该文章的详情页面,以了解回复或者留言情况,还有一些用户是想再次编辑一篇新的文章,还是少部分用户希望回到首页。所以系统自动跳转到已发文章列表页面就让很多用户感觉到不便,让用户产生很差的使用体验。其实我们可以在发布成功页面不做任何跳转,在给该页面上添加几个用户可能要去的页面链接。这就是要把决定权还给用户。

把决定权还给用户,是体现了对用户的尊重,让用户知道产品是掌握在用户自己手中,产品只是辅助用户完成他之前设定需要完成的目标或任务,只有这样才是给用户带来尊重感、安全感,给产品带来很好的使用体验。

4. 帮助用户做一些事情:在用户在使用网站的时候,很多地方我们是可以帮助用户完成一些事情,这个就可以让用户更省心更有效率的完成他需要带到目标。互联网用户相对于传统行业的用户来说,网站更容易收集用户的相关数据和用户使用网站的行为轨迹。这样就有助于我们了解用户,帮助用户做一些事情。比如在下单页填写物流信息的时候时很多用户不知邮政编码,通过用户填写的省市区系统可以自动完成填写大致的邮编,让用户顺利完成注册。但帮助用户必须有个度,不能过多也不能太少。

例如在莫网站用户在商品购买成功后会有个购物成功的页面提示,通过数据分析与用户调查,发现绝大部分的用户此时会希望看到订单详情,看订单的受理情况。于是当购物成功的页面生成后,系统将自动跳转到订单详情页面,帮助客户完成这一点击。

但并不是说这一做法是不变的,随着时间和环境的改变,如果发现订单详情页面的点击量下降,而继续购物和寻找其他商品的点击量变大,这些数据所能反映出来的信息是用户不希望直接跳转,这时就要考虑把自动跳转页面取消。

另外如果卖家在发布产品时要选择类目,如果以前多次发布过相关的类目,现在再发布时,系统会根据他以往的发布情况直接给出他要的类目,与此同时再给他一个选择全部类目的入口,便于卖家快捷地发布商品。

帮助用户做一些事情,其实就是充分利用网络系统的一些运算、速度上的一些优势辅助用户在网上完成相对复杂一些的任务,可以让用户快捷、方便的完成任务。

5. 用户也是不断的成长:我们的用户的使用经验也会随着互联网行业和网站的发展而发展,用户的经验也是在不断的积累中,也在不断的接受的新的事物和新的交互方式。所以不要用静止的眼光看待用户,不要把用户想的太笨,也不要把用户想的太聪明。

例如在一般网站的文字段落中都会有超文本链接,其表现形式一般使用区别于旁边普通文字的颜色外加下划线的形式表示。之前会有设计师认为也许这样的表示用户会不知道该处是一个超文本链接,所以会在旁边给予专门的提示文字告诉用户该处是超链接,其实随着互联网不断深入到人们的日常生活中,各个网站基本都使用该标准的超文本链接样式,用户已经熟知了这一样式和交互模式,如果在链接旁再加上文字说明,反而会阻碍用户阅读的完整性。

同样也不也要把用户想的很专业很聪明,网页技术人员通常对网页代码、服务器等技术问题非常熟悉,所以也想当然的认为用户也是同样知道这些技术。当用户输入了错误的网站时,页面会显示“404”错误,这个对于普通用户来说就会很困惑,用户不知道这个代表了什么错误,这个又意味着什么。会猜测是不是网络故障,是不是页面出现问题。这时如果我们把“404”错误,换成“该页面不存在”等说明,用户就可以清晰的明白出现了什么问题。这样实例充分说明了不好把用户想的太聪明,都是互联网资深用户。

最后要说一点的是:在设计中任何一个产品都不可能满足所有用户的所有需求,即使前期做过大量的调研和准备工作,新的产品上线时还是不可能做到百分百的功能齐全,可以先上线50%的功能,但是这部分的功能的体验是好的,之后通过实际运行中获得的用户数据和反馈不断优化升级,互联网产品文化就是Beta版文化。用户体验设计的实质就是一个产品不断优化的过程,没有最好,只有更好。

源地址:http://www.uxsong.com/?p=719

最容易被忽视的五大测试死角

分类:编程开发  来源:网络  时间:2012-4-4 20:46:26

在经历了策划、设计、开发等一系列的劳作辛苦之后,只要再进行细致地测试网站便可以上线了。笔者参与过很多大大小小的网站项目,今天从产品的角度来说说功能测试环节中最容易被忽视的测试细节点。

一:搜索死角

这里所说的搜索是指站内搜索,站内搜索可以让用户非常方便的找到目的内容,另外可以通过记录用户站内搜索关键词来进行用户分析。可是随着网站内容的增多以及条件的繁琐,站内搜索往往是以多重条件搜索的方式来展示给用户使用的。这就给测试人员造成了一定的压力,毕竟测试人员光从需求文档上是无法对每项搜索条件和结果进行深入分析的,因此搜索功能的测试可称之为“测试死角的老大”。

死角盘点二之最容易被忽视的五大测试死角

解决方法:建议测试人员邀请产品经理共同测试该功能,做到万无一失。

 二:列表排序死角

无论是门户网站还是电子商务网站或者是NNS社区,他们都少不了列表排序,今天笔者用某网站的口碑榜排序列表来叙述一下该死角到底有多深。如果我们来做一个公正的第三方评论平台的话我们只需要根据时间、口碑值来进行排列即可,这样一来死角不会太深。越来越多的网站把口碑榜,销售榜,关注榜作为提高PV和降低退出率的手段,这样一来列表排序会有网站的运营人员参与,在此我做一个比方大家就会明白列表排序会出现死角的原因了。假设我们现在来进行一个电脑关注度的排序,假设从网站后台的表单中我们查询是这样排列的:

死角盘点二之最容易被忽视的五大测试死角

这时运营接到市场部的通知,要求把神舟电脑加入到关注度排行榜的第三位,从网站后台我们查出神舟电脑的关注度为1200,这里就存在一个问题了如果强制将方正替换为神舟的话那么展现在网页上的列表排序就像下面这样:

死角盘点二之最容易被忽视的五大测试死角

用户不是傻子一眼就看出来这样的商业行为,因此测试人员在测试排序列表时,如果包含了强制置顶功能的列表不光是要把值插入进去,更要做到前后统一的效果,这样才不会穿帮。

解决方法:没有绝对的解决方法,因为本文是做死角探讨不是技术文章,因此具体的方式不做赘述,笔者以前的做法就是采用“补偿法”把少的补上,出现相同值得话就要视情况而去操作了。

三:SQL注入攻击死角

SQL注入攻击是黑客对数据库进行攻击的常用手段之一。随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多。但是由于程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候,没有对用户输入数据的合法性进行判断,使应用程序存在安全隐患。用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据,这就是所谓的SQL Injection,即SQL注入(摘取百度百科)。前段时间密码泄露门事件闹的沸沸扬扬,所以在测试环节对待这样一个普通用户涉及不到的操作还是需要倍加留心。

死角盘点二之最容易被忽视的五大测试死角

解决方法:笔者不是安全专家,所以没有非常好的解决方法,如果大家对此有兴趣的话可以在网上查阅相关资料。

 四:图片缩放死角

图片是网站的灵魂,一张恰到好处的配图能够吸引用户的目光,从而为用户提供优良的用户体验。UI设计师在设计页面时选取照片的尺寸会根据版面的需要来进行搭配,而往往这样的配图在网站上线后是需要运营人员根部不同的内容进行更换的,甚至有新闻采集系统会自动转发外站的新闻,由于配图的图片位置大小是固定的,所以一不小心的工作失误就会出现图片变形的情况从而影响用户使用的心情。

死角盘点二之最容易被忽视的五大测试死角

解决方法:根据版面的样式确定图片的最大长宽尺寸,并配以淡色的外框,如果程序检测到上传的尺寸与之不符,那么根据等于缩放的比例缩放最大宽度或者高度。即便左右留白或者上线留白总比一张变形的图片看得舒服。

五:文字截取死角

该死角和第四个颇有相似之处,最大字符长度如果设置不准确的话一来会影响用户的阅读,二来会影响页面的美观,好在这样的一个死角修正起来很简单,笔者就不做赘述希望测试人员在测试的时候多加小心便好。

死角盘点二之最容易被忽视的五大测试死角

解决方式:试验及调整到最佳的字符显示数量,如果标题真的过长的话建议用…放在标题的末尾,从程序的角度来说增加标题的“title” 显示。

 今天就说这么多,我相信肯定会有很多看官也有会有自己总结的死角,不妨说出来分享一下。

By:alex

代码注释和格式化的10个最佳实践

分类:编程开发  来源:网络  时间:2012-4-4 12:34:06

代码注释和格式化的目的都是为了让代码更容易阅读和理解,提升了代码的可维护性,下面是 10 个关于代码注释和格式的 10 个最佳实践(特别是 Java)。

代码注释

注释是代码的一部分,在统计代码行时注释也包含在内,非常重要。一段无任何注释的代码很可能是完全无用。尽管有些极端的建议说代码应该有自注释的方法,不过我们还是建议注释良好代码的必要条件。

  1. 只在需要的时候编写注释
    • 不要为每行代码都编写注释,无用而且降低可读性,例如:
      • int count = 0; // 给 count 变量设置初始值,这人人都能看懂 (?!?)
    • 缺少注释会增加代码维护难度和实践,首先变量和方法名应该是可理解和自注释的,下面是两个不好的例子:
      • int s = sqrt(v1) + v2 / v3 + fread(s). getChar(0)  //(?!?)
      • List<int> getVal(int val, int len, String op) //(?!?)
  2. 不要编写错误的注释,比无注释更可恶
  3. 为非常重要的变量编写注释,而不是使用自文档风格
  4. 为所有的公开的方法和接口编写注释,这是必须的
  5. 应该删除文档中一些无用的内容,例如 todo 之类的

代码格式化

很多的开发工具都提供代码格式化的功能,例如 maven checkstyle ,并且这些格式化操作可在代码保存时自动进行,但这些工具格式化的规则多少跟每个公司的要求不同,所以在使用前应该进行设置以便跟公司代码格式规范一致。

下面是一些对于代码格式化的建议:

  1. 统一使用括号的方式:你可以在同一行使用括号或者换一个新行,这都没关系,关键是要一致。
  2. 统一空行使用的规则,例如方法结束后可以来三个空行,是否每行代码都用空行隔开或者不,这些依照自身的习惯而行,但要统一。
  3. 缩进的处理方式统一
  4. 每行的字符数应该有所限制,提升代码可读性,一般 80 左右个字符最为合适
  5. 代码中的空格使用要一致,例如:
    • 操作符和变量:
      • a += b , c = 0; (a == b)
    • 语句和括号之间:
      • if (value) {, public class A { 
    • 循环之中:
      • for (int i = 0; i < length; i++) 
    • 类型转换:
      • (int) value , (String) value

来源:http://www.kuqin.com/software-engineer/20120324/319252.html

ASP和PHP如何删除自身文件

分类:编程开发  来源:网络  时间:2012-3-1 1:04:30

你会用asp和php删除其他文件,但你会用它们删除它们自身文件吗?其实这是可以实现的,下面的代码就为您实现这个功能,欢迎访问。

z.asp
代码如下:
<%
s= Server.MapPath("z.asp")
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(s) Then
fso.Deletefile(s)
End If
Set fso = Nothing
%>

z.php
代码如下:
<?php
$file = "z.php";
if (file_exists($file)) {
@unlink ($file);
}
?>


运行一下,文件自身被删除了....

代码如下:
<%
s2= Server.MapPath("z2.asp")
s= Server.MapPath("z.asp")
Set fso = CreateObject("Scripting.FileSystemObject")
fso.CopyFile s2,s
Set fso = Nothing
%>

出处:http://www.jb51.net/article/14768.htm

如何调用51ditu中的地图

分类:编程开发  来源:网络  时间:2012-2-27 20:55:46

今天研究下地图标注。实际上就是看看如何调用51ditu提供的api接口并结在PHP中应用。

其提供的api接口说明:http://api.51ditu.com/

帮助文档:http://api.51ditu.com/docs/index.html

以下简单的演示一个,用户从后台标注自己想用的东西,前台读出来。

从网站是复制,粘贴试了下,还是比较容易使用的。

第一。在http://api.51ditu.com/docs/ezmarkerapi.html

这里看了下,按上边说的引入JS,可以设这城市,上边说的是从下拉列表中选,实际应用时应该从数据库中读出

第二。他这里是把读出的经纬放到文本框里,实际用应是可以通过ajax提前并保存到数据库

function setMap(point,zoom)

{

document.getElementById("x").value=point.getLongitude();

document.getElementById("y").value=point.getLatitude();

document.getElementById("z").value=zoom;
//这里加代码通过ajax保存到数据库,如果是用jquery
$.get(¹map.php¹,{x:point.getLongitude(),y:point.getLatitude()},function(msg){
alert(msg);
});
//只需要在map.php中写插放到数据库中的代码即可

}

OK到这里已经能把位置保存到数据库里了,下边是读出

第三,读的话用http://api.51ditu.com/docs/mapsapi.html这里

如何依据经纬度或标记添加信息窗口

既然已经保存到数据库里了,这里再读出来就OK

更多的用法根据具体的需要求看下这网站的帮助文件。

字符串多模式精确匹配算法分析

分类:编程开发  来源:网络  时间:2012-2-25 0:21:57

什么是TTMP算法?不好意思,我发布这篇文章之前,估摸是没有其他地方能找着该算法的,因为那是俺生造的。
TTMP是啥意思呢?是Terminator Triggered Multi-Pattern 的意思,也就是结束符触发多模式算法。
-_-! 有点难理解,没关系,看完了也许就理解了。

不过这个自造的算法有点复杂,为了保证大家能够顺利阅读,请大家配合做一个测试:
拿出你的手表,或者其他计时器,看看你能用多块的时间阅读完下面这篇文章。
判断标准如下:
如果你的时间少于15秒,就可以不用读我的文章了,完全有能力造一个更强的算法;
如果你的时间少于30秒,我们可以沟通交流一下;
如果你的时间少于45秒,你可以仔细阅读一下,说不定可能也许有点启发作用;
如果你的时间少于60秒,你一定能够在这里挖到宝矿;
如果你不属于上述情况,我建议您啊,还是不要费力气阅读了,有点面为其难了。

Do you raelly know Engilsh?
At laest in Egnlish, wehn pepole raed, tehy
usaully wlil not noitce taht the charcatres bewteen
the frist ltteer and the lsat leettr are not in a
corrcet oredr. In fcat, hmuan brian does recongize
wrods by seeknig the fsirt ltteer and the lsat leettr,
and tehn fnidnig whcih charatcers are insdie of tehm.
See! All the wrods hree wtih mroe tahn 3 leettrs are
all wirtten in a worng way! Do you niotice taht?

嘿嘿!其实刚才那段能力测试的话是瞎扯的,主要是让大家快速阅读,而不是认真阅读。有意思吧?
这个不是我瞎扯出来的,是一个著名大学的研究结果(好像是剑桥),原文我没工夫找,瞎造一段对付一下。不知道你读上述文字的时候是什么感受,反正我自己觉得比较震撼,也比较有意思。

确实,如果按照自动机理论,一个字一个字的去认真阅读,那么也还是很有可能能够理顺语法结构,搞清楚一句话的含义的(理论上如此吧,实际上还没有任何一个机器能做到真人般的感知能力)。但是如果每个字都认真读,并查找语法表,一来速度会慢,二来需要海量的空间去做这个事情。而人脑比较聪明,经过若干年的锻炼之后,已经自动的学会了放弃细节,比如读"cerroct"这个词的时候,找到前面是c开头,后面是t结尾,中间有eoc各一个,r两个,一查表就知道肯定是“正确”这个词而不管他正确与否——哦,不好意思,我又写错了,应该是correct!

嗯?这个跟我们这次的主题——字符串多模式精确匹配,有什么关系呢?
有啊!当然有啦。不过在我告诉大家这个关系之前,我们先来分析一下,字符串多模式精确匹配的效率问题是什么?写之前我先给大家说一下,我下面的说明也许不会很严谨,因为有时候太严谨了,就不好理解了。例如什么令X=Y……反正我最近为了这个事情找的一些资料,尽是这个,看着也觉得头晕。

所谓字符串多模式精确匹配是啥意思呢?字符串不多说了,实际上能用于搜索字符串的,也能搜索其他东西。多模式嘛:比如
string s="xxx";
string t="xx";
s.IndexOf(t);
这个是在一个字符串s中,找出另外一个字符串t所在的位置(或者说是否存在),这种叫做单模式,只有一个要被寻找的字符串t——唯一的一个搜索模式;如果说是
string s="xxx";
string[] t= new string[]{"x1", "x2", "x3"...};
s.Scan(t);
这种呢,就叫做多模式匹配了。因为我要在s里面找出一组t中任意一个所在的位置,或者说是看看我们的文章里面是否有脏字表里面的敏感词汇。

关于多模匹配问题,有很多已有的算法,我没有仔细的看,只看了一个可能是WM的算法,实际上可能还有什么grep/agrep等算法。不过需要提醒大家的是,还有不少的算法是讨论模糊匹配的,比如说容许其中有一个字不正确,那些算法就不是我这个主题要讨论的内容了。我要讨论的是精确搜索,即要找“地瓜”就找“地瓜”,不要“地鼠”。

多模式精确匹配很难吗?不难,很简单:我们只需要循环一下,先找s.IndexOf(t1),再找s.IndexOf(t2)……但是如果你果然这么做,效率就会很低了,因为你会需要扫描文本很多很多遍。可以想象,我们的目标是只要扫描整个文章一遍就能够找出这个文章里面都有哪些敏感词汇。不过,很明显该目标并不容易达成,但至少我们可以尽量接近“只扫描一次”这个目标。在进一步分析之前,建议先看另外一篇文章:
(重发).NET脏字过滤算法
这篇文章的算法(比如叫做XDMP算法)其扫描速度已经是比较快的了,并且其思路也比较好理解,我们在这个文章的基础上进行讨论会比较有意义。首先我们先整理一下这个算法的思路:
1、首先扫描文章里面的每一个字符,只有当某一个字符是脏字表中任意一个脏词的第一个字符(称为“起始符”),我们才试图看看接下来是否是脏字(触发检索)。
2、但是我们也不是毫无头绪的就开始循环脏字表的每一个词条:
2.1、我们往后检索一个字符,先看一下这个字符是否是脏字表里面的任意一个字符,如果不是,就表明不可能是脏字表中的任何一个条目,就可以退出了。
2.2、如果是,我们就取从第一个被检出字符到目前扫描到的字符之间的字符串,求哈希值,看看能否从哈希表中检出一个脏词。
如果检出了,那就大功告成,否则继续检索后面一个字符(重复2.1、2.2),直至找不到,或者超出脏字表条目最大的长度。
2.3、如果都找不到,或者超长,那么接下来就回到刚才的那个“起始符”后一个字符继续扫描(重复1、2),直至整个文章结束。

我这里先引入了三个重要概念:
1、扫描,指扫描文章,看看是否有需要和脏字表开始进行对比的情况;
2、检索,指已经发现可能存在情况了,在将文本和脏字表进行对比的过程;
3、起始符,指脏字表中条目中的第一个字符。

如果我们只要扫描,不需要检索就可以完成任务,那一定是最快的,不过目前我比较孤陋寡闻,没有找到这样的算法。
又或者,如果我们扫描一遍,而检索全中,那也很不错,很不幸,还是没见过。
很明显,扫描不应该多于1遍,否则肯定效率不可能高。那么检索就是算法的关键了!拆开来,提高检索质量有下列几个方式:
1、尽可能不触发检索;
2、如果确实需要触发检索了,那么每次触发检索的时候,要尽可能减少检索所需要遍历的字符数量;
3、每次对比脏字表的时候,减少运算量。

回过头分析上面的XDMP算法,是:
1、一次扫描;(很好,没啥好说的)
2、只要发现“起始符”就触发检索;
3、检索的时候,需要遍历的字符数是 1+2+3+...+n,这里的n是被命中的脏词的长度,或者最接近的长度;
4、每次检索,需要重复计算HashCode,不要忘了,计算HashCode,也是需要扫描字符串的,也就是又要遍历1+2+3+..+n个字符。

于是,我就有了一下问题:
1、难道每次遇到“起始符”了,就一定要触发检索吗?哎呀妈呀,这个也要检索(因为脏字表里面可能有MB)?!
2、难道每次触发检索,都非得要检索长度为1的,长度为2的,长度为3的……直到检索成功,或者出现非脏字表字符的时候吗?
3、难道每次检索,我们都需要把特定长度的待检文本截取出来吗?
4、难道每次检索,都需要从头开始计算哈希值吗?不能利用同一次触发检索后,上一次检索的哈希值,来减少本次计算的不必要运算量吗?

这四个问题,基本上是我想要解决的问题。其中前两个是一类问题,后两个是另一类问题。首先我们检查第一类问题:
好,我们回顾一下最开始的那篇英文,我们是否有点什么启发?对!我们触发检索的条件太简单了!
如果一个单词我们都没有看完呢,为什么要开始想这个事一个什么词呢?
另外,我们触发检索之后,也作了很多不必要的检索,因为当我们遇到"cao"这个字符的时候,很可能脏字表里面只有"caoT妈","caoN妈"这两种情况。如果有文章里面是"操作",脏字表里面正好又有"作LOVE",上述XDMP算法还是会乖乖的搜索两个字符的情况,而实际上又是没有必要的。

那么我们如何减少这些不必要的运算呢?首先,我们改一下,不要每次遇到“起始符”就触发检索。我们扫描到起始符怎么办?记录下来他的位置等信息,然后继续扫描下去。当我们遇到了“结束符”,也就是脏字表每一个词条中,最后一个字符中的任意一个时,我们才考虑是否要开始触发扫描。而扫描的时候呢,也不一定非得要脏字长度为1、2、3……的情况。因为之前记录了各种起始位置,我们可能只需要扫描1、3两种情况,或者5这种情况。

接下来是第二类问题:
上述算法里面,为了加快检索某串字符是否在脏字表里面,使用了哈希表。为了能够查表,所以就必须把这个哈希值给截取出来。可是这就引发了两个性能损耗点:
1、每一次截取,都要重新计算哈细值;
2、每一次都需要截取出一个字符串。
要避免这个问题,首先我们需要了解哈希表大致是怎么工作的:
哈希表实际上是根据当前的字符串内容,得出一个概率相对比较平均的散列值(这样哈希效表才不会容易出现冲突,即内容不同数值却一样),然后找出表中哈希值相等的第一个结果,然后对内容进行比较,如果相同就是找到了。否则就找下一个,直到没有相等哈希值的条目为止。

于是,我们可以这么来解决上述问题:
1、首先,我们造一个哈希值的计算方法,使得我们可以利用上一次的计算结果,接着计算下一个结果。
比如说,我们可以一个字节一个字节的进行异或(好处是方向性不敏感),或者也可以规定从字符串后方往前开始计算。
为什么规定从尾部进行计算?因为TTMP是结束符触发扫描的,比如说有文本:
ABCDE
如果E是结束符,那么就会检索ABCDE、BCDE、CDE、DE、E(还要看是否扫描到这些起始符)。如果我们是从后方往前计算,那就可以利用E的哈希值以及字符D,就可以计算DE的哈希值,而不需要再次对E字符进行计算了。
2、其次,我们可以构造这样的哈希表:
Dictionary<int, List<string>> hash;
其key就是我们刚才算出来的哈希值,根据算出来的哈希值,我们就可以得到一个该哈希值下的脏字列表,然后我们一个个的和待检文本进行字符对字符的比较。这里看起来很奇怪,为什么有了哈希值,还不能够通过哈希值直接找到对应的字符呢?
不要忘了,哈希值本来就是会冲突的,我现在只不过把冲突的情况单独取出来自行处理,这样实际上的检索次数并没有增加(放在哈希表里面,也必须一个个的进行字符对字符的比较,才能够确定Key值是否完全相等,而不是Key的哈希值相等但Key值不等)。而好处是,我们不需要非得取出一个字符串,好让哈希表去获取这个字符串的哈希值(需要从头遍历每一个字符)。
通过以上的措施,我们就可以让每一次对n长度待检文本触发检索,只需要最多遍历n个字符,就可以得到最多n次遍历的所有哈希值了,而原XDMP算法则需要遍历Sum(n)个字符。

当然了,上述这几个措施,其效果并不会非常明显,原因有三个:
1、通常我们的文本都是很正常的文本,顶多偶尔有点敏感词汇,因此并不会经常挑战前面说到的性能损耗点;
2、通常我们的脏字表数量不会极其巨大,起始符和结束符也应该集中在有限的那些字符里面,因此绝大多数时候首字符表,以及结束符表就已经能够极大地提高性能了;
3、即使我们真的需要触发检索了,我们的脏字通常长度会比较短,或者大多数会比较短,因此上面的改进所带来的性能提升会比较有限。比如说两个字符的情况下,原算法计算哈希值需要遍历3个字符,而TTMP则只需要遍历2个字符……汗
而如果是5个字符,原算法需要遍历15个字符,而TTMP则只需要遍历5个字符,开始有差距感了。
可惜的是,5个字符的敏感词毕竟还是比较少的,而一篇文章正好中这个5字敏感词的地方也是很少的。

目前我这个TTMP算法还没有优化,已经能够做到和XDMP算法消耗时间比为1:1.5-2.5,算是很不错了。当然了XingD后来又做了一个新的算法,测试速度很快,可是当时我测的时候还不稳定,有漏检的情况,因此暂时不做评论了。
至于我的TTMP算法,也还有不少可以挖掘潜力的地方,比如现在是前向检索的,以及预先计算哈希值的。如果改成后向检索,检索时计算哈希值,性能应该会更好一点。不过暂时不打算继续挖掘了,准备把他先放到实战里面应用再说。

呃,其实本文开头说的还是没错的,本文还是有点难度,而本人描述能力也不是特别好,不知道各位看官有没有看懂了?
源码?嘿嘿,私货,先收藏一段时间再说。当然了,如果你有一段源码,能够合法制造让制造者合法拥有的人民币真币,能够用VS2005编译通过,部署过程只需要点一下鼠标,运行过程无需看管,并且你愿意和我交换的话,我会考虑一下的……真实的情况是,我现在还要继续让算法更稳定,不能放出一个问题多多的代码出来吧?
私下说一下,这个程序比XDMS算法复杂不少,如果将来放出来,并且各位想要整明白的话,还需要自己花点心思。

哦,顺预先给某人回复一下:
KMP算法是单模匹配算法,BM据说也是单模式的算法。
WM算法是多模匹配的,我找了一个据说是WM的算法看了看:
http://blog.chinaunix.net/u/21158/showart_228430.html
不知道你说的是不是这个。
我发现思路其实和KMP/BM类似,主要是通过“跳跃”技术来提升性能的。但是该文里面也提到了这么一段话:
假设其中一个模式非常的短,长度仅为2,那我们移动的距离就不可能超过2,所以短模式会使算法的效率降低。

可问题就在于,一般脏字表的长度都是1到2个的居多,因此绝大多数跳跃的作用并不强。即使是5个字符,再TTMP里面,也很可能因为超出长度没有遇到“结束符”而不会触发扫描。而WM需要有一个Shift表,为了节省空间还需要压缩,这就意味着需要对每一个扫描单元进行一个压缩计算。综上所述,TTMP和WM进行搜索脏字任务的PK,谁胜谁负还不一定呢。顺便说一下,即使是WM,也不是一次扫描的,因为如果不跳跃的话,就会要多扫描一下某些字符。

TTMP效率描述:
Ot = Ot(文本长度) + Ot[ 起始符与结束符在出现在扫描窗口中的次数*Avg(同一个结束符中哈希值相等的词条数目) ]
=Ot(N) + Ot[f*Avg(h)]

Om = Om(字符类型表) + Om(结束符表) + Om{ 词条总数*[哈希表内部变量消耗内存+列表消耗内存数量+Avg(词条长度) ] }
=256K + 256K + Om{n * [12+12+Avg(k) ] }
=512K + Om[n*(c+k)]

来源:http://www.cnblogs.com/sumtec/archive/2008/02/01/1061742.html

JSP与PHP详细性能测试

分类:编程开发  来源:网络  时间:2011-11-24 22:28:59

前几天在CU看到有人比较PHP与JSP,.net,结果表明PHP比JSP,.net性能低下很多。本人认为即使有差距,也不应该有这么大,所以认真测试一下几者间的性能差距。由于很久没用.net了,所以,暂时没有测试.net。

本测试数据真实,但只做为参考。欢迎大家讨论。
除做比较外,也可供PHP,JSP程序员参考,以便优化自己的程序。

本测试由一直漂(ipaddr,bcomcn)原创,欢迎转载,并注明出处。问题反馈:admin.net(at)163.com

测试环境:
硬件:P4 2.4G,1G内存 软件:WindowsXP+Apache2.0.54+PHP4.4.0+Mysql4.1.14+Tomcat5.0.28
讨论地址:http://bbs.chinaunix.net/viewthread.php?tid=641073

一.算术运算

a.测试标准

循环N次,并做整型自加运算。

b.测试

测试代码:

测试类型 JSP int整型 JSP long整型 JSP long整型2 PHP PHP2
测试代码 int i = 0;
while (i < XXXX) {
      i++;
}
long l = 0;
while (l < XXXX) {
      l++;
}
long l = 0;
while (l < XXXX) {
      l = l + 1;
}
$i = 0;
while ($i < XXXX) {
      $i++;
}
$i = 0;
while ($i < XXXX) {
      $i = $i + 1;
}

测试结果(单位:毫秒)

测试结果说明:m-n表示主要波动范围介于m和n之间;n表示出现次数非常之多的数值或平均值,m(x,y)表示偶尔会出现x,y。以下相同。

XXXX取值 JSP int整型 JSPlong整型 JSPlong整型2 PHP PHP2
1000 0 0 0 0-1 0-1
10000 0 0 0 3-4 6-7
100000 0 0 0(16,32) 34-35 51-52
1000000 0(10) 0(16,32) 0(16,32) 348-368 527-534
10000000 0(13) 16-32 32-78 3547-3585 5239-5390
100000000 0(16) 266-281 265-281 35309-35486  
1000000000 0(16,743) 2625-2676 2203-3687    

c.结论

Java的算术运算,优化得很好,估计是直接的对应CPU的指令,数值再大,算术运算性能都很平稳。
需要注意的是,long的运算时间要比int的运算时间要长一些(毕竟是32位的系统),所以,在无需用到long时,尽量不要用long,而用int.

PHP是弱类型的变量,算术运算很不尽人意,估计不是直接对应机器码的算术运算。
PHP算术运算的过程猜测如下,在运算前需要检测变量是否是数值,并要将非数值转换成数值,比如,PHP可以做这样的运算:100+"zhoutang",结果等于100.正是因为是弱类型语言,加上运算前的检测和转换,所以才导致算术运算的性能低下。
PHP的单次运算时间比较稳定,大概每10000次算术加运算花费的时间约为3.5ms

不同的运算方法,也对性能有影响。

二.字符串运算

a.测试标准

字符串连接运算对比。

b.测试

测试代码:

测试类型 JSP PHP
测试代码 String str = "";
while (str.length() < XXXX) {
      str += "a";
}
$str = "";
while (strlen($str) < XXXX) {
      $str. = "a";
}

测试结果(单位:毫秒)

XXXX取值 JSP PHP
1000 0-16 1
10000 656-703 9-10
100000 105078-105235 95-103

c.结论

Java的字符串是用对象处理,很明显,在字符串的比较过程中,Java比PHP差很远。(因为字符串操作,很大部分要做连接,这里只比较连接运算,另外粗略比较了一下substring,两者的差别不是很大)

PHP的字符串运算,估计很多是直接调用C的字符串函数,所以效率会高很多。

在做WEB开发中,字符串的连接操作还是很频繁的(包括很多时候生成SQL字符串),所以,在算术运算和字符串运算两个方面,Java(JSP)优势不明显,与PHP各有所长。

三.数据库查询

a.测试标准

循环N次做数据库打开,查询,关闭操作。主要对JSP直接连数据库,JSP连接池连数据训,PHP直接连数据库,PHP持久连数据库做比较。

b.测试结果

测试代码:

测试类型 测试代码
JSP String dbUrl, dbUser, dbPwd, strSQL;
dbUrl = "jdbc:mysql://localhost:3306/zhoutang";
dbUser = "root";
dbPwd = "";
strSQL = "update tblUser set UserLC=UserLC+1 where UserID=100";

Class.forName("com.mysql.jdbc.Driver");
Connection con;
Statement stmt;

int i = 0;
while (i < XXX) {
      con = DriverManager.getConnection(dbUrl,dbUser,dbPwd);
      stmt = con.createStatement();
      stmt.executeUpdate(strSQL);
      stmt.close();
      con.close();
      stmt = null;
      con = null;
      i++;
}

JSP连接池 Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/mysql");

String strSQL = "update tblUser set UserLC=UserLC+1 where UserID=100";

Connection con;
Statement stmt;

int i = 0;
while (i < XXXX) {
      con = ds.getConnection();
      stmt = con.createStatement();
      stmt.executeUpdate(strSQL);
      stmt.close();
      con.close();
      stmt = null;
      con = null;
      i++;
}

PHP $dbHost = "localhost";
$dbUser = "root";
$dbPwd = "";
$dbName = "zhoutang";
$strSQL = "update tblUser set UserLC=UserLC+1 where UserID=100";

$i = 0;
while ($i < XXXX) {
      $link = mysql_connect($dbHost, $dbUser, $dbPwd) or die(¹Could not connect: ¹ . mysql_error());
      mysql_select_db($dbName);
      mysql_query($strSQL);
      mysql_close($link);
      $i++;
}

PHP持久连接 $dbHost = "localhost";
$dbUser = "root";
$dbPwd = "";
$dbName = "zhoutang";
$strSQL = "update tblUser set UserLC=UserLC+1 where UserID=100";

$i=0;
while ($i< XXXX) {
      $link = mysql_pconnect($dbHost, $dbUser, $dbPwd) or die(¹Could not connect: ¹ . mysql_error());
      mysql_select_db($dbName);
      mysql_query($strSQL);
      mysql_close($link);
      $i++;
}

测试结果(单位:毫秒)

XXXX取值 JSP JSP连接池 PHP PHP持久连接
50 437-600 31-50 219-232 34-37
100 890-1047 62-94 448-468 69-73
200 2141-2263 157-189 948-979 159-175
500 5078-5140 375 2118-2221 358-379

c.结论

普通连接,Java连Mysql的速度是要比PHP慢的一倍左右。Java使用连接池技术,性能提升非常明显。

PHP使用的持久连接(pconnect)性能即然相当于Java的连接池,结果实在让人不可思议,本来挺担心PHP连数据库的,因为没连接池可用,特意在网上找了一些资料,没发现PHP可用的连接池,相关提法都很少,很多PHP程序员甚至没听过这概念,这样的结果,确实让我也大吃一惊。不过,话说回来,pconnect的原理,和连接池差不多的,都是程序关闭连接,但PHP并不真正关闭,再次打开时,直接使用可用的连接。但是,PHP的实现确实比Java方便多了,只需加个字母,就轻易实现,Java则麻烦一些,我配置Tomcat的连接池都费了些时间,按官方文档,在tomcat5.0.28下没配置成功,在CSDN上面,也看到很多新手发出求救,很多配置不成功的,最后自己摸索出来了,配置方法可参考我的Blog。

如果将连接数据库和关闭数据库的操作,移到循环外面,刚PHP和JSP的执行时间都差不多,循环50次约16ms。可见,数据库操作中,打开连接是相当耗资源的,其它操作,与语言差别不大。JSP在连接数据库的时候,开销比PHP大很多。(这里特意将打开数据库操作放在循环体做比较)

四.文件操作

在WEB开发过程上,文件操作一般不可缺少,大多数WEB系统都会上传或对文件操作。

a.测试标准

综合测试各种文件操作,测试的过程是首先判断某文件是否存在,存在的话删除文件,再新建文件,再往文件里写一定长度的内容。整个过程循环N次。

b.测试结果

测试代码:

测试类型 测试代码
JSP String fileName = "jsp.txt";
String filePath = request.getRealPath("");
int i = 0;
int j = 0;
while (i < XXXX) {
      File f = new File(filePath,fileName); 
      if (f.exists()) { 
            f.delete();
      }
      f.createNewFile();
      FileWriter fw = new FileWriter(filePath + File.separator + fileName);
      j = 0;
      while (j < 2 * i) {
            fw.write(j + " ");
            j++;
      }
      fw.close();
      i++;
}
PHP $fileName = "./php.txt";
$i = 0;
while ($i < XXXX) {
      if (file_exists($fileName)) {
            unlink($fileName);
      }
      $handle = fopen($fileName, "x");
      $j = 0;
      while ($j < 2 * $i) {
            fwrite($handle,$j." ");
            $j++;
      }
      fclose($handle);
      $i++;
}

测试结果(单位:毫秒)

XXXX取值 JSP PHP
100 265-292(326,431) 346-367
500 1703-2065 3256-3474
1000 4062-4398 9316-9348

c.结论

这个测试结果有点意外,本以为PHP会大胜的项目,却让JSP遥遥领先,循环次数大的时候,PHP比JSP慢一倍。有点不可思议。

五.总结

总体来说,PHP与JSP在性能上,差别不了很远,各有优势。JSP虽是编译执行,但却要通过JVM,性能会有所下降。从功能上说,JSP的相对强大一些,主要是因为有Java的支撑,在一些很大型的企业中,用JSP有优势(主要是有Java支撑),但一般的企业或一般的应用,PHP完全可以应付。另外,PHP比JSP更容易上手。另外,个人说为,做同样的WEB系统,PHP相对JSP来说,复杂度可能会低一些(JSP所有的技术都用上的话,估计架构环境,系统设计都够麻烦的,而且,Java体系各种技术和产品比较开放和松散,文档相对来说有点杂乱,至少我认为Tomcat的文档做得没有Apache,PHP的好。)。

PHP小巧而灵活,JSP就显得宠大,而且,概念众多,个人认为Java体系有故意夸大技术复杂度的嫌疑。

此外,PHP还有Zend可用,本来想装上Zend再来测试一番的,这几天Zend的网站老是上不去。据有关测试表明,Zend能提升PHP的性能大约100%左右。也有说30-40%的,也有说600%的。估计是算术运算能提升个档次,其它操作,最多提升30-40%左右。

在整个测试过程中,每个取值我都会测多次,一般10s以下的运算,我至少测10次,10s以上的运算,至少测3次。PHP的测试结果都比较稳定,每次测出的结果差别不是很大,从统计学的角度来说,方差比较小。JSP相对来说,偶尔会出现一些值,偏离平均值比较远,而且,由于需要编译的原因,首次执行一般时间比较长(虽然从程序里显示的数值看不出首次执行的时间差距,但在程序开始执行前,编译需要点时间。编译后才开始执行,所以程序显示的结果看不出来。),所以,JSP的测试,没取首次运行的结果。

另外,在测试连接数据库的过程中,由于一时疏忽,忘了在循环体内i++,导致出现死循环。所以,也特意做了几个死循环测试。算术运算测试,JSP死循环时,浏览器点了停止按钮,tomcat仍继续执行,CPU一直是100%,只有在任务管理器里停了tomcat,才得以停止死循环;PHP算术运算死循环,由于php.ini里有设置程序执行的最长时间和最大内存,所以,死循环能够自动结束。数据库连接死循环,JSP在循环大概900多次后,出现异常,报错,提示无法连接;PHP循环1500次后,仍然没有结束,只好在任务管理器里结束apache进程(我的php.ini设置PHP最长执行时间为300秒)。

六.其它环境简单测试

以上数据只能做为参考,同样的程序,在其它配置的系统,我也做了简单的测试:

I.p4 2.4G,512M DDR,Windows server2000的工作机

(安装东西比较多,比较乱,运行一年多没重装,由于是工作机,所以操作系统对应用程序优化,而不是对后端服务优化;所测得的数据,比XP下测得的数据要大很多,比如PHP连接Mysql循环500次,大约需要16000ms。),粗略的测试的结果是:

算术运算和字符串运算:算术运算,JSP领先很多,字符串运算,PHP领先很多,和测试机的结果一致。

连接数据库:PHP与JSP连Mysql速度差距不大,PHP大概快20%左右,奇怪的是我用pconnect连与connect是一样的结果,未测试JSP的连接池。估计JSP用连接池会快很多。

文件操作:PHP的文件操作比JSP性能高出约30%!与测试机的结果有点相差比较大,PHP领先。

II.p4 2.66G,1G DDR,Linux服务器

算术运算和字符串运算:和其它环境测试结果一致,JSP在算术运算时领先,PHP在字符串运算时领先很多很多。

连接数据库:执行500次循环,PHP用connect连接,花费185ms,PHP使用pconnect连接,花费70ms;JSP未用连接池,花费2030ms。

文件操作:JSP领先很多,1000次循环,JSP花费1500ms左右,PHP花费7000ms左右。

III.总结

不管什么平台系统,测试结果表明,JSP和PHP在做WEB开发时,性能差距不大,只能说各有所长,JSP在数据库操作以及字符串操作方面不如PHP,而PHP在文件操作及算术运算是,不及JSP。

此外,同种语言,在不同的平台表现也不一样,根据我的测试结果表明,Linux下PHP,JSP的性能都要优于Windows的。

七.运行时间的获取

 

语言 如何获取运行时间
JSP

long timeStart = 0;
long timeEnd = 0;
timeStart = Calendar.getInstance().getTimeInMillis();

//中间代码

timeEnd = Calendar.getInstance().getTimeInMillis();
out.println("开始时间:" + timeStart + "毫秒<br>");
out.println("结束时间:" + timeEnd + "毫秒<br>");
out.println("花费时间:" + (timeEnd - timeStart) + "毫秒<br>");

 

PHP

$timeStart = 0;
$timeEnd = 0;
$timeStart = mictime();

//中间代码

$timeEnd = mictime();
echo "开始时间:".$timeStart."毫秒<br>";
echo "结束时间:".$timeEnd."毫秒<br>";
echo "花费时间:".($timeEnd - $timeStart)."毫秒<br>";

function mictime() {
      //由于PHP支持不支持long型,所以,只取了5位秒数,再加上毫秒。时间段比较,前面的可以忽略
      list($usec, $sec) = explode(" ", microtime());
      $sec = substr($sec, -5);
      $usec = ceil($usec * 1000);
      while (strlen($usec) < 3) {
            $usec="0".$usec;
      }
      return $sec.$usec;
}




来源 http://blog.163.com/zl_dream1106/blog/static/842860201091693457610/

如何防止代码腐烂问题

分类:编程开发  来源:网络  时间:2011-11-13 12:30:14

很多团队都有这个问题,一个项目的代码本来开始设计得好好的,一段时间以后,代码就会变得难以理解,难以维护,难以修改。为什么?我一直在思考这个问题。

我们先看一个人的情况。

1.程序员的成长

新手的代码

新手的代码没有经验,基本不考虑代码设计,代码规模稍稍大一点则自己就乱了。

如何防止代码腐烂

进阶者的代码

如何防止代码腐烂

小规模的时候

如何防止代码腐烂

大规模的时候

进阶者已经知道如何设计代码,懂得代码规则,但一般局限于一个模块。规模一大,模块间的调用就会比较混乱,难以维护。

有经验者的代码

有经验者的代码,模块内部代码整洁,模块之间层次清晰,有设计模式,有成熟的体系。可以保持长期的代码整洁。

那么一个团队里面会出现什么情况呢?似乎,我们只要让一堆有经验的人来开发,那么代码必然不会出什么问题。可惜,事实不是这样。

2.背景

代码风格的多样性

有这样的。

 

如何防止代码腐烂

也有这样的

如何防止代码腐烂

放眼一看,会发现不同的代码风格,不同的设计思想,不同的设计理念。每个程序员都有自己的代码个性。

如何防止代码腐烂

团队层次的差异

一个团队内部有新人,有熟手,有牛人。一个设计好的架构可能会变坏。

如何防止代码腐烂

3.原因

风格的融合

当程序员A和程序员B在一起的时候,会有如下变化

如何防止代码腐烂

原本整洁的代码变得不整洁了。

进度的压力

进度导致了“飞线”的产生,未经设计的代码在时间的借口下产生了。

多个人修改一个模块

如何防止代码腐烂

4.本质

所有代码腐烂问题的本质是沟通问题。其表现又都可以统一为修改别人的代码。

当一个程序员在没有沟通的情况下,修改另一个程序员的模块的代码的时候,他可能不理解此模块的设计思路,代码结构,逻辑结构,于是按自己的想法去修改,虽然看起来解决了眼前的问题。但是留下了一个不稳定因素。此因素可以通过重构来解决。但是,大家都非常的“忙”,谁也没有空时间去 Review 代码,去沟通我改了你的哪里的代码。所以不稳定的因素越来越多,导致了代码的腐烂。

最快腐烂的代码,一定是很多人在修改的代码,相反,长期由一个人来维护的代码,就不会那么容易腐烂。因为一个人不存在沟通的问题,他修改代码的时候,明确的知道自己应该怎样去修改,怎样让代码更整洁。

5.解决

就一个办法,多沟通。

当你工作的时候需要修改别人的代码的时候,应该先找这个人沟通。说清楚需要改动的逻辑,然后尽量让他来修改。这样可以保证一块代码是由一个人维护,这样成本最少。

如果此人真的太忙,没有时间,那么你必须说明你的计划,让他做一个建议,最好能让他给你讲讲此模块的设计思路,代码设计,逻辑设计,现在的问题,以后的计划。保证你修改的代码都是合理的。

最理想的状态就是整个团队的思想是高度统一的,N个人可以像一个人那样去工作。这个需要团队长期的磨合。

你可以会想到,我们制定一个规范不就可以了么?纸面上的规范通常是不起作用的,成功团队的规范是在整个团队达到一个很高的水平以后总结的经验。与其说执行规范,不如说是学习经验。MFC的代码像是由一个人写出来的,Office所有产品都像是一个人做出来的。这就是高度的统一。我们把微软的规范搬过来,不一定就有效果。

代码的腐烂都是由于没有深入理解的情况下修改别人的代码导致的。

总结一下:

  • 解决的方法就是任何修改之前确保经过深入的沟通。
  • 简单的规则是一个模块仅允许一个人维护。
  • 理想的状态是整个团队思想高度统一。

文章出自:djt.open

程序员不要想着一辈子靠技术混饭吃

分类:编程开发  来源:网络  时间:2011-11-5 13:11:18

我现在是自己做,但我此前有多年在从事软件开发工作,当回过头来想一想自己,觉得特别想对那些初学JAVA/DOT .NET技术的朋友说点心里话,希望你们能从我们的体会中,多少受点启发(也许我说的不好,你不赞同但看在我真心的份上别扔砖头啊)。

一、在中国你千万不要因为学习技术就可以换来稳定的生活和高的薪水待遇,你千万更不要认为哪些从事市场开发,跑腿的人,没有前途。

不知道你是不是知道,咱们中国有相当大的一部分软件公司,他们的软件开发团队都小的可怜,甚至只有1-3个人,连一个项目小组都算不上,而这样的团队却要承担一个软件公司所有的软件开发任务,在软件上线和开发的关键阶段需要团队的成员没日没夜的加班,还需要为测试出的BUG和不能按时提交的软件模块功能而心怀忐忑,有的时候如果你不幸加入现场开发的团队你则需要背井离乡告别你的女友,进行封闭开发,你平时除了编码之外就是吃饭和睡觉(有钱的公司甚至请个保姆为你做饭,以让你节省出更多的时间来投入到工作中,让你一直在那种累了就休息,不累就立即工作的状态). 更可怕的是,会让你接触的人际关系非常单一,除了有限的技术人员之外你几乎见不到做其他行业工作和职位的人,你的朋友圈子小且单一,甚至破坏你原有的爱情(想象一下,你在外地做现场开发2个月以上,却从没跟女友见过一面的话,你的女友是不是会对你呲牙裂嘴)。

也许你拿到了所谓的白领的工资,但你却从此失去享受生活的自由,如果你想做技术人员尤其是开发人员,我想你很快就会理解,你多么想在一个地方长期待一段时间,认识一些朋友,多一些生活时间的愿望。

比之于我们的生活和人际关系及工作,那些从事售前和市场开发的朋友,却有比我们多的多的工作之外的时间,甚至他们工作的时间有的时候是和生活的时间是可以兼顾的,他们可以通过市场开发,认识各个行业的人士,可以认识各种各样的朋友,他们比我们坦率说更有发财和发展的机会,只要他们跟我们一样勤奋。(有一种勤奋的普通人,如果给他换个地方,他马上会成为一个勤奋且出众的人。)

二、在学习技术的时候千万不要认为如果做到技术最强,就可以成为100%受尊重的人。

有一次一个人在面试项目经理的时候说了这么一段话:我只用最听话的人,按照我的要求做只要是听话就要,如果不听话不管他技术再好也不要。随后这个人得到了试用机会,如果没意外的话,他一定会是下一个项目经理的继任者。

朋友们你知道吗?不管你技术有多强,你也不可能自由的腾出时间象别人那样研究一下LINUX源码,甚至写一个LINUX样的杰作来表现你的才能。你需要做的就是按照要求写代码,写代码的含义就是都规定好,你按照规定写,你很快就会发现你昨天写的代码,跟今天写的代码有很多类似,等你写过一段时间的代码,你将领略:复制,拷贝,粘贴那样的技术对你来说是何等重要。(如果你没有做过1年以上的真正意义上的开发不要反驳我)。

如果你幸运的能够听到市场人员的谈话,或是领导们的谈话,你会隐约觉得他们都在把技术人员当作编码的机器来看,你的价值并没有你想象的那么重要。而在你所在的团队内部,你可能正在为一个技术问题的讨论再跟同事搞内耗,因为他不服你,你也不服他,你们都认为自己的对,其实你们两个都对,而争论的目的就是为了在关键场合证明一下自己比对方技术好,比对方强。(在一个项目开发中,没有人愿意长期听别人的,总想换个位置领导别人。)

三、你更不要认为,如果我技术够好,我就自己创业,自己有创业的资本,因为自己是搞技术的。

如果你那样认为,真的是大错特错了,你可以做个调查在非技术人群中,没有几个人知道C#与JAVA的,更谈不上来欣赏你的技术是好还是不好。一句话,技术仅仅是一个工具,善于运用这个工具为别人干活的人,却往往不太擅长用这个工具来为自己创业,因为这是两个概念,训练的技能也是完全不同的。

创业最开始的时候,你的人际关系,你处理人际关系的能力,你对社会潜规则的认识,还有你明白不明白别人的心,你会不会说让人喜欢的话,还有你对自己所提供的服务的策划和推销等等,也许有一万,一百万个值得我们重视的问题,但你会发现技术却很少有可能包含在这一万或一百万之内,如果你创业到了一个快成功的阶段,你会这样告诉自己:我干吗要亲自做技术,我聘一个人不就行了,这时候你才真正会理解技术的作用,和你以前做技术人员的作用。

小结

基于上面的讨论,我奉劝那些学习技术的朋友,千万不要拿科举考试样的心态去学习技术,对技术的学习几近的痴迷,想掌握所有所有的技术,以让自己成为技术领域的权威和专家,以在必要的时候或是心里不畅快的时候到网上对着菜鸟说自己是前辈。

技术仅仅是一个工具,是你在人生一个阶段生存的工具,你可以一辈子喜欢他,但最好不要一辈子靠它生存。

掌握技术的唯一目的就是拿它找工作(如果你不想把技术当作你第二生命的话),就是干活。所以你在学习的时候千万不要去做那些所谓的技术习题或是研究那些帽泡算法,最大数算法了,什么叫干活?

就是做一个东西让别人用,别人用了,可以提高他们的工作效率,想象吧,你做1万道技术习题有什么用?只会让人觉得酸腐,还是在学习的时候,多培养些自己务实的态度吧,比如研究一下当地市场目前有哪些软件公司用人,自己离他们的要求到底有多远,自己具体应该怎么做才可以达到他们的要求。等你分析完这些,你就会发现,找工作成功,技术的贡献率其实并没有你原来想象的那么高。

不管你是学习技术为了找工作还是创业,你都要对技术本身有个清醒的 认识,在中国不会出现BILL GATES,因为,中国目前还不是十分的尊重技术人才,还仅仅的停留在把软件技术人才当作人才机器来用的尴尬境地。(如果你不理解,一种可能是你目前仅仅从事过技术工作,你的朋友圈子里技术类的朋友占了大多数,一种可能是你还没有工作,但喜欢读比尔盖茨的传记)。

文章来源:blog.csdn.net/chen__jinfei/article/details/5178144