BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ アーティクル マイクロサービス設計原則: SOLIDではなくIDEALS

マイクロサービス設計原則: SOLIDではなくIDEALS

キーポイント

  • For object-oriented design we follow the SOLID principles. For microservice design we propose developers follow the “IDEALS”: interface segregation, deployability (is on you), event-driven, availability over consistency, loose-coupling, and single responsibility.
  • Interface segregation tells us that different types of clients (e.g., mobile apps, web apps, CLI programs) should be able to interact with services through the contract that best suits their needs. 
  • Deployability (is on you) acknowledges that in the microservice era, which is also the DevOps era, there are critical design decisions and technology choices developers need to make regarding packaging, deploying and running microservices. 
  • Event-driven suggests that whenever possible we should model our services to be activated by an asynchronous message or event instead of a synchronous call. Availability over consistency reminds us that more often end users value the availability of the system over strong data consistency, and they’re okay with eventual consistency. 
  • Loose-coupling remains an important design concern in the case of microservices, with respect to afferent (incoming) and efferent (outgoing) coupling. Single responsibility is the idea that enables modeling microservices that are not too large or too slim because they contain the right amount of cohesive functionality.
     

原文(投稿日:2020/09/03)へのリンク

2000年、Robert C. Martin氏は、以下に示すオブジェクト指向設計の5つの原則をまとめました。Michael Feathers氏は後にこれらの原則をSOLIDの頭字語にまとめました。それ以来、オブジェクト指向設計のSOLID原則は本に記載され、業界で広く知られるようになりました。

  • 単一責任の原則 (Single responsibility principle)
  • 開放閉鎖の原則 (Open/closed principle)
  • リスコフの置換原則 (Liskov substitution principle)
  • インターフェイス分離の原則 (Interface segregation principle)
  • 依存性逆転の原則 (Dependency inversion principle)

数年前、私は仲間の開発者にマイクロサービス設計を教えていました。ある学生が「SOLID原則はマイクロサービスに適用されますか?」と質問をうけたとき、いくつか考えた後、私の答えは「部分的に」でした。

数か月後、私はマイクロサービスの基本的な設計原則 (およびそれに伴うキャッチーな頭字語)を探していました。しかし、なぜそのような質問が重要なのでしょうか?

私たちは業界として、6年以上にわたってマイクロサービスベースのソリューションを設計および実装してきました。この間、ますます多くのツール、フレームワーク、プラットフォーム、およびサポート製品が、マイクロサービスを取り巻く信じられないほど豊富な技術ランドスケープを確立しています。

この状況では、初心者のマイクロサービス開発者は、マイクロサービスプロジェクトで直面する多くの設計上の決定とテクノロジの選択に迷子になる可能性があります。

この領域では、核となる一連の原則が、開発者がマイクロサービスベースのソリューションの正しい方向に設計決定を向けるのに役立ちます。

SOLIDの原則の一部はマイクロサービスに適用されますが、オブジェクト指向は、一般に分散システムの要素、特にマイクロサービスとは根本的に異なる要素 (クラス、インターフェイス、階層など) を扱う設計パラダイムです。

したがって、マイクロサービス設計のために、次の一連の核となる原則を提案します:

  • Interface segregation: インターフェイス分離
  • Deployability (is on you): デプロイ容易性
  • Event-driven: イベント駆動
  • Availability over consistency: 整合性よりも可用性
  • Loose coupling: 疎結合
  • Single responsibility: 単一責任

原則は、マイクロサービスベースのソリューションの設計決定のすべての範囲を網羅しているわけではありませんが、最新のサービスベースのシステムを作成するための主要な懸念事項と成功要因に触れています。マイクロサービスに適用されるこれらの原則 (待望のマイクロサービスのIDEALS) の説明について読んでください。

インターフェイス分離 (Interface Segregation)

元のインターフェイス分離の原則では、オブジェクト指向クラスに「fat」インターフェイスを推奨しています。つまり、クライアントが必要とする可能性のあるすべてのメソッドを持つクラスインターフェイスの代わりに、クライアントの種類毎の特定のニーズに対応する個別のインターフェイスに分離することが必要です。

