とあるStartupに勤めるエンジニアの技術ブログ

Salesforce、テスト関係の技術ブログなどを書く予定

Salesforceで外部サービスと非同期に連携するアーキテクチャの考察

Salesforceで外部サービスと非同期に連携するアーキテクチャの考察

Salesforce界隈の皆さま、今年もお疲れさまでした!
1年の締めくくりといえば、やっぱり技術系アドベントカレンダー。新しい知識を得る喜びや、課題を乗り越える楽しさを共有し合いましょう。

はじめに

Salesforceにおいて、外部サービスと非同期に連携する汎用的なコンポーネントを開発するために考えたことを書いていきます。
前提として汎用的なコンポーネントを画面に配置して外部サービスを非同期で呼び出すようにするためにLightning Web Comoponentsを利用します。

Salesforceから外部サービスを非同期に呼び出す場合には下記のようなハードルがあります。

  • 外部サービスにリクエストを送る際に、固有のコリレーションIDを指定できるか?
  • コールバック処理でコリレーションIDから対象オブジェクトを特定できるか?
  • コールバック処理で任意の処理を実行できるか?

これらのハードルを解消する方法についてアーキテクチャを検討していきます。

Salesforceの処理から外部サービスに戻り先を渡す必要がある

まず、ポイントとなることとしては「非同期」である点です。
同期的なコールアウトであれば、Httpクラスを利用して外部サービスのWebAPIをコールするだけなので簡単です。
しかし、非同期であるために戻り先を指定する必要があります。

具体的には、外部サービス側の処理が終わったときにコールバックするためのCallback URLとコールバック処理内でデータを書き戻すなどの処理を実行するときにデータを特定す仕組みが必要となります。

ここからはそれらに必要な仕組みについて検討します。

コリレーションIDの生成と利用

Salesforce側のデータと外部サービスのコールバックを関連付けるためには、外部サービスにリクエストを送る際に、固有のコリレーションID(SalesforceのレコードIDやカスタムユニークID)を渡すことが一般的です。
外部サービスはこのコリレーションIDをそのままコールバック時に返すことで、呼び出し元を特定できます。

public static void sendRequestToExternalService(String recordId) {
    // 外部サービスへのリクエストを準備
    Http http = new Http();
    HttpRequest request = new HttpRequest();
    request.setEndpoint('https://external-service.example.com/api');
    request.setMethod('POST');

    // コリレーションIDを渡す
    String correlationId = recordId; // 例: SalesforceレコードIDを利用
    request.setBody('{"correlationId": "' + correlationId + '", "callbackUrl": "https://yourInstance.salesforce.com/services/apexrest/callback"}');
    request.setHeader('Content-Type', 'application/json');

    HttpResponse response = http.send(request);

    // 応答を処理
    System.debug('Response: ' + response.getBody());
}
Apex RESTエンドポイントの活用

SalesforceでコールバックするためREST APIのエンドポイントを用意する必要があります。そのためにApex RESTエンドポイントを活用します。
Apex RESTエンドポイントを外部サービスから認証なしでURLをコールしようとした場合、サイト機能の利用、など管理パッケージに含めることができない機能を利用する必要があります。
そこで、Apex RESTエンドポイントを呼び出すときには何らかの方法で認証します。
そのため、外部サービスでCallback URLと認証情報を事前に設定します。

以下は、Apex RESTエンドポイントを定義するサンプルコードです。

@RestResource(urlMapping='/callback')
global with sharing class CallbackHandler {
    @HttpPost
    global static void handleCallback() {
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;

        // 外部サービスからのデータを取得
        String externalId = req.params.get('externalId');
        String status = req.params.get('status');
        
        // 必要な処理を実行
        if (status == 'success') {
            System.debug('External service completed successfully for ID: ' + externalId);
        } else {
            System.debug('External service failed for ID: ' + externalId);
        }
    }
}
Lightningレコードページの活用

