たばりばりスタイル

たばりばりスタイル

バリバリバリ⚡︎

業務委託に初チャレンジで経験した商談や成約までの流れ

3 月末でヘルステック系 Web ベンチャーを辞め、4 月から業務委託にチャレンジするので、同じように業務委託に初チャレンジするエンジニアにむけて少しはためになれればいいなというような記事です。

案件はエージェントで紹介してもらったのですが、その紹介から参画が決まるまでのはなしです。

書く理由についてですが、僕が業務委託にチャレンジする際になおとさん(turmericN)の記事にすごくお世話になったので、他のケース紹介もあると良さそうと思ったからです。

自分が知りたかったシリーズ
- 25歳初めてのフリーランスエンジニアの単価について
- フリーランスエンジニアの面談ってこんな感じ

僕の職歴

エンジニア歴 3 年
インフラ SIer (CIer) -> ヘルステック系 Web ベンチャー -> 業務委託

インフラ SIer (CIer) : 2 年

主に金融系、ゲーム系、エンタメ系の複数案件に並列で join し、インフラエンジニアとして構築・運用を担当。
主に使った技術 : AWS / Terraform / Chef

ヘルステック系 Web ベンチャー : 1 年

新規サービス開発と既存サービスの追加開発プロジェクト 2 つに join し、Web エンジニアとして、設計・開発・運用を担当。
主に使った技術 : Ruby on Rails / React.js / AWS

業務委託 : 初チャレンジ

既存サービスの追加開発を担当予定。詳細は未定。
利用技術 : Ruby on Rails / GCP / Golang

使用したエージェント

geechs job のみです。
たまたま参加したイベントから成り行きで使うことになりましたが、案件紹介コンサルタントの方が丁寧ですごく良かったです。

紹介された案件と商談結果

案件 商談結果
サブスク系 Web ベンチャー ok
HR テック系 Web ベンチャー ok
ヘルステック系 Web ベンチャー 成約ならず
機械学習系 pj の受託企業 商談せず

商談までの流れ

  1. エージェントに登録
  2. エージェントの案件コンサルタントと参画したい案件を決める
  3. エージェントが商談の日程を調整
  4. 参画したい企業と商談 (エージェントの営業担当も同行)
  5. 1 ~ 3 日くらいで商談の結果をもらう

※ 1 ~ 4 までは 2 ~ 3 週間なので、1 ヶ月くらい前に登録すれば、余裕がありそう。

商談の内容

まずはじめに企業側からサービスの紹介を受け、自分の業務経歴を紹介、そのあとに質疑応答やテストなどを行い、終了。
基本的にエージェントの営業担当が商談の進行をしてくれます。

受けた質問

テスト

  • コーディングテスト
    • 某競プロサイトでいう B 問題くらい? ※ あまり参加していないのでわからない
  • テーブル設計テスト
    • その場で、空想サービスの要件を聞いて、テーブル設計を行う (中間テーブルも合わせて 15 ~ 20 くらいのテーブル)

感想

初のチャレンジで、エージェントとのやりとりや商談、成約までの流れ全てが新鮮でした。SNS とかで参画先が見つけれないみたいな投稿もみたので不安でしたが、なんとか成約できて良かったです。

業務委託のエンジニアといえばスーパーなエンジニアを想像しがちですが、よくよく考えるとこれまでの正社員として働いていた企業で隣にいた業務委託の方がみんなスーパーかと言われると違いましたし、僕レベルのエンジニアでも案件がありそうなので、必ずしも業務委託==スーパーなエンジニアである必要はないんだなと思いました。

ただ、せっかく成約していただいたので、参画する企業には契約して良かったと思っていただけるように頑張りたいと思います。

以上です。

「オブジェクト指向設計実践ガイド」を読んだ

開発者に転向してもうすぐ 1 年になります。
これまでは雰囲気で開発していたので、Web 業界で一般的である開発手法や考え方などを学びたくなりました。
例えば、クリーンアーキテクチャドメイン駆動開発などが当てはまるのですが、これらを学ぶにもまずはベースにオブジェクト指向の知識が必要となると思っており、まずはその初歩として、「オブジェクト指向設計実践ガイド」通称 POODR 本を読むことにしました。

実は同じようなことを半年前に考え、1 度読み終わっているのですが、駆け出したばかりの開発者には時期尚早で、読んでいて身につかない感覚がありました...。
なので今回は、満を持して読んだ感じです。

