ゆるふわ技術日誌

エンジニア見習いの悪戦苦闘日記

2019-2020 年末年始をまとめる

さて、冬休みも終わるので、2019年末〜2020年始なにやってたかをまとめようとおもいます。

2019年末① 4回目の納会幹事をやった

物好きというか、なんというか笑

毎回なんだかんだ達成感もあり、次回への課題もあり、たくさんの人から感謝されるのが楽しくて気がついたら入社して4回目の納会幹事をしました。納会は四半期に一度なのでこれで1年やったことになりますねw

2019年末② Flutterをやってるよ

年末だけじゃなく、年始もやってるけど個人的な興味からFlutterを触ってみたりしてました。上記ツイートはFlutterのDevToolsの作り込まれ具合に感動している様子。この辺はちゃんと勉強したらまとめたいと思ってます。

作りたいものがあるというワケではないので、業務で作っているアプリの一部をFlutterで再現してみて、違いを体感したりしたい。

2020年始① 初日の出を見にオフィスへ

カメラが趣味というのもあり、初日の出を見たいと思ったものの、思い立ったのは大晦日

有名スポットに向かったら人混みに飲まれてしまうのがわかりきっていたのでなんとかならないか…と考えた結果。。。。

普段めっちゃ景色いいところにおるやんけ、と気づいたので実家からバイクで職場に向かってみました。

f:id:uutarou:20190514224623j:plain
参考: 普段の景色

あんまりちゃんと見えませんでした。。。

(天気のせいにしているが、これもうあと10分くらい待ってたらちゃんと見えたのかも。。。日の出の時間過ぎて見えなかったから諦めてビル降りてしまった…)

帰りにODOが1111kmになった。

2020年始② ツーリング初め

また後輩に誘ってもらったので大洗〜栃木ツーリングに行ってきました。

f:id:uutarou:20200105002427j:plain
大洗の景色、天気良かった。

で、大洗から栃木のツインリンクもてぎへ。

下調べ全然できてなかったのですが、ツインリンクもてぎってサーキットだけじゃなくて様々なアクティビティができるんですね。

Hondaのミュージアムがあったり。

f:id:uutarou:20200105104953j:plain
モトコンポの実物をみられる日がくるとはw

ずっとやってみたかったカートをやりました。(写真撮り忘れた)

www.twinring.jp

初心者向けの体験カートだったので、最大速度は45km/hなのですが、低いのと狭いのもありスピード感があって楽しかったです。これはハマりそう。

そういえば、栃木にはセイコーマートがあるんですね。道も広いし、実質北海道ツーリング。。。

f:id:uutarou:20200105105342j:plain

おわり

そんなわけで結構充実した年末年始をすごせたかなとおもいます。

ここには書かなかったものの年末年始はたくさん買い物をしました。

カードの請求が怖いですね。。。

近況報告的な記事(趣味要素つよめ)

社会人になって半年経った。という記事から一切更新しておらず、このままだと社会の荒波にもまれて闇落ちしたのかと思われてもしょうがない(?)のでここらで近況報告をしておこうと思います。

久しぶりの記事で申し訳ないですが、技術要素はほぼないです。ゆるふわ技術日誌とは一体。。。。

仕事

相変わらずReact Nativeでアプリを書いています。

入社以来、開発しているアプリにおける技術の面を支えていたスペシャリストの方が別の役職の仕事を優先するためチームから離れることとなり、その後任として技術面の意思決定をする役割をもらったりと、自分としては少しチャレンジな日々を過ごしていると思っています。

任せてくれた上司の期待を裏切らずやっていきたい。そう思いながら必死に悩んだり、コード書いたりいろいろしてます。

言い訳でしかないものの、日々忙しくせっかくやっている技術に関してアウトプットできていないのは痛いところ。

qiita.com

先日会社のアドベントカレンダーに書いたこれくらいかもしれないな。これは2020年の課題。


本来の仕事とは外れるものの、職場のちょっとした課題を技術で解決するのが最近の趣味だったりします。