次に、考えるポイントとしてはコールバック処理でデータを特定するためのキーであるレコードIDを汎用的な仕組みで取得する方法です。

Lightning Web Components 間でのデータのやり取りとしては、publicプロパティ・publicメソッド、カスタムイベント、Lightning Messeging Serviceが考えられます。しかし、プロコードによるインテグレーションはできるだけ避ける方針とするため、これらの実装は採用できません。

そこで、LightningレコードページによってレコードIDを渡す方式を採用します。

LightningレコードページによってレコードIDを渡すサンプルコードです。

JavaScript ファイル (myRecordComponent.js)

import { LightningElement, api } from 'lwc';

export default class MyRecordComponent extends LightningElement {
    @api recordId; // レコードIDを受け取るプロパティ

    connectedCallback() {
        console.log('Received recordId:', this.recordId);
        // ここで recordId を使った処理を行うことができます。
    }
}

HTML ファイル (myRecordComponent.html)

<template>
    <lightning-card title="Record Details" icon-name="standard:record">
        <div class="slds-m-around_medium">
            <p>Record ID: {recordId}</p>
        </div>
    </lightning-card>
</template>

メタデータ ファイル (myRecordComponent.js-meta.xml)

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="myRecordComponent">
    <apiVersion>62.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target> <!-- レコードページに配置可能 -->
    </targets>
</LightningComponentBundle>

外部サービスからコールバックされたときに呼び出し元を特定する

外部サービスからコールバック処理を呼び出したとしても、汎用的な仕組みであるためコリレーションIDだけでは処理を実行することができません。
そのため、コールバックされたデータを使って柔軟な処理を行うには、外部サービスから戻されたコリレーションIDとしてのレコードIDから対象オブジェクトを特定する必要があります。

レコードIDから対象オブジェクトを特定する

対象オブジェクトが特定でき、メタデータ情報が取得できると、対象オブジェクトに対してデータ更新することができます。

レコードIDから対象オブジェクトを特定するためのサンプルコードです。

public static void describeObjectById(Id recordId) {
    // IDの接頭辞を取得
    String prefix = String.valueOf(recordId).substring(0, 3);

    // 全オブジェクトのDescribe情報を取得
    Map<String, Schema.SObjectType> globalDescribe = Schema.getGlobalDescribe();
    Schema.SObjectType objectType = null;

    // 接頭辞に基づき、対象オブジェクトを検索
    for (Schema.SObjectType sObjectType : globalDescribe.values()) {
        if (sObjectType.getDescribe().getKeyPrefix() == prefix) {
            objectType = sObjectType;
            break;
        }
    }

    if (objectType != null) {
        // オブジェクトのメタデータ情報を取得
        Schema.DescribeSObjectResult objectDescribe = objectType.getDescribe();
        System.debug('Object Label: ' + objectDescribe.getLabel());
        System.debug('Object Name: ' + objectDescribe.getName());
    } else {
        System.debug('Object not found for prefix: ' + prefix);
    }
}

コールバック時に任意の処理を実行できるようにする

コールバックされたデータを使って柔軟な処理を行うには、以下のような方法があります。

Platform Eventを利用した処理の柔軟化

Platform Eventを使うことで、Salesforce内での処理を非同期かつ疎結合で実行できます。
Platform Eventを利用することで、フローやApexを利用して処理を拡張することができます。

Platform Eventの定義例

// 定義されたプラットフォームイベント
event MyCallbackEvent__e {
    String CorrelationId__c;
    String Status__c;
}

コールバックハンドラーでイベントを発行

@RestResource(urlMapping='/callback')
global with sharing class CallbackHandler {
    @HttpPost
    global static void handleCallback() {
        RestRequest req = RestContext.request;

        // Platform Eventの発行
        MyCallbackEvent__e event = new MyCallbackEvent__e();
        event.CorrelationId__c = req.params.get('externalId');
        event.Status__c = req.params.get('status');
        EventBus.publish(event);
    }
}
Apexクラスの動的呼び出しによる柔軟化

