本文へジャンプ

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

送信されたすべての情報は安全です。

  • 閉じる [x]

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


送信されたすべての情報は安全です。

  • 閉じる [x]

Javaコードの診断: パッケージの依存関係の分離

コンポーネント・ベース・プログラミングにより、テスト可能なコードをより柔軟に接続

Eric Allen, Software Engineer, Cycorp, Inc.
Eric Allen氏は、コーネル大学でコンピューター・サイエンスと数学の学士号を取得しています。現在は、ライス大学の博士課程の大学院生としてJavaプログラミング言語チームに加わっています。学位を終了するためにライス大学に戻るまでは、Cycorp, IncでJavaソフトウェア開発主任として勤務していました。彼は、JavaWorldで「Java Beginner」ディスカッション・フォーラムの司会者も務めています。主な研究対象は、Java言語のセマンティック・モデルと静的分析ツールの開発であり、いずれもソース・レベルとバイトコード・レベルで研究しています。Ericは、NextGenというプログラミング言語 (汎用ランタイム型によるJava言語の拡張版) のためのライスのコンパイラーの開発にも携わってきました。連絡先は、eallen@cs.rice.edu です。

概要: みなさんは、プログラムをテストする時に、外部リソースとライブラリーへの接続をシミュレートするという難題にどのように対処しているでしょうか。コンポーネント・ベース・プログラミングやパッケージの依存関係の分離がその答えかもしれません。コンポーネント・ベース・ソフトウェア開発は、コードの再利用を円滑にする手段としてよく取り上げられますが、より多くのコードをテスト可能にする場合にも有効です。Eric Allen氏は、Java言語を使用したコンポーネント・ベース・プログラミングのための強力なフリー・ツールであるJiazziの例を用いて、このようなプログラミングの概念を説明しています。

日付:  2002年 11月 01日
レベル:  初級 この記事の原文:  英語
アクティビティー: 1666 ビュー
お気軽にご意見・ご感想をお寄せください: 


テスト・ファースト・プログラミングで何度も取り上げられている問題の1つは、プログラムの多くの部分が自動的にテストできないように見える点です。特に、外部リソースやライブラリーを頻繁に利用するプログラムでは、そのような外部リソースへの接続をシミュレートする適切な方法がないため、テストが困難であるように思われます。

そのようなプログラムをJavaコードのみでテストするのは難しいかもしれませんが、この問題に対処するある種のプログラミングがあります (開発ツールを使用)。それが、コンポーネント・ベース・プログラミングです。

コンポーネント・ベース・プログラミングとJava言語

コンポーネント・ベース・プログラミングとはどういう意味でしょうか。コンポーネント・ベース・プログラミングとは、JavaBeansや類似したテクノロジーのような実行時「コンポーネント」ではなく、単に、プログラム配布の単位に基づくプログラミングのことです。

概念上、これらの配布の単位は、Javaパッケージとおおまかに対応しています。ただし、Java言語でのパッケージは、個々に分離できないという点で非常に制限されています。各パッケージのクラスは、インポートするパッケージにコーディング的に関係付けられています (各クラスは、パッケージを明示的に参照しなければならないためです)。

各パッケージは他のパッケージと分離されていないので、あるプログラムで行われているパッケージ参照を、同じ機能を提供する他のパッケージ参照に一律に置き換えるのは困難です。

また、別々の開発チームが、偶然重複するパッケージ名を使用するかもしれません。これは、両チームが互いのパッケージを使用する場合にトラブルとなります。パッケージ名を明確に区別するために、Sunは、「各開発チームでは、開発するすべてのパッケージの接頭部にチームのインターネット・アドレスを逆にしたものを使用する」という規則を強く勧めています。この規則は多くの場合守られていますが、いつもではありません。

さらに、パッケージの命名規則が完全に守られたとしても、プログラマーが個々のコンポーネントの分離を望む理由は他にもあります。1つには、そのほうがはるかに効果的にコンポーネントをテストできるからです。これについては、コンポーネント・ベース・プログラミングのためのツールであるJiazziコンポーネント・システムを例にとって、説明しましょう。


