t0mmy

2020年12月30日に参加

学習サマリ

学習履歴一覧

183件中の 1-25件 を表示

リファクタリング 第二版 1章 読了

やったこと リファクタリング 第二版 1章 読了 学んだこと リファクタリングは、人間のために行う。 優れたプログラマは、人間にとってわかりやすいコードを書く。 リファクタリングでやること 小さな単位に分割する フェーズを分割する ポリモーフィズムを駆使して処理を動的に変化させる (順不同だけど、上からやる方がやりやすそう。また、対応済みだったり対応不要だったりする場合はスキップする) 小さな単位に分割する 長い処理を、意味のある小さな単位に分割する。 関数化を駆使するとやりやすい。 ... let thisAmount = ...; // 長い長い処理 ... const amountFor = () => {...}; /// 長い長い処理を関数化 ... let thisAmount = amountFor(); ... ローカル変数は、「小さな単位に分割する」際の障害になりやすい。 ローカル変数の排除を心掛けてリファクタリングしていくと、小さな単位に分割しやすい。 (=> 変数のインライン化) フェーズを分割する 小さな単位に分割したコンポーネントを、取り回しの効くような意味のある単位にまとめていく。 この時、最も大雑把なまとめ方として、「入力処理」「計算」「出力処理」がある。 ポリモーフィズムを駆使して処理を動的に変化させる 成し遂げたいこと(例: 料金を計算する)は同じだけど、分類によって計算ロジックを変化させたい(例: 通常価格、特売価格、会員価格など)ような状況。 計算ロジックをサブコンポーネントに委譲し、メインロジックを親コンポーネントでまとめ上げる... といった設計を行う。 これを実現するキーワードの一つが ' ポリモーフィズム ' 。 リファクタリングの第一歩 テストを作成する リファクタリングの度にコミットする 変数、関数などに、適切な名前を付ける テストを作成する リファクタリングによるコードの変更よって、新たにバグ(≒振る舞いが変化してしまうこと)が混入する事は十分考えられる。 このバグを早期に発見するためには、「振る舞いが変化していないこと」を検証する手段が必要。 テストは、この検証手段に相当する。 テストを作成することで、「振る舞いが変化していないこと」を常に確認できる。 振る舞いが変化していたとしても、それは「テスト失敗」という形である程度検知できる。 リファクタリングの度にコミットする リファクタリングに成功(≒コードを修正して、テストもパス)したタイミングでコミットする。 小さな単位でコミットしておくことで、万が一リファクタリングに失敗した場合でも、動いていた状態に戻すことが出来る。 コミット単位が小さいと、コードのロールバック量が少なくなり、開発効率が上がる。 意味のある単位としてまとまったてから、共有のリポジトリに変更をプッシュすると良い。 変数、関数などに、適切な名前を付ける 適切な名前を付けられた変数は、中身の値が容易に特定できる。 適切な名前を付けられた関数は、中身の処理が容易に想像できる。 名前が適切であれば、「コードを読んで中身を理解する」手間を省く。 開発効率の向上に寄与すると同時に、バグの発生を防ぐことにもつながる。 良いコードとは 好みによる部分も大きいが、「どれだけ変更が容易か」(≒どれだけソフトか)という視点は、共通してそう。

コーディング

2024年08月25日(日)

2.0時間

実践 Next JS 9章 データ更新とUI 読了

やったこと 実践 Next JS 9章 データ更新とUI 読了 学んだこと Server Action とは Form からサーバーの非同期関数を直接呼び出すことが出来る機能。 従来の「API Client を介して Route Handler (API Route) を呼び出す」という手法と比較して、以下のメリットがある。 API Client (中間コード)が不要 Browser 向けにバンドルされていた API Client が少なくなる ハイドレーションが完了する前に実行できる Typescript を採用していると、呼び出したい関数の型情報を参照できるため、型安全性が高まる。 Server Action を活用する 基本的な使い方 use server ディレクティブを宣言する。 関数内部で宣言すると、該当関数のみ Server でのみ実行される非同期関数とみなされる。 export default function ServerComponent() { const myAction = async () => { "use server"; ... } } または、use client の時のように、ファイルの先頭に記述することもできる。 この場合、同ファイルに記述された関数全てが Server でのみ実行される非同期関数とみなされる。 Server Action は、 <form> 要素の action 属性に渡して使用するのが一般的。 import {myAction} from "ServerActionを定義したファイルのパス" ... <form action={myAction}> // any code </form> ... form の action 属性に設定した関数は、第一引数に、 Web 標準の FormDate オブジェクトが渡される。 受け取り側(上記コードだと myAction 関数)は、 formData.get("id) のように、<input> 要素のデータを参照する。 参考: https://developer.mozilla.org/ja/docs/Web/API/FormData 引数のバインド 関数オブジェクトの bind メソッドを使用して、 Server Action に引数をバインドできる。 これにより、引数バインド済みの新しい Server Action を作成できる。 この時、FormdData は、バインドされた引数の後ろに渡される。 Progressive Enhancement 従来、<form> の aciton にはイベントハンドラをアタッチしていた。 これには、ハイドレーションが完了するまで Form イベントを送信できないという欠点がある。 Server Action のように、action に、 Server 側で動作する非同期関数を直接アタッチする場合、ハイドレーションは不要となる。 これは、ハイドレーションが機能しない(≒Javascript が動かない)状態でも動作することを意味している。 この、「Javascript が機能しない状態でも <form> を機能させる」という実装方針を、Progressive Enhancement と呼ぶ。 action イベントに加え、 onSubmit イベントハンドラも同時に設定可能。 この場合、以下のように動作する。 ハイドレーション未完了: action ハイドレーション完了: onSubmit onSubmit だと、バリデーションをはじめとしたクライアント側ロジックを実装できる。 このため、 onSubmit は優れた UX を提供できる(代わりに、ハイドレーションが完了するまで動かない)。 action と onSubmit を同時に実装すると、 action により最低限の動作を保証しつつ、 Javascript が有効な環境では、onSubmit に実装したロジックにより、優れた UX を提供できる。 On-demand Revalidation キャッシュを無効化するプロセスを On-demand Revalidation と呼ぶ。 (fetch の引数ではなく)以下専用の API を使用することで、任意のタイミングでキャッシュを無効化できる。 revalidatePath... 特定の Route のパスでキャッシュを無効化する revalidateTag 特定のタグ文字列でキャッシュを無効化する キャッシュを無効化するだけで、キャッシュを再作成するわけではない。 (キャッシュを作成するのは、次のリクエスト時) On-demand Revalidation との対比で、 Time-based Revalidation を「Stale-whilre-revalidate」とも呼ぶ。 Server Action で On-demand Revalidation を使用すると、以下の利点がある。 router.refresh() を実行せずとも「Router キャッシュ」がクリアされる redirect 関数を使用すると、更新と同時に画面遷移可能 この利点が大きいため、「データの作成、更新、削除」において、Route Hander よりも Server Action を優先した方が良い。 例外的に、「Next.js アプリケーションの外側から On-demand Revalidation を呼び出す」という処理を実現する場合は、Route Handler の On-demand Revalidation を採用できる。 ユースケース: ブログ記事 - 外部 CMS でブログ記事を書き、Next.js が、CMS からデータを取得するような構成 - ブログ記事更新後、 On-demand Revalidation を実行して、効率よくキャッシュを無効化できる useFormState Server Action と組み合わせて使用する、React 標準の Hook。 Form の状態を保持できる。Hook なので、 Client Component でのみ使用可能(そもそも Form 用だし、Client Compoennt でしか使わない)。 使い勝手は、React の useReducer 。 サーバー側で発生した事象を、「状態」という形でフロント側と共有できる。 const [state,dispatch] = useFormState( ServerAction に相当する関数, {state情報} ); useOptimistic 楽観的更新を実装できる、React 標準の Hook。 const [optimisticState,addOptimistic] = useOptimistic( state, (currentState,optimisticValue) => {} //楽観的に更新した状態を返す ) Revalidate の設計 On-demand Revalidation の考察 データの変更を反映させたい場合は、更新直後に On-demand Revalidation を使用するとよい。 以下二種類が存在する(再掲)。 revalidatePath... 特定の Route のパスでキャッシュを無効化する revalidateTag 特定のタグ文字列でキャッシュを無効化する 複数のキャッシュをまとめて無効化したい場合、 revalidateTag を使用することになる。 fetch 関数に定義した tags["具体的なタグ名"] を参照し、該当するタグをもつキャッシュをまとめて無効化できる 広範囲のキャッシュを頻繁に無効化すると、キャッシュが活きず、データアクセス速度が低下する。 一方で、局所的なキャッシュ無効化だけだと、キャッシュが悪さ(≒古い情報を提供)し、それを解消するための複雑なロジックを要する。 データ更新のユースケースに併せて、適切なタグの付与が必要。 ページをまたいだデータの更新が必要 => 抽象的なタグを用いて一括キャッシュ無効化 ID で区別された、一ページ分のデータの更新が必要 => 具体的なタグを用い、スコープを絞ってキャッシュ無効化 参考文献 https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations

Next.js

2024年06月02日(日)

2.0時間

実践Next.js 10章 パフォーマンスとキャッシュ 読了

やったこと 実践Next.js 10章 パフォーマンスとキャッシュ 読了 学んだこと 並列化でパフォーマンス改善 依存関係にないデータの取得は、 並行でデータを取得することで、パフォーマンスを改善できる。 ◆直列取得 const data1 = await getData1(); const data2 = await getData2(); const data3 = await getData3(); ◆Promise.all による並列取得 const [data1,data2,data3] = await Promise.all([ getData1(), getData2(), getData3() ]) ◆子サーバーコンポーネントに分割して並列取得 import { data1_component } from "..." import { data2_component } from "..." import { data3_component } from "..." ... return ( <> <data1_component /> <data2_component /> <data3_component /> </> ) データ取得処理用に 子 Server Component を用意し、データ取得処理を委譲する。 コンポーネント構造でも、データを並列取得するため、パフォーマンス改善が見込める。 可読性向上や再利用性向上といったメリットもある Server Component の動作に必要なデータが依存関係にない場合、子 Server Component に分割すると良い。 fetchCache の設定 fetch 関数のキャッシュデフォルト設定は auto。 これは、「動的関数が使用された」ことを起因に、キャッシュの挙動を切り替えるというもの。 fetchするデータと無関係な動的関数が使用された場合でも、動的データ取得扱いされ、リクエストが発生する恐れがある。 無関係な動的関数の例 : ログインしているユーザーの情報を取得するための getServerSession 関数 この場合、 fetch 関数の キャッシュ設定を force-cache とすると、常に静的データ取得扱いされ、常にキャッシュされるようになる。 静的 Route を増やす実装 無関係な動的関数の使用、静的Route であってほしい Route が、意図せず動的 Route になってしまうことがある。 ログインしているユーザーの情報を取得するための getServerSession 関数など Page のほかに、Layout.tsx で動的関数を使用している場合でも、動的 Route 扱いされる 動的 Route の原因となっている、 動的関数を取り除くために、以下の方法が採用できる。 動的関数を使用する部分を Client Component として 別コンポーネントに切り出す 動的関数を含む処理を CSR にて処理するよう修正することで、Route が 静的 Route を増やし、パフォーマンス改善につなげることが出来る。 ただし、動的データ取得処理が多い場合、 Server Component でまとめて取得する 動的 Route の方が、結果的に高パフォーマンスに繋がることもある。 動的関数 in CSR + 静的Route が、常に最適解というわけではない。 SSG Route の実装 予め Route のレンダリング結果を出力する SSG (またはISR)は、パフォーマンス改善において効果の高い手法。 SSG Route を提供する generateStaticParams 関数を使用する。 SSGしたいパスのパスパラメータを定義する関数 generateStaticParams 関数を export することで、 Next.js に認識される ビルド時にしか実行されない 例) export function generateStaticParams() { return [{ id: '1' }, { id: '2' }, { id: '3' }] } // Three versions of this page will be statically generated // using the `params` returned by `generateStaticParams` // - /product/1 // - /product/2 // - /product/3 export default function Page({ params }: { params: { id: string } }) { const { id } = params // ... } /product/1 、 /product/2 、 /product/3 は、SSGにより、ビルド時に事前レンダリングされる。 他のパラメータ( /product/4 , /product/5 など)は、リクエストが来たらレンダリングされ、レスポンスを返すと同時にSSGが行われる。 generateStaticParams 関数は、非同期として定義することもできる。 非同期関数として定義し、DBから SSGしたいID情報を取得し、return に設定する ... といった使い方が想定される。 generateStaticParams に複数の値を持たせたい場合、パラメータ部分を配列にするだけ。 export function generateStaticParams() { return [{ slug: ['a', '1'] }, { slug: ['b', '2'] }, { slug: ['c', '3'] }] } パスパラメータとなる変数が複数存在する場合、その数だけ key-value を定義する export function generateStaticParams() { return [ { category: 'a', product: '1' }, { category: 'b', product: '2' }, { category: 'c', product: '3' }, ] } // Three versions of this page will be statically generated // using the `params` returned by `generateStaticParams` // - /products/a/1 // - /products/b/2 // - /products/c/3 export default function Page({ params, }: { params: { category: string; product: string } }) { const { category, product } = params // ... } SSG を考慮したURI設計 パスにクエリパラメータを含め、 searchParams()を使用する ... というコードだと、 searchParams() が動的関数のため、動的Route と判断される。 categories/flower?page=1 など これを避けてSSG Route とした扱いたい場合、クエリパラメータではなくパスパラメータへ変更する...といった改善策がある。 categories/flower/1 など 参考 : https://nextjs.org/docs/app/api-reference/functions/generate-static-params#single-dynamic-segment Route Segment Config Route Segment 単位で、レンダリングやキャッシュ設定を一括制御できる機能。 特定の Route Segment に設定すると、 Subtree 全てに、設定内容を反映できる。 以下のように、変数をexport するだけで一括指定出来る。 export const revalidate = false // false | 'force-cache' | 0 | number SSG Route パフォーマンスの定量評価 以下の評価項目がある Time To First Byte (TTFB) サーバーからブラウザに、最初のデータが届くまでの時間 Largetct Contentful Paint (LCP) ブラウザの中で、最も大きなコンテンツが表示されるまでの読み込み時間 Lighthouse スコア https://chromewebstore.google.com/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk?hl=ja いずれも、開発者ツールで確認できる。 Next.js によるアセットの最適化 画像の最適化 <Image> コンポーネントの使用 Next.js が提供する <Image> コンポーネントを使用する。 これは html の <image> 要素を拡張したコンポーネントであり、以下の最適化が自動で適用される。 容量の最適化 : 配信に最適な画像形式(webpやavifなど)へ変換 視覚上の安定化 : 画像読み込み時、レイアウトずれの発生を自動防止 遅延読み込み : 初期表示ではプレースホルダー を表示し、ビューポートに入った時に読み込みを行う プレースホルダー表示ため、 alt 属性が必須となっている(空文字列でもOK。基本は画像を説明する文字列) 画像サイズ変更 : 画像サイズをオンデマンドで変更する 更に最適化された画像ファイルは、Next.js によってキャッシュされる。 キャッシュの格納先は .next/cache/images フォルダ 画像サイズ指定 画像サイズを指定することにより、 「Layout Shift」 というパフォーマンス問題を回避できる。 ◆Layout Shift 画像読み込みによって、他のHTML要素を動かしてしまう事象。 画像表示に必要なスペースを、事前に設定しておくことで回避できる。 画像サイズの設定必須。 優先読み込みを指定できる priority props priority を追加すると、追加された<Image>の画像は、優先的に読み込むことが出来る。 これにより、LCP向上につなげることが出来る。 画像の読み込み先を制限する 「信頼できる画像読み込み先」を指定し、信頼できない画像読み込み先との通信をブロックする。 これは、next.configにて設定する。 { const nextConfig = { images: { remotePatterns: [ { protocol: "https", hostname: "lh3.googleusercontent.com", }, { protocol: "http", hostname: "127.0.0.1", }, ], }, }; export default nextConfig; } 画像フォーマット指定 next.config にて、画像形式を指定できる。 const nextConfig = { images: { formats:['image/avif','image/webp'] } } 未指定の場合、 image/webp が採用される。 画像のキャッシュ時間を指定する 最適化された画像は Next.js によってキャッシュされる。 このキャッシュ時間を、 next.config にて指定できる。 const nextConfig = { images: { minimumCacheTTL: 60 } } 画像キャッシュを無効化することはできない。 キャッシュ保持期間を可能な限り短くすることで、暫定対応する。 キャッシュ時間は、上記 minimumCacheTTL の値と、サーバーレスポンスの max-age Cache Control ヘッダの内、大きい値が採用される。 フォントの最適化 next/font を使用すると、あらゆる Font ファイルのセルフホスティングが可能。 従来のようにFontファイル とCSSファイルの準備が不要になる。 サブセットの指定 Google Font は、自動的にサブセット化できる。 ◆サブセット化 使用している文字だけ抜き出しフォント化すること サブセット化により、Fontファイルのサイズを削減し、パフォーマンス向上が見込める。 const inter = Inter ({subsets: ["latin"]) CSS Variables の適用 外部CSS を読み込み、一部オプションを追加して使いたい場合は、CSS Variables を使用する。 import { Inter } from "next/font/google"; import styles from "../styles/component.module.css"; const inter = Inter({ variable: "--font-inter", }); スタイルを設定するテキストの「親コンテナのclassName」 をフォントローダーの変数値に設定する。 そして、テキストのclassNameを外部CSSファイルのセレクターが適用されるように設定する。 <main className={inter.variable}> <p className={styles.text}>Hello World</p> </main> そして、外部CSSファイル(component.module.css)で、以下のようにCSS Variables を使用する。 .text { font-family: var(--font-inter); font-weight: 200; font-style: italic; } フォント定義ファイルの使用 フォントファイルは、ロードする度にインスタンス生成処理が走る。 何度もインスタンス生成処理が走るのは非効率。 そのため、フォントファイルのロード処理は一か所にまとめておき、 exportする。 他のコンポーネントは、importするだけにしておく。 サードパーティスクリプト読み込みの最適化 Layout Script 複数のRoute でサードパーティスクリプトを読み込む場合は、 next/script をインポートし、 <Scriptl> コンポーネントを Layoutコンポーネントに含めるよう定義する。 これにより、 Layout側で一度スクリプトをダウンロードするだけで、 Subtree でもスクリプトを使用できる。 Root Layout に含めることで、全ての Route で使用するスクリプトを定義する事もできる。 不必要なスクリプトのダウンロードは、パフォーマンスの悪化につながる。 基本的に、サードパーティスクリプトのダウンロードは、スクリプトが必要な特定のページまたはサブコンポーネントで行う。 全ページで必要なサードパーティスクリプトのみ、 Root Layout でダウンロードする。 Next.js の 4種類のキャッシュ Next.js は、レンダリング結果とデータ取得結果をキャッシュする。 以下の順番でキャッシュする。 Request のメモ化 Data キャッシュ Full Route キャッシュ Router キャッシュ Request のメモ化 fetch 関数の戻り値(取得データ)を一時的にキャッシュする。 サーバー上で重複して呼び出された fetch 関数は、キャッシュした戻り値を再利用する。 同一のfetch関数リクエスト排除を目的としており、これを「メモ化」と呼ぶ。 これは、fetch 関数を使用して同一のリクエストを試みても、リクエストは1回のみに抑えることを意味する。 これにより、コンポーネント単位でデータ取得関数を呼びだしても、キャッシュが機能するようになる。 このメモ化は、レンダリング中のみ有効。 言い換えると、レンダリングが完了すると、メモ化したデータはリセットされる fetch 関数以外で Request をメモ化したい場合は、 React の cache 関数を使用する。 Data キャッシュ ビルド時、fetch 関数の取得データを永続的にキャッシュする。 当然、変更のない "静的データ" がキャッシュの対象となる。 キャッシュの有効期限は、 Time-based Revalidation の設定で設けることが出来る。 また、On-demand Revalidation にて、能動的に無効化する事もできる。 force-cache されたデータは、再ビルド時でもキャッシュは削除されず、ずっと再利用され続ける。 ローカル開発だと、Dataキャッシュを直接削除する( .next/cache/fetch-cache 配下)ことで、キャッシュを削除できる。 以下のように設定することで、プロジェクトを通して「キャッシュを使用しない」ことを設定できる。 // Segment Subtree 配下のデータ取得を、全て動的へ export const dynamic = "force-dynamic"; // Segment Subtree 配下のデータ取得時、一切キャッシュしない export const revalidate = 0; fetch 関数以外で Data キャッシュを作成したい場合、Next.js の unstable_cachce 関数を使用する。 第一引数に渡した非同期関数の戻り値が、キャッシュされるようになる。 Full Route キャッシュ 各 Route のレスポンスを永続的にキャッシュする。 Full Route キャッシュが存在せず、Routeでデータ取得がある場合、「Data キャッシュ」を経由してDataソースにアクセスする。 静的サイト生成(SSG)や静的レンダリングファイルのこと。 キャッシュはビルド時、またはリクエスト時に作成される。 再ビルドするまで、ずっと残る。 言い換えると、Full Route キャッシュを削除するには、再ビルドが必要 ただし、 Dataキャッシュの Revalidate が発生すると、関連する Full Route キャッシュも無効になる。 無効になった Full Route キャッシュは、 Dataキャッシュが作成されるときに、同時に作成される。 Router キャッシュ ブラウザにて保持するキャッシュ。 主な目的は、「戻る」「進む」ボタン処理を高速にしつつ、データアクセスの頻度を削減すること。 一定期間が過ぎると、部分的なRouter キャッシュは自動で無効になる。 キャッシュの有効期間は以下の通り。 動的レンダリングRoute : 30s <Link> コンポーネントの props に prefetch={true} を使用すると、有効期間が5分に延長される 静的レンダリングRoute : 300s (5分) <Link> コンポーネントの props に prefetch={false} を使用すると、有効期間が30秒に短縮される この有効期間は切り替え可能。 能動的にキャッシュを無効化するには、以下のいずれかの手段を取る。 ブラウザで router.refresh を実行する http リクエストが二往復必要になる Server Action 内で coolies.set または cookies.delete を使用する 古い Full Route キャッシュやDataキャッシュにヒットし、意図しない結果につながる可能性がある Server Action 内で on-demand revalidation を実施する 推奨