Apexクラスのクラス名をカスタムメタデータ型に定義し、それを動的に呼び出すことでコールバック処理を柔軟に拡張することができます。

以下のコードで、カスタムメタデータ型からクラス名を取得し、Typeクラスを使用してインスタンス化およびメソッドの実行を行います。

動的呼び出しコード

public class DynamicClassExecutor {
    public static void executeClass(String label) {
        // カスタムメタデータ型からクラス名を取得
        ClassMapping__mdt metadata = [
            SELECT ClassName__c 
            FROM ClassMapping__mdt 
            WHERE DeveloperName = :label
            LIMIT 1
        ];
        
        if (metadata == null || String.isEmpty(metadata.ClassName__c)) {
            throw new IllegalArgumentException('No class name defined for label: ' + label);
        }

        // クラス名をTypeクラスで動的にロード
        Type classType = Type.forName(metadata.ClassName__c);
        if (classType == null) {
            throw new IllegalArgumentException('Class not found: ' + metadata.ClassName__c);
        }

        // インスタンス化とメソッド実行
        Object instance = classType.newInstance();
        if (instance instanceof DynamicClassInterface) {
            ((DynamicClassInterface)instance).execute();
        } else {
            throw new IllegalArgumentException('Class does not implement DynamicClassInterface: ' + metadata.ClassName__c);
        }
    }
}

インターフェースの定義

public interface DynamicClassInterface {
    void execute();
}

サンプルクラスの実装

public class MyDynamicClass implements DynamicClassInterface {
    public void execute() {
        System.debug('MyDynamicClass is executed!');
    }
}

まとめ

Salesforceで外部サービスと非同期に連携する際に考慮すべきポイントを整理しました。

1. コリレーションIDを渡すことで呼び出し元を特定
2. コリレーションIDから対象オブジェクトを特定
3. Platform EventやApexクラスを活用して柔軟なコールバック処理を実現

これらを適切に組み合わせることで、Salesforceと外部サービス間の汎用的な非同期連携を構築できます。

最後になりますが、この投稿は Salesforce - Qiita Advent Calendar 2024 - Qiita の第8日目の投稿となります。

qiita.com

この記事は、 note.com に投稿した記事の転載になります。
note.com

ゼロからはじめるLightning Web Component 〜WebAPIっぽく実装したい!〜


今年の技術系アドベントカレンダーももう最終日ですね。
12月1日からクリスマスの25日まで、毎日投稿されるアドベントカレンダーの記事が投稿されてきましたが、面白い、勉強になる、記事は見つけられましたでしょうか?
これから年末年始のお休みにアドベントカレンダーの記事をじっくり読み耽ってみてはいかがでしょうか?

はじめに

さて、今回はLightning Web ComponentとApexクラスのデータ渡しについて、WebAPIっぽく実装したい私が抱いている願望が2つあります。

1つ目は、@wireがあまり仲良くなれそうにない私としては、JSON形式でデータをやりとりしたいという願望です。

そして、もう一つ@AuraEnabledはパッケージングするとパッケージをインストールした組織ではAPIが公開されてしまったり、気軽に追加・削除できなかったりするのでなんとかしたい願望です。

2つの願望を叶える設計思想

まずは、JSON形式でデータをやりとりするため、Lightning Web Component側ではJSON.stringify() / parse() を、Apexクラス側ではJSON.serialize() / deserialize()を利用します。
次に、@AuraEnabledの問題については、Lightning Web Component側からコールされるためのメソッドを作成し、そこから各処理に振り分けることで処理ごとにメソッドを作成しなくてもよくなります。

ApexとLWCの実装

今回は、ボタン押下時に入力ボックスに入力された文字列を送信して、結果をテキスト表示する簡単なサンプルになります。

Lightning Web Component側

Lightning Web Component側のソースコードは下記のようになります。
データ送信時には、JSON.stringify()を使って送信するデータをJSON形式に変換して、Apex側のメソッドをコールしています。

