japan.internet.comThe Internet & IT Network
RSS
  • ニュース
  • コラム
  • リサーチ
  • ヘッドライン
  • 特集
  • ブログ
  • プレスリリース
  • 専門チャンネル
  • イベント
  • ランキング
  • ニュースメール
2008年9月6日
文字サイズ文字サイズ小文字サイズ中文字サイズ大
デベロッパー2006年3月28日 10:10

Visual Studio .NETのウィザードを使ってN階層アプリケーションを作成する:パート1

海外海外internet.com発の記事
  • このエントリーを含むはてなブックマーク
  • この記事をクリップ!
  • Buzzurlにブックマーク
  • Yahoo!ブックマークに登録
  • newsing it!

はじめに

 MicrosoftはRAD(Rapid Application Development)ツールのための優れたツールを開発者に提供することで知られています。MS Access、Visual Studio 6、Visual Interdevなどの環境で、コントロールやプロパティ、自動生成コードを視覚的に組み合わせることで、アプリケーションをすばやく開発できます。Visual Studio .NETはこれらのツールを統合し、数多くのプログラミング言語に対応している素晴らしい開発環境です。

 Visual Studio .NET(以下、VS)には、アプリケーション開発に役立つウィザードが多数用意されています。しかし残念ながら、ウィザードでは効率的なプログラミング手法が使われない傾向にあります。具体的に言うと、コードが複数の層に分離されず、ビジネスロジックが分離されないのです。VSの既定のモデルでは、データオブジェクトをフォームにドラッグアンドドロップしながらフォームを作成します。コードは必要に応じて作成されますが、データアクセスコードとビジネスロジックコードが区別されず、ユーザーインターフェイスのフォームオブジェクト内に直接作成されます。このため、コードの再利用が難しく、同じテーブルデータを複数のフォームで使用する場面ではコードの重複が発生します。

 今日のアーキテクチャでは、コードを複数の層に分離するN階層アプローチが推奨されています。N階層アプローチでは、少なくともデータアクセス層、ビジネスロジック層、プレゼンテーション層の3つに分離されます。アプリケーションの各種パーツを複数のサーバー上に置く分散アプリケーションの場合は、より多くの層が必要になることもあります。

 層を分離する主なメリットは2つあります。1つはコードの再利用が容易になることで、もう1つはコードとデータベースの結合を回避できることです。データアクセス層とビジネスロジック層を分離すると、データのアクセスと使用に必要なコードをあちこちに繰り返し記述しなくても、さまざまなフォームを使ってデータを収集および表示できます。コードとデータベースの結合を回避すると、データベースのスキーマを変更する際にコードを修復する量が少なくなり、データストレージプロバイダを変更するときでも、コードを大幅に変更しないで済みます。

 Microsoft .NETは、OOP(オブジェクト指向プログラミング)の標準を目指して、開発者のサポートと支援に力を入れてきました。OOPは高度で深遠な話題なので、ここでは詳しく説明しませんが、1つだけ、データベースアプリケーションの開発者にとって興味深い「ビジネスオブジェクト」について簡単に触れておくことにします。データベースのテーブルとフィールドがエンティティと属性の実装において重要な役割を果たすのに対し、ビジネスオブジェクトは特定のエンティティのプロパティと動作を併せて実装します。アプリケーションが各エンティティ(テーブル)を表すビジネスオブジェクトクラスのインスタンスを作成すると、そのプロパティを介して属性にアクセスし、メソッドを介してエンティティの動作を呼び出せるようになります。また、この手法を採用すると、エンティティに関するコードをすべて1つの場所にまとめておいて、アプリケーションのその他のパーツから簡単に参照することが可能です。さらに、ビジネスオブジェクトで継承やポリモーフィズムを利用すると、非常に柔軟で強力なプログラミングが可能になるため、わずかなコードで大量の処理を実行することができます。

