ベルリンのITスタートアップで働くジャバ・ザ・ハットリの日記

日本→シンガポール→ベルリンへと流れ着いたソフトウェアエンジニアのブログ

 個人開発ウェブアプリのご意見を募集してネット文化の素晴らしさを再認識した

先日、個人開発して公開したウェブアプリの率直な感想を募集したら、とても親切かつ有用なコメントをいただいて「ネット文化はなんて素晴らしいんだ」と無邪気に感動してしまった。

ネット上には罵詈雑言が溢れている、などと言われるが、そんな人ばかりが大多数を占める訳ではない。ほとんどの人は真面目に生きていて、やたらめったら攻撃的な訳が無い。

意見を募集した際にいくつかはバカだのアホだの言われるんだろーな、と思っていた。すみません。すさんでいたのは私の心だけだった。今日までで60通以上のご意見をいただいて、その全てがとても親切で有用なご意見だった。無断な罵りはひとつも無い。中には文字説明では足りないので、と画像まで付けてご説明いただいた方が居て、その心意気にちょっと感動してしまった。

みなさん、本当にありがとうございます。

いただいた感想を元に今いろいろと変えているところ。既に5つほどの機能とページを追加したけど、どこをどう変えたとか、どんなコメントをいただいたとかはまた別記事にまとめる。ここではただ単にありがとうございました、と。

それとこれから個人開発を始める方がいて、どうしていいのか分からなくなった際にはユーザーの皆さんから意見いただくのはいい方法だと思う。だいたいそのシステムの作者で隅から隅までそのシステムのコード書いた人ってのは分かり過ぎてて分かってない。

正直に言えばシステムのデータベース構成から変数の型まで知っている私からすれば、今日初めてサイトにアクセスしたユーザーに「一体これはナニをするサイトなのか分からない」なんて言われる、とは思いもしなかった。エンジニアなんて「オレはこのシステムの全てを知っている」なんて偉そうにしてても、所詮はそんなモンなんですよ。

正直少し前までは「こんなシステムで巨大な知識のノードグラフなんてできないわ」とヘコみ気味だったが、みなさんのコメントを読んで再度やる気がみなぎってきた。素晴らしいネット文化と集合知をちゃんとしたシステムを使って結集すればできるはずだ。ポイントはそのちゃんとしたシステムになるまで改善を続けられるかどうか。

もっとデカいノードグラフができたら、どんなのになるのか見てみたいし、誰かの役にも立ちそうなのでもうちょっとがんばります。

tango-ruby.hatenablog.com
tango-ruby.hatenablog.com
tango-ruby.hatenablog.com
tango-ruby.hatenablog.com

個人開発したウェブアプリに対して好き放題に感想を言ってもらいたい!願う!

個人開発したウェブアプリnode-node-nodeを先日公開して、ログ解析しても何しても、これからどうすればいいのか本当に分からないので率直な感想ください、というお願い。

今日で公開して3日なんだけど、アクセスはまずまずで、とにかくユーザーや投稿などの登録数が少ない。個人開発してる人は共通であると思うのだが、公開前までは自分のプロジェクトに惚れ込んでいる訳でして。恥ずかしいけど「これは世界を変える!」とか思ってしまう。

しかし完成していざ公開すると白昼の目にさらされて現実的には1日に700PVしかなく登録数もほんのわずかだけ。「え?なにこれ?全然ウケてないのか?この企画?」となっていろいろログ解析するけど、どこをどう改善すればいいのかまったく不明。

どれだけページ遷移やら数字眺めてもユーザー思考のしの字も分からない。もうここまで来たらハッキリとユーザーの皆さんから「○○がイケてねーんだよ!」と分かりやすく教えていただけますか?、と。

今回の経験を経て私もユーザーの立場で誰かが作ったウェブアプリにアクセスしたら、できるだけ素直な感想を書こうと思った。やっぱり個人開発のアプリはリソース足りてないし、どこかイケてないことが多い。正直、他人のアプリを見て「うわーこんなクソなモノをよく公開したな」と思ったこともある。ただクソでも作った人の苦労とか感じて悪い気がして「イケてない」の一言を伝えることができていなかった。

今だから分かる。「クソ」と思ってそっとブラウザを閉じられるのが一番キツい。クソならハッキリと「クソだ」と言ってあげるのが作者にとって有用なのだ。

ツイッターで呟いていただいた感想を見たけど、なんかちょっと褒め気味。それはそれで嬉しいけど、じゃあなんでこんなに登録数が少ないんだよ、と。なにかを改善するべきでその答えを知っているユーザーが無言でブラウザを閉じていることだけは分かっている。
なになんだぁああ!!出て行く前になんか言ってくれー!