lwcCallApex.html
<template>
    <lightning-card title="Call Apex methods with JSON">
        <div class="slds-var-p-around_medium ">
            <lightning-input type="text" label="Message" value={message} onchange={changeHandler}></lightning-input>
            <lightning-button variant="brand" label="Submit" onclick={clickSubmit}></lightning-button>
            <p class="slds-var-p-horizontal_small">Result: {result}</p>
        </div>
    </lightning-card>
</template>
lwcCallApex.js
import { LightningElement, api } from 'lwc';
import callMethod from '@salesforce/apex/CallApex.callMethod';

export default class LwcCallApex extends LightningElement {
    message = "Lightning Web Component";
    result = "(No result)";

    clickSubmit(event) {
        const request = {};
        request.path = "/submit";
        request.param = this.message;

        callMethod({ request : JSON.stringify(request) })
        .then(result => {
            if(res.status == 200) {
                this.result = JSON.parse(result).body;
            } else {
                this.result = "Error";
            }
        })
        .catch(error => {
            console.log(error);
            this.result = error;
        })
    }

    changeHandler(event) {
        this.message = event.target.value;
    }
}

Apexクラス側

Apexクラス側のソースコードは下記のようになります。Lightning Web Component側から送信されてきたJSON形式のデータを受け取り、JSON.deserialize() でApexクラスに変換しています。
処理の振り分けには、Web APIっぽくパスを指定して、switch文で処理を振り分けています。
結果については結果を格納するApexクラス(Response)を生成して、JSON.serialize()でJSON形式のデータに変換しています。

CallApex.cls
public with sharing class CallApex {
    @AuraEnabled
    public static String callMethod(String request) {
        String body = '';
        
        try {
            Request req = (Request)JSON.deserialize(request, Request.class);            
            switch on req.getPath() {
                when '/submit' {
                    body = '[Submit] ' + req.getParam();
                }
            }
            Response res = new Response(200, body);
            return JSON.serialize(res);
        } catch(Exception e) {
            throw new AuraHandledException(e.getMessage());
        }
    }
    
    public class Request {
        String path;
        String param;
        
        public Request(String path, String param) {
            this.path = path;
            this.param = param;
        }
        
        public String getPath() {
            return path;
        }
        
        public String getParam() {
            return param;
        }
    }
    
    public class Response {
        Integer status;
        String body;
        
        public Response(Integer status, String body) {
            this.status = status;
            this.body = body;
        }
        
        public Integer getStatus() {
            return status;
        }
        
        public String getBody() {
            return body;
        }
    }
}

まとめ

以上で、Lightning Web Component側とApexクラス側のやりとりをJSON形式のデータにして受け渡すことができ、Web APIのようなパスを引数として渡すことで処理ごとにメソッドを増やすことなく処理を追加できるようになりました。

今後の拡張としてはデータ受け渡し処理をフレームワーク化していき、標準化できるものにしたいと考えています。

おわりに

今回は、Lightning Web ComponentとApexクラスのデータ渡しをJSON形式にしつつ、Apexクラス側で処理を振り分ける仕組みを導入した実装を紹介しました。

YouTubeチャンネル「migration talks」ではSalesforce開発関連の動画をアップロードしています。

www.youtube.com

最近ではLightning Web Componentを学習して内容を解説した動画をYouTubeに投稿していっています。序盤では開発環境のセットアップまでの動画をアップロードしています。これからはLightning Web Componentを実装していくための方法について紹介していきたいと思います。

ぜひチャンネル登録していただけると励みになります。

www.youtube.com

最後になりますが、この投稿はSalesforce Advent Calendar 2022 カレンダー2、およびチームスピリット Advent Calendar 2022 の第25日目の投稿となります。

qiita.com

adventar.org


この記事は、 note.com に投稿した記事の転載になります。
note.com

Japan Dreamin' 2022 でLTしてきた!

エンジニアが学ぶカスタマーサクセス

はじめに

