読者です 読者をやめる 読者になる 読者になる

yet another pomodoro

つくりました

github.com

いつもどおり英語は適当です。

モチベーション

  • ポモドーロテクニックがやりたかった
  • tmuxのバーに表示したかった
    • ターミナルを全画面で使ってる事が多いのでmacのステータスバーに表示するのは微妙
    • tmuxのバーが一番いいかな?っていう感じで決まった
  • 終わったら通知が欲しかった
    • macユーザーなので右上にピコンと出る系のやつがよかった

対抗馬は?

  • hughbien/thyme: Console Pomodoro timer
    • 使おうとしたんだけど依存関係がちゃんと定義されてなくて普通にやると動かなかった
    • たしかgem installしてレポジトリをとってきてbundle installしてその後bundle exec rakeしてテストを通すとようやく動くようになった
      • 最後の1ステップがマジで謎すぎる
  • ほかはしらない

作ったもの

1秒sleepして、ってやるとどんどんズレるよなー、どうやってんのかなーと悩んでた。悩みながら実装は見ないでthyme使ってた。
あるときgoでループ回しながら指定期間過ぎたら「過ぎたよ」っていうのをchannel経由で送ってくれるやつがいたらそれでよくね?と思いついたので作ってみた。
まだthymeの実装みてないのでどうやってるのかはしらない。

tmuxに出すのはthymeの設定ファイルから察したやり方で。$HOME配下にファイル出してtmuxのステータスバー側でcatで読んでる。

終わったら通知というのは設定ファイルにスクリプトのテキスト書いてそれをexecする感じにした。これもthymeの設定ファイルを参考にしている。スクリプトの中身はterminal-notifierというのを使っている。
julienXX/terminal-notifier: Send User Notifications on Mac OS X 10.8 from the command-line.

直したいところ

  • -dとかでdaemon化したい
    • goでdaemon化するのちょっとめんどくさそうで止まってる
      • 適当にやる分にはできそうだけどどういう問題があるのかよく把握してない
    • 実運用的には gomodoro & でバックグラウンドに飛ばしてる
  • SIGNAL対応
    • SIGINTくらいしか対応してない
    • まあ実用上困らんか……
  • tmux用のファイルは開きっぱなしのほうが効率がいい気がする?
  • 日別のpomodoroカウントとりたい気がする

実は作ったのは結構前で3commitしかないけど1commit目でmain.goは全部できてます。

2017年2月振り返り

記録

2017年2月 コーディング時間: 3378分 言語比率 1〜5位

Ruby 859
YAML    625
ERB 291
Docker  163
JavaScript  143
訂正版
total: 4517 minutes
Rank    Lang    Minutes
1   Ruby    1090
2   YAML    747
3   ERB 291
4   JavaScript  277
5   C++ 208

2017-03-13追記: 2/11と2/16のデータがないけど仕方ないのでこれで確定版

再訂正版
total: 11230 minutes
Rank    Name    Minutes
1   Ruby    4350
2   YAML    1418
3   JavaScript  702
4   Markdown    680
5   C++ 571

2017-03-15追記: 普通に計算ミスってました。 -> 懺悔 - Smoky God Express

ただしデータの信憑性があやうい

雑感

記録から

時間すくねーなって思ったんだけどこれはまた後で。

Rubyは主にCLIツール作ってた時間かな。いろいろ作った。使うかあやしいけど。

  • hakoのyamlを生成するやつ(諸事情あって2回つくった)
  • erbを自分たちのawsリソースの情報を埋め込みやすくしたラッパー
  • CircleCi内でやりたい処理を詰め込んだ便利gem

あとrubotyのプラグインとlambda(nodejs4.3)も書いてた。公開できないけど。流れとしてはこんな感じ
githubの通知 → lambda → ruboty → AWS CloudFormation

PRに対してChange SetのURL貼ったりマージしたらexecuteしたりexecuteしたらステータスが完了になるまでまって教えてくれたりって感じ。

Dockerfileは、うーん、なんでこんなに長いんだろう。そんなに書いてないと思うが。謎。herokuのdocker対応番作ろうとして挫折した記憶はある。

JavaScriptはwakatimeのviewerの構成を変えたからかなー。HTML直書きのVueだったのをcomponent分割してwebpackするようにした。
Go側はほぼいじってない。

wakatimeのviewerについて