マイクロサービスアーキテクチャスタイルは、サービス指向アーキテクチャの特殊化であり、インターフェイス (つまり、サービス契約) の設計は常に最も重要です。2000年代初頭から、SOAの資料では、すべてのサービスクライアントが準拠するべき正規モデルまたは正規スキーマが規定されていました。しかし、昔のSOAから、サービス契約設計へのアプローチ方法は変わっています。マイクロサービスの時代には、多くの場合、同じサービスロジックに多数のクライアントプログラム (フロントエンド) があります。それが、マイクロサービスにインターフェイス分離を適用する主な動機です。

マイクロサービスのインターフェイス分離の実現

マイクロサービスのインターフェイス分離の目標は、各タイプのフロントエンドがそのニーズに最適なサービス契約を認識することです。たとえば、モバイルネイティブアプリは、データの短いJSON表現で応答するエンドポイントを呼び出す必要があります。同じシステムに、完全なJSON表現を使用するWebアプリケーションがあります。同じサービスを呼び出し、XMLでの完全な表現を必要とする古いデスクトップアプリケーションもあります。異なるクライアントが異なるプロトコルを使用する場合もあります。たとえば、外部クライアントはHTTPを使用してgRPCサービスを呼び出す必要があります。

すべてのタイプのサービスクライアントに同じサービス契約 (標準モデルの使用) を課すのではなく、「インターフェイスを分離」して、各タイプのクライアントが必要なサービスインターフェイスを確認できるようにします。どうすればよいでしょうか? 有名な代替策は、APIゲートウェイを使用することです。メッセージ形式の変換、メッセージ構造の変換、プロトコルブリッジング、メッセージルーティングなどを実行できます。人気のある代替策は、Backend for Frontends(BFF)パターンです。この場合、クライアントのタイプごとにAPIゲートウェイがあります。この図に示すように、通常、クライアントごとに異なるBFFがあります。

(チームの意思による) デプロイ容易性 (Deployability)

ソフトウェアのほぼすべての歴史について、設計の取り組みは、実装ユニット (モジュール) の編成方法と実行時要素 (コンポーネント) の相互作用方法に関連する設計決定に集中してきました。アーキテクチャ戦術、設計パターン、およびその他の設計戦略は、ソフトウェア要素をレイヤに整理し、過度の依存関係を回避し、特定のタイプのコンポーネントに特定の役割または関心事を割り当て、「ソフトウェア」の領域で他の設計決定を行うためのガイドラインを提供しています。マイクロサービス開発者にとっては、ソフトウェア要素を超える重要な設計上の決定があります。

開発者として、私たちは長い間、適切なランタイムトポロジーにソフトウェアを適切にパッケージ化してデプロイすることの重要性を認識してきました。しかし、マイクロサービスを使用した今日のように、デプロイメントとランタイムの監視にこれほど注意を払ったことはありません。ここで「デプロイ容易性」と呼んでいるテクノロジーと設計の決定の領域は、マイクロサービスの成功にとって重要になりました。主な理由は、マイクロサービスがデプロイユニットの数を劇的に増やすという単純な事実です。

そのため、IDEALSの文字Dは、マイクロサービス開発者に、ソフトウェアとその新しいバージョンが楽しむユーザがすぐに利用できるようにする責任があることを示しています。全体として、デプロイ容易性には以下が含まれます:

  • コンテナ、ポッド、クラスタ、永続性、セキュリティ、ネットワークなどのランタイムインフラストラクチャを構成。
  • マイクロサービスのスケールインおよびスケールアウト、またはランタイム環境を別のランタイム環境への移行。
  • commit+build+test+deployプロセスの迅速化。
  • 現在のバージョンを置き換えるためのダウンタイムを最小限に抑える。
  • 関連ソフトウェアのバージョン変更の同期。
  • 障害をすばやく特定して修正するための、マイクロサービスの状態監視。

優れたデプロイ容易性の実現

自動化は、効果的なデプロイ容易性の鍵です。自動化には、ツールとテクノロジーの賢明な利用が含まれます。これが、マイクロサービスの登場以来、最も変化が続いている場所です。したがって、マイクロサービスの開発者は、ツールとプラットフォームの観点から新しい方向性を模索する必要がありますが、常に新しい選択肢それぞれの利点と課題に疑問を投げかけています。 (重要な情報源は、ThoughtWorks Technology RadarSoftware Architecture and Design InfoQ Trends Reportです) 。

