2021年の振り返り(趣味を除く)

これは「「はじめに」の Advent Calendar 2021」25日目(最終日)の記事です。

趣味の話は振り返り対象じゃないので書きません。

買った本

買った年月順ではありません。また、ななめ読みだけした本も含まれています。

技術系

マイクロサービスアーキテクチャに触れることが多かったので、そっち系が多め。

www.oreilly.co.jp www.oreilly.co.jp www.oreilly.co.jp

www.amazon.co.jp www.amazon.co.jp www.amazon.co.jp

会社の同僚におすすめされた本(英語) 内容的には、「プログラマが知るべき97のこと」の考え方に特化したもの

www.amazon.co.jp

チームビルディング系

チームトポロジー。自身の考え今までの組織パターンをまとめながら読んでいる最中。

www.amazon.co.jp

スクラムマスターとしての知識量を増やすために読んでいる本。

www.amazon.co.jp www.amazon.co.jp www.amazon.co.jp www.amazon.co.jp

ビジネス系

ザ・ゴールシリーズ

ザ・ゴールが出版20周年らしいので電子書籍で書い直したシリーズ。ついでにコミック版も購入。 多分、社会人になって初めて買ったビジネス系の書籍シリーズ。ちなみに、当時はビジネス系として意識して読んではいなかった。

www.amazon.co.jp www.amazon.co.jp

www.amazon.co.jp www.amazon.co.jp www.amazon.co.jp www.amazon.co.jp www.amazon.co.jp

マイケル・サンデルの翻訳本。過度の能力主義の行き着く先を考えさせる本。 www.amazon.co.jp

元日本マイクロソフト社長の本。 www.amazon.co.jp

物理本は結構前に買った記憶があるけど全部処分したので・・・ www.amazon.co.jp

OKRを取り入れた組織も増えてきたので改めて。 www.amazon.co.jp

以下の本は読むとの実践するのは違うけど、少しでも自身のアウトプットの質を高めるために買い続けているのかもしれない。 www.amazon.co.jp www.amazon.co.jp www.amazon.co.jp www.amazon.co.jp

IT系の知識にギャップを感じたときに役に立つのではと思って買った本 www.amazon.co.jp

会社の同僚がこの本ベースの話をしていたので。 www.amazon.co.jp

Github

github.com

仕事しての草はそれなりに生えたけどプライベートでの草が少ない。

記事

Zennのアカウントを作成。 zenn.dev

はてなブログhajimeni.hatenablog.jp

Qiia qiita.com

アドベントカレンダーで思いつくまで何もアウトプットしていない。来年の課題かもしれない。 Qiitaなんて、gitのブランチ削除記事が一番閲覧数が多いというね・・・

技術的に自分で手を動かし 新しく 学んだり検証したこと(順不同で列挙)

継続的に知見を得ようとしたこと

  • チームビルディング系の知識
  • ECS
  • Docker

その他

SNS

Twitter, Facebook, YouTrust, LinkedInのアカウント整備。

登壇系

社内の技術系の発表会で数回行ったのみ。外部は一切なし

イベント参加

結局これだけ。 smn.connpass.com

ふりかえり

  • 12月以外にアウトプットがない。
  • 読書は技術書というよりチームビルディングやビジネス書が多かった。
  • イベント参加回数が少ない
  • エンジニア個人としてのコードによるアウトプットが少ない

来年の抱負

  • 技術書を 1冊/2ヶ月
  • ブログ/Zenn/Qiitaへのアウトプットを1回/2週
  • イベント参加回数を 1回/2ヶ月
  • イベント登壇を 1回/6ヶ月
  • 個人のコードによるGithubへのアウトプットを1回/1週

AdventCalendarについてと、2021年AdventCalendarを書こうと思った理由

これは「「はじめに」の Advent Calendar 2021」4日目の記事です。

※この記事は、ただのポエムなので読まなくても良いです。

AdventCalendarとは