viewerのバグ直した。これは結構大事なバグで、なにかっていうと0分だとそもそも折れ線グラフに点が打たれないからスキップされちゃうってバグ。初歩的すぎる……。もしかしてバカなんだろうか。真面目にデータみてないからわかってなかったけど……。
そして0分をいれて折れ線グラフを見ると1月にやる気ないどころかマジでなにもしてない1週間があってちゃんと値とれてるのか不安になってきた。っていうか2月のこの日おれ絶対コード書いてるんだけどってのが抜けてるのでたぶん取れてない。

2017-03-13追記: このあとすぐにサーバにログインしてその時点からでもとれるデータはとった

エラー通知なんもいれてないけどさすがにいれてretryさせる形がいいのかなー。エラー通知はslackに投げときゃいいかな

2017-03-13追記: エラー検知してリトライはめんどかったので昨日の分がとれてなかったらslackに投げるようにした

これからの振り返り

施策を打てるような分析をやりたいなーと思ってる

  • 曜日単位での集計
  • タブの分け方の変更
    • 年次、月次、週次の種別をかんたんにかえたい
  • 書いてる時間の集計
    • 集中してる時間とかわかるかも?

最近のコーディングネタ

Ruby

  • テスタビリティのために引数をとりたい
  • 普通にプロパティアクセスするような気楽さでアクセスしたい

この2つの気持ちがあわさってこういうことをよくしている

class Foo
  attr_reader :baz, :qux

  def bar
    @bar ||= build_bar(baz, qux)
  end

  def build_bar(baz, qux)
    # baz, quxは結局 @baz, @quxなのだがとっておくとテストがしやすい
    # なんか適当な処理
  end
end

# test

subject = Foo.new
assert(foo.build_bar(1, 2) == 3) # こういう感じで内部状態@baz, @quxを意識しなくてよくなる

#build_bar がもう少し重い処理ならFactoryを使うべきだとは思うけど全部につくるのはめんどくさくてこういう妥協をしている

JavaScript

webpack

webpack入門した。自分で調べながらかいたらこの程度で済んでいる。

https://github.com/hkdnet/wakatime-viewer/blob/master/webpack.config.js

  • cssはもともと書いてないからsassとかの設定がない
  • 画像サーブもしてないからそのへんもない
  • htmlサーブはやるけどまだ書いてない

このへんが短くなってる理由だろうか。どんどん育てていきたい

underscore

標準JavaScriptのArrayで微妙にたりなくて使ってるがunderscoreに渡す関数内で普通にArray.prototype.reduceとか呼んでてどうなんだろうという感じがある。

fetch

fetch APIをつかってHTTPリクエストを送ろうとしている。自分のAPIエンドポイントのためにClientクラスも作っている。

そうするとテストのためにはfetchをDIで使えるようにしておくとよい、気がする。

class Client {
  constructor(opts) {
    this.fetch = opts.fetch || fetch;
  }
  getFoo() {
    return this.fetch('/foo');
  }
}

一方でfetchは呼び出しコンテキスト(っていう言い方であってますか?Rubyでいうレシーバみたいな)がwindowであることを期待しているので、結局bindして渡す必要がある。

const client = new Cleint(fetch.bind(window));

いやー、微妙にダサい。どうしたもんか。

C++

先日書いたけど競プロっぽいのにC++使ってる。

そして関数内で int[n] を確保したらセグフォって「は???」という気持ちだったのだけどそういうこともあるらしかった。
そのあとぼでさんにunique_ptrとか使うといいんですよーと聞いたのでつかってみている

ツイートのリンク先を見ればわかるが、モダンさを感じて結構よさげ。

一方で困っていることもある。
いままで適当に配列つくって渡してーとやっていたがスタック領域以外のところにメモリを確保するようになったのでそのメモリを使うオブジェクトの生存区間とかを意識することになった。
というか意識しなきゃいけないなってことに気づいて結局グローバルにint配列確保するようにしてごまかしている。せっかく教えてもらってるのにすみません……。

相対的鉈

久々に競プロをやったら「あーこれとりあえずこうすれば動くけどたぶんでかいケースで落ちそうだなー」と思う問題に多数当たってめちゃくちゃ悔しい思いをしたのでまたアルゴリズム系の勉強をしようと思った。

家にあるアルゴリズム系の本はAOJ*1の本だけ。ちゃんと(?)購入当時に挫折済み。
なのでAOJ本をやり直すことにしたのが3日前くらい。

