行動すれば次の現実

ほどよくモダンなシステム開発を目指しています。メインテーマは生産性、Ruby、Javascriptです。

それでも自社サービスを開発する理由

個人法人問わず、独立したエンジニアであれば、一度は自社サービスの立ち上げを検討したのではないでしょうか。

弊社も今まで何度か自社サービスの立ち上げを行ってきました。 自社サービスはマネタイズするまでに時間が掛かることがほとんどです。

一朝一夕で出来るようなことでは有りませんので、かなり根気のいる仕事であり、長い目で見ていく必要があります。

それでも私は「独立したのならば自社サービスを開発すべき」だと考えます。なぜそう思うのかについて持論を展開していこうと思います。

目に見えるポートフォリオとしての役割

ビジネスマッチングサイト等を利用して開発案件を獲得する際は、必ずと言っていいほど実績(ポートフォリオ)を提示するよう求められます。

しかし、SESや業務委託契約の案件ばかりやっていると、実績を目に見える形で証明できないことがほとんどです。

例えば「私がこのサービスを作りました!」と言ったとしても、サービスの運営会社は別に存在するので「本当にあなたが作ったのか?」「何人もいる開発者の内の一人なんじゃないか?」と勘ぐられ、説得力や信憑性に欠けてしまうこともあります。

また、NDAでサービス名を明かしては行けないという契約の場合も有り、「某プロジェクトの某システム」というように曖昧な実績を提示することになります。

しかし、自社サービスがあればそのようなことはなくなります。気兼ね無くポートフォリオとして実績を提示することができます。 また、自社サービスがあれば企業のブランディングとしての効果もあります。広報やメディア取材の対象にもなる可能性もありますので、自社の広告塔としての役割も担うことも期待できます。収益化まで時間が掛かるとしても、ブランディングとしての効果もありますので決して無駄にはならないと私は考えます。

収益の分散化としての備え

業務委託やSESの場合、基本的には満期日を迎えると契約はそこで終了しますので、収益が途絶えてしまいます。継続的な収益を得るためには業務委託契約を続けるほかありません。

受託開発の場合も納品して終わりというケースがほとんどです。保守契約で継続するといこともありますが、必ずとは言えません。

自社サービスの場合は、利用してもらい続ければ右肩上がりで収益を上げることができます。 新規顧客の開発と既存顧客フォロー(カスタマーサクセス)のサイクルを実施することで、解約率が低い状態を維持できれば基本的にはサービス利用者は伸び続けます。

自社サービスが軌道に乗るまでは、業務委託や受託等で食いつなぎながら、余剰金を使って自社サービスを育てていくことで、最終的には収益を分散化することが可能になります。

新しいテクノロジーの実験場所として

業務委託では使用するプログラミング言語やフレームワークは基本的に縛りがあるので、新しい技術を取り入れたいとしても簡単にはいきません。これは自己成長の機会を逃していると捉えることもできます。

受託でもやはりスピード重視になりますので、あえて不慣れな新しい技術を導入しようとはならないことがほとんどです。

自社サービスの場合は、完全に自社の独断で納期をコントロールできますので、あえて新しい技術を取り入れるという選択も可能になります。 新しいをテクノロジーを試験に取り入れられる実験場として絶好の場であると私は考えます。

また、自社サービスを売り込むためにはWebマーケティング知識も必要ですので、マーケティング関連の知識習得もでき、自己成長につながるという副次的な効果も期待できます。

Rails7+esbuild+TypeScriptで開発環境を構築する

Rails7のフロントエンド開発環境としてjsbundlingのesbuildを採用した際にTypeScriptの導入に少し手こずりましたので備忘録として記事にしました。参考になれば幸いです。

esbuildではTypeScriptの型チェックは行ってくれない

esbuildはデフォルトでTypeScriptのコンパイルをサポートしています。

そのため、特段何かインストールしたりや設定する必要はありません。 ただしサポートしているのはコンパイルのみで、型チェックまでは行ってくれません。そのため別途tsc -noEmit等のコマンドを並行して実行する必要があります。

それを踏まえると以下のようなnpm scriptsになるかと思います。

package.json(抜粋)

"scripts": {
    "build:js": "esbuild ./app/javascript/application.ts --bundle --sourcemap --outdir=app/assets/builds",
    "build:css": "sass ./app/assets/stylesheets/application.bootstrap.scss ./app/assets/builds/application.css --no-source-map --load-path=node_modules",
    "type-check": "tsc -w --noEmit"
}