感想

オブジェクト指向設計における考え方やアンチパターンリファクタリングの仕方が丁寧に書かれていて、すごくためになりました。特に継承やコンポジションの違いや、テストの観点など、実務ですぐに使えそうな知識がありがたかったです。
ただ、この一冊だけで満足できるか?と言われると、物足りない感じはありました。例えば、この本で "オブジェクト指向設計者の道具" として原則とデザインパターンを紹介しますが、デザインパターンについてはほとんど触れていないので、他の書籍に埋める必要があると感じました。
また、筆者にすべて納得!というような訳でもなく、静的型付けと動的型付けの比較における考えで、型とメソッドの定義は省く方が楽的なニュアンスについては少し違和感を感じる部分もありました。
ただ、トータルすると読んでかなり良かったと思っていますし、実務に取り入れたい考えばかりでした。

読書中に残しているメモがあるので、雑に抽出した自分用まとめを貼っておきます。

※ 解釈にズレがある場合がありますのでご注意ください。

雑なまとめ

第1章 オブジェクト指向設計

オブジェクト指向設計の考えたや原則やパターンについて触れている章。

詳細設計における筆者の考え方が印象に残った。

雑なメモは下記。

第2章 単一責任のクラスを設計する

単一責任がもたらす恩恵を色々教えてくれる章。

雑なメモは下記。

  • シンプルであれ。そして、いま求められる動作を行い、かつあとにも変更が楽なように設計しろ
  • TRUE なコードは、将来のニーズを満たす変更を加えることができる
    • (T) Transparent : 見通しが良い
    • (R) Reasonable : 合理的
    • (U) Usable : 利用性が高い
    • (E) Exemplary : 模範的
  • クラスが何をしているか定める方法は、1 文でクラスを説明してみること
    • "それと" が含まれれば、そのクラスは 2 つ以上責任持ち
    • "または" が含まれれば、クラスの責任は 2 つ以上あり、互いにあまり関連しない責任を負っている
  • メンテナンス性の高いオブジェクト指向ソフトウェアへの道のりは、単一責任のクラスから

第3章 依存関係を管理する

依存についての考え方や DI について書かれている章。

動的型付け言語と静的型付け言語について比較する部分もある。

雑なメモは下記。

  • クラスが他クラスを知るほど、あたかも一つのエンティティのように振る舞う
  • 依存を減らすとは、コードの合理性を損なう "不要" な依存を認識し、取り除くこと
  • オブジェクトは他オブジェクトについて知らない (オブジェクトの知識ではなくメッセージを信頼する) 方が賢くなる
  • 依存関係の方向性に関する決断はアプリケーションの寿命として現れる
  • 依存方向は自身より変更されないものに依存する

第4章 柔軟なインターフェースをつくる

パブリックインターフェースについて書かれている章。

ここでのパブリックインターフェースは、他のオブジェクトから使われることを意図して実装したメソッドのこと。

※ ここでのパブリックインターフェースは単なるパブリックメソッドではなく、静的型付け言語の Interface で定義されるようなメソッドを指していると思う。Ruby に Interface はないので、メッセージが定義されているであろうという信頼が Interface だと思った。つまりメッセージを渡す側が信頼しているメソッドが、ここでいうパブリックインターフェースだと思っている。

雑なメモは下記。

  • オブジェクト指向アプリケーションは、"クラスから成り立つ" が "メッセージによって定義される"
  • クラスは単一責任を果たすために存在するが、メソッド自体はいくつも実装する
  • パブリックインターフェースはクラスの責任を明確に述べる "契約書"
  • オブジェクトが存在するからメッセージを送るのではなく、メッセージを送るためにオブジェクトが存在する
    • "このクラスが必要なのは知っているけれど、これは何をすべきなんだろう" から "このメッセージを送る必要があるけれど、だれが応答すべきなんだろう" の思考に変える

第5章 ダックタイピングでコストを削減する

ダックタイピングやポリモーフィズムについて書かれている章。

動的型付けを恐れるな!というような表現が印象に残った。

用語

  • ダックタイピングは、特定のクラスとも結びつかないパブリックインターフェースのこと。
  • ポリモーフィズムは、多岐にわたるオブジェクトが同じメッセージに応答できる能力をさす。

