Learning

WordPressとオブジェクト指向プログラミング

「WordPressプラグインのOOPな雛形はあるけど、テーマのOOPな雛形って?」とググってみると、英文記事『WP+You+OOP(WP+You+オブジェクト指向プログラミング)』に辿り着いたので、和訳してみた。
現在のWordPressのバージョンに比べると、少し古いのをターゲットにしてるみたいだけど、最新版に読み替えても支障ない…と思う。
また、和訳した本人は「SubVersion」使ってないし、「Sunrise」「Must Use」も使ってないんで、その辺りは、まぁ、ごにょごにょ、と…。


WPに関連付けられてるプログラミングの多くは、本質的にオブジェクト指向ではない。 開発者が自身のブログ向けに書いたテーマモジュールやプラグインの殆どは、その場でのワンオフ関数だったり、コールバック関数に関連付けられてるフィルターやアクションの小さなセットである。
WPが“アプリケーション・フレームワーク”に成熟するにつれて、より良いコード編成である事や保守性が高くある事、そしてオブジェクト指向プログラミングの自己文書力の必要性が、直ちに明白になる。

WPサイトの大半は複雑ではない為、このような議論の対象読者は、少ない。 WPの約99%には、「サイトオーナーが望む事」を機能させる為の、追加のPHPコードを必要としない。
サイトの大半には、Multisiteを使用しない。
サイトの大半には、Web Servicesの必要性がないが、行なってしまう:それらには重労働な、Twitterウィジェットやその類いを、インストールしてしまう。
しかし、WPコアに関与する誰もが、WPの未来になることを望んでいるとは、思わない。
人々がWPの未来について話すとき、任意のwebアプリケーションを実行できる方法について話すが、説得力のある例が未だ多数ではない。

殆ど偶然ではあるが、eMusicがWPの良い実行例だけでなく、アプリケーション・フレームワークとしてのWPを用いたサイトの良い書き方の例になると思う。そして、解読して保守すべきコードの山を理解するのに悪戦苦闘している人の、手助けになる様なコードを組織化する、多くの例を知っている。

より良いオブジェクト指向コードの書き方を掘り下げる前に、まずは、コードベースの組織化方法を把握する必要がある。

セットアップのヒント

  • svn:externals(外部参照)としてWPを起動する:殆ど必須になる。 ディレクトリ構造は、こんな感じ。:
    /index.php
    /wp-config.php
    
    /wp-content/
    /wp-content/themes/
    /wp-content/plugins/
    /wp-content/mu-plugins/ …「Must Use」プラグインを収容
    /wp-content/sunrise.php …
    /wp-content/site-configs/ …サイトconfig
    /wp-content/requests/ …HTTPリクエスト
    
    /wordpress/ …SubVersionで外部参照するWPのコアファイル群を収容する
    	/wp-admin/
    	/wp-includes/
    	/wp-content/
    	/license.txt
    	/readme.html
    	/index.php
    	/wp-activate.php
    	/wp-app.php
    	/wp-blog-header.php
    	/wp-comments-post.php
    	/wp-config-sample.php
    	/wp-cron.php
    	/wp-links-opml.php
    	/wp-load.php
    	/wp-login.php
    	/wp-mail.php
    	/wp-settings.php
    	/wp-signup.php
    	/wp-trackback.php
    	/xmlrpc.php

    SubVersionのプロパティ「svn:externals」でWPをバージョン管理する。

    // サイト・ルートで
    svn propedit svn:externals .
    
    // このコードを追加(ターゲットとしたバージョンの物を指定)
    wordpress http://core.svn.wordpress.org/branches/3.4/

    これは、コアを上書きすることがないので、且つ、コアコードのデバグ中に貴方が追加したどんなハックもチェックインできないので、重要。

    外部参照を利用している為、wp-config.phpに下記の2行を追加する必要がある。:

    define(
    	'WP_CONTENT_URL'
    ,	'http://' . DOMAIN_CURRENT_SITE . '/wp-content'
    );
    
    define(
    	'WP_CONTENT_DIR'
    ,	$_SERVER['DOCUMENT_ROOT'] . '/wp-content'
    );

    こんな感じにindex.phpも変更する必要がある。:

    define(
    	'WP_USE_THEMES'
    ,	true
    );
    
    /**
      * WP環境及びテンプレートをロードする
      */
    require( './wordpress/wp-blog-header.php' );
  • Sunriseを利用する:複数ドメイン型Multisiteを利用している場合、Sunriseは、WPをフックしたり変更するのに、最も筆頭に挙げられる場所である。 wp-config.phpへの記述。:
    define(
    	'SUNRISE'
    ,	1
    );

    次に、ディレクトリwp-contentにファイルsunrise.phpを置く必要がある。

  • サイトconfigを使用する:sunrise.phpを利用する主な用途は、サイト固有の設定コーディングである。 ディレクトリwp-content/site-configsに、global.php(全サイト)、emusic.php(サイト1)、emusic-bbpress.php(サイト2)等のようなファイルを収容する。
  • HTTPリクエストを分離する:ディレクトリwp-content/requestsに、サイトとページ固有HTTPロジックを収容する。 メイン・サイトの大部分は動的であり、Web Servicesからそのデータを移入する為、1つの場所でロジックの全てを編成するのは、理に適っている。
  • “Must Use” プラグインを利用する:アプリケーションに必須のクラスやコードがある場合、ディレクトリwp-content/mu-pluginsに各ファイルを置くだけで、それらを自動ロードできる。 プラグインが追加ファイル群を必要とする場合:それはmu-plugins収容の良い候補ではない。

