FREITAGEEK

FREITAGが好きなエンジニア

Spring Frameworkの@Componentと@Controller,@Service,@Repositoryの違いを調べてみる

Springの@Component, @Controller, @Service, @Repositoryの違いについて気になったので調べてみます。

Stereotype Annotation

@Component, @Controller, @Service, @Repositoryなどは, Stereotypeアノテーションと呼ばれるものです。Stereotypeアノテーションとは、コンポーネントがアプリケーション内でどういう役割を担うかを表現するアノテーションです。 Springでは@Componentが付与されたクラスを、アプリケーション起動時にBeanとしてApplicationContextに登録します。@Controllerや@Service, @Repositoryなどはアノテーション内部で@Componentが付与されているため、@Componentと同じくクラスに付与することで、そのクラスはBeanとしてApplicationContextに登録されます。Stereotypeアノテーションは他にも@RestControllerや@Aspectなどがあります。

Spring Annotation Programming Model · spring-projects/spring-framework Wiki · GitHub

Spring Annotation Programming Model · spring-projects/spring-framework Wiki · GitHub

org.springframework.stereotype (Spring Framework 5.1.7.RELEASE API)

@Controller

@Controllerは、付与したクラスがMVCのコントローラの役割を持つことを表現します。機能面では@Componentと同じです。 @Controllerを使う場合は@RequestMappingや@ResponseBodyと一緒に使うことが多いと思います。ちなみに@ResponseBodyをコントローラクラスの描くメソッドに付与するのが面倒な場合は@RestControllerというstereotypeアノテーションを付与することで、デフォルトで@ResponseBodyアノテーションが各メソッドに付与されます。

Controller (Spring Framework 5.1.7.RELEASE API)

RestController (Spring Framework 5.1.7.RELEASE API)

@Service

@Serviceは、付与したクラスがDDD(ドメイン駆動設計)のサービスの役割、もしくはCoreJ2EEパターンの「ビジネスサービスファサード」の役割を持つことを表現します。裏側の複雑な処理を一つにまとめたシンプルなインターフェースを提供する役割と思ってもらえれば問題ないです。@Controllerと同じく機能面では@Componentと変わりません。Serviceという名前が汎用的なので、チームでどういう役割のときに付与するかは決めておいた方がよいです。

Service (Spring Framework 5.1.7.RELEASE API)

@Repository

@Repositoryは、付与したクラスがDDDのリポジトリの役割を持つことを表現します。また、PersistenceExceptionTranslationPostProcessorクラスをBean として登録することで、@Repositoryを付与したクラスで起きた例外をSpring独自のDataAccessExceptionという非チェック例外に自動で変換してくれます。

Repository (Spring Framework 5.1.7.RELEASE API)

PersistenceExceptionTranslationPostProcessor (Spring Framework 5.1.7.RELEASE API)

DataAccessException (Spring Framework 5.1.7.RELEASE API)

ロバストネス分析について

最近はドメインモデリングやコンテキストマッピングなどDDDの文脈で言う所の戦略的設計の具体的な取り組み方がよくわかっていないので、「ユースケース駆動開発実践ガイド」(以下リンク参照)を読んでいます。

ユースケース駆動開発実践ガイド (OOP Foundations)

ユースケース駆動開発実践ガイド (OOP Foundations)

今回はその中で紹介されている、ロバストネス分析について、どういうものか、なぜやるのか、どうやってやるのか、を自分の頭の整理も兼ねて書いていきたいと思います。

ロバストネス分析とは?

ロバストネス分析とは、システムのユースケースを記述した文章を基に、オブジェクトを用いた図(ロバストネス図)を作成する作業です。 ロバストネス分析を行うことによって、ユースケースを記述した文章からクラス図やシーケンス図といったUML静的モデルが作りやすくなります。

ロバストネス分析をなぜやるのか?

ロバストネス分析を行う目的は主に3つあります。

