设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客

挑刺PHP:全面解析PHP的糟糕设计

2012-4-22 10:25| 发布者: joejoe0332| 查看: 15584| 评论: 1|原作者: OSCHINA|来自: OSCHINA

摘要: 译者注:这篇文章很长,而且可能读起来很乱,很难懂 前言 我的脾气古怪. 我会抱怨很多东西. 这个星球上大多数技术我都不喜欢. PHP不仅使用起来尴尬, 还有要嘛我想要的不适合, 要嘛不是最令人满意, 要嘛违背我的信 ...

函数

>>    函数调用似乎相当昂贵.

>>    一些内建函数与 reference-returning 函数交互, 呃, 一种奇怪的方式.

>>    正如在别处提到的, 很多看起来像函数或者看起来它们应该是函数的东西实际上是语言的构成部分, 因此无法像正常函数一样的工作.

>>    函数参数可以具有 "类型提示", 基本上只是静态类型. 你不能要求某个参数是 int 或是 string 或是 对象 或其它 "核心" 类型, 即使每个内建函数使用这种类型, 可能因为 int 在PHP中不是个东西吧. (查看上面关于 (int) 的讨论). 你也不能使用特殊的被大量内建函数使用的伪类型装饰: mixed, number, or callback.

>>    因此, 下面:

1 function foo(string $s) {}
2   
3 foo("hello world");

    产生错误 the error:

       PHP Catchable fatal error:  Argument 1 passed to foo() must be an instance of string, string given,         called in...

        >>    你可能会注意到 "类型提示" 实际上并不存在; 在程序中没有 string 类. 如果你试图使用         ReflectionParameter::getClass() 动态测试类型提示, 將会得到类型不存在, 使得实际上不可能取得该类型名.

       >>     函数的返回值不能被推断

>>    將当前函数的参数传给另一个函数 (分派, 不罕见) 通过 call_user_func_array('other_function', func_get_args())完成. 但 func_get_args 在运行时抛出一个 fatal 错误, 抱怨它不能作为函数参数. 为什么为什么这是个类型错误? ( 已在 PHP 5.3 中修复)

>>    闭包需要显示的命名每个变量为 closed-over. 为什么解析器不想办法解决? (Okay, it’s because using a variable ever, at all, creates it unless explicitly told otherwise.)

>>    Closed-over 变量, 通过和其它函数参数相同的语义"传递". 这样的话, 数组和字符串等等, 將以传值方式传给闭包. 除非使用 &.

>>    因为闭包变量会自动传递参数, 没有嵌套范围, 闭包不能指向私有方法, 不管是否定义在类中. ( 可能在 5.4 中修复? 不清楚.)

>>    函数没有命名参数. 实际上被 devs 显示拒绝, 因为它 "会导致代码臭味".

>>    Function arguments with defaults can appear before function arguments without, even though the documentation points out that this is both weird and useless. (So why allow it?)

>>    向函数传递额外的参数会被忽略 (除了内建函数, 会抛出异常). 丢失的参数被假定为 null.

>>    "可变" 函数需要 func_num_args, func_get_arg, 和 func_get_args. 这类事情没有语法.

OO

>>    PHP的函数部分被设计成类似C, 但面向对象 (ho ho) 被设计成类似 Java. 我不想过分强调这有多不合谐. 我还没有发现一个有大写字母的全局函数, 重要的内建类使用驼峰式方法命名, 并有getFoo的Java风格的属性访问器. 这是门动态语言, 对吗? Perl, Python, 和 Ruby 都有一些 通过代码访问"属性"的概念; PHP 仅仅有笨重的 __get 之类的东西. 类型系统围绕着低层的 Java语言设计, Java 和PHP's处一时代, Java 有意的做了更多限制, 照搬Java, 我百思不得其解.

>>    类不是对象. 元编程不得不通过字符串名指向它们, 就像函数一样.

>>    内建的类型不是对象, (不像Perl) 也无法使得看起来像对象.

>>    instanceof 是个操作符, 尽管很晚才增加进来, 而大多数语言都建有专门的函数和语法. 受Java影响吗? 类不是第一类? (我不知道它们是不是.)

    >>    但有一个 is_a 函数. 它有个可选参数指定是否允许对象实际是一个字符串命名的类.

    >>    get_class 是函数; 没有 typeof 操作符. 同样有 is_subclass_of.

    >>    然而, 这对于内建类型无法工作, (再一次, int 不是个东西). 这样, 你需要 is_int 等等.

    >>    右值必须是变量或字面量; 不能是表达式. 不然会导致... 一个解析错误.

>>    clone 是一个操作符?!

