hitode909の日記

以前はプログラミング日記でしたが、今は子育て日記です

車検

今年の4月に買った車だけど、来年の1月で車検が切れるので車検というものをやってきた。
車体価格が安めだと思ったら、車検が近いので安かったのかもしれない。


何も考えずにディーラーでお願いしてみたら、消耗品を色々交換することになって、全部で10万円くらいかかった。
車検は通せるものの、タイヤを変えることをおすすめされた。
タイヤを変える場合の見積もりをもらったら6万円とのことで、出費の時期はずらしたいので見送ってきた。もうちょっと値段低めのものを探したい。安いタイヤはないのですか?って聞いたら数千円くらいは下がるとのことで、価格感が高めな気がする。


普段デミオに乗っていて、代車でMAZDA2を借りたらほぼ一緒で、ただ塗装の色が、赤だけどリニューアル後のものでちょっと違う。けど注意深く見ないと違いはわからないと思う。
あとは、うちのはディーゼルエンジンだけど代車はガソリンエンジンで、車体が軽いのか、コロコロ転がる感じで走った感触が違った。うちのは車体が重くて加速をがんばってるというか、よいしょっと移動する雰囲気。
エンジンの音はガソリンのほうが静かで、うちのは寝ている子供を起こすために設計されたような音がする。
代車には360度カメラがついていて便利だった。バックしなくても、壁に近づくと自動的に有効になるようで気が利いている。後付けできるならしたらよさそう、と思ったけど、ちょっと調べたところ、後付けはできないようだった。

引越し費用を払うためにつみたてNISAとかいったん売却するかどうか、とか考えていたのだけど、なんか急にお金が入ってきてなんとかなった。
悩みごとがあると精神的な余裕がなくなるのだな、ということを実感して、お金の準備ができたら著しく気が楽になって、先週とは全く別人みたいな精神状態になってきている。
あとは、引越し後の部屋のレイアウトどうしようってディスカッションしてたのだけど、とりあえずシミュレーションするために、今の家で近いフォーメーションにしたら、こんな感じね、と雰囲気がわかって、考えることが減ってきた。
考える前に試してみて様子を見よう、というのは、仮説に仮説を重ねて、想像する、という形から、やってみて現実を観察すればよい、という形に変えられるので、考える負荷を下げられる、という点でも良いのだな、と思う。

椅子に興味が出てきた。
かっこいい靴の代わりに椅子に目が向くようになってきていて、それだけ家にいる時間が増えたのだなと思う。
一人暮らしのときは、家の役割といえばめちゃくちゃに酔っ払って帰ってきてひっくり返る場所だった。椅子なんか当然持っていなかった。

逆に、今は靴はほぼ1種類で、足のモーションだけで最速で脱ぎ履きできるJUNGLE MOC一択になっている。これ以外、革靴を1個残して全部処分でもよさそう。
JUNGLE MOC 2.0ジャングル モック 2.0[メンズ] – MERRELL 公式オンラインストア

急に看病モードに切り替わって看病している。
夜中に子供が全然寝てくれないので、これはテレビでも見るしかないって録画したテレビ番組を再生して、ポテチを食べ始めたりしていて、それはそれでおもしろかった。
建もの探訪(最近一番好きな番組)を見てたら弓道場のある家が登場していて異常な雰囲気だった。
バックナンバー|渡辺篤史の建もの探訪|テレビ朝日


リポジトリ内のソースコードを機械的にリファクタリングし続けるスクリプトを作る

こんにちは、はてなのマンガチームでPerlを書いているid:hitode909です。
先日書いた、Perlのソースコードをリファクタリングし続けるスクリプトについて紹介します。

@EXPORTを撲滅したい

普段Perlを書くときに苦労していたのがテストを書くことで、さまざまなテスト用のヘルパ関数がどこからexportされているかわからない、という困りごとがありました。
私たちのプロダクトではマンガビューワを作っているので、テスト用の作品をcreate_seriesで作り、作品に紐づくエピソードをcreate_episodeで作り、エピソードに対してテストを書く、というような流れでテストを書くことが多いです。
以下の例ではGiga::Test::Core::Seriesからcreate_seriesがexportされていますが、込み入ったテストでは、このようなuseが数十行に渡って続き、どこからどの関数がexportされているかわからない!というのが困っていたことです。
@EXPORTを撲滅して、@EXPORTをすべて@EXPORT_OKに書き換え、名前付きimportに揃えることで、どのファイルから何がimportされているかが自明なものにできれば、テストを書くときに迷う時間を短縮できそうです。

