たれぱんのびぼーろく

わたしの備忘録、生物学とプログラミングが多いかも

Do -> Check -> Action -> Plan -> Do

PDCAじゃなくてDCAPD

サイクルは道具。
Doから生まれる価値&知識が全て。
2度とDoしないならほぼ意味がない (他へ流用できる知識が残るならまだ良い)
Doして学んでDo、これが基本形.
Checkは検査・現状把握、Actionは適応

Do -> (CAP) -> Do

do -> (working well) ------------------------------> do
   -> (not working)  -> check -> action -> plan -|

えいやでやって(do)うまくいくならplanなんかいらない、doし続ければそれでいい
->「100%上手くいく」とわかっている場合に計画を立てる妥当性
こけたときに必要に応じて導入するのが大事
えいやでうまくいかないから具体化した目標を立てる

アジャイルソフトウェア開発

宣言の理解

from Manifesto for Agile Software Development

.4. Responding to change over following a plan
より重きを置くのは、変化への応答

from Principles behind the Agile Manifesto

.1. Our highest priority is to satisfy the customer through early and continuous delivery of valuable software.
ソフトウェアによる価値提供→顧客満足

.2. Welcome changing requirements, even late in development. Agile processes harness change for the customer's competitive advantage.
「要件の変化を歓迎する、たとえ開発後期であっても。顧客の競合優位性を高めるために、アジャイルプロセスは変化を駆動力とする。」

.3. Deliver working software frequently, from a couple of weeks to a couple of months, with a preference to the shorter timescale.
CI/CDで当たり前の時代。浸透し切ったし、期間はもっと短い感じ

.7. Working software is the primary measure of progress.
動くソフトウェアが第一の評価指標

.10. Simplicity--the art of maximizing the amount of work not done--is essential.
日本語訳あんまり納得いってない (Twitterに対訳書いた)

解釈

Px: Principle x
Mx: Manifest x

変化

要件の変化を力とする (P2)。
変化を前提としないとこの文言は出てこない (稀な変化を重視するのは合理的でない)。
要件は環境の変化で変わる。要件は実装してみて明確になる。要件は運用してみて価値が分かる。要件は変わる。

要件が明確化することで変化した場合、明確化した要件に合わせればよい良いものが出来る。
実装して要件が不要なものだと判明したら、要件を取り下げればより良いものが出来る。
俊敏な変化は柔軟な強さの秘訣。

c.f. 変化ヲ抱擁セヨ

https://mobile.twitter.com/hiranabe/status/315435868057919488

http://objectclub.jp/community/XP-jp/xp_relate/xp-intro

要件

要件は道具。
要件を満たすことそのものは最優先ではない。最優先は価値提供→顧客満足 (P1)。
動かしたソフトウェア (P7) が顧客を満足させるか否かが最重要事項。

じゃあ道具たる要件の定義とは何か。
=> 明文化された、ソフトウェアに求められる要素。

要件=顧客満足に繋がり、明文化された、ソフトウェアに求められる要素。
でもリストアップしたものが要件か否か (顧客満足を生むか) は検証=運用しないとわからない。
=> “要件仮説”

仮説なんだから間違ってて当然。間違ってたら変えるのが当然。
仮説なんだから理解が深まったらより具体化して当然。具体化できるから仮説変えるのが当然。

なんかこう、requirementsって言われると、満たすべきもの・満たしたらOKって意味合いが凄い。
仮説に過ぎないんだから仮説って言ったほうがいいと思う。
software requirements for customer satisfaction
requirement hypothesis
仮説検証

c.f. 古典的な受託開発
要件を満たすことへ対価をもらうモデル.
要件が曖昧だと対価が曖昧になっちゃうので、要件はバッチリ決める必要がある。
要件仮説のはずなのに仮説を動かせなくなるため、仮説が間違ってたら悲惨なことに。
仮説を動かすためには対価を動かす必要があり、やれ契約変更だなんだと揉めるので、仮説なのに仮説を動かさないインセンティブが働いちゃう.

対価が曖昧: 「情シス: これくらいの修正は要件内でしょ」「ベンダー: いや、要件に無いもの足すのは新規見積もりを…」「いやいや」

c.f. コミットメント

効果的な静的コード解析

  • lint結果を無視したくなる心理
    • もう使っていないコードへの指摘
    • でけぇモノの1部をいじるコードであって一部以外の安全とわかりきっている部分をショートカットしたい

リファクタリングをしておかないと静的コード解析を無視し始める、非常に良くない.

派生作品とリスペクト

私の好み:
派生作品の場合、元ネタを良い方向で扱う.

