CINXE.COM
O'Reilly Japan - ドメイン駆動設計をはじめよう
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <title>O'Reilly Japan - ドメイン駆動設計をはじめよう</title> <link rel="stylesheet" type="text/css" href="/assets/css/font-face.css"> <link rel="stylesheet" type="text/css" href="/assets/css/layout.css"> <link rel="stylesheet" type="text/css" href="/assets/css/layout-books.css"> <link rel="icon" type="image/png" href="https://www.oreilly.com/favicon.ico"> <meta name="format-detection" content="telephone=no"> <meta property="og:title" content="ドメイン駆動設計をはじめよう" /> <meta property="og:type" content="article" /> <meta property="og:image" content="https://www.oreilly.co.jp/books/images/picture_large978-4-8144-0073-7.jpeg" /> <meta property="og:image:secure_url" content="https://www.oreilly.co.jp/books/images/picture_large978-4-8144-0073-7.jpeg" /> <meta property="og:url" content="https://www.oreilly.co.jp/books/9784814400737/" /> <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:site" content="O'Reilly Japan" /> <meta name="twitter:creator" content="oreilly_japan" /> <link href="http://www.oreilly.co.jp/sales/atom.xml" type="application/atom+xml" rel="alternate" title="Sales Information" /> <meta property="og:description" content="ドメイン駆動設計はエリック・エヴァンスにより提唱されたソフトウェア設計の手法です。対象とする事業活動(ドメイン)とその課題の観点から、より良いソフトウェアを構築するために関係者が協力する方法を提供します。本書は4部構成になっており、第Ⅰ部「設計の基本方針」では、ソフトウェアの設計方針を大きな視点から決めるための考え方とやり方を取り上げます。第Ⅱ部「実装方法の選択」ではソースコードに焦点を合わせ、業務ロジックをどう実装するかの選択肢を学びます。第Ⅲ部「ドメイン駆動設計の実践」では、ソフトウェア開発の現場にドメイン駆動設計を実践的に取り入れるための方法を紹介します。第Ⅳ部「他の方法論や設計技法との関係」では、ドメイン駆動設計とそれ以外の方法論や設計技法との関係を検討します。最新の技術トレンドを取り入れながら、ドメイン駆動設計の基本概念と実践方法をわかりやすく解説します。" /> <link rel="canonical" href="https://www.oreilly.co.jp//books/9784814400737/" /> <link rel="amphtml" href="https://www.oreilly.co.jp//books/9784814400737/mobile.html"> <!-- Google Tag Manager --> <script>(function (w, d, s, l, i) { w[l] = w[l] || []; w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' }); var f = d.getElementsByTagName(s)[0], j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : ''; j.async = true; j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl; f.parentNode.insertBefore(j, f); })(window, document, 'script', 'dataLayer', 'GTM-KR9JFVC');</script> <!-- End Google Tag Manager --> <!-- Global site tag (gtag.js) - Google Analytics --> <script async src="https://www.googletagmanager.com/gtag/js?id=G-M7QE72H4KS"></script> <script> window.dataLayer = window.dataLayer || []; function gtag() { dataLayer.push(arguments); } gtag('js', new Date()); gtag('config', 'G-M7QE72H4KS'); </script> <style> .collapsible { background-color: white; border: 0; border-bottom: 1px solid rgb(246, 246, 246); margin: 0; padding: 0; cursor: pointer; width: 100%; text-align: left; outline: none; font-size: 1.5rem; font-weight: 700; line-height: 1.5em; } .collapsible:after { content: '\02795'; /* Unicode character for "plus" sign (+) */ font-size: 1.0rem; margin-left: 5px; float: right; } .collapsible-active:after { content: "\2796"; /* Unicode character for "minus" sign (-) */ } .collapsible:hover { box-shadow: 2px0 4px 8px rgb(0, 0, 0, .1); transition: box-shadow .2s; cursor: pointer; } .collapsible+section { padding: 0; margin-bottom: 30px; background-color: white; max-height: 0; overflow: hidden; transition: max-height 0.05s ease-out; } </style> </head> <body> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-KR9JFVC" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <div id="skipToMain" class="nav__SkipToMain"><a href="#maincontent">Skip to main content</a></div> <header role="banner" class="nav__GlboalHeader"> <div class="pageWidth"> <nav role="navigation" aria-label="site sections" class="nav__GlobalNav"> <a aria-current="page" title="Go to home page" class="nav__Logo" href="/"><img src="/assets/images/logo_oreilly_japan.svg" alt="O'Reilly logo"></a> <div class="nav__NavItems" id="nav__NavItems"> <div class="nav__NavGroup"> <a class="nav__Link" href="/blog/">Blog</a> <a class="nav__Link active" href="/catalog/">Books</a> <a class="nav__Link" href="/ebook/">Ebooks</a> <a class="nav__Link" href="/online-learning/">Learning platform</a> <a class="nav__Link" href="/order/">Order</a> <a class="nav__Link" href="/company/">About</a> </div> <div class="nav__CTA"> <a href="/ebook/cart" class="nav__Cart">Cart</a> </div> </div> <button id="nav__MobileBtn" aria-expanded="false" aria-controls="menuList" class="nav__MobileBtn"><span><span></span></span></button> </nav> </div> </header> <main id="maincontent"> <div class="pageWidth"> <h1 itemprop="name"> ドメイン駆動設計をはじめよう </h1> <p class='sub_title'> ―ソフトウェアの実装と事業戦略を結びつける実践技法</p> <span itemprop="publisher" content="オライリー・ジャパン"></span> <div class="contributers"> <span itemprop="author"> Vlad Khononov 著、増田 亨、綿引 琢磨 訳 </span> </div> <section class="detail" itemscope itemtype="http://schema.org/Book"> <div class="detail-cover"> <img src="https://www.oreilly.co.jp/books/images/picture_large978-4-8144-0073-7.jpeg" class="cover-photo" alt="[cover photo]" /> </div> <dl class="item-props"> <dt>TOPICS</dt> <dd> </dd> <dt>発行年月日</dt> <dd itemprop="datePublished" content="2024-07-20"> 2024年07月 </dd> <dt>PRINT LENGTH</dt> <dd itemprop="numberOfPages"> 408 </dd> <dt>ISBN</dt> <dd itemprop="isbn"> 978-4-8144-0073-7 </dd> <dt>原書</dt> <dd><a href="https://learning.oreilly.com/library/view/learning-domain-driven-design/9781098100124/"> Learning Domain-Driven Design </a></dd> <dt>FORMAT</dt> <dd> Print PDF EPUB <div class="buying-options"> <div class="option-item"> <div class="option-name">Ebook</div> <div> 3,960円 </div> <a href="/ebook/cart?id=978-4-8144-0073-7&mode=add" class="update-button secondary-button"> Ebookを購入する </a> </div> <div class="option-item"> <div class="option-name">Print</div> <div> 3,960円 </div> <div class="link-book-order">書籍のご注文は<a href="https://www.ohmsha.co.jp/book/9784814400737/">オーム社サイト</a>へ </div> </div> </div> </dd> </dl> <div id="detail" class="content"> <p itemprop="description"> ドメイン駆動設計はエリック・エヴァンスにより提唱されたソフトウェア設計の手法です。対象とする事業活動(ドメイン)とその課題の観点から、より良いソフトウェアを構築するために関係者が協力する方法を提供します。本書は4部構成になっており、第Ⅰ部「設計の基本方針」では、ソフトウェアの設計方針を大きな視点から決めるための考え方とやり方を取り上げます。第Ⅱ部「実装方法の選択」ではソースコードに焦点を合わせ、業務ロジックをどう実装するかの選択肢を学びます。第Ⅲ部「ドメイン駆動設計の実践」では、ソフトウェア開発の現場にドメイン駆動設計を実践的に取り入れるための方法を紹介します。第Ⅳ部「他の方法論や設計技法との関係」では、ドメイン駆動設計とそれ以外の方法論や設計技法との関係を検討します。最新の技術トレンドを取り入れながら、ドメイン駆動設計の基本概念と実践方法をわかりやすく解説します。 </p> </div> <h2 class="collapsible">正誤表</h2> <section> <p> ここで紹介する正誤表には、書籍発行後に気づいた誤植や更新された情報を掲載しています。以下のリストに記載の年月は、正誤表を作成し、増刷書籍を印刷した月です。お手持ちの書籍では、すでに修正が施されている場合がありますので、書籍最終ページの奥付でお手持ちの書籍の刷版、刷り年月日をご確認の上、ご利用ください。 </p> <h3> 第1刷正誤表 </h3> <div class="errata"> 2024年10月更新<br> <br> ■P.7 カラスアイコンの説明3行目<br> 【誤】業務業域<br> 【正】業務領域<br> <br> ■P.43 図3-3の右の図<br> 【誤】販売の文脈<br> 【正】営業の文脈<br> <br> ■P.76 コード<br> 【誤】 <pre><code>DB.StartTransaction(); var job = DB.LoadNextJob(); var json = LoadFile(job.Source); var xml = ConvertJsonToXml(json); WriteFile(job.Destination, xml.ToString(); DB.MarkJobAsCompleted(job); DB.Commit() </code></pre> 【正】 <pre><code>DB.StartTransaction(); var job = DB.LoadNextJob(); var json = LoadFile(job.Source); var xml = ConvertJsonToXml(json); WriteFile(job.Destination, xml.ToString()<font color="red">)</font>; DB.MarkJobAsCompleted(job); DB.Commit()<font color="red">;</font> </code></pre> </div> </section> <h2 class="collapsible">目次</h2> <section> <div id="toc"> <pre>訳者まえがき 推薦の言葉 序文 この本について はじめに 第Ⅰ部 設計の基本方針 1章 事業活動を分析する 1.1 事業領域(ビジネスドメイン)とは何か 1.2 業務領域(サブドメイン)とは何か 1.2.1 業務領域を分類する 1.2.2 業務領域を比較する 1.2.3 業務領域の境界を明確にする 1.3 事業分析の具体例 1.3.1 ライブチケット社 1.3.2 バス・オンデマンド社 1.4 業務エキスパート 1.5 まとめ 1.6 演習問題 2章 業務知識を発見する 2.1 事業の課題 2.2 知識の発見 2.3 意図の伝達 2.4 「同じ言葉」とは何か? 2.5 業務で使う言葉 2.5.1 同じ言葉の使い方 2.5.2 一貫性 2.6 事業活動のモデル 2.6.1 モデルとは何か 2.6.2 効果的なモデル 2.6.3 事業活動のモデルを作る 2.6.4 継続的に取り組む 2.6.5 道具の利用 2.6.6 困難に立ち向かう 2.7 まとめ 2.8 演習問題 3章 事業活動の複雑さに立ち向かう 3.1 異なるモデルの混在 3.2 区切られた文脈とは何か 3.2.1 文脈の境界 3.2.2 同じ言葉の定義(改良版) 3.2.3 区切られた文脈の大きさをどうするか 3.3 区切られた文脈と業務領域の関係 3.3.1 業務領域 3.3.2 区切られた文脈 3.3.3 業務領域と区切られた文脈の対応 3.4 文脈の境界 3.4.1 物理的な境界 3.4.2 所有権の境界 3.5 現実世界の区切られた文脈 3.5.1 言葉の意味論 3.5.2 科学 3.5.3 冷蔵庫を買った時の話 3.6 まとめ 3.7 演習問題 4章 区切られた文脈どうしの連係 4.1 緊密な協力 4.1.1 良きパートナー 4.1.2 モデルの共有 4.2 利用者と供給者の関係 4.2.1 従属する関係 4.2.2 モデル変換装置 4.2.3 共用サービス 4.3 互いに独立 4.3.1 意思疎通の問題 4.3.2 一般的な業務領域 4.3.3 モデルの違い 4.4 文脈の地図 4.4.1 最新の状態を維持する 4.4.2 限界 4.5 まとめ 4.6 演習問題 第Ⅱ部 実装方法の選択 5章 単純な業務ロジックを実装する 5.1 トランザクションスクリプト 5.1.1 実装方法 5.1.2 それほど単純な話ではない 5.1.3 トランザクションスクリプトをいつ使うか 5.2 アクティブレコード 5.2.1 実装方法 5.2.2 アクティブレコードをいつ使うか 5.3 現実的に考える 5.4 まとめ 5.5 演習問題 6章 複雑な業務ロジックに立ち向かう 6.1 歴史 6.2 ドメインモデル 6.2.1 実装方法 6.2.2 ドメインモデルの部品 6.2.3 複雑さの扱い方 6.3 まとめ 6.4 演習問題 7章 時間軸でモデルを作る 7.1 イベントソーシング 7.1.1 検索 7.1.2 分析 7.1.3 真実を語る唯一の情報源 7.1.4 イベントストア 7.2 イベント履歴式ドメインモデル 7.2.1 利点 7.2.2 欠点 7.3 よくある質問 7.3.1 性能 7.3.2 データの削除 7.3.3 他のやり方ではだめですか? 7.4 まとめ 7.5 演習問題 8章 技術方式 8.1 業務ロジックと技術方式 8.2 レイヤードアーキテクチャ 8.2.1 プレゼンテーション層 8.2.2 業務ロジック層 8.2.3 データアクセス層 8.2.4 レイヤー間の通信 8.2.5 レイヤードアーキテクチャの派生型 8.2.6 レイヤードアーキテクチャをいつ使うか 8.3 ポートとアダプター 8.3.1 概念の整理 8.3.2 依存関係逆転の原則 8.3.3 インフラストラクチャ層のコンポーネントとの連係 8.3.4 ポートとアダプターの同類 8.3.5 ポートとアダプターをいつ使うか 8.4 コマンド・クエリ責任分離 8.4.1 目的別のモデリング 8.4.2 実装 8.4.3 読み取りモデルの投影方法 8.4.4 課題 8.4.5 モデルの隔離 8.4.6 コマンド・クエリ責任分離をいつ使うか 8.5 スコープ 8.6 まとめ 8.7 演習問題 9章 通信 9.1 モデルの変換 9.1.1 状態なしのモデル変換 9.1.2 状態ありのモデル変換 9.2 集約どうしの連係 9.2.1 送信箱 9.2.2 サーガ 9.2.3 プロセスマネージャー 9.3 まとめ 9.4 演習問題 第Ⅲ部 ドメイン駆動設計の実践 10章 設計の経験則 10.1 経験則 10.2 区切られた文脈 10.3 業務ロジックの実装方法 10.4 技術方式の選択 10.5 テストの基本方針 10.5.1 ピラミッド形 10.5.2 ダイヤモンド形 10.5.3 逆ピラミッド形 10.6 実装方法の判定 10.7 まとめ 10.8 演習問題 11章 設計を進化させる 11.1 事業活動の変化 11.1.1 中核から一般へ 11.1.2 一般から中核へ 11.1.3 補完から一般へ 11.1.4 補完から中核へ 11.1.5 中核から補完へ 11.1.6 一般から補完へ 11.2 設計の基本方針を再検討する 11.3 業務ロジックの実装方法を見直す 11.3.1 トランザクションスクリプトからアクティブレコードへ 11.3.2 アクティブレコードからドメインモデルへ 11.3.3 ドメインモデルからイベント履歴式ドメインモデルへ 11.3.4 過去の状態変化を修復する 11.3.5 移行イベントとして表現する 11.4 組織の変更 11.4.1 良きパートナーから利用者と供給者の関係へ 11.4.2 利用者と供給者の関係から互いに独立へ 11.5 業務知識 11.6 システムの成長 11.6.1 業務領域 11.6.2 区切られた文脈 11.6.3 集約 11.7 まとめ 11.8 演習問題 12章 イベントストーミング 12.1 イベントストーミングとは何か 12.2 誰がイベントストーミングに参加するべきか 12.3 イベントストーミングに必要なもの 12.4 イベントストーミングのプロセス 12.4.1 ステップ1:発散的に探索する 12.4.2 ステップ2:時系列に並べる 12.4.3 ステップ3:問題点を洗い出す 12.4.4 ステップ4:転換イベントを見つける 12.4.5 ステップ5:コマンドを見つける 12.4.6 ステップ6:ポリシーを定義する 12.4.7 ステップ7:読み取りモデルを見つける 12.4.8 ステップ8:外部システムを追加する 12.4.9 ステップ9:集約を見つける 12.4.10 ステップ10:区切られた文脈に分割する 12.5 いろいろなやり方 12.6 イベントストーミングをいつ使うか 12.7 ファシリテーションのコツ 12.7.1 変化に注目する 12.7.2 リモートでのイベントストーミング 12.8 まとめ 12.9 演習問題 13章 現実世界のドメイン駆動設計 13.1 戦略的な分析 13.1.1 事業活動を理解する 13.1.2 既存システムの構造を調べる 13.2 設計改善の基本方針 13.2.1 基本方針の改善 13.2.2 実装方法の改善 13.2.3 同じ言葉を育てる 13.3 実践的なドメイン駆動設計 13.4 ドメイン駆動設計を売り込む 13.4.1 ドメイン駆動設計を非公式に取り入れる 13.5 まとめ 13.6 演習問題 第Ⅳ部 他の方法論や設計技法との関係 14章 マイクロサービス 14.1 サービスとは何か? 14.2 マイクロサービスとは何か? 14.2.1 「メソッド単位のサービス」が完璧なマイクロサービスか? 14.2.2 設計の目的 14.2.3 システムの複雑さ 14.2.4 マイクロサービスの深さ 14.2.5 深いモジュール 14.3 ドメイン駆動設計とマイクロサービスの境界 14.3.1 区切られた文脈 14.3.2 集約 14.3.3 業務領域 14.4 公開インターフェースを小さくする 14.4.1 共用サービス 14.4.2 モデル変換装置 14.5 まとめ 14.6 演習問題 15章 イベント駆動型アーキテクチャ 15.1 イベント駆動型アーキテクチャとは? 15.2 イベント 15.2.1 イベント、コマンド、メッセージ 15.2.2 データ構造 15.2.3 イベントのカテゴリー 15.3 イベント駆動型の連係を設計する 15.3.1 分散した大きな泥団子 15.3.2 時間的な結合 15.3.3 機能的な結合 15.3.4 実装の結合 15.3.5 イベント駆動型連係のリファクタリング 15.3.6 イベント駆動型で設計する経験則 15.4 まとめ 15.5 演習問題 16章 データメッシュ 16.1 分析系データモデルと業務系データモデル 16.1.1 事実テーブル 16.1.2 特性テーブル 16.1.3 分析系モデル 16.2 分析系データの管理基盤 16.2.1 データウェアハウス 16.2.2 データレイク 16.2.3 データウェアハウスとデータレイクの課題 16.3 データメッシュ 16.3.1 データを業務の視点で分割する 16.3.2 データをプロダクトと考える 16.3.3 自律性を高める 16.3.4 エコシステムを構築する 16.3.5 データメッシュとドメイン駆動設計を組み合わせる 16.4 まとめ 16.5 演習問題 結びの言葉 課題 解決方針 実現手段 さらに学ぶために より進んだドメイン駆動設計 アーキテクチャと連係方法 既存システムの改善 イベントストーミング 最後に 付録A ドメイン駆動設計の実践:事例研究 A.1 五つの区切られた文脈 A.1.1 マーケットノバス社の事業活動 A.1.2 区切られた文脈 その1:販売促進 A.1.3 区切られた文脈 その2:顧客管理 A.1.4 区切られた文脈 その3:イベント処理装置 A.1.5 区切られた文脈 その4:販売報奨金 A.1.6 区切られた文脈 その5:マーケティングハブ A.2 ふりかえり A.2.1 同じ言葉 A.2.2 業務領域 A.2.3 区切られた文脈の境界 A.3 まとめ 付録B 演習問題の回答 第1章 第2章 第3章 第4章 第5章 第6章 第7章 第8章 第9章 第10章 第11章 第12章 第13章 第14章 第15章 第16章 参考文献 索引 </pre> </div> </section> </section> <div class="related-items"> <div class="sectionRow__Heading"> <h3>関連書籍</h3> </div> <div class="sectionRow__Content"> <div class="sectionRow__BestLarge" id="bestEbooks"> <div class="sectionRow__Best" id="bestEbook1"> <a class="sectionRow__BestCover" href="/books/9784873119946/"> <img src="https://www.oreilly.co.jp/books/images/picture_large978-4-87311-994-6.jpeg" alt="エンジニアリングマネージャーのしごと"> </a> </div> <div class="sectionRow__Best hidden" id="bestEbook2"> <a class="sectionRow__BestCover" href="/books/9784814400676/"> <img src="https://www.oreilly.co.jp/books/images/picture_large978-4-8144-0067-6.jpeg" alt="クラウドデータレイク"> </a> </div> <div class="sectionRow__Best hidden" id="bestEbook3"> <a class="sectionRow__BestCover" href="/books/9784814400430/"> <img src="https://www.oreilly.co.jp/books/images/picture_large978-4-8144-0043-0.jpeg" alt="プロダクトマネージャーのしごと 第2版"> </a> </div> </div> <div class="sectionRow__BestThumbnails" id="bestEbookThumbnails"> <button class="sectionRow__bestBookThumbnailsItem" data-for="bestEbook1" aria-selected="true" title="エンジニアリングマネージャーのしごと"> <img src="https://www.oreilly.co.jp/books/images/picture_large978-4-87311-994-6.jpeg" alt="94540438030368"> </button> <button class="sectionRow__bestBookThumbnailsItem" data-for="bestEbook2" title="クラウドデータレイク"> <img src="https://www.oreilly.co.jp/books/images/picture_large978-4-8144-0067-6.jpeg" alt="94540438586776"> </button> <button class="sectionRow__bestBookThumbnailsItem" data-for="bestEbook3" title="プロダクトマネージャーのしごと 第2版"> <img src="https://www.oreilly.co.jp/books/images/picture_large978-4-8144-0043-0.jpeg" alt="94540444257072"> </button> </div> </div> </div> </div> </main> <footer class="footer__FooterSection"> <div class="pageWidth"> <div class="footer__FooterTop"> <div class="footer__List"> <h3><a href="https://www.oreilly.co.jp/company/">About</a></h3> <a href="https://www.oreilly.co.jp/company/">会社概要</a> <a href="https://www.oreilly.co.jp/orj/privacypolicy.shtml">個人情報について</a> <a href="http://www.oreilly.com/">O’Reilly Media</a> <a href="http://makezine.jp/">Make: Japan</a> <a href="http://makezine.jp/events">Maker Faire Tokyo</a> </div> <div class="footer__List"> <h3><a href="https://www.oreilly.co.jp/company/">Support</a></h3> <a href="https://www.oreilly.co.jp/feedback/">Contact us</a> <a href="https://www.oreilly.co.jp/bookclub/">Bookclub</a> <a href="https://www.oreilly.co.jp/order/">書籍注文</a> </div> <div class="footer__Apps"> <h3>Download the O’Reilly app</h3> <p>Take O’Reilly with you and learn anywhere, anytime on your phone <span class="nowrap">and tablet.</span> </p> <div class="footer__DownloadLinks"> <a href="https://itunes.apple.com/us/app/safari-to-go/id881697395"><img src="https://cdn.oreillystatic.com/oreilly/images/app-store-logo.png" alt="Apple app store"></a> <a href="https://play.google.com/store/apps/details?id=com.safariflow.queue"><img src="https://cdn.oreillystatic.com/oreilly/images/google-play-logo.png" alt="Google play store"></a> </div> </div> </div> <div class="footer__FooterBase"> <a aria-current="page" class="footer__Logo" title="Go to home page" href="/"><img src="/assets/images/logo_oreilly_japan.svg" alt="O'Reilly logo"></a> <p>© 2022, O’Reilly Japan, Inc. oreilly.co.jpに掲載されているすべてのトレードマークおよび登録商標は、それぞれの所有者に帰属します。</p> </div> </div> </footer> <script src="/assets/scripts/cookies-policy.6d8dcbae.js"></script> <script> let coll = document.getElementsByClassName('collapsible'); for (let i = 0; i < coll.length; i++) { let button = document.createElement('button'); button.setAttribute('type', 'button'); button.setAttribute('class', 'collapsible'); button.textContent = coll[i].textContent; coll[i].replaceWith(button) coll[i].addEventListener('click', function () { this.classList.toggle('collapsible-active'); let content = this.nextElementSibling; if (content.style.maxHeight) { content.style.maxHeight = null; } else { content.style.maxHeight = content.scrollHeight + 'px'; } }); } </script> <script src="/assets/scripts/scripts.js"></script> <!-- Global site tag (gtag.js) - Google Analytics --> <script async src="https://www.googletagmanager.com/gtag/js?id=UA-6009404-1"></script> <script> window.dataLayer = window.dataLayer || []; function gtag() { dataLayer.push(arguments); } gtag('js', new Date()); gtag('config', 'UA-6009404-1'); </script> </body> </html>