Apollo serverのSchema directivesを使ってdeprecation warningを表示する

Apollo serverでリファクタリングや仕様変更などで、特定のフィールドをdeprecatedにしたい場合があります

Apollo serverの @deprecated を使えば簡単にdeprecation warningを表示できます

では、やってみましょう

// src/index.js
const { ApolloServer, gql } = require("apollo-server");

const typeDefs = gql`
  type Author {
    name: String
  }

  type Book {
    title: String
    author: Author
    authorName: String
  }

  type Query {
    books: [Book]
  }
`;

const resolvers = {};
const server = new ApolloServer({
  typeDefs,
  mocks: true
});

server.listen(4001).then(({ url }) => {
  console.log(`🚀 Server ready at ${url}`);
});

BookのauthorNameをdeprecatedにしたいので、deprecation warningを表示したいと思います

type Book {
  title: String
  author: Author
  authorName: String
    @deprecated(
      reason: "\`authorName\` is deprecated. Use \`author\` instead."
    )
}

これだけです!超簡単!

Playgroundで確認してみましょう!

f:id:murajun1978:20200311235454p:plain

DOCSもみてみましょう

f:id:murajun1978:20200311235619p:plain

ちゃんと表示されてますね!

schemaDirectivesは自分で定義することもできるので、特定のフィールドを表示するかを認可で切り替えとかもできますね

Happy GraphQL ヘ(^o^)ノ

RailsでYAMLに定義したカスタム設定を使う

Railsで自分で定義したYAMLファイルをロードしてアプリケーションで使いたい!

ってことでやってみますー

僕がRailsでカスタム設定といえば、そうこの子です!

github.com

Latest commit 0ae134b on Aug 7, 2014

なるほど、開発やめちゃったんだねー

そう言えばこんな子もいたよ

github.com

Latest commit 9a670d4 22 days ago

うん、大丈夫そう!これを使お、、う?

ちょっと気になったことが、

僕がゴリゴリRailsでアプリ作りまくってたときは、settingslogicはみんな使ってた

なのに、更新されてない???

なんで?

そこでRails本体のconfig周りを調べてみました!

すると、、

github.com

config_for って知らない子ですねー

どうやら、Railsのrootディレクトリ/config配下にあるYAMLファイルをシュッとロードしてくれるメソッドみたいです

# config/my_settings.yml

default: &default
  setting_name: My setting

development:
  <<: *default
irb(main):001:0> Rails.application.config_for(:my_settings)
=> {:setting_name=>"My setting"}

第2引数の env のデフォルトは Rails.env なので省略可能です

環境変数を使ってみましょう!

# config/my_settings.yml

default: &default
  setting_name: <%= ENV.fetch("MY_SETTING_NAME","") %>

development:
  <<: *default
irb(main):001:0> ENV["MY_SETTING_NAME"] = "My setting name"
irb(main):002:0> Rails.application.config_for(:my_settings)
=> {:setting_name=>"My setting name"}

settingslogicやconfigなどのgemがなくても、簡単にYAMLフィアルをロードできました!

Railsガイドにもちゃんと書かれてましたー

railsguides.jp

Markdown BlogをNext.jsで作る

はてなブログに書いてるけど、興味のある技術を試す場としてブログを自分でbuildしようかと思う

Markdownで記事を書くなら、GatsbyJSとかでさくっとできそうだけど、そこはあえて自分が興味あるもので作ってみる

Next.js + MDX + TypeScript でブログを構築していく

Next.js

Installation

$ npm install next react react-dom
$ npm install -D @types/node @types/react typescript

Add Index and Blog page

// src/pages/index.tsx
import Link from 'next/link';

const Index = () => (
  <div>
    <Link href="/blog">
      <a>Blog</a>
    </Link>
  </div>
);

export default Index;
// src/pages/blog.tsx
const Blog = () => (
  <div>
    <p>Welcome to my blog</p>
  </div>
);
export default Blog;

Add npm script

# package.json
{
  ...
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  }
}

Start Next.js

$ npm run dev

これでindexページとblogページが表示できるはず

僕はVSCodeを使ってdebugしたいので ↓ inspect用のスクリプトも用意している

# package.json
{
  ...
  "scripts": {
    "dev": "next",
    "dev:inspect": "NODE_OPTIONS='--inspect=0.0.0.0' next",
    "build": "next build",
    "start": "next start"
  }
}
# .vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Docker: Next.js",
      "skipFiles": [
        "<node_internals>/**"
      ],
      "remoteRoot": "/home/app",
      "protocol": "inspector",
      "port": 9229
    }
  ]
}

MDX

最初は react-markdown + gray-matter で行こうと思ったけど、

MDX が良さそうだったので採用

MDXはMarkdownをJSXで使えちゃうし、導入も楽ちんだった!

Installation

$ npm install @next/mdx @mdx-js/loader
// next.config.js
const withMDX = require("@next/mdx")({
  extension: /\.mdx?$/
});

module.exports = withMDX({
  pageExtensions: ["ts", "tsx", "mdx"]
});
// mdx.d.ts
declare module '*.mdx' {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  let MDXComponent: (props: any) => JSX.Element;
  export default MDXComponent;
}
# tsconfig.json
{
  ...
  "include": [
    "mdx.d.ts", # 追加
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx"
  ]
}

