旧gaaamiiのブログ

間違ったことを書いている時があります。コメントやTwitter、ブコメなどでご指摘ください

styled-componentsの良さがよくわからない

と、煽ってるような記事タイトルだけど、 煽りたいわけではなく、単にわからないというつぶやきです。

自分はいまCSS Modulesでやっていて、特に困ることがない。

最近styled-componentsのほうがよく聞くのはなんでだろう。 あっちのほうがなにかいけてるポイントがあるんだろうか。

2018年の振り返り

今年も色々あった。時間過ぎるのがあっという間で、気付いたら10年くらい経ってしまいそうなのでこうして思い出(?)をブログに残しておく。

1月

Reactを書いてた。Angularで書いたものをReact化するという少し変わった仕事だった。他にやるべきことはないか、なぜこれをするのか、という考えが足りなかった気がする。これをやりましょうというのを提案するべきだった。

2月

引き続きReactを書いていた。 組織的には、人がどんどん辞めていった時期。

3月

3月も人が辞めていた気がする。1〜3月の辞め具合がすごかったのでもはや何月に誰が辞めたか正確に覚えていない。

ここで、自分がそれまで携わっていたプロジェクトは開発を止めて、自分は異動する話になった。運良くやりたいことができるところへ異動になり、クビも切られなくてよかった。さすがにクビ切るというのは極端だけど、一瞬その会社での仕事がなくなったのは事実で、いろいろ考えた時期だった。

4月

新部署での仕事が始まる。ちゃんとしたRailsアプリケーションの開発を仕事でやるのは入社したばかりの頃以来で、ひたすら力不足を感じていた。あと会社が資金調達した。

5月

相変わらずひいひい言って大変だった。

6月

わりと大事な機能を開発することになり、これも大変だった。リーダーのレビューが最強で最高で学びが多かった。 難しかったのはオブジェクトの責務分けとか、RESTとして正しいURI設計をするだとか、たくさんテーブルを繋げて条件を指定するようなSQLの書き方だとか。あとRSpecもなかなかうまいこと書けなくて最初は特につらかった。

サーバーサイドの開発をするとき、esaでシーケンス図(UML)を書けて、それが考えを整理したり共有する上でとても役に立った。

7月

shgam.hatenadiary.jp

shgam.hatenadiary.jp

悩んでいる感じがこのブログにも残されている。今思うと、余裕がなかったとはいえwebpackerの設定直さないまま開発を続けていたのはとても良くなかった。

開発していた機能のリリースなどをした。

8月

React, Reduxなプロジェクトの雛形を用意してつく始めたり、Elmのあれをあれしたりしていた。

9月

仕事は引き続き、ReactとReduxのあれをあれしていた。

buildersconへ行ったり、ISUCONに出たりした。

shgam.hatenadiary.jp

shgam.hatenadiary.jp

10月

同じくReactの云々。

11月

Elmで途中まで作っていたものをデモでお披露目するということで、そちらを急いで進めたりなどした。その後のリリースまで持ってくのもけっこう大変で、Elm力が高まった気がする。スケジュール的には押してしまって反省あるのみ。

あと、RubyWorld Conferenceへ行った。

shgam.hatenadiary.jp

あと、結婚したり、歳をとったりもした。

12月

Elmで書いてたやつがリリースされ、Elmのアドベントカレンダーにも記事を投稿したりした。

qiita.com

その後は引き続きReactを書いてた。

会社が御茶ノ水へ移転した。それまでと比べて、戸惑うくらい快適なオフィスになった。 代々木もそれなりに長くいたので感慨深かった。またいつかいそじ行きたい。

shgam.hatenadiary.jp

一年通して

仕事全般について

1〜3月は会社が良い雰囲気ではなかった。業界的に人が辞めるのはよくあることかもしれないけど、それにしてもこんなに一気に…という感じだった(年の後半では人が増えてオフィスも移転して、雰囲気も明るくなって本当に良かった)。 当時は、困った、さあこれからどうするって感じで、そこで自分が関わってきたところも、問題を洗い出したりして、開発を止めることになり、そこを離れるということになった。

