バックエンドをAPIとして作成する必要がありますか?


322

今日、MVCアプリケーションについて熱く議論しました。MVC(ASP.NET)で記述されたWebサイトがあり、通常はビューで何かを実行するパターンに従います->コントローラーを押す->コントローラーがモデルを構築します(データを取得するマネージャーを呼び出し、モデルを構築しますコントローラのメソッド自体)->モデルが表示されます->すすぎと繰り返し。

彼は、私たちのコードが密結合しすぎていると言った。たとえば、デスクトップアプリケーションも必要な場合、既存のコードを使用することはできません。

彼が言った解決策とベストプラクティスは、APIを構築し、APIの上にWebサイトを構築し、デスクトップアプリケーション、モバイルアプリなどを構築することは非常に簡単です。

これは、さまざまな理由で私にとって悪い考えのようです。

とにかく、このプラクティスを議論するかもしれないグーグルで何も見つけられないようです。誰もが長所、短所、なぜそうすべきか、なぜそうすべきではないか、さらに読むべきかについての情報を持っていますか?

悪い考えだと思ういくつかの理由:

  • バックエンドをAPIから実行するにはあまりにも抽象的です。あなたはそれをあまりにも柔軟にしようとしているので、それは管理不能な混乱になります。

  • MVCに組み込まれているものはすべて、役割や認証など、役に立たないようです。たとえば、[Authorize]属性とセキュリティ。独自にロールする必要があります。

  • すべてのAPI呼び出しにはセキュリティ情報が添付されている必要があり、トークンシステムなどを開発する必要があります。

  • プログラムが実行する機能ごとに、完全なAPI呼び出しを記述する必要があります。実装するほとんどすべてのメソッドは、APIから実行する必要があります。すべてのユーザーのGet / Update / Deleteに加えて、ユーザー名の更新、グループへのユーザーの追加など、他の各操作のバリアントがあり、それぞれが個別のAPIコールになります。

  • APIに関しては、インターフェイスや抽象クラスなどのあらゆる種類のツールが失われます。WCFのようなものには、インターフェイスに対する非常に乏しいサポートがあります。

  • ユーザーを作成するメソッド、または何らかのタスクを実行するメソッドがあります。50人のユーザーを作成する場合は、50回呼び出すだけです。このメソッドをAPIとして実行することを決定すると、ローカルWebサーバーは名前付きパイプに接続でき、問題はありません-デスクトップクライアントもヒットできますが、突然、ユーザーの一括作成にはインターネット上でAPIを50回ハンマーする必要があります。良くない。したがって、バルクメソッドを作成する必要がありますが、実際にはデスクトップクライアント用に作成するだけです。この方法では、a)統合するものに基づいてAPIを変更する必要があり、直接統合することはできません。b)余分な関数を作成するためにより多くの作業を行う必要があります。

  • ヤグニ。たとえば、1つのWebアプリケーションと1つのWindowsアプリケーションなど、まったく同じように機能する2つのアプリケーションを作成することを特に計画しているのでなければ、膨大な量の開発作業が必要になります。

  • エンドツーエンドでステップスルーできない場合、デバッグははるかに困難になります。

  • 多くのやり取りを必要とする独立した操作がたくさんあります。たとえば、いくつかのコードは現在のユーザーを取得し、ユーザーが管理者ロールにあることを確認し、ユーザーが属する会社を取得し、他のメンバーのリストを取得し、それらをすべて送信しますEメール。そのためには、多くのAPI呼び出しが必要になるか、必要な特定のタスクに特注のメソッドを記述する必要があります。特注のメソッドの唯一の利点は速度ですが、欠点は柔軟性に欠けることです。

  • おそらく、これらの理由のいくつかが私の頭上にあります。

2つの同一のアプリケーションが本当に必要な場合を除き、私には好感が持てますが、それだけの価値はありません。このように構築されたASP.NETアプリケーションを見たことがありません。2つの個別のアプリケーション(APIとコード)を記述し、両方をバージョン管理する必要があります(ユーザーページに新しいフィールドが追加された場合、 dは、APIと消費コードを同時に更新して悪影響を与えないようにするか、堅牢性を維持するために多くの追加作業を行う必要があります)。


編集:いくつかの素晴らしい反応、本当にこれが今何を意味するのか良いアイデアを得るために始めています。それでは、私の質問を拡張するために、このAPI構造に従うようにMVCアプリをどのように構成しますか?

たとえば、ユーザーに関する情報を表示するWebサイトがあります。MVCには、次のものがあります。

ビュー-UserViewModelコントローラーを表示する(CS)HTMLページ-GetUser()を呼び出し、GetUserメソッドを持つビューマネージャークラス(APIの一種)に渡すUserViewModelを作成します。

コントローラーはGetUser()を実行しますが、デスクトップアプリも必要です。これは、GetUserが何らかのAPIを介して公開される必要があることを意味します。TCP接続、WCF、またはおそらくRemotingが必要になる場合があります。永続的な接続が不安定なため、RESTfulなモバイルアプリも必要です。

それでは、GetUser()メソッドがあり、コードが実行するWCF Webサービスごとに、各APIを作成しますreturn new UserManager().GetUser()か?そして、同じことを行うMVC 4 Web APIメソッド?MVCコントローラーメソッドでGetUserを直接呼び出し続けていますか?

または、3つすべて(Web API RESTサービス)で機能するソリューションを選択し、その上にすべてを構築して、3つすべてのアプリがAPI呼び出し(ローカルコンピューターに対してmvc呼び出し)を行うようにします。

そして、これは単なる理論上の完璧なシナリオですか?特に、RESTfulな方法で操作を行えるように開発する必要がある場合、この方法で開発する際に大きなオーバーヘッドが発生することがあります。これのいくつかは返信で取り上げられていると思います。


編集2:より多くのものを読んだ後、私はそれを説明するかもしれないと思うコメントを下に入れました。この質問は、私が考えるちょっとしたトリックの質問です。APIとしてバックエンドを書くと、すべて(mvcアプリ、デスクトップアプリ、モバイルアプリ)が何かを行うために呼び出す単一のWebサービスがあるべきだと思って混乱しました。

