Skip to main content

 

 

 

 

Template:OutSystems/Documentation_KB/Breadcrumb_New_Layout

 

 

Template:OutSystems/OSLanguageSwitcher

 

 

 

OutSystems

コード解析パターン

Architecture Dashboardの現行バージョンによるコード解析パターンの最新リストです。

パターンの追加・変更の履歴は、リリースノートでご確認ください。

アーキテクチャ

クライアント側とサーバー側のエンティティやロジックが分離されていない

クライアント側とサーバー側のエンティティやロジックが同じモジュール内に実装されています

影響
クライアント側のロジックやエンティティを再利用可能なサーバー側の定義と一緒に提供すると、モジュール機能が最適化されません。サーバー側のロジックは複数のアプリケーション向けに拡張できますが、同じ目的でクライアント側のロジックを汎用化すると、個別のモバイルアプリで冗長な情報や不要な同期ロジックが発生することが多くなります。
修正方法
クライアント側のロジックは、各モバイルアプリケーションのユースケースに合わせて提供するようにします。一般的には、Accountsなどの概念に関連する汎用的なサーバー側モジュールと、アカウントを処理する各モバイルアプリ専用のものを用意します。たとえば、エンドユーザー向けのモバイルバンキング(MB)アプリケーションとエージェント向けのモバイルエージェント(MA)アプリケーションがある場合、サーバー側のコアサービスであるAccount_CSモジュールに加えて、MB_Account_CSモジュールとMA_Account_CSモジュールを作成し、それぞれにクライアント側の専用データベースやロジックを持たせます。

モノリシックモバイルUIモジュール

すべてのモバイルUIコンテンツが同じモジュール内に保持されています

影響
ネイティブビルド生成の技術的要件により、例外フローやメニューを含むモバイルアプリケーションのすべての画面を同じモジュール内に配置する必要があります。そのため、UI画面モジュールはモノリシックモジュールとして増大し続け、異なるプロセスでのライフサイクルの管理が難しくなります。
修正方法
1つのモジュールにすべての画面フローを含めるようにします。ただし、画面をレイアウトコンテナとしてのみ使用するようにします。機能エリアごとに整理された様々なコアウィジェットモジュールからブロックにUIコンテンツが提供され、機能エリアごとに異なるライフサイクルを管理することができます。

オーケストレーションモジュールがサービスを提供している

オーケストレーションモジュールがサービスを提供している

影響
オーケストレーションモジュールはサービスを提供するためのものではありません。このモジュールへの参照がある場合は通常、再利用可能なコードが適切に配置されていないことが考えられます。また、オーケストレーションモジュールは最上位のレイヤーにあるため、このモジュールへの参照は、その配下にあるモジュールの階層全体を継承することになります。
修正方法
利用されている要素をDiscoveryで確認します。特定した要素を抽出し、それぞれの概念に応じてコア/ライブラリモジュールに移動します。この操作のサポートについては、ForgeコンポーネントのRefactorをご覧ください。

エンドユーザーモジュールがサービスを提供している

エンドユーザーモジュールがオーケストレーション以外のモジュールにサービスを提供しています

影響
エンドユーザーモジュールはサービスを提供するためのものではありません。このモジュールへの参照がある場合は通常、再利用可能なコードが適切に配置されていないことが考えられます。エンドユーザーモジュールへの参照があるとアプリケーション間のライフサイクルの独立性が損なわれ、必要のない間接的な参照が多く発生する要因となります。
修正方法
利用されている要素をDiscoveryで確認します。特定した要素を抽出し、それぞれの概念に応じてコア/ライブラリモジュールに移動します。この操作のサポートについては、ForgeコンポーネントのRefactorをご覧ください。

基盤モジュールがコアモジュールを利用している

コアモジュールが基盤モジュールにサービスを提供しています

影響
基盤モジュールはコアモジュールのサービスを利用するためのものではありません。基盤モジュールは完全に分離し、ビジネスロジックやビジネスモジュールへの参照を含まないようにする必要があります。分離されていない場合、ライブラリの利用時に予期しない影響が発生するおそれがあります。
修正方法
利用されている要素をDiscoveryで確認します。特定した要素がビジネスロジックでない場合は基盤モジュールに移動します。その他の場合は、コアモジュール要素を利用している基盤モジュール内のロジックが適切に配置されているかを確認します。

モジュール間の循環参照

2つのライブラリモジュール間またはコアモジュール間に循環参照があります

影響
多くの場合、モジュール間で循環があると、サービスの抽象化でエラーが発生し、開発時や実行時に悪影響を及ぼします。
修正方法
循環に含まれるモジュール間の概念の関係を把握し、他のモジュールを利用すべきでないモジュールを特定します。適切に利用されていない要素をDiscoveryで確認したうえで、特定した要素を本来のモジュールに移動することが概念の抽象化という点で妥当であるか、また、2つのモジュールの上位の複合モジュールにその要素を移動する必要があるかを検討してください。