パート1 - Visual Studio .NET 2003

 Visual Studio .NET 2003には、データベースアプリケーションを短時間で構築するためのウィザードやコード生成ツールが用意されていますが、本稿ではコードを複数のモジュールまたはクラスに分離して、アプリケーションの層を作成する方法について説明します。その例として、以降ではNorthwindデータベースを使用し、「Orders」テーブルや「Order Details」テーブルを表示および編集するためのフォームを作成します。

プロジェクトの作成

 最初にソリューションエクスプローラを使って新しいプロジェクトを作成します。この例ではWindowsフォームを作成しますが、Webフォームでもほとんど同じです。真の3層アプリケーションを作成する場合は、データアクセス層とビジネスロジック層のクラスオブジェクトを別々に作成しますが、モジュールは後で簡単に移動できます。

データオブジェクト層

 オブジェクト指向プログラミング(OOP)の原則に従って、まず取り扱う情報(通常はデータベースの情報)を含むデータオブジェクトを作成します。.NETでは、型指定されたデータセットを使うのが最も簡単です。このツールを使うと、通常のデータセットクラスがラップされ、オブジェクト指向に基づいたデータアクセスや、プロパティ(フィールド)の厳密な型指定が可能になります。コレクションや配列リストなどの構造でもデータベーステーブルオブジェクトを表現できますが、VSのほとんどのウィザードでは、型指定されたデータセットが使用されます。

 新しいデータセットを作成するには、プロジェクトを右クリックして[Add]、[Add New Item]の順にクリックします。ウィザードの場合は、Datasetオブジェクトを選択して、新しいデータオブジェクトに「OrdersDO」などの適当な名前を指定します。ウィザードによって、XSDと型指定されたデータセットに必要なコードが生成され、デザインサーフェイスが表示されます。開発者はこのデザインサーフェイスを使ってテーブルをサーバーエクスプローラからデータセットのスキーマにドラッグして追加したり、あるいは他のウィザードを使用してリレーションシップや制約を追加したりできます。テーブルからフィールドをいくつか除外する場合は、スキーマから削除します。本稿の例では、「Orders」テーブルと「Order Details」テーブルを、サーバーエクスプローラからデザインサーフェイスにドラッグしました。出荷のデータは一切必要ないので、「Orders」テーブルでは4つのフィールドだけ残してすべて削除しました。ツールボックスの[XML Schema]のセクションでデータリレーションシップを選び、Ordersオブジェクトにドラッグアンドドロップします。リレーションシップウィザードでは「Order Details」を子テーブルに選んでください。ここまでの作業を終えると、図1のように表示されるはずです。

図1 型指定されたデータセット(データオブジェクト)
図1 型指定されたデータセット(データオブジェクト)

