手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆
浏览模式: 标准 | 列表2025年07月的文章

nihilogic:一些JS的图片特效,几乎支持所有浏览器

不知道大家是否还记得08年的5月12日,那一天,所有的网页都是灰色的,纪念那逝去的生命。
对于网页开发者来说,为了让用户看到灰色的页面,大多数人都采取了直接修改CSS的方式,使得image的alpha通道为gray,然而,这个方法是不支持FF的。N多办法都不支持。
这是一个JS的特效。它有N多处理图片的方法,可以按需加载,网址是:http://www.nihilogic.dk/labs/imagefx/,可以看到一些效果。

根据网上提供的JS,下载下来后,直接src一下就能用了。然而在测试的时候只有IE有效,firefox下是无效的。打开firebug,发现在执行后报错:
大小: 10.54 K
尺寸: 490 x 104
浏览: 1512 次
点击打开新窗口浏览全图

开始的时候一直没有细看,发现上面写的是"code:"也没有什么代码。就利用firebug的watch功能监视。然而死活找不到问题。
代码与网络上是一模一样,问题在哪里呢?
再仔细看出错代码,发现,前两个单词居然是:Security error,难道是安全问题?FF对本地代码的执行进行了限制?
立马把代码拷到虚拟机下运行,果然一切正常。
唉。。。
原来我为了这样一个问题折腾了将近一周。不仔细看出错信息导致的呀。。

顺便贴一个开心网的BUG图片:
大小: 8.71 K
尺寸: 160 x 140
浏览: 1543 次
点击打开新窗口浏览全图

.NET调PHP Web Service的典型例子

一直都是关注着用PHP调用其他的soap方式的web service。偶尔看到一篇用php做web service的。有点感觉新鲜,备个案。哈哈

仅做了解。对于php做webservice,我还不知道性能如何呢。现在andot等人又在推出所谓性能超过phprpc的hprose,也不知道何时能够出来。。。

既然是用PHP做webservice,那么在看过phprpc之后,其实应该感觉用phprpc发布这些东西会更方便吧?不知道为什么不用phprpc或者hprose。。。。

纯记录,作者来自博客园的三聪,地址为:http://www.cnblogs.com/gateluck/archive/2009/08/10/php_web_service.html

原文如下:

最近一个项目由"WinForm直接访问DB2"移植到"WinForm通过PHP Web Service来访问DB2”。
(优点是php可以架在Linux上,而Linux是免费的)     
这个命题的难点不是访问DB2,而是.NET调用PHP的Web Service。对于我这个长期作.NET,之前一直以为只有.NET才可以做Web Service……的人来说,真是有点强“聪”所难了。
      但是问题还是要解决的,期限就摆在眼前呢。经过一番调查,终于有了眉目,现在分享给大家。
      
      首先要说明的,PHP服务器需要至少需要两个文件——一个WSDL文件和一个PHP文件。WSDL文件是一种机读的XML文件,用于描述WebService提供的服务和调用方法(对于.NET则可以自动生成调用代码,十分好用),php文件就是真正实现的WEB服务了。
      1)PHP服务器端代码
          1-1)TestWebService.php代码

[代码]

          1-2)TestWebService.wsdl代码