第一に、静的モデルを作りやすくすることです。書籍に詳しく解説されていますが、ロバストネス分析ICONIXプロセスというソフトウェア開発プロセスの中で使われています。ICONIXプロセスでは、ドメインモデリングユースケース作成 → ロバストネス分析UML静的モデリング→...という流れで開発をしていくので、ロバストネス分析が終わった段階でUML静的モデリングがしやすくなっていることが重要です。そのため、ロバストネス図にはユースケースが漏れなく表現されていることが要求されます。

第二に、ユースケースの記述から曖昧さをなくすことです。ロバストネス図を作成していると、うまくオブジェクトでユースケースで表現できないときや、作成したロバストネス図ユースケースを比較すると微妙に異なる表現をしているときが出てくるときがあります。こういうときは、ユースケースの記述を見直して、書き方に問題がないかをチェックします。こういったチェックをしてユースケースの記述から曖昧さをなくすことで、実際にシステムを実装した後の仕様の抜けや漏れを減らすことに繋がっていきます。

第三に、見逃していたドメインオブジェクトを発見することです。第二のユースケースの記述から曖昧さをなくすことと同様、ロバストネス図を作成していると、ユースケースの記述にはなかった語彙や概念が出てくることがあります。新しい語彙が出てきたときやより的確に表現する語彙が出てきたときは、その語彙をユビキタス言語としてドメインモデルに反映させます。こうすることで、ソフトウェアと実際の業務で使われている語彙のズレを無くしていき、メンバー同士、チーム同士の認識の齟齬が起きないようにしていきます。

ロバストネス図の作り方

ロバストネス図で登場するオブジェクト

ロバストネス図は以下の4種類のオブジェクトを使って、ユースケースを表現していきます。

  • アクター

  • バウンダリオブジェクト

  • エンティティオブジェクト

  • コントローラ

アクター

システムと対話をするオブジェクト(人間, 外部システム)です。例えば、「ユーザ」です。 アクターの名前は必ず名詞を使うようにします。 表記はUMLユースケース図と同じように棒人間で表現します。

f:id:dais39:20190519150822p:plain

バウンダリオブジェクト

システム外部との境界を表現するオブジェクトです。例えば、「ログインページ」や「申請ページ」です。 バウンダリオブジェクトの名前は必ず名詞を使うようにします。 バウンダリオブジェクトは以下のように表記します。

f:id:dais39:20190519150908p:plain

エンティティオブジェクト

ドメインモデルを表現するオブジェクトです。例えば、「アカウント情報」や「申請情報」です。 エンティティオブジェクトの名前は必ず名詞を使うようにします。 エンティティオブジェクトは以下のように表記します。

f:id:dais39:20190519151414p:plain

コントローラ

ソフトウェアの機能を表現するオブジェクトです。例えば「ID, パスワードをチェックする」「申請情報の入力チェックをする」です。 コントローラの名前は必ず動詞を使うようにします。 コントローラは以下のように表記します。

f:id:dais39:20190519151631p:plain

ロバストネス図を書いていく

書籍では他にもいくつかルールやTipsが紹介されていたのですが、まずは以下のルールや方針に則って書いていくことをおすすめします。

実際にユースケースロバストネス分析で簡単に表現したものが以下になります。

f:id:dais39:20190519154724p:plain

この例では、「Actorはログインページにアクセスする。Actorはログイン情報としてIDとパスワードを入力してログインボタンをクリックする。システムはIDとパスワードをチェックして、問題なければTOPページを表示する。ログインに失敗した場合はエラーメッセージとともにログインページを表示する。」というユースケースロバストネス図として表現してみました。

おわりに

今回はロバストネス分析について、どういうものか、なぜやるのか、どうやってやるのか、について書籍を読んで学んだことをまとめてみました。 実際にロバストネス図から静的モデルを作成するところは、まだよくわかっていないので、これからやっていきたいと思います。おわり。

「経産省と本気でアジャイル開発をやってみた!〜」 参加レポート

先日、「経産省と本気でアジャイル開発をやってみた!制度ナビPJで見えたGovTechのリアルと未来」というイベントに参加してきたので、イベントの様子や参加して感じたことを書き連ねていきたいと思います。