すっかりブログをアップするのを忘れてしまっていましたが、2022年1月22日(土)にオンライン開催された Japan Dreamin' 2022 で LT してきました。

今回の発表では、「エンジニアが学ぶカスタマーサクセス」と題してエンジニアが理解したカスタマーサクセス、Customer360の活かし方について話しました。こちらから資料と動画を見ることができますので、よろしければご覧ください。

スライド

speakerdeck.com

きっかけ

今回の発表では「カスタマーサクセス」をテーマとしました。なぜ「カスタマーサクセス」に興味を持ったか?きっかけは「Salesforce認定Data Management and Architecture デザイナー」(現在は「Salesforce認定Dataアーキテクト」)の資格勉強の中で「Customer360は何の役に立つんだろう?」という疑問から始まりました。どうもカスタマーサクセスというものに関係していることが分かり、関連する書籍を数冊読みました。そこで分かってきたことを私なりにまとめて発表したものが今回のLTとなります。

Japan Dreamin' 2022 の LT では時間も短かったこともあり、話しきれていない部分もあったので、追加で YouTube を投稿していますので、合わせてご覧いただければ幸いです。

カスタマーサクセス戦略の深掘り

「カスタマーサクセス」の概念は非常に幅広く、関わる人の立場によっていろいろな定義があると感じました。私はカスタマーサクセスは事業戦略であると捉えました。次の動画では、なぜカスタマーサクセスが事業戦略と考えたのか、どのように戦略と関連しているか深堀りしてみました。

youtu.be

Customer360とサービス活用度

カスタマーサクセスを事業戦略として推進するためにはサービス活用度(ヘルススコア)が重要だとわかりましたが、算出していくために必要となるデータが必要となります。次の動画では、サービス活用度(ヘルススコア)を算出するために顧客に関するデータこそがCustomer360であることを説明しました。

youtu.be

サービス活用度(ヘルススコア)の深堀り

カスタマーサクセスではサービス活用度(ヘルススコア)を利用してサービス改善に取り組んでいきます。次の動画ではサービス活用度(ヘルススコア)を利用して、どのようにサービス改善に繋げていくか深堀りしてみました。

youtu.be

まとめ

今回の発表では、カスタマーサクセスとは事業戦略であり、Customer360はその戦略実行を支えるデータプラットフォームであることを説明しました。

個人的には、Customer360の存在意義が理解できたこと、カスタマーサクセスが顧客のサポートだけではなくプロダクト改善にも活用するものだと理解できたことは非常に大きな学びになりました。

Enjoy Customer Success!

この記事は、 note.com に投稿した記事の転載になります。
note.com

Salesforceの通知を考える 2021年版(Salesforceフロー)

f:id:a-kura:20211130001146p:plain
Salesforceの通知を考える 2021年版(Salesforceフロー)

今年も技術系アドベントカレンダーの季節になりました。
12月1日からクリスマスの25日まで、毎日投稿されるアドベントカレンダーの記事を読んで楽しみながら過ごしていきましょう!

はじめに

Salesforceで通知する手段について、3年前に記事を書きました。Salesforce Platformもアップグレードしてきているので、2021年版を考えていきます。
teamspirit.hatenablog.com

2018年版では、下記の4つの通知方法についてメリット、デメリットをまとめました。

  1. メールアラート
  2. Chatter投稿
  3. レコードを作成
  4. Slack

ここ数年でSalesforceフローが急成長することによって機能が充足してきており、Salesforceフローでほぼ事足りるようになってきています。その流れを受けて今回はSalesforceフローを中心にお届けします。

続きを読む

Japan Dreamin' 2021でLT登壇してきた!

f:id:a-kura:20210314135704p:plain

Japan Dreamin' 2021 - なぜ、Salesforceは最強の業務アプリ・プラットフォームなのか?

2021年1月30日(土)に開催された Japan Dreamin' 2021 に参加・登壇してきました。今年はオンライン開催となったので、LT もオンラインでの発表となりました。