私が思いついた結論は、ビジネスロジックレイヤーが正しく分離されていることを確認することです。コードを見て、すでにこれを行っています。コントローラーはGetUser()マネージャーを呼び出し、それからビューモデルを作成してビューでレンダリングします。実際、ビジネスロジック層 APIです。ただし、デスクトップアプリから呼び出したい場合は、WCFサービスのようなものを記述して、呼び出しを容易にする必要があります。GetUser()コードを含むWCFメソッドを呼び出すだけでもreturn MyBusinessLayer.GetUser()十分です。したがって、APIはビジネスロジックであり、WCF / Web APIなどは、外部アプリケーションに呼び出しを許可するためのほんの一握りのコードです。

そのため、必要なものに応じてビジネスロジックレイヤーをさまざまなAPIでラップする必要があり、他のアプリで実行したい操作ごとにAPIメソッドを記述する必要があるというオーバーヘッドがあります。認証を行う方法を整理しますが、ほとんどの部分で同じです。ビジネスロジックを別のプロジェクト(クラスライブラリ)に固定すれば、おそらく問題はありません!

この解釈が正しいことを願っています。それが生成したすべての議論/コメントをありがとう。


25
悪い考えだと思う理由を教えてください。今日、私はそれをしない理由がないと認めなければなりません。それは...はるかに簡単に、さまざまなプラットフォームにアプリケーションを移植、他の利点の中で、になり、さらにはバックエンドのコードに触れることなく、フロントエンドに大きな柔軟性を可能に
ローランS.

12
@SLC:APIと言うとき、SOAPまたはRESTインターフェースのようなWebサービスAPIを意味しますか?バックエンドをAPIにする必要がありますが、Webサービスにするべきではないためです。
ジャックB

7
@IanNewson「たとえば、モバイルアプリは機能が少ない傾向があります。」I(まだ誰もがこのようにそれを行うようです)...モバイルアプリは二級市民である必要があり、なぜ説得力のある理由を聞いたことがない
マイケル・

3
@IanNewsonは、多分それは、私だけです...しかし、私はいつも自分自身が、私は携帯電話ではほとんどを行う点までの携帯電話でいくつかのことや他の操作を行うことができないことで身動き見つける
マイケル・

11
YAGNIが適用されると言いますが、私の経験では、アプリは数年ごとにUIを書き換えるか、誰もが必要だと文句を言いました。新しいフロントエンドテクノロジーが到着したので、ビジネスロジックを失わないのであれば、いいでしょう。
corsiKa

回答:


282

はい、そうすべきです。

バックエンドを再利用可能にするだけでなく、より多くのセキュリティとより良いデザインを可能にします。バックエンドを単一のシステムの一部として作成する場合、モノリシックなデザインを作成することになり、拡張、置換、拡張が決して簡単になりません。

これが現時点で人気のある分野の1つは、マイクロサービスです。バックエンドが、クライアントシステムが消費するAPIを提供する多数の小さな(または大規模な)サービスに分割される場所。アプリケーションで多くのサードパーティのデータソースを使用することを想像するなら、あなたはすでにこれをしているかもしれないことに気づきます。

もう1つの利点は、各サービスの構築と保守を別のチームに引き渡すことができ、製品を生産する他のチームに影響を与えない機能を追加できることです。それらが完了し、サービスをリリースしたときにのみ、それらを使用するために製品に機能を追加し始めます。これにより、開発がはるかにスムーズになります(全体的に遅くなる可能性がありますが、品質が向上し、理解しやすくなります)


編集: OKあなたの問題がわかりました。APIはリモートライブラリと考えています。そうではありません。サービスは、データを提供するサービスのようなものだと考えてください。サービスを呼び出してデータを取得し、そのデータに対してローカルで操作を実行します。ユーザーがログオンしているかどうかを判断するには、たとえば" GetUser"を呼び出してから'logged on'値を確認します。(もちろん、その例のYMMV)。

一括ユーザー作成の例は言い訳です-モノリシックシステムでできることは何でもサービスアーキテクチャで行うことができます(たとえば、一括作成にユーザーの配列を渡した場合、または作成する単一のもの。サービスでもまったく同じことができます)。

MVCは既に分離されたサービスの概念に基づいており、MVCフレームワークのみがそれらを単一のプロジェクトにバンドルしています。それは、フレームワークが提供しているバンドルされたヘルパー以外の何かを失うことを意味しません。別のフレームワークを使用すると、異なるヘルパーを使用する必要があります。または、この場合、独自にローリングします(またはライブラリを使用して直接追加します)。

デバッグも簡単です-APIを完全にテストできるので、APIをデバッグする必要はありません(エンドツーエンドでデバッグでき、Visual Studioは複数のプロセスに同時に接続できます)。

