KitchHike Tech Blog

KitchHike Product, Design and Engineering Teams

Sketch 初心者は入れておきたいオススメのプラグイン6選

f:id:featherplain:20170607100302p:plain

こんにちは。デザイナーの羽野です。KitchHike では Web プロダクトのデザインとコーディングを担当しています。最近は React Native に手を出し始めました。Web の知識が活かせるのでなかなか楽しいです。

さて、デザインの際は Sketch を使っているのですが、恐らく知らない方はもういないんじゃないでしょうか。Sketch の便利さを語ろうとしたらそれだけでひとつ記事が書けてしまいますが、便利さのひとつにプラグインを活用した拡張性の高さが挙げられます。

というわけで、今回は Sketch を使うにあたってぜひとも入れておきたいプラグインを厳選して紹介したいと思います。必須系プラグインに的を絞ってあるので、Sketch 初心者の方はぜひ入れてみてくださいね。

Runner

http://sketchrunner.com/

Sketch はデフォルトでも便利ですが、使っていくうちにドロップダウンメニューで操作するのがだんだん億劫になってきますよね。プラグインが増えたり、階層が深くなればなるほどめんどくさいです。

そんな課題を一気に解決してくれるのが Runner というプラグインです。一言で説明すると Sketch 版 Alfred といったところでしょうか。Run + <プラグイン名> または <アクション> で プラグインを検索できたり、Sketch のメニューアクションを実行できます。もちろんプラグインのアクションもすべて Runner 上で一発です。私はもう Runner がないと仕事ができない体になってしまいました。

f:id:featherplain:20170606215028p:plain

プラグインの管理ツールとしても使える

アップデート

f:id:featherplain:20170606220149p:plain Cmd + ( 日本語キーボードの場合は Cmd + Shift + ) で Runner を立ち上げると、アップデートできるプラグインがある場合は図のように <数字>UPDATES と表示されます。これをクリックするとアップデート可能なプラグインが表示されるので、 Update All をクリックすればあとはよしなにやってくれます。

f:id:featherplain:20170606220152p:plain

インストール

プラグインの検索やインストールには install + を実行します。キーワードを入力すれば勝手にサジェストしてくれるので非常に便利です。

f:id:featherplain:20170606215118p:plain

シンボルの検索や挿入が快適

insert + でシンボルの検索と挿入ができます。シンボルのプレビューが表示されるのがありがたいですね。さらにレイヤー ( シンボル ) を選択した状態で alt + Enter すると、シンボルの置き換えができるので、いちいちドロップダウンをたどる必要もありません。

f:id:featherplain:20170606220416p:plain

Craft

https://www.invisionapp.com/craft

Craft Official from InVision on Vimeo.

言わずと知れた Craft は有名すぎて説明する必要もないかもしれません。もともとは Silver Flows という名前だったのですが、inVision に買収されて Craft として生まれ変わった経緯があります。

Craft は inVision と連携することでその真価を発揮するのですが、できることは以下です。

  • Sync: Sketch のアートボードと inVision を同期する
  • Library: アセットの共有機能
  • Data: JSON や Web 上の画像データなどを挿入できる
  • Duplicate: 要素の複製 ( Sketch デフォルトの Make Grid と同じような機能 )
  • Prototype: Sketch 上でプロトタイピングができる
  • Freehand: 文字通り、フリーハンドでメモを残せる

Rename It

https://github.com/rodi01/RenameIt

f:id:featherplain:20170606220535p:plain

Sketch で作業しているとアートボード名やレイヤー名がだんだんとカオスになってきますが、 Rename it を使えばレイヤー名の整理も一発です。GitHub の README に使い方の gif 動画がはってあるので、ぜひそちらを見て欲しいのですが、できることを簡単にまとめておくと、以下のことができます。

  • 昇順と降順の連番 ( 例: item_%n )
  • 元の名前を保持したまま新たに名前をつける ( 例: item という名前に新たに連番をつける *_%n )
  • レイヤーやアートボードの Width と Height を付与

User Flows

https://abynim.github.io/UserFlows/

f:id:featherplain:20170606220746p:plain

User Flows は Sketch 上で画面遷移図を作成できるプラグインです。if / else のような条件分岐つきのフローも作成できます。

