@ledsun blog

無味の味は佳境に入らざればすなわち知れず

はてなブックマーカによる「凄い面白いファンタジー小説」

anond.hatelabo.jp

についた

b.hatena.ne.jp

ブックマークコメントを、趣味と実益を兼ねて集計しました。

ベスト3

  1. 十二国記 37票
  2. 守り人シリーズ 14票
  3. ゲド戦記 14票

十二国記

強い

  1. kangiren: 十二国記
  2. pucchon: 十二国記ブレイブ・ストーリー精霊の守り人、空色勾玉、図書館の魔女
  3. rikine': 日帰りクエスト、フォーチュンクエスト、龍と魔法使い、ちょーシリーズとかは若い頃好きだったな。大人が読むのならオススメはやっぱり十二国記。ほとんど読まなくなったけど、またファンタジー読みたくなるブクマだ
  4. rocoroco3310': ミヒャエルエンデ一通り読むだけで幸せが持続する。日本人なら柏葉幸子の霧の向こうのふしぎな街とか。十二国記もいいし梨木香歩好きなら裏庭もいいし宮部みゆきブレイブストーリーも…ああ時間が欲しい
  5. cubed-l: 十二国記はてしない物語もモモもグリムガルも後宮小説も挙がっているとなると俺は何を挙げれば…
  6. hachibeechan: ライラの冒険シリーズはマジで最高。あと日本人作家だと十二国記
  7. imaginaration': 『十二国記』は世界観や登場人物がいいんだよなぁ。。しかし完結するのか、コレ…が一番の悩み。。『ゲーム・オブ・スローンズ』は映像を観るのがよさそう、てかおもろい!
  8. shields-pikes: 十二国記そんなに面白いのか。Kindleで読んでみるか。
  9. asobime: 定番だけど、十二国記、勾玉シリーズ、図書館の魔女、守人シリーズ。
  10. Nice_Pubo': やっぱファンタジーならゲド戦記十二国記、卵王子(カイルロッドの苦難)。恋愛系ならちょーシリーズ(ちょー美女と野獣)かなぁ? ファンタジーおいしいれす(^q^)
  11. RondonZoo: 十二国記を勧めるコメの後ろにうっすら見える(ようこそ煉獄へ)
  12. udonmotch': 十二国記守り人シリーズは出てますよねーそうですよねー/毒味師イレーナ、好きな人なら好きだと思う。女子のどん底からの成り上がり&ステータスチートだけど恋に不器用なツンデレ男子との恋が好きなら、ぜひ
  13. yuzumikan15: 十二国記、の、特に慶国女王が出てくる話はどれも面白くて愛おしい
  14. mottie0911': 既出だけど、やっぱり十二国記は外せないと思う。完結してないけど、1巻1巻で楽しめる面白さがある。他には「ばいばい、アース」や「されど罪人は竜と踊る」とか私は好き。恋愛者なら彩雲国物語がおすすめかな…
  15. ponnao: ほんとに十二国記をまだ読んでないとは幸せ
  16. matarillo': ナルニアゲド戦記、魔法の国ザンス、エルリック・サーガ、クラバート、はてしない物語、モモ、十二国記、トムは真夜中の庭で、ダレン・シャン
  17. otihateten3510': 増田のリストを参考にする。/ 十二国記って進んだの? 止まってるって聞いたから読んでない
  18. Aodrey': トラバもブクマもすごく俺得。増田の挙げている本で読んでないの多いから読んでみたい。わたしからは既出だけど十二国記推す。
  19. heartbook: 十二国記アルスラーン戦記
  20. e-takeuchi': 『十二国記』は中途半端なところで止まってるんでおすすめできない。完結して欲しいと思うが、無理かな。
  21. redmagic1417': 十二国記支持されすぎw 一応もし未読ならロードス島伝説。恋愛ありのラノベであれば、ダンまち灰と幻想のグリムガルは割りと一気に読んだ。デルフィニア戦記は忘れがちだけど良い。
  22. and_hyphen': 「守り人シリーズ」「R.D.G」シリーズ、恥ずかしながら私も全部は読んでないけど「十二国記」シリーズ、「ナルニア国物語」シリーズ、「はてしない物語」こんなところ?
  23. dalk': ばいばい、アース。ヴォイド・シェイパ十二国記 (東の海神 西の滄海)。精霊の守り人(影の守り人)。和風Wizardry純情派。SORCERIANの説明書。
  24. htnmiki: 十二国記精霊の守り人だな。既出すぎるが。
  25. takamurasachi': 無職転生だな。ネットで無料で読める。十二国記すすめてる人多いけど、恋愛要素はほとんどないよ、面白いけどさ
  26. skip_jack': 毛利志生子風の王国」をどうぞ。切ない恋愛要素を含んだ歴史ファンタジーです。十二国記は未完なので勧め難いんですよね…。
  27. xap: 十二国記と卵王子カイルロッドは読まなきゃ損だよね。
  28. jack_oo_lantern: 十二国記読んでないなんて本当にラッキー
  29. white_cake': 既に出てるけどダイアナ・ウィン・ジョーンズ! 精霊の守り人。五神教シリーズ。十二国記ゲド戦記氷と炎の歌。あたりかなあ。メアリー・ポピンズとかも大好き。
  30. ushibito153': 十二国記流血女神伝をお勧めします。少女小説から始まった傑作です。BLに抵抗のない方にはやさしい竜の殺し方もお勧めです。
  31. hayaita: 十二国記だなあ。恋愛じゃないけど
  32. noki_e: こういうときに十二国記を勧めていいものか悩む(渇きの海的な意味で)
  33. amui': 十二国記精霊の守り人は鉄板だけど、宮部みゆきさんのブレイブストーリーがいいんじゃないかなー。 恋愛ものが好きなら空色勾玉やRDGなどの荻原規子さん作品も。
  34. asahiufo: 十二国記がいい。震える。
  35. roshi: 既に上がってるけど「十二国記」と「精霊の守り人」かなー。空色勾玉は積読してる。他の作品も気になる。
  36. rin51: 「十二国記」「精霊の守り人」どうすか/空鐘いいよね
  37. rain-tree': まだ十二国記を読んでないなんて幸せな増田だなあ。あと早川FTなら一番最初にでた妖女サイベルの呼び声があるじゃないか。あとは西の善き魔女とか(若い子でないときついかも)。まだまだ沢山ありそうでうらやましい

守り人シリーズ

知名度高い

  1. techonair: 勾玉3部作と呼ばれる『空色勾玉』『白鳥異伝』『薄紅天女』、続編じゃないけど繋がりを感じる『風神秘妙』。作者違うけど『精霊の守り人』も似た雰囲気。増田の趣味に合うかわからないけどおススメ。/既に出てた。
  2. pucchon: 十二国記ブレイブ・ストーリー精霊の守り人、空色勾玉、図書館の魔女
  3. hisamura75: 『魔の都の二剣士』収録の第3篇『凶運の都ランクマー』をまず読んでほしい/『守り人』シリーズのバルサとタンダみたいな微妙な距離感が好き。
  4. udonmotch: 十二国記守り人シリーズは出てますよねーそうですよねー/毒味師イレーナ、好きな人なら好きだと思う。女子のどん底からの成り上がり&ステータスチートだけど恋に不器用なツンデレ男子との恋が好きなら、ぜひ
  5. yamadar: 恋愛ならば、SFになってしまうが「星界の紋章」を推したい。恋愛要素薄めだけど面白いのは「精霊の守り人」、「はてしない物語」など。それからサクッと読める一巻完結の「旅のラゴス」。
  6. and_hyphen: 「守り人シリーズ」「R.D.G」シリーズ、恥ずかしながら私も全部は読んでないけど「十二国記」シリーズ、「ナルニア国物語」シリーズ、「はてしない物語」こんなところ?
  7. dalk: ばいばい、アース。ヴォイド・シェイパ十二国記 (東の海神 西の滄海)。精霊の守り人(影の守り人)。和風Wizardry純情派。SORCERIANの説明書。
  8. htnmiki: 十二国記精霊の守り人だな。既出すぎるが。
  9. anguilla: ゲド戦記守り人シリーズが好き。
  10. white_cake: 既に出てるけどダイアナ・ウィン・ジョーンズ! 精霊の守り人。五神教シリーズ。十二国記ゲド戦記氷と炎の歌。あたりかなあ。メアリー・ポピンズとかも大好き。
  11. amui: 十二国記精霊の守り人は鉄板だけど、宮部みゆきさんのブレイブストーリーがいいんじゃないかなー。 恋愛ものが好きなら空色勾玉やRDGなどの荻原規子さん作品も。
  12. roshi: 既に上がってるけど「十二国記」と「精霊の守り人」かなー。空色勾玉は積読してる。他の作品も気になる。
  13. tengo1985: とりあえず上橋菜穂子読めばいい。
  14. rin51: 「十二国記」「精霊の守り人」どうすか/空鐘いいよね

ゲド戦記