www.trailblazers.jp

 

今回の発表では、「なぜ、Salesforceは最強の業務アプリ・プラットフォームなのか?」と題してSalesforce Platformの強みについて話しました。こちらから資料と動画を見ることができますので、よろしければご覧ください。

www.slideshare.net

youtu.be

 

なぜ、Salesforceは最強の業務アプリ・プラットフォームなのか?

B2B サービスにおける Salesforce Platform の優位性は「カスタマイズ性」にあります。

B2C サービスであれば、利用者は大きくカスタマイズすることなくサービス提供されるまま利用してくれます。ただし、自分に合わないようであれば簡単に使わなくなったり、別のサービスに乗り換えてしまいますが。

しかし、B2B サービスでは自社の業務に直結するため必ず利用する必要があり、簡単には乗り換えられません。また、一つのサービスでは自社の業務を包含できないため、別のサービスと連携させる必要があります。そのため、利用者は自社の業務が回せるようにカスタマイズすることが必須となってきます。

 

Salesforce Platform の持つカスタマイズ性

このカスタマイズ性の源泉となる要素は No-Code / Low-Code、Pro-Code、AppExchange の3つにまとめられます。

f:id:a-kura:20210314135922p:plain

Salesforce Platform の持つカスタマイズ性

 

ノーコード / ローコード

Salesforce Platformはノーコード、ローコードとして、Salesforce フロー、承認プロセス、レポート・ダッシュボードなどコーディングしなくてもカスタマイズできる汎用的な業務機能を多く提供しています。

特に強力な機能としては、画面やオブジェクトを自在に作成できます。この機能は、新しく開発する画面やオブジェクトだけではなく、SalesCloud やServiceCloud が提供する機能も同じようにカスタマイズできる点です。この機能によって自社の業務に合わせるための糊代が格段に拡がっています。

youtu.be

 

プロコード

プロコードでは、Apex、Visualforce Page、Lightning Web Components によって独自の画面や機能、アクションを開発できます。

特に重要なことは Salesforce Platform の機能として提供されることです。カスタマイズするために別の環境を用意する必要がないため、シームレスに SalesCloud や ServiceCloud の機能を拡張できます。同じ環境で機能開発できるメリットとして、既存機能のデータベースに容易にアクセスできることがあります。

また、IT ガバナンス、内部統制、サービス運用などを考えるとシステムの稼働する環境が増えることは IT 運用部門にとってかなりの負担となります。そのため、同じ環境にさまざまなサービスがまとめられることは嬉しいポイントになります。

youtu.be

 

AppExchange

ノーコード、ローコード、プロコードを利用することで、顧客ごとにアプリケーションを開発できます。しかし、アプリケーションを開発しようとすると、それなりに工数がかかります。一般的なアプリケーションであれば、わざわざ開発するのではなく、市販のアプリケーションを利用したくなります。

AppExchagne はアプリケーション・マーケットで、パートナーによって開発されたアプリケーションを探し、インストールできるようになっています。 SalesCloud や ServiceCloud など Salesforce.com 社が提供するサービスだけでは業務を網羅できない部分があります。このパートナーが開発したアプリケーションを利用することで、その隙間を埋めることができます。

 

ISVforce

AppExchange のマーケットにアプリケーションを登録しているパートナーは AppExchange パートナーと呼ばれ、 SaaS プロダクトを開発・提供・運用するために必要な機能が Salesforce.com 社から ISVforce という名で提供されています。

最初に説明した Salesforce Platform で提供されるノーコード、ローコード、プロコードも AppExchange パートナーが開発したアプリケーションで利用できます。

これらをフル活用することで、AppExchange パートナーは B2B サービスで必要となる汎用機能や SalesCloud、ServiceCloudと同等のカスタマイズ性を手に入れ、さらにインフラ運用は Salesforce.com 社に任せ、アプリケーション開発に注力することができます。

youtu.be

 

