tofucodes diary

にほんごのほう

2016年、振り返り

2016年の目標振り返り

1つのサービスを上から下まで1人でつくる

未達成。作りたいサービスを思いついたので必要な機能を洗い出した後、MySQL workbenchでデータベース設計してる途中で終わってしまった。ぱっと思いついたアイデアEvernoteにメモしてあれやこれやと考える流れ(習慣)はできたが、実際に形にする段階でモチベーションが維持できてなかったのが問題かなと反省してる。1人でモノをつくる上で難しいところはやっぱりモチベーションなのかなと思った。。。

フィリピン留学する

達成。6月から7週間フィリピンに留学することができた。今回この目標が達成できたのは、「周りに宣言して逃げられない状況に自分を追い込む」ことが大きな要因だったと思う。

プライベートはイエスマンになる

未達成。やっぱりモチベーションが上がらない飲み会はある。

体脂肪率9.9%

未達成。2月からジムを契約して週2〜3回のペースで通ったが思ったように体型の変化は得られなかった。フィリピンから帰国時に10.8%くらいだった記憶だけどおそらくこの時がベスト。フィリピンで友達になった香港人から教えてもらったプランクが効果が高かったので、日本に帰国してからも続けたが腹筋が割れるまでには至らなかった。腹筋を割るにはまだ贅肉が多いのではと判断し、プランクを一旦辞め代謝を上げるために大きな筋肉から鍛えようと大胸筋、大腿四頭筋、広背筋を鍛えるメニューに変更した。2017年は今の筋トレを継続することに加え食事メニューも考えるようにしたい。

2017年の目標

お金の勉強をする

お金は将来エンジニアとしてでっかい金稼いでやるぜー、とか思って何にも考えずに生きてきたけど、会社で周りの人が株や不動産で資産運用をする人がけっこう多く、その人たちの話を聞いてると、お金の勉強をすることはお金自体を得ること以外にもプラスになることが多いのではないかなと思ったりするので、今年はお金の勉強を始める年にする。まずは積読してるこの本読む。

d.hatena.ne.jp

海外の企業に応募してみる

1月〜3月の間にできるだけたくさんの海外のスタートアップにエンジニアとしてアプライしてみる。アメリカ・ドイツのどちらかで働いてみたい。Facebookのエンジニアの求人も出るくらいだからstackoverflowの求人から応募してみようかなと。

stackoverflow.com

体脂肪率9.9%

朝ごはんはしっかり摂り、お昼ご飯は六本木の美味しいご飯を我慢できないので、夜ご飯を節制しながら週2~3回ジムでトレーニングをする。

2015年、振り返り

あと6時間ほどで2015年が終わろうとしている。

ガキ使の笑ってはいけない名探偵が始まるまでの30分で2015年を振り返ってみる。(30分じゃ無理だった)

振り返り

  • 2015/01
  • 2015/03
    • 納期に間に合わせるため死ぬ思いでiOSアプリをリリースする(それでも1週間遅れた)
    • リリース翌日東京から逃れるように九州へいく
  • 2015/07
    • iOSアプリの主要機能だったEC機能がクローズになる
    • 広告の部署に異動になる
    • いろいろ鬱なことが重なり逃れるように沖縄へいく
    • 沖縄でダイビングのライセンスを取る
  • 2015/08
    • 26歳になる
  • 2015/09
    • 人生初のアメリカ上陸を果たす
    • サンフランシスコのFacebook本社のいいね!マークの前でいいねする
    • 英語を話せるようになりたいと本気で思い始める
  • 2015/10
    • 人生初のサーフィンに挑戦
    • しかし左足が変な方向に曲がり靭帯をめっさ痛める(まだリハビリ中
    • プライベートでiOSアプリをリリースする
    • 留学説明会に参加する
  • 2015/11
  • 2015/12
    • iOSアプリを担当していたサービスのクローズが決定する

所感

仕事ではiOSObjective-C, Swift)とRailsと新しい技術に触れることができた良い1年だった。 Railsはずっとやりたいと思ってて念願が叶ったものの、いざやってみるとコードを書く時間に比べて使ってるgemの理解に時間を取られてしまってあまり楽しくなかった。(作ってるサービス自体にあまり熱意が持てなかったのも問題だと思うが) 一方サーバ側の仕事はチームメンバーにほぼ任せっきりになってしまって自分の力にすることができなかったのが残念だった。来年はこのあたりの弱点を補う方向で技術力を伸ばしていきたい。