モノリシックサービスモジュール

モジュールが提供するサービスのパブリック要素が多すぎます

影響
パブリック要素が多すぎるモノリシックモジュールでは、含まれる概念も過剰になります。モジュールが非常に重く、管理しにくくなり、粒度の不足によってサービスの一部のみを必要とするコンシューマに悪影響を及ぼします。
修正方法
モノリシックモジュール内の細かい概念を特定し、それらの概念の関係を設計し、グラフ化して循環のない関係になっていることを確認します。次に、モノリシックモジュールをリファクタリングし、概念の関係を踏まえて、特定した概念に分割します。この操作のサポートについては、ForgeコンポーネントのRefactorをご覧ください。

オーケストレーションアプリケーションがサービスを提供している

オーケストレーションアプリケーションがサービスを提供している

影響
オーケストレーションアプリケーションは完全に分離する必要があり、サービスを提供すべきではありません。通常、このアプリケーションへの参照がある場合、再利用可能なコードが適切に配置されていないことが考えられます。また、オーケストレーションアプリケーションは最上位のレイヤーにあるため、このアプリケーションへの参照はその配下にあるモジュールの階層全体を継承することになります。
修正方法
利用されている要素をDiscoveryで確認し、特定した要素を概念に応じてコア/ライブラリアプリケーションに移動します。

エンドユーザーアプリケーションがサービスを提供している

エンドユーザーアプリケーションがオーケストレーション以外のアプリケーションにサービスを提供しています

影響
エンドユーザーアプリケーションは、他のアプリケーションに再利用可能なモジュールを提供すべきではありません。エンドユーザーアプリケーションへの参照があるとアプリケーション間のライフサイクルの独立性が損なわれ、必要のない間接的な参照が多く発生する要因となります。
修正方法
利用されている要素をDiscoveryで確認し、特定した要素を概念に応じてコア/ライブラリアプリケーションに移動します。この操作のサポートについては、ForgeコンポーネントのRefactorをご覧ください。

基盤アプリケーションがコアアプリケーションを利用している

コアアプリケーションに含まれるモジュールがライブラリアプリケーションによって利用されています

影響
ライブラリアプリケーションはビジネス関連のサービスに依存しないため、基盤アプリケーションがコアアプリケーションのモジュールを利用することは想定されていません。

利用されているモジュールをDiscoveryで確認します。ライブラリが利用されている場合は、ライブラリアプリケーションに移動する必要があります。コアモジュールが利用されている場合は、そのモジュールを利用しているライブラリモジュール内のロジックが適切に配置されていることを確認します。

アプリケーション間の循環参照

2つのライブラリアプリケーション間または2つのコアアプリケーション間に循環参照があります

影響
コアアプリケーション間またはライブラリアプリケーション間に循環がある場合は通常、再利用可能なモジュールが適切に分離されていないことが考えられます。どちらか一方のアプリケーションが必要なときに、コンシューマに悪影響を及ぼします。
修正方法
循環に含まれるアプリケーション間の概念の関係を把握し、他のアプリケーションから利用されるべきでないアプリケーションを特定します。適切に利用されていないモジュールをDiscoveryで確認し、特定したモジュールを本来のアプリケーションに移動することが概念の抽象化という点で妥当であるかを検討してください。

モジュールが分類されていない

DiscoveryでモジュールがCanvasレイヤーに配置されていません

影響
Discoveryでモジュールを分類(定義)していない場合、アーキテクチャを適切に検証することができません。
修正方法
未分類のモジュールをDiscoveryで確認します。モジュールの特性やアーキテクチャのベストプラクティスに基づいて、各レイヤー(Orchestration、End-user、Core、Foundation)に分類します。1つのモジュールが複数のレイヤーに該当する場合は、上位のレイヤーに分類します。たとえば、あるモジュールがEnd-userレイヤー(画面)とCoreレイヤー(エンティティ)の両方の概念に当てはまる場合、End-userレイヤーとして設定します。

基盤モジュールまたはコアモジュールに画面が含まれている

エンドユーザー画面が適切に配置されていません

影響
ビジネスプロセスをサポートするエンドユーザー画面は、オーケストレーションモジュールまたはエンドユーザーモジュールで提供するようにします。例外は、例外処理画面と再利用可能なポップアップ画面です。
修正方法
ビジネスプロセスをサポートするエンドユーザー画面を、エンドユーザーモジュールに移動します。ロジックの検証用にテスト画面を作成している場合は、使用しなくなった時点で削除します。今後のためにテスト画面を保持する場合は、テストエンドユーザーモジュールに移動します。こうすることで、開発中のモジュールで直接、簡単なテストを一時的に実行することができます。再利用可能なポップアップ画面を作成している場合は、「popup」というサフィックスを付けておくと除外されます。

パブリックエンティティが読み取り専用でない

パブリックエンティティは読み取り専用として公開する必要があります