このように AppExchange パートナーは Salesforce.com 社のサービスが提供していない機能を提供し、Salesforce.com 社は AppExchange パートナーに SaaS を構築するための業務アプリ・プラットフォームを提供する、相互補完的なエコシステムを構築しています。

 

まとめ

今回の発表では、B2B サービスではカスタマイズ性が重要となること、Salesforce Platform が強力なカスタマイズ性を持つことを説明しました。

Salesforce Platform のカスタマイズ性を分割すると、下記の3つになります。
1. No-Code / Low-Code
2. Pro-Code
3. AppExchange

これらの要素は、AppExchange パートナーもその恩恵を受けられます。それ以外にも ISVforce の機能や堅牢なインフラを活用できることで、AppExchange パートナーは B2B サービスのアプリケーション開発に集中できます。これが、Salesforce が最強の業務アプリ・プラットフォームである理由になります。

 

そして、コミュニティ

最後に、Salesforce コミュニティ・イベントでの発表なので、Salesforce.com 社が作り上げた Trailblazer についても言及しました。これまであまり脚光を浴びていなかったシステム管理者をヒーローにした施策は本当に驚異的です。Salesforce が最強である所以はこの人々の存在が大きいので、イベントの締めで話させてもらいました。

f:id:a-kura:20210314140340p:plain

Trailblazer

 

今年で3年目となりました。今年も運営してくれた人たちのおかげで素晴らしいイベントになりました。運営メンバーの努力と貢献に感謝します。そして、来年はさらに進化したイベントになると確信しています。

 

Enjoy Japan Dreamin'!

 


この記事は、 note.com に投稿した記事の転載になります。

note.com

 

B2B SaaSエンジニアMeetup - Sharing Issues Online #1 に登壇してきた!

2020年11月6日(金)に開催された B2B SaaSエンジニアMeetup - Sharing Issues Online #1 に参加・登壇してきました。

smartcamp.connpass.com


今回の発表では、SaaS プロダクトでは重要となる管理画面について話しました。こちらから資料と動画を見ることができますので、よろしければご覧ください。

www2.slideshare.net

www.youtube.com

愛される管理画面の作り方

これまでの受託開発であれば、管理画面はバグなく使えればよいと重視されないことも多かったのではないでしょうか?しかし、SaaS プロダクト開発において、管理画面は重要性が増してきています。

理由としては、SaaS プロダクトの選定・推進・運用が情報システム部門から業務管理部門(人事部、経理部など)にシフトしてきていることが大きいです。ITの専門家でない業務管理部門が自ら SaaS プロダクトを利用していくためには管理画面がITに精通していない人でも習熟できる程度に作り込まれている必要があります。

もし、管理画面が習熟するために多大な労力が必要な場合には、導入時には使いこなせないと判断されてしまう可能性があります。なんとか導入されたとしても他のメンバーに継承されず、管理者が変わってしまうことで活用できなくなると結局解約につながってしまいます。

解約率を下げて活用し続けてもらうことを目指す SaaS プロダクトでは、愛される管理画面を作ることが非常に重要になってきます。

どんな管理画面が愛されるのか?

では、どんな管理画面が愛されるのでしょうか?

f:id:a-kura:20201116121550p:plain
狩野モデル

一般的な品質の考え方として、狩野モデルがあります。当たり前品質を確保し、一元的品質が高めることはもちろんですが、愛されるためには魅力的品質が重要であることがわかります。

管理画面が抱える問題

まず、使い勝手を高めるために管理画面がどういった問題を抱えているか整理します。管理画面が抱える問題としては、下記の3点があります。

① 機能や設定が多く、探しきれない
② 機能や設定がそれぞれ難解である
③ 複数の機能や設定が関連している

これらの問題について、それぞれの解決策を考えていきたいと思います。

PROBLEM ① 機能や設定が多く、探しきれない

SaaS プロダクトはバージョンアップしていくに従い、機能や設定が増えていきます。そのためにどこに設定があるか探しきれなくなっていきます。ツリーメニューなどを準備して探しやすくしたとしても限界があります。