inVision や Prott のようなプロトタイピングツールを使用していれば普段は必要ないかもしれませんが、資料として画面遷移図を提出することがある場合は重宝するでしょう。

Sketch Measure

http://utom.design/measure/

f:id:featherplain:20170606220912p:plain

Sketch Measure は Sketch 上にオブジェクトのサイズやマージンなどの情報を記載できるプラグインです。ワンクリックで簡単にデザインの指示書を作成できます。Ctrl + Shift + Bでツールバーを呼び出して使います。

Symbol Organizer

http://sketchapp.rocks/plugins/symbol-organizer/

Sketch のシンボルページに生成されたシンボルを整理できるプラグインです。Sketch のシンボル機能はとても強力ですが、プラグインを入れない状態でシンボルを作ると、ひたすら横一列に作成順に集約されてしまいます。

Before

こちらがプラグインを使わない状態です。整理しようにもちょっと収拾がつかない感じですね。

f:id:featherplain:20170606221325p:plain

After

Symbol Organizer を使ってシンボルを整理しました。Lv1/Icons/Icon といった半角スラッシュ / を活用した階層が反映された状態できれいに並び替えられました。

f:id:featherplain:20170606221309p:plain

f:id:featherplain:20170606221317p:plain

いかがでしたでしょうか。Sketch を使いこなしている人には知っているものばかりかもしれませんが、もし「知らなかった!」というものがひとつでもあれば、ぜひインストールして試してみてくださいね。プラグインを活用して素敵な Sketch ライフを送りましょう!

DHH流のルーティングで得られるメリットと、取り入れる上でのポイント

はじめに

こんにちは。KitchHikeエンジニアの小川です。KitchHikeでは主にサーバーサイドを担当しています。

少し前のものですが、「DHHはどのようにRailsのコントローラを書くのか (原文)」というすばらしい記事があります。Railsのコントローラ分割の(DHH流)ベストプラクティスについて解説した記事なのですが、私はこの記事に大変感銘を受け、KitchHikeのルーティング定義にもこのプラクティスを取り入れるようになりました。

本日はこのDHH流ルーティングを取り入れることで得られるメリット、実際の routes.rb でのルーティング定義のしかたについて紹介したいと思います。

DHH流ルーティングとは?何がうれしいの?

詳しくは元記事を是非とも読んで下さい・・・なのですが、かいつまむと、ここで示されているのはたったひとつの単純明快なルールです。

コントローラはデフォルトのCRUDアクションindex、show、new、edit、create、update、destroyのみを使うべきだということです。その他のアクションはどれも専用の(それ自体はデフォルトのCRUDアクションしか持たない)コントローラの作成につながるのです。 DHHはどのようにRailsのコントローラを書くのか

このルーティングを取り入れるとどのようなメリットがあるのでしょうか?私は大きく2点あると考えています。

1.コントローラのスリム化

重要な責務のコントローラはえてしてアクションが増えがちです。気づけばコントローラの行数が増え、肥大化を招いてしまいます。

コントローラをスリム化するRailsのベストプラクティスとしては、古からよく聞かれる「Skinny Controller, Fat Model」というものがあります。ただ、これはモデル層にビジネスロジックを寄せようというアプローチで、アクション数自体が増えてしまった場合にはあまりマッチするものではありません。

それに対し、DHH流のルーティングのアプローチは、細かくコントローラを分割するというものです。Railsのデフォルトのアクション( indexshowneweditcreateupdatedestroy )のみに制限することで、むやみにコントローラ内にアクションが増えることを防いでくれます。結果として、コントローラのスリム化につながります。

KitchHike内でもモデル層に対するアプローチ(たとえばConcernsへの分割など)は継続的に行っていましたが、こうしたコントローラ自体を分割する方法は意識していなかったので非常に新鮮でした。

2. ルーティングのルールが明解になる

コーディングルールは厳格に決まっていても、ルーティングのルールはあまり意識されていないところが実は多いのではないでしょうか?KitchHikeもそのきらいがあり、ルーティング定義は実装者の裁量まかせで、カスタムアクションにも特にルールは設けていませんでした。

カスタムアクション自体は悪いものではありませんが、ルールがないと実装者ごとのばらつきが出がちです。また、仮にルールを厳密に決めたとしても、それが複雑であれば誰もわからなくなってしまうでしょう。