生成されるコード

 型指定されたデータセットの場合、データテーブルや行を抽象化するため、およびデータフィールド(プロパティ)の厳密な型指定を可能にするために、数百行のコードが生成されます。これにより、構文やIntelliSenseがデザイン時に検証され、オブジェクト指向的な方法でデータオブジェクトを参照できるようになります。生成されたコードを表示するには、プロジェクトを選択してソリューションエクスプローラの最上部にあるアイコンをクリックし、ファイルを表示します。次に、データセットの隣の[+]を展開してください。表示される2つのファイルのうち、拡張子が.vb(または.cs)であるファイルにコードが格納されています。このコードはデータセットを保存するたびに再生成されるので、編集はしないでください。

 生成されるコードについて、以下に簡単にまとめます。この例では、「MyTab」という名前のテーブルを含む型指定されたデータセットが、「MyDS」という名前で生成されます。

 型指定されたDataSetは、DataSetから派生したMyDSという名前のクラスを生成することで厳密な型指定を実現します。DataSetクラスのサブクラスの名前は、XMLスキーマを生成した元のDataSetに含まれるDataSet.DataSetNameと同じになります。次の4つのパブリックな入れ子のクラスが公開されます。

  • DataTableを継承しIEnumerableを実装するMyDS.MyTabDataTable
  • DataRowを継承するMyDS.MyTabRow
  • EventArgsを継承するMyDS.MyTabRowChangeEvent
  • MyDS.MyTabRowChangeEventHandler

 このとき、

  • MyDSDataSet.DataSetNameの値
  • MyTabDataTable.TableNameの値
  • MyTabRowDataTable.TableName + Rowの値

 を表します。

 MyDS.MyTabDataTableには、一連のプライベートなDataColumnメンバが含まれています(テーブルまたはクエリ/ストアドプロシージャの結果セットの列ごとに1つのデータメンバがあります)。これらに関するgetメソッドが用意されていますが、実行時にDataColumnsを追加または削除することは許可されないので、Internalに指定されています。また、変更中(Changing)、変更済み(Changed)、削除中(Deleting)、削除済み(Deleted)の行に関する型指定された4つのデリゲートもあります。

 型指定されたDataTableには以下のメソッドが含まれます。

  • Rowsに関するIndexerGetEnumeratorメソッド
  • 2つの追加メソッド。メソッド名はどちらもAddMyTabRowですが、それぞれ少し違う方法で使用されます。Rowを受け取るAddMyTabRow(row)は、型指定された空の行であるNewMyTabRowで使用されます。AddMyTabRow(n1,n2,n3)はN個のパラメータを受け取ります(Nはテーブル内の列数で、MyTabにはテーブル名が入ります)
  • 削除メソッドRemoveMyTabRow

 DataColumnsDataTableInitClassメソッドで作成され、DataTableに追加されます。メタデータが使用できる場合は、このメソッドでメタデータの入力も行われます。主キーまたは一意の列が存在する場合は、入力に主キーを使用するFindBykeycolnameメソッドが用意されます。

 MyTabRowクラスは列をパブリックプロパティとして公開します。列にnullを入力できる場合は、IsColumnnameNullSetColumnnameNullという2つのヘルパー関数があらかじめ定義されます(Columnnameにはいずれも列名が入ります)。

 厳密に型指定されたDataSetに、複数のテーブルが含まれる場合があります。テーブルに親子のリレーションシップを指定(DataSetRelationsコレクションにDataRelationを作成)すると、データとメソッドがいくつか追加で生成されます。DataSetRelationが含まれる場合、生成されるコードは次のようになります。

  • PrimaryKeyプロパティが親テーブルのDataColumnプロパティに追加され、ForeignKeyConstraintが子テーブルに追加されます。また、DataRelationが追加されます。元のスキーマでDataSetNestedプロパティが設定されていた場合は、型指定されたDataSetでもこれが維持されます。
  • ChildTabRowParentTabRow型のプロパティを持ちます。プロパティのgetメソッドはGetParentRowを呼び出し、setメソッドはSetParentを呼び出します。
  • ParentRowGetChildTabRowというメソッドが追加されます。このメソッドはGetChildRowsを呼び出すことによって、型指定された子行の配列を返します。

 このとき、

  • ParentTabは親テーブルのDataTable.TableNameの値
  • ChildTabは子テーブルのDataTable.TableNameの値

 を表します。

 最後に、XMLの永続性に関連する特定のメソッドとプロパティが、厳密に型指定されたDataSetに含まれます。これらはDataSetのメソッドをオーバーライドします。

  • protectedコンストラクタはSerializationInfoの情報と、StreamingContextのコンテキストを受け取ります。このコンストラクタはGetSerializationDataを呼び出す前にInitClassを呼び出します。これは、ISerializableを実装する場合に必須の動作です。
  • ReadXmlSerializableは単純に基本クラスのReadXmlメソッドを呼び出します。
  • GetSchemaSerializableWriteXmlSchemaを呼び出して、スキーマをXmlTextWriterに書き込みます。続いて、System.Xml.Schema.XmlSchemaにそれを読み込みます。この動作は基本クラス(DataSet)のコードと同様です。
  • ShouldSerializeTablesプロパティとShouldSerializeRelationsプロパティ、およびShouldSerialize[MyTable]という追加のプロパティはfalseを返します。

 本稿の例では、2つの関連付けられたテーブルを使用します。およそ720行のコードを自動生成して、データオブジェクト層が構築されます。