プラグイン及びテーマのconfigを、クラスを用いてカプセル化する

WPプラグイン・リポジトリの殆どのプラグインは、手続き型コード–関数とグローバル変数の塊–を用いて書かれている(どうしたんだ、Akismet!)。 願わくば、それが悪いアイデアだ、とプログラミングについて、充分に知って欲しい。
1)グローバル変数は、吸い出されて、簡単に上書きされるし。
2)PHPは、関数を多重定義しようとする(同一スコープ内で、同時に同じ名称の関数を宣言する)と、致命的エラーを投げる。

これに対抗し、関数名を保護する必要がある為、殆どの手続き型プラグインの作者は、関数名に識別子を前置して名前空間化する。:

function my_unique_plugin_name_woo_hoo() {
	return 'whatever';
}
// こんな感じでコールする
my_unique_plugin_name_woo_hoo();

プラグイン内のアクション及びフィルターへのコールバック関数の塊を宣言する場合、殆どの手続き型プラグインの作者は、こんな感じにするだろう。:

function my_unique_plugin_name_alter_the_content() { ... }
add_filter(
	'the_content'
,	'my_unique_plugin_name_alter_the_content'
);

function my_unique_plugin_name_red() { ... }
add_filter(
	'the_content'
,	'my_unique_plugin_name_red'
);

function my_unique_plugin_name_green() { ... }
add_filter(
	'the_content'
,	'my_unique_plugin_name_green'
);

function my_unique_plugin_name_blue() { ... }
add_filter(
	'the_content'
,	'my_unique_plugin_name_blue'
);

打って変わってオブジェクト指向アプローチを利用する場合、メソッドとして1つのクラスに全ての関数を追加するので、関数名の名前空間化が不要になり、1つのメソッド“init”にフィルター及びアクションをグループ化できる。:

class MyUniquePlugin {
	function init() {
		add_filter(
			'the_content'
		,	array( $this, 'alter_the_content' )
		);
		add_filter(
			'the_content'
		,	array( $this, 'red' )
		);
		add_filter(
			'the_content'
		,	array( $this, 'green' )
		);
		add_filter(
			'the_content'
		,	array( $this, 'blue' )
		);
	}

	function alter_the_content() { ... }
	function red() { ... }
	function green() { ... }
	function blue() { ... }
}

呼び出し方は、こんな感じ。:

$my_unique_plugin = new MyUniquePlugin;
$my_unique_plugin->init();

メソッド「init」はコンストラクターのように使用するが、__construct()class MyPlugin{ function MyPlugin() {} }の両者には曖昧さがある。 ここで、init()の代わりに__construct()を用いて、PHP5シンタックス天国に至らせるか?
多分できる。
だが、どちらも本当は使いたくない。プラグインクラスは自由に呼び出せる、という印象を与えたくない。
殆どの状況に於いて、プラグインクラスは1度だけ呼び出されるべきであり、このルールはコード中で適用されているべきだ。
Singletonパターンという形で、それをお見せしよう。

Singletonパターン

Singletonパターンとは、GoF(Gang of Four)パターンの1つである。 これは、「あるオブジェクトのインスタンスを、ただ1つのものに制限する」という方法を提供する。:

class MySingletonClass {
	private static $instance;

	public static function get_instance() {
		if( !isset( self::$instance ) )
			self::$instance = new MySingletonClass();    

		return self::$instance;
	}

	private function __construct() {}
}

MySingletonClass::get_instance();

インスタンスの数を1つに制限する事を、何故気にするべきなのか? データベースに接続されるコードをカプセル化する、という或るクラスを考えてみる。
データベース接続がコンストラクター内で行なわれている場合、そのクラスの全インスタンス間で、接続を共有する必要があり、SQLにクエリーする度に、毎回接続を開こうとしてはならない。

WPプラグインクラスでは、コンストラクター或いはメソッドinit()の内部に、アクション及びフィルターの全てを保存したい。 これらのフィルター及びアクションを、1回以上、登録したくない。
プラグインクラスの複数のインスタンスが、欲しい訳でも、必要な訳でもない。
このようなプラグインクラス実装の最適な候補は、Singletonパターンである。:

class MyUniquePlugin {
	private static $instance;

	public static function get_instance() {
		if( !isset( self::$instance ) ) {
			$c = __CLASS__;
			self::$instance = new $c();    
		}

		return self::$instance;
	}

	private function __construct() {}

	function init() {
		add_filter(
			'the_content'
		,	array( $this, 'alter_the_content' )
		);
		add_filter(
			'the_content'
		,	array( $this, 'red' )
		);
		add_filter(
			'the_content'
		,	array( $this, 'green' )
		);
		add_filter(
			'the_content'
		,	array( $this, 'blue' )
		);
	}

	function alter_the_content() { ... }
	function red() { ... }
	function green() { ... }
	function blue() { ... }
}

MyUniquePlugin::get_instance();

// もしくは、クラス呼び出しの値を収容し、後でpublicメソッドをコールする
$my_plugin = MyUniquePlugin::get_instance();

OK、素晴らしい、Singletonで実装し、プラグインをたった1つのインスタンスに制限しよう。 全てのプラグインでこれをしたいが、全プラグインのコードで、繰り返させない方法…即ち、これをするだけで、クラス・メンバー/メソッドが、Singletonで実装される…があれば、素晴らしいのだが。:

private static $instance;

public static function get_instance() {
	if( !isset( self::$instance ) ) {
		$c = __CLASS__;
		self::$instance = new $c();    
	}

	return self::$instance;
}

private function __construct() {}

そうするには、拡張できる基底クラスや中間クラスが必要になる。 基底クラスが、これ。が、いくつか問題が在る。:

class BaseSingleton {
	// $instanceが上書きされるので、これは機能しない
	// BaseSingletonは、サブクラスで毎回インスタンス化される
	private static $instance;

	public static function get_instance() {
		if( !isset( self::$instance ) ) {
			// __CLASS__は、BaseSingletonを参照してる為、これは機能しない
			// ランタイム時点、クラスは未拡張である
			$c = __CLASS__;
			self::$instance = new $c();    
		}

		return self::$instance;
	}

	// 子クラスは、親::__constructを可コールでなければならない為、これは機能しない
	// つまり、親のコンストラクターは、子から可視でなければならない
	// - the child has to have >= visibility
	private function __construct() {} 
}

その問題を、フィックスしてみた。:

class BaseSingleton {
	// __CLASS__(クラスのインスタンス)をkey => valueペアとして収容する
	private static $instance = array();

	public static function get_instance( $c = '' ) {
		if( empty( $c ) ) 
			die( 'クラス名が必須' );

		if( !isset( self::$instance[ $c ] ) )           
			self::$instance[ $c ] = new $c();    

			return self::$instance[ $c ];
		}
	}

	// 拡張クラスにコンストラクターをコールさせる
	protected function __construct() {} 
}

近づいたが、でも手を入れなきゃならない。 PHPのオブジェクト指向機能とPHP5.3での新機能を用いて、Singletonを実装し、望む通りに機能する、基底クラスを作成しよう(こんなハックはしたくない:クラス名::get_instance( 'クラス名' ))。

抽象クラス

抽象クラスとは、インターフェイスの様なものだ。:

abstractと定義されたクラスは、インスタンス化できないし、少なくとも1つのabstractメソッドを備えるクラスは、abstractとしなければならない。 abstractと定義されたメソッドは、メソッド名を宣言するだけになる…実装を定義できないのだ。