議事録のようなものではなく、あくまで登壇者の発表を聞いて感じたことを一個人が書いているエントリなのでそこは、ご理解ください。また聞き逃しや勘違いをしている箇所があるかもしれないので、その場合はコメントで指摘していただけると助かります。

イベントの雰囲気

  • 主催はCode for Japanさん
  • 会場は経産省の地下2F
  • 約250名参加
    • 会場のアンケートでは参加者の割合では開発者の方が多かった
    • 省庁関係者の方らしき人もたくさんいたように感じた

挨拶&Code for Japan紹介

  • Code for Japan代表理事 関 治之 さんによる発表
  • イベント全体で質問したいことはslido.jpを使って集約
  • 今回のイベントは、以下のテーマを発表
  • このイベントの目的
  • Code For Japanとは
  • なぜ行政にアジャイルが必要か?
    • 完璧な仕様は書けない
    • プロジェクトが失敗したときのリスクが大きい
    • 異動が前提
    • デジタル化についての経験値が浅い
  • なぜ行政でアジャイルが難しいか?
    • 年度単位の予算
    • 知識不足
    • 受発注者間の信頼関係構築の難しさ
    • 失敗を忌避する文化

スマート公共サービス官民協議会から見えてきたこと

  • Code for Japan理事、前総務省大臣補佐官 太田 直樹 さんによる発表
  • 太田さんのブログで発表
  • スマート公共サービス官民協議会
    • 未来投資会議の一つ
      • 6月の未来投資戦略のための会議
      • 未来投資戦略によって次年度の予算が決まるため未来投資会議は重要
  • スマート公共サービス

    • GovTech
    • 公民の連携
    • データのオープン化
    • API連携の整備
    • LGWAN問題
      • 10年前は省庁のインターネットが遮断されていたらしい
    • 会津若松, 益田市, 加古川市などの官民連携事例
      • 行政の外にDBがあって公民連携
      • 同意した利用者のデータを集めている(オプトイン)
      • このデータをベースにサービスを作っている
      • 官民連携すればよい行政サービスが作れるのではないか?
    • 自治体向けアプリマーケットの事例
      • アプリの開発者と利用者の密なコミュニケーションを実現するため自治体向けアプリマーケットというものを作った
      • 残念ながらオープンデータを作るのは自治体だけど、活用するのは民間にお任せという考えを持っている人もいる
  • 失敗を通して組織の垣根を超えて学んでいくことが重要

経産省DXの取り組み

  • 経済産業省情報プロジェクト室 室長補佐 吉田 泰己 さんによる発表
  • 行政サービスと民間サービスの質の差が見過ごせなくなってきた
  • デジタルトランスフォーメーションという取り組みを行なっている
  • 解決したい問題
    • 国民、事業者にとって不便なサービス
    • 職員の業務効率が非効率
  • ユーザ中心のサービス作り
  • 優れたUI/UXからデータが集まるという認識
  • ビズリーチを使いながら民間から人材を集めてデジタル化を進めている
  • アジャイル支援を行っているベンダーと一緒にものを作っている
  • tableauを使ってデータ分析をしている
  • 認証やデータの連携基盤を標準化し、サービス間で利用できるようにする
  • 目指すこと
    • UI/UXの整備
    • データ分析基盤の整備
    • 行政サービスを民間と同じ水準に

制度ナビPJ紹介&デモンストレーション

  • 経済産業省中小企業庁 松原 匠 さんによる発表
  • なぜ制度ナビを作ったか
    • 職員でも適切な情報を探せる気がしなかったから笑
    • 電話帳みたいなガイドブック
    • ミラサポという既存のwebサービス
      • 施策マップがユーザの要求を満たす機能ではなかった
      • ユーザ目線になっていない
  • 制度ナビ
    • メール通知ではなくプッシュ通知
    • 補助金の人気はある程度固まっている
    • 検索結果の表示(ページング)
  • 導入したアジャイルプロセス
  • 3つの制度の問題
    • 定義の違い
      • 制度や法律によって定期が異なる
      • 定義があいまい
      • 説明を読んでも補助金の対象化わからない
    • 補助金リテラシー問題
      • 補助金交付要項分厚過ぎる
      • ルールが複雑
      • 毎年変わる
    • アプリの実証に使えるデータがない
      • データのフォーマットがなく組織ごとに独自フォーマット
      • 委託していて役所がデータを持っていないケースも
  • どうやって改善してくか
    • 行政の担当者の意識改善
    • 利用者から不便を訴えていく
      • 行政はなるべく手間をかけずにサービスを作っている