デプロイ容易性を改善するためにマイクロサービスベースのソリューションで開発者が考慮すべき戦略とテクノロジーのリストを次に示します:

  • コンテナ化とコンテナオーケストレーション: コンテナ化されたマイクロサービスは、プラットフォームやクラウドプロバイダ間での複製とデプロイがはるかに簡単です。オーケストレーションプラットフォームは、ルーティング、スケーリング、レプリケーション、負荷分散などのための共有リソースとメカニズムを提供します。DockerとKubernetesは、コンテナ化とコンテナオーケストレーションの今日の事実上の標準です。
  • サービスメッシュ: この種のツールは、トラフィックの監視、ポリシーの適用、認証、RBAC、ルーティング、サーキットブレーカ、メッセージ変換などに使用でき、コンテナオーケストレーションプラットフォームでの通信に役立ちます。一般的なサービスメッシュには、Istio、Linkerd、およびConsul Connectが含まれます。
  • APIゲートウェイ: APIゲートウェイ製品は、マイクロサービスへの呼び出しをインターセプトすることにより、メッセージ変換とプロトコルブリッジング、トラフィックモニタリング、セキュリティ制御、ルーティング、キャッシュ、リクエストスロットリングとAPIクォータ、サーキットブレーカなどの豊富な機能セットを提供します。この分野の著名なプレーヤには、Ambassador、Kong、Apiman、WSO2 API Manager、Apigee、Amazon API Gatewayがあります。
  • サーバレスアーキテクチャ: FaaSパラダイムに従ってサーバレスプラットフォームにサービスをデプロイすることで、コンテナオーケストレーションの複雑さと運用コストの多くを回避できます。AWS Lambda、Azure Functions、Google Cloud Functionsはサーバレスプラットフォームの例です。
  • 監視ツール: オンプレミスとクラウドインフラストラクチャ全体に広がるマイクロサービスでは、システムの正常性に関連する問題を予測、検出、および通知できることが重要です。New Relic、CloudWatch、Datadog、Prometheus、Grafanaなど、利用可能な監視ツールがいくつかあります。
  • ログ統合ツール: マイクロサービスは、デプロイメントユニットの数を容易に1桁増やすことができます。これらのコンポーネントからのログ出力を統合し、アラートを検索、分析、および生成する機能を備えたツールが必要です。この分野で人気のあるツールは、Fluentd、Graylog、Splunk、ELK (Elasticsearch、Logstash、Kibana) です。
  • トレースツール: これらのツールを使用してマイクロサービスを計測し、サービス全体の呼び出しを示すランタイムトレースデータを生成、収集、視覚化できます。ツールは、パフォーマンスの問題を特定するのに役立ちます (アーキテクチャを理解するのに役立つこともあります) 。トレースツールの例は、Zipkin、Jaeger、AWS X-Rayです。
  • DevOps: マイクロサービスは、開発チームと運用チームがインフラストラクチャの構成からインシデントの処理に至るまで、より緊密にコミュニケーションして共同作業を行う場合により適切に機能します。
  • ブルーグリーンデプロイとカナリアリリース: これらのデプロイ戦略により、新しいバージョンのマイクロサービスをリリースするときに、ダウンタイムがゼロまたはほぼゼロになり、問題が発生した場合に迅速にスイッチバックできます。
  • コードによるインフラストラクチャ (IaC): この方法により、ビルド、デプロイサイクルで人の操作を最小限に抑えることができ、より速く、エラーが発生しにくくなり、監査が可能になります。
  • 継続的デリバリー: これは、ソリューションの品質を維持しながら、コミットから展開までの間隔を短縮するために必要な方法です。従来のCI/CDツールには、Jenkins、GitLab CI/CD、Bamboo、GoCD、CircleCI、Spinnakerが含まれます。最近では、WeaveworksやFluxなどのGitOpsツールがCDとIaCを組み合わせてランドスケープに追加されています。
  • 構成の外部化: このメカニズムにより、構成プロパティをマイクロサービスデプロイメントユニットの外部に保存し、簡単に管理できます。

イベント駆動 (Event-Driven)

マイクロサービスアーキテクチャスタイルは、次の3つの一般的なタイプのコネクタのいずれかを使用して通常アクティブ化される (バックエンド) サービスを作成するためのものです:

  • (RESTサービスへの) HTTP呼び出し
  • gRPCやGraphQLなど、プラットフォーム固有のコンポーネント技術を使用したRPCのような呼び出し
  • メッセージブローカのキューを通じた非同期メッセージ