抽象クラスから継承する場合、親クラスでabstractと宣言された全メソッドは、子クラスによって定義しなければならない;さらに、これらのメソッドは、同じ(或いはそれ以下に制限された)可視性で定義しなければならない。

例を見て判る様に、BaseClassは、「継承クラスでは何を書くか?」という青写真の提供以外、何もしない。:

abstract class BaseClass {
	protected function __construct() {}

	abstract public function init();     
}

Singletonコードを追加して変更してみよう。:

abstract class BasePlugin {
	private static $instance = array();

	public static function get_instance( $c = '' ) {
		if( empty( $c ) ) 
			die( 'クラス名が必須' );

		if( !isset( self::$instance[ $c ] ) )           
			self::$instance[ $c ] = new $c();    

			return self::$instance[ $c ];
		}
	}

	protected function __construct() {} 

	abstract public function init(); 
}

今や、基底クラスは、下記の性質を備えている。:

  • abstractと宣言し、直接コールできなくなった
  • Singletonコードでカプセル化している
  • クラスのインスタンス内に「key=>value」ペアを収容している(まだ書いてないけど)
  • 継承した子クラスに対して、メソッドinit()を定義する様、指示している
  • コンストラクターを非表示にし、自分自身或いは子クラスからのみコールできる様にした

BasePluginを継承したプラグインの例。:

class MyPlugin extends BasePlugin {
	protected function __construct() {
		 // 親クラスのコンストラクターには、共有コードが含まれているかも
		parent::__construct();
	}

	public function init() {
		// 実装したが、何もしてない
	}
}

// 孤立インスタンスを生成
MyPlugin::get_instance( 'MyPlugin' );

// インスタンスを変数に収容し、後で取得する
$my_plugin = MyPlugin::get_instance( 'MyPlugin' );

ここで起きた事:

  • MyPluginは、BasePluginを拡張し、そのクオリティの全てを継承している
  • MyPluginは、要求されたabstract関数init()を実装している
  • MyPluginは、コンストラクターが保護されている為、キーワードnewでインスタンス化できない
  • MyPluginは、staticメソッドでインスタンス化は可能な為、$thisは自身のメソッド全体を通して利用できる

ここ迄で殆ど出来たが、ハック無し(つまり、クラス名無し)でget_instance()をコールしたい。

遅延静的バインディング(PHP 5.3)

PHP5.3の新関数get_called_class()は、ランタイムに、親クラスのメソッドをコールしている子クラスの名称を取得する。 クラス名は、メソッドが定義されているクラスを用いて解決されるのではなく、寧ろ、ランタイム情報を用いて、解決される。
それはstaticメソッドコールに用いられる様に、“静的バインディング”とも呼ばれる(staticメソッドコールに限定してる訳ではない)。

使い方の簡単な例。:

class A {
	public static function name() {
		echo get_called_class();
	}
}

class B extends A {}

Class C extends B {}

C::name(); // "C"が出力される

get_called_class()はPHP5.3での新関数であり、WPはPHP5.2以上が必要な為、このクラスをこんな感じに実装可能な様にアップグレードする必要があるかもしれない。:

abstract class BasePlugin {
	private static $instance = array();

	public static function get_instance() {
		$c = get_called_class();
		if( !isset( self::$instance[ $c ] ) ) {
			self::$instance[ $c ] = new $c();
			self::$instance[ $c ]->init();     
		}

		return self::$instance[ $c ];
	}   

	protected function __construct() {}

	abstract public function init();      
}

今や、こんな感じに、プラグインをインスタンス化できる。:

// 孤立インスタンスを生成する
MyPlugin::get_instance();

// インスタンスを変数に収容し、後で取得する
$my_plugin = MyPlugin::get_instance();

プラグイン及びテーマの基底クラス

こう言ってる様なもの:プラグイン及びテーマに基底クラスを使用する。 Multisiteを利用していない場合、複数サイト間で共有されるであろう、親テーマと子テーマ間を通じてコードをメンテナンスする際の問題を抱えていないことだろう。
各テーマはファイルfunctions.phpを持ち、私見では、そのファイルは、テーマconfigコード(アクション及びフィルター、等)をカプセル化すべきである。
親テーマと子テーマは、基底クラスとサブクラスに似ている。