データアクセス層

 データアクセスとビジネスロジックの間でも、必要に応じて層を分離することがあります。バックエンドのデータストレージエンジンが更新されたとき、それらの変更はすべてこの層で処理されます。データアクセス層では、データオブジェクトとデータストアとの連携を行い、データベースからデータセットを入力および更新するためのメソッドを提供します。また、この層によって、ビジネスロジックに必要なストアドプロシージャとのやり取りを行う場所が追加されます。この層を作成するには、プロジェクトに新しい項目を追加し、一覧からコンポーネントクラスオブジェクトを選択して、「OrdersDA」などの名前を指定します。すると、デザインサーフェイスが表示され、その他のオブジェクトを画面上で追加することができます。

 ツールボックスのデータセクションで、データアダプタオブジェクト(SQL Serverの場合はSqlDataAdapter、その他のデータベースの場合はOleDataAdapter)をデザインサーフェイスにドラッグします。通常、ウィザードは自動的に起動しますが、起動しない場合はデータアダプタを右クリックして、[Configure Data Adapter]をクリックしてください。

 最初の画面では接続を指定します。データベースへの既存の接続を選択するか、新しい接続を作成してください。2つ目の画面では、SQLまたはストアドプロシージャを作成するか、既存のストアドプロシージャを使用するかを選択できます。新しく作成する場合は、次の画面で必要なクエリを作成します。ストアドプロシージャを作成する場合は、各自の命名方法に従って名前を入力してください。なお、既存のストアドプロシージャを使用する場合は、3つ目の画面でストアドプロシージャ名を指定します。

 SQLステートメントを使用する場合、3つ目の画面では、必要なデータをデータベースから返すSelectステートメントを入力します。[Query Builder]ボタンを使うと、テーブルやフィールドを選択することができます。テストすることも可能です。[Advanced]ボタンでは、指定したSelectステートメントから更新、挿入、および削除のコマンドを生成するかどうかを選択できます。[Next]をクリックすると最後の画面に進み、生成された内容を表示します。

 デザインサーフェイスに戻り、先ほど作成したデータアダプタを選択します。プロパティ一覧の名前フィールドで、このオブジェクトに自分の命名方法に合った名前を指定してください(「daOrders」など)。次に、データ接続を調整する必要があります。作成した接続オブジェクトを選択し、プロパティで名前を「con」に変更します。接続文字列をハードコーディングする代わりに、この情報をapp構成ファイルに移動します。[Configurations]セクションのDynamicPropertiesエントリを展開し、その下(Dataセクションの下ではないことに注意)にあるConnectionStringプロパティを選択してください。プロパティの値の右にある、ビルドを実行する楕円形のボタンをクリックし、[map to a key in configuration file]チェックボックスをオンにして任意の名前を入力します(既定の名前を変更してください)。これで、「App.Config」ファイルにエントリが正しく作成され、実行時にそれを取得するためのコードが生成されます。

図2 データアクセス層
図2 データアクセス層

 次に、先ほどと同じ手順で「Order Details」テーブルにデータアダプタをもう1つ追加し(必ず同じ接続を使用してください)、名前を「daOrderDetails」に変更します。

 それぞれのデータアダプタを右クリックし、[Generate dataset]をクリックします。1つ目の手順で作成したデータセット「ProjectName.OrdersDO」を選択して、正しいテーブルが指定されていることを確認してください。[OK]をクリックすると、データアダプタからデータセットへのリンクに必要なすべてのコードがウィザードによって作成されます。

 最後に、デザインサーフェイス上で右クリックし、[View Code]をクリックして表示をコードウィンドウに切り替えます。コンポーネントではなく型指定されたデータセットを継承するように、クラスの定義を変更してください。以上で、すべてのデータセットオブジェクトにビジネスオブジェクトからアクセスできるようになります。