f:id:a-kura:20210314133548j:plain
1st 機能や設定が多く、探しきれない

では、どうすればよいでしょうか?

SOLUTION ① 管理メニューに検索機能をつける

この問題の解決策としては、インデックス型の探し方を諦め、サーチ型に移行することです。つまり、検索機能をつけてしまいます。

f:id:a-kura:20210314133725j:plain
SOLUTION ① 管理メニューに検索機能をつける

では、どうすればよいでしょうか?

SOLUTION ② 運用観点の説明を充実させる

この問題の解決策としては、運用観点の説明を充実させることです。具体的には、ポップアップで説明を表示する、注意事項を表示する、ヘルプページへのリンクを配置する、といったことです。

f:id:a-kura:20210314133826j:plain
SOLUTION ② 運用観点の説明を充実させる

管理画面はたまにしか利用しないため、利用方法が分からないことがあります。設定などは設定するときにならないと、どういった設定なのか知らないことも多いです。そこで、できるだけ管理画面から情報提供できるようにすることで使いやすくなります。

PROBLEM ③ 複数の機能や設定が関連している

複雑化した機能や設定は、一つだけではやりたいことを実現できなくなっていきます。また、管理メニューは機能によって分類します。複数の機能や設定が関連する場合は単純に分類しただけでは管理メニューのなかでは分散してしまいます。そのため、機能や設定を探すのに手間取ったり、手順を抜かしたり前後してしまったりします。

f:id:a-kura:20210314133857j:plain
PROBLEM ③ 複数の機能や設定が関連している

では、どうすればよいでしょうか?

SOLUTION ③ やりたいことから辿れる

この問題の解決策としては、やりたいことから辿れるようにします。管理メニューは機能を分類しており、やりたいことの分類になっていません。その役割はFAQやガイドなど別のドキュメントに役割を持たせたほうがよいです。

f:id:a-kura:20210314133926j:plain
SOLUTION ③ やりたいことから辿れる

FAQにはお客様がやりたいと質問してきたこと、ガイドにはお客様の業務イベントに沿った手順、がまとめられており、やりたいことを抜け漏れ手順前後することなく実施できるようになっています。

このようにすることで、慣れていることは管理メニューから、不慣れなことはFAQやガイドから辿れるようにすることでスムーズにやりたいことを実施できるようになります。

まとめ

今回の発表では、「なぜ、愛される管理画面を作る必要があるのか?」から紐解きながら、どういった機能を備えておくことが望ましいか紹介しました。

f:id:a-kura:20201117074206p:plain
まとめ

プロダクトの状況によって今回紹介したことが当てはまらないこともあると思いますが、管理画面の使いやすさを向上させる一助になれば幸いです。

Enjoy Engineering!


この記事は、 note.com に投稿した記事の転載になります。
note.com

在宅勤務で散財ヒストリー 2020

2020年は突然のコロナ禍によって、オフィス勤務から在宅勤務に切り替わりました。そのため、在宅勤務の職場環境を整える必要がありました。
今回は、今年在宅勤務を快適にするために散財してきた商品を紹介していきたいと思います。

WHALEN Ⅳ メッシュチェアー

まずは1品目。

下記のPodcastのエピソードで紹介されている「WHALEN Ⅳ メッシュチェアー」です。このデスクチェアはコストコジェネリックアーロンチェアとして一部で有名なものになります。
backspace.fm

この「WHALEN Ⅳ メッシュチェアー」は非常にしっかりとした作りになっているにもかかわらず、価格は11,980円(税込)。圧倒的なコストパフォーマンスです!

f:id:a-kura:20201205185844p:plain
WHALEN IV メッシュチェアー

在宅勤務が始まって2ヶ月くらいした頃にハードな腰痛に見舞われて、デスクチェアを買い直しました。以降、腰痛もなく在宅勤務できています。

「この散財、まったく後悔はない」

続きを読む