Cookpadのサマーインターンに参加してきました

インターン内容

internship.cookpad.com

前半は現在Cookpadで使われている技術やサービス開発についての講義、後半はOJTコースとPBLコースに分かれてサービス開発の実践を行うという内容です。

前半について

講義については後日資料を公開するとのことだったので、そちらを見ていただけると良いかと思います。

一日コードを一切書かず、Cookpadのサービス開発の手法を学ぶという日があったのがとても印象的でした。自分たちでユーザーストーリーを考え制作したプロトタイプに、超丁寧なフィードバックを貰えたのはとてもありがたかったです。

ペルソナをしっかり設定しないと、出来上がるプロダクトもぼんやりしたものになってしまうということを痛感し、サービスを考えるのって本当に難しいと感じました。

後半について

私はOJTコースの配属になりました。

実際にCookpadの現場に入り、今実際に世の中で使われているサービスの開発に携わります。

私は、モバイル基盤部という部署に配属され、アプリのバグ修正やObjective-CファイルをSwiftに書き換える業務等をやらせていただきました。

メンターの方が本当にすごい方で、私が一つ質問すると付随することを一緒にたくさん教えてくれたので、毎日新しい知見が増えてとても楽しかったです。

また、人為的ミスを防ぎ時間を短縮するためにあらゆるところが自動化されているのを見れたり、Cookpadで採用されているアーキテクチャに触れられたりしたのもとても良い勉強になったと思います。

Cookpadは歴史のあるサービスなのでレガシーな部分もまだ残っていますが、それとモダンなコードを上手に共存させて、サービスのグロースを止めずに少しずつリファクタリングを進めていっているというところに技術力・開発力の高さを感じました。

モバイル基盤部には、fastlaneのコミッターの方がおられたり、カニ大好きな方がおられたり、技術的にもキャラクター的にもすごい人が揃っていて、同じ部署で仕事をさせて頂けたのが本当に光栄でした、、、!

会社の雰囲気

お昼休みや仕事終わりに社員さん同士でご飯を作っていたり、カードゲーム大会開催してたり、和気あいあいみんな仲が良いなという印象でした。

それに対して仕事の場では良い緊張感があって、そういうメリハリを大事にしているみたい。(実際インターン生もそうするように言われた)

また業務中には、部署が違うけど席が近かった方々が「なにか困ってることない?」って気にかけてくださったりして、社内全体のあったかい雰囲気が感じられました。

講義中のランチは手作りのものを用意して頂いて、インターン生同士で夕飯を作る機会も多くて、さすがレシピサービスを提供するCookpad!という感じ。

毎日のご飯が楽しみでしょうがなかったです。

f:id:aomathwift:20190901161434j:plain f:id:aomathwift:20190901161500j:plain

1週目終了後のクッキングバトルではジャスティン(@juschin_)さん率いる私のチームが優勝!週末の疲れた大人の胃袋を掴みました。

f:id:aomathwift:20190901162300j:plain

こうして料理したり一緒にごはん食べたりしているうちに同じインターン生や社員さんと仲良くなれたような気がします。

まとめ

歴史あるCookpadのサービス開発について学び、実際に現場にも入ってその手法に触れたことで、ユーザーが喜ぶサービスを提供し続けることの大変さを感じられました。

それと同時に、将来はそういったサービスの開発に携わりたいという気持ちが強くなりました。これから就活をしていく上での軸にもなるような気がします。

最後に、Cookpadの皆様、素敵な2週間をありがとうございました!!ここでの経験を糧に、これからもたくさんのことを学んでいきたいと思います。

余談

私がリスペクトして止まないお二人からこんなリプを頂いたので、そのうちObjective-C駆逐しに行きます。

Wantedlyのサマーインターンに参加してきました!

8月5日から8月16日までの二週間(実質祝日挟んで9日間)、WantedlyさんのサマーインターンiOSコースに参加してきました!

夏のインターン一発目からとても濃くて貴重な経験ができたので、ここで記録しておきたいと思います。

Wantedlyとは?

Wantedlyさんでは、主に以下の2つのサービスを制作しています。

  • はたらくを面白するための採用SNSWantedly Visit
  • かしこく名刺管理するためのサービスWantedly People

www.wantedly.com

私はVisitを使って今のインターン先を見つけたり、現在はその会社で同サービスのAdmin側を利用したりと、もともとこちらの会社のサービスに非常に馴染みがありました。

また、Wantedlyさんのエンジニアは技術力が高いと予てから話に聞いていたということもあり、今回インターンに応募するに至りました。

インターンの内容

Wantedlyさんのインターンは、完全就業形です。実際のチームにジョインして、タスクを振ってもらってそれに取り組む、というスタイル。

私はVisitのグロースチームに配属され、プロフィール入力欄のUIの改修を主に取り組みました。

