nakaoka3の技術ブログ

2023年中に52本なにか書きます

年末なのでカメラのファイルをバックアップした

年末なのでデジカメのファイルをバックアップした。rsyncaws CLI を使って、DropboxとS3にバックアップを行った。更にタスクランナーに追加して、簡単にバックアップを実行できるようにした。

SDカードからDropbox

Dropboxの2TBプランを使っていて、空き容量に余裕があるのでDropboxに写真のバックアップをしている。

SDカードにデータが入ったカメラをUSBケーブルでmacにつないで、 rsync コマンドを使ってカメラのファイルをDropbox のフォルダに移動する。後はDropboxのデスクトップアプリがファイルをアップロードしてくれるのを待つ。

rsync -avu --progress --exclude=".*" /Volumes/Untitled/ ~/Library/CloudStorage/Dropbox/Camera/ZV1/

SDカードからS3

aws CLIaws s3 sync コマンドを使って、s3バケットにカメラのファイルをアップロードした。Dropboxになにか問題が起きたときや、Dropboxを脱出したいときのことも考えてS3にもバックアップするようにした。まだS3にバックアップしておいたよかったと思ったことはないけど、保険みたいなものだ。

aws s3 sync --storage-class STANDARD_IA /Volumes/Untitled/ s3://your-s3-bucket

スクランナーを使う

繰り返し行うことなので、忘れないようにタスクランナーで実行できるようにしてみた。

最近使い始めたTaskというタスクランナーを使った。

nakaoka3.hatenablog.com

タスクの定義を Taskfile.yml に書くと、 task タスク名 で実行できるようになる。以下の例では task backup-to-dropboxDropboxにバックアップするタスクが実行できる。

version: '3'

tasks:
  backup-to-dropbox:
    desc: "カメラのファイルをDropboxにバックアップする"
    cmds:
      - rsync -avu --progress --exclude=".*" /Volumes/Untitled/ ~/Library/CloudStorage/Dropbox/Camera/

  backup-to-s3:
    desc: "カメラのファイルをS3にバックアップする"
    cmds:
      - aws s3 sync --storage-class STANDARD_IA /Volumes/Untitled/ s3://your-s3-bucket

複数のタスクをまとめる

複数のタスクを呼び出すタスクを作る事もできる。以下の例では backup-to-dropboxとbackup-to-s3 の2つのタスク を呼び出す backup というタスクを追加した。

  backup:
    desc: "カメラのファイルをDropboxとS3にバックアップする"
    cmds:
      - task backup-to-dropbox
      - task backup-to-s3

このように書くと一つのタスクで、他の複数のタスクを順番に実行できる。

グローバルタスク

ホームディレクトリにおいた Taskfile.yml に定義されたタスクは、どのディレクトリからでも task -g タスク名 で実行できる。

上記の場合だと task -g backup というコマンドを実行すると、Dropboxへのバックアップを行った後に、S3へのバックアップを行う処理が実行される。

カメラのバックアップは手作業でやるとなるとやり方を忘れたり手間がかかる作業だ。なるべく自動化で簡単にしていきたい。

Task(go-task)を使い始めた

Goで書かれているTaskという名前のタスクランナーを使い始めた。仕事でMakeをタスクランナーとして使っていたところを、Taskに置き換えようという動きがあったので、仕事で使いつつプライベートでも使って慣れようとしている。

Taskでは Taskfile.yml というYAMLファイルにタスクを書いて、task コマンドで実行する。Makefileよりは読みやすいし書きやすそうでいい。

taskfile.dev

補完

taskコマンドの補完が効かなくて不便だと思っていたら、補完のセットアップをしたらできると同僚に教えてもらった。zsh用のセットアップをすると無事補完が効いて、効率的に使えるようになってよかった。

ホーム|タスク #補完のセットアップ

task -l と task -a

taskコマンドには -l または --list というオプションがあるので、これでタスクの一覧が確認できるのかと思ったら、一覧は表示されるのに含まれていないタスクがある。このオプションだとdescriptionが書かれたタスクしか一覧に表示されない

一方で -a または --list-all オプションだとdescriptionがないタスクも一覧表示される。

-a を使うのではなく、descriptionを書いて -l で使うべきなのだろう。タスクの数が増えると、使う頻度の低いタスクやややこしいタスクは何をするものなのか分からなくなる。Makeを使っているときはそうだった。調べたらわかるだろうが無駄な労力だ。わかりやすい description を書いて時間と判断の節約をしていきたい。

macのショートカット.appでやってること

macにはショートカット.appというアプリが入っている。「アクション」を組み合わせた一連の処理をショートカットとして登録しておくとワンクリックで実行できるという機能だ。複雑なロジックをショートカットで組み立てるのは大変そうだが、トリガーや入出力の取り回しが便利そうなので使ってみた。

support.apple.com

記事中で使っているmacOSはSonoma(macOS 14)、ショートカット.appのバージョンは7.0(2106.0.3)です。

時計.appでタイマーを開始する

「10分間だけ〜をやろう」というように、時間制限をつけて作業するときに使う。

時計.appでタイマーを開始する

変数を指定する方法が独特でわかりにくくて苦労した。右クリックすると選択メニューが表示されるというのは、一度見つけたらわかるが、初見ではわからなかった。なんとなくXcodeを初めて触ったときを思い出した。

右クリックで変数の選択メニューが表示される

「メニューバーにピン固定」のチェックを入れておくとメニューバーから実行できるので便利だ。

メニューバーに固定しておくと便利

Homebrewの更新をする

Homebrewでインストールしたパッケージを更新するのに使う。

シェルスクリプトを実行」というアクションでシェルスクリプトの実行ができるのでHomebrewでインストールしているパッケージの更新もできるようにした。

ショートカットは以下のようなコマンドで実行する事もできる。

$ shortcuts run "check brew"

これの何が嬉しいかというと、成功して標準出力があるときにダイアログを表示したり、失敗したときに通知が送られる。

ショートカット内の「シェルスクリプトを実行」失敗したときの通知

上記のコマンドをcronなどを使用して定期的に実行しておけば、更新がないときは静かに成功して、更新があったときや失敗したときだけ結果を表示するということもできる。

このようにターミナルから実行できるスクリプトも、ショートカットで実行するとmacOSGUIと統合された体験ができる。

まとめ

いくつかショートカットを作ったけど、たいていシンプルなものばかりだ。ショートカットには「if文」などのアクションもあるけど、辛そうなのでやってない。ロジックがあるときはスクリプトに書いて、トリガーや入出力のためにショートカットを使うのが楽そうだ。

『証明の読み方・考え方』が面白い

本屋にいくと『証明の読み方・考え方』という本が目に入った。数学の証明の本だ。手にとって眺めると面白そうなので買ってみた。中学や高校の数学でも証明問題は苦手だった。苦手というよりちゃんと証明の仕方を教わったり、勉強した覚えがない。『証明の読み方・考え方』で紹介されている前進後退法という考え方を知ることで証明の苦手意識が薄くなった。

後ろから前から

この本で紹介されている証明方法の基礎となるのが前進後退法だ。聞いたこともない方法だったが、難しい話ではない。

証明したい対象から考える後退過程と、仮定など既知の情報から結論に向かって考える前進過程という2つの過程を組み合わせて証明の道筋を探していく方法だ。

まず後退過程で、証明したい命題というゴールに到達するためはどういう命題が真であればいいのかを考える。さらにその命題が真であるには……と、証明したい命題から逆順に論理を遡っていく。

続いて前進過程だ。前進過程は仮定などの既知の情報からスタートして、別の命題を作っていく。このときに後進過程に接続できるように論理を進んでいく。

後退過程と前進過程が接続すると、仮定から証明したい命題への論理的な道筋が出来上がる。

最初の一歩が後進過程で、何が言えればいいのか?を考えることと、仮定から直接結論を目指すのではなく、後進過程に接続できるところを目指すというところが特に個人的に面白いと思った。

本の中では図形の簡単な証明の例でわかりやすく説明されているので、専門的な知識は不要だ。この章だけでも面白いのでおすすめだ。

迷路の探索

『証明の読み方・考え方』の表紙は迷路が描かれているが、証明の道筋を考えるのは迷路の入り口から出口を見つける探索のようだ。

迷路の探索といえば、グラフの探索アルゴリズム。証明もある種の探索問題なのか、という考えが頭に浮かぶ。

それにしても前進後退法で、スタートとゴールからそれぞれ探索を始めるというのは奇妙な方法だ。双方向探索アルゴリズムというものもあるらしいが、あまり聞かない。

証明問題が構成するグラフというのが、双方向から探索するのが効率的な特性を持っているのだろうか。

本の構成

前進後退法は全15章のうちの第2章で、全体は以下のような構成になっている。

  • 第1章 数学的に真理であるとはどういうことか
  • 第2章 前進後退法
  • 第3章 定義と数学用語について
  • 第4章 量化詞1:構成法
  • 第5章 量化詞2:抽出法
  • 第6章 量化詞3:特殊化
  • 第7章 量化詞4:入れ子の量化詞
  • 第8章 主張の否定をどう書くか
  • 第9章 背理法
  • 第10章 対偶法
  • 第11章 一意性の証明法
  • 第12章 帰納法
  • 第13章 二者択一法
  • 第14章 最大最小の証明法
  • 第15章 まとめ

証明の読み方・考え方〔原著第6版〕 - 共立出版

前進後退法が具体的な証明方法の最初の基礎で、その後に含まれるキーワードから各種の証明パターンを見極めていくという流れだ。量化詞というのは∀や∃などの記号のことだ。

数学の教科書で「数学的帰納法」という言葉は載っていたけど、この本のようにまず前進後退法の考え方を教えておいてくれよと思った。

感想

この本を手に取ったときの期待通り、数学の証明の考え方の基礎を知ることができてよかった。証明に対する苦手意識も薄くなったと思う。

大人になってから数学の証明を読んだり考えたりする必要に迫られることはないけど、何が正しくて何が正しくないのかを論理的に考える機会は少なくない。例えばソフトウェアのバグの原因を考えたり、障害の原因を考えるときにも論理的な思考が必要だ。前進後退法のように目的から後ろ向きに考えることと、既知の情報から前向きに考えることを組み合わせるという考え方は応用できそうだ。そういう意味でも読んでよかった。

Raycastから勤怠管理システムの打刻を行う

勤怠管理システムのWebページの反応が遅い。ボタンをクリックしたけど打刻できていませんでした、ということがよくある。そのため後で修正する作業が必要になっている。本来必要のない仕事が発生してるのでなんとか減らしたい。勤怠の修正には承認フローが走るので、自分だけではなく他の人の作業も発生してしまっているだろう。なので勤怠管理システムのAPIを叩いて打刻することにした。ランチャーアプリのRaycastにAPIを叩くスクリプトコマンドを登録して簡単に素早く打刻できるようにした。

勤怠システムのAPIを叩く

使っている勤怠システムだとAPIを使うのにはAPIトークンが必要なので勤怠システムのWebページから生成しておく。

API仕様ページを読んで、書かれているとおりに、以下のようなcurlAPIを叩くだけのシェルスクリプトを作る。

#!/bin/bash
set -euxo pipefail
token="xxxxxxxxxxxxxxxx"
# 123: 退勤
type=123
curl -X POST -H "Content-Type: application/json" \
-d "{\"token\": \"$token\", \"type\": $type }" \
"https://example.com/api"

Raycastから実行する

ターミナルから実行してもいいが、Raycastから叩くのが使いやすくてよさそうだ。Raycastはmac向けのランチャーアプリで、spotlightやAlfredのようなUIからアプリの起動や検索以外のコマンドも実行できる。Raycastで Create Script Command を実行すると簡単にシェルスクリプトが登録できる。上記のシェルスクリプトを登録する。

manual.raycast.com

退勤コマンド

これで勤怠システムのWebページの読み込みを待つ無駄な時間が削減できて、打刻漏れが減ることと嬉しい。1日使って便利に使えているが、トークンの有効期限が長くないといことに気がついたので、いい感じに更新できるようにしないと不便そうだ。

タスクの細かいスケジュール管理は避けたほうがいいかもしれない

最近仕事をしていて、日単位で細かくスケジュールを立てることでやりにくくなって、かえって進捗がでないと感じることがあった。

一般的に、大きなプロジェクトを小さなタスクに分解して、それぞれのタスクにスケジュールをつけることで、全体のスケジュールを管理するということはよくあることだと思う。

プロジェクトの管理は必要だが、ソフトウェア開発の現場ではタスクの細かすぎるスケジュール管理はかえって非効率になるときがある。

予定通りには進まないし、調整コストが大きい

数日単位でタスクが並んでいると、非の打ち所がない計画のように見える。しかし当然だが予定通りには進ない。障害対応などの差し込みで予定していた作業ができないことがある。自分や家族の体調が崩れて普段通り働けないこともある。そもそもいつも通りに働けていても、事前に決めた予定通りには終わるとは限らない。

一日単位の細かいスケジュール管理を行っていると、少し予定がずれただけで修正しなくてはいけない。このスケジュール管理自体が開発からリソースを奪うことになり非効率的だ。

例えば日礼のミーティングがあるとする。そこで「昨日は〜があって作業が少し遅れてます」などの情報を報告し合ったり、毎日タイムラインを確認して調整したり、細かくスケジュールを立ててしまうとそういう作業が発生する。

調整コスト以外の問題

細かいスケジュール管理は、個人のエンジニアにもパフォーマンスに悪い影響を与えるだろう。毎日スケジュールどおりに進行しているかということを考える負荷が常にかかっている。

締切がある方が集中できるという考えもあるだろうが、個人が自分の持っているスケジュールを守ることに気を取られていると、誰の責任でもないがチームにとって重要なタスクは見逃されたり先延ばしにされてしまう。

個人的にはタスクは週単位でざっくり持つぐらいがちょうどいいんじゃないかと思う。体調が悪い日もあればいい日もある。思ったより長くかかったタスクもあれば、一瞬で終わったタスクもある。平均したらだいたい予定通りならそれでいい。スケジュールを調整するのは毎日ではなく、1週間や2週間くらいサイクルで行う。それくらいのスパンでみるのが割に合うんじゃないかと思う。

同じ人でも、欠乏に気を取られているときのほうがそうでないときよりIQが低くなるのだ。これは私たちの主張の鍵である。 (センディル ムッライナタン; エルダー シャフィール. いつも「時間がない」あなたに 欠乏の行動経済学 (早川書房))

オブジェクト指向プログラミングでなくてもドメイン駆動設計できるらしい

ドメイン駆動設計(DDD)というと、オブジェクト指向プログラミング言語というイメージが強かった。 Javaのようなクラスベースのオブジェクト指向プログラミング言語で、業務をモデリングするときの設計手法という印象だった。

Scott Wlaschin は 『Domain Modeling Made Functional 』で、関数型プログラミング言語のF# で ドメイン駆動設計をする手法を提案している。

pragprog.com

『Domain Modeling Made Functional』は3つのパートから成り立っていて、Part I. Understanding the Domain でしっかりとDDDの基本について丁寧に説明している。

関数型プログラミング言語について関心があって読んだが、予想よりも DDD のアプローチを丁寧に取り入れていて、DDDについての理解が深まった。

実はこの書籍よりも先に、Scott Wlaschin の動画を見た。動画もオススメだ。

www.youtube.com

また、DDDが向いているソフトウェアとそうでないものがあるということも 『Domain Modeling Made Functional 』 の最初で言及されている。

“Domain-driven design is not appropriate for all software development, of course. There are many types of software (systems software, games, and so on) that can be built using other approaches. However, it is particularly useful for business and enterprise software, where developers have to collaborate with other nontechnical teams, and that kind of software will be the focus of this book.” - Chapter 1, Domain Modeling Made Functional

いま仕事で小説投稿サイト1の開発をしている。小説家や出版社の編集者のような、DDDの用語でいうドメインエキスパートにあたる専門家が登場する。

ドメインエキスパートと開発者と知識の差の存在する分野なのでDDDは効果を発揮するのだろう。『Domain Modeling Made Functional 』で学んだ関数型プログラミングとDDDの組み合わせの知見を活かせる機会があるかも知れない。