これでも良いのですが、build:jsとtype-checkがそれぞれ別で動いてしまいますので、型チェック(type-check)が通ったらコンパイル(build:js)を実行するようなことができません。

そのため今回はtsc-watchという型チェックの監視プロセスの結果によって挙動を制御するnpmパッケージがありましたので、それを使用します。

 yarn add -D tsc-watch

tsc-watchをインストールしましたら、package.jsonとProcfile.devを以下のように書き換えます。

package.json(抜粋)

"scripts": {
  "build:js": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds",
  "build:css": "tailwindcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/tailwind.css",
  "failure:js": "rm ./app/assets/builds/application.js && rm ./app/assets/builds/application.js.map",
  "dev:js": "tsc-watch --noClear -p tsconfig.json --onSuccess \"yarn build:js\" --onFailure \"yarn failure:js\""
}

また、Procfile.devでのjsコマンドもyarn dev:jsに変更します。

Procfile.dev

web: bin/rails server -b 0.0.0.0 -p 3000
js: yarn dev:js
css: yarn build:css --watch

このようにすることでTypeScriptの型チェックが成功すればコンパイルを実行し、失敗すれば前回のコンパイルファイルを削除させるような分岐をすることができます。

ちなみに、tsc-watchは内部的にtscコマンドを使用していますので、開発環境にTypeScriptがインストールされていない状態だとcannot find module 'typescript/bin/tsc'というエラーが出てしまいます。そのため、別途TypeScriptをインストールする必要がありますのでご注意ください。

 yarn add -D typescript

参考

https://esbuild.github.io/content-types/#typescript

現場主義の企業がどのようにDX化を進めていけばよいか

コロナ禍によって企業のDX化(デジタル・トランスフォーメーション)推進の動きが加速しております。 弊社でも今までシステム導入を見送っていた企業のシステム開発を請け負う機会が多くなりました。

DX化の案件を進めていく上で、どのようにDX化を進めていけばよいのかというのは永遠の課題だと思います。 今回は現場主義の企業がどのようにDX化を進めていけばよいのか弊社のナレッジを含めて考えを展開したいと思います。

エクセル管理の限界がDX化のサイン

DX化されていない企業の多くはエクセルを使用して日々の業務を管理しているケースがとても多いです。

簡易なエクセルマクロで業務の補助ツールとして利用している企業もあれば、コアなデータをシートに貼り付けて、そのデータを自動的に計算するような作り込みがされている職人芸のようなエクセルマクロを作って作業の効率化を図っている企業もあります。

エクセルマクロはシステマチックなことも実装できますので、非エンジニアであってもプログラミング思考を持っていれば複雑で高機能なツールを作ることが可能です。

ただし、このような高機能なエクセルマクロは作りが複雑であるがゆえに、特定の担当者でなければ修正できない状態(属人化)してしまったり、一つの修正により他の箇所が連鎖的に壊れてしまったりと様々な問題が生じてきます。

このような状態になることは考え方によっては、DX化を進める上でのサインであると捉えることもできます。 ツールで扱おうとする業務範囲が拡大し、エクセルのような簡易システムで管理できる範疇を超えてしまった状態です。

エクセル管理での限界を感じ始めたら、それがDX化を考えるスタートラインです。 まずはどのような解決策があるのか、インターネットや他企業から情報収集から始めるのが良いでしょう。

いきなり100%を目指すのではなく、1歩ずつDX化を進める

DX化する上で重要な考え方があります。

それはマネジメント層と現場スタッフとではDXに対する考え方が全く異なるという点です。 マネジメント層はすぐにでもDX化を推し進めようと考えますが、現場スタッフはそれに対して反発する傾向が強いように感じます。

人間というのは変化を恐れて現状維持のバイアスがかかります。現場スタッフもそれは例外では有りません。

日々ルーチンワークとしてある居心地良く回している業務が、新たなシステムの導入により抜本的に変化してしまうと、スタッフにとって大きなストレス要因となります。 また、一時的に作業効率が大きく落ちたり、新しいシステムの操作を覚えるためにスタッフへの負荷が高まり、他作業に影響が派生してしまうことも少なくありません。

DX化が重要だとは分かっていても最初からそれを理解していくれるスタッフは多くはありません。

そのため、いきなり0から100へのDX化を進めるではなく、0から1を目指すように、まずは一部の業務から移行したり、一部のスタッフから導入を促してシステムに慣れてもらうような考慮が大切になります。

