2007/08 14
Transplanted Real-World Business Models 现实世界的商业向互联网的转移

The mail-order model 以邮件,包裹的形式销售现实产品。 案例:amazon.com

The advertising based model 广告模式 许多的搜索引擎公司和一些免费站点 案例:yahoo, sina,

The subscription model 订购模式。在很多的音乐站点和成人站点的可以发现这种模式,付费购买之后,获得更多的信息。

The free trial model 免费试用。 即软件中的共享软件模型

The direct marketing model 直接的市场联系 以垃圾邮件,垃圾回复为代表,直接宣传实际市场的资料等,如培训,发票等

The real estate model 资产模型 如域名,Email名等

Incentive scheme models 坑蒙拐骗型 利用抽奖,优惠卷,“免费”服务等,诱导用户点击广告或者提供其私人信息 一些web调查机构使用此模式

Business to Business B2B模式

Combinations of the above models. 综合模式

Native Internet Business Models 纯粹的互联网模式

Unlike the real-world the native economy of the Internet is not based on scarcity but on abundance.
与real-world Model的区别:基于流量,而不是用户

The library model 图书馆模式 指企业站,大学信息站等

The freeware model 免费软件模式 当这个软件被广泛使用后,再发布一些其他的收费或增值版本。 案例:netscape

The information barter model 出卖信息模式 把本站的用户信息出卖给其他的公司 一些新闻资讯站精于此道

Digital products and the digital delivery model. 数字产品和数字产品发送。 数字资料是免费的,但当你需要它的实体时,你需要邮寄它们。利润就在这里。

The access provision model 访问入口提供商 即ISP

Web site hosting and other Internet services. 网站空间或其他服务提供,并在上面放置广告以盈利。


来源: A Taxonomy of Internet Commerce by Paul Bambury
Defined tags for this entry:

Posted by rollenc

Last modified on 2007-08-14 15:15
2007/04 25
Mark 一下。
整理 描述
armscii8 (ARMSCII-8 Armenian)
armscii8_bin 亚美尼亚语, 二进制
armscii8_general_ci 亚美尼亚语, 不区分大小写
ascii (US ASCII)
ascii_bin 西欧 (多语言), 二进制
ascii_general_ci 西欧 (多语言), 不区分大小写
big5 (Big5 Traditional Chinese)
big5_bin 繁体中文, 二进制
big5_chinese_ci 繁体中文, 不区分大小写
binary (Binary pseudo charset)
binary 二进制
cp1250 (Windows Central European)
cp1250_bin 中欧 (多语言), 二进制
cp1250_croatian_ci 克罗地亚语, 不区分大小写
cp1250_czech_cs 捷克语, 区分大小写
cp1250_general_ci 中欧 (多语言), 不区分大小写
cp1251 (Windows Cyrillic)
cp1251_bin 西里尔语 (多语言), 二进制
cp1251_bulgarian_ci 保加利亚语, 不区分大小写
cp1251_general_ci 西里尔语 (多语言), 不区分大小写
cp1251_general_cs 西里尔语 (多语言), 区分大小写
cp1251_ukrainian_ci 乌克兰语, 不区分大小写
cp1256 (Windows Arabic)
cp1256_bin 阿拉伯语, 二进制
cp1256_general_ci 阿拉伯语, 不区分大小写
cp1257 (Windows Baltic)
cp1257_bin 巴拉克语 (多语言), 二进制
cp1257_general_ci 巴拉克语 (多语言), 不区分大小写
cp1257_lithuanian_ci 立陶宛语, 不区分大小写
cp850 (DOS West European)
cp850_bin 西欧 (多语言), 二进制
cp850_general_ci 西欧 (多语言), 不区分大小写
cp852 (DOS Central European)
cp852_bin 中欧 (多语言), 二进制
cp852_general_ci 中欧 (多语言), 不区分大小写
cp866 (DOS Russian)
cp866_bin 俄语, 二进制
cp866_general_ci 俄语, 不区分大小写
cp932 (SJIS for Windows Japanese)
cp932_bin 日语, 二进制
cp932_japanese_ci 日语, 不区分大小写
dec8 (DEC West European)
dec8_bin 西欧 (多语言), 二进制
dec8_swedish_ci 瑞典语, 不区分大小写
eucjpms (UJIS for Windows Japanese)
eucjpms_bin 日语, 二进制
eucjpms_japanese_ci 日语, 不区分大小写
euckr (EUC-KR Korean)
euckr_bin 朝鲜语, 二进制
euckr_korean_ci 朝鲜语, 不区分大小写
gb2312 (GB2312 Simplified Chinese)
gb2312_bin 简体中文, 二进制
gb2312_chinese_ci 简体中文, 不区分大小写
gbk (GBK Simplified Chinese)
gbk_bin 简体中文, 二进制
gbk_chinese_ci 简体中文, 不区分大小写
geostd8 (GEOSTD8 Georgian)
geostd8_bin 乔治亚语, 二进制
geostd8_general_ci 乔治亚语, 不区分大小写
greek (ISO 8859-7 Greek)
greek_bin 希腊语, 二进制
greek_general_ci 希腊语, 不区分大小写
hebrew (ISO 8859-8 Hebrew)
hebrew_bin 希伯来语, 二进制
hebrew_general_ci 希伯来语, 不区分大小写
hp8 (HP West European)
hp8_bin 西欧 (多语言), 二进制
hp8_english_ci 英语, 不区分大小写
keybcs2 (DOS Kamenicky Czech-Slovak)
keybcs2_bin 捷克斯洛伐克语, 二进制
keybcs2_general_ci 捷克斯洛伐克语, 不区分大小写
koi8r (KOI8-R Relcom Russian)
koi8r_bin 俄语, 二进制
koi8r_general_ci 俄语, 不区分大小写
koi8u (KOI8-U Ukrainian)
koi8u_bin 乌克兰语, 二进制
koi8u_general_ci 乌克兰语, 不区分大小写
latin1 (cp1252 West European)
latin1_bin 西欧 (多语言), 二进制
latin1_danish_ci 丹麦语, 不区分大小写
latin1_general_ci 西欧 (多语言), 不区分大小写
latin1_general_cs 西欧 (多语言), 区分大小写
latin1_german1_ci 德语 (字典), 不区分大小写
latin1_german2_ci 德语 (电话本), 不区分大小写
latin1_spanish_ci 西班牙语, 不区分大小写
latin1_swedish_ci 瑞典语, 不区分大小写

整理 描述
latin2 (ISO 8859-2 Central European)
latin2_bin 中欧 (多语言), 二进制
latin2_croatian_ci 克罗地亚语, 不区分大小写
latin2_czech_cs 捷克语, 区分大小写
latin2_general_ci 中欧 (多语言), 不区分大小写
latin2_hungarian_ci 匈牙利语, 不区分大小写
latin5 (ISO 8859-9 Turkish)
latin5_bin 土耳其语, 二进制
latin5_turkish_ci 土耳其语, 不区分大小写
latin7 (ISO 8859-13 Baltic)
latin7_bin 巴拉克语 (多语言), 二进制
latin7_estonian_cs 爱沙尼亚语, 区分大小写
latin7_general_ci 巴拉克语 (多语言), 不区分大小写
latin7_general_cs 巴拉克语 (多语言), 区分大小写
macce (Mac Central European)
macce_bin 中欧 (多语言), 二进制
macce_general_ci 中欧 (多语言), 不区分大小写
macroman (Mac West European)
macroman_bin 西欧 (多语言), 二进制
macroman_general_ci 西欧 (多语言), 不区分大小写
sjis (Shift-JIS Japanese)
sjis_bin 日语, 二进制
sjis_japanese_ci 日语, 不区分大小写
swe7 (7bit Swedish)
swe7_bin 瑞典语, 二进制
swe7_swedish_ci 瑞典语, 不区分大小写
tis620 (TIS620 Thai)
tis620_bin 泰语, 二进制
tis620_thai_ci 泰语, 不区分大小写
ucs2 (UCS-2 Unicode)
ucs2_bin Unicode (多语言), 二进制
ucs2_czech_ci 捷克语, 不区分大小写
ucs2_danish_ci 丹麦语, 不区分大小写
ucs2_esperanto_ci Esperanto, 不区分大小写
ucs2_estonian_ci 爱沙尼亚语, 不区分大小写
ucs2_general_ci Unicode (多语言), 不区分大小写
ucs2_hungarian_ci 匈牙利语, 不区分大小写
ucs2_icelandic_ci 冰岛语, 不区分大小写
ucs2_latvian_ci 拉脱维亚语, 不区分大小写
ucs2_lithuanian_ci 立陶宛语, 不区分大小写
ucs2_persian_ci 波斯语, 不区分大小写
ucs2_polish_ci 波兰语, 不区分大小写
ucs2_roman_ci 西欧, 不区分大小写
ucs2_romanian_ci 罗马尼亚语, 不区分大小写
ucs2_slovak_ci 斯洛伐克语, 不区分大小写
ucs2_slovenian_ci 斯洛文尼亚语, 不区分大小写
ucs2_spanish2_ci 传统西班牙语, 不区分大小写
ucs2_spanish_ci 西班牙语, 不区分大小写
ucs2_swedish_ci 瑞典语, 不区分大小写
ucs2_turkish_ci 土耳其语, 不区分大小写
ucs2_unicode_ci Unicode (多语言), 不区分大小写
ujis (EUC-JP Japanese)
ujis_bin 日语, 二进制
ujis_japanese_ci 日语, 不区分大小写
utf8 (UTF-8 Unicode)
utf8_bin Unicode (多语言), 二进制
utf8_czech_ci 捷克语, 不区分大小写
utf8_danish_ci 丹麦语, 不区分大小写
utf8_esperanto_ci Esperanto, 不区分大小写
utf8_estonian_ci 爱沙尼亚语, 不区分大小写
utf8_general_ci Unicode (多语言), 不区分大小写
utf8_hungarian_ci 匈牙利语, 不区分大小写
utf8_icelandic_ci 冰岛语, 不区分大小写
utf8_latvian_ci 拉脱维亚语, 不区分大小写
utf8_lithuanian_ci 立陶宛语, 不区分大小写
utf8_persian_ci 波斯语, 不区分大小写
utf8_polish_ci 波兰语, 不区分大小写
utf8_roman_ci 西欧, 不区分大小写
utf8_romanian_ci 罗马尼亚语, 不区分大小写
utf8_slovak_ci 斯洛伐克语, 不区分大小写
utf8_slovenian_ci 斯洛文尼亚语, 不区分大小写
utf8_spanish2_ci 传统西班牙语, 不区分大小写
utf8_spanish_ci 西班牙语, 不区分大小写
utf8_swedish_ci 瑞典语, 不区分大小写
utf8_turkish_ci 土耳其语, 不区分大小写
utf8_unicode_ci Unicode (多语言), 不区分大小写
Defined tags for this entry: ,