Jiazzi: Java言語のためのコンポーネント・システム

Jiazziは、Java言語の世界におけるコンポーネント・ベース・プログラミング実現の有力候補であり、JVMとの完全な互換性とコンポーネントの完全な分離を提供しようとするものです。このJiazziは、ユタ大学のコンピューター・サイエンス学部の開発プロジェクトです。このシステムにより、プログラマーは、コンポーネントを重ね合わせ、既存のJavaコードの一番上にそれらをまとめて接続できます。Java言語やJVMの変更は必要ありません。

開発者による説明

Jiazziの開発者は、これについて以下のように説明しています。

... Javaで、大規模なバイナリー・コンポーネントの構築を可能に (そのサポートを追加)するシステム ...。Jiazziコンポーネントは、外部のリンクと分割コンパイルに対するサポートが追加された、Javaパッケージの一般化と考えることができます。Jiazziコンポーネントは、標準のJavaソース・コードから構築されているので実用的です。Jiazziでは、Java言語への拡張も、コンポーネント内部を参照するJavaソース・コードを作成するための特別な規則も必要ありません。Jiazziは、循環的なコンポーネントのリンクとミックスイン (mixin) をサポートするので、コンポーネントは表現力が豊かです。循環的なコンポーネントのリンクとミックスインは、既存のクラスに対して新たな機能のモジュラーな追加を可能にするオープン・クラス・パターンで一緒に使用されます。

現在のJiazziの実装は、リンカー (コンポーネントの操作用) とスタブ・ジェネレーター (Jiazziを通常のJavaソース・コンパイラーと使用できるようにする) を使用してJavaプラットフォームに統合されます。JiazziのコンポーネントはJavaクラスを含み、それらをインポート、およびエクスポートします。また、継承に対するJavaプラットフォームの言語面でのサポートが、コンポーネントの境界を越えて使用できます。表現力が豊かであることに加え、コンポーネントは堅固であり、コンポーネントの実装とリンクは個別に型検査できます。

コンポーネントの分離に注意する

Jiazziがどのようにコンポーネントを分離するかを知るために、GUIライブラリー・パッケージを利用したJavaパッケージの簡単な例であるview について考えてみましょう。このパッケージをtoolkit と呼びます。パッケージのすべてのクラスを参照するために、パッケージのソース・ファイルの一番上にインポート・ステートメントを置きます。

package view;
import toolkit.*;
...
            

通常、これによりview パッケージがtoolkit パッケージと結びつけられます。しかし、今仮に実際にインポートするパッケージを確定せずに、このソース・ファイルをコンパイルしたいとします。toolkit パッケージとview パッケージの間の接続をコード上で記述する代わりに、全てのパッケージで有効な次のような関数を定義するという構想が可能です。それは、toolkit パッケージという情報を入手すると、それに依存するview パッケージという情報を戻す関数です。Jiazziでは、こうした関数をユニットと呼びます。

ユニットはLEGOブロックのようなもので、結合して1つのプログラムを作成することができます。ユニットを関数と考えると、Jiazziは関数合成を提供すると言えるでしょう。各ユニットは、指定された「パッケージ・シグネチャー」と共に1つ以上のパッケージを取り込み、再び、指定されたシグネチャーと共に1つ以上のパッケージをエクスポートします。

パッケージ・シグネチャーは、型のようなもので、パッケージの形状を制限します。パッケージ・シグネチャーは、パッケージで要求されるクラスや、そうしたクラスのメソッド・シグネチャーなどを定義します。エクスポートされるパッケージのシグネチャーは、インポートされるパッケージに依存する場合があります。

ユニットの型には2種類あります。

  • アトムは、パッケージ間のシンプルなマッピングです。
  • コンパウンドは、他のユニットの合成です。