影響
パブリックエンティティが読み取り専用として公開されていない場合、レコードを作成、更新、削除するエンティティアクションがすべてのコンシューマから参照可能になります。これらのエンティティアクションはエンティティのレコードに直接影響するため、セマンティックやオペレーションを適切にチェックできず、コンシューマが整合性のない破壊的な変更を行うおそれがあります。
修正方法
パブリックエンティティの「Expose Read Only」を有効にし、これらのエンティティのレコードを作成、更新、削除する固有のパブリックアクションを作成します。このアクションにおいて、チェック機能やビジネスルール、監査ルールのほか、他のシステムへの変更通知機能などをすべて抽象化します。

モノリシックWeb UIモジュール

モジュールに含まれるエンドユーザーインターフェイスが多すぎます

影響
モノリシックエンドユーザーモジュールまたはオーケストレーションモジュールに含まれる画面が多すぎる場合、独立したライフサイクルを持つビジネスプロセスが過剰に含まれることになります。モジュールが非常に多くなり、保守性とリリース管理に悪影響を及ぼすおそれがあります。
修正方法
UIフロー自体の中にターゲットを持たない独立したフローを特定し、複数のモジュールに分離します。

コアモジュールがサブレイヤーにサービスを提供している

上位のサブレイヤーにあるコアモジュールが下位のサブレイヤー内のコアモジュールにサービスを提供しています

影響
コアモジュールのサブレイヤーに上位レイヤーのモジュール(BL、API、同期モジュールなど)があり、そのモジュールが下位レイヤーのモジュール(CSなど)によって利用されています。 これは、概念の抽象化が不適切で、一部のコアコンセプトが特定のビジネスコンセプトの構成に依存していることが考えられます。通常、コアモジュール内では上位から下位への依存関係になっている必要があります。
修正方法
該当箇所をDiscoveryで確認します。上位のコアモジュールを下位のサブレイヤーに移動します(他の下位のコンシューマにサービスを提供するものであるため)。または、利用されている上位のモジュールのオブジェクト/ロジックのいずれかが不適切に配置されていないかを確認し、必要に応じて下位のサブレイヤーのモジュールにリファクタリングします。

基盤モジュールがサブレイヤーにサービスを提供している

上位のサブレイヤーにある基盤モジュールが下位のサブレイヤーにある基盤モジュールにサービスを提供しています

影響
概念を不適切に抽象化すると、管理できない依存関係が生じるおそれがあります。上位レイヤーのモジュールは下位のモジュールによって構成されるべきであり、その反対ではありません。 プロデューサモジュールをDiscoveryで確認します。
修正方法
プロデューサが現在のコンシューマにサービスを提供すべきである場合、下位のサブレイヤーに移動します。 そうでない場合は、利用される要素をプロデューサモジュールに含めることを検討し、下位のサブレイヤーモジュールに移動します。

保守性

パブリック要素の説明がない

パブリック要素の説明が必要です

影響
モジュール、パブリック要素、エンティティ、アトリビュート、入力/出力パラメータにわかりやすい説明を付けることで、それぞれの用途と予測される動作が明確になります。非公開のモジュールを利用している場合は、実装されたロジックを見ることができないため、これが特に重要になります。
修正方法
モジュールに説明を追加し、モジュールの用途やモジュールに含まれる概念を明確にします。すべてのモジュールのパブリック要素および関連するパラメータ(エンティティまたはストラクチャの場合はアトリビュート)にわかりやすい説明を追加します。 パラメータ名/アトリビュート名が確立された命名規則に準拠している場合は、説明を追加しなくてもかまいません(Id、Name、Label、Description、CreatedBy、UpdatedBy、CreatedOn、UpdatedOnなど)。

コメントのない長いフロー

コメントのない長いフローがアクションに含まれています

影響
ノードが20以上あるPreparationや画面アクション、またはノードが40以上あるアクションでは、ロジックを説明するコメントがないと管理が難しくなります。
修正方法
フローのロジックを再利用可能な細かい単位に分割し、フローを説明するコメントを追加します。 フローの選択時に右クリックするとExtract to Action機能を利用できます。

トランザクションを管理するパブリックアクションが不明

パブリックアクションがデータベーストランザクションを管理することが説明で示されていません

影響
明示的なCommitTransaction操作やAbortTransaction操作は、予期しない場所のデータをコミット/ロールし、アプリに影響を及ぼします。再利用可能なパブリックアクションのコンテンツにアクセスすることはできないため、アクション内でトランザクションが処理されるタイミングを明示的に記述し、実行時の不要な動作を避けることが非常に重要です。
修正方法
パブリックアクションの説明の最後に「commit transaction」や「abort transaction」を追加し、トランザクションを管理していることと、どのような場合にコミットや中止を行うかを明確にします。

無効なコードが多すぎる

モジュールに含まれる無効なコードが多すぎます