セキュリティを実装するための余分な作業のようなものは良いことです。現在、すべてのコードをWebサイトにバンドルすると、ハッカーがアクセスできるようになると、DBを含むすべてのものにもアクセスできるようになります。APIに分割すると、APIレイヤーもハッキングしない限り、ハッカーはコードに対してほとんど実行できません-これは非常に困難です(攻撃者がどのようにしてすべてのWebサイトのユーザーまたはcc詳細の膨大なリストを取得するのか疑問に思ったことはありませんか? OSやWebサーバーをハッキングし、select * from users簡単に実行できるDBへの直接接続がありました。

このように書かれた多くのWebサイト(およびクライアントサーバーアプリケーション)を見てきました。金融サービス業界で働いていたとき、セキュリティリスクが大きすぎることや、安定した(つまりレガシーな)バックエンドデータ処理を介したかなりのGUIが原因で、ウェブサイトをオールインワンで書く人はいませんでした。システム。サービススタイルアーキテクチャを使用して、DPシステムをWebサイトとして公開するのは簡単です。

2回目の編集:件名に関するいくつかのリンク(OPの場合):

これらのことをWebサイトのコンテキストで説明する場合、Webサーバーはプレゼンテーション層と見なされる必要があります。これは、他の層を呼び出すのはクライアントであり、レンダリングのためにブラウザーに送信されるUIビューを構築するためです。これは大きなテーマであり、アプリケーションを設計する方法は多数あります-データ中心またはドメイン中心(通常、ドメイン中心は「より純粋」であると考えていますが、YMMV)、それはすべて、ロジック層を間に挟むことですクライアントとDB。中間、API、層をモデルと同等とみなす場合、MVCに少し似ています。モデルはDBの単純なラッパーではなく、より豊富で多くのことができます(たとえば、2つのデータソースからのデータの集約、 -データをAPIに合わせて処理する、データをキャッシュするなど):


2
それは建築宇宙飛行士の観点からはイエスですか?2番目と3番目の段落はサービスの観点から理解できますが、GetUser、CreateUser、IsUserLoggedIn、および以前は1行のコードがAPI呼び出しに変換されていた数百の小さな関数について説明しています。
-NibblyPig

12
あなたがそれをウェブサイトとして書いていると想像してください-それらの小さな機能はすべてあなたが想像するほどインタラクティブではないので、ページを構築する間、データを取得してローカルにキャッシュする必要があります(または潜在的に古いデータとしてクライアント、システムに応じて)。多くの場合、デザインを「オンデマンドで反応する」から「事前に予測する」に変更する必要がありますが、システムのほとんどはAPI呼び出しを行います。APIをより細かくなく、データ中心に設計します。IsUserLoggedOnはAPI呼び出しである必要はありません。ローカルで検査した後は、「GetUserDetails」のみが必要です。
gbjbaanb

5
私は最後の雇用地でこの方法を使用しましたが、それは見事に機能しました。主な製品はWebアプリでしたが、すべてのデータに対してWebアプリが行ったのと同じWebサービスにアクセスできるデスクトップアプリとExcelシートを作成し、さらにクライアントにサービスを公開することができましたそれらに対するプログラム。
キック

2
もう1つの利点は、バックエンドAPIをWebサイトの顧客に公開できることです。私たちの会社ではこれを行いました。(ホストでバックエンドを試した後)一部の大手ソフトウェア会社の顧客は、バックエンドをセルフホスト製品として単独でラップするために支払いました。製品によっては、一部の顧客はフロントエンドのベニアにあまり関心がなく、製品が実際に行うこと、つまりバックエンドにもっと関心があります。それは販売する別の製品です。
リード

2
これにより、Webサービスから同じロジックを簡単に使用できます。私たちのチームは、私たちがやる必要がないといつも思うことの1つです。
ps2goat

87

APIの構築は避けられません。「単なるWebサイト」を構築したとしても、何らかの方法でそのデータをバックエンドから取得する必要があります。ただし、これを行うことにした場合、それがデファクト APIです。

これを知っている本当の問題は、APIを構築するかどうかではなく、APIを構築する方法です。アドホックなものとしてオンザフライで実行できます(実際、多くのWebサイトはまさにこの方法で構築されます)か、他のコンテキストで使用できるように慎重に設計できます。このコンテキストに入れると、同僚が正しいことが明らかになります。最初にAPIを実行してから、その上にサイトを構築する必要があります。

それにもかかわらず、あなたが指摘するように、これはいくつかの懸念をもたらします。それらに対処するには:

バックエンドをAPIから実行するにはあまりにも抽象的です。あなたはそれをあまりにも柔軟にしようとしているので、それは管理不能な混乱になります。

それはあなたのやり方次第です。ジョージポリアは、彼の優れたテキストに指摘しそれを解決するためにどのようにしばしば「より一般的な問題は解決する方が簡単な場合があり」。これは、発明者のパラドックスと呼ばれます。プログラミングの場合、懸念事項の分離によって機能することがよくあります。バックエンドは、データを出し入れするデータの形式を気にする必要がなくなるため、コードをより簡単にすることができます。データパーサーとレンダラーは、作成したデータに何が起こるかを気にする必要がなくなり、より簡単になります。それはすべて、コードをより管理しやすいチャンクに分割することで機能します。

MVCに組み込まれているものはすべて、役割や認証など、役に立たないようです。たとえば、[Authorize]属性とセキュリティ。独自にロールする必要があります。

自分のツールを学ぶことを拒否する人々に同情するのは非常に難しいと私は認める。あなたがそれらの使用を理解していないからといって、それらが役に立たないことを意味するわけではありません。まったく逆です。代替手段を理解するまで、独自のツールを使用することは避けてください。そうすることで、確実に同じ問題に対処できるようになります(独自の方法であっても)。

Linuxを書くことで最も有名なLinus Torvaldsを考えてみましょう。彼はgitも書いています。現在は世界で最も人気のあるバージョン管理システムの1つです。彼の設計の推進要因の1つは、Subversion(別の非常に人気のあるVCSであり、おそらくgitが書かれた時点で最も人気のあったVCS)に対する深い反対でした。彼は、Subversionができるすべてを、そして可能な範囲で、それらの問題を異なる方法で解決することを決意しました。これを行うには、彼は同じ問題領域を理解し、異なるアプローチを取るために、正確にSubversionの専門家になる必要がありました。

または、ツールを学習する過程で、ツールがそのまま有用であり、交換する必要がないことに気付くかもしれません。

すべてのAPI呼び出しにはセキュリティ情報が添付されている必要があり、トークンシステムなどを開発する必要があります。

はい。これがその方法です。

プログラムが実行する機能ごとに、完全なAPI呼び出しを記述する必要があります。実装するほとんどすべてのメソッドは、APIから実行する必要があります。すべてのユーザーのGet / Update / Deleteに加えて、ユーザー名の更新、グループへのユーザーの追加など、他の各操作のバリアントがあり、それぞれが個別のAPIコールになります。

必ずしも。これが、RESTのようなアーキテクチャーが登場する場所です。アプリケーションが動作するリソース、およびそれらのリソースに適用する意味のある操作を特定し、他のリソースをあまり心配することなくこれらを実装します

APIに関しては、インターフェイスや抽象クラスなどのあらゆる種類のツールが失われます。WCFのようなものには、インターフェイスに対する非常に乏しいサポートがあります。

それどころか、APIを使用している場合、lessではなくインターフェースがより重要になります。それらはあなたがそれらをレンダリングする表現で出てきます。最近ではほとんどの人がこのためにJSONベースの形式を指定していますが、適切に指定する限り、任意の形式を使用できます。バックエンドでこの形式への呼び出しの出力をレンダリングし、フロントエンドで希望するもの(おそらく同じ種類のオブジェクト)に解析します。オーバーヘッドは小さく、柔軟性の向上は莫大です。

ユーザーを作成するメソッド、または何らかのタスクを実行するメソッドがあります。50人のユーザーを作成する場合は、50回呼び出すだけです。このメソッドをAPIとして実行することを決定すると、ローカルWebサーバーは名前付きパイプに接続でき、問題はありません-デスクトップクライアントもヒットできますが、突然、ユーザーの一括作成にはインターネット上でAPIを50回ハンマーする必要があります。良くない。したがって、バルクメソッドを作成する必要がありますが、実際にはデスクトップクライアント用に作成するだけです。この方法では、a)統合するものに基づいてAPIを変更する必要があり、直接統合することはできません。b)余分な関数を作成するためにより多くの作業を行う必要があります。