それに対し、DHH流のルーティングのいいところはルールが単純で分かりやすいところです。はっきりしたルールがあれば、実装者によるばらつきは出にくくなりますし、更に開発者間でのコミュニケーションが取りやすくなります。

DHH流ルーティングのケーススタディ

さて、次はDHH流ルーティングを実際にどう取り入れるかをご紹介します。コントローラを分割するタイミングは大体以下の2パターンが多いのではないかと思います。

  • リソースにサブアクションを追加する
  • リソースをフィルタリングする

以降はこの2つのパターンをそれぞれ見ていきましょう。

ケーススタディその1. リソースのサブアクション編

ある特定のリソースに対して、CRUD以外の追加のアクションを付け加えたい場合です。 たとえば recipe のリソースに対して、公開/非公開のアクションを付け加えるとしたらどうでしょう?

カスタムアクションを追加するのであれば、コントローラは以下のようになるでしょう。

class RecipesController < ApplicationController
  def index
  end
  # デフォルトのCRUDアクションが続く

  def publish
    # 公開処理
  end

  def unpublish
    # 非公開処理
  end
end

でもDHH流に書くのであれば、ここはコントローラの分割のポイントです。

class Recipes::PublicationsController < ApplicationController
  def update
    # 公開処理
  end

  def destroy
    # 非公開処理
  end
end

recipe リソースの配下に publication という公開/非公開を担うサブアクションを追加し、 update に公開処理を、 destroy に非公開処理をマッピングしてみました。

URLは以下のイメージです。

/recipes/:id/publication

素朴に書いてみる

次はルーティングです。

素朴にルーティング定義を書いてみるとこんな感じになるのではないでしょうか。何だかうまくいきそうです。

resources :recipes do
  resource :publication, only: [:update, :destroy]
end
  recipe_publication PATCH  /recipes/:recipe_id/publication(.:format)  publications#update
                     PUT    /recipes/:recipe_id/publication(.:format)  publications#update
                     DELETE /recipes/:recipe_id/publication(.:format)  publications#destroy
             recipes GET    /recipes(.:format)                         recipes#index
                     POST   /recipes(.:format)                         recipes#create
          new_recipe GET    /recipes/new(.:format)                     recipes#new
         edit_recipe GET    /recipes/:id/edit(.:format)                recipes#edit
              recipe GET    /recipes/:id(.:format)                     recipes#show
                     PATCH  /recipes/:id(.:format)                     recipes#update
                     PUT    /recipes/:id(.:format)                     recipes#update
                     DELETE /recipes/:id(.:format)                     recipes#destroy

ダメでした。コントローラーがネストされず、 publication そのままになってしまっています。

Railsはデフォルトではネストしたリソースに対して、ネームスペースを使ってくれないのです。

namespace を使ってみる

では namespace を使ってみるとどうでしょうか。

namespace :recipes do
  resource :publication, only: [:update, :destroy]
end
resources :recipes

ルーティングを見てみると・・・。

  recipes_publication PATCH  /recipes/publication(.:format)            recipes/publications#update
                      PUT    /recipes/publication(.:format)            recipes/publications#update
                      DELETE /recipes/publication(.:format)            recipes/publications#destroy
              recipes GET    /recipes(.:format)                        recipes#index
                      POST   /recipes(.:format)                        recipes#create
           new_recipe GET    /recipes/new(.:format)                    recipes#new
          edit_recipe GET    /recipes/:id/edit(.:format)               recipes#edit
               recipe GET    /recipes/:id(.:format)                    recipes#show
                      PATCH  /recipes/:id(.:format)                    recipes#update
                      PUT    /recipes/:id(.:format)                    recipes#update
                      DELETE /recipes/:id(.:format)                    recipes#destroy

こちらも上手くいきません。 publication のアクションを行うリソースのidがどこかへ行ってしまいました。 namespace だからよく考えると当たり前ですよね・・・。

module を使おう

先の記事のコメント にもありますが、今回のケースだと module を使うのがよいです。以下のように書いてみましょう。

resources :recipes do
  resource :publication, only: [:update, :destroy], module: "recipes"