アトムは、直接インポートおよびエクスポートするパッケージを記述します。コンパウンドは、合成するユニットでインポートおよびエクスポートされるパッケージを継承します。ユニットをLEGOブロックと考えると、アトムは個々のLEGOブロックであり、コンパウンドは、複数のLEGOブロックから構築される構造体です。

ユニットは、特別な仕様言語によって別々のファイルに記述されます。この言語は、ユニットによって入出力されるパッケージに名前を割り当てます。たとえば、以下のシンプルなアトミック・ユニットは、toolkit パッケージを取り込み、view パッケージを出力します。

atom app_view {
	import toolkit: toolkit_s;
	export view: view_s;
}
            

このユニットの名前はapp_view です。このユニットは、インポートするパッケージに「toolkit」という名前を割り当てます。このパッケージは、toolkit_s と呼ばれる特定のパッケージ・シグネチャーに適合するように宣言されています。ユニットによってエクスポートされたパッケージはview と呼ばれ、view_s シグネチャーに適合するように宣言されています。

前述したように、パッケージ・シグネチャーは型のようなもので、ユニットに渡される (あるいは、ユニットから戻される) 引数の形状を制限します。たとえば、toolkit_s シグネチャーは、以下のように、javax.swing パッケージのクラスのセットによく似たクラスのセットを指定することがあります。

signature toolkit_s {
	class Frame {
		public Container getContentPane();
		public Component getGlassPane();
		...
	}
	
	class OptionPane {
		public Object getDialog();
		...
	}
	...
}

view_s シグネチャーも、以下のように指定できます。

signature view_s {
	class EditorPane {...}
	class InteractionsPane {...}
	...
}
            

当然ですが、シグネチャーで参照されるクラスのいくつかは、別のパッケージにある場合があります。特定のパッケージからパッケージ・シグネチャーを分離できるようにするために、Jiazziでは、パッケージ・シグネチャーのパラメーター化ができるようになっています。シグネチャーのパッケージ・パラメーターは、シグネチャー名の後に、不等号括弧で囲んで指定します。たとえば、以下のように、awt パッケージによってtoolkit_s シグネチャーをパラメーター化することができます。

signature toolkit_s<awt> {
	class Frame {
		public awt.Container getContentPane();
		public awt.Component getGlassPane();
		...
	}
	
	class OptionPane {
		public Object getDialog();
		...
	}
	...
}

この場合、新しいシグネチャーを考え (awt_s と呼びましょう)、awt パッケージを取り込むためにapp_view ツールキットを変更し、それによってtoolkit_s シグネチャーをインスタンス化しなければなりません。

signature toolkit_s<awt> {
	class Frame {
		public awt.Container getContentPane();
		public awt.Component getGlassPane();
		...
	}
	
	class OptionPane {
		public Object getDialog();
		...
	}
	...
}

この場合、新しいシグネチャーを考え (awt_s と呼びましょう)、awt パッケージを取り込むためにapp_view ツールキットを変更し、それによってtoolkit_s シグネチャーをインスタンス化しなければなりません。

atom app_view {
        import my_toolkit: toolkit_s<awt_s>;
                my_awt: awt_s;           export my_view: view_s;
}
            

そうすると、my_toolkitmy_view という割り当てられた名前が、あたかも本物のパッケージ名のように、Javaソース・ファイルによって参照できるようになります。実際、Jiazziによって、上述のソース・ファイルを再コンパイルし、まったく変更することなく、これらの割り当てられた名前を参照できるようになります。(それがどのように行われるかについては、後で説明します。)

LEGOブロックと同様に、それぞれのユニットは、コンパウンド・ユニットを使用して結合することができます。コンパウンド・ユニットは、特別な「link」節で他のユニットを構成し、あるユニットによってエクスポートされたクラスと、他のユニットによってインポートされたクラスを識別します。たとえば、app_view アトムは、以下のように、default_toolkit ユニットとdefault_awt ユニットによって構成できます。