既存のメソッドの一括バージョンを作成することは、「はるかに多くの作業」と呼ぶことはほとんどありません。原子性のようなことを心配していない場合、バルクメソッドは、オリジナルの非常に薄いフロントエンドにすぎないことになります。

ヤグニ。たとえば、1つのWebアプリケーションと1つのWindowsアプリケーションなど、まったく同じように機能する2つのアプリケーションを作成することを特に計画しているのでなければ、膨大な量の開発作業が必要になります。

いいえ、YANI(すでに必要です)。上記のように概説しました。唯一の問題は、どれだけの設計作業をそれに入れるかです。

エンドツーエンドでステップスルーできない場合、デバッグははるかに困難になります。

エンドツーエンドをステップスルーできないのはなぜですか?

しかし、もっと重要なのは、表示されているすべてのデータを切り取る簡単に認識できる形式でデータをやり取りできることで、実際にはデバッグ難しくなるのではなく、簡単になる傾向があります。

多くのやり取りを必要とする独立した操作がたくさんあります。たとえば、いくつかのコードは現在のユーザーを取得し、ユーザーが管理者ロールにあることを確認し、ユーザーが属する会社を取得し、他のメンバーのリストを取得し、それらをすべて送信しますEメール。そのためには、多くのAPI呼び出しが必要になるか、必要な特定のタスクに特注のメソッドを記述する必要があります。特注のメソッドの唯一の利点は速度ですが、欠点は柔軟性に欠けることです。

RESTは、オブジェクトの個々のプロパティではなく、完全なオブジェクト(REST理論の用語を使用するためのリソース)で作業することでこれを解決します。ユーザーの名前を更新するには、ユーザーオブジェクトを取得し、名前を変更して、ユーザーをPUTします。ユーザー名を変更すると同時に、他の変更を加えることもできます。より一般的な問題は、オブジェクトの個々のプロパティを更新するための個々の呼び出しをすべて排除できるため、解決が容易になります。オブジェクトをロードして保存するだけです。

ある意味では、これはハードウェア側のRISCアーキテクチャとは異なりません。RISCとCISC(その前身)の主な違いの1つは、CISCアーキテクチャはメモリ上で直接動作する多くの命令を含む傾向があることです。一方、RISCアーキテクチャは主にレジスタで動作する傾向があります。 LOAD(メモリから何かをレジスタにコピーする)とSTORE(レジスタから値を取得してメモリに入れる)。

これは、レジスタからメモリへのより多くのトリップを意味し、マシンの速度が低下することになると思います。しかし、実際には、逆のことがよく起こります。プロセッサ(クライアント)はメモリ(サーバー)へのトリップの間により多くの作業を行います。これが高速化の原因です。

簡単に言えば、同僚は正しい。これが道です。少しアップフロントの仕事と引き換えに、それは劇的にあなたのウェブサイトのためのコードを簡素化しますし、他のウェブサイトやアプリケーションとの統合を可能にします。それは支払う価値のある価格です。

参考文献:

  1. REST API設計-リソースモデリング

7
これらにも事実上の APIがあります。他の多くの開発者を恐怖にさらす傾向がありますが、APIはすべて同じです。うまく設計されたものではありません。
スプーニエスト

7
それは本当に貧弱なAPIになります:非常に貧弱なので、多くの人はそれをAPIであるとさえ考えていません。しかし、フロントエンドがバックエンドとやり取りする方法は依然として定義されていますが、その方法は粗雑です。これをAPIとして考えることは、それをうまくやることの重要性を理解するのに役立ちます。
スプーニエスト

1
Linuxコミュニティがカーネルに使用された商用Bitkeeper DVCSの使用に反抗したため、Linusがgitを作成したと思います。
gbjbaanb

2
あなたの最初の文は私の混乱をすべて払拭します。APIという用語をWebサービスに関連付けましたが、それが私を混乱させた主な理由です。
-NibblyPig

4
@IanNewson:コードとやり取りする方法があり、httpと呼ばれます。それは多くの無関係な要件を持ち、多くの無関係なデータを返すかもしれませんが、それはそれをお粗末なAPIにします。
jmoreno

63

現在、マイクロサービスが大流行していることは知っていますが、必ずしも価値があるわけではありません。はい、疎結合コードが目標です。しかし、より苦しい開発サイクルを犠牲にしてはいけません。

適切な中間点は、ソリューションに別のデータプロジェクトを作成することです。データプロジェクトは.NETクラスライブラリになります。ASP.NET MVCプロジェクトは、データライブラリへの参照を追加し、すべてのモデルがデータプロジェクトから取得されます。次に、デスクトップまたはモバイルアプリを作成するときが来たら、同じコードを参照できます。したがって、公式のAPIではないかもしれませんが、1つとして機能します。APIとしてアクセス可能にしたい場合は、データプロジェクトのラッパーとして機能する単純なWebプロジェクトを作成できます。

マイクロソフトはこの概念を推進しており、これをポータブルクラスライブラリと呼びます。