end
  recipe_publication PATCH  /recipes/:recipe_id/publication(.:format)  recipes/publications#update
                     PUT    /recipes/:recipe_id/publication(.:format)  recipes/publications#update
                     DELETE /recipes/:recipe_id/publication(.:format)  recipes/publications#destroy
             recipes GET    /recipes(.:format)                         recipes#index
                     POST   /recipes(.:format)                         recipes#create
          new_recipe GET    /recipes/new(.:format)                     recipes#new
         edit_recipe GET    /recipes/:id/edit(.:format)                recipes#edit
              recipe GET    /recipes/:id(.:format)                     recipes#show
                     PATCH  /recipes/:id(.:format)                     recipes#update
                     PUT    /recipes/:id(.:format)                     recipes#update
                     DELETE /recipes/:id(.:format)                     recipes#destroy

理想通りのルーティングになりました!

module はコントローラーの名前空間を変更したいときに使います。今回はリソース名と同じ名前を module に記述して、対応するコントローラー名をネストさせています。

ケーススタディその2. リソースのフィルタリング編

次はリソースを特定の条件でフィルタリングするケースを考えてみたいと思います。recipe を「下書き」という条件でフィルタリングしてみましょう。

コントローラは先ほどと同じく分割して書いてみました。

class Recipes::DraftsController < ApplicationController
  def index
    # 下書き一覧
  end
end

素朴に書いてみる

早速ルーティング定義を書きましょう。こんな感じでどうでしょうか。

resources :recipes do
  resources :drafts
end
      recipe_drafts GET    /recipes/:recipe_id/drafts(.:format)           drafts#index
                    POST   /recipes/:recipe_id/drafts(.:format)           drafts#create
   new_recipe_draft GET    /recipes/:recipe_id/drafts/new(.:format)       drafts#new
  edit_recipe_draft GET    /recipes/:recipe_id/drafts/:id/edit(.:format)  drafts#edit
       recipe_draft GET    /recipes/:recipe_id/drafts/:id(.:format)       drafts#show
                    PATCH  /recipes/:recipe_id/drafts/:id(.:format)       drafts#update
                    PUT    /recipes/:recipe_id/drafts/:id(.:format)       drafts#update
                    DELETE /recipes/:recipe_id/drafts/:id(.:format)       drafts#destroy
            recipes GET    /recipes(.:format)                             recipes#index
                    POST   /recipes(.:format)                             recipes#create
         new_recipe GET    /recipes/new(.:format)                         recipes#new
        edit_recipe GET    /recipes/:id/edit(.:format)                    recipes#edit
             recipe GET    /recipes/:id(.:format)                         recipes#show
                    PATCH  /recipes/:id(.:format)                         recipes#update
                    PUT    /recipes/:id(.:format)                         recipes#update
                    DELETE /recipes/:id(.:format)                         recipes#destroy

・・・リソースがネストしたルーティングになってしまいました。今回はサブリソースを表現したいわけではないので、これではダメです。

namespace を使う

また namespace を使ってみましょう。

namespace :recipes do
  resources :drafts
end
resources :recipes
      recipes_drafts GET    /recipes/drafts(.:format)                     recipes/drafts#index
                     POST   /recipes/drafts(.:format)                     recipes/drafts#create
   new_recipes_draft GET    /recipes/drafts/new(.:format)                 recipes/drafts#new
  edit_recipes_draft GET    /recipes/drafts/:id/edit(.:format)            recipes/drafts#edit
       recipes_draft GET    /recipes/drafts/:id(.:format)                 recipes/drafts#show
                     PATCH  /recipes/drafts/:id(.:format)                 recipes/drafts#update
                     PUT    /recipes/drafts/:id(.:format)                 recipes/drafts#update
                     DELETE /recipes/drafts/:id(.:format)                 recipes/drafts#destroy
             recipes GET    /recipes(.:format)                            recipes#index
                     POST   /recipes(.:format)                            recipes#create
          new_recipe GET    /recipes/new(.:format)                        recipes#new
         edit_recipe GET    /recipes/:id/edit(.:format)                   recipes#edit
              recipe GET    /recipes/:id(.:format)                        recipes#show
                     PATCH  /recipes/:id(.:format)                        recipes#update
                     PUT    /recipes/:id(.:format)                        recipes#update
                     DELETE /recipes/:id(.:format)                        recipes#destroy

思ったとおりのルーティングになりました!