雑なメモは下記。

  • Ruby におけるオブジェクトの振る舞いについての一連の想定は、パブリックインターフェースへの信頼で行われる
  • ダックタイプのパブリックインターフェースは、クラスをまたぐ型
  • ポリモーフィックなメソッドは "送り手の視点から見て" 入れ替え可能であることに合意する
  • ダックタイピング (抽象) に依存することで、メンテナンスコストが下がる

第6章 継承によって振る舞いを獲得する

継承の考え方やテクニックについて書かれた章。

雑なメモは下記。

  • 継承が常に成立するのに必要な2つのこと
    • モデル化しているオブジェクトが「汎化-特化の関係」の関係をもつ
    • 正しいコーディングスタイルを使っている
      • NotImplementedError を使ったテンプレートメソッドパターン
      • フックメッセージ

第7章 モジュールでロールの振る舞いを共有する

ロール (役割) の考え方を共有する方法について書かれた章。

雑なメモは下記。

  • どんなオブジェクトにも mixin できる Ruby のモジュールは、様々なクラスのオブジェクトが 1 カ所に定義されたコードを使って共通のロールを担うための完璧な方法

第8章 コンポジションでオブジェクトを組み合わせる

コンポジションや集約、委譲について書かれている章。

継承やロールとの比較がすごくためになる。

用語

  • コンポジションとは、組み合された全体が単なる部品の集合以上となるように、個別の部品を複雑な全体へ組み合わせる行為
  • 集約とは、コンポジションのようなものだが、包含される側のオブジェクトの存在が独立していることが異なる
    • コンポーズされたオブジェクトが消えても、包含されるオブジェクトは削除されない
  • デリゲーション (委譲) とは、単にメッセージを受け取り、どこかに転送すること

雑なメモは下記。

  • コンポジションにおいて、より大きいオブジェクトとその部品が「has-a」の関係で繋がる
  • コンポジションと集約の違いが、少しばかり実用的な影響をコードに及ぼす
  • 継承の方が良い解決法であるとはっきり言えないなら、コンポジションを使うべき
    • コンポジションの持つ依存は、継承が持つ依存よりもはるかに少ないため良い選択肢になりやすい
  • コンポジション、継承、振る舞いの共有はテクニックなので、適切に使うには経験と判断が必要。経験を得る方法は、自身の失敗から学ぶこと。試して失敗を受け入れ、容赦無くリファクタすること。

第9章 費用対効果の高いテストを設計する

テストの考え方、視点や各種手法について書かれた章。

用語

  • TDD とは、内から外へのアプローチしていくテストで、通常、ドメインオブジェクトのテストからはじまり、それらの新しくつくられたドメインオブジェクトをコードの隣接するレイヤーのテストで再利用していく。
  • BDD とは、外から内へのアプローチしていくテストで、アプリの境界でオブジェクトをつくり、内に入ってくる。まだ、かれていないオブジェクトを用意するために、モックが必要となる。

雑なメモはなし。ほとんど有益な情報ばかりでメモが多くなりすぎたので割愛します。

この本を読み終えて、オブジェクト指向について説明するなら...

オブジェクト指向とは?

世界をオブジェクト間のメッセージの受け渡しの連続として捉える考え方。

オブジェクト指向で正しく設計されたアプリケーションは、各種原則やパターンを守っているため、メンテナンス性が高く、将来予想される変更にも強い。またテストコードとの相性も良い。

オブジェクト指向のテクニックとして、継承やロールの共有、コンポジションなどがあり、正しく使うことで良い結果に導くが、誤った使い方をするとコストがかかる。正しく使うには経験と知識が必要で、それらを身につけるには失敗して受け入れ、容赦なくリファクタすることが必要。

オブジェクト指向の三大要素と言われる、クラスの継承、ポリモーフィズムカプセル化についてまとめると...

※ POODR 本を読んでからは、意識すべきはオブジェクト指向の三大要素ではなく、メッセージの送受信における正しい考え方や実装方法であって、三大要素はそれについてくるおまけ程度に感じています。

クラスの継承とは?

自動移譲の仕組みを使って、コードを短く書くテクニックのひとつで、クラス同士の関係が has-a の時に使う。構成する際は、抽象的な振る舞いをスーパクラスに、具象な振る舞いをサブクラスに置くように構成する

ポリモーフィズム(多様性)とは?

コードを短く書くテクニックのひとつで、応答オブジェクトが応答できる能力を指し、"送り手の視点から見て入れ替え可能" であること。