民間から見た行政のサービス開発

  • ギルドワークス株式会社 代表取締役 市谷 聡啓 さんによる発表

    www.slideshare.net

  • 今回のプロジェクトでは以下の3つの役割で動いた

    • マネジメント, PO支援, スクラムマスター
    • ここからすでに怪しげな雰囲気が感じられる笑
  • 発表のテーマは「現実対越境」
    • 案件はミラサポのリニューアル
    • 行政側がアジャイル開発をしたいということで今回支援にはいった
    • アジャイル開発への暗黙的な期待が感じられた
      • スプリントの空振り
      • 最終スプリントで浮き上がるこれじゃない感
    • まずアジャイル開発をなぜするのか、目指す状態を理解
    • その上で本当に期待と現実があっているのか?を考えた 「提案してー」でもなく「やってきてー」でもなく「自分たちで(も)やる」
    • 大きな問題
      • プロダクトの「全体感欠如」
        • 今回のミラサポ案件はアプリが3つにわかれている
        • ユーザの体験が3つのアプリに分断されてしまう
        • ユーザの統一的なUX設計ができない状態
      • データの境界は「組織の境界」
        • データが組織ごとにバラバラで管理されていたり、そもそもデータがない場合があった
        • データを揃えるのはスケジュール的に到底不可能
    • 現状維持の文化, 流れに立ち向かうには関係者全員が探索的にならないといけない
    • 上であげた2つの大きな問題を解決するのは体制と時間的に困難
    • 自分たちだけでできないのであればユーザを巻き込む
    • 3アプリ合同でユーザテスト実施
  • アジャイルのやり方を学ぶのではなく、なぜやるのかを考えることが大事
  • 「正しいものを正しく作る」という本を出します

民間による行政サービスのアジャイル開発

  • 株式会社グラファー 代表取締役 石井 大地 さんによる発表
  • 民間企業が行政サービスを開発する話
  • Graffer
    • 面倒な行政手続きをシンプルなUI/UXで提供するサービスを提供する企業
      • 46000種類の行政の手続き
    • Grafferは紙, API, スクレイピングで行政と連携
    • サービスは3.5人(0.5は代表の石井さん分)で開発
    • コンセプトを深く議論して〜というサービス開発ではなく、まず作ってみる。作った上で改善を加えていく。というやり方を取っている。
  • 技術力ではなく組織の文化が重要
  • アジャイルプロセスを取り入れたからといってうまくいくわけではない

