我正在阅读如何在PHP中检测文件的编码,在某些博客或某处,有人建议这样做:
if (function_exists('mb_detect_encoding')) {
function is_utf8($str) {
// do stuff using the mb* libraries
}
} else {
function is_utf8($str) {
// do stuff manually
}
}
对我而言,这感觉非常混乱,可以用这个代替:
function is_utf8($str) {
if (...) {
// mb stuff here
} else {
// manual stuff here
}
}
但是,我也可以看到它也有一些好处。根据{{1}}语句的复杂程度以及调用函数的频率,这可能会更有效。我的问题是:你会在什么时候考虑将功能分成两个,就像在第一个例子中一样?我错过了其他任何优点/缺点吗?
修改:请不要挂在这里的例子上,问题是关于这种做法。
答案 0 :(得分:5)
我的直觉反应是使用is_utf8
函数的单个声明。 PHP引擎非常擅长优化,对function_exists()
的多次调用的开销应该可以忽略不计。
答案 1 :(得分:3)
一个好的做法,也许不是那种情况,但通常可能涉及使用工厂方法的OOP(对象)。
class my_utf8
{
// A static method that determine what object to create
public static function factory() {
if (function_exists('mb_detect_encoding')) {
return new my_utf8_with_mb;
} else {
return new my_utf8_without_mb;
}
}
}
class my_utf8_with_mb extends my_utf8 {
public function is_utf8($str) {
// do stuff using the mb* libraries
}
}
class my_utf8_without_mb extends my_utf8 {
public function is_utf8($str) {
// do stuff without the mb* libraries
}
}
在您的申请中:
global $myUtfInstance;
// Call once
$myUtfInstance = my_utf8::factory();
// later and forever...
$myUtfInstance->is_utf8($str);
根据您的操作,您还可能涉及单身模式。它不会跳过IF,但不需要全局变量。
class my_utf8
{
private static $instance;
public static function factory() {
if (function_exists('mb_detect_encoding')) {
return new my_utf8_with_mb;
} else {
return new my_utf8_without_mb;
}
}
public static function getInstance()
{
if (!self::$instance) {
self::$instance = self::factory();
}
return self::$instance;
}
}
在您的代码中:
my_utf8::getInstance()->is_utf8($str);
答案 2 :(得分:2)
在风格上,我倾向于推动第二个。如果性能是一个问题,那么你最好考虑使用第一个。
if (function_exists("sin")) { function baz($farfs) { print "I am the first baz"; } } else { function baz($farfs) { print "I am the second baz"; } } function blarg($fgar) { if (function_exists("sin")) { print "I am the first blarg"; } else { print "I am the second blarg"; } } for ($i=0;$i
我在我的工作站上运行了这个,发现调用baz的总时间占总调用的50-75%到blarg,这取决于被测试的函数是否确实存在。
以下是实际数字:
这两个函数之间的唯一区别是条件和输出中的两个额外字符。有趣的是,10001对function_exists的调用在两次测试中分别只需要0.18和0.11 ms。我想知道是否在某个配置文件中都没有考虑到某些函数调用开销。
至于风格,我真的不喜欢第一个。在两个不同的地方通过名称定义函数似乎是一件很糟糕的事情,特别是当依赖于PHP中的奇怪性时,使得在全局范围内不执行的函数定义无论如何都会影响全局范围。另一方面,我的偏见可能正在显示,并且PHP社区的其余部分可能没有问题,在这种情况下依赖PHP解释器作为一种预处理器。
耸肩这就是风格问题。
答案 3 :(得分:1)
默认情况下,始终使用最易读的解决方案。如果特定的代码片段在您的应用程序中被证明是一个重要的阻力(测量,而不是假设),那么您可以对其进行优化。
答案 4 :(得分:0)
我会提前为最可能非常丑陋的PHP道歉,但我会做更多的事情:
if (function_exists('mb_detect_encoding')) {
function is_utf8_mb($str) {
// do stuff using the mb* libraries
}
}
function is_utf8_manual($str) {
// do stuff manually
}
if (function_exists('is_utf8_mb')) {
function is_utf8($str) {
is_utf8_mb($str)
}
} else {
function is_utf8($str) {
is_utf8_manual($str)
}
}
即:执行环境中将存在is_utf8
变体,仅依赖于它是否可以在该环境中工作。每个变体都在一个最小大小的代码块中,以确定是否应该加载该变量并执行其功能。主要原因是我认为编写函数所需的空间量越小,读者就越容易理解函数的行为。你的眼睛必须减少旅行,你必须少滚动,一般来说,首次理解一个功能所涉及的琐碎挫折通常较少。第二个原因是它提供了一种更好的代码测试方法 - 当你可以同时访问所有代码时,你可以更容易地自动检查is_utf8
变体例程产生相同的结果。
答案 5 :(得分:0)
这里有两个方面:表现(不要为你不需要的东西买单)和可读性。
正如许多明智的海报所说:在被证明是一个问题之前,不要担心表现。
但是关于可读性,在我看来,一个功能应该尽可能少地展示责任。完全一件事的函数最容易理解。
你的问题实际上是关于'我应该如何混合两个责任':
这就是我真正创建两个'层'的原因:一层调度到适当的函数,另一层包含'代码块',包含在一个具有正确名称的函数中。
然后你仍然可以选择是否明确地进行调度,或者使用PHP来实时声明函数。
// functionality: defines how to detect utf8 encoding
//
function is_utf8_mb( $arg ) {
... // using the mb library
}
function is_utf8_bare( $arg ) {
... // hand coded
}
// dispatching layer: decide what library to use
//
// option 1: define on-the-fly
function define_utf8_function() {
if( function_exists('mb_detect_encoding') ) {
function is_utf8( $arg ) { return is_utf8_mb( $arg ); }
} else {
function is_utf8( $arg ) { return is_utf8_bare( $arg ); }
}
}
// option 2: check the dispatching on each function call
function is_utf8_runtimedispatch( $arg ) {
if( function_exists('mb_detect_encoding') )
return is_utf8_mb( $arg );
else
return is_utf8_bar( $arg );
}