ramenjunitiメモ

自分なりに調べたものをまとめたり、文章を書く練習したり

JS修正してGoにコントリビュートした

Treasure Advent Calendar 2019 の22日目の記事です。

adventar.org

先日、Treasureでもお世話になったGoへコントリビュートしました!

この記事では、初のOSSへコントリビュート成功ということで、その経緯を書いていこうと思います

ある日

Go Conference 2019 Autumnに参加した影響か、Goへの思いが高まりGoへコントリビュートしたいなーと思いながらGithubでGoのコードを覗いてました

気になるものを見つける

どうやらGoにはgophertoolというChrome拡張機能があるらしい

粗探しをする

中身を覗いてみると5~9年前で更新が止まってるっぽい

f:id:ramenjuniti:20191219162621p:plain
コントリビュートする前

なんか怪しそう!

過去にChrome拡張を作ったことがあり雰囲気でコードは読むことができたので、何かミスってるとこないかなーと粗探しをしてみることに

お!?

Chrome拡張のAPIドキュメントを見ながら、gophertool/background.jsを粗探ししてると

chrome.omnibox.onInputEntered.addListener(function(t) {
  var url = urlForInput(t);
  if (url) {
    chrome.tabs.getSelected(null, function(tab) { // <-- お?
      if (!tab) return;
      chrome.tabs.update(tab.id, { "url": url, "selected": true });
    });
  }
});

chrome.tabs.getSelectedを使ってるんか、ドキュメント見てみるか」

f:id:ramenjuniti:20191219171948p:plain

「ん?」

f:id:ramenjuniti:20191219174346p:plain

「うおー!Deprecatedやんけー!」

興奮しました

「修正も難しくなさそうだし、プルリク作ったらマージしてもらえそう!」

興奮しました

プルリクを投げる

修正できそうなコードを見つけることができたので、実際にプルリクを投げてみることに

Goにはコントリビュートの手順に関するドキュメントが用意されています golang.org

ドキュメントに従い、issueを作り github.com

GoではレビューシステムにGerritというシステムを利用しているので、Gerrit上でコードを以下のように修正してプルリクを投げました

chrome.omnibox.onInputEntered.addListener(function(t) {
  var url = urlForInput(t);
  if (url) {
    chrome.tabs.query({ "active": true, "currentWindow": true }, function(tab) { // <- 修正箇所
      if (!tab) return;
      chrome.tabs.update(tab.id, { "url": url, "selected": true });
    });
  }
});

色々と面倒くさいのかなと思ってましたが、ドキュメントに書かれた手順に従っていくだけなので、プルリク自体はすぐ作ることができました

あとはレビューを待つだけ!

そしてマージへ

マージされた!

わーい!🎉 f:id:ramenjuniti:20191219185718p:plain

プルリクを作って約4時間後にレビューされ、特に問題がなかったようでそのままマージされました

このコードはGo1.13.5から反映されてるようです

おわりに

以上のような経緯でコントリビュートしました

正直今回修正した箇所は小さく(しかもJS)、ラッキーコントリビューションではあるんですが、普段お世話になっているGoへコントリビューションだったので、純粋に嬉しいです

今回が初のOSS貢献で、修正できそうなコードを見つけた時やプルリクがマージされた時、脳汁ドバドバサイコー!を体験して味を占めたので、これからも継続してやっていきたいです笑 OSS楽しい!

シェルをfishにしたらイイ感じだった

この記事は Sunrise Advent Calendar 2019 の8日目の記事です。 adventar.org

シェルをfishに変更したらイイ感じだったので、それについて書いていきます。(Sunriseとは全く関係ないですが...笑)

fishとは

github.com

fish is a smart and user-friendly command line shell for macOS, Linux, and the rest of the family. fish includes features like syntax highlighting, autosuggest-as-you-type, and fancy tab completions that just work, with no configuration required.

fish はスマートでユーザーフレンドリーなシェルで、シンタックスハイライト、サジェスト、補完などの機能をデフォルトで持っています。

また、fish は the friendly interactive shell という意味らしく、名前から人類に優しそうな雰囲気を感じます。

