Apex コードの概要

摘要

Force.com Apex コードは、Force.com プラットフォーム上で実行する、強い型付けのプログラミング言語です。この Apex コードでは、アプリケーションにビジネスロジックを追加したり、データベーストリガを記述したり、ユーザインターフェース層のコントローラを作成したりできます。また、データベースやクエリ言語との緊密な連携を実現しているほか、Web サービスに対応しています。さらに、マルチテナント環境での利用を促進する future やガバナなどの機能も備えています。

このドキュメントでは、Apex コードの概要を紹介します。まず構文について簡単に説明した後、データベースのサポート、テスト、Web サービス、ダイナミック Apex などのトピックを順に取り上げます。最後に、Force.com プラットフォーム上で Apex コードを実行することによりもたらされる DaaS (Development as a Service: サービスとしての開発) をはじめとするメリットについて説明します。

このドキュメントをご一読いただくことで、Apex コードの概要と Force.com プラットフォームでの基本的な使用方法を理解できます。

構文

Java や C# でのプログラム経験があれば、Apex の構文は容易に理解できます。Apex は、クラス、インターフェース、定数、クラス変数、アノテーションなどの一連の標準的な機能を備えています。ただし、一般的なプログラミング言語と異なり、大文字と小文字は区別しません。

クラスとインターフェース

次に、インターフェースとインターフェースを実装するクラスが記述された簡単な例を示します。
  
public interface PurchaseOrder {
  Double discount();
}

public class CustomPurchaseOrder implements PurchaseOrder {

  static final Integer DEFAULT_DISCOUNT = .05;
	  
  public Double discount() { 
    return DEFAULT_DISCOUNT; 
  } 
	
} 

インターフェースの実装には implements キーワードを使用します。 static キーワードはクラスのインスタンスを使用せずにアクセスできるクラス変数 (またはメソッド) であることを示します。また、final キーワードは定数であることを示します。


new キーワードを使用すると、クラスのインスタンスを作成できます。次に例を示します。

PurchaseOrders po = new CustomPurchaseOrder();

thisinstanceOf などの Java に類似したキーワードもサポートしています。

プリミティブデータ型

Apex では、次のようにさまざまなデータ型をサポートしています。

  • Integer、Date などのプリミティブデータ型
  • 永続オブジェクトであることを示す sObject 型
  • コレクション型、列挙型
  • ユーザまたはシステムによって定義された Apex クラス

プリミティブデータ型には次のようなものがあります。

  • Blob (バイナリデータを格納)
  • Boolean
  • Date、Time、Datetime
  • Decimal (通貨などの任意精度の数値用)
  • ID (Force.com データベースレコードの識別子型)
  • Integer、Long、Double、String

次のコードは、プリミティブデータ型の変数の定義方法の例を示しています。

DateTime dt = System.now() + 1;
Boolean mustI = true;
String s = 'abc'.toUpperCase();
Decimal d = Decimal.valueOf('123');

String データ型では、二重引用符ではなく一重引用符が使用されている点に注意してください。

コレクション型

Apex では、列挙型および Set、List、Map などのコレクション型をサポートしています。使用方法はきわめて簡単であるため、ここではいくつかの例を使って説明するにとどめます。コレクション型の最初の要素のインデックス位置が 0 になる点に注意してください。

Set は、プリミティブ型の集合であり、順序の指定はなく、要素の重複は許されません。

Set<String> s = new Set<String>{'a','b', 'c'}; 
s.add('c');
System.assert(s.contains('b'));
System.assert(s.size() == 3);

List は、要素の集合です。要素間の順序を保持したい場合に使用します。要素の重複は許されます。

List<Integer> myList = new List<Integer>();
myList.add(47);
myList.get(0);

また、List では配列構文を使用できます。次に例を示します。

String [] colors = new List<String> ();
colors[3] = 'Green';

Map は、キーと値のペアの集合です。作成時にはショートカット構文を使用できます。

Map<String,String> myStrings = new Map<String,String>{'a'=>'b','c'=>'d'.toUpperCase()}; 
Map<ID,Contact> m = new Map<ID, Contact>([select id, lastname from contact]); 

最後のステートメントには、データベース連携の処理が記述されています。対象の Contact オブジェクトから、id 項目および lastname 項目の値のみを取得しています。

続いて、列挙型の例を取り上げます。次のコードでは、Season という新しいデータ型を作成し、このデータ型の変数を宣言して値を代入します。