影響
無効なコードが大量に残っているとコードが煩雑になり、読みにくくなります。無効なコードを解釈してその関連性を理解しようとすることで、保守コストが増加し、時間の無駄が発生します。
修正方法
コードが無効化されてからしばらく経っている場合や稼働中のアプリが適切に動作している場合は、そのコードを削除します。

セキュリティ

SQLインジェクション

SQLクエリパラメータのExpand Inlineプロパティを有効にすると、アプリケーションがSQLインジェクションに対して脆弱になるおそれがあるため、有効化しないようにします

影響
SQL要素で定義したSQLクエリを実行する際、OutSystemsはデフォルトで用意されているステートメントを使用します。これらのステートメントには、SQLステートメントを実行する前に値を定義するSQLパラメータやプレースホルダが含まれます。これらのパラメータには、任意のSQLフラグメントではなく、特定の型の値のみを格納することができます。 クエリパラメータのExpand Inlineプロパティを有効にすると、パラメータの値がSQLパラメータ値として処理されなくなります。その代わりに、SQLエンジンによるクエリ評価やリテラル変換を最初に行うことなく、SQLステートメントに含めることができます。このように、クエリパラメータを使用してSQLフラグメントをSQLステートメントに動的に挿入することが可能になりますが、必要な対策を怠ると、エンドユーザーによる悪用にもつながります。

OutSystemsでは、Expand Inlineプロパティが無効になっているすべてのクエリパラメータにSQLパラメータを使用します。このプロパティはデフォルトでは無効になっており、これによりSQLインジェクション攻撃に対してデフォルトで保護を提供しています。

インライン展開されたパラメータは、SQLステートメント内で使用する前にユーザー入力が適切にエスケープされていることを確認する必要があるため、適切に使用することが難しくなります。そのため、可能な限りこのプロパティは有効化しないようにしてください。

修正方法

OutSystemsでは、Expand Inlineプロパティを有効化せずに一般的なユースケースを実装する方法があります。オンラインヘルプのベストプラクティスにある「適切な動的SQLステートメントの作成」をご覧ください。

Expand Inlineを有効にする必要がある場合は、以下の推奨事項を検討してください。

  • Replaceによる手動での文字列エンコードを実行しない。 文字列リテラルのエンコードはEncodeSql関数でのみ行ってください。Replace関数を使用して手動で行うとエラーが発生しやすく、アプリケーションにバグが発生し、後でエンドユーザーによって悪用されるおそれがあります。
  • EncodeSqlを使用して文字列リテラルをエンコードする。EncodeSql関数は、Expand Inlineプロパティが有効になっている場合に、SQLステートメントで使用される文字列リテラルをエンコードします。EncodeSqlを使用する場合は以下の不適切なプラクティスを避けるようにしてください。
  • EncodeSql()を使用してSQLパラメータのコンテンツ全体をエンコードしない。例: myparameter = EncodeSql(""WHERE surname = "" + @myVariable1 + "" OR name = "" + @myVariable2) このパターンは不適切であることが多いため、使用すると警告が表示されます。 EncodeSqlでSQLステートメントのフラグメント全体をエンコードするのではなく、文字列リテラルのみをエンコードしてください。
  • EncodeSqlの呼び出しですべての値をラップする方法で「"WHERE column IN (@values)"」句を作成しない。 values = EncodeSql(name1 + "","" + name2 + "","" + name) この方法ではSQLインジェクションから保護されません。 「WHERE column IN (@values)」句の作成には、BuildSafe_InClauseIntegerList()関数とBuildSafe_InClauseTextList()関数を使用してください。

無効なボタンが表示されている

無効なボタンが表示されたままになっています

影響
ボタンを無効にしても、熟達したユーザーであれば、ブラウザの開発ツールなどを使用して実行時にボタンを再度有効にすることが可能です。これによって機能が有効になり、権限を持たないユーザーもボタンを押せるようになります。
修正方法
ボタンのEnableプロパティを「False」に設定するのではなく、Visibleプロパティ(または両方のプロパティ)を「False」に設定します。こうすることで、クライアントブラウザで完全にボタンが描画されなくなり、熟達したユーザーでもボタンを改ざんして機能を有効にすることができなくなります。

AnonymousやRegisteredユーザーによる画面アクセス

システムロール(AnonymousまたはRegistered)ではなくカスタムロールを画面に設定する必要があります

影響
OutSystemsには、AnonymousとRegisteredというデフォルトのシステムロールがありますが、アプリに固有のカスタムロールを独自に定義する必要があります。 Registeredロールにアクセスを付与すると、有効なOutSystemsセッションを持つすべてのエンドユーザー(同じPlatform Serverで実行中のアプリにログインしているすべてのユーザー)が画面にアクセスできるようになります。 Anonymousロールにアクセスを付与すると、ログインしていないユーザーを含むすべてのエンドユーザーが画面にアクセスできるようになります。
修正方法
すべての(Anonymousロールがない)画面でRegisteredロールのアクセスを無効にし、アプリに固有のカスタムロールに明示的にアクセスを付与します。 画面を公開して、アプリにアクセス可能なすべてのユーザーが画面にアクセスできるようにする場合を除き、Anonymousロールのアクセスを無効にします。