👇ここでfishを体験することができます rootnroll.com

なぜfish

  • 夏のインターンで会った人が何人か使っていて興味があった
  • ちょうどPCを買い換えて導入する良いタイミングだった

って感じで、どんなもんなんやろなーってインストールしました

fishを入れてみる

brewでインストール

brew install fish

/etc/shells/usr/local/bin/fishを追記

echo /usr/local/bin/fish | sudo tee -a /etc/shells

シェルをfishに切り替え

chsh -s /usr/local/bin/fish

これでオーケー。インストール方法はzshとだいたい一緒な気がする

fishを使ってみた感想

ん、なんか既にええ感じやん!

色で教えてくれてわかりやすい!

設定も楽やん!

テーマいっぱい!

プラグインいっぱい!

最高!

ってことで、下でよかったところを書いてきます

fishの良いと思ったところ

1. デフォルトですでにイイ感じ!

  • サジェストしてくれる

f:id:ramenjuniti:20191203210918g:plain

  • 色でそのコマンドがあるかどうか教えてくれる

f:id:ramenjuniti:20191203210829g:plain

  • タブで候補を表示

f:id:ramenjuniti:20191203210846g:plain

👇このコマンドで各アプリケーションのmanからサブコマンドやオプションの補完も生成してくれます。これを実行しとくとほとんどのアプリケーションで補完機能を発揮してくれます。

fish_update_completions

2. 設定が楽!

  • fish_configを実行するとブラウザでfishの設定を行うことできます。ポチポチでカスタマイズできる!

f:id:ramenjuniti:20191203203708p:plain

3. pluginの導入が楽!

fisher というfishのプラグインの管理ツールを用いて、プラグインを簡単にインストールすることができます。

github.com

fisher をインストール

curl https://git.io/fisher --create-dirs -sLo ~/.config/fish/functions/fisher.fish

fisherを用いたプラグインのインストールは以下のように行うことができます。

fisher add {プラグイン}

私は今のところ以下のプラグインを入れています。

pecoは標準入力されたものを検索して出力するコマンドで、このプラグインでは履歴の検索とプロセスキルを提供してくれています。

インストールは以下の通り

brew install peco
fisher add oh-my-fish/plugin-peco

私は.config/fish/config.fishに以下のコードを追加してCtrl + rで履歴の検索ができるようにしています。

function fish_user_key_bindings
  bind \cr 'peco_select_history (commandline -b)'
end

こんな感じ https://i.gyazo.com/dac498a2d47aca376b9c89edf2c508db.gif

z {ディレクトリ名}で直接そのディレクトリに移動できるプラグインです。zは訪れたディレクトリを追跡して頻度と最新性から飛ぶディレクトリを決めてるみたいです。

インストールは以下の通り

fisher add jethrokuan/z

こんな感じ https://i.gyazo.com/95879aece5b4dd4e9955727855cb3f5e.gif

他にも良さそうなプラグインたくさんありそう...

4. テーマが豊富!

ここにいっぱいテーマが載ってます。

github.com

Fisherで簡単にインストールできます。

fisher add {テーマ}

私はclearanceっていうテーマを使っていて、以下のようにインストールしました。

fisher add oh-my-fish/theme-clearance

終わりに

前まではzsh使ってて、イイ感じするために色々設定が大変(時間を溶かしてた)だったんですが、fishはそこらへんが楽でサイコーですね(イイ感じにするのすぐできた)

まだ使って間もなく無知な部分もあるので、他に良いプラグインなどを知っている方、是非教えて欲しいです!

GoLandのターミナルでfishを動かそうとするとエラー吐く

何が起きたか

普段シェルはfishを使っていて、Golandでもfishを起動するように設定していました。

設定はこんな感じ👇

f:id:ramenjuniti:20191206005320p:plain

だたGoland内のターミナルを起動すると

~/.config/fish/conf.d/z.fish (line 40): 
__z_complete
^
from sourcing file ~/.config/fish/conf.d/z.fish
        called on line 9 of file /Applications/GoLand.app/Contents/plugins/terminal/fish/config.fish