しかしこう言ってはなんだが、このウェブアプリが仮にスベっていたとしても一定の効果はあると思っている。それは私がこのブログで主張している、海外でITエンジニアとして働くにあたって「あーこの程度のコーディングで海外行けるんだ」と思ってもらえること。おおーそうだよ。この程度でのうのうとヨーロッパでエンジニアやってますわ。ここまで来たら恥も外聞もねーわ。

こちらに「node-node-nodeに言いたい放題」を用意しました。匿名です。名前書くと思いっきり書けないかも、と思ったから。
書くのが面倒くさかったら点数だけでもOk。10点満点で「ナン点!」と言ってやって。
ぜひ率直な感想をお願いします!
https://goo.gl/forms/eXIkx3oNDdNmA6If2
node-node-nodeに言いたい放題


ちなみに公開したウェブアプリはこちら。(デスクトップ版のみです)

エンジニアの集合知をノードグラフで図解するSNS。
「node-node-node(ノード ノード ノード)デスクトップ版」
 https://www.node-node-node.com/

tango-ruby.hatenablog.com

GraphQLを導入してみて得た知見と雑感。GraphQLはタイタニックの救命ボードになりえるかも

GraphQLは実装内容に合えばタイタニックの救命ボードのように混沌から救い出してくれる。だからと言って全てのプロジェクトがタイタニックな訳ではないので、使い所が合わなければそんな救命ボードにもあまり意味は無い、という話。

先日、個人開発して公開したプロジェクト「node-node-node」はGraphQLを使っていて、このプロジェクト内容に対しては最高の親和性を発揮してくれた。

GraphQLのメリットを一言で言えば「クライアント=サーバー間での複雑なトランザクション処理の全てをGraphQLが吸収してくれる」ということに尽きる。ややこしい技術の詳細を書いたところでメリットはこれ以外に無い。

/usersや/postsというそれぞれのエンドポイントにリクエストを投げていたのがRESTful。
f:id:tango_ruby:20180208211439p:plain

GraphQLにするとエンドポイントを気にすることなく「これとこれが欲しい」という感じで投げればGraphQLが理解して返してくれる。
f:id:tango_ruby:20180208211502p:plain

なぜ個人開発のプロジェクトにGraphQLが大ハマりしたかを書く。このプロジェクト実装のポイントはRESTで言う複雑なGETにあった。

親子関係が何回も続く階層構造になったノードがサーバー側のDBにあって、クライアントは適切なノード情報をサーバーから取り寄せる必要がある。全てのノードは以下のようになっていて、親子関係がずっと続く。

ジジイ、ババア、ジジイ、ババア
|
親、親、親、親
|
本人、兄弟、兄弟、兄弟
|
子、子、子、子
|
孫、孫、孫

できるだけサクサク感を出すためにクライアントはユーザが今アクセスしているノードから次にクリックするかもしれないノードの情報を非同期でサーバーから集めている。ユーザーがクリックするころには既に裏側で集めておいた情報を出すだけ、とした。
この設計の場合、ユーザの置かれた状況によって、裏側で集めるべきノードが異なってくる。

例えば上のジジイ側から本人へ下りてきたユーザの場合、裏側で集めるべきノード情報は子や孫だけになる。なぜならジジイ側から下りてくる過程で既に本人より上の親ノードの情報は持っているから。
逆に孫側から上ってきたユーザーの場合は集めるべきは親やジジイになる。上がってくる過程で子ノード以下の情報は持っていることになるから。
兄弟の兄側から来た場合は末っ子側のノード情報が必要になる。

で、これを丁寧にRESTfulで書いていくとすごい数のエンドポイントになっていった。

ざっくりと親から、子から、兄弟からと3パターンだけ示したが、それ以外にもLikeした情報がある場合、無い場合、とかそれぞれのエンドポイントに独自の情報の有り無しを加えていったのでパラメータまで煩雑な状態となっていた。私はDHHのルーティングを支持しているのでCRUDアクションindex、show、new、edit、create、update、destroyのみを使うようにして、これ以外が必要な時は新しいコントローラーを作っていた。するとスゲー数のエンドポイントになって、Reactで作ったクライアントは状況に合わせてエンドポイントを使い分ける必要があって、どれがどれか混乱してきて「キー!」となった。

で、これをGraphQLに移行することでクライアント=サーバー間にあったややこしい部分をクエリ言語が全て吸収してくれた。クライアントからは欲しい情報を書いてリクエストすれば、それをそのままサーバーが返してくる仕組み。
そしてエンドポイントはたったひとつに、バージョンも何もない、ただひとつ!

例えば親側から来たユーザー向けに子情報が欲しい時のリクエストがこれ。要はchildrenをよこせ、と。

# client => server へのリクエスト(query)

query {
  Nodes {
    id
    message
    children {
      id
      message
    }
  }
}