Slack bot作ったり、GASで作ったAPIとReactで適当に作ったフロントエンドで困りごとを解決したり。やっぱ本質的に自分は人に感謝されることが好きなんだなあと感じておる今日この頃です。

技術

なんだかんだ仕事で使ってる技術以外に手を出して遊んでみたり、とかできてないなあという反省。

最近唯一ハマってちょいちょいやっているのはGCPのいろんなサービスをつまみ食いすること。特にCloud Functionsにはハマっています。あれ、Chromeが使えるのでPuppeteerが使えるんですよね。めちゃ楽しい。

qiita.com

つい最近書いたやつ。

趣味

何を思ったか8月末のある日、二輪免許が欲しくなり教習所を検索すると、なんと家から通える範囲に教習所が…!

これは行くしかないと思い立ち入校。目黒と恵比寿の間という土地柄もあってか、相場よりだいぶ高く普通免許所持の普通二輪免許取得のはずが14万位払いました。

後から聞いた話、通っていた教習所は芸能人御用達らしい。

仕事をしながらなので土日しか通えませんでしたが、無事ぴったり2ヶ月後の10月末日に教習所を卒業。10月31日に二輪免許を取得しました。

免許センターを出たその足で、YSP(ヤマハのディーラー)へ行きお目当てだったSR400というバイクを見に行きました。

ぶっちゃけこれを買うことを目標に免許を取ったところがあるのですが、なんと納車待ちが2ヶ月。。。。しかも思ったより見積もりも高く(車検のある車両の乗り出し価格は結構すごい)ひとまず諦めて、ふわっと頭の片隅にあったもう一台のバイクを見に行くためホンダドリームへ。

こんなバイク。

f:id:uutarou:20191216233904p:plain

思った以上にかっこいいし、思った以上に安く(これは直前にSR400の見積もりを見ていたせい。このバイクは250ccなので税金等がSR400より安い)しかも在庫あり。1週間ちょっとで納車可能とのこと。

うっかり契約と相成りました。

納車はこんな感じで。

f:id:uutarou:20191216234413j:plain
店の一番目立つところに置かれていたマイバイク

f:id:uutarou:20191216234501j:plain
マジの新車

f:id:uutarou:20191216235231j:plain
その後同期に連れられて東京駅に。カメラの充電切れててスマホ撮影になってしまったのが悲しい。

というのが約1ヶ月前の話。

それから1ヶ月の間は、冬でクソ寒い中毎週土日にちょこちょこバイクに乗る生活をしていました。大好きな海ほたるへ行って初高速を体験したり、これまた大好きなアイドルであるでんぱ組.incの幕張で開催されたライブにバイクで行ったり、東雲のバイク用品店に行ったり、ずっと行ってみたかったコメダ珈琲店に行ったり。

住んでるところがバリバリの都会なので全然バイクなんてなくても生きていけるし、電車なら寒くないし、コケて怪我したりする可能性もないけどそれでもエンジンの振動や音を感じながらいろんなところへ自力で行けると言うのはなんとも言えない楽しさがあります。

f:id:uutarou:20191216235856j:plain
これはそのライブで行ったライブのひとまく。初めてスマホによる撮影が解禁されたライブとなりました。しばらくアイドル熱は冷め気味だったのですが、やっぱりライブはいい。というか「でんぱ組の」ライブはいい。(オタク特有の早口)

で納車から1ヶ月が経ち、昨日は初めてツーリングをしました。行先は千葉。

バイク乗りの後輩に誘われて行ってきました。買ったけどサイズが合わなかったらしい冬用グローブを納車祝いにいただいてしまいました。本人は安物と言っていたけどアレがなかったら今頃手が凍傷にでもなっていたと思う。本当に救われた。

ちょっとした(いやけっこう?)ハプニングはありつつも、楽しく千葉をまわることができました。天気も👍

f:id:uutarou:20191217000424j:plain

f:id:uutarou:20191217000438j:plain