パネルトーク①「行政は使いやすいデジタルサービスを作れるのか?」

  • 関さん, 松原さん, 林 大輔さん(経済産業省デジタル化推進マネージャ), 市谷さん, 平本 健二さん(内閣官房政府CIO上席補佐官/経済産業省CIO補佐官) によるパネルトーク
  • sli.doの質問に答えるタイム
    • 行政でコラボレーションツールはつかっている?
      • 部署によるがSlackやBackLogを使っているところもある
    • 組織を動かす, 説得するコツは?
      • 利用者視点と対案を用意する
      • 関係者としてプロジェクトに巻き込む
      • 当事者意識を芽生えさせる
      • ワークショップを開く
      • 手を動かす、頭を動かす機会を作る
    • アジャイルの納品っていつ?
      • 納品する側とされる側で優先度をすり合わせて決める
      • トレードオフスライダーを使った
    • 請負契約ではなく準委任契約でやったのか?
      • 準委任契約でやった
      • 準委任契約だが、準委任契約をそのままやるとうまくいかないので請負契約的なことをやった?
    • チャレンジングな取り組みを他に行なっているのか?
  • 行政は使いやすいデジタルサービスを作れるのか?
    • アジャイル開発を取り入れて開発のプロセスは改善できた
    • UXの改善はまだあまりできていないので今後重要なテーマ
    • アナログなプロセスを改善するシステムを目指して、そこからデジタルなものづくりを目指す
    • ユーザの立ち位置に立ってものづくりを考える
    • 行政の中でPdMが不足していることは深刻な問題
      • 人を管理するProjectManagerはいるが、サービスを管理するProductManagerがいない
      • ユーザ視点に立ってものづくりを考える役割を増やしていく
  • トライアルでアジャイル開発をやってきたが今後どのようなプロセスでミラサポを作っていくか?
    • まずはデータの整備
    • PdMを引き継いで部署横断で進めていく
  • 今後行政としてどうやってサービスを作っていくか?
    • 今までは大手ベンダーと連携をとっていくことが多かった
    • 今回新しい取り組みをしている企業と連携を取って新しいことをした
    • これをさらに大人数でやっていきたい

パネルトーク②「民間事業者と考える行政サービスの未来」

  • 吉田さん, 平本さん, 石井さん, 木村 康宏さん(freee株式会社 執行役員)によるパネルトーク
  • こういうAPIがあるといいなというのはある?
    • WebブラウザでできることはAPIで全部できるようにしてほしい
    • 行政プロジェクトにアサインしてエンジニアから不満が出ないような環境を用意してほしい
  • APIをどうやって作っていいのかわからない
    • APIを作ってください、というの要求になってしまっているのが現状
    • APIを作るためのレビュー環境を整えることが重要
    • アメリカではGitHubで仕様書を管理
  • 既存の窓口はユーザインターフェースとしてもっと重要視していいと思うが、現場との距離感はどう取り組んでるか?
    • 現状使われているところでもっと簡単に使えるようにするということが大事
      • データフォーマットの整備
      • 豊富なAPIの提供
    • ただ、行政としても最低限の窓口は持つ必要がある
    • メモ: 国としてはプラットフォームとして民間にデータを提供することに注力していきたいということなんだろうか?
  • 行政の評価の仕組みはどうなっているのか?
    • 行政内外でどれだけコストを減らせたのか(KPI)
    • サービスの利用率(KPI)
    • 正しい失敗を許容して評価していかないといけない
    • そのためには国民も正しい失敗を許容することを理解しないといけない
    • KPIを達成すれば適切な報酬が与えられるためには、公務員も人事制度改革をしていかないといけない
  • アジャイル開発を行う場合の契約どうしたらいい?
    • アジャイル開発用の契約書の雛形みたいなものがあればよい
    • 別の省庁で雛形について議論する機会があった
    • 経産省の今回のプロジェクトが支援をしていく必要がある
  • 行政サービスの未来を考える上で行政側に期待することは?
    • 失敗談を赤裸々に外部に公開してほしい
    • 届きにくい部署に、失敗してもいい文化がある、ということを届かせることが大事
  • サービス利用の契約をしやすくしてほしい

「なぜ、あなたの仕事は終わらないのか」を読んだメモ

以下メモです。

  • 8:2を意識する

    • 10日間だったら最初の2日間で8割終わらせるつもりで取り組む

    • できなかったら締め切りを伸ばす

    • あと8日間は「流し」

    • 残りの完成度を高める

  • モックアップをまず作る

    • アプリの更新と同じ

    • 最初から100%は作れない

    • 修正を繰り返す

  • 1日の仕事は午前中にほぼ終わらせる

  • 長期の仕事は10-14日単位で分けて取り組む

  • マルチタスクはしない

  • 並行した仕事がある時は1日の中で時間を分配して取り組む

  • 人の仕事は遅れるもの

  • 仮眠を取る

  • 花屋のエピソード

    • 「花をパーティーのために用意する」事が仕事

    • 「花屋にパーティーのための花を予約する事」が仕事なのではない

  • 問題を分割して考える

  • 崖から飛び降りながら飛行機を組み立てるつもりで行動する

  • 寝る前にタスクリスト作る