カプセル化とは?

具体化される知識を隠蔽させるテクニック。※ この本ではあまり触れていない

今後読みたい本について

いつ読み始めるかはわかりませんが、下記の本に興味があります。

まとめ

読んでよかった。

以上です。

2019年の振り返りと2020年の目標

今回は ''2019 年の振り返りと 2020 年の目標'' を書きます。

2019 年の振り返り

大きな出来事だけまとめます。

転職した

新卒で入社したインフラ系 SIer から、ヘルステック系 Web ベンチャーに転職しました。 趣味で触っていた Rails を業務で使いたいと思ったのが大きな理由でした。

転職活動は、Wantedly でスカウトが来た企業に会いにいって、よければ採用フローに入れてもらうという感じでした。 もともとスカウトをもらっている企業ということもあって、すんなり採用まで行ったような気がしました。 はじめて 10 日ほどで、3 件うけて 2 件内定をいただきました。

その中から興味のあった ''ヘルステック'' 分野の Web ベンチャーを選びました。

Web サービスの新規開発を経験した

転職後、すぐに新規プロジェクトにアサインされ、新規開発を経験しました。 要件定義をもらって、そこから API スキーマや DB テーブルの設計、実装、テストまでを自力で対応しました。 これまで趣味レベルの Rails プログラマだった僕にはなかなか歯ごたえのある経験でした。

データモデリングは本当に難しいと思いましたし、ユースケースをコードに落とし込むのにも本当に苦労しました。 ドメイン知識を理解せずに実装を初めて、後で後悔する。みたいな流れも多くありました。

ただ、結果的には遅れると予想されたスケジュールもオンで完了させ、1st リリースまでの API 実装はほとんど一人で完成させるという感じで、業務未経験にしては役にたったと思っています。

OSS へ PR を投げてみた

OSS に貢献してみたい!と思って、唐突に GolangRails に糞 PR を投げてしまいました。もちろん、どちらもボツです...

github.com

github.com

その後、Devise の機能を知るためにソースを読んだ際に見つけた不足しているテスト項目の追加 PR はマージされ、人生初コントリビュートも経験しました。 github.com

2020 年の目標

2020 年は目標は下記にしたいと思います。

  • DDD の基礎知識を説明できるくらい理解する
  • OAuth や OpenID Connect を説明できるくらい理解する
  • 業務やプライベートでお世話になっている OSS に貢献する
  • Github や Qitta、ブログなどのアウトプットを増やす

以上です。

RailsでModelになるべく自前メソッドを書かないようにしている

Rails を業務で使うようになって、数百行ある Fat なモデルの保守をすることも増えました。
Fat なモデルでは、同じようなメソッドが複数存在したり、使用されていないメソッドが存在したりなどカオスな状況が起こりやすいと思います。

行数が短いモデルが必ずしも ''正義'' だとは思いませんが、短い方がメンテが楽だと思っており、コードを書くときはなるべく行数が少なくなるように努力をしています。

今回は、モデルの行数を節約するために実践している ''Rails の標準機能を使うようにして、自前でメソッドを作らない方法'' をまとめたいと思います。

has_many で絞り込みを使う

関連オブジェクトの絞り込みをしたい場合、自前メソッドを用意するより has_many で絞る方が行数を節約できます。

# 自前メソッド例
class User < ApplicationRecord
  has_many :posts

  def recently_posts
    posts.order(created_at: :desc)
  end
end

# has_many で絞り込みを使う
class User < ApplicationRecord
  has_many :recently_posts, -> { order(created_at: :desc) }, class_name: 'Post'
end

scope を使う

関連オブジェクトやモデルのクエリを用意したい場合、自前クラスメソッドを用意するより scope を使う方が行数を節約できます。

# 自前メソッド例
class User < ApplicationRecord
  class << self
    def matches_email(email)
      where(email: email)
    end
  end
end

# scope を使う
class User < ApplicationRecord
  scope :matches_email, ->(email) { where(email: email) }
end

delegate を使う

関連オブジェクトのメソッドを利用したい場合、自前メソッドを用意するより delegate で委譲した方が行数を節約できます。

# 自前メソッド例
class Post < ApplicationRecord
  belongs_to :user

  def user_first_name
    user.first_name
  end

  def user_last_name
    user.last_name
  end
end