>>    OO 的设计是一只混合 Perl 和 Java 的怪物.

>>    对象属性通过 $obj->foo, 但类属性是 $obj::foo. 我没见过任何其它语言这样做, 或者这样做有什么用. 

>>    而, 实例方法仍然能通过静态的(Class::method)调用. 如果从其它方法中这么调用, 会在当前 $this 上被看成常规的方法调用. 我认为吧.

>>    new, private, public, protected, static ,等等. 试图虏获 Java 开发者的芳心? 我知道这更多是个人的品位, 但我不知道为什么这些东西在一门动态语言中是必要的 -- 在 C++ 中, 它们中的大多数是有关汇编和编译时的命名决议. 

>>    子类不能覆盖 private 方法. 子类覆盖的公共方法也不可见, 单独调用, 超类的私有方法. 会有问题, 如在测试mocks对象时.

>>    方法无法命名为, 例如 "list" , 因为 list() 是特殊的语法 (不是个函数) , 而解析器会被搞晕. 如此暧昧的原因无从得知, 而类工作得就很好. ($foo->list() 不是语法错误.)

>>    如果当解析构造函数参数时抛出异常(如, new Foo(bar()) 而 bar() 抛出), 构造函数不会被调用, 但析构函数会. (已在PHP 5.3 中修复)

>>    在 __autoload 和解析函数中的异常会导致 fatal 错误.

>>    没有构造器或析构器. __construct 是个初始化函数, 像 Python 的 __init__. 无法通过调用类申请内存和创建对象.

>>    没有默认的初始化函数. 调用 parent::__construct()的时候, 如果父类没定义它自己的 __construct 方法会导致 fatal 错误.

>>    OO 带来了个迭代器接口, 是语言规范的部分(如 ... as ...), 但该接口实际上没有内建实现(如数组) . 如果你想要个数组迭代器,你必须用 ArrayIterator 包装它. 没有内建方式能够让迭代器將其作为第一类对像工作.

>>    类可以重载它们转化成字符串的方式,  但不能重载怎样转换成数字或任何其它内建类型的方式.

>>    字符串, 数字, 和数组都有字符串转换方式; 语言很依赖于此. 函数和类都是字符串. 然而,如果没定义 __toString , 试图將换内建或自定义对像(甚至于一个闭包) 转换成字符串会导致错误, 甚至连 echo 都可能出错.

>>    无法重载相等或比较操作.

>>    实例方法中的静态变量是全局的; 它们的值跨越该类的多个实例共享.

标准库

    Perl "某些需要汇编". Python 是 "batteries included". PHP 是 "厨房水槽, 它来自加拿大, 但所有的水龙头用C贴牌".  

概括

>>    没有类型系统. 你可以编译PHP, 但必须通过 php.ini 指定要加载什么, 选项因扩展部分存在(將它们的内容注入到全局名称空间中)或不存在.

>>    因为名称空间是最近才有的特性, 标准库一点没被打乱. 在全局名称空间中有上千个函数.

>>    库的某些部分很不一致. 

    >>    下划线 对 无下划线: strpos/str_rot13, php_uname/phpversion, base64_encode/urlencode, gettype/get_class

    >>    “to” 对 2: ascii2ebcdic, bin2hex, deg2rad, strtolower, strtotime

    >>    Object+verb 对 verb+object: base64_decode, str_shuffle, var_dump versus create_function,     recode_string

    >>    参数顺序: array_filter($input, $callback) versus array_map($callback, $input), strpos($haystack, $needle) versus array_search($needle, $haystack)

    >>    前缀混乱: usleep vs microtime

    >>    Case insensitive functions vary on where the i goes in the name.

    >>    大概一半的数组函数以 array_ 开头. 剩下的不是.

>>    厨房水槽. 库包括:

    >>    绑定 ImageMagick, 绑定 GraphicsMagick (ImageMagick的派生), 少量的几个函数能检测 EXIF 数据 (其中ImageMagick已经可以做到)

    >>    解析 bbcode 的函数, 一些非常特殊的标记, 被几个少量的论坛包使用.

    >>    太多 XML 包. DOM (OO), DOM XML (not), libxml, SimpleXML, “XML Parser”, XMLReader/XMLWriter, 和一大砣我不能认出的东西就省略了. 当然会有些不同, 你可以自由的弄清晰它们的区别.

    >>    绑定了两个特别的信用卡处理器, SPPLUS 和 MCVE. 什么?

    >>    三种访问 MySQL 数据库的方式:  mysql, mysqli, 和 PDO 抽象的一些东西.


酷毙
1

雷人

鲜花

鸡蛋

漂亮

刚表态过的朋友 (1 人)

  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部