SDK Developmentのベストプラクティス

このページは機械翻訳により提供されています。翻訳内容と英語版に相違がある場合は、英語版が優先されます。

カスタムコネクターのDevelopment、構築、テスト、保守を容易にするベストプラクティスについては、次のリストを参照してください:

概要

  • コードをクリーンで理解しやすく保ち、命名は表現力のあるものにします。
  • 安全な認証とユーザーフレンドリーなフィールドを使用し、機密データをコードに含めないでください。
  • テストには、最小限で低権限のエンドポイントを使用します。
  • 静的なオブジェクト定義よりも動的なオブジェクト定義を優先し、ユーザーフレンドリーなラベルを含め、control_typeを慎重に使用します。

全般

これらのベストプラクティスは、WorkatoのSDKプラットフォームでのカスタムコネクターのDevelopmentに直接関連しています。

  • コネクターには、アプリケーションにちなんだ名前を付ける必要があります。 これにより、自分またはワークスペース内のコラボレーターが独自のカスタムコネクターを検索しやすくなります

    • 標準/グローバルコネクターがすでに存在する場合、SDKには<app name> (Custom)という名前を付ける必要があります。これはカスタムSDKコネクターであることを示します
  • アクションを構築するときは、トリガーおよびアクションレベルのヒントを提供します。 これにより、コネクターに詳しくないユーザーでも、どのアクションを選択すべきかを理解できます

  • コネクターコード内に未使用の変数、メソッド、ピックリスト、object_definitionsを残さないでください

  • コードをクリーンで、読みやすく、理解しやすく、拡張しやすい状態に保ちます

    • RubyのDRY原則に従い、再利用可能なコードにはメソッドとobject_definitionsを積極的に使用します
  • 名前付きオブジェクトまたはメソッドを宣言するときは、常に表現力のある名前にします

    • アクション、トリガー、ピックリスト、メソッド、変数を宣言するには、スネークケースの命名規則を使用します
    • 変数の宣言に短いコードや特殊文字を使用しないでください
    • ユーザーは、各コードブロックが何を実現しようとしているかを、その名前から理解できる必要があります
    • アクションとトリガーの前にコメントを含め、何を行うか、および特別な指示や制限を示します
  • 各キー(メソッド、アクション、トリガー、ピックリストなど)の間に空行を含めます。 これにより、改善しようとする人にとってコードが読みやすくなります

  • データを2階層以上たどる必要がある場合は、digメソッドを使用します。 詳細はこちら

  • 可能な場合は、文字列連結("string" + "string")ではなく#{}を使用します

    • 変数が宣言されていない場合でもエラーが発生しないため、#{}の方が防御的です
  • 日付フィールドと形式は慎重に使用し、タイムゾーンが処理されていることを確認します

  • Recent testsタブのConsoleセクションを使用してテストやデバッグを行う場合を除き、コード内でputsを使用しないでください

  • HTTPレート制限があるエンドポイントに対して、トリガー(厳密に)およびアクションを実装しないでください

    • アクションが必要な場合は、コネクターコードではなくレシピでレート制限ロジックを処理します
  • 各トリガーとアクションには、適切なアクション名またはトリガー名を含む説明タグを設定する必要があります

    • 標準規則: <action/trigger> <object> in <applicationName>
    • 例: Xeroで請求書を検索

セキュリティ

  • エンドユーザーのターゲットアプリケーションを保護するために必要な検証を、executeラムダで実行します。 ユーザーがSlack、Teams、外部フォームなどのアプリケーションからデータをマッピングする可能性があり、インジェクションまたはパストラバーサル攻撃の試行がある可能性があることを想定してください。
    • アプリケーションを管理している場合は、APIリクエストから受信した入力をサニタイズすることで、扱うアプリケーションがこれらの入力を処理するようにしてください。 APIプロバイダーは、特定の入力が悪意のあるユーザー入力に対して敏感になる状況をより深く理解する必要があります。
    • Workato側では、入力を検証することで悪意のある入力を防ぐための追加の試みを行ってください。
    • エンドユーザーには、機密フィールドに自由形式のユーザー入力を提供しないよう助言します。 たとえば、可能な場合は列挙値のドロップダウンを指定します。

ルートキー固有