当時はたしか水たまりを計算する問題が解けなくて挫折したのだけど*2今解いてみたらあっさり終わって「いつの間にこんなに……」という気持ちになった。解説の内容をうろ覚えながら頭にいれてたのでソレが残ってただけだと思うけど。特に地力があがったわけでもないだろう。いや上がってないわけではないと思うけど別に競プロっぽいことやってないしな……。

普段はRuby使いだしRubyで書くかと思ってたのだけど、どうも便利メソッドが揃いすぎてて卑怯な気がしてきた。卑怯というか学習目的なら不適切というか。なのでC#でEnumerableとか封印して書くか、と思ったらAOJのランタイムがmonoでめんどいことになるのもなーと思ってうじうじ。そこでC++書けばいいじゃんって気持ちになってきたので最近書いてる。

「Goがなんとなく好き。Rubyは魔法で切れたか切れてないかよくわかんないけどスパスパパシパシ切れる感じでそれはそれでステキなんだけど、Goは鉈でオラァっていって切り回していく感じがあって好き。書いた分だけ動くっていうプログラミングの原点に立ち戻れる気がする」みたいなことを前にいった記憶があるのだけど、C++を前にするとGoは日本刀くらいの切れ味がありますね。ほんものの鉈の無骨さを目の当たりにしている。
たぶん僕の書いてるC++がマクロもtemplateもautoも使ってないのでだいぶ無骨だっていうのはあるのですが。というかたぶんほぼCで書いてる気がする。便利にC++書けたら嬉しいよなって気持ちもあるけどたぶんそこへの道のりがかなり長そうなので尻込みしちゃう。あくまでも競プロ用、みたいなね。適当なバッチかいてたときにpowershellの文法があやしいのと同じ。複雑なのはC#書くけど書き捨てはpowershellで。仕事でならRubyだけど勉強なら(無骨な)C++で。

元鉈現日本刀のGoは書いた分だけ動くといってもfor rangeとか配列とSliceとかが言語機能として備わっててやっぱモダンなんだよなーという感じ。C++を書いてGoへの想いを強くしている。
AOJでは選べないけどyukicoderはGoとかRustが選べた気がするので、yukicoderでこの問題を問いていけばアルゴリズムの勉強になるよという記事(あるいは本)の登場が待たれますね。

*1:サイト 具体的にはALDSコース

*2:見直したら超序盤で笑う。もうちょい頑張れ

mrubyだと32個以上の必須引数をとれない

www.amazon.co.jp

別に普段mruby使ってるわけでもないんですが『言語のしくみ』を読んでたら気になったので検証。

本の記載

タイプ3 Ax(25ビット) op(7ビット)

命令タイプ3はオペランド雨を全部1つにして25ビットのオペランド(Ax)として取り扱います。タイプ3の命令は、OP_ENTERの一つだけです。
(中略)
OP_ENTERはAxに指定されたビットパターンを見て、メソッドの引数チェックをします。OP_ENTERは25ビットのうち23ビットを5/5/1/5/5/1/1に分割して引数指定と解釈します。各ビットの意味を表2に示します。

ビット | 内容  
 5  | 必須引数の数
(以下略)
表2 OP_ENTERの引数指定 より一部抜粋

全体は1-3 バーチャルマシン、mrubyの命令を見てみる より。

思ったこと

必須引数の数が5ビットで管理されてるってことは 25 = 32 で 0〜31 までしかないはず。
32個の引数をとったら困るんじゃね?

検証

環境はこんな感じ。

$ ruby -v
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]
$ bin/mruby --version
mruby 1.2.0 (2015-11-17)

さて、引数32個も書くの嫌なのでさくっと生成します*1