JavaScriptまたはHTMLインジェクション

ユーザー入力または画面の変数がエスケープされていないか、エンコードされていません

影響
画面のユーザー入力や変数が、HTMLインジェクションまたはJavaScriptインジェクションで利用されるおそれがあります。 また、この脆弱性は、クロスサイトスクリプティング(XSS)でも利用されるおそれがあります。
修正方法

以下のいずれかの手順を実行します。

  • ExpressionのEscape Contentプロパティを有効化する。
  • EncodeHtml()ビルトイン関数を使用して、HTML予約文字をエスケープ処理された文字にすべて置き換える。
  • EncodeJavascript()ビルトイン関数を使用してJavaScriptの予約文字をエスケープ処理された文字にすべて置き換え、JavaScriptの文字列に含めることができるようにする。
  • SanitizationエクステンションモジュールのSanitizeHtml()関数を使用して、エンドユーザーが入力した値に悪意のあるコンテンツが含まれないようにする。
  • EncodeUrl()ビルトイン関数を使用して、URLの無効な文字を、「%」を使用してコーディングされた文字にすべて置き換える。

Webサービスが保護されていない

Webサービスでは、SSL/TLS認証を適用する必要があります

影響
接続が保護されていない場合、権限のない第三者に読み取られたり、中間者攻撃の標的になるおそれがあります。
修正方法
SSL/TLSを設定してアプリケーションのエンドポイントを保護し、公開サービスに送信されるデータの盗聴や改ざんができないようにします。 OutSystemsでは、ログイン/パスワード保護による公開REST APIのコントロールを提供しています(内部アクセス専用に設定されている場合を除く)。

モバイルデバイスの侵害が未確認

モバイルデバイスでルート化(Android)や脱獄(iOS)といったセキュリティ侵害が発生していないかを確認していません

影響
モバイルアプリは、コードが変更されやすいという特性があります。OSによって暗号化されていても、高度な技術を持つ攻撃者であれば、復号化されたバイナリを元に戻し、システム呼び出しや条件文、その他のアプリケーションロジックを編集することが可能です。
修正方法
攻撃者によるアプリケーションの改ざんを防ぐため、OWASPは実行時に実行可能ファイルの完全性を検証することを推奨しています。Secure Deviceプラグイン(Forgeで入手可能)を使用すると、エンドユーザーがデバイスのセキュリティを侵害して権限が必要なサブルーチンにアクセスしていないかを確認し、その対策としてアプリケーションをシャットダウンすることができます。 Secure Deviceプラグインを使用するには、プラグインへの参照を追加し、OnApplicationReadyイベントでCheckSecureDevicePluginアクションを使用します。これによりプラグインがネイティブビルドに含まれるようになります。

パフォーマンス

ViewStateにクエリデータ

Preparationで取得したクエリデータを画面アクションで使用しています

影響
画面アクションでPreparationのデータを使用すると、画面のViewStateにそのデータが保存されます。 ViewState内のデータが増えることで、レスポンスのサイズが大きくなり、ブラウザの読み込み時間が長くなります。これは、ViewStateがページリクエストのたびにユーザーに送信され、また、POSTやポストバック、Ajaxリクエストのたびにサーバーに送り返されるためです。
修正方法
Preparationのデータを画面アクションで使用しないようにします。 たとえば、画面アクションでTableRecordsのレコードデータを使用する代わりに、レコードの識別子を画面アクションの入力パラメータとして送信し、必要なときにデータベースからデータを取得するようにします。レコードの一覧が必要な場合はクエリを更新します。ViewStateでデータを送受信するよりもサーバー側でクエリを再実行するほうが効率的です。

ViewStateに大きなローカル変数

大きなローカル変数が画面アクションで使用されています

影響
画面のローカル変数が画面アクションで使用されている場合、ローカル変数データは画面のViewStateに保存されます。 Compoundデータ型やCollectionデータ型のローカル変数は大きいとみなされます。 ViewState内のデータが増えることで、レスポンスのサイズが大きくなり、ブラウザの読み込み時間が長くなります。これは、ViewStateがページリクエストのたびにユーザーに送信され、また、POSTやポストバック、Ajaxリクエストのたびにサーバーに送り返されるためです。
修正方法
画面アクションで画面のローカル変数を使用しないようにします。

非効率な空のリストの確認

AggregateまたはSQLクエリのCountプロパティを使用して、リストが空かどうかを確認しています

影響
パフォーマンスを上げるため、OutSystemsのクエリオプティマイザは、Aggregateと高度なクエリの出力では画面にフィードする重要なデータのみを返すようになっています。Countプロパティは、レジストリの全数を取得するためにクエリを追加で実行する必要があります。
修正方法
List.CountではなくList.Emptyプロパティを使用して、リストが空かどうかを確認します。