# このcreate_seriesがどこから来たのかわからなくて困る
use Giga::Test::Core::Series;
ok create_series;

# こうしたい
use Giga::Test::Core::Series qw(create_series);
ok create_series;

上記のような課題に対して、同僚のid:papixが1ファイルを対象にした書き換えスクリプトを書いてくれていました。
papix.hatenablog.com


このスクリプトはPPIを使ってPerlのソースコードを書き換えてくれるもので、人間がエディタでリファクタリングするのと比べると、機械的かつ短時間で実行できて便利、結果がいつも同じなので間違いが起きづらい、という利点があるのですが、以下のように対象ファイルを人間が指定して起動する必要がありました。

$ docker-compose exec app \
  carton exec -- perl script/tools/code/kill-export.pl lib/Example.pm

1ファイルずつ実行して動作確認して…というのを繰り返すのは手間が大きく、途中で飽きてしまいそうで、できることなら機械的に対象のファイルを探して書き換えていってほしい!ということで、もうちょっと自動化をしてみます。

対象ファイルを探す→書き換え→テスト→コミット を繰り返すスクリプト

人間が置き換えをするとき、以下のような工程をたどることになります。

  • リファクタリング対象のファイルを探す
  • リファクタリング対象のファイルをスクリプトに渡し、書き換える
  • 影響のありそうなテストを実行する
  • テストが通ったら結果をコミット

どの工程も、機械的に判定できることに気づきます。

  • リファクタリング対象のファイルを探す
    • @EXPORTを使っている箇所をgit grepして探せる
  • リファクタリング対象のファイルをスクリプトに渡し、書き換える
    • 探したファイルを上記スクリプトに渡して実行すればよい
  • 影響のありそうなテストを実行する
    • git diffして、差分のあるファイルだけを探してテストを実行すればよい
  • テストが通ったら結果をコミット
    • 人間が操作していなければ、スクリプトの書き換え結果をgit commit -a -m を使ってまとめてコミットできる
  • 全ファイルの書き換えが終わるまで繰り返し

ということで書いてみたのが以下のスクリプトです。なんとなくRubyで書きました。こちらのgistにぺたっと貼っています。
普段メンテナンスしているプロダクト用のスクリプトをそのまま貼っているので、動かしてみたいという方は少々手直しが必要です。

利用回数の少ない順に書き換えていく

今回の書き換えは以下のような操作になります。

  • t/lib/以下には@EXPORTを使ったpackageがあり
    • こちらは@EXPORT_OKに書き換えたい
  • t/以下に、packageを利用しているテストファイルがある
    • こちらは名前付きimportに書き換えたい

まずは簡単なところからやっていくため、利用回数の少ないところから順にリファクタリングしていくことにしました。
簡単な場所なら、1箇所からのみ参照されているファイルを書き換えることになりますし、一番多く参照されているpackageをリファクタリングするときには、数百ファイルをまとめて書き換えることになります。
ソースコードはgitを使って管理しているので、git grep --name-onlyを使って、参照回数を数えています。雑にfindコマンドを使うとtmp/以下などに書き散らしたファイルも対象となって思ってもみない変更が起きがちだったり、gitで管理していないファイルをいきなり触ると、もとに戻せない可能性もあって危険が伴います。

target_files = `git grep --name-only -z -w '@EXPORT' t/lib/`.split(/\0/)

# 利用回数の少ない順に処理していく
used_counts = {}
target_files.each{|target_file|
    package = IO.read(target_file).scan(/package ([^; ]+)/).first.first
    used_count = `git grep --name-only -z -w 'use #{package}'`.split(/\0/).length
    used_counts[target_file] = used_count
}
target_files_order_by_used_count_asc = target_files.sort_by{|target_file|
    used_counts[target_file]
}

実装から対応するテストファイルを探す