# delegate を使う
class Post < ApplicationRecord
  belongs_to :user

  delegate :first_name, :last_name, to: :user, prefix: true
end

composed_of を使う

年齢などの計算ロジックが必要な値を利用する場合、自前メソッドより値用のクラスを分けて composed_of を利用する方が行数を節約できます。

# 自前メソッド例
class User < ApplicationRecord
  def age
    current = Time.current.strftime('%Y%m%d').to_i
    birthed = birthed_on.strftime('%Y%m%d').to_i
    (current - birthed) / 10_000
  end
end

# composed_of を使う
class User < ApplicationRecord
  composed_of :age, mapping: [:birthed_on]
end

カスタムバリデーションクラスを使う

自前のバリデーションが必要な場合、自前メソッドを用意するよりカスタムバリデーションクラスを用意した方が行数を節約できます。

# 自前メソッド例
class Tweet < ApplicationRecord
  CONTENT_MIN_LENGTH = 1
  CONTENT_MAX_LENGTH = 140

  validate :content_cannot_violate_length_restriction

  private
  def content_cannot_violate_length_restriction
    return if self.content.blank?
    unless self.content.length >= CONTENT_MIN_LENGTH && self.content.length <= CONTENT_MAX_LENGTH
      errors.add(:content, 'Violates length restriction')
    end
  end
end

# カスタムバリデーションクラスを使う
class Tweet < ApplicationRecord
  validates_with TweetLengthValidator
end

最後に

行数が短いモデルが必ずしも ''正義'' だとは思っていないので、これらの方法がどの状況でも良い選択になるかといえば違うと思います。
ただ、「Rails の機能を使って短く書く」をチーム内で意識すれば、コードにも統一感が出てメンテの面でもいい感じになりそうだなと思っています。

以上です。

Railsのscopeを使って今月や今週で絞って取得する

Model.today や Model.this_month みたいなスコープをよく使うので備忘録で残します。

今日、今週、今月のスコープは以下のように実装しています。

# 今日
scope :today, -> { where(created_at: Time.current.all_day) }
# 今週
scope :this_week, -> { where(created_at: Time.current.all_week) }
# 今月
scope :this_month, -> { where(created_at: Time.current.all_month) }

その他に使えそうな...

# 昨日
scope :yesterday, -> { where(created_at: Time.zone.yesterday.all_day) }
# 明日
scope :tomorrow, -> { where(created_at: Time.zone.tomorrow.all_day) }

# 先週
scope :last_week, -> { where(created_at: Time.current.last_week.all_week) }
# 来週
scope :next_week, -> { where(created_at: Time.current.next_week.all_week) }

# 先月
scope :last_month, -> { where(created_at: Time.current.last_month.all_month) }
# 来月
scope :next_month, -> { where(created_at: Time.current.next_month.all_month) }

# 今年
scope :this_year, -> { where(created_at: Time.current.all_year) }
# 去年
scope :last_year, -> { where(created_at: Time.current.last_year.all_year) }
# 来年 
scope :next_year, -> { where(created_at: Time.current.next_year.all_year) }

Arel で書くなら...

# between
scope :today, -> { where(arel_table[:created_at].between(Time.current.all_day)) }
# in
scope :today, -> { where(arel_table[:created_at].in(Time.current.all_day)) }

雑談

最近 all_day の存在を知りました。
これまでは all_day の実装と同じような beginning_of_dayend_of_day を使った実装をしていました。
(Rails って本当になんでもメソッド揃って便利です😌

    # Returns a Range representing the whole day of the current date/time.
    def all_day
      beginning_of_day..end_of_day
    end

https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb#L288

以上です。

最初

はじめまして。

「SOFT SKILLS ソフトウェア開発者の人生マニュアル」 という本を読んで、 エンジニアのキャリアを続けていくのに技術ブログは必須だと思ったので開設してみました。

まずは僕のキャリアですが、新卒でインフラ SIer に入社、その後 Web ベンチャーに転職し、エンジニア 3 年目になります。 業務では Rails, Ruby, React, AWS なんかを使うことが多いです。

「手を動かすエンジニアとして働くことを第一とし、10 年後も手を動かし続けれる」を目標に日々精進していけたらと考えています。

ブログには、プライベートや仕事で学んだことなどを書いていけたらと思います。 Qiita なんかもあまり書いたことがないので、どういう風に書くは迷いそうです。

最初の記事はこんな感じかな。

以上です。