『フロントエンド開発入門: プロフェッショナルな開発ツールと設計・実装』学習メモ
Part 1 導入編 何故使うかを知る
Ch01 frontend history
- static UI → dynamic UI
- DOM utilityを提供したjQuery
- cross browserや下位互換性を吸収したAPI
- Ajax
- XMLHttpRequest objectを隠蔽し冗長な通信記述を簡略化できる
- Shorthand
- 簡易的なanimationの活用
- pluggable API
- 自身のobjectを拡張できる
- → 周辺のlibraryやpluginを充実させるecosystemを築く
- 自身のobjectを拡張できる
- browserで動作する画面を取り扱う技術者にとって,JavaScriptはinteractionや機能実現のための手段として重要な言語となってきた
- SassといったCSS meta language
- DOM utilityを提供したjQuery
- frontend_engineerという専門職
- single_page_applicationの誕生
- 内部では,applicationの状態管理やroutingのみならず,routingごとのcontrollerやdata_modelingなどが盛り込まれるようになる
- → AngularJSやBackbone.jsなどのsingle_page_applicationを実現するためのall_in_one frameworkが使われだす
- client MVCやrouting, data_modelingにはsoftwareのdesign_patternへの理解が求められる
- → frontend engineer
- single_page_applicationの誕生
- Node.jsによる開発基盤の構築
- server_side JavaScriptとしてNode.jsが発表
- → bundled package managerであるnpmによって開発におけるecosystemが急速に充実する
- → frontendでのlibraryのversion_controlや開発におけるさまざまなタスクの自動化が可能になる
- CommonJS: module system
- ECMAScript規格更新に伴う周辺事情の活性化
- ES6からES5への変換tool: 6to5 → Babelに名称変更
- 新しい仕様をcompileするためのpluginを開発することで,健全にcodebaseに最新仕様を持ち込むことができる
- 現時点でfrontendが誇るすばらしいecosystem
- 止まらないfrontend
- focus
- 昨今の技術要素が何のために必要なのか,何を解決するのか
- 実践的な内容で技術要素を取り扱い必要なことを必要なタイミングで学ぶ
- focus
Ch02 frontend_engineerに求められるskill
- frontend_engineerが取り組む実務
- JavaScriptの成長と要求の変化
- 変容する中で維持すべきdeveloperの姿勢
Ch03 frontendにおける一般的なtools
- Node.jsとその周辺のecosystem
- Node.js: asyncのevent_driven_modelを採用したserver_side向けのJavaScript
- server_sideのscript_languageであることに加えて,開発環境において必要なtoolやlibraryを動作させるために必要不可欠
- core
- V8と,libuvというasync I/OをsupportするC言語libraryなどから構成され,binary化されて配信される
- libuv → async event_driven JavaScript runtimeを実現
- JavaScriptはsingle thread
- main processを進めながら,callback queueとしてasync processを積み上げる
- async/await
- JavaScriptはsingle thread
- package_manager
- npm: JavaScript用のpackage_managerのCLI
- packageを格納するregistryを提供・開発する会社名でもある
- Yarn: npmと同類.Facebookが開発.
- version lock file
- workspace
- 別applicationどうしの依存関係を単一にするarchitectureであるmonorepoを実現する仕組みを提供する
- npm: JavaScript用のpackage_managerのCLI
- Node.jsがもたらす恩恵
- Node.js: frontendのtool_chain, 開発環境構築を支える根幹そのもの
- server_side languageとしても有能
- event_loopやnon_blockingという特性を活かして,高traffic requestをさばいてもperformanceが低下するcaseが少ない
- Backends_For_Frontends layerとbrowserとで同じ言語であるJavaScriptを扱うこともできる
- 共通言語 → 一気通貫のcontextをdevelopment_memberに提供し,言語別に切り替えるストレスなく,継続的なdevelopment processを可能にする
- 技術選定の主軸となるcaseもいくつか存在し,組織的な戦略として候補になりえる言語
- Node.jsにより,JavaScriptが戦術・戦略として価値のある言語になるまで発展
- Node.js: frontendのtool_chain, 開発環境構築を支える根幹そのもの
- Node.js: asyncのevent_driven_modelを採用したserver_side向けのJavaScript
- compiler, module_bundler
- 言語仕様を吸収し,解釈可能な状態で展開・連結する変換器
- Babel
- 構文解析で下位仕様の構文へと変換
- webpack
- file間のmodule解決を行い1ファイルに連結させる機能を提供
- Babel
- compiler: Babel
- 新しいJavaScript構文を環境に合わせて解釈可能な下位構文へとdown_compileするRole
- ECMAScriptが年次策定していく新しい仕様と大きく関係
- T39という団体により策定
- 構成
- 構文解析のためのparserやcompilerとしてのcore機能,それらを補うhelperや変換のためのpluginなど細かなpackage群による
- babel/preset-envという主要な変換用pluginがpreinstallされたpresetを使うcaseが多い
- module_bundler: webpack
- 言語仕様の一部であるmodule機構を実装していない下位環境においての再現(emulate)を担当
- 設定ファイルの柔軟性やloader, pluginというAPIを提供し強力な結合・連結機能を提供することで,周辺のecosystemも充実し,activeに開発が続けられている
- ParcelやRollup.jsなども同じ役割
- module仕様であるES Modulesの実装がすべてのbrowser環境で整うには時間がかかることも,module_bundlerが利用される理由の1つ
- JavaScript module_system
- Node.jsが採用したCommonJSとES2015で採択承認されたES Modulesの2つがあるが,Node.jsはES Modulesへの移行を試験的に実装している
- Can I use: browserでの実装状況を調べるためのDBのdefacto standard
- cross browserの課題解決を目的としたJavaScript toolが利用していることも多い
- Babelは,webpackにおいてbabel-loaderとして変換のRoleを担う
- → ほとんどはwebpackをfrontend code compile環境として選択する
- Babel, webpackが解決すること
- Babelには正式な仕様以外のpluginが作成・使用されてしまったという経緯があることに注意
- → babel/preset-envは,ECMAScriptと歩みを合わせ,developerが実際に取り組むようなcross platformやbrowser要件の問題に対して最適な機能を提供
- optionで互換性をどこまで保って変換するかのtargetを指定可能にする
- → babel/preset-envは,ECMAScriptと歩みを合わせ,developerが実際に取り組むようなcross platformやbrowser要件の問題に対して最適な機能を提供
- まとめ
- 開発において,年次策定される言語仕様の進化と並行しながら開発できる環境を提供できる
- JavaScriptにおけるnative module仕様をemulateし現実的に課題を解決できる
- → 開発において変更可用性,scalingの担保をもたらす恩恵となる
- Babel, webpackを使う場面がなくなっても,codebaseが外的環境の変化に柔軟である点が重要
- Babelには正式な仕様以外のpluginが作成・使用されてしまったという経緯があることに注意
- 言語仕様を吸収し,解釈可能な状態で展開・連結する変換器
- JavaScript代替言語: TypeScript
- AltJSと呼ばれる
- CoffeeScript (with Ruby on Rails) → あまり使われなくなった
- Dart (by Google, with Flutter) → JavaScriptにcompile可能
- Reason (by Facebook)やElmは,TypeScriptと同じく静的型付言語としての特性を持つ
- TypeScript: あくまでJavaScriptの構文を維持し,型annotationなどで拡張された静的型付言語
- 自身が持つ型systemを省いた記述も可能
- JavaScriptにとってのsuper_setとなる存在
- TypeScriptの特徴
- 静的型付言語で,型checkとJavaScriptへのcompileを担う
- 型定義の場所
- interface.typeと呼ばれる型宣言
- 型checkとcompile errorによって,applicationの堅牢性とcodebaseの健全性に恩恵がある
- compilerとしてのTypeScript
- JavaScriptへの出力
- Babelのecosystemとは違った,独自の形でECMAScriptの新しい構文をfollowする
- あくまでもJavaScriptへの変換
- decoratorsは技術的負債になりうる
- ECMAScriptとRoleが重複するものもある
- TypeScriptによって解決できること
- 3 points
- compile errorによって,JavaScriptではfollowできない.script実行前の未然検知を可能にする
- IDEと組み合わせることで型補完やerrorを表示させ開発体験を向上させられる
- ECMAScriptとの歩みの中でBabelとは別のecosystemを築いている.早期的に取り込まれた構文利用には注意する
- applicationの堅牢性を高めたり,team developmentを行う上でcodebaseの健全性を維持することに役立つ
- 意図しない記述を許容しないという強力な安全策になる
- 3 points
- AltJSと呼ばれる
- framework/view library: Vue.js, Angular, React
- 中規模以上のapplication開発においてbackend_APIとの連携を主体に据えたviewの構築が必要であったり,user_experienceを高めるためにstressない画面遷移が求められたり,開発序盤における技術選定の中でframeworkやview libraryの選択が求められることがある
- 中長期的な運用や保守の中でproduct, applicationの特性を踏まえながら技術選定をすることは開発の現場では特に重要
- 混とんとしていた変化の時期と比べ,背後を支えるecosystemが盤石となったことも開発者の学習コストを下げている
- frameworkのbuild機構にはおよそwebpackが存在する
- 過渡期はRequireJS, SystemJSをruntimeで実現する手法もあれば,CommonJSの記法を使いながらBrowserifyがWebのためにバンドルを行う手法もあった
- → 今はapplicationと無関係なことに頭を使う必要がない
- ↑ ECMAScriptによって規格化されたES Modulesの記法で,webpackがそれをemulateするようbundleすれば十分
- frameworkのbuild機構にはおよそwebpackが存在する
- Vue.js
- PHPのbackend frameworkであるLaravelの作者が気に入って,LaravelのCLIによって新規applicationが作成される際,file setにVue.jsが内包されるようになった
- 公式サイトの説明
- UIを構築するためのprogressive framework
- monolithic frameworkと異なり,Vueは少しずつ適用していけるように設計されている
- Single_File_Componentという単一のcomponentにDOM template, style, scriptをまとめて記述しcompileする仕組みを持つことで,すべてJavaScriptのcontextに載せ替えることも可能になる
- 少しずつ適用し,小さなcomponent群を集約させながらscaleできるframework
- HTML template: \<template>
- script template: \<script>
- CSS: \<style>
- scoped
- CSSのscopeをcomponent単位で閉じるapproachは,JavaScriptのcontextで完結するlibraryにはよく見られる
- scoped
- まとめ
- communityの支えるlibraryが数多く存在し実績も多くあるので手に取りやすい
- 状態管理libraryとしてのVuexや,SSRやroutingなどを網羅したNuxt.jsなどもある
- component単位で責務をまとめSingle_File_Componentというファイルに集約することで,視覚的・機能的にcomponentが果たすべき領域を捉えられるようになっている
- 別々に分離されたlayer・責務をcomponentという単位で1つのlayerに統合している点が大きな特徴
- Angular
- by Google
- HTMLとTypeScriptでsingle_page_client_applicationを開発するためのplatform, framework
- version 1.xとして開発されたAngularJSとは互換がない
- 開発におけるひととおりのものがそろっている
- SPAのためのclient routingからfetchしresourceを取得するHttpClientなどapplication開発に必要となるものをmoduleとして最初から持っている
- command line toolによる開発一式も完備し,codebaseの足場を作るscaffoldやtest runner/unit testの仕組みまで網羅
- frameworkの概念やarchitectureは盤石 → file 構成や管理方法,細かなtool chainを組み合わせ選定し調査するといった考慮はほとんど不要
- 公式documentにより指南されたfile構成,style guideが一番参考になる
- software designやarchitectureの文脈で多少前提知識が必要
- decoratorによるDependency Injection
- RxJSでの外部通信など非同期の扱い Observablesといったarchitectureやstreamというsequenceについての理解も求められる
- webpackとの組み合わせで起点となるfile: entry fileと呼ぶ
- 例ではmain.ts
- 起点として階層別にcomponent群を集約する
- NgModule: app.modules.ts
- applicationに必要な外部moduleを整理・集約し,下層layerに分配するRole
- applicationには少なくとも1つのroot moduleが必要になる
- Component: app.component.ts
- Angular componentのinstanceを作成しそれが扱う変数やmethodが指定されるほかdecoratorによる記述がある
- Vueにおけるdata modelやevent handlerなどをobjectとして定義した形と似ている
- HTML: app.component.html
- 一部にMustache構文
- CSS: app.component.css
- 明示なしでstyle定義がcomponent内にとどまる
- まとめ
- Vue.jsと同じく,component baseのUI構築といった構成
- style guideで理想となる構造を示している
- 初手から学習領域が広くなる
- DI, HttpClientなど
- React
- by Facebook
- UI構築のためのJavaScript library
- UI構築にのみ関心
- simple view library
- minimum
- JSX: JavaScriptの拡張としての表現
- virtual_DOMという考え方
- 宣言的な記述がlogicによってのみ更新される
- Vue.js, Angularとの違い・共通点
- ReactはあくまでJavaScriptの文脈上ですべてを成立
- 木構造という概念を意識することなく宣言的なUI表現であるJSXを記述
- 実際にbrowserで表現される際のUIの一貫性を保てる
- 3 points
- all_in_one frameworkではなくUI表現にのみ関心を寄せたlibrary
- HTML templateではなくJavaScript構文で記述
- JavaScript context内で完結し変更差分を意識せずにUIに集中できる
- component指向のframework/libraryであること
- framework/libraryによりfrontend developmentはcodebaseの一貫性を保てる
- frameworkの選定には,user数,communityがactiveであることも重要だが,teamの学習状況やmember のskillにあったlibraryを選定することも考慮が必要
- 捨てやすさ
- 技術的な潮流に求められる柔軟性
- componentを疎結合に構成しいつでも変更できる状態に保つ → 技術的な環境の変化に耐えうる
- frontend developmentに求められる要件
- speed感をもって継続的に変更に対応しながらも,障害やバグを生みにくい堅牢性の高い状態を保つ
- 変更につぐ変更への耐久性のある,捨てやすさ・変更容易性が強く求められる
- component指向であることで解決できること
- framework/view libraryを利用することでteam_developmentにおけるcodebaseの一貫性や保守性を持つことができる
- 疎結合なcomponentであることで技術的な変更に耐えうる,時間とともに古びたり腐ったりしても変更可能な状態を保てる
- speed感あるrelease cycleを求められるfrontend developmentにおいて十分な堅牢性と持続性を発揮できる
- 中規模以上のapplication開発においてbackend_APIとの連携を主体に据えたviewの構築が必要であったり,user_experienceを高めるためにstressない画面遷移が求められたり,開発序盤における技術選定の中でframeworkやview libraryの選択が求められることがある
- state_management/data_layer: Redux
- componentをまたぐような横断的な関心ごとは不可欠
- browserにおけるstate_managementは煩雑
- browserの状況・動作を考慮しながらbrowserで画面遷移を完結させる動的な実装で考慮するcase
- user面で起きうることはなかなか網羅しづらい
- 主たる目的以外に考慮すべき項目が多い
- user event以外にも,deviceや周辺環境の考慮が必要
- user actionのlifecycleが長くなるほど,扱うデータもUIの状態も多岐にわたる → solution必要
- client_MVC
- 極端に抽象化すると,Model: application data model, View: output, Controller: input
- contextごとにRoleが多少異なる
- GUI application
- Model: 監視しViewに通知
- View: Modelの値をuserに適切に表示するdisplay interface
- Controller: user actionを受けてmodelへ変更を伝える
- server_side framework
- Model: data structure(DB entityと同義), data操作method
- View: browserに流すためにModelの値を埋め込んだHTML
- Controller: requestを受けて処理を振り分けデータ操作methodを呼び出す
- GUI application
- 簡易的なclient_MVC
- objectから構成され,singleton instanceが変更される,object_orientedのcode構成
- event_driven, broadcastを利用したapproach
- observer pattern
- View, Controllerがほとんど同義になることも多い
- frontendで抽象化されるModel, 扱う上での課題
- Model: GUI applicationがもつ画面に表示・plotするdata modelであることが多い
- 特にSPAなどでは,一意のendpointから得られるdata source(JSON object)を指したり,それを加工しfrontend用のobjectに整形したりするのが一般的
- client, frontend固有の表現を実現しなくてはならないdata modelも含まれる
- server_side frameworkにおけるMVCと違ってDBのentityだけでなく,UIを表現・操作するための抽象化された固有のdata modelもfrontendには必要になる
- ModelとViewは強く紐づく
- frontendに転写されるModelと対をなすようなserver_sideのDB entityやAPI endpointの改修がapplicationの基幹的なRoleを担うことが多いため,frontendに課題解決がシフトしがち
- 双方向のdata_flow
- 各layerが単一責務を果たすための制約
- 以上の制約は,複雑になったときにどこでどんな変更があったのか・なぜViewが影響を受けたのか認知の範囲を超える危険性がある
- 規模が大きくなった際に抽象化されたdataがlayerをまたいで双方向に行ったり来たりすることは懸念が増える要因の1つ
- Model: GUI applicationがもつ画面に表示・plotするdata modelであることが多い
- RoleがあいまいになるController
- frontendにおいてはRoleがserver_side以上のものになりうる
- Controller ≒ Viewのようになり責務があいまいになって,制御しづらく複雑化しがち
- client_MVCの課題
- Modelにはserver_sideのdata_modelをAPIを通して投射したmodel, frontend固有のUIを抽象化したmodelが含まれ,Viewにおける関心がModelをまたいで複雑に絡み合っている
- ModelとViewの変更において密に相互利用しているため,変更起点が不明瞭になりdata_flowが制御しづらくなる
- ModelとViewは関連性が強い一方で変更が望まれやすく,可用性や変更可能性が求められる
- Controllerの担う責務が多くRoleがあいまいで,管理や制御が困難
- → Flux pattern → Redux
- Fluxというapplication architecture pattern
- by Facebook
- frontendに主軸を置くapplication architecture
- 単一のdata_flowを採用した,MVCとはまったく考え方が異なるarchitecture
- Action → Dispatcher → Store → View → Action
- Actionを起点にして一方向にdata_flow
- 各layer
- Action: Storeに存在するデータを更新するうえで必要な識別子.合わせて関連するデータも送出.
- Dispatcher: データを伴って発行されたActionを補足しStoreに送り出すためのAction hub
- Store: applicationが扱うdata/state. Storeの変更はAction → Dispatcherにおいてのみ変更される.基本的にはJavaScriptにおけるobject
- View: UIそのもの.Storeの変更通知を受けるための接合点が必要.ViewからもActionを発行する.
- Redux: dataの一極管理
- Fluxはarchitecture patternのため,多くの実装が存在する
- Fluxは複数のStoreを許容するが,Reduxは1つのStoreのみ許容する
- single source of truth
- 複数のdata_modelやstateを扱うStoreこそがapplicationが唯一依存すべきtree状のobject
- DispatcherがStoreに大きく紐づいている
- Reducerがいる
- Reducer: 実際にStoreの変更を受け持つ
- 発行されたActionと現State=今のapplication stateを引数にした関数
- Reduxの2つの重要な原理を持つ
- 状態を読み取りのみとして,更新する場合は新しい状態を作成して送出
- : immutable
- debug, test容易
- Reducerは純粋な関数
- 引数によって新しいStateを返却する冪等な処理の関数
- Storeを1つのReducerで管理させるところからスタートしても,applicationの成長とともに適切に切り出すことでscaling〇
- 状態を読み取りのみとして,更新する場合は新しい状態を作成して送出
- ReducerからapplicationのStoreを作成
- Reducer 1つがState 1つとなる対の構成となるケースがほとんど
- combineReducersという複数のReducerを束ねるhelper functionがある
- Reducer 1つがState 1つとなる対の構成となるケースがほとんど
- ViewがどのModelと紐づくかより,application全体における状態の一部を参照し,変更によって再実行されるという構成
- Viewと紐づくrender functionがStoreの値を監視し反映する
- button click時の挙動もModelの直接的な変更ではない
- 識別されるuniqueなActionを発行しStoreに送り出しているだけ
- Storeの変更は監視するrender functionの再呼び出しにより順次Viewに反映していく
- MVC patternのModel/Controllerというlayerの責務・Roleは,Flux/ReduxにおいてはStoreに内包されている
- Reduxは,messageによるbroadcastをより強固にしたevent_driven architecture
- Reduxが解決できること
- 3 points
- ViewをまたがるModelの変更検知という煩わしさはStoreという唯一のstateをViewにbindすることで解決
- Storeの変更は,Actionからしか変更できないという制約により状態変更の見通しが立ちやすい
- Model/Viewの密結合を避けることが可能であるため,可用性や変更容易性に優れている
- ViewであるcomponentはStoreの値にのみ集中できる点から,疎結合で構成されるcomponent指向のlibraryとの親和性が高い
- Redux周辺のecosystemを支えている
- 採用を検討するケース
- 複数のUI componentをまたぐdata_model, stateの共有が増えてきた
- release後に変更が多く発生するにもかかわらず開発コストが大きく感じる
- 3 points
- CSS: CSS meta_language, design手法, CSS-in-JS
- CSSを取り巻く現状
- W3Cがまとめている
- 1~2年単位でmoduleの使用状況をsnapshotとして文書化している
- browser vendorや開発者communityとどう関わりあっているかがECMAScriptよりも追いかけづらい
- 各browserの対応状況について
- Can I use
- 全体として大きな機能を扱う
- CSS Grid Layout Moduleなど機能レベル
- 全体として大きな機能を扱う
- MDN
- 仕様や詳細なproperty levelを扱う
- grid-column, grid-templateなど
- 仕様や詳細なproperty levelを扱う
- npmにlibraryとして公開されている
- Can I use
- CSSの表現力を高めたSass,CSS meta_language
- JavaScriptで作成されたPostCSS
- 構文をparseしAST(Abstract Syntax Tree)を操作するAPIを提供し最終的にCSSを出力するtool
- pre-processだけでなく最適化などを行える
- plugin群で,変数化やネスト構造の実現などの機能をそれぞれ単体で提供
- pluggable, 拡張性が高い
- Sassの一部の機能だけを取り出し個別に組み合わせたいといったケース,CSS module levelがfixしてbrowser実装を完了したが対応していない下位browserに対してfall backしながら変換したいケースなどに有効
- e.g.
- Sassにおける@extendを利用してstyleの継承を行いたい
- postcss-extend-rule
- Sassにおけるnest構造によって親selectorの疑似クラスを記述したい
- postcss-nested
- 新しい仕様を後方互換性をもって下位browserへfall backしながら実装
- postcss-preset-env
- babel/preset-envと名前も役割も似ている
- vendor prefixの問題も解決する
- Autoprefixerというlibraryで,通常のstyle propertyに合わせて,vendor prefixのついたpropertyを追加する変換を担当する
- libraryはCan I useのDBを利用している
- Autoprefixerというlibraryで,通常のstyle propertyに合わせて,vendor prefixのついたpropertyを追加する変換を担当する
- 具体的に対応させたいbrowser, OS versionはBrowserlistのqueryを書く
- postcss-preset-env
- Sassにおける@extendを利用してstyleの継承を行いたい
- CSS design手法
- CSSの大きな特徴であり弱点
- styleをいつでも(後方から)上書きできること
- cascadingと詳細度により意図しないstyle崩れが起きる
- styleをいつでも(後方から)上書きできること
- BEM
- componentという概念とselectorの命名規則を組み合わせたCSS design手法
- uniqueな名前空間とuniqueなselectorによるstyling
- Block
- 独立した構成要素の粒度で1番大きいもの
- Element
- Blockを構成する粒度の細かい構成要素1つ1つ
- Modifier
- Elementを拡張・装飾するvaliation
- 厳格なrule
- styleにはclass selectorを使うことがほとんど
- ID selectorを使わない
- uniqueなsingle selectorを要素のclassに付与しstyleを組み上げる
- HTMLが冗長という負担はあるものの,無記名のHTML要素を廃しそれぞれの要素がuniqueな名前空間を持つことでBlockでまとめたcomponentのscope管理を実現可能にする
- JavaScript framework/libraryとの組み合わせで解決する手法もある
- CSSの大きな特徴であり弱点
- CSSの弱点を補うためには
- postcss-preset-envで利用できるoption: stage
- ECMAScriptの策定におけるステージ制と類似したもの
- postcss-preset-envで利用できるoption: stage
- CSSを取り巻く現状
- static_analysis_tool
- 不整合をsource code実行前に検出し問題を提案するtool
- 実行せずにcodeの欠陥を予測する
- あらかじめrule/coding規約をteamに持つ
- → 無駄な指摘を減らし機械的な指摘ができる
- → source codeに一貫性をもたらし可読性が上がる
- JavaScriptはruntimeでのみerrorを検出するため事前に検出が必要
- Prettier
- 多言語をfollowするJavaScript製のformatter
- EditorConfigでformatする場合もある
- trailingComma, printWidthなど個人のcoding styleによるところが大きい部分をformat
- printWidthは多言語・記述をフォローしている
- この強力な機能がPrettierを選択する理由になる
- codebaseにおける規約やstyleは,teamで合意・納得している状態が,開発を進める中で健全
- ESLint
- codebaseにおける細やかなruleをpluggableに追加可能なlinter
- Lint: 潜在的なerrorを未然に検知し警告すること
- no-cond-assign
- より強力
- .eqeqeq
- prefer-const
- より強力
- no-fallthrough
- typescript-eslint, eslint-plugin-reactなどの追加ができる
- 実行前に警告できる + team ruleを投射
- teamとcodeの成長に合わせて追加できることが重要
- codebaseにおける細やかなruleをpluggableに追加可能なlinter
- ほかのlinter/checker
- npx htmlhint https://example.com
- HTMLの規格への準拠や規格とは別のruleのチェックもできる
- 厳密にはlinterというよりvalidator
- stylelint
- CSSにおけるlinter
- BEMの設計手法に頼らず,cascading/詳細度による意図しないstyleの上書きを防ぐために,stylelintのselector-max-specificityといったruleで詳細度を制御することもできる
- npx htmlhint https://example.com
- static_analysis_toolが可能にすること
- 構文のformatをrule化
- bugの未然検知に役立つような記述ruleやcode styleのrule化が可能になる
- 3 points
- 人間による指摘以前に機械的にcode styleやteamのcoding styleを指摘できる
- code styleの衝突はいつでも起こるもの,事前にteamで取り決めておくことで不要な議論を避けられる
- static_analysisによってscript実行前にbugの芽を摘み取れる
- 本質的な作業に集中することを助ける
- unit_test: Mocha, Jest, Karma
- テストの種類
- unit_test
- programの正常性をmodule単位で検証する
- 多くは言語に合わせてprogrammable toolやtest frameworkを使う
- by developer
- integration_test
- module同士を結合し動作させ,usecaseからtest項目を作成し実施,正常動作を担保する
- by developer, test engineer
- acceptance_test
- Web frontendのGUIからの操作におけるテスト項目を作成し実施し,正常動作を担保する
- by QA, test engineer, tester
- unit_test
- unit_testとfrontend development
- unit_testは品質の担保という側面より,developerが心理的負担のない状態で安全に開発するために存在しているという考え
- 安全に変更できることがメインで,おまけで品質がついてくる
- unit_testは品質の担保という側面より,developerが心理的負担のない状態で安全に開発するために存在しているという考え
- Mocha, Jest, Karmaそれぞれの特性
- range
- Mocha
- test environmentの提供
- test framework
- 監視機能
- Jest
- test environmentの提供
- test framework
- assertionの提供
- snapshot test
- test double
- 監視機能
- coverage計測
- Karma
- test environmentの提供
- 監視機能
- Mocha
- Mocha
- 別にassertion libraryが必要
- assertion: testの合否を確認するためのmethod
- Chaiなど
- describe: test grouping
- it: testcase
- Node.jsのassertion libraryを使った例
- test frameworkは出力結果にテストが通ったことを表示する仕組みや関数を持つ
- 別にassertion libraryが必要
- Jest
- Jestを使うと,実行環境はNode.jsだがbrowser側のWeb APIをfollowすることができる
- 必ずしもこれがJestを選択する目的ではない
- jsdomを利用してWeb APIをfollowしbrowserでの実行をemulateしているため
- expect
- matcherの引数に期待する値を設定したり,引数なしのmatcherで期待する値を表現したりするassertionが一般的
- matcher: chainするmethod
- mock
- spy
- 呼び出された際の引数や結果,呼び出し回数などの情報を格納している
- matcherの引数に期待する値を設定したり,引数なしのmatcherで期待する値を表現したりするassertionが一般的
- 小回りが利きやすくNode.jsのみで実行しやすい
- 便利なall_in_one test framework
- Jestを使うと,実行環境はNode.jsだがbrowser側のWeb APIをfollowすることができる
- Karma
- unit_testでbrowserを変えたい,browserのJavaScript engineで実行したいという需要のため
- Angularが提供するcommand line tool
- AngularはKarma + jasmine
- test frameworkではなく,unit_testの実行環境を起動するためのrunnerのRoleのみ果たす
- test frameworkの変更や実行環境の変更が設定により柔軟
- range
- unit_testやtest frameworkが解決できること
- release後に変更可用性やspeedを求められるのがfrontend
- 変更に耐えうるcodebaseや環境を作るためにunit_testのtest frameworkが必要になってくる
- 必要な部分から必要なだけ始めてみるのもfrontendにおけるunit_test導入のための戦略の1つ
- 変更が頻出する部分など
- テストの種類
Ch04 開発の現場における仕事の進め方
- agileといった考え方
- technologyやlifestyleが刻々と変容していくなかで,柔軟な対応が必要になっている
- source codeやapplicationを変更に耐えうる状態にすること,変更容易性を保った状態にすることが重要
- → agile
- scrumという開発手法
- 個人との対話と他者との協調
- → 学習メモ参照
- communication hubとして
- 誰もが触れることができるbrowserを主務としているengineerであり,操作や機能要望を一手に担うことが多い
- frontend_engineerの責務
- 画面デザインをbrowserで具現化するために実装する
- server_sideから渡ったdataを使ってbrowserにGUIを組み上げる
- browser上で正常にapplicationが動作するようにする
- → team_memberとの合意を経て,browserという職種に依存しないfieldの上で形にしていく必要がある
- → publicに情報を明確にしてteam_memberと相談しながら開発を前に進める,communication hubのような責務を持つ
- 変化に対応しながら提供するサイクルを速くする
- ここまでのまとめ
- 動くproductを速いサイクルで変化に対応しながら提供するために必要な解決策を持っていることがimportant
Part 2 どう使うかを学ぶ
Ch05 development_environment
- 既存applicationのdevelopment_environment構築
- Dockerのinstall
- Node.jsのinstall
- Yarnのinstall
- API serverの起動
- docker-compose build
- docker-compose up -d
- -d: backgroundで実行
- clientの起動
- 既存機能の把握
- どんなapplicationなのかを知る
- まずdata_structureを見る
- 機能を見る
- applicationが抱える課題を探る
- jQueryのcode
- DOMへの影響を常に考慮する必要がある
- すべてのcodeがbrowser event紐づき複雑に絡み合っていく
- → React, Fluxで解決できる
- 文字列内に変数を挿入することで書きづらいcodeになっている
- communityがどれだけ活動しているかやrelease頻度なども技術選定において重要な指標になる
- jQueryのcode
- どんなapplicationなのかを知る
Ch06 設計と実装
- branchの切り替え: git checkout \<branch>
- frontend環境の構築
- TypeScriptの導入
- TypeScriptのinstall
- yarn add typescript --dev
- yarn run tsc --init
- 公式referenceで必要な設定を選択していく
- Babel経由でTypeScriptのcompile
- yarn add @babel/preset-typescript --dev
- 既存コードをTypeScriptで書き換える
- compile errorを解消する
- TypeScriptのinstall
- codeの分割
- 処理を別のファイルに切り出す
- export, import
- 処理を別のファイルに切り出す
- Jestを利用したunit_test
- Jestのinstall
- yarn add jest @types/jest ts-jest --dev
- jest.configの設定
- yarn run jest --init
- 描画されたDOMの検査
- id, classで判別か,それができなければselectorでDOMをたどる
- 仕様をテストコードに入れておく → 改修時の確認コストが大きく下がる
- Jestのinstall
- Reactの導入
- Reactのinstall
- yarn add react react-dom
- yarn add @types/react @types/react-dom --dev
- JSXのためのcompile設定
- yarn add @babel/preset-react --dev
- JSXで要素を表示
- webpack-dev-serverのinstallと設定
- yarn add webpack-dev-server --dev
- fileに変更を加えた際に自動でbrowserに反映
- jQueryで書いたcodeをReactに置き換える
- APIとの通信 → stateに保存 → 画面が再描画
- event_handlerの記述
- yarn add react-transition-group
- yarn add @types/react-transition-group
- react-transition-groupはReact Componentでanimationを実装するためのpackage
- useState(), useEffect()などのHookを使うことで,大量のコードを書かずに動的な画面を構築できる
- 独自のHookの作成もできる → 複数のComponentで再利用したい処理の切り出しもできる
- Reactのinstall
- Enzymeを使ったcomponentのtest
- Enzyme: React_Componentのテストを補助するためのutility
- Enzymeのinstall
- yarn add --dev enzyme @types/enzyme enzyme-adapter-react-16 @types/enzyme-adapter-react-16
- Jestの設定
- jest.config.jsにEnzymeの設定を追加
- setupEnzyme.tsをJestが読み込むように設定
- Jest実行時にJSXのcompileができるよう修正
- yarn add babel-jest --dev
- yarn remove ts-jest
- babel-jestはbabel.config.jsを見にいく
- jest.config.jsにEnzymeの設定を追加
- React_Componentをテストする
- Enzymeのrendering方法
- shallow(): child componentは描画せず,引数に与えたcomponentのみを描画する
- mount(): jsdomなどのDOM emulatorを利用してchild componentを含んだ状態でDOMにmount.React lifecycle methodも呼ぶ
- render(): child componentを含んだ状態で描画するがlifecycle methodは実行されない
- → 表示結果の確認だけならshallow()/render(), lifecycle内で処理した結果をもとにDOMを構築しているようなcomponentではmount()
- mock機能
- mocks/(filename)にmock用のfileを置く
- APIとの通信などにmockを用意する
- act()でEnzymeの描画実行をラップ
- Hookをテスト対象のcomponentが利用していた場合にテストが実行できなくなる問題の回避方法
- Enzymeのrendering方法
- styled-componentsの導入
- componentとstyleをセットで扱う
- styled-componentのinstall
- yarn add styled-components
- yarn add @types/styled-components babel-plugin-styled-components --dev
- babel.config.jsに追加
- CSSからstyled-componentsへの移行
- 目的
- 開発効率を上げてreleaseまでのlead timeを短くするために開発基盤を整備し,開発者が安全にコードを変更し運用していくために型の導入やunit_testを作成している
- まずは足場を固めて自由度の高いcodebaseを作る
- 開発効率を上げてreleaseまでのlead timeを短くするために開発基盤を整備し,開発者が安全にコードを変更し運用していくために型の導入やunit_testを作成している
Ch07 CI/CDによって受けられるmerit
- workflowに自動検出を導入し安定したapplicationを提供しながらどのようなmeritを受けられるか
- CI/CDによって受けられるmerit
- lint, test, compileなどを自動化
- 理由
- developerの手動負担を抑える
- development_processのあり方の変化
- agile
- 安定した定期的なreleaseのためには自動化された安全性の確認が非常に重要
- agile
- 理由
- CI/CDについて
- 各tools
- GitHub Actionsを始める
- ESLintを導入し動作させる
- CIで自動化するmerit
- 手動操作やreviewでの疲弊を回避
- development_processが健全になる
- product code自身も健全性を維持できる
- 安心感
- CI: 安定したapplicationを効率よくuserに届ける仕組みであるとともに,本質的なdevelopmentに集中できる
- lint, test, compileなどを自動化
- performanceと改善
- backendでHTML documentのresponseを返すlatencyが大きい
- ↑ Performance/Network tabで確認
- frontendでJavaScriptファイルのサイズ肥大化やscriptがUI構築のblock要素になっている
- Performance tabで計測後Long taskの警告数が多いかどうか確かめる
- 50ms以上で警告
- performanceの問題とは
- 新規開発
- developerの関心の薄さや非機能要件の認識不足に起因する
- release済
- userの問い合わせで発覚することが多い
- 定期的な計測が必要
- performanceだけを意識する必要はない
- 新規開発
- 基礎的なperformance知識: critical_rendering_path
- 早い段階での画面描画のspeedが重視されている
- conversion rate, 直帰率の低下, 滞在時間の長さ, 同セッションでのpage viewの多さにつながる
- critical_rendering_path: 初期描画に必要なresource/step
- Reactを使ったclient_side renderingの実践では,loading中のUI提供をする限り初期描画が問題になることはあまりない
- critical_rendering_path: CSS
- critical_rendering_path: JavaScript
- 初回画面構築に不要なら,headではなくbody tagを閉じる手前に移す
- async: download後のscript実行時はblock
- defer: 画面構築に影響がないときに〇
- 初回画面構築に不要なら,headではなくbody tagを閉じる手前に移す
- Lighthouseを利用した定期的なperformance計測
- 根本原因を探ることが難しくなることがある
- → 定期的な計測・検知の仕組みを整えて計測結果を得ることが重要
- CIで定期的な計測を実行する
- Core Web Vitals
- Largest Contentful Paint(LCP)
- First Input Delay(FID)
- Cumulative Layout Shift(CLS)
- 指標の判断は各々
- Lighthouseを利用する
- npx lighthouse ...
- goal: outputを知り目標とする数値を超えていないかを検知して知らせること
- lighthouse-ciを使ったaction: treosh/lighthouse-ci-action
- 新しいworkflowを追加する
- GitHub Actionsではworkflowを物理ファイルで分けられる
- .github/workflows/lighthouse.ymlを作成
- 特定のmetricsや閾値の設定
- uploadArtifacts: true
- 結果reportをdownloadできる
- Developer_Toolからtrace可能なreportがほしいときは,lighthouseを使うのも〇
- --save-assets optionが必要
- puppeteerというChroniumをheadlessで動かすtoolとlighthouseを使って簡単にscriptの実装ができる
- Datalogという監視やmonitoringのためのSaaSで数値をplotして可視化もできる
- GitHub Actionsではworkflowを物理ファイルで分けられる
- 早い段階での画面描画のspeedが重視されている
- 強力な武器はない,人には人のperformance
- performanceは1つの指標に過ぎない
- backendでHTML documentのresponseを返すlatencyが大きい
Ch08 analysis, monitoring
- serviceの成長とともに開発する
- 保守・運用: product, serviceを成長させていくphase
- 数字として可視化して目標と比較するために,計測する仕組みとしてanalysis_toolやAB_testが導入されることが多い
- 計測のための実装やAB_testの実施もfrontend_engineerの責務
- 仮説検証,AB_testの目的
- 仮説検証
- personaを使って施策の議論や価値提供の優先度を考えることも多い
- analysis_toolの導入により,目標値に向かうためのuser actionをある程度可視化できる
- AB_test
- personaから推察される行動を考え仮説を立てて,短いiterationで立証するため
- marketingにおける調査・試験の一種
- GUIにおけるpatternや組み合わせで立証することが多い
- UIや使い勝手,操作性などclient接点における価値をすばやくuserに届け仮説検証を行うことが,analysis, AB_testの目的になる
- 仮説検証
- toolの導入: Google_analytics
- 計測のためのsnippetを導入するだけでデータの可視化や計測がいちはやく手に入れられる
- Google_marketing_platformの1 product
- analyticsの利用登録
- 計測のためのtracking code
- eventの計測,属性の追加
- ラップしたようなevent送信用の関数を作る
- service 1つに対してproperty 1つ
- 重要
- action nameやcategory, label nameなどをteamで設計し,memberが共通理解を得ること
- toolの導入: Google_optimize
- AB_test用のtool
- html code → p.211
- 振り分けの完了は,Cookieの_gaexpの値の末尾を見るとわかる
- product codeに組み合わせる
- ReactのHooks APIを利用した実装方法
- UIと振り分けを宣言的にする
- Reactが実行される段階ではtest patternは決定している
- third_party scriptとの兼ね合い
- client performanceにはいくらか影響が出ることに注意する
- AA_testで導入によって数値に影響が出ないことや実際に振り分けが行われることを確認する
- toolの導入における懸念事項の洗い出しや組み込んだ場合の結果の提供もfrontend_engineerの責務
- user_monitoring, error_event_monitoring
- 障害や問題をrealtimeで検知する仕組みが必要
- userを取り巻く環境を知る
- Developer_Tool
- network状況をemulate
- specをemulate
- analysis_toolでまずuserの環境・状況を知ることがimportant
- Developer_Tool
- browserで起きるerror_eventなどからuserを知る
- error_event_monitoringのため,Sentryを導入
- yarn add @sentry/react
- 設定できること
- error_eventへの緊急度levelの設定
- error_eventの閾値超えによるalert(各種tool連携)
- release versionやuser definitionのmeta information付与
- sourcemapを利用した影響のあったsource codeの表示
- documentが豊富
- team全体で導入する
- Sentryの動作とcodeへの組込
- global scopeにおける例外handler
- top levelに繰り上がった例外をさばいている
- 事前に用意できるものは個別に準備しておく
- global scopeにおける例外handler
- React Error Boundaryを使う
- fallback UIをuserに提供できる
- error_eventのlogも取れる
- 昨今のReactでの開発は関数としてcomponentを実装するが,Error Boundary componentはclass baseの componentである必要がある
- 収集したerror_eventを役立てる
- errorとして収集して対応したものも,情報として収集を続ける必要があることもある
- Cookieの使用状況など
- error_eventのlevelづけ
- error_eventの発生ログは,大きな判断材料になる
- この数字がteamでの対応優先度を決めるのに一番良い判断材料になる
- product_backlogに追加も〇
- errorとして収集して対応したものも,情報として収集を続ける必要があることもある
Part 3 応用編 より深く学ぶために知る
Ch09 team_developmentとWebへの貢献
- teamで働く
- Scrumという開発手法について(あらためて)
- → 学習メモ参照
- Scrumを採用したteamに入ったら
- story: sprint_planning
- story: sprintの開始
- story: sprintの終わり
- team_developmentとはtechnical skillではない
- Scrumという開発手法について(あらためて)
- communityへの貢献活動
- OSSへの貢献はcode_commitだけではない
- bug report, document修正, 簡単なpull_requestから始めてもよい
- communityをのぞいてみる,issueを立てる
- CONTRIBUTION.mdのようなdocumentに,貢献の方法や何から始めるのが良いかが書いてある
- CODE_OF_CONDUCT.mdで行動規範を掲げているものもある
- 機能報告・bug報告の方法
- まずは,OSSのrepositoryにあるissueを検索し,類似した内容の有無を確認
- bugの再現状況の追記なども〇
- templateを使う
- できることからOSSへcommitする
- 各issueにはlabelがある
- 寄付する,翻訳するといった違ったapproach
- Webというplatformに貢献する
- Webというplatform: Web site/applicationを開発するためのHTML,CSS,JavaScriptの標準化されたtechnology群
- Webは維持し続けることがimportant
- product_codeを健全に保ち周知していくことも,小さな規模だがteamへの貢献になる
- OSSへの貢献はcode_commitだけではない
- Web platformにかかわるfrontend_engineerとして
- 仕様を知るには
- lightにcatch_upする
- frontend technologyを楽しむために
- 動くproductを早いcycleで変化に対応しながらuserへ届けるために,必要な解決策を持ち実現できることがより重要
- 実現できることよりさらにproductに反映できることが重要
- Webへの興味関心を持ち続ける
- 変化が早く感じるときは,情報を見過ぎている可能性を考える
- enduserはdeveloperではない
- userの課題を解決するために,userへの価値提供のためにWeb platformを使ってdevelopmentを進めていく・課題を解決するということに,意識的であることや楽しむことがfrontend開発において大切
『入門React: コンポーネントベースのWebフロントエンド開発』学習メモ
Part 1 基礎
Ch01 Introduction
- 背景
- React: XHPというPHPのframeworkのJavaScriptへの移植
Ch02 JSX
- Separation of concernsのために,Componentを使う ←→ templateと表示logicといった分離
- Component: Markupとそれを生成するcodeが強く結びついたもの.Reactの中心的な概念.
- What's JSX
- JSX: JavaScript XML
- ReactのComponent内でMarkup言語を記述するためのXML風のsyntax
- 特徴
- JSXはsyntax拡張.(あとでJavaScriptの関数呼び出しに変換される)
- JSXはruntime libraryが不要
- JSXはただの関数呼び出し
- JSXのmerit
- 既知の構文
- 意味的な分かりやすさ
- JavaScriptのcodeをよりsemanticで意味のあるMarkup言語で記述できる
- Componentの構造と情報のflowはHTML風なsyntaxで宣言的に記述
- applicationで定義されたcustom Componentをタグ名として使用〇
- 構造の可視化
- 抽象化
- projectの進展に伴うcodeの変更を減らす
- Separation of concerns
- Component内のMarkupとBusiness Logicを分離
- Component合成
- custom Componentの定義
- dynamic value
- child node
- this.props.children: start-end tag内の全子nodes
- JSXとHTMLの違い
- JSXなしでReactを使用したい場合
- ReactElementの作成
- 簡略化
- 参考文献
Ch03 Componentのlifecycle
- Component: state machine → inputに対して常に同じoutput
- Component作成時に呼ばれるmethod
- Componentのinstance作成~初回描画
- Componentを利用可能にするための設定
- getDefaultProps
- Componentにつき1回のみ
- 非scalar値は共有
- getInitialState
- instance作成事
- ここからthis.propsが利用できる
- componentWillMount
- 初回の描画前
- renderの前にComponentのstateを変える最後の機会
- render
- Virtual DOM(Componentのoutput)を作成
- ReactのComponent中で唯一省略できないlifecycle method
- rules
- componentDidMount
- Componentのinstance作成~初回描画
- Component作成後に呼ばれるmethod
- componentWillReceiveProps
- 親Componentがpropを変更したとき
- shouldComponentUpdate
- optimezeのためにある
- develop時には使わない.tuningで使う.
- PureRenderMixinでperformance tuneも〇
- componentWillUpdate
- state, propsの更新は×
- componentDidUpdate
- 変更されたDOMのreferenceへのaccess
- componentWillReceiveProps
- Component破棄時に呼ばれるmethod
- 不要になったらReact DOMから切り離してdelete
- componentWillUnMount
- deleteの直前
- 後処理できる
- timer, event listenerなど
- anti pattern: 加工された値をstateに保存する
- a single source of truthの原則 @React
- → 単一のinformationのcopyが可能になる
- e.g.
- initialValueはOK
- a single source of truthの原則 @React
- まとめ
- lifecycle method: applicationがComponentのeventにeffectiveに反応できるようdesign
- 各Component: state machine.一貫して安定した予測可能なmarkupをoutput
Ch04 data flow
- 基本は親から子への一方通行
- Component: 親からのpropを描画
- propの変更 → propを参照する全Componentが再描画
- 内部state: Componentの内部でのみ変更可能
- Component: propsとstateをinput, Virtual DOMをoutputする一種のfunction
- props
- props: Componentに渡される任意のdata
- setProps: 子Componentに対して呼ぶか,Component treeの外側で呼ぶのみ
- Componentは自身のpropsを変えない
- JSXでのpropsの指定
- ...: 後に続くObjectをその場に展開
- event handlerの格納も〇
- propTypes: propsとして渡された値をvalidate
- Componentの仕様が明確になるため,使用推奨
- getDefaultProps
- React.createClass時にキャッシュ
- state
- Componentの内部でのみ使用
- 要素の表示内容の決定に使う
- getInitialStateっでinitialize
- setState
- 必ずrender()を伴う
- directにthis.stateの変更は絶対×
- なるべく一部のComponentのみ
- 複雑になるため
- stateとpropsの使い分け
- stateはComponentの機能にdirectに必要な単純なdataのみに〇
- propsの値をstateにcopy×
- まとめ
- prop経由でCompにdataを渡し,tree全体に伝播
- propsはimmutableとして扱う(Component内)
- 子Componentとのやりとりのために,event handlerをpropsに指定
- 表示内容を決定するためのsimpleなdataのみstateに保存可能
- this.setStateを必ず使う
Ch05 event_processing
- UIの半分は表示,残りの半分はuserのinputに反応すること
- JavaScriptで,userのinput eventに応じたevent_handlerを記述する
- Reactでのevent_processing
- まずevent_handlerを登録
- handlerが呼び出されたときにcomponentのstateを変更する処理を記述
- render method内でstateを参照しさえすれば,変更は自動的に描画に反映される
- 追加の情報は,event_handlerに引数として渡されるevent objectが追加の情報を含んでいるので,それをもとにstateを適切に更新できる
- techniqueとReactの高性能なRenderingの仕組みにより,容易にuser inputに反応してUIを更新できる
- event_handlerの登録
- onClick
- eventとstate
- たいていはsetStateで既存のObjectにマージする
- Object変更時は必ずsetState/replaceState
- event_object
- event.target.valueからformのinputを取得
- 特にonChangeでよく使われる
- event.target.valueからformのinputを取得
- まとめ
- Reactでuser inputをUIに反映させる手順
- React componentにevent_handlerを登録する
- event_handler内でcomponentのstateを変更する.stateを変更するとcomponentは再描画される.
- componentのrender method内でthis.stateを参照するように変更する
- Reactでuser inputをUIに反映させる手順
Ch06 componentの合成
- HTMLではpageは要素から構成されるが,Reactではcomponentから構成される
- ReactのcomponentはHTMLの要素にJavaScriptの表現力が追加されたもの
- component: propsとstateをinputとして受け取り,HTMLを出力として返す一種の関数のようなもの
- 各componentはapplication内のデータの一部を表示するために設計されている → React componentはHTMLの拡張といえる
- HTMLの拡張
- lifetimeを通じて,React_componentは振る舞いをcontrolできる
- React.createClass
- 継承より合成
- 小さくて単純なcomponentを組み合わせて,より大きくて複雑なapplicationを構築する
- 合成の例
- has aで表現できる
- 汎用的なinput要素から初めて,radiobuttonにcustomizeし,多肢選択の機能を提供する例
- original form controlのcomponentの作成
- 親子間の関係
- 親child_componentでの通信の最も簡単な方法: propsを使う.親がcallback functionをpropsとして渡して,子がそれを呼び出す
- child_componentの変更に対する振る舞いを定義
- 親child_componentでの通信の最も簡単な方法: propsを使う.親がcallback functionをpropsとして渡して,子がそれを呼び出す
- まとめ
- Reactにおいて合成のpatternを使用する手法
- HTMLの要素や自信のcustom componentをwrapして,必要に応じてそれらの機能をcustomizeすることで,componentを作成する
- 汎用的なcomponentは,合成のたびに特化され意味を持ったものになる
- Mixin: 合成以外の方法 → 次章
- Reactにおいて合成のpatternを使用する手法
Ch07 Mixin
- Mixin: 複数のcomponent間で共有可能なmethodを定義できる
- Mixinとは
- Mixinを使ったTimer componentの実装
- componentにmixinsというpropertyを定義する
- 制限
- 複数のタイマーは持てない
- Timer eventのhandler methodの名前はonTickに固定
- タイマーを止めるには内部の__interval propertyにアクセスする必要がある
- → コードは増えるが修正できる
- 適用例
- eventを監視してstateを更新するMixin(e.g. FluxのStore Mixin)
- XHRのuploadを行いprogressをstateに反映するMixin
- child_componentをの末尾に表示するためのlayer Mixin(e.g. modal dialog)
- まとめ
- Mixin: codeの重複を避けるために有効な手段
- componentは自身に固有の責務に集中できる
- 強力な抽象化の手段を提供
- ある特別なふるまいや役割をcomponentと切り離して記述できるので,codeはより理解しやすいものになる
- Mixinとして定義できないか常に検討する
- Mixin: codeの重複を避けるために有効な手段
Part 2 応用
Ch08 DOM操作
- 通常はReactの提供するAPIだけでUIを構築できるので,実際のDOMに直接アクセスすることはほとんどない
- componentを合成することで,複雑なUIをまとまった全体としてuserに提示できる
- Reactとともに使用することを想定していないthird partyのlibraryを導入する場合や,Reactで非supportのDOM操作を行いたいときがは,DOMへのアクセスが必要になる
- componentのlifecycleの特定の局面でしか利用できないという制限あり
- DOM_nodeへのaccess
- まずそのnodeを表現するcomponentにアクセス
- componentにref属性を設定して実現する
- ref属性はcomponentのすべての子nodeの中でuniqueである必要あり
- ほかの子nodeのref属性と重複は×
- ref属性はcomponentのすべての子nodeの中でuniqueである必要あり
- → componentDidMountの中で,React.findDOMNode()を使って実際のDOM_nodeにアクセス
- event_handler中でも〇
- componentにref属性を設定して実現する
- どうしても必要な場合以外は使わない
- Reactが内部で行う最適化の妨げになるうえ,applicationが複雑化する要因になる
- まずそのnodeを表現するcomponentにアクセス
- React friendlyでないlibraryの使用例
- オートコンプリートlibraryの例
- 行儀の悪いlibrary
- 自身がアタッチされた要素の内容を,カスタムイベント経由で変更してしまうpluginの例
- 親の要素まで変更する場合は対応できないので,Reactとの併用はできない
- Reactを守るために,pluginの使用するDOM_nodeを完全にcontrolする必要がある
- componentDidMountの中で独自に要素を作成し,renderで作成された要素の子nodeとして追加する
- 不要になった際は自分自身で削除が必要 @componentWillUnMount
- pluginのdocumentをみて,ほかに必要な手順がないか確認する
- global event_listenerやtimerやAJAX requestなど
- pluginのdocumentをみて,ほかに必要な手順がないか確認する
- Reactに管理されていないdivの描画の更新
- 確実: componentを疑似的にpageから削除して追加する
- 簡潔でperformance〇: pluginの更新用のAPIを呼び出す
- ごく単純なpluginの場合は,同じ機能を提供するReact componentを作ってしまった方が早いこともある
- 自身がアタッチされた要素の内容を,カスタムイベント経由で変更してしまうpluginの例
- まとめ
- Reactが提供するAPIだけでは不十分で,どうしても実際のDOMにアクセスしなければいけない場合がある
- ref属性を設定して,特定のcomponentにアクセスし,そのcomponentの実際のDOM_nodeへの参照をReact.findDOMNode()経由で取得する
- componentDidMountが呼び出されてからでないとアクセスできない
- → ReactがサポートしていないDOM操作や,Reactとともに使われることを考慮されていないthird partyのlibraryの使用が可能になる
- ref属性を設定して,特定のcomponentにアクセスし,そのcomponentの実際のDOM_nodeへの参照をReact.findDOMNode()経由で取得する
- Reactが提供するAPIだけでは不十分で,どうしても実際のDOMにアクセスしなければいけない場合がある
Ch09 form
- single_page_applicationでは,formを正しく扱うのは至難
- user inputにより扱うべき状態が一気に増えるため
- formの複雑な状態の管理のために,Reactを使える
- React_componentの主要な側面
- 動作が予測可能であること
- testの容易さ
- ↑ 同じ内容のpropsとstateで描画を行った場合,常に同じ描画結果を出力するというReact_componentの特徴のため
- Reactのformのcomponentには,管理された/されていないcomponentの2種類がある
- 複雑なformを扱う場合などは,DOMにアクセスが必要になる
- 管理されていないcomponent
- 複雑なformに向いている
- 直接DOM_nodeにアクセス
- ある意味アンチパターン
- formはほかのReact_componentと異なる動作
- 値は要素が管理し,formは管理しない
- DOM_nodeに直接アクセスが必要
- ref: React独自の特性
- validationや入力制御を行う必要がないformに向いている
- 管理されたcomponent
- 通常のReact_component patternを踏襲する
- valueをcomponentのstateとして保持することで,React_component自身がform stateを管理する
- formを完全にcontrolしたい場合
- dataflowが明確になる
- codeは増えるが,データが入力されるたびにstateが変化するため,dataflowを完全にcontrol〇
- data input中にほかのcomponentの値の参照も可能
- form event
- event: form stateのcontrolに欠かせない
- HTMLで発生するすべてのeventに対応
- target property経由で,発生元のDOM_nodeにアクセスできる
- targetを参照することで,管理されたcomponentにおいて,user inputにアクセスできる
- label
- radiobuttonやcheckboxの意味をuserに伝える
- htmlFor @JSXがHTMLのfor属性
- classをclassNameと扱うのと同じ理由(予約語)
- textareaとselect
- 統一性と使いやすさのために,original HTMLの仕様から変更されている
- select
- 複数選択が有効だと,child_componentのoption要素のselected propertyのみ変更される
- checkboxとradiobutton
- checked属性をcontrolする
- form要素のname属性
- 基本はあまり重要ではない
- 欠かせない場面
- formをseriarizeするthird_partyのpluginをReactとともに使うとき
- submit eventを横取りせずにbrowserに処理を任せるとき
- browserのauto complete機能はuserのmail addressなどを提示するためにname attributeを使う
- 管理されていないradiobuttonの場合,同じname属性を持つ要素同士は同時に1つしか選べないのがdefault動作
- 管理されたradiobuttonでは,event_handlerで処理を行い同様の動作を実現
- 複数のform要素とchange event_handler
- change event_handlerの再利用の方法・例
- bind経由でevent_handlerに追加の引数を渡す
- event_handler内でDOM_nodeのname attributeを参照する
- React.addons.LinkedStateMixinも異なる方法で解決する
- linkState method
- form input valueを親componentのstateとして保持する場合は,とてもsimpleになる
- dataflowを細かく制御したい場合は,かえって複雑になる
- change event_handlerの再利用の方法・例
- custom form component
- checkbox, radiobuttonなどの複雑なcomponentのinterfaceを改善するためにも使われる
- ほかのform componentとinterfaceを合わせる
- 可読性のため
- focus
- formへのfocus設定: userが次に取るべき行動を明確に伝える良い方法
- 使いやすさも〇
- autoFocus attribute
- focus()
- formへのfocus設定: userが次に取るべき行動を明確に伝える良い方法
- usability
- 要求を明確に伝える
- label: formの要素が何を期待しているのか伝えるRole
- radiobutton, checkbox
- placeholderよりも,labelやpopupが〇
- label: formの要素が何を期待しているのか伝えるRole
- inputに即座に反応する
- validation
- 最善のtiming: input要素のblur event発生時
- 処理中であることを示す
- transition, animation
- validation
- performance
- transition, network delayなどによる動作の遅延について
- 速度は相対的かつ体感的
- 速いように見せることがimportant
- predictable
- platformのdefault 動作に準拠するか,userの操作をまったく異なったものにする
- 一貫性
- platformの標準動作に準拠
- accessibility
- 試しに単一のinput deviceでapplicationを操作してみる
- Accessible Rich Internet Applications(ARIA)
- Accessibility Developer Tools
- input項目数の削減
- usability〇
- 実際の項目数よりも,userがどう感じるか
- input項目を複数の小さいformに分割
- autocomplete
- autoFocus
- 要求を明確に伝える
- まとめ
- Reactでは,form state managementはDOMではなくcomponentで行う
- form要素の動作を完全に制御
- application固有の複雑なcomponentを作成できる
- formはapplication内で最も複雑な操作を必要とする
- form design時にはusabilityに配慮が重要
- Reactでは,form state managementはDOMではなくcomponentで行う
Ch10 animation
- applicationを洗練されたものにするための方法
- animation: user_experienceを滑らかで自然なものにする効果がある
- CSSTransitionGroupというアドオンをCSS3とともに使用する → 簡単にanimationを追加
- 初期はimperative(命令的)だった
- DOM要素に直接accessして座標値などのstyleを絶え間なく更新
- → ReactではCSS animationを利用した,よりdeclarativeな手法
- CSSTransitionGroup
- CSSを使わずにJavaScriptのtimerを使ってanimationを行うこともできる
- CSSを用いたanimation
- CSSTransitionGroup
- transitionの適用対象となるcomponentのgroupを表し,componentが追加/削除されるたびに自動的にCSS_styleを切り替えてanimationを実現する
- transitionのclassごとにstyleを記述する
- componentのtransitionName attributeの値に基づいて,4つのCSS class名が作成される
- -enter, -enter-active, -leave, -leave-active
- componentのtransitionName attributeの値に基づいて,4つのCSS class名が作成される
- transitionのlifecycle
- -enter classがchild_componentが追加されたときに適用され,すぐに(次のanimation frameで) -enter-active classが適用される
- transitionの開始時と終了時のstyleおよびそれらの間をどのように遷移するか定義できる
- transitionEnter={false}とすると無効にできる(transitionLeaveも同じ)
- 上位のcomponentからprop経由で設定もok
- -enter classがchild_componentが追加されたときに適用され,すぐに(次のanimation frameで) -enter-active classが適用される
- よくある過ち
- leaveのanimationが完了するまでchild_componentは削除されない
- child_componentのkey attributeはtransition group内でunique要
- CSSTransitionGroup
- timerを用いたanimation
- 古いbrowserに対応したり,ScrollのanimationやCanvas描画などを扱いたい場合
- CSS3のanimationよりperformance ×
- componentのstateが定期的に更新される
- stateはanimationのtimelineの中での現在位置を保持する
- render method中でこのstateの値を参照することで,applicationは適切なanimationのframeを描画できる
- 頻繁な再描画を行うので,timerのAPIとして一般的に効率的とされているrequestAnimationFrameを使う
- 代替: 効率で劣るsetTimeoutを使うしかない
- requestAnimationFrameを使ったanimation
- position: absolute
- 要素のstyleのleftとtopの値を時間の経過とともに更新する
- componentWillUpdate handler内で呼び出す例
- position: absolute
- setTimeoutを使ったanimation
- これらのときはsetTimeout
- requestAnimationFrameは少ないoverheadで滑らかなanimationの効果が得られるが,古いbrowserでは非support
- 絶え間なく呼び出されるのが煩わしいときもある
- React Tween State
- Open Source Library
- 汎用的なanimationのAPIを提供
- これらのときはsetTimeout
- まとめ
- Reactを使った以下のanimationを見た
- CSSTransitionGroup addon
- requestAnimationFrame
- setTimeout
- Reactを使った以下のanimationを見た
Ch11 performance_tuning
- Reactの差分描画のalgorithmは優れているので,UI全体を入れ替えたとしても実際のDOMの描画は最小限に抑えられる
- 深くnestしたcomponentなど,delicate tuneが必要な場面では,virtual_DOMの不要な入れ替えを避けることでperformance改善〇
- React componentの簡単な設定により,applicationのperformanceを改善する方法を見る
- shouldComponentUpdate
- shouldComponentUpdateで,Reactにcomponentのlifecycle methodを呼び出す必要があるか教える
- falseならrender methodを呼び出さず,描画済みのvirtual_DOM objectをそのまま使う
- defaultはtrue
- 初回描画時は呼び出されない
- 新しいpropsとstateを受け取るので,それをもとに決定できる
- componentがpure(同一のpropsとstateに対して常に同じ内容のDOMを描画する)であれば,React.addons.PureRenderMixinを使える
- shouldComponentUpdateを上書きする
- Mixinを定義するだけでいい
- propsやstateが複雑なobjectである場合は,比較そのものが重くなりうる
- → immutable data_structureを使うか,helper_functionを使う
- shouldComponentUpdateで,Reactにcomponentのlifecycle methodを呼び出す必要があるか教える
- immutablility helper_function
- React.addons.updateというhelper_functionにより,簡単にimmutableなdata_structureを使用できる
- first argument: object/array, second argument(option): hash object
- bottleneckを調べる方法
- React.addons.Perfを使うとわかる
- Developer Toolsのconsoleから,React.addons.Perf.start(); (終わるときは~.stop();)
- → ~.printWasted();でprofile結果を表示
- Wasted time: renderが呼び出されたにもかかわらず,実際のDOM内容が変わらなかった処理にかかった時間をcomponentごとに集計したもの
- React.addons.Perfを使うとわかる
- key attribute
- componentのclassよりさらに細かくinstanceを識別できる
- 不要な処理を避けるために使う
- key attributeの値が変更された場合,差分計算を行わずに即座にchild_componentを含めたすべてのvirtual_DOM objectを破棄し,一から再描画する
- listの要素の順番が変わったことをReactに伝える
- → 移動だけで済むようになる
- こちらの目的で使われることが多い
- 制限事項
- 同一階層のcomponent, 同一の親を持つcomponent間でunique要
- 要素が現在のparent_componentのlistと別のlistに移動したときは,同一性の追跡不可能
- component内部からpropsの値として参照できない
- 同一階層のcomponent, 同一の親を持つcomponent間でunique要
- まとめ
- shouldComponentUpdateを使用してperformanceを改善
- React.addons.Perfを使用して不要なrender呼び出しを特定
- key attributeを使用してReactの処理を最小化
Ch12 server_side_rendering
- 以下の問題への解決策
- search_engineのindexの対象にならない
- JavaScriptのロードを完了してからページを作成するので,初回のページ表示が遅い
- virtual_DOMのため,server_side_renderingが可能
- virtual_DOM: 単なるmemory上のdata_structure
- server_sideでvirtual_DOMを実際のDOMに反映する代わりにHTML文字列として出力する
- → 同じReact_componentをclient_serverで共用できる
- React.renderToString/React.renderToStaticMarkupの2関数
- server_sideにおける描画関数
- renderToString
- ほとんどはこっち
- 第2引数のtarget DOMが不要で,戻り値としてHTML文字列を返す
- sync_callで,非常に速く動作
- data-reactid
- browserでDOM_nodeを特定するために使う
- data-react-checksum
- server_side_renderingの場合にのみ追加される
- server_sideで作成されたDOMが再利用できるかどうかを判断する
- DOMの作成処理とそれをdocumentに挿入する処理を省略
- → 特に複雑なサイトではページの初期表示までの応答時間が著しく改善
- 作成するReact_componentの内容がserver_clientの間でまったく同じであることが特に重要
- root要素のみ
- renderToStaticMarkup
- 独自のdata attributeなし
- server_sideで描画したReact_componentをbrowserで再描画しない場合のみ
- HTML mailの作成
- 作成したHTMLを後でPDFに変換する
- componentのテスト
- renderToString
- server_sideにおけるcomponentのlifecycle
- renderより後のlifecycle methodは呼び出されない
- 特に,componentDidMount, componentはserver_sideでは呼び出されない
- → event_listenerの定義において,componentの終了を通知するlifecycle methodは存在しない前提で設計する
- → event_listenerやtimerは常にcomponentDidMountで登録して,componentWillUnMountで解除する
- componentWillMountはserver_clientいずれでも呼び出される
- renderより後のlifecycle methodは呼び出されない
- client_server両方で使えるcomponentの設計
- 同一のpropsとstateが与えられた場合,常に同じ内容を出力するようにcomponentを設計する
- → テストしやすく,server_clientで同じoutputを保証できる
- randomな値は外部からpropsとして受け取るようにする
- applicationの初期値をどのようにしてclient側に渡すか
- 最も簡単: JavaScriptのobjectとして初期値を渡す
- 同一のpropsとstateが与えられた場合,常に同じ内容を出力するようにcomponentを設計する
- async_data
- まずdataを取得して,そのcallback_functionでcomponentを描画する
- e.g.
- async_dataを取得する処理をstatics methodとして定義する
- props.initialStateとしてclientに渡す
- lifecycle method経由でasync_dataの変更を監視し,変更があった場合statics methodを使ってdataを再取得
- async_dataを取得する処理をstatics methodとして定義する
- Isomorphic(同型の) routing
- react-router
- Isomorphic JavaScript(: client_server両方のcodeをJavaScriptで記述することでコードを共有すること)を可能にする
- server_clientで同じAPIを提供するrouterを使ってroutingすること
- 既存のrouterでserver_sideでReact_componentを描画する場合,そのrouterはDOMのAPIに依存していないことが重要
- SEOの観点から重要なデータを取得するときは,routerのhandlerで非同期に取得して,top levelのcomponentから末端のcomponentへ順番に渡す必要がある
- 重要でないdataは,componentのcomponentDidMount methodでAJAXでdataを取得すればよい
- 常にclientでデータを取得
- Reactと併用するrouterを選定するときは,routerのhandlerでasyncにデータを取得してrenderingできるか注意する
- react-router
- singleton_object
- async_dataがsingleton_objectの状態に依存している場合,描画時にasync_dataが予期せぬ値になってしまう可能性がある
- 描画のたびにsingleton_objectをresetではなく,applicationを隔離されたcontextで実行する
- ContextifyのようなNodeのpackageなど
- Web Workersによく似ている
- 与えられたcodeをV8の異なるinstanceで実行する
- performanceは犠牲になる
- 実行contextをcomponent間で共有することは,非推奨
- componentの移植性が低下するため
- tradeoffがある
- ContextifyのようなNodeのpackageなど
- 描画のたびにsingleton_objectをresetではなく,applicationを隔離されたcontextで実行する
- async_dataがsingleton_objectの状態に依存している場合,描画時にasync_dataが予期せぬ値になってしまう可能性がある
- まとめ
- server_side_renderingは,Web applicationのSEOとperformanceの観点から有効な手段になる
- React_componentはserver_client両方でのrenderingが可能
- application全体がserver_side動作するように設計されている必要がある
Ch13 React_family
- Jest
- test runner
- Jasmineがベース
- Nodeのrequire()関数を書き換えて,すべてのCommonJS style moduleをmockに置き換える
- → すべてのcodeをテストできる
- Immutable.js
- React, Fluxと相性〇
- applicationのperformanceとsimplicityが改善
- 通常のJavaScript objectまたは配列を受け取り,独自のデータ構造に変換したものを返す
- 戻すこともできる
- object, arrayの比較が早くなる
- ===を使える
- Flux
- design pattern
- 厳密に単一のdataflowを規定
- 何にも依存していないので,気に入った部分だけ取入れられる
- まとめ
- Jestにより,Unit test時に依存moduleをmockに置き換える方法
- Immutable.jsを通常のデータ構造の代わりに使用する方法
- FacebookのFlux patternの概要
Part 3 tool
Ch14 build, debug
- Reactはcomponent単位の開発を容易にするため,いくつかの抽象的なlayerを設ける
- debug, release作業は複雑になる
- build_tool
- Reactでのapplication developmentにおいて,最も繰り返し実行される処理はJSXのパース処理
- そのほかに大部分を占める処理: 複数のmoduleをbrowserで実行するために単一もしくは少数のfileにまとめる(bundle)処理
- Browserify
- JavaScriptをpackagingするためのtool
- Node.js styleのrequire()呼び出しをbrowserでも使えるようになる
- requireされたすべてのmoduleを単一のJavaScript fileに連結(bundle)するのみ
- 単一のfile → browserで簡単にloadできる
- installと設定
- React projectの作成
- Watchify
- 変更時に自動でbuild
- buildの実行
- Webpack
- Browserifyと同じく,JavaScriptをpackaging + たくさんの機能
- BrowserifyがGruntやGulpと併用して実現する機能を単体で実現できる
- WebpackとReact
- 自身が依存するassetを内包するcomponentを作成できる
- assetがcomponentに紐づけられる → componentの移植性が高まる
- あるcomponentが使われなくなったときにその依存assetも削除
- どこからも参照されていないCSSや画像がなくなる
- Browserifyと同じく,JavaScriptをpackaging + たくさんの機能
- Reactでのapplication developmentにおいて,最も繰り返し実行される処理はJSXのパース処理
- debug_tool
- React Developer Tools
- Chrome拡張機能
- displayName
- JSXがJavaScriptに変換されるときに,componentの定義に自動で追加される
- そのほか多くの情報を見ることができる
- JSBinとJSFiddle
- online demo site
- React Developer Tools
- まとめ
- React developmentにおいて,build, debug toolがいかに有用であるか
Ch15 test
- TDDのworkflowでコードをmodule化し,変化に強くし,より安全にコードベースを変更できるようにする
- はじめに
- testにより,よりよいコードを書けるようになる
- 単一責任の原則や,デメテルの法則にしたがうことになる
- testの種類
- unit_test
- E2E_test
- test_tool
- testにより,よりよいコードを書けるようになる
- 初めてのtest: render method
- testでは,React.renderの代わりにReact.addons.TestUtils.renderIntoDocumentを使う
- ReactにおけるHTMLの検査
- Reactでは,componentのrender methodで指定したHTMLは,実際のDOMとは異なる
- componentのmock
- 対象のcomponentの機能だけをテストする
- 前処理,後処理
- beforeEach, afterEach
- 要約
- mock componentを定義する
- componentのローカル変数の値を保存する
- ローカル変数の値を書き換える
- testを実行する
- ローカル変数の値を元の値に戻す
- Jasmineのhelper moduleでspec間の共通の処理を記述できる
- (mockの内容はp.147の下段)
- npmを使わないvanilla projectのcase
- functionのstub化
- stub化の目的
- unit_testの対象範囲の限定
- 関数内で使われているAPIやthird_partyのserviceなどの処理がテスト中に実行されるのを避ける
- その関数が正しい呼び出し元から正しい引数で呼び出されていることをチェックしたい
- jasmine-react-helpers
- spyOnClass
- stub化のmethod例
- ランダム
- serverからdataを取得
- testで再現困難なstateを参照する
- 副作用の範囲が大きい
- 現在時刻やtimezoneを扱う
- callback_functionのテスト
- test→実装の流れ
- stub化の目的
- event simulation
- test→実装の流れ
- testにおけるcomponentのselector API
- Mixinのテスト
- Mixinを直接テストする
- Mixinの内部で呼ぶReactのmethodをすべてスタブ化必要
- とても細かいテストになる
- 機能が複雑な場合は利点もあるが,機能ではなく実装そのもののテストになってしまう状況になる
- Object.createでテストごとにMixinを新たにcopyする方法
- Reactの機能はスタブ化する
- Reactのlifecycle methodの呼び出し順を忠実に再現が必要になる
- dummy_component経由でMixinをテストする
- 非常にsimpleなcomponentであり,テストの意図がより明確になる
- 唯一の難点: Reactの制限によりrender methodを必ず実装する必要がある
- componentが画面から削除されたときにclearIntervalが呼び出されることを保証したい
- → componentWillUnMountを直接呼び出すのではなく,componentを画面から削除してReactに適切なcallbackを実行させることが重要
- まずは直接の方式でテストを書いてみて,困難な場合はdummy_component経由に書き直すのが〇
- 共有スペックを記述する
- testの記述先がMixinのspec_fileではなくMixinを使用するcomponentのspec_fileになる
- 複数のcomponentから使われるので,共通部分は共有スペックに記述する
- Mixin内の呼び出しをテストするためであり,Mixinを使うcomponentからの呼び出しのテストではないので,idを分ける
- ほかからの影響を受けやすく,より複雑になる
- 適している場面
- Mixinを使うときにcomponentが特別なmethodを実装する必要があるとき
- componentがそれらのmethodを正しく実装しているか,共有スペックでテストできる
- Mixinとcomponentの間のinterfaceをテストできる
- Mixinの提供する機能がcomponent側で上書きされることで破壊される可能性がある場合,共有スペックによりそれを検出できる
- Mixinを使うときにcomponentが特別なmethodを実装する必要があるとき
- Mixinを直接テストする
- \<body>に対する描画
- renderIntoDocumentを使う意図: pageと切り離されたDOM_nodeに対して描画を行うため
- 可能な限りこちらを使う
- 実際にcomponentがpageに描画される必要があるときは,renderを使う
- 親のDOM_nodeに対s手行った変更を注意深く元に戻す必要がある
- jasmin-react-helpersを使うと,テスト終了時に自動でcomponentを削除してくれる
- renderIntoDocumentを使う意図: pageと切り離されたDOM_nodeに対して描画を行うため
- server_sideのテスト
- Mochaを使う
- Nodeのecosystem内でとても有名で,非同期処理をうまく扱える
- spec_fileのtemplate
- npm run test-server
- doneでassertionの完了を知らせる必要
- chain上で呼び出す
- SuperTest
- CheerioでHTMLとしてパースしてassertする
- 404のテスト
- Mochaを使う
- browserを使ったテストの自動化
- E2E_testについて
- end_userの観点からapplicationの機能の正しさを検証するテスト
- 基礎
- browserを操作してWeb pageの内容が正しいか検査する
- CasperJS
- browserを簡単に操作するためのtool
- 内部的にPhantomJSを使っている
- PhantomJS
- JavaScriptから操作可能なheadless browser
- rendering engineとしてWebkitを使っている
- headless browser
- 画面に何も表示しない
- terminalからcommand経由で操作できる
- testで行うbrowser操作
- linkのclick, formの記入, URLの入力, drag and dropなど,userが通常行うbrowser操作
- Webkit
- Safariで使用されるrender engine
- ChromeはWebkitをforkしたBlinkというrender engineを使っている
- FirefoxはGeeko
- Internet ExplorerはTrident
- CasperJSでのテストがどのようなものか
- end_userの視点でbrowserを操作 → Reactの文字は出てこない(Reactを使っているかどうか関知しない)
- testが始まる前にnpm startでapplicationを起動する必要がある
- リンクのクリック
- thenのコールバック関数の中でテストを実行する
- serverの起動
- 自動的にserverを起動するためのscript
- spec_fileのポート番号を変更する
- E2E_testについて
- まとめ
- テストに関連するさまざまな概念について
- 描画のテスト
- 関数のスタブ
- componentのmock
- Mixinのテスト
- componentの検索
- server_sideでのテスト
- E2E_test
- テストに関連するさまざまな概念について
Part 4 実践
Ch16 architecture pattern
- Reactをほかのframeworkやarchitecture patternと併用してapplicationを構築する方法を見る
- routing library
- single_page_applicationにおいて,routerはURLをハンドラにマッピングするためのモジュール
- Backbone.Router
- Backbone: single_page_applicationを開発するためのlibrary
- MVW(Model-View-Whatever)の形態
- Backbone: single_page_applicationを開発するためのlibrary
- Aviator
- router機能のみを持つstand alone library
- 複数のtargetを指定できる
- react-router
- routerの定義自体がReact_componentで構成される
- path属性に基づいてrouting, 該当するRouteのhandler属性に指定されたcomponentを描画
- Link component
- page navigationに使える
- Om(ClojureScript)
- 永続データ構造を提供
- → Omはapplication全体を高速にrendering
- snapshotを容易に取得
- → undoのような機能を簡単に実装できる
- 永続データ構造を提供
- Flux
- Facebookにより考案されたarchitecture pattern
- 単一方向のdataflowを強制
- → Reactとともに使うことでapplicationの動作を推測しやすくなる
- 大きな変更が不要.容易に導入
- Store/Dispatcher/View(React_component_tree)で構成
- Actionを4つ目のパーツとみなせる
- Action: 補助的なmethodを提供しDispatcherのinterfaceとして機能する
- Actionを4つ目のパーツとみなせる
- 最上位のReact_componentはController-ViewとしてのRoleを担う
- Storeとchild_componentとの仲介役として機能する
- (iOSのViewControllerとは全く別物)
- Storeとchild_componentとの仲介役として機能する
- 各パーツは独立 → 関心の分離を強いられる → 個別テスト容易
- dataflow
- 情報が一方向に流れる
- merit
- applicationの動作が推測しやすい
- application stateを1か所に集めて管理できるようになる
- application stateはStoreに集約され,すべてのdataの取得/更新はStoreで管理
- Fluxを構成するパーツ
- Dispatcher
- applicationの中心的なRole
- すべてのデータがいったんDispatcherを通る
- singleton_object
- callback経由でStoreにイベントを通知
- 複数のcallback_functionの依存関係の管理はDispatcherの責務
- userやnetworkからの入力を登録しているすべてのStoreに通知し,各Storeがそれをチェックして自身に関係のあるinputのみを処理する
- Action
- user視点での入口
- userがUIに対して行った操作はAction経由でDispatcherに届けられる
- DSLとして機能する
- 1段階高いレベルの言語へと翻訳され,Storeが意味を理解できるActionに変換される
- userの操作はcomponent_treeをさかのぼってDispatcherに届けられる
- その過程で,userの操作はapplication固有のActionに変換される
- Store
- applicationのデータのやりとりを一手に引き受け,developerはここにbusiness_logicを記述する
- Dispatcherに登録したcallback_function経由でActionの通知を受け,自身の管理するデータに関係のあるActionの場合のみ応答する
- dataが更新された場合,change eventを発行してReact_component_treeに更新を通知する
- applicationのほかの部分からは厳密に分離
- Storeはapplicationのすべてのデータを保存
- applicationのほかの部分はデータの操作方法を知らない.Storeはapplicationで唯一データの変更が行われる場所になる
- Storeはgetter methodのみサポートし,setter methodを持たない
- dataの変更はすべてDispatcherからのcallback経由で行われる
- Controller-View
- Viewのtreeの最上位のcomponentがStoreとのやりとりを受け持つ
- componentはController-Viewと呼ばれる
- 規模が大きくなると複数のController-Viewとなることもある
- Viewのtreeの最上位のcomponentがStoreとのやりとりを受け持つ
- Dispatcher
- 複数のStoreを管理する
- 変更内容
- DispatcherはActionをqueueに格納するように変更
- DispatcherはActionの処理が完了するまで処理を停止できるように変更
- Dispatcherにcallbackを登録する際に,どのActionに対して待ち受けるか指定できるようにする
- Dispatcherの改善
- Dispatcherの返すidに対してWaitFor
- 変更内容
- まとめ
- Reactをほかのframework/architecture patternと併用してapplicationを構築する方法
- MVC framework ~ Flux patternまで,Reactの高い順応性
- Reactをほかのframework/architecture patternと併用してapplicationを構築する方法
Ch17 そのほかのusecase
- React: interactiveなUIを構築するための非常に強力なrendering library
- Web application以外の分野にも適用可能
- Reactが提供するデータおよびuser inputを処理する方式や,再利用可能でテスト容易な小さいcomponentを複数組み合わせてapplicationを構築するやり方
- desktop application
- atom-chellやNW.jsなどによる
- desktop上のinteractiveなapplicationを構築するためにReactを使える
- game
- gameは本質的にstate machineで,以下の基本的なRoleを持つ
- 画面の更新
- eventへの反応
- Reactは以下の2点に対してのみ責任を果たす
- DOMの更新
- eventへの反応
- Reactのvirtual_DOMの方式は,高性能のgame engineから着想を得たもの
- 2048の例
- immutable method
- dataの共有
- 不要な状態更新を避ける
- 柔軟な構造 → undoを簡単に追加できる
- ReactによりViewの動機を気にすることなくgame_logicとplayerとのやり取りに集中できる
- gameは本質的にstate machineで,以下の基本的なRoleを持つ
- HTML_mail
- React.renderToStaticMarkupを使う
- 与えられたcomponent_treeをHTML文字列に変換
- 独自のデータ属性を出力しない ←→ renderToString
- 実装例
- CSSファイルの追加
- 再利用・テスト可能なcomponentを組み合わせてinteractiveなUIを構築できるという利点をHTML_mailでも得られる
- React.renderToStaticMarkupを使う
- data_visualization
- まとめ
- 以下を見た
- Reactはbrowserで動作するWeb applicationだけでなく,desktop applicationやHTML_mailの作成にも使える
- game developmentでReactを利用する方法
- D3のようなlibraryと併用してdata_visualizationの用途で使用する方法
- 以下を見た
Appendix A 開発環境構築について
- Reactは開発版と製品版がある
- & アドオンありなし
- Nodeの使用
- Nodeのpackage management toolであるnpmを中心に,frontend developmentのための様々なtoolのecosystemが形成されているため
- Nodeを使わない開発環境構築手順,react-tools
- JSXTransformer/react-tools
Appendix B API reference
- 3種類
- 用語の整理
- component仕様
- React.createClass()に引数として渡すobject
- render methodなどのlifecycle methodを定義する
- component class
- React.createClass()の戻り値として得られるobjectか,またはES6 class.
- JSXにタグ名として直接記述するか,React.createElement()の引数として渡す
- ReactElement
- React.createElement()の戻り値として得られるobject
- 内部的にはすべてのcomponent classはReactElementに変換される
- React.render()の第一引数やrender methodの戻り値において使用される
- component instance
- ReactElementをもとにReactが生成するobject
- component仕様で定義したmethod内で,this経由で参照できる
- 外部からcomponent instanceにaccessするために,React.render()の戻り値もしくはref属性経由で参照を取得する
- component仕様
- top level API
- React
- libraryとしてのentry point
- React.createClass
- React.createElement
- React.createFactory
- React.render
- React.unmountComponentAtNode
- React.renderToString
- React.renderToStaticMarkup
- React.isValidElement
- React.findDOMNode
- React.cloneElement
- React.DOM
- React.PropTypes
- React.initializeTouchEvents
- React.Children
- React.Children.map
- React.Children.forEach
- React.Children.count
- React.Children.only
- React
- component API
- setState
- replaceState
- forceUpdate
- getDOMNode
- isMounted
- setProps
- replaceProps
- component 仕様
- object
- propTypes
- mixins
- statics
- displayName
- lifecycle method
- render
- getInitialState
- getDefaultProps
- componentWillMount
- componentDidMount
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- componentDidUpdate
- componentWillUnMount
- object
『エッセンシャル スクラム: アジャイル開発に関わるすべての人のための完全攻略ガイド』学習メモ
まえがき
- Essential Scrum
- 基礎に,coreとなる価値,原則,practiceの小さなまとまりがある( → 集まってframeworkになる )
- どのようなapproachを組み合わせるべきかわかるまでは,Scrum frameworkを忠実に守った方が良い
Ch01 Introduction
- What's Scrum
- Scrum: 革新的なProduct, Serviceを開発するためのapproach
- Agile approach
- product backlog
- iteration
- 機能横断型チーム
- Scrumの起源
- all-at-once product development(団結型product開発): scalable チーム based approach
- Object Oriented developmentの概念・経験にもとづくprocess control
- iterative and incremental development
- softwareのprocessと生産性に関する研究
- 複雑で適応力のあるsystem
- Scrumの革新的な価値と原則は,softwareとは異なる種類のproduct開発や,さまざまな仕事のflowを生み出すためにも使える
- Why Scrum
- 事前の設計を創発的な設計とjust_in_timeで組み合わせられるapproach
- より機能横断的
- ゲノミカ社の顛末
- Scrumは役に立つか
- 頻繁なrelease
- 組織的な機能不全や無駄を晒す
- iterationのたびに動作・統合・テスト・business的に価値のあるfeatureのdeliveryに注力
- Cynefin framework
- 複雑な領域
- 創発的
- 検査と適応
- Scrum〇
- 探索(調査)・理解(検査)・反応(適応)
- 込み入った領域
- 単純な領域
- 正統的なbest practiceの領域.既知のsolution.
- 適切に定義され,反復可能な手順が組み合わせられたprocessを用いたほうが,Scrumより上手くいく
- chaosな領域
- 状況と行動に対して誰かが責任を負う
- Scrumは×
- 無秩序
- 状況を構成要素に分解して,それぞれをそのほかの4つの領域に当てはめる必要がある
- 割り込み駆動の作業
- Scrumは×
- カンバンが〇
- 推奨
- 作業がsystemをどのように流れているか可視化
- 各手順で仕掛け中の作業(WIP)を制限.こなせる以上の作業はしない.
- system内の作業の流れを計測,最適化して,継続的に改善
- softwareの保守とsupportに〇
- systemごとにScrumとカンバンの使い分けもよい
- 推奨
- 複雑な領域
- まとめ
- Scrumは複雑なproduct開発という営みの変化を受け入れられる
- 組織のpotentialを妨げている機能不全や無駄を可視化
- Scrumは複雑なproduct開発という営みの変化を受け入れられる
Part 1 Core Concept
Ch02 Scrum framework
- Scrum frameworkの概要
- practiceに焦点を合わせ,役割,activity,作成物について見る
- 概要
- Scrum: 作業をまとめあげ,管理するためのframework
- value,principle,practiceに基づき,組織に合ったengineering practiceや,Scrumのpracticeを実践するための具体的なapproachの追加ができる
- → originalのScrumができあがる
- 建物の土台や壁のようなもの.備品や機能の付加だけが可能.
- 人間中心主義
- 正直,開放性,勇気,尊敬,集中,信頼,権限付与,協力といった価値に基づく
- practice: role, activity, 作成物, それらに関連するruleで構成
- Scrum: 作業をまとめあげ,管理するためのframework
- Scrumの役割
- 1つ以上のScrum_teamから構成
- product_owner
- productのleadershipの権限
- どのfeatureや機能をどの順番で構築するか判断する責任
- チームの目標に明確なvisionを持ち,関係者全員に伝える
- 開発や保守を含めたsolution全体を成功させる責務
- 最も価値の高い作業が行われるようにする義務
- Scrum_masterや開発チームと協力.質問にすぐ答えられるようその場にいる必要.
- Scrum_master
- Scrumのvalue, principle, practiceを関係者全員が理解し,受け入れられるよう手助けする
- as a coach, processについてleadershipを持ち,チームがoriginal Scrum approachを育てられるようにする
- 組織変革のmanagementを支援
- as a facilitator
- impediment(ゴルフでのコース上の小石など)を取り除くときにleadershipを発揮
- not a manager, but a leader
- development_team
- productをdesign, develop, testする責任
- product_ownerが設定した目標を達成するための最善の方法を決定
- 5人~9人
- Scrumのactivityと作成物
- flow
- vision → groomingでfeatureに分解 → product backlog
- sprint planningの結果: forecast/ commitment
- sprint backlog
- sprintの実施 with daily_Scrum
- daily_Scrum: 作業の流れの管理のため,検査と同期を行う適応型planning activity
- → product increment
- sprint review: productをstakeholderとScrum_teamが検査
- sprint_retrospective: processをScrum_teamが検査
- product backlog
- product_ownerが,stakeholderと協力して収集,定義し,正しい順序にする
- 順序: value, cost, knowledge, riskから
- grooming
- prioritized/orderedはどちらでもよい
- 各itemの大きさ・コストを認識
- 相対基準
- product_ownerが,stakeholderと協力して収集,定義し,正しい順序にする
- sprint
- timeboxing
- product planning
- product_ownerと開発チームがsprint goalを合意
- 持続可能なpace
- sprint backlog: 第2のbacklog.product backlog itemごとに細かいtaskに分解したもの.
- just_in_timeのplanning
- 期間: 2週間~1か月.sprint planningは4時間~8時間
- simple cycle: product backlog itemを1つ選び,itemをtaskに分解し,選んだitemがsprintに収まるかjudge
- taskは1時間単位で見積もる
- sprintの実施
- 完成: 高品質な機能を達成するのに必要な作業をすべて終えたという強い自信があること
- チーム memberがtask levelの作業を定義.自己組織化して実施.
- daily_Scrum
- sprint期間中の毎日・同じ時間に,15分以内のtimeboxで実施
- a.c.a. daily standup
- 検査と適応のactivity
- Scrum_masterがfacilitatorとして,各memberがほかのmemberに3つの質問
- 前回のdaily_Scrumのあと,自分が何をしたか
- 次回のdaily_Scrumまでの間,どんな作業をするか
- 進捗を妨げる障壁・impedimentは何か
- → 全員が今の状況の全体像を理解
- sprintで作業をすばやく柔軟に実施するうえで欠かせない
- sprint backlog itemの状況を開発チーム member間で共有するためのもの
- 同期および検査と適応の毎日のplanning activity
- 完成
- sprint の成果: 出荷判断可能なproduct increment
- 完成の定義: 品質・出荷判断可能であることへの,自信の度合い
- 出荷判断可能: sprintで構築したものに対する自信の度合い
- 終わらせるべき重要な作業で,完了していないものがないということ
- sprint review
- 構築中のproductの検査と適応
- 参加者同士が会話
- 開発activity全体へのreview
- 今起きていることを可視化,次の開発をガイド,ビジネス上最も適切なsolutionが確実に作り出されるようにするための機会を得る
- チーム内外で情報が双方向に流れるようになる
- sprint_retrospective
- processの検査と適応
- Scrumと関連する技術的なpracticeについて議論
- 継続的なprocess改善
- 現実的な数のprocess改善actionを特定し,実施をcommit
- 次のsprintで取り組む
- 現実的な数のprocess改善actionを特定し,実施をcommit
- processの検査と適応
- flow
- まとめ
- Scrum frameworkの役割,activity,作成物のすべてに焦点を当てて,Scrumのcoreとなるpracticeを見た
Ch03 Agile principle
- Agile principleをtraditional 計画駆動のproduct developmentのprincipleと比較
- Scrumとの違いの理解の下準備
- 概要
- a.c.a. 順次的なprocess
- 計画駆動の開発
- 基礎となる信念が,product開発に伴うUncertaintyと見合わない
- 変動性とUncertainty
- 役立つ変動性を受け入れよ
- product developmentは製造業とは全く異なる
- 製造業: 要件を固定し,よく理解された工程に従うことで,(定義された振れ幅の中で)常に同じ完成品を作り出す
- product development: ほかにないproductをただひとつだけ作り出す
- 1つだけのproduct: 料理のrecipeに似ている
- product developmentは製造業とは全く異なる
- iterativeでincrementalなdevelopmentを採用せよ
- iterative: 計画された手戻り戦略
- 構築しているものを改善するために,いくつもの道を辿る
- 優れたsolutionに辿り着く
- 最大の欠点: Uncertaintyがあるため,どれだけの改善があるか事前に判断・計画することが難しい
- 構築しているものを改善するために,いくつもの道を辿る
- incremental: 全部作る前に少し作ってみる
- productを小さい部品に分割し,その一部を構築して,実際の環境でどのように動くか学習し,その学習に基づいて適応し,続きを構築する
- developmentを調整し,やってきたことを変更するうえでの重要な情報を獲得する
- 最大の欠点: 部品ごとに構築すると,全体像を失ってしまうriskがある
- 併用することで,個別に使う場合の欠点を埋められる
- Scrumではsprintと呼ばれるtimeboxingされたiterationで適応を繰り返すことで,iterative and incrementalという考え方を実現する
- Water Scrumは×
- featureに対して作業をし,統合・テストを経ることで,全体的な視点でproductを見られる
- sprintの結果についてfeedbackを受け取ることで,適応ができるようになる
- iterative developmentと継続的な改善に対するcommitmentの一部として,将来のsprintでやり直しを計画できる
- → どの程度の改善が必要か事前に正確に知ることができないという課題を克服
- 適切で経済的にも意味のある回数のiterationを行いつつ,productをincremental development
- iterative: 計画された手戻り戦略
- 検査,適応,透明性(経験的なprocess control)を通じて変動性を活用せよ
- 計画駆動とScrumの違い
- processが定義される度合い
- 成果のばらつき
- 使われるfeedbackのtiming, 量
- Scrumの核心が,検査,適応,透明性
- 構築するものだけでなく,構築する方法も検査と適応を行う
- このために透明性が必要
- 透明性: productを作り出すための重要な情報はすべて,productの構築にかかわる人が入手できること
- communicationの基礎: 透明性により,観察・理解が可能になる
- → 信頼関係
- このために透明性が必要
- 構築するものだけでなく,構築する方法も検査と適応を行う
- 計画駆動とScrumの違い
- あらゆる形のUncertaintyを同時に削減せよ
- 目的(what)のUncertainty: 最終的なproductのfeatureを取り巻くUncertainty
- 手段(how)のUncertainty: product developmentに用いられるprocessやtechnologyを取り巻くUncertainty
- 顧客(who)のUncertainty
- iterative and incremental developmentにより容易に同時の削減ができる
- 検査と適応,透明性を定常的に行うことで実現
- 未知の未知を学習できる
- 役立つ変動性を受け入れよ
- 予見と適応
- 予見への願望と適応の必要性との間のバランスをとる
- 選択肢を広げておく
- 最終責任時点(LRM)
- 拙速な判断は×
- 判断しないcostが判断するcostを上回るときに決定する
- 判断に関する理解が深まれば,判断のcostが下がっていく
- 最終責任時点(LRM)
- 事前に正しく行うことは不可能だと認める
- 重要な知識がない状態では,精度の低い要件を大量に作ってしまう
- 目的のUncertaintyが見えなくなる
- 無駄になる
- Scrumでは,ある程度は事前に要件を集め,計画を立てるが,必要な分だけ
- 詳細は,構築中のproductの学習に合わせて埋めていく
- 重要な知識がない状態では,精度の低い要件を大量に作ってしまう
- 適応型で探索型のapproachを好む
- 適応: 何らかのactivityで知識を得ること
- prototypeの構築,概念実証(POC),勉強,実験
- 調査によって情報を買う
- tool, technologyが,調査のcostを大きく下げる
- 適応: 何らかのactivityで知識を得ること
- 経済的に妥当なやり方で変化を受け入れる
- 予見のし過ぎは逆効果
- 自己成就的な予言pattern
- Scrumでは変更cost曲線をできるだけ平たんにする
- processにおける作業の量と流れを管理し,時間の影響を変更costに与えないようにする
- 多くの作業の成果物(詳細な要件,設計,testcaseなど)をjust_in_timeで作り出す
- processにおける作業の量と流れを管理し,時間の影響を変更costに与えないようにする
- 予見のし過ぎは逆効果
- 予見的な事前の作業と適応型のjust_in_timeの作業とのbalanceを取る
- 経済的に妥当なやり方で,素早いfeedbackに基づく適応の量を最大化し,事前の予見を最小化する
- かつ,complianceや法規制,企業の目的から外れない
- 革新的なproductを素早く開発するためには,適応すべきことに対して,chaosにならない程度の予見が必要
- chaos → 作業が非効率
- 経済的に妥当なやり方で,素早いfeedbackに基づく適応の量を最大化し,事前の予見を最小化する
- 検証による学び
- 想定を確認したり反証したりする知識を得たとき
- 重要な想定をまず検証する
- 想定: 推測や信念.検証による学びがまだのもの
- 開発に重大なrisk
- Scrumでは最小化かつ残る期間を短くする
- iterative and incremental developmentをlow cost researchと組み合わせる
- 想定: 推測や信念.検証による学びがまだのもの
- 複数の学習loopを並行して活用
- Scrumにおける継続的な学習
- feedback loop
- 予め定義された複数の学習loop
- daily_Scrum, sprint review
- pair programming(秒単位のfeedback), test driven development(分単位のfeedback)
- Scrumにおける継続的な学習
- 素早いfeedbackのためのworkflowをまとめる
- Scrumでは作業の直後にfeedback
- 経済的恩恵が大きい
- 学習loopをすばやく閉じる
- riskを小さくできる
- Scrumでは作業の直後にfeedback
- 仕掛け中の作業(WIP)
- 作業は経済的に妥当なサイズにまとめよ
- 計画駆動: all-before-any型approach
- batch サイズ: 100%
- 規模の経済をproduct developmentに当てはめたもの
- Scrum: batch サイズを小さくする
- 規模の経済の当てはめは重大な経済的損失を呼ぶ
- 恩恵
- cycle time削減
- flowの変動性の低減
- feedbackの推進
- riskの低減
- overheadの低減
- 士気と危機意識の向上
- cost, scheduleの肥大の抑止
- 1個流しにこだわることはない
- 作業の流れ,全体の経済性も重要
- 計画駆動: all-before-any型approach
- 在庫を認識し,適切な流れで管理
- 在庫: WIP
- 大量の在庫があるときの変更は,重大な無駄につながる
- → just_in_timeで在庫管理を健全に行う
- 要件が多すぎると,要件の変更時に在庫の無駄が生じる
- 要件が十分にないと,作業をすばやく流せない
- → ちょうどよい在庫と多すぎる在庫との間で適切なbalanceを見出すことが目的となる
- 在庫は要件だけではない.ほかのものも管理要
- 作業者の手待ちではなく,作業の手待ちに注目
- 作業の手待ち: 実施したいのに何らかの原因でできない作業
- 作業者の手待ち: capacityに余裕があり,もっと作業ができる人
- 走者ではなくバトンを見よ
- queue理論のgraph
- 作業の手待ち(遅延した作業)は,いったん高稼働率になると,指数関数的に積みあがる
- → 作業の流れの中でbottleneckを見つけ削減する,という経済的に意味のあるactivityに注力する
- delay_costに考慮
- delay_cost: 作業の遅延やmilestoneの達成の遅延に関連した,経済的cost
- どの種類の無駄が経済的に損失を与えるか算出できる
- 例
- delay_cost: 作業の遅延やmilestoneの達成の遅延に関連した,経済的cost
- 作業は経済的に妥当なサイズにまとめよ
- 進捗
- 自分たちがdeliveryし,検証したものによって測る
- realtimeの情報に適応してreplan
- plan: 物事がどう進むか事前に予見しただけのもの
- 経済的に重要な情報の流れに適応
- 開発期間中に継続的に行う
- 動作する資産を検証することで進捗を測る
- 動作する資産を検証 → 重要な想定の検証 → 次のstepへのfeedback
- 顧客にとって価値のある作業をどれだけ終わらせたかがimportant
- valueを主眼に置いたdeliveryに集中
- 中間成果物は顧客が認識できる価値をもたらさない.目的のための手段に過ぎない.
- それ自体が重要なfeedbackを生み出したり,重要な知識を得るために役立つことに意味がある
- 作業効率
- 素早く進む,しかし,あわてない
- 機敏 & 状況に適応 & speed
- 機敏 & 持続可能なpace & 品質
- 品質を作りこむ
- 機能横断型のScrum_teamに責任
- 継続的に作りこんで,sprintごとに確認
- valueのincrement: 強い自信をもって完成され,productに組み込んだり出荷しようと思えばできるようになっている
- 必要最低限の儀式
- 不要な形式主義の儀式 ←→ Scrumは価値中心的
- processのためのprocess
- documentを書くcase
- productの一部
- 重要な議論や意思決定,合意を記録して,何があったのか将来分かるようにするという目的
- 新しいmemberが追い付くうえで役に立つ,価値の高い方法
- 規約上の要件
- 不要な形式主義の儀式 ←→ Scrumは価値中心的
- 素早く進む,しかし,あわてない
- まとめ
- 核心的なAgile principle
- Scrumの方法を導く基本的な信念
- 計画駆動との違い
- 核心的なAgile principle
Ch04 sprint
- sprint: 1週間~最大1か月までのcycleの繰り返し
- timeboxing
- 短く固定された期間に,一度設定した目標をなるべく変えず,チームで合意した完成の定義を達成した出荷判断可能なproduct incrementを生み出す
- 概要
- sprint: Scrum frameworkの枠組み
- goal, memberは変えない
- 特性は,あらゆるチームのあらゆるsprintに当てはまる(一部例外がある)
- sprint: Scrum frameworkの枠組み
- timeboxing
- 時間管理のtechnique.
- 仕事の能率を高め,scope managementを支援
- sprint goalに向けて選択した作業を完了するために,持続可能なpaceで働く
- merit
- WIPの上限設定
- 優先順位づけを強制
- 重要な少量の仕事が優先される
- 集中力を研ぎ澄ます??
- 進捗状況の可視化
- sprintの最終日という締め切りまでに重要な作業が完了し,検証されているかどうかという観点で進捗を可視化できる
- 不必要な完璧主義を避ける
- 期限がある
- 締めくくりの促進
- 切迫感
- 予測可能性を改善
- 予測の範囲がはっきりする
- 短期間
- 計画の立てやすさ
- すばやいfeedback
- 投資収益率の改善
- 損失の限定化
- 失敗しても,短い期間を失うだけで済む
- 熱狂を取り戻す
- 待ち時間が少なくなる
- 目に見える進捗,終わりがある
- 頻繁なcheckpoint
- 動作するfeatureを実際に見て,誰もが意思決定できる
- immutable sprint term
- 例外
- feedback speed up
- 休暇,会計年度末
- release span
- 一定のrhythmのmerit
- 予測可能,計画が立てやすい
- 安定した健康的な鼓動
- 高速で柔軟なbusiness valueのflowを実現するため
- zoneに入りやすくなる,roleを果たせるようになる,波に乗りやすくなる
- 平凡だが必要不可欠なactivityが習慣化される
- 短いrhythmで,仕事への集中力を一定に保てる
- 調整のためのoverheadが大きく減少
- 簡潔なplanning
- velocityへの信頼度up
- sprint単位で平準化
- releaseまでのsprintの回数がわかる
- velocityへの信頼度up
- 例外
- immutable goal
- sprint goal: sprintを要約したもの.取り組むbusiness上の目的とvalue.
- 明確で1つの事柄に焦点を当てる
- 複数のgoalとなることもある
- development_teamが洗練・合意し,sprintで完成できるproduct backlog itemを特定する
- sprint goalをさらに精緻化
- 相互commitment
- 変更と明確化
- 変更は×,明確化は〇
- 変更の影響
- あらゆる点でloss大きい
- 実利的であるべし
- 経営状況や障害など実利的に問題があれば,ruleより実利を優先する
- 変更の必要性を,経済的な観点でproduct_ownerがチームと議論できれば,やる気と信頼は高まる
- sprintの中止
- 経済的な事情
- 奥の手
- sprint goal: sprintを要約したもの.取り組むbusiness上の目的とvalue.
- 完成の定義
- 出荷判断可能な
- ≠ 出荷しなければならない
- sprintで構築したものが完成しているという自信
- 出荷するために必要な仕事(重要度の高いテストや統合など)が確実に完了している
- 概念的には仕事のcheck listのようなもの
- 変動要因
- 成果物の性質
- 成果物に使われている技術要素
- 成果物を構築した組織
- 現在の可能性に影響しうるimpediment
- 変動要因
- sprint期間より長くなりうるテスト
- 自動化に取り組む
- 完成の定義は時間とともに改善
- 完成の定義と受入条件
- 受入条件: product_ownerが規定した満足条件
- 受け入れテストで確認
- product backlog itemは,個別の受入条件とsprint levelの完成の定義の両方を達成して,完成したとみなされる
- 受入条件: product_ownerが規定した満足条件
- 完成と完全に完成
- 出荷判断可能な
- まとめ
- Scrum frameworkにおけるsprintの果たす重要な役割
- sprint: ほかのactivityや作成物を配置するEssential Scrumの枠組み
- 短い,timeboxing,期間は固定
- sprint goalで定義
- 経済的な妥当な理由以外は変更不可
- 出荷判断可能なproduct incrementを生み出す
- 全員で合意した完成の定義を満たす
- sprint: ほかのactivityや作成物を配置するEssential Scrumの枠組み
- Scrum frameworkにおけるsprintの果たす重要な役割
Ch05 要件とuser_story
- 要件の扱いが伝統的なprojectとどう違うか
- user_story: business valueを表現する共通形式
- 概要
- Scrumでは,要件の詳細はprojectを通じて継続的に対話しながら調整
- 要件はjust_in_time.チームが開発を始める必要なときに,必要な分だけ
- business goalを達成するために操作できる重要な自由変数
- Product Backlog Item(product_backlog_item): 要件の置き場所.それぞれが何らかのbusiness valueを表す
- 会話の中で,より詳細なproduct_backlog_itemに分解し,最終的にsprintに入る大きさまで小さく・詳細化される
- 設計・構築・テストができる
- Product Backlogはproduct_backlog_itemの集合のsnapshot
- product_backlog_itemの標準形式はない
- user_storyやusecaseなど
- 会話の中で,より詳細なproduct_backlog_itemに分解し,最終的にsprintに入る大きさまで小さく・詳細化される
- 対話する
- 要件: 構築しようとしているproductに欠かせない事柄についての共通理解を促進するcommunication手段
- 音声によるcommunicationは,帯域が広く,feedbackもすばやく,安くて簡単に共通理解が得られる
- 双方向communicationが問題解決のためのideaの発見を促す
- Product Backlogは生きているdocument
- 改良し続ける
- 段階的洗練戦略
- what's user_story
- 様々な種類のproduct_backlog_item(特にfeature)に期待されるbusiness valueを表現する便利な形式
- business側と技術側ともに理解しやすくなっている
- 単純な構造,会話のために優れたplaceholder
- 段階的改良もしやすい
- Agile development principleとneedsを効率的に結びつける軽量approach
- 要件の詳細化として,重要・役立つ情報の記録のために使う
- Card
- userの分類(役割),目的,求める理由(利益)を具体的に書く
- 要件の意図や本質を捉えた数行の文章にする
- 関係者をより詳細な議論に導く
- 対話(Conversation)
- Conversationは,要件の詳細を適切な時期に具体化・共有するためのstart point
- user_storyはConversationのための約束事
- user_storyが,書くことに向けていた注意を対話に向ける
- 豊かな情報のやり取りと協調をもたらす
- 正確な要件を誰にも理解できる表現にする
- 文書と相互補完的
- Conversationは,要件の詳細を適切な時期に具体化・共有するためのstart point
- 確認(Confirmation)
- 満足条件,受入条件
- 期待される振る舞いを示す
- 受入テスト
- 実例による仕様,ATDD(受入テスト駆動開発)
- 具体例を精緻化し,user_storyを作成・改善するprocessを駆動できる.user_storyに自動化された受入テストも用意できる
- 満足条件,受入条件
- 様々な種類のproduct_backlog_item(特にfeature)に期待されるbusiness valueを表現する便利な形式
- 詳細化のlevel
- うまく書けたuser_storyとINVEST
- INVEST: user_storyが書き手の意図に合うかどうかを評価するために有用なprinciple
- Independent
- 依存性を最小化
- Negotiable
- user_storyは内容と理由を書く
- 規制や制約がなければ,方法がNegotiableとなるようにする → Innovation
- user_storyは内容と理由を書く
- Valuable
- 顧客と利用者双方にとって → product_ownerから見てすべてのstoryはValuableが要
- technical storyはProduct Backlogに入れない.business storyの関連タスクとする
- Estimatable
- storyの規模,労力,costが目安
- Small
- 近いうちに取り掛かりたいstoryは小さくする必要がある
- sprintで扱うため
- 近いうちに取り掛かりたいstoryは小さくする必要がある
- Testable
- 確認 → 5.4
- 必須ではないし不可能なこともある
- 非機能要件
- system levelの制約
- できる限り多く完成の定義に含める
- → すばやいfeedback
- 学習のためのstory
- prototype, POC, 実験, 学習, spike
- 探索的activity
- cost, valueの算出・比較
- fail first戦略もある
- storyの収集
- userは作家というより批評家
- userにチーム memberとして関与してもらう
- user_story記述workshop
- 目的: business valueについて協調的にbrain storming,想定するproduct/serviceのためのuser_storyの類型を作る
- 初回はuser role analysis
- personaというprototype的人物描写も作成する
- 進め方は上手くいくやり方でいい
- story mapping
- user中心指向の観点からuser_storyを作成
- 抽象的なuser actionを,詳細taskによって組み立てられるworkflowに分解する
- epic/theme/sprint可能なstory
- userにとってのvalueから優先順位づけ
- storyの分解とuset中心設計の考え方の結びつけ
- user目線での行為の流れを示す
- 顧客の価値という大きな観点からの,個々のstoryの関連性が分かる
- workflow: contextとなり,関係するstoryに注目できる
- user_story記述workshopに,優先順位を補完する
- まとめ
- Scrumでの要件の扱いを見た
Ch06 product_backlog
- 概要
- product_backlog: productに求められる機能を,優先順位をつけてリスト化したもの
- 何を作るか,どの順番で作るかについての認識が一か所にまとまり,共有できる
- Scrum frameworkの肝
- product_backlog: productに求められる機能を,優先順位をつけてリスト化したもの
- product_backlog_item
- だいたいはfeatureや機能項目を表し,userや顧客の目に見える価値をもたらす
- user_story形式で書かれることが多いが,書式は不定
- good product_backlogの特徴
- Detailed appropriately(適切な詳細度)
- 取り掛かる時期に合った詳細度.近いほど細かい.
- 適切なtiming
- Emergent(創発的)
- 時間とともに姿を変える
- 対応可能になっている
- Estimated
- story_point, 理想日を使う
- 近いものは小さめで正確な見積もり
- 遠いものは見積もりはしなかったり,Tシャツのサイズ程度の見積もりになることもある
- Prioritized
- 遠いものは細かい優先順位不要.全体のlevelでの優先順位程度でいい
- Detailed appropriately(適切な詳細度)
- grooming
- DEEPなproduct_backlogのために,product_backlogの中身を整理
- product_backlog_itemの作成と改良(詳細の追加)/product_backlog_itemの見積もり/product_backlog_itemの優先順位づけ の総称
- product_ownerが主導する全員での共同作業
- 開発チームは,各sprintの作業時間の最大1割程度までgrooming用に時間を確保
- timing
- 最初はrelease planningのときに,stakeholderとともに
- 週に1度かsprintに1度程度で,development_teamとともにgrooming workshop
- daily_Scrumのあとにincremental groomingを行うこともある
- 全員でやる必要はない
- daily_Scrumのあとにincremental groomingを行うこともある
- sprint reviewの際にも行う
- きちんとprocessに組み込みさえすれば,timingは重要ではない
- business valueを柔軟かつ高速にdelivery
- 準備完了の定義
- grooming: Backlogの最初のitemを準備完了にする
- 作業のchecklist
- product_backlog_itemについて必要なことのリスト
- 厳しく設定すると,sprint goalの達成可能性が大きく上がる
- flow management
- product_backlog: 不確実性がある状態でも高速かつ柔軟にvalueを提供する流れを実現できる
- 重要な情報は絶え間なく少しずつやってくる
- → 作業を整理して管理し,頻繁にやってくる情報をすばやく効率的に処理しながら対応する必要
- release flow management
- release planningに備えたgrooming
- 必須/できれば含める/含めない の3 エリアに分ける
- sprint flow management
- groomingにより,feature群をsprintに流し込める
- product_backlogの先頭のitemは,明確に定義されていてテスト可能な状態
- product_backlogを要件のpipelineと考えてgroomingが〇
- pipelineからsprintに流し込まれた要件を,設計・開発・テスト
- product_backlogを上がっていく間にgroomingで要件が見直されていき,準備完了な状態になる
- development_teamが理解できるほど詳細で,1回のsprintで完了できる規模になる
- 必要十分なだけのproduct_backlog_itemを在庫として抱え,一定のflowを作ることがimportant
- sprint 2回から3回分程度のstoryを準備完了状態で抱えておくとうまくいく
- groomingにより,feature群をsprintに流し込める
- product_backlog: 不確実性がある状態でも高速かつ柔軟にvalueを提供する流れを実現できる
- どんなproduct_backlogをいくつ用意するか
- 基本原則: Productごとにproduct_backlogを1つ用意
- 注意が必要なcaseある
- Productとはなにか
- さまざまな捉え方
- goal: component_teamの数をできるだけ減らす
- → packagedで,デリバリー可能であり,利用者に価値をもたらすものに合わせて,product_backlogを並べる
- 大規模product -階層化backlog
- できるだけ1つのproduct_backlogがよいが,現実的に不可能なこともある
- → 階層化backlog
- feature area単位のBacklog Itemは.対応するproduct_backlogのitemよりも,サイズが小さい
- release train → Ch12
- portfolio_backlog, program backlog, チーム backlogの3 level
- 複数のチーム -単一のproduct_backlog
- Productごとに1つのBacklog → Productにかかわるすべてのチームがproduct_backlogを共有するため
- Product全体で見たときの経済的最適化可能
- 各チームがproduct_backlogのどのItemに対応できるのか知っておく必要
- → 共有Backlogに対するチームごとのviewを用意する
- チームの交換可能性に価値がある
- Productごとに1つのBacklog → Productにかかわるすべてのチームがproduct_backlogを共有するため
- 単一のチーム -複数のProduct
- チームは複数のProjectの担当は極力避ける
- 少なくとも,同時に複数のProductにかかわらないようにする
- どうしても同時に複数のProductの作業をするときは,各product_backlog_itemを1つのproduct_backlogにまとめる
- 基本原則: Productごとにproduct_backlogを1つ用意
- まとめ
- product_backlogが果たす,不確実性のもとで高速かつ柔軟に価値を提供する流れを実現するための役割
Ch07 見積もりとVelocity
- 概要
- まず作ろうとしているもののサイズを見積もる
- さらに,その作業におけるVelocityを計測
- 各sprintで完成したItemの見積もりサイズを合計することで出せる
- → 期間・costを導ける
- いつ何を見積もるのか
- Portfolio Backlogの見積もり
- 作成するすべてのProductの優先順位づけ
- ざっくりとした相対的な見積もり(Tシャツのサイズていど)
- Product Backlogの見積もり
- product_backlogのgroomingの一環として行うactivity
- 見積もりmeeting @初回のrelease planning
- 以降も新たなproduct_backlog_itemの見積もりが必要なら見積もりmeetingを招集する
- 成熟したScrum_teamならすべてのproduct_backlog_itemを同程度のサイズにまとめられる
- 見積もる理由
- すべてのproduct_backlog_itemが同時に同じサイズにはならない
- チーム memberがすべてのproduct_backlog_itemのサイズを同程度にまとめられるようになるには,それなりに時間がかかる
- 同じサイズにすることが目的となってしまい,不自然なところでstoryを分割せざるをえなくなることを避ける
- 最重要なこととして,見積もりの最大の目的は,対話の過程でいろいろな気づきが得られる
- 健全な議論を促す
- taskの見積もり
- commitmentが達成可能だと確信するため
- 大きさは理想時間単位で判断(a.c.a. 工数)
- Portfolio Backlogの見積もり
- product_backlog_itemの見積もりの考え方
- チームで見積もる
- development_teamが,全員で見積もる
- 全員の意見をまとめて,それぞれのproduct_backlog_itemのサイズを判断できるようにする
- 見積もりはcommitmentではない
- 数字を操作しないでよいようにする
- 正確性か精度か
- 無駄は×
- やり過ぎると逆効果
- 相対サイズの見積もり
- チームで見積もる
- product_backlog_itemの見積もりの単位
- story_point
- product_backlog_itemの大きさを計測する指標
- storyの複雑さ,物理的サイズなどを組み合わせて,相対サイズを測る単一の指標としたもの
- development_teamの視点からの,storyの完成に要する作業を表す
- 理想日
- 誤解を招くriskあり
- あと(理想日)日で終わるというわけではない
- 作業日数(人日)で表す
- 誤解を招くriskあり
- story_point
- planning poker
- memberの同意ベースで見積もりを行うtechnique
- 見積もりの尺度
- フィボナッチ数列や2の累乗などで,同程度のサイズのproduct_backlog_itemをひとまとめにして同じ数字をassign
- 進め方
- merit
- チーム memberをまとめて,正確な見積もりとなる
- 議論によりproduct_backlog_itemの理解が深まる/共有できる
- Velocity
- 各sprintで完成した仕事量
- 計測対象: 生産量(サイズ), not 成果(value)
- 利用目的
- Scrumでのplanning
- チームの現状を診断
- Velocityの幅の算出
- 幅を持たせる → 不確定要素があることが伝わる
- min/max sprint数が分かる
- 最大値と最小値の平均や,90%信頼区間など単純計算で求める
- Velocityの予想
- sprint planning
- commitしたproduct_backlog_itemのサイズを合計してチームの予想Velocityとする
- 2回のsprintで見積もりを行うなどで,幅を求める
- sprint planning
- Velocityへの影響
- 向上のための手段や悪影響のある手段など
- Velocityの誤用
- performanceの指標としては使えない
- 数字の操作(pointのインフレなど)や手抜きが起こる
- 見積もりの正確さの検証,チーム内での改善がどの程度進んでいるのかの判断にのみ使う
- performanceの指標としては使えない
- まとめ
- サイズの見積もり,Velocityの算出,期間の求め方
- 各levelでの見積もり
- story_point/理想日
- planning poker
- Velocityの使い方
Ch08 技術的負債
- 概要
- 負債の返済のために十分に注意が必要
- systemの設計や実装は,業務ドメインに関する知識をよく反映できるように発展させていく必要
- 無責任や不注意といった原因で発生する,ナイーブな技術的負債
- 不可避な技術的負債
- 戦略的な技術的負債
- 技術的負債の行く末
- 技術的負債を生む要因
- 納期を守るためのpressure
- Velocityの偽装
- testを減らせばVelocityが向上するという神話
- TDDのような優れた手法を使うのが〇
- 負債が生む新たな負債
- 納期を守るためのpressure
- 技術的負債の管理
- どんなproductも技術的負債からは逃れられない
- 技術者の言い分とbusiness関係者の言い分のbalanceを取る
- product_ownerが存在する理由の1つ
- 技術的負債の発生の管理
- 優れた技術的practiceの活用
- ナイーブな技術的負債を増やさない
- simple design, TDD, CI, 自動テスト, refactoringなど
- refactoringによる負債の支払い
- 厳しい完成の定義の使用
- checklistの技術的な網羅性を高める
- 技術的負債の経済的意味についての適切な認識
- 技術的負債の多方面への影響
- 真のcostより低く見積もってしまいやすい
- 技術的負債の多方面への影響
- 優れた技術的practiceの活用
- 技術的負債の可視化
- 技術的負債という例えの最大のmerit: development_teamと経営者の会話での共通認識の獲得
- business levelでの技術的負債の可視化
- 組織のBalanceSheetに短期・長期の技術的負債の行を追加
- Velocityの変化の追跡
- 金銭的costを明確にできる
- 技術者levelでの技術的負債の可視化
- 既存の障害管理systemに記録
- product_backlog_itemを作成
- 返済のcostが高い場合
- 技術的負債だけを扱うBacklogを作成
- 技術的負債の現状を把握
- どの時期に負債を返済するか積極的に決められる
- 同じ場所で作業なら,掲示板を壁に掲げるのもよい
- 技術的負債の返済
- category
- 偶発的な技術的負債
- 既知の技術的負債
- 返済対象の技術的負債
- flow
- 既知の技術的負債を返済すべきか判断
- 作業中のコードに偶発的な技術的負債を見つければ,きれいにする
- 多すぎるときもできるだけは対応する
- 返済できない分は既知の技術的負債としてまとめる
- sprintごとに既知の技術的負債のいくつかを返済対象の技術的負債とみなす.
- とくに利率の高いものを選ぶ
- すべての技術的負債を返済すべきというわけではない
- 寿命が近づいているproduct
- 使い捨てのprototype
- 短期間しか使わないproduct
- boy scout ruleに従う(負債を見つけたらその場で返済)
- 「来た時より美しく」
- 偶発的な技術的負債の返済用の時間を予めある程度見込んでおく
- 5%~33%
- 技術的負債の返済はincremental
- 一括払いは×
- 返済のためだけのsprintが必要となってしまうような状況にしない
- 既知の技術的負債をピックアップして返済対象の技術的負債とみなし,次のsprintで返済
- 金利の高い技術的負債から返済
- 多くのコードが依存していて頻繁に変更が加わるモジュールなどでの負債
- 技術的負債を返済しながら顧客に価値をもたらす作業も行う
- できるだけ,返済のためだけのsprintは作らない
- 負債の返済だけを扱うproduct_backlog_itemは置かない
- merit
- 負債の削減の作業を顧客に価値を届ける作業とうまく組み合わせて進めれられ,product_ownerが適切に設定した優先順位に合わせられる
- development_team_member全員が,技術的負債の削減に関する責務を共有.ほかの人が後で対応してくれるものではないとはっきりできる.
- 技術的負債の予防や対策の力を養える.
- 金利の高い分野を見つけやすくなる. ← 対応中のコードは何かしらの重要性がある(からこそ対応している)ため.
- 対応不要な分野の技術的負債の返済に,時間を無駄遣いせずに済む.
- 既知の技術的負債の返済をproduct_backlog_itemと関連付けて進めるのは,simpleに組み合わせられて〇
- category
- まとめ
- 技術的負債の概念
- 3つの分類
- 管理
- activity
- 発生の管理
- 可視化
- 返済
Part 2 Role
Ch09 product_owner
- 概要
- product_owner: productの統括を認められた中心的な存在.Scrum_teamを構成する3つのRoleのうちの1つ.
- 2方向を見る → business analyst & tester
- 組織内のstakeholder, client, userが持つneedsや優先順位について,代理ができるくらいに深く理解
- product managerとして振る舞い,正しくsolutionが開発されていることを保証
- development_teamに何をどの順番で構築するか伝える
- & 受け入れ条件を明確にして,条件を満たすテストを実行させる
- 抽象的なtestは書く
- 組織内のstakeholder, client, userが持つneedsや優先順位について,代理ができるくらいに深く理解
- 主な責任
- 経済性の管理
- 各levelで適切な経済的意思決定が継続的になされるようにする
- release levelの経済性
- product development中に生じる経済的に重要な情報に対応
- scope,納期,予算,品質との間で継続的にtradeoff
- sprint終了時に,次のsprintを実施するかどうか判断
- product_backlogによる柔軟性
- sprint levelの経済性
- sprintごとのROI(投資収益率)を高めるため
- sprintのcost: 期間とチーム 構成を把握
- Product Backlogの経済性
- 経済状態に応じた優先順位に責任
- planningへの参加
- product_backlogのgrooming
- 受け入れ条件の定義と検証
- product_backlog_itemの受け入れ条件を定義する責任
- 受け入れ条件: 機能要求や非機能要求が満たされているとproduct_ownerが納得できる条件
- sprint planningの前に受け入れ条件が必要 ← 準備完了の定義に含まれる
- 受け入れ条件が満たされていることを確認する最終的な責任
- 検証は,sprint実施時に行う
- sprint reviewまで待たない
- sprint reviewでのデモは完成した機能のみ
- sprint reviewまで待たない
- product_backlog_itemの受け入れ条件を定義する責任
- development_teamとの協力
- 積極的な関与,献身,毎日果たすべきRole
- stakeholderとの協力
- 内外のstakeholder
- 経済性の管理
- 特性とskill
- domain skill
- 対人skill
- stakeholderとよい関係が必要
- → 交渉,合意形成
- stakeholderとdevelopment_teamとの橋渡し
- 適切な言葉で情報を伝えるcommunication skill
- 特性
- 現状に反する場合でも声を出す
- ideaに自信がある
- domain 知識がある
- 単純かつ簡潔にわかりやすく情報を伝えられる
- 信用されている
- 周囲のmotivationを高められる
- businessの課題を伝えて,仕事の目的を思い出してもらい,情熱を持続させる
- stakeholderとよい関係が必要
- 意思決定力
- 意思決定の権限が必要
- 適切なtiming, 正当な理由
- 最終的な意思決定者
- business needsと技術的な実現性とのbalance
- 説明責任力
- business resultを届けることへの説明責任
- resourceを有効に活用する責任
- product_backlogの変更,優先順位の調整,開発の中止が可能
- stakeholder, Scrum_teamともにかかわる,フルタイムの仕事
- product_owner, Scrum_master, development_teamは共通のgoalをもつ1つのunit
- 1日の様子
- 1週目,2週目
- 3週目
- 初期のrelease planning
- 内部stakeholder, development_team_member, ときに外部stakeholderも参加する,product_backlog_item記述(story writing) workshopを含む
- release planningで使用する概要levelのproduct_backlogを作成
- 見積もりworkshop
- 1~2日
- development_team_memberが価値の高いproduct_backlog_itemの規模を見積もる
- 最初のrelease planningのfacilitation
- product_backlogの優先順位づけ
- 制約(scope, schedule, budget)のbalanceをとる
- stakeholderに加え,development_team_memberの一部~全員で,product_backlog_itemの並び順に影響を与える技術的な依存性を特定
- goal: releaseの全体像の明確化.いつ何ができるのかというbusinessの最初の質問に答える
- 1~2日
- 継続的なactivity
- 内部stakeholder, development_team_member, ときに外部stakeholderも参加する,product_backlog_item記述(story writing) workshopを含む
- 初期のrelease planning
- 4周目~ Scrum_teamが最初のsprintを開始
- 開始時に,sprint planningを統括
- 実施中は,daily_Scrumに参加
- 質問に答え,review可能になった機能をテスト
- 毎日する必要があるので,できないときは代理を立てる
- 内外のstakeholderに会って,次のsprintの優先順位が正しいことの確認
- 今後のsprintで機能を選択するときに影響を与えるuserからの重要なinputを取得
- product_backlogのgrooming
- sprintの終わりに,検査と適応の2つのactivityに参加
- sprint review, sprint_retrospective
- 誰がproduct_ownerになるべきか
- 社内開発
- 開発の恩恵を受ける部門から任命された人がなる
- 商用開発
- product managerやproduct marketerなど,clientの声を代弁する人がなる
- できるだけ多くのactivityに責任をもつ
- 1人でこなしきれないほど膨大ならproduct_owner チームを作るが,Scrum_teamのproduct_ownerの役割は常に1人
- 外部委託開発
- 委託元の社員がproduct_owner
- 固定価格契約は× → 複雑
- component開発
- 技術componentに注力 → Backlogの優先順位を決定できる技術志向の人がなる
- feature_teamの技術的要求の優先順位や統括方法がわかるproduct_ownerが必要
- 社内開発
- その他のRoleとの組み合わせ
- 余裕があれば,同じ人が複数のScrum_teamのproduct_ownerの担当も〇
- それぞれの成果に関連があるときはこの方が簡単
- product_ownerとScrum_masterの兼任は×
- 余裕があれば,同じ人が複数のScrum_teamのproduct_ownerの担当も〇
- product_owner チーム
- 1人の人間が, product_ownerとして意思決定し,stakeholderやScrum_teamとの橋渡しをする必要がある
- 1人のproduct_ownerに対してproductに問題があるだけなら,productの問題に対応するべき
- 必要なときのみproduct_owner チームを作る
- product_owner proxy
- 事業部門の人にproduct_ownerを担当してもらい,IT部門の人はproduct_ownerとチームのやり取りをするproduct_owner proxyを任せるcase
- 特定の状況でproduct_ownerの代理になれる人
- 本当のproduct_ownerではなく,代わりに戦術的な意思決定をする人
- 責任はproduct_owner
- chief product_owner
- 階層的にscale
- 各チームのproduct_ownerが上の階層に投げることなく,ほとんどの意思決定をできるようにしておく
- まとめ
- product_ownerのRole
- productの統括を認められた中心的な存在
- product_ownerの重要な責任と特性
- Scrumの各activityにおけるproduct_ownerの行動
- 誰がなるべきか
- product_ownerのRole
Ch10 Scrum_master
- 概要
- Scrum_master: Scrumのvalue, principle, practiceがみんなに正しく理解され,受け入れられるようにする
- as a coach
- 自分たちに適したperformanceの高いScrum手法で開発できるように,processのleaderとして支援する
- Scrum_master: Scrumのvalue, principle, practiceがみんなに正しく理解され,受け入れられるようにする
- 主な責任
- coach
- Scrum_teamのAgile coach
- development_teamとproduct_owner間の垣根を取り払う → product_ownerが直接開発を駆動できる
- 問題には支援する.impedimentは解決する.
- 新人product_ownerが責任を理解し,Roleを果たせるようcoaching
- product_backlogのgroomingなどのactivityを継続的に支援
- Scrum_masterとproduct_ownerの関係: sport チームのcoachとownerの関係に似ている
- Scrum_master: Scrumでbusinessの成果を最大化,期待を管理,product_ownerがチームに必要なものを提供,変化に対するproduct_ownerの不満や要求を聞き出し,チームが実行可能な改善へと翻訳
- Scrum_teamのAgile coach
- servant leader
- processの権威者
- 防御壁
- チームがvalueを届けることに集中できるようにする
- impedimentの除去
- change agent
- 意識の変化を支援
- 変化の必要性やScrumの影響・利点を理解してもらう
- 長期的な成功につなげる
- 大きな組織では複数のScrum_master
- 意識の変化を支援
- coach
- 特性とskill
- 博識
- いずれも専門のtop levelでの知識は不要だが,ある程度の知識は技術でもbusinessでも必要
- 質問力
- 内容を促す質問(probing question)
- 自分で答えを見つけられることを認識してもらう
- 辛抱強い
- 自分の方がチームの集合知よりも賢いと考えない
- 定期的に内省を促す質問をして,チームにsolutionを見つけてもらう
- 協力的
- 保護力
- 経済的に正しいbusiness judgeができるようにチームを保護
- Scrum_teamが健全なbalanceを取れるように支援
- Scrumからさまよい出るmemberを支援.チームが難しさを克服できるようにする
- 透明性
- 博識
- 1日の様子
- Scrumのactivityの開催やfacilitationに毎日時間を使う
- sprint planning
- sprintの実施
- sprint review
- sprint_retrospective
- daily_Scrum
- activityの準備・統括・Scrum_teamが価値の高い成果を達成できるように支援することも含む
- 毎日チーム memberをcoaching
- 毎日一定時間をcommunicationに使う
- sprintでは,product_ownerとともにproduct_backlogのgrooming
- change agentとしての時間
- impedimentの除去
- Scrumのactivityの開催やfacilitationに毎日時間を使う
- Roleを果たす
- 誰がなるべきか
- project managerやproduct managerからScrum_masterになることもある
- technical leadは△
- managerとの兼任も△(×)
- 必ずしもfull timeではない
- ほかのRoleとの組み合わせ
- ほかのRoleと兼任するより,複数のチームのScrum_masterになるのが〇
- 誰がなるべきか
- まとめ
- Scrum_masterのRoleなど
Ch11 development_team
- 概要
- 機能横断的
- Role別のチーム
- 技術的skillを一通り備えたチームが必要
- できるだけ機能横断的
- 主な責任
- sprintの実施
- 大半の時間を割く
- 自己組織化
- 日々の検査と適応
- daily_Scrumに全員で参加
- product_backlogのgrooming
- sprintの10%を使い,product_ownerのactivityを支援
- sprint planning
- sprintの期間に応じて,半日~1日
- 反復して実施, just_in_time
- productとprocessの検査と適応
- sprint review
- sprint_retrospective
- sprintの実施
- 特性とskill
- 自己組織化
- bottom up型の創発的な特性
- 外部からの圧力なし
- 複雑適応system
- 多くのentityが様々な方法でやりとり
- やりとりは,単純で局所的なruleで統括され,定期的なfeedback
- 大いに堅牢で斬新
- managerは自己組織化チームのための環境を設定・再構築する
- bottom up型の創発的な特性
- 機能横断的な多様性と十分な能力
- product_backlog_itemを選択し,Scrum_teamの完成の定義を満たして動作する,高品質の機能を作り出す
- 成果の手渡しの数を最小化
- 複数の視点が良い成果になる
- 問題解決のための認知toolの持ちより
- 解釈,戦略,mental model,手法やsolutionの嗜好が異なる
- → すばやいsolution,高品質の提供物,大いなるinnovation,という観点から良い成果につながり,経済的valueへと変わる
- 問題解決のための認知toolの持ちより
- チームの多様性のために,senior, juniorを組み合わせる
- みんなで協力して学習し合う健全な環境
- T型skill
- 幅広さと深さ
- 継続的に学習してskill setを増やせるような環境が必要
- skill set: domain knowledge, technical knowledge, thinking skillなど
- 学習と実験の時間がうまく作れるように,managerがチーム memberを支援
- 専門家は,複数のチームに余裕がある状態で時間を分割するか,ほかのmemberの学習支援に時間を使う
- チーム memberがcoreとなる専門分野をもち,全体として柔軟性をもたらすような,skillに重なりのあるチームを作ることがgoal
- 銃士の姿勢
- one for all, all for one
- 仕事を成し遂げる責任をチーム member全員が負う
- できないことがあるときは,skillある人に学習支援をしてもらい,チームの総合力を高める
- 1人に負担がかからないように作業を構成
- 議論に多様性
- 広帯域のcommunication
- 有益な情報をすばやく交換,overhead少なく効率的にやり取り
- 情報共有の頻度と品質を向上
- → 検査と適応の機会が増え,意思決定を迅速にできる
- 情報の経済価値は時間に依存 → 共有速度が高まれば,チームは情報の価値を最大化できる
- 方法
- face to face
- TV会議system
- 機能横断的チーム
- 形式的な提出物によるやり取りの量も回数が少なくなる
- valueのない儀式を減らす
- 小さなチーム
- channel数の増加率
- 適切な規模
- 小さなチームの理由
- 社会的手抜きが少ない
- 建設的なやり取りが頻繁に起こる
- 調整に必要な時間が少ない
- 誰も陰に埋もれない
- 小さなチームの方がmemberを満足させられる
- 有害な過度の専門化が発生しにくい
- 人数が多すぎたら,9人程度にチームを分割
- Scrum projectのscale: 複数のScrum_teamを作る
- Scrum of Scrum
- 上位levelのdaily_Scrum相当のものを開催する
- Scrum of Scrum
- 小さなチームの理由
- 集中とcommitment
- 集中: チーム memberが積極的にかかわって,チーム goalに専念
- commitment: よいときも悪いときも,チーム goalの達成に尽力
- 3つ以上のprojectの仕事を同時に行うのは経済的でない
- 調整・想起・情報の追跡に時間がかかり,valueを付加する仕事の時間が減るため
- 基本は1つがよい
- 持続可能なpaceで仕事をする
- Scrumの優れた技術的なpracticeで平準化
- 長寿
- groupではなくチーム
- チーム: 機能横断的で多様性のある協調性の高い人たちで構成され,visionを共有し,それを実現するために協力する集団
- group: 共通のlabelがついた人の集団
- 長寿は経済的に好ましい
- forming, storming(争乱期), norming(規範期), performimg
- 上手く機能したチームはbusiness資産になる
- 歴史的に重要な情報を蓄積
- Velocityや見積もりの履歴
- 歴史的に重要な情報を蓄積
- Agileの通貨はチーム
- 個人と対話に価値
- チームの信頼,一貫性,作業効率を保つ
- 人ではなくチームを移動させる方が,経済的に優れている
- チームは資産
- 同時に行うWIPの数やproductの種類を決めるときのcapacityの単位
- 自己組織化
- まとめ
- development_teamのRole
- product_backlog_itemを出荷判断可能なproduct incrementに変える責任
- sprintにおける責任
- 10個の特性
- 自己組織化,機能横断的で多様性がある,仕事を成し遂げるために十分なskillがある
- T型skill
- 銃士の姿勢
- 広帯域のcommunication
- 小さなチーム
- 集中とcommitment
- 長寿
- development_teamのRole
Ch12 Scrum_teamの構成
- チームの構成や,チーム間のかかわり方が,Scrumをうまく進めるために重要になる
- 概要
- businessのvalueを提供するために,複数のScrum_teamsの協力が不可欠
- feature_team or component_team
- feature_team: 機能横断型かつcomponent横断型のチーム
- component_team: 何か1つのcomponent, subsystem(featureの一部)のdevelopmentにのみ注力
- a.c.a. asset チーム, subsystem チーム
- 同じ専門skillを持った人たちの集まりで構成される実行部隊など
- 中央管理型の共有resource的
- 各component_teamが作ったcomponentを統合し,完全なfeatureにまとめてdelivery
- 一番良いのは,機能横断型のfeature_team
- 移行措置としては,1つのfeature_teamがfeatureをproduct_backlogから取り出し,作業完了までの責任を持ち,完成までの手配をする
- 個々のcomponent_teamも残り,各チームからfeature_teamのmemberをassignし,仲介者・収穫者の責務を持たせる
- 頻繁にやり取りするcomponentを1つのfeature_teamにまとめる
- component_teamを導入するのは,resourceを1つのチームにまとめて集中管理した方が合理的なときだけ
- 複数チーム間での調整
- Scrum of Scrum
- チームをまたがる作業を複数チーム間で調整
- question
- 前回以降で各自のチームの作業で,ほかチームに影響しそうなもの
- 次回の各自のチームの作業で,ほかチームに影響しそうなもの
- 各自のチームの今抱えている問題で,ほかチームに助けてほしいもの
- 階層化も〇
- release train
- vision, planning, 複数チーム間の依存関係などを調整するための手法の1つ
- チーム間でのsync
- product levelでの高速で柔軟な流れに注力
- featureが「駅を出発」するscheduleが決まっている
- rules
- 頻繁に定期的にplanning, solutionのrelease日またはPSI(出荷判断可能なincrement)の公開日を決めておく(固定期日,固定品質,可変scope)
- すべてのチームでiterationの長さをそろえる
- 全体での中立的かつ客観的なmilestoneを決める
- 継続的なsystem integrationを,top level(system level)だけでなくfeature level, component levelで行う
- releaseできるincrementを定期的に(一般的に60日/120日ごと)用意し,client向けのpreviewや内部review, system level のQAに使えるようにする
- system levelのhardening iterationを実行し,技術的負債の返済やrelease levelの検証・テストを行う
- 各チームを同じような構造にするために,基盤になる各種component(interface, SDK, 共通でinstallするsoftware, license, UX framework, data, Web serviceなど)をきちんとそろえる
- richな概念
- portfolio level, release levelなど,何段階かの詳細度で考えられる
- enterprise backlog modelに基づく
- portfolio_backlog, program backlog, チーム backlogの3段階のbacklog を使う
- チーム levelのrelease train
- 各チームが数個のfeature areaに分かれてまとまる
- 現実的な頻度で,feature areaをまたがったsystem全体の統合やテストを行う
- 列車が発射する直前をhardeningのための時間と決めていることもある
- release trainの流れ
- release planningのmeeting
- sprintの実行
- release train levelでの検査と適応
- Scrum of Scrum
- まとめ
- Scrum_teamを構成するさまざまな方法
- feature_team
- component_team
- feature_team, component_teamの組み合わせ
- 徐々にfeature_team主体に移行し,codeの共同所有を実現
- Scrum of Scrum
- release train
- 数多くのScrum_teamのactivityを調整
- Scrum_teamを構成するさまざまな方法
Ch13 manager
- 組織内にはScrumと関係ないRoleがあり,それらも組織に必要
- 各managerのRoleを見る
- 概要
- Scrumでもmanagerはimportant
- functional_managerの責務: teamの編成と育成, 環境を合わせてなじませる,value創造の流れを作る
- teamを編成する
- 境界を定める
- managerが,product, project(砂場)を定める
- teamの構成を決める(誰をどのprojectとするかを決める)
- teamはprojectの中で自己管理する
- 自己組織化したteamにどこまで許すか決定
- いくつのprojectを作るか決定し,各projectの境界も定める
- teamの構成を決める(誰をどのprojectとするかを決める)
- managerが,product, project(砂場)を定める
- 明確なgoalを定める
- 目的と方向性をteamにもたらす
- product_ownerがgoalをより具体化する
- teamの体制を決める
- business上のneedsや制約とのbalanceをうまくとったteamを作る
- 機能横断的なScrum teamを作る
- 各分野やcommunity(functional area)にfunctional_managerがいて,各functional areaからmemberを選んでteamを組む
- teamの構成を変更する
- memberの変更
- teamに権限を持たせる
- 自己組織化したteamでお互いをよりうまく管理することの達成のため,team_memberに責務を委譲
- 権限のlevel
- 通知,説得,相談,合意,助言,確認,委譲
- 信頼し,委譲した分は任せる
- team_member間に銃士の姿勢を育てる
- 境界を定める
- teamを育てる
- managerがteam を管理するわけではない
- teamを活気づける
- 楽しくて創造的でvalueをもたらせるような環境を作るのが責務
- → motivation, energyを引き出す
- task levelの作業のassignはやる気をそぐ
- 楽しくて創造的でvalueをもたらせるような環境を作るのが責務
- 能力を伸ばす
- memberが常に何かを学び,skill setを磨き続けられるような環境づくりをする
- 研修の受講,カンファレンスへの参加
- 個別のfeedbackの頻度を調整し,各memberの直属の上司が属するteam内での学習loopにマッチさせる
- sprint単位など
- 個人のperformanceがteamのperformanceを以下に支えるかという観点で行う
- memberが常に何かを学び,skill setを磨き続けられるような環境づくりをする
- functional areaのleadershipを発揮する
- functional area での一貫性を保ち,memberを指導する
- areaに関する標準を設定
- teamの安定を保つ
- teamの構成を可能な限り変えずに保ち続ける
- 環境に合わせてなじませる
- 価値創造の流れを作る
- manager's Role @Scrum
- 戦略的な方向性を定める
- 戦略目標を達成するための組織的resourceを,採算を考慮して揃える
- 全体的な視点で考える
- 財政の管理
- 任された財源をどのように使うか責任
- portfolio management, corporate governance
- 評価や報告の管理
- 評価や報告をScrumの価値や原則に見合ったものにする
- 作業の手待ちを評価
- 動作する検証済みの成果物で進捗を見積もる
- すばやいfeedback flow を作る
- 革新会計の要点となる評価基準
- 革新会計: 不確定要素が多い状況でproduct, serviceを作るような組織でimportant
- 行動につながる評価基準を使って,自分たちがどの程度すばやく学べるか評価
- → business valueのある結果を得るための進捗を見る重要な指標
- 3段階
- 実用最小限の製品(MVP)を作って,組織やproductの現状に基づいた行動につながる評価基準のbaselineを設定
- productのincrementalな改良をもとに行動につながる評価を向上させ,目標値に近づける
- 行動につながる評価の値から目標に向かっての進み具合が実証できればそのまま続行.実証できなければ,新たな戦略にpivotして,この手順を繰り返す
- 評価や報告をScrumの価値や原則に見合ったものにする
- manager's Role @Scrum
- project manager
- Scrum_teamにおける project managementの責務
- Scrumの3つのRoleに分散している
- 調整を任せるのではなく,さまざまな分野にまたがる依存関係を把握して各所とやり取りし,ほかチームとの調整を効率的にできるようにすること
- project managerのRoleを残す
- 大規模で複雑な開発の場合は,手配や調整にからむタスクが非常に多いので,そのままRoleを残すのも〇
- ただし,かなり大規模になったときのみ
- できる限り,チーム間でのcommunication channelを見直すべき
- Scrum of Scrumなどを使う
- できる限り,チーム間でのcommunication channelを見直すべき
- 調整の責務を第3者に渡すべきではない
- project managerはScrum_teamのassistant(servant leaderのようなもの)
- system全体の視点で考えて,各clusterや個々のチームのために動く
- チーム間の調整に何が必要か,誰もがきちんと理解している状態にする.実際の調整はチーム自身で行う
- project managerはScrum_teamのassistant(servant leaderのようなもの)
- 大規模なproduct/service developmentでほんの一部だけがScrumを採用している場合にも使える
- Scrum_teamにおける project managementの責務
- まとめ
- Scrumの組織におけるfunctional_managerのRole
- 4 category
- team編成
- team育成
- 環境を合わせてなじませる
- 価値を創造する流れを作る
- 伝統的な組織とScrumを使った組織でのfunctional_managerの責務の比較
- project managerの責務,Role
Part 3 planning
Ch14 Scrumのplanning principle
- 伝統的な開発よりplanningに時間を割く
- Scrum principleの一部をさらに掘り下げ,planningにどのように適用するのか見る.その土台となる議論を見る.
- 事前にきちんと計画を作れると思うな
- 検査と適応の経験に従う
- 最初のうちにある程度はplanningの成果物を出す
- 事前のplanningとjust_in_timeでのplanningのbalanceのため
- 事前のplanningのやり過ぎに注意
- planningの選択肢は,最終責任時点まで変更可能にする
- planを守ることよりも,planの調整や再計画を重視する
- knowledgeがない状態で作られたため,事前のplanは抜けがある
- plan list management
- WIP management
- 無駄なplanningの作成物を作らない
- 早めにrelease, 頻繁にrelease
- すばやいfeedback, ROIの向上
- 市場に出せるlevelは保つ
- 早めに学び,必要ならpivot
- pivot: 方向転換しながらもそれまでに学習したことはそのまま維持し続ける
- 製品,戦略,成長のengineに関する根本的な仮説を新たに策定し,それを検証できるコースに方向転換すること
- 学習loopを高速かつ経済的に回すことが目標であり,正しくない方向に向かっていればpivot
- pivot: 方向転換しながらもそれまでに学習したことはそのまま維持し続ける
- まとめ
- Scrumにおけるplanning principleの概要を見た
- 原則に従い,経済面で妥当なplanningを達成する
- 事前に用意する適度な量の計画と,実際の結果をふまえたより詳細なjust_in_timeの計画との間で,うまくbalanceをとる
Ch15 さまざまなlevelでのplanning
- Scrumにおけるplanningの概要を全体的な視点で見る
- 概要
- 5種類のplanning
- 範囲,作成者,対象,成果物
- 5種類のplanning
- portfolio_planning
- 複数のproductの中から,どれをどの順番でどの程度の期間で進めていくか決める作業
- 概念的にはproduct_planningより上だが,inputの1つはproduct_planningで得られる新たに考え出したproduct idea
- product_planning(envisioning)
- 作ろうとしているproductの本質を見出して,productを作るための大まかな計画を作る
- まずvisionを作り,その後,概要levelのproduct_backlogを作る
- product_loadmapを作ることも多い
- product vision
- user, clientといったstakeholderたちが得る価値を明確に説明するもの
- 概要levelのproduct_backlog
- まったく新しいproductを作る場合なら,少なくとも最低限の要件は事前に決めて,product_backlogに含める
- 少なくとも最優先のitemがどれになるかも判断する
- 想定されるuser_storyを設定
- product_loadmap(release loadmap)
- productを今後どのように構築してどのようにdeliveryするのかのincrementalな性質を示し,各releaseに含まれる重要なfeatureについても示す
- continuous deploymentがあっても有用になりうる
- 意思決定者に十分な安心感を与え,product developmentを認めてもらうため
- release_planning
- incremental deliveryに向けて,scope, 期日, 予算とのtradeoffを考慮する
- product_planningが終わったら,releaseの最初のsprintを開始する前に最初のrelease_planningを実施する
- そのreleaseでどれだけのものを作るか,それをいつreleaseするのかの間でbalanceを取ったもの
- ある程度のitemをproduct_backlogに用意して見積もる必要がある
- product_backlogに線を引く
- product_loadmapとproduct_backlogをより強く結びつける
- 期間を,そのreleaseを達成するために必要なsprint数で表す
- 直近の数回のsprint程度の推測は,作業の調整や事前に必要な支援のために有用.それより先の推測は無駄
- sprint_planning
- product_backlog_itemの中から,Scrum_teamが次のsprintでどのitemに取り組むかを決める
- 各sprintの最初に行う
- sprint backlogを作る
- product_backlog_itemの完成に必要な作業を,task levelで記述
- より踏み込んだlevelで,just_in_time planning
- daily_planning
- 最も詳細なlevelのplanning
- team_memberが集まり,高度に可視化されたstyleで,当日の大まかな予定を話し合う
- resourceのproblemに気づけるようにする場でもある
- 良い流れでsprintを進める
- まとめ
- さまざまな詳細度でのplanningが,Scrumの開発中にどのように発生するのかを見た
- Scrumの階層的なplanningの図
Ch16 portfolio_planning
- 複数のproductを作るにあたって,product_portfolioをどのように管理するか,継続的に理にかなった選択をする必要がある
- portfolioの管理processを,Agile practiceとうまく協調させる必要もある
- 概要
- portfolio_planning: portfolio_backlogのitemから,どれをどの順番にどの程度の期間で進めていくか決める作業
- item: product, そのincrement(1回分のrelease), or project
- 素早く柔軟な流れを壊さないように実施する
- timing
- product_planningのdataを使って,どのproductにどの順に投資するのかを判断し,portfolio_backlogにまとめる
- 新たなproductに対してだけでなく,既存(仕掛け中)のproductについても見直す
- 参加者
- 内部のstakeholder
- business的な大局観が必要
- portfolio_backlog itemの優先順位の決定や,仕掛け中のproductに対する判断のため
- business的な大局観が必要
- 各productのproduct_owner
- 必要なresourceを主張
- option: senior architect, technical leader
- 技術的な制約を考慮
- 内部のstakeholder
- process
- output: portfolio_backlog, active product群
- outputのために,4種類のactivityがある(→ 以下に続く)
- portfolio_planning: portfolio_backlogのitemから,どれをどの順番にどの程度の期間で進めていくか決める作業
- schedulingの戦略
- 組織内のproductに割ける限りあるresourceを,経済的に理にかなった方式で配分するために,product群を優先順位づけ
- lifecycle 収益で最適化
- 最適化が効いているかどうかをどの変動要因で判断するか決定する必要
- → lifecycle 収益を使ってあらゆる判断やtradeoffを見る
- 標準化されていて使いやすい経済的枠組み
- lifecycle 収益の総量が最大となるように,portfolio_backlog内のproductを並べ替える
- goal: portfolio_backlog itemを並べ替えて,portfolio全体のlifecycle 収益を最大化すること
- 最も影響する重要な2つの変動要因
- delay_cost
- 存続期間(作業量やproductの規模の代替)
- → いずれも各productで異なる場合は,重み付きで一番短いjobを優先する(WSJF)
- delay_costを存続期間(or 実装の作業量)で割ったもの
- delay_costを算出する
- 経済的な意思決定をするにあたって欠かせない情報
- ほとんどの変動要因が時間の影響を受けるという事実
- → 時間軸を必ず考慮してportfolio_backlog内のitemを並べ替える
- 算出方法: spread sheetを2つ作り,遅延がない場合と遅延がある場合の2種類の収益をそれぞれ計算すればよい
- model
- user的な価値
- 時間的な価値
- riskの削減/機会の確保
- 以上の3つの属性について,delay_costを1から10までの数字で設定し,合計したものがproductのdelay_costになる
- または,よくありがちな特徴でdelay_costを分類する
- 線形, 巨大なcost, すぐにでもやるべき, 固定期日, 対数, 実体がない
- 見積もるのは正確性であって精度ではない
- portfolio_backlogのitemを適切にschedulingするために,各productの作業量/costを理解する必要
- 最初の見積もりが必要になる時点では手持ちのdataはたかが知れているので,精度より正確性に注目する
- Tシャツのサイズなどでcostの範囲を関連付け
- → すばやく見積もれる,十分な正確さを得られる,portfolio levelで次の動きを決めるための情報を用意できる
- → 無駄な時間を削減,見積もりの数字を過大評価したり誤った安心感を与えることもなくなる
- inflowの戦略
- product developmentを始めるかどうかの判断において,組織の経済的filterを以下に適用するのかを見る
- 経済的filterの適用
- envisioningのoutputは,product visionに加えて,信頼の閾値を明確にするための情報となる
- → このdataをもとに,product developmentを進めるか中止するか判断
- ↑ このactivityが新しいproductへの「経済的filterの適用」
- 組織の資金需要を満たすかどうかを確かめるactivity
- 組織ごとに経済的filterを定義
- よいfilterはコストをはるかに上回る価値を生み出せる機会をすばやく承認できる
- それ以外の機会は,やむを得ない事情がある場合を除いて却下すべき
- costや価値に合意が取れず決断ができないなら,十分な資金援助が得られないことは明白
- ほとんどの組織ではよい機会がありあまっている
- 追加と取り出しのbalanceを取る
- 年に1度で達成内容の詳細をproduct levelまで全部決めてしまう必要はない
- productをportfolio_backlogに追加する頻度を高くする(月に1度か少なくとも四半期に1度)
- → 新しいproductのreviewやportfolioへの追加にかかるcostや労力を大きく軽減できる
- → portfolio_planningの全体的な安定性や予測可能性を高められる
- productを小さめにすることにも力を入れる
- 頻繁に取り出せるようにしておく
- → inflow, outflowのbalance〇
- portfolio_backlogの肥大化 → portfolio_backlogに追加するproductの流れを絞る
- 経済的filterを調整して,productを承認する条件を厳しくする
- → より価値の見込めるproductだけを承認
- 創発的なchanceへの素早い対応
- 小さめなreleaseを頻繫に行うための計画
- 明白なmeritのほかに,コンボイ効果を回避できる
- 大きなproductが共有resourceを占有することを回避
- 徐々にreleaseしていった方が経済的なmeritが大きい
- 一括releaseをできるだけ避けるようにplanning
- 明白なmeritのほかに,コンボイ効果を回避できる
- outflowの戦略
- 作業者の手待ちではなく作業の手待ちに注目
- productをportfolio_backlogからいつ取り出すのか判断するカギとなる戦略
- WIPを制限する
- 自分たちが完了させられるだけの量に達したら,それ以上のproductをportfolio_backlogから取り出さない
- 制限の程度
- Scrum_teamがいくつあるか,それぞれのteamがどのtypeのproductの作業ができるかで判断
- team全員の準備が整うのを待つ
- 作業者の手待ちではなく作業の手待ちに注目
- 仕掛け品の戦略
- 現在作業中のproductについて,開発を続行するかpivotするか停止するかを判断する助けとなる
- 定期的に判断
- 臨時にも判断する
- 限界費用を使う
- これまでにいくら使ったのかは一切無視して判断する
- 判断のflow
- 資金の追加投入に値するか → 維持
- 必要最小限の機能が実装されているか → delivery
- 別の未知はあるか → pivot
- → 打ち切り
- まとめ
- portfolio_planningに関する11の重要な戦略
- すべて互いに補強し合う
- 各categoryで1つずつのみの場合
- delay_cost
- 小さめのreleaseを頻繁に
- WIPを制限
- 限界費用
- portfolio_planningに関する11の重要な戦略
Ch17 envisioning(product_planning)
- product_backlogを最初に作るときに,productについてのvisionのための事前の作成物を用意するactivity
- 概要
- goal: ideaを詳しく説明し,できあがるであろうproductの本質を示し,実際に作るための大まかなplanを用意
- ideaをportfolio_planningに組み込めるだけの十分な自信が必要
- productの資金調達にまず不可欠なのは,visionを持つ
- client, feature, 概要levelのsolutionについて理解するために必要な程度に情報を把握する
- productにかかるであろうcostの見当をつける
- 短時間で実施する
- timing
- 何度も繰り返す
- きっかけは誰かからのidea
- 組織の戦略的filterを通し,組織の戦略方針に一致しているか調べ,さらなる調査と資金投入の価値があるか判断
- 通過したら,最初のenvisioning
- これから作ることになるproductに関する十分な理解を得て,最初の最低限のreleaseがどんなものであるべきか定義
- → 最大限の価値をすばやく提供,costを抑えられる,すぐに役立つfeedbackを得られる
- feedbackで間違いを判断したら,pivotしenvisioningをやり直して計画を見直す
- 参加者
- 最初のenvisioningに必ず参加が必要なのはproduct_ownerのみ
- 内部のstakeholderも巻き込むことが多い
- specialist(market分析,投資対効果の拡大,UX design,system architectureなど様々な分野)もかかわることが多い
- Scrum_teamが割り当てられてからは,Scrum_master, development_teamも含めてteam全体で参加すべき
- process
- input
- 最初: 戦略的filterを通過したidea
- 2回目から: pivotしたidea
- userやclientからのfeedback, 財源の状況の変化,競合の予期せぬ動き,その他重要な変更から,ideaを更新,修正する
- planningの範囲
- いつまでにenvisioningを完了させるか
- 割けるresourceの量や種類
- 信頼の閾値
- envisioningの完成の定義
- より詳細な開発に向けた出資をするべきか否かを意思決定者が決断する際に,十分な確信をもって結果を出せるようにするために必要な情報をまとめたもの
- input
- goal: ideaを詳しく説明し,できあがるであろうproductの本質を示し,実際に作るための大まかなplanを用意
- SR4Uの例
- 最初の開発に進むべきか否かの判断材料
- 最初のproduct vision, product_backlog, product_loadmap
- userについての最初の前提の検証
- userについてのそのほかの重要な前提・仮説や,最初のreleaseでテストしようとしているfeature群に関する説明
- その他の全体を確かめたり,最初のreleaseが期待通りか判断したりするために使う,計測可能な基準
- 対応すべき疑問点のlist
- 最初の開発に進むべきか否かの判断材料
- visionづくり
- 概要levelのproduct_backlogの作成
- product_loadmapの定義
- visionと概要levelのproduct_backlogが完成したら,最初のproduct_loadmapの作成に進める
- product_loadmap: 一連のreleaseでproduct visionのどの部分を達成していくか示す
- incremental deploymentについて,当初の概要を示す
- 1回のreleaseの規模を小さくして,releaseをより頻繁に行う
- 小さめのrelease 1度で済んでしまうような計画なら不要
- 頻繁なrelease: 個々のreleaseをrelease可能な最小限のfeature(MRF)単位にまとめる
- MRFの補完として,定期的なrelease(四半期ごとなど)を採用するのも〇
- product_loadmapがsimple
- わかりやすい
- 内外を含めた関係者全員へreleaseの周知がしやすい
- 組織のreleaseを事前の予測通りに活用できる
- ほかのgroupもその組織の計画に合わせて動きやすくなる
- MRFの開発がrelease間隔より短く済む場合は,さらに追加で価値の高いfeatureを作る
- release goalの明示
- releaseの目的と期待される成果を示す
- solutionのreleaseの内容を決める助けとなるあらゆる要素を考慮
- target client
- 各segmentのclientに対していつどのように対応するか示す
- 概要levelのarchitectureや技術面の課題
- 市場の重要eventなど
- target client
- 大雑把な予想に過ぎない
- 詳細な情報が分かり次第loadmapを更新する
- どの程度の将来までカバーするか
- 大規模なvisionでも,理にかなった必要な分だけのloadmapを作る
- 誰かに出資をお願いする期間はカバー必要
- その他のactivity
- 信頼の閾値を満たすために関係があると参加者が認めた作業なら,どんな作業を含めてもよい
- e.g. 市場調査,競合productとの比較分析,大雑把なbusiness modelを作成して経済的filterと照合
- envisioningを複数のsprintに分けて行うときには,担当teamがenvisioning関連の作業のbacklogを管理する
- 優先順位を決めて,短期間(1週間程度)のsprintを回す
- 知識を得るためのsprintもある
- 信頼の閾値を満たすために関係があると参加者が認めた作業なら,どんな作業を含めてもよい
- 経済的に理にかなったenvisioning
- envisioning系の作業は,project charteringやproject inception, or project initiationと呼ぶこともある
- このprocessを,総合的なstage gate型管理modelの一部として組み込んでいる組織もある
- 重厚で儀式的なprocessになってはいけない
- このprocessを,総合的なstage gate型管理modelの一部として組み込んでいる組織もある
- できるだけsimple
- productの性質や規模,risk levelに基づいて,必要最小限の事前planning,そして知識獲得のための作業を行うのみ
- 詳細な作成物はjust_in_time
- goal: 現時点での最良な判断をするのに十分なだけの情報を,資金や期間を考慮して得ること
- 指針
- 現実的な信頼の閾値を目指す
- 注目するのは短期間だけ
- 1度にやり過ぎず,主に,直近のreleaseで必須となるfeatureに注目する
- すばやく動く
- envisioningは手早く効率的に済ませる
- → できあがるのが早まり,検証できる
- → delay_costを小さくできる
- 緊迫感をもってproductについての判断を下せるようになる
- 適切なresourceを割り当てて,envisioningを適切なtimingで終えられるようにする助けとなる
- 方法
- envisioningの完了予定日をenvisioning teamに知らせておく
- envisioningは手早く効率的に済ませる
- 検証による学びに投資する
- envisioningのactivityを経済面で評価するときの基準
- 対象とするclient, feature, and solutionについての検証による学びを得るためにどの程度役立ったのか
- envisioningのactivityを経済面で評価するときの基準
- incrementalに出資する
- 出資にかんする判断は,より正確な情報がそろうのに合わせて常に行う
- envisioningに要する時間も短縮できる
- 早めに学んでpivotする(fail_first)
- 責任をもって効率的にresourceを管理し,手早く格安にenvisioningを行う
- 資金負担を大きく減らすことができる
- envisioning系の作業は,project charteringやproject inception, or project initiationと呼ぶこともある
- まとめ
Ch18 release_planning(長期計画)
- release_planningでは,scope, schedule, budgetといった制約の下で,clientにもたらす価値と全体的な品質とのbalanceを取らなければならない
- release_planningをどのようにScrum frameworkに組み込むのか,固定期日と固定scopeのそれぞれのreleaseで,release_planningをどのように行うか見る
- 概要
- featureをclientに届けるためのreleaseの周期を適切に定める必要
- continuous deployment(delivery): sprintの終わりを待たず1つのfeatureが完成するたびにrelease
- どの周期でも,ある程度の長期間にわたる概要levelの計画(release_planning)を作っておくと便利
- a.c.a. 長期的planning, milestone駆動planning
- 狙い: 重要な変動要因(期日,scope,予算など)のbalanceを取ったうえで,将来の状態を定める
- timing
- sprintごと
- envisioningやproduct_planningのあと
- product_planningの目的: productがどうあるべきか思い描く
- ←→ release_planningの目的: そのproductのgoalに向けて,次の一歩を定める
- 初回releaseの前に最初のrelease_planningを行い,release planを作成する
- 通常は1日から2日程度だが,productの規模やreleaseのrisk,参加者のproductへのなじみによって変わる
- 完全でなくてよい
- 検証による学びをもとに更新する
- sprint review中でも次のsprintの準備のときでもよい
- 参加者
- stakeholderとScrum_team全体が,互いに協力し合って行う
- businessと技術のtradeoffを考慮して,もたらす価値と品質の間で最適なbalanceが必要なため
- process
- input
- product_planningのoutput: product visionや概要levelのproduct_backlog, product_loadmap
- releaseにかかわるであろうteamのvelocity
- 繰り返すactivity
- releaseの制約であるscope, 期日, budgetを確認し,これまでの流れやわかってきたことから,制約を変更する必要があるかどうか見直す
- product_backlogのgrooming
- 概要levelのproduct_backlogをもとに,より詳細なproduct_backlog_itemを作ったり,見積もったり,優先順位をつけたりする作業
- timing
- product_planningを終えてから,最初のrelease_planningに入る前
- 最初のrelease_planningの一環として
- 各sprint中で,必要に応じて
- envisioningで定義された明確に定義されたrelease可能な最小限のfeature(MRF)を,常に見直す
- client視点で,実現最小限の製品になっていることを確かめる
- sprint mapを作ることも多い
- 各product_backlog_itemがどのsprintで作られるか示す
- 直近の範囲の可視化
- → team内の依存関係やresource配分を管理しやすくなる.複数のteamでの共同作業の調整にも役立つ
- release_planningのoutputをひとまとめにしてrelease planと呼ぶ
- どの時点までに判断できる妥当なlevelの正確さでの計画を表す
- 開発作業がどれくらい残っているか,いつごろ終わるか,どのfeatureができあがるか,costがどの程度かかわるかなどを含む
- そのreleaseで求められるMRFを明確化
- releaseのための各sprintで対象となるproduct_backlog_itemをどのように扱うのか示すことも多い
- どの時点までに判断できる妥当なlevelの正確さでの計画を表す
- input
- release制約
- release_planningの目的: 次のreleaseで最も重要なものが何なのか,そしてそれをどの程度の品質で用意するのかを定める
- scope, 期日, 予算といった制約は重要な変動要因であり,どうやって目標を達成するかに大きく影響する
- product_planningにもとづいて,いくつかの制約が生じる
- 各制約の固定/可変の組み合わせ
- すべて固定
- 現実的でない
- scopeと期日を固定
- 多くの問題があり,厳しすぎる
- 固定したものはいずれもかなり予測しづらい
- いずれかは犠牲になる
- resourceを投入すればするほど多くの作業をこなせ,作業の所要時間も短縮できるという想定だが,現実的でない
- 実現できないか,持続可能なpaceに反するか
- Scrumのiterative and incrementalなapproachを使うことで,何か問題が発生しても早めに気づけるようになる
- scopeを固定
- 実際問題として,scopeのほうが期日より重要な場合
- 全体的なscopeがあまりにも大きすぎる場合
- より小さ目なreleaseに分割して,それぞれを期日で固定した方がよい
- 期日を固定
- Scrumの原則に最もあてはまる
- timeboxingを重視するScrumにぴったり
- 優先度の高いfeatureから作るという原則に従うことで痛みを軽減できる
- 優先度の高いfeatureが本当に(合意済みの完成の定義にもとづいて)完成している場合だけ
- MRFを小さめに定義できるとき
- Scrumの原則に最もあてはまる
- 品質を可変に
- 制約が厳しすぎる場合
- 期待に添わないsolution, 技術的負債の発生
- 制約の見直し
- 現時点でわかっていることから,制約のbalanceを見直すべきかどうか見極めることが,release_planningにおいて重要
- 継続的に判断する
- すべて固定
- product_backlogのgrooming
- 概要levelのproduct_backlog_itemを,user_story 記述workshopなどで,より詳細なlevelに踏み込んだproduct_backlog_itemにする
- → teamで見積もって,どの程度costがかかるかを判断できるようになる
- → releaseのgoalと制約に基づいて,各storyの優先順位を判断
- MRFがrelease_planningの参加者間で常に合意の取れた状態である必要
- release可能な最小限のfeature(MRF,Minimum Releasable Feature)の見直し
- sprint_mapping
- 直近のsprintについて,product_backlog_itemを事前にmappingしてみるのが有用
- 複数のteamで作業を進めている環境で,協調が上手くいくようになる
- 移動する先読み範囲: 直近のsprintと少なくともその後数sprintで必要なproduct_backlog_itemを検討する
- team間の依存関係が扱いやすくなる
- 複数のteamで作業を進めている環境で,協調が上手くいくようになる
- ある程度詳細なlevelまで落とし込み,見積もりが終わって,優先順位のついたproduct_backlogが必要
- teamのvelocityを使って,product_backlog_itemをsprint単位に適切に割り当てられる
- 一般的なschedule表にsprint_mapを並べることもある
- 単一のScrum_teamのdevelopmentでは,mappingは最初のrelease_planningで行う
- そのsprintで各teamがどのfeatureを担当するかを最終的に決断するのは,最終責任時点,sprint_planningのとき
- product_backlog_itemとsprintのmappingをほとんど/全くしないこともある
- 直近のsprintについて,product_backlog_itemを事前にmappingしてみるのが有用
- 固定期日のrelease_planning
- release_planningの手順
- このreleaseでsprintを何回実行するか決める
- product_backlogを適切な詳細度までgroomingする(backlog itemを細かくしたり,sizeを見積もったり,優先順位を決めたりする)
- MRFを構成するfeatureは,与えられた時間の60~70%で完成できるようにしたい
- teamのvelocityの範囲を計測する
- 最も遅い場合のvelocityとsprintの数を掛ける.product_backlogの先頭からその結果分だけのitemを数え,そこに線を引く
- 最も早い場合のvelocityとsprintの数を掛ける.product_backlogの先頭からその結果分だけのitemを数え,そこに2番目の線を引く
- release日までにどのfeatureができあがるかという問いの答えがある程度分かる
- release_planどおりに進んでいるか判断するためには,必須featureを表す線をproduct_backlogの上に重ねてみるだけでよい
- sprintが終わるごとにrelease_planを見直す
- release_planningの手順
- 固定scopeのrelease_planning
- 実際には期日よりもscopeの方がずっと重要という場合
- 本当の意味でのMRFを厳選し,徐々に増やしていくようにする
- → 固定scopeのreleaseもいくつかの固定期日のreleaseに分割できる
- どうしても期日が最大の制約の場合の流れ
- 少なくとも今回releaseしようとしているproduct_backlog_itemを含むよう,product_backlogをgrooming(新たなitemを作ったり,sizeを見積もったり,優先順位を決めたりする)
- このreleaseでdeliveryするproduct_backlog_itemの合計サイズを決定する
- team velocityの範囲を計測する
- product_backlog_itemの合計サイズを最も早い場合のvelocityで割り,端数を切り上げる
- product_backlog_itemの合計サイズを最も遅い場合のvelocityで割り,端数を切り上げる
- costの算出
- 手順
- team_memberを決める
- sprintの長さを決める
- team 構成とsprintの長さに基づいて,sprintあたりの人件費を算出する
- 固定期日のreleaseの場合は,sprintあたりのcostとsprint数を掛ける
- 固定scopeのreleaseの場合は,sprintあたりのcostと最大sprint数,最小sprint数をそれぞれ掛ける
- story_pointあたりのcostを把握しておけば,story_pointさえ求められればcostが分かるという別の方法がとれる
- 手順
- communication
- 固定scopeのreleaseにおける進捗の把握
- 完了させない作業のscopeが分かっている
- その作業の完了に向けて,今どの程度の進捗なのかを把握することが目標
- burn_down_chart: 現在のrelease goalに達するまでの残作業の累計を,sprint単位で示したもの
- y: 残story_pointの見積もり, x: release内のsprint
- burn_up_chart: releaseにおける作業の総量をgoalとして示し,sprint単位でそのgoalに近づいていく様子を示した図
- 軸はburn_down_chartと同じ
- 好まれる理由: release内でのscopeの変更を表しやすいから
- 固定期日のreleaseにおける進捗の把握
- releaseにおけるsprintの回数が分かっている
- sprintごとの進捗を見ながら,最終的にどの程度のfeatureを完了させられそうなのか(deliveryできるscopeの範囲)を把握する
- product_backlogの並び順を反転して,burn_up_chartを作成する
- 目標とするfeatureの範囲に到達するまでの進捗の把握
- 必須featureの完成までの進捗も確認できる
- 固定scopeのreleaseにおける進捗の把握
- まとめ
- release_planningについて
- いつ,だれが,どんなことをするのか,最終的にどんなrelease_planができあがるのか
- 固定期日/scopeそれぞれの場合でのrelease_planningの方法と,進捗を把握する方法について
- release_planningについて
Part 4 sprint
Ch19 sprint_planning
- releaseは1つ以上のsprintで構成
- 各sprintでは,user/clientに価値を提供する
- sprintはsprint_planningから始まる
- Scrum_teamが集まって,sprint_goalに合意し,sprintで何をdeliveryできるかを決定
- Scrum frameworkにおけるsprint_planningの位置づけと実施方法について
- 概要
- sprintで構築する最も重要なproduct_backlog_itemを決定するために実施する
- sprint_goalについて合意する
- sprint_goalに合致しており,sprint終了までに現実的にdeliveryできるproduct_backlog_itemを決定する
- 決定したitemをきちんとdeliveryできる自信を持つために,product_backlog_itemを完成させるための計画が必要
- 選択したproduct_backlog_itemと計画を合わせたものが,sprint_backlogになる
- timing
- 継続的なjust_in_time activity
- sprint開始時に実施する
- 2週間から1か月のsprintの場合,sprint_planningに4~8時間かける
- 参加者
- Scrum_team全員
- product_owner: 最初のsprint_goalを共有して,product_backlogの優先順位を示し,product_backlog_itemに対するteamの疑問に答える
- development_team: sprintで何をdeliveryできるか決定し,現実的なcommitment
- Scrum_master: Scrum_teamのcoachとしてplanning activityを観察し,内省を促す質問をして,確実に良い成果が得られるよう支援する
- 何を作るか代わりに決められはしない
- teamのcommitmentに問題を提起して,現実的で適切なcommitmentができるようにする
- process
- input
- product_backlog
- 最も重要
- 準備完了の定義に合うように,sprint_planningよりも前にgrooming
- 準備完了の定義: 受け入れ条件が定義済みで,適切なsizeで,見積もりが終わっていて,優先順位がつけられている
- team velocity
- 現実的な判断のため(以下2つも同じ)
- 制約
- team capacity
- initial sprint_goal
- development_teamのcommitmentが現実的なものになるため
- teamは優先順位のbalanceが取れる
- product_backlog
- sprint_goalを達成するための計画を作る
- sprint_backlog
- product_backlog_itemを見積もり可能なtaskに分解
- 1つのtaskは8時間以内
- product_backlog_itemを見積もり可能なtaskに分解
- sprint_backlog
- sprint_planningが終わると,development_teamのcommitmentが最終的なsprint_goal, sprint_backlogとなって伝えられる
- input
- sprint_planningの手法
- 二部構成のsprint_planning
- what part
- development_team capacityを決定し,sprint終了時にdeliveryできるproduct_backlog_itemを予想する
- how part
- product_backlog_itemをtaskに分解して,task完了に必要な工数を見積もり,計画を立てる
- 見積もったtaskの時間とcapacityを比較して,最初のcommitmentが現実的かどうか確認
- 予想がcapacityの範囲や制約に収まれば,commitmentを最終決定して,sprint_planningを終了する
- what part
- 一部構成のsprint_planning
- itemの選択とそのための自信の獲得を交互に行う
- まず,development_teamがcapacityを決定する
- 次に, product_backlog_itemを選択して,それがsprintに収まるという自信を持つ
- これをteamのcapacityの上限に達するまで続ける
- 最後にcommitmentを最終決定して,sprint_planningを終了する
- 二部構成のsprint_planning
- capacityの決定
- sprint_planningの最初の重要なactivity
- what's capacity
- 影響を与える要因
- sprint以外のactivityに必要な時間
- sprint以外のcommitment
- 個人的な休暇
- 必要なbuffer
- 経験的に決定
- capacity
- 単位
- product_backlog_itemに使う単位(story_point or 理想日)
- team velocity
- teamのこれまでの平均velocityや前回のsprintのvelocityを参考にする
- そして今回のsprintとの違いを考慮する
- → 予測したvelocity
- team velocity
- or sprint_backlog_taskに使う単位(作業時間)
- まず,team_memberが次のsprintで何日作業できるかを表明する
- 次に,sprint以外のactivityにかかる日数を決定
- team_memberの1日の作業時間を決定
- product_backlog_itemに使う単位(story_point or 理想日)
- 単位
- 影響を与える要因
- product_backlog_itemの選択
- sprint_goalがあれば,それに合わせてproduct_backlog_itemを選択する
- なければ,product_backlogの優先順位の高いほうから順番にitemを選択する
- skillの問題などでitemにcommitできないときは,優先順位がその次に高くて実現できそうなproduct_backlog_itemを選択する
- 完成できそうにない場合は,clientにとって価値のある小さなitemに分割するか,完成できそうな別のitemに着手する
- 準備完了の定義を用意しておくことで,定義・resourceが不十分だったり,依存関係が未解決のproduct_backlog_itemを選択して,sprintで完成できなくなることを回避できる
- 「完成できそうなものだけを開始する」
- WIPの制限や未完成作業のムダの原則に基づく
- 出荷判断可能なproduct incrementがsprint終了時に必要
- WIPの制限や未完成作業のムダの原則に基づく
- 自信の獲得
- velocityを予測
- commitmentが現実的かどうか確認
- ただし,実際はtask levelにするまで分からない
- → さらに,product_backlog_itemをtaskに分解することで自信を獲得する
- taskは見積もり可能で,team capacityを考慮して決定
- 一種の設計で,itemを完成させるためのjust_in_timeの計画
- 分解した結果がsprint_backlog
- それぞれのskillを把握しておかないと,正しいcommitmentができない
- ただし,個人へのtask assignは×
- taskは見積もり可能で,team capacityを考慮して決定
- velocityを予測
- sprint_goalの洗練
- sprint_goal: sprintでのbusinessの目的と価値をまとめたもの
- commitmentの最終決定
- sprint_planningが終了するまでに,development_teamはsprintでdeliveryするbusiness valueにcommit
- sprint_goalと選択したproduct_backlog_itemは,commitmentを具現化したもの
- 予想/commitment
- ニュアンスの違いは,development_teamが何をdeliveryするかのscopeと,Scrum_teamがsprintの実施中に手に入れた新しい情報への対応に影響する程度
- まとめ
- sprint_planningをいつ実施するか,誰が参加するか
- 2つの手法
- teamがproduct_backlog_itemを選択して,それらをすべてdeliveryできるという自信を獲得
- product_backlog_itemの選択と自信の獲得を交互に行い,少しずつcommitmentに追加する
- development_team capacityを決定するための2手法
Ch20 sprintの実施
- Scrum_teamがsprint_goalを達成するための作業
- sprintの実施において,Scrum_teamが計画,管理,実行,伝達するためのprinciple, technique
- 概要
- sprintの実施は,それ自体が1つのmini projectのようなもの
- 出荷判断可能なproduct incrementをdeliveryするために必要な作業をすべて行う
- timing
- sprint_planningが終わった後に始めて,終了したらsprint review
- 8割程度はsprintの実施が占める
- 参加者
- development_teamのmemberが自己組織化して,sprint_planningで設定したgoalを達成する最善の方法を決定
- Scrum_masterは,あらゆる支援
- product_ownerは,質問に答えたり,feedback, sprint_goalを調整,product_backlog_itemが満たすべき受け入れ条件を検証
- process
- input
- sprint_planningで作ったsprint_goalとsprint_backlog
- output
- 出荷判断可能なproduct_increment
- 開発が終わったproduct_backlog_itemの集まり
- Scrum_teamの完成の定義に従う
- 開発が終わったproduct_backlog_itemの集まり
- 出荷判断可能なproduct_increment
- 実施
- testされた動作する機能に必要な計画,管理,実行,伝達
- input
- sprintの実施は,それ自体が1つのmini projectのようなもの
- sprint_planning
- 万全な計画にはしない
- taskに依存関係があるときは,事前の計画が有用なこともある
- sprintの実施の原則: 事前に完璧な作業計画を立てるのではなく,状況に応じてtask levelの計画を立てる
- teamで継続的にtask planningをすることで,sprintを取り巻く環境の変化に適応できる
- flow management
- teamの責任
- どれだけの作業を並行でやるべきか,特定のitemにいつ着手すればよいか,task levelの作業をどのように構成するか,何の作業をすべきか,誰が作業すべきか,を決める
- 並列作業とswarming(群がる)
- 単純なmulti taskでもoverheadは極めて高い
- 並列作業が少なすぎてもムダ
- swarming
- 適切なbalanceのために,team_memberのT型skillやcapacityを活用できるだけのitem数に絞って作業する
- deliveryするvalueを最大化しながらも,各itemの作業時間を短縮
- 新しいitemに着手する前にcapacityあるteam_memberが集まって,すでに誰かが着手したitemを完成させる
- taskではなくgoalに集中し,より多くより早く作業が終わる
- 同時に作業するitemの数を極力減らすべき
- 複数のitemが適切な場合もあるので,必ずしも1つではない
- 適切なbalanceのために,team_memberのT型skillやcapacityを活用できるだけのitem数に絞って作業する
- mini waterfallのようになるのは×
- 同時にすべてのproduct_backlog_itemに着手することになるため
- → riskが非常に高い
- どの作業から着手すべきか
- itemの優先順位をproduct_ownerが決定
- 技術的な依存関係やskill capacityの制約がitemの順番に影響を及ぼすため,常には上手くいかない
- → development_teamは,itemを適時適切な順番で選択する能力が必要
- itemの優先順位をproduct_ownerが決定
- どのようにtaskを計画すべきか
- 作業に論理的な順番はない
- test first development
- 適時team_memberがtaskや担当をうまく構成する
- → 作業の手待ちを最小化し,team_memberがほかのmemberに手渡す作業の量や回数を減らせる
- → すばやいfeedback, 課題の発見と解決が迅速に実施できる
- どの作業を完了させるべきか
- team_memberが決定
- 経済的に合理的な方法でinnovative solutionを作るための権限を与える必要
- product_owner, managerは,どのtaskを完了させるべきかに影響を与えるinputを持っている
- product_ownerが機能のscopeと受け入れ条件を確定する.いずれもtask levelの作業の境界線となる
- 完成の定義に必要なbusiness 要件を提供する
- product_ownerは,businessに重大な結果をもたらす技術的判断が経済的合理性をもって行われるように考慮しながら,teamと一緒に作業する
- 決定の中には,完成の定義の技術的な側面に組み込まれているものもある
- そのほかの決定は,機能に特化したもの
- development_teamはproduct_ownerと一緒にtradeoffを行い,経済的に合理的な決定をすることが望まれる
- team_memberが決定
- 誰が作業をするのか
- 作業をすばやく正しくできる人が最適
- 様々な要因が影響する
- team_memberの共同責任
- T型skillで,より効率的なteamになる
- daily_Scrum
- team activityを高速にして,solutionまでの流れを柔軟にする,毎日の検査と適応のactivity
- 24時間ごとに15分のtimebox
- 自己組織化teamが仕事をより良くするために,検査とsyncを行う適応型planning activity
- goal: sprint_goalの達成に集中している人たちが集まって,何が起きているかの全体像を共有し,どれだけの作業をしているか,どのitemに着手したか,team_memberの最適な作業配分についてみんなで理解すること
- 待ち時間の回避にもなる
- flowの管理に欠かせない存在
- taskの実行(technical_practice)
- 短期間のtimeboxというiterationで作業する → 出荷判断可能なproduct incrementを届けることを期待されている
- 技術的負債を制御して仕事をやりきるというpressureがteamにかかる
- → 適切な技術的skillを持っていなければ,長期にわたって継続的にbusiness valueを届けるために必要なagilityのlevelを達成できない可能性がある
- Scrumを使う場合は,software developmentのtechnical_practice_skillが必要になる
- TDD, refactoring, simple design, pair programming, CI, codeの共同所有, coding standard, metaphor
- called as XP
- TDD, refactoring, simple design, pair programming, CI, codeの共同所有, coding standard, metaphor
- 長期的なScrumの利点のためには,task levelの作業に,強力なtechnical_practiceが必要
- 短期間のtimeboxというiterationで作業する → 出荷判断可能なproduct incrementを届けることを期待されている
- communication
- information radiator(radiate: 放射 ← 光を放つ)
- task_board, burn_up_chart, burn_down_chartの組み合わせ
- task_board
- sprintの進捗が一目で伝わる簡単だが強力な手法
- sprint_backlogの変化の状態を伝える (→ 図20.6)
- sprint_backlog_itemが複数のtaskで表現
- すべてのtaskはTO DOから
- → 進行中
- → 完了
- カンバンではより詳細なboard
- sprint burn_down_chart
- product_backlog_itemのtaskは,いつでもsprint_backlogに追加できる
- y: 見積り残作業時間, x: sprint日数
- 進捗管理に使える
- 傾向線を書くことで,sprintのflowを管理するための知識となる重要なdataを得られる
- 常に残りの見積もり時間を使用する.実際にかかった作業時間は不要.
- sprint burn_up_chart
- sprintの進捗を可視化
- 完了した作業の量を表す
- y: story_point, or 作業時間, x: sprint日数
- ほとんどはstory_point
- ↑ business valueのための成果に注目するため
- 作業の流れが滞っていないか,teamがどのようにproduct_backlog_itemを完成させているかの感覚がつかめる
- ほとんどはstory_point
- sprintの進捗を可視化
- information radiator(radiate: 放射 ← 光を放つ)
- まとめ
- sprintの実施について
- sprintの大部分を占めるもの
- who, what, whenの計画に従うものではない
- teamのskillを活用して,完了した作業やsprintの予期せぬ環境の変化からfeedbackを受け取る
- flow management principleに従う
- 並行していくつの作業をするか,何の作業に着手するか,作業をどのように構成するか,誰が作業をするか,作業にどの程度の時間をかけるか,を決める
- daily_Scrum meetingはflow managementのimportant activity
- technical_practice's importance for high level agility
- sprintの進捗を視覚的に伝える
- task_board, sprint burn_down_chart, sprint burn_up_chart
- sprintの実施について
Ch21 sprint_review
- productに集中したもの
- 目的,参加者,事前準備,問題について
- 概要
- 作業結果(出荷判断可能なproduct_increment)の検査と適応をする.
- sprint終了間際に実施する
- product developmentのinputにかかわった人に対して,これまでに構築したものについて検査と適応をする機会を提供する
- 質問,観察,提案したり,現状を考慮して今後の方針について議論する
- 正しいproductを開発中だと組織が確信できるようになる
- → 最も重要な学習loopの1つ
- sprintの期間は短いので高速
- → 頻繁に軌道修正〇
- → 最も重要な学習loopの1つ
- 参加者
- sprint_reviewは,Scrum_teamに対して,sprintの実施に毎日参加できないような人たちからのfeedbackを得る重要な機会を提供
- sprintで作成された成果について議論する最初の機会
- すべての利害関係者が参加すべき
- Scrum_team
- 内部stakeholder
- business area owner(developing systemの発注者), exective management, resource担当managerなど
- → teamが経済的に合理性のある成果に向かっているか確認
- 内部userがいる場合は内部userからのfeedbackも有益
- そのほかの内部stakeholder
- 営業,marketingから,productが市場で成功するかどうかの有益なfeedbackを得る
- support, 法務部は,teamの進捗の把握や,timelyなinputを提供したり,自分たちの仕事をいつ開始すればよいか判断するために,参加することもある
- ほかのdevelopment_teamの代表者も〇
- 外部stakeholder
- client, user
- direct feedback
- 内部の議論で済むなら,必要はないかもしれない
- 常識,熱意,人格を考慮して招待する対象を検討
- client, user
- すべての利害関係者が参加すべき
- 事前準備
- 誰を招待するのか決める
- 適切な人たちを集める
- schedule調整
- Scrum_team以外の参加者が多いので,調整が難しい
- important stakeholderが希望するscheduleを聞いてから,そのほかのactivityをその時間の前後に設定する
- sprintの期間は固定されているので,ほぼすべてのsprint_reviewのscheduleが決まる
- 長さ
- sprintの期間,teamの規模,reviewに参加するteam数など複数の要因で決まる
- 4時間のtimeboxを超えない
- sprint 1週間につき1時間
- sprintの成果が完成したことを確認
- 利用可能になったproduct_backlog_itemを,product_ownerがjust_in_timeでreview
- demoを準備
- goal: productの検査と適応のために透明性を提供すること
- 儀式を少なく,価値を高く
- sprint 1週間につき30分から1時間をsprint_reviewの準備に使う
- 誰が何をするかを決める
- facilitator, demoを誰がするか,Scrum_teamが決定
- 誰を招待するのか決める
- approach
- input
- sprint_backlog, sprint_goal, teamが作成した出荷判断可能なproduct_increment
- output
- groomingしたproduct_backlogと更新したrelease_plan
- sprint_goalの何を達成して何を達成していないかの概要を示し,出荷判断可能なproduct_incrementのdemoをして,productの現状について議論し,今後のproductの方向性を適応させる
- 概要
- sprint_goal, sprint_goalに関連したproduct_backlog_item, sprintで実際に開発したproduct_incrementの概要をScrum_teamのmemberが伝えるところから始まる(product_ownerが担当することが多い)
- sprintの成果とsprint_goalを比較したときの結果が分かる
- 不一致なら,説明
- 責任追及,非難はしない
- 何が達成できたかをもとに,今後取るべき行動を決定する
- 不一致なら,説明
- demo
- sprint_reviewの目的はdemoではない
- 最も重要な側面は,参加者たちの徹底した対話や協力
- → 生産的な適応を可能にし,有効活用する
- demoは,対話をより具体的にするための効率の良い方法
- 準備完了の定義に,Scrum_teamがdemo方法を理解することも含まれる
- product_ownerの要求を満たしていることをdemoするテストが必要
- sprint_reviewでは,テストを使ってdemoできる
- sprint_reviewの目的はdemoではない
- 議論
- product_incrementのdemoは会話の中心になる
- productや今後の方向性に関する意見,コメント,妥当な議論が,参加者に強く求められる
- sprint_reviewは問題解決の場ではない
- Scrum memberが,client/userを喜ばせるためのfeedbackを得ることで,productのbusiness, marketingの認識を深める
- 適応
- question
- stakeholderは見たものを気に入っているか
- 変更点を見たいと思っているか
- 今でも市場やclientに受け入れられるのか
- 重要な機能が不足していないか
- 不必要なところに機能を作りこみすぎたり,costをかけすぎていないか
- → product_backlogやrelease_planの適応のinputになる
- grooming @sprint_review
- より大きなscopeのrelease_planにも影響する
- 変動要因に影響
- scopeの変更など
- 変動要因に影響
- より大きなscopeのrelease_planにも影響する
- sprint終了ごとに,適応の方法,変化の反応方法,それらを実施できる時期を見つけるための機会を提供する
- question
- input
- sprint_reviewのproblem
- signoff
- 正式な認可やsignoffのeventではない
- 事前にproduct_ownerが承認済み
- product_ownerがproduct leadershipの権限を持つため,承認は決定事項
- 要求があれば新しいproduct_backlog_itemを作成し,機能変更の予定を立てるのが〇
- なぜ要求を出した人がstakeholderから外れていたか調査し,今後は調整する
- 正式な認可やsignoffのeventではない
- 参加者の不在
- 数週間で価値のあるものを作り出せると思われていないため
- 解決方法: business valueのある出荷判断可能なproduct_incrementをsprintごとに開発する
- → 頻度の高いreviewに参加する価値を理解してもらえる
- 大規模project
- sprint_reviewの共同実施
- merit
- stakeholderはsprint_reviewに1回だけ参加すればよい
- 成果が統合できれば,個別のincrementではなく統合した結果をreviewすればよい
- すべてのteamが完成の定義に統合test要
- demerit
- 時間がかかる
- 大きな部屋が必要
- merit
- sprint_reviewの共同実施
- signoff
- まとめ
- sprint_reviewの目的であるScrum developmentのfeedbackについて
- 参加者のgoalは,現状のproductの検査と適応
- 非公式なactivityだが,最小限の事前準備をする
- Scrum_teamは,reviewの概要とsprintで達成したことを説明する
- product_incrementのdemoをする
- 質問,意見,提案が歓迎される
- grooming, release_planの更新を行う
Ch22 sprint_retrospective
- productを構築するのに使ったprocessを,Scrum_teamが調査する
- 目的,参加者の概要,事前準備,主要なactivityを見る
- 最も重要なのは,参加者が発見した改善をsprint_retrospectiveの後に継続的に行うこと
- 概要
- 考える機会を与えるもの
- teamは何が起きているのかを調査したり,自分たちの仕事のやり方を分析したり,改善の方法を見つけたり,改善の計画を立てたりする
- teamのproductの作り方に影響を与えるものであれば,なんでも自由に調査・議論できる
- e.g. process, practice, communication, 環境, 作成物, tool
- 最も重要で,最も使用されているpractice
- teamが自分たちの環境に合わせてScrumをcustomizeできる機会を提供するため
- しかし「実際の」作業ではないので過少評価されている
- Scrumが提供する継続的改善に不可欠
- sprintごとにretrospectiveを行い,insightやdataを見失うことなく活用できる
- 早期にincrementalな学習ができる
- → projectの成果に大きな影響
- theme
- sprintでうまくいったので,今後も続けたいこと
- sprintでうまくいかなかったので,今後は中止したいこと
- これからやった方がよいこと,改善した方がよいこと
- → 行動可能な変更点を決定,incrementalに改善したprocessで次のsprintに取り組む
- 考える機会を与えるもの
- 参加者
- Scrum_team全員
- team memberの多様な視点で,さまざまな観点からprocessの改善点を見つけられる
- Scrum_master: processに欠かせないRole,processの権威
- teamが合意したprocessで守られていない点を指摘
- teamにとって重要な知識やideaの源泉となる
- product_ownerとteamの信頼関係をScrum_masterがcoachingして築くまでは,product_ownerは参加できない
- 信頼と安全が確保できれば,product_ownerは欠かせない
- 高速で柔軟性の高いbusiness valueのflowの達成のため
- 要求のflowをteamに伝えるchannelやrouteなどのRoleを担う
- stakeholder, managerなどは,招待されたときだけ
- 参加は安全性の問題がないときだけ
- Scrum_team全員
- 事前準備
- sprintの期間が短かったり,実践的で簡潔なretrospectiveのformatを使っていれば,事前準備には必ずしも時間はかけなくていい
- focusを定義
- default: Scrum_teamが使用したprocessの関連する側面をすべてreviewする
- 現状のteamの重要性や改善点に合わせて,別のfocusの選択も〇
- e.g.
- TDD skill up方法にfocus
- 要求の誤解の頻発の理由にfocus
- e.g.
- 開始前にfocusが分かることの効果
- Scrum_team以外の人たちを招待するかどうか決定できる
- 適切なexerciseを選択できる
- retrospectiveを円滑にするために必要なdataの収集や準備に時間をかけられる
- 具体的に定義 → retrospectiveから計測可能な価値を抽出〇
- → 持続可能なhigh performance Scrum_teamになる
- exerciseを選択する
- 協力して考え,探索し,意思決定するためのもの
- 通常のexercise
- event timelineの作成と発掘
- insightのbrainstorming
- insightのgroupingと投票
- focusや参加者に合わせて変更可能
- 新鮮さのために新しいexerciseを試すのも〇
- 事前準備で決める必要はない, just_in_timeで決定〇
- data, 備品が必要なexerciseは,事前準備で決めておく
- 準備しながら,柔軟性は確保
- 客観的dataを収集する
- data収集に必要な作業は,retrospectiveの開始前に済ませておく
- 客観的data: 確実なdata(not 意見)
- e.g. どのようなeventがいつ起きたか,着手したが完成しなかったproduct_backlog_itemの個数,完了した作業のflowを示したsprint burn_up_chartなど
- この段階では,dataの構造化や分析は行わない
- retrospectiveを構成する
- sprint_reviewと場所や時間を合わせるかどうか,参加者やexerciseの都合などから考えておく
- 正確な時間は,team人数,年数,memberがremoteにいるかどうかなどの要因の影響を受ける
- sprintの期間に合わせて時間を決定する
- 2週間のsprintなら1.5時間をretrospectiveに割り当てる
- sprintの期間に合わせて時間を決定する
- 成功に最適な場所
- 情報にaccessしやすい仕事場
- 安全な環境のために仕事場以外
- facilitatorは,Scrum_masterがやることが多いが,誰でもよい
- 中立性のため外部から招くこともある
- approach
- input
- 合意したfocusなど,retrospectiveで使用するとteamで決めたものならどんなexerciseや道具でもいい
- 事前に収集した客観的data
- 参加者は,sprintについての主観的なdataを持参する
- 前回retrospectiveで作成したinsight backlog
- output
- 次のsprintで行う具体的な改善action
- 今回retrospectiveで作成したinsight backlog
- 仲間意識の向上
- theme
- sprintでうまくいったので,今後も続けたいこと
- sprintでうまくいかなかったので,今後は中止したいこと
- これからやった方がよいこと,改善した方がよいこと
- 有効なapproach
- retrospectiveの雰囲気づくり
- team/個人を徹底検証するのは不愉快な経験なので,心地よくなってもらうための雰囲気づくりが必要
- 報復を恐れずに自分の意見を言えるような,安全性を感じてもらう
- rule設定/取り決め
- 自分の意見や内輪の恥をさらしても安全であることを明確にする
- 間違いを探しても安全だとわかるように,個人ではなく組織のsystemやprocessにfocusしていることを明確にするruleを設定しておく
- 問題が人の問題であることもあるが,retrospectiveは問題解決の場ではない
- 責任の所在を明らかにしたり,個人の振る舞いを非難したりする場ではなく,Scrum_teamのprocessを改善する場
- 非難のない環境を作るためのruleであることを明確にしておく
- rule設定/取り決め
- 積極的な参加の前例を作る
- 参加者に口を開いてもらう
- 今の感情やenergy levelを一言で表現してもらうteamもある
- 内容より,何かを言うことで,話そうという雰囲気を作る
- 参加者に口を開いてもらう
- 参加者によるcontextの共有
- → 客観的に大局的にsprintを見ることができるようになる
- 多様性のある個人の視点をteamの視点に統一
- sprintのevent, 達成, 欠点に対する大局的な考えに基づくようにする
- × 個人的な経験
- → ただの意見の言い合いになる
- × 個人的な経験
- sprintのevent, 達成, 欠点に対する大局的な考えに基づくようにする
- contextを共有して行動可能な成果に注力
- 雰囲気づくりができたら,客観的data(commited product_backlog_item, 完成したproduct_backlog_item, 不具合数など, retrospectiveのfocusに合ったもの)を共有する
- 主観的dataも共有・議論する
- → 誤解の回避のため
- 誤解があると,他人のcommentや提案を理解できない
- event_timeline
- sprintのeventの流れをvisualに表現した作成物
- 簡単で強力
- event: buildが動かなくなった,本番環境の修正で手間取った,Salinaが休暇から戻ったなど
- timelineを壁やwhiteboardに描き,eventを表すカードをtimelineに貼り付ける
- colorfulなcardを使う
- sprintのactivityの流れが時間軸で可視化されて,contextがよくわかる
- → 見逃していたり忘れていたeventをすばやく特定できる
- 感情seismogram(seiein: 揺れる)
- event_timelineの補完
- 上下に並べる
- sprintにおける参加者の感情の起伏を視覚的に表現
- 客観的dataだけでなく,主観的dataまで含めてcontextを共有できる
- event_timelineの補完
- 改善につながるinsightの特定
- dataを深く調査,理解,解釈して,process改善のためのinsightを獲得
- system levelの(より大きな)focusが必要
- → 表面的なproblemだけでなく,根本的な原因を特定できる
- まずは共有したdataを発掘
- insightを明らかにするための質問
- 何がうまくいったか
- 何がうまくいかなかったか
- やり方を変えるところはないか
- → brainstorming
- insightを明らかにするための質問
- insight backlog
- 優先順位をつけたが,まだ実行されていないinsight
- 検討すべきものがあるか調査
- insightを意味のあるgroupに分けて,類似や重複しているカードを示す親和図法のようなexerciseを行うことが多い
- silent groupingは,時間の効率も効果も高い
- 複数のcategory area(継続,中止,挑戦)に分けることもある
- → 参加者同士の深い議論につながり,根本原因,重要なpattern,関連をよく理解できるようになる
- 次のsprintで実施する具体的な改善actionの決定
- insightからvalueを抽出するために,実際に行動可能なものにする
- 前回から行われた改善actionのreviewもする
- 何故できなかったのか把握
- 改善を続けるか,優先順位を新しいinsightと入れ替えるかなどする
- insightの選択
- 短期間で実行できる以上のinsightが手に入る
- 参加者がどれを重要と思っているか,どこを改善していきたいと思っているかで決めることが多い
- ドット投票
- 参加者がinsightに専念できるcapacityや期間によって,いくつ選択するか決定する
- 期間: 次のsprint期間
- capacity: 前回のretrospectiveで見つけたactionの計画から決定できる
- product_ownerからのinputをもとに,Scrum_teamが時間を割り当てる
- capacityが分かれば,どのinsightに取り組むべきか分かる
- actionの決定
- 優先順位のついたinsightが手に入り,それらに取り組むcapacityが判明した状態
- 具体的なactionの決定
- ほとんどのactionは,次のsprintで1~2人のScrum_team memberが担当できる程度の具体的なtaskになる
- development_team_memberのtask levelの作業が必要
- 誰がどれだけの時間をかけるかteamで決定する
- → insightが実行可能かどうか決まる
- すぐにinsightには取り組めない
- 次のsprintではinsightの調査が必要
- まず問題をよく理解するためのactionを作る
- insight backlog
- retrospectiveで発見したが,すぐには改善できない課題をまとめる
- backlogのinsightと新しいinsightを比較して,次のsprintで集中するところを決める
- 定期的にgrooming
- 選択肢しなかったinsightを破棄することもある
- 必要ならまた発見できるという考え
- retrospectiveの終了
- 学んだことをふまえて,決定したteamのactionを再確認する
- commited actionと担当者を読み上げるだけの簡単なものでいい
- 感謝を述べる絶好の機会
- retrospectiveを改善できる提案を求める
- 学んだことをふまえて,決定したteamのactionを再確認する
- retrospectiveの雰囲気づくり
- input
- その後のfollow
- 参加者が選択したactionをfollow_up
- 何度も言い続けるしかないものもあるが,それ以外はsprint_planningで指摘する
- actionに関連するtaskをsprint_backlogに追加して,新しい機能よりも優先順位を高くする
- 分離×.統合〇.
- team_memberの時間を必要としないactionは,Scrum_masterのimpediment listに加える
- ほかのteamや組織のactionは,担当者の適切なbacklogに入れておく
- 確実に実行されるように,Scrum_masterは外部の人たちをfollow
- 参加者が選択したactionをfollow_up
- sprint_retrospectiveのproblem
- retrospectiveを実施していないか,参加者が少ない
- All fluff(ふわふわしたもの, つまらないこと), no stuff(本当に役立つこと)
- 外部からretrospective facilitatorを招いて支援してもらう
- 部屋にいる象を無視している
- 劇的な影響をもたらす重大な問題に誰も触れない
- Scrum_masterがleadershipのRoleを担い,まずそのimpedimentを除去する
- facilitatorのskill不足
- 外部からretrospective facilitatorを招いて支援してもらう
- 気がめいってenergyが奪われる
- 雰囲気づくりの時間を作る
- 責任追及game
- facilitatorがすぐに悪い振る舞いを消滅させるようにする
- 不満大会
- face to faceで対話するようにする.
- 現場の改善をつぶす
- retrospectiveは改善活動そのものではない
- 意識が高すぎる
- Scrum_masterが熱意を和らげるよう支援する
- followがない
- Scrum_masterの支援が必要
- まとめ
- sprint_retrospectiveは,teamがScrumをうまく活用できたか振り返る時間,改善案を策定する時間
- Scrum_team member(必要ならそれ以外の人たちも)の共同作業
- 事前準備が終わったら,雰囲気づくりをして,dataに基づいたcontextを共有して理解を統一し,改善insightを見つけ,改善actionを決定し,retrospectiveを終了する
- 終了後は,参加者をfollowして,改善actionを実行していくことがimportant
- → 次のsprintでteamがより効果的になる
- 成功を阻害する問題に注意を払い,すばやく対処することもimportant
- sprint_retrospectiveは,teamがScrumをうまく活用できたか振り返る時間,改善案を策定する時間
Ch23 未来へ
- Scrumを実践するうえでの,普遍的な最終目的はない
- agilityに向かって,独自の道を定義する必要がある
- 最終形態などない
- Scrumの適応やScrumの移行について完成の定義はない
- 継続的改善の一形態
- より効率的かつ経済的にbusinessの目的を達成するための手段に過ぎない
- productによって状態が異なる
- Scrumの適応やScrumの移行について完成の定義はない
- 独自の道を探し出す
- 学び,検査し,適応して,進むべき道を探る
- base: 組織独自の目標・文化,変わりゆく複雑な環境
- 自分の学習loopを素早く完結させて,その学びに基づいて,検査と適応を行う
- 学び,検査し,適応して,進むべき道を探る
- best practiceを共有せよ
- practice: Scrumの核心的基礎的な側面
- approach: Scrumのpracticeの1つの実装
- Scrumを使って,進むべき道を探し出せ
- enterprise_transition_community
- managerと経営者で構成されたgroup
- 組織変革のための取り組みや,Scrum_teamを妨げている重大なimpedimentの除去がbacklogに入る
- Scrumを適用するためにScrumを用いる
- iterative and incrementalによりいっそうAgileになっていくうえで適切なapproach
- enterprise_transition_community
- 歩みを止めるな
- 経験上,teamの最初の2回程度のsprintはうまくいかない
- 次のsprintで,前のsprintより良くなっていさえすればよい
- 始めるのを遅らせてはならない
- Scrumの実施を難しくするimpedimentが必ずある
- 機能不全やムダが可視化される
- こうした課題の解決は,Scrumでは組織の中にいる人にゆだねられる
- 現状維持をしたいという強い力の考え
- 組織を変革するために確固たる信念をもって辛抱強く立ち向かう必要
- 変革に対する抵抗は自然なもの
- 協力し合うことで障害を取り去る
- → team, product development, 組織が,Scrumの実践の恩恵を十二分に理解できるようになる
『Webフロントエンド ハイパフォーマンス チューニング』学習メモ
Ch1 Web performanceとは何か
- performance: userの様々な振る舞いにWeb pageが応答する速さ
- Web page内でのinteractionのperformanceの最適化を目指す
Ch2 browserのrenderingの仕組み
- 対象とするrendering engine
- history
- WebKit系のrendering engineを見る
- rendering engine: browserの内部で利用するHTMLの描画engine
- HTML, 画像ファイル, CSS, JavaScriptなどの各種resourceを読み取って,画面上の実際のpixelとして描画
- JavaScript engine
- V8など
- V8はNode.jsでも使われている
- V8など
- WebView: browserと異なり,Web pageの表示のみを行うcomponent
- online contentsをapplication内で表示/application内のcontentsを再installすることなしにdynamic updateのため.
- WKWebView > UIWebView
- browserのrenderingの流れ
- HTML, CSS, JavaScript, HTTPなどの周辺要素が相互に関連し合って進むため,複雑
- 4つの工程からなるrenderingが始まって,最終的に描画されるまで: Frame
- resourceの読み込み: Loading
- browserが, URLからHTMLを読み込んで,そこからさらにrenderingに必要な付属するresourceを読み込んで解釈
- resourceのdownload + resourceのparse
- resource: HTML/CSS/JavaScript/{JPEG, PNG, GIF, SVG} file
- resourceの取得のためのnetwork protocol
- 各resourceの読み込み
- HTMLの読み込み
- URLからHTTP request → HTTP responseとしてHTMLを取得
- → 取得したHTMLを解釈し,DOM(Document Object Model) treeを構築
- DOM: HTMLのDocumentを表現するObject.rendering engineが利用する木構造を持つ内部表現.
- DOM treeへの変換過程で,画像やCSSなどのDocumentに紐づくresourceの取得や読み込みを行う
- DOM tree: JavaScriptからアクセス〇 → DOM操作
- process
- 字句解析によるtokenのlist化
- 構文木内にあるJavaScriptを実行しつつDOM treeの構築
- img: 画像.link: CSS.script: JavaScript.
- CSSの読み込み
- HTMLの読み込み
- browserが, URLからHTMLを読み込んで,そこからさらにrenderingに必要な付属するresourceを読み込んで解釈
- JavaScript 実行 -Scripting
- JavaScriptの実行: 最初にJavaScriptファイルを読み込んだとき + DOMイベントが発火しevent listenerが起動するとき
- 字句解析と構文解析
- 字句解析: source code → token list
- 構文解析: token list → 抽象構文木
- 抽象構文木: JavaScriptの文法に則った形で表現される木構造のdata
- compile
- 実行
- JavaScript内では,DOM APIを通じてDOM treeを操作
- 後続のRendering, Painting phaseやLoading phaseを引き起こす
- Layout tree構築 -Rendering
- Calculate Style + Layout
- Calculate Style
- Layout
- 要素の大きさ,margin, padding, 位置,z軸の位置を計算
- rendering結果の描画 -Painting
- Paint
- 内部の低レベルな2D graphic engine向けの命令の列(Display List)を,Layerごとに生成
- browserによって,組み込むgraphic engineが異なる
- bottleneckにはならない
- Rasterize
- 生成された命令から,pixel(bitmap)へと描画
- overhead大きい
- layerという単位で1枚ずつ描画
- layer: overwrapして表示するcontentsがあるときに生成
- 描画済みのlayerを再利用して,再renderingが素早く容易になる
- Composite(複合,合成) Layers
- pixelにしたlayerを合成して最終的なrendering結果を生成
- 3Dの処理などはGPU.ほかはCPU.
- Paint
- 再rendering
- DOM eventにより発生
- JavaScriptのコードにより,どのphaseを引き起こすか知ることがimportant
Ch3 tuningの基礎
- 闇雲なtuningの害
- trade off: developerの時間的resource.コードの単純さ.
- best practice
- HTTP requestを減らす
- CDNを使う
- Expires headerを設定する
- componentをgzipする
- style sheetは先頭に置く
- scriptは最後に置く
- CSS expressionの使用を控える
- JavaScriptとCSSは外部ファイル化する
- DNS lookupを減らす
- JavaScriptを最小化する
- redirectを避ける
- scriptを重複させない
- ETagの設定を変更する
- Ajaxをcache可能にする
- ×推測,〇計測
- bottleneckの解消がimportant
- 目指すべき指標を設定する
- performance metrics: RAIL
- user中心のperformance model
- Web page以外にも,複雑なinteractionやanimationを含むWeb applicationやHybrid applicationにも適用できる
- Response, Animation, Idle, Load
- Response: 100 ms
- userが感じられる視覚的な変化
- over 100 msなら,処理中を意味するindicatorの表示が〇
- 指のtouchやscrollはAnimationと同じく16 ms以内が必要
- Animation: 16 ms
- 連続して行われるframeの中で1 frameの処理時間の目安
- frame: Scripting, Rendering, Painting
- 16 ms → 60 FPS(Frames Per Second)を満たす
- frame中のJavaScriptの処理時間は6 ms以内
- Idle: 50 ms
- Idle状態で実行されるJavaScriptの処理時間
- Load: 1000 ms
- 1000 ms以内にsplash screenを表示して,そのほかのresourceの読み込みは遅延でも〇
- cacheやloading 画面の表示で,各種resourceの読み込みを遅らせるのが〇
- performance metrics: RAIL
- 計測手段
- Chrome DevToolsなどdeveloper toolによる計測
- Web page内の細かな計測や解析を行うのに有効
- Web pageがどのように処理されてRenderingに至るのかを詳細・多角的にみられる
- performanceのbottleneckの原因箇所の調査に有効
- 継続的かつ定量的な計測には向かない
- JavaScriptによる計測
- performanceのmetricsの収集・算出の自動化
- userの環境にばらつきがあるcaseで特に有効
- performance診断tool
- performanceが適切かどうか,performance改善のためのtechniqueをadvice
- 継続的監視
- 改修を重ねていくときにperformanceの問題を常に確認する必要がある
- Chrome DevToolsなどdeveloper toolによる計測
- Chrome DevToolsなどdeveloper toolによる計測
- AndroidでのChrome DevToolsの利用方法
- PCとAndroidをUSBで接続する
- WebViewを使う場合
- iOSでのWeb inspectorの利用
- Chrome DevToolsの主要機能
- Network panel
- networkを通じたresource取得のtimelineを細かく見る
- blue line: DOMContentLoaded
- 遅い場合はscriptによる読み込みブロックなどの問題
- red line: Load event
- 遅い場合はresourceの容量が過大
- 回線状況の再現も〇
- 個別のresourceの取得時間: timeline上の表示にカーソルを合わせる
- Connection SetupやRequest/Responseの内容
- Waiting(TTFB)が長いときは,サーバ処理に時間がかかっている
- Performance panel
- page loadや操作に関するすべてのeventを分析〇
- frame chart
- blue/red lineはNetworkと同じ
- green line: 最初のPaintが発生するtiming(page上になんらかの表示が反映されるtiming)
- 特に時間のかかっている処理の割り出しに使う
- profileの取得: Performance panelの記録
- Rendering engine内のほとんどすべてのphaseのprofileを細かくとることができる
- Memory panel
- memory leakの検知やmemoryの使い過ぎの把握のため
- heap snapshot, memory割り当ての確認ができる
- AndroidでのChrome DevToolsの利用方法
- JavaScriptによる計測
- Navigation Timing APIによる計測
- browserのnavigation時の詳細なperformance情報を取得できる
- browserの各段階の処理時間を計測〇
- 以前のWeb pageのunloadの時間など,Web serverでは検知できない情報を得られる
- Objectのpropertyの差を求め,処理時間を算出
- timing Objectは参照するtimingに注意
- navigation Objectの内容も合わせて見る
- どのようなnavigationか
- User Timing APIによる計測
- 任意の処理にかかる時間を計測〇
- interactionなど必ずしも計測地点を機械的に宣言できない処理の計測
- performance
- mark()
- measure()
- getEntriesByName()
- 任意の処理にかかる時間を計測〇
- Resource Timing APIによる計測
- 個別のresourceの取得にかかっている時間の統計情報を取得
- redirectにかかる時間
- DNS lookupにかかる時間
- network connectionの確立にかかる時間
- HTTP responseを受け取るのにかかる時間
- Network panelとほとんど同じものが対象
- PerformanceResourceTiming Object
- 個別のresourceの取得にかかっている時間の統計情報を取得
- Performance Observerによる監視
- これから起こる処理のperformance informationを指定して監視
- 柔軟にperformance informationを取得
- SPAなどinteractionを多く持つようなWeb pageでのperformanceも容易に取得〇
- 記録・解析のためにreal timeでserverに送信も〇
- modern browserの中では,Google Chromeのみ対応
- 高精度なtimestampを得る
- Navigation Timing APIによる計測
- performance diagnostics tools
- performanceの継続的監視
- New Relic Browser
- JavaScriptをWeb siteに埋め込む
- New Relic Browser
Ch4 resource読み込みのtuning
- resource読み込みの流れ
- HTML fileから始まるresourceのgraphを構築しつつ,network protocolを通じてresourceを取得・parse
- TCP/IP + HTTP/1.1で考える
- HTML/CSS/JavaScriptを最小化する
- 余計なbyte列を除去する各tools
- deploy前で自動化する
- JavaScript libraryは最小化されているものを使っても〇
- 余計なbyte列を除去する各tools
- proper image typeを選択
- image fileを最適化
- 各toolsを,wrapper tool, task runnerやbuild toolなどから使うことも多い
- Web fontも最適化可能
- CSSのimportを回避
- HTTP requestを減らすという原則 + 直列な取得・読み込みを避けるため
- toolやメタ言語で結合する
- JavaScriptのsyncな読み込みを避ける
- JavaScriptのdocument.write()はDOM treeの構築に影響を与えるため,script要素はdocumentのparseやCSS fileの読み込みをブロックする
- JavaScriptをasyncに読み込む
- defer attribute
- JavaScript fileは,DOM treeが構築されてから初めて実行
- DOMContentLoaded eventの発火前に実行
- 実行順を保証
- JavaScript fileは,DOM treeが構築されてから初めて実行
- async attribute
- JavaScriptのdownload時点で実行される
- 実行順を保証しない
- 依存関係は,ファイルの結合などで解消が必要
- JavaScriptでscript要素をasyncに読み込む
- 読み込むtimingを細かく制御したい場合など
- async 読み込みの利用方針
- asyncが一番performance〇
- asyncがダメならdefer
- deferもダメなら通常のscript要素
- defer attribute
- device pixel比ごとに読み込む画像を切り替える
- srcset
- さらにresponsive対応をするなら,pictureやsizes
- CSSのmedia queryを適切に指定する
- CSS spriteを使って複数の画像をまとめる
- HTTP requestを減らす
- まとめた画像の一部を切り取って表示
- CriticalCSSで最初の描画を最適化
- resourceを事前読み込みしておく
- Gzip圧縮を有効にする
- CDNを用いてresourceを配信する
- Akamai, Cloudflareなど
- domain sharding
- not redirect
- directoryの名前で終わらず,/をつけるかファイル名を明示する
- directoryの名前で終わると,/をつけたURLにredirectされる
- directoryの名前で終わらず,/をつけるかファイル名を明示する
- browserのcacheを活用
- Expires header
- 強いcache
- Apacheでの指定方法
- HTTP response headerを確認するとわかる
- server/clientで時間設定がずれていると×
- Cache-Control header
- 強いcache
- max-age
- Apacheでの指定方法
- Expires/Cache-Control headerの使い分け
- Cache-Control headerが優先される
- Expires headerは古い
- URLにtokenを付加する
- 強いcacheを疑似的に消す
- PHPなどのserver sideで付加することがほとんど
- 弱いcacheの活用
- 条件つきHTTP requestを使う
- Last-Modified headerの設定
- ETag headerの設定
- Entity Tag(version)で表現
- Last-Modified/ETag headerの使い分け
- ETagが優先される
- Apacheでの指定方法
- 複数台のWeb serverのときは,ETagが変わってしまうため対応が必要
- ETagの柔軟性が不要なら,ETagを付加せずLast-Modifiedのみ指定
- cacheの使い分け
- 静的なresourceは強いcache
- まず強いcacheを使えないか判断し,だめなら弱いcache
- Expires header
- Service Workerの使用
- JavaScriptからcacheの制御を柔軟に実行可能
- Web Workerの一種で,main threadとは別threadで動作
- Web pageとWeb server間でproxyのように動作し,resourceをcacheから取得するかWeb serverから取得するか決定
- Service Workerの導入
- 廃止されるApplication Cacheの代替になる
- HTTP/2の利用
- SPDY protocolがbase
- SPDY protocol: resource読み込みのlatencyの削減を目的にGoogleが開発
- binary化したprotocol
- HTTP/1.1: text baseの通信
- 効率〇
- HTTP/1.1のsemanticsの再利用
- HTTP/1.1とTCPの間に挟まって通信を効率化するような形
- requestとresponseの多重化
- browserの同時connection数のlimitなし
- HTTP headerの圧縮(HPACK)
- RFC7541
- 以前送ったHTTP headerの差分のみをお互いに送る
- 無駄が減る.requestごとの効率up
- HTTP/2 protocolはTLSが事実上必須
- 速度は問題ないケースもある
- HTTP/2で無意味になるtechnique
- HTTP request数を減らしたり,同時接続数の制限を疑似的に増やす必要がなくなる
- HTTP/2 対応 reverse proxyの利用
- clientからのaccessをHTTP/2 serverが処理し,実際のcontents配信はHTTP/1.1 serverが行う構成を取れる
- SPDY protocolがbase
- QUIC protocol
- build tool
- ファイルの依存関係を解決し,複数のファイルをまとめる目的
- task runnerも同等の用途で使われる
- tuningのためのtechniqueの自動化に必要
- TypeScriptやBabelのtranspileや,buildまでの経路の複雑化などから,build toolは不可欠になってきている
Ch5 JavaScript実行(Scripting)のtuning
- HTML5になり,文書だけでなくapplicationを表現するplatformになった.
- 文書と構造: HTML, CSS ←→ 動的な側面: JavaScript
- JavaScriptの実行model
- UI thread
- tab1つにつき1つのUI thread(main thread)
- JavaScriptの実行だけでなく,rendering engineの様々な処理が実行
- Layoutの計算,rendering処理,DOM eventの発火など
- event loopと実行queue
- JavaScriptはevent loopというmodelで動作するため,single threadでの動作にもかかわらず,複数の処理を同時に実行できる
- responseの受け取りなどの継続する処理は,asyncで動作するcallbackの受け渡しやevent listenerによる
- networkなど処理待ちの時間は,タスクを一度終了しUI threadに制御を戻す.処理の再開時にはじめてUI thread上での処理が始まる.
- 例外
- alert(), confirm(), prompt(), sync XMLHttpRequest
- JavaScriptはevent loopというmodelで動作するため,single threadでの動作にもかかわらず,複数の処理を同時に実行できる
- UI thread
- JavaScriptのbottleneckを特定する
- Performance panelによる計測
- rendering engineの行うほとんどの処理のprofileを取れる
- JavaScript, UI threadのrendering, DOM eventの処理など
- JavaScriptでは,どの関数でどのくらい時間がかかっているか細かくわかる
- performance diagnosticsなら,まずはPerformance panelでprofileを取る
- rendering engineの行うほとんどの処理のprofileを取れる
- 各処理の確認方法
- 警告箇所と,ほかの処理の妨げになっているところや明らかに処理時間が長いものを見ていく
- Performance panelによる計測
- GCを避ける
- requestAnimationFrame()などのときに,問題になる
- 検知: Performance panelでprofileを取る
- 防ぐ: 新しいObjectを生成しないか,必要なObjectや配列を予め生成しておく
- memory leakを防ぐ
- importance
- performanceやapplicationの安定性のためにimportant
- desktopでもswapで遅くなるし,mobileではapplicationがcrashする
- detection
- Performance panelでprofileを取る
- heapの3点観測
- heap snapshotを3つとる
- Summary viewの見方
- 黄色のObject: JavaScriptから参照されているObject
- 赤: documentのDOM treeから分離したDOM treeに含まれているDOM要素
- console.log()によるmemory leak
- log()以外も,consoleに値を解析して表示する類のものは,特殊な参照がつく
- debug処理の除去の自動化ができる
- DOM leak
- DOM tree自体もleakする
- DOM leakの検知
- importance
- WeakMap, WeakSet
- weak reference: GCでは利用されていると見られない
- WeakMap: あるObjectの拡張や,private memberを持ちたいときに使える
- WeakSet: あるObjectにflagを立てたいときに使える
- 利用して〇なら最初から利用する
- Web Workersの利用
- codeの複雑化,thread生成costなどのtrade offあり
- 利用方法
- Web WorkersのthreadとUI thread間の通信: message passing(asyncにデータを通信し合う
- postMessage(), event listener
- 共有ではなくcopy
- Web WorkersのthreadとUI thread間の通信: message passing(asyncにデータを通信し合う
- multi Web Workersを生成する
- multi coreで並列計算
- navigator.hardwareConcurrencyを参照してコア数を取り,それに応じたWeb Workersを生成する
- 論理的なコア数が見える
- Transferableを利用
- copyとcopyのoverheadを回避
- 所有権が移動する
- Transferableを実装しているObject
- ArrayBuffer: 型つき配列のdata storage
- MessagePort: ほかのdocumentとの通信のために使う
- 制限
- 使えないObject
- DOM要素,document Object, window Object, parent Object
- → 純粋なデータ処理のみをWeb Workerで行う
- 使えないObject
- asm.jsによるJavaScript高速化
- 高速実行のためのJavaScriptのsubset language
- specification
- 計算はすべてstatic typing
- 計算で使える型はint, double, floatのみ
- asm.js module内部では仮想的にGCが利用不可
- asm.js形式のコードを書きだすtranspilerによって処理を記述する想定
- いずれWebAssemblyにreplaced
- WebAssembly
- より高速なloadと実行を目的として各browser vendorによって策定されている,browser上で実行可能なbinary format
- JavaScriptの一部の機能を代替
- merit, compared to asm.js
- load time短縮
- parseの簡略化
- heap sizeの制限緩和
- memoryに対する柔軟な読み書き
- SIMD.jsの利用
- 高頻度で発火するeventの抑制
- scroll, resize, touchmoveなど
- setTimeout()やrequestAnimationFrame()で,ある一定の頻度でのみ実際の処理を行うようにする
- そのほか,視差効果やscroll event listenerなど
- mobile端末でのclick eventの遅延をなくす
- meta要素によるviewportを適切に設定する
- FastClickやTappy libraryを使っても〇
- Passive Event Listenerでscrollのperformanceを改善する
- event.preventDefault()が無効になることを保証
- capture phaseでevent listenerを呼び出し
- browserでのsupportの確認処理
- scroll performanceの改善以外にも,event listenerがinteractionをブロックする時間が気になるときには検討〇
- setImmediate()のasync 実行
- setTimeout()は,指定した時間の後にasync実行
- ↑ ずれがある
- ←→ setImmediate()は,UI threadがidleになったらすぐに実行
- clearImmediate()で解除
- polyfill libraryのsetImmediate.jsで使える
- setTimeout()は,指定した時間の後にasync実行
- idle時処理を使う
- requestIdleCallback()
- cancelIdleCallback()で解除
- page表示状態を確認する
- 状態に応じて,animationのon/offなどを行う
- 正確なpage viewの測定にも使う
- Page Visibility API
- document.hiddenを参照
- visibilitychange event
- document.visibilityState
- 無駄なForced Synchronous Layoutを減らす
- DOM操作→関連するDOM要素のLayout情報を参照で,Forced Synchronous Layoutが引き起こされる
- Recalculate StyleとLayoutがsyncに処理される
- JavaScriptともsyncに実行
- Layoutに影響する操作
- style attributeやstyle propertyを通じて要素の大きさや座標にかかわる操作をする
- DOM要素のclass属性を変えて,当たるstyleを変更して要素の大きさや座標を変更する
- DOM treeの構造に変更を加える操作(DOM要素の追加・削除など)
- 計測
- Layout Thrashingを避ける
- loop中でFSLを繰り返し起こしてしまうこと
- FSLを防ぐ
- DOM 操作の前にLayout情報を参照する
- requestAnimationFrame()で計算済みのLayout情報を参照する
- DOM操作→関連するDOM要素のLayout情報を参照で,Forced Synchronous Layoutが引き起こされる
- DocumentFragmentの追加
- Web pageのdocumentの断片を表す
- DOM treeへのDOM要素の追加を速くできる
- 複数のDOM要素を格納〇
- Intersection Observerで効率的に交差を検知する
- あるDOM要素と親要素が視覚的に交差しているか監視
- 使い方
- not supportedなら,scroll eventで処理したりしないといけない.問題がある.
- canvas要素の2D Context animation
- requestAnimationFrame()を活用する
- setTimeout()やsetInterval()の課題
- proper timingでcallbackの呼び出しがdifficult
- requestAnimationFrame()によるanimation
- 自動的に呼び出しtimingを最適化
- 指定したcallbackを,browserのrenderingの処理に合わせて,proper timingで呼び出し
- setTimeout()やsetInterval()の課題
- JavaScriptからCSS Transitionを使う
- animationの進行中はJavaScriptのコードは一切実行されない
- requestAnimationFrame()とは異なり,JavaScriptがbottleneckにはならない
- UI threadとは別のthreadで実行
- rendering engine内部で最適なtimingで実行される
- animationの進行中はJavaScriptのコードは一切実行されない
- WebGL
- WebCL
- 小さな最適化
- 有意味でないことが多い
- まずはbottleneckの解析
- 次は,アルゴリズム・データ構造や基礎技術の改善
Ch6 Layout tree構築(Rendering)のtuning
- Rendering: Calculate Style + Layout
- interactionの高速化にもつながる
- Layout tree構築の流れ
- Layout tree構築におけるperformanceの計測
- Performance panel
- Recalculate Style
- Elements Affected
- Layout
- Nodes that need layout
- Layout root
- Recalculate Style
- Performance panel
- 高速なCSS selectorの記述
- BEMを用いる
- 設計・保守しやすさを上げる + performance〇
- BEM: Block, Element, Modifier
- Block: page内を構成するひとかたまり.header, footer, 記事など.
- Element: Blockを構成する要素
- Modifier: BlockやElementの見た目や振る舞いを拡張
- 1つのclass selectorのみでCSS selectorを宣言する
- CSS selectorのmatching処理を避ける
- DOM要素のstyle propertyを直接変更すると,matching処理を回避できる
- 必ずそうするべきというわけではなく,高速なperformanceが必要なanimationやinteractionのときのみ
- 利用していないCSS rule setを減らす
- UNCSS
- build toolとの組み合わせも〇
- UNCSS
- media queryを指定する
- 不要なrule setをまとめて除外できて〇
- DOM要素のstyle propertyを直接変更すると,matching処理を回避できる
- Layoutを高速化する
- a.c.a Reflow
- Layoutを避ける
- Layoutの原因
- DOM要素の座標や大きさの変化
- DOM treeの構造の変化
- DOM要素のcontentの変化
- Layoutの範囲を限定する
- いずれかの条件
- svg要素
- type="text", or type="search"のinput要素
- table要素の子孫じゃなくてかついろいろ条件を満たす
- いずれかの条件
- Layoutの原因
- DOM treeから切り離して処理する
- DOM treeから離れれば,Renderingはなくなる
- remove()
- 必要になった時にappendChild()などで再挿入すればよい
- Layoutを減らす非表示
- display: none
- img要素のsizeを固定
- height, widthを指定しないと仮の大きさで1度Layoutが走る
Ch7 Rendering結果の描画(Painting)のtuning
- interactionやanimationを実装するときに頻繁に実行される
- Rendering結果の描画の流れ
- → Ch2
- 再描画(Repaint)
- CSS propertyの変更が何を引き起こすか
- CSS Triggers
- Layerの生成条件
- Layer treeが構成される
- GPUに転送されるGraphics Layerが,performanceに影響大きい
- うまく扱うと,animationを高速化できる
- Layer treeを確認する
- Performance panel
- Layer treeの詳細を確認
- 歯車 → Enable advanced paint instrumentation(slow)にチェック → profileを取得 → Frames → Layers
- Layerの範囲を確認
- Rendering optionのLayers Borders
- 描画のoverheadを解析
- Performance panelでPaint Profilerを見る
- Paint Profilerの確認方法
- GPUによって合成されるlayer
- translateZ hack
- translateZ(0)により,結果を変えずにGPUで合成できる
- position: fixedのscroll speedの改善
- body要素にtranslateZ hackを用いる問題
- translateZを使うためのrule
- Rasterizeされることが少ない要素に用いる
- 領域がそれほど大きくない要素に用いる
- 必要なときだけ用いる
- translateZを使うためのrule
- 必要なtimingだけtranslateZ hackを用いる
- JavaScriptでDOM要素のstyle propertyを指定する
- will-changeCSS propertyによるtranslateZ hackの代替
Ch8 高度なtuning
- 大量のDOM要素を扱うvirtual rendering
- なめらかなanimation
- 指標と基本的な考え方
- RAILを使う
- Rerenderingのphaseを減らす
- skip Calculate Style
- JavaScriptでDOM要素のstyle propertyを直接変更
- 不要ならDOM treeの構造やDOM属性を変更しない
- skip Layout
- transformCSS propertyの値に,translate()やscale()を使う
- skip Paint
- Paintを引き起こさないproperty
- opacity
- transform
- これらを使えない場合は仕方ない
- Paintを引き起こさないproperty
- layerの合成の最適化
- translateZ hack
- 指標と基本的な考え方
- will-changeCSS propertyによる最適化
- CSS property名を指定
- opacity, transformのみ
- scroll-positionを指定
- 要素の移動(animation)や素早いscrollに対応
- contentsを指定
- animationや変更を予想
- cacheの生成・維持を省ける
- dynamicに利用
- JavaScriptからのdynamicな利用が〇
- CSSでの宣言は,その要素が常に変更されるときのみ
- 使い方
- 最適化においては,見かけほど有用ではない
- CSS property名を指定
- CSS ContainmentでRerenderingを最適化
- CSS Containment: DOM treeの一部に封じ込め〇
- 利用方法
- layout: Layoutの封じ込め
- 副作用: floatCSS propertyでの回り込みの影響がなくなる
- paint: Paintの封じ込め
- Layoutの封じ込めとともに,大きな最適化
- 副作用3点
- style: styleの封じ込め
- 単体では使わない
- size: 大きさの封じ込め
- 単体では使わない
- layoutと併用したり,content/strictを指定して使う
- content/strict: 複数の封じ込め
- content: layout + paint + style
- strict: layout + paint + size + style
- 最も最適化の効果〇
- まずはstrictで,だめならcontent
- AMP(Accelarated Mobile Pages)
- static contentsを高速に提供
- 専用CDNやprerenderingなどで〇
Ch9 認知的tuning
- indicatorを使う
- 1sを超える処理や読み込みのとき
- 10sを超えるときはprogress barなどの進捗の表示が必要
- interface previewを使う
- indicatorより印象〇
- 処理が終わったように振る舞う
- beforeunloadで処理中の離脱へのアラート
- 無限scroll
- 同様の要素を表示するpageで使う
- userのscrollをJavaScriptで検知,pageの最下部になると,次のpageの情報を読み取って動的に読み込むべきcontentsを画面下部に追加
- 一部のRerenderingで済むため速い
- 実装上の注意
- → 5.11
- virtual renderingとの違い
- 無限scrollはvirtual renderingと併用する
- merit
- waiting time小さい
- demerit
- footer使えない
- back buttonで表示が壊れることがある
- リンクは別windowにするなど対応が必要
- 投機的なresourceの先読み
- user activityの洞察と解析が必要
- 事例
- 手段
- JavaScriptで実装したapplication levelのcacheを使う
- IndexedDB, LocalStorageなどのstorageで保存するか,もしくは単にJavaScriptの変数で保持(SPAなどのとき)
- Resource Hints API(4.11)も〇
- SPA: Single Page Application
- SPA以外は,page操作で断絶 → userの体感速度を大きく低下
- Ajaxの発展形
- library, frameworkが必要
- React.js, Angular, Vue.jsなど
Appendix SVGのperformance特性
- SVG: Scalable Vector Graphics
- XMLで表現されるVector Graphicsのformat
- browserで利用できる唯一のVector Graphics format
- HTMLと親和性がある
- img要素ではなく,svg要素で,その画像をdocument内に直接埋め込める
- tagの記述も〇
- JavaScriptでの振る舞いを追加したり,CSSで修飾もできる
- img要素ではなく,svg要素で,その画像をdocument内に直接埋め込める
- JavaScriptでSVG内の視覚的要素をanimationさせたり,event listenerを追加してinteractionを与えられる
- HTMLのanimationの問題もいくつか回避している
- JavaScriptでanimationを行う
- SMILによるanimation
『Web API: The Good Parts』学習メモ
Ch01 what's Web API
- Web API: HTTP protocolを利用してnetwork越しに呼び出すAPI
- API: Application Protocol Interface
- APIのpattern
- 使用例
- APIで公開するもの
- Web APIを美しく設計する重要性
- 使いやすさ,変更しやすさ,頑強さ,魅力
- Web APIを美しくするには
- 仕様が決まっているものは仕様に従う
- 仕様がないものはdefacto standardに従う
- RESTとWeb API
- RESTの本来の意味に合っていない使われ方がされている
- RESTの考えを適用する場面は多いが,すべてがRESTではない
- target developerの数とAPIの設計思想
- LSUDs(Large Set of Unknown Developers)とSSKDs(Small Set of Known Developers)
- SSKDs向けは,RESTを基本にしたAPIでは不十分
- → Orchestration layer
- まとめ
Ch02 endpointのdesignとrequestの形式
- APIとして公開する機能をdesign
- UCを考える
- API endpointの考え方
- HTTP methodとendpoint
- APIのendpoint design
- 検索とquery parameterのdesign
- loginとOAuth 2.0
- 認証のAPIとして,Authが真っ先に検討できる標準仕様
- 自社開発のClient Applicationにおいて,ユーザ名とパスワードをapplication内に入力して認証を行う場合
- OAuthのGrant Typeのうち,Resource Owner Password Credentialsを使う
- 扱い方
- OAuthのGrant Typeのうち,Resource Owner Password Credentialsを使う
- access tokenの有効期限と更新
- other Grant Type
- Client Credentials: User name, Password不要な認証.Clientの認証のみ行う.
- 自分の情報へのalias
- me, self
- ほかのユーザの情報の処理とは,処理自体を分岐することでバグを防げる
- hostnameとendpointの共通部分
- api.example.comの形が最も適当
- SSKDsとAPI design
- HATEOASとREST LEVEL3 API
- まとめ
- [Good] 覚えやすく,どんな機能を持つか一目でわかるendpointにする
- [Good] 適切なHTTP methodを利用する
- [Good] 適切な英単語を利用.単複にも注意.
- [Good] 認証はOAuth 2.0
Ch03 response dataの design
- data format
- JSONPの取り扱い
- dataの内部構造の考え方
- 各dataのformat
- response dataのdesign
- あるデータを返すときは同じ構造になるよう,それぞれのデータの構造を定義してしまうとsimpleで〇
- errorの表現
- proper status code
- detail
- bodyで〇.headerに入れるのも悪くはなさそう
- detail code, detail information link
- HTMLで返らないようにする
- @maintenance
- 503
- Retry-After
- 意図的に不正確な情報を返す
- まとめ
Ch04 HTTPの仕様を最大限利用する
- 意義
- 不本意に独自仕様をいれてしまう危険性を下げる
- HTTP protocolがenvelopeの役割という例
- status codeを正しく使う
- APIで使うcode一覧
- 2xx: success
- 204: No Contentは,是非あり
- PUT, PATCHは,200とともに操作したデータを返す(POSTは201)
- DELETEは204
- 204: No Contentは,是非あり
- 3xx: 追加で処理が必要
- redirect: 301, 302, 303, 307
- Locationを伴う
- POSTによるデータ送信 → GETで別のページを表示のケースが多い
- 302, 301はmethodの変更を許可
- 308, 307は不許可
- APIではできるだけredirectを避ける
- 300: Multiple Choices
- 304: Not Modified
- redirect: 301, 302, 303, 307
- 4xx: Clientのrequestに問題があった場合
- 400: Bad Request
- ほかのcodeでは表せない「その他」
- 401: Unauthorized. Authentication(認証) error. ← 誰ですか?
- 403: Forbidden. Authorization(認可) error. ← 許可がないよ.
- ほかにも色々ある
- 400: Bad Request
- 5xx: Serverに問題があった場合
- cacheとHTTPの仕様
- cacheのmerit. → 可能な限り利用するべき
- proxy serverへの考慮必要
- reverse proxy
- Expiration Model
- fresh ←→ stale
- Expires
- 特定の日時に更新されることがあらかじめわかっているdataに使う
- Cache-Control
- max-age
- HTTP時間
- RFC1123を使う
- HTTP時間
- max-age
- Validation Model
- 条件付きrequest
- Last-Modified, ETag (Entity Tag)
- If-Modified-Since, If-None-Match
- e.g. MurmurHash3
- strong/weak Validation
- weakなら,広告などの違いは無視できる
- 条件付きrequest
- Heuristic Expiration(発見的期限切れ)
- ClientがCacheの期限を自分で決める
- Cache-Control: no-cache
- VaryでCacheの単位を指定
- Server Driven Content Negotiation
- Accept-Encoding, User Agent, Accept-Language, Authorization, Cookie
- Cache-Control header
- stale-while-revalidate
- asyncでcacheの検証をしている間はcacheを返してよい → 速度〇
- stale-if-error
- origin serverに接続できなかったときに,stale cacheを返してよい秒数
- stale-while-revalidate
- media typeの指定
- media type: data format
- Content-Type @response
- MIME: Multipurpose Internet Mail Extensions
- top level type name/ sub type name [; parameter]
- top level type: text/image/video/applicationなど
- sub type: 具体的なdata format
- top level type name/ sub type name [; parameter]
- 前提知識なくても読めればtext, そうでなければapplication
- MIME: Multipurpose Internet Mail Extensions
- 正しいmedia typeをContent-Typeで返す
- x-で始まるmedia type
- IANA(Internet Assigned Numbers Authority)に登録されていないもの
- application/x-www-form-urlencodedだけ例外的に登録されている
- IANA(Internet Assigned Numbers Authority)に登録されていないもの
- 自分でmedia typeを定義する
- Registration treeで接頭辞が決まっている
- vnd.を使うことが多い
- Registration treeで接頭辞が決まっている
- JSONやXMLを用いた新しいdata形式を定義する場合
- 独自に別のHTTP headerを用意するのが折衷案として〇
- media typeが正しくないと,security riskあり
- media type @request
- 同一生成元policy(Same Origin Policy)とCross-Origin Resource Sharing
- 独自のHTTP headerを定義する
- 接頭辞: X-
- X-は不要という論もある
- まとめ
- [Good] HTTPの仕様を最大限利用し,独自仕様の利用を最低限に止める
- [Good] 適切なstatus codeを用いる
- [Good] 適切な,なるべく一般的なmedia typeを返す
- [Good] Clientが適切なcacheを行えるように情報を返す
Ch05 設計変更をしやすいWeb APIを作る
- 設計変更のしやすさのimportance
- 影響が分かりづらい
- 外部/mobile/web serviceいずれの場合も問題あり
- web service,自分のserviceで使っているAPIであれば,問題は小さいが,cacheの問題はある
- APIをversionで管理する
- versionを変えるときの指針
- security, authorityにアップデートは,後方互換なしで〇
- 以降のバージョンアップの影響を小さくするために実施する
- 常に最新版を返すaliasは不要
- APIの提供を終了する
- 終了日時の周知
- Blackout Test
- 予め提供終了時の仕様を盛り込む
- 強制アップデート,ユーザのOSの調査
- 利用規約にサポート期限を明記
- applicationの性質による
- Orchestration layer
- LSUDs: one-size-fits-all(OSFA)
- OSFAではなく,それぞれのClientに対応するために,ServerとClientの間にOrchestration layerを挟むようにする.
- まとめ
Ch06 堅牢なWeb APIを作る
- 安全性と安定性
- Web APIを安全にする
- riskのe.g.
- Server-Client間での情報の不正入手
- browserでアクセスするAPIの問題
- browserは汎用的で機能が豊富
- XSS
- XSRF: Cross Site Request Forgery
- Forgery: 偽造,捏造
- 回避方法
- methodを正しく使う
- XSRF tokenを使う
- X-Request-With
- JSON hijack
- 回避方法
- JSONをSCRIPT要素では読み込めないようにする
- X-Requested-With
- XMLHttpRequest, browser以外からのClientからのアクセスのみを想定の場合は,必ずやる
- X-Requested-With
- JSONをbrowserが必ずJSONと認識するようにする
- 正しいmedia typeを返す
- JSONをJavaScriptとして解釈不能,または実行時にデータを読み込めないようにする
- JSONをSCRIPT要素では読み込めないようにする
- 回避方法
- browserからのアクセスを想定しないAPIでは,browserからのSCRIPT要素を使ったアクセスを防ぐのが〇
- 悪意あるaccessへの対策
- security関係のHTTP header
- 大量accessへの対策
- まとめ
Appendix
『メタプログラミングRuby』 学習メモ
Part 1 meta programming Ruby
Ch01 initial M
- introspection
- Active Recordがintrospectionを使っている
- meta programming: 言語要素を実行時に操作するコードの記述
- codeを記述するcodeを記述
- meta programmingの学習により,Rubyのruleがわかる
Ch02 Monday, Object model
- すべての言語要素はObject model内に共存する
- Open Class
- classはscope 演算子のようなもの
- monkey patchは×
- Object modelの内部
- Objectの中身
- instance variable
- 値が代入されたときに初めて出現
- method
- ObjectではなくClassに存在する.
- 共通のClassを持つObjectはメソッドも共通
- → instance method: Classに定義されていて,呼び出すにはObject(instance)が必要になるmethod
- ←→ method: Object(instance)がもつmethod
- ObjectではなくClassに存在する.
- instance variable
- Classの真相
- Class.superclass # => Module
- Class: Objectの生成やClassを継承するための3つのinstance methodを追加したModule
- Moduleはinclude, Classはinstanceの生成や継承
- Classの参照も保持できる.ClassはObject,Class名は定数
- 定数
- file systemと類似
- Rakeの例: moduleで定数をまとめる例
- まとめ
- Object: instance variableの集まりに,クラスへのリンクがついたもの
- Classについて
- load, require
- load: codeの実行のため.呼び出すたびにファイルを実行する.
- 定数の扱いのための引数
- require: libraryのimportのため.1回だけファイルを読み込む.
- load: codeの実行のため.呼び出すたびにファイルを実行する.
- Objectの中身
- Object, Module, Classの関係について
- 循環したり自己参照したりしている.
- method call
- method探索 + method実行
- method 探索
- receiverと継承チェーン
- one step to the right, then up
- Moduleも継承チェーンに入る.
- includeは上に,prependは下にModuleを挿入
- include, prependは1度目のみ有効
- Kernel: ObjectがKernelをinclude
- method 実行
- receiverの参照を持つ
- self, top level
- private: explicit receiver不可
- Refinements
- monkey patchの回避.
- usingで有効にする
- 発展途上なので,直感に合わない挙動がある
- 絡み合ったModule
- 継承チェーンの確認
- まとめ
Ch03 Tuesday, method
- boiler plate methodの回避
- 重複問題
- dynamic method
- dynamic dispatch: sendを使うことで,method nameをargumentにしてdynamicにcallできる
- :(name) ← symbol
- immutable. String: mutable.
- immutableなので,メソッド名などのmeta programmingに関係する名前に使う
- Pryの例
- methodをdynamicにdefine
- 実行時にmethod nameを決定するため,defではなくModule#define_methodを使う
- Stringと変換可能
- e.g.
- Array#grep → define_method
- method_missing
- ghost method: method_missingのoverride
- Hashieのe.g.
- dynamic proxy: ghost methodを補足して,ほかのObjectに転送するObject
- Gheeのe.g.
- GitHubのObjectをdynamic hash に保持.hashのattributeは,ghost methodの呼び出しでアクセスできる
- hashをProxy Objectでラップ.
- Gheeのe.g.
- respond_to_missing?もあわせてoverride必要
- const_missing
- 古いクラス名が呼び出されたときに,警告を出して新しいクラス名を返す
- 受付可能な引数以外はBasicObject#method_missingを呼ぶ必要がある
- ghost method: method_missingのoverride
- blank slate
- 最小限のmethodしか引き継がないClass
- BasicObjectの継承.指定しなければObject.
- methodの削除
- Builderのe.g.
- まとめ
- Rubyのdynamicな能力により,複数のmethodに共通した外部の重複を排除できる
- 可能であればdynamic method, 仕方なければghost method
Ch04 Wednesday, block
- not from Object Oriented Design, but from Functional Programming Language like LISP
- block day
- blockの基本
- do...end, {}
- yieldでblockを呼び出す
- blockの基本
- Kernel methodで,usingのように例外の有無によらず処理を呼び出せるようにする振る舞いを追加できる
- block is closure
- blockは,コードと束縛の集まりの両方を含む
- scope
- scope gate: scopeを切り替えて,新しいscopeをopenする場所
- class, module, def
- defは呼び出したときに実行.class, moduleはすぐに実行
- scopeのflatten, flat scope
- shared scope
- instance_eval
- instance_evalに渡したblock: context 探査機
- instance_execなら引数で渡すことができる
- replace scope gate to method call
- encapsulateの破壊
- irb, test
- Padrinoのe.g.
- clean room: blockを評価するためだけのObject
- callable Object
- blockの使用の2process
- codeの保管 → blockを呼び出して実行
- block以外のコードを保管できるところ
- Procのなか.← blockがObjectになったもの.
- lambdaのなか. ← Procの変形.
- methodのなか.
- Proc Object
- あとで評価
- lambdaとprocで生成できる
- ->lambda
- &修飾
- methodに渡されたblockを受け取って,それをProcに変換
- Procをblockに戻すときも&修飾
- HighLineのe.g.
- あとで評価
- Proc vs lambda
- return
- lambdaはlambdaから戻るだけ.Procは,Procが定義されたscopeから戻る
- 項数(引数の数)
- lambdaは一般的に厳しい.Procは合わせてくれる.
- lambdaはmethodに似ていて,一般的にはlambdaを使う.
- return
- Method Object
- blockやlambdaに似ているが,所属するObjectのscopeで評価
- UnboundMethod
- Active Supportのe.g.
- 自分ではやらない方が〇
- blockの使用の2process
- DSLを書く
- event間で共有
- global variableの削除
- clean roomの追加
- まとめ
Ch05 Thursday, Class definition
- RubyのClass definitionはcodeを実行する
- Classは高性能のModule. Class definitionに関することはModule definitionにも置き換えられる.
- Class definitionの分かりやすい説明
- Class, Moduleも単なるObjectで,selfになれる.
- current Class
- class_eval
- self, current Classを変更する → Classを再open可能
- flat scope
- class_execもある
- instance_evalとの使い分け.
- class_eval
- Class instance variable
- Class instance variableとObjectのinstance variableは別物
- Class variableは△.共有の度合いが大きい.
- testでのClass instance variableの使用
- Class のtaboo
- Class.new()で,Class keywordを使わずにClass作成
- 特異method
- 特定のObjectにmethodを追加できる.
- Duck typing
- Class methodはClassの特異method
- Class macro
- Module#attr_*のe.g.
- attr_accessorなど
- Module Classに定義されているので,selfがModuleでもClassでも使えるもの.
- Class定義の中で使える単なるClass method
- Module#attr_*のe.g.
- 特異Class
- a.c.a. meta Class, singleton Class
- 変わった構文を使わないとみることができない.
- only one instance( so that called singleton Class )
- Objectの特異methodの在り処
- 特異methodがあれば,特異Classから探索する.特異ClassがObjectのsuper Classになる.
- 継承
- metaの2乗
- 特異Classの特異Class
- 大統一理論
- Object, Module, Methodはそれぞれ1種類だけ.
- Objectの特異Classのsuper Classは,ObjectのClass
- Classの特異Classのsuper Classは,Classのsuper Classの特異Class
- Class methodの構文
- Class methodはClassの特異Classにある特異method
- instance_evalは,current Classをreceiverの特異Classに変更する
- 意図としては,selfの変更で良い.
- Classのattributeの追加のe.g.
- metaの2乗
- Class拡張
- Object拡張も〇
- どちらもObject#extendを使うのが〇
- method wrapper
- methodの再定義: 新しいmethodを定義して,元のmethodに名前を付ける
- Thorのe.g.
- around alias
- Refinementsでaround alias
- Prepend wrapper
- 計算methodをaround aliasで変更することもできるというe.g.
- まとめ
Ch06 Friday: codeを記述するcode
- meta programmingの新しいtrickと,様々なtrickを組み合わせて難しいcoding課題を解決する方法を見る
- Kernel#eval
- REST Clientのe.g.
- code文字列は文字列の代わりになるものを使うことが多い
- 外部ソースにある任意のcode文字列を評価するときも使う
- Binding Object
- scopeをObjectにまとめたもの
- eval "@x", b ← b: Binding
- TOPLEVEL_BINDING
- Pryの例
- irbのe.g.
- code 文字列 vs block
- 基本はblockを使うべき
- evalのproblem
- code injection
- 代用: dynamic dispatch
- Object taintとsafe level
- ERBのe.g.
- safe levelがあるときは, sandboxが作られてそこで実行される.
- load, requireとの比較
- REST Clientのe.g.
- evalでの実装とevalの置き換え
- classのscopeに入るためにclass_eval → 実行時まで分からないのでdynamic method
- instance variableの読み書き: Object#instance_variable_set(/get)
- blockでの置き換え
- Kernel methodをClass macroに変更
- あらゆるClass定義で使うために,ModuleまたはClassのinstance methodを作成する.
- → class_evalも不要になる
- あらゆるClass定義で使うために,ModuleまたはClassのinstance methodを作成する.
- hook method
- Class#inheritedなどのmethod.defaultでは何もしない
- 特異methodにはsingletonをつけないと動作しない
- standard methodにplugin
- superで元のincludeを呼び出す必要ある
- VCRのe.g.
- instance methodを特異Classにmix in → Class methodを追加できる
- Class macroから,includeしたClassだけaccessできるように制限する
- Moduleのincludedを上書きして,ClassMethodsを拡張する
- まとめ
Ch07 epilogue
- meta programmingも単なるprogramming
Part2 Railsにおけるmeta programming
Ch08 Rails tourの準備
- Ruby on Rails
- Active Record(applicationのObjectをDBのテーブルにmapping), Action Pack(Web frameworkの「Web」の部分を扱う), Active Support(時刻計算やloggingなどの汎用的な問題を扱うutility)
- gem unpack activerecord -v=4.1.0
Ch09 Active Recordのdesign
- Object Relational Mapping
- Relational DB + Object Oriented Programming
- Active Recordのまとめられ方
- Active Support + Active Model
- auto loading by ActiveSupport::Autoload
- ActiveRecord::Base
- Moduleの外側にある機能をまとめるClass. Moduleの集まり
- Moduleのincludeで,instance methodとClass methodを手に入れる
- history
- Active RecordからActive Modelが分離
- Active Record: DB操作, Active Module: Object Modelの操作
- Active RecordからActive Modelが分離
- 学んだこと
- ActiveRecord::Baseは,究極的なopen Class
- 疎結合,simplicity, 重複の排除という基本的な設計原則を実現するための技法が,ほかの言語と大きく異なる
Ch10 Active SupportのConcern Module
- history
- ActiveSupport::Concern
- Module#append_features
- Concern#append_features
- concern(ActiveSupport::ConcernをextendしたModule)のなかで,別のconcernをincludeしない
- 依存を管理する.最小主義の依存管理system
- 学んだこと
- 柔軟性のためのmeta programming
- codeが複雑になったり,排除しにくい重複が見つかった時に使う.
- Moduleの相互作用のような基本的な部分でも,meta programmingで変更できる
- 柔軟性のためのmeta programming
Ch11 alias_method_chainの盛衰
- problem
- 学んだこと
- 素直なObject指向で解決できれば,meta programmingは使わない
Ch12 attribute methodの進化
- どのようにmeta programmingを使うか
- codeが複雑になり,微妙に意味が違ってくる中で起きたことを見る.
- Rails 1: はじめはsimple
- method_missing
- Rails 2: performanceに注目
- method_missingは遅い
- → ghost method + dynamic method
- 各Classで1度だけmethod_missingを呼ぶ
- backにDBのカラムがない派生fieldなどのattributeへの対応.→ attribute accessorを定義しない
- Rails 3, 4: もっと特殊なcase
- Rails 4ではattribute accessorの定義時に,UnboundMethodに変更し,Method cacheに保存している. → ほかのClassが同じ名前のattributeを持ち,同じaccessorが必要な場合はcacheから取り出す.
- performanceが目に見えて変わる.
- ReaderMethodCacheの初期化処理にコメントがある
- attribute methodがどれだけ深くて複雑なものになったか,どれだけの数の特殊ケースに対応しているか,最初はsimpleだったところからどれだけ変わったか,を示している.
- Rubyのsafeなmethod nameにするための対応
- Rails 4ではattribute accessorの定義時に,UnboundMethodに変更し,Method cacheに保存している. → ほかのClassが同じ名前のattributeを持ち,同じaccessorが必要な場合はcacheから取り出す.
- 学んだこと
- 「最初から正しくやる」よりも「進化的設計」に傾いている.
- Rubyが柔軟性の高い言語であるため
- 最初から完璧なmeta programmingのcodeを書くことは難しい
- → codeはできるだけsimpleに保ち,必要になったら複雑にする
- 「最初から正しくやる」よりも「進化的設計」に傾いている.
Ch13 最後の教訓
- meta programming: simple, clean, and tested codeを書くための単なるtool
付録
A よくあるidiom
- mimic method
- mimicry: 擬態
- 偽装method
- Campingの例
- class Help < R '/help' ← R('/help')と読み替えるとわかる
- attributeの不具合
- attributeのsetterは,privateでもselfをつけて呼び出せる
- nil guard
- ||=
- OR と =
- falseになりうるときは使わない
- ||=
- 自己yield
- blockにObject自身を渡せる
- Faradayのe.g.
- 新しく生成したConnection Objectをselfとしてyieldに渡す
- tapのe.g.
- 呼び出しのchainを断ち切らずに,中間の作業をtap {} で差し込む
- Symbol#to_proc
- one call blockを短い記述に置き換える
- inject(init)などで使える
B DSL
C 魔術書
- 今までのものの短いsample
D から騒ぎ
『Webを支える技術』学習メモ
Part1 Web概論
Ch01 what's Web
- Webの作用
- 非線形なhyper media @Web
- distributed system @Web
- simple protocol
Ch02 Web history
- Web以前のhyper media
- hyper media: hyper textの拡張
- 必要最小のリンク機能のみ持つWeb
- RPC, CORBA, DCOM
- Web以前のdistributed systemの問題
- Webの起源
- simpleな単方向リンク
- client-server間のIF.simple protocolとしてのHTTP
- IETF→W3Cでのstandardize
- especially HTML, CSS
- Webのstandardize
- RESTの起源,意味
- HTTPはresourceのstateの表現を転送している
- REpresentational State Transfer
- Hyper Media Format: HTML, RSS, Atom, microformat, JSON
- RESTの起源,意味
- Web API
- SOAP @RPC/distributed object
- WS-*
- mashupのためのREST
- SOAP @RPC/distributed object
- REST, Ajax, CometによるWebの進化
Ch03 REST: Web architecture style
概要
- architecture style: architecture pattern
- e.g. MVC, Pipe&Filter, Event System
- architecture style > micro architecture pattern(design pattern) @粒度
- architecture styleをもとに,architectureを決定する
内容
- REST: network systemのarchitecture style
- Web: client/server style
- REST: client/server + 制約
抽象度 | Webでの例 |
---|---|
architecture style | REST |
architecture | browser, server, proxy, HTTP, URI, HTML |
implement | Apache, Firefix, IE |
詳細
- resource: Web上の名前を持ったあらゆる情報
- resource name, identifier: URI
- addressability
- URIによってresourceが表す情報にアクセス
- client-server間でやり取りするdata: resourceの表現
- 1つのresourceは複数表現を持てる
- e.g. html, pdf
- 1つのresourceは複数表現を持てる
- addressability
- RESTの構成
- RESTは複数のarchitecture styleを組み合わせて構築した複合architecture
- a.client-server
- Web: httpでclient-serverが通信するというarchitecture style
- merit: client-serverを分離できる
- multi platform @client + serverの冗長化で可用性UP
- b.stateless server
- clientのapplicationのstateは管理しない
- c.cache
- resourceをclient側で再利用
- d.統一IF
- 統一IFにより,client-server間の独立性を高める
- GET, POSTなど限定的なmethodのみを持つ
- 統一IFにより,client-server間の独立性を高める
- e.階層化system
- 統一IFにより,load balancerやproxyを使用したsystemの階層化が容易になる
- f.code ondemand
- a-fを組み合わせたarchitecture styleがREST
- REST以外のarchitecture style: P2P
- RESTの2つの側面
- RESTとHypermedia
- resourceをリンクで接続することで1つのapplicationを構成する
- 接続性: RESTの基幹をなす
- RESTとdistributed system
- linkをたどってapplication stateを遷移することで性能劣化を抑える.
- 統一IFにより互換の問題が起こらない.
作用
- RESTというdistributed network systemのための理論により,Webが機能する
- RESTの制約に従っていること: RESTful
Part2 URI
Ch04 URIの仕様
目的
- URI: Uniform Resource Identifier
- resourceを統一的に識別するID
概要
詳細
まとめ
Ch05 URI design
目的
概要
詳細
- Cool URI
- usability高まる
- URIの変更のためのredirect
- 拡張子でresourceの表現を特定
- 言語を指定する拡張子
- → Content Negotiationのためのbrowserの設定不要
影響
Part3 HTTP
Ch06 HTTPの基本
目的
- TCP/IPの基礎とHTTPの歴史を見る
- HTTPは以下のRESTの重要な特徴を実現する,Webの基盤となるprotocol
- 統一IF
- stateless server
- cache
概要
- TCP/IPの観点
- 階層型protocol → 層ごとに抽象化して実装
- application layer
- transport layer
- internet layer
- IPでpacket単位でdataをやり取り.IPに相当.
- 自分のnetwork IFでのdata送信の保証
- network IF層
- 物理的な部分
- 階層型protocol → 層ごとに抽象化して実装
詳細
- HTTP history
- client-serverのarchitecture style
- client ≒ user agent
- request-response型のprotocol
- @client, @server
- HTTP message: request-response message
- request messageの構成
- request line
- method, request URI, protocol version
- header
- body
- request line
- response messageの構成
- status line
- header
- body
- request messageの構成
- stateless HTTP
- application state = session state
- statefulの欠点
- client増 → scaleout difficult
- statefulの欠点
- stateless の利点
- 自己記述的messageでscaleout easy
- statelessの欠点
- performance down
- data量,冗長(認証など)
- 通信エラー
- performance down
- application state = session state
作用
- simple HTTPにより,Web ServiceとWeb APIが同じprotocolで表現
Ch07 HTTP methods
目的
- 8 methodsのうち,主要な6つのmethodsの使い方を見る
- and, HTTPの設計上の工夫を見る
- method数が少ないからこそHTTPやWebは成功
概要
- HTTP methodsの観点
詳細
- methodの使用の観点
- POSTでPUT/DELETEを代用
- _method parameter
- X-HTTP-method-override header
- 条件付きrequest
- 冪等性(idempotence)と安全性
- idempotence: PUT, DELETE
- idempotence and safe: GET, HEAD
- どちらでもない: POST
- methodのproper use
- 他methodでできることにPOSTを使わない
- PUTの冪等なuse
- DELETEの冪等なuse
- POSTでPUT/DELETEを代用
作用
- 数少ないmethodによりprotocolをsimpleに保つ
- RESTの統一IFの実現
Ch08 status code
- 観点
- status line
- status codeの分類による意味
- client-server間を疎結合に
- 先頭の数字でclientが解釈
- よく使われるcode
- status codeとerror handling
- {protocol, Accept header}に従ったformatのerror
- status codeの設計
Ch09 HTTP header
目的
- HTTPの構成要素
- method
- status code
- header
- meta dataをstandardize
- 認証やcacheを実現
- history
- headerの成り立ち
- mailと共通の部分
- mailと異なり双方向
- headerの成り立ち
概要
- 観点
- GMTでのdate
- MIME: Multipurpose Internet Mail Extensions
- Content-Type
- charset → textのときの文字化け
- Content-Language: resource表現の自然言語
- Content Negotiation: client がrequest
- Accept
- Content Length
- chunk transfer @画像などを分割
- 認証: realmの値: URI空間
- cache
- cache用headerでcontrol
- 条件付きGET
- 持続的接続 @HTTP1.1でdefault
- pipeline化
- closeで切断
- その他のHTTP header
作用
- various 技術標準の組み合わせでheaderを構成する.十分な調査によりHTTP headerを扱える.
- authenticationやcacheなどのHTTPの重要な機能を実現
Part4 HyperMediaFormat
Ch10 HTML
- HyperMediaFormatとしてのHTMLを見る
Ch11 microformats
目的
- microformatsによりlinkの細かい意味やevent informationを表現
問題
- semantics(意味論)
- program semantics
- program languageのもつ意味を確定させる理論
- Web semantics「semantics Web」
- resourceの持つ意味を確定させる理論
- program semantics
- RDFの問題とmicroformatsでの解決
概要
- microformatsのstandardize
- 分類
- elemental
- compound
- 分類
作用
- microformatsで解決できない部分
- RDFa(RDF-in-attributes)での解決
- 可能性
- microformatsによりWeb pageをそのままWeb APIとして提供
- Web page/APIの機能差少ない
- 保守・開発コスト小さい
Ch12 Atom
目的
概要
- resource model
詳細
- entryの構成
- feedの構成
- Atomの拡張
- Feedの分割
- archived feed
- Open Search
作用
- Atom: title, author, update timeなどの基本的なmeta dataを持ったresource表現のためのformat
Ch13 Atom Publishing Protocol
- Atom Publishing Protocol
- Atom Publishing Protocolのresource model
- 1つのresourceがmulti 表現
- member resourceの操作
- service document
- Atom Publishing Protocolに向いている/いないWeb API
Ch14 JSON
- JSON: hashや配列などのdata構造の記述
Part5 Web Serviceの設計
Ch15 Read Only Web Serviceの設計
目的
- resource designの観点
概要
- resource指向のarchitectureのapproachの観点
- RESTfulなWeb Serviceの性質
- addressability
- stateless
- 接続性
- 統一IF
詳細
- 各手順の観点
作用
- resource design skillの習得でよい設計
Ch16 writable Web Service
目的
- ROのServiceより観点多い
概要
- 観点
- resource create/update/delete
- batch処理
- transaction
- 排他
詳細
- create
- factory resource
- PUT作成
- 〇 作成と更新の区別不要
- × clientにURI構造流出
- update with PUT
- bulk update
- partial update → 通信料cut
- update error
- delete
- 子resource
- batch: POSTでURIを非指定
- response
- transaction
- transaction resource
- (or batchのtransaction化)
- 上位resourceへの操作
- 排他
- pessimistic lock
- LOCK/UNLOCK @WebDAV
- 独自Lock resource
- optimistic lock
- conflictを解消
- Condition PUT/DELETE
- conflictを解消
- pessimistic lock
作用
- 以下の観点でバランス
- なるべくsimple
- 別resourceで解決
- 必要ならPOST
Ch17 resource design
目的
- dataの特定とdataのresource分割のための方法を見る
内容
- 関係モデルからの導出
- data model with math的基盤
- 中心tableの1行を1 resource
- 自己記述のため非正規 → network負荷減
- resourceに必要な項目をすべて入れる
- 階層 difficult
- linkのためのER図
- Object Oriented modelからの導出
- 主要entityからresource
- 階層関係 → URI構造
- link by object reference
- top levelは別に作る
- information architectureからの導出
- information分類の観点: information architecture
- resource oriented architectureと相互補完
- information architectureがinformationを分類し,resource oriented architectureにつながる
作用
- 既存の3つの手法を,serviceとAPIを分けずに用いることで,resourceを導出できる