三大ファンタジー

  1. qt_fb: ゲド戦記は4巻以降のほうがむしろ楽しめた派
  2. fukurow57: ゲド戦記。1~3まで一気読みオススメ(それ以降は…まぁ…)。
  3. mionhi: 『ハウルの動く城』が何故居ない恋愛物としての指定もバッチリだ!『ゲド戦記』や『ナルニア国物語』も読んでないみたいだから一応書いておきます。なろう系で恋愛なら『妹が勇者になりました』を勧めておきます
  4. Nice_Pubo: やっぱファンタジーならゲド戦記十二国記、卵王子(カイルロッドの苦難)。恋愛系ならちょーシリーズ(ちょー美女と野獣)かなぁ? ファンタジーおいしいれす(^q^)
  5. You-me: 指輪物語読んでるならあと「ホビット」と「ゲド戦記」と「パーンの竜騎士」「魔法の国ザンス」は読んでおきたい感じかな/グインサーガも二十巻台くらいまでは勧めて大丈夫じゃないですかね(小声
  6. babelap: ゲド戦記は魔法の在り様の描写がとても好きであるよ。(一巻だね)
  7. matarillo: ナルニアゲド戦記、魔法の国ザンス、エルリック・サーガ、クラバート、はてしない物語、モモ、十二国記、トムは真夜中の庭で、ダレン・シャン
  8. kotoripiyopiyo: この場合ベストとしてはドラゴンランス戦記/ドラゴンランス伝説を推すけど、ゲド戦記1〜4巻、モモ、アルスラーン戦記アルケミスト、まおゆう、ゲートなどなどもオススメ
  9. nomitori: 「ゲド戦記」「ホビット」「魔法の国が消えていく」
  10. anguilla: ゲド戦記守り人シリーズが好き。
  11. white_cake: 既に出てるけどダイアナ・ウィン・ジョーンズ! 精霊の守り人。五神教シリーズ。十二国記ゲド戦記氷と炎の歌。あたりかなあ。メアリー・ポピンズとかも大好き。
  12. Alceste: 古典大丈夫なら、ゲド(一巻)、エルリック(ストームブリンガーまで我慢)、永遠のチャンピオン、コブナント、ロードダンセイニ。次点でファファード、ディルヴィシュ、サイベル、ザンスあたりはどうか。
  13. sekisetsu_ibuki: ゲド戦記が地味に面白かった。
  14. about42: ゲド戦記:1巻は学園モノ、2巻のアルハは強烈なツンデレ。アニメ化もされたよ!/ハザール辞典:辞典型小説、間違いなくラブストーリー。

4位以下

ドラゴンランス

ナイトブリンガー!

  1. nishik-t': 手に入るかわからないけど「ドラゴンランス」シリーズを推しておきます。未だにクソアメコミ風映画以外の映像化してないのが不思議。
  2. hate_flag': 『ドラゴンランス戦記』を読むんだ。フィズバンはかっこいいジジイだしレイストリンはひねくれてるしティカは美人だしタッスルホッフバーフットはかわいい。キャラがみんな生き生きしてるのでとてもよい。
  3. mousou_denka': ドラゴンランス戦記、ドラゴンランス伝説、魂の戦争がいいよ!最終決戦直前で、主人公が元カノとベッドでいちゃいちゃしてしまって、後世まで語り継がれてしまうヒドさ!
  4. m-naze': 自分の手で物語を紡げるテーブルトークという仕組みを知ってからはどんな小説も物足りなくなる(なった)のでお勧め。(しない。)/D&Dやれば指環・ロードス・ドラゴンランスの世界に行けると衝撃を受けて早30年…。
  5. kotoripiyopiyo': この場合ベストとしてはドラゴンランス戦記/ドラゴンランス伝説を推すけど、ゲド戦記1〜4巻、モモ、アルスラーン戦記アルケミスト、まおゆう、ゲートなどなどもオススメ
  6. k-holy': ドラゴンランス戦記&ドラゴンランス伝説。世界の危機を救う冒険の中に様々な愛憎関係が描かれてて面白いよ。子供向け小説になってて表紙の変わりようにビックリしたけど、あれまだ続いてるのかな?
  7. tano13', 'なつかしい。ドラゴンランスは面白かったな。ダークソードも。アニメではダンバイン一択
  8. agano', 'ドラゴンランス戦記を推しておきます
  9. ichiken7', 'ドラゴンランス戦記
  10. YukeSkywalker', 'ドラゴンランス
  11. shibaone': ゲームブック「ソーサリー!!」4作。小説指定だが敢えて。和製、佐藤さとる「誰も知らない小さな国」。そして「ドラゴンランス戦記」。
  12. no__future', 'ドラゴンランス

魔法の国ザンス

恥ずかしながら知らなかった。読んでみます。

  1. kowyoshi: ルーチンワークっぽくなる前の「魔法の国ザンス」
  2. bjita: とっくに出てるけど魔法王国ザンスシリーズ。ジョジョとかの能力系バトル物の元祖だと思ってる。その上で無能力者が主人公の一作目の面白さが素晴らしい。あとダジャレ。
  3. Iridium: 「魔法の国ザンス」って変なところでエロいからいいよね
  4. You-me: 指輪物語読んでるならあと「ホビット」と「ゲド戦記」と「パーンの竜騎士」「魔法の国ザンス」は読んでおきたい感じかな/グインサーガも二十巻台くらいまでは勧めて大丈夫じゃないですかね(小声
  5. snowcrush: ここまで氷と炎の歌なしってマジ?// 下コメで出てた // 恋愛物?だと「烏に単は似合わない」、「カメレオンの呪文」かな。
  6. matarillo: ナルニアゲド戦記、魔法の国ザンス、エルリック・サーガ、クラバート、はてしない物語、モモ、十二国記、トムは真夜中の庭で、ダレン・シャン
  7. sbedit1234: この方向だとザンスシリーズ一択ざんす。私は絨毯世界のあたりで飽きたが。
  8. jitojito: ザンス推しかな。ゲームのノベライズだけど「風よ。龍に届いているか」とか恋愛要素あるね。
  9. hobbling: 恋愛ものと言うと、一巻ごとにカップルが出来る魔法の国ザンス。つーか邦訳21巻、原作40巻まで行ったのか。
  10. son_toku: 魔法の国ザンス(小声)
  11. Alceste: 古典大丈夫なら、ゲド(一巻)、エルリック(ストームブリンガーまで我慢)、永遠のチャンピオン、コブナント、ロードダンセイニ。次点でファファード、ディルヴィシュ、サイベル、ザンスあたりはどうか。

本好きの下剋上

なろう小説読んだことないです。

  1. furan: 既に出てるけどやっぱり「本好きの下剋上」がオススメ。男女ともに楽しめると思う。Web原作が完結済みなので安心。
  2. hiduki001', '本好きの下剋上、面白いけど文章がけっこうおかしいから気をつけろよな!
  3. accent_32: なろう系完結済で好きなの上位から「無職転生」「本好きの下剋上」「うちの娘の為ならば、俺はもしかしたら魔王も倒せるかもしれない 。」「ギルドの新人教育係(自称)」
  4. kagakaoru', '『本好きの下克上』をこれから読める増田に祝福を。
  5. khtokage: あんまり古典ファンタジー読んでないからお勧め出来そうなものが思いつかない…… なろう系なら「本好きの下剋上」と「無職転生」かな。
  6. suimin28', '本好きの下剋上はコミカライズ版読んでるけど恋愛要素ほとんど無い気が…原作はそうでもないのかな
  7. himakao: 本好きの下剋上は転生モノって題材を活かしてファンタジー世界の価値観常識のズレの描写がすごく多くて好き。
  8. n314: 本好きの下剋上ってなろうで一番面白いのに名前上がらないなあと思ってたけどここ見て分かった。あれ異世界転生チートものじゃなくて恋愛ファンタジーものなのな。
  9. beiru', '本好きの下剋上...と言おうとしたらもう出てた
  10. bunkyouku: 本好きの下剋上 ファンタジーの中では異色の本好き女子が主人公なのに王道路線にみえる異世界ファンタジー 世界観がはんぱなくすごい

はてしない物語

ネバーエンディングストーリー

  1. rocoroco3310: ミヒャエルエンデ一通り読むだけで幸せが持続する。日本人なら柏葉幸子の霧の向こうのふしぎな街とか。十二国記もいいし梨木香歩好きなら裏庭もいいし宮部みゆきブレイブストーリーも…ああ時間が欲しい
  2. cubed-l: 十二国記はてしない物語もモモもグリムガルも後宮小説も挙がっているとなると俺は何を挙げれば…
  3. jou2: 「はてしない物語」の作者、ミヒャエル・エンデが書いた「鏡の中の鏡」。イチオシです。ファンタジーって言うか短編集だけど
  4. wwweric: すでにでてるけど、「はてしない物語」「モモ」「魔法のカクテル」「オズの魔法使いシリーズ」
  5. matarillo: ナルニアゲド戦記、魔法の国ザンス、エルリック・サーガ、クラバート、はてしない物語、モモ、十二国記、トムは真夜中の庭で、ダレン・シャン
  6. yamadar: 恋愛ならば、SFになってしまうが「星界の紋章」を推したい。恋愛要素薄めだけど面白いのは「精霊の守り人」、「はてしない物語」など。それからサクッと読める一巻完結の「旅のラゴス」。
  7. and_hyphen: 「守り人シリーズ」「R.D.G」シリーズ、恥ずかしながら私も全部は読んでないけど「十二国記」シリーズ、「ナルニア国物語」シリーズ、「はてしない物語」こんなところ?
  8. Nfm4yxnW8: 「はてしない物語」を"単行本で"読むのがオススメ。古本ならさらに良い。
  9. hazardprofile: 指輪読んだら『ホビットの冒険』から『ナルニア国物語』『はてしない物語』 恋愛含なら『クレヨン王国月のたまご)』とか復刊.comで復活させた『海時間のマリン』とか 勾玉も何度も読んだな ただこれ全部児童書
  10. sirobu: はてしない物語

ナルニア国物語

三大ファンタジー最後の将

  1. mionhi: 『ハウルの動く城』が何故居ない恋愛物としての指定もバッチリだ!『ゲド戦記』や『ナルニア国物語』も読んでないみたいだから一応書いておきます。なろう系で恋愛なら『妹が勇者になりました』を勧めておきます
  2. soyogon: 恋愛ものではないし児童書だけどファンタジーといえば、わたりむつこの「はなはなみんみ物語」「ゆらぎの詩の物語」「よみがえる魔法の物語」の3部作は珠玉の逸品。これとナルニアは個人的ファンタジーバイブル。
  3. kamanobe: SFやミステリはともかくFTみたいに歴史が長いジャンルで指輪とかナルニアとかが「古典」って言われてるのは妙な違和感あるな。/ふと検索したらジョージ・マクドナルドの表紙がokamaで吹いたけど振り返れば竹宮恵子
  4. osiripenpenski: ナルニアハリーポッター好きなら、ジョーン・エイケンのおおかみ年代記シリーズをぜひ。
  5. crime577: ナルニア国物語はガチハマリした
  6. matarillo: ナルニアゲド戦記、魔法の国ザンス、エルリック・サーガ、クラバート、はてしない物語、モモ、十二国記、トムは真夜中の庭で、ダレン・シャン
  7. and_hyphen: 「守り人シリーズ」「R.D.G」シリーズ、恥ずかしながら私も全部は読んでないけど「十二国記」シリーズ、「ナルニア国物語」シリーズ、「はてしない物語」こんなところ?
  8. t-oblate: デラックス押し入れの冒険ことナルニア物語おすすめ
  9. hazardprofile: 指輪読んだら『ホビットの冒険』から『ナルニア国物語』『はてしない物語』 恋愛含なら『クレヨン王国月のたまご)』とか復刊.comで復活させた『海時間のマリン』とか 勾玉も何度も読んだな ただこれ全部児童書

勾玉シリーズ

  1. techonair: 勾玉3部作と呼ばれる『空色勾玉』『白鳥異伝』『薄紅天女』、続編じゃないけど繋がりを感じる『風神秘妙』。作者違うけど『精霊の守り人』も似た雰囲気。増田の趣味に合うかわからないけどおススメ。/既に出てた。
  2. pucchon: 十二国記ブレイブ・ストーリー精霊の守り人、空色勾玉、図書館の魔女
  3. asobime: 定番だけど、十二国記、勾玉シリーズ、図書館の魔女、守人シリーズ。
  4. air7743: 童話物語に一票 /荻原作品よく上がってるな はてな民が好みそうにない作風だと思ってた
  5. zn0621: アルスラーンは少なくとも王都奪還までは面白いけど、恋愛要素がさっぱりだしな。増田のラインナップからすると、勾玉シリーズが一番近いんだろうな。ラノベでもいいなら、魔弾の王と戦姫とかかな。
  6. shima_aya: 荻原規子の勾玉シリーズ。恋愛っぽい和製ファンタジー。あと「これは王国のかぎ」も。こっちはアラビアンなファンタジー。
  7. amui: 十二国記精霊の守り人は鉄板だけど、宮部みゆきさんのブレイブストーリーがいいんじゃないかなー。 恋愛ものが好きなら空色勾玉やRDGなどの荻原規子さん作品も。
  8. roshi: 既に上がってるけど「十二国記」と「精霊の守り人」かなー。空色勾玉は積読してる。他の作品も気になる。

グイン・サーガ