その時は、ああこうやって仕事って無くなるんだなと、はっきりとした危機感を持った。 事業的にいろいろ整理が発生するのは絶対あることだろうけど、突然仕事が無くなったときに、どこにも行き場がないみたいな状態にならないように精進していかなくてはと思った。今回に関しては運が良く、希望のところへ異動させてもらえた。

ウェブフロントエンドについて

自分の仕事に危機感を持ったこともあり、ウェブフロントエンドに関して考えることが多かった。 そこで考えて出てきたのは、やっぱりウェブアプリケーション使うなら、使いやすく、速く感じられるのが良いだろうということ。そのために必要な技術がウェブフロントエンドの諸々だと思っている。

iOSAndroidのネイティブアプリだったら、はじめからサーバー側のロジックととクライアント側のロジックは切り離されてるけど、古くから(クライアントMVCとかSPAが持て囃される以前)のウェブアプリケーションだと、サーバー側のコードの一部として管理されていて、密結合だったりする。すると、クライアント側での最適化みたいなのは難しく、基本的にユーザーは毎回サーバーから手元のブラウザへ、HTMLドキュメント全体をダウンロードして、画面を更新することになる。

Fluxみたいなパターンと仮想DOMみたいな仕組みで、ユーザーの行動に応じて画面のなかの必要な分だけ更新するようなアプリケーションが可能になった。ただウェブにはURLがあるので、フロントエンド側にルーターを持ち、ウェブのURLの表現を保つ工夫も必要になる。

もちろんSPAみたいなのは良いことばかりではなく、サーバーがリクエストに応じたHTMLドキュメントを返すだけというシンプルさを捨てることになる。実装の複雑度は増すし、ユーザーからの目線で考えてみても、SPAのほうが体験が良いと言えるのはちゃんと作られている場合だけで、不具合があったり不自然な画面遷移をしたりするものを作ってしまうと、SPAなんかしなけりゃよかったということになりかねないとは思う。それでも、自分はサーバーとクライアントは分けたほうが良いと思っている。APIと画面を分けるのは、サーバーはサーバーを、クライアントはクライアントのことをうまくやるのに集中できる環境をつくることだと思う。

しかし、モバイルで最高の体験を、と考えるならやっぱりウェブよりネイティブアプリだと思っていて、じゃあ上で書いたようなものは何をつくるために必要なのかと考えると、PCで使うSaaSみたいなものがあってると思う。「クラウドなんちゃらシステム」みたいなもの。そして、人がパソコンのキーボードを叩くのは多くが仕事かそれに近いようなときで、それ以外はみんなスマホを使ってる(と思う。すごい雑認識だけど)。だから、ウェブフロントエンドをさらに個人的な視点で狭く言うと、仕事でPCで使うときに使うシステムを使いやすくする技術になる。

今まさにやっている仕事もそれに近いものなので、これをどこまでの出来にできるかというのが、事業にも、自分のキャリアにも重要になっていると思ってる。なかなかうまくいかないこともあるけど、引き続き頑張っていきたい。

プログラミング言語について

Ruby(Rails)は、よく考えてる人が書いたものは洗練されていて、責務がしっかり分けられていてきれいという感想を持った。オブジェクト指向の本読みきらねばという気持ちが強まった。

あと、一時期Elmを書いたことにより以下のような気持ちが芽生えた。

  • 静的型付け言語良い
  • Lintとかなるべく自分で設定する必要がなく、コードのフォーマットとかは自動でされたほうが嬉しい

関数型言語についての感想は、関数の入力の型がその入力を制限していて、同じ入力に対して常に同じ出力になるっていう単純さが良くて、ほかの難しそうなことについては正直よくわかっていない。

特にオブジェクト指向デザインパターンのような、プログラム全体の整理整頓みたいなのをどうやるべきかというのがまだよくわかってないけど、Elmの場合は中心となる型があり、それをいじくる関数が一緒にまとまったものがモジュールになるという考え方っぽかった。

来年はGo言語も少し触ってみたいという気持ちになってる。

健康

大きい病気はしなかったけど、地味に疲れやすい体になってきてるなという気はした。 健康はなんかぼーっとしてるとどんどん奪われていくので、きっと健康オタクくらいの感じがちょうどいい。

生活

今年は結婚をしたので、人生設計を堅くしてこれからのことに備えていきたい。