Next.js

2024年06月02日(日)

3.0時間

実践Next.js 8章 モーダル表示とデータ連携 読了

やったこと 実践Next.js 8章 モーダル表示とデータ連携 読了 学んだこと モーダルの価値 閲覧中の画面から離脱することなく別の作業に移ることが出来、 作業終了後は、前の画面へ即座に戻ることが出来る。 Next.js だと、モーダルの実装には二つの選択肢がある。 React の標準機能で実装 Next.js (AppRouter)機能を活用して実装 React の標準機能でモーダルを実装 useModal を使用する。 よくあるのは button コンポーネントと組み合わせ、「ボタンのクリックを検知したらモーダルを表示する」というもの。 AppRouter 機能を活用てモーダルを実装 Parallel Routes と Interceptiong Routes を用いてモーダルを実装する。 React の標準機能で実装したモーダルと比較して、以下のメリットがある。 モーダル表示の際に遷移元のコンテキストを失わない モーダルから別のモーダルへ遷移できる モーダル => 元画面 => モーダル と、元画面を経由する必要が無い モーダルの URL をシェアできる モーダルの URL をシェアしても、遷移元の情報を漏らさない Intercepting Routes を使用することで、URLを持つページを、モーダルとして表示することが出来る。 Parallel Routes の役割は、よくわからない。 バックエンド間連携によるデータ保存 サンプルアプリケーションの説明が中心。

Next.js

2024年06月01日(土)

2.0時間

実践Next.js 7章 認証機能 読了

やったこと 実践Next.js 7章 認証機能 読了 学んだこと Next.js で、クレデンシャル情報を環境変数へ設定する 想定するクレデンシャル: DB サーバーのログイン情報や、API の認証情報 基本は以下の通り。 .env といった隠れファイルに、環境変数をまとめる web アプリケーションではおなじみの名前とのこと .gitignore に、環境変数をまとめたファイルのファイル名を記述し、git 管理下から外す Next.js では、以下のファイルを自動で読み込んでくれる。 .env: 常時読み込む .env.$(NODE_ENV): 該当の NODE_ENV の値が有効な場合に読み込む .env.local: ローカル開発環境で常時読み込む .env.$(NODE_ENV).local: 開発環境にて、該当の NODE_ENV の値が有効な場合に読み込む $(NODE_ENV) の有効な値は、 production, development, test の 3 つ。 なお、 Next.js 以外だと、dotenv 等のライブラリを利用することになる。 なお、環境変数ファイルは、以下の順で読み込まれる。 .env.development.local .env.local .env.development .env 既に存在している環境変数は上書きされない。 つまり、環境変数が重複していた場合、優先順位の高いファイルの値が設定されることになる。 環境変数の公開範囲 ◆public な環境変数 NEXT_PUBLIC というプレフィックスが付く環境変数のこと。 この環境変数は、ビルド時にインライン化される。 値を変えるには再ビルドが必要。 ◆private な環境変数 NEXT_PUBLIC というプレフィックスを持たない環境変数のこと。 private な環境変数は、(client component に直書きしたなどで)誤ってインライン化しようとした場合、空文字で置き換えてくれる。 NextAuth.js の導入 NextAuth.js の導入手順 環境変数 NEXTAUTH_SECRET の設定 Middleware の設置 NextAuthOptions の設定 Route Handler の設置 getServerSession の利用 環境変数 NEXTAUTH_SECRET の設定 OAuth 認証用 にシークレットキーを作成し、NextAuth.js に読み込ませる。 シークレットキーは、 openssl コマンドなどで生成する。 openssl rand -base64 32 参考 : https://next-auth.js.org/configuration/options#nextauth_secret 生成したシークレットキーは、.env 系統の環境変数ファイルに、 NEXTAUTH_SECRET という名前の変数で定義する。 あとは、 NextAuth.js が、 NEXTAUTH_SECRET 環境変数を自動で判別し、読み込んでくれる。 Middleware の設置 Middleware は、「リクエストを処理する前に実行したいコード」を定義できる機能。 ユースケース : レスポンスヘッダの書き換えやリダイレクト NextAuth.js では Middleware を活用して、 特定のURLパターンにマッチするRoute を「認証が必要なRoute」としてハンドリングする といったことが可能。 export { default } from "next-auth/middleware"; export const config = { matcher:["/profile"], } NextAuthOptions の設定 NextAuth.js の設定をカスタムする。 NextAuthOptions インターフェースに沿ったJSONを定義し、 export して使用する。 NextAuthOptions インターフェースの主要なオプションは以下の通り。 adapter? : Adapter 他のサービス(ORMなど)と連携する場合に使用する、アダプター providers : Provider[] OAuth プロバイダー情報。 Google なら、 GoogleProvider オブジェクト。 callbacks? : Partial<CallbacksOptions> OAuth 認証成功後に呼び出したい、コールバック関数を定義できる OAuth 認証後は jwt を取得できるので、これを起点に後続処理を記述していく ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ Prismaと接続する場合は、 PrismaAdapter を使用する。 参考 : https://next-auth.js.org/v3/adapters/prisma Route Handler の設置 NextAuth.js 専用の Route Handlerが存在するため、これに沿って handler 関数を定義する。 // api/auth/[...nextauth]/route.ts import NextAuth from "next-auth" import { authOptions } from "NextAuthOptions を定義したファイル" const handler = NextAuth(authOptions) export { handler as GET, handler as POST } 参考 : https://next-auth.js.org/configuration/initialization#route-handlers-app getServerSession の利用 サーバーサイド側で getServerSession 関数を使用すると、ログインユーザー情報を参照できる。 import { getServerSession } from "next-auth" import { authOptions } from "NextAuthOptions を定義したファイル" ...{ const session = await getServerSession(authOptions) ... } 参考 : https://next-auth.js.org/configuration/nextjs#getserversession 関連ドキュメント NextAuth.js 公式: https://next-auth.js.org/getting-started/introduction Middleware 公式 : https://nextjs.org/docs/app/building-your-application/routing/middleware

Next.js

2024年06月01日(土)

2.0時間

実践 Next JS 4章 Route Handler

やったこと 実践 Next JS 4章 Route Handler 学んだこと Route Handler 概要 Segment 構成フォルダに route.ts ファイルを定義する。 /** /api/hello のリクエストを処理するRoute Handler */ app/api/hello/route.ts route.ts 内で、 HTTP メソッド別に処理を記載していく。 export const GET = () => {} // GET リクエストに対応する処理 export const POST = () => {} // POST リクエストに対応する処理 ... HTTP の request および response は、 Next JS が提供する NextRequest および NextResponse を通じてやり取りする。 import { NextRequest, NextResponse } from "next/server"; export const POST = async (request: NextRequest) => { return NextResponse.json({ liked: true }); } Route Handler を使用する場合、ルーティングのコンフリクトを避けるために、 api ディレクトリを用意することが通例となっている。 Route Handler のレンダリング Route Handler は、JSON をレンダリングする。 画面のレンダリング同様、 Route Handler がレンダリングする JSON も、 静的レンダリングと動的レンダリングの二つをサポートする。 静的 Route Handler 静的 Route Handler は、JSON をキャッシュする。 言い換えると、リクエストの度に、外部 Web サーバーからデータを取得したりしない 画面レンダリング同様、Next JS は、まず静的 Route Handler としてレンダリングを試行する。 静的レンダリング不能な(≒特定の条件を満たす)場合、 動的 Route Handler としてレンダリングする。 動的 Route Handler 以下検出すると、 Route Handler を動的 Route Handler とみなす。 Dynamoc Segment 値の参照 Dynamoc Segment 自体は、 各 HTTP リクエストに対応したメソッドの第二引数から参照する Request オブジェクトの参照 動的関数の使用 GET と HEAD 以外の HTTP 関数の export Segment Config Options の指定 このオプションを指定すると、実装に関係なく、 Route レンダリングを強制できる export const dynamic = "force-dynamic"; Route Handler の使用例 ブラウザ/サーバー間のリクエスト・レスポンス ブラウザからの HTTP リクエストに対処する I/F として、Route Handler を使用する。 公式ドキュメント: https://ja.next-community-docs.dev/docs/app-router/building-your-application/routing/route-handlers

Next.js

2024年05月19日(日)

2.0時間

実践Next JS 2章 Server Component とレンダリング 読了

やったこと 実践Next JS 2章 Server Component とレンダリング 読了 学んだこと Server Component と Client Component Server Component とは サーバーサイドでのみ実行されるコンポーネント。 同期/非同期関数 のどちらでも記述できる。 AppRouter 内で実装される React コンポーネントは、デフォルトでは全てのコンポーネントが Server Component として扱われる。 Client 側で実行したくない処理(DB からデータを取得する処理など)は当然として、 ブラウザとサーバー、どちらで実行しても問題ないものは、 とりあえず Server Component として実装すると吉(要件によって異なる)。 Client Component とは クライアントサイドで実行されるコンポーネント。 use client と明示することで、 Client Component として扱われる。 Client Component として実装するユースケースは、主に以下がある。 alert のような、ブラウザの機能を使用するコンポーネント イベントハンドラによる動的処理を実現したいコンポーネント 補足 RSC は React Server Component の略 Server Component と SSR は別物 参考記事: https://postd.cc/how-react-server-components-work/#01 ハイドレーションとは 事前に生成された HTML に対してイベントハンドラをアタッチしていく処理 画面の初期表示の際に、サーバーから取得したデータを用いて画面の基本的な構造を構築します その後、フロントエンドの JavaScript やフレームワークによって、画面に追加のデータやコンポーネントがダイナミックに挿入されます ユーザーが画面を操作すると、追加のデータやコンポーネントがサーバーから取得され、画面に反映されます Next JS のキャッシュ NextJS では、 独自拡張した fetch 関数を使用することで、キャッシュ機能を使用できる。 {cache: "no-store"} キャッシュしない 頻繁に更新されるデータなど、キャッシュしたくないデータに対して使用 {cache: "force-cache"} キャッシュする 更新される見込みがないデータに対して使用 {next: {revalidate: wait_second } wait_second で指定した時間だけキャッシュする 更新頻度がある程度わかっているデータや、正確性が求められない(≒大雑把でよい)データに対して使用 ISR (Incremental Static Regeneration) とも密接に関係 デフォルトでは、 {cache: force-cache} 、つまりキャッシュする。 キャッシュデータは、 .next/cache/fetch-cache に保存される。 Route のレンダリング Routeのレンダリングには、動的レンダリングと静的レンダリングの二種類が存在する。 動的レンダリング ... リクエストの度に、HTMLをレンダリングするレンダリング方針 静的レンダリング ... 事前にHTMLをレンダリングしておき、リクエストに備えるレンダリング方針 これらは、ビルド時にNextJS側で判断してくれる。 Next JSのキャッシュ機能を活かした高速配信を実現するためにも、静的レンダリング+CDN という構成が望ましい。 Next JSでも、まずは静的レンダリングを試みて、ダメだったら動的レンダリングに切り替わる ... という挙動をする。 動的レンダリングの要因は以下のとおり。 動的データ取得の使用 HTTPリクエストを参照するような関数の使用 Dynamic Segment の使用 用語整理 Client Side Rendering まっさらな HTML ファイルを用意。 JS で DOM を生成し、HTML にアタッチしていく。 以下のデメリットを抱える。 DOM の生成 & アタッチが完了するまで、画面に何も表示されない js ファイルのサイズ次第で、js ファイルのダウンロード時間が無視できないほど長くなる SEO で不利 上記デメリットは、Server Side Rendering によってある程度軽減できる。 Server Side Rendering 「DOM 生成 & HTML へアタッチ処理」の一部分をサーバー側で実行する。 つまり、サーバー側でレンダリング処理の一部を行い、結果をクライアントへ配信する。 Client Side Rendering のデメリットをある程度軽減できる。 Static Site Generator サーバーへのリクエストに応じて、事前に生成しておいた HTML ファイルを配信する。 動的な JSON ファイル Astro とか ハイドレーション 事前に生成された HTML に対してイベントハンドラをアタッチしていく処理。 レンダリングの種類 Full CSR... まっさらな HTML & JS CSR with Prerendering... 骨格レベルの HTML は事前にレンダリング (静的 HTML)) & JS Dynamic HTML & JS/DOM... 参考 https://qiita.com/akashixi/items/84cd79e090a283bb8c67 https://zenn.dev/dozo13189/articles/07e96c182afa46

Next.js

2024年05月19日(日)

2.0時間

実践Next JS 3章 App Router の規約 読了