PCやインターネットに対して苦手意識が低いスタッフや、比較的年齢層の若いスタッフを中心に広めていくと良いかと思います。

良いシステムであれば、使い慣れ始めると必ず賛同してくれます。賛同者が増えれば、また新しいスタッフへ伝播してくれる役割にもなりますので、ゆっくりでも1歩ずつ確実に浸透させていく心掛けが重要です。

Railsを5.2から6.0にバージョンアップする方法

この記事では、Railsをバージョンアップ(アップグレード)する方法を説明します。 バージョン5.2から6.0にアップグレードする手順を例にとって説明しています。

テストや確認の工程などは省き、なるべくシンプルな内容にしています。

Gemを最新状態にアップグレードする

Railsのアップグレードの前に、使用しているGemを最新状態にアップグレードしておきます。 こうすることによりアップグレード作業がスムーズになります。

bundle update

Railsのバージョンを上げる

Gemfileに記載されているRailsのバージョンを書き換えます。

gem 'rails', '~> 5.2.0'
  ↓
gem 'rails', '~> 6.0.0'

その後、Rails本体および関連Gemを含めアップグレードを実行します。

bundle update

rails app:updateタスクを実行する

bundle updateが正常に完了したら、下記のコマンドを実行します。

rails app:update

対話形式で設定ファイルを上書きするかどうか聞かれますので、ひとまず全てYで上書きします。

上書きが完了したら、ファイルの差分を一つずつチェックします。旧ファイルで必要な設定を適宜反映させて設定ファイルの内容を確定させます。

なお、Rails6.0にアップグレードする場合は、新たにmigrationファイルも生成されますので、rails db:migrateタスクも実行する必要があります。

rails db:migrete

古いバージョンとの差分を確認する

この状態で一旦railsを起動させて、動作確認をします。

動作確認に問題なければapplication.rbの以下の項目を変更します。

config.load_defaults 5.2
  ↓
config.load_defaults 6.0

また、新たに作成されたnew_framework_defaults_6_0.rbというファイルも不要ですので削除します。

最終確認

上記書き換え後に再度動作確認をします。問題なければアップグレード作業はこれで完了になります。

当記事では最低限の作業のみ記載しておりますが、RSpecで問題なくテストがパスするか、DEPRECATIONメッセージが出力されていないか、ステージング環境で問題なく動作するか等の作業が発生します。

また、バージョンによっては独自の作業が必要な場合もありますので、必ずRails アップグレードガイド等の内容もチェックすることをオススメします。

React+Reduxのアクション名のコンフリクトを避ける方法

React+Reduxのパターンで開発しているとアクション名の衝突を避けるために管理が煩雑になってきます。

例えば、ある機能でINCREMENTというアクション名をすでに使用している場合、他の機能で同じような振る舞いのアクションを定義する場合はINCREMENTという命名を避けなければなりません。

これは、アクション名が衝突するとそれぞれに定義されたreducerが発火してしまい意図しない動作を引き起こしてしまうためです。

そのため、XXX/INCREMENTZZZ/INCREMENTのように機能ごとのprefixをつけてアクション名の衝突を避ける工夫が必要になります。

redux-actionsを使ってアクション名の衝突を避ける方法

アクションの定義にはredux-actionsというライブラリを使用しているケースが多いかと思います。

redux-actionsを使用することで上記のようなアクション名の衝突を避けるような命名をすることが出来ます。

const { increment, decrement } = createActions(
  'INCREMENT', 
  'DECREMENT', 
  { prefix: 'XXX' },
);

createActionsのオプションにprefixを設定することで、アクション名がXXX/INCREMENTXXX/DECREMENTという命名に変更されます。

同様にreducer側で使用するhandleActionsメソッドにおいてもprefixを指定する必要があります。

export default handleActions({
  [actionTypes.INCREMENT]: (prevState, action) => {
    return {
      ...prevState,
      count: count + 1,
    };
  },
  [actionTypes.DECREMENT]: (prevState, action) => {
    return {
      ...prevState,
      count: count - 1,
    };
  },
}, defaultState, { prefix: XXX });

github.com

また、注意点としてredux-sagaを使用している場合、takeEvery等でアクション名のパターンマッチングをしていますので、そこの考慮も必要になります。 redux-actionsとは別のライブラリですので、仕様のギャップは吸収しなければなりません。