するとサーバーからのレスポンスはこうなる

# client <= server レスポンス
  "data": {
    “Nodes”: {
      “id”: 3,
      “message”: “Hi I’m CEO.”,
      "children": [
        {
          “id”: 4,
          “message”: “Hi, I’m CTO.”
        }
      ]
    }
  }

つまりリクエストとまったく同じ形でレスポンスが返ってくる。
親情報が欲しければただリクエストにparentをつければいいだけ。めちゃ楽ちん。

ページネーションはこんな感じに実装した。例えばたくさん子ノードがあって3ページ目が欲しい場合はchildren(page: 3)とするように。

query {
  Nodes {
    id
    children(page: 3) {
      id
      message
    }
  }
}

ほとんどのウェブサイトにおいてクライアントが欲しい情報が1種類ではない。記事情報とユーザー情報とそのユーザーへの通知情報、となったりする。RESTfulの場合はそれぞれを

GET api/v1/users
GET api/v1/posts
GET api/v1/notifications

という感じで3回リクエストしてそれぞれの情報を集める。

GraphQLの場合は全てを1発のリクエストにして放り込める。

例えばこんな感じで、PostsとUsersとNotificationsをまとめてよこせよ、と。

query {
  Posts(page: 0) {
    id
    message
  }
  User {
    id
    name
  }
  Notification {
    id
    status
  }
}

するとこの型のまま記事とユーザーと通知の情報の入ったレスポンスがひとかたまりで得られる。クライアントからすれば欲しい時に指定した欲しい情報だけが取れる。(最初これを実装して本当にその通りにレスポンスが返ってきた時になぜが声出して笑った。)

限りなく薄いGraphQLが理想

ある記事でRailsにGraphQLを入れた場合、MVCで言うところのMVC全てがGraphQLに集約されてしまう、みたいなのを読んだ。これ明らかにおかしい。初めてGraphQLに出会った際には「これスゲー!」と興奮してなんでもGraphQLに入れ込みたい気持ちは分かるが、そんなことしろ、なんて公式サイトのどこ見ても書いてない。ファットコントローラーと同じくファットGraphQLはメンテナンス不能でたちが悪い。

GraphQLの作者Lee Byron氏も言うように「なんでもできるGraphQLだが、GraphQLはできるだけ薄く保つのがいい」と。GraphQLの責務と役割はquery(RESTfulのGET)とmutation(POSTもしくはPATCH)だけであって、それ以外は無い。したがってresolve ->(obj, args, ctx)の中にロジックがあったら、その責務はどこが持つべきか考えてそこに移すべき。

GraphQLが遅いって?それ設計の問題では

GraphQLのディスり記事にスピードに関する言及が多かった。例えば「まともにキャッシュが効かねー」とか。これは間違い。もう既に数々のキャッシュ方法がクライアント、サーバー共に提案されている。実際、前述のnode-node-nodeにおいてもキャシュを入れている。大きめのqueryでキャッシュ無しだと300msかかっているレスポンスがキャッシュで3msとかで返すことができている。そこはキャッシュ使うので当たり前なんだけど、スピードを議論するのであればキャッシュどうこうではなく、クライアントが欲しい情報を何msで取れるのか、とすべき。多少GraphQLのあるクエリが遅かったとしてもリクエストを1発でまとめて入れてるのでRESTfulで5、6回繰り返して「はいできました」となるまでにかかる時間と比較して必ずしも遅いとはならない。

N+1問題

GraphQLはN+1問題を誘発する、というディスり記事もあった。もうこれはハッキリしていてN+1問題なんて出てる時点でそれをクエリ言語のせいにするのはお門違い。確かに気付かないところでN+1を含むおそれはあるが、百歩譲ってもそれGraphQLじゃなくて、あなたの設計の問題ですから、と。

GraphQLはちゃんとハマればハッピー

本記事の冒頭でGraphQLをタイタニックの救命ボートに例えたが、既存のプロジェクトの船底に穴が空いて沈みかけてるのに船の上で上品なお食事を楽しんでいる人達みたいに気付いていないだけ、というのがよくある。熱い技術なのでGraphQLが合うかどうかぐらいは確かめた方がいいと思う。

以上がGraphQLを使ってみて得た雑感でした。


これがGraphQLで実装したプロジェクトです。よろしければぜひお試しください!
良くても悪くても叱咤激励のコメントお待ちしています。(反応無しが一番辛い。。。)

エンジニアの集合知をノードグラフで図解するSNS。
「node-node-node(ノード ノード ノード)」
 https://www.node-node-node.com/


tango-ruby.hatenablog.com
tango-ruby.hatenablog.com
tango-ruby.hatenablog.com
tango-ruby.hatenablog.com


tango-ruby.hatenablog.com