非効率なクエリカウント

非効率なクエリを使用してクエリ結果をカウントしています

影響
SQLクエリは通常、データの取得を目的としており、結合を実行して処理に必要な追加データを取得する場合がありますが、これはクエリ結果のカウントには必要ありません。クエリのCountプロパティを使用すると、結果をカウントするために同じクエリが実行され、同じクエリ定義を使用することになるため、非効率です。
修正方法
効率的に結果をカウントするための単純なSQLクエリを使用し、不要な追加データや結合をなくします。

インラインJavaScript

エスケープされていないExpression内でインラインJavaScriptが定義されています

影響
画面/Webブロックレベルで定義しているJavaScriptは、OutSystemsによって最適化されます。たとえば、画面で同じWebブロックを2つ定義した場合、含まれるのは1つだけになります。これにより保守性も向上します。
修正方法
インラインExpression内ではなく画面/WebブロックレベルでJavaScriptを定義します。

インラインCSSスタイル

CSSスタイルが画面要素の拡張プロパティとして定義されています

影響
CSSとHTMLは分離すべきです。インラインスタイルを使用すると、非効率で管理しにくくなり、HTMLのサイズが大きくなります。
修正方法
大量のCSSファイルの読み込みを避けるため、アプリケーションのスタイルガイドでCSSを一元管理します。CSSが1つの画面やWebブロックに固有のものである場合、拡張プロパティではなく画面/WebブロックレベルでCSSを定義します。

SQLクエリでレコード数が制限されていない

データベースから取得するレコード数がSQLクエリで設定されていません

影響
アプリケーションで使用する以上のレコード数をデータベースから取得すると、I/Oやメモリを無駄に消費する要因となります。
修正方法
SQLクエリでROWNUM(Oracleの場合)またはTOP(MS SQL Serverの場合)を使用し、レコード数を必要な数に制限します。SQLクエリ内のMax. Recordsパラメータでは、表示するレコード数のみが制限され、取得するレコード数は制限されないことに注意してください。

Aggregateでレコード数が制限されていない

データベースから取得するレコード数がAggregateで設定されていません

影響
アプリケーションで使用する以上のレコード数をデータベースから取得すると、I/Oやメモリを無駄に消費する要因となります。
修正方法
AggregateのMax. Recordsパラメータを必要なレコード数に設定します。

サイトプロパティの更新

アプリケーションロジックを使用してサイトプロパティが更新されています

影響
サイトプロパティが更新されると、モジュールのキャッシュが無効になります。そのため、その後にキャッシュデータにアクセスする際に、データベースから取得したりアプリケーションロジックで再計算したりすることになり、パフォーマンスに悪影響を及ぼすおそれがあります。
修正方法
サイトプロパティの値がプログラム的に変更されないようにします。値をデータベースに保存し、必要なときにアクセスするなどの代替手段を使用します。

動的なインラインパラメータ

SQLクエリのインライン展開されたクエリパラメータで動的なExpressionが使用されています

影響
インライン展開されたクエリパラメータが頻繁に変更されると、新しいクエリが絶えず生成されるため、データベースの実行計画を最適化することができません。
修正方法
クエリを変更し、頻繁に変更されるインラインパラメータを削除します。パラメータに応じた専用のクエリを選択したり、サブクエリや一時テーブルを使用することを検討してください。

不適切なデータ処理

ループ内でクエリが実行されています

影響
各クエリの実行速度が十分でも、ループ内ではデータベースの処理量が多くなることがあります。
修正方法
多くの場合、単純なAggregateをFor Eachループ内で実行するよりも、複雑なSQLクエリを1回だけ実行して必要な情報を取得するほうが効率的です。また、エンティティモデルがニーズに即しているかを確認します。データベースモデルが不適切な場合、必要な情報の取得が複雑になり、単一のクエリでは取得できなくなります。

セッション変数が大きい

大きなセッション変数が使用されています

影響
すべての画面リクエストで、データベースから現在のセッションのデータが読み込まれます。このデータはバイナリデータであり、すべてのセッション変数が含まれます。 Compoundデータ型やCollectionデータ型のセッション変数は大きいとみなされます。 大きな変数が使用されている場合、各リクエストでセッションデータの処理(シリアル化と逆シリアル化を含む)に時間がかかり、レスポンス時間が増加し、すべての同時リクエストで競合が発生します。
修正方法
セッション識別子を主キーにしてこのデータをエンティティに保存し、必要なときにのみ取得するようにします。セッションは、すべてのリクエストで使用できるコンテキスト情報に限定します。

画像サイズが大きい

モジュールにサイズの大きな画像が含まれています