最初の2つは通常同期であり、HTTP呼び出しが最も一般的な代替手段です。多くの場合、サービスは他のサービスを呼び出してサービス構成を形成する必要があり、多くの場合、サービス構成での対話は同期的です。代わりに、キュー/トピックに接続してメッセージを受信するための参加サービスを作成 (または適応) する場合は、イベント駆動型アーキテクチャで作成します (メッセージ駆動型とイベント駆動型の違いについては議論の余地がありますが、Apache Kafka、RabbitMQ、Amazon SNSなどのメッセージブローカ製品によって提供されるキュー/トピックを使用するネットワーク上の非同期通信を表すために、用語を同じ意味で使用します)。
イベント駆動型アーキテクチャの重要な利点は、スケーラビリティとスループットが向上することです。この利点は、メッセージの送信者が応答を待機してブロックされず、同じメッセージ/イベントが複数の受信者によってパブリッシュ/サブスクライブ方式で並行して消費できるという事実から生じます。

イベント駆動マイクロサービス

IDEALSの文字Eは、今日のソフトウェアソリューションのスケーラビリティとパフォーマンスの要件を満たせるだろうイベント駆動型マイクロサービスのモデリングに努めることを思い出させるためのものです。この種の設計は、メッセージの送信者と受信者 (マイクロサービス) が独立しており、お互いについて知らないことで疎結合を促進します。マイクロサービスの一時的な停止の後、キューに入ったメッセージを処理して追いつくことができるため信頼性も向上します。

ただし、リアクティブマイクロサービスとも呼ばれるイベント駆動型マイクロサービスは、困難に見えるかもしれません。処理は非同期にアクティブ化され、並行して行われます。同期ポイントと相関IDが必要になる場合があります。設計では、エラーと失われたメッセージを考慮する必要があります。編集イベント、およびデータ変更を元に戻すためにSagaパターンなどのようなメカニズムが必要になることがよくあります。また、イベント駆動型アーキテクチャによって引き継がれるユーザ向けトランザクションの場合、ユーザエクスペリエンスは、エンドユーザに進捗と障害を通知することを慎重に考える必要があります。

整合性よりも可用性 (Availability over Consistency)

CAPの定理は、基本的に2つのオプションを提供します: 可用性をとるか整合性をとるかです。可用性を選択して結果整合性の確保を可能にするメカニズムを提供するために業界での多大な努力が見られます。その理由は単純です。今日のエンドユーザは可用性の不足に我慢しないでしょう。ブラックフライデイのWebストアを想像してみてください。製品の閲覧時に表示される在庫数と購入時に更新される実際の在庫との間に強い整合性を適用すると、データ変更にかなりのオーバーヘッドが発生します。在庫を更新するサービスに一時的にアクセスできなかった場合、カタログは在庫情報を表示できず、チェックアウトは使用できなくなります。代わりに、可用性を選択した場合 (不定期な不整合のリスクを受け入れる) 、ユーザは少し古くなっている可能性のある在庫データに基づいて購入を行うことができます。数百または数千のトランザクションに1つは、チェックアウト時の不正な在庫情報が原因で、不運なユーザが後でキャンセルされた購入について謝罪する電子メールを受け取ることになります。ただし、ユーザ (およびビジネス) の観点からは、このシナリオは、システムが強力な整合性を強制しようとしてシステムを利用できなかったり、すべてのユーザが非常に遅い処理になるよりも優れています。

一部のビジネスオペレーションには強い整合性が必要です。しかし、Pat Helland氏が指摘するように、あなたがそれを正しくしたいのか、それとも今すぐにしたいのかという疑問に直面したとき、人間は通常、正しいというよりは今すぐに答えを求めています。

結果整合性 (eventual consistency)と可用性

マイクロサービスの場合、可用性を可能にする主な戦略はデータ複製です。異なるデザインパターンを使用することができ、組み合わせることもあります:

  • サービスデータレプリケーションパターン: この基本パターンは、マイクロサービスが他のアプリケーションに属するデータにアクセスする必要がある場合に使用されます (API呼び出しはデータを取得するのに適していません) 。そのデータのレプリカを作成し、マイクロサービスですぐに利用できるようにします。ソリューションには、定期的またはトリガーベースでレプリカとマスタデータの整合性を確保するデータ同期メカニズム (ETLツール/プログラム、パブリッシュサブスクライブメッセージング、マテリアライズドビューなど) も必要です。
  • コマンドクエリ責務分離 (CQRS) パターン: ここでは、データ (コマンド) を変更する操作の設計と実装を、データ (クエリ) のみを読み取る操作と実装から分離します。CQRSは通常、クエリのサービスデータレプリケーションに基づいて構築され、パフォーマンスと自律性が向上しています。
  • イベントソーシングパターン: オブジェクトの現在の状態をデータベースに保存する代わりに、そのオブジェクトに影響を与えた、追加のみの不変 (immutable) のイベントシーケンスを保存します。現在の状態はイベントを再生することで取得され、データの「クエリビュー」を提供するために取得されます。したがって、イベントソーシングは通常、CQRS設計に基づいて構築されます。