from sourcing file /Applications/GoLand.app/Contents/plugins/terminal/fish/config.fish
        called during startup

って言われる。

Golandのバージョンは2019.3

原因

Goland内にもfishがあって、読み込んで欲しい~/.config/fishを読んでくれないらしい

解決策

解決策はここに載ってます stackoverflow.com

いくつか方法があるようで、私は以下の方法で解決しました。

設定 > ツール > ターミナル > アプリケーション設定シェルの統合のチェックを外す

f:id:ramenjuniti:20191206005748p:plain

CA Tech Challenge 学生版ヒダッカソン -API編- に参加しました

サイバーエージェントインターン「CA Tech Challenge 学生版ヒダッカソン -API編-」に参加しました。

www.cyberagent.co.jp

用意された仕様を満たすAPIをいくつ実装できるのかを競うハッカソン形式のインターンです。

参加まで

私は普段のアルバイトではフロントをメインにやっているのですが、最近サーバーサイドにも興味があって、「このインターン面白そうだし、チャレンジしてみよう」ということで、エントリーしました。

ES通過後はそのまま面接でした。 面接はオンラインで行われ、一通り面接が終わった時に、その場で合格を告げられました(スピード感すごい)

1日目

午前に競技の説明があり、午後から開発という流れでした。

環境はある程度揃っていました。(ありがたい🙏)

判定には判定サーバーのようなものが用意されており、APIを実装したら判定リクエストを送って、APIがちゃんと実装できているかが判定され、良ければスコアが伸びるという流れです。

いざ開発

初っ端から環境周りに苦戦しました😅

環境がどうなっているのかの把握や、DB接続あたりに時間を使ってしまいました。

1日目はそれにほとんど時間を使い、スコアをあまり伸ばすことができず終了

インフラ周りの知識不足が身にしみました😢

2日目

社員さんのLT

2日目の午前は社員さんのLTがあり、CAのサーバーサイド周りのお話を聞くことができました。 CAは様々な事業を抱えており、サーバーサイドも事業ごとに使用する技術が違っていて、とても興味深かったです。

開発

1日目でわからないところに時間を使いすぎていたので、その反省から2日目は、自分ができそうなものから実装するという作戦で臨みました。 なので一旦仕様を全部見て、実装が軽そうなAPIから取り掛かりました。

この方法がうまくいき、スコアを伸ばすことができました。

しかし、ある程度点数が伸びてきたところで開発終了

結果発表

私は残念ながら賞をもらうことはできませんでした。全体の真ん中ぐらいのだった気がする。 上位の人は、全部のAPIを実装し終わって、チューニングとかやっててすごく強かったです。

感想

このインターンでは、限られた時間の中で自分ができることを模索し、実行するということを学びました。 (これが最初からできていればもうちょっとスコア伸びたかも?) また、自分に何が足りていないのか(Docker周り、SQL力など)明確化出来たので、今後はその部分をやっていきたいです。

初めてのハッカソンで色々戸惑いましたが、とても勉強になったし、なにより楽しかったです。実装するたびにスコアが伸びてくのが最高でした笑

サポートをして下さったメンターの方々、運営の方々、ありがとうございました!

f:id:ramenjuniti:20191001025640j:plain

VOYAGE GROUPのインターンシップ「Treasure」に参加しました

f:id:ramenjuniti:20190929171849j:plain
voyage_group

株式会社VOYAGE GROUPの「Treasure」に参加してきました。

voyagegroup.com

参加まで

エントリー

Treasureのテーマが「Go言語を使って学ぶ、価値のあるもの創りとチーム開発」とあって、Go好きだし、チーム開発もやってみたいからちょっと応募してみるかーと軽い感じで応募しました。

面接

選考には特に技術的な試験は無く、ES通過後はそのまま面接でした。

エンジニアの方2人、人事の方1人の3人(1人30分)と面接をしました。面接といっても、ガチガチな感じはなく、ほとんど雑談みたいな感じでした。

参加決定

私は知らない番号から電話がかかってくると出ないタイプの人間で、人事の方からの電話を数回無視してしまいました笑(すみません。。。)