1ヶ月経って走った距離はこのツーリングを含めておよそ950kmくらい。だいぶ慣れてきましたが、これからも安全に楽しく乗っていきたいなと思います。


てなわけでほとんどバイクの話しかしてないけど近況報告でした。

学生のころはしょっちゅう病んでたけど、今は平日精一杯仕事して、休日はバイクに乗ってあっちこっちへ。というとてもメリハリのある生活をしているおかげか心もわりかし健康です。

ついついいろんなことに首を突っ込んでしまって、めっちゃ忙しいので体を壊さない程度にがんばっていきます。

社会人になって半年経った。

表題の通りです。

ちょっとだけ振り返っておく。

4月/5月

この辺の話は過去にブログに書いてた。

yurufuwa-tech.hatenablog.com

初めての一人暮らしで浮かれているのがよくわかる記事。

あの頃は、目覚ましかけなくても朝目が覚めてしまって、それで凝った朝食を作っていたなあというのを思い出した。

多分一人暮らしに体が慣れずに目が覚めてしまっていたというのと、業務もそれほど忙しくなかったのがあるのかなあ。

結局朝食は、目玉焼き+トースト+(ときどき)ヨーグルト+コーヒーというので安定しました。ウインナーとか毎朝焼くのはちょっとコストパフォーマンスが悪いのでやめました。

6月

なんだか必死に目の前のタスクだけをこなしていたような。

試しにそのあたりのSlack遡って見てみたら、オリジナルなライブラリ作ってプロダクションコードにマージされて喜んだり、React Nativeのアニメーションが扱えるようになってニヤついたりしてた。

あとは業務でHTML/CSS書いたり。(CSSなんて趣味のレベルでしか書いたことなかったのに、急に書くことになって雑に書いたら「コーディング規約あるよ…」って言われて死んだ)

この頃はとにかく、毎日会社にいけば新しいチャレンジができて、自分のスキルが上がっていくのが身を以て体感できて仕事が楽しいと思っていたような気がする。

yurufuwa-tech.hatenablog.com

yurufuwa-tech.hatenablog.com

TSの言語機能勉強したりとかもしていた。

記事にしていないことを含め、継続的に勉強していたのだが、いつの日かやめてしまった。

というのも、プロダクトのコードを触る程度であれば、基本的な型やinterface/enum/typeあたりがわかっていれば差し支えなく、やっても実戦に活きないと感じたから。

実戦の役に立たなければそれは無駄な知識なのか、と言われれば絶対にNOだと思うしなんでやめてしまったんだろうと、ちょっとこの記事を書きながら後悔している自分がいる。

こういうところから差は広がっていくんだろうな。

7月

驚くほどに何をやっていたか思い出せない。それくらい虚無。

それなりに毎日仕事をして、帰ってご飯食べて寝て翌朝仕事に行くという生活をしていたんだと思う。

Slack遡って調べてみたら、Reactのパフォーマンス計測/チューニング的なことをやっていた。

結局、shouldComponentUpdateを適切に書いたり、PureComponentを使って再レンダリングを抑制するのがもっとも効果がある、という結論が出て、じゃあやるか、と思ってコードに手をつけたら、構造上手をつけられないコンポーネントが大多数で、結局ちょっとだけ手を入れて終了した記憶。。。。

8月

業務は引き続きなにをやってたんだか全く覚えてないくらい無難に黙々とタスクをこなしていた気がする。

プライベートでは勉強会に2本登壇した。なぜか2週連続で。

nihonbashi-js.connpass.com

meguroes.connpass.com

喋りが苦手とかそういうのは練習不足だったのもあるし、致し方ないと思えたが、やっぱりエンジニアとして自分はイマイチなんだなと思った。

こういう場にいくと上には上がいることを思い知って辛くなってしまう。こういうタイミングで、悔しさをバネにして成長できる人は大成するんだろうと思うが、残念ながら僕はそう言うタイプではない。

こんな発言をしていた。発言当初はできると思って発言しているんだと思うが、今は全く自信がない。