次の図は、よく使用するCQRS設計を示しています。データを変更できるHTTP要求は、中央集中型のOracleデータベースで動作するRESTサービスによって処理されます (それでも、このサービスはマイクロサービスごとのデータベースパターンを使用します) 。読み取り専用のHTTPリクエストは、Elasticsearchテキストベースのデータストアからデータを読み取る別のバックエンドサービスに送信されます。Spring Batch Kubernetes cronジョブは定期的に実行され、Oracle DBで実行されたデータ変更に基づいてElasticsearchストアを更新します。このセットアップでは、2つのデータストア間の結果整合性を使用します。クエリサービスは、Oracle DBまたはcronジョブが動作していない場合でも使用できます。

疎結合 (Loose-Coupling)

ソフトウェアエンジニアリングでは、結合は2つのソフトウェア要素間の相互依存度を指します。サービスベースのシステムの場合、求心性 (afferent) 結合は、サービスユーザーがサービスと対話する方法に関連しています。この対話は、サービス契約を通じて行われるべきであることがわかっています。また、契約は実装の詳細や特定のテクノロジーと密接に結びついてはなりません。サービスは、さまざまなプログラムから呼び出すことができる分散コンポーネントです。場合によっては、サービス管理者は、すべてのサービスユーザがどこにいるのかさえ知らないことがあります (多くの場合、パブリックAPIサービスの場合) 。したがって、契約の変更は一般的に避けられるべきです。サービス契約がサービスロジックまたはテクノロジーに密接に結合されている場合、ロジックまたはテクノロジーが進化する必要があるときに変更される傾向があります。

多くの場合、サービスは他のサービスまたは他のタイプのコンポーネントと対話する必要があるため、遠心性 (efferent) 結合が生成されます。この相互作用により、サービスの自律性に直接影響する実行時の依存関係が確立されます。サービスの自律性が低い場合、その動作の予測は難しくなります。呼び出す必要があるサービスで、最も遅く、最も信頼性が低く、最も可用性の低いコンポーネントと同じ速さ、信頼性、可用性になるのが、最良のシナリオです。

サービスの疎結合戦略

IDEALSの文字Lは、サービスつまりマイクロサービスの結合に注意するように促します。 (求心性および遠心性の) 疎結合を促進するために、いくつかの戦略の使用および組み合わせることができます。そのような戦略の例は次のとおりです:

  • ポイント to ポイント、パブリッシュ/サブスクライブ: これらのビルディングブロックメッセージングパターンとそのバリエーションは、送信者と受信者がお互いを認識していないため、疎結合を促進します。リアクティブマイクロサービス (Kafkaコンシューマなど) の契約は、メッセージキューの名前とメッセージの構造になります。
  • APIゲートウェイとBFF: これらのソリューションは、サービス契約とクライアントが確認したいメッセージ形式およびプロトコルとの間の不一致を処理する中間コンポーネントを規定するため、それらを切り離すのに役立ちます。
  • 契約優先設計: 既存のコードとは独立して契約を設計することで、テクノロジーと実装に密接に結びついたAPIの作成を回避します。
  • ハイパーメディア: RESTサービスの場合、ハイパーメディアはフロントエンドがサービスエンドポイントからより独立するのに役立ちます。
  • ファサードとアダプタ/ラッパパターン: マイクロサービスアーキテクチャにおけるこれらのGoFパターンのバリエーションにより、内部コンポーネントや、マイクロサービスの実装全体に広がる望ましくない結合を防ぐことができるサービスを規定できます。
  • マイクロサービス毎のデータベースパターン: このパターンにより、マイクロサービスは自律性を向上させるだけでなく、共有データベースへの直接結合を回避します。

単一責任 (Single Responsibility)