影響
サイズの大きな画像がある場合、アプリケーションに様々な影響を及ぼします。画面内に大きな画像を使用して表示する場合、サーバーから画像を取得する必要があり、使用する帯域幅が増加し、ブラウザでのリクエスト処理時間が長くなります。幅/高さを小さい値に設定しても、サーバーから画像を取得する際の帯域幅は減りません。 開発側では、サイズの大きな画像を含むモジュールがあると保存やパブリッシュ時に時間がかかり、サーバーからのアップロードやダウンロード時に利用する帯域幅が増加します。
修正方法
画像サイズをユーザーに適切に表示される必要最低限(モバイルでは150KB、Webでは500KB以下)まで落とします。 また、画像の解像度を1024px以下に下げます。 サイズの大きな画像をモジュール自体には含めずに、外部リソースとして扱うことも検討してください。

サーバーリクエストのタイムアウトが長い

サーバーリクエストのタイムアウトが長くなっています

影響
サーバーアクションリクエストのデフォルトタイムアウトが長すぎるか、サーバー呼び出しの明示的なタイムアウトが長すぎます(10秒以上)。モバイルアプリケーションではサーバーリクエストを効率的に処理すべきです。10秒以上経つとデバイスはスリープモードになるか、ネットワーク接続が失われます。
修正方法
サーバー側で事前にデータを準備してキャッシュし、必要なときにすぐに利用できるようにします。また、多少時間がかかっても許容される明示的な操作の場合を除き、サーバーリクエストのタイムアウトを短く設定します(失敗時には「後で再試行してください」というメッセージを表示します)。

クライアントイベントでのサーバーリクエスト

クライアントイベントでサーバーアクションが呼び出されています

影響
クライアントイベント(On Initialize、On Ready、On Render、On After Fetch)でのサーバー呼び出しは避けるべきです。これらのイベントはリクエスト時やサーバー呼び出し時にシリアル化され、画面の描画中の待機時間に大きく影響するすおそれがあります。
修正方法
モバイルアプリでは、パフォーマンスとオフライン対応の観点からローカルストレージを利用します。サーバー側のリクエストは、同期リクエスト(通常、画面アクション、セッション開始、オンラインイベントで起動したビジネスイベントで実行)とオンライントランザクション(通常、画面アクションで実行)に限定します。

ローカルデータの取得が最適化されていない

クライアントイベントでローカルデータの取得が実行されています

影響
クライアントイベント(On Initialize、On Ready、On Render)でのローカルデータの取得は避けるべきです。これらのイベントは完全にシリアル化されるため、画面の描画中にはデータの並列取得が行われません。
修正方法
データ取得の呼び出しによってデータを取得し、複数のデータ取得と画面の描画を並列で行えるようにします。データ取得が前の取得に依存している場合は、On After Fetchイベントを使用します。

ローカルストレージが最適化されていない

ローカルストレージモデルが最適化されていません

影響
ローカルストレージがサーバーエンティティからそのままコピーされているか、(過剰なフィールドや外部キー、複雑なデータ型が含まれる)複雑なモデルを使用しています。この場合、クライアントのAggregateで複数の結合が必要になり、モバイルデバイスでのアプリケーションのパフォーマンスの低下を引き起こします。
修正方法
ローカルエンティティを簡素化してアトリビュート数を最小限にし、可能な限り非正規化します。また、クライアントのAggregateで不要な結合を確認します。

ローカルストレージを利用していない

ローカルストレージが利用されていないため、サーバーリクエスト(画面データアクション)が過剰になっています

影響
サーバーからデータを取得する画面データアクションが過剰に使用されている場合は、ローカルストレージが適切に定義されていない、または利用されていないために、すべてのデータをサーバーから取得していることが考えられます。これは、モバイルアプリケーションのパフォーマンスやオフライン対応の低下を引き起こします。
修正方法
適切な同期メカニズムとローカルストレージを実装し、データの大半をローカルストレージで利用できるようにします。これにより、オフライン対応も向上します。

クライアントアクション内の複数のサーバーリクエスト(Aggregateまたはアクション)

クライアントアクション内に複数のサーバーAggregateやサーバーアクションのリクエストがあります

影響
サーバーアクションやサーバーAggregateのリクエストがそれぞれ異なる場合、接続の確立とサーバー側プロセスの開始時にオーバーヘッドが発生します。また、プロセスが複数あることによってそれぞれ異なるデータベーストランザクションが発生します。
修正方法
クライアント側のコードでサーバーリクエストやサーバーAggregateを順番に実行するのではなく、すべての必要なサーバーロジックを1つのサーバーアクションにまとめ、サーバーリクエストの数を減らします。

不適切なオフライン同期方法

オフライン同期パターンが適切に実装されていません

影響
オフライン同期が実行されないか、低いパフォーマンスで実行されています
修正方法
OfflineDataSyncアクション内にローカルエンティティ同期アクションを配置し、同期の手動開始と自動開始を設定し、バックグラウンド同期としてTrigerOfflineDataSyncを使用します。不要なエンティティの更新を避けるため、SyncUnitパラメータを使用することが推奨されます。

