| @労働

瑞梅寺川の桜

リモートワークが長くなってきた。正直どのくらい自宅で仕事しているか定かではない。ほとんど外出しないので時間の感覚がおかしくなってきている。職場がリモートワークを許可するようになってもしばらくは出社していたが、二週間ほどで自分の具合が悪くなり会社に行くのを控えるようになった。その後本格的に具合が悪くなって家庭内隔離状態になり、同時に会社もリモートワークを推奨から出社禁止という状態に変わった。約 3 年ぶりのリモートワークで色々思うことがあったので雑に書きます。

リモート会議

リモートのミーティングでは前職の頃から Zoom をよく使っていた。いまの職場でも Zoom を多用している。リモートミーティングの Tips みたいなのは最近どこかで流れてきたのを読んだ気がするけど自分も思うところがあるのでまとめておく。

まず第一にはミュートだ。話さない人はとにかくミュート。 Zoom は音が鳴っているマイクの音を拾って音声ストリームに載せる。そして音声ストリームでは主として話している(音を出している)人の音声が採用されて、その他の人の音声はカットされてしまうようだ。図にするとこんなイメージ。

オフラインの会話

Zoom の会話 1

Zoom の会話 2

Zoom の会話 3

イヤフォン・ヘッドフォンを使う

自宅だとイヤフォンを付けずにスピーカーから音を出しがちだ。 Zoom のミーティングにもイヤフォンを付けずに参加してしまうかもしれないが、ハウリングしてしまったりするのでなるべくイヤフォンを付けてパソコンのスピーカーからは音を出さずに参加したい。

またイヤフォンを付けずに参加するとパソコンのマイクを使うことになって、会話と会話の切れ目が聞き取りにくくなる。 Zoom はハウリングが起こらないよう、ストリームで流している音と同じ音がパソコンのスピーカーから出ていたらそれを拾わないようにしているはずで、パソコンのマイクで話し始めるときに切り替え処理が必要になり、会話の始まりのあたりが拾われなかったりする。マイク付きのイヤフォンを使うことでこの問題は回避できる。

ちなみに以前も書いているけど Apple の iPhone 用イヤフォンはよくできていると思う。 2800 円くらいなのにマイクの音が良好で、相手の声もよく聞こえる。 10 倍以上の値段がする AirPods Pro を使っている人の声より、 2800 円の iPhone 用イヤフォンを使っている人の声の方が聞き取りやすい。 Lightning 端子ではなく 3.5mm ジャックのやつじゃないとパソコンにつなげないので注意。

やっとるわ感

先週、 sudoken さん( Kaizen Platform の CEO )が三戸正和さんという人と対談してる YouTube Live を見た。ほとんど三戸さんという方の話で sudoken さんの話はあまり聞けなかったが、「リモートワークではプロセスでの評価ができないので、アウトプットを意識的に行い、自分の成果をアピールすることまでが仕事のうち」という話が面白かった。リモートワークでは結果による評価に移行せざるを得ないということだ。

エンジニア業を止めてからつくづく感じるのが、人はしつこいほど言わないとわかってくれないということだ。伝えたいことは社内ブログに書いていたらみんな読んでくれるわけではなく、目立つような場所に掲示したり、目立つ方法で喧伝したり、何度もしつこく見せたりしないとなかなか見聞きしてもらえない。リモートワークをやっていて自分はそこそこ頑張って仕事してるつもりでも、その成果をちょっと過剰なんじゃないのと思えるくらいにアピールしないと、組織や同僚からは仕事してる風には受け取ってもらえないだろうな、と思った。リモートワークではやっとるわ感を出すところまでが仕事の範疇に入ることになる。

増えた自由に使える時間を有効に

リモートワークに移行して、毎日通勤にかかっていた 2 時間を自由に使えるようになった。前職時代は朝仕事を始めるギリギリまで寝ていたけど、いまは 7 時くらいに起きて仕事を始める 9 時半くらいまでブログを書いたり散歩したり食器を洗ったりしてる。最近、ブログの記事が増えているのはそういうわけだったりする。

コロナウイルスのせいで恐らく世界大恐慌に陥るだろうと思う。 1 ヶ月も 2 ヶ月も世界中の人が外出しなかったら経済回らなくなる。この時期にゲームしたり Netflix 見たりするだけでなく、何かしら一つ生産的なことをして自分に投資しておかないと数ヶ月後に泣きを見ることになるだろうなと思う。いまはインターネットの会社はコロナウイルスの影響をあまり受けていないか、あるいは Zoom や Slack 、そのほか EC をやっているところは逆に業績好調かもしれない。ただ、世の中が全体的に不景気になると必ずその余波が及ぶわけで、そのときをどう迎えるかはソフトウェア企業に勤める人々にも重要なテーマとなるだろう。

| @ブログ

75 件ほどあった tech.portalshit.net の記事を取り込んだ。実家に住んでいた 10 年前に始めた技術ブログで、最初は Rails 製の Mephisto 、その次に Jekyll で構築した。まだ GitHub Pages の仕組みが存在する前で、自前で用意したさくら VPS に git push すると自動でビルドして記事が公開されるような仕組みを作ったりしてた。

職業プログラマーになろうとしてもがいてた頃にやってたブログで、いま読み返すと「頑張ってたんだな」感があっていなたい記事が多い。

だいぶ放置していて、いまは S3 で静的サイトとして公開していたのでそのまま放置でもよかったが、 10 年前と違って何でも一カ所にまとめて書いておきたいという気持ちが強くなって取り込むことにした。ブログはトピックを混ぜずに一つのトピックにフォーカスした方がよいと 10 年前は考えていたのだけど、最近の世の中のブログ記事の読まれ方は変わってきていて、一人の人のブログをフィードリーダーに登録して読むというより、 SNS をだら見していて流れてきた記事を適当に消費するというスタイルに変わってきているので、一つのブログに一つのテーマという書き分けは不要になったと感じる。

tech.portalshit.net を取り込んだおかげで Archive ページのグラフに占める技術記事の割合が増えた。

Tech category Bar extension

ちなみに取り込みは以下のようなコードを書いて SQL の INSERT 文に変換した。

require 'yaml'
require 'pathname'

files = Dir.glob(File.join(__dir__, '_posts', '*.markdown'))
files.each do |file|
  content = File.read(file)
  _, header, body = content.split('---')
  header_yml = YAML.load(header)
  title = header_yml['title']
  tags = header_yml['category']
  tags = tags.is_a?(Array) ? tags.map(&:downcase) : [tags&.downcase]
  slug = Pathname.new(file).basename.to_s.sub(/\d{4}\-\d{2}\-\d{2}\-(.+?)\.markdown/, '\1').gsub('_', '-')
  body = body.strip.gsub(/\n/, "\\n").gsub('\'', '\'\'')
  created_at = File.birthtime(file).to_s.sub(' +0900', '')
  updated_at = File.mtime(file).to_s.sub(' +0900', '')
  puts <<~EOS
    INSERT INTO entries(title, user_id, category_id, slug, markup, type, draft, body, frozen_tag_list, created_at, updated_at) VALUES('#{title}', 1, 6, '#{slug}', 'redcarpet', 'Post', 0, '#{body}', '#{tags.join(',')}', '#{created_at}', '#{updated_at}');
  EOS
end

| @ブログ

Chart Tooltip

Archive ページにこだわってしまう理由、グラフを表示させてみて(ブログ過去記事をカテゴリーごとに集計してグラフ化 - portal shit!)何となくわかった気がする。過去記事ページというのはブログの書き手にとってはアクティビティダッシュボードなのだ。ジョギング系アプリ使ってる人なら記録をあとから振り返ることがあると思う。それと同じで、自分が過去にどのくらいの頻度、密度でブログを書いていたかを自分は知りたいと思うのだろう。その用途に適しているのが過去記事ページというわけで、 Archive ページの使い勝手の改善は自分のブログアクティビティをふり返りやすくしたいという欲求の表れだったのだと思う。

ちなみにグラフを作ってみたことで、 2006 年頃に異常な数の記事を書いていたことがわかったし、かなり内容のない記事(新聞やテレビを見た感想)ばかり書いていたことがわかって興味深かった。 2007 年からは記事の数が減るが、これは Twitter を使い始めたからだと思う。2009 年頃、病気療養を終えて就職しようとしているあたりからプログラミング関係の記事の数が増え、実家を出て福岡のブラック企業に勤め始めてからは記事数が減った。

あまり ASP 型のブログを使ったことがないのでよく分からないが、こういうカテゴリーごとの Chart 機能はないような気がする。一時期、ダイエット日記を書いていたはてなブログにはアクセス解析機能とアクセス数の統計機能はあったが、自分のブログアクティビティを振り返る機能はないと思う( PRO になればあるのかもしれない)。

自己満足的なブログの書き手にとっては、どれだけ読まれたかももちろん気になるけど、どれだけ書いたかも重要なのではないかと思う。読まれたかというのは結果であり、書いたかというのはプロセスというか、自分の頑張りだ。仕事をする上では結果にフォーカスにしなければ意味がないけど(使われない機能を作ってリリースするのは自己満足)、ブログは趣味なのだからプロセスの部分(自分の頑張り)が可視化される仕組みがあってもよいと思う。

| @技術/プログラミング

Chart

Rechars という React のチャートライブラリを利用して、 Archive ページにカテゴリーごとに記事を集計してグラフ化する機能を作った。

グラフの Bar にカーソルを載せると Tooltip が表示されて、具体的な件数がわかる。

Chart Tooltip

カテゴリごとに表示・非表示を切り替えることも可能。グラフ下のカテゴリー名( Legend )をクリックして切り替えられる。

Chart Show-Hide Toggle

ただし残念なことに Bar を非表示にしたときに Legend の表示を変化させるのが難しくてできていない。

仕事で使ってる Looker とか Redash であれば Legend をクリックして表示・非表示を切り替えることができ、それに連動して Legend の色をトーンダウンさせたりする機能が付属しているが、利用した Recharts にはその機能がなかった。 Bar の表示・非表示切り替えも標準サポートされていなかったので、 GitHub の Issue の情報を頼りに無理矢理実装した。

コードはこんな感じ。結構汚い Hack で、 Bar の表示・非表示を、表示用のキー文字列に空白を追加するかしないかで切り替えている。

  // クリックされたアイテムが `this.state.disabled` 配列の中にすでに存在していれば除外し、
  // 存在してなければ追加する
  selectBar(event) {
    let dataKey = event.dataKey.trim()
    if (this.state.disabled.includes(dataKey)) {
      this.setState({ disabled: this.state.disabled.filter(item => item !== dataKey) })
    } else {
      this.setState({ disabled: this.state.disabled.concat([dataKey]) })
    }
  }

  render() {
    return (
      <ResponsiveContainer height={500}>
        <BarChart
          data={this.state.data}
          margin={{
            top: 20, right: 20, left: 0, bottom: 20,
          }}
          style={{ fontSize: '14px' }}
        >
          <CartesianGrid strokeDasharray="3 3" />
          <XAxis dataKey="year" />
          <YAxis />
          <Tooltip labelStyle={{ color: '#000', fontWeight: 'bold' }} itemStyle={{ margin: '0 2px 0 4px', padding: '0' }} />
          {// Legend クリック時のコールバックに `this.selectBar` を指定する }
          <Legend onClick={this.selectBar} />
          {/*
            `this.state.categories` 配列と `this.state.disabled` 配列の内容を比較し、
            `this.state.disabled` に追加済のカテゴリーは dataKey に空白を追加することで非表示に
          */}
          {this.state.categories.map((category, index) => {
            let dataKey = this.state.disabled.includes(category) ? category + " " : category
            let color = this.colors[index % this.colors.length]
            return(<Bar key={index} dataKey={dataKey} stackId="a" fill={color} />)
          })}
        </BarChart>
      </ResponsiveContainer>
    );
  }

| @技術/プログラミング

DataMapper のドキュメントを見たくてググったが出てくるのは Stack Overflow ばかりで公式サイトが検索結果に出てこない。 GitHub の DataMapper のリポジトリ( Archive されている)経由で見に行ってみると、なんと ROM ( Ruby Object Mapper ) のページにリダイレクトされた。

ROM は Hanami で使われる ORM で、 DataMapper よりもさらに ActiveRecord と使い心地が異なる。

Qiita の以下の記事を読むと使い方のイメージが湧く。

軽くてシンプルなのだろうがだいぶ特殊だ。

Lokka の使い手は少なくとも Heroku が使える人で、そういう人ならば ActiveRecord の方が Rails の本やドキュメントで学びやすいはずだ。というわけで早めに、真剣に ActiveRecord への移行を考えなければならない。