Public Class OrdersDA
    Inherits OrdersDO  ’System.ComponentModel.Component

 生成されたコードは、次の折り畳み領域の中に隠されています。

+Component Designer generated code

 生成されたコードに、データセットの入力と更新に必要な2つのメソッドを自分で追加する必要があります。以下のコードを追加してください。

    Public Function FillDataSet() As DataSet
        con.Open()
        Me.daOrders.Fill(Me.Orders)
        Me.daOrderDetails.Fill(Me.Order_Details)
        con.Close()
        Return Me
    End Function
    Public Function UpdateDataSet(Optional ByVal TableName _
        As String = "All") As DataSet
        con.Open()
        If TableName = "Orders" Or TableName = "All" Then _
            Me.daOrders.Update(Me.Tables("Orders"))
        If TableName = "Order Details" Or TableName = "All" Then _
            Me.daOrders.Update(Me.Tables("Order Details"))
        con.Close()
    End Function
    ’Add any other business object functionality here

End Class 

 最後に、すべてを保存してプロジェクトをビルドします。Sub Mainがないというエラーが表示されますが、これは次の手順で作成します。

生成されるコード

 「+Component Designer generated code」のセクションを展開すると、生成されたコードを確認できます。以下のコードが含まれています。

  • Connectionオブジェクト。接続文字列は構成ファイルに分離されています。
  • 各テーブルのデータアダプタ。テーブルマップとコマンドオブジェクトが関連付けられています。
  • 各データアダプタにCRUD機能を実装するための、4つのCommandオブジェクト。
  • パラメータを必要とする各コマンドのParameterオブジェクト。
  • データセットのインスタンス生成コード(含まれない場合もあります)。

 今回の2つのテーブルの場合、約150行のコードが生成されます。

ビジネス層

 次に、ビジネスオブジェクトクラスを作成する手順に移ります。このクラスにはすべての検証ロジックとその他のビジネスロジックを含めます。Bizプロジェクトの場合は、クラス項目を「OrdersBO」という名前で新規作成します。コードウィンドウで、OrdersDAクラスを継承する新しいクラスを作成してください。このクラスについては、後で必要なロジックを追加する方法を説明します。

注意
 ビジネスロジックがそれほど多くなければ、データアクセスクラスに入れても構いませんが、ビジネス層の分離ができなくなります。

プレゼンテーション層

 Visual Studioには、アプリケーションのユーザーインターフェイスの部分を、マスタ-詳細のリレーションシップを表示しながら作成できるData Formウィザードがあります。

 ソリューションエクスプローラで、これまでに使用してきたのと同じプロジェクトを右クリックし、[Add new item]をクリックします(ここでは、Data Formウィザードでビジネスオブジェクトを検出するために同じプロジェクトを使用します。コードは後で移動します)。一覧からData Formウィザードを選択して、フォームの名前に「OrdersWin」などを指定します。

図3 Data Formウィザード
図3 Data Formウィザード

 次の画面で、プロジェクトに含まれる既存のデータセットが検索されます。このデータセットを使うことも、この画面で新しく作成することもできます。ここでデータセットを作成してもまったく問題ありませんが、データ層とプレゼンテーション層を混ぜると、N層アプリケーションのセオリーに反することになるので、ここではそのためにデータオブジェクトとビジネスオブジェクトを別に作成しています。

図4 Data Formウィザード(画面2)
図4 Data Formウィザード(画面2)

 OrdersBOを選択すると(データオブジェクトではなくビジネスオブジェクトであることに注意)、ビジネスオブジェクト内に作成されている入力と更新のメソッドが一覧表示されるので、その中から、データセットの入力と更新に使うメソッドを選択します。