9月

流石にまだ記憶にある。

ここまでの振り返りでお気付きの通り、普段の開発アイテムは一通り無難にこなせるようになって、完全に仕事がつまらなくなっていた。

そんなタイミングで降ってきた巨大開発アイテム。ある画面の挙動を変更するために、アプリケーション全体のデータ構造を変更するというものだった。

普段の開発アイテムは、雑に見積もっても大抵それ通りに終わるし、と思っていつも通りろくに既存の実装も確認せず見積もりをしたら大誤算。数日残業しまくっても終わらず、決められたバージョンでのリリースができなかった。

ここにきて初めて挫折した。


というのが半年の振り返り。綺麗にまとめて、じゃあ次の半年もがんばるぞ!って言って終わるつもりが記事を書き始めたらこうなってしまった。

慣れって怖くて最近全然仕事に対して、やりがいとか楽しさを感じなくなってしまった。

おまけに、周りはすごい人だらけ自分は上半期トータルで見ると全然成長した実感がない。

今目の前にある仕事に本気で向き合ったら、その先には何があるんだろうか。

そもそも自分がどうなりたいというのがなさすぎて、何に向かって努力すればいいのかわからない。

あるのは、自分の書いたものが意図通りに動くことは嬉しいし楽しいという気持ちだけ。とはいえそんなの学生インターンでもできる。

じゃあどうすればいいのか、何を目指せばいいのか。全くわからん。

そして、こういう自分の意思がない人は会社も求めてないだろうと思うと、余計に苦しい。


追記

将来とか知らんけど目の前の仕事は全力でやることにした。

点と点はどっかでつながるかもしれないし

スティーブ・ジョブス 伝説の卒業式スピーチ(日本語字幕) - YouTube

この動画、中学生の時に初めて見て、それなりに感銘を受けたつもりだったが、先日思い返してまた観たらその時より染みた。

TypeScriptのReadonly/Partial/Pick/Recordについてまとめる

引き続きTypeScript handbookの英語に苦しみつつ読み進めています。

ちょっとだけ日本語訳にも頼ったりしているけど許してね。


さて、今日はAdvanced TypesのMapped Typeというところに出てくるReadonly/Partial/Pick/Recordという型について。

つい先日やりたいと思っていたことが全部解決したので、自分用メモとしてまとめておきます。

www.typescriptlang.org

Readonly

これは、既存の型の各プロパティを読み取り専用にしたい時に使う型。定義は以下。

type Readonly<T> = {
    readonly [P in keyof T]: T[P];
}

使い方は、

interface SomeType {
    hoge: string;
}

type ReadonlySome = Readonly<SomeType>

これでReadonlySomeは、

{
  readonly hoge: string;
}

と等しくなります。

Partial

これは、既存の型の各プロパティをoptionalにしたい時に使う型。定義は以下。

type Partial<T> = {
    [P in keyof T]?: T[P];
}

使い方はReadonlyと変わらないので省略。ちなみに僕はこれがやりたくて、つい先日interfaceを2個書きました。。。

Pick

これは既存の型から、一部のプロパティを抜き出した型を作るのに使う型です。定義は以下。

type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
}

だいぶ型が複雑になってきますね…。使い方は以下。1つ目の型引数には元となる型を渡して、2つ目の型引数には、キーを渡してやります。

interface SomeType {
    hoge: string;
    fuga: string;
    piyo: string;
}

type PickedType = Pick<SomeType, 'fuga' | 'piyo'>

PickedTypeは、

type PickedType = {
  fuga: string;
  piyo: string;
}

となります。

Record

新しい型を定義するための型。(ちょっとうまく説明できない)

定義は以下。

type Record<K extends keyof any, T> = {
    [P in K]: T;
}

使い方は以下。

type SomeType = Record<'hoge' | 'fuga' | 'piyo', string>

↑のようにするとSomeTypeは、

type SomeType = {
  hoge: string,
  fuga: string,
  piyo: string
}