私の好まない:
派生作品が元ネタをdisる、元ネタに物申す

基本スタンス: 好きなものを推せ、好きでないものは「こういうのが好きな人もたぶん居るんだと思う」と思ってノータッチ。disるくらいなら自分で好きなバージョンを作れ。創作前提じゃない批判は優先度が低い。そういう批判に目くじらたてるほど人生余ってない。

Node.jsでもimport/exportは動く

Node.jsでES Modulesがネイティブに動く時代なのです。

Working Code

// package.json
{
  "type": "module",
}

// eptESM.js
export const f1 = () => 1;

// eptCJS.cjs
const f2 = () => 2;
module.exports = f2;

// ipt.js
import { f1 } from "./eptESM.js";
import f2 from "./eptCJS.cjs";
console.log(f1()); // 1
console.log(f2()); // 2

TypeScriptと組み合わせた時の注意点

拡張子がデフォルトだと必須なため import x from "./m.ts になるんだけど、TSのコンパイラはコードに触らないデザインなので拡張子を変換してくれない(import x from "./m.jsに変換してくれない)
1つの選択肢は 「拡張子無しで書いてtscコンパイル -> --experimental-specifier-resolution=nodeフラグを建ててNode.js実行」
Babelとかで良い感じにmodule resolutionしてもらうという手もありそうだけど調べてない.

web app manifestは実体として何をするのか

  1. ユーザーエージェントへ「ネイティブアプリぽいUXでwebアプリを動かす」ためのメタデータを渡す

インストールできるんじゃないの?

manifestを含むwebページを用意しインストール、機内モードにした上でブラウザキャッシュを消し、インストールされたwebアプリを立ち上げると通信エラーでページが開かない.
すなわち、manifestはweb app実体(index.htmlを始めとするコード)をマシンにインストールはしない.
(キャッシュを残しておくと機内モードでも動く。ハマった。ブラウザはなんて優秀なんだ.)

じゃあ何しているの?

ブラウザ(ユーザーエージェント, UA)に「このメタデータに基づきネイティブアプリっぽく起動してね」とお願いしてる.

(典型的には)ユーザーがweb appアイコンをクリックし、UAはmanifestに基づいてtop-level browsing contextを設定、start URLへナビゲート(通常のHTTPSアクセス)する.

startURL = parse(start_url, manifestURL) ?? documentURL

start URL , which is URL that the developer would prefer the user agent load when the user launches the web application (e.g., when the user clicks on the icon of the web application from a device's application menu or homescreen).
The start_url member is purely advisory, and a user agent MAY ignore it or provide the end-user the choice not to make use of it. A user agent MAY also allow the end-user to modify the URL when, for instance, a bookmark for the web application is being created or any time thereafter.

オフラインでも動いてるやつあるけどあれなにさ

Cache API on Service Workerです.

Abstract of Spec

  • Definition: web app manifest === JSON with defined format
  • Purpose: centralized place to put metadata associated with a web application
  • Metadata examples
    • application's name
    • links to icons
    • preferred URL to open when a user launches the web application
    • default screen orientation
    • display mode
      • in fullscreen
    • "scope" a web application to a URL
      • This restricts the URLs to which the manifest is applied and provides a means to "deep link" into a web application from other applications.
  • Usage
    • user agents: create user experiences that are more comparable to that of a native application

mocking with Jest

spy と stub の両機能を達成するために、spy 可能なフックを持ちつつ返り値を実装できるmock functionが提供されている.

spy としての利用: 何回 call されたとか、spy での入出力とか
stub としての利用: 値を吐き出す

APIs

mock

  • jest.fn(): mock function (mockFn) generation

  • mockFn.mock.instances: mock function list

  • mockFn.mockClear(): clear the mock function's spy results
  • mockFn.mockReset(): clear the mock function's spy results & stub functionality
  • mockFn.mockRestore(): mockFn.mockReset() and restore original/non-mocked functionality

spy functionality

  • mockFn.mock.calls: spy call arguments
  • mockFn.mock.results: spy result (status & value, e.g. return & 5, throw & Error("hello"))

stub functionality

mockFn.mockImplementation[Once](implementation)

stub suger syntaxes

  • mockFn.mockReturnValue[Once](value): suger of () => value implementation
  • mockFn.mockReturnThis(): suger of () => this implementation
  • mockFn.mockResolvedValue[Once](value): suger of () => Promise.resolve(value) implementation
  • mockFn.mockRejectedValue[Once](): suger of () => Promise.reject(value) implementation

Usage

Spy

do spy -> expect(mock.calls)

関数を引数として渡す場合にspyを渡して記録が可能.