人間関係

ありがたいことに、仕事でも親族関係でも友人関係でも、嫌いな人と接することがほぼない。とても恵まれていた。

インターネット上での活動

Podcastとかほとんどとれなかった。

きまべんという思いつきで始めたScrapboxプロジェクトが、熱意のある方々によって続けられていて、自分もやっていかなくてはと刺激される。

まとめ

今年もお世話になりました。来年もよろしくお願いします。

レイアウトのためのatomコンポーネントとかtemplates層とかの実装

Atomic Designの本「Atomic Design ~堅牢で使いやすいUIを効率良く設計する」を参考にしながら、こういう感じでやっていってる。

// atoms/AppLayout.tsx
const AppLayout = (props: Props) => {
  const children = React.Children.toArray(props.children)

  return (
    <div className={styles.left}>{children[0]}</div>
    <div className={styles.right}>{children[1]}</div>
    <main>{children[2]}</main>
  )
}

// templates/UserPageTemplate.tsx
interface Props {
  user: UserInterface;
}

const UserPageTemplate = (props: Props) => {
  return (
    <AppLayout>
      <AppHeader />
      <AppSidebar />
      <UserView user={props.user} />
    </AppLayout>
  )
}

AppLayout に当てるCSSのflexboxなりgrid layoutなりでレイアウトを実現しておいて、同じレイアウトのページを作成するときは同じようにAppLayoutで囲えばそのレイアウトになるという感じになる。

templateのコンポーネントでは、どのレイアウトにどのOrganismを置くかということを記述する。URLから最初の状態を作ってpropsとして渡すのはその上のpageコンポーネントにやってもらう。なのでtemplateはStateless Functional Component (状態無し関数コンポーネント)になる。

レイアウトがAtomだってことに最初はちょっと違和感あったけど、別に何もおかしなことはなかった。

代々木の思い出

オフィス移転のため、今日が代々木オフィス最終日だった。

今の会社に転職してから色々あったけど、いそじというラーメン屋のつけ麺がずっと安定して美味かった。

26歳

忘れてた。26歳になっていました。若者を自称するのはもはや不可能になり、身体能力も着実に衰えてきています。この前テニスしたら大学生にロブで振られてボロボロにされ、負けました。翌々日の筋肉痛が全てを物語っていました。つらい。26歳も頑張ります。

キウイの本を読んでる

キウイ🥝。

なんで読んでるのか

自分はいまウェブアプリケーションのUIをつくる仕事をしているので、ReactやらReduxの記事とかはよく読む。けどもう少し広めの、UIをつくるプログラミング全般に適用できる設計パターンみたいなのを学びたかった。

あとで感想ここに書く

Storybookを使って気付くCSSの粗さ

がっと作った大きなOrganismがあって、それを構成するMolelculeやらAtomやらのレベルのコンポーネントをすべてStorybookに置いた段階で、「あれ、なんかこれいい感じに表示できない...」ということに気付く。CSS Modulesを使ってスタイルのスコープをそのコンポーネントに閉じさせているものの、それだけでは期待する見た目にならない。正しい見た目が上の要素に依存していて、それがないとちゃんとした見た目にならない。直さなくては...ということになる。

Storybookに細かい単位でコンポーネントを置かなければこういうのをごまかせてしまうので、いざ細かいコンポーネントを使い回すときになるまで「なんだこれ」ということに気づかなかったりする。Storybookの使いみちはいろいろあるけど、こういうスタイルのスコープ確認につかえて便利だと思う。

fetch-mockでStorybookからモックデータを利用する

新たに開発している画面で、Storybookを利用してデザイナーさんに見た目のレビューしてもらいやすくしようとしている。この画面はAPIと並行して開発しているので、モックデータを用意してそれを見るようにする必要がある。

アプリケーション本体の方ではjson-serverを使っていて、Storybookもローカルで確認するにはそれで十分だったのだけど、確認のために用意した環境はS3なので、別でモックサーバーを立てるというのはそこまでするの感がある。

ferch-mockを使うと、APIへのリクエスト部分をモックのpromiseに差し替えられる。setTimeoutの値を変えれば遅いAPIをシミュレーションできるし、エラーを返せばエラー時の挙動を確認できる。便利。