アドベントカレンダー (Advent calendar) は、クリスマスまでの期間に日数を数えるために使用されるカレンダーである。待降節の期間(イエス・キリストの降誕を待ち望む期間)に窓を毎日ひとつずつ開けていくカレンダーである。すべての窓を開け終わる迎えたことになる。

引用: Wikipedia ja.wikipedia.org

元はといえばキリスト教にまつわるイベントの一つでクリスマスまでの日数を数えるカレンダーでしかありません。 いまやソフトウェア界隈では技術ブログの投稿を12/1から12/25まで連続で行うという年末を飾る一大イベントの一つにまでなっていると思います。

Wikipediaに引用リンクがあるので詳細はそちらを見てもらいたいですが、せっかくなのでこちらでも紹介しようと思います。

日本のソフトウェア界隈のAdvent Calendarの歴史っぽいもの

自分が最初にAdventCalendarのことを知ったのは2010年くらいだった記憶があります。 惜しまれつつも昨年サービスを終了した atnd で募集があったりして、昔使っていた「はてなダイアリー」でなにかに参加した記憶があります(記憶なので、改ざんされているかもしれません。)

QiitaとAdventarくらいしかチェックしていませんが、もしかしたら他の箇所でも公開されていると考えたらカレンダー数自体はもっと多いのかも。

qiita.com

2021/12/04時点でのカレンダー数を数えたら合計 777 カレンダーでしたので、Qiitaを利用している層でAdventCalendarに参加して発信をする人たちはここ数年変わっていなさそうですね。 AdventCalendar登録数はかわらなくても記事の充足率(記事が埋められた割合)や完走率(毎日しっかりアップロードされた数)は増えているのかも? 興味があるのでQiitaさん、調査おねがいします!

自分がAdventCalendarを書こうと思った理由

続きを読む

今年のAdvent Calendar

つい昨日思いついた「毎日1時間使って小ネタをAdvent Calendarに登録する」企画。

ルール:

  • 毎日投稿する
  • 記事は投稿する当日に書く(前日までに書き溜めるはNG)
  • 当日は 05:00 区切り(13日の記事は14日05:00まで投稿可能とする)
  • 当日に投稿できなかったら反省文を140文字以内でtwitterで書く。
  • 書く時間は1時間じゃなくても良い。
  • 最低10行以上書く。
  • タイトルは当日に変更しても良い。

場所: adventar.org

なぜやるのか

最近、世間に対するアウトプットが少ないと感じていたので強制的に何かを出すためにやる。 癖をつけないといけないが、ハードルが高すぎても尻込みしたり言い訳をしてやらなかったりするので。

APIのE2Eは `カラテ` を使うべし。古事記にもそう書いてある。

<これまでのあらすじ>

API開発を終えたサラリマンエンジニアであるタロウは、しめやかにテストを開始した。しかし、そこに待ち受けたのはジェーソン(訳注: JSONのことだと思われる)の複雑怪奇極まりない組み合わせだった。納期を守らないエンジニアは実際シツレイにあたりセプクものだ。このままではジリー・プアー(訳注:徐々に不利)であるタロウの前に恩師であるカラテ・マスターが現れる。

TL;DR

続きを読む

プログラミングする上で避けるべき命名パターン