13
同じ共有データ構造を呼び出して、ロジックをUIレイヤーに配置するプロジェクトを維持する必要がありました。そのため、1つのバグを30回修正する必要がありました(「同じロジックを再度使用する必要がある場合は、コピーして貼り付けます!APIは不要です」)。ロジックレイヤーがあれば(今はありました)、たった1つの修正で十分でした。
SJuan76

1
この答えは、そのライブラリを独自のNuGetパッケージにラップし、独自のNuGetパッケージフィード/サーバーをホストすることに加えて、良い方法です。細かいネットワークについて心配する必要はなく、すべての呼び出しをスレッドに対してローカルに(したがってより高速に)行うことができます。さらに、NuGetを使用してクラスライブラリに適切なバージョンを導入すると、他のチームがアップグレードする際の柔軟性が得られます。
グレッグブルクハート

34

いいえ、すべきではありません。同じバックエンドにアクセスする代替フロントエンド(モバイルアプリやデスクトップアプリ、別のWebアプリケーションなど)をすぐに作成する計画がない場合は、Webサービスレイヤーを導入しないでください。ヤグニ

疎結合は(高い凝集度とともに)常に望ましいですが、それは設計原則であり、異なるサーバー上のオブジェクトを物理的に分離する必要があるという意味ではありません!また、サービスAPIの設計が適切でないと、サーバーの境界を越えて密結合が発生する可能性があるため、APIを使用しても疎結合が保証されるわけではありません。

将来、サービスAPIの必要性が生じた場合、その時点でいつでも導入できます。コードを適切に階層化しておく限り(データアクセスとビジネスロジックをUIロジックから完全に分離)、現在よりも後から導入するのは難しくありません。また、実際の要件を満たすように設計された場合、結果として得られる設計はより良くなります。


注:Webサービス APIを作成する必要があるかどうかという質問だと思います。質問は単にAPIと言っていますが、APIはライブラリのインターフェイスを意味することもあり、当然、すべてのレイヤーは定義によりAPIを持ちます。結論として、ビジネスロジックとデータアクセスレイヤーは、デザインレベルでUIロジックから完全に分離する必要がありますが、必要でない場合はWebサービスレイヤーを導入しないでください。


8
悪いデザインのものは良くありません。APIを作成するのは時間ではなく、将来性があります。能力が極めて重要な、今日、より良いあなたも知らないあらゆるニーズを満たすために強力な基盤を築くこと変化に適応するが、それはあなたが考えるよりも早く来るかもしれない...
ローランS.

9
@Bartdude:到着しない未来のために「将来を保証する」ために不必要な複雑さを導入することは、単にリソースを浪費することです。
ジャックB

6
@BartdudeがAPIを追加するのは間違いなくもっと時間があります。そうでないと主張できるかどうかはわかりません。
イアンニューソン

13
「Webサービスレイヤーを導入しないでください」API!= Webサービス。APIの背後にビジネスロジックがある場合は、ある時点でそのAPIをWebサービスとして公開できます。ただし、これは事前の要件ではありません。
セロス

2
@JacquesB:...必要になるかどうかわからない場合、確かに機能を開発しません。それが私がYAGNIから理解していることです。しかし、アーキテクチャは機能ではないため、アーキテクチャの選択が不適切な場合、悲惨な失敗につながる可能性があります(そしておそらくそうなるでしょう)。繰り返しますが、この議論は起こる可能性もあると思いますが、予算、市場投入までの時間、リソース、または知識不足の理由のためにそうではない場合もあります。私はしばしば自分と同じ議論をしたので、あなたの主張を理解しています^ _ ^
ローランS.

29

私の会社には、このように作成されたアプリケーションが1つあります。最初は、別の開発者が作成しているフロントエンドのAPIを使用してバックエンドを構築するよう依頼されました。他の開発者がそのフロントエンドを開発できなかったとき、フロントエンドの構築も依頼されました。このアプローチには確かにメリットがありますが、コストという大きなデメリットがあります。メンテナンスするコードが多くなり、2つの別個のシステムもデプロイされるため、初期ビルドは大幅に高価になり、進行中のメンテナンスはより高価になります。余分なコストがあるため、これは常に開発者が気まぐれに行うのではなく、ビジネス上の決定である必要があります。

それを理解するために、私は上記のプロジェクトがこのアプローチのために20%多くの費用がかかると見積もっています。どんな種類のプロジェクトに取り組んでいるのかを説明していませんが、製品を立ち上げようとしている場合は、製品を作るいくつかの追加機能を出荷するのとは異なるコストがかかる可能性があります成功。

少なくとも普遍的ではないもう1つの理由は、2番目のインターフェイスを作成する場合、または作成するときに、機能の1対1のマッピングがほとんどないことです。たとえば、モバイルアプリを作成する場合、機能が少なくなる傾向があります。これは、APIメソッドの一部が再利用されないことを意味します。したがって、同僚との妥協点は、最も重要/重要な呼び出しを決定し、それらをAPIに追加し、他のすべてに従来の方法を使用することです。

考慮すべきもう1つの点は、同僚が既存のコードを再利用できないと言っていることです。これは、ビジネスロジックを分離している場合は当てはまりません。内部APIの周りにシンWebサービスラッパーを作成するだけでよく、これは特に大きなタスクではありません。とにかく、まったく変更せずに、Webサービスレイヤーを別のフロントエンドに再利用できると考えるのは簡単でしょう。


22

それは、アプリケーションのタイプとあなたがいる市場のタイプに依存します。

この方法にはトレードオフと利点があります。1つの方法が他の方法より優れているというのは明確な答えではありません。

私は個人的な経験から話をします。私は2007年にこの方向で作業しているコードベースを採用することを決めました。そのコードベースは、現在約100万行のコードのどこかにあり、その半分は大量のWebサービスの背後に隠されたサーバーコードです。 APIの残りの半分は、クライアント、デスクトップネイティブ、デスクトップWeb、モバイル、バックエンド統合などの小隊です。この決定にはマイナス面はありませんでしたが、20/20後知恵でもう一度やり直せます。関連するいくつかのトレードオフを示します。