public enum Season {WINTER, SPRING, SUMMER, AUTUMN}
Season s = Season.AUTUMN;

ステートメント、式

すでに先ほどのセクションでステートメントや式をいくつか見てきましたが、もう少し例を挙げて説明します。

Integer count = 1; 
while (count < 11) { 
  System.debug(count); 
  count++; 
} 
for (Integer i = 0, j = 0; i < 10;i++){ 
  System.debug(i+1); 
}  
Integer[] myInts = new Integer[]{1,2,3,4,5,6,7,8,9,10}; 
for (Integer i : myInts) { 
  System.debug(i); 
} 

このコードの最後の for ループは、コレクションに対する反復処理を定義しています。Apex は、クエリによって返された永続的な sObject レコードに対して反復処理を行う特殊なループ処理もサポートします。次に例を示します。

String s = 'Acme'; 
for (Account a : [select id, name from account where name like :(s+'%')]){ 
  //Your code 
} 

角かっこでくくられたクエリや、変数 s の参照の実行方法に注意してください。

例外

Apex では、throwtrycatchfinally などの標準的なステートメントを使用して例外を処理します。次に例を示します。

try { 
  throw new Exception();
} catch(ListException e) { 
  //List Exception handling code here 
} catch(Exception e) { 
  //Generic exception handling code here 
}

その他の構文

Apex は 2 種類のアノテーションをサポートしています。1 つは @future で、非同期的に実行されるメソッドを示します。もう 1 つは @isTest で、これはすべてのメソッドがテストメソッド (後述) であることを示すクラスアノテーションです。

次の例では、@future を使用して Web サービスの非同期な呼び出しを行っています。

@future(callout=true) 
public static void doCalloutFromFuture(){ 
    //Executes when the platform has resources
} 

なお、カスタムのアノテーションを作成することはできません。

Apex はプロパティの短縮構文もサポートしています。たとえば、任意の変数と、その変数の getter メソッドと setter メソッドを宣言するには、次のように記述します。

	
public Integer prop { 
  get { return prop * 2; }
  set { prop = value; } 
}

ここで短縮構文を使用すると、プロパティの定義を以下のように簡素化できます。

public Integer anotherProp {get;set;} 

データベース連携

Apex は、Force.com の永続層であるデータベースと緊密に連携しています。このセクションでは、Apex を使用してデータベースオブジェクト (sObject) を作成、保持、更新する方法と、データベースクエリを実行し、その結果に対して反復処理を行う方法を説明します。そのほか、データベーストリガの記述方法についても触れます。Force.com データベースとそのサービスに関する包括的な情報は、 An Introduction to the Force.com Database (Force.com データベースの概要) を参照してください。

sObject の操作

「sObject」とは、Force.com プラットフォームのデータベースに保存できるすべてのオブジェクトのことを指します。これは、「Apex クラスのインスタンス」という意味でのオブジェクトではなく、永続的に保持されるデータの表現です。

Apex コードでは、このような永続オブジェクトを第一級オブジェクトとして扱えるため、データベースの連携処理をきわめて直観的かつ簡単に行うことができます。

「sObject」は、永続性を備えたあらゆるオブジェクト型で使用できる汎用的な抽象型の名称でもあります。たとえば、namebillingcity という項目を持つ sObject Account がデータベース内に存在する場合、次のいずれの行を実行しても、sObject が作成されます。

sObject s = new Account();
Account a = new Account( name='Acme', billingCity='Edinburgh');

後ろの行では、オプションとして項目の初期値が設定されています。Apex では、ドット (.) 表記を使用してオブジェクト内の項目に容易にアクセスすることができます。たとえば次の例は、Account オブジェクトの ID と文字列を返します。

ID id = a.ID;
String x = a.name;

なお、ダイナミック Apex では弱い型付けの構文を使用することができます。たとえば、直前の例の最後のステートメントは、次のように書き換えることができます。

String x = a.get('name');

クエリと埋め込みクエリ

Force.com プラットフォームでは 2 種類のクエリ言語をサポートしています。

  • Salesforce Object Query Language (SOQL) - クエリ専用の言語です。SQL に似ている面もありますが、結合ではなくリレーションを使用するオブジェクトクエリ言語である点が異なっており、データをより直観的に操作することができます。後ほど、具体的な例をご紹介します。
  • Salesforce Object Search Language (SOSL) - すべての永続オブジェクトを対象に検索を実行するシンプルな言語です。

両言語とも Apex コードに埋め込むことが可能であり、データを簡単に取得できます。たとえば、次のコードでは、name 項目の値が Acme である sObject (データベースのレコード) を 1 件取得します。