初日はまずコードを追うことで一日が終わり、サービスの大きさを痛感。

翌日からは実際にUIButtonのカスタムクラスを作るところから始めましたが、今までデザイナーの考えたデザインに沿ってUIを作ったことが無かったので、色とかマージンとか、細かいところまでこだわってUIを作るということ自体が初めての経験でした。

レイアウトも、曖昧なプロパティが絶対存在してしまうStoryboard上で作った経験しかなかったので、全部コードでレイアウトするというのは最初はなかなかうまく行かなったです。

しかしながら、ここと見た目が似ている他の部分ではどんなふうに実装されているかな、とか、改修前はどんなふうに書かれていたかな、とかを追っていくと段々自力で想像した通りのUIが実装できるようになっていきました。 現在実際に動いてるプロダクトのコードを見れるということの有り難みをすごく実感。

メンターもインターン生1人に付き1人ついていただき、しかもインターン生は常にメンターの隣で仕事ができるという、かなりの安心感のもと仕事をすることができました。

会社の雰囲気

基本的に作業してる間は個人でもくもくって感じですが、MTGとかになると新卒の子でも関係なく積極的に意見を出し合ってたのが印象的でした。

お昼は社内全体のシャッフルランチがあったり、他チームのエンジニアとの交流ランチがあったりと、社内での交流の機会は多かったです。

私はこのタームで女子1人だったので、女性の人事さんが何もない日にランチ誘ってくれたりすごく仲良くしてくれて、とっても嬉しかった、、、!

ちなみにお昼で一番おいしかったのは会社の裏路地にある「馳走 麹屋」というお店の和食ランチ。 f:id:aomathwift:20190818221437j:plain

ただし、白金台周辺のランチは基本的にちょい高めです。

インターン生同士で関わる機会は正直そんなになかったですが、結果として最終日の打ち上げで結構仲良くなれました。

まとめ

就業形のインターンは初めてでしたが、実際にプロダクトとして生きているコードに直に触れられるし、その中に自分のコードを入れていくっていうのはすごくやりがいがありました。

また、インターン生だけの空間で作業しているわけではないので、会社の雰囲気を直接感じられたのも良かったです。ちなみにWantedlyさんのメンバーは根がおもしろい技術オタクって感じの人が多い印象でした笑

最後に、Wantedlyの皆様、2週間貴重な体験を本当にありがとうございました!!

打ち上げで出てきたGopherくんのケーキが可愛かったです。

f:id:aomathwift:20190818222839j:plain

次のインターン

明日から2週間、クックパッドさんの10Techインターンに行ってきます!!

無事ついていけるかは不安だけど、とても楽しみ!!

Sansanのモバイルアプリ開発1dayインターンに参加してきました

7月20日に、青山のSansanオフィスで行われたモバイルアプリ開発の1dayインターンに参加してきました! アプリメインのイベントに参加するのはなにげに初めてでしたが、とても充実した時間でした。

どんな人が参加していたか

書類選考があったので、来ていたのはモバイルアプリ開発AndroidiOS)の経験者のみでした。
どれくらいやってるかは人それぞれでしたが、個人で開発して個人でリリースしてた人が多かった気がします。 中にはめっちゃいろんなアーキテクチャ知ってたり、課題制作1時間もかからずに終わって周りの人にめっちゃ教えてたりするツワモノも。すごい。

インターンの内容

名刺管理サービスで有名なSansanさんの企画したインターンということで、
課題は名刺を撮影しOCRした結果を表示するアプリを作ることでした。

Googleが提供しているCloud Vision APIを使って撮影した写真のテキスト検出を行います。

ちなみにこのCloud Vision API、結構精度が高くかなり優秀です。
テキスト検出以外にもいろんな画像処理のAPIが提供されています。

cloud.google.com

午前中は今回使うAPIアーキテクチャ(MVP)に関する講義、午後はずっと開発という感じ。
基本は個人開発でしたが、iOSiOSでグループに固められているので、わからなければ周りの人に聞けるし、メンターのエンジニアの方も声かけたらすぐにとんできてくれます。

途中から自分の好きなライブラリ入れて好きなアーキテクチャでやってもいいよーって言われて、使い慣れてるMoya使って通信をやってたのですが、APIKeyをうまくURLにエンコードできない問題にハマり、しかもその原因をなかなか突き止められずめちゃめちゃ時間がかかってしまった、、、。
そのときデバック一緒にやってくれたエンジニアの方が、ライブラリの中にブレイクポイント置いて原因を見つけてくださったのがめちゃありがたかったです。
私ならそんなとこで止めようとか多分思いつかなかった。

ちなみに開発中はお菓子もジュースも飲み食べ放題でした。最高。

懇親会

一通り開発した後は、オードブルとお酒で懇親会。