export default function* () {
  yield takeEvery(`XXX/${actionTypes.INCREMENT}`), increment);
  yield takeEvery(`XXX/${actionTypes.DECREMENT}`), decrement);
}

Herokuアプリの監視サービス「Pingdom」のススメ

Herokuで本格的にアプリを運用するためには、アプリがダウンせずに動き続けているのかを監視する必要があります。

Herokuアプリの死活監視アドオンとして有名なのがPingdomですが、実は死活監視以外に様々な機能を提供しており、かなりコスパが高いアドオンです。 恥ずかしながら私自身は1年間ほどPingdomを死活監視のみで使用していました。

この記事ではPingdomでできる以下の4つの機能を事例を交えながら紹介します。

死活監視(Uptime)

Pingdomではアプリが利用できる状態であるか死活監視することができます。

Heroku単体でも監視することは出来ますが、Heroku自体が落ちてしまったら監視することは困難になります。 そのため、監視サーバーは基本的には外形監視(外部のサーバーから監視する)にするのが望ましいです。

Uptimeでは指定したURLに対して細かな条件を指定してアプリの死活監視することが出来ます。

  • 死活監視の頻度(1分~60分の間)を設定できる
  • サーバーのタイプをWeb(http・https)、メールサーバー、ネットワークアクセス(ping等)の3種類から選べる
  • どの国からアクセスするか選択できる
  • 問題があった場合の通知方法と復帰した場合の通知方法(webhook、メール) など...

Uptimeのダッシュボード画面イメージ

アプリがダウンした場合にエンドユーザーからの連絡により判明するというのは絶対に避けなければなりません。なるべく早くダウンを検知することで復旧時間を早めることも可能ですし、ユーザーにとってクリティカルな業務の代替案を提案することも可能になります。

ユーザーアクセス解析(Real User Monitoring)

PingdomではReal User Monitoring(RUI)という機能により、エンドユーザーがアプリをどのような操作・体験をしているのかを可視化することができます。イメージ的にはGoogle Analyticsの高機能版という感じです。

  • アプリにユーザー何人訪れているかリアルタイムおよび履歴が確認できる
  • ユーザーが使用しているデバイスやブラウザの割合
  • ページ閲覧時のユーザーの快適度をApdexという指標で確認できる
  • ページごとのアクセス数のランキングを表示できる
  • ページのロード時間の履歴を確認できる など...

RUIのダッシュボード画面イメージ

アクティブユーザー数をリアルタイムに監視できるので、どのくらいのユーザーが同時アクセスしているのか履歴を追って確認できます。

サーバーに負荷がある時間帯とアクティブユーザー数の相関関係を確認するデータとして有益に利用できます。また、リリースする際になるべく影響の少ない時間帯は何時なのか把握することが出来ますので、ユーザー数の少ない時間帯を狙ったリリース作業を行うことが可能です。

アクセス数ランキングでは、自分たちが想定していなかったページが意外と使われていたりすることがあり、今後の改善や新機能の提案に結びつくこともあります。

E2Eテスト(Transactions)

Transactionsという機能を使うことで、エンドユーザーがアプリ上で行う操作をシナリオを組むことで自動的にシミュレーションして、シナリオが正しく動くかどうかをテストすることが出来ます。 いわゆるE2Eテストをpingdom上で簡単に組むことが出来ます。

Transactionsの編集画面イメージ

E2Eテストというと導入と保守のハードルが高いというイメージがありますが、Transactionsを使用することでアプリ側には特段何も設定せずに、シナリオテストを簡単に構築することが出来ます。

複雑なシナリオも組もうと思えば組めるとは思いますが、あくまでもUI上での操作になりますので、弊社ではクリティカルな導線のみ取り入れております。

スピードテスト(Page Speed)

Page Speedを利用することで、様々な観点からページのスピードテストを行い、ページのパフォーマンス改善をするための材料を提供します。

弊社ではSaaSを運用しているため、ログイン後のページがメインになります。 Page Speedではオープンなページに対してスピードテストを提供していますので、弊社のようなプライベートなSaaSにおいてはあまり効果がないと判断し、使用を見送りました。

ちなみにPage Speedの簡易版は無償でも利用することができます。

tools.pingdom.com

異業界からWebエンジニアに転身するために必要なこと

コロナ禍により、リモートワークと相性が良いと言われているエンジニアの転職市場が加速しているように感じています。

SNSの世界にはエンジニアになるためにプログラミング勉強中系のアカウントをよく見かけます。 私の周りにも異業界からエンジニアに転身したいという人が多くいましたが、実際にエンジニアになれた人は半分も満たないというのが実情です。