n = 32
args = (1..n).map { |e| "a#{e}" }
str = <<-EOS
def foo(#{args.join(', ')})
  puts true
end
foo(*Array.new(#{n}))
EOS

File.write('main.rb', str)

じゃあ検証してみましょう。rubyとmruby両方で実行します。

$ ruby generate.rb
$ cat main.rb
def foo(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32)
  puts true
end
foo(*Array.new(32))
$ ruby main.rb
true
$ bin/mruby main.rb
trace:
        [1] main.rb:1:in Object.foo
        [0] main.rb:4
ArgumentError: 'foo': wrong number of arguments (32 for 0)

たしかに引数チェックは5ビットで行われてるみたい。 32 for 0 だから0個の引数を期待してることがわかります。

31個だと両方共trueを出力します。 33個だと wrong number of arguments(33 for 1) になってることも確認。

じゃあ0個を期待してるらしいので実際0個にしたらどうなるの?というのが以下。

$ cat main.rb
def foo(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32)
  p a1 # 中身みたかったので変更
end
foo # 引数ゼロ個
$ ruby main.rb
main.rb:1:in `foo': wrong number of arguments (given 0, expected 32) (ArgumentError)
        from main.rb:4:in `<main>'
$ bin/mruby main.rb
nil

当然rubyでは引数の数が違ってエラー。mrubyだと通りました。やったね
ただし引数は全部nilなので特に意味はありません。

じゃあ引数の最大値は31個なのかというと違います。
表2を全部写すのがめんどかったので書いていませんが、オプション引数の数とかキーワード引数の数も管理されています。
キーワード引数はmruby 1.2.0では未対応なので使えません*2。しかしオプション引数ならば5ビットまで使えるのでもう少し頑張れそうです。

n = 31 # これで31 * 2 の62個まで
args = (1..n).map { |e| "a#{e}" }
args += (1..n).map { |e| "b#{e} = #{e}" }
str = <<-EOS
def foo(#{args.join(', ')})
  puts true
end
foo(*Array.new(#{n}))
EOS

File.write('main.rb', str)

これで実行するとちゃんと通るのでたぶん62個ですかね。

$ cat main.rb
def foo(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, b1 = 1, b2 = 2, b3 = 3, b4 = 4, b5 = 5, b6 = 6, b7 = 7, b8 = 8, b9 = 9, b10 = 10, b11 = 11, b12 = 12, b13 = 13, b14 = 14, b15 = 15, b16 = 16, b17 = 17, b18 = 18, b19 = 19, b20 = 20, b21 = 21, b22 = 22, b23 = 23, b24 = 24, b25 = 25, b26 = 26, b27 = 27, b28 = 28, b29 = 29, b30 = 30, b31 = 31)
  puts true
end
foo(*Array.new(31))
$ ruby main.rb
true
$ bin/mruby main.rb
true

ビット的には必須引数の数とオプション引数の数が隣あってるからオーバーフローしたりしないかなって思ったんですがしなかったです。まあそりゃそうだ

# generate.rbは上記のをn = 32に変更
$ bin/mruby main.rb
trace:
        [1] main.rb:1:in Object.foo
        [0] main.rb:4
ArgumentError: 'foo': wrong number of arguments (32 for 0)

rubyだと引数の最大値いくつなんだろ?というのも気になりますが、n = 2_000_000_000_000 でも大丈夫だったのでまあいいかと思って最大値は見てません ( ˘ω˘)

*1:時間的には変わんないというか遅い気もするけど気持ちの問題ですよ

*2:たぶん。表2中に未対応とあり、mirbでやってもSyntax Errorになったので

『オブジェクト指向設計実践ガイド』 実践編

はじめに

この記事は『オブジェクト指向設計実践ガイド』の内容をもとにテストコード書いてたらよくわかんなくなったので助けてくれ、という内容です。だれか助けてください。コメントとかRe:記事とかのリアクションあると嬉しいです!

本の内容の抜粋

詳細は買って読んでね、ということでざっくりと。

www.amazon.co.jp

  • Dependency Injectionでテストしやすくしよう」
    • 依存オブジェクトの注入*1ってやつだよ
    • サンプルコード参照
  • 「送信コマンドメッセージはテストダブルを使うとよい」
    • コマンド: 副作用がある
    • 送信メッセージ: テスト対象のメソッドから呼ばれてる他のメソッド
    • 要は副作用があるなら副作用を呼び出せてるかはチェックすべきってこと

サンプルコード

サンプルコードの数値リテラルは適当な値なのでどんなギアだよって感じになってます。すみません。

# DependencyInjection 適用前
class Wheel
  attr_reader :rim, :tire
  def initialize(rim, tire)
    @rim = rim
    @tire = tire
  end
  
  def diameter
    rim * (tire * 2)
  end
end

class Gear
  attr_reader :ratio, :rim, :tire
  def initialize(ratio: nil, rim: nil, tire: nil)
    @ratio = ratio
    @rim = rim
    @tire = tire
  end

  def gear_inches
    ratio * Wheel.new(rim, tire).diameter
  end
end

Gear.new(ratio: 1, rim: 3, tire: 2) # 値はてけとー
# DependencyInjection 適用後
class Gear
  attr_reader :ratio, :wheel
  def initialize(ratio: nil, wheel: nil)
    @ratio = ratio
    @wheel = wheel
  end

  def gear_inches
    ratio * wheel.diameter
  end
end

Gear.new(ratio: 1, wheel: Wheel.new(3, 2)) # ここでDependency = Wheelを注入!

んで、これをやっておくとテストで Wheel クラスを参照しなくて済みます。『参照しなくて済む』というのは『GearのテストがWheelに依存しな』くなるということです。

# 旧
class GearTest < Minitest::Test
  # 受信メッセージのテスト
  def test_calculates_gear_iniches
    gear = Gear.new(ratio: 1, rim: 3, tire: 2)
    assert_equal(12, gear.gear_inches) # gear_inchesの中でWheel#diameterに依存
  end
end

# 新
class DiameterDouble # テストダブルの導入
  def diameter
    6 # 固定値で返すとバグらなくてあんしん
  end
end

class GearTest < Minitest::Test
  def test_calculates_gear_iniches
    gear = Gear.new(ratio: 1, wheel: DiameterDouble.new) # WheelじゃなくてDouble使う
    assert_equal(12, gear.gear_inches)
    # 実行してもWheelはどこにも必要とされてない = 依存していない ので変更につよい
  end
end

ほんとはこれ以降もダブルをどう扱うかとかが続くんですけどこのへんで。

実践してみた

タイトルが実践入門ですからね、実践していきます。
雰囲気を出すためにそれっぽいコードを書きます。記事をファイルに保存するような処理を考えましょう。
もらった文字列の1行目をタイトルとし、他を本文としてファイルに書き出す処理です。

vs クラスメソッドへの依存

DI前のコードがこちら。

module FileCreator
  def self.create(title, text)
    # いろんな処理とか
    File.write(title, text)
  end
end

class Article
  attr_reader :title, :body
  def initialize(body)
    @title, @body = body.split("\n", 2)
  end
  
  def save
    FileCreator.create(title, body)
  end
end

Article#save は明らかに FileCreator.craete に依存していますね。DIしましょう*2

DIする

DI版にしてみたのがこちら。

class Article
  attr_reader :title, :body, :creator
  def initialize(body, creator: FileCreator)
    @title, @body = body.split("\n", 2)
    @creator = creator
  end
  
  def save
    creator.create(title, body)
  end
end

でもこのコード、2点気になるところが。

  • creatorの値をほぼ変える予定がない場合にオプション引数取れる実装は、今後の変更に備えすぎてるように見える
    • KISSとかYAGNIとかそういう感じで
    • 変更する予定ないくらいに密結合になってるならテストでもそのままでいいような気がする
      • でも副作用は気になる……
    • 拡張性じゃなくてテスタビリティのための実装だと思えば仕方ない気もする……。
  • クラスをインスタンス変数にとるの、結構キモくないですか?
    • 「クラスもインスタンスもオブジェクトだよ。過度に区別すんな」という趣旨のことは同書の別の場面で言ってた気がする*3
      • あくまで「キモい」という感覚であって具体的に何が悪いのと言われるとよくわからない
        • Railsみたいな定数リロードがあると古いの残ったりはしそう
        • プロダクションでの実害は特にないと思う

DIはしないけど継承 + オーバーライドでなんとかしてみる

あるいはこういう感じにメソッドにしてみるとか。

class Article
  attr_reader :title, :body
  def initialize(body)
    @title, @body = body.split("\n", 2)
  end
  
  def save
    creator.create(title, body)
  end
  
  def creator
    FileCreator
  end
end

# テスト時にはオーバーライドしてどうにかする

class ArticleDouble < Article
  def creator
    Class.new { def self.create; end }
  end
end

うーん、まあ、ギリギリ……?テスト用のクラスができちゃうの、あんまり好きじゃないけど……。

スタブ使う

違うアプローチとして、アプリケーションコードをDIでよくするんじゃなくてスタブ使ってみるとか。

class ArticleTest < Minitest::Test
  def test_save
    article = Article.new(<<~EOS)
    たいとるでーす
    本文でーす
    2行目でーす
    EOS
    expected_args = [
      'たいとるでーす', 
      "本文でーす\n2行目でーす\n"
    ]
    creator = MiniTest::Mock.new.expect(:call, nil, expected_args)
    FileCreator.stub(:create, creator) do
      article.save
    end
    assert(creator.verify)
  end
end

これがすっきりしてていいけど、テスト側に思いっきり FileCreator って書かれてるのがうーん……。Dependency減らしたいんじゃなかったっけ?

まとまらないまとめ

  • クラス同士の依存が明らかな場合、スタブがよさそう
    • つまりFileCreator以外のcreatorが存在しそうにないとき
    • テストコードにクラス名がおもいっきり書かれるけど増えるかわかんないんだしいいんじゃないの
  • creatorが多数存在するとき
    • DIにするのがよさそう……なのか?
    • BaseArticleとFileArticleとDatabaseArticleと、みたいにして #creator をそれぞれ実装しちゃうのがよさそう
      • テストはArticleDoubleを作ってそこにスタブいれちゃう
      • オーバーライド版 + スタブ版って感じ
      • テスト用のクラスができちゃうのは仕方ない

あるいはなんかいい方法があるんでしょうか?実際のアプリケーションの成熟具合とも関連すると思いますがご意見お待ちしております 🙋


2017/02/06 04:24追記

クラスオブジェクトをインスタンス変数にもちたくない問題がー

これたぶん基本的には問題なくてArticleのインスタンスはFileCreatorよりも寿命が短いことが想定されるから。
DIにするのもそんなに高コストではないのでDI化しておいていいんじゃないのってのがいまの結論です

*1:依存性の注入って訳は好きじゃない

*2:書き終わってからFileCreator.createがtitleとbody取るっていうArticleに特化したものなのに名前が汎用的すぎるのでは、と思ったけど直してません

*3:UMLとかのあたりだったっけ?

2017年1月振り返り

はやいものでもう2017年の1/12が終了したんですね*1。2016年振り返りで書いたように、定量的な指標を導入してみたのでそれを使って振り返りをやろうと思います。

定量的な指標というのはwakatimeで計測した時間です。wakatimeはコーディングしているときの時間を計測してくれるサービスです。
自分が最近何やってるかな、というのの振り返りにはもってこいですね。 プロジェクト名を書いても伝わらないので言語別の指標での振り返りを毎月やっていくことにします。

記録

2017年1月 コーディング時間: 3724分 言語比率 1〜5位

YAML         601 
Ruby         388
ERB          254
Go           233
JavaScript   201

total: 8135 minutes

訂正版
Rank    Name    Minutes
1   Ruby    1658
2   YAML    1511
3   Go  1018
4   JavaScript  326
5   ERB 321

2017-03-15追記: 普通に計算ミスってました。 -> 懺悔 - Smoky God Express

雑感

記録から

えーと、アホみたいにYAMLをいじってますがこれはインフラをやっていたせいです。最近はAWSでDockerを走らせるには、というのをいろいろ試してます。CloudFormationの設定ファイルを書き、hakoの設定ファイルを書き、docker-compose.ymlを書き、circle.ymlを書き。試行錯誤をひたすら繰り返していたらこうなりました。得意言語はYAMLです(キリッ*2。ERBもひたすら多いですがこれも設定ファイルのテンプレートとしてERB使ってたからですね。 Rubyは、まあ普通にアプリケーション書いてたので妥当。
GoとJavaScriptは振り返り用のツールでGo + Vue.jsのwebアプリを作ったのでそれの影響ですね。

総コーディング時間が3724分 = 60時間ちょいなのは、なんか少ない気がする。
AWSの画面でイベント見つめたり、ドキュメント読んだり、どうするかミーティングしたりというのは平常より多めだった気がする。

あと日別で見ると完全にやる気を失っている日が何回かあって、なるほどという感じ。

f:id:hkdnet:20170201000344p:plain

こういうのをなくしていきたいのでアラートとかいれたほうがいいのかな。
「昨日n分しかコード書いてませんけど大丈夫ですか?」的な。

やったこと

ざっと思い出していきます

  • 振り返り用webアプリ書いた
  • google slides apiについて調べてある程度使えるようになった
  • cloudformationに詳しくなった
  • awsでのNW構築ができるようになった
  • hako + ECSあるいはEBを使ったデプロイができるようになった
    • hakoは割と難しいと思うのでなんか記事書きたい

こんなかなー。
やったことはほんとに忘れていくので週次くらいでサクサク書いてったほうがいいかもしれない。

*1:このフレーズを直近3日で使った人70%くらいいそう

*2:なお全然仕様把握してない