atom default_toolkit {
	import my_awt: awt_s;
	export my_toolkit: toolkit_s<my_awt>;
}
atom default_awt {
	export my_awt: awt_s;
}
compound app {
	export my_view: view_s;
	
	local v: app_view, a: default_awt, t: default_toolkit;
	link 
		a@my_awt to t@my_awt, a@my_awt to v@my_awt,
		t@my_toolkit to v@my_toolkit,
		v@my_view to my_view;
}

app ユニットのlocal 節に注意してください。この節は、ローカル変数を定義して、「ユニット・インスタンス」を表します。これらのユニット・インスタンス内のクラスが、実際にリンクされる要素になります。ユニットを直接リンクするのではなく、ユニット・インスタンスをリンクすることにより、Jiazziは、コンパウンド・ユニットのリンケージが、構成ユニットの定義に影響しないことを明確にします。

プログラムでこうしたシグネチャー、アトム、コンパウンドを指定することにより、プログラム内のパッケージがどのようにリンクされるかが記述されます。Javaソース・ファイルは、ユニットによって入出力されたパッケージを参照しますが、そうでなければ、単なる普通のJavaファイルのように見えます。次のセクションでは、Jiazziを使用して、ユニットで指定する方法で、実際にJavaクラスをどのようにリンクできるかを説明します。


Jiazziはどのように機能するか

Jiazziは、3段階にわたってコードのコンパイルを行います。

  • 最初に、シグネチャーのセットとユニットの定義が、Jiazziスタブ・ジェネレーターに渡されます。Jiazziスタブ・ジェネレーターは、渡されたすべてのユニットのシグネチャーでインポートされたすべてのクラスに対してスタブ・クラス・ファイルを生成します。
  • 次に、これらのクラス・ファイルが、従来のJavaコンパイラーによって使用され、スタブ・ジェネレーターに渡されたユニットでエクスポートされているクラスのソース・ファイルをコンパイルします。
  • ソース・ファイルのコンパイル後、Jiazziユニット・リンカーは、結果のクラス・ファイルが、元のユニットで宣言されたクラス・シグネチャーと一致することを確認します。これは以下の理由で必要です。
    1. あらゆるサード・パーティー製のコンパイラーがJiazziサポート付で使用できる
    2. JiazziはJavaソース・ファイルを調べない

(余談ですが、Javaソース・コードを実際に調べないJiazziのアプローチが、思わぬ幸運を招いたことに注目してください。これにより、Jiazziは、JythonやJSR-14、NextGenなど、JVMを対象とした非Java言語用のコンパイラーと一緒に使用することができます。実際に、Jiazzi自体JSR-14で作成されています。)

確認後、コンポーネント・リンカーは、渡された各ユニットに対してJARファイルを生成します。このJARには、コンパイル済みのソースとスタブ、シグネチャー情報がメタデータとして含まれています。その後、これらのJARは、Jiazziと適切なコンパウンド・ユニットに渡すことにより、リンクすることができます。

Jiazziユニット・リンカーは、オフラインで、クラス・ファイルの定数プールに対してのみ作業を行い、メソッド名の偶発的な衝突を回避するために、隠しメソッドの名前を変更します。

ユニットは、特別なクラス・ローダーによってオンラインでリンクすることもできます。ただし、そのユニットが、その対象としてコンパイルされたスタブ・クラスは利用できないので、型検査は、「インクリメンタルな全プログラム分析」としてクラス・ローダーで行わなければなりません。実際に、現在、標準のJavaライブラリーの多くのクラスが、クラス・ローダーを介さなければリンクできないので、Jiazziプログラマーは、オフラインとオンラインのリンクを組み合わせて使用しなければなりません。

現在のシステムのもう1つの制限は、名前の変更が、JNIとリフレクション・ライブラリーに悪い影響を与えるという点です。特に、ネイティブ・メソッドはCコードで作成されているため、名前の変更が行われません。その結果、クラス・ライブラリーの多く (JNIとリフレクションに大きく依存している) が、Jiazziコンポーネントとしてリパッケージできません。