この記事は ただの集団 AdventCalendar PtW.2019 (https://gw-advent.9wick.com/calendars/21) の4日目の記事です。
前日は erika 様の AWS GlueでETL - Qiita でした。

はじめに

きれいな変数名、クラス名、メソッド名つけれていますか?

出来ていない理由の大半に、

  • すでにある名前に合わせている
  • 複雑なことをしていて、適切に名前を考えられない

などがあると思いますが、ここではそういった構造や歴史的経緯などは取り扱いません。
単純に見かけた瞬間、「やばい?」という感覚を持ってもらいたいだけです。

ここで言いたいことは、 以下のようなパターンの名前が出てきたら大抵の場合、何かがおかしい可能性があるのでコードを見直しませんか? という問題提起です。 ヒヤリハットだったり、気付きの一助になれば幸いです。
プログラミング言語として、Webアプリケーションでよく使われるような言語を対象にしています。

あと、適当にパターンとかつけていますが特に分類したわけではないし、個人的な考えにすぎないのであまりツッコミしないでください。

略語パターン

標準(だと書いた人が思っている)略語パターン

  • tmp
  • ret
  • fmt
  • frm
  • cd
  • cvt
  • cmn

やたらと3文字に納めようとしているパターンです。
おそらく書いた人は標準で、よく使われていると思っています。 しかし、残念ながら通じていないことのほうが多いので気をつけたほうが良いです。

こういった単語が出てきた場合、 x, y, z や m, n などに置き換えてもコードが読めるかどうか考えてみましょう。
通じない場合、この命名自体が間違っています。
通じる場合、そもそも意味を持っていないので、 a, b, c などで置き換えてもとの単語を考えさせないようにしましょう。

母音省略パターン

  • kbn
  • kss
  • bbr
  • nyknb
  • 例はいくらでもあるので省略

もはや、なんのことか一見しただけでは意味不明なパターンです。
DBのカラム名などでよく発見されます。
8文字以内に収めようとして母音の一部だけ省略している亜種がある場合もあります。

いかなる場合においても許されない(と自分は考えています。異論は認めます)
たとえファイルサイズやメモリサイズを削りたい場合においても、意味をなしていないので省略したいなあらいっその事全く意味をなさない文字の方がまだマシです。
何らかの意味を持っているのではないか?業界特有の略語があるのではないか?など余計な考えを発生させてしまうことが良くないと思います。

数字Suffixパターン

  • xxxx1
  • xxxx2

など後ろに数字がついており、かつ数字以外の名前が一致しているパターンです。
メソッド内の変数名の場合、多分順次処理を一時変数に置き換えているのでしょうが、時々使う順番を変えていたりするので読む側に混乱を招きます。
メソッド名そのものの場合、もはや使い分け方法は他人には理解不能になります。
オーバーロードのように、同名のメソッドを型で区別する方法があるのでそういった手法を取る、位なことをしましょう。
そもそも処理ごと違っており同名をつけるべきでない場合もあるので、 気をつけたいパターンです。

文章パターン

  • fooAndBarAndBazAnd...
  • doHogeThenDoFugaAnd...

やたらと長い変数名やメソッド名がある場合、よく読むと文章や複数の小節から構成されているときがあります(例外としてテスココード中の変数名・メソッド名は除きます)
責務を適切に分離できていない場合、こういったパターンが見受けられます。
このパターンは上記までのパターンに比べ、リファクタリングのチャンスだ、というポジティブに捉えることができます。
And, Or, Then, などが変数名・メソッド名に含まれているのがよくある特徴です。

おそらくメソッドが長い、特定処理に対して適切なドメインを導き出せていない、など改善できそうな事が多いので、積極的に見つけた箇所のリファクタリングを推進すると良いと考えます。
その際に、 コードの臭い - Wikipedia を探すのが良い対処方法になるかもしれません。

英語がわかんないよパターン

動詞と名詞がおかしいパターン

  • クラス名に CreateUser
  • メソッド名に UserCreate

日本人だからね・・・仕方ないね・・・
で、終わればよいのですがおそらく周りのコードに流されて惰性で何も考えずにつけられている事が多いです。
この場合、適切にクラスやメソッドが作られているとは言えないことが多いです。
名前そのものがヤバイ、というよりこの名前が残ってしまっているとおそらくコードにも何らかの問題があると推測される方がヤバイです。

ハイブリッドパターン

  • createRiyousha
  • sakujoUser

みたいなパターンです。 日本人だからね・・・(ry
では済まないことが多いです。
こちらの場合、動詞や名詞がおかしいパターンよりも深刻な場合があります。
おそらく、他のクラスや他のパッケージに同じ意味を示すような変数名が複数存在している可能性が高いです。
ユビキタス言語がなく、開発者が好き勝手に名前を考えてつけたけど、命名方法は個人の裁量に任された結果発生している可能性が高いです。
今すぐにでも開発者全員集めてドメインモデルをみんなで考えて見ることをおすすめします。

英語で統一されていてもユビキタス言語がない場合もありますが、これは別の問題なので今回取り扱いません。

コメントで言い訳しているパターン

// 本当は○○だが、その後△△△する必要があるため、一旦□□する
val savedFileTemp1 = ...

はい。
時間がなく、ひどいコードやひどい名前であることを実装者は知っています。
これを見た人がマネージャーなりリーダーなら、今すぐリファクタリングのタスクを作り本人に是正することをお願いしましょう。同時に「無理させてゴメンね」と優しく声をかけましょう。
マネージャーなのか、リーダーなのか、はたまたプロダクトマネージャーなのかわかりませんが、無理のあるスケジュールや他人が決めた納期という謎の概念によって書いた人は苦渋の選択でこういったコメントを残しています。
変数名とは離れましたが、ひどい変数名になっていたとしてもこういったコードになった原因は違うところにある場合が多いです。

避け方としては、 常にリファクタリングしたりコードを見直す時間も考えていくしかありません。

まとめ

つらつらと書きましたが、こういったパターンに陥らないためには

  • プログラム上で使う名前を考える時間は、コードを書く時間の7割を注ぎ込んでも良い

と思うくらいには大事です。 一番時間をかけても良いと思います。
うまい変数名、メソッド名が考えられない、ということは責務の分離が必要だったり、コードそのものや設計そのものを見直すきっかけになります。
納期が・・・という言葉に惑わされない強い心と、ときには組織の仕組みの改善が必要になったりしますが、それはまたの機会に・・・

プログラム上で時間を扱う際に気をつけること

この記事はただの集団 Advent Calendar 2018の22日目の記事です。昨日は wararaki (Kyohei Watarai) · GitHub さんの 玉子焼きとだし巻き玉子を分類してみた - Qiita でした。

adventar.org

結論

結論から先に示しておきます。

  • 日付・時刻を扱う際は、目的に合わせて使いたいクラスを適切に選択する必要がある。
  • 日付・時刻に関わらず、クラスの選択や設計・実装は目的に沿って行う必要がある。

背景 - 時間を扱う際に発生する問題

あと3日でクリスマスですね。(記事の投稿日は2018年12月22日09:00)

こういった会話は日常的によく行われていると思います。では、これをプログラム上のコードで表現してみましょう。

(※サンプルコードは全てScalaのREPLで記述します。)

scala> import java.time.{Duration, LocalDateTime}
import java.time.{Duration, LocalDateTime}

scala> val today = LocalDateTime.of(2018, 12, 22, 9, 0, 0)
today: java.time.LocalDateTime = 2018-12-22T09:00

scala> val christmasDay = today.plusDays(3)
christmasDay: java.time.LocalDateTime = 2018-12-25T09:00

一見良さそうに見えます。でもちょっと待ってください。

アプリケーションを開発する上では、コードは厳密に表現していかないと思わぬバグを生みます。

クリスマス という日が始まるのは 12月25日の00時 からではないでしょうか? コード上ではクリスマスはすでに始まっており、既に9時間も経過しています。
これでは、コードでクリスマスと言う日を正しく表現したことにはならない可能性があります。

では、それを考慮し あと3日あと2日と15時間 と表現するべきではないでしょうか?会話の文章を変えてみましょう。

後2日と15時間経過するとクリスマスと呼ばれる日が始まりますね。
(記事の投稿日は2018年12月22日09:00)

これをコードで表現してみます。

scala> import java.time.{Duration, LocalDateTime}
import java.time.{Duration, LocalDateTime}

scala> val today = LocalDateTime.of(2018, 12, 22, 9, 0, 0)
today: java.time.LocalDateTime = 2018-12-22T09:00

scala> val christmasDay = today.plusDays(2).plusHours(15)
christmasDay: java.time.LocalDateTime = 2018-12-25T00:00

コードは確かに正確になりました。

しかし、今度は別の問題が発生します。日常会話で 後2日と15時間でクリスマス とか普通は言いません。ならば、コードの方に問題があるのではないでしょうか?

このあたりの勘所が強い方達は最初のコードの時点でお気づきになられたと思いますが、LocalDateTime -> LocalDate にしてみます。

scala> import java.time.{Duration, LocalDate}
import java.time.{Duration, LocalDate}

scala> val today = LocalDate.of(2018, 12, 22)
today: java.time.LocalDate = 2018-12-22

scala> val christmasDay = today.plusDays(3)
christmasDay: java.time.LocalDate = 2018-12-25

良さそうですね。つまり、最初の文章は正確には

今日(2018-12-22)から後3日経過(+3 day)するとクリスマスと呼ばれる日(2018-12-25)になる

と表現していました。コードでも無理なく表現できています。

しかし、往々にして後ろに余計な情報 2018年12月22日09:00 などがあるとそちらに目がくらんで時間も扱うクラスでコードを書いてしまったり、書かれたコードを見たことがあるのではないでしょうか?

また、 良さそう と書いたのはここにタイムゾーンという情報が増えると、 日本ではクリスマスだがアメリカはクリスマスではない 、といった状況が発生しプログラムで予期せぬバグを生むこともあるからです。(※LocalDate,LocalDateTimeではTimezoneを扱えません)

ということで、今回はプログラミングをする際、時間を扱う時にどういった観点が必要か、どういった点に気をつけなければいけないかを考えていきたいと思います。

続きを読む

DataDog 用の jolokia AgentCheck書いてみた

記事名のとおりなんですが、AgentCheck用のインストール方法とか特に無くてファイルを置くだけっぽいので、 gist にあげておきます。コードが酷かったり、項目増やせなかったりするのは今後の課題。

gist.github.com

モチベーションとか

そもそもの話、JVMの監視をするときには極々単純に以下の項目を監視したいわけです。

  • JVM内のメモリの状態
  • GCの状態

また、メモリの状態と言ってもJVMって Heap/NonHeap みたいな単純なものではありません。EdenとかSurvivorとかOldとかがあります。 (※G1GCではちょっと違う)

GCも、 Java8 のデフォルトでは ParallelGC Java9ではG1GCだったりで、見なければいけない項目も少しずつ違います。

JVMのメモリについては、詳しくはこちらの方のブログが分かりやすかったので、是非参照してください。

blog.pepese.com

それなのに、監視サービスの某鯖とか某犬とかのJVM監視の項目を見ると、全然足りないんですよ。

mackerel-agent-plugins/mackerel-plugin-jmx-jolokia at master · mackerelio/mackerel-agent-plugins · GitHub

Java

鯖の方は、jstatで監視するなら十二分に満たしているんですが。

mackerel-agent-plugins/mackerel-plugin-jvm at master · mackerelio/mackerel-agent-plugins · GitHub

Jolokia(JMX)で監視する際には、鯖の方も項目を増やすプラグインを書いてみたりとかしています。

github.com

本題に戻って、DataDogのJmx監視のためのプロセスなんですが、JolokiaではなくてJmxFetchといって、JMX取得のためのJavaプロセスを内部で動かす方式となっています。 これが、dd-agentをDockerで動かして、AutoDiscoverを前提にすると Xmx512M 固定で起動します。公式のDockerのメモリ推奨量が256MBなのに。

https://github.com/DataDog/dd-agent/blob/5cad70dd33b58716ed102070c95edbd557bf3816/jmxfetch.py#L48

_JVM_DEFAULT_SD_MAX_MEMORY_ALLOCATION = " -Xmx512m"

コード見つつ動かしながら挙動調べた感じ、AutoDiscoverじゃなくて監視用のファイルを置いた場合にはプロセスのメモリ使用量を変更できそうでしたが、それだとAWSのECSとかでなんのタスクが動くかわからないものに対しては使えそうにありません。

そもそも、監視のプロセスだけで512MBも必要とか尋常じゃないです。AWSのECS上のTaskとして動かした場合、t2.small なんて1GBしかないんだから、残りの使えるメモリがもう半分以下しかないです。

サポートとかに聞いてもAutoDiscoverとかDocker上のdd-agentとかあんまり考慮されていなさそうだったのと、Docker起動時に外部の環境変数から変更できそうな感じじゃなかったので、Jolokiaで監視すればいいんじゃないかなと思い立った次第。

で、探したけどJolokiaようのAgentCheckスクリプトが見つからなかったので作ったのが冒頭のスクリプトになります。

使い方とか

dd-agentをDockerで動かしているので、Dockerfile置いておきます。 サーバー上で普通に動かしているのであれば、 check.d ディレクトリにファイルを置くだけでいいはずです。

FROM datadog/docker-dd-agent:latest

ADD jolokia.py /opt/datadog-agent/agent/checks.d/jolokia.py

buildして、

docker build -t dd-agent-jolokia .

dd-agentを起動(MacOSの場合。cgroupを通して監視するので、詳細は以下のリンクを参照)

docker run -d \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /proc:/host/proc:ro \
-v /sys/fs/cgroup:/host/sys/fs/cgroup:ro \
-e API_KEY=<API_KEY> \
-e SD_BACKEND=docker \
-e DD_LOGS_STDOUT=yes \
dd-agent-jolokia

https://hub.docker.com/r/datadog/docker-dd-agent/

監視対象のDockerはラベルを付けて起動 JavaagentでJolokiaを指定してポートを開けるようにすること。

docker run -d \
-p 13333 \
-l com.datadoghq.ad.check_names='["jolokia"]' \
-l com.datadoghq.ad.init_configs='[{}]' \
-l com.datadoghq.ad.instances='[{"host": "%%host%%", "port": "%%port%%" }]' \
jvm_application -javaagent /paht/to/jolokia-jvm-agent.jar,port=13333,host=0.0.0.0

起動したDockerContainerの監視はLabelをつければ自動で監視対象に追加してくれる仕組み。このあたり、DataDogの仕組みは素晴らしいですね。

https://docs.datadoghq.com/guides/autodiscovery/docs.datadoghq.com

ParallelGCの場合、監視項目はこれだけ増えます。 MemoryPoolから動的に項目取得してくるので、GCの種別を変えれば項目も変わります。

jolokia.class_load.loaded
jolokia.class_load.total
jolokia.class_load.unloaded
jolokia.gc.count
jolokia.gc.time
jolokia.memory.code_cache.committed
jolokia.memory.code_cache.init
jolokia.memory.code_cache.max
jolokia.memory.code_cache.used
jolokia.memory.compressed_class_space.committed
jolokia.memory.compressed_class_space.init
jolokia.memory.compressed_class_space.max
jolokia.memory.compressed_class_space.used
jolokia.memory.heap.committed
jolokia.memory.heap.init
jolokia.memory.heap.max
jolokia.memory.heap.used
jolokia.memory.metaspace.committed
jolokia.memory.metaspace.init
jolokia.memory.metaspace.max
jolokia.memory.metaspace.used
jolokia.memory.non_heap.committed
jolokia.memory.non_heap.init
jolokia.memory.non_heap.max
jolokia.memory.non_heap.used
jolokia.memory.ps_eden_space.committed
jolokia.memory.ps_eden_space.init
jolokia.memory.ps_eden_space.max
jolokia.memory.ps_eden_space.used
jolokia.memory.ps_old_gen.committed
jolokia.memory.ps_old_gen.init
jolokia.memory.ps_old_gen.max
jolokia.memory.ps_old_gen.used
jolokia.memory.ps_survivor_space.committed
jolokia.memory.ps_survivor_space.init
jolokia.memory.ps_survivor_space.max
jolokia.memory.ps_survivor_space.used
jolokia.thread.count

雑感

勢い余って書いてしまったけど、本当に他に困っている人いないのかどうか・・・ みんなそこまでJVM内の項目気にしていないのかなぁ。 あと、いくらなんでも雑に書きすぎたかもしれない。