やったこと 実践Next JS 3章 App Router の規約 読了 学んだこと App Router では、予約済みの特殊なファイル(以下構成ファイル)が存在する。 構成ファイルの一覧は、以下を参照。 https://nextjs.org/docs/app/building-your-application/routing#component-hierarchy 構成ファイル名は事前に決まっている。 つまり、構成ファイルとして決めれられている名前でファイルを作成すると、Next JS が自動で読み込んで、適用してくれる。 構成ファイルは、 Segment 別に定義できる。 構成ファイルを使用することで、Next JS の機能を活かした効率的な開発を実現できる。 Segment 構成ファイルの役割 構成ファイル名 役割 備考 loading ローディング UI を提供 not-found 404 UI を提供する next/navigation の notFound() 関数を呼び出すのが通例 error 何らかの例外を捕捉した場合の UI を提供する use client でのみ機能する route web api を提供する default Parallel Routes 用ファイル global-error error 構成ファイルで捕捉できなかった例外用の UI を提供する use client でのみ機能する Segment 構成フォルダ 予約済みの特殊なフォルダ(以下構成フォルダ)も存在する。 構成フォルダにて、Segment 構成をコントロールできる。 Dynamic Route Segment パスに含まれるパラメータを参照できる。 パラメータ変数は、[slug] のように [] で埋め込む。 基本 [slug] という命名規約でフォルダを作成する。 Route(ディレクトリ構成) URL リクエストの例 params app/blog/[slug]/page.tsx /blog/a {slug:'a'} app/blog/[slug]/page.tsx /blog/b {slug:'b'} Catch-all Segment [...slug] という命名規約でフォルダを作成する。 [] から page.tsx までの間に存在する全パラメータを、配列として参照できる。 Route(ディレクトリ構成) URL リクエストの例 params app/shop/[...slug]/page.tsx /shop/a {slug:['a']} app/shop/[...slug]/page.tsx /shop/a/b {slug:['a,b']} Optional Catch-all Segment [[...slug]] という命名規約でフォルダを作成する。 Catch-all Segment の挙動に加えて、パラメータなしのリクエストにも対応できる。 Route(ディレクトリ構成) URL リクエストの例 params app/shop/[[...slug]]/page.tsx /shop {} app/shop/[[...slug]]/page.tsx /shop/a {slug:['a']} app/shop/[[...slug]]/page.tsx /shop/a/b {slug:['a,b']} Route Groups 以下の両方を満たすようなユースケースで使用する。 いくつかのコンポーネントを、フォルダでまとめたい まとめ用フォルダは URL Path で扱いたくない Route Groups を使用すると、フォルダの一部を URL Path から除外できる。 フォルダ名を (feature) のように () で囲むことで、Route Groups として認識され、URL Path の Segment として認識されなくなる。 // website を表現する "site" フォルダでまとめたコンポーネント ./src/app/(site)/photos/page.tsx ./src/app/(site)/categories/page.tsx // 情報提供を表現する "static" フォルダでまとめたコンポーネント ./src/app/(static)/company-info/page.tsx ./src/app/(static)/privacy-policy/page.tsx これにより、URL Path を参照するソースコードを変更することなく、フォルダによるグループ化を実現できる。 また、Route Group フォルダ (() で囲った名前のフォルダ)にも、構成ファイルを適用できる。 ./src/app/(site)/layout.tsx // (site)用 Layout ./src/app/(site)/photos/page.tsx // (site)用 Layoutが適用される ./src/app/(site)/categories/page.tsx // (site)用 Layoutが適用される ./src/app/(static)/layout.tsx // (static)用 Layout ./src/app/(static)/company-info/page.tsx // (static)用 Layoutが適用される ./src/app/(static)/privacy-policy/page.tsx // (static)用 Layoutが適用される Private Folder とコロケーション コロケーション (co-location): 特定機能の関連ファイルをまとめること。 Route に影響を与えないフォルダを配置できる。 フォルダ名の先頭に _ をつけるだけ。 特定の Route でしか使用しないコンポーネントを、Route の近くに配置したい場合等で使用する。 /src/app/_components/page.tsx // ルーティング対象外 /src/app/page.tsx // メイン画面 Parallel Routes と Intercepting Routes いずれも、ソフトナビゲーションを活用した UI の実装で使用する。 Parallel Routes 概要 複数のコンポーネントを、一つのレイアウト内で同時に(または条件付きで)レンダリングできる機能。 Parallel Routes の使い方 @users のように、先頭が @ で始まるフォルダ名を作成する。 この時、 @users を Slot と呼ぶ。 言い換えると、 Slot は、 @xxx という命名規約によって機能する slot 部分を除いた URL Path に一致するページをレンダリングする際に、 Parallel-routes も一緒にレンダリングされる。 ./layout.tsx ./@users/accounts/pages.tsx // slot ./accounts/pages.tsx // @users slot にヒットする Slot は Segment として扱われない。 そのため、URL Path に影響を与えない。 Slot は、 Layout コンポーネントで受け取る。 受け取り方は、React Component の Children と同じように Props として受け取る。 export default Layout = (props:{ children : React.ReactNode; // React Component の Children users: React.ReactNode; // @users というフォルダの情報が渡される }) => { ... } Slot フォルダ内で default.tsx を設定してい置くと、 Route Segment が表示されるまでの間、 default.tsx の内容がレンダリングされるようになる。 ユースケース @user Slot と @admin Slot を作成し、権限に応じてレンダリング先を変更する(条件付きルート) 後述する Intercepting-routes と組み合わせたモーダルの実装 など 公式ドキュメント: https://ja.next-community-docs.dev/docs/app-router/building-your-application/routing/parallel-routes Intercepting Routes の概要 Route を横取りする Route 定義。 正しく言うと、現在のページのコンテキストを維持したまま、現在のレイアウト内でルートをロードできる。 モーダルがリンクを持つイメージ。 ソフトナビゲーション時のみ、 Intercepting-routes は機能する。 画面リロードのようなハードナビゲーションでは発動しない Intercepting Routes の使い方 (..) で始まる命名規約でフォルダを作成する。 Linux のディレクトリ指定とそっくりな挙動。 (.) は、同じ階層の Segment とマッチ (..) は、一つ親の Segment とマッチ (..)(..) は、二つ親の Segment とマッチ (...) は、ルート app ディレクトリの Segment にマッチ /feed/(..)photo/[id]/page.tsx // /photo/[id]/page.tsxの中身をインターセプト /photo/[id]/page.tsx 公式ドキュメント: https://ja.next-community-docs.dev/docs/app-router/building-your-application/routing/intercepting-routes Route のメタデータ 静的、および動的メタデータを定義する API が用意されている。 主に SEO の観点で重要となる。 静的・動的メタデータともに、基本的には Metadata オブジェクトを、任意の階層で Export することになる。 静的メタデータ 固定のメタデータを出力する。 Metadata オブジェクトを Export するだけ。 import type { Metadata } from 'next'; export const metadata:Metadata = { title:'hoge', description: 'fuga', } これで、レンダリング後の HTML に、メタデータが書き出される。 動的メタデータ generateMetadata 関数経由で Metadata オブジェクトを Exportする。 export generateMetadata = async ({params}):Promise<Metadata> => { /** 任意の非同期処理 */ return { title: asyncData.name, description: asyncData.description, } } メタデータの継承 Next JS では、親Segment から Route Segment までたどり、各メタデータと結合してくれる。 このため、全てのSegment でメタデータを設定する必要はない。 親で定義したメタデータに挿入・上書きしていくイメージ 親から継承したメタデータは、 ResolvingMetadata 変数を使用することで参照できる。

Next.js

2024年05月19日(日)

2.0時間

書籍「エンジニアのためのドキュメントライティング」 PART3 (7,8,9,10,11章) 読了

やったこと 書籍「エンジニアのためのドキュメントライティング」 PART3 (7,8,9,10,11章) 読了 学んだこと 7章 ドキュメントの公開 最初から完璧を求めない。 リリース後、フィードバックに基づいて更新を繰り返すつもりでいること。 ドキュメントの公開に当たって、やるべきこと コンテンツリリースプロセスの構築 公開タイムラインの作成 公開の最終決定と承認 読み手へのコンテンツの告知 コンテンツリリースプロセスの構築 リリースするまでの計画(≒流れ)を予め用意しておく。 以下の質問に答えることで、計画に必要な情報を収集できる。 コンテンツをいつ公開するか? 最終レビューと公開の責任者は誰か? コンテンツをどこで公開するか? コンテンツを公開するために、追加で必要となるソフトウェアツールは? 新しいコンテンツをどのように発表するか? 公開タイムラインの作成 ドキュメント公開に向けて必要なタスクについて、作業計画(=> 公開タイムライン)を作成する。 ◆公開タイムライン 公開に向けて必要不可欠なタスクがすべて揃っていること、 および、タスクの完了に向けて十分な時間があることを確認するための方法の一つ イメージはガントチャート。 基本的には、ドキュメントは、対応するアプリケーションと同時に公開する。 そのため、公開タイムラインのタスクには、ソフトウェアのリリース作業情報も含めると良い。 公開の最終決定と承認 ドキュメントのリリース・差し止めを判断する最高責任者を 一人任命する。 その人物にリリース・差し止めを判定してもらう。 差し止めの主な基準は、「ドキュメントがユーザーにとって有害かどうか」 コードレビューと同じタイミングでドキュメントのレビューを挟む。 こうすると、リリースする機能に関するドキュメントもレビュー済みであることを確信できる。 読み手へのコンテンツの告知 ドキュメントを公開しても、ユーザーに読まれなければ意味がない。 ユーザーに合わせて、適した公開方法を選択すること。 そして、読み手の取って最も合理的なスタート地点に、リリースしたドキュメントのリンクを貼ること。 社内向けだと、社内でよく使用されるWikiなど ソースコードやエンドポイントを使用する外部の開発者であれば、リポジトリの中に含めるとよさそう サービス利用者であれば、少なくともソフトウェアの外部にドキュメントを配置すること ◇◆◇◆◇ コンテンツのリリースに慣れてきたら、改善できそうな箇所が無いか探してみること。 公開プロセスの自動化も、良い選択肢。 ただし、最初は作りこみ過ぎず、最も単純な個所から取り組むと良い。 8章 フィードバックの収集と組み込み リリースしたドキュメントを改善するために、ユーザーからフィードバックを受け取る。 フィードバックチャンネルの作成 フィードバックからアクションを決定 フィードバックのトリアージ フィードバックチャンネルの作成 ユーザー数、ユーザーの属性に応じて、フィードバックチャンネルを設ける。 ドキュメントページからフィードバックを直接受け取る サポートチケットをモニタリングする ドキュメントに対する感情を測定する 「このページは役立ちましたか?」「「はい」、「いいえ」」のアンケート 感情は、コンテキストの影響を受けやすい トラブルシューティングページは、低評価をつけやすい傾向にある ... など ユーザーサーベイを作成する ユーザー会を設立する ユーザーの目的は、ドキュメントを読んで目的を達成すること。 フィードバックを送信する事ではない。 ユーザーの労力が少なくすることを念頭に、色々なチャンネルを検討すること。 フィードバックからアクションを決定 フィードバック情報を基に、ユーザーの目的達成を妨げる障害を排除する(または、目的達成を更に助ける)アクションを決定する。 フィードバックのトリアージ フィードバックのアクションに対して、優先順位をつけて対応する。 優先順位をつける際、以下の評価項目を考えると良い。 そもそもドキュメントに関連する課題であるか? ドキュメントに関係ない課題であれば、関連部署にエスカレーションする ドキュメントの改善に向けて、アクションに落とし込めるか? 再現可能? 「全部書き直してほしい」とか「役に立たない」のように、曖昧で範囲が広すぎると、アクションに落とし込めない 課題はどれぐらい重要か? アクションを実行し、課題に対応したら、フィードバックを送ってくれたユーザーに感謝を伝えると良い。 9章 ドキュメントの品質測定 目的にかなっているドキュメントこそ、優れたドキュメント。 ドキュメントの目的は、以下の二点。 ユーザー特定の行動を促進すること 組織のゴールを達成すること 上記二点に合わせて、ドキュメントの品質を次の二つの基本的なカテゴリに分類できる。 機能品質 : ドキュメントの目的やゴールが達成されているかどうか 構造品質 : ドキュメントが上手く構成されているか、読みやすいか 機能品質 ドキュメントが、役割(≒ユーザーが目的を達成すること)をどの程度果たしているかを表す指標。 機能品質は、以下のカテゴリに分解できる。 アクセシビリティがあること 難しい文法、語彙を使用しない ユニバーサルデザインを導入している 目的があること 目的に加え、想定読者や読み手が達成できることを書いておくと良い みつけやすいこと 以下を表す指標 どれぐらい簡単に読み手がコンテンツにたどり着けるか どれぐらい簡単にコンテンツ内を読み進めることが出来るか サイト全体における現在地を表示するなど、各ドキュメントに、できるだけ多くのコンテキストを記載すると良い 正確であること 完全であること 以下を満たすこと 読み手が従うべき前提条件がすべて一覧化されている タスク完了に必要なすべてのタスクが載っている 読み手が取るべき次のステップが定義されている 構造品質 ドキュメントをいかに簡単に理解できるかを表す指標。 以下3つのCで定義する。 Clear (明確な) ドキュメントをいかに簡単に理解できるか 難解な専門用語や、不必要に長い言葉を避ける...など Concise (簡潔な) 読み手に関連する情報とゴールに関する情報のみが含まれること 短くてわかりやすいこと =>不要な言葉や不必要なコンセプトは記載しないこと Consistent (一貫している) コンテンツの構造、導入するコンセプト、言葉の選択(≒語彙)がドキュメント全体で同一であること 機能品質と構造品質の優先順位 機能品質の方が重要。 => どれだけうまく構成されていても、読み手が目的を達成できなければ、ドキュメントの存在意義はない。 レビューやメトリクス収集の際も、「機能品質を満たしているか」が重要な観点になる。 なお、レビューやメトリクス収集の際、人間は構造品質に目が行きやすい。 注意すること。 メトリクスを収集して品質向上に役立てる 「目的にかなっているドキュメントこそ、優れたドキュメント」であることを念頭に、収集するメトリクスを決定する。 知りたいこと(質問)に合わせて、収集するメトリクスを決定する。 質問 ドキュメントのメトリクス ドキュメントを読んでいるユーザー数は? ユニーク訪問者数 最も閲覧されているドキュメントは? PV数 など 収集したメトリクスを評価する場合、以下の点を念頭に置くこと。 計画を作る なぜ測定したいのか? その情報を使って何をするのか? その努力で、どのように組織のゴールを前に進めることが出来るのか? 基準値を確立する 比較できるようにする(比較できなければ、評価できない) コンテキストを検討する ドキュメントのコンテキスト次第で、メトリクスの解釈を誤る可能性がある 例) PV数増加 => 利用者急増? => 実はエラーページのPV数が大きく増加 => 読み手が問題を抱えている可能性が高い 複数のメトリクスを組み合わせることで、より詳細な問題発見につながる可能性がある。 この辺りは、監視と同じ。 評価の際は、フィードバック情報も参考にすると良い。 具体的な問題について、より多くの背景情報が得られる可能性がある。 10章 ドキュメントの構成 サービスの成長に伴い、ドキュメントも増加する。 ドキュメントが増加していくと、未整理、または不適切な配置のドキュメントも現れる。 未整理、不適切な配置のドキュメントを整理し、構成を組み立てなおす必要がある。 "ドキュメントに適用する構成上の組み立て" を、 ドキュメントの情報アーキテクチャと呼ぶ。 ドキュメント構成のゴールは、以下の通り。 ーザーが必要な情報を見つけるのに役立ち、 管理者が長期間にわたって保守・スケールで切るような、 コンテンツにとって最適な構成上の組み立てをつくること。 イメージは、駅や空港の地図。 以下の情報をドキュメントに組み込むことで、読み手が、コンテンツのメンタルモデル(コンテンツ構成のイメージ)を作れるよう支援する。 サイトナビゲーションと構成 ランディングページ ナビゲーションの手がかり また、プロダクトとドキュメントの進化に合わせて、サイトに対するユーザーのメンタルモデルを検証し、改善に努めること。 サイトナビゲーションと構成 サイトナビゲーションは、現在のコンテンツの地図と将来追加されるコンテンツの予定図の両方を示す。 コンテンツ整理の主要な方法は、以下の3つ。 シーケンス(順序構造) 階層(ピラミッド構造) Web (階層構造を持たない、相互リンク構造) 扱う情報に合わせて、上記方法を組み合わせて情報アーキテクチャを構築する。 チュートリアルや手順書はシーケンス、ノウハウ集は相互リンク、ランディングページは階層...など ランディングページ 「最小限の文章量で、適切なコンテンツへとユーザーを誘導する」ことを目的としたページ。 道路上で進行可能な方向を指し示している大きな標識に相当する。 ユーザーにとって、最も重要で関連のある情報は、強調しつつランディングページに乗せると良い。 ランディングページに載せるコンテンツを決める場合、ユーザー調査の結果(1章)と会社の戦略目標は良い参考情報になり得る。 ランディングページがごちゃごちゃしてはならない。 ランディングページに乗せるコンテンツは、ユーザーにとって最も重要である情報に制限すること。 ナビゲーションの手がかり コンテンツのほかの部分と、読み手の現在位置を比較できるような情報。 迷子になりつつある読み手に現在位置を示しつつ、次に向かうべき場所を知るきっかけになる。 ナビゲーションの手がかりには、以下の要素がある。 パンくずリスト 再度ナビゲーション ラベル止めたデータ 「前提条件」、「次のステップ」、「追加の情報」といった、関連情報へのリンク 間違ったページに迷い込んだ読み手向けの脱出口(「ホーム」など) ドキュメント再構成にあたって 以下の質問を投げかけ、既存のコンテンツを評価する。 このページは役立っているか? このページは最新化されているか? このページは適切な位置に配置されているか? 評価に応じて、ドキュメントへの対応を表す、以下のようなラベルを付与しておく。 そのまま 削除する 正確性をレビューする 他のドキュメントと統合する 複数のドキュメントに分割する など 評価後、「ユーザーは欲しがっていたけれど、リストに書いていない情報はあった?」と自問自答し、コンテンツのギャップを探索する。 発見したギャップが小さくなるよう、コンテンツを再構成していく。 特に、再構成に当たって、読み手は以下を期待する。 一貫している 構造に一貫性があり、目的の情報の配置場所が予測しやすい 関連している 目的の達成に役立つ、最も重要なドキュメントをすぐに発見できる 見つけやすくなっている 11章 ドキュメントの保守と非推奨化 ドキュメントに記載された情報が不正確だと、ユーザーはドキュメント、および製品への信頼を失う。 ユーザーが目的を達成できるよう、ドキュメントを保守していく。 保守計画 ドキュメントの保守に当たり、コードとドキュメントの整合が必要。 整合を取るためにも、保守計画を立てる。 コード、およびドキュメントの変更が、ユーザーへ与える影響を分析する。 今回の変更によって、ユーザーにどのような影響があるか? 今回の変更によって、プロダクトの既存機能に影響があるか? 既存のドキュメントには、どのような影響があるか? ユーザーを支援するために、ドキュメントを新規に作る必要があるか? リリースプロセスの中に、ドキュメントの保守作業を組み込むと、整合を取りやすい。 ドキュメントの変更に責任を持つ、ドキュメントオーナーを明示的に任命し、責任の所在を明確にする。 これにより、ドキュメントが古くなることの防止につながる。 そして、コンテンツの保守を担当している開発者に報いること。 ドキュメントの保守は必要な作業である、「余分な」もしくは「追加」の作業と考えてはならない。 リリースプロセスの計画段階から、ドキュメントの保守工数を見積もりに追加しておくとよさそう 保守の自動化 トイルを根絶する目的で、保守作業を自動化する。 ❓トイルとは プロダクションサービスを動作させることに関係する作業で 手作業で繰り返し行われ、自動化することが可能であり、戦術的で長期的な価値を持たず、 作業量がサービスの成長に比例する傾向を持つ...といった特徴がある。 主な保守作業は以下の通り コンテンツの鮮度確認 コンテンツの最終更新日を確認する 古いドキュメントを発見したら、記述に問題が無いかレビューを行う リンクチェッカー ドキュメントに記載されているリンクが、リンク切れを起こしていないか確認する ツールで十分確認可能 デプロイ前 : CI/CDにリンク検査プロセスを組み込む デプロイ後 : 公開後のドキュメントに対して、クローラーを使用して検査 リンター 誤字脱字、怪しい構文を自動検出・修正する リファレンスドキュメント生成 可能な場面であれば、リファレンスドキュメントを自動生成する => API ドキュメントであれば、OpenAPI書き出しなど ドキュメントの非推奨化 サービスの成長に伴い、コンテンツが非推奨化することは十分あり得る。 誤った情報をユーザーに伝えないためにも、 コンテンツの非推奨化に合わせて、関連ドキュメントにも、コンテンツが非推奨である旨を記載する必要がある。 基本的には、APIを非推奨化するプロセスと同じ要領で、関連ドキュメントも非推奨化する。 今後非推奨となる事項をユーザーに告知する...という方法もある。 以下の方法が考えられる。 リリースのお知らせやリリースノートの中で、非推奨機能の一覧を書きだす ドキュメント内に、非推奨機能の一覧を書きだす ドキュメントの削除 原則として、ドキュメントは、ユーザにとって不要になった時点で削除する。 「不要になった時点」 非推奨APIの移行が完了し、非推奨APIの利用者が0であることを確認できた場合 陳腐化・無関係化したドキュメントが存在し、その修正工数が割に合わない場合 不要な情報が減ると、ドキュメントを探索する読み手は、その分迷子になりにくくなる。 削除の前に、事前にユーザーに知らせるべき。 その際、リリースノートにて、機能削除と併せて告知すると効果的。