プライベートでは精神的にも身体的にもしんどい時期が多い1年だった。。 その瞬間瞬間はとても苦しいけど、今はどの決断も後悔してない。 中でも一番大きい決断だったと思うのは語学留学へ行く意思決定をしたこと。 なるべく多くの人に話して後戻りできないように自分を追い込んでるので必ずや実現させたい。 来年の年末に振り返ってみて、良かったと思える決断であったと信じてるし、そうなるように2016年突っ走りたい。

2016年やること

以下の4項目を2016年の目標として設定する。 2016年の年末に4つのうちいくつ達成できたか確認したい。

  • 1つのサービスを上から下まで1人でつくる
    • サーバ側が自分の弱みだから
  • フィリピン留学する
    • フィリピンの1on1学習で会話力を伸ばしたい
  • プライベートはイエスマンになる
    • 基本的に誘いを断らない姿勢で。自分から誘うと尚良し
  • 体脂肪率9.9%
    • そろそろ腹筋割りたい

Facebook iOS SDK でアプリ招待が動かなくてはまった話

職場の仲間とマッチングサービスを作ってiOSアプリを担当しリリースしました。

簡単にサービスの概要を書くと、1日1回特定のエリア(恵比寿、六本木など)で開催される食事会にエントリーすることができ、同じエリアにエントリーしたユーザとマッチングさせる(ひと昔前に流行ったようなw)サービスです。

このアプリの中ではパートナーとなる友だちがいないとエントリーできない仕組みになっているため、Facebookのアプリ招待機能を実装することになりました。

iOS用のドキュメントに従い、App Link ToolでApp Linkを作成し、以下の実装で招待のダイアログを開きました。

  • Xcode: 7.2
  • FBSDK: 4.8.0
let content: FBSDKAppInviteContent = FBSDKAppInviteContent()
content.appLinkURL = "FacebookのAppLinkToolで作成したAppLink"
content.appInvitePreviewImageURL = "任意の画像URL"
FBSDKAppInviteDialog.showFromViewController(self, withContent: content, delegate: self)

ところがダイアログの中でユーザを選択して招待を送信してみたところ、被招待ユーザに肝心の招待通知が届きません。

何度もドキュメントと自分の実装を見直したり、ググって解決策を見つけようとしましたが、結局分からず諦めていました。

先日久しぶりに再度招待の実装してみるか、ということで調べ直してみたところ解決したので共有します。

上記のコメントでは以下のように言っています。

Also live App ID from iTunes Connect must be filled in in Facebook App settings

つまり、Facebookのアプリ設定でAppIDも埋まってる必要があるということです。

そこで自分のアプリを確認してみたところ、AppIDの欄はリリース以降更新しておらず空欄のままでした。

そこを埋めて実装は変えず、再度ダイアログから招待を実行してみたところ、無事被招待ユーザに招待通知が届きました。

f:id:tofucode:20151231171424j:plain

アプリの1stリリース時にFacebookログイン機能などを実装して(この時点ではまだAppIDが決まっていないため空欄になる)、リリース後にそのまま招待機能を実装しようとしたら同じような状況になる人がいるのではないかなと思います。(まさに僕がそのパターンでした。)

RubyのEnumeratorが理解できたような気がした話

仕事で先人のRubyのコードを見てたらEnumeratorというクラスが出てきました。

初見だったのでググってドキュメントを見てみたがよく分かりませんでした。

特に「遅延評価」てところがパッときませんでした。

(1..Float::INFINITY).map{ |n| n * 2 }.first(5)

=> 無限リストをループするためfirstまで実行されず処理が終わらない
(1..Float::INFINITY).first(5)

=> [1,2,3,4,5]

これが遅延評価(どん!)。