が、 routes.rb がいけてないですね・・・。 recipes を書く場所が分散してしまっています。できればまとめたいところです。

さらに、上記では namespace ~resources :recipes の下に書くと、 drafts:id と見なされてルーティングエラーとなります。書き順の依存があるのは何だかもやもやします。

そもそもリソース名を変えてみる

ここで提案したいのがそもそも「リソース名を変えてみる」ということです。下書きではない、通常の recipe リソースを items で表してみるとどうでしょうか。

namespace :recipes do
  resources :items
  resources :drafts
end
       recipes_items GET    /recipes/items(.:format)                      recipes/items#index
                     POST   /recipes/items(.:format)                      recipes/items#create
    new_recipes_item GET    /recipes/items/new(.:format)                  recipes/items#new
   edit_recipes_item GET    /recipes/items/:id/edit(.:format)             recipes/items#edit
        recipes_item GET    /recipes/items/:id(.:format)                  recipes/items#show
                     PATCH  /recipes/items/:id(.:format)                  recipes/items#update
                     PUT    /recipes/items/:id(.:format)                  recipes/items#update
                     DELETE /recipes/items/:id(.:format)                  recipes/items#destroy
      recipes_drafts GET    /recipes/drafts(.:format)                     recipes/drafts#index
                     POST   /recipes/drafts(.:format)                     recipes/drafts#create
   new_recipes_draft GET    /recipes/drafts/new(.:format)                 recipes/drafts#new
  edit_recipes_draft GET    /recipes/drafts/:id/edit(.:format)            recipes/drafts#edit
       recipes_draft GET    /recipes/drafts/:id(.:format)                 recipes/drafts#show
                     PATCH  /recipes/drafts/:id(.:format)                 recipes/drafts#update
                     PUT    /recipes/drafts/:id(.:format)                 recipes/drafts#update
                     DELETE /recipes/drafts/:id(.:format)                 recipes/drafts#destroy

routes.rb も実際のルーティングもすっきりしたのではないでしょうか?

とはいえ、URLも変わってしまいますし、少々やり過ぎな気もします。先ほどの namespace 案との違いは routes.rb を綺麗に書けるかどうか、というあくまでコードだけの問題です。

フィルタリングが複雑な場合などはいいかもしれませんが、単純なものであれば namespace 案で充分だと思います。

まとめ

以上DHH流のルーティングのメリットと実際のルーティング定義についてまとめてみました。あらためて整理するとこんな感じでしょうか。

  • DHH流のルーティングは以下2つのメリットがある。
    • 多数のアクションで肥大化したコントローラのスリム化
    • ルーティングのルールが明確なのでコミュニケーションが取りやすい
  • リソースのサブアクションを表すには module を使うと便利。
  • リソースのフィルタリングを表すには namespace を使ってサブリソースを表現する方法、そもそもリソース名を変更する方法がある。

コミュニケーションが取りやすくなることが個人的にはとても重要に思います。コミュニケーションが取りやすくなることで、メンバー同士でレビューがしやすくなり、ルーティングの改善の機会に繋がりやすいからです。

DHH流ルーティングを取り入れて、一度チームメンバーの皆さんとわいわい話し合ってみてください。きっと楽しいですよ!

KitchHikeでは一緒にルーティングを考えてくれるRailsエンジニアを絶賛募集中です!

www.wantedly.com

KitchHike Tech Blog – First Post

Welcome to the KitchHike Tech Blog!

初めてブログを書いた日を覚えていますか? 個人ブログの記事を遡ってみると、ちょうど10年前の2007年ころのようだ。

2007年は、初代iPhoneがMacworld Expo 2007で発表された年で、LINEはもちろんFacebookの日本語版もまだない。
(Wikipediaによると、LINE 2011年6月公開, Facebook 日本語対応 2008年公開)

10年で世界は変わった。さらに10年後は、世界はどうなっているだろう?

未来を予測するのは難しい。ただ一つ、間違えなく言えることは、10年後も僕らは何かを食べているということだ。食はそれほど特別な普遍性を持っている。

このブログでは、KitchHikeのミッション「“食”でつながる幸せな暮らしを実現する」ためのプロダクトを開発しているメンバーが、デザイン・技術的な視点から記事を書いていきます。

2017年 元旦