複数回無視した後、いつ頃電話できるのか確認メールがきて、そこで初めて電話が繋がり、合格を告げられました。

インターン全体の流れ

前半

  • 講義
    • Go
    • フロント
    • データベース
  • 中間課題
  • 講義
    • セキュリティ
    • 認証
    • インフラ
    • アイディア

後半

  • チーム開発
  • 最終発表

こんな感じの流れでした。

前半

短い時間でたくさんインプットするので、スピード感がすごかったです。講義といってもただ話を聞くだけではなく、実際にコードを書いたり、ホワイトボードを使って議論したりなど、実際にやってみる形式が多く、とても理解しやすかったです。

私は普段フロントエンドをやっているので、サーバーサイドの話などの知らない領域の講義はとても勉強になりました。(API生やせるマンになった、嬉しい!)

中間課題

中間課題は「面白いものを作る」というものでした。

私はサーバーサイドの復習をやりたかったので、Goの講義でやったAPIを拡張してウェブアプリケーションを作りました。短い時間でしたが、最低限動くものは作れました。

週明けに作ったものを発表するのですが、みなさん色々なものを作っていて、面白かったです。(筋トレ系💪とか)

後日、社員さんに中間課題のコードレビューをして頂けるということで、実装の良かったところ、改善できるところを教えてもらいました。めっちゃ勉強になった!

後半

チーム分け

チームメンバーは5人で、そこにエンジニアの方2人と人事の方1人がサポーターとしてつきます。

我々のチーム名とソウル(迷った時に、チームとしてブレないための合言葉みたいなもの)は

  • チーム名:静かなる修造

  • ソウル:「心」燃えてる?

です。

チームメンバーの「静かなタイプだが、中に熱い想いを秘めている」部分を表現した結果、このチーム名とソウルになりました。

プロダクト案決め

決めるのに結構時間が掛かりました。 というのも、チームとしてここで妥協はしたくないという思いがあったため、全員が納得できるプロダクト案が決まるまで時間を掛けました。

ただ時間を掛けたと言っても、時間は限られているので「今は何をする時間で、いつまでに終わらせるか」は常に意識をして進めていました。

最終的に決まった案は、私がアイディアの講義の時に軽い気持ち(ほとんどネタのつもり)で出した案が元になっていたりしていて、アイディアって思わぬところから生まれてくるんだなーと感じました笑

開発 

開発はサーバーサイドエンド3人、クライアントサイド2人に分かれて進めました。私は、クライアントサイドを担当しました。 クライアントサイドは、プロダクトの機能的にネイティブとウェブどちらも実装することにしました。 ネイティブはReact Nativeで、ウェブはReactで開発しました。

ネイティブの方は、クライアントサイドを担当したもう一人のチームメンバーがネイティブアプリにめっちゃ強い人だったので、その人にネイティブアプリとしてのコア機能を任せて、私はそれ以外部分をやってました。 React Nativeでは、ある程度Reactっぽく書けるので「初心者な俺でもいけるやろ」とか思ってたのですが、

謎エラー大量発生して無事死にました笑(何度何も分からんマンになったことか。。。)

f:id:ramenjuniti:20191001001028j:plain
ビーチに打ち上げられた私

チームメンバーや、サポーターさんの助けを借りて何とか開発を進めました。(ありがとうございました🙇‍♂️)

ウェブの方は、クライアントサイドの二人で手分けして開発を進めました。何とか最低限の機能は実装できました。

発表

最終日にチーム開発の成果を社員さんやCTOの前で発表しました。

社員さんからガチのフィードバックをもらうことができて、とても勉強になりました。

結果発表

私たちのチームは残念ながら賞を取ることはできませんでした。とても悔しかったですが、どのチームもとてもクオリティが高く、実際に使ってみたいと思うようなサービスばかりだったので、そこは納得しました。

結果発表が終わった後に3週間の振り返りがあり、一人一人コメントしていくのですが、感極まって涙を流す人もいて、いざ自分の番になると3週間の記憶がよぎってちょっとだけ泣いちゃいました笑。私が思う以上に、私にとって熱中した期間だったのかもしれません。

