手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 免费部署 N8N 的 Zeabur 注册 | 登陆
浏览模式: 标准 | 列表分类:PHP

HTML重构

HTML重构,以前是一个新鲜的东西,我也没有理解,博客园上有人在介绍,还写了三篇。。。

我这里只简单的复制点东西,还是以链接为重吧。(战略篇全文如下)

Refactoring HTML: Improving the Design of Existing Web Applications》是一本精彩的HTML重构指南,作者给出了HTML重构的实践路线和方法。本文是《Refactoring HTML》的读书笔记,按照我的理解将全书的分为:战略篇,战术篇,工具篇。

本文是战略篇:全局方略的角度介绍重构的内涵,原因,时机,目标

嗯哼,我们开始:

 

         进行重构就像打一场仗,而战争的发起是要慎重考虑的,《孙子兵法》里面讲“兵者,国之大事,死生之地,存亡之道,不可不察也。”所以动手重构之前首先要回答下面几个问题:

  • 什么是重构?
  • 为什么进行HTML重构?
  • 什么时候进行HTML重构?
  • HTML重构的目标是什么?
  • 面对质疑:还要重构么?

 

什么是重构 Refactoring?

        本书侧重实战,没有《UML Distilled》那样高屋建瓴的抽象,即使有抽象,抽象层面牵扯的细节过多(这一点在后续的阅读中也可以发现)。这一部分内容我援引了《Refactoring: Improving the Design of Existing Code》对重构的定义:

Refactoring (noun): a change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior.

Refactor (verb): to restructure software by applying a series of refactorings without changing its observable behavior.

 

为什么进行HTML重构?

抽象地讲,HTML重构的可以让代码更能适应变化,应对系统和领域需求为新功能的开发提供更优秀的基础。

具体地讲,HTML重构可以:

  • 让代码更具有可读性,更容易理解
  • 重构过程中往往有意外的收获:发现隐藏的系统Bug
  • 增强页面可用性, 关注点从设计者开发者转移到使用者
  • 缩短提高页面的呈现时间(Slow pages -Rendering Times)
  • 解决页面浏览器不兼容问题
  • 搜索引擎优化Search Engine Optimization

 

进行HTML重构的时机?

  • 每一次进行重新设计之前;新功能将构建在一个更稳固的基础之上
  • Refactor When You Need to Fix a Bug
  • Refactor As You Do a Code Review
  • 一个原则:勿以善小而不为;重构的过程往往是断断续续的,很少有一个连续的时间给我们进行重构。所以我们只要有机会进行重构,就动手去做吧

 