文書作成

2024年05月09日(木)

3.0時間

書籍「エンジニアのためのドキュメントライティング」 PART1 (1章、2章) 読了

やったこと 書籍「エンジニアのためのドキュメントライティング」 PART1 (1章、2章) 読了 学んだこと 1章 読み手の理解 ドキュメントは、読み手のためのもの。 まずは、読み手のことを知る必要がある。 「知識の呪い」は、読み手の理解を妨げる。 ❓知識の呪い 「自分が知っていることは、相手も知っている」と思い込むこと。 いくつかのステップを踏むことで、知識の呪いから逃れ、ユーザーを理解することができる。 ユーザーのゴールを特定する 「ドキュメントを読んで、ユーザーが達成したいこと」を突き止め、ゴールとして定める 注意点として、プロダクトのゴールと、ユーザーのゴールは、必ずしも一致しない ユーザーを理解する どんなユーザー(開発者・マネジャーといったロール、技術習熟度など)がドキュメントを読むのか、想定する ユーザー全員のニーズを満たすことは不可能 ビジネスやプロダクトにとって最も重要なユーザーを優先すること 例?)セキュリティ、SRE、開発では、いずれも求められる情報が異なるはず ユーザーのニーズを理解し、ドキュメントがそれをどう解決するか理解する 詳細は後述 わかったことを、ツール(ペルソナ、ストーリー、マップなど)を使ってまとめる フリクションログを使って仮説検証する ユーザーの立場に立って、ユーザーの目的達成を阻害する要因(≒フリクション)を自分で体験する よくあるユースケースを定義し、自分でなぞらえると良い ❓フリクション(ログ) 摩擦や抵抗のこと。 特に、ソフトウェアやサービスをうまく使えなかったことや違和感といった体験を示す。 "フリクションログ" だと、摩擦や抵抗を示す記録。 ユーザーのニーズを理解し、ドキュメントがそれをどう解決するか理解する ドキュメントで答える必要がある(≒ユーザーが疑問に思う事項)のリストを作る。 よくある疑問は、以下の通り。 これは何のプロダクト? 個のプロダクトが解決する問題は? どんな機能がある? 費用はどれぐらいかかる? どこから始められる? 出来上がったリストを、「アウトラインの作成」という形でまとめる。 アウトラインが出来上がり次第、「ユーザーは誰か」「ユーザーのゴール」「ユーザーのニーズ(アウトライン)」を検証する。 検証の際は、ユーザーのウォンツ(要望)ではなく、のニーズ(要求)に焦点を当てること。 主な検証方法は以下の通り。 サポートチケットなど、存時の情報リソースを使う インタビュー、アンケートなどで、新しいデータを集める 2章 ドキュメントの計画 ユーザーのニーズに合わせて、コンテンツの種類(手順書、クイックスタートなど)を決定していく。 よく使われるコンテンツタイプは以下の通り。 コードコメント README スタートガイド コンセプトドキュメント 手順書 チュートリアル ハウツーガイド リファレンスガイド トラブルシューティングドキュメント 変更に関するドキュメント リリースノート 質の高いドキュメントを作成するために、ドキュメント作成の計画を立てる。 以下の質問に答えることで、ユーザーにとって適切な情報を絞り込むことが出来る。 対象の読み手は誰か? プロダクトのローンチから、ユーザーに一番学んでもらいたいことは何か? 重要度順で考えると、どの機能からリリースされていくか? ユーザーはローンチに何を期待しているか? ユーザーがプロダクトや機能を使い始める前に必要な事前知識はあるか? 何のユースケースをサポートしているか? ユーザーが躓きそうな既知の課題や、フリクションはあるか? これらの質問に答えることで、コンテキストを形成できる。 コンテキストが分かってくると、何から作り始めればよいか決められるようになる。 コンテンツのアウトライン作成から、ドキュメント計画を立てると良い。 以下、コンテンツアウトラインの例 タイトル コンテンツのタイプ 簡単な説明 xxx スタートガイド スタートガイド xxxを使うための非常に簡単なデモと他のドキュメントへのリンク xxx yyy機能の解説 コンセプト yyy機能の仕組みの技術説明 認証方法 ハウツーガイド 認証スルタンのステップバイステップ手順 APIリファレンス APIリファレンス API呼び出し方法と構文の一覧 リリースノート l変更履歴 xxxのリリースノート 以下、コンテンツタイプ別の追加情報。 コードコメント コーディング上の意思決定とその背景や、トレードオフを記録することで、読み手である将来の開発者の時間を節約する 過剰なコメントは、保守コストが増大することを念頭に置くこと README 以下の役割を担う 読み手に、システム全体の概要を理解してもらう リポジトリに対するチートシートとして機能する ユーザーが利用する包括的なドキュメントの基礎(ポータル)として機能する より詳細な情報が必要な場合は、重要なサブフォルダに追加情報を配置し、追加情報へのリンクをREADMEに貼る テンプレート スタートガイド 読み手(ユーザー)の立ち上げを支援する より高度(≒専門的・詳細)なコンテンツへ進む前のスタート地点として機能する スタートガイドを書く上で、自身に問うべき質問は以下の通り サービス内容と核となる機能を一番短く説明するなら? プロダクトをインストールして使うための最も簡単な方法は? 新規ユーザーが感じる最も重要な疑問は? サービスを使ってできるすごい事は何か? コンセプトドキュメント サービスの裏側にある考え方とアイデアの理解を助ける 手順書やチュートリアルの背景を説明する ... といった用途で作成する 実装に関する詳細は、コンセプトドキュメントの領分ではない(手順書などの領分) テンプレート 手順書 具体的には、「チュートリアル」と「ハウツーガイド」が該当する 読み手(開発者)が、特定のゴールを達成する方法を、手順として説明する 以下、手順書作成時のガイド できるだけガイド単体で読めるようにする ユーザーが必要とするすべての行動を1つのページにまとめる 手順数を最低限に絞る ステップが多いほど、読み手は複雑に感じ、ミスが多発する ステップが多いほど、手順書の保守が大変になる 長文説明を避ける 説明が長すぎると感じたら、コンセプトガイド等に分割すること チュートリアル 手順書に分類されるドキュメント 読み手に、特定のゴールを達成する方法(≒手順)を伝える(≒学習させる)ことを目的とする 長く、時間のかかるチュートリアルを、ユーザーがやり遂げる可能性は低い 長すぎる手順は、サービスが複雑すぎる可能性を示唆する ハウツーガイド 手順書に分類されるドキュメント 現実のビジネス課題を解決するための、特定の手順を説明する チュートリアルのような学習目的ではなく、実装に基づく課題解決が目的 以下、良いハウツーガイドの特徴 シンプルな言葉を使用する 行動を明確にする ハイツーガイドが解決する問題を継続的に改善する ガイドの冒頭には、前提条件を入れると良い リファレンスガイド 行動とその結果を説明する APIリファレンス、用語集、トラブルシューティングドキュメントなどが該当する トラブルシューティングドキュメント リファレンスガイドに分類されるドキュメント 既知の問題に対して、その回避策、または解決策を説明する 説明よりも、回避策に集中すること 読み手の大部分は、「なぜ問題が発生したか」ではなく、「どうやったら問題を回避、または解決できるか」に関心を持つため エラーメッセージとその説明、および解決策を列挙するのも手 テンプレート 変更に関するドキュメント リファレンスガイドに分類されるドキュメント 変更時期、顧客に影響が出たタイミングなどを整理し、トラブルシューティングに役立てる 以下の情報を記録する 過去のサポートバージョン、統合、または廃止予定の機能 パラメータや重要なフィールドの名前の変更 オブジェクトやリソースの移動 リリースノート リファレンスガイドに分類されるドキュメント(特に、変更に関するドキュメントの一種) 変更履歴の背景情報を記載し、読み手に対して、ある変更が生じた理由を説明する リリースノートには、以下の内容を記載する 新機能 バグ修正 既知のバグや制約 移行方法 テンプレート

文書作成

2024年05月05日(日)

3.0時間

書籍「エンジニアのためのドキュメントライティング」 PART2 (3,4,5,6章) 読了

やったこと 書籍「エンジニアのためのドキュメントライティング」 PART2 (3,4,5,6章) 読了 学んだこと 3 章 ドキュメントのドラフト 白紙のドキュメントの冒頭に、「読み手、目的、コンテンツパターン」を書くところからスタート。 タイトルを決める 「読み手、目的、コンテンツパターン」が決まると、タイトルを決定できる(特に「目的」は有用)。 タイトルを見た瞬間、ゴールがイメージできるようなフレーズにする そのため、キュメントのゴールは一つに絞ること 複数のゴールが存在する場合、ゴールが一つになるようドキュメントを分割すること アウトラインを作る 読み手が、タイトルに書いたゴールを達成するために、読み手が知っておくべきこと、やるべきことを考え、必要な手順を列挙する。 ゴールを達成するために、ゴールをサブタスクに分割するイメージ 正しいタイミングで、正しい情報を読み手に提供できるよう、アウトラインを修正する。 順序を変える (必要に応じて)項目を追加・削除・変更する 複雑すぎる場合、項目を分割する 以下の質問を自身に投げかけ、アウトラインをレビューする。 追記すべき事前情報や設定情報はあるか? 飛ばしている手順や、説明が不完全な手順は無いか? 手順は合理的な順で並んでいるか? アウトラインに自信が持てたら、アウトラインの項目を肉付けしてく。 流し読みに対応する 大多数の読み手は、必要な情報を求めてドキュメントを流し読みする(F 型)。 流し読みする読み手を想定し、必要な情報を見つけやすくすることは重要。 流し読みする読み手に役立つコンテンツ作りの戦略は、以下の通り。 最も重要な情報を冒頭で述べる ドキュメントのゴールを要約して、タイトルに設定する 大きな文章の塊を分割する 複数の長文ドキュメントを分割する 簡潔さと明確さに向けて努力する 「このコンテンツで読み手のニーズを満たせているか?」と問い、改善に努める ドラフト作成に行き詰ったら 完全主義からの脱却 かけるところから書く 周りの人に、助けを求める 足りないコンテンツを強調する 書けない(重要な情報が欠けているなど)箇所は、TODO, T.B.D. などと書いていったんスルー 確信をもって書ける部分から書いていく 順不同で書く 書けるところから書く メディア(ツールや手法など)を変える ドラフトを完成させる 以下、ドラフト完成のチェックリスト。 [ ] 大見出しはドキュメントのゴールを要約しているか? [ ] 複数の見出しによってドキュメントは十分に要約されているか? [ ] ドラフトは最初から最後まで読み手のニーズにこたえているか? [ ] 情報の流れは読み手に取って理解しやすいものか? [ ] 何らかのドキュメントパターンやテンプレートに正しく従っているか? [ ] 全手順が動作することをテストし確かめたか? 4 章 ドキュメントの編集 ここで言う編集とは、ドキュメントを見て、ユーザーニーズに応えているか確認するプロセス。 レビューや評価といった、分析的なプロセスではない。 編集方法 編集プロセスを一連の複数の周回に分解して、一つの周回で一つの観点に絞って編集すると良い。 編集速度が向上する 開発者向けドキュメントだと、以下の観点で編集を周回すると良い。 技術的な正確さ 観点 指示通りに作業すれば、ドキュメントに記載された結果が得られるか? 技術的な専門用語、もしくは混乱しやすい用語はあるか? コードの関数、パラメータ、エンドポイントは正しく命名され、説明されているか? 手順があれば、指示通り実行して、うまくいくことを確認すること 手順に制約条件があれば明記する事 完全性 観点 TODO, T.B.D. が無いこと コンテンツにギャップが無いか OS 上の制約や情報の有効期限があれば記載する 構成 観点 タイトルと見出しから、何について書かれたドキュメントか明確になっているか? ドキュメントは、一貫性のある、論理的な方法で構成されているか? 他のドキュメントに配置すべきセクションは無いか? テンプレートが存在するならば、テンプレートに従って書かれているか? 一貫した構成は、予測が可能となり、読み手が適切な部分にたどり着きやすくなる 読み手がコンテンツを読む前後にすべきことが無いか確認する 読み手は、前後のドキュメントを読まず、いきなり特定の章から読み始めることが少なくないため 明確さと簡潔さ 不自然な表現は書き換え、重複情報を削除し、不要な言葉を取り除く コンテンツはできる限り短くし、要点を絞る さしずめ、ドキュメントに対するリファクタリング ドキュメントレビュー 自身でレビューする場合、以下のチェックリストを使用する。 [ ] タイトルが短くて具体的である [ ] 見出しは論理的に並べられており、一貫性がある [ ] ドキュメントの目的が最初の段落で説明されている [ ] 手順はテストされていて動作する [ ] 技術的なコンセプトが説明されている、もしくはリンクされている [ ] テンプレートの構成に従っている [ ] リンクがすべて有効である [ ] 誤字脱字・文法チェックツールが実行されている [ ] グラフィックや画像が明確で有用である [ ] 前提条件や次のステップが定義されている 他のメンバーにレビューを依頼する場合、レビューの観点を伝えること。 構成をレビューしてほしいのか?技術面なのか?明確さと簡潔さを見てほしいのか? など また、フィードバックの受け取り方も合意しておくこと。 場合によっては、専門家にレビューを依頼する(=>テクニカルレビュー) もらったフィードバックを取り入れる ドキュメントのゴールは、知識を読み手に効果的に伝えること。 フィードバックは、非難ではなく、より効果的に伝える方法を指摘するものだと捉える。 矛盾したフィードバックがある場合、「ユーザーがこのドキュメントを読んで達成したいこと」、つまりはゴールを満たすことに繋がるフィードバックを優先する。 どのみち、全てのフィードバックに対応するのはリソース的にも困難となりやすい 良いフィードバックを提供するためには、以下を守る。 フィードバックの際は、「人」ではなく、「アイデア」に集中する 「あなたが間違っている」ではなく、「この部分が不明確だ」といった具合 批判に続けて、建設的な代替案を出す フィードバックに反応するための時間を確保する また、フィードバックでは素晴らしかった部分を伝えてもよい。 素晴らしい文章を共有することで、他の人がまねできるようになる。 5 章 サンプルコードの組み込み 良いサンプルコードは、文章で説明する以上に多くの情報を読み手に提供できる。 サンプルコードは、一般的に「説明用」と「実行可能なもの」の二種類存在する。 実行可能なサンプルコードは、コピペ(かつ必要に応じて改変)して実行できるコード 説明用のサンプルコードは、読み手の理解向上や、読み手の環境での実行結果を比較する目的で使用するコード 良いサンプルコードの原則 読み手は、サンプルコードが(可能ならコピペしてそのまま)動作することを期待する。 そんな、良いサンプルコードは、以下の原則を満たすべき。 説明されていること サンプルコードのそばに、コードの必要性を説明したコメントが存在すること コードを動かすために必要な前提条件が、全て説明されていること 制約などがあれば、きちんと書くこと 簡潔であること 読み手が必要とする、過不足ない量の情報が提供されていること 明確であること 読み手が期待する言語習慣に従ってサンプルコードが書かれている 読み手が混乱しないよう、複雑なテクニックは避ける 加えて、実行可能なコードは、以下の原則を満たすべき。 利用可能(であり拡張可能)であること パラメータの置き換えが必要な場合、置換用データを説明する 何で置き換えればよいのか一目でわかる変数を使用すること your_password や replace_with_actual_xxx など 信頼できること ペースト可能であり、動作し、余計なことを実行しない サンプルコードの設計 サンプルコードの設計に当たっては、以下の点を留意する。 読み手になじみがあって、最も使われそうな言語を選んで、サンプルコードを作成する 快適さ・理解度合いに幅がある読み手をサポートするため、様々な複雑さのサンプルコードを提供する 初心者向けだと、 hello_world レベル 習熟した読み手向けだと、 特定のユースケースに特化したサンプルコードなど 入門者向けドキュメントと、熟練者向けドキュメントを混同しないよう注意すること コードだと一目でわかるような、一貫したスタイルでサンプルコードを提供する Markdown なら バッククォート がメジャー その他、サンプルコードに関する Tips 実行可能なコードは、動作確認しておくこと 場合によっては、読み手が自由にコードを試せるサンドボックスを提供する 多くのユースケースでは過剰な選択 サンプルコードを自動生成する 背景説明といった文脈が必要な場合、人手によるコメント追加も行うこと 6 章 ビジュアルコンテンツの追加 " 百聞は一見にしかず " 。 ビジュアルコンテンツはドキュメント補助が目的。 ドキュメントの代替にはなり得ない。 ビジュアルコンテンツの目的は、ドキュメントの理解促進であり、これに寄与しない情報は全て邪魔、ぐらいに思っておくこと。 読み手の必要とする情報と、作り手の好みは、異なることが多い ビジュアルコンテンツは、以下の三点を満たすことを常に意識する。 理解容易性 読み手に役立つ情報であること アクセシビリティ 読み手を限定しないこと パフォーマンス ビジュアルコンテンツの掲載によって、ドキュメント表示が遅くなり、読み手の時間を奪わないこと ビジュアルコンテンツも、ドキュメント同様にレビューすること。 その際、上記三点を満たしているかがレビューの観点となる。 ビジュアルコンテンツの例 スクリーンショット 可能なら、画像が表現している情報を、文章でも表現すると良い 加えて、画像が、さも存在しないようなコンテンツ説明文にすると良い ×「メニュー上部にある小さな歯車の画像」 〇「メニュー上部に小さな歯車があります」 コピペが必要になりそうな情報をスクショで提供しないこと 図表 ボックスと矢印 文書単体では説明が難しい、エンティティ間のデータの流れや関係性をわかりやすく描くことが出来る 使用する図形に一貫性を持たせること 必要なら凡例を記載すること フローチャート プロセスをドキュメントに落とし込むことが出来る 使用する図形に一貫性を持たせること スイムレーン 複数のコントリビューター(もしくはアクター)が存在する状況を表現できる 複数のコントリビューター(もしくはアクター)が存在することを除けば、特徴はフローチャートと同じ 図の目的は " 単純化 "。 一つの図で表現するアイデアは、一つに絞ること 場合によっては複数の図に分割すること 図表の要素には、可能なら、読み手の理解を促進するようなラベルを付与すること 色に一貫性を持たせること 基本は、ラベルで情報を伝える 可能なら SVG 形式で画像を公開すること 映像コンテンツには注意 映像コンテンツには、以下の問題点があり、総じて高コスト。 作成には専門知識が必要であり、素人には難しい 修正が困難(≒保守コストが非常に高い) 基本的には、上記問題点によるデメリットが大きい。 数枚の図で大体できないか検討すること。