その後の’打ち上げは、疲労と酒であまり覚えてないです。

フィードバック

Treasure自体は8/30で終わりですが、別の日にチームのサポーターの方々からチーム開発について直接フィードバックがあり、チーム開発での動き方の良かった点やこうした方か良かった点を教えてもらえます。私はチーム開発の経験があまりないので、このフィードバックはとてもありがたかったです。

感想

最初は軽い気持ちでエントリーをしましたが、今はTreasureに参加できて本当に良かったと思っています。とても充実した時間を過ごすことができました。

技術はもちろん、チーム開発でのコミュニケーション、エンジニアとしての必要なスキル、0からプロダクトを生み出す難しさや楽しさなどたくさんのことを学ぶことができました。

チームメンバーのみんな、サポーターの方々、講師の方々、TAの方々、運営の方々、Treasure生のみんな、3週間ありがとうございました!

f:id:ramenjuniti:20191001003340j:plain

その他

VOYAGEの人がよく行くお店「橙」のめっちゃ辛いやつ。

f:id:ramenjuniti:20191001003814j:plain
地獄谷
中間課題発表が終わった日に連れてってもらいました。めちゃ辛かった

お菓子

Treasureでは15:00にお菓子がデプロイされます。

自作キーボード

Treasure生で自作キーボードを持っている人がいて、それをみて自作キーボード沼に落ちるTreasure生が続出しました笑

私も後日ちゃんと落ちました笑

他のTreasure生の記事

tomu28.hatenablog.com

tako8ki.hatenablog.com

kotaro7750.hatenablog.com

tjmschk.hatenablog.com

note.mu

kirohi.com

nasaemon.hateblo.jp

kitchen-py.hatenablog.com

denden-seven.hatenablog.com

shinya-ml.hatenablog.com

日本語文書のTFIDF値を計算するGoのパッケージを作った

先日、メルペイさんのGopher道場に参加させてもらってGoの知識が増えたので、何かアウトプットしてみよう!ということでGoのパッケージを作ってみました😁

Gopher道場に関する記事はこちら ramenjuniti.hatenablog.com

作ったもの

日本語文書のTF値, IDF値, TFIDF値を計算するパッケージです。

github.com

このパッケージでは、形態素解析器としてikawahaさんのkagomeを利用しています。

github.com

テストやGoDocも書いてみました!

以下のコマンドでインストールできます!

go get -u github.com/ramenjuniti/jtfidf

TFIDFとは

そもそもこのパッケージが提供しているTF、IDF、TFIDFが何かと言うと、自然言語処理などで、文書中に含まれる単語の重要度を評価する手法の一つとして使用されているものです。

TFIDFは、TF(Term Frequency、単語の出現頻度)とIDF(Inverse Document Frequency、逆文書頻度)の二つの指標から計算されます。

TF

TFは、文書内の単語の出現頻度です。


{{\mathrm{TF}_{i,j}} ={\frac {n_{i,j}}{\sum _{k}n_{k,j}}}}

{\displaystyle n_{i,j}}は文書{\displaystyle d_{j}}における単語t_{i}の出現回数

{\displaystyle {\sum _{k}n_{k,j}}}は文書{\displaystyle d_{j}}におけるすべての単語の出現回数の和

実装

func Tf(t, d string) float64 {
    terms := splitTerm(d)
    n := len(terms)
    var count int

    for _, term := range terms {
        if t == term {
            count++
        }
    }

    return float64(count) / float64(n)
}

IDF

IDFは、単語の文書頻度の逆数です。


{{\mathrm{IDF}_{i}} =\log {\frac {|D|}{|\{d:d\ni t_{i}\}|}}}

{\displaystyle |D|}は総文書数

{|\{d:d\ni t_{i}\}|}は単語t_{i}を含む文書数

実装

func Idf(t string, ds []string) float64 {
    n := len(ds)
    termsList := make([][]string, n)
    var df int

    for i, d := range ds {
        termsList[i] = splitTerm(d)
    }

    for i := 0; i < len(termsList); i++ {
        for j := 0; j < len(termsList[i]); j++ {
            if t == termsList[i][j] {
                df++
                break
            }
        }
    }

    if df == 0 {
        return 0
    }

    return math.Log(float64(n) / float64(df))
}