Add Sample post

// src/posts/sample_post.mdx
export const meta = {
  title: 'Sample Post',
};

# Sample Post

## Welcome to My Blog
// src/pages/blog.tsx
import SamplePost from '../posts/sample_post.mdx';

const Blog = () => (
  <div>
    <SamplePost />
  </div>
);

export default Blog;

参考

f:id:murajun1978:20200210000411p:plain

これでmarkdownの記事を表示することができました{^^)

【現場で役立つシステム設計の原則】ドメインオブジェクトの見つけ方

現場で役立つシステム設計の原則をよみ直している

ドメインオブジェクトの見つけ方

かなり適当に言ってしまうと、会話だと思いました! (実際、そう書いてある)

この辺は僕もあやしくて、多分こんな感じーって実装してしまいます

ですが、優秀なエンジニアさんはめっちゃ聞きますw

業務でやってることや困ってることを聞いて、それを解決するアーキテクチャを決めてコードを書くって流れでしょうか

そう、いいプロダクトは会話からできると言っても過言ではないかもですねー

ま、人が使うものを人が作るわけで当たり前と言えば当たり前です

見つけ方ですが、ざっくり全体のフローを聞き取りしてから、手帳なりホワイトボードなりに書くのがよさそうです

プロジェクトチームから常に見えるところに、ドットペーパーに付箋を貼っておくのもいいかも

業務の関心ごとをヒト、モノ、コトに分類して整理する方法が紹介されています

業務を理解するときに使う図法も紹介されています

  • コンテキスト図
  • 業務フロー図
  • パッケージ図
  • クラス図

これらの図から、ドメインオブジェクトを見つけクラスにしていきます

そう、ドメインモデルは業務知識の塊なのです

なので、新たな業務が発見されると、必然的にクラスが追加され、そのクラスにはロジックが記述されます

そうして、業務知識を得ながらドメインモデルを育てていきます