図5 Data Formウィザード(画面3)
図5 Data Formウィザード(画面3)

 DataSetに複数のテーブルがある場合、ウィザードは画面をもう1つ表示します。この画面では、マスタテーブルと詳細テーブルを選択します。また、フォームに追加するフィールドも選択できます。

図6 Data Formウィザード(画面4)
図6 Data Formウィザード(画面4)

 最後に、1つの親をフォームビューに表示するのか、複数の親をグリッドビューに表示するのかを選択します。子レコードは画面下部のリンクされたグリッドに表示されます。

 生成されるフォームは図7のようになります。このプロジェクトを実行すると、「Orders」と「Order Detail」の情報を操作するためのフォームになります。

図7 Data Formウィザードによって生成されたフォーム
図7 Data Formウィザードによって生成されたフォーム

 ウィザードの最後のオプションで、親を1つだけ表示する設定にした場合は、1対多のリレーションシップを表示するフォームになり、Ordersレコードの間を移動するためのコントロールと、必要に応じてレコードを編集するためのコントロールが追加されます(図7を参照)。

 アプリケーションをビルドして実行すると(プロジェクトのプロパティはOrdersWinフォームを起動するように設定しておきます)、最初にマスタ-詳細フォームが表示されます。リンクがどのように実行されたかを確認してください。詳細のグリッドのデータソースがobjOrdersBOに設定され、データメンバがデータセットのリレーションシップ名であるOrders.OrdersOrder_x0020_Detailsに設定されたことがわかります。

 以上のように、このアプリケーションはわずかなコードを記述するだけで簡単に作成できます。これなら経験の浅い開発者でもアプリケーションをすぐに構築できますし、3層アーキテクチャの個々の層を分離することができます。

生成されるコード

 ウィザードのコード生成機能により、各コントロールをデザインサーフェイスにドラッグしてプロパティを適切に指定したときと同じように、以下のコードが生成されます。

  • テーブル内の個々のフィールドを表すラベルおよびテキストボックスコントロール。それぞれのコントロールに、データ行のフィールドにバインドした適切な名前が割り当てられます。
  • データの読み込み、およびレコードの更新、追加、削除を行うためのボタン。
  • レコード間の移動を処理するためのボタン。
  • リレーションシップを持つ子レコードを表示するグリッド。子レコードへのリンクも設定されます。
  • グリッドの各列のテーブルスタイル。
  • 各ボタンのクリックイベントを処理するメソッド。
  • データを読み込むメソッド(ベースメソッドを呼び出します)。
  • データセットを更新するメソッド。データバインドを効率的に処理するマージメソッドを利用します。

 これらのコードのほとんどは、ビジュアルツールを使っても生成できますが、このウィザードを使用すれば20〜30分を節約できるうえに、優れたコーディングパターンが組み込まれます。生成されたコードは、合計でおよそ190行になりました。

 一方で、このウィザードは非常に気難し屋です。このウィザードは、ビジネスオブジェクトクラスにすべてのプロパティを過不足なく作成しておかないと、そのクラスを検出してくれません(正しい組み合わせは、筆者もまだ確実にはわかりません)。また、入力と更新のメソッドには必ず正しいシグネチャを指定する必要があります。それができたとしても、グリッドが正しく生成されるとは限りません。

層の分離

 分離する層は、アプリケーションの開発を始める前に作成しておくのがベストです。Windowsプロジェクトのすべての要素が用意できたら、「NorthwindBiz」という名前で新しいクラスライブラリプロジェクトを作成し、OrdersDOオブジェクトとOrdersBOオブジェクトをこのプロジェクトにドラッグアンドドロップしてください。次に、「OrdersWin.vb」ファイルから「NorthwindWin」の記述を探して「NorthwindBiz」に書き換えます。また、NorthwindBizプロジェクトへの参照をNorthwindWinプロジェクトに追加することも必要です。この2つの簡単な変更で、新しいフォームを前と同じように実行できます。また、同じビジネスロジックを使用するWebインターフェイスを追加するためのプロジェクトを追加することもできます(残念ながら、Webアプリケーション用のData Formウィザードはまだないので、このバージョンを実現するにはもう少し手間がかかります)。