どうでしょうか?分かりましたか?

僕は上記ではよく分かりませんでしたが、Enumerator::Lazyを使って手元でコード書いてみてやっと理解できました。

まずはEnumerator::Lazyを使わない例。

[1,2,3,4,5].map do |item|
    p item
    item * 10
end.each do |num|
    p num
end

=> 1,2,3,4,5,10,20,30,40,50

次にEnumerator::Lazyを使った例。

[1,2,3,4,5].lazy.map do |item|
    p item
    item * 10
end.each do |num|
    p num
end

=> 1,10,2,20,3,30,4,40,5,50

こちらの記事を見て理解することができました。

Rubyist Magazine - 無限リストを map 可能にする Enumerable#lazy

あとから知ったんだけど、上記の記事の筆者はEnumerator#lazyの作者だそうな。

CloudWatchでSNSのメトリクス取得につまずいた話

SNSの通知の成功数・失敗数を集計したかったんです。

前任者のコードを見てみたら

// SNSは通知の成功数・失敗数が分からないため0を入れておく

とコメントがあったんだけどそんなことはなくw

CloudWatchでSNSのメトリクスを見ればちゃんと確認できました。

SNSはPush通知で使っているため、iOSAndroidそれぞれの通知成功数・失敗数が取得したかったのですが

ディメンションでPlatformを指定してもどうにも取得できない。

Amazon Simple Notification Service は以下のディメンションを CloudWatch に送信します。

上記リンクにもこう書いてあるのに…。

でなぜ取得できなかったのか結論から言うと、SNSのTopicを使ってPush通知を送っていたから、でした。

以下は取得できるメトリクスをAWS-CLIで確認した結果です。

TopicNameの方は取れてますが、Platformの方は取れてませんね。

$ aws cloudwatch list-metrics --namespace 'AWS/SNS' --dimensions "Name=TopicName,Value=トピック名"

{
    "Metrics": [
        {
            "Namespace": "AWS/SNS",
            "Dimensions": [
                {
                    "Name": "TopicName",
                    "Value": "トピック名"
                }
            ],
            "MetricName": "DwellTime"
        },

    (省略)

    ]
}
$ aws cloudwatch list-metrics --namespace 'AWS/SNS' --dimensions "Name=Platform,Value=APNS"

{
    "Metrics": []
}

試しにTopicではなくSNSのApplicationに対して通知をしてみたところ、Topicメトリクス以外のフィルタについても確認することができました。

AWSコンソールの表示も以下のように変わりました。

before

f:id:tofucode:20151030213415p:plain

after f:id:tofucode:20151030213337p:plain

自作ライブラリをbowerに登録してみた

以前作ったショボいライブラリが会社の人にバレて「npm install、bower installでインストールできるようになるのはまだできない認識であってますか?」って言われて微妙な反応したら

expect(response).to.eq(‘はい、そちらはまだです’);

というチャットが送られてきたのでbowerに登録してみた(パワハラです)

流れ

こんなかんじ。というかこれだけ

  1. 登録したいGithubレポジトリを決める
  2. bower.jsonを作成する
  3. Git tagでversioningする
  4. bower registerする

1. 登録したいGithubレポジトリを決める

今回登録したのはこれ

以前このブログでも取り上げたので一応再掲

2. bower.jsonを作成する

$ bower init

そしたら対話形式でいくつか質問に答えていけば自動でbower.json作成完了

自宅のbower1.2.7では以下のような質問内容

[?] name: dateformatjs
[?] version: 1.0.0
[?] description: Extension of the Javascript Date object with a minimum function for shaping the date.
[?] main file: dateformat.js
[?] keywords:
[?] authors: Toru Furuya t.furuya825@gmail.com
[?] license: MIT
[?] homepage: https://github.com/torufuruya/DateFormat.js 
[?] set currently installed components as dependencies? Yes
[?] add commonly ignored files to ignore list? Yes
[?] would you like to mark this package as private which prevents it from being accidentally published to the registry? (y/N)
[?] would you like to mark this package as private which prevents it from being accidentally published to the registry? No

3. Git tagでversioningする

remember to push your Git tags!

