【OutSystems】Service Studioの開発で躓いたポイント

## はじめに
こちらの記事は、OutSystems 公式サイトトレーニング「Web開発者への道」を受講済レベルの筆者が、実際にアプリケーションを作成した際に躓いたポイントをまとめた記事となります。トレーニングを受講いただいているほうが、スムーズに読めるかと思います。<br><br>また、普段からAPIやForgeを使ってガツガツ開発している方にとっては、「もう知っているよ！」「初歩的すぎる」という具合で物足りない記事かもしれません。その点、ご承知おきください。<br><br>※有識者の方で、「ここもっとこうした方がいいよ」等アドバイスがありましたら、ご教示いただけると助かります！また、Qiitaを書くのも初めてのため、見づらい点ありましたらコメントください。

## 今までの開発実績
ほぼ皆無に等しいです。<br><br>画面遷移やCRUDのあるアプリケーションを一度作成した機会はありますが、1画面1アグリゲートでほぼ完結していたので、Service Studioに多少の慣れがあれば難易度としては、星1レベルでしょう。<br>(慣れていなかったので、当時は1か月近く詰まりましたが...。)<br><br>今回は、その初回開発からおよそ1年後に行った2回目の開発で躓いた部分のまとめです。

## 今回作成したアプリケーション
本当はコピー機能等をつけたアプリケーションを作成したのですが、それは諸事情によりお見せできないため、代わりに作成したアプリケーションで説明させていただきます。<br>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754477/e0c669e8-1c80-0789-6a9d-17329369576d.png)
このアプリケーションでは、都道府県の情報とその都道府県の有名な食品等を登録・修正することができます。
###### 手順
1.画面上部の「都道府県コード」を入力し、Enterキー押下
2.都道府県情報を取得
→取得できれば、「都道府県コード」に対応する都道府県情報・有名品情報を取得し、画面に表示。修正を行える。取得できない場合は、新規登録となる。
3.Formに都道府県情報・有名品情報を入力し、確定ボタン押下(取消を押すと、これまで入力した都道府県コード等すべての値が初期化されます。)
4.登録(修正)のロジックが最後まで流れれば、処理完了メッセージを表示<br>
###### 作成エンティティの説明
![2024-03-24_14h09_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754477/47fc4cc8-7344-4ac0-a5d9-c054d061d261.png)
![2024-03-24_14h05_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754477/0a6b318e-17c2-8455-a978-2735c0c744ea.png)

作成したのは、以下4つのエンティティ。
<dl>
  <dt>①Heading_Specialty</dt>
  <dd>1枚目画像 ①のTableの見出し(左2列)を表示するために作成した静的エンティティ。</dd>
  <dt>②Specialty</dt>
  <dd>有名品情報のエンティティ。Specialtyは、Todofuken_Cd、Specialty_Noの2つの外部キーを持ち、各都道府県の有名品情報を格納する。</dd>
  <dt>③Region</dt>
  <dd>2枚目画像 ③のDropdownで各地方を取得するために作成した静的エンティティ。</dd>
  <dt>④Prefectures</dt>
  <dd>都道府県コードを主キーとした都道府県情報のエンティティ。Table部分を除くほぼすべてのウィジェットと紐づく。</dd>
</dl>

## 躓いたポイント
※個人的な難易度を★1～3でつけておきます。
##### 1.特定キーの入力判定(難易度:★★☆)
今回のアプリケーション手順でいうと、
>1.画面上部の「都道府県コード」を入力し、Enterキー押下

の部分です。

ウィジェット内で、Enterキーが入力された場合のみ、都道府県情報等を取得したいのですが、InputウィジェットのEventには特定のキーを押した場合のみの処理は用意されていません。<br>
今回は、**Screenの「On Ready」イベントでJavaScriptの処理を埋め込む**ことで作成することができました。

    var textbox = document.getElementById($parameters.TodofukenCd); 
    /* テキストボックスでEnterキーが押されたら都道府県情報等取得 */
    textbox.addEventListener('keypress', function (e) {
        var key =  e.key;
        if(key === "Enter") { //Enter keycode
            $actions.GetTodofukenInfo()
        }
    });