Posted by rollenc

Last modified on 2007-04-25 14:04
2007/03 11

Error-Handing Techniques

  • 返回中立值 如:数值返回0
  • 换用下一个正确的数据
  • 返回与前次相同的数据
  • 换用最接近的合法值 如经度设置为(-180,180)之间
  • 把警告信息记录到日志文件中 兼用以上的处理,同时记录它。
  • 返回一个错误码
    • 设置一个状态变量的值(个人不推荐)
    • 用状态值作为函数的返回值
    • 用语言内建的异常机制跑出一个异常
  • 调用错误处理子程序活对象 优点:能把错误处理的职责都集中到一起。代价:错误处理代码与整个程序紧密耦合。
  • 当错误发生时显示出错信息 出错信息散布于整个应用程序中。
  • 用最妥当的方式在局部处理错误 留给执行设计和实现的程序员来解决,灵活性强,但整体正确性和可靠性无法满足,风险显著
  • 关闭程序 用于人身攸关的应用程序
知识来源:《代码大全2》
Defined tags for this entry: ,

Posted by rollenc

Last modified on 2007-03-11 20:40
2007/01 15
Verycd、豆瓣、EEmap
Defined tags for this entry: ,

Posted by rollenc

Not modified
2006/11 30
上一篇BLOG以及这一篇都是使用Performancing来发布的,感觉很不错。比FLOCK上的功能要强多了。wordpress上几乎所有的功能都可以使用到,比如Category选取,发布为草稿,也支持编辑以前发布的文章。
功能非常棒。赶快下载使用吧:
Firefox的Performancing插件下载地址
Defined tags for this entry: , ,

Posted by rollenc

Not modified
2006/11 30
来源:http://www.developer.com/lang/php/article.php/10941_3604111_1
Part1:
PHP 5 made significant improvements on the Object Orientated programming model of PHP 4 bringing it more in line with languages such as Visual Basic .NET and Java. The improved object model in PHP 5 makes developing applications using OOP much easier and gives you the programmer, greater flexibility.

In this series of articles I will demonstrate the new features of the PHP 5 object and show you how to create a database abstraction layer similar to PEAR DB. I will also introduce you to a few design patterns that can be applied to common OOP related problems.

In this article, I introduce you to some of the features of the PHP 5 object model. You will see how to create a database abstraction layer similar to the Pear DB abstraction layer. You'll also learn how to adapt this abstraction layer for your own uses.

Introduction


One of PHP's stronger areas is its support for database connectivity. It is able to connect to and talk to just about any database server or interface you can imagine. However, with this comes a few inherent problems; each database system has its own features, functions and in most cases they have their own versions of SQL. Although the functions used to access these databases are similar they do vary subtly meaning that if you were to want to port an application written for MySql to MS SQL server, the refactoring would require manually changing all calls to mysql_query() to mssql_query().

While we are not going to go as far as developing a database independent version of SQL, the new features of PHP 5 will be us build a consistent database API with support for stored procedures (where it is not already present). This will then make switching from one database system to another as painless as changing one line of code.



Interfaces Abstract Classes and the Adapter Pattern


The first features new to PHP 5 to be covered in this article are abstract classes and interfaces. These concepts are nothing more than features added to OOP, which help the programmer follow good coding standards.



Abstract Classes


An abstract class is a class that is only partially implemented by the programmer. It may contain one or more abstract methods. An abstract method is simply a function definition that serves to tell the programmer that the method must be implemented in a child class.



To create an abstract class we use the code shown in Listing 1:


Listing 1: An Abstract PHP class


SerialNumber = $SerialNumber;  
    }
    public function getSerialNumber()  
    {  
        return $this->SerialNumber;  
    }  
}  
?>

The abstract class in Listing 1 contains some of the methods required for a weapon. The fire() method however, cannot be implemented because each different weapons use different firing different mechanisms. The method is therefore declared as abstract, meaning it will be implemented in a more specific child class.


Because the class is abstract, an instance of it can never be created (remember, it is only a partial implementation). Instead a child class must be created using inheritance and implement the fire method in itself. Failure to do so will result in a fatal error. Listing 2 shows a child class being created from the Abstract Weapon class.


Listing 2: Extending the Abstract Weapons class


SafetyOff) {  
            return $this->CurrentBullet;  
        }  
    }  
}  

class Cannon extends Weapon  
{  
    public function fire()  
    {  
        $this->NeedsLoading = true;  
        return $this->CurrentCanon;  
    }  
?>


An instance of the Cannon and Gun classes can now be created because they now fully implemented subclasses of weapon.


Interfaces


An interface is similar to an abstract class; indeed interfaces occupy the same namespace as classes and abstract classes. For that reason, you cannot define an interface with the same name as a class. An interface is a fully abstract class; none of its methods are implemented and instead of a class sub-classing from it, it is said to implement that interface.


An interface will be used in the database abstraction layer you create. This ensures that every time you create a class for a particular database, the same API is exposed. When using an interface, you can then rely on the methods defined for the interface to be part of the class because, if they are not, PHP will not parse it.


The MySql functions will be used as an example because they are the most commonly used amongst PHP programmers. The most commonly used functions are:


  • mysql_connect()
  • mysql_error()
  • mysql_errno()
  • mysql_query()
  • mysql_fetch_array()
  • mysql_fetch_row()
  • mysql_fetch_assoc()
  • mysql_fetch_object()
  • mysql_num_rows()
  • mysql_close()

If all the database class APIs you create can expose the same methods with the same return types then you can be sure that changing from one database to another, such as from MySql to Postgre SQL, will be painless. As such, the interface in listing 3 can be determined for your API.

Listing 3: An Abstracted Database Interface


interface DB 
{ 
    public function connect(); 
    public function error(); 
    public function errno(); 
    public static function escape_string($string); 
    public function query($query); 
    public function fetch_array($result); 
    public function fetch_row($result); 
    public function fetch_assoc($result); 
    public function fetch_object($result); 
    public function num_rows($result); 
    public function close(); 
} 

Any class implementing the interface must define each method that is declared in the interface, and each method must have at least the parameters identified in their interface definitions. It may have more parameters as long as they are optional, but it cannot have less.

Part2

Look at a class in Listing 4 that implements the database interface. You should recall that I mentioned the adapter pattern earlier. This is an example of the adapter pattern, which is used by programmers in order to adapt one API. The API you are adapting from could be another object-based API or as being done here, an adaptation from a modular API. If you want to read more about the adapter pattern, you can find a more detailed explanation and examples here.

Notice how the escape_string() method is included as a static method. This method does not require an active connection to a database and should not require and instance of any object which implements the DB interface. In my opinion, this is the single most important method of any database implementation; a poorly implemented escape string method could make your applications vulnerable SQL injection.


Listing 4: Implementing the database interface


class MySqlDB implements DB 
{ 
        private  $link; 
         
        public function connect($server='', $username='', $password='', $new_link=true, $client_flags=0) 
        { 
            $this->link = mysql_connect($server, $username, $password, $new_link, $client_flags); 
        } 
     
        public function errno() 
        { 
            return mysql_errno($this->link); 
        } 

        public function error() 
        { 
            return mysql_error($this->link); 
        } 

        public static function escape_string($string) 
        { 
            return mysql_real_escape_string($string); 
        } 

        public function query($query) 
        { 
            return mysql_query($query, $this->link); 
        } 
         
        public function fetch_array($result, $array_type = MYSQL_BOTH) 
        { 
            return mysql_fetch_array($result, $array_type); 
        } 

        public function fetch_row($result) 
        { 
            return mysql_fetch_row($result); 
        } 
         
        public function fetch_assoc($result) 
        { 
            return mysql_fetch_assoc($result); 
        } 
         
