音楽をどのように好きか
ひとり Advent Calendar 24日目、きょうはポエムです。
音楽が好きだ。詳しくはないが。
俺はどう音楽が好きなのか、昔から考えていたけど、ここ数年で安定してきた。それは、俺は音楽に憧れ、音楽になりたいということだ。
続きを読む
いろいろな Web フロントエンドの技術
最近フロントエンドのあれこれに触ることが多い。フロントエンドといえば諸々のつらみとの戦いである。それらを解決するいろんな技術があるがいろいろありすぎてとっつきづらいので各技術が何を解決したいのかまとめてみた。
各技術の詳細は、それぞれ詳しい記事が世の中に溢れてるので省く。包括的にどんな技術があるのか、をみつめることをこの記事の価値におく。
- JavaScript フレームワーク
- JavaScript トランスパイル
- CSS トランスパイル
- テンプレートエンジン
- パッケージ管理
- モジュールバンドラー
- タスクランナー
(各技術は、それぞれ重複する部分もある;たとえばモジュールバンドラーである webpack はタスクランナー的な機能ももっている)
JavaScript フレームワーク
例
- Vue.js / AngularJS / React
何を解決するか
- JavaScript でビューを変更する / ビューの変更を受け取るときのつらみ
- ビューとロジックの分離
- ビューで変更があったらロジックが起動し、その結果を受けてビューが変更される、とかが書きやすくなる
JavaScript トランスパイル
例
- CoffeeScript / TypeScript / Babel
何を解決するか
- JavaScript の書きっぷりのつらみ
- 動的型付け言語である JavaScript に型を付けられたりする
==
を厳密に扱えたりする- 最新の ECMAScript の記法が使える
- ブラウザによって JavaScript の挙動が異なる問題も併せて。
CSS トランスパイル
例
- sass / less
何を解決するか
テンプレートエンジン
例
- Jade / Haml / Slim
- そのほかサーバーサイドの言語によっていろいろ
何を解決するか
- 静的な HTML を動的に生成したい問題
- そのほか boilerplate
- コピペで毎回書かなきゃいけないおまじない的なやつとか
<
>
はタイピングのコストが高いので避けようとしてるものが多い
パッケージ管理
例
- npm / bower / yarn
何を解決するか
- JavaScript のライブラリ管理
- 欲しいライブラリをわざわざダウンロードしたり、クライアントに CDN にアクセスさせたりするコスト
- ライブラリ間の依存性も解決できる
- このライブラリを使うためにはこのライブラリが必要で...とか、バージョンが新しくなって互換性がなくなって...とかの (yak shaving)http://blogos.com/article/65001/
モジュールバンドル
例
- webpack / browserify
何を解決するか
- JavaScript / CSS を使用するためには HTML でどのファイルを使用するか指定する必要がある
- 複数のファイルをまとめて
hogehoge.bundle.js
みたいなファイルにして、これさえ読み込めば OK、という体制にしてくれる - クライアントからのリクエストも減る
- 複数のファイルをまとめて
- JavaScript / CSS のサイズが大きいとクライアント側にダウンロードの負荷がかかる
- 改行とか無駄な記述をなくしてくれる (minify という)
タスクランナー
例
- gulp / Grunt
何を解決するか
- 上述してきたツール群の多くは、コマンドを叩かなきゃ機能しない
- たとえばファイルが保存されたら勝手にコマンドを起動する、とかの処理を記述できる
Node.js で Elasticsearch にクエリ
Elasticsearch の公式クライアントで叩く。
const elasticsearch = require('elasticsearch'); const client = new elasticsearch.Client({ host: 'http://localhost:9200' httpAuth: 'user:password' log: 'trace' }); client.search({ index: index, type: type, size: size, body: { _source: [ // to be included fields ], aggs: { // aggregation contents }, query:{ // query contents } } });
直で REST API 叩く時とちょっとだけ違っていて、 query や aggs の前に body
を挟む必要があったりするので注意。
.search
の戻り値は Promise になっていて、中身はこんな以下のように取得する。これは REST API の戻り値と (たぶん) おなじ。
client.search().then(response => { const documents = response.hits.hits.(x=>x._source); const aggregated = response.aggregations; // ... });
当然、
function get() { return client.search().then(response => return response;) } get().then(result => { // ... });
とか、
const result = await client.search();
とか書ける。
Scroll API で取得したい場合はちょっと違って
let documents = []; client.search({ index: index, type: type, size: size, scroll: chacheTime body: { query:{ // query contents } } }, function scroll(error, response) { documents = documents.concat(response.hits.hits); if(response.hits.total !== documents.length) { client.scroll({ scrollId: response._scroll_id, scroll: cacheTime }, scroll) } else { return documents; } });
のようになる。この戻り値が Promise とならず、 client.search({...}, function(){...}).then()
のように書けない。なので 上述の例と同じように扱いたければ
const promise = new Promise((resolve, reject) => { let documents = []; client.search({ // ... }, function scroll(error, response) { documents = documents.concat(response.hits.hits); if(response.hits.total !== documents.length) { client.scroll({ scrollId: response._scroll_id, scroll: cacheTime }, scroll) } else { resolve(documents); } }) })
と Promise オブジェクトを new してやる必要がある。
これはもっとスマートに解決できる方法があるかも?
Array.prototype.reduce() に親しむ
JavaScript の配列に reduce という関数がある。 MDM のドキュメント によると以下のように書かれている。
arrayObj.reduce(function(previousValue, currentValue, index, array){ // ... })
previous とか current いわれてもよくわからん。。 ただ、感覚を掴んでくるとこいつがなかなか便利だ。
たとえば、配列をループの中で処理する場合、そのままだと二重ループになっちゃって計算量がかさむってことがある。なので事前に配列じゃなくて連想配列だと嬉しい。そんなとき、こいつを使うと配列を連想配列に変換することができる。
array.reduce((map, obj) => { map(obj.key) = obj; return map; }, {});
また Object.assign()
とも相性がいい。これは、第一引数のオブジェクトに第二引数のオブジェクトをくっつけることができるというものだ。なので、たとえばオブジェクトの配列
const array = [ { "1" : { ... }, } { "2" : { ... } } ]
を使って
const result = array.reduce((map, obj) => { Object.assign(map, obj); }, {});
すると、
result = { "hoge" : { ... }, "fuga" : { ... } }
のように変換できる。たとえば Node.js でデータを配列として取得して、 key-value として扱いたいってときに超便利。
Node.js × TypeScript 勉強中 (2)
Node.js × TypeScript 勉強中 - take a keen edge から続いた。
JavaScript の拡張メソッド (って呼ぶの?) 書くときはこうなる。
Array.prototype.chunk = function (size) { if (!this.length) return []; return [this.slice(0, size)].concat(this.slice(size).chunk(size)); }
で、 Node.js でこいつを別ファイルに切り出したい。そんなときは、
Array.prototype.chunk = function (size) { ... } exports = Array;
として、呼び出し側で
require('arrayExtensions'); function hoge(array) { const chunked = array.chunk(100); }
してやる。モジュールじゃないので const extenstions = require('arrayExtensions')
する必要はない。 TypeScript でいうと import extensions = require('arrayExtensions')
みたいに書くと怒られる。
コピペばっかしてると import とか require とかがどの文脈のものなのかわからなくて詰みそうなところである。
ちなみに TypeScript の拡張メソッド (?) は ↑ だと怒られて、 interface を切る必要がある。
interface Array<T> { chunk(size: number): Array<T>; } Array.prototype.chunk = function (size) { ... } exports = Array;
打ち合わせで実現したいこと
良い打ち合わせは自然とは生まれないものです。自戒の意味も込めて考え直してみました。
参加者と、いわゆるファシリテーターの役割がごっちゃになっているので注意が必要かもしれません。
- 目的を明確にする
- 何のために集まっているか?
- 情報を知ってもらう / 案を出す / 決断する(どれか1つの場合もあるし、複数の場合もある)
- 進行する
- 上記の目的が複数に該当する場合、いまどの段階なのか意識する
- 参加者に意識してもらう、も大事
- 意見が少ない(が、何か言いたそうな)人にタイミングよく振る
- ある観点で情報が充足してきたら観点を増やす
- 意見が盛り上がらなかったとき用の話題を出す
- 事前に用意しとく
- 上記の目的が複数に該当する場合、いまどの段階なのか意識する
- 次の行動を決める
- 誰が / いつまで / 何を
- 何を、はとくに曖昧になりがち;参加者全員で具体的に認識をあわせることが理想
- もし早く終わったらさっさと終わる
- 誰が / いつまで / 何を
- 上記を準備しとく
- できれば事前に展開しとく
これらは文字にしたら誰にとっても当然なことに見えると思いますが、なかなか(部分的にですら)達成された打ち合わせには出会えません。
あと、教科書的にはこれらを「常に意識しましょう」とか言いたくなりますが、何かを常に意識するなんて(少なくとも自分には)不可能なので、チェックポイント的に時間を区切って確認する、とかの技術も別途必要ですね。
ドヴォルザークの序曲「オセロ」について
ドヴォルザークの序曲「オセロ」作品93は、ここ数年で出会ったクラシック曲の中で断トツに好きな曲だ。
この曲は序曲3部作の3曲目らしい。2曲目はドヴォルザークの作品の中でも有名な「謝肉祭」。アマチュアオケの演奏会情報を掲載されている i-Amabile さん をみてみると、これまでの演奏回数は2017年12月19日現在で「謝肉祭」が119回、「オセロ」が11回と、10倍以上の差がある。たしかに、謝肉祭と比べられたら派手さは少ない。というか地味。
そんな地味なこの曲のどこが好きなのかというと、上の音源でいうと序盤である4:00以降に現れる、映画音楽的な勇ましい旋律、この旋律が一瞬で終わってその後同じ形では二度と登場しないところ。 こんなに格好いいのに。チャイコフスキーだったらこれをもう2、3回は使ってるよ。8:30あたりでもう一度現れると思いきや肩透かし。9:50あたりから、すこし形を変えて登場。でもあの頃の姿じゃない。コーダでついに来るか!と思ったらやっぱり来ない。で、ドヴォルザーク特有のアクロバティックなコード進行で突然終わり!
で聴き終わって、あの旋律がまた聴きたくなるんだ... 序盤にいいところを持ってきて、期待感を膨らませたまま、そのカタルシスを解放させるでもなく終わる。もしこれが映画だったら不快だろう。でも音楽なんだから、そのまま繰り返しても誰も文句を言わないはずだ。しかしドヴォルザークはそうせず、敢えて手間をかけて変奏した。1回聴いただけでは満足できない音楽体験、それを彼は目指していたんだ(本当か?)。
それでいて、何回も聴いているうちに、前奏も内声が充実しててクソ良いことに気づいたり、各楽器のソロ、アンサンブルがめっちゃ良かったり、そういえばドヴォルザークのここまで洗練されて劇的な曲って知らないかも?と思いはじめたり、「ここ完全に新世界じゃん!」とツッコミをいれたり(オセロと新世界は作曲時期が重複している;新世界のほうが完成が3年ほど後)、いろいろな楽しみ方ができるようになっている。
いつか演奏したい。