コネクション

  • 機密データにはcontrol_type: passwordを使用します

  • 認可URLでスコープをリクエストできるOAuth 2.0コネクションの場合、コネクターのユーザーがコネクションを作成するときに選択できる入力にする必要があります。

  • サブドメインパラメーターに関するユーザー入力を求める場合は、control_type: subdomainおよびurlを使用します

    • これにより、エンドユーザーにとって入力フィールドが使いやすくなり、人為的ミスの可能性が最小限になります
    • 例:
      ruby
      fields: lambda do |_connection, _config_fields|
        {
            name: 'sub_domain',
            control_type: 'subdomain',
            url: '.salesforce.com',
            optional: false,
            hint: 'Provide salesforce sub-domain for example, <code>test_instance</code>'
        }
      end
  • コネクターを配布する目的がある場合は、機密情報がコード内に保持されていないことを確認します

    • これは、OAuth 2.0フローで認証する際のクライアントIDとシークレットでは特に重要です
  • 時間の経過とともに期限切れになる認可トークンには、refresh_tokenキーとdetect_onキーを定義します。 初回のコネクションは成功しても、トークンの有効期限が切れるとコネクションが切断される場合があります

  • ユーザーが正常なコネクションを作成するための認証情報を取得する方法を支援する参照リンクを提供します

    • APIキーやクライアントIDとシークレットを生成できるURLへのリンクを追加するだけでも、カスタムコネクターのユーザーにとって大きな助けになります。
  • OAuth 2.0認証の認可URLに、必要なスコープが含まれていることを確認します

  • type: "custom_auth"を使用する場合、acquireキーはdetect_onまたはrefresh_onがトリガーされた場合にのみ実行されます。 トークンなどの認証情報を取得するためにacquireキーを使用する場合は、適切なトークンを取得せずにtestキーが実行されたときに返されるエラーコードを必ず含めてください。

  • アプリが同時に複数のバージョンをサポートしている場合は、APIのバージョンを含めます

  • API URLをコネクションハッシュに保存します

    • ベースURLが動的でテナント固有の場合は、acquireキーを使用してbase_urlを動的に取得します
  • SDKが異なるEnvironmentをサポートする必要がある場合は、ピックリストを使用してプロダクション、サンドボックスEnvironmentを選択します

  • コネクション失敗につながる入力ミスを避けるため、connectionキーのfieldsキーでピックリストを使用します

  • API呼び出しのベースURLを設定するには、base_uri(該当する場合)を使用します。これにより、トリガー、メソッド、ピックリストに完全なURLを保持することを避けられます

    • 例:
    ruby
    base_uri: lambda do |connection|
      if connection['custom_domain']
        "https://#{connection['custom_domain']}"
      else
        'https://go.trackvia.com'
      end
    end
  • 静的なbase_uriを使用するか、エンドポイントからbase_urlを取得します(アカウント固有のbase_urlを返すAPIがある場合)