        public function fetch_object($result) 
        { 
            return mysql_fetch_object($result); 
        } 
         
        public function num_rows($result) 
        { 
            return mysql_num_rows($result); 
        } 
         
        public function close() 
        { 
            return mysql_close($this->link); 
        } 
}
?>


You'll notice that there are many more mysql functions than methods that are adapted in the interface in listing 3. However, this small subset of functions is sufficient to meet the needs of most applications requiring trivial data storage and retrieval. The additional functions can be implemented and I have done this in the attached example file, you may also choose to add additional functionality to the class and the interface.


Listing 5: Creating a database class


    $db = new MySqlDb; 
    $db->connect('host', 'username', 'password'); 
    $db->query('use users'); // we could also use $db->select_db here but it is not consistent with the interface 

    $result = $db->query("SELECT username FROM users"); 
         
    while($row = $db->fetch_assoc($reuslt)) 
    { 
        echo($row['username']); 
    } 

As shown in listing 5, you can now create a class for each database you want and as long as it implements the DB interface, switching from one to another is as easy as changing one line of code:


$db = new MsSqlDb; 

Conclusion


In this first article, you've seen how to create an abstraction layer to access a database. Using this, you saw how creating an interface helps you to isolate your application so that you can easily switch from one database to anther without rewriting your own applications.


Downloads


About the Author


Adam Delves is a university student and web programmer from the UK who is studying computing. He has been a PHP programmer for over 3 years and now runs two small websites and writes articles for PHP builder.com.

rollenc总结


将本文标题相对应,MySqlDb实现了DB接口(interface),也对mysql_*函数进行了适配(Adapter)(我就很喜欢进行这种适配,php中有很多带‘_’字符的函数(这也被PHP反对者们发现,并抨击PHP的一大有力证据),与我喜欢的骆驼编程风格很不协调,所以,为了隐藏它们,我常常进行适配)。
抽象类只在weapon上出现到了,为了增加代码的灵活性,建议使用接口,而不是继承。(完)
Defined tags for this entry: , ,

Posted by rollenc

Last modified on 2007-01-12 18:56
2006/10 29
Test First Guidelines
Sean Shubin
01/25/2002
Sean Shubin has begun using Test-First development. He wanted to share these ideas and guidelines with us.

Contents:

This document is my attempt to filter out guidelines about Test First Design from the XP series of books. Thanks to Denise Phillips and Ron Jeffries for their input. It is not my intent to justify Test First Design, I just want summarize what martin Fowler's Refactoring and the XP texts have to say on the subject. If you see anything that you think contradicts these sources, please e-mail me with the book and page number. I am still working on samples for each of these guidelines. If you find any of them completely confusing, send me an e-mail to let me know which ones I need to work on. Send e-mail to Sean Shubin, (remove the "nospam" portion of the e-mail address).

The tests should drive you to write the code, the reason you write code is to get a test to succeed, and you should only write the minimal code to do so. Note that test-first-design is more than just unit testing. Unit testing by itself does not change the design of the code. In addition to documenting how code should be used, test-first-design helps you keep the design simple right from the start, and keeps the design easy to change.

As project complexity grows, you may notice that writing automated tests gets harder to do. This is your early warning system of overcomplicated design. Simplify the design until tests become easy to write again, and maintain this simplicity over the course of the project.
Guidelines for test first design:

* The name of the test should describe the requirement of the code
* There should be at least one test for each requirement of the code. Each possible path through of the code is a different requirement
* Only write the simplest possible code to get the test to pass, if you know this code to be incomplete, write another test that demonstrates what else the code needs to do
* A test should be similar to sample code, in that it should be clear to someone unfamiliar with the code as to how the code is intended to be used
* If a test seems too large, see if you can break it down into smaller tests
* If you seem to be writing a lot of code for one little test, see if there are other related tests you could write first, that would not require as much code
* Test the goal of the code, not the implementation
* One test/code/simplify cycle at a time. Do not write a bunch of tests, and try to get them working all at once
* Keep writing tests that could show if your code is broken, until you run out of things that could possibly break
* When choosing an implementation, be sure to choose the simplest implementation that could possibly work
* If you are unsure about a piece of code, add a test you think might break it
* A test is one specific case, for which there is a known answer
* If all of the tests succeed, but the program doesn't work, add a test
* Tests should be as small as possible, before testing a requirement that depends on multiple things working, write a test for each thing it depends
* Tests should not take longer than a day to get working, typical test/code/simplify cycles take around 10 minutes
* Don't test every single combination of inputs. Do test enough combinations of inputs to give you confidence that the any code that passes the test suite will work with every single combination of inputs
* Do not write a single line of code that doesn't help a failing test succeed. (Clarification for GUI's, some aspects of GUI's are impossible to test automatically, so it will have to be an acceptance test that drives you two write some GUI code. Use automated testing whenever possible)
* Do not fix a bug until you have written a test that demonstrates the bug

What is the simplest code? (Paraphrased from the "Extreme Programming" series of books)

* All of the tests run
* There is no duplicate code (any given code segment or structural pattern should appear "once and only once")
* Clarity. The code and tests communicate the intent as clearly as possible
* The code is minimal (no classes or methods unnecessary to get the tests to pass)

The Test-Code-Simplify cycle (Quoted verbatim from "Extreme Programming Applied", p159)

* Write a single test
* Compile it. It shouldn't compile, because you haven't written the implementation code it calls
* Implement just enough code to get the test to compile
* Run the test and see it fail
* Implement just enough code to get the test to pass
* Run the test and see it pass
* Refactor for clarity and "once and only once"
* Repeat

Online Examples of Test First Design:

Roman numeral converter example

http://www.differentpla.net/~roger/devel/xp/test_first/

Sample application that calculates bowling score

http://www.objectmentor.com/publications/xpepisode.htm

Books:

"Refactoring" and "Design Patterns" tell you how to maintain a simple design.

The "Extreme Programming" series explains test-first design in detail, and was the primary resource I used to put together this set of guidelines.

来源:http://xprogramming.com/xpmag/testFirstGuidelines.htm
最近感觉想翻译的东西太多了,有一些就纯粹转载了。有时间再翻译。
Defined tags for this entry: , , ,

Posted by rollenc

Not modified
2006/10 27
From: http://www.devshed.com/c/a/PHP/Unit-Testing/
Unit Testing
单元测试

Having a formalized unit testing infrastructure for your projects will save you time in the long run, especially when looking for bugs in code. This article introduces you to setting up a unit testing framework. It is excerpted from chapter 6 of the book Advanced PHP Programming, written by George Schlossnagle (Sams; ISBN: 0672325616).
在正式的单元测试编程的基础上,你可以给你的程序开发节省下不少时间,特别是查找和修复BUG时的时间。本文介绍了如何建立一个测试框架。本文引于《告急PHP编程》第六章,作者:George Schlossnagle (Sams; ISBN: 0672325616).

Testing and engineering are inextricably tied forever.
测试和开发紧密联系

All code is tested at some point—perhaps during its implementation, during a dedicated testing phase, or when it goes live. Any developer who has launched broken code live knows that it is easier to test and debug code during development than after it goes into production.
所有的代码都在同一时候被测试,很可能是在程序执行的时候,或者是在专门的测试阶段,或者在程序发布后。程序员们都知道,在开发阶段中,在开发阶段修复程序BUG比发布后再修复要容易。

Developers give many excuses for not testing code until it is too late. These are some of the popular ones:
程序员给没有经过测试的代码找了很多的理由,常见的有:
* The project is too rushed. 程序开发过于匆忙。
* My code always works the first time. 程序在开始是可以正常运行的。
* The code works on my machine. 这些代码在我的机器上是可以正常运行的。

Let's explore these excuses. First, projects are rushed because productivity lags. Productivity is directly proportional to the amount of debugging required to make code stable and working. Unfortunately, testing early and testing late are not equal cost operations. The problem is two-fold:
我们来研究这几个理由。首先,工程匆忙是因为效率不佳,对代码的稳定性和正确性的调试直接影响到开发效率。不幸的是。在不同时候对代码进行调试所需要的花费是不一样的。从下面几点来说明:

* In a large code base that does not have a formalized testing infrastructure, it is hard to find the root cause of a bug. It's a needle-in-a-haystack problem. Finding a bug in a 10-line program is easy. Finding a bug in 10,000 lines of included code is a tremendous effort.
* 项目中没有基于一个正式的测试基础,这导致很难查找到BUG的来源。在10行代码中找出错误是简单的,但是在10,000行代码中,而且包含很多文件包含关系的代码中找出一个错误则是一场噩梦。

* As the code base grows, so do the number of dependencies between components. Seemingly innocuous changes to a "core" library—whether adding additional features or simply fixing a bug—may unintentionally break other portions of the application. This is known as refactoring. As the size and complexity of software grow, it becomes increasingly difficult to make these sorts of changes without incurring time costs and introducing new bugs.
*
* All software has bugs. Any developer who claims that his or her software is always bug-free is living in a fantasy world.
* System setups are all slightly different, often in ways that are hard to anticipate. Differing versions of PHP, differing versions of libraries, and different file system layouts are just a few of the factors that can cause code that runs perfectly on one machine to inexplicably fail on another.
Defined tags for this entry: , ,

Posted by rollenc

Not modified
2006/10 6
原地址:http://www.phpbuilder.com/columns/kassemi20050613.php3?aid=923


XMLHttpRequest and AJAX for PHP programmers, Part 2

PHP程序员需要了解的XMLHttpRequest和AJAX 第二部分

James Kassemi

翻译:rollenc


Let's Jump Right In!

我们继续!


This week's article takes off where last week's tutorial left off--we're about to jump into the creation of the PHP backend! If you haven't read the previous article, we recommend that you begin there before moving forward so you don't miss anything.

通过上周的学习,本周文章开始正式开始了。我们准备开始编辑PHP后台!如果你还没有阅读上一篇文章,我们建议你先阅读它,不要拉下必要的知识。


Calling the Functions

调用函数


Now, how is the products.html page supposed to call these functions? We want to be able to let the user select an item, and then load the values based on that selection. Using a "Search" or "Go" button is a little archaic, so let's use the onChange method, which we can use to call javascript functions whenever the user changes the selected item. Change the <select> tag in products.html to look like this:

那现在,products.html如何来调用这些函数呢 ?我们需要在用户选择条目后,加载与这个条目相关的信息。使用“搜索”或“go”显得有点老套,所以我们使用了onChange方法(事件),当用户改变选择的条目时,我们通过JAVASCRIPT来调用。将products.html文件中的<select>标签修改成这样:




                    
                    

                    
                
            
        
^ Please select a category from above.


Source for Included File: internal_request.js
products.html的源代码:
/* The following function creates an XMLHttpRequest object... */
function createRequestObject(){
    var request_o; //declare the variable to hold the object.
    var browser = navigator.appName; //find the browser name
    if(browser == "Microsoft Internet Explorer"){
        /* Create the object using MSIE's method */
        request_o = new ActiveXObject("Microsoft.XMLHTTP");
    }else{
        /* Create the object using other browser's method */
        request_o = new XMLHttpRequest();
    }
    return request_o; //return the object
}

/* You can get more specific with version information by using
    parseInt(navigator.appVersion)
    Which will extract an integer value containing the version
    of the browser being used.
*/
/* The variable http will hold our new XMLHttpRequest object. */
var http = createRequestObject();

/* Function called to get the product categories list */
function getProducts(){
    /* Create the request. The first argument to the open function is the method (POST/GET),
        and the second argument is the url...
        document contains references to all items on the page
        We can reference document.form_category_select.select_category_select and we will         
        be referencing the dropdown list. The selectedIndex property will give us the
        index of the selected item.
    */
    http.open('get', 'internal_request.php?action=get_products&id='
            + document.form_category_select.select_category_select.selectedIndex);
    /* Define a function to call once a response has been received. This will be our
        handleProductCategories function that we define below. */
    http.onreadystatechange = handleProducts;
    /* Send the data. We use something other than null when we are sending using the POST
        method. */
    http.send(null);
}

/* Function called to handle the list that was returned from the internal_request.php file.. */
function handleProducts(){
    /* Make sure that the transaction has finished. The XMLHttpRequest object
        has a property called readyState with several states:
        0: Uninitialized
        1: Loading
        2: Loaded
        3: Interactive
        4: Finished */
    if(http.readyState == 4){ //Finished loading the response
        /* We have got the response from the server-side script,
            let's see just what it was. using the responseText property of
            the XMLHttpRequest object. */
        var response = http.responseText;
        /* And now we want to change the product_categories 
content. we do this using an ability to get/change the content of a page element that we can find: innerHTML. */ document.getElementById('product_cage').innerHTML = response; } }


Source for Included File: internal_request.php
internal_request.php的源代码:

                    
  • CDex
  • CoolEdit
  • Winamp
  • XMMS
  • '; break; case 1: //Games echo '
    • Blackjack
    • Calculatron
    • Hold\'em
    • Minesweeper
    • Tetris
    '; break; case 2: //Internet echo '
    • Epiphany
    • Internet Explorer
    • Mozilla
    • Netscape
    • Opera
    • Safari
    '; break; default: echo 'You didn\'t select an item from above!'; break; } } ?>
    Defined tags for this entry: , , , , , ,

    Posted by rollenc

    Last modified on 2007-01-12 19:06
    2006/10 5
    Link:http://www.phpbuilder.com/columns/kassemi20050606.php3?aid=917

    XMLHttpRequest and AJAX for PHP programmers
    php程序中的XMLHttpRequest 和 AJAX

    Introduction:
    前言:

    Although the concept isn't entirely new, XMLHttpRequest technology is implemented on more sites now than ever. Compatibility is no longer an issue (IE, Mozilla and Opera all support it), and the benefits to using it are amazing. There are too many PHP programmers avoiding any work with javascript beyond simple form validation, and for good reason. It's difficult to keep several languages proficiently under your belt. But using the XMLHttpRequest object is not as hard as everybody thinks, and you don't need to buy and memorize another reference manual.
    虽然 XMLHttpRequest概念并不是新的,但最近在网站上的应用远多于以前。兼容性也不存在问题了(IE, Mozilla and Opera都支持),其应用有时也是令人惊奇的。很多PHPer通过这一方式来避免使用javascript来验证简单的表单输入。同时使用几种语言是很困难的。而使用XMLHttpRequest并不象人们想象的那么难,你也不需要去为此买一本参看书或者记忆一本参考手册。

    Let's Get To It!
    开始!

    Asynchronous JavaScript and XML, or AJAX is a method of sending and receiving data (usually XML) from a server-side application through javascript. Since javascript offers the ability to change the contents of a web page on-the-fly, this technique allows web programmers to venture closer to programming truly interactive web applications similar to those built with Java and ActiveX.
    Ajax(Asynchronous JavaScript and XML)是通过javascript去请求和获取一个服务器端操作。由于这种功能,javascript可以改变网页中的内容。这种技术使得web程序员可以像Java和ActiveX程序一样进行交互设计。

    As PHP developers, it might seem tempting to avoid the use of Javascript and leave it to the designer. After all, we aren't usually programming the UI, but the processing components required by the UI. The distinction between the two is disappearing. Here's a simple diagram that demonstrates just how AJAX works:
    PHP开发人员更倾向于不使用javascript,而把他交给前台设计人员来处理。毕竟,我们不常对UI进行编码。但AJAX过程中的一些部分是在UI中的。这两者没有什么区别。这里是演示AJAX如何运行的一个简单图表。

    点击查看原始尺寸

    If you're working for a small or medium sized company interested in implementing AJAX solutions, you might end up responsible for figuring out how.
    如果你任职于一家中小型公司,仅仅对AJAX的解决方案感兴趣的话,你可能仅仅能够理解到AJAX是如何工作的而已。

    XMLHttpRequest objects can be a simple way of getting data to and from a PHP application while keeping your client right at home on the same page. Our example today will allow a user to select a specific piece of software that your company makes. We will show a selection box with several categories. When a user selects a category, a request is sent to a PHP application which returns a list of applicable software. The information is used to generate a list of the results underneath the selection box. Since the information is not loaded with the initial page, your company saves bandwidth, and because the user doesn't have to bounce from page to page for results, he will find your company's page more inviting and faster to load.
    XMLHttpRequest对象在客户端的同一页面可以简单的从获得数据后从PHP程序结果。这里的例子允许用户选择贵公司的程序模块。我们通过一个选择框来实现。当用户选择一个种类时,就会发送一个请求到PHP程序,以得到应用程序的列表。这些生成的列表信息属于用户所选择类别之下。由于信息不需要在首次全部载入,这为贵公司省下了流量。对用户来讲,他们不需要在页面间跳来跳去,他们对觉得贵网站很有吸引力,加载也很快。

    Javascript for PHP Programmers
    PHPer需要的Javascript

    Since we'll be working with Javascript, it's good to get a basic tutorial given a background in PHP.
    因为我们需要编写Javascript,先通过PHP背景来了解一下Javascript语言的基础。

    Variables:
    变量:

    Variables in javascript are declared in much the same was as in PHP. To declare a variable in javascript, use the following:
    Javascript中的变量声明与PHP中的很相似。在Javascript中声明一个变量如下:

    var varname = varvalue; //Declaring your variable is not mandatory, but good practice.
    var varname = varvalue; //变量声明不是必须的,但这是一个好的习惯
    


    Control Structures:
    控制结构:
    PHP and javascript have a very similar way of using these as well... You can use if/else statements, switch statements, for and while loops and nested loops all with PHP syntax. If/elseif/else statements are a little different, but not much:
    PHP和Javascript具有非常相似的语法结构,你可以使用PHP语法中的if/else句型,swicth句型,for和while循环和嵌套循环。if/elseif/else句型有一点点区别。

    var variable1 = 1; //Declare a variable.
    if(variable1 == 1){
        // Increment variable value by 1
        variable1++;
        /* The following brings up a message box, a handy way of checking variable values as you
                        go. Be careful not to use these in loops that are too long. */
        alert(variable1);
    }else if(variable1 == 2){ //Elseif's in javascript require a space between the else and if.javascript中Elseif一定需要一个空格
        for(i=0;i < 20;i++){ //For loop.
            variable1++;
        }
            switch(variable1){ //Switch conditional
                   case 22:
                       alert("variable 1 has value of 22!");
                       break;
                   default:
                       alert("didn't have value of 22!");
                break;
        }
    }else{
        alert('The final else statement');
    }
    


    Functions
    函数
    To declare a function in javascript, use the following:
    在javascript中声明一个函数的方式如下:

    function functioname(argument1, argument2, argument3){
        /* Arguments not provided will be null */
        if(argument3 == null){
            return argument1 + argument2
        }else{
            return argument1 + argument2 + argument3
        }
    }
    
    /* And call it with */
    alert(functionname(1, 2)); //returns 3
    /* or */
    alert(functionname(1, 2, 3)); //returns 6
    


    Other than the difference with default values for optional arguments, you should assign a default when a passed argument has a null value.
    和PHP不同的是可选参数,你需要比较它是否是空的,再赋给它一个默认值。

    Using Javascript in a Document:
    在文档中使用Javascript

    Javascript can be included in your document in two ways, similar to CSS inclusion:
    Javascript可以通过两种方式在文档中使用,与CSS很像:

    
    
    
    
    


    The first way is to link to the file directly, and the second is to include it on the page itself. If your code is getting long and is used on multiple pages, it is preferable to use the first method, as the browser will cache the file for future use. And that's all you need to know about Javascript to continue.
    第一种方式是从文件中引用,第二种是在文档自身调用。如果你的代码需要很长后者需要在多个页面中使用的话,最好使用地一种方法,浏览器会缓存这些文件以便将来之用。现在你需要的是继续看下文。

    Developing the Initial Page
    第一个页面
    Below we're going to be creating the page the user loads to view your companies products.
    以下我们准备建立一个用户调用和查看公司产品的页面。

    
        
            CompanyXYZ Software
            
        
        
            
    ^ Please select a category from above.


    The above HTML first links to a javascript file, internal_request.js, and displays a page with two <div> tags, the second of which is where we'll be displaying our data. Go ahead and copy the above code into a file called products.html.
    以上的HTML文件第一行指向了一个Javascript文件,internal_request.js,页面通过两个DIV标签来显示,我们会在第二个标签里显示我们的内容。复制以上代码到一个文件中,保存为products.html

    Creating the XMLHttpRequest Object
    建立XMLHttpRequest对象

    The XMLHttpRequest object works differently in Internet Explorer and Mozilla-like browsers. To create an XMLHttpRequest object in IE, the following can be used:
    XMLHttpRequest对象调用方式在Internet Explorer和Mozilla的浏览器不同,在IE中可以像如下方式使用:
    var request_o = new ActiveXObject("Microsoft.XMLHTTP");
    


    And the following works for supporting browsers other than IE:
    这种方式对其他IE外的浏览器使用:
    var request_o = new XMLHttpRequest();
    


    Determining what browser you are working with and creating the appropriate object is simple:
    兼容代码如下:
    /* The following function creates an XMLHttpRequest object... */
    
    function createRequestObject(){
        var request_o; //declare the variable to hold the object.
        var browser = navigator.appName; //find the browser name
        if(browser == "Microsoft Internet Explorer"){
            /* Create the object using MSIE's method */
            request_o = new ActiveXObject("Microsoft.XMLHTTP");
        }else{
            /* Create the object using other browser's method */
            request_o = new XMLHttpRequest();
        }
        return request_o; //return the object
    }
    
    /* You can get more specific with version information by using
        parseInt(navigator.appVersion)
        Which will extract an integer value containing the version
        of the browser being used.
    */
    


    Copy the above code into a file called internal_request.js, located in the same directory as the products.html file.
    复制以上代码,保存到文件internal_request.js,与products.html放在同意目录。

    We now have a function that will create an XMLHttpRequest object in internal_request.js, and we have an HTML file that calls upon the code in internal_request.js. Remember how we left the product selection <div> in products.html blank? Let's write the code that utilizes our createRequestObject function to get the list of products.
    我们现在已经有了一个可以创建XMLHttpRequest对象的internal_request.js和调用这个JS的HTML文件,注意我们把DIV中的列表留空了。我们来写一段代码利用createRequestObject函数来的得到公司产品列表。

    /* The variable http will hold our new XMLHttpRequest object. */
    var http = createRequestObject();
    
    /* Function called to get the product categories list */
    function getProducts(){
        /* Create the request. The first argument to the open function is the method (POST/GET),
            and the second argument is the url...
            document contains references to all items on the page
            We can reference document.form_category_select.select_category_select and we will
            be referencing the dropdown list. The selectedIndex property will give us the
            index of the selected item.
        */
        http.open('get', 'internal_request.php?action=get_products&id='
                + document.form_category_select.select_category_select.selectedIndex);
        /* Define a function to call once a response has been received. This will be our
            handleProductCategories function that we define below. */
        http.onreadystatechange = handleProducts;
        /* Send the data. We use something other than null when we are sending using the POST
            method. */
        http.send(null);
    }
    
    /* Function called to handle the list that was returned from the internal_request.php file.. */
    function handleProducts(){
        /* Make sure that the transaction has finished. The XMLHttpRequest object
            has a property called readyState with several states:
            0: Uninitialized
            1: Loading
            2: Loaded
            3: Interactive
            4: Finished */
        if(http.readyState == 4){ //Finished loading the response
            /* We have got the response from the server-side script,
                let's see just what it was. using the responseText property of
                the XMLHttpRequest object. */
            var response = http.responseText;
            /* And now we want to change the product_categories 
    content. we do this using an ability to get/change the content of a page element that we can find: innerHTML. */ document.getElementById('product_cage').innerHTML = response; } }


    The above code should be appended to what you already have in the internal_request.js file.
    以上的代码依赖于internal_request.js文件。

    Conclusion
    结论

    We'll followup with the rest of this informative article next week, so be sure to visit us again for the conclusion! btw, don't miss the important Quick Tips listed below!
    剩下的内容我们将在下周进行介绍,记得对本站的继续关注!顺便提一下,不要忘记以下的快速提示。

    Quick Tip 1: (Using the POST method instead of GET):
    The following will send the request to the PHP file using the POST method:
    快速提示1:使用Post方法替代GET
    下面是使用POST方法发送请求的例子:
        http.abort;
        http.open('post',  'back_end.php');
        http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        http.send('arg1=val1&arg2=val2&arg3=val3');
    


    Quick Tip 2: (Parsing XML results):
    快速提示2:(解析XML结果):

    If you're receiving XML instead plain-text results from your processing PHP script, you can use the javascript DOM to parse them. Suppose you receive the following:
    如果你从PHP程序返回XML结果而非纯文本结果,你可以使用Javascript DOM来解析他们。假设你得到了以下结果:
        
            
                EeasySMS
                2.2
            
            
                BabyMon
                1.2
            
        
    


    To receive a DOM compatible response from our XMLHttpRequest object, instead of using the responseText property, substitute the responseXML property. In this case we'll refer to it by assigning it the variable XMLResponse.
    为了使DOM模型可用,需要使用responseXML来替代responseText属性。这是,我们把结果赋给变量XMLResponse。

    The product_list element contains two elements of interest: product elements. In order to get to these, we can use the following:
    product_list元素包含有两个product元素,为了获得他们,可以使用以下代码:
    /* Reference the product_list element to the variable product_list */
    product_list = XMLReponse.getElementByTagName('product_id');
    
    /* By substituting product_list for XMLResponse, we will be searching
        only the product_list element, not the entire response
        We also use getElementsByTagName, not getElementByTagName,
        since we are interested in all of the results, not just one. */
    
    product_id = XMLResponse.getElementsByTagName('product');
    
    /* getElementsByTagName produces an array, which we can access  like this:
        product_id[n], the same way we access an array item in PHP.
        Let's get the id attribute from the product elements like this: */
    
    for(i=0; i < product_id.length; i++){ //length is the same as count($array)
        id = product_id[i].getAttribute('id') //Grabs the id attribute.
        /* To get the text from within a text node, we use firstChild.data
            for the corresponding element. */
        name = product_id[i].getElementByTagName('name').firstChild.data;
        version = product_id[i].getElementByTagName('version').firstChild.data;
    }
    


    This may seem like a bit to work with at first, but with a little work, you can get what you want to work. If you want to avoid this, you could use the responseText method, parsing the XML in PHP before sending it to the XMLHttpRequest object.
    你可以少量的工作来使的这段代码来实现你自己的功能。如果你不想使用他,你可以在返回XMLHttpRequest对象前使用PHP来解析XML文档而使用responseText属性。

    Quick Tip 3: (Relevant Links):
    快速参考3:(相关参考)
    * Microsoft XMLHttpRequest Documentation
    * XMLHttpRequest @ Apple Developer Connection
    * The DOM Model in Mozilla

    About the Author:
    关于作者:
    James Kassemi lives in Albuquerque, New Mexico. He works mainly with PHP, programming for a variety of clients in the southwest.

    翻译:rollenc
    Defined tags for this entry: , , , , , ,

    Posted by rollenc

    Last modified on 2007-01-12 19:09
    2006/09 9



    英文中文




    Optimizing PHP Scripts
    By Leon Atkinson

    June 20, 2001

    One reason I like PHP is that it allows the freedom to quickly create Web applications without worrying about following all the rules of proper design. When it comes to rapid prototyping, PHP shines. With this power comes the responsibility to write clean code when it's time to write longer-lasting code. Sticking to a style guide helps you write understandable programs, but eventually you will write code that doesn't execute fast enough.

    Optimization is the process of fine-tuning a program to increase speed or reduce memory usage. Memory usage is not as important as it once was, because memory is relatively inexpensive. However, shorter execution times are always desirable.

    There are many tips for writing efficient programs, and I can hardly discuss them all here. And anyway, that would be like giving you a fish instead of teaching you to catch your own. This month, I will review the techniques I use for speeding up my PHP scripts.

    When to optimize

    Before you write a program, commit yourself to writing clearly at the expense of performance. Follow coding conventions, such as using mysql_fetch_row instead of mysql_result. But keep in mind that programming time is expensive, especially when programmers must struggle to understand code. The simplest solution is usually best.

    When you finish a program, consider whether its performance is adequate. If your project benefits from a formal requirements specification, refer to any performance constraints. It's not unusual to include maximum page load times for Web applications. Many factors affect the time between clicking a link and viewing a complete page. Be sure to eliminate factors you cannot control, such as the speed of the network.

    If you determine that your program needs optimization, consider upgrading the hardware first. This may be the least expensive alternative. In 1965, Gordon Moore observed that computing power doubled every 18 months. It's called Moore's Law. Despite the steep increase in power, the cost of computing power drops with time. For example, despite CPU clock speeds doubling, their cost remains relatively stable. Upgrading your server is likely less expensive than hiring programmers to optimize the code.

    After upgrading hardware, consider upgrading the software supporting your program. Start with the operating system. Linux and BSD Unix have the reputation of squeezing more performance out of older hardware, and they may outperform commercial operating systems, especially if you factor in server crashes.

    If your program uses a database, consider the differences between relational databases. If you can do without stored procedures and sub-queries, MySQL may offer a significant performance enhancement over other database servers. Check out the benchmarks provided on their Web site. Also, consider giving your database server more memory.

    Two Zend products can help speed execution times of PHP programs. The first is the Zend Optimizer. This optimizes PHP code as it passes through the Zend Engine. It can run PHP programs 40% to 100% faster than without it. Like PHP, the Zend Optimizer is free. The next product to consider is the Zend Cache. It provides even more performance over the optimizer by keeping compiled code in memory. Some users have experienced 300% improvements. Contact Zend to purchase the Zend Cache.
    Measuring performance

    Before you can begin optimizing, you must be able to measure performance. The two tools I'll discuss are inserting HTML comments and using Apache's ApacheBench utility. PHP applications run on a Web server, but the overhead added by serving HTML documents over a network should be factored out of your measurements.

    You need to isolate the server from other activity, perhaps by barring other users or even disconnecting it from the network. Running tests on a server that's providing a public site may give varying results, as traffic changes during the day. Run your tests on a dedicated server even if the hardware doesn't match the production server. Optimizations made on slower hardware should translate into relative gains when put into production.

    The easiest method you can use is insertion of HTML comments into your script's output. This method adds to the overall weight of the page, but it doesn't disturb the display. I usually print the output of the microtime function. I insert a line like:

    print("\n");

    I place these calls to microtime at the beginning, end and at key points inside my script. To measure performance, I request the page in a Web browser and view the source. This produces lines like this:







    The microtime function returns the number of seconds on the clock. The first figure is a fraction of seconds, and the other is the number of seconds since January 1, 1970. You can add the two numbers and put them in an array, but I prefer to minimize the affect on performance by doing the calculation outside of the script. In the example above, the first part of the script takes approximately 0.005 seconds, and the second part takes 0.03.

    If you decide to calculate time differences, consider the method used in the example below. Entries to the clock array contain a one-word description followed by the output of microtime. The explode function breaks up the three values so the script can display a table of timing values. The first column of the table holds the number of seconds elapsed since the last entry.
    //start clock
    $clock[] = 'Start ' . microtime();

    //fake some long process
    sleep(2);
    $clock[] = 'Connected ' . microtime();


    //end clock
    $clock[] = 'End ' . microtime();

    //print clock
    $entry = explode(' ', $clock[0]);
    $lastVal = $entry[1] + $entry[2];
    print('');
    foreach($clock as $c)
    {
    $entry = explode(' ', $c);

    print('');

    print('');
    print('');
    print('');

    print('');

    $lastVal = $entry[1] + $entry[2];
    }
    print('
    ' . ($entry[1] + $entry[2] - $lastVal) .
    '
    ' . $entry[0] . '' . ($entry[1] + $entry[2]) . '
    ');
    ?>

    Inserting HTML comments is my favorite method, because it takes no preparation. But its big weakness is a small sample size. I always try three or four page loads to eliminate any variances due to caching or periodic server tasks.

    The Apache Web server includes a program that addresses this problem by measuring the number of requests your server can handle. It's called ApacheBench, but the executable is "ab". ApacheBench makes a number of requests to a given URL and reports on how long it took. Here's an example of running 1000 requests for a plain HTML document:

    ~> /usr/local/apache/bin/ab -n 1000 http://localhost/test.html

    This is ApacheBench, Version 1.3c <$Revision: 1.1.2.6 $> apache-1.3

    Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/

    Copyright (c) 1998-2000 The Apache Group, http://www.apache.org/

    Server Software: Apache/1.3.19

    Server Hostname: localhost

    Server Port: 80

    Document Path: /test.html

    Document Length: 6 bytes

    Concurrency Level: 1

    Time taken for tests: 5.817 seconds

    Complete requests: 1000

    Failed requests: 0

    Total transferred: 262000 bytes

    HTML transferred: 6000 bytes

    Requests per second: 171.91

    Transfer rate: 45.04 kb/s received

    Connnection Times (ms)

    min avg max

    Connect: 1 1 11

    Processing: 3 3 16

    Total: 4 4 27

    I requested an HTML document to get an idea of the baseline performance of my server. Any PHP script ought to be slower than an HTML document. Comparing the figures gives me an idea of the room for improvement. If I found my server could serve a PHP script at 10 requests per second, I'd have a lot of room for improvement.

    Keep in mind that I'm running ApacheBench on the server. This eliminates the effects of moving data over the network, but ApacheBench uses some CPU time. I could test from another machine to let the Web server use all the system resources.

    By default, ApacheBench makes one connection at a time. If you use 100 for the -n option, it connects to the server one hundred times sequentially. In reality, Web servers handle many requests at once. Use the -c option to set the concurrency level. For example, -n 1000 -c 10 makes one thousand connections with 10 requests active at all times. This usually reduces the number of requests the server can handle, but at low levels the server is waiting for hardware, such as the hard disk.

    The ApacheBench program is a good way to measure overall change without inconsistencies, but it can't tell you which parts of a script are slower than others. It also includes the overhead involved with connecting to the server and negotiating for the document using HTTP. You can get around this limitation by altering your script. If you comment out parts and compare performance, you can gain an understanding of which parts are slowest. Alternatively, you may use ApacheBench together with microtime comments.

    Whichever method you use, be sure to test with a range of values. If your program uses input from the user, try both the easy cases and the difficult ones, but concentrate on the common cases. For example, when testing a program that analyzes text from a textarea tag, don't limit yourself to typing a few words into the form. Enter realistic data, including large values, but don't bother with values so large they fall out of normal usage. People rarely type a megabyte of text into a textarea, so if performance drops off sharply, it's probably not worth worrying about.

    Remember to measure again after each change to your program, and stop when you achieve your goal. If a change reduces performance, return to an earlier version. Let your measurements justify your changes.
    Attacking the slowest parts

    Although there are other motivations, such as personal satisfaction, most people optimize a program to save money. Don't lose sight of this as you spend time increasing the performance of your programs. There's no sense in spending more time optimizing than the optimization itself saves. Optimizing an application used by many people is usually worth the time, especially if you benefit from licensing fees. It's hard to judge the value of an open-source application you optimize, but I find work on open-source projects satisfying as recreation.

    To make the most of your time, try to optimize the slowest parts of your program where you stand to gain the most. Generally, you should try to improve algorithms by finding faster alternatives. Computer scientists use a special notation to describe the relative efficiency of an algorithm called big-O notation. An algorithm that must examine each input datum once is O(n). An algorithm that must examine each element twice is still called O(n) as linear factors are not interesting. A really slow algorithm might be O(n^2), or O of n-squared. A really fast algorithm might be O(n log n), or n times the logarithm of n. This subject is far too complex to cover here -- you will find lots of information on the Internet and in university courses. Understanding it may help you choose faster algorithms.

    Permanent storage, such as a hard disk, is much slower to use than volatile storage, such as RAM. Operating systems compensate somewhat by caching disk blocks to system memory, but you can't keep your entire system in RAM. Parts of your program that use permanent storage are good candidates for optimization.

    If you are using data stored in files, consider using a relational database instead. Database servers can do a better job of caching data than the operating system because they view the data with a finer granularity. Database servers may also cache open files, saving you the overhead in opening and closing files.

    Alternatively, you can try caching data within your own program, but consider the lifecycle of a PHP script. At the end of the request, PHP frees all memory. If during your program you need to refer to the same file many times, you may increase performance by reading the file into a variable.

    Consider optimizing your database queries, too. MySQL includes the EXPLAIN statement, which returns information about how the join engine uses indexes. MySQL's online manual includes information about the process of optimizing queries.

    Here are two tips for loops. If the number of iterations in a loop is low, you might get some performance gain from replacing the loop with a number of statements. For example, consider a for loop that sets 10 values in an array. You can replace the loop with 10 statements, which is a duplication of code, but may execute slightly faster.

    Also, don't recompute values inside a loop. Before the foreach statement appeared in PHP, I often wrote for($i=0; $i

    Function calls carry a high overhead. You can get a bump in performance if you eliminate a function. Compiled languages, such as C and Java, have the luxury of replacing function calls with inline code. You should avoid functions that you only call once. One technique for readable code is to use functions to hide details. This technique is expensive in PHP.

    If all else fails, you have the option of moving part of your code into C, wrapping it in a PHP function. This technique is not for the novice, but many of PHP's functions began as optimizations. Consider the in_array function. You can test for the presence of the value in an array by looping through it, but the function written in C is much faster.


    优化PHP脚本
    作者:Leon Atkinson

    2001年6月20日

    我喜欢PHP的一个原因是我可以在很少的语言规则约束下进行快速的网络应用程序开发。当谈及快速原型时,PHP具有足够的优势。为了让代码具有长久有效性(译者注:是不是指可重用性),我们需要使代码简洁。遵循编码规范可以是你的代码易读,但并不能使你的代码效率提高。



    优化是为了增加速度或减少内存使用的微调过程,内存使用量并不想以前那样重要了,应为现在内存很便宜。而更好的执行效率更让人关注。



    这里有一些的编写高效率代码的提示,我很难在这里一条条列出。授人以鱼不如授人以渔,这个月我将回顾一下我的一直用来加快我的PHP脚本的技术。



    何时优化

    在写代码前,就要告诫自己要编写该效率程序,遵循代码编写惯例,如使用mysql_fetch_row替代mysql_result。紧记程序执行时间是很重要的,另外不要使你的代码很难读懂。越简单越好。




    程序编写完毕时,充分考虑程序的性能. 如果你需要正式确定项目受益,参考一些性能规范。通常不要包含大量的文件,这将花费一些加载时间。排除诸如网速等补课控制的因素外,还有狠斗因素影响了用户点击链接和页面显示的这一过程时间。




    如果你决定去优化你的程序,首先去优化。这是最廉价的方法。在1965年,Gordon Moore提出计算机运行速度每18个月就可以增加一倍。这被称为Moore规律。尽管计算机速度增快,但他的价格也在随时间降低。比如,CPU的主频不断在提升,二价格确一致保持在一定水平。升级服务器比雇佣一个程序员来优化代码要便宜得多。



    升级硬件后,再考虑升级支持你运行的软件。从操作系统升级开始。Linux和BSD Unix在老式硬件的一行效率上比商业操作系统享有很高的声誉。




    如果你的程序使用了数据库,考虑关系数据库将的差别。如果你不打算使用存储过程,MySQL是一个执行效率较高的数据库解决方案。参考一下其他的网站。当然,也要考虑给数据库更大的内存。



    两个Zend产品可以帮助你提高程序的执行效率。一是Zend优化器,优化的代码和Zend引擎优化的结果相同,可以提高PHP40%~100%的执行效率。Zned优化器也是免费的。第二是Zend Cache(直译为高速缓冲存储器,对这个产品不知道是什么)。它将编译后的代码存储在内存中,以提高执行效率。一些有经验的程序员可以使效率提高300%。Zend Cache是Zend公司的商业商品。

    在开始优化前,你需要前分析一下服务器性能。我想讨论的来年改革工具是插入HTML注释和使用Apache的ApacheBench效用。PHP应用程序是在WEB服务器上运行的,而在服务器头部输出传送的HTML文档将超出了的衡量因素。


    你需要从其他应用中隔离你的服务器,可能包括其他用户或断开网络中。
    翻译了这么长了,还没到PHP的优化
    Defined tags for this entry: , , ,

    Posted by rollenc

    Last modified on 2008-12-20 23:07
    2006/09 8
    PHP Optimization Tricks

    PHP优化技巧

    原文地址:http://ilia.ws/archives/12-PHP-Optimization-Tricks.html







    英文 中文
    There are a number of tricks that you can use to squeeze the last bit
    of performance from your scripts. These tricks won't make your
    applications much faster, but can give you that little edge in
    performance you may be looking for. More importantly it may give you
    insight into how PHP internals works allowing you to write code that
    can be executed in more optimal fashion by the Zend Engine. Please keep
    in mind that these are not the 1st optimization you should perform.
    There are some far easier and more performance advantageous tricks,
    however once those are exhausted and you don't feel like turning to C,
    these maybe tricks you would want to consider. So, without further
    ado...



    1)
    When working with strings and you need to check that the string is
    either of a certain length you'd understandably would want to use the
    strlen() function. This function is pretty quick since it's operation
    does not perform any calculation but merely return the already known
    length of a string available in the zval structure (internal C struct
    used to store variables in PHP). However because strlen() is a function
    it is still somewhat slow because the function call requires several
    operations such as lowercase & hashtable lookup followed by the
    execution of said function. In some instance you can improve the speed
    of your code by using a isset() trick.



    Ex.

    if (strlen($foo) < 5) { echo "Foo is too short"; }

    vs.

    if (!isset($foo{5})) { echo "Foo is too short"; }



    Calling isset() happens to be faster then strlen() because unlike
    strlen(), isset() is a language construct and not a function meaning
    that it's execution does not require function lookups and lowercase.
    This means you have virtually no overhead on top of the actual code
    that determines the string's length.



    2) When incrementing or decrementing the value of the variable $i++
    happens to be a tad slower than ++$i. This is something PHP specific
    and does not apply to other languages, so don't go modifying your C or
    Java code thinking it'll suddenly become faster, it won't. ++$i happens
    to be faster in PHP because instead of 4 opcodes used for $i++ you only
    need 3. Post incrementation actually causes in the creation of a
    temporary var that is then incremented. While pre-incrementation
    increases the original value directly. This is one of the optimization
    that opcode optimized like Zend's PHP optimizer. It is a still a good
    idea to keep in mind since not all opcode optimizers perform this
    optimization and there are plenty of ISPs and servers running without
    an opcode optimizer.



    3) When it comes to printing text to screen PHP has so many
    methodologies to do it, not many users even know all of them. This
    tends to result in people using output methods they are already
    familiar from other languages. While this is certainly an
    understandable approach it is often not best one as far as performance
    in concerned.



    print vs echo



    Even both of these output mechanism are language constructs, if you
    benchmark the two you will quickly discover that print() is slower than
    echo(). The reason for that is quite simple, print function will return
    a status indicating if it was successful or not, while echo simply
    print the text and nothing more. Since in most cases (haven't seen one
    yet) this status is not necessary and is almost never used it is
    pointless and simply adds unnecessary overhead.



    printf



    Using printf() is slow for multitude of reasons and I would strongly
    discourage it's usage unless you absolutely need to use the
    functionality this function offers. Unlike print and echo printf() is a
    function with associated function execution overhead. More over
    printf() is designed to support various formatting schemes that for the
    most part are not needed in a language that is typeless and will
    automatically do the necessary type conversions. To handle formatting
    printf() needs to scan the specified string for special formatting code
    that are to be replaced with variables. As you can probably imagine
    that is quite slow and rather inefficient.



    heredoc



    This output method comes to PHP from PERL and like most features
    adopted from other languages it's not very friendly as far as
    performance is concerned. While this method allows you to easily output
    large chunks of text while preserving things like newlines and even
    allow for variable handling inside the text block this is quite slow
    and there are better ways to do that. Performance wise this is just
    marginally faster then printf() however it does not offer nearly as
    much functionality.



    ?><?


    When you need to output a large or even a medium sized static bit of
    text it is faster and simpler to put it outside the of PHP. This will
    make the PHP's parser effectively skipover this bit of text and output
    it as is without any overhead. You should be careful however and not
    use this for many small strings in between PHP code as multiple context
    switches between PHP and plain text will ebb away at the performance
    gained by not having PHP print the text via one of it's functions or
    constructs.



    4) Many scripts tend to reply on regular expression to validate the
    input specified by user. While validating input is a superb idea, doing
    so via regular expression can be quite slow. In many cases the process
    of validation merely involved checking the source string against a
    certain character list such as A-Z or 0-9, etc... Instead of using
    regex in many instances you can instead use the ctype
    extension (enabled by default since PHP 4.2.0) to do the same. The
    ctype extension offers a series of function wrappers around C's is*()
    function that check whether a particular character is within a certain
    range. Unlike the C function that can only work a character at a time,
    PHP function can operate on entire strings and are far faster then
    equivalent regular expressions.

    Ex.

    preg_match("![0-9]+!", $foo);

    vs

    ctype_digit($foo);



    5) Another common operation in PHP scripts is array searching. This
    process can be quite slow as regular search mechanism such as
    in_array() or manuall implementation work by itterating through the
    entire array. This can be quite a performance hit if you are searching
    through a large array or need to perform the searches frequently. So
    what can you do? Well, you can do a trick that relies upon the way that
    Zend Engine stores array data. Internally arrays are stored inside hash
    tables when they array element (key) is the key of the hashtables used
    to find the data and result is the value associated with that key.
    Since hashtable lookups are quite fast, you can simplify array
    searching by making the data you intend to search through the key of
    the array, then searching for the data is as simple as $value =
    isset($foo[$bar])) ? $foo[$bar] : NULL;. This searching mechanism is
    way faster then manual array iteration, even though having string keys
    maybe more memory intensive then using simple numeric keys.



    Ex.



    $keys = array("apples", "oranges", "mangoes", "tomatoes", "pickles");

    if (in_array('mangoes', $keys)) { ... }



    vs



    $keys = array("apples" => 1, "oranges" => 1, "mangoes" => 1, "tomatoes" => 1, "pickles" => 1);

    if (isset($keys['mangoes'])) { ... }



    The bottom search mechanism is roughly 3 times faster.



    If you know or have any additional optimization tricks let me know -).
    这里是几条优化技巧,你可以在你最终优化时用到它们。这些技巧并不是让你的代码变得更快,而只能使代码稍稍的优化一点。更重要的是它可以让你洞察到PHP内在的运行原理,使得ZEND引擎能够更好的对代码进行优化。提醒一下,这不是你在编码开始时就要执行的优化。有一些更简单更快的优化技巧,在使用后,however once those are exhausted and you don't feel like turning to C,
    these maybe tricks you would want to consider. So, without further
    ado...


    1) 当对字符串进行操作时,如果你需要检查字符串是否超过某一长度,你很容易理解如何使用strlen()函数。这个函数执行较快,没有进行任何计算操作,而仅仅返回C结果字符串的长度(在PHP中的变量与C变量内部结构相同)。但是strlen()是一个函数,于其他函数一样,在使用时需要进行几个操作,如全部小写化,函数查找。在某些场合,不可以使用isset()来提高你的代码速度。
    例子:

    if (strlen($foo) < 5) { echo "Foo is too short"; }

    vs.

    if (!isset($foo{5})) { echo "Foo is too short"; }

    调用isset()比strlen()要快,因为isset(0是一种语法结构而不是以个函数。在执行时不需要进行小写化和函数查找。这意味着你并没有真正取得字符串的长度。








    2)使用递增或递减时,$i++比++$i稍慢,和其他语言相比,在PHP是一个特例的,不要在C和JAVA中也使用这个技巧。在PHP中$++比++$i快的原因是$i++进行了四次计算,而++$i进行三次。后缀递加先申请了一个临时变量,然后增加。而前缀递加直接使用了原变量。这也是ZEND的PHP优化器优化的一部分,但这还是一个好的建议,因为并不是所有的优化器都优化了这一点,以及并不是所有ISP都支持优化器。







    3)当需要输出文本时,PHP有很多的方法。很多PHPer并不知道所有的方法,结果PHPers使用了他们以前所习惯的语法。这是可以理解的,虽然这并不是达到所有程序运行的最佳效率。




    print 对 echo

    两者都是语法结构,但print比echo 还是稍稍慢一点。理由很简单,不管是否需要,print会返回一个状态标示,而echo只是简单的输出而不做其他任何事情。而在绝大多数情况下,这个状态标示是没有用到的不必要的花费。





    printf

    使用printf()很慢,我强烈建议不在万不得已的时候不要使用这个函数。printf()对花费函数消耗。printf()是给需要进行参数格式化的情况下使用的。php是类型无关语言,大部分时间用在类型的隐形转化上。调用printf()来格式化字符串需要在字符串中扫描需要被替换的特殊字符,你可以预计的到这样的速度和效率。



    heredoc
    这种输出方式继承自PERL,这也被其他语言所采用。

    没时间翻译了,给个精要得了:
    ?><?
    替代
    ?>
    <?
    这样,PHP在执行时就不需要退出去处理那些空白输出。
    当然,我觉得这个可以直接删掉这一个?><?


















    4)很多脚本都喜欢使用正则表达式来验证用户输入数据,但正则匹配的速度是很慢的,在很多情况下,我们只是验证数据是不是象A-Z,0-9等等。我们可以使用ctype来替代正则。ctype扩展提供了一系列类C的is*()函数,不象C函数一次只能对一个字符进行验证,PHP的ctype函数可以对整个字符串操作,比正则的运行效率要高。
    例子:

    preg_match("![0-9]+!", $foo);

    vs

    ctype_digit($foo);









    5) 另一个PHP常用的操作是数组搜索,这个操作使用正则查找或完全遍历整个数组来实现,这在查找一个大数组或频繁查找时相当耗资源,我们该怎么做呢?你可以使用ZEND引擎技巧来优化它,关联数组元素实质上是以哈希表来存储的。哈希表查询速度是非常快的。所以查找数据可以简单的这样写:$value =
    isset($foo[$bar])) ? $foo[$bar] : NULL;这种查找模式比遍历查找要快,即便是字符关键字比数字关键字占用了更多内存。

    例子:



    $keys = array("apples", "oranges", "mangoes", "tomatoes", "pickles");

    if (in_array('mangoes', $keys)) { ... }



    vs



    $keys = array("apples" => 1, "oranges" => 1, "mangoes" => 1, "tomatoes" => 1, "pickles" => 1);

    if (isset($keys['mangoes'])) { ... }

    下一个查找比上一个要快3倍。








    如果你知道其他的优化技巧,请告诉我 -)
    Defined tags for this entry: , , ,

    Posted by rollenc

    Not modified
    2006/08 18
    Table 8-1. Comparing sequence and communication diagrams
    表8-1. 时间图与交互图比较

    Feature
    特征

    Sequence diagrams
    时间图

    Communication diagrams
    交互图

    The result
    比较结果

    Shows participants effectively

    有效的显示参与者

    Participants are mostly arranged along the top of page, unless the drop-box participant creation notation is used. It is easy to gather the participants involved in a particular interaction.

    如果没有使用构建符号时,参与者被排列在图顶层。很容易知道所有有联系的参与者。

    Participants as well as links are the focus, so they are shown clearly as rectangles.

    参与者被连成链状,在小范围区域内既可清楚的知道参与者间的联系。

    Communication diagrams barely win. Although both types of diagram can show participants as effectively as each other, it can be argued that communication diagrams have the edge since participants are one of their main focuses.

    交互图有些许优势,虽然两者都能有效的显示参与者间的关系,但交互图是以参与者为中心的。

    Showing the links between participants

    显示参与者间的联系

    Links are implied. If a message is passed from one participant to another, then it is implied that a link must exist between those participants.

    联系很隐晦。如果在两个参与者间有消息传递,即暗指两个参与者间有联系。

    Explicitly shows the links between participants. In fact, this is the primary purpose of these types of diagram.

    很清楚的显示了参与者间的联系,事实上,交互图的目的就是为了描述这种联系。

    Communication diagrams win because they explicitly and clearly show the links between participants.

    交互图有优势,因为它可以清楚明白的显示参与者间的关系。

    Showing message signatures

    显示消息

    Message signatures can be fully described.

    消息能够被完整的描述。

    Message signatures can be fully described.

    消息能够被完整的描述。

    Draw! Both types of diagram can show messages as effectively as each other.

    尽管去画,两种图都是有效的。

    Supports parallel messages

    显示并行信息

    With the introduction of sequence fragments, sequence diagrams are much better.

    使用时间小片断可以很好的显示并行信息。

    Shown using the number-letter notation on message sequences.

    使用数字-字母符号可以显示并行信息

    Draw! Both types of diagram show parallel messages equally well.

    尽管去画,两种图都是有效的。

    Supports asynchronous messages (fire and forget)

    支持异步信息

    Achieved using the asynchronous arrow.

    使用异步箭头完成

    Communication diagrams have no concept of the asynchronous message since its focus is not on message ordering.

    交互图并不关心异步信息传递,在交互图中没有异步的概念。

    Sequence diagrams are a clear winner here because they explicitly support asynchronous messages.

    时间图有明显优势,非常好的支持了异步信息。

    Easy to read message ordering

    信息顺序表达

    This is a sequence diagram's forté. Sequence diagrams clearly show message ordering using the vertical placement of messages down the diagram's page.

    这是一个时间图的特点。 时间图明确显示采用垂直图形清楚的现实了信息的顺序。

    Shown using the number-point-nested notation.

    使用数字字母组合符号显示。

    Sequence diagrams are a clear winner here since they really show off message ordering clearly and effectively.

    时间图清楚明白的显示了消息的顺序。

    Easy to create and maintain the diagram

    容易建立和维护

    Creating a sequence diagram is fairly simple. However, maintaining sequence diagrams can be a nightmare unless a helpful UML tool is being used.

    建立时间图是容易的,但是没有好的UML工具的话,维护时间图将是个恶梦。

    Communication diagrams are simple enough to create; however, maintenance, especially if message numbering needs to be changed, still ideally needs the support of a helpful UML tool.

    交互图很容易建立,但如果涉及到信息编号的话还是需要借助于一个好用的UML工具。

    This is a difficult one to judge and is largely based on personal preference. However, communication diagrams do have the edge on the ease-of-maintenance stakes.

    根据个人喜好,两种图优势表现不同。

    原文来源:
    Learning UML 2.0
    By Kim Hamilton, Russell Miles
    ...............................................
    Publisher: O'Reilly
    Pub Date: April 2006
    Print ISBN-10: 0-596-00982-8
    Print ISBN-13: 978-0-59-600982-3
    Pages: 286
    Defined tags for this entry: , , , ,

    Posted by rollenc

    Last modified on 2007-04-27 15:38