オフライン同期が非同期になっていない

サーバーデータがローカルデータベースに非同期的に保存されていません

影響
サーバーデータを同期的に保存すると、画面やアクションがブロックされ、ユーザーエクスペリエンス全体に影響を及ぼします。
修正方法
TriggerOfflineDataSyncを使用してOfflineDataSyncを非同期的に実行し、OnSyncCompleteイベントに反応してUIモジュールを更新するようにします。

不良なネットワークやサーバー接続に対処していない

不良なネットワークやサーバー接続に対処していません

影響
ロジックを設計する際は、ONとOFFの設定だけではなく、様々なネットワーク状況に対応できるようにする必要があります。
修正方法
GetNetworkStatusを使用してネットワーク状況を検出し、ロジックやUIが状況に応じて適切に反応するようにします。

各画面のスタイルシートにCSSが分散しています

各画面のスタイルシートにCSSが分散しています

影響
CSSが様々な画面に分散していると、保守上の問題の要因となります。 CSSをアプリのテーマに一元化することで、保守コストを減らすことができます。 また、モバイル画面でCSSを定義すると、ページを移動する際にちらつきが発生します。
修正方法
アプリケーションのテーマ内でクラスを定義します。変更がわずかな場合でも、特定のページに追加するよりも、特定の(再利用可能な)クラスを定義して同じクラスを繰り返しコピーするほうが効率的です。

Imageウィジェットの幅が設定されていない

Imageウィジェットの幅を設定する必要があります

影響
Imageウィジェットの幅と高さを設定していない場合、画像のダウンロード中にアプリのユーザーがちらつきを感じることがあります。たとえば、画像の高さが設定されていない場合、ウィジェットの高さが0pxから最終的な画像の高さまで変化するため、画像の読み込み中に画面全体の高さが変化することになります。
修正方法
Imageウィジェットの幅と高さを予測される最終的な画像のサイズに設定します。どちらか一方のみを設定した場合は、もう一方は比率に応じて調整されます。

スプラッシュ画面が複雑

スプラッシュ画面をシンプルかつ高速に保つ必要があります

影響
スプラッシュ画面に負荷の高い操作や時間がかかる操作を追加すると、アプリが使用可能になるまでの時間が長くます。また、スプラッシュ画面に複雑なUIが含まれていると、スプラッシュ画面が描画されるまで空白の画面が表示されることがあります。
修正方法

シンプルで読み込みが速いスプラッシュ画面にするには、次のことを避ける必要があります。

  • サーバーへのリクエスト
  • 大量のロジック
  • 複雑な(ブロックが多すぎる)UI

長時間のタイマー実行

タイマーを30分以上実行しないようにします

影響
Minutesプロパティのタイムアウトを超えるタイマーを使用すると、エラー発生時にコードを再実行するタイマーの自動再試行メカニズムによって、コードやデータが再処理される場合があります。 ウェイクタイマーパターンに従うことで、Minutesのタイムアウトに達したときにタイマーがSchedulerプロセスによって中断される確率が低くなります。 ウェイクタイマーパターンでは次のことができます。 * タイマーが中断される確率の減少 * データの不整合の回避 * 同じデータが際限なく再処理されることの防止
修正方法
長時間実行するタイマーはウェイクタイマーパターンに従い、タイマーを再度スケジュール設定して再開し、現在の残りのタスクを続行します。 ウェイクタイマーパターンを実装するには、タイマーロジック内に明示的な論理タイムアウトを追加します。このロジックでは、タイムアウトに達すると、必要なアクションを行って現在の実行を適切に終了するほか、処理の現在の進捗状況を保存することで、保存された時点から簡単に実行を再開できるようにします。このパターンは、タイマーフローの最後に、タイマー自体に対するウェイクタイマーアクションで終了します。 また、長時間のタイマーに関するベストプラクティスとして、データに影響を及ぼすことなくタイマーを停止して再開できるようにするため、タイマーを定義する際にチェックポイントを設定することが推奨されます。また、エラーの発生時に処理済みのデータのみが前回のコミットまでロールバックされるようにするため(また、次の実行で同じデータが再処理されるのを避けるため)、これらのチェックポイントで部分コミットを実行することを検討してください。

リソースサイズが大きい

モジュールにサイズの大きなリソースが含まれています

影響
環境にパブリッシュする際、モジュール内にサイズの大きなリソースがあるとパブリッシュやダウンロードが遅くなり、開発に影響を及ぼすおそれがあります。
修正方法
リソースサイズを使用状況に応じて必要最低限(モバイルでは150KB、Webでは500KB以下)まで落とします。 また、リソースを外部に持つことも検討してください。たとえば、リソースをアップロードする画面を作成し、リソースをファイルシステムやバイナリデータベーステーブルに保存します。
  • Was this article helpful?