すでに述べたように、コンパウンド・ユニットは、他のユニット間の接続を表します。このリンケージは、コンパウンドのインポートおよびエクスポートされたユニットのバウンド名に関係していますが、リンクされたユニットは、リンクが行われたことをまったく認識しません (リンカーは、最終的にこれらのコンパウンド・ユニットをマクロ展開してアトムにします)。

このようにして、簡単な再コンパイルによって新しいパッケージをスワップ・インおよびスワップ・アウトできる方法で、プログラムのJARファイルを作成し、配布することができます。Javaソース・コードは一行も変更する必要はないのです。

さらに、Jiazziの他のユーザーは、私たちのプログラムによって提供されるクラスを、そのJARファイルが利用できるようになる前に開発することができます。必要なのは、エクスポートするものに対応するパッケージ・シグネチャーのみです。また、それらの拡張も、まったく同じようにそのパッケージ・シグネチャーの他の実装にリンクします。


ユニット・テストとJiazzi

コンポーネント・ベース・プログラミングは、大きな利点をもたらします。最も多く取り上げられる利点は、コンポーネントがコードの再利用の可能性を広げるということです。既製のコンポーネントを個々に分散し、新しいアプリケーションに自由に接続することができます。ただし、この種のプログラミングは、はるかに有効なユニット・テストも可能にします。

テストの間に、プログラムの構成コンポーネントは、クラスがテスト対象のコンポーネントのアクションを記録するだけの特別な「模擬」コンポーネントとリンクすることができます。本質的に、そのような模擬コンポーネントは、Recorderのコンポーネントと同様の役割 (参考文献の「正しいメソッド呼び出しのためのRecorderテスト」を参照) をコンポーネント・レベルで行います。

テスト済みのコンポーネントは、デカルトの「培養槽の中の脳」のようなもので、模擬コンポーネントに接続されているのか本物のコンポーネントに接続されているのか区別できません。たとえば、前述のアプリケーションの例では、以下のように、app_view ユニットとtest_toolkit ユニットを接続する特別なコンパウンドtest_app を作成できます。

compound test_app {
	export my_view: view_s;
	
	local v: app_view, a: default_awt, t: test_toolkit;
	link 
		a@my_awt to t@my_awt, a@my_awt to v@my_awt,
		t@my_toolkit to v@my_toolkit,
		v@my_view ot my_view;
}
            

test_toolkit パッケージは、toolkit と同じシグネチャーのパッケージをエクスポートしますが、このパッケージは、app_view に本物のツールキットにリンクされているように思わせる模擬オブジェクトのみで構成されています。これらの模擬オブジェクトは、app_view によって実行されたアクションを記録でき、その記録内容はユニット・テストで確認できます。

このようなシステムと、各ソース・ファイルでインポート対象のパッケージを明示的に示さなければならないJavaパッケージ・システムを比較してみましょう。Javaパッケージ・システムにおいて、パッケージ全体をテスト・パッケージにリンクさせる唯一の方法は、ソース・ファイルをすべて編集し、再コンパイルすることです。しかし、この方法は、実際のところテストの自動化には有効ではありません。

残念ながら、Jiazziは、リフレクションやJNIを (あまり適切に) 処理できず、また、このような機能は、多くの組み込みJava APIによって広く使用されているため、既存のAPIパッケージをJiazziコンポーネントに変換することはできません。しかし、それができれば、プログラムに対して非常に強力なテストを実行することができるでしょう。たとえば、実際にグラフィックス・オブジェクトをロードせずに適切なAPI呼び出しのすべてが行われるように、テストの実行時、Swing APIを使用するプログラムを模擬Swingコンポーネントに接続できるようになるかもしれません。同様に、java.io パッケージやJava3D、JDBC、RMI、および機能のパフォーマンスや性質によりクライアントがテストを行うのが難しいあらゆるAPIとの相互作用をテストできるようになるかもしれません。

いかがですか。すばらしい夢でしょう? しかし、リフレクションとJNIによって、既存のAPIを優れたJiazziユニットにできない場合でも、妥協の余地があります。