今から追いかけるのは辛いのでは・・・と思って遠慮しています。

  1. s2kw: グイン・サーガ、氷と炎の唄
  2. You-me: 指輪物語読んでるならあと「ホビット」と「ゲド戦記」と「パーンの竜騎士」「魔法の国ザンス」は読んでおきたい感じかな/グインサーガも二十巻台くらいまでは勧めて大丈夫じゃないですかね(小声
  3. shinichikudoh: 『グインサーガ』『宇宙皇子』『世界の終りとハードボイルド・ワンダーランド
  4. saiusaruzzz: 何回か出てるけど、グインサーガ。恋愛ものがいいなら、ケイロニア編を楽しみにしていて欲しい。
  5. kathew: 上がってないのだと、風の大陸は面白かったわね / グイン・サーガは原作未読 / ロードスは伝説の方は読んだのかしら。ロードスの中でも一番面白いところだけども / ほか、ブレイドライングランクレスト戦記など
  6. pon00: グイン・サーガ

〈卵王子〉カイルロッドの苦難

懐かしい。

  1. Tailchaser: ロードス読んでるならクリスタニアは?と思ったけど、今だと入手先がBookOffくらいなのかなー、恋愛ファンタジーならフォーチュン・クエストで。あと卵王子カイルロッド
  2. houyhnhm: カイルロッドのあれは恋愛か微妙だな。人間関係の複雑さではコブナント推す(図書館にハードカバーであるかも)。ご都合主義な感じならハロルドシェイか。
  3. paradisecircus69: 冴木忍は泣ける/未完でもいいなら神代創「ヴェルナディグサーガ」とか
  4. Nice_Pubo: やっぱファンタジーならゲド戦記十二国記、卵王子(カイルロッドの苦難)。恋愛系ならちょーシリーズ(ちょー美女と野獣)かなぁ? ファンタジーおいしいれす(^q^)
  5. drylemon: 「卵王子カイルロッドの苦難」を上げてる人がいて嬉しい。同じ冴木忍の「天高く、雲は流れ」お奨め。恋愛要素は少なめだけど、終盤、准主人公の魔族青年が○○を好きという気持ちと向き合う下りは胸熱。
  6. xap: 十二国記と卵王子カイルロッドは読まなきゃ損だよね。

以下票数のみ

名前も整形していないので、間違っているかもしれません。

集計方法

データ取得

はてばブックマークのAPI http://b.hatena.ne.jp/entry/json/https://anond.hatelabo.jp/20171108101404 をつかってコメント一覧を取得します。

curl 'http://b.hatena.ne.jp/entry/json/https://anond.hatelabo.jp/20171108101404' > bookmarks.json

集計

あとはJavaScriptを使ってバーン!です。

作品名は、コメントを描く人によってばらつくので、辞書を使って名寄せします*1。 8行目からはじまる二次元配列が辞書です。 配列の最初の要素が正式名称(集計後に表示する名前)で、それ以降はバリエーションです。

['十二国記', '小野不由美']

を見ればわかるように、今回は作者を代表作に寄せています。

またコメントのidを使って、一人一票で集計しました。

const source = require('./bookmarks')
const filterd = source
  .bookmarks
  .filter(c => c.comment)
  .map(c => [c.user, c.comment])

const summary = filterd.reduce((map, bookmark) => {
  [
    ['十二国記', '小野不由美'],
    ['守り人シリーズ', '精霊の守り人', '守り人', '上橋菜穂子'],
    ['ゲド戦記', 'ゲド', 'アーシュラ・K・ル=グウィン'],
    ['ドラゴンランス'],
    ['本好きの下剋上', '本好きの下克上', '香月美夜'],
    ['魔法の国ザンス', 'ザンスシリーズ', 'ザンス', 'ピアズ・アンソニイ', 'カメレオンの呪文'],
    ['はてしない物語', 'ミヒャエルエンデ'],
    ['ナルニア国物語', 'ナルニア', 'C・S・ルイス'],
    ['勾玉シリーズ', '荻原規子', '荻原作品', '空色勾玉'],
    ['グイン・サーガ', 'グインサーガ', '栗本薫'],
    ['〈卵王子〉カイルロッドの苦難', 'カイルロッド', '冴木忍'],
    ['図書館の魔女', '高田大介'],
    ['モモ'],
    ['無職転生 - 異世界行ったら本気だす -', '無職転生', '理不尽な孫の手'],
    ['氷と炎の歌', '氷と炎の唄', 'ジョージ・R・R・マーティン'],
    ['新世界より', '貴志 祐介'],
    ['妖女サイベルの呼び声', 'サイベル', 'パトリシア・A・マキリップ'],
    ['エターナル・チャンピオンシリーズ', 'エルリック・サーガ', 'エルリック', 'メルニボネの皇子', 'エターナルチャンピオンシリーズ', 'ムアコック'],
    ['裏庭', '梨木香歩'],
    ['アラビアの夜の種族', '古川日出男'],
    ['ライラの冒険', 'フィリップ・プルマン', '黄金の羅針盤', '神秘の短剣', '琥珀の望遠鏡'],
    ['ドラゴンクエスト 精霊ルビス伝説', '精霊ルビス伝説', '久美沙織'],
    ['灰と幻想のグリムガル', 'グリムガル','十文字青'],
    ['九年目の魔法', '9年目の魔法', 'ダイアナ・ウィン・ジョーンズ'],
    ['ヴァルデマール年代記', 'マーセデス・ラッキー', '誓いのとき', 'メルセデス・ラッキー'],
    ['英国パラソル奇譚', 'アレクシア女史', 'ゲイル・キャリガー'],
    ['死の王', 'タニス・リー'],
    ['スタープレイヤー', '恒川光太郎'],
    ['煌夜祭', '多崎礼'],
    ['後宮小説', '酒見賢一'],
    ['辺境の老騎士', '支援BIS'],
    ['ブレイブ・ストーリー', '宮部みゆき'],
    ['魔弾の王と戦姫', '川口士'],
    ['ちょーシリーズ', '野梨原花南'],
    ['空ノ鐘の響く惑星で', '空鐘', '渡瀬草一郎'],
    ['旅のラゴス', '筒井康隆'],
    ['ザ・スタンド', 'スティーヴン・キング', 'キング'],
    ['家守綺譚', '家守奇譚'],
    ['クラバート', 'オトフリート・プロイスラー'],
    ['ハウルの動く城'],
    ['水滸伝'],
    ['ドラゴンラージャ'],
    ['ランドオーヴァー'],
    ['スライム転生'],
    ['オーフェン'],
    ['ローワン'],
    ['スレイヤーズ'],
    ['スコットウェスタフェルド'],
    ['ドグラ・マグラ'],
    ['星界の紋章'],
    ['ネシャン・サーガ'],
    ['ベルガリオン'],
    ['姫騎士アンジェリカ'],
    ['リフトウォー・サーガ'],
    ['クロニクル千古の闇'],
    ['ルーンの子供たち'],
    ['破妖の剣'],
    ['ドラッケンフェルズ'],
    ['ドラキュラ紀元'],
    ['吟遊詩人オルフィーオの物語'],
    ['オーラバトラー戦記'],
    ['ゼロの使い魔'],
    ['ハリーポッター'],
    ['烙印の紋章'],
    ['六花の勇者'],
    ['始まりの魔法使い'],
    ['僕僕先生'],
    ['パーンの竜騎士'],
    ['古王国戦記'],
    ['指輪物語'],
    ['導師リジィオ'],
    ['日帰りクエスト'],
    ['火の国、風の国物語'],
    ['ドリトル先生'],
    ['風の白猿神'],
    ['最果てのパラディン'],
    ['f植物園の巣穴'],
    ['忍法帖'],
    ['天冥の標'],
    ['人狼への転生、魔王の副官'],
    ['アトランティス', '佐々木君紀の'],
    ['茅田先生'],
    ['烏に単は似合わない'],
    ['五王戦国志'],
    ['長安異神伝'],
    ['ウィンターワールド'],
    ['村田エフェンディ滞土録'],
    ['封仙娘娘追宝録'],
    ['オーリエラントの魔道師シリーズ'],
    ['黄金の王 白銀の王'],
    ['安徳天皇漂海記'],
    ['蕃東国年代記'],
    ['八咫烏シリーズ'],
    ['夢の上'],
    ['天山の巫女ソニン'],
    ['魔の都の二剣士'],
    ['薔薇の荘園', 'トマス・バーネット・スワン'],
    ['ブラックブラッドブラザーズ'],
    ['黄昏色の詠使い'],
    ['王女コクランと願いの悪魔'],
    ['ウィッチャー'],
    ['ダレン・シャン'],
    ['アルテミス・ファウル'],
    ['ある飛空士シリーズ'],
    ['マロリオン'],
    ['ベルカリ'],
    ['モンスター物語'],
    ['アイテム物語'],
    ['がんばれぼくらのノーカン先生!'],
    ['ダンジョン+ハーレム+マスター'],
    ['クレヨン王国月のたまご'],
    ['ゴブリンスレイヤー'],
    ['プリンセスブライド'],
    ['エラントリス'],
    ['クシエル'],
    ['レジェンド'],
    ['槍使いと、黒猫'],
    ['おかしな転生'],
    ['イセスマ'],
    ['イラハイ', '佐藤哲也'],
    ['夢の棲む街', '山尾悠子'],
    ['ガンバ三部作', '河童のユウタの冒険', '哲夫の春休み', '斎藤惇夫'],
    ['ドラクエ5の小説版'],
    ['彩雲国物語'],
    ['宇宙皇子'],
    ['世界の終りとハードボイルド・ワンダーランド', 'ハードボイルド'],
    ['瞳の中の大河', '沢村凛'],
    ['夜の写本師'],
    ['神の誓いと裁きの門'],
    ['図書館戦争'],
    ['ウォリアーズ'],
    ['ルナヴァルガー'],
    ['星の大地'],
    ['ぽっぺん先生シリーズ'],
    ['終わらざりし物語'],
    ['ダーククリスタル'],
    ['wonder wonderful'],
    ['ファーシーアの一族シリーズ'],
    ['MYTHシリーズ', 'お師匠様は魔物!'],
    ['カードミステリ', 'ヨースタイン・ゴルデル'],
    ['力の言葉', '魔法の窓', '荒涼たる妖精の地', '荒れ狂う海', '帝王と道化'],
    ['リンゴ畑のマーティン・ピピン', 'エリナー・ファージョン'],
    ['半村良'],
    ['混沌の叫び', 'パトリック・ネス', '心のナイフ', '問う者、答える者', '人という怪物'],
    ['キングキラークロニクルシリーズ'],
    ['オーリエラント', '乾石智子'],
    ['最後のユニコーン', 'ビーグル'],
    ['未知との遭遇'],
    ['2001年宇宙の旅'],
    ['ダンセイニ卿', 'ロードダンセイニ'],
    ['リフトウォーサーガ'],
    ['ガラスの短剣'],
    ['魔法の国が消えていく'],
    ['ヴェルナディグサーガ'],
    ['キマイラシリーズ', '夢枕獏'],
    ['吸血鬼ハンターDシリーズ', 'エイリアンシリーズ', '菊地秀行'],
    ['猫舌男爵', '皆川博子'],
    ['デス博士の島その他の物語', 'ジーン・ウルフ'],
    ['エンジン・サマー', 'ジョン・クロウリー'],
    ['ロードス島戦記'],
    ['風よ万里を翔けよ', '田中芳樹'],
    ['新・人間革命'],
    ['チャリオンの影'],
    ['騎士の息子'],
    ['鹿の王'],
    ['スクラップド・プリンセス'],
    ['陋巷に在り'],
    ['マヴァール年代記'],
    ['シャンクシリーズ', '秋田禎信'],
    ['エンジェル・ハウリング'],
    ['灼眼のシャナ'],
    ['ファファード'],
    ['ディルヴィシュ'],
    ['永遠のチャンピオン'],
    ['ジャック・フィニイ'],
    ['これは王国のかぎ'],
    ['株式会社魔法製作所'],
    ['ミストボーン'],
    ['幻想再帰のアリュージョニスト'],
    ['ディスクワールド'],
    ['エラゴン-意志を継ぐもの'],
    ['魔法の国シリーズ', 'ラリイ・ニーヴン'],
    ['あかがね色の表紙の本'],
    ['星虫'],
    ['異次元騎士カズマ'],
    ['デルフィニア戦記'],
    ['ゲーム・オブ・スローンズ'],
    ['フォーチュンクエスト'],
    ['龍と魔法使い'],
    ['アン・マキャフリィ'],
    ['ゼラズニィ'],
    ['華竜の宮'],
    ['霧の向こうのふしぎな街', '柏葉幸子'],
    ['妹が勇者になりました'],
    ['リトル・カントリー'],
    ['妖魔の騎士'],
    ['星を帯びし者'],
    ['有翼騎士団'],
    ['水の都の王女'],
    ['鳥姫伝'],
    ['はなはなみんみ物語', 'ゆらぎの詩の物語', 'よみがえる魔法の物語', 'わたりむつこ'],
    ['ハロルドシェイ'],
    ['コブナント'],
    ['アイスウィンド・サーガ'],
    ['ベルガリアード物語', 'ベルガリアード'],
    ['鏡の中の鏡']
  ].forEach(keywords => collect(map, bookmark, keywords))

  return map
}, new Map())

const formatted = []
for ([name, comments] of summary.entries()) {
  formatted.push([name, comments.length])
}
formatted.sort((a, b) => {
  if (b[1] - a[1] !== 0) {
    return b[1] - a[1]
  }

  return b[0] - a[0]
})

masudaRead = [
  '狼と香辛料',
  'ゼロの使い魔',
  'アリソン',
  'ロードス島戦記',
  'ベルガリアード物語',
  'デルフィニア戦記',
  'ハリーポッター',
  '指輪物語',
  '空ノ鐘の響く惑星で',
  '鋼殻のレギオス',
  '烙印の紋章',
  'シャングリ・ラ',
  '家守綺譚',
  '獣の奏者'
]

// 増田既読を除く
// N票以上
const top = formatted
  .filter(s => !masudaRead.includes(s[0]))
  .filter(s => s[1] > 0)

console.log(summary);
console.log(JSON.stringify(top))

// どこにも属して居ないコメント
let notMach = filterd
for (story of summary.values()) {
  notMach = notMach.filter(bookmark => !story.map(s => s[0])
    .includes(bookmark[0]))
}

// console.log(notMach)

function collect(map, bookmark, keywords) {
  keywords.forEach(k => collectHasKeyword(map, bookmark, k, keywords[0]))
}

function collectHasKeyword(map, bookmark, keyword, mainName) {
  if (bookmark[1].includes(keyword)) {
    const container = map.get(mainName) || []

    // 同一ユーザのコメントは除外
    if (container.filter(e => e[0] === bookmark[0])
      .length === 0) {
      container.push(bookmark)
      map.set(mainName, container)
    }
  }
}

*1:JavaScriptを使ってバーン!」とか言いながら、一番時間がかかるのはこの名寄せ辞書を作る部分です。元データが約500件なので、手動で2〜3時間かけて作りました。

技術書典3にサークル参加しました #技術書典 #技術書典3

サマリ

部数読みが偶然上手く行った*1ので1,421円の黒字でした。 なお、人件費は数えないものとします。

経費

  • サークル参加費 7,000円
  • 日光企画さん オンデマンド印刷 中とじ 100部 17,010円
  • テーブルクロス 829円
  • コインケース 140円

売上

  • 300円 x 88部 販売 26,400円

よかったこと

  • たくさん売れた
  • @takahashim さんに聞いてタイトルに改行を入れた
  • 日光企画さんのオンデマンド印刷は、コピー本に比べて、自分で作らなくていいし、搬入もやってくれるし超楽
  • クリーム色の表紙が予想していたより濃い色だったが、かえって目立ってよかった(戦利品写真でも一目でわかる)

  • GrifletのWebhook連携を直してもらえた

  • 13:45 − 14:15に休憩をとって自分の分を買えた
  • 14:30以降の客足がまばらになった時間を使って、早速読んで感想を書いた(積ん読防止)

  • 食料:おにぎり3個、ウォーカーズ3本、烏龍茶500ml

次に工夫したいこと

  • 本文とは別に表紙をつけたい
  • 28ページ越えると平とじの方がわずかに安いのでそっちにしたい
  • 重量を考えるとA5にした方が優しい?
  • ブックスタンドとか垂直に立てて遠目にわかるようにした方が親切?

感想

同人誌を書く第一の目的を「自分の知識を体系化して棚卸すること」にしています。 これは満たせたのでよかった。

タイトルで読者が絞れているからか、ほぼソフトウェア開発従事者しか手に取らなかったです。 手に取ってくれた人の半数以上は買ってくれたので、Win-Winなタイトル付けができたと思います。

台風なのに3000人近い人が来るのは、どう受け止めていいのかよくわかりません。

参考情報

頒布情報

techbookfest.org

前回参加した時の記事

ledsun.hatenablog.com

*1:前回の3倍の時間売れる、切りの良い数字にしました

技術書典3で「受託開発インアクション 〜顧客の期待をコントロールする〜」を頒布します

優秀なプログラマになるために

みんな良いこと言うので、刺激を受けて考えたことを記録します。

生きてるだけで丸儲け

優秀なプログラマーになるためのコツ · GitHub

優秀なプログラマーに「育つ」んだし、それには時間が必要

優秀なプログラマーになるということは、上記の通り長時間を要するということも踏まえると、メンタルヘルスにリスクがある環境に長時間暴露されることが不可避である

業界で長きにわたり活躍し続けている人というのは、それだけですでにひとかどの人物

すごく良いです。 優秀なプログラマになる前に、死んでしまっては元も子もありません。 生き延びることはなにより大切です。

幸か不幸か現状のIT業界はハードなストレスにさらされやすい環境です。 生き延びて前線に居続けるのは優秀な証です。 間違えやすいのは「優秀なプログラマになるには、長い時間IT業界を生き延びなければいけない」因果はありません。 優秀になるための方法としては参考になりません。

人間、つらい状況にいつ巻き込まれるかわかりません。 生き延びる方法は重要です。 炎上プロジェクトでチームメンバーを失った悲しみを癒すために、自分なりの生存戦術を書きます。

ストレス対処法

ハードな環境で生き延びるには、平時にストレス対処法を身につけておきます。 単に「趣味を持つ」です。 ハードな状況で、新しいストレス対処法を試そうとしても、学習するコストがストレスになって取り入れられません。 日頃から、ほどほどに遊んでおくと良いでしょう。

適当に羅列すると

  • 運動・瞑想・睡眠
  • 散歩・旅行・ドライブ・自転車
  • 食事・飲酒
  • 映画・観劇・音楽
  • ゲーセン・麻雀・ギャンブル
  • アニメ・漫画・ゲーム・読書
  • プログラミング・プラモ・イラスト
  • キャバクラ・ホストクラブ

特に、ストレス対処法としては

  1. 自分に合っていること
  2. 金銭的、時間的に繰り返し実行可能であること
  3. 一つに頼らないこと

が大事です。

「男が痴漢になる理由」という本によれば、

痴漢の再犯防止プログラムの参加者は

ストレス・コーピングの選択肢が少ない傾向があります。

だ、そうです。(ストレス・コーピングはストレス対処法だと思ってください。)

ストレス対処法の選択肢が少ないと、一つの方法にのめり込み、過激化と依存化のリスクが高まります。 個人的な経験では、特にストレスが強い場面では、過激化する傾向があります。 気をつけましょう。

「自慢できない趣味」とか「恥ずかしい趣味」とかの概念は、生きる死ぬに比べれば大切ではありません。 法の範囲で、いろんなパターンのストレス対処法を試しておきましょう。

撤退戦術

プロジェクトが炎上した際にエモーショナルな対応をすると燃えつきやすいので危険です。

「タスク殺すマシーン」になることと、「人間に戻る儀式」を用意しましょう。

タスク殺すマシーン

人間は、状況がコントロールできずに長時間労働をすると、ストレスを強く感じます。

プロジェクトの終わりが見えない状況では、「この大きなタスクが終わればプロジェクトが終わる」と希望的な予想を立てがちです。 単に希望なので、特定のタスクを終わらしても、プロジェクトは終わりません。 このマインドセットは単発のタスクを終わらせるには有効ですが、終わりのないプロジェクトでは逆効果です。 何度も希望を折られ、コントロールできないことを実感することになります。 大きなストレスを蓄積します。

プロジェクト全体のコントロールを放棄して、もう少し小さな状況をコントロールします。 プロジェクトの終わりのことを考えるのは無視して、 直近で実行可能なタスクを定義し、タスクを殺して常に進捗を出し続けます。 状況を逆転するような大きなタスクは定義しません。 絶対に実施可能なタスクを定義します。 不可能なタスクを押し付けられた時は、実行可能なタスクもねじ込みます。

少しずつでも進んでいる印象を自分に与えます。 ちょっと良いことがあると、プロジェクトの終わりのことを考えてしまいます。が、考えるのはやめましょう。 未来のことは、せいぜい次の休暇のことを考えて、死なないように体調コントロールすることを考えましょう。

すごく頑張ろうが、淡々と頑張ろうが、プロジェクトの終了まで死にさえしなければ、プロジェクト方が先に終わります。 何らかの原因で必ず終わります。 無限に投資できる組織は存在しないので、いつかプロジェクトに投入可能な資金は尽きます。 お金がなければプロジェクトは続けられません。終わります。

プロジェクトの失敗や成功より、生存が第一目標です。

人間に戻る儀式

マシーンモードはストレスへの反応を軽減するには便利ですが、 感情を殺しすぎるとストレスを検知できなくなります。 自分でわからないうちに、突然死んでしまうので危険です。

毎日でなくても週に2,3回は、「人間に戻る儀式」を実行して感情を復元しましょう。 その後ストレスに応じて、ストレス対処法を実施しましょう。 経験上、マシーンモード中にストレス対処法を実行しても効果が少ないように思います。

僕の場合は、ある時期の「人間に戻る儀式」が、帰宅前の一人飲みでした。出費が大変でした。 胃へのダメージがバカにならないので、ハイボール等の薄めのお酒を量を控えて飲む、みたいなスタイルに変わりました。 それ以前は、ウイスキー等の強いお酒も飲んでいました。

また、マシーンモードでは他人に対する優しさを失います。 家庭持ちの人は気をつけましょう。 職場の人間関係は、生きる死ぬよりは低優先です。

どんな方法を講じても、つらい環境が長期間続くと、人間は耐えられません。 死ぬ前に、逃げる必要があります。

逃げる選択をするのは勇気と体力が要ります。 つらい状況では体力は削られているので、決断し行動に移すことは、多くの場合無理でしょう。

結局は、自分のキャパシティを超える辛いプロジェクトに遭遇しないに運につきます。 願わくば辛いだけの戦いはしたくないものです。

技術力を身につける方法

車輪を再発明する

watilde.hatenablog.com

車輪を再構築する。多くの人は、それを止めてくるが、止めてくる人は再構築をしたことがないことが多い。彼らは、おそらく車輪について理解していない、かもしれない。きっと、新しい車輪が必要な際に新しいトラックを買うタイプの人。

素晴らしいです。 お仕事で使うライブラリやフレームワークは既存のものを使うと良いと思います。 ドキュメントが多いため、自分以外の開発メンバーの学習コストが低く、メンテナンスも(あるいは)外部に依存できます。 何より枯れたインタフェースは、設計コストの節約になります。

自分の技術力を高めるためには別です。 車輪の再発明をして、フレームワークやライブラリを実装しましょう。 全部を実装しなくても、一部だけでも実装してみましょう。 実装したことがあれば、既存のフレームワークを見たときに、フレームワーク全部が必要なのか、どこか一部分が必要なのか判断できるようになります。 どうしてそういう実装や構成にしたのか、作者の気持ちがわかります。 フレームワークのどの部分が、欲しい機能に関係するか目星がつきます。 機能が足りなくても、なぜ他の機能を重視しているのかわかります。 モジュール構成や依存関係も目星がつくので、ソースコードを読んで必要な部分だけをパクることもできます。 これらの判断できなければ、既存のフレームワークをそのまま使うしかありません。 ゴールデンハンマー病です。

脱ゴールデンハンマー病

If all you have is a hammer, everything looks like a nail. (ハンマーを持つ人にはすべてが釘に見える)

アブラハム・ハロルド・マズロー (Abraham Harold Maslow, 1908–1970)のお言葉です。

以前は「ハンマーだけでなくドライバーも身につけて、適材適所で使えばいいんでしょ?」と思っていました。 この方法は、思ったより応用が効きません。

今あるハンマーで打てないぐらい大きな釘を打たなければいけない時に困ります。 ハンマーに何かくっつけて大きくすれば良いかもしれません。 何をつけてどうやって固定すれば、大きな釘を安定して打てるようになるでしょうか? 改造するのは中々大変です。 ハンマーの作り方を知っていれば、大きなヘッドを買ってきて付け替えるだけで済みます。 解決方法の探し方に幅だけでなく深さが出てきます。 ゴールデンハンマー病から抜け出ることができます。

フレームワークやライブラリの場合も、フレームワークAとBを比較してより良い方を選ぶ、以外の選択肢がでてきます。 既存のフレームワークやライブラリは色々な用途に汎用的に使えるように作られています。 多くの場合ではオーバースペックです。 フレームワークで解決できる問題もありますが、フレームワークを使わない方が工数が減ることもあります。

学習の助

車輪の再発明をしようにも、徒手空拳で取り掛かるのは大変です。 世の中には、車輪の再発明を助けてくれる教材があります。

UNIXプログラミングから始まって、簡易HTTPサーバの実装に至ります。 HTTPサーバの実装はまさに車輪の再発明です。

著者の用意したお助けライブラリを使って、簡易Rubyインタプリタが実装できます。 Rubyインタプリタの実装も車輪の再発明です。

とちぎRuby会議07でラムダノート株式会社の鹿野さんが 「知識のテコになる本を作りたい」(正確な内容は覚えていません)的なことを言っていたのは、なるほど、こういうことなのかな?と今になって思いました。

優秀なプログラマとは?

ここまで書いておいて、どういう人が優秀なプログラマかの定義がないので、 一応、整理しておきます。 評価軸の一つだと思ってください。

すごい専門家さんとすごい素人になるためには – Koichiro Honda – Medium

優秀な通訳の方はどういう人かといわれたら、それは語学ではなくて、例えばめちゃくちゃビジネスが詳しい人である。パフォーマンスを決めるのは、話すコンテンツの方をどれだけ理解しているか、にかかっている。英語を喋れるから発注するわけじゃない

仕事を頼む側からするとと、仕事のコンテキストを理解してくれる、むしろ先読み・深読みしてくれるのはとてもありがたいです。 「SEには、実装技術も大事だけど業務知識も大事だよ」みたいな話です。

これは「車輪の再発明」とはちょっと違う話です。 どちらかというと「ハンマーだけでなくドライバーも身につけよう」な話です。 優秀なプログラマになる方法は一つではありません。

DBエンジニアだけどアプリケーションコードも多少書ける人や、デザイナーだけどJavaScriptもいくらか書ける人たちは、すごくありがたいです。 プログラミングでも「組み込みが得意だけどネットワークもわかる」や、「フロントエンドが得意だけどサーバサイドも多少わかる」は大事です。

多くの現実の問題は、特定の領域にあるわけではなく、領域と領域の間にあります。 どっちの領域の問題として扱うのが良いのか判断できることは、問題解決の役に立ちます。

アプリケーション開発の文脈で言えば、見た目に関わる機能、たとえば「表示内容の絞り込み」をサーバーサイドで実装するか、フロントサイドで実装するか迷うことがあります。この時に相談できるプログラマはとても有用です。

一つの領域しか知らないと、その領域で解決しようとしがちです。 その領域でやるのがもっとも効率的とは限りません。 自分の一番得意な領域以外のプログラムも素振りして、雰囲気を掴んでおくことは大事です。 そういう時はQiitaによくある「HelloWorldやってみた」な記事が結構役に立ちます*1。 嫌いな人もいるみたいですが、僕は好きです。

おまけ

自分用の簡単な道具を作るのもオススメです。 コツは自分だけのために作ることです。 他の人にも使えるようにと考えるとグッと難易度が上がります。 今まで作ったものを自慢します。

github.com

毎週金曜日に掃除の時間をチャットワークに書き込んでくれます。

github.com

面談の組み合わせをモンテカルロ法で決めてくれます。

github.com

cpxコマンドでhtmlファイルをコピーする時に、srcのリンクをhttpsに書き換えてくれます。 gulpとかのそれっぽい変換ツールをnpmスクリプトに置き換えるために使った気がします。

github.com

Markdownで書いたテスト手順の順序を入れ替えます。

github.com

gitlabのWebhook通知をチャットワークに書き込んでくれます。 いまはgitlab使っていないので、使っていません。

github.com 「技術ブログ書いて」と通知するbotです。 効果なかったので止めました。

github.com ESLintの適用できそうなルールを列挙します。 ESLintのルールが増えた時に使いました。 適用できそうなルールを機械的に適用していくと、ルールセットに思想がなくて、意外と嬉しくなかったです。 チェックして欲しい部分にあったルールを探して手で入れた方が、いい感じのルールセットになります。

github.com とあるフレームワークを使っている時に、gitの差分から変更のありそうなユーザ操作のヒントを洗い出してくれるツール。 テスト項目の優先順位を考えために使いました。

github.com

ブログの記事にアフィリエイトリンクを埋めるためのコマンド。

*1:情報が古いことがあるので、本家情報も確認する必要はあります

Node.jsでつくるNode.js その2

ledsun.hatenablog.com

の続きです。四則演算の対応するオペレーター(演算子)を増やします。

オペレーターを増やす

前回+に対応しました。 次に、-, *,/,%に対応します。

実装

switch文に演算子ごとの分岐を追加するだけです。

const esprima = require('esprima')
const util = require('util')

console.assert(test('1 + 1') === 2)
console.assert(test('1 + 2') === 3)
console.assert(test('1 - 2') === -1)
console.assert(test('2 * 2') === 4)
console.assert(test('10 / 2') === 5)
console.assert(test('100 % 49') === 2)

function test(expresssion) {
  const parsed = esprima.parse(expresssion)

  console.log(util.inspect(parsed, false, null))

  const body = parsed.body
  for (const statement of body) {
    return evaluate(statement)
  }
}

function evaluate(statement) {
  switch (statement.type) {
    case 'ExpressionStatement':
      switch (statement.expression.type) {
        case 'BinaryExpression':
          let left, right
          switch (statement.expression.operator) {
            case '+':
              [left, right] = getOperandFromBinaryExpression(statement.expression)
              return left + right
              break;
            case '-':
              [left, right] = getOperandFromBinaryExpression(statement.expression)
              return left - right
              break;
            case '*':
              [left, right] = getOperandFromBinaryExpression(statement.expression)
              return left * right
              break;
            case '/':
              [left, right] = getOperandFromBinaryExpression(statement.expression)
              return left / right
              break;
            case '%':
              [left, right] = getOperandFromBinaryExpression(statement.expression)
              return left % right
              break;
            default:
              console.log(`unknown operator ${statement.expression.operator}`);
          }
          break;
        default:
          console.log(`unknown expression ${statement.expression}`);
      }
      break;
    default:
      console.log(`unknown type ${statement.type}`);
  }
}

function getOperandFromBinaryExpression(expression) {
  let left;
  if (expression.left.type === 'Literal') {
    left = expression.left.value
  } else {
    console.log(`unknown type ${expression.left.type}`);
  }

  let right;
  if (expression.right.type === 'Literal') {
    right = expression.right.value
  } else {
    console.log(`unknown type ${expression.right.type}`);
  }

  return [left, right]
}

leftとrightの値をとる処理をgetOperandFromBinaryExpression関数にしました。

項数を増やす

1 + 1 + 1のように式の項数を増やします。

この時、ASTは

Script {
  type: 'Program',
  body:
   [ ExpressionStatement {
       type: 'ExpressionStatement',
       expression:
        BinaryExpression {
          type: 'BinaryExpression',
          operator: '+',
          left:
           BinaryExpression {
             type: 'BinaryExpression',
             operator: '+',
             left: Literal { type: 'Literal', value: 1, raw: '1' },
             right: Literal { type: 'Literal', value: 1, raw: '1' } },
          right: Literal { type: 'Literal', value: 1, raw: '1' } } } ],
  sourceType: 'script' }

leftの中にBinaryExpressionが入れ子になっています。

これに対応すると、小町算を計算できるようになります。

(1 + 2) / 3 * 4 * (56 / 7 + 8 + 9) = 100

実装

BinaryExpressionの評価を再帰的にしたいので、evaluateBinaryExpression関数を作って再起呼び出しします。

const esprima = require('esprima')
const util = require('util')

console.assert(test('1 + 1') === 2)
console.assert(test('1 + 2') === 3)
console.assert(test('1 - 2') === -1)
console.assert(test('2 * 2') === 4)
console.assert(test('10 / 2') === 5)
console.assert(test('100 % 49') === 2)
console.assert(test('1 + 1 + 1') === 3)
console.assert(test('(1 + 2) / 3 * 4 * (56 / 7 + 8 + 9)') === 100)

function test(expresssion) {
  const parsed = esprima.parse(expresssion)

  console.log(util.inspect(parsed, false, null))

  const body = parsed.body
  for (const statement of body) {
    return evaluateStatement(statement)
  }
}

function evaluateStatement(statement) {
  switch (statement.type) {
    case 'ExpressionStatement':
      switch (statement.expression.type) {
        case 'BinaryExpression':
          return evaluateBinaryExpression(statement.expression)
          break;
        default:
          console.log(`unknown expression ${statement.expression}`);
      }
      break;
    default:
      console.log(`unknown type ${statement.type}`);
  }
}

function evaluateBinaryExpression(expression) {
  let left, right
  switch (expression.operator) {
    case '+':
      [left, right] = getOperandFromBinaryExpression(expression)
      return left + right
      break;
    case '-':
      [left, right] = getOperandFromBinaryExpression(expression)
      return left - right
      break;
    case '*':
      [left, right] = getOperandFromBinaryExpression(expression)
      return left * right
      break;
    case '/':
      [left, right] = getOperandFromBinaryExpression(expression)
      return left / right
      break;
    case '%':
      [left, right] = getOperandFromBinaryExpression(expression)
      return left % right
      break;
    default:
      console.log(`unknown operator ${expression.operator}`);
  }
}

function getOperandFromBinaryExpression(expression) {
  return [getOperandValue(expression.left), getOperandValue(expression.right)]
}

function getOperandValue(operand) {
  switch (operand.type) {
    case 'Literal':
      return operand.value
    case 'BinaryExpression':
      return evaluateBinaryExpression(operand)
    default:
      console.log(`unknown type ${operand.type}`);
  }
}

getOperandValue関数はleftとrightにコピペするのが面倒だったので、関数にしました。

RubyでつくるRubyとの違い

EsprimaのASTはstatementとexpressionの二階層になっています。 一方minirubyのASTたexpressionだけの一階層です。

Rubyで作るRubyソースコードは本を買って確認してください。

式と文の取り扱い

これは言語仕様の違いによるものです。

Ruby

プログラムは式を並べたものです

プログラム・文・式 (Ruby 2.4.0)

式と文に区別はありません。

JavaScriptでは式と文は区別されます。 例えば

1 + 1

は式です。

var i = 1

は文です。JavaScriptの文は値を返しません。

Node.jsでつくるNode.js その1

ledsun.hatenablog.com

の続きです。Node.jsで動くJavaScriptインタプリタを実装しようとする試みです。

作戦

  • パーサにはEsprimaを使う
  • TDD的なスモールスタート戦略で進める(最初はセルフホスティングを意識しない)

下調べ

EsprimaがどのようなASTを返すか確認します。

準備

Esprimaをインストールします。

npm init -y
npm install esprima

ASTを見る

REPLでパース結果を確認します。

nodeコマンドでREPLを起動し

~ node
> const esprima = require('esprima')
undefined
> const util = require('util')
undefined
> console.log(util.inspect(esprima.parse('1 + 1'), false, null))
Script {
  type: 'Program',
  body:
   [ ExpressionStatement {
       type: 'ExpressionStatement',
       expression:
        BinaryExpression {
          type: 'BinaryExpression',
          operator: '+',
          left: Literal { type: 'Literal', value: 1, raw: '1' },
          right: Literal { type: 'Literal', value: 1, raw: '1' } } } ],
  sourceType: 'script' }
undefined

木構造JSONが帰ってきます。

1 + 1を実行する

const esprima = require('esprima')
const util = require('util')

console.assert(test('1 + 1') === 2)

function test(expresssion) {
  const parsed = esprima.parse(expresssion)

  console.log(util.inspect(parsed, false, null))

  const body = parsed.body
  for (const statement of body) {
    return evaluate(statement)
  }
}

function evaluate(statement) {
  switch (statement.type) {
    case 'ExpressionStatement':
      switch (statement.expression.type) {
        case 'BinaryExpression':
          switch (statement.expression.operator) {
            case '+':
              let left;
              if (statement.expression.left.type === 'Literal') {
                left = statement.expression.left.value
              } else {
                console.log(`unknown type ${statement.expression.left.type}`);
              }
              let right;
              if (statement.expression.right.type === 'Literal') {
                right = statement.expression.right.value
              } else {
                console.log(`unknown type ${statement.expression.right.type}`);
              }
              return left + right
              break;
            default:
              console.log(`unknown operator ${statement.expression.operator}`);
          }
          break;
        default:
          console.log(`unknown expression ${statement.expression}`);
      }
      break;
    default:
      console.log(`unknown type ${statement.type}`);
  }
}
  • console.assertを使って実行結果を評価
  • ASTを表示(見ながら実装を進めたい)
  • test関数でスクリプトを実行
  • evaluate関数で文を実行(「RubyでつくるRuby」の最終形に引きづられた、evaluateStatementがベター?)
  • for ofもTemplate literalも使う(現時点でセルフホスティングは考えない)
  • 二項分岐なのにswitchを使った(「RubyでつくるRuby」の最終形に引きづられた、ifで十分)
  • ;有無は統一していない(普段は無し派、ESLintの助けが必要)

実行すると

~ node .
Script {
  type: 'Program',
  body:
   [ ExpressionStatement {
       type: 'ExpressionStatement',
       expression:
        BinaryExpression {
          type: 'BinaryExpression',
          operator: '+',
          left: Literal { type: 'Literal', value: 1, raw: '1' },
          right: Literal { type: 'Literal', value: 1, raw: '1' } } } ],
  sourceType: 'script' }

ASTを表示するだけです。 結果が間違っているときは、console.assertで引っかかってAssertionErrorがでます。

とりあえずここまでです。 次は対応するoperator(-, *, /)を増やします。

RubyでつくるRuby 読書感想文

どんな本?

f:id:ledsun:20170908114109p:plain

RubyでつくるRuby ゼロから学びなおすプログラミング言語入門(紙書籍)www.lambdanote.com

言語処理系の実装を体験するための本。 言語処理系の実装はパーサの実装が面倒臭くて、大抵の人はそこで力尽きます。 そこで、パーサは著者の方が用意しておいて、構文木の解釈だけを読者が実装するスタイルです。

ところで著者の方は

の著者で

の訳者で

regional.rubykaigi.org

NESファミコン)のエミュレータruby で書いた、Rubyハッカーの方です。 さらに

