防衛的プログラミングの技術

画像






開発者が安全なコードを記述できないのはなぜですか? ここでは、 「クリーンコード」について再度説明しません。 私たちは、純粋に実用的な観点から、ソフトウェアの信頼性とセキュリティということについてもっと話しています。 はい、安全でないソフトウェアはほとんど役に立たないので。 「安全でない」ソフトウェアの意味を見てみましょう。





これは、特に特定のアプリケーションで安全で動作するソフトウェアを作成することがどれほど重要かを理解するのに十分なはずです。 しかし、他の使用例では、ソフトウェアエラーが何につながるかを知る必要があります。



防御的プログラミング(自己テストおよび自己修正プログラムの設計)の最初の知り合い



なぜある種のプロジェクトでこれらの問題を解決するために、防御的な(防御的な)プログラミングが良いアプローチだと思うのですか?

それが起こるので、不可能からあなた自身を守ってください。
「防御(防御)プログラミング」という用語には多くの定義があります。 それらは、 「セキュリティ」のレベルとソフトウェアプロジェクトに必要なリソースのレベルに依存します。

防御的プログラミングは、予期しない状況で一部のソフトウェアの機能が中断されないようにするために設計された、 防御的(防御的)な設計の一形態です。 高可用性、セキュリティ、および信頼性( Wikipedia )が必要な場合、セキュリティプログラミング手法がよく使用されます。
個人的には、このアプローチは、多くの人々が関与する大規模で長寿命のプロジェクトがある場合に推奨されると思います。 また、例えば、重要かつ継続的なメンテナンスを必要とするようなオープンソースプロジェクトにも適しています。



防衛的なプログラミングアプローチを達成することを目的とした、私の簡略化された重要なポイントのいくつかを見てみましょう。



ユーザー入力を信用しない



常にあなたが期待しないものを手に入れることができると仮定してください。 これは、ユーザー入力、または一般的にはシステムに入るすべてに関して、防御的なプログラミングプログラマーとしてのアプローチでなければなりません。 なぜなら、上記のように、不可能は可能だからです。 できるだけ厳しくしてください。 入力値が期待どおりであることを証明します。



画像






最善の防御策は攻撃です。



たとえば、画像の拡張子をチェックするとき、ブラックリストではなくホワイトリストを作成します。無効なタイプはチェックしませんが、実際のタイプはチェックし、他のすべてを除外します。 たとえば、PHP言語では、作業を簡素化するための多くのオープンソーステストライブラリも用意されています。



最善の防御策は攻撃です。 厳しくしてください。



抽象データベースビューを使用する



OWASPによると、ソフトウェアの脆弱性トップ10のうち最初のものはインジェクションです。 これは、誰か(または多くの人)がまだデータベースにアクセスするための安全なツールを使用していないことを意味します。 抽象データベース表現にパッケージとライブラリを使用します。 PHPでは、 PDO (ポータブル分散オブジェクト)を使用して、インジェクションに対する基本的な保護提供できます。



車輪を再発明しないでください



フレームワーク(またはマイクロフレームワーク)を使用していませんか? それでは、おめでとうございます。 これは、フレームワークだけでなく、 すでに行われ、十分にテストされ、数千の開発者によって信頼され、安定して動作するものを簡単に使用できる他の多くの新機能にも適用されます。 ここでは、それを愛するだけでスキルのデモンストレーションを行うことは価値がありません。 自分で何かをする唯一の理由は、存在しないか、存在するものの要件を満たさない(パフォーマンスの低下、特性の欠落など)ことです。



これは、 スマートコードの再利用と呼ばれるものです。 この機会を利用してください。



開発者を信頼しないでください



防御的プログラミングは、運転者が「慎重な」運転と呼ぶものに似ています。 「注意深い」運転では、私たちの周りの誰もが不適切に行動する可能性があると想定しています。 したがって、他者の行動を注意深く監視する必要があります。 開発者として他の開発者のコ​​ードを信頼してはならない場合、防御的プログラミングにも同じことが当てはまります。 独自のコードを信頼するべきではありません。



多くの人が関与する大規模なプロジェクトでは、プログラムを作成および編成するためのさまざまな方法があります。 これは混乱を招き、エラーを引き起こす可能性があります。 そのため、開発スタイルと生活を簡素化するコード品質コントローラーを適用する必要があります。



信頼できるコードを書く



(保護)プログラマーが適切なコード記述することは困難です 。 多くの人はこれを知っており、話しますが、実際には、 信頼できるコードを取得するために十分な注意と努力を気遣う、または努力する人はほとんどいません。



不適切なアプローチの例をいくつか見てみましょう。



これをしないでください:初期化されていないプロパティ



<?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を呼び出す必要があることを覚えておく必要があります。 これは非常に悪いアプローチです。示されている(支払いを行う)ような状態変更操作は、 2つ(またはそれ以上)のパブリックメソッドを使用して2段階で実行しないでください。 多くの支払い方法を使用できますが、 ステータスを変更するための単純なパブリックメソッドは1つだけ必要です (未定義の状態のオブジェクトを見つけることは基本的に受け入れられません)



この場合、 Moneyオブジェクトに初期化されていないプロパティをカプセル化することで、さらに改善しました。



 <?php class BankAccount { public function payTo(Account $to, Money $money) { ... } } $bankAccount->payTo($joe, new Money(100, new Currency('GBP')));
      
      





不適切な処理からプログラムを保護します。 初期化されていないオブジェクトプロパティは使用しないでください。



これをしないでください:クラスのスコープ外に状態をリークします



 <?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();
      
      





この場合、 メッセージは参照によって渡され、結果は両方のケースで「ジョーメッセージ」になります。 解決策は、メーラーコンストラクターでメッセージオブジェクトを複製することです。 しかし、私たちが常にやるべきことは、単純な可変のMessageオブジェクトの代わりに( 不変の値オブジェクトを使用することです。 可能な限り不変オブジェクトを使用します。



 <?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();
      
      





テストを書く



これについて本当に話す必要は本当にあるのでしょうか? 単体テストを作成すると、 強力な接続性、個人の責任、弱い結合、オブジェクトの適切な構成などの一般的な原則を順守するのに役立ちます。 これは、動作する個別の小さなモジュールだけでなく、オブジェクトを構造化する方法もテストするのに役立ちます。 実際、小さな機能をテストし、テストする必要のあるモジュールの数、およびコードテストで100%のカバレッジを得るためにシミュレートする必要のあるオブジェクトの数を明確に確認できます。



結論



記事をお楽しみください。 ここはオファーのみであることを忘れないでください。 それらをいつ、どこで適用するか、まったく適用するかどうかを決定します。



読んでくれてありがとう!



All Articles