PHP[译] 防守式编程的不二法门

写SOLID代码

这是对一个防守式程序员困难的地点,writing code that doesn’t
suck
。那是成百上千人精通和座谈的事情,但从未人真正关心或投入正确的注意力和努力来实现
SOLID代码

让我们来看有些欠好的事例。

决不:未起首化的性能

<?php

class BankAccount
{
    protected $currency = null;
    public function setCurrency($currency) { ... }
    public function payTo(Account $to,$amount)
    { 
        // sorry for this silly example
        $this->transaction->process($to,$amount,$this->currency);
    }
}

// I forgot to call $bankAccount->setCurrency('GBP');
$bankAccount->payTo($joe,100);

在这种情景下,大家必须记住,为了发出付款,我们需要先调用 setCurrency

这是一个百般不佳的政工,像这么的图景更改操作(发出付款)不应当在多少个步骤使用七个(或六个)公共措施。
我们仍旧能够有诸多办法来付款,可是我们亟须只有一个简便的公家措施,以改变状态(对象应当永远不会处于不一样的状态)。

在这种场馆下,我们得以做得更好,将未开首化的性质封装到 Money
对象中。

<?php

class BankAccount
{
    public function payTo(Account$to,Money$money){ ... }
}

$bankAccount->payTo($joe,newMoney(100,newCurrency('GBP')));

使它万无一失。 并非拔取未起首化的靶子属性

Don’t: Leaking state outside class scope.

毫无:类效能域之外的展露状态。

<?php

class Message
{
    protected $content;
    public function setContent($content)
    {
        $this->content=$content;
    }
}

class Mailer
{
    protected $message;
    public function__construct(Message$message)
    {
        $this->message=$message;
    }
    public function sendMessage(
    {
        var_dump($this->message);
    }
}

$message = new Message();
$message->setContent("bob message");
$joeMailer = new Mailer($message);

$message->setContent("joe message");
$bobMailer = new Mailer($message);

$joeMailer->sendMessage();
$bobMailer->sendMessage();

在这种情景下,消息透过引用传递,结果将在两种情景下都是 “joe
message”
。 解决方案是在 Mailer 构造函数中克隆音信对象。
可是我们相应总是尝试接纳一个(不可变的值对象去顶替一个大概的
Message mutable对象。当您可以的时候使用不可变对象

<?php

class Message
{
    protected $content;
    public function __construct($content)
    {
        $this->content = $content;
    }
}

class Mailer 
{
    protected $message;
    public function __construct(Message $message)
    {
        $this->message = $message;
    }
    public function sendMessage()
    {
        var_dump($this->message);
    }
}

$joeMailer = new Mailer(new Message("bob message"));
$bobMailer = new Mailer(new Message("joe message"));

$joeMailer->sendMessage();
$bobMailer->sendMessage();

为什么开发人士不编写安全代码? 我们不再在此间研商 “绝望的代码
。我们从一个纯粹的角度,软件的安全性来谈谈更多的东西。是的,因为一个不安全的软件几乎是没用的。让大家来探视不安全的软件意味着什么样。

绝不再度造轮子

你绝不框架(或微框架)?
你就是喜欢没有理由的做额外的行事。恭喜您!只假设经过精彩测试、广受看重的稳定的代码,你就足以即便用于各样新特色(不仅是框架)的支付,而不是只因为它是曾经造好的轮子的原故而重新造轮子。你自己造轮子的绝无仅有原因是你需要部分不设有或存在但不相符您的要求(性能欠好,缺少的效应等)。

充分(使用框架)我们称它为智能代码重用,它值得所有。

  • 南美洲航天局的 Ariane 5 Flight 501 在起飞后 40
    秒(1996年7月4日)被毁。10
    亿先令的
    原型火箭是因为机载导航软件中的错误而自毁。

  • 在 20 世纪 80 年代,一个治疗机中决定 Therac-25
    辐射的的代码错误,导致其施用过量的 X 射线致使至少五名患儿去世。

  • MIM-104 爱国者的软件错误造成其系统时钟在 100
    刻钟时段内偏移三分之一秒,以至于无法稳定和阻拦来袭导弹。伊拉克导弹袭击了沙特阿拉伯在达哈兰的一个部队大院(
    1991 年 2 月 25 日 ),杀害了 28 名美利坚同盟国人。

总结

可望你喜爱这篇著作。
记住这一个只是提议,什么日期、什么地方采取这多少个提出,那有赖于你。

应用数据抽象

OWASP
十大安全漏洞

中的第一个是流入。这象征有人(很两人)还平素不使用安全工具来查询他们的数据库。请使用数据库抽象包和库。在
PHP 中你能够利用
PDO
保证基本的流入珍视

那些事例可以让我们认识到编辑安全的软件,特别是在某些意况下是何等首要。在其它应用境况下,我们也相应掌握大家软件错误会带给大家什么。

防守式编程角度一

为啥自己觉着防守式编程在某些品种中是一个意识这个问题的好办法?

守卫不容许,因为不容许将可能发生。

对于防御性编程有无数定义,它还取决于安全性的级别和你的软件项目所需的资源级别。

防守式编程是一种防守式设计,目的在于确保在意想不到的场所下软件的持续性效率,防守式编程实践常被用在高可用性,需要安全的地点—
维基百科

自家个人认为这种措施适合当你处理一个大的、长时间的、有这一个人涉足的花色。
例如,需要大量维护的开源项目。

为了贯彻防守式编程方法,让自己谈谈自己个人简陋的看法。

尚未相信用户输入

假诺你总是会收下你意想不到的事物。那应当是您作为防守式程序员的法子,针对用户输入,或者平日进入你的类其余各个东西。因为大家可以预料到出人意料的,尽量做到尽量严苛。断言)你的输入值是你指望的。

PHP 1

The best defense is a good offense

抢攻就是最好的守护

(将输入)列入白名单而不是把它内置黑名单中,例如,当验证图像扩张名时,不检查无效的项目,而是检查有效的项目,排除拥有其他的品种。
在 PHP 中,也有很多的开源验证库来使你的行事更易于。

出击就是最好的守卫,控制要严加。

毫无相信开发人士

防守式编程可以与称为防御性驾驶的事物有关。在防守驾驶中,我们只要我们周围的每个人都有可能犯错误。
所以大家必须小心旁人的表现。那多少个同样适用于咱俩的防守式编程,作为开发者,我们不应该相信任何开发者。大家也一样不应有相信大家的代码。

在众多少人涉足的大品种中,大家能够有成千上万两样的不二法门来编排和社团代码。
这也恐怕引致混乱,甚至更多的荒唐。
这就是怎么我们归总编码风格和运用代码检测器会使大家的生存越来越自在。

写测试

我们还索要说些什么?
写单元测试将帮扶您坚守共同的规则,如高聚集,单一责任,低耦合和不利的对象组合
它不光扶助你测试小单元,而且也能测试你的目的的社团的主意。
事实上,你会分晓地来看,为了测试你的小功用需要测试多少个单元和你需要效法多少个目标,以贯彻100%的代码覆盖率。

相关文章