利点

  • 柔軟性。デスクトップエクスペリエンスを強化するモバイルアプリを構築する要求であろうと、SAPのバックエンドと統合する要求であろうと、APIがすでにある場合はすべて簡単になります。これらのリクエストを十分に取得すると、APIに向かって有機的に進化します。唯一の問題は、その前に標準のWebサービスがあるかどうか、またはWebサービスがテーラーメイドの内部APIであるかどうかです。

  • (チームの)スケーラビリティ。私たちの場合、このAPIの上にすべての開発者グループが多数あります。専用のAPIチームがあり、さまざまなグループと話し合い、ニーズをまとめ、そこから汎用APIを構築します。人々はAPIの上に何かを構築しているとは言われていませんが、それを行うすべての人が当社で働くわけではありません。

  • セキュリティ。コードベースの安全でない部分と安全な部分を明確に区別することは、セキュリティを推論するのに役立ちます。UIとバックエンドコードを混同すると、問題が混乱する傾向があります。

トレードオフ

  • 柔軟性。APIに何かを「適切に」構築するには、作業を行う必要があります。特定の問題を解決するために、UIコード内からDBクエリをすばやく実行することはできません。また、実際に再利用可能なAPIでは、多くのユースケースを考慮に入れる必要があるため、通常、迅速な解決策は間違った解決策です。特に、すでに多くのクライアントコードが既に存在するため、APIの柔軟性が低下します(そのため、バージョン管理されたAPIに移行しています)。

  • 初期開発速度。疑いの余地なく、APIファーストの開発は遅くなります。APIの上に十分なクライアントが構築されている場合にのみ、それを取り戻します。しかし、APIが十分に汎用的に進化する前に、3つの異なるクライアント実装が必要であることがわかります。最初のAPIデザインのほとんどが間違っていることがわかり、Webサービスの構築方法に関するガイドラインを強く修正する必要がありました。

赤ニシン

あなたはこれらの束に言及しました。実際には問題ではありません。

  • 抽象化。APIは、製品が提供する必要があるすべてのユースケースをカバーするのに十分なほど抽象的になります。Webサービスがなくても、これを実行する内部APIを使用するか、多数の重複コードを使用します。私は複製よりも抽象化を好みます。

  • サーバー側のMVCスタックを放棄します。最近では、ほぼすべてのシステムでしばらくしてモバイルアプリが必要になります。その後、そのモバイルアプリに対応するWebサービスを構築する場合、とにかくAPIコンテキストで認証と承認を行う方法を理解する必要があります。実際には、それを行う方法が1つしかない場合(Webサービスで行う方法)に、作業量が少なくなります。

  • 一括操作。通常、バックエンドジョブを起動し、ステータスクエリ用のジョブIDを返すバルクAPIを作成することで解決します。それほど大きな問題ではありません。

  • デバッグ。全体として、システムのトラブルシューティングが少し簡単になったことがわかりました。フロントエンドコードとバックエンドコードの両方にブレークポイントを設定することもできるため、実際にはステップスルーするのはそれほど難しくなく、自動化されたAPIテストを構築し、実稼働システムを監視するためにAPIをインストルメントすることができます。

  • 多くの独立した操作。それは、物事をどのように設計するかという問題です。純粋なCRUD APIを使用することを主張する場合、はい、この問題に苦しむことになります。しかし、それを補強するためにいくつかのCQRS APIを用意することは通常良いアイデアです。また、サービスがフロントエンドである内部APIがあることを確認したら、その内部APIを簡単に再利用して特定のサービスを構築できますシナリオの。

要約すれば

十分に異なるコンテキストで使用されるシステムでは、すべてのニーズに応える最も簡単な方法であるため、APIは自然に進化します。しかし、YAGNIが進行していることは間違いありません。トレードオフがあり、それが意味をなすまで意味がありません。重要な点は、独断的ではなく、製品の進化するニーズを満たすために、アーキテクチャのさまざまなアプローチに対してオープンな心を保つことです。


興味深い読み物ですが、APIを設計する際に間違ったことや、学んだことについて詳しく説明できますか?
aaaaaaaaaaaa

3
主な3つの間違いは、(1)プライマリUIのニーズにAPIを過剰に適合させる、(2)セッションを使用して複数のリクエストにまたがって状態を構築する(徐々にセッションレスになっている)、および(3)生成された識別子としてのdb id。多くの場合、ユーザー設定可能なコードがより優れた識別子です(外部システムとの統合では、通常、APIで後で使用するためにシステムに識別子をアップロードします)。これらの3つと弱いドキュメントと役に立たないエラーメッセージにより、APIは支援なしでは使用できませんでした。
ジョーリセブレヒト

10

同僚が説明しているのは、サービス指向アーキテクチャです。これは非常にスケーラブルで、テスト可能で、コードを作成するための健全な方法になりますが、実際に作成しているものに依存します。

SOAにはいくつかの重要な利点がありますが、それらを列挙してみます。

拡張性

バックエンドは分離されているため、フロントエンドは単なるフラットファイルの一連のテンプレートになります。フラットファイルは、CDNから提供するのに非常に高速で安価です。これらを縮小して静的HTMLにプリコンパイルし、クライアント側でデータを取り込むことができます。

APIは一貫性を維持する必要がありますが、既存のテクノロジーよりも大きくなった場合、スタックを壊すことなく、より高速なテクノロジーに交換できます。たとえば、Goでリメイクできます。断片的に再構築し、サーバー間で負荷を分散できます。インターフェイスが同じである限り、テクノロジーは抽象化されます。

テスタビリティ

通常、MVCはクリーンな状態から始まりますが、実際にはコントローラーが単一のリソースに集中することはめったにありません。コントローラーメソッドの処理が多いほど、テスト可能性は低くなります。

APIはこの問題を回避します。各API呼び出しは、リソースをプルして提供します。クリーンでテスト可能。

懸念事項の分離を保証

フロントエンドとバックエンドは完全に離婚しています。フロントエンドを別の開発者またはデザイナーに提供できます。これは、MVCを別のレベルに引き上げたものです。MVCをあきらめたくないと思います。SOAはMVCですが、それ以上です。

欠点

もちろん、いくつかの欠点もあります。多くの場合、モノリスの方が早いです。慣れているかもしれません。それはあなたのスタックによりうまく適合するかもしれません。ツールはモノリス作成用に最適化されている場合があります。