文書作成

2024年05月05日(日)

3.0時間

書籍「実践NextJS」1章 読了

やったこと 書籍「実践NextJS」1章 読了 学んだこと Route 系の用語整理 Tree/Subtree Tree ... 階層構造 Subtree ... 入れ子のTree Root ... TreeまたはSubtreeにおける根っこのノード Leaf ... 子を持たないノード Segment / Path example.com/profile/settings example.com ... ドメイン名 profile , settings ... Segment profile/settings ... Path 特定のPathに対応する Segment を、 「Root Segment」 と呼ぶ。 末端(≒子Segment を持たない)Segment を Leaf Segment と呼ぶ。 Dynamic Route / Dynamic Segment Pathが動的に変わり得るRouteを Dynamic Route と呼ぶ。 ID情報を含む場合など Dynamic Route を構成するSegment を Dynamic Segment と呼ぶ。 Route Segment の構成 app ディレクトリを頂点に、ファイル配置でRouteを表現する。 src/app/ ├── company-info │ └── page.tsx // localhost:3000/company-info ... └── page.tsx // localhost:3000/ (ルート) layout.tsx Header , Footer , サイドナビなど、全画面共通で表示したいUIを実装する場所。 また、layoutファイルはネスト出来る。 つまり、layoutファイルは、Segment毎に設けることが出来る。 Segment は Pageファイル必須ではなく、layoutファイルだけでも良い。 ナビゲーションの概念と用語 ハードナビゲーション ... 画面を再読み込みする画面遷移 ソフトナビゲーション ... 画面を再読み込みしない画面遷移 ※ナビゲーション ... 画面遷移のこと NextJS の SPAは「ソフトナビゲーション」。 加えて、データやレンダリングした画面をキャッシュしてくれる。 Dynamic Segment [categoryName] 部分が Dynamic Segment。 ディレクトリ構成 ├── categories │ └── [categoryName] │ └── page.tsx index.tsx ... <li> <Link href="/categories/flower">花</Link> </li> <li> <Link href="/categories/animal">動物</Link> </li> ... 所感 NextJS で言う Route は、ファイルシステムに近そう "Root Segment" の解説から、どのSegment も、必ずRootを持つ...ということになりそう layout ファイルを使いこなすことで、コードを共通化 が捗りそう dynamic segment は、機能としては理解できたが、有効なユースケースが思い浮かばない 経験を積めばわかるかな?

Next.js

2024年04月13日(土)

2.0時間

SAP on AWS 練習問題 100問

やったこと Udemy SAP on AWS 練習問題 100問解いた 学んだこと メモ SAP oracle ワークロードは、SUSE Linux ではサポートされていない SAP HANA をAWS上で動かす場合、推奨OSはRHELかSUSE<br>SAPアプリケーションの場合、OSは色々(RHEL,SUSE,Oracle Linux, WIndows Server あたりがメジャー) システム移行 : AnyDB => HANA HANA DB をバックアップから復元する際は、 テナントDBのみ必要。SYSTEMDBは不要。 移行には、 "移行キー" なるデータが必要。 SAP Support Portal からダウンロードできる模様。 AWS Application Migration Service (MGN) <br>- ブロックレベルのレプリケーションを提供<br>- 基盤となるOSとDBを変更しないまま移行する、リフトアンドシフト向け AWS Data Provider for SAP : SAPアプリケーション関連のパフォーマンスメトリクスを収集できる ABAP プラットフォーム 1809 以降 => SAP カーネル version 7.73 以降 Oracle DB サポート状況は ... OS : Oracle Linux , Oracle 11g R2以降がサポート Launch Wizard にて、以下の流れでカスタムスクリプトを実行可能<br>- S3にカスタムスクリプトをアップロード<br>- Launch Wizard 所定の画面にて、スクリプトのS3 URLを指定<br>または、Launch Wizardから直接スクリプトをアップロードできる。 SAP カーネル version 7.45以降では、 IMDSv2をサポートしている。未満では、v1のみサポート SAP HANA データベースへのオプション 「SAP HANA 動的階層化」<br>ホット層よりもウォーム層に最大 5 倍のデータを保存できるようになり、クエリや更新に使用できるオンライン データ ストレージが可能になる。 HANAの移行。OS は変えずに、 AnyDB => HANA SAP 拡張モニタリング : SAPOSCOL 拡張機能<br>SAP システム内に追加のパフォーマンス メトリックとモニタリング機能を提供。<br>Cloud Watch 詳細モニタリング、Data Provider for SAP と並んで、監視用メトリクス設定の最有力候補 Backint Agent は、SAP HANA version 1.0 SP12 をサポート HANA Backint Agent ... DBのネイティブソリューション。 RHELおよびSUSEでサポート。<br>AWS Backint Agent ... DBのネイティブソリューションではない 。AWSが提供する、SAP認定ツール。 u-*tb1.metal は、ホスト テナントを持つ専用ホストとしてのみ起動できるベアメタル サーバー。 <br>u-*xlarge バリアントは、デフォルト、専用、またはホスト テナントで起動できる。 ファイル システムの SAP インスタンス セキュア ストア (SSFS)<br>データボリューム、各種ログ、バックアップの暗号化、暗号化用ルートキーの保護を提供する、DBネイティブ機能。 SAP HANA コックピット にて、バックアップ保持ポリシーを変更できる。<br>古いバックアップを自動削除する場合に活用できる。 IBM Db2 高可用性災害復旧用のオーバーレイ IP アドレス ルーティングを有効にするには、データベース EC2 インスタンスのソース宛先チェックをオフにする必要がある。<br>オンのままだと、送信元宛先チェックにより、トラフィックがブロックされる。 Oracle DBの移行 & エージェントのインストール不可 => Oracle Data Guardを使用したOracleデータベースのレプリケーション SLIC_HW_VERSION Linux 環境変数 : ハードウェア キーの計算に同じネットワーク カードが常に使用されるようになり、ライセンス キーが無効になるのを防ぐことができる

AWS

2024年01月21日(日)

3.3時間

Design It! 13章 チームのアーキテクト力を強める 読了

やったこと Design It! 13章 チームのアーキテクト力を強める 読了 学んだこと ポイント 現在、アーキテクトに求められる役割、仕事 なぜ、チームのアーキテクト力を強める(高める)必要があるのか チームのアーキテクト力を強める(高める)ために何ができるか 学び 現在では、チームのアーキテクト力を強める(高める)ことが求められる チームを成長させ、価値を生むアーキテクチャを設計できるよう導くことが、アーキテクトに求められる チームのアーキテクト力を高めると、以下の効果がある チームに、「自分たちのシステム」という意識が芽生え、以下の効果が得られる 皆が設計の意図を理解でき、設計の一貫性を保ちやすくなる コミュニケーションが効率化される アーキテクチャを批評できる人間が増え、以下の効果が得られる 品質が向上する 設計判断が早くなる などなど チームのアーキテクト力を強める(高める)ために、アーキテクトは以下を実施できる チームに、「自分たちのシステム」という意識を持ってもらう 「自分たちのシステム」という共同所有意識を持ってもらう そのために、チームメンバに多くの学習と成長の機会を与える チームの成長度合いに応じて、適切に権限を委譲していく アーキテクチャを協働で設計する メモ 現代ではコンテナやクラウドの台頭により、様々な技術を手軽に利用できるようになった。 私たちは、これらの技術を使用して、強力なアーキテクチャを構築できる。 同時に、私たちは、様々な技術の中から、自分たちの問題を解決できるものを適切に選択できる必要がある。 現在、開発者とアーキテクトの違いは希薄になっている。 アーキテクトに求められ得る役割は、以下のように変化している。 従来 : トップダウン型のリーダー 現在 : 一緒に設計でき、チームの能力を向上させることができるリーダー そんな現在のアーキテクトは、コーチであり、メンターであり、技術の第一人者である。 アーキテクチャを理解しているメンバーが増えるほど、チームは難しい問題へ取り組むことが可能になる。 こうした理解は、システムを共に設計することによって生まれてくる。 この章では、チームを成長させ、力を与える方法に触れていく。 アーキテクチャ思考を促進する メンバー全員がアーキテクチャに関心をもち、アーキテクトであろうとするチームは、以下の恩恵が得られる。 ソフトウェア品質が向上 ソフトウェアを批評できる人間が多いほど品質が向上する、という意図 迅速な設計判断 共同所有意識が高くなる => 「自分たちのシステム」という意識が芽生える 「自分たちののシステム」という意識が芽生えた結果、誰もが設計の意図を理解でき、設計の一貫性を保ちやすくなる。 コミュニケーションが効率化され、開発のベロシティも向上する。 メリットは非常に大きい。 大まかな方針は、「チームの設計スキルを高めながら、同時にそれを使ってアーキテクチャを設計していく」こと。 これを実現するため、チームが順調に進む手引きを行い、学習と成長の機会を与える。 (設計判断を全部監視したりしない) 意思決定を促し、スキルの成長を促進する 共同所有意識を高めるには、チームに学習と成長の機会を与える。 普通のソフトウェアアーキテクト 優れたソフトウェアアーキテクト チームの手を借りることなく、一人でパターンと技術を選定する チームの意見に基づいて協働してパターンと技術を選択する 詳細なドキュメントを書く。ドキュメントを完璧に完成させ、一度だけリリースする チームでドキュメントを作成、レビュー、更新する。得た知見から、チーム用のテンプレートを構築する 全ての設計判断を下す チームに判断方法を教える。設計判断を行うために必要な情報をチームに提供する。レビューとフィードバックに努める 誰が特定の要素を構築するか決める チームが自己組織化し、自分でタスクを選択できるようになるよう手伝う アーキテクチャへの変更を避ける アーキテクチャを変更しやすくする 技術的な判断を下す 技術的な判断について合意形成を行う 優れたアーキテクトになるために何が必要なのか? これを、チームが学んでいく必要がある。 学ぶために必要なことは、「練習」である。 安全に実践する機会を作り出す 設計判断を学ぶため、練習の機会を設ける。 練習には、以下のような手段がある。 ペア設計 経験あるメンバーとペアとなって設計作業を行い、学びを得る 足場を作る 学習促進及び強化を目的とした支援構造 設計作業をサポートするためのテンプレート作成 建設的な批評 スケルトンコード作成 良い例と悪い例を共有 アーキテクチャのガイドレールを導入する 設計の選択肢を制限し、目的範囲から逸脱しないことを助ける仕組み 設計ポリシー ... やるべきことや避けるべきことを説明した指示。シンプルだが強制は困難 コードに対する静的解析の導入 説明会(勉強会)を開く 設計権限を委譲する 大事なのは、重要な品質特性(つまりアーキテクチャ)を危険にさらすことなく、できるだけ多くの設計権限をチームに委譲すること。 「権限の7つのレベル」という考え方がある。 この考え方から、委譲すべき権限、そうでない権限を判断できる。 権限レベル 名前 概要 1 指示する アーキテクトが設計判断を下し、チームに指示する 2 説得する アーキテクトが設計判断を下し、その判断が正しい理由をチームに示す 3 相談する 設計判断を行う前にチームに意見を求める。設計判断はアーキテクトが行う 4 合意する チームと協働し、チームの判断として設計判断に合意する 5 助言する アーキテクトは助言や知見共有に留まり、設計判断はチームが行う 6 尋ねる チームが行った設計判断に対して、アーキテクトは、その判断が正しい理由をチームに尋ねる 7 委譲する アーキテクト以外のメンバーで設計判断を行う。チームが、判断に責任を持つ 状況に応じて、適切な設計権限を適切なレベルで委譲する。 「適切」を把握するには、試行錯誤が必要。 以下のような場合では、設計権限を維持する方向で検討すると良い。 失敗のリスクが高い場合 チームが未熟な場合 権限レベル1,2,3 ぐらいでよい 確信が持てない時、「適切な機会が現れるまで設計権限を維持する」という判断を下すのは悪くない。 反対に、以下のような場合設計権限を委譲する方向で検討すると良い。 チームが既に経験を積んでいる場合 チームがアーキテクチャについて学ぶようになり、チームを導け得る自信が得られてきたら、共同ワークショップを実践すると良い。 共同ワークショップの中で、権限レベル5,6,7辺りで振る舞うことが出来る。 (この時、アーキテクトはファシリテーターとしてチームをサポートすることになる) 意思決定プロセスに複数のステークホルダーを巻き込む例 アーキテクチャについての会話もするよう、チームに働きかける 協働ワークショップへの参加を働きかける デザインスタジオ、リスクストーミング、シナリオウォークスルーなど チームの影響力を確認し、発生していることを理解する アーキテクチャーブリーフィング、サニティチェックなど 良い例が存在する場合には、成果物の作成を委譲する 共にアーキテクチャを設計する 顧客に価値を届けるのはアーキテクチャであり、アーキテクトではない。 チームが価値を生むアーキテクチャを設計できるよう導くことが、アーキテクトの仕事である。 アーキテクトの重要な責任を次のように見直す。 エンジニアリングの観点から問題を定義する アーキテクトには、アーキテクト上重要な要求、特に品質特性を鄭ぐする責任がある。 ステークホルダーの真のニーズを見誤らないよう、人間中心の設計手法を駆使して要求を収集する。 システムを分割し、要素とチームに責任を割り当てる チームを導き、望ましい品質特性を促進するパターンを見つけ出す。 重要な品質特性が確実に達成されるよう、最小限のアーキテクチャを設計し、その他のすべての判断を後続の設計者に委ねる。 全体に目を向け、設計の一貫性を保ち続ける 設計が現れてくるタイミングでは、それをしっかり把握する。 アーキテクチャを実装するタイミングではチームを手助けする。 チームやステークホルダーに適した最も軽量な文書化を行い、設計判断を正確なモデルとして記録する。 記録したモデルから、システムを見通したり、判断を評価したり、リスクを明らかにしたりする。 品質特性間のトレードオフを決定する 設計判断を重ね、アーキテクチャが進化する中で、チームがトレードオフを調整するのを助ける。 リスクを使い、どれくらい設計するかや、何に専念するかを決定する。 技術的負債を管理する やむを得ず負った技術的負債を認識し、返済の戦略を立てる。 技術的負債を、「成功のために避けられない結果」と捉え、負債を負うことと返済をうまく計画に組み込み、戦略的に管理するよう努める。 チームのアーキテクチャスキルを高める チームに、「自分たちのシステム」という意識を持ってもらえるよう、働きかける。 チームのためにアーキテクチャを設計するのではなく、チームと共にアーキテクチャを設計する。