自分自身を繰り返したくないので、コードは、別のテーマへとコピー&ペーストで機能性を継承するのではなく、クラスBaseThemeに配置すべきだ。 テーマconfigクラスも、Singletonを実装すべきだ。

eMusicに於いて、テーマ間で共有すべき機能性の1つのピースは、地域化だ。 地域化は、カスタム・タクソノミー“地域”とカスタムアクション及びフィルターを利用する事で、実現される。
テーマを地域化するには、クラスメンバーを上書きし、BaseTheme::regionalize()をコールしなければならない。

クラスBaseTheme。:

abstract class BaseTheme implements Singleton {
	var $regions_map;
	var $regions_tax_map;
	var $post_types = array( 'post' );
	private static $instance = array();

	public static function get_instance() {
		$c = get_called_class();
		if( !isset( self::$instance[ $c ] ) ) {
			self::$instance[ $c ] = new $c();
			self::$instance[ $c ]->init();
		}

		return self::$instance[ $c ];
	}

	protected function __construct() {}

	abstract protected function init();

	protected function regionalize() {
		add_filter(
			'manage_posts_columns'
		,	array( $this, 'manage_columns' )
		);
		add_action(
			'manage_posts_custom_column'
		,	array( $this, 'manage_custom_column' )
		,	10
		,	2
		);
		add_filter(
			'posts_clauses'
		,	array( $this, 'clauses' )
		,	10
		,	2
		);
		add_filter(
			'manage_edit-post_sortable_columns'
		,	array( $this, 'sortables' )
		);
		add_filter(
			'pre_get_posts'
		,	array( $this, 'pre_posts' )
		);
	}

	...
}

それを拡張するテーマ内のファイルfunctions.php。:

if( ! isset( $content_width ) )
	$content_width = 448;

class Theme_17Dots extends BaseTheme {
	function __construct() {
		global $dots_regions_tax_map, $dots_regions_map;

		$this->regions_map = $dots_regions_map;  
		$this->regions_tax_map = $dots_regions_tax_map;          

		parent::__construct();
	}

	function init() {    
		$this->regionalize();

		add_action(
			'init'
		,	array( $this, 'register' )
		);
		add_action(
			'after_setup_theme'
		,	array( $this, 'setup' )
		);
		add_action(
			'add_meta_boxes_post'
		,	array( $this, 'boxes' )
		);
		add_action(
			'save_post'
		,	array( $this, 'save' )
		,	10
		,	2
		);
		add_filter(
			'embed_oembed_html'
		,	'_feature_youtube_add_wmode'
		);
	}

	....
}

“Must Use”プラグイン

class-base-themeclass-base-pluginというファイルにそれぞれBaseThemeBaseClassというクラスが収容されている、と仮定しよう。 次の質問:これらのファイルを何処に配置すべきか?
おそらくwp-content/mu-pluginsに配置するのが最良だろう。
WPブートストラップ・ルーチンは、そのディレクトリー内のファイルを自動的にロードする。
クラスBaseThemeは、そのファイル内で即座には発動されないので、functions.php内の子クラスを拡張する為に、そのファイルをロードするだけで、テーマに対してクラスを利用できる。

Sunrise

sunrise.phpは、ネットワーク全体のfunctions.phpと見做せる。 $current_blog及び$current_siteのコンテクストをスイッチさせるのとは別に、アクション及びフィルターの追加も開始できる。

この機会を利用して、eMusic sunrise.phpでは、どのサイトにどのプラグインがロードされるのか、そして全サイトにどのプラグインがロードされるのかを主にフィルタリングする、“サイトconfig”をロードしたい。 これを実現するには、こんな感じで“グローバル”config及び各サイト用configが必要になる。:

require_once( 'site-configs/global.php' );

if( get_current_blog_id() > 1 ) {
	switch( get_current_blog_id() ) {
	case 2:
		require_once( 'site-configs/bbpress.php' );
		break;

	case 3:
		require_once( 'site-configs/dots.php' );
		break;

	case 5:
		require_once( 'site-configs/support.php' );
		break;
	}

	add_filter(
		'pre_option_template'
	,	function () {
			return 'dark';
		}
	);
} else {
	require_once( 'site-configs/emusic.php' );
}

サイトConfigs

グローバル・サイトconfigでは、アクティブなネットワーク・プラグインをフィルタリングしたい。 以前の記事やプレゼンテーションで述べてる様に、「データベース上のアクティブ・プラグインは、正しいのだ」に頼る事は危険であり、環境間の同期を維持するのは難しい。