まとめ

 現在ではアプリケーション生成のための優れたフレームワークやコード生成ツールが数多く販売されていますが、そのほとんどは、時間とお金をかけなければうまく使いこなすことができません。私はVisual Studio付属の生産性向上ツールを好んで使用しますが、このツールが展開するお粗末なプログラミング手法には満足していません。本稿で説明した手順がこの問題の解決に役立つはずです。

 OrdersBOクラスにコードをさらに追加して、検証を実行したり、その他のビジネスロジックを実装したりすることもできます。

 本稿では、正しく設計された実用的なアプリケーションモジュールを、およそ20分間で作成しました。生成したコードは1000行を超えましたが、自分で作成したコードはわずか10行ほどでした。

関連情報

著者紹介

David Catherman(David Catherman)
データベースアプリケーションのデザイン/開発に20年以上の経験を持ち、ここ4、5年は特にMicrosoft .NETとSQL Serverに仕事が集中している。現在はCMI Solutionsのアプリケーション設計者および上級開発者であり、Visual StudioとSQL Server 2005を使用している。.NETのMCPを取得し、現在MCSDを取得中。
メールの宛先はDCatherman@CMiSolutions.com。
関連テーマ
最新トップニュース
データメーション
【データメーション】
OSについて気に入らないこと(9月5日)
ベンチャー専門家の目利きブログ「なぜこの企業は伸びるのか?」
【ベンチャー専門家の目利きブログ「なぜこの企業は伸びるのか?」】
「導入期〜成長期へ!一歩一歩と前進を目指す『Annoii(アノイ)』」/maka hou,Inc.(9月5日)
最新テクノロジーの意外な処方箋
【最新テクノロジーの意外な処方箋】
グリッドコンピューティング技術でETに遭遇(9月5日)
Graphic Design Forum
【Graphic Design Forum】
古い Emigre を探して (9月3日)
エンジニアの独り言
【エンジニアの独り言】
データをローカルに保存するWebアプリケーション(8月22日)
デスマーチからの脱却
【デスマーチからの脱却】
30min. iPhoneアプリリリース(8月18日)
最新ハイテク講座
最新ハイテク講座
なぜ勝った? 世界No.1シェアをつかんだ“Windows”(9月5日)
developer.com
developer.com
デザインパターンの使い方: Composite(9月5日)
最新アフィリエイト事例にみる成功の法則
最新アフィリエイト事例にみる成功の法則
コンバージョンレートを高めよう!(9月5日)
百式のネットビジネス研究
百式のネットビジネス研究
ガジェット購入時に将来の買取保証プランを提供する「TechForward」(9月5日)
週刊-サイト別アクセス状況データ
週刊-サイト別アクセス状況データ
ビデオリサーチインタラクティブ調査(月間インターネットオーディエンスデータ)(9月4日)
「IT の耳」
「IT の耳」
【書評】『検索にガンガンヒットさせる SEO の教科書』――SEO テクニックで効果的に PR する(9月4日)
検索エンジンマーケティング
検索エンジンマーケティング
果たしてモバイル SEO は必要なのか?(9月4日)
Eメールマーケティング事情
Eメールマーケティング事情
読者が迷惑メールと認識する時…(9月3日)
日本と韓国のインターネットビジネス最新動向調査
日本と韓国のインターネットビジネス最新動向調査
日本と韓国の動画サイト比較1―現状(9月3日)
SNSをビジネスに活用しよう
SNSをビジネスに活用しよう
「しまじろう」に学ぶ企業内コミュニティの活性化のポイント(9月2日)
海外のインターネットコムアメリカ韓国ドイツトルコ
Copyright 2008 Jupitermedia Corporation All Rights Reserved.http://www.internet.com/