私の意見では、これらのどれも特に正当な理由ではありません。もしそれらがあなたに当てはまるなら、あなたは改造を検討したいと思うかもしれません。


これはこれまでで最も明確な答えです。
トニー・エニス

7

ここにはたくさんの良い答えがありますので、実装の経験を追加します。

これは私が物事を行う方法:

  • すべて/のみのDB対話を処理するデータベースアクセスレイヤーを作成します(通常、速度と制御には手動SQLが使用され、ORMは使用されません)。挿入、更新、削除、選択...
  • 必要なAPI関数を公開/強制するinterfacevirtual class)を作成します。実装時には、高度に特化したDBAL関数を使用して結果を達成します。また、コンパイラレベルでAPIを実施するのに役立ちます。そのため、サーバー+ API実装にすべての機能が組み込まれていることを確認します。
  • インターフェイス(これは実際のAPI)を実装し、セキュリティ制限を実施する2番目のレイヤーを作成します。また、ここで外部APIと対話します。
  • Webサイトは、リモートアクセス可能なAPI (SOAP、JSONなど)を経由せずに、(パフォーマンスのために)第2レイヤーを直接使用します
  • スタンドアロンサーバーは、インターフェイスを実装し、外部デスクトップ/モバイルクライアント(非Webサイトアクセス)に実際のリモートアクセス可能なAPIとして第2レイヤーを公開するビルドです。リクエストをデコードし、レスポンスをエンコードし、クライアントを管理/切断するだけです。また、接続されている他のピアによって生成されたイベントをクライアントに大量に通知するプッシュバック機能もサポートしています(Webサイトでは通常必要ない機能)

したがって、技術的には、APIは第2層です。Webサイトで直接使用し、サーバーを介してリモートクライアントに公開します。コードは再利用され、再利用可能なコードの塊はインライン化されません。(このルールで生きて死ぬ、すべてが素晴らしい)保守性、テスト...すべてを支援します。

Webサイトをデスクトップ/モバイルAPIサーバーに接続することはありません(サイトがAJAXでJSONで実行されている場合を除く)。ただし、サイトがマークアップで動的コンテンツをレンダリングする場合、中間APIを通過するとパフォーマンスが低下します。ウェブサイトは高速である必要があります!リモートクライアントアクセスは少し遅くなる場合があります。

PSはい、より多くのホイールが連動するためメンテナンスは少し複雑になりますが、長期的には簡単です。そのため、プロジェクトがしばらくの間存続することを意図しており、少し複雑な場合は、常にAPIを用意してください。また、各レイヤーを単独でテストする方がはるかに簡単です。


それは非常にクールに聞こえ、多くの意味をなします。特に、APIタイプ関数にインターフェースを配置します。次回プロジェクトを作成するときに、この設定を試してみます!
NibblyPig

6

競合のポイントは、APIを使用すべきかどうかではなく、実際に「API」とは何かということです。設計されたAPIを使用する唯一の代替方法は、ランダムなコードの混乱であるAPIを使用することです。あなたは、APIが物事を「非常に柔軟」にし、それが物事を管理できないようにすることを書きます。これは、APIが何であるかを完全かつ完全に誤解していることを示しています。その誤解があなたとあなたの同僚の間で共有されない場合、あなたは完全に異なることについて議論することによって多くの時間を無駄にしました。

明確に定義されたAPIを使用しないことで、何でも好きなことができます。定義により、これは最も柔軟なオプションです。また、定義上、「あなたがやりたいことを何でもする」は依然としてAPIです。API の唯一の仕事は、柔軟性を取り除くことです。優れたAPIは、柔軟性を排除することにより、ユーザーが同様の方法で同様のことを行えるようにします。

もちろん、悪いAPIが提供する柔軟性は多すぎたり少なすぎたり、あるいは両方を同時に提供したりします。本当に不十分に設計されたAPIは、「何でもする」アプローチよりもさらに速くプロジェクトを殺すことができます。ただし、ベストプラクティスは、アプリケーションと共にAPIを開発および進化させる有能なプログラマーを配置することです。

•多くのやり取りを必要とする独立した操作がたくさんあります。たとえば、いくつかのコードは現在のユーザーを取得し、ユーザーが管理者ロールにあることを確認し、ユーザーが属する会社を取得し、他のメンバーのリストを取得し、送信しますすべてのメール。そのためには、多くのAPI呼び出しが必要になるか、必要な特定のタスクに特注のメソッドを記述する必要があります。特注のメソッドの唯一の利点は速度ですが、欠点は柔軟性に欠けることです。

まともなAPIでこれが必要とするAPI呼び出しの数は、おそらく1になります。


4

彼は、私たちのコードが密結合しすぎていると言った。たとえば、デスクトップアプリケーションも必要な場合、既存のコードを使用することはできません。

さて、あなたは?そうでない場合、それはかなり無関係なステートメントです。

2015年に新しいアプリケーションを構築する場合は、サーバーで生成されたHTMLページではなく、APIを含むユーザーインターフェイスを使用して真剣に検討します。明らかな費用がありますが、明らかな利点もあります。

しかし、いくつかの異なるインターフェースを持つ具体的な計画のない既存のサイトがある場合(私が知る限り)、彼のコメントはまったく関係ありません。


4

短いバージョン:コントローラーは、何であれ、事実上APIです。ただし、ASP.NETはそれをあいまいにしている可能性があります。

長いバージョン:

ビールに関する情報を提供し、オプションでビールを販売する基本的なMVC Webアプリについて考えてください。ルートはどのように見えますか?

/sign_in
/sign_out
/beer
/beer/{beer_name}
/order
/order/{order_number}

通常のWebアプリでは、次のような補助的なルートがいくつかあります。

/beer/new
/beer/{beer_name}/edit
/beer/{beer_name}/delete
/order/new
/order/{order_number}/edit
/order/{order_number}/delete

Web APIでは、HTTPメソッドから推測されるため、これらは必要ありません。

上記の対称性を考えると、これはかなり説得力のあるケースになり、APIとコントローラーが非常に近くなり、同じものになる可能性があると思います。