HTML重构的目标(What  Refactor To ?

  • XHTML
    理由:XHTML更加严格,浏览器不再解析乱作一团的标签而是格式规范的页内容,这时负担从浏览器转移到页面开发者。内容聚合,搜索引擎优化,样式表都可以更好的应用基础。开发者能够更容易调试和解决问题,因为问题更容易定位了。XHTML不能完全解决浏览器兼容问题,但是它能够消除大部分的浏览器不兼容问题已经居功甚伟。主流HTML编辑器都提供对XHTML的支持。XHTML是未来Web应用提供坚实的基础,如:MathXML MusicXML SVG
  •  CSS

理由:将展现层从内容中分离出来。为不同的阅读者提供高可读性。减少代码重复,节省带宽。

  • REST

REST(Representational State Transfer表述性状态转移)是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。REST提出了一些设计概念和准则:

1.网络上的所有事物都被抽象为资源(resource);

2.每个资源对应一个唯一的资源标识(resource identifier);

3.通过通用的连接器接口(generic connector interface)对资源进行操作;

4.对资源的各种操作不会改变资源标识;

5.所有的操作都是无状态的(stateless)。

 

REST之所以能够提高系统的可伸缩性,是因为它强制所有操作都是stateless的,这样就没有context的约束,如果要做分布式、做集群,就不需要考虑context的问题了。同时,它令系统可以有效地使用poolREST对性能的另一个提升来自其对clientserver任务的分配:server只负责提供resource以及操作resource的服务,而client要根据resource中的datarepresentation自己做render。这就减少了服务器的开销。

 

重构的目标不是金科玉律,你没有必要逐一进行实践。你可以按照XHTML->CSS-->Rest的顺序按部就班步步为营,也可以根据实际情况调整重构目标和计划。但是只要你做了,你就可以从重构过程中得到好处。

 

面对质疑:还要重构么?

重构的本质决定了它不是生产性的,重构的完成并没有新功能的产生。所以重构往往面临来自各方面的质疑:

  • 重构就是在浪费时间,我们还是开发新功能吧

 

面对质疑我们给出这样的答案:

  • HTML重构从长远来看为后续开发提供了一个良好的基础,实际上是节省了时间。因为系统更容易添加新功能,更容易维护。重构的过程能让开发者对以前的工作有一个思考,对新人是一个熟悉系统的机会。
  • HTML重构本身并不会占用太多的时间,因为我们有很多自动化的工具可用。
  • HTML重构不需要一个连续的时间,断断续续的时间未尝不可,对于开发者来说,进行重构就像日行一善。

 

HTML重构:战略篇


HTML重构:战术篇

 

HTML重构:工具篇

Tags: html, 重构

免费webService

这个东西,我实在不知道放在哪个分类了。。但因为我是用PHP进行开发的,因此我还是将它归为PHP分类

昨天在Yhustc的博客上看城管操作手册,结果顺便看到了这个免费的webservice列表

yhustc的博客功能越来越强大了,支持直接的ID的文章,现了也支持这种以英文名为路径的文章了,等再强一点,我也考虑换成yblog,哈哈,不过,要等他写转sablog的程序(实在是2.0到现在都没有出来,等的心急了)

对于sablog,我在另外的应用里,已经将它的模版机制全部转为discuz的,因为自己熟悉DZ的模版,改起来更快了。只是不知道何年才会派上用场。。。。

废话说了这么多,上重点的:

某网站支持

国内手机号码归属地查询WEB服务
2400多个城市5日天气预报 WEB服务
股票行情数据 WEB 服务(支持香港、深圳、上海基金、债券和股票;支持多股票同时查询)
中国电视节目预告(电视节目表)
火车时刻表 WEB 服务
IP地址来源搜索 WEB 服务
等等...

是什么网站呢?Look。。。

http://www.webxml.com.cn/zh_cn/web_services.aspx

其他两种我不懂,但wsdl我还是懂的。啥时候有空看看,oh yeah

Tags: webservice

切勿过早优化

放在PHP栏目是我仔细想过的,虽然文章内容里并未提及到PHP
开发WEB,很多人在一开始就考虑了优化优化再优化,但是,如果按照你这样的优化下去,当你发现瓶劲的时候你怎么办?你已经无法优化了。。
因此,为自己的代码预留一点优化空间,先赶着把代码上线,然后再边运行边优化。一来也保证了上线的时间,二来也可以在运行时注意到哪些地方是需要重点优化的。

以下内容来自守望轩(博客园)的文章:原文http://www.cnblogs.com/xjb/archive/2009/04/13/no-premature-optimization.html

Donald Knuth说“过早优化是万恶之源”(premature optimization is the root of all evil)。这话也许有些夸张,但“过早优化”的危害我觉得不能忽视。同时,我觉得“过早优化”的概念不专属编写程序,生活中的示例也比比皆是。不信,你看看下面这些情形你是否遇到过:

http://www.watch-life.net/life-thinking/no-premature-optimization.html

1、当你开始学一门程序语言的时候(比如c#),你想如果可以精通开发工具(比如Visual Studio)一定如虎添翼,于是一开始你就花很多时间去研究开发工具,而忘记自己学习的重点是语言本身,而非工具。或者,一开始,你花不少的时间去选择哪门程序语言,比较各种语言的优劣,在五花八门的语言前面犹豫不决,这个想学,那个也不想放弃,结果都是学个半路子。

2、当你学习一门外语比如英语的时候,一开始,你花了很多的时间去下载有关英语资料,花了很多的时间去找英语书籍,以为有了这些资料和书籍就可以学好英文,而不是一开始就踏踏实实的从单词、语法开始,结果后来资料下载了一大堆,书籍买了不少,却没有坚持下去。

3、你想搞体育锻炼,比如打羽毛球,于是一开始你花大量时间去买球衣、球鞋、球拍等装备,可没连几天,你发现自己开始三天打鱼了,最后,那些装备都起了灰,也没锻炼几次。

4、你想做时间管理(Getting Things Done),于是你研究各种时间管理的资料,上各种时间管理技巧的网站,比如lifehack、 digg 、gtdlife,下载对最流行的GTD的管理软件,以节省时间的名义浪费时间,很浮躁,不能做到实实在在把每天的计划都落实,拖拖拉拉。

5、你有没有这样的体验,一本书你总是对开头的部分看的最仔细,后面的章节没坚持看下去,下次又重复这种循环。当你计划做一件事的时候,总是规划的 非常完美,几乎考虑每个细节,但却没有认认真真、一步一步执行,或者过早完美计划,反而让你缩手缩脚,犹豫不前,瞻前顾后,顾此失彼,最后虎头蛇尾。

6、比如,如果我有了钱,我就如何如何享受快乐,比如,如果我将来有了很多的时间,我就会花更多的时间陪家人或锻炼…

这样类似的例子还可以举很多。

过早优化对大的问题在于:过早关注不重要的部分,而忽略行动和目标本身。以静态的思维来优化,殊不知,事务发展总是动态的,“优化”是需要长期的实 践积累才可以获得。出发点是好的,但往往好心办坏事,折腾大量的时间,做了很多不该做的,而该做的、重要的反而没做。强化外部条件、工具等外在,而忽略内 在因素和行动本身,或者,过多期望将来,而忽略当下眼前。

活在当下,实实在在做好手头的事,是避免“过早优化”最好的方法之一

Tags: 优化

一个很旧的PHP分词程序

这是一个比较老的分词程序,原文中的一些链接现在不是地址不正确就是打不开了。由此可以证明它是多老了。
再加上PHP直接进行分词的性能本来就不咋地,因此,建议仅仅用在很小的地方,比如自动添加TAG之类的。

原文如下:http://blog.sina.com.cn/s/blog_5677bc54010000i5.html

用PHP去做中文分词并不是一个太明智的举动, :p

下面是我根据网上找的一个字典档, 简易实现的一个分词程序.

(注: 字典档是gdbm格式, key是词 value是词频, 约4万个常用词)
代码请参见http://www.shi8.com/out/support/art_316.txt

PHP代码
  1. <?php  
  2. //中文分词系统简易实现办法  
  3. //切句单位:凡是ascii值<128的字符  
  4. //常见双字节符号:《》,。、?“”;:!¥…… %$#@^&*()[]{}|\/"'  
  5. //可以考虑加入超常见中文字: 的 和 是 不 了 啊 (不过有特殊字比如 "打的" "郑和" .. :p)  
  6.   
  7. //计算时间  
  8. function getmicrotime(){  
  9.     list($usec$sec) = explode(" ",microtime());  
  10.     return ((float)$usec + (float)$sec);  
  11. }  
  12. $time_start = getmicrotime();  
  13.   
  14.   
  15. //词典类  
  16. class ch_dictionary {  
  17.     var $_id;  
  18.   
  19.     function ch_dictionary($fname = "") {  
  20.         if ($fname != "") {  
  21.             $this->load($fname);  
  22.         }  
  23.     }  
  24.   
  25.     // 根据文件名载入字典 (gdbm数据档案)  
  26.     function load($fname) {  
  27.         $this->_id = dba_popen($fname"r""gdbm");  
  28.         if (!$this->_id) {  
  29.             echo "failed to open the dictionary.($fname)<br>\n";  
  30.             exit;  
  31.         }  
  32.     }  
  33.   
  34.     // 根据词语返回频率, 不存在返回-1  
  35.     function find($word) {  
  36.         $freq = dba_fetch($word$this->_id);  
  37.         if (is_bool($freq)) $freq = -1;  
  38.         return $freq;  
  39.     }  
  40. }  
  41.   
  42. // 分词类: (逆向)  
  43. // 先将输入的字串正向切成句子, 然后一句一句的分词, 返回由词组成的数组.  
  44. class ch_word_split {  
  45.     var $_mb_mark_list;    // 常见切分句子的全角标点  
  46.     var $_word_maxlen;    // 单个词最大可能长度(汉字字数)  
  47.     var $_dic;        // 词典...  
  48.     var $_ignore_mark;    // true or false  
  49.      
  50.     function ch_word_split () {  
  51.         $this->_mb_mark_list = array(","," ","。","!","?",":","……","、","“","”","《","》","(",")");  
  52.         $this->_word_maxlen  = 12;    // 12个汉字  
  53.         $this->_dic = NULL;  
  54.         $this->_ignore_mark = true;  
  55.     }  
  56.   
  57.     // 设定字典  
  58.     function set_dic($fname) {  
  59.         $this->_dic = new ch_dictionary($fname);  
  60.     }  
  61.   
  62.     function set_ignore_mark($set) {  
  63.         if (is_bool($set)) $this->_ignore_mark = $set;  
  64.     }  
  65.   
  66.     // 将字串切成句子再加以切分成词  
  67.     function string_split($str$func = "") {         
  68.         $ret = array();  
  69.          
  70.         if ($func == "" || !function_exists($func)) $func = "";         
  71.          
  72.         $len = strlen($str);  
  73.         $qtr = "";  
  74.   
  75.         for ($i = 0; $i < $len$i++) {  
  76.             $char = $str[$i];  
  77.   
  78.             if (ord($char) < 0xa1) {  
  79.                 // 读取到一个半角字符  
  80.                 if (!emptyempty($qtr)) {  
  81.                     $tmp = $this->_sen_split($qtr);  
  82.                     $qtr = "";  
  83.   
  84.                     if ($func != "") call_user_func($func$tmp);                     
  85.                     else $ret = array_merge($ret$tmp);                     
  86.                 }  
  87.   
  88.                 // 如果是单词或数字. 根据 char 将数据读取到 >= 0xa1为止  
  89.                 if ($this->_is_alnum($char)) {  
  90.                     do {  
  91.                         if (($i+1) >= $lenbreak;  
  92.                         $char2 = substr($str$i + 1, 1);  
  93.                         if (!$this->_is_alnum($char2)) break;  
  94.   
  95.                         $char .= $char2;  
  96.                         $i++;  
  97.                     } while (1);  
  98.   
  99.                     if ($func != "") call_user_func($funcarray($char));  
  100.                     else $ret[] = $char;                     
  101.                 }  
  102.                 elseif ($char == ' ' || $char == "\t") {  
  103.                     // nothing.  
  104.                     continue;  
  105.                 }  
  106.                 elseif (!$this->_ignore_mark) {  
  107.                     if ($func != "") call_user_func($funcarray($char));  
  108.                     else $ret[] = $char;                     
  109.                 }  
  110.             }  
  111.             else {  
  112.                 // 双字节字符.  
  113.                 $i++;  
  114.                 $char .= $str[$i];  
  115.                  
  116.                 if (in_array($char$this->_mb_mark_list)) {  
  117.                     if (!emptyempty($qtr)) {  
  118.                         $tmp = $this->_sen_split($qtr);  
  119.                         $qtr = "";  
  120.   
  121.                         if ($func != "") call_user_func($func$tmp);  
  122.                         else $ret = array_merge($ret$tmp);  
  123.                     }  
  124.   
  125.                     if (!$this->_ignore_mark) {  
  126.                         if ($func != "") call_user_func($funcarray($char));  
  127.                         else $ret[] = $char;  
  128.                     }  
  129.                 }  
  130.                 else {  
  131.                     $qtr .= $char;  
  132.                 }  
  133.             }  
  134.         }  
  135.          
  136.         if (strlen($qtr) > 0) {  
  137.             $tmp = $this->_sen_split($qtr);  
  138.   
  139.             if ($func != "") call_user_func($func$tmp);             
  140.             else $ret = array_merge($ret$tmp);             
  141.         }  
  142.   
  143.         // return value  
  144.         if ($func == "") {  
  145.             return $ret;  
  146.         }  
  147.         else {  
  148.             return true;  
  149.         }  
  150.     }  
  151.   
  152.     // 将句子切成词, 逆向  
  153.     function _sen_split($sen) {  
  154.         $len = strlen($sen) / 2;  
  155.         $ret = array();  
  156.   
  157.         for ($i = $len - 1; $i >= 0; $i--) {  
  158.             // 如: 这是一个分词程序  
  159.              
  160.             // 先取得最后一个字  
  161.             $w = substr($sen$i * 2, 2);  
  162.   
  163.             // 最终的词长  
  164.             $wlen = 1;  
  165.              
  166.             // 开始逆向匹配到最大长度.  
  167.             $lf = 0; // last freq  
  168.             for ($j = 1; $j <= $this->_word_maxlen; $j++) {  
  169.                 $o = $i - $j;  
  170.                 if ($o < 0) break;  
  171.                 $w2 = substr($sen$o * 2, ($j + 1) * 2);  
  172.                  
  173.                 $tmp_f = $this->_dic->find($w2);  
  174.                 //echo "{$i}.{$j}: $w2 (f: $tmp_f)\n";  
  175.                 if ($tmp_f > $lf) {  
  176.                     $lf = $tmp_f;  
  177.                     $wlen = $j + 1;  
  178.                     $w = $w2;  
  179.                 }  
  180.             }  
  181.             // 根据 $wlen 将 $i 偏移了  
  182.             $i = $i - $wlen + 1;  
  183.             array_push($ret$w);  
  184.         }  
  185.   
  186.         $ret = array_reverse($ret);  
  187.         return $ret;  
  188.     }  
  189.   
  190.     // 判断字符是不是 字母数字_- [0-9a-z_-]  
  191.     function _is_alnum($char) {  
  192.         $ord = ord($char);  
  193.         if ($ord == 45 || $ord == 95 || ($ord >= 48 && $ord <= 57))  
  194.             return true;  
  195.         if (($ord >= 97 && $ord <= 122) || ($ord >= 65 && $ord <= 90))  
  196.             return true;  
  197.         return false;  
  198.     }  
  199. }  
  200.   
  201.   
  202. // 分词后的回调函数  
  203. function call_back($ar) {     
  204.     foreach ($ar as $tmp) {  
  205.         echo $tmp . " ";  
  206.         //flush();  
  207.     }  
  208. }  
  209.   
  210. // 实例(如果没有输入就从 sample.txt中读取):  
  211. $wp = new ch_word_split();  
  212. $wp->set_dic("dic.db");  
  213.   
  214. if (!isset($_REQUEST['testdat']) || emptyempty($_REQUEST['testdat'])) {  
  215.     $data = file_get_contents("sample.txt");  
  216. }  
  217. else {  
  218.     $data = & $_REQUEST['testdat'];  
  219. }  
  220.   
  221. // output  
  222. echo "<h3>简易分词演示</h3>\n";  
  223. echo "<hr>\n";  
  224. echo "分词结果(" . strlen($data) . " chars): <br>\n<textarea cols=100 rows=10>\n";  
  225.   
  226. // 设定是否忽略不返回分词符号(标点,常用字)  
  227. $wp->set_ignore_mark(false);  
  228.   
  229. // 执行切分, 如果没有设置 callback 函数, 则返回由词组成的array  
  230. $wp->string_split($data"call_back");  
  231.   
  232. $time_end = getmicrotime();  
  233. $time = $time_end - $time_start;  
  234.   
  235. echo "</textarea><br>\n本次分词耗时: $time seconds <br>\n";  
  236. ?>  
  237. <hr>  
  238. <form method=post>  
  239. 您也可以在下面文本框中输入文字,提交后试验分词效果:<br>  
  240. <textarea name=testdat cols=100 rows=10></textarea><br>  
  241. <input type=submit>  
  242. </form>  
  243. <hr>  

文章引用自:http://www.im286.net/viewthread.php?tid=1157015

Tags: 分词, gbm

[转]PHP删除cookie的一个小秘密

首先我们看一下php手册中关于删除cookie的说明

------以下引用php手册内容--------------

bool setcookie ( string name [, string value [, int expire [, string path [, string domain [, bool secure]]]]] )



要删除 cookie 需要确保它的失效期是在过去,才能触发浏览器的删除机制。
下面的例子说明了如何删除刚才设置的 cookie: 例子 2. setcookie() 删除
例子

// 将过期时间设为一小时前

setcookie("TestCookie", "", time() - 3600);
setcookie("TestCookie", "", time() - 3600, "/~rasmus/", ".utoronto.ca", 1);

----------------引用结束--------------------------

删除一个cookie的方法就是把这个cookie的有效期设置为当前时间以前,这
也是几乎所有php程序员都会这么做。

  后来一个初接触php的朋友告诉我,他在程序中本想把一个cookie的值设置为
空,结果导致这个cookie直接被删除。我当时的第一反应是不相信,于是测试
了一下

setcookie("testcookie", '');
print_r($_COOKIE);

结果果然是整个$_COOKIE数组都是空的,而非仅仅$_COOKIE['testcookie']为
空.于是用winsock抓包,观察返回的http头,发现http头竟然是

Set-Cookie: testcookie=deleted; expires=Mon, 18-Jun-2007 02:42:33 GMT



这说明setcookie("testcookie", '');的的确确是将testcookie这个cookie直
接删除.而关于这种情况在php手册中完全没有说明.

最后阅读php源码,终于发现真相(这就是开源的好处了,有什么不清楚的内幕
直接查源码)

以下代码可以在php5.20的linux源码包中ext/standard/head.c第99行附近找到.

C++代码
  1. if (value && value_len == 0) {  
  2.     /* 
  3.      * MSIE doesn't delete a cookie when you set it to a null value 
  4.      * so in order to force cookies to be deleted, even on MSIE, we 
  5.      * pick an expiry date 1 year and 1 second in the past 
  6.      */  
  7.     time_t t = time(NULL) - 31536001;  
  8.     dt = php_format_date("D, d-M-Y H:i:s T"sizeof("D, d-M-Y H:i:s T")-1, t, 0 TSRMLS_CC);  
  9.     sprintf(cookie, "Set-Cookie: %s=deleted; expires=%s", name, dt);  
  10.     efree(dt);  
  11. else {  
  12.     sprintf(cookie, "Set-Cookie: %s=%s", name, value ? encoded_value : "");  
  13.     if (expires > 0) {  
  14.         strcat(cookie, "; expires=");  
  15.     dt = php_format_date("D, d-M-Y H:i:s T"sizeof("D, d-M-Y H:i:s T")-1, expires, 0 TSRMLS_CC);  
  16.         strcat(cookie, dt);  
  17.         efree(dt);  
  18.     }  
  19. }  



源码中清清楚楚的显示,if (value && value_len == 0) ,当value_len为0

sprintf(cookie, "Set-Cookie: %s=deleted; expires=%s", name, dt);
会发送删除cookie的http头给浏览器.

最后我们可以得出结论,在php中使用
setcookie($cookiename, '');或者 setcookie($cookiename, NULL);
都会删除cookie,当然这些手册中并没有。

Tags: 删除, cookie, 清空