サイトオプションactive_sitewide_pluginsをフィルタリングする事で、アクティブなネットワーク・プラグインをフィルタリングできる。:

add_filter(
	'pre_site_option_active_sitewide_plugins'
,	function () {
		return array(
			'batcache/batcache.php'                         => 1
		,	'akismet/akismet.php'                           => 1
		,	'avatar/avatar.php'                             => 1
		,	'bundle/bundle.php'                             => 1
		,	'cloud/cloud.php'                               => 1
		,	'download/download.php'                         => 1
		,	'emusic-notifications/emusic-notifications.php' => 1
		,	'emusic-ratings/emusic-ratings.php'             => 1
		,	'emusic-xml-rpc/emusic-xml-rpc.php'             => 1
		,	'johnny-cache/johnny-cache.php'                 => 1
		,	'like-buttons/like-buttons.php'                 => 1
		,	'members/members.php'                           => 1
		,	'minify/minify.php'                             => 1
		,	'movies/movies.php'                             => 1
		,	'shuffle/shuffle.php'                           => 1
		,	'apc-admin/apc-admin.php'                       => 1
	//	,	'debug-bar/debug-bar.php'                     => 1
		);
	}
);

このマナーでプラグインをフィルタリングすることで、大きく2つの事が可能になる。:

  • コメント/アンコメントで、プラグインをOFF/ONできる
  • ネットワーク・プラグインの基本セットを、adminやデータベースを開かずに、視覚的に確認できる

site-configs/global.phpには他にも色々あるが、主に、1つの組織化されたマナーで、複数クラスのロード方法をデモンストレーションしたい。 サイト固有configでは、そのサイトでのみアクティブなプラグインをフィルタリングする。

メインeMusicテーマでは、こんなプラグインを利用している。:

add_filter(
	'pre_option_active_plugins'
,	function () {
		return array(
			'artist-images/artist-images.php'
		,	'catalog-comments/catalog-comments.php'
		,	'emusic-post-types/emusic-post-types.php'
		,	'discography.php'
		,	'emusic-radio/emusic-radio.php'
		,	'gravityforms/gravityforms.php'
		,	'super-ghetto/super-ghetto.php'
	//	,	'theme-check/theme-check.php'
		);
	}
);

これは、自分自身を繰り返していない、もう1つの例。 オブジェクト指向マナーで全ての物を考えると、全ての物はよりクリーンに、より組織化されたものになる。

HTTPリクエスト

コードを組織化すべきもう1つのエリアとは、HTTPリクエストの周辺だ。 WPでは、“ページ”は、データベースからだけでなく、リクエスト変数に基づくWeb Serviceの組み合わせから、コンテンツを介して取り込まれる。

以下のファイルを利用している。:

// 基底クラス
/wp-content/mu-plugins/request.php 

// Factoryパターンを実装するテーマクラスを拡張したテーマ『dark』
/wp-content/requests/dark.php

// テーマクラスは、特定のページで要求された際に、リクエストクラスをロードする
/wp-content/requests/home.php
/wp-content/requests/album.php
/wp-content/requests/artist.php
... etc ...

1つの例として、アルバムページは、AlbumRequestをロードする。:

class AlbumRequest extends RequestMap { ... }

class RequestMap extends API { ... }

// CURLを実装したAPIクラス
class API {}

// curl_multi()等、cURL PHP エクステンションを実装
class CURL {}

HTTPファイルの組織化は、アクションでのオブジェクト指向原則の一例であり、WPでは指定されていない手段で、コードベースを組織化する方法が含まれている。

これは、オブジェクト指向プログラミングの自己文書化性の一例でもある。 アルバムページに固有のリクエストを扱うAlbumRequestは、cURLを実装するPHPコアAPIのメソッドをコールするRequestMapの機能性を継承している。

結論

願わくば、これを最後迄読むと、オブジェクト指向マナーでコードを組織化する事の利点が、クリアに見えてくる事だろう。 オブジェクト指向の基本は、この記事の範囲外であるが、スキルにバラツキがあるメンバーの居るチームで働く開発者にとって、特に学ぶべき不可欠な物である。

組織化され、読解し易いコードは不可欠な物であり、コンピューター・プログラミングの歴史から、パターンの利用は、その手助けになる。

広告