IntelliJのLanguage Injectionsを使ってみる

今回はIntelliJのLanguage Injectionsという機能を使ってみたいと思います。 IntelliJの細かい設定や操作の詳細は公式ドキュメントを参考してください。

Language injections - Help | IntelliJ IDEA

Language Injectionsとは

Language Injectionsとは、文字列の中でJSON,やSQLなどの言語を記述する際に、文法チェックや補完などをIDEがおこなってくれたり、文字列の中の言語をより書きやすくしてくれる機能です。

Language Injectionsを使わない場合

例えば文字列の中でJSONを記述しようとすると、以下のようにダブルクオーテションをエスケープしながら記述する必要があるのですが、これを手で書いていくのはなかなかつらいと思います。

f:id:dais39:20190508214540p:plain

また、以下のようにJSONの文法エラーとなるような記述をしても、文字列として扱われるためIDEはエラーと認識しません。

f:id:dais39:20190508215138p:plain

Language Injectionsを有効にするとこういった不便な問題を解決することができます。

Language Injectionsを使った場合

まず、空の文字列を記述して、カーソルを文字列に合わせた状態でalt + returnを押して、以下を表示させます。

f:id:dais39:20190508215349p:plain

Inject language or referenceをクリックして、JSONを選択します。

f:id:dais39:20190508215630p:plain

もう一度文字列にカーソルを合わせてalt + returnを押すと、Edit JSON Fragmentが表示されるのでクリックします。

f:id:dais39:20190508215851p:plain

クリックすると、JSON Fragementというviewが表示されます。そこに生のJSONを記述すると、実際のコードの文字列の中でも自動的にダブルクオーテーションがエスケープされた状態でJSONが同時に記述されます。

f:id:dais39:20190508220324p:plain

また、この状態で文字列の中にJSONの文法エラーとなるような記述を書くと以下のようにIDEがエラーを表示してくれるのでとても便利です。

f:id:dais39:20190508220512p:plain

おわりに

今回はJSONのケースを紹介しましたが、SQLでは候補予測や補完が有効になったり、他にもxmlyaml, JPAのJPQLやJiraのJQLなど様々な言語に対応しているので、ぜひ試してみると良いと思います。

競技プログラミングを始めてみました

エンジニアとして開発業務をおこなっていく中で、アルゴリズムやデータ構造を考慮して実行速度などをほとんど意識せずにプログラムを書いてしまっているなー、と最近危機感を持ち始めたので勉強もかねて競技プログラミングを始めてみました。

まず、大学の講義の復習も兼ねて以下2冊を購入して基本的な知識を復習していきました。2冊とも気軽に空き時間に読むことができるので、リスト, 木, グラフなどのデータ構造や、ソートなどのアルゴリズムの基本を復習するのにはとても役に立つ本です。

Java データ構造とアルゴリズム基礎講座

Java データ構造とアルゴリズム基礎講座

アルゴリズム図鑑 絵で見てわかる26のアルゴリズム

アルゴリズム図鑑 絵で見てわかる26のアルゴリズム

さすがに上記の本だけだと学生の授業のおさらいで終わってしまうので、学生の頃に登録だけして放置されていたAtCoderの問題を最近は解いています。今は、以下のdrkenさんのQiitaの記事や、過去問サイト(AtCoder Problems)を参考に「動的計画法」や「累積和」,「尺取り法」などを絶賛勉強中です。

qiita.com

qiita.com

自分の今の実力はAtCoderのABCのD問題が解けるか解けないかという辺りなので、コンテストに定期的に参加して半年後にAtCoder水を目指してこれから頑張っていきたいと思います。

おしまい。

Kotlinのスコープ関数のユースケースをまとめてみる

Kotlinのスコープ関数について公式ドキュメントを参考に特徴とユースケースをまとめてみます。公式のドキュメントがとてもわかりやすくまとまっているので、詳細はそちらを参考にしてください。Kotlinのversionは1.3.21です。

let