ソフトウェアアーキテクチャ

2024年01月21日(日)

2.0時間

Design It! 12章 アーキテクチャに通知表をつける 読了

やったこと Design It! 12章 アーキテクチャに通知表をつける 読了 学んだこと ポイント アーキテクチャ評価とは 良いアーキテクチャ評価の特徴 評価ワークショップの目的 学び アーキテクチャ評価とは、アーキテクチャがどの程度目的を達成しているのか知るプロセス 良いアーキテクチャ評価 頻繁に評価を行い、フィードバックサイクルを回す 評価の観点 アーキテクチャはどの程度良いか? アーキテクチャはどのように良いか? 評価と価値のバランスを取る イメージは、テストピラミッド たくさんの軽い評価と、少数の重い評価でバランスを取る 様々な課題を探る いくつかある観点から、アーキテクチャにおける課題を探り、既知の未知をふやす 同じ観点の問題ばかり探るのは、よくある失敗 評価ワークショップを開き、評価に必要なデータを収集して分析し、改善に役立てる メモ アーキテクチャを評価・改善することによって、後続のプログラミングは、更に効率的なものになる。 評価から得たフィードバックは、学び、設計判断への肯定的な意思の作成、リスク軽減、アーキテクチャの改善など、様々なことに活用できるはずだ。 評価し、そこから学ぶ アーキテクチャの評価は、アーキテクチャが目的を満たしている程度について学ぶプロセス。 アーキテクチャの評価は何回か行うことになる。 少なくとも、「最後に一度だけ実施すればよい」という考えは間違っている アーキテクチャ全体を一度に評価するのは非常に困難 アーキテクチャが誤っていれば、振出しに戻る 評価で得るべき学びの観点は、以下の二つ。 アーキテクチャはどの程度良いか? アーキテクチャはどのように良いか? アーキテクチャが、「アーキテクチャ上重要な要求」を十分に満たしているほど、アーキテクチャは目的を満たしているといえる。 設計をテストする アーキテクチャを 早くにテストし、早く失敗し、早くフィードバックを得よう。 このサイクルを素早く回そう。 アーキテクチャの評価に必要なものは、以下の3つ。 視認できる成果物 ステークホルダーの視点から見た「よりよい」または「悪い」を定義したルーブリック レビュー計画 ◆ルーブリック 学習の達成度を示す評価基準を、観点と尺度からなる表として示したもの 評価できるものを作る 実物が無ければ、評価は非常に難しい。 ホワイトボード上のスケッチでも、アーキテクチャ記述でも構わないので、視認できる成果物を作成する。 欲しいフィードバックに合わせて、評価の準備を行う。 例)特定の品質特性の評価が欲しいなら、品質特性に関連するレビューの準備を行う ... など デザインルーブリックを定義する デザインルーブリックとは、アーキテクチャの適合性を判断する時にレビュアーが採用する基準を定義するもの。 ルーブリックは、「観点」と「尺度」から成る。 観点に品質特性シナリオを例としたルーブリックを示す。 品質特性 シナリオ(観点) 評価 (1-4) 可用性 インデックスが利用できない場合でも応答する 可用性 メンテナンス中を除いて、結果は常に返される パフォーマンス 結果は平均負荷で5秒以内に表示される スケーラビリティ このシステムは、今後7年間で年間5%のデータ増加を処理するように拡張できる 評価尺度 ... 観点の評価方法を定義 1 : 期待に応えられない、または評価できない ... 4 : シナリオを満足させる ルーブリックを作成する際のポイントを示す。 観点は、アーキテクチャ上重要な要求に基づいて選択する 以下を満たす、優れたルーブリックとなり得る 重要かつ不可欠 観点が重複しない 観察可能かつ測定可能 明確 観点の評価尺度を決定する 上記例では 1 ... 4 の4段階だが、2段階など、必要に応じて変更できる 5段階以上は、使用を控えること 評価者によって尺度のブレが生じ始めるため レビュアーが評価した際、「何を考えてその評価を下したのか」という情報は非常に貴重。 これを得るために、インサイトを生成する。 インサイトを生成する インサイトとは、「設計がアーキテクチャ上重要な要求を満たしているか」をレビュアーが意見するために使用するもの。 インサイトは、アンケートや探求、リスクの導出やコードの分析など、様々な方法で生成できる レビュアーがインサイトを文字や言葉にするのを助け、評価を下した理由を明確化する。 ルーブリックで答えなくてはならない情報は何か?を把握すると、どういったインサイトが効果的か見えてくる。 ルーブリックの観点 観点を評価するのに役立つインサイト リスクの量 リスクストーミングなどでリスクを明らかにする 不確実性の量 質問-意見-懸念のワークショップを開き、未解決の質問を生成する レビュアーの合意 投票、アンケート、サムズアップ評価など デザインの一貫性 設計状態を一覧化する 問題への適合度合い 不安定な部分、問題点、リスク、質問を見つけ出す。 技術的負債 現在実装できない、付加価値あるユースケースを一覧化する 品質 品質の高低の閾値を定義する 評価ワークショップを開く アーキテクチャ評価ワークショップの目標は、アーキテクチャを評価するのに必要なデータを集めて分析する事。 望ましい品質特性やその他アーキテクチャ上重要な要求をどれだけ満たしているか確認する。 大体、以下の流れ。 準備する ルーブリックの定義、レビュアーの招待、評価で使用する成果物の検索または作成など レビュアーには、アーキテクチャで使用する技術に明るい人物が良い レビュアーに前もって伝える - 評価の目的、システムのコンテキスト、成果物、ルーブリックなど、評価に必要な背景情報を前もって伝える 評価する 分析する リスクと未解決の問題を探し、アーキテクチャがどのように良いか判断する 事後点検する ワークショップで得た学びから、次のアクションアイテムを決定する 見解の要約とアクションアイテムを、すべての参加者に共有する 早くから評価をはじめ、頻繁に継続的に評価する 早い段階で評価するほど、早く改善できる。 可能であれば、アーキテクチャ評価を開発ルーチンに組み込もう。 評価ピラミッドを使ってコストと価値のバランスを取る 評価ピラミッドのイメージは、テストピラミッド。 大部分は、低コストで素早くチェックできる評価 個別の設計判断 少数の、徹底的で高コストな評価 システム全体と、いくつかのアーキテクチャ上重要な要求の相互作用 上記二つの評価の間に一貫性を持たせる、対象を絞った評価 一つの判断、コンポーネント、アーキテクチャ上重要な要求 様々な課題を探る アーキテクチャにおける課題を探る観点を示す。 リスク 発生する可能性があるものの、まだ発生していない良くないこと 未知のこと 未解決の問題から得られる、わかっていないこと 既知の未知と、未知の未知は全然違う 問題 顕在化してしまった、良くないこと 理解のずれ ステークホルダーの考えと設計のずれ 進化するアーキテクチャに対して、理解が遅れている など アーキテクチャの浸食 設計されたアーキテクチャと実装されたアーキテクチャの差 状況の横滑り 新事実の発覚や状況の変化によって、ビジネスの推進要員や判断を左右するコンテキストが変化すること 常に同じ種類の問題を探そうとしてはならない。 様々な課題を探ることで、既知の未知を増やすことが出来る。

ソフトウェアアーキテクチャ

2024年01月18日(木)

2.0時間

Design It! 10章 設計判断を可視化する 読了

やったこと Design It! 10章 設計判断を可視化する 読了 学んだこと ポイント 図を描く際の注意点 良い図を描くためのポイント 学び ビューを描く際の注意点 関心事一つにつき、一つのビュー 図での表現が難しい部分は、注釈・表・説明文で補足する 品質特性、優先度の高いリスクを説明するために、拡大ビューを描く アーキテクチャが品質特性を保証する方法を示す 良いビューを描くためのポイント 図に凡例を書く 選択したアーキテクチャパターンに合わせて、図を構成する 図の一貫性と、単純さを目指す 叙述的散文を挿入し、アーキテクチャの補助的説明としてストーリーを表現する 所感 「単一責任の原則」というが、これは作図にも当てはまることになるみたい。 「シンプルにする」の一つの具体例が、「焦点を一つに絞る」になりそう。 メモ アイデアを共有する最良の方法は、アイデアを可視化する事。 可視化することで、認識を素早く共有でき、議論も可能。 共有するだけなら、アナログツールにて作成したスケッチで十分。 綺麗に作図する必要はない。 図を使い、設計判断によって品質特性が向上するストーリーを伝える。 ストーリーと図がかみ合うと、アーキテクチャの理解促進につながる。 異なる視点からアーキテクチャを示す アーキテクチャの詳細を一つの図で描くことはほぼ不可能。 たとえ描くことが出来たとしても、誰も理解できないような非常に複雑な図になる。 一つにまとめるのではなく、一つの関心事に絞った図を、表現したい関心事の数だけ作成する。 一つの関心事に絞った、アーキテクチャに関するストーリーを、ここでは ビュー と呼ぶ。 要素責務ビューで要素が何をするのかを把握する 箱で要素が何をするのか、線で箱をつなぎ、要素間の関係を表現する。 図での表現が難しい共有すべき必須情報は、注釈・表・説明文などを使用して埋め込む。 絞込ビューで拡大または縮小する 図に、より詳細な情報を詰め込むこともできる(≒解像度を上げる)。 三層アーキテクチャの解像度を上げる例。 ![[Drawing 2024-01-13 16.36.46.excalidraw]] より詳しいパッケージ関係を図示したことで、保守性について詳しく知ることが出来る。 モデルレイヤーとユーティリティレイヤーは、全コンポーネントから参照される。 全部描くと図が煩雑になるため、あえて記載していない。 解像度を上げると、図が煩雑になる可能性がある。 図で表現したいことを一つに絞り、特化させることを意識すると、ある程度マシになる。 以下を共有する際、詳細化は非常に有効。 特定の品質特定を説明する 優先度の高いリスクを減らす アーキテクチャが品質特性をどう促進するか示す 品質特性の実現方法を示したビューを、品質特性ビューと呼ぶ。 品質特性と関係ある情報のみ記載することで、品質特性に焦点を当てることを目的とする。 例)可用性を満たすために、冗長化できるアーキテクチャを選択し、図示する 図だけで品質特性の説明が困難な場合は、説明文や表で補足する。 ビュー間の要素を結びつける 分割した複数のビューの関連を示したい場合、ビューの関連を明示した情報(マッピングビュー)を作成する。 コンポーネント 割り当てられたチーム 備考 Web UI A チームはフロントエンドWeb開発の専門家で構成 表示ビジネス A このコンポーネントは、Web UI と密接に関係している 検索サービス B 検索インデックス B ... ... ... ビューの関連を示すことが出来れば、形式に拘る必要はない。 表で十分な場合も多い。 ラフスケッチでアイデアを感じる アイデアを共有する目的であれば、図の精密さは重要ではない。 むしろ、素早い反復と形式ばらないコミュニケーションを前提とするなら、精密な図を描く時間や修正する時間が無駄になりかねない。 アイデアを広げて試行錯誤している際は、単純な図で構わない。 精密な図を描くのは、アイデアが固まり、設計判断が収束してきたらでも遅くはない。 カスタムビューを作成し、必要なものを正確に示す ユースケースをうまく説明できる図は、図の作成ルールから外れた図であっても、価値がある。 この場合、特定の目的に合わせた、カスタムビューを作成する。 素晴らしい図を描く 素晴らしい図とは、アーキテクチャの概念や土台を正確に反映した図。 素晴らしい図を描く際のポイント。 すべきこと 避けるべきこと 図に関連するメタモデルの各部分を要約した判例を作成する 読者が表記法を知っていると仮定すること(UMLでも) 説明的なタイトルを追加して、図にどのような種類の構造があるかを伝える 全ての要素を一つの図に含める 精密さを高めるためにテキスト注釈を追加する 白黒で印刷すると意味が失われる表記を使う 全ての図にわたって一貫した表記法を使用する 余計な飾り、多種多様な形や線を使い過ぎる パターンをわかりやすくする 説明文を省略する 凡例を上手に使う 図内で何が起こっているかを表現するためにも、凡例は必須。 凡例が無ければ、何が起こっているのかを理解するのは困難。 例え一般に普及している表記(UMLなど)でも、凡例を載せる。 すべての読み手が、一般的な表記を理解しているわけではない パターンを際立たせる 選択したアーキテクチャに合わせて図を描くことで、アーキテクチャを直感的に理解できる。 例)レイヤー構造であれば、層に合わせて要素を並べ、どの層に属するか記述する。 ![[Drawing 2024-01-13 16.36.46.excalidraw]] 以下のような戦略が考えられる。 パターンを反映した名前を選択する 強調表示する パターンを反映するよう、要素の配置を工夫する 語彙を統一する 一貫性と単純さを目指す 伝えたい焦点を絞るよう、余分な詳細を避ける。 詳しすぎる詳細は、読み手の注意があちこちに分散し、本当に伝えたいことがぼやける 伝えたいことに応じて、要素の色や形を統一し、読み手の理解を促進する。 色や形を選ぶのは、異なるアイデアを際立たせるためであり、綺麗に見せるためではない 読み手は、色や形からも意図を見出そうとする。要素の色や形の不統一は、意図しない誤解を与えかねない 叙述的散文を提供する アーキテクチャについてのストーリーをビジュアル的に補助する手段として、叙述的散文を使用する。 ◆叙述的散文 物事を客観的な説明によって順に並べた文章のこと 叙述的散文によって、アーキテクチャのストーリーを語る。 アーキテクチャはどこから来たのか どう動くか どこに向かっているのか など 表やテキストの段落、箇条書きなどに用いる。

ソフトウェアアーキテクチャ

2024年01月13日(土)

2.0時間

Design It! 11章 アーキテクチャを記述する 読了