sObject s = [select id, name from account where name='Acme'];

次のコードは、条件に一致するすべての Account レコード (0 件、またはそれ以上存在すると仮定) を取得し、リストに代入します。

String myName = 'Acme';
Account [] accts = [select ID from Account where name=:myName]; 

次のコードは、条件に最初に一致した Accout レコードを取得し、その annualRevenue 項目の値を変数に代入します。

Double rev= [select annualRevenue from Account where name = 'Acme'][0].annualRevenue; 

Account と Contact など、2 つの sObject がリレーションを持つ場合は、ドット (.) 表記を使用して、クエリでリレーションをトラバースできます。たとえば、次のコードは、sObject Contact から、リレーション関係にある sObject Account の名前を取得します。

Contact c= [select Account.name from Contact where id =:id];

SOSL ステートメントは、sObject のリストにもとづいて sObject の型ごとに検索結果を格納したリストを返します。たとえば、すべての Account レコードと Contact レコードを対象に name 項目を検索するステートメントは以下のようになります。

List<List<SObject>> searchList= [FIND 'map*' IN NAME FIELDS RETURNING Account (id, name),Contact]; 
Account [] accounts= ((List<Account>)searchList[0]); 
Contact [] contacts= ((List<Contact>)searchList[1]);

クエリを、特殊な for 構文に埋め込むこともできます。この構文は、返されたレコードに対するループ処理にも使用できます。次に例を示します。

for (Account[] tmp : [select id from Account where name= 'yyy']){ 
   j = tmp.size(); 
  // perform some actions on the accounts
}

トリガ

Apex でトリガを記述して、sObject に対する挿入、更新、削除、復元などのイベントの前後に実行することができます。トリガは、次に示すように、冒頭にキーワード trigger を設定して作成します。構文は比較的容易です。

trigger myAccountTrigger on Account (before insert, before update) { 
  if (Trigger.isInsert) {
   //
  } 
  if (Trigger.isUpdate) {
    for(Account a: Trigger.new)
      if (a.name == 'bad') 
        a.name.addError('Bad name'); // prevent update
     }
}

上記のコードは、sObject Account が挿入、更新される直前に実行されます。Trigger.new コンテキスト変数は、挿入、更新対象の Account のリストへのアクセスに使用されます。更新トリガや削除トリガでは、Trigger.old を使用することで、更新または削除の対象となった sObject の古いバージョンを参照できます。

トリガでは Apex を柔軟に利用できるため、ユーザは使い慣れた言語でそのままデータを操作できます。ただし若干の制限事項があり、たとえば、トリガからの Web サービスの呼び出しは、トランザクションが必要以上に増大するという理由から許可されていません。

DML (Data Manipulation Language: データ操作言語)

Apex では、DML を使用してデータベース内のデータの検索、挿入、削除、更新処理を実行できるほか、保存ポイントの作成や編集も行えます。次に例を示します。

Account[] accounts = new account[] {new Account(name='foo'), new Account(name='bar')};
insert accounts;
Savepoint sp = Database.setSavepoint(); 
delete accounts;
Database.rollback(sp);

テスト

Force.com プラットフォームでは、運用環境にコードを実装する要件として、Apex クラスに対して 75% 以上のテストカバレッジの達成を求めています (理想的には 100% が望ましいと言えます)。そのため、Apex での開発は、通常、単体テストの進展状況を確認しながら進めます。このような制約は、Developer Edition 組織には適用されません。

Apex では、テストメソッドは testMethod キーワードによって表します。次に、テストメソッドを含んだクラスの例を示します。

public class myClass {
  static testMethod void myTest() {
    Account a = new Account(name='foo');
    insert a;
    System.assertEquals('foo', [select name from Account where id=:a.id].name);
    System.assertEquals(1, [select count() from Account where id=:a.id]);
    try {
      delete a;
      Foo.myMethod(a); //call some method
    } catch (DmlException e) {
      System.assert(false);  // assert that we should never get here
    }
 }
}

一般に、こうしたテストでは System.assert() メソッドを使用してコードの動作をチェックし、例外を検出します。

Apex による Visualforce コントローラの作成

「Visualforce」は Force.com プラットフォームのユーザインターフェース層です。Visualforce では、MVC (Model-View-Controller: モデル-ビュー-コントローラ) パラダイムを採用しており、ブラウザなどから受信した Web 要求をコントローラに転送して処理を行い、作成したユーザインターフェース上に結果を表示することができます。