リファクタリングが成功しているかテストするのも自動化しているのですが、全テストを手元で実行すると時間がかかるので、今回変更のありそうなファイルだけを対象にして実行しています。
このあたりのテストを実行する部分も頑張っているポイントで、普段メンテナンスしているプロダクトでは、lib/Giga/Example.pmのテストをt/Example.tに配置しているので、実装とテストファイルの対応を機械的に変換して対応づけています。
Kernel.#systemの結果が失敗していたらそこでraiseして処理を打ち切っているので、目視で壊れた部分を手直ししてコミットし、再度スクリプトを実行すると、続きからリファクタリングを再開できる作りとなっています。
最終的に本当にリファクタリングが成功しているかは、CI上でテストが通るかどうかで確認します。

def run_changed_tests
    test_target = `echo "$(git diff --name-only t lib/)\n$(git diff --cached --name-only t lib)" | perl -pe 's{^lib/Giga/}{t/}g; s{\.pm$}{.t}g;' | sort | uniq | perl -nlE 'say if -e'`.gsub(/\n/, ' ')
    return if test_target.empty?
    puts "Running tests #{test_target}"
    result = system %Q(docker-compose exec app carton exec -- prove -v #{test_target})
    unless result
        raise "test failed"
    end
end

コミットメッセージにpowered byを入れておく

機械的に変更されたコミットは、blameしたときなどに、あとからみて意図を読み取りづらい場合があります。
結果をgit commitするところは以下なのですが、powered by #{$0}をコミットメッセージに入れておくことで、このコミットがスクリプトによって機械的におこなわれたことがわかるようになっています。
結果が間違っていたときには、スクリプトを見に行くと、どこがおかしかったかわかるように手がかりを残しています。

def commit target_file
    system %Q(git commit -a -m "#{target_file} の @export 撲滅\n\npowered by #{$0}")
end

結果

上記のようなスクリプトを用意することで、ほぼ自動的に63コミット、649ファイルの書き換えに成功しました。
この63コミットにかかった時間は数時間ほどで、定時後にご飯を食べたり風呂に入ったりしている間にPCをほったらかしにしていたら、コミットがどんどん進んで便利でした。
もし仕事しているふりをしたい人がいたら、リファクタリングのスクリプトはリポジトリにコミットせず、1ファイルずつ丁寧に書き換えているという報告をすれば、しばらく遊んで暮らせそうです。

f:id:hitode909:20211222193222p:plain
63コミット、649ファイルの書き換えに成功
f:id:hitode909:20211222193030p:plain
機械的にコミットしている様子

その後も手分けして何個かPull Requestを出していくことで、プロジェクト内のテスト用パッケージ(t/lib/)からは@EXPORTを撲滅することができました。
残るはlib/以下にいくつか残っていますが、こちらはテストを書くときにはあまり参照しないので、そんなに困っている箇所ではなく、難しいポイントは乗り越えられて、ほっとしています。

まとめ

今回、以下のような知見を得られました。

  • ソースコードが大きく、機械的に書き換えられる場面では、スクリプトを使ったリファクタリングが有用
  • リファクタリング方針に沿って自力でリファクタリングを進めるスクリプトを書くことで、リファクタリングを自動化できる

GitHub上で自動的にパッチを送ってくれるbotは、こういうことをソースコードのクロールとセットでやっているわけですね。GItHubなどのコードリポジトリを対象にして、スク数のリポジトリから対象のソースコードを探す機能を入れられれば、人類滅亡後もしばらくはリファクタリングを続けることができて良さそうです。


この記事は、Perl Advent Calendar 2021の23日目でした。前日はid:papix、明日はid:karupaneruraです。おたのしみに!
qiita.com

altにもスタイルを当てられる

altにスタイルを当てたいと思ったことがなかったので知らなかったけど、普通にスタイルをあてられるようだった。

こんにちは

色を変える

こんにちは

フォントサイズを変える

こんにちは


画像のリンク切れなどでalt属性が目に見えていたら、画像が読めないことに対処しがちで、altの見た目をカスタマイズしよう、と思い当たったことがなかった。
骨折したときにギプスに落書きする、みたいな活動。