『Ruby で学ぶ Ruby』非公式あとがき - まめめも

個人的に盛り上がってきたので、そこから 1 週間で全 8 回(当時)の原稿をすべて書き上げました

130ページの本の第1稿を1週間で書いたとか、ちょっと意味わかんないです・・・(汗

どんな縁?

咳マニアなので、Tochigi RubyKaigi 07 に参加しました。 そこで「RubyでつくるRuby」読書会があったので、読み始めました。

サインももらえました!やったね!!

何をした?

一通り読んだ後に、インタプリタソースコードの最終形を写経して動かしてみました。 120行に満たないRubyソースコードを打ち込んだだけで、インタプリタが動いた!すごい!(そういう趣旨の本です)

淡々と条件分岐を打ち込んでいくのは、正直、面倒臭い作業でした。 パーサ部分を実装していないのに、この面倒臭さ!言語処理系の実装は大変ですね。

既存のRubyソースコードをいくつか試したら、動かないものもありました。 たとえばArray#starts_withを使っているソースコードです。 組み込みライブラリが入っていないので当然ですね。 まともに言語処理系を作るには、パーサ加えて、組み込みライブラリも必要です。 ますます大変ですね。

最終形を写経するだけでは、どういうことを考えながら判断しながら言語処理系を実装していくのかは、あまり理解できませんでした。 もうちょっとゆっくり、手順を守って実装してみたほうが良いかもしれません。

次に何をしてみる?

JavaScriptで同じようなことをしてみようと考えると、JavaScript界ではASTの定義やパーサライブラリは整っています。

efcl.info

Esprimaで作ったASTを使ってJavaScript(のサブセットの)インタプリタを実装すれば、言語処理系実装への理解がもうちょっと進みそうです。

Mac の言語設定を英語にした時のGoogle Chromeのフォント設定

OSの言語設定を英語に

qiita.com

OSの言語設定を英語に変更しましょう

に触発されて、言語設定を英語にします。

Google Chromeの言語設定

Change Chrome languages & translate webpages - Computer - Google Chrome Help

Chrome ブラウザの言語を変更する(WindowsChromebook のみ)

MacGoogle ChromeはOSと異なる言語設定はできません。 これ自体は困りません。

Google Chromeは言語設定が変わるとフォント設定がかわります。 標準フォントがTimesになります。 フォント設定が無いWebページを見ると少し違和感があります。

Google Chromeのフォント設定

requlog.com

を参考にして、日本語のフォントを設定します。

f:id:ledsun:20170629103928p:plain

  • Standard font: Hiragino Kaku Gathic ProN
  • Serif font: Hiragino Mincho ProN
  • Sans-serif font: Hiragino Kaku Gathic ProN
  • Fixed-width font: Osaka

リーダーシップ理論

リーダーシップに関する情報を調べた記録です。

luccafort.hatenablog.com

はてなブックマーク

リーダー(管理者)ではなくエンジニア(実務者)でありたいと願う人々へ - おうさまのみみはロバのみみ

これははるか昔に作られたリーダーシップ理論の基礎では。「リーダーシップ理論」でググるといっぱい出るよ

2017/06/12 04:08
b.hatena.ne.jp

というのを見つけました。 ググって

リーダーシップ理論の流れと リーダーシップの実践的開発方法(PDF) を見つけました。

参考図書で

が、上がっていました。 以上です。

失敗プロジェクトの弔い方

プロジェクトを燃やした経験から、どうすれば有効なふりかえりができるのか考えてみました。

要約

  1. 失敗プロジェクト参加者の信用を回復
  2. 失敗プロジェクトの撤退戦術を共有
  3. 失敗プロジェクトの回避方法を検討

背景

を見て考えました。 外野から見たら、確かにまったくこう見えると思います。 なぜ、傷口を抉るようなことをするなと言いたい「気持ち」になるのでしょうか?

失敗プロジェクトの当事者の立場

外野も嫌がらせや、憎くしみででやってはいません。 わかってはいます。 ただ、原則として、デスマ中は前門の客、後門の同僚、両方から打たれている状態です。 その直後に、罰しないから「失敗ポイントを明確にしてふりかえろう」と言われても、信用できません。

外野の方たちは、本当に辛い場面で後ろから殴ってた人たちです。 ふりかえりに参加している特定個人が本当に殴っていたかはあまり関係ありません。 社内の誰か一人でも殴っていれば、「ふりかえりの参加者も殴りに参加していた」と疑うのが人間の心理です。 一度疑えば、「ふりかえりで殴りネタを探している」と疑うのが人間です。

本当に「ふりかえりで殴りネタを探している」かは問題ではありません。 傷ついていて、疑う心理状態にあるのが問題です。

「そんな傷口を抉るようなことするな」と怒られ

は、こうした背景を意識した反応だったようにも思えます。

ご提案

「失敗」とつけない

最初に「失敗プロジェクト」という認識自体を改めましょう。 なぜ「失敗」とつけたのでしょうか? 外野からでも

  • プロジェクトの進行が、当初聞いていた予定より0.5倍以上伸びている
  • プロジェクト参加者の平均残業時間が長い

といった情報が観測できると思います。 もう少し詳しい情報を知っていれば

  • 売上をコストが超過した
  • メンバーが逃亡した
  • 納品できず、損害賠償請求を受けた

という情報を知っているかもしれません。

これらの現象のどの段階で「失敗」とつけるべきでしょうか?

「失敗」と名付けると、プロジェクトとプロジェクト参加者が批判されます。 批判には「正当な批判」もありますが、誤解に基づく「誤った批判」もあります。 批判にはコントロールが必要です。 コントロールされない批判が増えると、吊るし上げになります。 雑談における批判は、多くの場合コントロールできません。 結果として「誤った批判」が増え、「プロジェクト参加者を吊るし上げてよい」空気が生まれます。

私の観測範囲では、吊るし上げられた人間に、批判と自分を分離する圧倒的メンタルタフネスがない場合は、退職することが多いです。 万が一退職された場合、組織を維持するためには、欠員を埋める分の採用コストと教育コストが必要です。 プロジェクトに「失敗」とつけることには退職者を生むリスクがあります。 現実のコストにつながるリスクです。

「失敗」を禁止すると、別の悪い名前がつきます。 「失敗プロジェクト」には別のポジティブな呼び名をつけましょう。

奇跡の生還プロジェクト

(例えば)「奇跡の生還プロジェクト」と呼びましょう。

「奇跡の生還プロジェクト」のふりかえりでは生還方法を学びましょう。

炎上プロジェクトから生還した人は、少なくとも「困難な状況で逃げない」という特性がひとつ以上の事例で証明されています。 どんな過酷な状況でも生き残る「生還者(リターニングマン)」かもしれません。

この特性は、先天的なものでしょうか? 後天的な要素はないでしょうか? もしあるならば共有する価値があります。

同様の、困難であることがわかっていても、やり遂げなければいけない状況では、使いやすい人材です。 また、開発者には、自身の努力と関係ない部分で「奇跡の生還プロジェクト」に巻き込まれるリスクがあります。

「奇跡の生還プロジェクト」に巻き込まれるリスク

「炎上しはじめたプロジェクトからは全力で逃げる」を貫けると個人の幸せは得られるかもしれません。 ただ、そう強い人間ばかりでもありません。

  • 受注時にリスクを低く見積もっていた
  • 受注後に追加要望が現れた、しかし政治力によって拒否できない
  • すでに炎上しているプロジェクトに助けに入った

のような状況では、多くの人は「奇跡の生還プロジェクト」から逃れるのは難しいでしょう。 「奇跡の生還プロジェクト」に巻き込まれたときに、生還するためのプラクティスを聞いておくのは、いつか役に立ってしまうかもしれません。

奇跡の生還プロジェクトに遭わないようにする

もちろん「奇跡の生還プロジェクト」の芽をみつけ、事前に潰して回るのが至上です。 もしかすると多くの開発の現場では、早すぎる願いなのかもしれません。 残念ながら

デメリット

「奇跡の生還プロジェクト」として扱うことにデメリットはないのでしょうか?

アドレナリンジャンキー問題

当然考えるのが、「奇跡の生還プロジェクト」として褒め称えられなら、最初から炎上させようと考える人間が現れることです。 炎上している時に生きている実感を感じる人間もいます。 そういう人は早めに検出して、「奇跡の生還プロジェクト」の助っ人要員にしましょう。 プロジェクトの立ち上げからは外しましょう。 お互いのためです。

潜在的な問題

ところで「失敗プロジェクト」として吊るし上げられて辞めない人間はどのような人でしょうか?

批判を受けても、ものともしない人間です。 このような人物は、ふりかえりで得た改善案を実践するでしょうか?

また、次の仕事にあてがなければ、なかなか辞められません。

とすると「失敗プロジェクト」などのネガティブな名前付けを放置しておくと 「アドバイスを聞かない頑固者」「つぶしの効かない偏った技術者」を選別して 会社に残すバイアスが働きそうな気がします。

10年後にはどうなっているのでしょうか? 興味深い思考実験です。

おまけコンテンツ

後門から刺される例

外野経験

とは言っても、自分が外野だった時は「いつまでやってんの?早く終わらしてよ」と思っていました。 人間、その立場になってみないとわからないことがあるようです。

IoTゲートウェイのモデリング

用語

  • 機器:HTTP/HTTPSな環境から操作する機器
  • 機器種別:機器の種類。例、エアコン、照明、etc。あるいはエアコンもメーカによって異なる機種種別として扱う必要があるかもしれません。

要件

現在のIoTでは機器種別によって、ネットワークを介した操作方法が異なります。 機器種別によっては直接HTTP/HTTPSの世界と接続できないことがあります。

例えば6LoWPANという規格でつながっているかもしれません。 IoT規格 6LoWPANとは? | IoT

IoT機器を制御するWebアプリケーションを作るには、HTTP/HTTPSの世界につなぐゲートウェイが必要です。 RESTful APIでIoT機器を制御できれば、Webアプリケーションエンジニアにアプリケーション作成環境を提供できるでしょう。

モデリング

IoTゲートウェイでは、原則として、機器種別に応じて変わる情報をロジックで実装します。 機器の設定変更に応じて変える情報はDBに保持します。 大きく次の3つのモデルに分けます。

  • Deviceクラス
  • Profileクラス
  • Clientクラス

これらのクラスはWebMVCの分類では、いずれもModelです。 ここではViewやControllerに関する設計は扱いません。

Device

Deviceは機器操作ロジックを担当します。

  • 対象機器と通信相手のマッチング
  • RESTful APIのパラメータを機器向けのパラメータに変換
  • 複数リクエストが必要なシーケンスの管理

操作したい機器と通信相手が1:1とは限りません。 1つの通信相手が複数の機器を管理していることがあります。 この関係性は静的な情報です。ロジックとして実装します。

機器がJSONでのリクエストを受け入れない場合は、JSON以外の異なるフォーマットに変換する必要があります。 ゲートウェイのRESTful APIは、人間が読めるパラメータが望ましいです。 機器が16進数文字列を要求する場合、変換して送る必要があります。

1つのRESTful APIリクエストに対して、機器に複数のリクエストが送る必要がある場合、 それらのシーケンスはここで実装します。

DeviceはProfileとClientを持ち(に依存し)ます。

Profile

Profileクラスは機器の情報を持ちます。 代表的なものに次があります。

  • 名前
  • 機器種別
  • 位置情報
  • 接続情報

ロジックとしては、検索ロジックを担当します。 ProfileクラスはDBのレコードと対応しています。 Active Recordパターンを使うのに適しています。 Ruby on RailsであればActiveRecordやApplicationRecordを継承したクラスとして実装します。

機器種別ごとの拡張が必要な場合は機種別のSubProfileクラスを作ります。 例えば、機器種別ごとに接続方式が異なる場合は次のように情報を持ち分けます。

  • Profile
    • 名前
    • 位置情報
    • 機種種別
  • SubProfile
    • 接続情報

ProfileクラスとSubProfileクラスには継承関係は持たせません。 DeviceがProfileインスタンスとSubProfileインスタンスを持ち、適宜使い分けます。

想定外の新しい機種種別を追加した際に、Proflieには影響を与えたくありません。 1:1関係のテーブルに分けます。

関連付けにはidを使います。 外部との接続性を重視した場合は、idにUcodeを使うかもしれません。 Ucode | IoT

Client

Clientは機器との通信を担当します。 原則として状態は持ちません。 通信状態は持ちますが、通常はHTTPClientなどの別のクラスに移譲しているでしょう。

機器がHTTP/HTTPSで通信できれば、特に難しいことはありません。 リクエス送信先を整形し、リクエストボディを整形し、リクエストを投げるだけです。 ロジックと言っても、せいぜい通信エラーを例外で抽象化するぐらいです。

Clientを別クラスに分ける最大の効果はユニットテストの書きやすさにあります。 Deviceのテストコードを書く際に、ClientのインターフェースにあわせたMockに置き換えることができます。 Deviceは比較的複雑なロジックを持っているので、ユニットテストで品質を確保します。

IoTではエンドツーエンド試験環境を作るために、機器を用意する必要があります。 機器とゲートウェイの製造が並行している場合は、試験が開発期限ギリギリまで行えないことがあります。 事前にユニットテストでテストしておきたいところです

アプリケーションレベルの分割戦術

エアコンと言ってもメーカごとに接続方法や操作方法が異なります。

ここで扱ったHTTP/HTTPS世界とのゲートウェイの他にもう1つ エアコンを抽象化するゲートウェイを用意すると、分業しやすくなるでしょう。

技術書典2にサークル参加しました #技術書典

サマリ

  • 謎のモチベーションの高まりにより技術同人誌を書いた
  • 30部が1.5時間ではけた
  • Re:VIEWで書いた
  • 想定読者が勉強会の発表より広いのはおもしろい

書いたこと

デバッグ最速理論」という薄い本を書きました。 最終的に表紙と奥付、裏表紙等を合わせて16ページになりました。 原稿はこんなです。

当初の野望は

  • カラー表紙
  • 32ページ
  • オフセット(?)印刷

でした。 3月の執筆時間が思っていたより取れなかったので、執筆時間をギリギリまで稼ぐためにコピー本に倒しました。 深夜に、コピー機でガッションガッション印刷して、ホッチキスでバッチンバッチン留めて作りました。 「デバッグ最速理論」自体は、今のところ16ページで十分表現できています。 もうちょっとデバッグ初心者や非技術者に間口を広げようと思ったら、ページ数を増やして 導入章を増やしたり、図表を増やした方がいい気はします。

部数について

30部用意して、一時間半ではけました。

今みたら被チェック数が30を大幅に超えていたので、もっと用意しておけばよかったです。 f:id:ledsun:20170417193415p:plain

営業時間は6時間あったので、単純計算でも100部はけた可能性があります。 一般参加者は3100人だったそうです。1%の人しか手に入れられないのはちょっと寂しい気がします。

雨の中、3100人の参加者って、雨降ってなかったら一体どういうことになっていたのか恐ろしいです・・・

皮算用

次の機会があれば100部用意しても良いかもしれません。 ただ、一人サークルのワンオペなので、100部売るのは体力的に辛いです。

200円だから売れた面もあると思うので、ページ数が増えたり、印刷所使ったりで単価が上がればそんなに部数はいらなさそうです。 加筆&印刷で単価が1000円で60部とか?

Re:VIEWについて

techbookfest.connpass.com

に参加してざっくり把握したので、Re:VIEWで書きました。 記法としてはMarkdownと大差がないので大して苦労はありませんでした。

vvakame/docker-reviewを使って簡単にPDFにできました。 余談:tklx/base使えばコンテナを軽量化できるか試しました。

! LaTeX Error: File `xcolor.sty' not found.

と、エラーが出てダメでした。

自分の書いた文章が技術書っぽい体裁で読めるのはちょっとした感動でした。

一方で組版部分のlatexの知識がなく、手も足も出ないのには苦労しました。 任意の場所で改行を入れたり、フォントサイズを調整したり、ページ繰りを調整したりしたいものです。

フォント埋め込みはtechboosterでGrifleを提供してもらえたのが大変助かりました。

書き終わってわかったこと

技術同人誌は、勉強会の発表より自由なターゲットに対して情報発信して良いようです。

勉強会ではテーマに関連のある発表だと、参加者のニーズにマッチしそうです。 「デバッグ早速理論」のような一般的な話は、テーマが関連する勉強会がありません。 あったとしても16ページ相当では、発表時間は30分以上かかりそうです。 発表枠を確保するのは困難です。

それに対して技術同人誌は、テーマやボリュームの選択の自由度が高いです。 興味があることを好きなように書いて、それに対して「興味があるから」「応援したいから」と買っていく人がいるというのは 個人的には新鮮で不思議な感覚です。

今年の目標

  • 家族を大事に
  • 責任のあるポジションにチャレンジ
  • 技術同人誌を書く
  • プログラミング作法」に現代の視点からツッコミを入れる
  • TOEIC 800点*1
  • 共感能力の向上
  • 自分が使うAndroidアプリケーションを作る*2

回避型愛着スタイル

はじめに

私は

  • 共感能力に低い
  • 他人に共感されることを避ける
  • 「共感されたい」という欲求を過小評価する

性質があります。 世の中では、これを「回避型愛着スタイル」と言うようです。 エンジニアにはこのタイプが多いように思います。

今わかっている範囲の情報を書きます。

愛着障害

精神医学の分野には「愛着障害」という障害があります。 他人との「愛着」を安定して築けないため社会生活に困難がでる障害です。

○○型愛着スタイル

自閉症」や「発達障害」と同じく軽い人もいれば重い人もいます。 軽い人は一見社会生活に全く支障がない人もいます。 そういう人に「○○障害」とつけるのは引っかかるので、ここでは「○○型愛着スタイル」と表現します。

原因

発生する原因は、両親(育成者)との間に「愛着」を上手く築けないから起きるようです。 わかりやすい例は幼い時の親との死別や、一定期間預けられていた場合などです。 他にも親の愛着スタイルが安定していない場合も起きるようです。

不安定型、回避型

大別して不安定型と回避型の二種類があります。

不安定型は十分な愛着が得られなかったために、愛着を過剰に求めたり、愛着を失うことを過剰に恐れます。 回避型は十分な愛着が得られなかったために、愛着を求めることをやめてしまいます。

不安型はラオウ、回避型はサウザーと思えばわかりやすいと思います。

共感

共感されたい

回避型愛着スタイルの人は「共感されたい」という欲求を過小評価します。 これは、以前から自覚がありました。

ずいぶん昔の話ですが、当時お付き合いしていた女性から「相手をしてほしい」アプローチをされたときに逃げ回っていました。 逃げると、相手からの「相手をしてほしい」アプローチが強化され、辟易して破綻しました。

当時の実感としては「めんどうくさい」でした。 今思うと、「相手をしてほしい」感情に共感できていなかったのだと思います。 さらに共感したように振舞うこともできず、どう反応してよいのかわからず戸惑っていたように思います。

共感できない

「相手をしてほしい」感情に共感できないのは、「自分の考えや感情が共感されるわけがない」と思っているからです。 「回避型愛着スタイル」の人が考える、共感される予想確率は限りなく低いです。 例えれば「空から女の子が降ってくる」確率と同レベルです。 このため、「共感されない」不満は「自分のところには空から女の子が降ってこない」不満と同レベルに思えます。 最初から失敗しかないチャレンジに失敗して、何が不満なのかが理解できません。

社会生活

共感能力の低さは、社会生活に影響が出ます。学生時代はあまり上手くいかなかったように思います。 共感できないため、ウェイウェイ出来ません。 ウェイウェイ出来きない人間がスクールカーストの上位に入ることはないので、中学高校は暗黒時代です。 ウェイウェイしなくてもよい仲間が見つかると楽しく生活できます。

社会人になると、社会生活への影響は少ないです。 会議であれば、論理的な説明さえできれば成り立ちます。 飲みニケーションなどで共感を求められることもありますが、拒絶さえしなければ、共感しないからといって迫害されることはありません。

共感能力が低くて、嫌われることもありませんが、特別好かれることもありません。 いわゆる人望に欠けます。ポジションによっては不利になるかもしれません。

個人的な対応

私は外見上は、実際どう見られているのかはわかりませんが、人の感情が読み取れないようには見えないと思います。 せいぜい愛想がないぐらいではないでしょうか?

共感能力がある人がどうやって人の感情を感じているかはわかりません。 私の場合は、心理学のように感情の原因を推測して理解しています。 たくさん本を読んだせいか、脳内にある人間の感情の原因リストは長いです。 そのうちで、現在の状況に一番近いものをパターンマッチして推測しています。

これは有利な面と不利な面があります。 誰かが怒っている時に、「口で言っている怒りの原因と真の原因が違いそうだ」と推測ができることがあります。 問題解決には有効です。 一方で、怒っている人は「とにかく怒っている感情を受け止めてほしい」と思っているようですが、 これに対しては「受け止める is 何?」となります。

おかげさまで対面でのコミュニケーションより、文章でのコミュニケーションの方が得意になりました。

治療?

治療が必要な性質のなのかはわかりませんが、共感能力を育てることはできるようです。

共感能力が低いといってもゼロではありません。 まれに共感出来ることがあるようです。 また「共感された」経験が少ないため、「共感されたい」という欲求を過小評価します。これは他人に共感することを放棄する原因になっています。

自分が他人に「共感する」「共感される」体験を繰り返すことで、共感能力を育てることはできるようです。 *1

典型的な例

1年前に ledsun.hatenablog.com で「生きる技法」を読んだと書きました。

いまの知識で思えば、著者の安冨さんは「強迫性パーソナリティ」でかつ「回避型愛着スタイル」でした。 「回避型愛着スタイル」の人間が感情を論理的に解釈しないと理解できない好例だと思います。

参考文献

愛着障害の克服 「愛着アプローチ」で、人は変われる

愛着障害の克服 「愛着アプローチ」で、人は変われる

愛着障害一般の話です。愛着障害の不安型と回避型を両方取り扱った本です。 過去の文豪や心理学の大家の愛着障害の例がふんだんに載っています。

回避性愛着障害 絆が稀薄な人たち

回避性愛着障害 絆が稀薄な人たち

上の本と同一著者です。回避性愛着障害に焦点を当てています。 回避性愛着障害をいくつかのタイプにわけて説明しています。 心理学の人には回避性愛着障害の人が多いようです。 共感能力の低い回避性愛着障害の人は、心理を論理で整理せずには居られないのかもしれません。

異性の心を上手に透視する方法

異性の心を上手に透視する方法

恋愛をテーマに、回避型愛着スタイルの男性と不安型愛着スタイルの女性がくっつきやすく、かつ上手く行きにくい理由が書いてあります。過去の経験がもろに該当していました。自分以外でも、該当する組み合わせは見かけるので、自分が当てはまるかもしれない人は読んでおくと心の準備ができて良いかもしれません。

タイトルは半分ぐらい詐欺です。特定の組み合わせのカップルが、お互いと心が全く噛み合わない理由を説明しています。

*1:世の中にはもっと良い方法があるでしょう。確実なことは専門家に聞きましょう。

サービス開発チームの拡大期におけるリーダーのレスポンシビリティ移譲に関する1アイデア

開発組織に関するポエムです。

背景

常駐や請負で、サービス開発チームのお手伝いをしたことがあります。 私に依頼がくる時は、サービスは売れていて、開発チームは拡大期にあります。 その時、開発者の人数は増えているが、開発リーダーの負荷は減らず、逆に増え続けるという現象を観測したことがあります。 過去に2件、目撃しました。

課題

開発リーダーはすべての「問い合わせ」と「機能拡張の意思決定」に参加する必要があります。 おまけに自分の実装タスクも持っています。 必然的に労働時間は伸び、「いつ寝てんだこの人?」という働き方をしています。

はたから見ていると、何年も続けられる働き方はないので、いつか破綻しそうな危機感があります。 実際、2件のうち1件の開発リーダーは退職しました。

果たして、我々はこの状況に対して何かできるでしょうか?

経験談

開発メンバーの視点

開発メンバーからはリーダーが大変なことはわかります。 ただ、どんな問題を抱えているのかはわかりません。 この立場でできることは

  • 要件を一度でなるべく細く聞き取る
  • リファクタリングを避けてレビュー工数を減らす
  • 修正点を最小にしてレビュー工数を減らす

などでした。このためには、受け入れるタスクを小さくする必要があります。 タスクが大きいと、リーダーとの相談量が増え、リーダーへの割り込み量が増えます。

アウトプットが少ないと評価されるのを覚悟で、手戻りにリーダーを巻き込まない強い心が必要です。 実際は、これができる人とやっている人は、とても少ないように思います。

開発リーダーの視点

今年の9月から11月に掛けて、炎上プロジェクトのリーダーをやりました。 立場は違いますが、共通する点もあるかもしれません。

炎上中のリーダーは手を止めることができません。 次のいずれをやめても、プロジェクトの進捗止まります。

  • 各機能の仕様や実装方針の意思決定
  • ボトルネックになる機能の実装
  • 進捗の把握
  • 顧客への進捗の報告とスケジュール調整

特に困るのがタスクを切り出す作業です。 タスクとして切り出したものは、開発メンバーにお願いできます。 問題をどのように解決するか、考えタスクに落とす部分は一番負荷が高いです。 一方で、それまでの経緯などコンテキストへの理解が必要であり、簡単に移譲はできない部分です。

また、プロジェクトの遅れに責任を感じているリーダーから、「プロジェクトを一度停止して体制の修正をしたい」とは言い出しづらいです。

方法の一つとして、リソースプランナー役の人に入ってもらって

  • 進捗の把握
  • 顧客への進捗の報告

を巻き取ってもらうと、だいぶ楽になります。 経験するまでリソースプランナーは要らない役職だと思っていました。 実際はすごく頼りになります。 ただし、感覚としては20%ぐらい楽になるぐらいです。 すでに120%以上の稼働に達している場合は、それほど効果がありません。

問題

  • 開発メンバーからはリーダーの本質的な課題が見えない
  • 開発リーダーは作業を止めることができない

開発チームからボトムアップで状況を改善することは難しそうです。

イデア

ワイガヤやったらいいのではないかな?と思います。

この手のコミュニケーションのミスマッチは、「サービスに対する熱意の差」みたいな誤解に基づいている気がします。

  • リーダーは、俺がこんなに頑張っているのにメンバーのやる気が足りない
  • メンバーは、俺も頑張りたいのに、どう頑張ればリーダーの役に立つのかわからない

熱意とかやる気は、見た目に差があっても内部的に差があるかはわかりません。 一方で、サービスに対する興味のある点や価値観は、開発メンバー全員が違うはずです。 今のフェーズに、たまたま価値観が合っている人が「熱意がある」ように見えているだけではないでしょうか?

そんなわけでワイガヤです。 サービスの開発を数日止めて、 二泊三日の合宿でサービスに対する思いを表明しあってはどうでしょうか?

  • 次の施作案
  • 既存の気にくわない点
  • 俺の感じるかっこよさにマッチする点、マッチしない点
  • どんなユーザーに使わせたいか

色々なアイデアがあると思うので、決めるためでなくて、「みんな、そんなこと考えてたのかよ!」と思うための会をとことんやるといいのではないかな?と考えました。

参考:「ホンダ流ワイガヤ」実践のコツと方法を、元ホンダ 本間 日義氏にインタビュー |ビジネス+IT

実践したことはないので、与太話です。

うまくいけば

すくなくとも開発リーダーの気持ち面で時間は稼げそうです。 その隙に、「雑用タスク何でもできるマン」*1を投入して、開発リーダーの持っているタスクまで落ちていない作業をタスク化。 チーム内に振りまいていけばなんとかなるでしょう。 開発リーダーの稼働が80%ぐらいまで落ちれば、もともと優秀な人ですから、あとは自分で改善できるはずです。

*1:例えば、私。ただ、目に見えるアウトプットは、通常の開発者とは違うので、そういうjob descriptionの元でないと怖くてできません。