もっとも大事だと感じたのは、クラス名やメソッド名ですね (ここも僕はいまいち自信がないw

業務で使っている言葉を、ドメインモデルに起こして、ロジック (処理) がメソッド名とマッチしていれば、業務知識(ドメイン)がコードに落ちている状態だと言えますね

うん、あとから参加したメンバーにもわかりやすく良さそうです

中途半端なドキュメントを保守するより、業務ドメインをコードに落とし込み、テストコードで仕様を確認できるとすばらし

【現場で役立つシステム設計の原則】データとドメインモデル

最近、現場で役立つシステム設計の原則をよみ直している

データベースにはコトを、ドメインモデルには業務ロジックを記述していく

このことを考えるとデータベースをアップデートすることは、マスターデータ以外はそうはなさそう

例えば、商品名は変更することはあるけども、購入データを変更することはない

購入したという事実をデータとして登録するだけだからね

わかりやすい例を書いてくれていた

年齢という関心事があると、年齢というクラスが必要になる

でも、データはコトなので生年月日が登録されている

Rubyだとこんな感じでしょうか

require 'date'

class Age
  def initialize(birthday)
    @birthday = DateFormatter.new(birthday)
  end

  def calculation
    difference / 10000
  end

  private

  def difference
    today.to_yyyymmdd - @birthday.to_yyyymmdd
  end

  def today
    @today ||= DateFormatter.new(Date.today)
  end
end

class DateFormatter
  FORMAT = '%Y%m%d'.freeze

  def initialize(date)
    @date = date
  end

  def to_yyyymmdd
    @date.strftime(FORMAT).to_i
  end
end

birthday = Date.new(1978, 5, 18)
age = Age.new(birthday)
puts age.calculation #=> 41

でわ、なぜドメインオブジェクトにロジックを書いたほうがいいのでしょうか?

例えば、人間とペットにはそれぞれ誕生日があります

人間クラスとペットクラスにそれぞれ年齢というロジックを実装してしまうと、同じロジックが重複してしまいます

そして、年齢計算ロジックが変更したい!とすると人間クラス、ペットクラスそれぞれを修正しないといけません

さらに、テストも重複してしまいます、、悲しいですね

そこに、ドメインモデルである年齢というクラスがあると、年齢の計算は一箇所に集約されて、テストも1つでOKですよね

担保する箇所が1つになるので、品質も向上します

そう、いいこと尽くめなのです!

コントローラやビューにロジックが書いてあるのを見つけたら、それに名前をつけてモデルに業務ロジックを移動させてみましょう

そうすると、年齢の仕様を確認するときは、年齢クラスを見ると明らかになります

明日はドメインオブジェクトの見つけ方を書いてみます

JSConfJP 2019に参加してきたヘ(^o^)ノ

JSConfJP 2019のスピーカーを見た瞬間にチケット購入したイベントに参加してきました!

jsconf.jp

チケットを買ったときに聞きたかったセッション は以下

Day 1

  • THE STATE OF JAVASCRIPT by Sacha Greif
  • BUILDING SECURE AND SEAMLESS SIGN-IN EXPERIENCE USING WEBAUTHN by えーじ
  • DEFINING OPEN SOURCE by Henry Zhu
  • BUILDING AND DEPLOYING FOR THE MODERN WEB WITH JAMSTACK by Guillermo Rauch
  • WRITE WHAT NOT HOW by Jorge Bucaran
  • DENO - A NEW WAY TO JAVASCRIPT by Kitson Kelly
  • MAKE IT DECLARATIVE WITH REACT by Toru Kobayashi
  • あとは体育館

ほぼ、予定通り聞いたけど、一つだけ予定を変更したのがある

それは、TECHNICAL SEO FOR JAVASCRIPT DEVELOPER 3つ目かな

ZEITのCEOのセッションは魅力的だけど、いまのお仕事がらSEOってワード入ってたらちょっと無視できないので、

変更して話を聞いてきた!

結果、とてもおもしろい話で、英語も聞きやすく最高だった!けど、寒かった、、

そう、JSConfJP 2019の会場は、2F体育館でこの変更したセッションは屋上だった、、

寒さを忘れるほど楽しいセッションだったけど、寒かった、、いや、まじで、、

最近、Pixel4を購入してろくに使いこなしてなかったけど、JSConfJP 2019で録音 & 文字起こしを試してみた

最初はもたつきます。推測ですが、最初は声を認識してるのかなと思います

司会の方とスピーカーがワイワイしてるときは、うーんって考えてますw

ところが、スピーカーが話し出すと、スラスラと文字に起こしていくではないですか!

しかも、制度はちょーいい感じです!

音声は取れてるので、あとで確認してみるとネイティブな英語であれば95%くらいは文字に起こせてると思います!

まじですごい!

ちなみに英語以外の文字起こしは未対応なので、アップデートを待ちましょう

1Dayのセッションを終えて思ったことは、どれもすばらしいセッションでした!

あと、話にメリハリというか、感情がこもっているほうが聞きやすかったですねー

セッションが30分という短いこともあり、みなさん早口になりがちでした

そんななか、Martin Splittさんのセッションは、言いたいことと感情(これは、、クソだ!(実際は言ってないけどそれっぽく言っての一番ウケたw

がこもっていて、ホントに英語が聞きやすかった

僕も英語のセッションとかやってみたいから、すごく参考になりました

聞いてる方も、あー、ここ嫌なんだなーとかここめっちゃ気に入ってるんだなーがわかりやすいので、自然と英語も入ってくるのかなと思いました

Day 2

予定はしてたけど、あんまり参加できなかったです (寒かった)

予定東リ午後から参加でしたw

  • PASSWORDS ARE SO 1990 by Sam Bellen
  • MIGRATION FROM REACT NATIVE TO PWA by ohbarye
  • PERFORMANCE TUNING IN EC SITE WITH GRAPHQL by 澤井宣彦
  • ANALYSIS OF AN EXPLOITED NPM PACKAGE by Jarrod Overson
  • DISCOVERING ANIMALS WITH AI AND JAVASCRIPT by Jonny Kalambay
  • PIKA: REIMAGINING THE REGISTRY by Fred K. Schott
  • あとは体育館

こんな感じです

2Daysはほんとに楽しかったけど、土日で新幹線人多い問題とか、会場寒い問題とかいろいろありました

東京は寒いですね、、

新大阪に帰ってきて、551の豚まんで温まりました

スタッフのみなさま、海外、国内からのスピーカーのみなさま、ほんとにお疲れ様でした

来年も是非参加したいと思います!温かい会場がいいです、、

Happy JavaScript ヘ(^o^)ノ

明神岳を登ってきたヘ(^o^)ノ

最近、登山いってます!

今回は明神谷ルートで、明神平 => 前山 (ルート間違いww) => 明神岳にチャレンジしてきました!

入り口はこんな感じ f:id:murajun1978:20190929092336j:plain

第1印象はけっこう激坂!

心拍数はあがりましたが、筋トレの成果もあり足は余裕でした!

だた、40分ほど登ってるとやっぱり心臓が悲鳴をあげてきます、、

それでも、Max 165でした

心拍数が振り切れなくなったのは、ジムに通っている成果なのでしょうか? (きっとそうです

休憩しながら登りきると明神平に到着

f:id:murajun1978:20190929111411j:plain

まわりに自分がいるとこより高い山があって、あんま登頂感はないですww

お昼ゴハン食べて、いざ明神岳へ!

僕が先導したのですが、ルート間違えたみたいで前山へ向かってましたw

10分ほどで制覇!w

そこから明神岳へ向かいました

明神岳 (1,432m)

途中、川を渡ったりして楽しかったなー

予報では雨だったせいか、登山者は少なめでしたねー

下りは相変わらず膝にきます、、(ダイエットせねば\

登った印象は、ひたすら登りが続く感じでした

ただ、絶壁みたいなのはないので、楽しく登れるはずです(はずです

あと、川を渡らないとダメなので、雨とかで増水してるとキビシそうですね

ちがうルートもあるみたいなので、また登ってみたいと思います

Enjoy Climbing ヘ(^o^)ノ