テスト

  • コネクションをテストするには、レスポンス内のデータが最小限で、最小権限のエンドポイントを使用します。

    • たとえば、メモリ内に最小限のデータを保持する可能性があるエンドポイント“get(/profile/me”を使用します。
  • テストエンドポイント呼び出しで保存されるデータを可能な限り少なくするため、getメソッドを最小化します。

    • これにより、コネクションを正常に作成するまでの時間が短縮されます
    • レシピを開始する前にコネクションステータスを検証します

オブジェクト定義

  • 静的なオブジェクト定義よりも、動的なオブジェクト定義を優先する必要があります

    • 動的なオブジェクト定義は、カスタムコネクターのメンテナンス量を減らします。特に、接続先のアプリケーションでユーザーがカスタムフィールドを作成できる場合に有効です
    • 動的なオブジェクト定義は通常、接続先のアプリのメタデータエンドポイントにHTTPリクエストを送信することに依存します。 レスポンスを使用して、データをinput_fieldsキーとoutput_fieldsキーで想定される形式に変換します。
  • オブジェクト定義は、使用しない場合でも常に引数付きで定義されていることを確認してください。 これにより、将来の後方互換性の問題を防ぐことができます。

  • オブジェクトフィールド名では、アンダースコア_を除き、特殊文字は許可されません

  • カスタムコネクターのエンドユーザーのユーザビリティを高めるために、ラベルを使用します

    • たとえば、一部のAPIは、レスポンスにフィールドに適したラベルを含むメタデータエンドポイントを提供します。 たとえば、ターゲットアプリケーション内のフィールドに関するメタデータには、IDフィールドとnameフィールドが含まれる場合があります。 エンドユーザーのユーザビリティを最大化するために、オブジェクト定義のnameIDに、オブジェクト定義のlabelnameにマッピングする必要がある場合があります。
  • ユーザーエラーを減らすために、control_typeを慎重に使用します

    • たとえば、日時入力を収集する場合は、textではなくcontrol_type = date_timeを使用します
  • booleanselectmulti-selectのcontrol_typesではトグルフィールドを使用し、レシピ設計時にデータピルをマッピングするためにユーザーがtext入力に切り替えられるようにします

  • トグルオプションを提供する場合、トグルヒントには許可される値を示す必要があります。

    • 値が少ない場合はレシピUIに値を一覧表示し、それ以外の場合はトグルフィールドで可能な値を示す適切なページにリンクします
  • double、float、通貨値が必要な場合は、number型を使用します。

  • オプションが静的な場合、たとえば性別、住所タイプ、通貨タイプなどでは、selectオプションに静的なpick_list値を使用します


アクション

一般

  • アクションには明確な名前を付ける必要があります

    • アクションの命名規則:
      • Get: IDで特定のレコードを1つだけ取得
      • Search: 検索クエリに基づいて0、1、または複数のレコードを返す
      • List: すべてのレコードを一覧表示
      • Add: 新しいレコードを作成
      • Create: 新しいレコードを作成
      • Update: 既存のレコードを更新
      • Upsert: 新しいレコードを作成、または既存のレコードを更新
  • 必要に応じて、必ずinput_fieldsに対して検証を実行します

    • 検証を実行してエッジケースに備えることを常に推奨します
  • ユーザーへの特別な指示を示すには、helpタグを使用します

  • executeブロックでは、データのためにのみターゲットアプリケーションのエンドポイントを呼び出します

    • メタデータHTTPリクエストはobject_definitionsで実行されている必要があります
  • 冗長なコードを減らすため、可能な限りメソッドを使用します

  • Cookieなどのレスポンスヘッダー情報を取得するには、after_responseブロックを使用します。

  • CRUD操作用に、任意のエンドポイントで使用できるカスタムアクションをコネクターに用意しておくことは良いプラクティスです

  • テーブル全体を削除したりobject_definitionsに影響を与えたりするアクションは、Workatoでは推奨されません

    • これらのアクションは永続的な影響を及ぼし、データ損失につながる可能性があります
    • これらのアクションは、レシピを通じてではなく、アプリケーションの管理者が直接、意図的に実行することを推奨します

メモリ管理

  • レシピアクションを最適化する
    • アクション入力から冗長または不要に重い属性を削除し、実際に必要なフィールドのみを残します。
    • 過剰なペイロードを避けるため、アクションに渡されるエンティティのサイズを確認します。
    • 大きなファイルやデータセットを扱う場合は、ストリーミングまたはページネーションを使用します。
      • たとえば、ファイル全体をメモリに読み込むのではなく、チャンク単位(たとえば一度に5~10 MB)でファイルをダウンロードまたはアップロードします。
      • ページネーションまたはカーソルをサポートするAPIでは、すべてのレコードを一度に読み込むのではなく、ページを順番に処理します。

トリガー

一般

  • トリガーの名前は、その動作を具体的に示す必要があります

  • 例: Repliconの新規従業員: Repliconで新しい従業員が作成されたときにトリガーされます

  • トリガーの命名規則:

    • New: オブジェクトが作成されたときに検出するトリガー
    • New or updated: オブジェクトが作成または更新されたときに検出するトリガー
    • Deleted: オブジェクトが削除されたときに検出するトリガー
  • Since入力フィールドは、ユーザーが過去のデータを取得する場合に役立つことがよくあります

    • これは、レシピを最初に開始するときに、過去の日付からレコードを取得できるようにする任意フィールドにできます
    • 従来、APIは設定パラメーターを使用して過去の日付以降のレコードをクエリできるようにすることで、これをサポートする必要があります
  • pollキーでは不要なAPIリクエストを行わないでください。このキーは各トリガーポーリングで少なくとも1回実行されます

  • クエリフィールド、ページ番号、最終更新日時(必要な場合のみ)を保存するにはclosureキーを使用します

    • closureにキャッシュされた情報は、ポーリング間隔をまたいで保持されます。
  • 冗長なコードを減らすため、可能な限りメソッドを使用します

  • Webhook URLの設定と削除をプログラムで行う機能を持つAPIでは、動的Webhookを使用する必要があります

    • 静的Webhookは代替手段ですが、Workatoから提供された静的URLを手動で登録する必要があります

連続ポーリング

ポーリング時、トリガーは有効な結果を取得するために連続してポーリングできます。 SDKのトリガーpollラムダレスポンス内のcan_poll_moreブール属性が、この動作を制御します。 trueに設定すると、トリガーは即時ポーリングを開始します。 Workatoは、ジョブが生成されない場合、単一のポーリングサイクル内での連続ポーリングの最大回数に制限を適用します。 詳細については、ジョブなしの単一ポーリングサイクルにおける連続ポーリングセクションを参照してください。

can_poll_moreを効果的に設定し、ポーリング制限への準拠を確保するには、次のベストプラクティスに従ってください:

ポーリングする追加ページが残っている場合にのみcan_poll_moretrueに設定する

取得できる追加のデータページがある場合にのみ、can_poll_moreフラグをtrueに設定します。 これにより、不要なAPI呼び出しを防ぎ、無期限のポーリングを回避できます。

たとえば、APIがページ分割されたレスポンスを返し、取得されたレコード数がページサイズと一致する場合、さらに取得するレコードがあることを示している可能性があります。 そのような場合は、can_poll_moretrueに設定します。 それ以外の場合は、falseに設定し、次のポーリング間隔を待ちます。

適切なフィルターでイベント取得を最適化する

各ポーリング中に必要なイベントのみを取得するようにトリガーを設定します。

たとえば、フィルターを使用して、前回のポーリング以降に作成または更新されたイベントを取得します。 last_modifiedcreated_atなどのタイムスタンプのフィルターを適用して、冗長なデータの取得を避けます。

リアルタイム監視にWebhookを活用する

リアルタイム監視では、Webhookはポーリングトリガーよりも効率的です。 Webhookはイベント発生時にアプリケーションへデータをプッシュするため、継続的なポーリングの必要性が減り、ソースシステムとアプリケーションの負荷を最小限に抑えられます。

メモリ管理

  • ポーリングを重い処理から分離する

    • トリガーは、新規/更新レコードのポーリングのみに集中させます。
    • 添付ファイルのダウンロード、大きなバイナリファイル処理、繰り返しのAPI呼び出しなど、メモリを大量に消費する操作は、メモリ不足やタイムアウトエラーを防ぐために別のアクションへ移動します。
  • トリガーでのメモリ利用状況を最適化する

    • ページネーションなしですべてのデータを一度にダウンロードしないでください。
    • pollメソッド内で不要なデータコピーや変換を最小限に抑えます。
    • 単一操作で大きなデータセットを処理するのではなく、選択的なフィールド取得でより頻繁にポーリングすることを検討してください。

サンプル出力

  • Workatoレシピでは、すべてのアクションまたはトリガーに、アプリデータセクションの出力データピルを含むサンプル出力データを設定する必要があります

    • これにより、下流システムに渡されるデータに関する情報がユーザーに提供され、ユーザビリティが向上します
  • フィールド数が少ないオブジェクトには、静的なサンプル出力データが推奨されます

    • フィールド数が多いオブジェクトには、動的なサンプル出力を使用できます
    • sample_outputキーでサンプルデータを表示するために、過度なデータ変換や多数のAPI呼び出しを行わないでください
    • ファイルのダウンロードアクションでは、sample_outputキーに静的データを使用します
  • 各トリガーまたはアクション(出力)にサンプルデータが設定されていることを確認します

    • これは各データピルの横にグレーのテキストとして表示される必要があります
    • トリガーに入力フィールドがない場合、2つ目のアクションが追加されるまでデータツリーは表示されません

エラー処理

  • raiseメソッドを使用して例外を通知します

  • APIがエラーを返すのを待つのではなく、検証エラーを早期に検出します。

  • SDKで特定のエラーコードを処理し、独自のレスポンスを定義する必要がある場合は、エラー処理を実装します

  • 例外を抑制しないでください。隠すよりも、より多くのAPI情報を公開する方が適切です


ユーザビリティとテスト

一般

  • アクションとトリガーについてレシピUIを確認します

  • アクション名、トリガー名、ラベル、ヘルプ指示が、その目的をエンドユーザーに明確に伝えていることを確認します

  • レシピを作成して、カスタムコネクターのエンドツーエンドテストをいくつか設定することを忘れないでください

    • これは、サンドボックスEnvironmentを使用したレシピで先にテストしてから、コネクターの新しいバージョンをプロダクションワークスペースにプッシュする場合に特に役立ちます

ユーザビリティルール

オブジェクトベースのアクションとトリガーの作成に関する概念を学んだので、コネクターをテストする必要があります。 Connector SDKのTest codeタブだけでなく、レシピで使用する場合にも機能をテストします。 この段階に達したら、コネクターの特定の側面が期待したほど使いやすくないことにも気付き始める場合があります。 優れたコネクターは、コードの観点で整理されているだけでなく、レシピ構築体験全体でユーザーエクスペリエンスを最優先にします。 ユーザーフレンドリーではないコネクターと優れたコネクターを区別するルールをいくつか示します:

説明的なヘルプテキスト

アクションのヘルプテキストは、構築したアクションに関してユーザーが持つ可能性のある知識のギャップを埋めるうえで重要です。 アクションのヘルプテキストに含めるべき重要な詳細を以下に示します:

サポートされるAPIバージョン

接続先アプリケーションのAPIバージョンは、ユーザーの期待値を管理するのに役立ちます。 ユーザーは、コネクターの機能面で何を期待できるかをよりよく理解できます。

オブジェクト固有のヘルプ

オブジェクトによっては、異なるアクションレベルのヘルプヒントが必要になる場合があります。 ヘルプテキストは、ユーザーが選択したオブジェクトに基づいて簡単に変更できます。

ruby
help: lambda do |input, picklist_label|
  if input['object'] == 'invoice'
    {
      body: "Creates an invoice in XYZ. Invoices in XYZ accounting are essential " \
      "components of the platform. This action supports the creation of invoices " \
      "including custom fields",
      learn_more_url: "docs.xyz.com",
      learn_more_text: "Learn to setup this action"
    }
  else
    {
      body: "Creates an object in XYZ. First, select from a list of " \
      'objects that we currently support. After selecting your object,' \
      ' dynamic input fields specific to the object selected ' \
      'will be populated.'
    }
  end
end,

ヘルプテキストには、このアクションの設定方法についてユーザーがさらに情報を必要とする場合に、適切なドキュメントへのリンクを含めることもできます。

ヘルプテキストのヒント小さな段落にすべての情報を含められない場合、ドキュメントへのリンクはユーザーの助けになります

フィールドレベルのヒント

ヒントは、特定の入力フィールドの使用方法についてユーザーを案内するための重要な手段です。 タイムスタンプが特定の日付形式(iso8601またはDD/MM/YYYY)である必要があるかどうかなど、想定される入力について知らせます。

フィールドレベルのヘルプ

ユーザーがアクションを適切に設定するためにこれを読むことが重要な場合は、フィールドレベルのヘルプを使用することをお勧めします。 これは控えめに使用する必要があります。

ruby
[
  {
    control_type: "text",
    label: "Txn date",
    type: "string",
    name: "TxnDate",
    optional: true,
    sticky: true,
    help: {
      title: "Extra info",
      text: "This field is super important"
    }
  }
]

ヘルプテキストのヒントフィールドレベルのヘルプを使用して特定のフィールドに注意を向ける

ユーザーフレンドリーな入力フィールド

コネクターを可能な限りユーザーフレンドリーにするために微調整する際に役立つ、いくつかの簡単なルールを示します。 最終的にWorkatoにグローバルスコープのコネクターとして掲載されることを目指してコネクターを作成する場合、これらのルールは各コネクターに対して行うUIUXレビューの重要な部分になります。

  1. 入力フィールドのラベルは十分に説明的ですか? エンドユーザーと同じページに立てるように、入力フィールドのラベルを定義するときは可能な限り明確にします。 フィールドのnameidであっても、ラベルをInvoice IDに変更すると、エンドユーザーは何をしているのかをすぐに理解できます。

  2. 入力フィールドのtypeとcontrol_typeは正確ですか? Typesとcontrol_typesは、ユーザーが扱っている値の種類を理解するのに役立ちます。 何も定義されていない場合、Workatoはtypeとcontrol_typeのデフォルトをstringとtextに設定します。

  3. ラベルを変更してもまだ曖昧な入力フィールドに対してヒントを宣言しましたか? ヒントを使用すると、ユーザーをさらに的確に案内できます。 HTML形式のリンクも使用できます。

  4. この入力フィールドは定義済みの値セットのみを受け入れますか? selectドロップダウンを使用すると、ユーザーが回答を手動で入力するのではなく、正しい入力を行いやすくなります。 これにより、ユーザーが直面する可能性のあるエラーの数も減ります。

  5. この入力フィールドはID値を受け入れますか? たとえば、XYZ accountingのcreate invoiceアクションでは、関連する顧客のIDを含む入力フィールドが必要になる場合があります。 ユーザーは顧客のIDを手元に持っていない場合がありますが、代わりに顧客名は持っている場合があります。そのため、入力フィールドを、ラベルとして顧客名を表示し、値として顧客のIDを提供するピックリストにすることを検討できます。

  6. ドロップダウンを使用する場合は、必要に応じてユーザーがデータピルをマッピングできるtoggle_fieldオプションも必ず含めます。 ドロップダウンは便利ですが、ユーザーが代わりにデータピルをマッピングする必要がある場合もあります。 toggle_hintsもそれに応じて変更することを忘れないでください。

  7. このドロップダウンは設定フィールドですか? はいの場合、データピルがマッピングされないように、セカンダリトグルフィールドのcontrol_typeplain-textに設定されていることを確認します。 アクション内の他の入力フィールドがその情報に依存しているため、設定フィールドはデータピルを受け入れてはいけません。

  8. アクションまたはトリガーのすべての必須フィールドに必須としてラベル付けされていますか? ユーザーは、このアクションを有効にするために入力する必要があるフィールドをすばやく理解できる必要があります。

  9. 一般的に使用される任意フィールドはありますか? これらのフィールドをstickyにすると、エンドユーザーがフィールドを探すのではなく、その入力フィールドに注意を向けられます。

  10. コネクターのエンドユーザー向けに、可能なカスタムフィールドを動的に取得していますか? 各カスタムフィールドでcustomパラメーターを使用し、どのフィールドが標準で、どのフィールドがユーザーにとってのカスタムなのかについてフィードバックを提供します。

各入力フィールドについて、この一連の質問をすばやく確認することをお勧めします。 慣れてくると、調整が必要な入力フィールドを特定し、スキーマ定義に戻って変更を加えるだけのシンプルなプロセスになります。

説明的なエラーメッセージ

説明的なエラーメッセージは、エンドユーザーのレシピ構築体験において非常に重要な要素です。 適切なエラーメッセージがないと、ユーザーはレシピが失敗している理由を把握するのに苦労します。 Workatoでエラーを表示する方法をまだ確認していない場合は、エラー処理ガイドを確認してください。

コネクターに適切なエラー処理を含めるための一般的なルールを以下に示します。

  1. コネクターでピックリストや何らかの動的スキーマを使用していますか? after_error_response関数を連結することで、ユーザーは何が問題だった可能性があるかについて正確な情報を受け取れます。 例はこちら。

  2. コネクターには、開始日と終了日など、一緒に必須となる特定のフィールドがありますか? これらのフィールドは常に必須ではない場合がありますが、一部のフィールドは一緒に必須となることがよくあります。 このような場合、検証によってこれらのエラーをより適切に表面化し、不要なAPI呼び出しの数も減らせます。 例はこちら。

  3. 接続先のAPIは適切なHTTPステータスコードで応答しますか? 場合によっては、APIが実際にはエラーであるべきレスポンスを返しても、HTTPステータスが200になることがあります。 このような場合は、 after_error_response関数を使用することで、代わりにユーザーへ問題を明示できます。 例はこちら。

Last updated: