DDG - Develop a Digital Garden

develop a digital garden

Commitizenの導入手順

Commitizenとは

Commitizen commitizen/cz-cli: The commitizen command line utility. #BlackLivesMatter

gitコメントのテンプレを提供してくれるCLIツールです。 導入することでコミットメッセージに盛り込む内容に悩む必要がなくなります。

インストール

Homebrewでインストールすると日本語化プラグインが認識されないので、npmでグローバルインストールする。

$ npm i -g commitizen

日本語化設定

日本語化モジュールをインストールする

$ npm install -g cz-conventional-changelog-ja

設定を追加する

# dotfiles管理下に設定ファイルをつくる
touch ~/dotfiles/.czrc
{
  "path": "cz-conventional-changelog-ja"
}
# dotfiles管理下の設定ファイルを参照させる
ln -snfv /Users/HOGE/Documents/github.com/shootacean/dotfiles/.czrc ~/.czrc

日本語化完了

$ git cz
cz-cli@4.2.4, cz-conventional-changelog-ja@0.0.2

1行目は100文字で切り取られ、超過分は次行以降に記載されます。

? コミットする変更タイプを選択: (Use arrow keys)
❯ feat:     新機能 
  fix:      バグ修正 
  docs:     ドキュメントのみの変更 
  style:    フォーマットの変更(コードの動作に影響しないスペース、フォーマット、セミコロンなど) 
  refactor: リファクタリングのための変更(機能追加やバグ修正を含まない) 
  perf:     パフォーマンスの改善のための変更 
  test:     不足テストの追加や既存テストの修正

参考

Google検索を効率化するテクニック

こんにちは、shootaceanです。

プライベートでのちょっとした調べ物や仕事での調査など、Google検索を使う機会はかなり多いと思います。

今回紹介するちょっとしたテクニックを活用することで、調べ物における作業を効率化できます!

さっそく紹介していきます。

Google検索の設定を変更する方法

まず、Google検索の設定を変更する方法についてですが、検索結果ページ右上の歯車アイコンから変更できます。

Google検索設定メニューの場所

Google検索設定ページ

検索結果1ページ内に表示される件数を増やす

ページあたりの表示件数

ブログやアフィリエイトサイトが増えてきた影響か、内容の薄い記事や海外サイトを日本語に自動翻訳しただけの記事などが増えているので、1ページ目だけでは欲しい情報が見つからないことも多いです。 その際にいちいち2ページ目に移動するのは面倒なので、デフォルトのページ件数の10件から30件に変更します。

検索結果のリンクを別タブで開くようにする

結果ウィンドウ

デフォルトの挙動だと、検索結果のリンクをクリックするとページ遷移してしまい、検索結果ページに戻るにはブラウザバックをしないといけないです。 それだと、複数の結果ページを行き来しづらいので、常に別タブでリンクを開くように設定します。 PCだとctrl/command + 左クリックで別タブで開くことができますが操作が手間なので、この設定を行います。

デフォルトで英語検索にする

検索の設定

私の場合だとソフトウェアエンジニアなので、日本語のサイトよりも海外のサイトで調べ物をすることが多いです。 まずは英語圏の情報で収集し、必要に応じて日本語の情報で検索します。

英語圏の情報にアクセスする頻度が高い場合は、この設定をしておくことをおすすめします。

ブックマークレットで英語検索から日本語検索に簡単に変更できるようにする

上記の「デフォルト英語検索」とセットで使えるテクニックです。

英語検索で欲しい情報が見つからなかった場合は、日本語検索に切替えるのですが、普通に切り替えようとすると、再度Google検索の設定を変更する必要があり、かなり面倒くさいです。

そこで、こちらのブックマークレットを使います。
Googleの検索言語をサクッと切り替えるためのブックマークレット - かみのメモ

以下のJavaScriptをブックマークのURL部分に貼り付けて、ブックマークバーに置きます。

javascript:(()=>{if(location.host=='www.google.com'&&location.pathname=='/search'){var params=new URLSearchParams(location.search);params.set('hl', params.get('hl')=='ja'?%27en%27:%27ja%27);location.search=params.toString();}})()

ブックマークレット

こうすることで、ブラウザのアドレスバーから検索したときは英語検索、英語検索で欲しい情報が見つからなかった場合はブックマークレットを実行して、日本語検索に切り替える、ということが実現できます。

まとめ

かなり小技的なTipsですが、毎日使うものなので、かなりの時間の節約になるのではないかと思います。 Google検索での調べ方にストレスを感じている方は、ぜひ試していただければと思います!

個人利用に最適な翻訳APIを探してみた

500,000 character limit / month

https://shootacean.com/entry/2021/10/10/i-tried-to-find-the-best-translation-api-for-personal-use

こんにちは、shootaceanです。

こちらの記事で紹介したプログラムを書く上で調べた、個人利用で使いやすい無料で利用できる翻訳APIをご紹介します。

DeepL API Freeを使った日本語ブログ記事タイトルをブログURLに変換するPythonスクリプト

用途の前提

  • 個人利用
  • 月間の翻訳文字数は500,000文字に満たない
  • 公開してはいけない文字列を翻訳しない
  • APIを利用して自動化などを行う

結論

いきなり結論ですが、 個人利用で無料で済ませたいのであれば、クレジットカードの登録なしで利用できる「DeepL API Free」 一択です。
その他のサービスは無料枠は存在するものの、無料枠に収まらない場合は費用が発生してしまいます。
DeepL API Freeの場合は、無料枠の月間上限に達するとAPI自体が利用できなくなるため、費用の心配をする必要がありません。

ただ、

500,000 character limit / month

の制限があるので、翻訳頻度が高く翻訳文字数も多ければ、すぐに月間の制限に達してしまうのでガッツリ使う場合は、有料プラン前提で他サービスと比較しましょう。

DeepL API

DeepL Translate API | Machine Translation Technology

DeepL Pro | Translate Text, Word Docs & Other Docs Securely

Google Cloud Translation

Cloud Translation  |  Google Cloud

料金  |  Cloud Translation  |  Google Cloud

Amazon Translate

Amazon Translate(高速で高品質なニューラル機械翻訳サービス)| AWS

料金 - Amazon Translate | AWS

Microsoft Azure Translator

Translator - サービスとしてのソフトウェア | Microsoft Azure

価格 - Translator | Microsoft Azure

参考

gRPC + Goのhelloworldを試してみる

Image from Gyazo

こんにちは、shootaceanです。

実務でWEBサービスのリアーキテクチャが進もうとしているので、気になっていたgRPCを学習してみます。

基本的にgrpc.ioのクイックスタートの手順で進めたのですが、エラーなどで手順どおりにならない部分もあったので、その点も含めて書いていきます。

https://grpc.io/docs/languages/go/quickstart/

前提

  • macOS Catalina 10.15.7
  • zsh
  • go: 1.16.6
    • 1.15.5
  • protoc: 3.17.3
$ echo $SHELL
/bin/zsh

$ go version 
go version go1.16.6 darwin/amd64

$ protoc --version
libprotoc 3.17.3

Procol Bufferのコンパイラをインストールする

Protocol Buffersのコンパイラ protoc をインストールします。

$ brew install protoc

gRPCのGoプラグインをインストールする

$ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1

上記のコマンドで以下のエラーが発生する場合があります。

cannot use path@version syntax in gopath mode

私の場合は、go getでインストールすることで、解決できました。1

$ go get -u google.golang.org/protobuf/cmd/protoc-gen-go
$ go get -u google.golang.org/grpc/cmd/protoc-gen-go-grpc

サンプルコードを実行してみる

サンプルコードが公開されているので git clone します

$ git clone -b v1.35.0 https://github.com/grpc/grpc-go
$ cd grpc-go/examples/helloworld

gRPCサーバープログラムを実行します。

$ go run greeter_server/main.go

別のターミナルでgRPCクライアントプログラムを実行します。

$ go run greeter_client/main.go
2021/08/19 20:30:00 Greeting: Hello world

gRPCクライアントプログラムを実行して上記のような出力が得られれば成功です。

サンプルコードに変更を加えてみる

サンプルコードそのままは動かせたので、新しいエンドポイントを作ってみます。

  1. 定義ファイルを更新
  2. 定義ファイルから再生成
  3. サーバ側プログラムを修正
  4. クライアント側プログラムを修正
  5. 実行

という流れです。

Protocol Buffersファイルを修正する

gRPCプログラムを変更する場合は、まず IDLであるProtocol Buffersの .protoファイルを修正します。
今回のサンプルコードであれば、helloworld/helloworld.protoファイルを修正します。

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}

  // 以下2行を追加する
  // Sends another greeting
  rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}

修正できたらProtocol Buffersからgoプログラムを再生成します。 helloworld/helloworld.pb.gohelloworld/helloworld_grpc.pb.go の2ファイルが再生成されます。

$ protoc --go_out=. --go_opt=paths=source_relative \
        --go-grpc_out=. --go-grpc_opt=paths=source_relative \
        helloworld/helloworld.proto

上記のコマンド実行時に以下のエラーが発生した場合は、
前手順の protoc-gen-go-grpc のインストールが漏れているので、インストールしてください。

protoc-gen-go-grpc: program not found or is not executable
Please specify a program using absolute path or make sure the program is available in your PATH system variable
--go-grpc_out: protoc-gen-go-grpc: Plugin failed with status code 1.
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
または
$ go get -u google.golang.org/grpc/cmd/protoc-gen-go-grpc

gRPCサーバープログラムを修正する

helloworld/greeter_server.goを修正します。

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    log.Printf("Received: %v", in.GetName())
    return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

// ここを追加する
func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    return &pb.HelloReply{Message: "Hello again " + in.GetName()}, nil
}

gRPCクライアントプログラムを修正する

helloworld/greeter_client.goを修正します。 main関数の最後に追記します。

func main() {
 
    // 省略
 
    r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }
    log.Printf("Greeting: %s", r.GetMessage())

    // ここを追加する
    r, err = c.SayHelloAgain(ctx, &pb.HelloRequest{Name: name})
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }
    log.Printf("Greeting: %s", r.GetMessage())
}

実行する

$ go run greeter_client/main.go Alice
2021/08/19 21:17:00 Greeting: Hello Alice
2021/08/19 21:17:00 Greeting: Hello again Alice

無事に変更点が反映されて、問題なくクライアントからサーバー関数を呼び出せています!

まとめ

gRPCはもっととっつきにくい技術かと思っていたのですが、実際に手を動かしてみると思っていたよりも簡単に試すことができました。

マイクロサービスでのサービス間通信で使われていることが多いようですが、gRPC-webでブラウザとサーバー間の通信にも利用できるようになりつつあるので、大部分の通信をgRPCで完結することもできそうです。

何よりもProcol BufferというIDLによるスキーマ駆動開発の恩恵が大きいと感じました。 REST APIでもSwaggerなどでOpen APIに沿ってのコード自動生成は可能ですが、通信方法であるgRPCとIDLであるProtocol Buffersの密接な関係により、開発時のモック用意など、よりスキーマ駆動開発がやりやすい印象です。

Goのシンプルな構文とProtocol BuffersのIDLによって、チームでの開発もやりやすそうですね。 個人的にもかなり興味がある分野なので、gRPC-webも含めて何か個人開発してみようと思います。

参考


  1. この記事を書いている際に Go 1.16.6 にバージョンアップしたのですが、手順通り go install でインストールできました。

CloudFormationやCDKからLightsailは操作できない

こんにちは、shootaceanです。

https://web-labs.shootacean.com でバックエンド側の検証環境も用意したく、ホスティングできる環境としてLightsailを検討していました。

現状web-labsは静的ページしか無いので CloudFront + S3 でホスティングしています。 CDKでリソースを管理しているので、同じようにLightsailも管理できればいいなと思い、調べていました。

結論

できません。
CloudFormationがLightsailをサポートしていないので、当然CDKもサポートしていません。

調べた内容

「cdk lightsail」などでGoogle検索すると、すぐに該当するGitHub Issueが出てきました。

Add Lightsail support · Issue #10471 · aws/aws-cdk

Issueの内容の通り、
CloudFormationがサポートしていないので、CDKもサポートしていないです。
まず、CloudFormationでサポートする必要があるので、そっちにIssue作ったよ。
というやり取りがされていました。

AWS::Lightsail::* · Issue #640 · aws-cloudformation/cloudformation-coverage-roadmap

CloudFormationのIssueでも議論が進んでいないので、残念ながらサポートは期待できなさそうです。

まとめ

そもそものLightsailの立ち位置がAWSの主要サービスを少し隠蔽して簡単に使いやすくしたものなので、IaCまで考えるなら通常のEC2を使えばいい、ということで議論が進んでいない・サポートされていないのかもしれないですね。

今回のweb-labsではCDKを学習する面もあるので、Lightsailではなく通常のEC2を利用しようと思います。

Elmでフィボナッチ数列を計算してみた

Image from Gyazo

こんにちは、shootaceanです。

Elmで何かをつくりたくなったので フィボナッチ数列を生成するWEBアプリ をつくってみました。

こちらのサイトにホスティングしているので、ぜひ試してください! https://web-labs.shootacean.com/elm/fibonacci/index.html

ソースコードGitHubで確認できます! https://github.com/shootacean/shootacean.com/blob/main/web-labs.shootacean.com/src/elm/fibonacci/src/Main.elm

バグってるよ、もっと簡単に書けるよ、などの指摘や意見があればTwitterのDMやメンションなどでお願いします!

フィボナッチ数列を計算する関数

他のプログラミング言語でもよくあるメモ化している実装です。

fibonacci : Int -> List Int -> Int
fibonacci n memo =
    let
        m = List.getAt n memo
    in
        case m of
            Just memoNum -> memoNum
            Nothing ->
                case n of
                    0 -> 0
                    1 -> 1
                    _ -> ( fibonacci (n - 2) memo ) + ( fibonacci (n - 1) memo )

update処理

メモ化とViewに表示するためのリストを更新しています。

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
    case msg of
        Increment ->
            let
                n = model.num + 1
                fib = fibonacci n model.sequences
            in
                ( { model | num = n, sequences = List.append model.sequences [fib] }
                , Cmd.none
                )

メモ化なので永続的な状態を保つ必要があるのですが、他のプログラミング言語と違ってElmはTEAに縛られています。

まだElmとTEAの理解ができていなかったので、メモ部分をどうやって持つかで1時間くらい悩んでしまいました…

TEAに従って updateで計算して model を更新する ことしかできないので、 ただいつもどおりTEA様に従うだけでよかったです。

おわりに

個人的にElmを書いていて一番嬉しいのは、HTMLとJavaScriptを行き来しないでよくなることですね。 本当にのんびりとElmを学習しているのでまだまだわからないことばかりですが、ゆったりとElm書いていこうと思います!

aws cliのs3 syncで特定の拡張子ファイルだけをアップロードする方法

Image from Gyazo

こんにちは、shootaceanです。

aws s3 sync というコマンドで特定の拡張子のファイルだけをアップロードする方法をご紹介します。

Web技術を試す場として、
https://web-labs.shootacean.com
というサイトをつくっていて、そのサイトにデプロイする際に利用しているコマンドです。

HTML、CSSJavaScriptファイルだけをアップロードしたい場合は、以下のコマンドになります。

$ aws s3 sync src/ s3://bucket-name/ \
     --exclude "*" \
     --include "*.html" --include "*.css" --include "*.js"

注意点

s3 — AWS CLI 1.20.10 Command Reference
When there are multiple filters, the rule is the filters that appear later in the command take precedence over filters that appear earlier in the command.
複数のフィルターがある場合、コマンドの後半に表示されるフィルターが、コマンドの前半に表示されるフィルターよりも優先されるという規則があります。

とドキュメントに記載されているとおり、
上記コマンドの --exclude--include の指定順序を変えると 全てが exclude されてしまいます。

Reference

ユーザー入力のユーザビリティを高めるためのautocomplete属性

こんにちは、shootaceanです。

HTMLのautocomplete属性使ってますか?僕は全然意識していませんでした…

入力フォームのHTMLを書いていると、Chrome Dev Toolsのコンソールに以下のメッセージが表示されているに気づきました。
そのメッセージ内にあったリンク先1に「autocomplete属性使うといいよ〜」ということが書かれていました。

[DOM] Input elements should have autocomplete attributes (suggested: "username"): (More info: https://goo.gl/9p2vKq)

Image from Gyazo

よく利用しているサービスとかにあったオートフィルはこの属性を使ってやっていたのかと、恥ずかしながら初めて意識しました。

この記事は実際に試してみた感想と気づきをご紹介します。

実際にコードを書く

ひとまず、自分の手元でコードを書いて試してみました。

ログイン情報にあたるユーザー名にしっかりとオートコンプリート候補が出てきました。

Image from Gyazo

パスワード項目に関しては、Dropbox PasswordsのChrome Extentionsもautocomplete属性で制御しているようで、current-passwordnew-passwordをつけた項目には、アイコンが適用されました。

Image from Gyazo

特に意識した方がいいのはユーザーの氏名や住所などの部分ですね。 配送先などの入力は面倒ですし、サービス毎に入力する内容が変わることもそんなにありません。

一度入力した内容をそのまま1アクションで埋めて、そのまま登録できる、というのはかなり手間が省けるので、積極的にautocomplete属性を設定したいですね。

Image from Gyazo

オートコンプリートしたくない場合

銀行系などの機密性の高いサイトの場合は、オートコンプリートしないようにすることがあります。 その際は autocomplete=off と明示的に指定することでオートコンプリートのデータとしてブラウザに保存されなくなります。

HTMLの仕様としては、以下のように記載されているので autocomplete属性が未指定の場合は、ブラウザに保存される可能性があるのかもしれません。2

HTML Standard #autofill When an element's autofill field name is not "off", the user agent may store the control's data, and may offer previously stored values to the user. 要素の自動入力フィールド名が「off」でない場合、ユーザーエージェントはコントロールのデータを保存し、以前に保存された値をユーザーに提供することができます。

MDNの方にはもっと具体的な説明がありました。

フォームのオートコンプリートをオフにする方法-Webセキュリティ| MDN autocomplete="off"フィールドに設定すると、次の2つの効果があります。 ・準拠するためのヒューリスティックはブラウザによって異なりますが、ユーザーが入力したデータを後で同様のフォームでオートコンプリートするために保存しないようにブラウザに指示します。 ・ブラウザがセッション履歴にフォームデータをキャッシュするのを停止します。フォームデータがセッション履歴にキャッシュされている場合、ユーザーがフォームを送信し、[戻る]ボタンをクリックして元のフォームページに戻った場合に、ユーザーが入力した情報が表示されます。 オートコンプリートをオフに設定した後もブラウザが提案を続けている場合は、入力要素の名前属性を変更する必要があります。

ただし、ログインフィールドに関しては、autocomplete=off を無視してブラウザのパスワード管理機能をサジェストされることがあるみたいです。

フォームのオートコンプリートをオフにする方法-Webセキュリティ| MDN ユーザーはブラウザに保存されているパスワードを覚えておく必要がないため、他の方法よりも強力なパスワードを選択できます。

ユーザーが記憶できるレベルのパスワードよりも、難易度の高いパスワードをブラウザのパスワード管理機能で管理したほうが強力なので納得できますね。

まとめ

オートコンプリートの独自実装や機密性の高い入力項目が無い限りは、必須で設定したほうがユーザビリティが上がるのではないかと思います。

氏名や住所が変わる頻度はそう高くないですし、ブラウザ側に保持してオートコンプリートする方が、初期訪問時のユーザーにも恩恵があります。

ブラウザ側の仕様や機能を理解しておくことで、ユーザビリティを上げることもできるので、しっかり情報は追っていかないといけないですねー。

補足

自動入力でユーザーがより速くチェックアウトできるようにする| Web | Google Developers

このサイトに記載されていた「autocomplete=region」「autocomplete=locality」は非推奨になっているおり、情報が古いので注意です。

ちなみに使ってみると、DevToolsのコンソールにワーニングが表示されます。3

autocomplete='region' is deprecated and will soon be ignored. See http://goo.gl/YjeSsW

autocomplete='locality' is deprecated and will soon be ignored. See http://goo.gl/YjeSsW

Referrence


  1. Create Amazing Password Forms - The Chromium Projects

  2. まだ検証できておらず、可能性がありそうだというとこにとどまっています…

  3. 本当に親切で素晴らしい…

【Todoist】タスクの説明を入力できるようになりました!

Image from Gyazo

こんにちは、shootaceanです。

Todoistの7月22日のアップデートで、タスクの説明が入力できるようになりました!
新機能のお知らせ

今まで、タスクの補足やちょっとしたメモはコメントに残すしかなく、 コメントはファーストビューに表示されないので、確認するときには能動的にコメントを見に行く必要がありました。

それだと「このタスクにはコメントに何か補足やメモを残していたはず」というように少し記憶しておかなければならず、完全に忘れ去ることができません。

今回のアップデートで追加された「タスクの説明」項目はファーストビューに表示されるので、上記のようなことを全く気にする必要がなくなりました!

モバイルアプリではこのように表示されます。
複数行の場合は1行目しか表示されません。

Image from Gyazo

地味ですが素晴らしいアップデートですね!

Amazon RDSのバックアップ設定を一覧で取得するPythonスクリプト

Image from Gyazo

こんにちは、shootaceanです。

AWS環境の現状把握作業の一環で、RDSのバックアップ設定を一覧出力するPythonスクリプトを書きました。

同じことはaws cliだけでも実現できるので、そのコマンド例も載せています。 取得した結果を元にさらに処理を行いたい場合は、Pythonスクリプトの方を参考にできると思います。

実行例

$ python3 describe_rds_cluster_backup_window.py
rds-cluster-identifier-123456789 7 20:00-20:30 tue:21:00-tue:21:30

Pythonコード

Amazon RDSのバックアップ設定を一覧で取得するPythonスクリプト

AWS CLIコマンド

% aws rds describe-db-clusters \
    --query="DBClusters[*].[DBClusterIdentifier,BackupRetentionPeriod,PreferredBackupWindow,PreferredMaintenanceWindow]" \
    --output text \
    --region ap-northeast-1 \
    --profile your-profile
rds-cluster-idnetifier-123456789      7       20:00-20:30     tue:21:00-tue:21:30