既存のAPI間の接続は分離できませんが、新しいユニットからそうしたAPIへの接続の分離は可能でしょう。本質的に、このようなAPIは、クラスのエクスポートのみを行った特別なユニットでバンドルすることができ、そのインポートは、既存のJavaパッケージ・システムをそのままを使って行われます。こうしたAPIがまっとうに作られたユニットであるならば、それを行うことにより、私たちが持ち得る機能の99 %が現実のものとなるでしょう。喜ばないプログラマーは、既存のAPIに対してサード・パーティーの代替の構築を望んでいる人たちだけでしょう。

Jiazziが、このような方向、あるいは、既存のAPIとの使用を可能にする同様な方向へと進化することが望まれますが、当面、Jiazziは、リフレクションやJNIを使用しないテスト・パッケージに非常に強力なメカニズムを提供します。


過去との訣別

Jiazziの背後にある本来の動機は、機能の拡張性のためのメカニズムとして、設計を複数の機能 (各機能を別々のコンポーネントに置く) に分割することでした。コンポーネント・ベース・プログラミングの提唱者は、開発者が、コンポーネント・ベンダーによって提供された既製のコンポーネントからプログラムを構築できるような将来を心に描いています。共通のシグネチャーを持つコンポーネントを車の部品のようにスワップ・インおよびスワップ・アウトすることができます。

実現してもしなくても、また、遍在的なコンポーネント・ソフトウェア市場がなくても、コンポーネント・ベース・プログラミングには大きな利点があります。とりわけ、この種のプログラミングは、非常に効率的なユニット・テストを可能にします。

これまでに説明してきたように、Jiazziによるコンポーネント・ベース・プログラミングは、プログラム・コンポーネントをテストするための非常に強力な方法を提供し、既存のJava (またはJython、またはJSR-14) ソース・ファイルと一緒に使用されます。私たちはみな、この強力なツールの恩恵を受けます。このようなツールや、それと同様のその他のツールは、テスト指向のプログラミングに必要不可欠な部分です。

次回は、Jamについて取り上げます。これは、ミックスイン・ベースのプログラミングを可能にするJava言語の拡張です。Jiazziがパッケージの依存関係を分離する方法を提供するように、ミックスインは、クラスの依存関係を分離する方法を提供します。お気づきかもしれませんが、ミックスインは、プログラムをテストするためのもう1つの強力なメカニズムを提供します。


参考文献

著者について

Eric Allen氏は、コーネル大学でコンピューター・サイエンスと数学の学士号を取得しています。現在は、ライス大学の博士課程の大学院生としてJavaプログラミング言語チームに加わっています。学位を終了するためにライス大学に戻るまでは、Cycorp, IncでJavaソフトウェア開発主任として勤務していました。彼は、JavaWorldで「Java Beginner」ディスカッション・フォーラムの司会者も務めています。主な研究対象は、Java言語のセマンティック・モデルと静的分析ツールの開発であり、いずれもソース・レベルとバイトコード・レベルで研究しています。Ericは、NextGenというプログラミング言語 (汎用ランタイム型によるJava言語の拡張版) のためのライスのコンパイラーの開発にも携わってきました。連絡先は、eallen@cs.rice.edu です。

不正使用の報告のヘルプ

不正使用の報告

ありがとうございます。 このエントリーは、モデレーターの注目フラグが設定されました。


不正使用の報告のヘルプ

不正使用の報告

不正使用の報告の送信に失敗しました。


developerWorks: サイン・イン


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。 プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。 お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

表示名をお選びください

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

(半角英数字で3文字以上31文字以下にする必要があります)


「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


この記事を評価する

コメント

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Java technology
ArticleID=224132
ArticleTitle=Javaコードの診断: パッケージの依存関係の分離
publish-date=11012002
author1-email=
author1-email-cc=

タグ

Help
このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。

スライダーバーを使用することで、より多く(少なく)タグを表示します。

人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。

マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。

このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。