今までアプリやってる人達だけで話すということがなかったのですが、同年代の学生が個人で作ってるアプリ見してもらったり、社員の方からDI・DIコンテナの良さを教えてもらったりとアプリ開発するにあたってめちゃいい刺激を受けられたと思います。

女性のiOSエンジニアの方もおられて、RxSwiftの勉強するのにマーブルダイアグラム見るのめっちゃ良いよねって話で盛り上がったの超楽しかった。
iOSDCでの登壇が決まってるそうなので、絶対聞きに行こう。

長いので中身は割愛しますが、CTOの方からめちゃめちゃありがたいお話も頂いて、とても充実した時間となりました。

Sansanの皆様本当にありがとうございました!!

余談

青山は私みたいな若造が行くにはちょっと大人な街で、勝手に気後れしてました。
がしかし、来週また青山に行く予定です。
今度はZOZOテクノロジーズさんのミートアップにいってきます!

Coderetreat for Girlsに参加してきました!

うちの大学で

Coderetreat for Girls

というイベントが行われたので参加してきました!
こちらのイベントは、enPit事業の女性部会WiTによって開催されたもので、今回で3回目なんだそう。
友達に誘われて初めて参加しましたが、とても密度の濃い時間を過ごせたと思います。 イベントの概要と感想をざっくり記録しておきます!

Coderetreatとは?

Coderetreat(コードリトリート)は、ソフトウェアの開発と設計の基本に焦点を当てて集中的に練習をするための、プログラマのための終日イベントです。 2009年に米国で発祥し、今や世界中の各地で開催されており、毎年秋にはGlobal Day of Coderetreatが世界中で一斉に開催されます。 開発者はCoderetreatに参加することで、「完成させなきゃ」という圧力から引き離され、練習に集中できます。

Coderetreatではライフゲームといった単純なお題に、45分のセッションを繰り返し取り組みます。すべてのセッションはペアプログラミングやモブプログラ ミングで行われ、セッションごとに新しい人と組み直します。書いたコードもセッションごとにすべて消します。

イベントページより引用)

当日の流れと内容

タイムテーブル

09:00 - 09:30 開場

09:30 - 10:00 趣旨説明、準備

10:00 - 11:00 セッション#1

11:00 - 12:00 セッション#2

12:00 - 13:00 ランチ

13:00 - 14:00 セッション#3

14:00 - 15:00 セッション#4

15:00 - 15:30 おやつ

15:30 - 16:30 セッション#5

16:30 - 17:30 セッション#6

17:30 - 18:00 クロージング

内容

各セッション振り返り

  • セッション#1
    言語:Python
    アクティビティ:なし
    ペアの相手は学部の男の子でした。共通言語がPythonしかなかったのでPythonを選択。
    一回目だったので、そもそもライフゲームって何?ってところを理解するのにかなり時間が取られ、完成せず。

  • セッション#2
    言語:Swift
    アクティビティ:ドライバー
    ペアの相手はランチを提供していただいたクラウドネイティブさんのエンジニアの方。セッション1での状況を伝えたら、一番得意な言語でまずはアルゴリズムちゃんと理解しようということでSwiftで書くことになりました。
    アプリまで落とし込めたらいいねなんて話してたけど、さすがに45分でそこまでは行けず。でもここで割といいところまでいけました。 この回ご一緒した方がファシリテーション上手すぎて感動。

  • セッション#3
    言語:Python
    アクティビティ:ドライバー
    ペアの相手はenPit関係者の女性の方でした。だんだんライフゲームというものを掴んできたので最初にできなかったPythonで再トライ。
    ペアの方が実装するべきメソッドを整理して紙に書いてくださったおかげでわりとさくさく進んで、ほぼ完成までいけました。
    アルゴリズム考えるの苦手だけど、一旦紙とかに書いて整理するのめっちゃ大事。

  • セッション#4
    言語:C
    アクティビティ:1メソッド4行以内
    この回は同じ大学の3年生×2と3人でモブプログラミングやりました。みんな前のセッションでやってきた言語全然違ったので、3年生の子のうちの1人がドライバーとしてCで一旦普通に実装して、それを1メソッド4行以内の条件で書き換えてみるというのをやりました。
    普段eurekaのSwiftコーディング規約に則ってスペースとか1行空けるとかめちゃめちゃ意識してるせいか、きつきつに詰めて書かれたコードはかなり違和感を感じた、、、

  • セッション#5
    言語:Ruby
    アクティビティ:ドライバー
    ペアの方は一般参加の女性エンジニアの方。やってみたい言語とかでいいよって言われて、これからインターンで書くことになるであろうRubyを選択しました。
    文法とかふたりともほぼ知らない状態だったけど、ペアの方も一緒にいろいろ調べてくださって、なんとかRubyライフゲーム完成したのかなり嬉しかったです。

  • セッション#6
    言語:Python
    アクティビティ:ループ禁止
    最後のペアは男性のエンジニアの方でした。最後なので既に実装できた言語で何かアクティビティに挑戦したいという話をしたら、Python再帰関数を使ってループ処理をする方法を提案してくださいました。派生して他にもいろんな書き方教わってたらライフゲームは全然実装できなかったけど、とても良い時間でした。なんとペアの方が数学科の出身らしく(しかも専門代数幾何だったらしい、すごい)振り返りタイムに数学の話もできたのは楽しかったです。