public inline fun <T, R> T.let(block: (T) -> R): R
  • レシーバオブジェクトをラムダの引数(it)として参照する。
  • ラムダの結果を返す

ユースケース

nullチェック

// letを使わない場合
val number: Int? = 1
if(number != null) println(number)

// letを使う場合
val number: Int? = 1
number?.let { println(it) }

メソッドチェーンの結果に対して関数を使いたい場合

// letを使わない場合
val list = listOf("one", "two", "three")
val result = list.map { it.toUpperCase() }.filter { it != "three" }
println(result)

// letを使う場合
val list = listOf("one", "two", "three")
list.map { it.toUpperCase() }.filter { it != "three" }.let { println(it) }

メソッドチェーンの途中結果を読みやすい名前に変換したい場合

// letを使わない場合
val list = listOf("alice", "bob", "chris")
val person = list.first()
println(person.toUpperCase())

// letを使う場合
val list = listOf("alice", "bob", "chris")
val result = list.first().let { person ->
  println(person.toUpperCase())
}

apply

public inline fun <T> T.apply(block: T.() -> Unit): T
  • レシーバオブジェクトをthisとして参照する
  • レシーバオブジェクトを返す

ユースケース

オブジェクトの設定をする場合

// applyを使わない場合
val datasource = SampleDataSource()
datasource.url = ""
datasource.username = ""
datasource.password = ""

// applyを使う場合
val datasource = SampleDataSource().apply{
  // オブジェクトの設定
  url = ""
  username = ""
  password = ""
}

with

public inline fun <T, R> with(receiver: T, block: T.() -> R): R
  • レシーバーオブジェクトthisとして参照する
  • ラムダの結果を返す
  • 拡張関数としてではなく引数としてレシーバーオブジェクトを受け取る

ユースケース

プロパティやメソッドへのアクセスを簡潔にしたい場合

// withを使わない場合
println(datasource.url)
println(datasource.username)
println(datasource.password)

// withを使う場合
with(datasource){
  println(url)
  println(username)
  println(password)
}

run

public inline fun <R> run(block: () -> R): R 
public inline fun <T, R> T.run(block: T.() -> R): R
  • オブジェクトをレシーバーオブジェクトthisとして参照する
  • ラムダの結果を返す

ユースケース

オブジェクトの初期化と、オブジェクトを使った計算を返す処理をまとめて行いたい場合

// runを使わない場合
val datasource = DataSource()
datasource.url = ""
datasource.username = ""
datasource.password = ""
val result = datasource.fetch()

// runを使う場合
val result = DataSource().run{
  // オブジェクトの設定
  url = ""
  username = ""
  password = ""
  // オブジェクトの処理を実行
  fetch()
}

ローカル変数と処理を1つにまとめて名前をつけたい場合

// runを使わない場合
val schema = "https://"
val hostname = "localhost"
val port = ":8080"
val path = "/"
val url = schema + hostname + port + path

// runを使った場合
val url = run{
  val schema = "https://"
  val hostname = "localhost"
  val port = ":8080"
  val path = "/"
  schema + hostname + port + path
}

also

public inline fun <T> T.also(block: (T) -> Unit): T
  • レシーバオブジェクトをラムダの引数(it)として参照する
  • レシーバオブジェクトを返す

ユースケース

ログ出力やデバッグなどオブジェクトに変更を与えない処理を追加/削除したい場合

// alsoを使わない場合
val list = mutableListOf(1, 2, 3)
println(list)
list.add(4)
println(list)

// alsoを使った場合
val list = mutableListOf(1, 2, 3)
list.also { println(it) }
    .add(4)
    .also { println(it) }

最後に

スコープ関数のユースケースについて公式ドキュメントを参考にまとめてみました。 公式ドキュメントにも書いてある通り、スコープ関数をネストさせたり、むやみにスコープ関数をメソッドチェーンしすぎると、itやthisが乱立してしまい、読みづらいコードになってしまうので注意が必要です。

参考資料

https://kotlinlang.org/docs/reference/scope-functions.html#scope-functions