Visualforce のコントローラと拡張機能は、Apex で記述する必要があります。Apex で記述したコントローラは、このドキュメントの他のセクションで取り上げている Apex コードと一見同じように見えますが、より多くのデータ型、クラス、メソッド、プロパティにアクセスできます。たとえば、ページのパラメータにアクセスすることなどが可能です。また Visualforce ページはそれ自体が Apex における第一級オブジェクトであるため、さまざまなページにリダイレクトしたり、ページを PDF として表示したり、電子メールを Blob として作成したりできます。

シンプルなコントローラの例を次に示します。

 public class MyController { 
   PageReference where;
   public PageReference dynamicJump() {
     if (ApexPages.currentPage().getParameters().get('p') != null) {
       where = Page.foo;                                           
       where.setRedirect(true);
     } else {
       where = Page.bar;
       where.getParameters().put('p', 'nowHasParam');
     }
     return where;
 }

PageReference は Visualforce ページのデータ型を示します。上記のコードは、現在のページのパラメータを検証し、その結果によって 2 つのページのいずれかへのリダイレクトを実行します。このようなコントローラでは DML も実行可能です。たとえば、データベースをクエリして結果を返す処理を実装できます。

Web サービス

Apex を使用すると、外部の Web サービスを呼び出したり、メソッドを外部から利用可能な Web サービスエンドポイントに公開したりといった作業を容易に実行できます。

Web サービスの公開

Apex では、メソッドをカスタムの Force.com Web サービス API コールとして公開することも、外部のアプリケーションから呼び出せるようにすることも簡単です。たとえば、次のコードは、webService キーワードを使用してメソッドをサービスとして公開します。

global class MyWebService { 
  webService static Id makeContact(String lastName, Account a) { 
   Contact c= new Contact(lastName= 'Weissman',AccountId = a.Id); 
   insert c; 
   return c.id; 
  } 
} 

global アクセス修飾子はすべての Apex コードがこのクラスに一様にアクセスできることを宣言します。なお、Web サービスを使用するクラスはすべて global クラスとして定義する必要があります。

Force.com プラットフォームでは、Web サービスを簡単に使用できます。Web サービスを呼び出すには、そのサービス用の WSDL を自動生成します。まず、Force.com Builder 環境で該当のクラスを表示し、クラス名を選択して [WSDL の作成] ボタンをクリックします。その後、生成された WSDL ドキュメントを指定言語にフィードし、Force.com プラットフォームの Apex Web サービスとして呼び出します。

外部 Web サービスの呼び出し

Force.com プラットフォームでは、Apex を自動生成して外部の SOAP Web サービスを簡単に呼び出すことができます。これを行うには、Force.com Builder 環境を使用して、アクセスしたい外部 Web サービスの WSDL を Force.com プラットフォームにフィードします。

具体的には、[設定]、[開発]、[Apex クラス] の順にメニューを選択し、[WSDL からの生成] ボタンをクリックして表示されたウィザードで WSDL ドキュメントを指定します。続いて、Force.com プラットフォームにより WSDL のアップロードと解析が行われ、その WSDL にサポート対象のスキーマや型が含まれている場合は、生成された Apex クラスを使用して必要な Web サービスを呼び出すことができます。

外部の Web サービスを呼び出すコードの例を次に示します。

AcmeServices.grabService gs = new AcmeServices.grabService(); 
String result = gs.doLookup('some data');

ご覧のように、標準的な Apex コードが使われています。WSDL ドキュメントから Apex クラスを生成する手間のかかる手順は、Force.com プラットフォームによって自動的に処理されます。

ダイナミック Apex

ダイナミック Apex には、動的に実行されるプログラムを作成する 2 つの仕組みがあります。ひとつは、実行時に sObject の内容を分析し、得られた情報を使用して特定のオブジェクトに対して動的に処理を行う方法、もうひとつは、動的な SOQL や SOSL クエリを記述して、実行時にクエリを生成する方法です。それでは、この 2 つの方法を順に解説します。

sObject の内容の分析

sObject にはオブジェクトの名前、項目の名前と型、項目のデフォルト値などのメタデータが格納されますが、こうしたメタデータ情報を分析し、取得された結果に応じて異なる動作を実行するコードを作成できます。この分析は、コンパイル時および実行時のタイミングで行うことが可能です。

コンパイル時の処理では、sObject のメタデータ情報を表すトークンを作成します。トークンは軽量でシリアル化が可能であるため、さまざまなプログラミング要件に対応します。次の例は、sObject または sObject のリストが特定のデータ型を含んでいるかどうかを判定します。

//Create a generic sObject variable s 
SObject s = [select id from account limit 1];  
//Verify if that sObject variable is an Account token 
System.assertEquals(s.getSObjectType(), Account.sObjectType); 
//Create a list of generic sObjects 
List<sObject> l = new Account[]{}; 
//Verify if the list of sObjects contains Account tokens 
System.assertEquals(l.getSObjectType(),Account.sObjectType);

同様に、次のようなコードにより、sObject の項目 (この例では AccountNumber) に対するトークンを取得できます。

Schema.SObjectField F = Account.AccountNumber;

コンパイル時にトークンを作成するのではなく、実行時に一連の getDescribe() メソッドを呼び出して、sObject の内容を分析することもできます。次の例では、Industry という選択リスト項目を持つ Account オブジェクトがある場合に、選択リストの値や、そのオブジェクトのすべての子オブジェクトを取得します。

Schema.DescribeFieldResult f = Account.Industry.getDescribe(); 
List<Schema.PicklistEntry> p = f.getPicklistValues();  
List<Schema.ChildRelationship> c = f.getChildRelationships();

この処理では、非常に包括的な情報を取得できます。たとえば、項目を例にすると、含まれる値は ID なのか名前なのか、空白値は許可されるか、一意でなければいけないか、大文字と小文字は区別するか、どのレベルの精度が求められるか (Double 型の場合) といった、あらゆる情報を収集できます。

動的なクエリ

このドキュメントの他のセクションでは、主に次に示すようなコンパイル時のクエリを取り上げていますが、実行時に Apex で SOQL 文を生成することによって、動的なクエリが可能になります。

Contact c = [select Account.name from Contact]; 

組織の設定で動的クエリの機能が有効化されている場合は、データベースに対して query() メソッドを呼び出し、文字列 (文字列も動的に作成することが可能) を渡すことで、動的なクエリを作成できます。次に例を示します。

sObject c = Database.query('select Account.name from Contact limit 1');

SOSL についても同じ方法で動的なクエリを作成できます。

その他

Apex は、Web サービスのスタックやデータベースと緊密に連携した、非常に使いやすいプログラミング言語ですが、クラウド環境での実行という要件にもとづく独自の特徴があります。Apex クラスのコンパイル処理では、クラスは Force.com プラットフォームに渡され、コンパイル済みコード (ユーザが通常アクセスすることはありません) が生成され、コンパイルに失敗した場合はエラーメッセージが返されます。ほかには、マルチテナント環境での実行という要件にもとづく特徴も複数存在します。このセクションでは、こうした Apex 独自の特徴について解説します。

DaaS (Development as a Services: サービスとしての開発)

sObject、ワークフロールール、トリガなどの定義を含んだ Apex は、それ自体で 1 アプリケーションのメタデータであると考えることができます。こうしたメタデータすべてを Force.com プラットフォームにフィードしたものが、アプリケーションとしてクラウドで動作します。

DaaS とは、従来型の開発手法にもとづいたオンデマンド型アプリケーションの開発を可能にする機能の集合を指します。Force.com プラットフォームでのアプリケーション開発方法は、主に次の 2 つに分かれます。

  • Force.com Builder - Web ブラウザを介して利用し、Force.com プラットフォームの構成や、カスタムアプリケーションのあらゆる設定を制御します。たとえば、sObject や Apex クラスを作成し、結果を確認することなどが可能です。
  • メタデータ API - 個々の Web サービスエンドポイントを介して、アプリケーションに関連付けられているすべてのメタデータへのアクセスを可能にする Web サービスです。

特に後者の方法は、さまざまなツールで利用可能です。たとえば、Apex をはじめとする Force.com プラットフォームコンポーネントを作成可能な Eclipse ベースの統合開発環境である Force.com IDE には、構文の強調表示、コンパイル、エラー処理、テストメソッドの実行などの機能が備わっていますが、こうした機能を既存のメタデータ API を呼び出すことによって実行できます。コードのコンパイル処理では、メタデータ API がコードを Force.com プラットフォームに転送し、その後、コンパイルによって生成されたメタデータが Force.com IDE に返されます。

Force.com 移行ツールを使用するか、メタデータ API 用のカスタムインターフェースを作成すると、メタデータに直接アクセスしてさまざまな操作を行えます。たとえば、メタデータ API ですべてのメタデータを取得し、同じ API を使用して別の環境に移植することで、任意の環境から別の環境にコードを移行できます (Force.com では、運用環境、サンドボックス環境、開発環境など、さまざまな環境を構築できます)。

マルチテナント

Force.com プラットフォームはマルチテナント型プラットフォームであり、アプリケーションで使用するリソース (データベースなど) は他の多くのアプリケーションと共有されます。マルチテナント方式には多くのメリットがありますが、ユーザはわずかな手間でそのメリットを享受できます。ユーザが作成した Apex コードに対して、Force.com プラットフォームではそのコードが適切に機能するようにさまざまな処理を実行します。

もしユーザが単純なループ処理を繰り返す Apex コードを作成した場合、それはユーザにとってもクラウド環境にとっても無益です。そのような不適切なコードが実装されることを回避するため、Force.com プラットフォームでは、運用環境にコードを実装する場合に、Apex クラスに対して 75% 以上のテストカバレッジを達成するという要件を定めています。

Apex のランタイムエンジンでは、多くのガバナ制限を設定することによって、制御不能な Apex が共有リソースを占有するというリスクを回避しています。このようなガバナ制限では、さまざまな指標を追跡して評価を行います。制限の例としては、トリガにおける Apex 呼び出しの合計スタックの深さ (16 まで)、単一の文字列内の文字の総数 (100,000 字まで)、DML ステートメントの結果として処理されるブロック当たりの総レコード数 (10,000 件まで) などがあります (いずれも執筆時点の値)。

これらの制限を超えないようにするには、さまざまな要件を把握しておく必要があります。たとえば、前に述べた for ループ処理では一部の制限が緩和され、Apex の実行元に応じて異なる制限が適用されます。通常、トリガによって実行された Apex に対しては、Web サービス呼び出しのプロセスとして実行された Apex よりも厳格な制限が課されます。

まとめ

このドキュメントでは、オンデマンドコンピューティングをサポートする新しいオブジェクト指向プログラミング言語である Apex の概要を説明しました。

Apex は Force.com データベースと緊密に連携しており、Apex から直接、データの操作や検索を簡単に実行できます。また、Apex では、データベースオブジェクトが操作された時点で実行するトリガや、Visualforce によって提供されるユーザインターフェースのコントローラを作成することも可能です。さらに、Apex は Web サービスを強力にサポートします。Force.com プラットフォームで外部 Web サービスを呼び出す Apex を自動作成できるほか、Apex を使って Web サービスを容易に作成できます。

クラウドプラットフォーム向けのプログラミング言語である Apex には、Apex も含めたさまざまなメタデータを広範に処理できる API や、標準ベースの統合開発環境 Force.com IDE も用意されています。さらに、ガバナ制限やテストフレームワークによって、マルチテナント環境での Apex コードの適切な動作を保証する仕組みが整えられています。

より詳細な情報については、次のセクションでご紹介する「Apex コード 言語リファレンス」を参照してください。

参考資料

  • Developerforce サイト: このサイトで無料の開発者用エディション Developer Edition を入手して、すぐに Apex プログラミングをスタートできます。ドキュメントやフォーラムなどへのリンクも用意されています。
  • Apex コード 言語リファレンス: Apex コードについての包括的なドキュメントです。今回のドキュメントで取り上げられていない詳細な情報が記載されています。
  • Force.com データベースの概要 : Force.com データベースの概要を広範にわたって解説しています。
  • Apex コードのテストメソッドの概要 : 単体テストの作成方法の詳細を学ぶことができます。
  • Governors in Apex Code (Apex コードのガバナ): Apex コードのガバナについて解説しています。
  • Force.com IDE ページ: このページから Apex の統合開発環境である Force.com IDE や関連ドキュメントにアクセスできます。

執筆者について

Jon Mountjoy は Developerforce コミュニティの管理者および編集長として、新しいテクノロジを意欲的に探求し、コミュニティにフィードバックしています。Jon は Developerforce でブログを執筆しているほか、Twitter、FriendFeed などにも参加しています。以下に Jon 本人からのメッセージをお伝えします。「この場を借りて、素晴らしいコンテンツを作成した Force.com プラットフォームドキュメンテーションチームに対して、執筆者より感謝の意を表したいと思います。また、貴重な助言ならびに誤りのご指摘をいただいた Rick Greenwald 氏、Leah Cutter 氏、および Taggart Matthiesen 氏に厚くお礼申し上げます。このドキュメントに関する皆様からのご意見をお待ちしています」