やったこと Design It! 11章 アーキテクチャを記述する 読了 学んだこと ポイント アーキテクチャ記述の種類 優れたアーキテクチャ記述を作成するためにできること 設計根拠を残す効果 学び アーキテクチャ記述には、いくつか種類がある 部族的な方法 共通の方法 形式的な方法 無駄な方法 優れたアーキテクチャ記述を作成するためには、以下が重要 聴衆のことを考えて作成する ステークホルダーの関心事に合わせて、ビューを構成する 設計根拠を残す 設計根拠を残すことで、読み手に設計判断の意図を伝えることが出来る 読み手には、アーキテクチャや設計判断の判断残量として機能する これにより、アーキテクチャや設計の一貫性を保ちやすくなる 所感 「アーキテクチャ記述にスライドを使用するな」という話について あえて機能の制限されたツールを使用することは、表現したい本質から意識がそれることを防ぐ効果があることを理解した。 スライド作成ツールを使用すると、きれいな作図に意識を取られる可能性が生まれる メモ 優れたアーキテクチャ記述は、チームに明確なビジョンを与える。 設計判断をすべてのステークホルダーに届け、品質向上に寄与する。 この章では、素晴らしいアーキテクチャ記述を作成する方法を学ぶ。 全体像を語る アーキテクチャとコードの間には、常に何らかのずれがある。 コードでは、全アーキテクチャ上の設計判断を表現することはできない。 特に、計画的な設計が必要なプロジェクト初期では、コードもないため、アーキテクチャを評価できない。 このようなときに、アーキテクチャ記述は重宝する。 アーキテクチャ記述は、以下の効果がある。 整理する 技術同士、または技術と人々がどう連携するのか整理し、記述する 技術サイドとビジネスサイドの間で使用できる、共通の語彙を確立する 品質特性にスポットライトを当てる 考えを明確にする 記述する過程で、頭の中の考えを整理できる わかっていること、わかったつもりになっていること、わからないことを明確にできる 評価できるものを作る 見せびらかす 優れたアーキテクチャ記述は、顧客や管理職を安心させる チームメンバーに対しても、リーダーシップを発揮する 状況に応じた記述方法を選ぶ アーキテクチャ記述には、複数の記述方法が存在する。 費用対効果を高めるためには、現在のプロジェクトとチームの状況に応じて、適切な記述方法を選択する必要がある。 記述方法 概説 適した状況 例 部族的な方法 チーム内での認識合わせに重きを置いた、チーム内でのみ通用するような記述。<br>変更は容易だが、チーム外に対して共有するのは困難。 アーキテクチャが固まっていない、プロジェクト初期など ラフスケッチ、ストーリーテリングなど 共通の方法 チーム外の人々にも共有できる、共通の記述。<br>変更容易な状態を保ちつつ、部族的な方法よりも共有容易な運用が求められる。 アーキテクチャが成熟し、変更する頻度が低下してきた段階 アーキテクチャ俳句、コーディングスタイル<br>アーキテクチャデシジョンレコードなど 形式的な方法 リスクの高いシステムや、高度な調整を必要とするプロジェクトで必要となる、<br>より高い精度や精密さを必要とする記述。<br>膨大な量になる傾向があり、多くの時間と労力を要する。 リスクの高いシステムや、高度な調整を必要とするプロジェクト SAD(Software Architecture Description) 無駄な方法 変更困難で共有も難しい記述方法。<br>本質以外のことに意識がそれる可能性も 無し スライドで作成するアーキテクチャ記述 SAD(Software Architecture Descriptionには、様々なテンプレートが存在する。 有名なSADたちは、いずれも以下の基本部分を含む。 導入と事前情報 SADの概要と照会 ステークホルダー、ビジネス目標、アーキテクチャ上重要な要求の概要 コンテキストビュー 関連ビュー 一つのビューでは、伝えたいこと全てを書ききることは不可能 品質特性やそれ以外の要求を満たす方法について、関連するビューを作成して説明する リスク、未解決の質問、今後の課題 付録 優れたアーキテクチャ記述を作成する 優れたアーキテクチャ記述は、以下4つの特徴を持つ。 聴衆を念頭に置いて特別に作られている アーキテクチャの複数のビューを示している 要素とその責務を明確に定義している 設計判断についての根拠を説明している 言い換えると、これら4つの特徴を意識することで、優れたアーキテクチャ記述を作成できる。 これらを守ることは、後述する「時間を無駄にするのを避ける」ことにもつながる。 時間を無駄にするのを避ける 変更困難で共有も難しいアーキテクチャ記述も存在する。 その最たる例が、「スライドによるアーキテクチャ記述」である。 共有が難しい : 誰かがプレゼンしなければ、スライドは意味を成さない 変更が困難 : 整えた見栄えを変更するのをためらってしまう 聴衆に配慮する 聴衆のことを理解できれば、彼らが必要としているアーキテクチャ記述を作成できる。 聴衆が価値を置くものを考える。 どのような情報を処理するのを好むか 渡した情報をどう使うか など 理解しやすさに専念する 大事なのは、聴衆とのコミュニケーション。 聴衆にとってなじみ深いドメインの言葉を使用、アーキテクチャ記述を作成すると良い 平易な話し方を心掛け、専門用語を避ける 背景知識が必要なことを示すために、アーキテクチャの概念を簡単に定義する など 以下、アーキテクチャ記述で気を付けるべきこと。 すべきこと 避けるべきこと 新しいアーキテクチャあゐ年は、初出のタイミングで定義する 不必要に新しい概念を導入する ドメイン領域の言語を話す 全員が図の表記法を理解していえると思い込む 図に凡例を含める 専門用語を使う 共通のテンプレートが存在する場合はそれを使用する ステークホルダーの関心事を中心にビューを構成する ステークホルダーに合わせて、アーキテクチャやそれに伴う様々な設計ドキュメントのビューを構成する。 開発者は、コードの構成、デプロイ、コンポーネントの相互作用などを知りたがる テスターは、I/Fや通信プロトコルを知りたがる プロダクトオーナーは、技術的な依存関係や全体の進捗を知りたがる など そのためには、「ステークホルダーが何を知りたがるか?」を考える必要がある。 また、アーキテクチャ記述には、少なくとも以下を加えるべき。 設計判断とその根拠 設計したものの構造 アーキテクチャの文書化方法を決定する際は、必ず聴衆を考慮する。 ビューポイントを確立する 「ステークホルダーの特定の関心事に関連するまとまり」に従って、アーキテクチャを説明する方法を定義するもの。 どんなビューか、誰向けのビューか、ビューの表記法や語彙、規則を定義する。 例えば、コンポーネントの配置先を知りたいステークホルダー向けには、以下のようなビューになる。 コンポーネント デプロイ先 Web UI ユーザーのブラウザで実行される ... ... カスタムビューポイントを作成する ステークホルダーの特定のニーズを満たすために、カスタムしたビューポイントを構成できる。 特に、品質特定を中心としたビューポイントを構成することは多い。 スケーラビリティ、セキュリティ、保守性のビューポイント アーキテクチャが特定の品質特性シナリオをどのように満たすか示す 規制のビューポイント 規制要求に関心を持つ特定のステークホルダーグループに監査を実施するために必要な情報を提供する 学習容易性のビューポイント あるいは チーム受け入れのビューポイント 新しいチームメンバーが、スムーズに開発へ参加できることを目標とした、開発プラクティスを確認できるようにする ビジネスインパクトのビューポイント アーキテクチャの各部分がビジネス価値にどのように貢献しているか示す ビューポイントは、伝統的なアーキテクチャ記述では必須。 部族や共通のアプローチでも、効果はある。 ビューは、アーキテクチャを効果的に共有できるようアイデアを構成するのに役立つ。 判断の論理的根拠を説明する 設計根拠とは、各設計を決定した理由を説明するもの。 品質特性のトレードオフ、コスト、チームメンバーの能力や外的要因など、様々な要因をもとに設計判断を行うはず。 その判断を行った背景を記載すること。 設計根拠を残すことで、読み手は設計の意図を理解できる。 理解した意図から、アーキテクチャの一貫性に寄与する可能性が高まる。 選ばなかった道を説明する 様々な候補の内、選択されなかった設計判断とその理由を残す。 背景知識は、読み手がアーキテクチャやコードを正確に理解することを助ける。

ソフトウェアアーキテクチャ

2024年01月13日(土)

2.0時間

Design It! 9章 アーキテクチャデザインスタジオを開く 読了

やったこと Design It! 9章 アーキテクチャデザインスタジオを開く 読了 学んだこと ポイント アーキテクチャデザインスタジオの目的 短めのタイムボックスを設ける目的 ワークショップの流れ デザインアクティビティ 学び アーキテクチャデザインスタジオの目的は、グループができるだけ色々なアイデアをできるだけ早く作成すること そのために、短めのタイムボックスを設ける 時間をかけるだけ優れたアイデアがでる ... とは限らない 短めのタイムボックスを設定し、短時間で、効果的なデザイン探求を目指す ワークショップの流れは以下の通り 作成 => 共有 => 批評 を繰り返す 結果をまとめ、次のアクションを決定する 結果と次のアクションを記録する デザインワークショップ内での活動(デザインアクティビティ)は、いくつか選択肢がある 目的に応じて、デザインアクティビティを選択する メモ デザインに時間をかけ続けても、必ずしもより良いデザインとなるとは限らない。 デザインにかける時間に制約を設けてることで、無駄を省くことが出来る。 この教えは、「デザインスタジオ」として普及した。 アーキテクチャ デザインスタジオを計画する デザインスタジオでは、グループができるだけ色々なアイデアをできるだけ早く作成することを目的とする。 そのために、探求に費やす時間を大きく制限する。 上記目的を達成するために、デザイン探求では、早く(Fast)、効果的で(effective)、楽しいもの(fun)にする(これをデザイン探求の「3つのF」と呼ぶ)ことに重きを置く。 デザインスタジオでは、3種類のアイデアが生まれる。 作るもののアイデア 有望なアイデア モデルやプロトタイプを作成して、詳細を具体化していく もっと探求が必要なアイデア 「前提が間違っている」「重要な情報が欠けている」などを発見する 新しい疑問としてのアイデア アイデア探求の過程で、解決したい問題の新しい問題に気付くことがある(問題を、事前に発見できたことになる) ステークホルダーに報告し、問題に対する理解を深めることが出来る ワークショップ以前 : 準備 ワークショップの目標を定め、招待する人を決定する。 目標は、1,2つ程度定める。 目標を明確に定めるには、以下について理解を深める必要があり、そこそこ大変。 - ビジネス目標 - 品質特性 - アーキテクチャ上重要な要求 - など キックオフ 以下を行う。 解決したい問題とアーキテクチャに関する情報を参加者に共有し、参加者の認識を一致させる。 デザインスタジオの目標を共有する 作成 - 共有 - 批評 のサイクルを繰り返す アイデアを探求し、可能性についてグループの理解を深める ◆作成 一人、または少数のグループでワークしょんぷのゴールに向かって取り組む。 アイデアのスケッチ、モデル化など。 アナログツールを使用すると良い。 必ずタイムボックスを設け、その時間内で完結させる。 ◆共有 各グループが作成したアイデアを共有し、自分たちの設計が目標をどのように満たすかを説明する。 完全な説明を避け、要点の説明に留める。 タイムボックスが、完全な説明を避ける仕組みとして機能する 共有する段階では、聴くことを意識し、質問は避ける(質問は、次の批評で行う)。 ◆批評 他のグループのアイデアを批評する。 目標に関する設計のメリットに評点を当てる。 言い換えると、否定的で非建設的な批評は避ける。 ◆繰り返す 作成-共有-批評 により、素早い思考の発散と収束を促進する。 これを繰り返し、学びを積み重ね、よりよいアイデアの議論につなげる。 また、繰り返しの中で、メンバーに合わせてルールを調整すると良い。 デザインスタジオを閉じて、次にやることを決定する ワークショップの結果をまとめる。 まとめ結果から、次のアクションを決定する。 最も注目すべきアイデアは何か? 対処すべき重大なリスクは網羅できたか? 実験すべきことはあるか? など まとめや次のアクションは、記録に残そう。 適切なデザインアクティビティを選択する デザインスタジオの進め方には、いくつかのアクティビティがある。 ワークショップの際には、目的に応じてアクティビティを選択し、カスタマイズできる。 適切な参加者を招く ワークショップの質は、参加者に左右される。 また、参加者が多すぎると、ワークショップの結果がコストに見合わない可能性が高い。 適切な大きさのワークショップ 大規模なグループは、以下の問題がある。 管理が難しい コミュニケーションに時間がかかる スケジュールの調整が難しい 大規模なグループのままだとワークショップはうまく機能しない。 そのため、いくつかの小さなグループに分割するとよい。 多様な聴衆を招待する 活発な議論を呼ぶために、以下のようなメンバーを参加者に加えると良い。 異なる価値観を持つ参加者 異議を唱えることができる参加者 まずは、重要なステークホルダーを招く。 後は、価値観が偏らないように、参加者を調整する。 グループの力を賢く利用する グループワークでは、 "集団思考" に陥らないよう注意する必要がある。 周囲に同調しているだけの、静かな大多数を探し、コミュニケーションを促そう。 意見の不一致がない状態は、衝突を恐れ、集団思考に陥っている可能性を示す。

ソフトウェアアーキテクチャ

2024年01月13日(土)

2.0時間

Design It! 8章 意味のあるモデルで複雑さを扱う 読了

やったこと Design It! 8章 意味のあるモデルで複雑さを扱う 読了 学んだこと ポイント アーキテクチャモデルを構築するメリット アーキテクチャのメタモデルを作成する目的 アーキテクチャモデルをコードに盛り込むための手段 学び アーキテクチャモデルを構築 & 更新し、アーキテクチャの理解を促進する アーキテクチャのメタモデルを記述し、アーキテクチャモデルの理解を促進する 新しい概念をブラッシュアップし概念を固めていく 概念の更新に合わせて、メタモデルに矛盾が生まれないよう規則を更新する 良い名前を使う アーキテクチャモデルをコードに盛り込むために、以下のような手段がある コードの命名に、アーキテクチャモデルの語彙を使用する 品質特性を損なうようなコーディングが出来ないようにする ツールで強制できる状態がベスト 時点で規律や戒めに頼る コメントにて、設計根拠を説明する 所感 アーキテクチャの一面を説明するモデルとして、アーキテクチャモデルは役に立つ。 概念、規則、メタモデルなど、モデルをうまく説明するための定義がいくつか登場。 全体的に抽象的な話が多く、理解が難しかった。 うっすらイメージできるレベルで、人に説明できるレベルまで理解できているとは言えない。 何か一つ、説明できるような例を経験したり思いついたりすると全然違うと思う。 メモ ソフトウェアは、多かれ少なかれ複雑さを抱える。 解く問題が難しいほど、後から機能を足すほど、ソフトウェアは複雑になっていく。 複雑さを抑えるために何ができるか見ていく。 アーキテクチャを見通す アーキテクチャをうまく説明できる、新しい抽象概念を作成する。 新しい抽象概念は、図と同じように、アーキテクチャのある一面を説明する。 優れた抽象概念は、アーキテクチャを正確かつ精密に説明できる「アーキテクチャモデル」となる。 優れたアーキテクチャモデルの利点を示す。 設計の語彙を確立する アーキテクチャモデルを指す言葉で会話ができる 関心を持つべき細部に注意を向ける 品質特性やその他のシステム特性を見通せる アーキテクトの意図を記録できる なぜモデルに書いた方法を選択したのか、モデルの背後にある意図を表現できる 全てのモデルには、「概念」と「規則」がある。 メタモデルを記述する アーキテクチャのメタモデルは、モデルの「概念」と「規則」を定義する。 ![[Drawing 2024-01-09 20.17.26.excalidraw]] 概念は、アーキテクチャにおける要素や関係になる。 概念を定義したら、その概念を使用するための規則を設定する。 新しい概念を固定化する 新しいアイデアから、概念を定義する。 アイデアのブラッシュアップに合わせて、概念も更新していく。 アイデアが固まってくれば、概念が固まってくる。 十分に固まった概念は、概念を指す言葉で意思疎通が可能になる。 矛盾を調整する 新しい概念を追加したり、パターンをマージすると、規則に矛盾が生まれることがある。 矛盾は、アーキテクチャの一貫性を損ない、メタモデルを見た人に誤解を与える。 そのため、生まれた矛盾はうまく調整する必要がある。 つまり、新しい概念を追加したり、パターンをマージする場合、矛盾が生まれないよう規則の更新も必要となる。 また、規則には、アーキテクチャに課すと決定した「概念上の制約」も記述する。 これにより、特定の品質特性を促進できる。 (概念上の制約を維持している限りは、特定の品質特性を維持できる ... という考え方) 良い名前を使う 良いコードに良い名前が必須なのと同じように、良いアーキテクチャにも良い名前は必須。 アーキテクチャの場合、問題の理解が深まるほど、概念に付ける名前も変化する。 名付けには、7段階ある。 No ステージ 名前(例) 1 名無し 何かをするもの 2 無意味 クランベリー 3 的確 ジョブスタータープロセス 4 的確かつ完全 データフェッチャー、チェッカー、トランスフォーマー 5 適切な行い データ変換ジョブランナー 6 意図 データプリペアラー 7 ドメイン抽象 データ準備エージェント コード内にモデルを構築する モデルはアーキテクチャの見通しを良くする。 構築したモデルの名前をソースコードに持ち込むことで、アーキテクチャとソースコードが関連するようになり、理解の促進につながる。 他にも、以下のような利点がある。 概念的な設計の一貫性を維持し、望む品質特性の維持に貢献できる モデルとコードの足並みがそろい、理解が容易になる ドキュメントの必要性がいくらか軽減する アーキテクチャの語彙を適用する アーキテクチャでは、レイヤーやサービス、フィルターについて表現する。 コードでは、パッケージやクラス、メソッドを実装する。 アーキテクチャの抽象概念をコードに移行する際、用語を揃えないと、混乱の原因となりかねない。 用語を揃えるためには、コードに、アーキテクチャの語彙を使用すると良い。 例) レイヤーパターンを使用する場合は、コードパッケージをレイヤーと呼ぶ パイプとフィルターパターンを使用する場合は、クラス名に「パイプ」や「フィルター」を使用する システムメタファーとしてパイロットやナビゲーターといった単語を使っている場合、単語や型の名前に使用する 要素間の関係を強制する コードの構成は、コード内のアーキテクチャ構造に大きな影響を与える。 言語仕様(パッケージプライベート、アクセス修飾子など)を活用し、品質特性を損なうようなコーディングが出来ないよう強制できる状態がベスト。 強制できない部分は、規律や戒めに頼ることになる。 静的ツールによる、違反の検出 契約による設計 & アノテーション マイクロサービスなどで、実装を完全に隠蔽 コメントとしてヒントをつける 強制や規律の背景を説明するために、コメントは有効。 特に、コメントは設計根拠の説明に有効。 設計ドキュメントへのリンクを貼るだけでも効果的。

ソフトウェアアーキテクチャ

2024年01月09日(火)

1.5時間

Design It! 7章 パターンで土台を作る 読了