元の単一責任原則(SRP)は、オブジェクト指向クラスにまとまりのある機能を持たせることを目的としています。クラスに複数の責任があると、当然、密結合につながり、進化しにくく、変更時に予期しない方法で壊れる可能性がある脆弱な設計になります。アイデアはシンプルですが、ボブおじさんが指摘したように、SRPは非常に理解しやすい反面、正しく理解するのは困難です。

単一責任という概念は、マイクロサービス内のサービスのまとまりにまで拡張できます。マイクロサービスアーキテクチャスタイルでは、デプロイメントユニットには1つのサービスのみ、またはいくつかのまとまったサービスのみを含める必要があります。マイクロサービスに責任が詰め込まれている場合、つまり、あまりにも多くの非常にまとまりのないサービスが多すぎる場合、それはモノリスの苦痛に耐えるかもしれません。肥大化したマイクロサービスは、機能性とテクノロジースタックの観点から進化が難しくなります。また、多くの開発者が同じデプロイメントユニットに含まれるいくつかの変更部分に取り組んでいるため、継続的デリバリーは困難になります。

一方、マイクロサービスの粒度が細かすぎる場合は、ユーザ要求を満たすためにマイクロサービスのいくつかが対話する必要性が高くなります。最悪のシナリオでは、データの変更がさまざまなマイクロサービスに分散し、分散トランザクションシナリオが作成される可能性があります。

適切な粒度のマイクロサービス

マイクロサービス設計の成熟度の重要な側面は、粗すぎたり細すぎたりしないマイクロサービスを作成できることです。ここでの解決策は、ツールやテクノロジーではなく、適切なドメインモデリングにあります。バックエンドサービスのモデリングとそれらのマイクロサービス境界の定義は、さまざまな方法があります。マイクロサービスの範囲を推進するために業界で一般的になっているアプローチは、ドメイン駆動設計(DDD)の指針に従うことです。簡単に言えば:

  • サービス (RESTサービスなど) は、DDD集約のスコープを持つことができます。
  • マイクロサービスは、DDD境界付けられたコンテキストのスコープを持つことができます。マイクロサービス内のサービスは、境界付けられたコンテキスト内の集約に対応します。
  • マイクロサービス間の通信には、次を使用できます: 非同期メッセージングが要件に適合する場合のドメインイベント。リクエストとレスポンスのコネクタがより適切な場合には、何らかの形式の腐敗防止レイヤを使用してAPIを呼び出す。または、マイクロサービスがすぐに利用できる他のBCからの大量のデータを必要とする場合の、結果整合性を備えたデータ複製。

結論

IDEALSは、最も一般的なマイクロサービス設計で従うべきコア設計原則です。ただし、IDEALSに従うことは、マイクロサービス設計を成功させる魔法の薬や呪文ではありません。いつものように、品質属性の要件を十分に理解し、それらのトレードオフを認識して設計上の決定を行う必要があります。さらに、設計原則の実現に役立つ設計パターンとアーキテクチャ戦略について学ぶ必要があり、利用可能なテクノロジーの選択肢を十分に理解する必要があります。

私はここ数年、マイクロサービスの設計、実装、および展開にIDEALSを採用しています。設計ワークショップと講演では、これらのコア原則とそれぞれの背後にある多くの戦略について、さまざまな組織の数百人のソフトウェア開発者と話し合いました。ときどき、マイクロサービスのツール、フレームワーク、プラットフォーム、およびパターンの地滑りがあるように感じます。マイクロサービスのIDEALSをよく理解すると、テクノロジースペースをより明確にナビゲートできるようになると思います。

これらのアイデアをIDEALSに進化させるのを助けてくれたJoe Yoder氏に感謝します。

著者について

Paulo Merson氏は、30年以上にわたって小規模なプログラミングと大規模なプログラミングを行ってきました。Brazilian Federal Court of Accountsの開発者です。またSoftware Engineering Institute (SEI) の客員科学者であり、Arcituraの認定インストラクタであり、Brasilia大学 (UnB) のApplied Computingの修士プログラムの教員です。Paulo氏は、米国、ラテンアメリカ、ヨーロッパの開発者に専門的なトレーニングを提供することがよくあります。Documenting Software Architectures: Views and Beyond、第2版の共著者です。Paulo氏は、UnBで理学士号を、Carnegie Mellon大学でソフトウェアエンジニアリングの修士号を取得しています。彼はLinkedinStackOverflowStravaで見つかります。

 

この記事に星をつける

おすすめ度
スタイル

BT