本家にこれしか書いてなかったのでやり方書いてくれればいいのにとか思いつつ

$ git tag v1.0.0
$ git push origin v1.0.0

version指定はsemver方式でやれ、みたいなことが書いてあるんだけど要は vX.Y.X のフォーマットなら大丈夫ぽい

4. bower registerする

さいごに登録

$ bower search XXXXX  //一応既に同名のパッケージがないか確認
$ bower register <my-package-name> <git-endpoint>

bower infoで確認しておしまいおしまい

そういえば

javascriptで日付を扱う際の近頃のトレンドは Moment.JS らしい

http://momentjs.com/

SourceMapを用いてOSSのライセンス表記を外に出す方法

OSSライセンスの明記をSourceMapで回避しちゃおうという話。

例えば

複数のjsファイルを結合したプロダクトのコードをminifyしてCDNとかに置くパターンを想定。 こういう場合おそらく以下のようなケースがあると思うんですよ。

  • 各jsファイルのminifyされたものを結合する
  • 全てのjsファイルを結合した後の1ファイルをminifyする

前者のケースの場合は、各min.jsにライセンスが表記してある必要がありますし(まあ大体のOSSライブラリはこうなってるかもだけど)、後者のケースでも結局minifyする時にライセンス表記を消さないようにしないといけないんですね。 自分のチームじゃないんですが、前者の方法でライセンスを保持してるチームも実際にあります。

で自分のとこはどうしようかなあと思っていたところ、チームの先輩がタイトルにあるSourceMapを用いたライセンスの表記の方法を提案してくれました。 SourceMapを用いると以下の2点のメリットを得ることができます。

  1. minify後の最終ファイルにライセンス文を含めなくて良い
  2. デバッグしやすい

minify後の最終ファイルにライセンス文を含めなくて良い

らしい。としか言いようがないのですがw このあと触れますがブラウザでminify前のjsを参照できてそっちにライセンスが表記してあれば大丈夫「らしい」です。(ご自身で調べてみることをおすすめしますmm) 自分も調べてみたのですが、残念ながらそれっぽい情報には辿り着けませんでした。 でもpixivでも同じ方法が取られている「らしい」です。 ファイルの大きさ的にはライセンス文の分だけ少なくなるくらいであまりここにはメリット無いかなと、あくまで自分のチームのプロダクトではそう感じました。

デバッグしやすい

これはSourceMapを利用したことがある人なら分かることですが、ブラウザでデバッグがしやすくなります。 具体的にはminify前後のファイル(sample.js/sample.min.js)とSourceMap(sample.min.js.map)を同じパスにデプロイした状態でブラウザでminify済みファイル(sample.min.js)を読み込みます。すると読み込んでるのはminify済みのファイルだけなのに、ブラウザのデバッグツールではminify前のファイル(sample.js)も参照することができるようになります。そのminify前のファイルにブレイクポイント差し込むこともできちゃいます。すばらしいですね。

方法

ほぼほぼ前の項目で書いてしまったんですが一応まとめとして。

  1. minifyする時にSourceMapを書き出すようにする
  2. minify後の最終ファイルと同じパスにminify前のファイルとSourMapもデプロイする

僕のチームでは結合&minifyはGruntで自動化してるのでこれ使ってSouceMapを書き出してデプロイとかしてます。

お願い

今回記載した内容についてもし間違いが含まれてましたら、コメント等でご指摘いただけたら幸いです。

追記

1日空けて考えてみたらちょっと思うところがあったので追記。 たぶんSourceMapの良い点としてminifyしてもコードを「可読性の良い状態で」公開することができることなのかと思いました。思い返せば、今回のアドバイスをくれた先輩も常日頃コードは公開すべきみたいな立場にいたなぁ、、、とw

なので今回の内容の本質はライセンスどうこうではなく、コードを公開するという点だったのかもしれませぬ。

さらなる追記

t-wadaさんからこのようなご指摘を受けまして、、、まさに言いたかったことをおっしゃってくれましたw ということでタイトルが誤解を招くような感じを受けるので修正しました。

t-wadaさんありがとうございますー。