掘り下げた後、使用しているASP.NETのバージョンに応じて、これがあなたにとっての状態になる可能性があると判断しました。古いMVC 5以前には、2つの実装を適切に統合するための規則とインターフェイスがありません。古いバージョンでは、Webアプリはビューにデータを入力しますが、APIはHttpResponseを返します。ただし、どちらの場合でも、それらは意味的にまったく同じ応答を生成しています。

MVC 6を使用している場合、ユニファイドコントローラークラスで両方を取得するため、返されるものについてスマートになります。このモデルに適したASPサンプルコードは見つかりませんでしたが、同じパターンのRailsコードをいくつか見つけました。Diasporaプロジェクトの「いいね」のコントローラーを検討してください。各コントローラーメソッドには、ここでAPIのLCRUDに相当する「リソースの多い規則」定義されたルートがあります。

ただし、実装を読むと、それぞれがHTML、モバイルHTML、またはJSONに応答する可能性があります。これを、ビューを見つけるための規則と組み合わせて、WebアプリとWeb APIを完全に統合します。また、すべてのメソッドが実際に各応答を提供するわけではないことにも注意してください(UIにはAPIが必要としないメソッドが必要な場合があり、その逆も同様です)。

これはインピーダンスの不一致です。これは、ASP.NETがこのすべてを遅らせたのに対し、Railsはしばらくの間対称性を受け入れ、非常に明確にしたためです。

投機:

使用しているASPバージョンに応じて、同僚はおそらく正しいか間違っています。古いMVCバージョンでは、ASP.NETのモデルでは適切なコードの再利用が実際には許可されていなかったため、APIとAppの違いにより、APIを事前に構築することが「ベストプラクティス」となる可能性があります。

新しいものでは、統一されたコントローラーの基本クラスでコードを再利用しやすくなるため、統一されたコードを使用する方が理にかなっています。

ただし、どちらの場合でも、コントローラーは事実上APIです。


この質問は死に対して答えられましたが、他の答えはそれほど明確ではなかったと思います。「APIの構築を避けることはできません。」答えはほぼ正解であり、受け入れられた答えは同じ問題をめぐって踊りました。しかし、どちらも私がASPに具体的に取り組んでいなかったので、私はポイントを家に帰したと感じました。
ジェイソン

より多くの回答は陽気です、彼らはこれについて他の人々が感じるもののバランスの取れた感謝を得るのを助けます。
NibblyPig

2

2006年に私のキャリアを始めたとき、このタイプのアーキテクチャは.NETの世界で大流行していました。私は、ビジネスロジックレイヤーとWebフロントエンドの間のWebサービスで、2000年代半ばに考案された3つの別個のプロジェクトに取り組みました。もちろん、最近のWebサービスはSOAPでしたが、それでも同じアーキテクチャです。想定される利点は、フロントエンドまたはバックエンドのいずれかを切り替え、さらにデスクトッププログラムを開発できることです。最終的にYAGNIは真実であることが証明されました。これが起こるのを見たことがありません。この間ずっと、この方法でプロジェクトを分割するコストだけを見ました。プロジェクトの1つからWebサービスをリッピングすることになり(他のことをしながら段階的に削除するには半年かかりました)、チーム全体が満足していました。それ以来、私はそのアプローチを試みたことはなく、非常に具体的な理由が与えられない限りそうしません。このアーキテクチャを試した5年間の経験から、私はこのアーキテクチャを必要としないことを学びました。私が必要とするプロジェクトのみがそれを行うことができます。

さて、ビジネスロジックとコントローラー/プレゼンターの間のレイヤーの開発に一生懸命取り組んでいます。たとえば、サービスレイヤーがあり、クエリ可能なものを公開せず、すべてのサービスにインターフェイスを使用し、IoCを使用してコントローラーに挿入します。アーキテクチャにWebサービスが必要になった場合、手頃なコストで導入できます。事前にこの費用を支払いたくありません。

また、マイクロサービスのアイデアは非常に好きですが、マイクロサービスは水平層ではなく垂直モジュールを意味するという私の理解です。たとえば、Facebookを構築している場合、チャット機能は独自のサーバーなどに個別に展開される別個のサービスになります。これは、私が推奨する独立したサービスのタイプです。


2

サードパーティはそれを使用しますか? はい、そうすべきです。

近い将来にそれを再利用する予定はありますか? はい、そうすべきです。
あなたはサードパーティとなり、文書化された、または文書化可能な、またはサードパーティが使用可能な APIを使用して、確実な再利用性とモジュール性を提供します。

急いでいますか? いいえ、すべきではありません。
後のリファクタリングは、ほとんどの方法論や教師が予測して伝えるよりも簡単かつ迅速です。何も持たないよりも、(リファクタリングできる可能性があり、リファクタリングされる内部設計が悪い場合でも)動作している何かを持つことがより重要です。(ただし、信じられないほどの内部設計、wohoo)

フロントエンドは、理由により日の明かりを見ることはないでしょうか? はい、する必要があります。
この理由を付け加えたのは、まあ、これは私によく起こったことだからです。
そして、少なくとも、再利用や再配布などのためにコンポーネントが残っています。


1

ここには良い答えがあります。これを部分的な回答として投稿します。おそらくコメントとしては良いでしょう。ただし、同じコメントを多数の投稿に貼り付けるのはよくありません。

YAGNIがAPIを作成しない理由であると主張することはできません。

APIは、自然で論理的なテストエンドポイントです。したがって、0日目から、APIを使用する2つのアプリケーションがあります。UIとテストスイートです。1つは人間向け、もう1つは機械向けです。それらは必然的に異なります。フロントエンドの動作のテストは、バックエンドの動作のテストとは非常に異なるタスクです。したがって、テクニックとおそらくツールは完全に異なります。APIを使用すると、ジョブに最適なツールを使用できます。さらに、APIによって提供される分離により、フロントエンドテスターはバックエンド機能をテストする必要がありません。

また、このAPIは、フロントエンドコーダーをバックエンドコーダーの懸念から保護するのに役立ちます。これらは当社の非常に異なるスキルです。APIにより、私たちが最も強い場所に集中できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.