やったこと Design It! 7章 パターンで土台を作る 読了 学んだこと ポイント パターンとは パターンを用いるメリット 「アーキテクチャ上の不一致」とは 学び パターンとは、先人の知恵の集合体 パターンを利用することで、以下のようなメリットがある アーキテクチャの選択にかかる時間を大幅に短縮できる パターンの名前で円滑なコミュニケーションをとることが出来る 「アーキテクチャ上の不一致」とは、達成したい品質特性と、選択したアーキテクチャが得意とする品質特性が一致しない現象 そもそもアーキテクチャの選択が不適切 アーキテクチャは適切だが、使用する技術がアーキテクチャに合っていない 所感 パターンを知らなければ、選択することもできない。 まずは、パターンを知るところから。 巨大な泥団子には悪いイメージしかなかったが、意図的に選択するユースケースをしった。 巨大な泥団子もアーキテクチャであり、アーキテクチャである以上トレードオフが存在する...ということだった。 (なお、基本的に良い事はない) "問題重視"と"解決策重視"という二つ観点は考えたことが無く、興味深かった。 メモ 新しい問題に直面した場合、先人の知恵を借りると良い。 つまり、パターンとして整備されたアーキテクチャを選択する。 選択したアーキテクチャを、問題に合うようチューニングする。 この章で扱うこと 有名なアーキテクチャパターンの紹介 アーキテクチャをチューニングする方法 深く触れず、軽く説明する アーキテクチャパターンとは アーキテクチャパターンとは、過去にある問題を解決したことがある、再利用可能な解決策。 パターンを使用すると、以下のメリットがある。 適したパターンを選択できると、アーキテクチャの設計を大幅に短縮できる パターンの名前で円滑なコミュニケーションをとることが出来る レイヤー ある関心事1つを、1つのレイヤーとして実装する。 関心事別にレイヤーを分割し、複数人での共同作業を可能とする。 以下を満たすように実装する。 レイヤー間は疎結合 レイヤ内は高凝集 下位レイヤーは、上位レイヤーに依存しない 言い換えると、下位レイヤーを取り換えても、上位レイヤーが動くよう実装する ポートとアダプター 別名 ヘキサゴナルアーキテクチャ。 核となるビジネスロジックと、その他関心事を分離するパターン。 その他関心事と、取り換え可能なアダプターとして実装する。 アダプターは、ビルド、または実行時に取り換え可能。 これにより、柔軟な動作を可能とする。 パイプとフィルター 一つのデータ操作を、「フィルター」という単位で実装する。 フィルターは、ある一つのデータ処理のみを担当し、処理結果を出力する データをたくさんのフィルターに通して、目的の処理を実現する。 フィルターを並列に処理する場合は「パイプとフィルター」と呼ぶ。 フィルターを直列に処理する場合は「バッチシーケンシャル」と呼ぶ。 一フィルターの処理が重く、次のステージのために結果をファイル化する必要があるような、重たい処理を想定 サービス指向アーキテクチャ 特定の機能を1つ提供するコンポーネントを実装。 このコンポーネントを組み合わせて、任意のサービスを実現するアーキテクチャ。 サービス利用者は、背後にある実装の詳細を知らずに、目的を達成できる必要がある。 旧来は、メッセージバスおよびSOAP経由の通信に依存する形が主流だった。 現在では、HTTP などのメッセージプロトコルを使用して相互に通信する、マイクロサービスの使用を奨励している。 パブリッシュ・サブスクライブ コンシューマー、プロデューサー(パブリッシャー)に分けて実装する。 コンシューマーは、事前に関心のあるイベントのみ購読(サブスクライブ)する。 プロデューサーは、自身が観察しているイベントを観測した場合、イベントを発行(パブリッシュ)する。 コンシューマーは、興味のあるプロデューサーのイベント発行を検知し、即座に目的の処理を実行できる。 共有データ システム全体で共有するデータソースを作成する。 あらゆるコンポーネントがこのデータソースにアクセスして処理を実現する。 RDBとか、オブジェクトストレージとか。 多層 実行時の構造単位でレイヤーを分割する。 レイヤーパターンとは、分割する単位が異なる。 レイヤーパターン : 設計時の要素単位でレイヤーを分割する 多層パターン : 実行時の要素単位でレイヤーを分割する また、分割した層単位で、割り当てるサーバーやプラットフォームを選択できるイメージ。 コンピタンスセンター 専門家チームを雇い、彼らにパターンの定義、ベストプラクティスの確立、サポートツールの開発、教育などを担当してもらう。 システム開発ではなく、開発補助を目的とするパターン。 オープンソース型の貢献 チーム以外の第三者も開発に参加するパターン。 チームは、開発に加え、第三者の変更依頼をレビューし、メインのコードにマージする裁量を持つ。 チームには、書き込み権限を与える 第三者には、変更依頼を提出する権限を与える チームは、第三者の開発を促進するため、以下を実施する スタイルガイドの用意 テスト容易性を考慮した設計 技術に制約を課してプラットフォームを構築 巨大な泥団子 特に定義された要素や関係はない。 開発プラクティスの未熟さ、アーキテクチャへの理解不足などに起因する、保守や拡張が困難な状態を指す。 設計への理解不足に起因するが、設計作業をスキップし、意図的に泥団子を選択することが出来る。 この場合、設計に割く時間を丸々カットできる、つまり開発スピードを一時的に促進できるメリットがある。 泥団子自体は保守困難なため、長期的な開発を視野に入れるなら、早い段階で泥団子を解体する必要がある アーキテクチャ上の不一致を避ける 達成したい品質特性と、選択したアーキテクチャが得意とする品質特性が一致しない現象を、「アーキテクチャ上の不一致」という。 アーキテクチャ上の不一致は、以下の理由で起こり得る。 そもそもアーキテクチャの選択が不適切 アーキテクチャは適切だが、使用する技術がアーキテクチャに合っていない Pub/Subパターンを選択し、データの受け渡しにRDBを選択する アーキテクチャ上の不一致が発生した場合、フレームワークとの戦うことになる。 アーキテクチャ上の不一致を発生させないためにも、適切なアーキテクチャの選択に加えて、アーキテクチャの前提に一致する技術を選択する必要がある。 新しいパターンを発見する 新しいパターンを見つける、以下の2つの方法が知られている 経験した問題たちから、共通の問題を探してパターン化する "問題重視のアプローチ" 問題の解決策たちから、共通の解決策を探してパターン化する"解決策重視のアプローチ" 発見したパターンは、フィードバックを得るために発信しよう。

ソフトウェアアーキテクチャ

2024年01月01日(月)

1.5時間

Design It! 6章 アーキテクチャを選ぶ 読了

やったこと Design It! 6章 アーキテクチャを選ぶ 読了 学んだこと ポイント アーキテクチャを適切に選択するにはどうするか 制約の種類 品質特性を考慮してアーキテクチャを選択する 要素に機能的責務を割り当てる目的 変化を見越して設計する 学び アーキテクチャを適切に選択するため、探求プロセスを実施する 問題を解決できるアーキテクチャを列挙する「発散」と、問題に適していない選択肢を排除する「収束」を繰り返す 制約には、「技術的」なものと「ビジネス上」のものがある アーキテクチャに影響を与える制約もある 列挙したアーキテクチャが、解決したい問題に合う品質特性を得意とするか判断する 必須の機能要求を達成したことを確認するために、アーキテクチャ上の要素が負う機能的責務を明文化する 変化に対応できるよう設計する 変更に困難が伴う判断を、可能な限り遅らせる 判断を、アーキテクチャの外に移す アーキテクチャではなく、コーディングレベルの設計で判断を下せるよう、アーキテクチャを決定する 所感 ビジネス上の制約は、技術以外でもなんとかできる可能性がある。 どうにもならないのは、与えらた技術的制約。 前の章にもあったが、勝手に変更できないものと思い込むのは危険。 覚えておきたい。 「品質特性を促進していけるような技術やフレームワークを探求する」は、普段無意識にやっていることだと思う。 例)「スモールにスタートして価値提供を早めたいから xxx を使用する」 これをうまく抽象化した文だと感じた。 「変更に困難が伴う判断を、可能な限り遅らせる」という話は、違う言葉で何度か目にしてきた。 この辺りはよく知られているテクニックなのだと感じた。 メモ 解決したい問題について学ぶほど、よりニーズに合ったアーキテクチャを選択できるようになる。 言い換えると、何も考えず、サイコロを振る感覚でアーキテクチャを選択すると、悲惨な末路を辿る アーキテクチャ上重要な要求を実現するために、トレードオフを加味して複数のアーキテクチャから一つを選択する。 選択肢を広げるために発散させ、決定するために収束させる 「複数のアーキテクチャが存在する」ことを認識するためにも、考えの発散と収束を行う。 発散 : 問題を解決できるアーキテクチャを列挙する 収束 : 合意形成によって、問題に適していない選択肢を排除する 発散と収束を繰り返し、最適なアーキテクチャを模索する。 この過程を、書籍では探求と呼称する。 アーキテクチャ上重要なものを探求する アーキテクトが探求するのは、一般的に以下の分野。 アーキテクチャ構造の全体構成を決定するために、要素とその役割を探求する 要素の責務を明確化する その過程で責務の無い要素を発見した場合、これを排除する 要素が度相互作用するかを決定するために、関係とそのインターフェースを探求する アーキテクチャの要素間を連携させていく手段を探求する REST ? TCP ? 共有メモリ ? GlaphQL ? アーキテクチャが形取る世界を理解するためにドメインを探求する 解決したいドメインの独自用語や概念を説明する 解決したい問題領域を深く理解するほど、適切な要素分割と責務割り当てにつながる 品質特性を促進していけるような技術やフレームワークを探求する 選択した技術の得意分野と、優先したい品質特性が一致する状況が理想 反対に、不一致したり、フレームワークから外れて得意分野を十全に生かせなくなった場合は良くない 出荷を確実にするような構築方法やデプロイ方法を探求する 意思決定を導く視点を得るため、過去の設計を探求する 制約を受け入れる 制約には、「技術的」なものと「ビジネス上」のものがある。 与えられた技術的制約は、受け入れるしかない。 自分たちで判断を下した、技術的制約と化したものは、痛みと引き換えに変更は可能。 ビジネス上の制約は、時としてアーキテクチャに影響を与える 例 : 納期がタイト 並行開発や設計が簡単(または不要)なアーキテクチャ インクリメンタルなデリバリーを促進するパターン 自動化と開発速度を支援する技術を選択 他、速度を上げるために有用な選択肢 上記選択肢を組み合わせる また、ビジネス上の制約は、アーキテクチャの外側で満たすこともできる。 例 : 予算がない 低コストの下請け業者に発注 など 望ましい品質特性を促進する アーキテクチャごとに、品質特性の得手不得手が存在する。 解決したい問題にて重要視する品質特性を明らかにすることで、重要視する品質特性が得意なアーキテクチャを選択できる。 文献を漁り、パターンを調べると良い。 品質特性という観点では、常に「正しい設計」や常に「誤った設計」というのは滅多にない。 「解決したい問題に合うか合わないか」というだけ。 アーキテクチャが、解決したい問題に合う品質特性を得意とするか判断するために、表にまとめると良い。 品質特性 3層 pub/sub サービス指向 ... 可用性 + 〇 + パフォーマンス 〇 - + セキュリティ 〇 - 〇 ++ , + , 〇 , - , -- 左に行くほど得意で、右に行くほど不得意 表にまとめることで、議論のたたき台として機能する。 この時、数字ではなく曖昧な記号を用いること。 数字を用いると、平均や合計といった、数字をいじることに意識が向きかねない 機能的責務を要素に割り当てる アーキテクチャの要素ごとに、責務を明文化し、リスト化する。 これにより、必須な機能要求を達成できることを確認する。 基本的に、機能、要素、責務は、1 : 1 : 1 となる。 例 要素 責務 Web UI WebブラウザでUIを表示し、ユーザー操作を処理する 契約DB 永続ストレージ。契約情報の記録システム 変化に向けて設計する 変化に対応できるようする。 そのために、以下の手段が考えられる 変更に困難が伴う判断を、可能な限り遅らせる 言い換えると、適切な時期に設計判断を下す これにより、判断を遅らせることが出来、得られた時間を、よりよいアーキテクチャや技術を選択するための調査や探求に充てることができる 以下の質問に答えることは、適した時期か判断するのに役立つ 判断しないことが進捗を妨げるか? 判断は後回しにできない問題を解決するか? 判断はより多くの選択肢や新しい機会を生み出すか? 判断を遅らせることで、大きなリスクが発生するか? 判断の意味を理解し受け入れるか? 今この判断を下す理由について明確な根拠があるか? 判断が間違っていた場合に、それを取り消す時間があるか?失敗を許容できるだけのゆとりがあるか? 判断を、アーキテクチャの外に移す アーキテクチャではなく、コーディングレベルの設計で判断を下せるよう、アーキテクチャを決定する SOLID原則のような、プログラミングパターンから学べる事も多々ある

ソフトウェアアーキテクチャ

2023年12月29日(金)

2.0時間

Design It! 5章 アーキテクチャ上重要な要求を掘り下げる 読了

やったこと Design It! 5章 アーキテクチャ上重要な要求を掘り下げる 読了 学んだこと ポイント アーキテクチャに影響を与える要求とは アーキテクチャの制約をうまく利用する 品質特性シナリオとは ASRワークブックとは 学び アーキテクチャに多大な影響を与える要求に注視し、これを発見するために手を尽くす 適切に選択された制約は、問題を単純化し、アーキテクチャ設計を容易にする 一方で、非常に厳しい制約は、アーキテクチャ設計を必要以上に複雑化する 設計判断(特に開発初期)は、後々制約と化す しかし、制約と化した設計判断は変更できる 与えられた制約か、制約と化した設計判断なのか、区別できるようにする 品質特性の説明するために、品質特性シナリオを書く テスト可能で、測定可能であると良い 特定した「アーキテクチャに多大な影響を与える要求」は、ASRワークブックとして文書に記録する ## 所感 要求の内、アーキテクチャに大きな影響を与えるものに注視するのは、非常に納得感のある話だった。 アーキテクチャを判断する際、優先的に考慮するべき事項として、貴重な情報元になりそう。 与えられた制約か、制約と化した設計判断なのか区別するというのは、あまり考えたことが無かった。 制約とかした設計判断を、勝手に「変えられないもの」と思い込み、「変更する」という選択肢が見えなくなってしまう状態は非常に怖い。 そうならないためにも、与えられた制約か、制約と化した設計判断なのか区別することは重要だと考えるようになった。 初期の設計判断が、後々に制約と化す様はイメージしやすかった。 制約を活用することで選択肢を絞る話、バックログを作成する際にスコープを絞る話に似ていると感じた。 メモ ステークホルダーの要求の内、アーキテクチャに多大な影響を与える要求を アーキテクチャ上重要な要求、(ASR) と呼称する。 アーキテクトは、ASRを明らかにする責務を負う。 ステークホルダーも気付いていない、隠れたASRは無いか ステークホルダーの要求の内、ASRに該当するのか ASRだと判定するには、以下の要求分類について考える。 制約 変更できない設計判断 通常は与えられるものだが、選択することもある 品質特性 影響を与える機能 アーキテクチャにおいて特別な注意を必要とするフィーチャーや機能 その他、影響を及ぼすもの 例) 時間、知識、経験、スキル、社内政治など 制約を活用して設計の選択肢を絞る ここで言う制約とは、 変更できない設計判断を指す。 適切に選択された制約は、問題を単純化し、アーキテクチャ設計を容易にする。 一方で、非常に厳しい制約は、アーキテクチャ設計を必要以上に複雑化する。 制約によって、人、プロセス、予算、スケジュールに関する判断を制限する。 制約の例) 技術的な制約 プログラミング言語の選択(JVM上で動くか、など) OS・プラットフォーム(特定のOSで動くか) ビジネス上の制約 チーム編成 予算・スケジュール 法的制約 制約について、決定事項とその発生源を簡潔にまとめておく。 まとめた制約の例) 制約 発生源 タイプ コンテキスト OSSとして開発しなければならない。 市長 ビジネス 市はオープンデータポリシーを持ち、市民はソースコードにアクセスできなければならない。 ... ... ... ... 制約は一度決定すると、 100%交渉不可能となる。 そのため、受け入れる制約は慎重に決定する。 ソフトウェア開発が進むにつれて、設計判断は(変更が困難という意味で)制約のようになる。 特に、開発初期の設計判断は、開発終盤で大きな制約となる可能性がある ステークホルダーから与えられた制約とは異なり、設計判断は(困難を伴うかもしれないが)変更することはできる。 そのため、「与えられた制約」なのか、「制約と化した設計判断」なのかは区別するようにする。 品質特性を定義する 品質特性とは、ソフトウェアシステムの外部から見える特性とそのシステムの運用に対する期待を表す。 つまり、アーキテクチャ特性。 ASRを考える際、品質特性は常について回る。 品質特性は、システム運用の文脈においては非機能要件と同義と言える。 一方で、品質要求の文脈においては、品質特性は機能的な意味合いもあるため、非機能要件とは呼べない。 また、ソフトウェアアーキテクチャ設計の際は、機能、制約、品質特性を区別した方がよい。 品質特性シナリオとして記録する 品質特性を明確に説明するために、品質特性シナリオを使用する。 品質特性シナリオは、ソフトウェアシステムが特定の環境のコンテキスト内でどのように動作するかを説明したもの。 ◆品質特性シナリオの例 品質特性 シナリオ 優先度 可用性 RFPDBが応答しない場合、システムは障害を記録し、3秒以内に古いデータで応答する必要がある 高 可用性 ユーザーは、RFP検索機能を、年間を通して平均99%の確率で行うことが出来る 高 信頼性 RFPの更新は、変更後24時間以内にアプリケーションに反映される 低 ... ... ... 良い品質特性シナリオは、以下を満たす。 誤解の余地なく、誰でも理解できる文で要求の意図を伝えることが出来る 正確 測定可能 具体的かつ測定可能な応答測定とするように努める ステークホルダーと会話を始める前に、応答測定のたたき台を用意する。 たたき台をもとに、ステークホルダーと議論を重ね、ステークホルダーの共感を呼ぶ応答測定を発見する。 よい応答測定は、テストしやすい。 言い換えると、シナリオを使ったテストを作成できないのであれば、そのシナリオは特定の計測可能な応答測定を持っておらず、詳細化が不十分だと言える。 機能要求の分類を探す アーキテクチャ設計に影響を与える機能要求を、影響力のある機能要求と呼ぶ。 影響力のある機能要求を発見するのはセンスを伴う。 書籍では、以下の手順を紹介している。 アーキテクチャについての現在の考えを要約した概念的なアーキテクチャをスケッチする 大量の機能要求リストから、同じものをグループ化し、代表的な機能要求のみ抽出する 同じアーキテクチャ要素内に実装されている可能性のある機能要求を探す 実装が難しそうな機能要求を探す 価値が高く、優先度の高い機能要求を探す 特定した問題の種類ごとに、概念的なアーキテクチャを辿りながらそれぞれの要求グループをどう達成背売るか示す 実装方法がすぐに示せない場合、ASRである可能性がある それ以外のアーキテクチャに影響するものを見つけ出す 例 知見のある技術 RoRしか経験が無ければ、他のフレームワークの採用は見送られやすい => 設計判断 コスト(金) システムにかける予算が十分になく、貧弱なマシンしか使えないのであれば、それに合った機能や言語・フレームワークを使用せざるを得ない など 必要な情報を掘り下げる ASRは、プロダクトバックログから発見しやすい。 ユーザーストーリーから、品質特性シナリオを作成し、詳細を明らかにしていく。 そのためにも、ステークホルダーと話をする。 ASRの発見に役立つ手法の例 GQMワークショップ ステークホルダーインタビュー 前提リスト ミニ品質特性ワークショップ インセプションデッキ ステークホルダーの目標を理解するためにも、積極的傾聴能力を磨く ASRワークブックを組み立てる 特定したASRは、 ASRワークブックとして文書に記録する。 開発初期は頻繁に更新される。 アーキテクチャがまとまっていくと、更新頻度が減る。代わりに、参照頻度が高くなり、重要な文書に昇華する。 まれに、実行可能なテストやソースコードが、ASRワークブックにとって代わる

ソフトウェアアーキテクチャ

2023年12月28日(木)

1.5時間

183件中の 1-25件 を表示