と等しくなります。

実際はkeyofとかと組み合わせて、動的に型を生成するのに使うのかなと思います。

const some = {
    hoge: 1,
    fuga: 2,
    piyo: 3
};

type SomeType = Record<keyof typeof some, string>

こんな感じ???

所感

Readonly/Partialあたりは割とすぐ使いどころが出てきそうな感じがした。

あと、副作用として、これくらいのレベルの型の定義を読み解けるようになっておくと、他でも役に立つ気がした。

今日も朝から学びになりましたね。

JavaScriptのインスタンスメソッドを変数に代入してはいけない

JSerにとっては当たり前の事なのかもしれないが、うっかりハマってしまったので備忘録として書いておく。


こんな感じのコードがあったして…

class User {
  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

const user = new User('mirin');

UserクラスのインスタンスであるuserのgetNameメソッドを呼び出します。

user.getName() // -> mirin

これは間違いなく、インスタンスかする時にコンストラクタで指定した名前が返ってきます。

しかし、以下のような感じで呼び出すと…

const gn = user.getName
gn() // -> Uncaught TypeError: Cannot read property 'name' of undefined

となる。

なぜか。

(ちょっとこの辺は正確さに欠ける表現があるかもしれないので、ご承知おきください)

JavaScriptthisは、呼び出したオブジェクトが入ります。(アロー関数を使った場合の挙動は別になります。要注意)

user.getName()の場合は、userがthisになるため、名前を取り出す事ができますが、メソッド自体を変数に代入して呼び出してしまうと、thisはundefinedとなってしまうため↑に示したエラーが起こります。

ちなみに

実際に僕がやらかしたのは、条件によって呼び出すメソッドを変える必要があるという、割と複雑なロジックを書いていた場面でした。

結局、それくらい複雑なことをやるなら関数分けた方がいいよね、となってやめたのですが、もしインスタンスメソッドを変数に代入したい場合は、

const gn = user.getName.bind(user)
gn() // -> mirin

という感じで、bindを使ってthisを束縛してやればOKです。もしくはメソッドの定義をアロー関数を使う、でもOKです。

TypeScripのkeyofについて

TypeScriptのHandbookに一通り目を通す、というチャレンジを今週はしております。

なんとも読みにくい英語だなーなんて思いながら読んでたらkeyofという知らない演算子が出てきたので、調べてみました。


keyofが出てきたのはこちらの「Using Type Parameters in Generic Constraints」というセクション。

www.typescriptlang.org

サンプルコードを引用すると、

function getProperty<T, K extends keyof T>(obj: T, key: K) {
    return obj[key];
}

let x = { a: 1, b: 2, c: 3, d: 4 };

getProperty(x, "a"); // okay
getProperty(x, "m"); // error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'.

こう。

どうやら、keyofにオブジェクトのキーを渡すと、そのオブジェクトのキーのいずれかを取るUnion Typeになるみたいです。

単純にするとこう

interface HogeInterface {
    a: string;
    b: number;
    c: boolean;
}


type Keys = keyof HogeInterface;

const hogeKey: Keys = 'a';
const fugaKey: Keys = 'd'; // error

Keys'a' or 'b'or'c'になります。

特定のオブジェクトのkeyの値しか許容しない、みたいなパターンの時に使えるって話なんだとは思うのだがこれがどこで使えるのか…というのはちょい謎。。。

誰か教えてほしい。


追記 2019/06/15

誰か教えて欲しい。

と書いていたら本当に教えてくれた方がいました。感謝。

shgam.hatenadiary.jp

結局ジェネレータって何に使うの…?って話

JavaScript基礎力強化を図っています。

初めてのJavaScript 第3版 ―ES2015以降の最新ウェブ開発

初めてのJavaScript 第3版 ―ES2015以降の最新ウェブ開発

この本を読み返しながら、知識のないところを学習するシリーズ。


※先に結論を話すと、表題に関して答えを見つけられませんでした😉

ジェネレータについて話す前に、イテレータについて。

JSのイテレータについてざっくり

他の言語にあるイテレータ同様、繰り返しのための機構で、JSの場合Array/String/Map/SetなどがIterable(イテレート可能)なオブジェクトです。

イテレート可能なオブジェクトは[Symbol.iterator]という名前で、iteratorプロトコルに準拠したメソッドを実装しています。(Symbol.iteratorについては前回の記事参照)

developer.mozilla.org

詳しくは↑のMDNをみてもらうとして、ざっくり説明すると、