[代码]
      WSDL的代码比较长,当方法很多时,手敲代码是不太可能的。有一个巧的办法,就是也用.NET实现一个不含真正方法体的Web Serivce,然后通过http://***/TestWebService.asmx?wsdl的方法生成wsdl代码文件。
         关于WSDL文件,我要说明特别说明两点:
        (1)soap:address结点是声明WebService的地址,在部署时要改成相应地址;
        (2)一维数组的声明类型为ArrayOfType,字符串数组为ArrayOfString。如果Type不是简单类型,则Type需要另外声明。

      2).NET客户端代码
           先要添加Web引用,地址为WSDL文件的Http地址。
           调用代码(C#)
[代码]


总结: (一)PHP是一种弱类型语言,检查错误比较困难。array类型也与一般理解的数组不同,它也有类似Hashtable的用法。
          (二)PHP Web Service方法的传入参数、返回值都至多有一个,因为真正调用时的参数和返回值,都是包装到一个对象中传送的。
          (三)PHP Web Service也支持自定义类型和自定义类型数组等复杂类型,但不支持多组数组。
          (四)若返回值需要是多张二维表时,我浅薄的以为,可以传化一组字符串数组传送,格式为
                        [表1行数],[表1列数],[表1列名1],[表1列名2],……[表1列名N],[表1中按行列存放的值]
                        [表2行数],[表2列数],[表2列名1],[表2列名2],……[表2列名N],[表2中按行列存放的值]
                        ……
                        [表M行数],[表M列数],[表M列名1],[表M列名2],……[表M列名N],[表2中按行列存放的值]

                   按顺序将上面[]中的内容串成字符串数组,效率还不错,我测试10000行240列的数据,我有现成编解代码,有兴趣的可以向我索取.

jQuery is DSL (Part 1 - DSL)

DSL,不算新名词了。转至博客园,看名称,估计还有后续文章,先转载,相当于mark一下,哈哈。这样就不会以后找不到链接了。

作者是博客园的cat chen,原文地址,http://www.cnblogs.com/cathsfz/archive/2009/08/10/1543266.html
内容如下:

jQuery刚刚出来的时候,我没有太多关注它,觉得这不过是Yet Another JavaScript Library。早期的jQuery专注于DOM节点的筛选与操作,不提供众多的基础类扩展,更不提供UI组件,因此体积能够做到很小。然而,我实在看不 出它和我熟悉的Prototype比有什么明显的优势——jQuery能做的各项独立的操作,Prototype都能做。

后来用jQuery的人越来越多,并且大家都爱用它的链式方法调用,甚至还把这种写法推广到其它语言中去。例如ASP.NET MVP Omar AL Zabir就把他的服务器端C#组件设计为支持链式方法调用的。这时候我才开始关注jQuery,并且逐渐喜欢上了链式方法调用的写法,也在我自己的JavaScript组件中实现类似的API(参考AsyncOverload)。最后,我突然明白到,这其实就是一种Internal DSL嘛!

在这篇文章里,我准备先讨论Internal DSL,在下一篇文章里面再解释为什么jQuery是Internal DSL。现在我们就从最根本的问题开始吧——

什么是Internal DSL?

DSL是指Domain Specific Language,也就是用于描述和解决特定领域问题的语言。例如说,我们有专门描述字符串特征的正则表达式,有专门描述数据库查询的SQL,有专门描述 XML结构的DTD和XSD,甚至有专门描述XML变换的XSLT,这些都是DSL。

当然,并非我们关注的领域都有现成的DSL,这时候我们有三个选择:

  1. 使用通用语言描述该领域的问题(non-DSL)
  2. 发明一门全新的语言描述该领域的问题(External DSL
  3. 在一门现成语言内实现针对领域问题的描述(Internal DSL

例如说,我们现在要描述一个很简单的金融领域问题,“我在花旗银行存款$200”这样一句话对应的三种法写法可能是:(假设已经存在I和CitiBank两个实体实例)

  1. I.DepositTo(new USD(200), CitiBank); /* C# */
  2. I deposit 200USD to CitiBank /* E-DSL */
  3. I.deposit(200.USD()).to(CitiBank); /* I-DSL */

第1种做法的成本最低,你只需要有OO的思想就可以了,你总能把实体类设计出来,但可能和人类描述此领域问题的思维方式有一定偏差(为什么USD可以new?为什么不是deposit [something] to [somewhere]?)。

第2种做法的成本最高,你需要写一个全新的解释器,至少是写一组全新的规则,然后让YACC这类工具帮你生成一个解释器,但这样出来的语法最贴近人类思维方式,甚至就如同自然语言一样流畅。

第3种做法术语上述两者的折中方案,如果语法不太复杂可以使用Builder模式实现语法分析,写出来的语法相当贴近自然语言,但还是有学习门槛。由于脚本语言有相当的灵活性,所以现在很多人倾向于选择在脚本语言内实现Internal DSL。

如何构造Internal DSL?

常见的两种Internal DSL实现方法是Method ChainingFunction Sequence。如果我们需要描述一台机器的硬件组成,两种实现方式的代码分别如下:

/* Method Chaining */
computer()
  .processor()
    .cores(2)
    .i386()
  .disk()
    .size(150)
  .disk()
    .size(75)
    .speed(7200)
    .sata()
  .end();

/* Function Sequence */
computer();
  processor();
    cores(2);
    processorType(i386);
  disk();
    diskSize(150);
  disk();
    diskSize(75);
    diskSpeed(7200);
    diskInterface(SATA);

无论是哪一种写法,中间都必须写一个分析器层。就如同语法分析器需要使用状态机一样,Internal DSL的实现也必须内置一个状态机,以记录当前执行到什么状态了,并且接下来可以转移到哪些有效状态。

由于这不是一篇专门讲语法分析器和状态机实现的文章,所以我们把关注点保持在API层面就可以了,不深入讨论其实现细节和成本。我们知道链式方法调用能够实现Internal DSL就够了,至于jQuery是如何利用好这一点的,我们在下一篇文章里再作讨论。

小结

在这篇文章里,我们了解了Internal DSL与External DSL之间的区别,同时还了解到实现Internal DSL的具体方式,这为我们接下来讨论jQuery的Internal DSL式接口做好了铺垫。在下一篇文章里,我们将深入地来看看为什么jQuery的接口要如此设计,它能为用户带来了怎样的便利,同时它自身的实现上又有 什么优势。

如果你不希望错过下一篇文章,你可以考虑订阅我的博客:

JavaScript中的memoization(memoizing) 技术介绍.

膘叔写在前面的话,关于memoization好象在jquery里被应用到了。但应该是1.2.6的事情了,最初的ajax是没有缓存的。后来增加了Data缓存。(记不清了,希望没有记错)
对于memoization的记忆大约是在07年,好象有一个red开头的国内的某个网站,把菲伯拉契数列用memoization实现了一遍,当时记得的测试结果,一个是3000多ms,一个是1000多ms,这已经不是一个量级的了。
于是后来,我看了一下,根据这个原理,写了一个gdata的cache,缓存一些我经常使用的函数和数据。现在当然是不用了。呵呵

以下是原文内容,它来自playgoogle的http://www.cssrain.cn/default.asp?id=1392:

最近在读《JavaScript 设计模式》一书,其中工厂模式中提到了memoizing技术,今天仔细整理了一下memoization 相关的资料,与大家共享。

memoization 一词是Donald Michie 根据拉丁语memorandum杜撰的一个词。相应的动词、过去分词、ing形式有memoiz、memoized、memoizing.

Memoization 是 一种将函数返回值缓存起来的方法,Memoization 原理非常简单,就是把函数的每次执行结果都放入一个键值对(数组也可以,视情况而定)中,在接下来的执行中,在键值对中查找是否已经有相应执行过的值,如 果有,直接返回该值,没有才 真正执行函数体的求值部分。很明显,找值,尤其是在键值对中找值,比执行函数快多了。现代 JavaScript 的开发也已经大量使用这种技术。

  •  一个简单的使用memoization的例子

我们知道,在不同的浏览器中,xmlHttpRequest对象的具体实现都不同。需要判断何种浏览器以执行具体的方法。这里就有一个使用memoization来实现的例子。

  1. function createXHRObject = function(){
  2.     //先把三个匿名函数缓存起来。
  3.     var methods = [
  4.         function(){return new XMLHttpRequest();},
  5.         function(){return new ActiveXObject("Msxml2.XMLHTTP");},
  6.         function(){return new ActiveXObject("Microsoft.XMLHTTP");}
  7.     ];
  8.     for(var i=0,len=methods.length;i<len;i++){
  9.         try{//这里用try catch来代替了条件判断,通常我不赞成这种写法
  10.             methods[i]();
  11.         }
  12.         catch(e){
  13.             continue;//如果报异常,则执行下一次循环
  14.         }
  15.         // 把createXHRObject 与能正常执行的匿名函数对应起来,再调用createXHRObject不用再检测浏览器了
  16.         createXHRObject = method[i];
  17.         return method[i];
  18.     }
  19. }

以上是一个简单的例子,第一次执 行createXHRObject()的时候,会循环判断methods 中的方法,获取一个能正确执行的,并将createXHRObject的引用指向这个方法。以后再使用这个方法的时候,不用去判断,直接自动获取正确的方 法。这省去了频繁的ajax调用中浏览器的检测。

当然,这个方法看上去效率的提升不是特别明显,我之所以写上来,是因为能比较清晰的理解memoization是如何实现的。在递归调用的时候,memoization的威力才能更好的显现。

一个递归的例子

  1. function fib(n) {
  2. if (n < 2) {
  3. return n;
  4. }
  5. return fib(n - 1) + fib(n - 2);
  6. }

 这是一个经典的斐波纳契序列,fib(20) 会把fib这个方法执行21891次,如果是fib(40),这会执行331160281次。

再看看如何使用memoization来实现,

  1.  var iterMemoFib = (function() {
  2.     var cache = [1, 1];
  3.     var fib = function(n) {
  4.         if (n >= cache.length) {
  5.             //将一个递归转换成了一个
  6.             for (var i = cache.length; i <= n; i++) {
  7.                 cache[i] = cache[i - 2] + cache[i - 1];
  8.             }
  9.         }
  10.         return cache[n-1];
  11.     }
  12.     return fib;
  13. })();

将Function的原型扩展memoize unmemoize 方法,这样你可以对任何函数实现memoize和解除memoize,当然,这个方法要慎,对一些不是频繁执行的函数,没必要缓存:

  1. Function.prototype.memoize = function() {
  2.     var pad  = {};
  3.     var self = this;
  4.     var obj  = arguments.length > 0 ? arguments[i] : null;
  5.  
  6.     var memoizedFn = function() {
  7.         // 把参数作为数组保存,作为键,把函数执行的结果作为值缓存起来
  8.         var args = [];
  9.         for (var i = 0; i < arguments.length; i++) {
  10.             args[i] = arguments[i];
  11.         }
  12.         if (!(args in pad)) {
  13.             pad[args] = self.apply(obj, arguments);
  14.         }
  15.         return pad[args];
  16.     }
  17.     memoizedFn.unmemoize = function() {
  18.         return self;
  19.     }
  20.     return memoizedFn;
  21. }
  22. Function.prototype.unmemoize = function() {
  23.     alert("Attempt to unmemoize an unmemoized function.");
  24.     return null;
  25. }
  26.  

使用方法:

fib.memoize();

参考文档:

  1. Memoizing functions in JavaScript
  2. JavaScript Memoization
  3. 提升JS性能:将递归转换为迭代
  4. MemoizationFrom Wikipedia, the free encyclopedia

项目过程中的教训总结

taobaoQA的葵儿之作,任何一个项目都会有总结,善于总结才能抓住事物的本质,否则永远浑浑噩噩的。当然,在不同的职位上,所做出的总结也会不一样,但总有可以借鉴的地方。了解团队中其他人员的问题,结合自己的问题,相信,取精华去糟粕,总可以得到一个相对来说比较适合的方案,给下次开发打下良好基础。

原文如下:

一、项目中如何正确投入测试资源?
         五彩石之后,我参与收费线,一度进入了修整期,主要工作是日常。前一阵子有个比较大的项目成立,但是由于人员不够,便决定安排日常与项目兼顾。当时我凭以 往经验认为,在项目前期阶段,我们是可以做到将两者兼顾的。但事实是,那段期间并没有按我的计划进行,由于种种原因,也可能是我的时间管理出了差错,我们 把多数时间投入到了日常,剧减了前期去理解项目需求的时间。而这一决定直接导致了在UC评审时没能很好的明确把控住,致使现阶段我们的测试成员还在为确认 项目中某些功能需求而犯愁。

        当这个风险暴露出来后,我曾反思:日常与项目兼顾,以前我可以,为什么现在做不到?是业务复杂度的问题!是时间管理的问题!是团队 合作的问题……原因可能还有很多,而我作为项目的测试负责人,前期没将这些风险完全评估出来。即使有一万个理由,也还是一个不称职的测试负责人。

总结:在项目启动时,最好能将资源完整投入,特别是业务比较复杂的项目。若确实出现资源不足,应该及时且坚决地反馈出来。

二、对UC评审的把控。
        对UC质量的把控,本该是开发人员的事。但UC写出来,看得最多的则是测试人员。所以测试人员对UC的质量是最关心的。那么从测试的角 度,什么样的UC才是可以通过评审的呢?我们现在的流程中还没有完全的标准,这就需要测试人员靠前期对需求的理解来把控。要是前期投入时间不够,自己的工 作没做足,在评审时找不出有效的问题。或是由于项目进度,虽然评审出问题,但之后马上进入下个阶段,那么将会导致后期过程中问题多、反复问,此时开发修复 完善的积极性又不高。最终致使测试理解需求准备阶段进展较累。这也是前一个问题带来的直接后果。

总结:虽然我们的流程,对特殊的项目可以适当灵活运用,但无论是什么项目,UC对测试人员的指导参考价值是第一位的。这回的教训再次告诉我,在UC评审阶段一定要把握好这个度,那么前期一定要有足够的时间去做准备。

三、项目中的沟通、协调。
          一个项目比较大,投入的开发、测试资源肯定也就增多。这期间,成员中出现了沟通上的问题,也曾为之愤愤过,也曾努力协调过……

总结:在测试团队中收集上来的问题,理应站在测试者的角度考虑,但对这类问题也要学会过滤整理。我们每个人的性 格不一样,看待问题的态度也不同,作为测试负责人,要综合平时对队友的了解,具体对待。项目组是一个整体,我们的目标是一致的。而且从产品线的角度,大家 将是长期合作的伙伴。虽然我们对事不对人,但可以寻找更好的沟通方式,不该因小问题上大和气。

        我们的项目业务比较复杂,繁多,所以周期比较长,现在发现了,还可以从某些方面做些弥补措施。但对多数项目来说还是短期的,可能问题发现了要到下个项目中才有机会去弥补。

        本来想项目结束后再来好好总结的,不过现在这些教训等到项目结束后,感觉可能就不太一样了,所以想先写出来,以督促自己,也供大家借鉴。