json-serverのために用意したモックデータをそのまま使えてよかった。

ContainerコンポーネントとPresentationalコンポーネント、reduxとの接続についての方針とか

ReactとReduxでアプリケーション書いていて、containerコンポーネントとpresentationalコンポーネントの分け方どうするかという話。スマホで雑に書いているので、あとでまとめる。

元ネタ

redux作者のブログ記事のあれ。

参考にしたもの

AbemaTVの人のAtomic Designの本に書いてあった方法

コンポーネントの種類分けることで何ができるのか

もう少し詳しく

  • イベントが起きたときに何をするかというのをcontainer側に書いておいて、見た目のコンポーネントにはそれをpropsとして渡す
  • reduxのstateに変更を加えるような処理はactionを投げてreducerが処理をする
  • 見た目コンポーネントがそのコンポーネント自身でしか使わないような見た目のStateを持つのは許容する。
  • ファイルは今のところ分けずに、1ファイル内にcontainerもpresentationalも書いてる
  • reduxと接続するのはcontainer

elm/timeの使い方よくわからない問題

あるイベントが起きた時刻をサーバーに送信したい!というときに、Elmではどう書くのか調べたけどよくわからなくて、頑張って実現するとこういう感じになってしまったというメモ。これでいいのかよくわからない。サンプルを書いたので識者の知見がほしい...。

サンプル

疑問点

JSなら任意の時点で new Date()すれば現在時刻が取れるのだけど、Elmの場合はsubscriptionsに関数を入れて、一定間隔でmodelの値を更新して、使うときはその値を参照するみたいにしないといけないのか...?というところ。イベントが起きたときだけほしいのに、前もってそれをmodelに持って常に更新しておかないといけないのだとしたらなんか変な感じする。おれがやってることが間違ってるんじゃないか感がある。というのが現状。

Reduxのreducerはなんでreducerと呼ばれているのか

Reduxのreducerはなんでreducerなのか、そもそもreducerってなんだ、みたいなことを調べたので書きます。間違ったこと書いてたら直します。

背景

Reduxでは、reducerってやつが状態の変更方法を知っています。reducerはReduxのドキュメントに以下のように書いてある通り、

状態とアクションを受け取って、次の状態を返すやつです。

しかし、reducerという言葉はどういう意味なのでしょう。「状態とアクションを受け取って、次の状態を返すやつ」を、なぜreducerと呼ぶのでしょう。

Weblioの辞書で調べると、

〔+目的語+to+(代)名詞〕〈ものを〉(整理して)〔簡単な形に〕変える,まとめる.

という意味が出てきます。上述の通りReduxのreducerはstateを変えたものを返すやつなので、これが適切なのではないでしょうか。

ここで納得して終わりにしてもいいのですが、Reduxのreducerの意味がこれでよしとするには少し早いような気がします。Reduxの文脈で、なぜreducerという言葉が使われているのかをもう少し調べてみます。

Why is it called a reducer?

Google検索で、雑に why reducerと検索すると、先程のページが出てきます。

疑問に対する答えに当たる部分はここでしょうか。

It's called a reducer because it's the type of function you would pass to Array.prototype.reduce(reducer, ?initialValue).

ふむ。Array.prototype.reduce(reducer, ?initialValue)として渡せるような関数だからreducerと呼ばれている…?

なるほどわからん

Array.prototype.reduceの仕様

なるほどわからんなのは、私がArray.prototype.reduce関数を普段使っていないからのような気がします。reduceという関数に慣れていれば、上記の説明で一発理解ということになるのかもしれません。reduceは使ったこともあるし他の言語でもだいたいあるような一般的なものですが、ちゃんと仕様を読んで理解しているわけではありませんでした。

そこで、このreduce関数の仕様を見てみます。

さすがMDN、説明が丁寧です。これもじっくり読んでいきます。

reduce() はアキュムレータと配列の各要素に対して(左から右へ)関数を適用し、単一の値にします。

なるほどわからん。今度はまた新たななるほどわからんです。

今度のなるほどわからんは、「アキュムレータ」ってなんだ、という話です。こういうことを正直に書いてしまうとコンピュータのこと知らんやつだなというのが露呈するのであれなんですが、わからないものは仕方ない。