1行目:イベントを発生させたいウィジェットのIdを取得。
JavaScriptには入力パラメータを設定し、そこにIdを代入するようにしてください。
2行目以降:Enterキーが押された場合に、都道府県情報等取得アクション(=GetTodofukenInfo)を実行する。<br>
##### 2.入力内容の判定(難易度:★☆☆)
OutSystemsでは、プロパティを設定することでフォームのフィールドを検証することができます。

https://success.outsystems.com/ja-jp/documentation/11/developing_an_application/design_ui/forms/validate_the_fields_of_a_form/


しかし、ここで検証できるのは「必須」「基本データ型に沿った入力か」のみで、特定条件の入力内容に対する検証はできません。(例:郵便番号等)<br><br>

そういった場合には、**Text (extension)のRegex_Search**を使用します。Manage Dependenciesから、依存関係の作成を忘れずに！<br>

https://success.outsystems.com/ja-jp/documentation/11/reference/outsystems_apis/text_api/#Regex_Search

![2024-03-24_15h06_50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754477/6c0f89c9-52f0-b4a6-e204-caf25bdf4d2c.png)

例えば、半角カナ・数字のみの入力かどうか検証したい場合には、<br>Text...検証したい入力内容<br>Pattern..."^[\uFF61-\uFF9F0-9]+$"(検証したい値の正規表現)<br>を設定したRegex_Searchを使用する。<br><br>検証結果は、出力パラメータ「Found」に格納され、当てはまる場合はTrue、当てはまらない場合はFalseを返してくれます。
![スクリーンショット 2024-03-24 151233.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754477/e47c67bd-965c-ffda-e621-15f79e47cdd5.png)

##### 3.整合性のないレコードの削除(難易度:★★☆)
アプリケーション作成途中の動作確認等により、主キーのないレコードの登録が発生してしまった！このような場合、DataタブからDelete Row→Applyを実行しても、レコードが削除できず、エラーとなってしまいます。<br><br>でもレコードは何としても削除したい...といった場合には、以下の方法が有効だそうです。(確証のない言い方となってしまい、すみません。これは調べても見つからず、人づてに聞いた方法です。)<br>

:::note alert
ただし、以下2点に必ず注意してください。
1.該当テーブルにこれまで登録していた他レコードもすべて削除される。
2.他テーブルとのリレーションがおかしくなり、エラーとなることがある。
→その場合は、もう一度リレーションを見直す等してください。
:::

1.該当テーブルをCut(切り取り)する。
2.該当テーブルを再度DatabaseにPaste(貼り付け)する。<br>
##### 4.Actionのロジック組み立て(難易度:☆☆☆)
これは個人のロジック力やセンスがあると思うので、個人的に苦戦した部分として記載させてください。以下は自分の失敗例です。<br>

<dl>
  <dt>①Connectorの整理できていない</dt>
  <dd>For EachやSwitch、Ifで複数のConnectorがあるとき、Connector同士が交錯してごちゃごちゃになってしまう</dd>
　<dt>②全体が整理できていない</dt>
  <dd>行き当たりばったりのなれの果て。あとはセンスの問題としか言いようがありません。ロジックを一通り作成したら、「このロジックは第三者が見ても分かるか？」という視点に立ち、見直しを行いましょう。これは他言語でも言えることですが、複数回使用している処理は別Actionにまとめましょう。<br><br>If等わかりづらい部分はLabel、Commentをつけると良いです。</dd>
</dl>

![2024-03-24_15h43_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754477/b0d296c6-9542-5a99-12ff-05001daac65e.png)

## さいごに
躓いた際には、まず作成したいターゲットを確認し、要素の過不足、ロジックの流れを確認しましょう。特にロジックの流れが自分で読んでも分からない場合は、ロジック部分から整理しなおすと良いと思います。<br>
次に公式ドキュメントと公式Forumsの確認です。Forumsは英語で解読が難しいですが、翻訳サイトと格闘しながら読み解きましょう。まれに回答に.omlファイルが付属しているので、Service Studioで確認して真似してみるのもアリです。<br>
それでも解決できない場合は、ちょっと案が浮かばないです。すみません。<br>今後さらに普及して色々なドキュメントが参照できるようになることを願うばかりです。

## 公式リンク
* [公式ドキュメント-OutSystems 11 アプリケーションの開発](https://success.outsystems.com/ja-jp/documentation/11/developing_an_application/)
* [公式Forum](https://www.outsystems.com/forums/)