「なぜ半分以上の人はエンジニアになれなかったのか?」を私なりに分析してみました。本記事ではエンジニアになれた人の共通点を元に私なりの持論を展開したいと思います。

アウトプットせざるを得ない環境をいかに作るかが重要

エンジニアになるために机上の勉強をすることはとても重要ですが、いつまでも勉強だけをしているのは危険です。どこかで区切りをつける必要があります。 プログラミング勉強中という人の中にはいつまでも勉強の域を超えられていない人が多く見受けられるように感じます。

インプットとアウトプットの割合は3:7が良いと言われています。

インプットだけしていては何も生まれません。インプットは続けようと思えばいつまでも続けられるゴールのないマラソンのようなものです。

目的なくインプットだけ続けていては次第に勉強を続けるモチベーションが低下してしまいます。勉強を続けるためにもアウトプットをする必要があるのです。

そのため、まずはアウトプットをせざるを得ない環境に身を投じることが重要です。例えば以下のようアウトプットが挙げられます。

  • スタートアップ企業にインターンシップとしてジョインする
  • プログラミング学習塾でアウトプットする場を設ける
  • 勉強したことをブログに記載してアウトプットする
  • ベンダー資格や基本情報技術者試験等を取得する

最近は、平日は自分の仕事をして週末だけインターンするという複業的な働き方もありますので、それも有効です。

反対に、学習したことをSNSで日報形式で投稿することはあまり有効ではないと思います。 あくまでも学習したことを活かして何かを生み出すことに意味がありますので、報告形式のアウトプットはあまり意味がないと感じています。

アウトプットをすることで自分に足りていない部分が明確になりますので、インプットの質も向上し、相乗効果が期待できます。 また、アウトプットというのは学習を続ける原動力になりますので、途中で投げ出すリスクも減らすことができます。

独学はダメ。なによりもメンターの存在が大きい

プログラミング学習を進めていくと必ず自分だけでは解決できない部分が出てきます。

書籍やブログを参考にして、なんとか動くまで持ってきたが「なぜ動いているのか?」「これが本当に正しい実装方法なのか?」と感じた経験は誰しもあるかと思います。 誰にも相談せずに、これが正しいのだと自分の体に刻んでしまうと、変な癖のある可読性の悪いプログラムを実装し続けることになります。

独学のみでプログラミング学習をステップアップしていくことはオススメできません。

右に行くか左に行くか道に迷ったときに間違った方向を選んでしまうと到達する場所も全く別の場所になります。 スポーツの世界でもコーチのもと正しいフォームでトレーニングを行うことで実力を伸ばせられるのと同じように、エンジニアの世界にもコーチ(メンター)の存在は絶対に必要です。

このコードが正しいのかレビューしてもらうことで新しい技術を習得する機会が与えられますので、確実な成長が見込めます。 独学で学習している方は、一旦学習を止めてメンターを探しに注力したほうが良いです。

メンターを探す方法としておすすめなのが、知人から現役エンジニアを紹介してもらうことです。

「エンジニアに転職したい人がいるから相談に乗って欲しい」という旨を伝えればほとんどのエンジニアは喜んで話を聞いてくれるでしょう。 これは不思議なことで、人は自分の喜びよりも他人の喜びのほうが幸福や充足感を感じる傾向があるので、意外と快く引き受けてくれます。

紹介してもらった現役エンジニアからメンターにしたい人を選ぶと良いでしょう。 現に私自身も現役エンジニアとしての立場から相談を受けてメンターになったことが経験が多くあります。

どうしても周りにエンジニアの知人がいないという方はMENTAというマッチングサービスもありますので、これを使用してみるのも有効かと思います。

終わりに

どのような業界でもはじめの一歩を踏み出すことはとても勇気が必要です。

アウトプットが重要だと理屈では分かっていてもインプットばかりしてしまうのは、変化を嫌う人間にとって当たり前の思考だと思います。 しかし、エンジニアになりたいと本気で思うのならば勇気を持って踏み込むことを強くおすすめします。

  • 強制的にアウトプットする機会を設ける
  • メンターを作る

まずはこの2点を厳守するだけでもエンジニアになれる確率が格段に上がると私は確信しております。

エンジニアになりたかったのに途中で挫折してしまうのはとても残念なことです。 そのような人をなるべく生み出さないためにも、私自身も微力ながらこのような発信を続けていきたいと思います。