感想

  • ファシリテーターの皆さんが優しくて、やったことない言語・書き方でも安心して挑戦できたのが良かった。
  • 学生の皆さん意識が高くて、かなり良い刺激を受けた。
  • 美味しいランチとおやつが無料で提供されて最高だった。
  • 学生同士だと、非情報系としてどうしても引け目感じて思ってることとかはっきり言えなかったのは反省点。
  • 次回も是非参加したい!

最後に

今回のイベントを主催してくださったWiT様、スポンサーの株式会社ねこじゃらし様、株式会社クラウドネイティブ様、サイボウズ株式会社様、ありがとうございました。 とても充実した時間となりました。

UINavigationControllerに関するちょっとした躓き

インターン先でやってる開発の中で、
UINavigationControllerに関してちょっと立ち止まったところがあったので
メモしておきます。

躓きポイント

ページングビューを簡単に実装できるParchmentというライブラリを使ったPagingViewControllerをNavigationControllerの元に配置しようとしたら、対象のViewがNavigationBarの下に潜り込んでメニューバーなどが見えなくなりました。
これを解消するべく調べてみたら以下の記事がヒット↓

qiita.com

// PagingViewController

override func viewDidLoad() {
        
        super.viewDidLoad()
        
        self.navigationController?.navigationBar.isTranslucent = false
    }

これを参考にPagingViewControllerにこんなコード追加したらとりあえず直ったのですが、isTranslucentってプロパティは何ぞや?ということで少し調べてみました。

UINavigationController.navigationBar.isTranslucentについて

これはUINavigationBar、のプロパティで、ナビゲーションバーが半透明になったときにナビゲーションバーの下のコンテンツを表示するように設定します。デフォルト値はtrueです。

developer.apple.com

このデフォルト値がtrueなのにも関わらず、普通にナビゲーションバーを設置しても後ろが透過されてるように見えないのは、

  • レイアウトの中に不透明なナビゲーションバーが含むかどうかを示すextendedLayoutIncludesOpaqueBarsというプロパティのデフォルト値がfalseである
  • 通常SafeAreaはバーの下から設定されている
  • ナビゲーションバーの後ろはデフォルト背景が設定されている といった理由があります。

つまり、isTranslucentがtrueであることを活かしNavigationBarを透過させて下のコンテンツを表示するには、まずextendedLayoutIncludesOpaqueBarsプロパティをtrueにする必要がありそうです。 実は通常はこの設定だけでナビゲーションバーの下のコンテンツが見えるようになるんですが、それが叶うのはedgesForExtendedLayoutというプロパティがデフォルトで.allであるということが前提としてあるためです。

edgesForExtendedLayoutは端的にいうと、Viewがどの端まで伸びているかを示すもので、以下の項目があります。

public static var top: UIRectEdge { get }

public static var left: UIRectEdge { get }

public static var bottom: UIRectEdge { get }

public static var right: UIRectEdge { get }

public static var all: UIRectEdge { get }

デフォルトは.allに設定されています。StoryBoardからも設定できて、複数項目も設定できます。全部選ぶと.allと同じとみなされるみたいです。

ここまでをまとめると、通常であればisTranslucentがtrueであってもナビゲーションバーの下にViewが潜り込んでしまうことは無いはずなんですが、外部のライブラリ使ったりすると、意図せずしてデフォルト設定が変わっちゃってたりすることもあります。 そんなときに、isTranslucentをfalseに設定してあげると、

  • ナビゲーションバーが無条件に透過されなくなる
  • ナビゲーションバーが表示されている状態では、ViewControllerのビューの描画範囲が狭くなる

となり、潜り込んじゃったViewをちゃんと見ることができるようになるみたいです。

ちなみにこれは、TabBarなども持ってるプロパティです。

注意点

この設定を変えると、該当するNavigationController下にある全てのViewに影響が出るので、設定を変えたView以外のViewでレイアウトに多少の影響が出る可能性があります。(ちなみに私はこれいじって他のViewが崩れました)
設定を全部で統一した上で開発を進めるか、viewWillAppearとかでViewを描画するたびに設定してあげるかすると良さそうです。

間違ってたり足りなかったりしたらご指摘お願いします!