TFIDF

TFIDFは、TFとIDFの積です。 しかし、IDFが0である場合、TFに関係なくTFIDFが0になってしまいます。 そのため、このパッケージではIDFに1を足して、それを防ぎます。


{{\mathrm{TFIDF}_{i,j}} = {\mathrm{TF}_{i,j}} \cdot ({\mathrm{IDF}_{i}} + 1) }

実装

func Tfidf(t, d string, ds []string) float64 {
    return Tf(t, d) * (Idf(t, ds) + 1)
}

使用方法

GoDocに書きました!

godoc.org

まとめ

TFIDF自体はシンプルなもので実装自体にはそこまで時間は掛かりませんでしたが、「使いやすさ」を大事にしたかったので、「どのように実装したら使いやすいのか」を考えるのに時間を掛けました。

また、テストやGoDocなどにも力を入れました。Gopher道場で学んだテーブル駆動テストをバリバリ使っています笑f

GoDocの書き方はこちらの記事を読んで勉強しました。

qiita.com

シンプルなパッケージの実装でしたが、色々学ぶことができました!

GoでTFIDFを求めたい人がいましたら、ぜひ使ってみてくださいー

参考文献

tf-idf - Wikipedia

TF-IDF - Qiita

Gopher道場#5卒業&人生初LTをしました!!

この度Gopher道場を卒業しましたので、記事に残します。

Gopher道場とは

mercari.connpass.com

こちらに書いてある通り、メルペイさんが提供する実践的なGoを体系的に学べる場です。

私は今回の5期生として入門しました!

参加した動機

私は普段、アルバイトなどではフロントエンドの開発をしてます(TypeScriptでReactとか書いている)。

最近はサーバーサイドもやってみたいなと思うようになり、Goを独学で勉強していました。

しかし、独学では理解があやふやになる部分やよくわからないところが出てきたりして、限界を感じていました。

そこに、丁度Gopher道場が開催されるということで、ちゃんと理解を深めるために参加してみようと思ったのが動機です。

事前課題

Gopher道場には事前課題があり、これをクリアしないと入門できません。

課題はあまり出来た自信は無かったのですが、無事に通って参加することができました。

講義

Gopher道場の講義は全部で4回あり、最後の1回が卒業式&LT大会となっています。

講義では、Goの基礎的な内容から実践的な内容まで、幅広く教えていただきました。

こういう場合は、どのように実装すればいいのかや、どういう風な考えて実装していけばいいのかなどのあまり本や記事には書いてないようなことを学ぶことも出来ました。

特に、私はinterfaceあたりの理解があやふやだったので、しっかり理解できるようになってよかったです。

宿題

毎回宿題が出題されます。

その宿題を実装してGithubにPRを投げるとtenntennさんからレビューを受けることができます。

そのレビューも非常に勉強になりました。

また、他の道場生がどのように実装しているのかを見ることもできたので、そこから学ぶことも多かったです。

まだ終わってない宿題があるのでやらないと😅笑

卒業式&LT大会

私は「GoでChrome拡張機能を作ってみた」というテーマでLTしました。

これの内容を発表しました ramenjuniti.hatenablog.com

発表資料はこちらです

人生初のLTだったのでめっちゃ緊張しましたが、結構練習したので、あまり詰まらずに言えた気がします笑

練習って大事だなーって改めて思いました笑

卒業生だけがもらえるTシャツとシール

f:id:ramenjuniti:20190625020358p:plain
卒業記念品

やったー

まとめ

Gopher道場最高だった。これで無料ってどういうことやねんってぐらい笑

これからもGoをもっと勉強していこうと思いました。

せっかくなので、研究室でGoの勉強会とかしようかなとか思っています。

謝辞

最後になりますが、Gopher道場を開催してくださったtenntennさん、会場を提供してくださったメルペイさん、第5期生のみなさま、本当にありがとうございました!