  • nextという名前のメソッドを持つ
  • 呼び出した時に{value: any, done: boolean}なオブジェクトを返す

というのがイテレータの条件です。

上記の条件を満たすことでfor..ofが使えたりします。もちろん自作のクラスに対して実装してあげてもOK。

で、ジェネレータは?

で、なぜイテレータについての説明を先にしたかというと、ジェネレータは呼び出すとイテレータを返す特殊な関数のことです。

こんな感じで定義します。

function* generator() {
  yield 'hoge'
  yield 'fuga'
  yield 'piyo'
  return
}

function*yieldという特別なキーワードを使って宣言するのが特徴で、この関数を呼び出すとイテレータがかえります。

const it = generator();
it.next(); // -> {value: 'hoge', done: false}
it.next(); // -> {value: 'fuga', done: false}
it.next(); // -> {value: 'piyo', done: false}
it.next(); // -> {value: undefined, done: true}

こんな感じ。

何が起こっているかというと、ジェネレータが返したイテレータを実行していくと、ジェネレータ内のyieldまで実行して、渡された値を返します。 実行はその時点で一旦ストップし、次に呼ばれたら、前回のyieldの位置の続きから実行して、次にyieldが出てきたら、渡された値を返します。

最後、returnが呼ばれるとイテレータはdone: trueを返すようになります。

また、イテレータのnextメソッドには引数を渡すことができ、

function* generator() {
  const name = yield 'What is your name?';
  console.log(`Your name is ${name}.`);
  return;
}

const it = generator();

it.next(); // -> {value: 'What is your name?', done: false}
it.next('mogami');
// Your name is mogami.
// -> {value: undefined, done: true}

みたいな感じで、前回実行したyieldの返り値がnextに渡した値になります。

何に使えるのか

やっとここで何に使えるのか、という話になります。

オライリー本では、イテレータ/ジェネレータの説明は12章で行われているのですが、14章 非同期プログラミングのところで再度ジェネレータが出てきます。

ジェネレータランナーという関数を用意することで、非同期処理が同期的に書けるという話。

本のソースコードを引用すると、

function grun(g) {
  const it = g();

  (function iterate(val) {
    const x = it.next();
    if (!x.done) {
      if (x.value instanceof Promise) {
        x.value.then(iterate).catch(err => it.throw(err));
      } else {
        setTimeout(iterate, 0, x.value);
      }
    }
  })();
}

こんな感じの関数を用意してやって

function* fileReadAndWrite() {
  const dataA = yield readFile('a.txt');
  const dataB = yield readFile('b.txt');
  const dataC = yield readFile('c.txt');  
  yield writeFile('d.txt', dataA+dataB+dataC);
}

(readFile/writeFileはいずれもPromiseを返す関数)

最後にこのジェネレータを最初に作ったジェネレータランナーに投げ込む

grun(fileReadAndWrite);

すると、非同期処理が同期的に書けて人間にみてもわかりやすいよね、と書いてありました。

とはいえ、コレって今となってはasync/awaitで解決しちゃう問題なんですよね…。

async function fileReadAndWrite() {
  const dataA = await readFile('a.txt');
  const dataB = await readFile('b.txt');
  const dataC = await readFile('c.txt');  
  await writeFile('d.txt', dataA+dataB+dataC);
}

fileReadAndWrite();

こうか?

で、よりわけわからなくなった。

じゃあもうジェネレータって何に使うのよ、って感じですね。

はぁ…。