JP_Stripes で LT 登壇してきました!
2019年4月26日に開催された JP_Stripes Tokyo Vol.12 に「 Billing でサブスク決済を実装してよかった話」というタイトルで LT 登壇させていただきました。
はじめに
今回の LT は、「 Billing でサブスク決済してよかった話」というタイトルで発表しました。
スライドはこちらです。
この記事は、LT で発表したことを文字で起こした記事となります。要点だけを知りたい方はスライドをご覧ください。
JP_Stripes とは?
JP_Stripes とは、オンライン決済のプラットフォームである Stripe を日本で利用するユーザのコミュニティです。
今回は東京で12回目の開催となるイベントで LT 登壇をさせていただきました。
JP_Stripes のイベント情報は、 Event Regist で公開されているようです。
発表内容「 Billing でサブスク実装してよかった話」
Billing ってなに?
一言で説明すると「 Stripe が提供している、定期支払いを簡単に実現できる API 」です。
詳しい説明は公式サイトをご覧ください。
↓
stripe.com
MVPとして始まったサブスク決済
私が所属する会社のサービスでは、サブスクを提供しています。サブスク実装当初は、 MVP ということもあり、支払い日になったらスタッフが Admin 画面から手動でサブスク継続処理を実行していました。
軌道に乗りはじめ、スタッフから嬉しい悲鳴が...
サブスク機能をリリースしてから、嬉しいことに契約者が増えていきました!
しかし、サブスク契約者が増えるのに比例して、スタッフが手動でサブスク継続処理を実行する手間も増えていきました。
その結果、スタッフから サブスク決済の自動化 や 管理画面のバージョンアップ を求める声があがります。
スタッフの要望に対応するコストの高さ
1. サブスク決済自動化
当時は Stripe ではない他のオンライン決済サービスを使用していました。
そのオンライン決済サービスには、サブスクのサービスが提供されていなかったため、サブスク自動決済機能を実装しようとすると、全て自前で用意する必要がありました。
そのため、対応するコストが非常に高く、判断に迷っていました。
2. 管理画面のバージョンアップ
また一方で、サブスク契約者が増えてきたので、サブスク契約者の予約状況なども管理画面に表示してほしいといった要望も上がりました。
ひとつひとつの要望への対応コストはそこまで高くありませんが、今後要望があがるたびに機能追加していくとなると、メンテナンスコストが高まります。
悩めるエンジニアに決済サービスクローズの追い打ち
スタッフの要望にどう対応しようか悩んでいたある日、当時利用していた決済サービスがクローズするというアナウンスがありました。まさに追い打ち。。
サブスクの自動化や管理画面のバージョンアップ以前に、迅速に他の決済サービスに移行しなければならない という状況になってしまいました。
Stripe との出会いでピンチがチャンスに!
様々なオンライン決済サービスを調査してみたところ、 Stripe を導入すれば悩みの種となっていたサブスク周りの課題も一緒に解決しそうなことがわかり、移行が行われました。
1. サブスク決済自動化
Stripe には Billing というサブスク機能を簡単に実装できる API が提供されているため、 サブスク自動決済機能を自前で用意する必要がなくなりました。
2. 管理画面のバージョンアップ
Stripe には高機能な管理画面がすでに準備されているため、 管理画面も自前で用意する必要がなくなりました 。そのおかけで、将来かかったであろう管理画面のメンテナンスコストも実質なくなったことになります。
Stripe と出会ったおかげで、オンライン決済サービスのクローズというピンチを乗り越えただけでなく、これまでの悩みまで解決してしまいました!
まとめ
オンライン決済サービスとして Stripe を導入し、 Billing というサービスを利用したことで サブスク自動決済機能 を自前で用意しなくてよくなっただけでなく、 サブスク契約者の管理画面 も自前で用意してメンテナンスしていく必要もなくなりました。
自前で用意するものがなくなったおかげで、 自分たちのサービスのコアとなる部分の機能開発によりいっそう時間をさけるようになった ということが Stripe の Billing を導入してよかったと思えることです。
Stripe に移行したときのより詳しい話
Stripe に移行したときのより詳しい話については、私が所属するチームのリーダーが記事にまとめていますので、そちらをご覧ください。
10月13日の日記
今日の学び
わからなかった単語
ポインタ
変数の一種で、あるオブジェクトの論理的位置情報を格納する変数のこと
参考にしたサイト
リンク
ある構造体のメンバに別のメンバの構造体にアクセスするためのポイントを格納することで、構造体をつなぐことを リンク という。
参考にしたサイト
コレクション
データやオブジェクトなどをまとめて格納するためのデータ構造やクラスなどの総称
配列やハッシュ、スタック、キューもコレクションの例である
参考にしたサイト
10月9日の日記
今日の学び
私の苦手なもの「読解・要約」
今日の学びというと嘘になってしまいますが、週末(10月7・8日)に自分を振り返り、今の私には「読解力・要約力」が足りないと感じました。
相手の伝えたいことをしっかりと理解することが小学生の頃から苦手で、今に至るまで逃げて生きてきました。(今思えば国語の点数はずーーっと悪いままでした)
文字を読むのも苦手ですし、人の話を聞いて「つまり、〜〜〜ということ」と要約するのが苦手です。いつも途中で何について書いているのか、話しているのかわからなくなります。
それが原因で学びの効率も悪くなっている ような気がします。なぜなら、文章を読んで理解するのは苦手だったり、人の話を聞いてまとめることが苦手だったりするからです。
まずは文字アレルギーの克服から!
私は文字と向き合うことから、ほとんど逃げてきました。本も指で数えるほどしか読んだことがありません。(ちょっといいすぎかもw)
しかし、このままでは学べるものも学べず、成長スピードが遅いままです。まずは「文字アレルギー」を克服し、「読解力・要約力」を伸ばして、成長スピードを向上させようと思います!
そこで、先週末に6つの小説を購入しました。いきなり純文学など難しそうな本に挑戦すると、あっという間に挫折しそうだったので、まずはライトな小説から挑戦しようと思いました。
ちなみに私が購入した小説はこちらです。
- 作者: 住野よる
- 出版社/メーカー: 双葉社
- 発売日: 2017/04/27
- メディア: 文庫
- この商品を含むブログ (21件) を見る
- 作者: 住野よる
- 出版社/メーカー: 双葉社
- 発売日: 2018/07/12
- メディア: 文庫
- この商品を含むブログを見る
スマホを落としただけなのに (宝島社文庫 『このミス』大賞シリーズ)
- 作者: 志駕晃
- 出版社/メーカー: 宝島社
- 発売日: 2017/04/06
- メディア: 文庫
- この商品を含むブログ (2件) を見る
- 作者: 村田沙耶香
- 出版社/メーカー: 文藝春秋
- 発売日: 2018/09/04
- メディア: 文庫
- この商品を含むブログ (5件) を見る
ビブリア古書堂の事件手帖 ~扉子と不思議な客人たち~ (メディアワークス文庫)
- 作者: 三上延
- 出版社/メーカー: KADOKAWA
- 発売日: 2018/09/22
- メディア: 文庫
- この商品を含むブログ (4件) を見る
- 作者: 池井戸潤
- 出版社/メーカー: 集英社
- 発売日: 2016/02/19
- メディア: 文庫
- この商品を含むブログ (10件) を見る
10月6日の日記
今日の学び
リファクタリング: Rubyエディション
Self Encapsulate Field
フィールドとの密結合により、フィールドへの直接アクセスが不都合になっているとき、アクセサを使って関節アクセスするようにする
# リファクタリング前 def salary @base_salary * @bonus_rate end # リファクタリング後 attr_reader :base_salary, :bonus_rate def salary base_salary * bonus_rate end
スーパークラスはフィールドに直接アクセスしているが、サブクラスでは計算した値を返すためにフィールドへのアクセスをオーバーライドしたくなったときが絶好のタイミング
class Employee attr_accessor :base_salary, :bonus_rate def initialize(base_salary, bonus_rate) @base_salary = base_salary @bonus_rate = bonus_rate end def salary base_salary * (1 + bonus_rate) end end class Manager < Employee attr_reader :position_allowance def initialize(base_salary, bonus_rate, position_allowance) super(base_salary, bonus_rate) @position_allowance = position_allowance end def total super + position_allowance end end
大事なのは、リファクタリングによって直接変数アクセスも関節変数アクセスにも切り替えることができること。
Change Value to Reference
同値のインスタンスをいくつも生成するクラスがあり、それらのオブジェクトを同じものと判断したいとき、そのオブジェクトを参照オブジェクトに変更する
# リファクタリング前 class Guest attr_reader :name def initialize(name) @name = name end end guest1 = Guest.new("Bob") guest2 = Guest.new("Ken") guest1 == guest2 # => false # リファクタリング後 class Guest attr_reader :name def initialize(name) @name = name end Instances ={} def self.load_guests new("Bob").store end def store Instances[name] = self end def self.create(name) Instances[name] end end Guest.load_guests guest1 = Guest.create("Bob") guest2 = Guest.create("Bob") guest1 == guest2 # => true
オブジェクト導入時は、イミュータブルな値を持つ単純な値オブジェクトという位置付けだったけれども、後で変更可能なデータが追加したり、概念的に同じオブジェクトを参照する部分に変更による効果を与えたくなる場合がある。
そういった場合に上記のように、ファクトリメソッドを定義し、オブジェクトの作成処理を管理するようにして実装する必要がある。
つまりは、単純な値オブジェクトから参照オブジェクトに変更しなければならないということである。
Change Reference to Value
イミュータブルな参照オブジェクトの管理が面倒になってきたとき、オブジェクトを値オブジェクトに変更するテクニック
# リファクタリング前 class CurrencyRate attr_reader :code def initialize(code) @code = code end def self.get(code) ...レジストリから CurrencyRate インスタンスを返す end end jpy1 = CurrencyRate.get("JPY") jpy2 = CurrencyRate.get("JPY") jpy1 == jpy2 CurrencyRate.new("JPY") == CurrencyRate.new("JPY") # => false CurrencyRate.new("JPY").eql?(CurrencyRate.new("JPY")) # => false # リファクタリング後 class CurrencyRate attr_reader :code def initialize(code) @code = code end def self.get(code) ...レジストリから CurrencyRate インスタンスを返す end def eql?(other) self == (other) end def ==(other) other.equal?(self) || (other.instance_of?(self.class) && other.code == code) end end jpy1 = CurrencyRate.get("JPY") jpy2 = CurrencyRate.get("JPY") jpy1 == jpy2 CurrencyRate.new("JPY") == CurrencyRate.new("JPY") # => true CurrencyRate.new("JPY").eql?(CurrencyRate.new("JPY")) # => true
Change Value to Reference とは全く逆のことをしている。
イミュータブルな参照オブジェクトの管理が面倒になってきた時に、オブジェクトを値オブジェクトに変更することで、管理コストを下げることができる。
しかし、そのためには eql? メソッドと == メソッドをオーバライドする必要があるので、注意が必要。
調べたこと
値オブジェクト
以下のような特徴を持ったオブジェクトを「値オブジェクト」という
- インスタンス自体よりも、保持するデータ値が重要な意味をもつ。
- インスタンスが異なっても、同じ値を保持していれば同じオブジェクトとみなす。
- 必要に応じて自由にコピーを作ることができる。
- 原則としてイミュータブルでなければならない。
参照オブジェクト
以下のような特徴を持ったオブジェクトを「参照オブジェクト」という
10月3日の日記
今日の学び
リファクタリング: Rubyエディション
第7章は オブジェクト間でのメンバの移動 をテーマに、リファクタリングのテクニックがまとめられている。
全部で6つのテクニックが紹介されている。
- Move Method
- Move Field
- Extract Class
- Inline Class
- Hide Delegate
- Remove Middle Man
Move Field
要約
フィールドが、他クラスでよく使われていたら、最もよく使われているクラスにフィールドを移動する
例
# リファクタリング前 class Employee def initialize(bonus_rate) @bonus_rate = bonus_rate end def bonus @bonus_rate * base_salary end end # リファクタリング後 class Employee def initialize(employee_type) @employee_type = employee_type end def bonus(base_salary) @employee_type.bonus_rate * base_salary end end class EmployeeType attr_accessor :bonus_rate def initialize(bonus_rate) @bonus_rate = bonus_rate end end
※ 注意: 上記サンプルは、 bonus_rate フィールドが Account クラスではなく AccountType クラスでよく使われるようになることが前提となっている
説明
- フィールドは最もよく使われているクラスに定義する
備考
- 以前までは正しかった実装が、今では誤った実装になりうる
- 仕様が変われば、リファクタリングで実装し直せばいいだけ
- 問題は誤った実装のまま、何も対策を打たないこと
所感
フィールドは最もよく使われているクラスに定義することで、コード量が減ることを実感。
コード量が少なくなれば、それだけ人間が読むコードの量も減るし、結果的に効率的な開発に繋がるのだろうと思った。
調べたところ
ここでいうフィールドとは?
クラス内のインスタンス変数のことを差すようだった
アクセサ
クラス内にインスタンス変数を定義するだけでは、そのクラスのインスタンスから定義したインスタンス変数にアクセスできない
class Person def initialize(name) @name = name end end person = Person.new("Bob") person.name # => NoMethodError: undefined method `name' for #<Person:0x00007fd0faaf99e8 @name="Bob">
上記のインスタンス変数にアクセスするためには、以下のようなゲッターとセッターを実装する必要がある
class Person def initialize(name) @name = name end # ↓ これがゲッター def name @name end # ↓ これがセッター def name=(val) @name = val end end person = Person.new("Bob") person.name # => "Bob" person.name = "John" person.name # => "John"
Ruby には attr_reader
・ attr_writer
・ attr_accessor
といったアクセスメソッドが用意されていて、ゲッターとセッターを簡単に実装できる
定義式 | 機能 |
---|---|
attr_reader: 変数名 | 参照が可能 |
attr_writer :変数名 | 更新が可能 |
attr_accessor :変数名 | 参照と更新が可能 |
class Person attr_accessor :name def initialize(name) @name = name end end person = Person.new("Bob") person.name # => "Bob" person.name = "John" person.name # => "John"
10月1日の日記
今日の学び
リファクタリング: Rubyエディション
第7章は オブジェクト間でのメンバの移動 をテーマに、リファクタリングのテクニックがまとめられている。
全部で6つのテクニックが紹介されている。
- Move Method
- Move Field
- Extract Class
- Inline Class
- Hide Delegate
- Remove Middle Man
Move Method
要約
メソッドが、他クラスの機能を多く使っていたり、他クラスに何度も利用されたりしていたら、最もよく使われているクラスにメソッドを移動する
例
# リファクタリング前 class Employee def base_salary if @employee_type.manager? return 200000 else return 100000 end end end # リファクタリング後 class EmployeeType def base_salary if manager? return 200000 else return 100000 end end end
説明
- メソッドは最もよく使われているクラスに定義する
- 他クラスを参照しなくて済むので、コードが少なくなる
- 他クラスの実装を見に行かなくてよくなる
備考
- リファクタリングをしたら、必ずテストを実行する
所感
メソッドは、最もよく使われているクラスに定義するということを、恥かしながら最近知った。
しっかり考えればわかることではあるが、他クラスのオブジェクトを参照しなくてもよくなるし、他クラスの実装も見に行ったりしなくてよくなる。結果的に効率よくコードがかけるようになるなと実感した。
また Ruby はインタープリタ言語であり、リファクタリング後にコンパイルによってミスをキャッチできない。だからこそ、テストが重要であるということに深く納得した。
タスクを効率よく進めるために改めようと思った3つの考え方
背景
私はタスクの進捗が遅いことに課題を感じていて、それを解決するために我流でどうにかしようとしていました。
しかし、それだと効率も悪く、なかなか根本的な解決に繋がらないことを実感していたので、他の方の知恵を借りようと本を読むことにしました。
テーマが似た本を3冊を読んだところ、仕事が遅い人の特徴で共通して挙げられているものがいくつかありました。
私自身思い当たる節があったので、今の私の考え方で改めるべきだと感じたものついてまとめてみました。
読んだ本
今回参考にさせていただいた本は以下の3冊です。
「仕事が速い人」と「仕事が遅い人」の習慣 (アスカビジネス)
- 作者: 山本憲明
- 出版社/メーカー: 明日香出版社
- 発売日: 2013/10/19
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (4件) を見る
- 作者: 塚本亮
- 出版社/メーカー: 明日香出版社
- 発売日: 2017/01/16
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る
- 作者: 古川武士
- 出版社/メーカー: ディスカヴァー・トゥエンティワン
- 発売日: 2017/05/27
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
ひとつのことに集中する
課題となる考え方
1つ目は、 複数のことを一度にこなそうという考え方 です。
私は目の前のタスクに、なかなか集中することができません。
なぜなら目の前のタスク以外のこと(調査や雑務など)もこなそうと、様々なことに気を取られてしまうからです。例えば、以下のようなことです。
- Slack に調査が必要な要件が流れてくると気を取られてしまう
- 社内で困っている内容の話を耳にすると一緒に解決しようとしてしまう
- 自分より先輩のメンバーに雑務をさせまいと常に周りを見てしまっている
具体的な解決方法
シングルタスク
集中をするには、シングルタスクを行うとよいそうです。
シングルタスクとは、 一度にひとつの作業に集中すること を指し、生産性をあげることを目的としています。
複数のタスクを一度に進めようとすると、タスク・スイッチングで空白の時間が発生してしまい、一説によると生産性を 40% も下げてしまうとのことでした。
シングルタスクに関する本も出ていたので、せひご覧ください。
SINGLE TASK 一点集中術――「シングルタスクの原則」ですべての成果が最大になる
- 作者: デボラ・ザック,栗木さつき
- 出版社/メーカー: ダイヤモンド社
- 発売日: 2017/08/31
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
誘惑を遮断する
もうひとつは、気を取られそうな誘惑を物理的に遮断することです。
誘惑と戦おうとするとそれだけでパワーを使いますし、戦った時点で目の前のタスクに100%集中できているとは言えません。
誘惑と戦うよりも誘惑から物理的に遮断する方が効率的です。例えば、
- 目の前のタスクが終わるまで Slack を閉じる
- 集中できる音楽を聞いて、雑音を遮断する
- 他のメンバーの動きが目に入らない環境で仕事をする
といったことを習慣にすると良いかもしれないですね。
仕事の時間は有限であると意識する
課題となる考え方
2つ目は、 寝なければいくらでも時間はあるという考え方 です。
私はあまり寝なくても頑張って働ける体質(だと思っていた)なので、時間はいくらでもあると考えてしまっていました。
そのせいか明確な時間制限を設けずにタスクに取り組んでしまい、結果的にだらだらとタスクに取り組んでいました。
具体的な解決方法
制限時間を設けてタスクに取り組む
時間制限を設けてタスクに取り組むことで、半ば強制的に集中を余儀なくされます。
時間の強制力をうまく活用して、瞬発力を引き出すことが大切です。
プライベートを充実させる
プライベートな時間にやりたいことがあれば、定時までに仕事を終わらせようという力がはたらきます。
プライベートが充実していればいるほど、その力も大きくなります。
まずは没頭できる趣味などを見つけることが良いのかもしれませんね!
体と脳のコンディションを意識する
課題となる考え方
3つ目は、 体や脳のコンディションが悪くても、気合いと体力でカバーするという考え方 です。
睡眠時間が少ないと、頭の中に霧が張っているような感覚になって集中ができないとわかっているのに、それは甘えだと長時間労働でカバーしていました。
これだといつまでたっても、タスクを効率よくこなせないですよね。負のスパイラルです。
具体的な解決方法
脳の性質に合わせて取り組むタスクを変える
人間は朝起きてから2, 3時間あたりでもっとも効率的に脳が動くようなので、その時間帯に合わせて重要な課題やクリエイティブな仕事に取り組むと良いそうです。
逆に夜は脳も体も疲れ切っているので、単純作業をするのに適しているとのことでした。
脳の性質に合わせて取り組むタスクを変えると効率的に仕事が進められそうですね。
戦略的に睡眠をとる
遅く起床してしまい、もっとも効率的に脳が動くタイミングが、お昼ご飯の時間と重なってしまっては勿体無いですよね。
何時に就寝すれば良いかを逆算する必要があります。
また人間は基本的に睡眠時間が6時間未満になると、意志力が低下し、誘惑に負ける可能性を高めてしまうそうです。
つまり、効率よくタスクをこなすには、戦略的に睡眠をとるべきだということでした。
まとめ
上記の3つに共通するのは、 仕組みを作って頑張らずに課題を解決する というアプローチの仕方ではないでしょうか。
私はこれまでの人生、多くの課題を根性で乗り切ってきたので、根本的に考え方を変える良いきっかけになりました。
もし私と同じようなことで悩んでいる方がいましたら、今回紹介した3冊の本を読んでみてください。
私と同様に今までの悩みや問題が解決できるきっかけになるかもしれません。