アキュムレータ(英: Accumulator)は、コンピュータにおいて、演算装置による演算結果を累積する、すなわち総和を得るといったような計算に使うレジスタや変数のことである。

accumulateというのが累積するという意味の英単語なので、そのままAccumulatorは累積するやつのようです。コンピュータアーキテクチャのことを学びたい気持ちも湧いてきてしまいますが、MDNのreduceのドキュメントを理解する上では、accumulatorという言葉の理解は上の説明で十分でしょう。

もう一度MDNのドキュメントに戻って、reduceが何をしているのかを見ていきます。

const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;

// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10

// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15

Reduceの使い方として、上のコードが例示されています。配列内の数の総和を出しているだけです。

やっていること、使い方はわかりますが、どう動作しているのでしょう。それについても書かれています。

なるほどわかりました。accumulatorがそれまでの返り値を保持していて、currentValueが配列内の現在の要素です。

let array = [1,2,3,4];
let accumulator = 0;
for (let i = 0; i < array.length(); i++) {
  let currentValue = array[i];
  accumulator += currentValue;
}

for文で書くとこんなかんじでしょうか。外で宣言した変数に詰めるのではなく、引数として渡ってくるのでreduceのほうがすっきり書けます。

Array.prototype.reduce?

Array.prototype.reduceがやっていることはわかったものの、

It's called a reducer because it's the type of function you would pass to Array.prototype.reduce(reducer, ?initialValue).

これは結局どういうことでしょうか。ReduxのreducerがArray.prototype.reduce(reducer)として呼べるのであれば、reduceのレシーバに当たる配列は何になるんでしょうか?

Stack Overflowのある回答がとてもわかりやすかったです。

['INCREMENT', 'DECREMENT', 'INCREMENT'].reduce(reducer, 0)

つまりアクションの配列がレシーバになる。なるほど〜〜〜、そういうことを言っていたのか!0が最初のstate(accumulator)になり、reducerで定義された変更が3つ行われた結果が返ってくる。

雑感

Reducerというのが「stateを変えるためのあれ」くらいの認識だったけど、今回の調べで言葉の意味から理解できた。

ところで、reduceを調べているとfoldとか折り畳み関数みたいな言葉も出てきていた。次はここらへんについてもまとめてみたい。

参考リンクなど

RubyWorld Conference 2018 参加記(2日目)

shgam.hatenadiary.jp

1日目に続き、2日目も参加しました。

Chad Fowler氏の基調講演 Don't Stop Moving

エンジニアのキャリアなどについての話でした。そういえばまだちゃんと情熱プログラマー(Chadさんの本)を読んだことなかったので読みたくなりました。

mrubyについて

2日目はmrubyの話が多かったです。おもむろにrbenv install mruby-1.4.1してから話を聞いていましたが正直あまりついていけませんでした...。後でmrubyについて調べつつ発表の動画を見返したい。

2日間通しての感想

運営も会場も内容もすべてしっかりしたカンファレンスでした。

とても貴重な経験ができました。様々なRubyistと話すことができましたし、島根県松江市Rubyの関係とか雰囲気とか、そういったものも感じることができました。プログラミング言語で町おこしというのは先例もなかったと思うのですが、市がRubyの価値を理解してそれを利用してるというのがすごい。

また、自社のスタディプラスブースで好きなRuby本のアンケートを取っていたんですが、これがとても面白かったです。 Rubyのしくみ -Ruby Under a Microscope-が思ったより得票数多くて、さすがRubyWorld Conferenceだ...!という感じでした(青い付箋がRubyのしくみ)。

RubyのしくみはRuby構文解析とかの説明をした本なので、Rubyそのものに興味がある人達が集まっているこのカンファレンスでは人気が出るのもそれはそうか、とも思いましたが、それにしてもすごい。

自分はRubyのしくみをけっこう序盤で挫折してから読んでいないのですが、なんとかまた読み直そうと思いました。

2日間、自分は講演の聴講と自社ブースの案内だけで発表などはしていませんが、それでもとても貴重な経験ができました。 関係者の方々、スポンサーになってくれた自社に感謝です。ありがとうございました。