銀行員からのRailsエンジニア

銀行員からのRailsエンジニア

銀行員から転身したサービス作りが大好きなRailsエンジニアのブログです。個人で開発したサービスをいくつか運営しており、今も新しいサービスを開発しています。転職して日々感じていること、個人開発サービス運営のことなどを等身大で書いていきます。

【技術書メモ】体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 〜毎週アウトプットチャレンジ④〜

毎週 1冊技術書を読んでブログでアウトプットするチャレンジの第4弾ですーー!

今回は、体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践 を読みました。

本書はWebアプリケーションの脆弱性に関する名著であり、2018/6/20に第2版が発売されました。

少し長くなってしまいましたが、頑張ってまとめましたので是非読んでみてください。

f:id:ysk_pro:20180813150939j:plain

1 Webアプリケーションの脆弱性とは

- 脆弱性とは悪用できるバグ

- 脆弱性が生まれる理由

  - バグ

  - チェック機能の不足

 

3 Webセキュリティの基礎

3-1 HTTPとセッション管理

- 秘密情報をPOSTで送信すべき理由(GETのリスク)

  - URL上に指定されたパラメータがReferer経由で外部に漏洩する

  - URL上に指定されたパラメータがアクセスログに残る

  - パラメータ付きのURLを利用者がソーシャルネットワークなどで共有してしまう

- hiddenパラメータは利用者は書き換えることができるが、第三者からの書き換えに対しては堅牢

- クッキーは少量のデータをブラウザ側で覚えておけるものだが、アプリケーションデータを保持する目的では次の理由から行われない

  - クッキーが保持できる値の個数や文字列長に制限がある

  - クッキーの値は利用者本人には参照・変更できるので、秘密情報の格納に向かない

- クッキーには整理番号としてセッションIDを格納し、実際の値はサーバー側に管理する方法がよく取られる

- セッションIDに求められる要件は次の通り

  - 第三者がセッションIDを推測できない

  - 第三者からセッションIDを強制されない

  - 第三者にセッションIDが漏洩しない

- セッションIDは自作せず、Webアプリケーション開発ツールで提供されるセッションIDを利用すべき

- Secure属性をつけたクッキーはHttps通信の場合のみサーバーに送信される

- HttpOnly属性は、JavaScriptからアクセスできないクッキーを設定するもの

 

3-2 受動的攻撃と同一オリジンポリシー

- 受動的攻撃とは、攻撃者がサーバーを直接攻撃するのではなく、Webサイトの利用者に罠を仕掛けることにより、罠を閲覧したユーザを通じてアプリケーションを攻撃する手法

- 同一オリジンポリシーとは、JavaScriptなどのクライアントスクリプトからサイトをまたがったアクセスを禁止するセキュリティ上の制限

 

4 Webアプリケーションの機能別に見るセキュリティバグ

4-1 Webアプリケーションの機能と脆弱性の対応

- 脆弱性には処理に起因するものと出力に起因するものがあり、出力に起因するものはインジェクション系脆弱性と呼ばれる

 

4-2 入力処理とセキュリティ

- Webアプリケーションの入り口では、入力の文字エンコーディング検証と変換、入力値のチェックを実施する。これらはセキュリティに対する根本的な対策ではないが、プラットフォームやアプリケーションに潜在的脆弱性があった場合のセーフティネットとして作用する 

 

4-3 表示処理に伴う問題

- XSS脆弱性の対策としては、表示の際にHTMLで特殊な意味を持つ記号文字(メタ文字)をエスケープすることが有効

- XSSに対する保険的対策

  - X-XSS-Protection レスポンスヘッダの使用:ブラウザのセキュリティ機能を有効にする

  - クッキーにHttpOnly属性を付与する

 

4-4 SQL呼び出しに伴う脆弱性

- SQLインジェクションは、データベース内の任意のデータを漏洩し、書き換えることができるので非常に危険

- SQLインジェクションの確実な対策は静的プレースホルダを利用してSQLを呼び出すこと

  - SQL文中の「?」がプレースホルダで、変数や式など可変のパラメータの場所に埋め込んでおくもの

  - 静的プレースホルダは値のバインド(? に値を割り当てること)をデータベースエンジン側で行う。プレースホルダの状態でSQL文がコンパイルされるため、後からSQL文が変更される可能性はない

  - 動的プレースホルダはアプリケーション側のライブラリ内でパラメータをバインドしてデータベースエンジンに送る方式

 

4-5 重要な処理の際に混入する脆弱性

- クロスサイト・リクエストフォージェリ(CSRF)は、重要な処理の前に利用者のリクエストであることを確認する処理が抜けている場合に、罠のサイトを閲覧しただけで利用者のブラウザから勝手に重要な処理を実行されられる脆弱性

- CSRFの対策は、利用者の意図したリクエストであることの確認で、以下の方法がある

  - トークン埋め込み 〜重要な処理のページに第三者が知り得ないトークンを要求することによって利用者を識別する

  - パスワード再入力

  - Referer確認

- クリックジャッキングはiframe要素とCSSを巧妙に利用することで、透明にした攻撃対象ページと罠のサイトを重ね合わせ、利用者が気づかないうちに攻撃対象サイトでのうリックを誘導する攻撃手法

- クリックジャッキングは、主要ブラウザで採用されているX-Frame-Optionsを有効にすることで対策ができる 

 

4-6 セッション管理の不備

- セッションの固定化攻撃の対策としては、認証後にセッションIDを変更する方法がある 

 

4-7 リダイレクト処理にまつわる脆弱性

- パラメータにより指定した任意のドメインにリダイレクトできる脆弱性をオープンリダイレクト脆弱性と呼び、フィッシングに悪用される

- オープンリダイレクト脆弱性の対策としては、リダイレクト先のURLを固定にすればよい

- HTTPヘッダ・インジェクションの原因は外部から指定された改行をそのまま出力することで、HTTPヘッダ出力部分を自分で作らずにヘッダ出力用のライブラリやAPIを利用することで対策ができる 

 

4-8 クッキー出力にまつわる脆弱性

- クッキーにSecure属性をつけていないと、平文で送信されて盗聴される可能性がある 

 

4-9 メール送信の問題

- メールのメッセージヘッダに外部から改行を追加されることがメールヘッダ・インジェクションの原因となり、対策にはメール送信に専用のAPIやライブラリを用いることが有効 

 

4-10 ファイルアクセスにまつわる問題

- ディレクトリ・トラバーサル脆弱性とは、外部からパラメータの形でサーバー上のファイル名を指定できるWebアプリケーションでファイル名のチェックが不十分な場合にアプリケーションの意図しないファイルが閲覧・改ざんされてしまう脆弱性

- ディレクトリ・トラバーサル攻撃の対策としては、外部からファイル名が指定できる仕様を避けることが有効 

 

4-10 OSコマンド呼び出しの際に発生する脆弱性

- OSコマンド・インジェクションの対策としては、OSコマンドを呼び出さない実装方法を選択することが有効 

 

4-11 ファイルアップロードにまつわる問題

- Webアプリケーションのアップロード機能に対して大量のデータを送信することで、
Webサイトに過大な負荷をかけるDoS攻撃があり、対策にはアップロードファイルの容量制限が有効 

 

4-12 インクルードにまつわる問題

- require・ includeなどでソースの一部を外部から指定できる場合、アプリケーションが意図しないファイルを指定することにより脆弱性が生まれることがあり、対策としてはインクルードするパス名に外部からのパラメータを含めないことが有効

 

4-16 Web API実装における脆弱性

- APIにおいてJSON文字列生成時のエスケープ処理に不備があると、意図しないJavaScriptJSONデータに混入する脆弱性があり、対策としては信頼できるライブラリを用いてJSONを生成することが有効

 

5 代表的なセキュリティ機能

5-1 認証

- パスワードを桁数や文字種類などで厳しくチェックしすぎると、かえって安全なパスワードをつける利用者のモチベーションを下げてしまうことがある

- オンラインでのブルートフォース攻撃への対抗策としてはアカウントロックが有効。10回程度パスワードを間違えたらアカウントロックがかかり、ロックから30分経過した場合は自動的に解除される、というような実装がされることが多い

 

5-2 アカウント管理

- メールアドレスの受信確認は、①メールにトークン付きURLを添付してそのURLから処理を継続する、②メールアドレスを入力した後にトークン(確認番号)入力画面に遷移し、トークンはメール送信される、の2パターンある。Aがよく使われるが、メール記載のURLを利用者に閲覧させるという習慣はフィッシング対策上よくないので、筆者はBを推奨している

- 外部からの自動操作により大量に新規ユーザを作成されることを防ぐため、「私はロボットではありません」にチェックしてもらう等のCAPTCHAがよく利用される

- パスワードを変更する際は、現在のパスワードを照合する。これによりセッションハイジャックされた状態で第三者がパスワードを変更することを防止できる

- メールアドレス変更時のメール通知は新旧両方のメールアドレスに対して行う。これは第三者に不正にメールアドレスを変更された場合に正当なユーザが気づけるようにするため 

 

5-3 認可

- 認可制御の実装がきちんとされていないと、情報リソースのURLを知っているだけで認証なしで情報が閲覧できてしまう

- 認可制御の不備の原因の多くは画面の制御のみで認可制御を実装しているつもりになっていることであり、操作に先立ってこの機能を実行してよいユーザであるかを確認する必要がある

- ユーザ情報は、外部から書き換えできないセッション変数に保持する。書き換えができるクッキーやhiddenパラメータなどに保持しない 

 

5-4 ログ出力

- ログに記録すべきイベントは多すぎても少なすぎてもダメで、ログの使用目的から決定すべき。一般的には以下の認証・アカウント管理・重要な情報の操作をログ出力することが多い

  - ログイン・ログアウト(失敗も含む)

  - アカウントロック

  - ユーザ登録・削除

  - パスワード変更

  - 重要情報の参照

  - 重要な操作(物品の購入、送金、メール送信など)

- ログの出力項目は、4W1H(いつ、誰が、どこで、何を、どのように)に従った以下の項目を取得する

  - アクセス日時

  - リモートIPアドレス

  - ユーザID

  - アクセス対象(URL、ページ番号、スクリプトIDなど)

  - 操作内容(閲覧、変更、削除など)

  - 操作対象(リソースIDなど)

  - 操作結果(成功あるいは失敗、処理件数など)

- ログの出力先にはデータベースやファイルがよく用いられるが、ログの保護という観点からはログ専用のサーバーを用意することが望ましい 

 

6 文字コードとセキュリティ

- 文字コードの扱いに問題があると文字列処理にバグが生じ、脆弱性の原因になる

- 対策としてはアプリケーション全体の文字エンコーディングUTF-8で統一することが推奨されている 

 

7 脆弱性診断入門

- 開発時に脆弱性を作り込まないように気をつけていても脆弱性は混入してしまう可能性が高い。プログラミングにおいて機能を実装したら必ずテストをするのと同じように、脆弱性がないこともテストで確認する必要があり、それが脆弱性診断である

 

8 Webサイトの安全性を高めるために 

- Webサーバーがマルウェアに感染する経路は、メールが9割

- Webサーバーマルウェア対策としては、サーバーの脆弱性対処をタイムリーに行うことや、クライアントPCに最新のセキュリティパッチを導入することが有効

 

9 安全なWebアプリケーションのための開発にマネジメント

- 安全なアプリケーション開発のために費用対効果が高いのは開発標準(セキュリティガイドライン)の整備

- 開発標準に記載すべき重要項目は以下の通り

  - 脆弱性毎の対処方法

  - 認証、セッション管理、ログ出力などの実装方法

  - 各フェーズでのレビューとテストの方法(いつ、誰が、何を、どうやって)

  - 公開判定基準(誰が、いつ、どの基準で許可するか)

- セキュリティ機能は最終的にテストにより要件を満たすことを確認する必要がある。セキュリティテスト(脆弱性検査)の方法には、専門家に依頼する、専用ツールで診断する、などの方法がある

 

おわりに

ここまで読んでいただきありがとうございます。

Webアプリケーションの脆弱性については、実務では必須の知識なので(僕の会社でも現在進行形でこの本の勉強会を毎週しています)ご興味ある方は是非読んでみることをおすすめしますー!

来週も頑張ります!

【技術書メモ】安全なウェブサイトの作り方・安全なSQLの呼び出し方 〜毎週アウトプットチャレンジ③〜

毎週 1冊技術書を読んでブログでアウトプットするチャレンジの第三弾です〜!

今回は、安全なウェブサイトの作り方安全なSQLの呼び出し方(短いので2冊で1冊扱い)を読みました。

どちらもIPA独立行政法人 情報処理推進機構)が無料で公開しています。

f:id:ysk_pro:20180805204003j:plain

# はじめに

脆弱性対策には、根本的解決と保険的解決がある

根本的解決

- 脆弱性を作り込まない実装

- 根本的解決を実装することでその脆弱性を狙った攻撃を無効化できる

保険的対策

- 攻撃の影響を軽減する対策

- 根本的解決と違い、脆弱性の原因そのものを無くすものではないが、攻撃の影響を軽減できる
- 根本的解決の実装に漏れが生じる場合、保険的対策はセーフティネットとして機能するので、根本的解決と保険的対策を組み合わせるのが有効

 

1. ウェブアプリケーションのセキュリティ実装

設計や実装レベルでの対策

1) SQLインジェクション

根本的解決

- SQL文の組み立ては全てプレースホルダで実装する

- SQL文の組み立てを文字列連結で行う場合は、エスケープ処理を行うデータベースエンジンのAPIを用いて、SQL文のリテラルを正しく構成する

保険的対策

- エラーメッセージをそのままブラウザに表示しない 〜 攻撃者への手がかりを与えてしまう

- データベースアカウントに適切な権限を与える 〜 データベースに接続するアカウントの権限が必要以上に高いと攻撃による被害が深刻化する恐れがある

 

2) OSコマンド・インジェクション

- WebサーバのOSコマンドを不正に実行されてしまう問題

根本的解決

- シェルを起動できる言語機能の利用を避ける

保険的対策

- シェルを起動できる言語機能を利用する場合は、その引数を構成する全ての変数に対してチェックを行い、あらかじめ許可した処理のみを実行する

 

3) パス名パラメータの未チェック/ディレクトリ・トラバーサル

- パラメータにファイル名を指定しており、ファイル名指定の実装に問題がある場合、公開を想定していないファイルを参照されてしまう恐れがある

根本的解決

- 外部からのパラメータでWebサーバ内のファイル名を直接指定する実装は避ける

- ファイルを開く際は固定のディレクトリを指定し、かつファイル名にディレクトリ名が含まれないようにする

保険的対策

- Webサーバ内のファイルへのアクセス権限の設定を正しく管理する

- ファイル名のチェックを行う

 

4) セッション管理の不備

- セッションIDの発行や管理に不備がある場合、悪意のある人にログイン中の利用者のセッションIDを不正に取得され、その利用者になりすましてアクセスされてしまう可能性がある

根本的解決

- セッションIDを推測困難なものにする

- セッションIDをURLパラメータに格納しない

- HTTP通信で利用するCookieにはsecure属性を加える 〜 secure属性が設定されたCookieHTTPS通信のみで利用できる

- ログイン成功後に、新しくセッションを開始する

- ログイン成功後に既存のセッションIDとは別に秘密情報を発行し、ページ遷移ごとにその値を確認する

保険的対策

- セッションIDを固定値にしない

- セッションIDをCookieにセットする場合、有効期限の設定に注意する

 

5) クロスサイト・スクリプティング

- スクリプトを埋め込むことが可能な脆弱性がある場合、利用者のブラウザ上でスクリプトが実行される可能性がある

根本的解決

- Webページに出力するすべての要素に対して、エスケープ処理を施す

- URLを出力するときは、http://・https://で始まるもののみ許可する〜 javascript:の形式で始まるURLはクロスサイト・スクリプティング攻撃が可能になる場合がある

- <script>...</script>要素を動的に生成しない

- スタイルシートを任意のサイトから取り込めるようにしない

- HTTPレスポンスヘッダのContent-Typeフィールドに文字コード(charset)を指定する

保険的対策

- 入力値の内容チェックを行う

- Cookie情報の漏えい対策として、発行するCookieにHttpOnlyを加え、TRACEメソッドを無効化する

- クロスサイト・スクリプティング潜在的脆弱性対策として有効なブラウザの機能を有効にするレスポンスヘッダを返す

 

6) CSRF(クロスサイト・リクエスト・フォージェリ)

- ログインした利用者からのリクエストについて、その利用者が意図したリクエストであるかどうかを識別する仕組みを持たないwebサイトは、外部サイトを経由した悪意あるリクエストを受け入れてしまう場合がある

根本的解決

- 処理を実行するページPOSTメソッドでアクセスするようにし、そのhiddenパラメータに秘密情報が挿入されるよう、前のページを自動生成して、実行ページではその値が正しい場合のみ処理を実行する

- 処理を実行する直前のページで再度パスワードの入力を求め、実行ページでは再度入力されたパスワードが正しい場合のみ処理を実行する

- Refererが正しいリンク元かを確認し、正しい場合のみ処理を実行する 〜 Refererを確認することで、本来の画面遷移を経ているかどうかを確認できる

保険的対策

- 重要な操作を行った際に、その旨を登録済みのメールアドレスに自動送信する

 

7) HTTPヘッダ・インジェクション

- HTTPレスポンスヘッダのフィールド値を外部から渡されるパラメータ等を利用して動的に生成する実装に対して、レスポンス内容に任意のヘッダフィールドを追加する攻撃

根本的解決

- ヘッダの出力を直接行わず、webアプリケーションの実行環境や言語に用意されているヘッダ出力用APIを使用する

- 改行コードを適切に処理するヘッダ出力用APIを利用できない場合は、改行を許可しないように開発者自身で適切な処理を実装する 〜 HTTPヘッダは改行によって区切られる構造になっており、改行を許すと任意のヘッダフィールドや任意のボディを注入されたり、レスポンスを分割されたりする原因となる

保険的対策

- 外部からの入力の全てについて、改行コードを削除する

 

8) メールヘッダ・インジェクション

- メール送信機能を持つwebアプリケーションにおいて、管理者が設定した本来固定のメールアドレスではない宛先にメールを送信され、迷惑メールの送信に悪用される

根本的解決

- メールヘッダを固定値にして、外部からの入力は全てメール本文に出力する 〜 to, cc 等のメールヘッダの内容が外部からの入力に依存する場合、外部から与えられた改行コードが差し込まれてしまい、任意のメールヘッダの挿入や、任意の宛先へのメール送信に悪用される原因になる

- メールヘッダを固定値にできない場合、webアプリケーションの実行環境や言語に用意されているメール送信用APIを使用する

- HTMLで宛先を指定しない

保険的対策

- 外部からの入力の全てについて、改行コードを削除する

 

9) クリックジャッキング

- ログインしている利用者のみが使用可能な機能を、細工された罠ページを重ね合わせてクリックさせることにより、意図せず実行させる

根本的解決

- HTTPレスポンスヘッダに、X-Frame-Optionsヘッダフィールドを出力し、他ドメインのサイトからのframe要素やiframe要素による読み込みを制限する

- 処理を実行する直前のページで再度パスワードの入力を求め、実行ページでは再度入力されたパスワードが正しい場合のみ処理を実行する

保険的対策

- 重要な処理は、一連の操作をマウスのみで実行できないようにする

 

10) バッファオーバーフロー

- プログラムが入力されたデータを適切に扱わない場合、プログラムが確保したメモリの領域を超えて領域外のメモリを上書きして、意図しないコードを実行してしまう可能性がある

根本的解決

- 直接メモリにアクセスできない言語で記述する 〜 Rubyはメモリに直接アクセスできないため、バッファオーバーフローの問題は発生しない

- 直接メモリにアクセスできる言語で記述する部分を最小限にする

- 脆弱性が修正されたバージョンのライブラリを使用する

 

11) アクセス制御や認可制御の欠落

根本的解決

- アクセス制御機能による制御措置が必要とされるwebサイトには、パスワード等の秘密情報の入力を必要とする認証機能を設ける

- 認証機能に加えて認可制御の処理を実装し、ログイン中の利用者が他人になりすましてアクセスできないようにする 〜 認可とはどの利用者にどの操作を許可するか制御すること

 

2. ウェブサイトの安全性向上のための取り組み

運用レベルでの対策

1) Webサーバに関する対策

- OSやソフトウェアの脆弱性情報を継続的に入手し、脆弱性への対処を行う

- 公開を想定していないファイルを、web公開用のディレクトリ以下に置かない

 

2) DNSに関する対策

- DNSによりドメイン名を指定するだけで、該当するwebサイトへのアクセスやメールの送受信が可能になってしまう

- DNSソフトウェアの更新や設定を見直す

 

3) ネットワーク盗聴への対策

- 通信や情報が暗号化されていない場合、盗聴によって取得された情報が悪用される可能性がある

- webサイトの通信を暗号化する手段として、SSLを用いたHTTPS通信がある

- 利用者へ通知する重要情報は、メールで送らず暗号化されたhttps:// のページに表示する

 

4) フィッシング詐欺を助長しないための対策

- EV SSL証明書を取得し、サイトの運営者が誰であるかを証明する

- 利用者がログイン後に移動するページをリダイレクト機能で動的に実装しているウェブサイトについて、リダイレクト先のURLとして使用されるパラメータの値には自サイトのドメインのみを許可するようにする

 

5) パスワードに関する対策

- 入力後の応答メッセージが認証情報の推測のヒントとならない工夫をする

- ユーザIDもしくはパスワードが違います、というような表示をすることで、ヒントを与えないようにする

- パスワードをサーバ内で保管する際は、平文ではなくソルト付きハッシュ値の形で保管する

- ソルトとは乱数等により利用者毎に異なる文字列を生成すること

 

6) WAFによるwebアプリケーションの保護

- WAF(Web Application Firewall)はHTTP(HTTPS)を検査し、攻撃等の不正な通信を自動的に遮断するソフトウェア・ハードウェア

- webアプリケーションの改修が困難な状況でWAFが有効

 

おわりに

これら内容は分かっていないとwebエンジニアとして話にならないと思うので早く身につけます…!!

こちら(↓)記事で紹介した本を順番にアウトプットしていく予定ですー!

ysk-pro.hatenablog.com

参考にしてみてください〜!

来週も頑張ります!

【技術書メモ】Everyday Rails - RSpecによるRailsテスト入門 〜毎週アウトプットチャレンジ②〜

毎週 1冊技術書を読んでブログでアウトプットするチャレンジの第二弾です〜!

 

技術書の読み方はこちらの記事に書きました。

【保存版】技術書の読み方について - 銀行員からのRailsエンジニア

「何が書いてあったか」「抽象的な考え方」を中心にアウトプットしていきます。

f:id:ysk_pro:20180722073459j:plain

第二弾で読んだ本はこちらです。

leanpub.com

RSpecについての有名な電子書籍です。

 

RSpecのセットアップ

RSpec gemをインストールすると作成されるファイルは以下の4つ
 - .rspec:設定ファイル
 - spec:スペックファイルを格納するディレクト
 - spec/spec_helper.rb・spec/rails_helper.rb:RSpecの動きをカスタマイズするヘルパーファイル
 
・.rspec ファイル内に一文追加することで、RSpec出力を読みやすいドキュメント形式にすることができる
 
・binstub をインストールすると、アプリケーションの起動時間を素早くするSpringの恩恵が受けられる
 
rails g コマンドを使った際にスペックファイルを同時に作成するための設定方法について
 

モデルスペック

・モデルはアプリケーションのコアであり、モデルが十分にテストされていると信頼性の高いコードを構築できる
 
・モデルスペックには次のテストを含める
 - 有効な値が入力された場合は、モデルの状態が有効(valid)になっていること
 - バリデーションを失敗させるデータであれば、モデルの状態が有効になっていないこと
 - クラスメソッドとインスタンスメソッドが期待通りに動作すること
 
境界値のテストをするべき
 
・describeとcontextは互換可能であるものの、基本的な使い分け方は以下の通り
 - describe:クラスやシステムの機能に関するアウトラインを記述
 - context:特定の状況に関するアウトラインを記述
 
・before はdescribeまたはcontextブロック内の各テストの前に実行される
 
可読性を優先してDRY原則に違反するのは問題ない。テストはDRYであることよりも読みやすいことの方が重要
 

テストデータの作成

・テストシナリオが複雑になった際にFactory Bot gemを使うとテストデータのセットアップをシンプルにすることができる
 
・ファクトリを使えば、FactoryBot.create(:user)と書くだけで、簡単に新しいユーザーを作成でき、スペック全体で使うことができる
 
・FactoryBot.build では新しいテストオブジェクトをメモリ内に保存し、FactoryBot.create ではアプリケーション用のデータベースにオブジェクトを永続化する
 
・ファクトリはシーケンスを使うことでそれぞれにユニークな値を設定できる
 
・ファクトリは数行のコードを書くだけで、必要なデータを作ってくれてセットアップ用のコードも短くなりテストコードが読みやすくなる。しかし、ファクトリを使うとテスト中に予期しないデータが作成されたり、無駄にテストが遅くなったりする原因にもなる可能性がある。できる限りFactoryBot.createではなく、FactoryBot.buildを使うことでデータベースに追加する回数が減り、パフォーマンスの低下が軽減できる
 

コントローラスペック

・前提として、RailsチームとRSpecチームの双方が、コントローラのテストを削除するか、モデルのテストやより高いレベルのフィーチャスペックと置き換えることを推奨している
 
・コントローラスペックは、基本的にブラウザに返すレスポンスコードをテストする
 
・Deviseのヘルパーを用いて、認証が必要な処理もテストすることができる
 

フィーチャスペックでUIをテストする

・Capybara gemを使うとリンクをクリックしたり、Webフォームを入力したり、画面の表示を検証したりすることができる
 
・コントローラスペックではユーザーインターフェースを無視して、パラメータを直接コントローラのメソッドに送信するのに対して、フィーチャスペックではユーザーが使うものと全く同じユーザーインターフェースを使ってテストをする
 
・フィーチャスペックでは1つのexample、もしくは1つのシナリオで複数のエクスペクテーションを書くのは問題ない
 
・save_and_open_page、Launchy gemを使うことで、save_and_open_pageをスペック内で呼び出した時にHTMLを自動で開き、デバッグすることができる
 
・シナリオ文の後に、js: trueというオプションを渡すことで、JavaScriptを用いたテストを行うことができる
 

リクエストスペックでAPIをテストする

API関連のテストは spec/requests ディレクトリに配置する
 
・リクエストスペックではCapybaraは使わない(Capybaraはブラウザの操作をシミュレートするだけであり、プログラム上のやりとりは特にシミュレートしないため)
  
・コントローラスペックをリクエストスペックで置き換えることは可能
 

スペックをDRYに保つ

・重複するコードはサポートモジュールに切り出すことが可能であり、フィーチャスペックでよく使われる
 
letメソッドは遅延読み込みされるため、使う必要のないデータを作成してテストが遅くなるといったことが起きにくい
 
・shared_contextを使うと、複数のテストファイルで必要なセットアップを行うことができる
 
・自分で独自のカスタムマッチャを作成することが可能
 
・aggregate_failures を使うとその中では1つのエクスペクテーションが失敗しても、次のエクスペクテーションが実行される。これにより、同じコードを何度も実行して遅くなったり、複雑なセットアップを複数のテストで共有したりせずにテストが失敗した複数のポイントを把握することができる
 

速くテストを書き、速いテストを書く

・Soulda Matchers を使えば、モデルの簡単なテストを1行で書くことができる
 
・モックは本物のオブジェクトのふりをするオブジェクトで、テストのために使われる。テストダブルと呼ばれることもある
(メリット)
 - モックはデータベースにアクセスしないため、テストにかかる時間が短くなる
 - 時間のかかるネットワーク呼び出しを実行する必要があったり、レートリミットを持つ外部APIとやりとりする必要があったりする場合、モック化はそうしたコストを最小化してくれる
 
・スタブはオブジェクトのメソッドをオーバーライドし、事前に決められた値を返す。つまり、呼び出されるとテスト用に本物の結果を返すダミーメソッド
 
・テストがとても遅くなったり、再現の難しいデータ(外部APIなど)をテストするのでなければ、無理にモックやスタブを使う必要はない
 
タグ機能を使えば、ファイル内の特定のテストだけを実行して、それ以外はスキップするようにできる。新機能追加の時などに使うとテストの実行が早くなる
 
・ParallelTests gemを使ってテストを並列に実行すると格段にスピードアップする可能性がある
 

その他のテスト

・ファイルアップロード機能のテストについて
 
・Active Jobを使ったバックグラウンドジョブのテストについて
 
・メール送信のテストについて
 

テスト駆動開発

テスト駆動開発(TDD)は、以下の手順で行うとスムーズに進む
  1.  必要なステップをテストコードにコメントとして記載する
  2.  コメントをテストコードに置き換える
  3.  テストを実行し、テストが失敗したエラーメッセージを見て、そのエラーを発生させたないための実装をする
  4.  テストが成功するまで 3. を繰り返す
 
・新機能を実装する際にテストを書くことで、リファクタリングが楽になり将来的に時間をかなり節約することができる
 

テストを書く順序

・テストを書く順序は、フィーチャスペックを書いてからモデルスペックを書く。その際はエンドユーザがタスクを完了させる手順を考えて書く。これは外から中へと呼ばれるテストを書く際の一般的なアプローチ
 

RSpecを書いてみた感想

↑テストコード書くのが楽しくなってきました!笑

 

RSpec自体は思っていたよりも難しくなく、直感的に書くことができました

 

・テストコードを実装前に考えることで、実装方法を考える時間が増え、実装がスムーズになったような気がします

 

おわりに

来週も頑張ります!(来週末引越しなので次は再来週になってしまうかもしれませんが…)

この記事で紹介した本を順番にアウトプットしていく予定ですー!

ysk-pro.hatenablog.com

【技術書メモ】パーフェクトRuby on Rails 〜毎週アウトプットチャレンジ①〜

はじめに 

 ということで、毎週 1冊技術書を読んでブログでアウトプットするチャレンジを始めました!
この記事はその第一弾です。 

f:id:ysk_pro:20180715134345j:plain

毎週読むにあたって心がける読み方のポイントはこちらです。

何が書いてあったかを覚えるだけでいい → 辞書のように使う

・具体的なことよりも抽象的な考え方を身につける → 抽象的なことの方が汎用的

できるだけたくさんの本を読んだ方がいい → 引き出しを増やす

アウトプットをする → 考えながら読むようになる 

詳細はこちらのブログに書いています。

ysk-pro.hatenablog.com

「何が書いてあったか」「抽象的な考え方」を中心にアウトプットしていきます。

 

第一弾として読んだ本はこちらです。 

パーフェクトRuby on Rails

パーフェクトRuby on Rails

 
Ruby on Railsの超有名な本です。 
 

1章 Ruby on Railsの概要

Railsの思想>
・CoC(Convention over Configuration)(設定より規約)
(メリット)
 - 規約に従うことで設定ファイルを書く必要がなくなる
 - 開発者毎の設定の差異が無くなり、他のエンジニアと共通のルールでコミュニケーションが取れる
 
・DRY(Don’t Repeat Yourself)
 - 1つのことは1箇所だけに書く
 
・REST(Representational State Transfer)
 - Webアプリケーションの設計概念の1つ
 - 全てのリソースに一意となる識別子(URI)がある
 - URIを通じてリソースを操作する手段を提供する
(メリット)
 - リソースを中心に考えることで、機能追加のしやすい自然な設計になる
 
・自動テスト
 - Railsでは自動テストを行う文化を重要視している
 

2章 Ruby on RailsMVC

・Model:データベースとの接続とデータに対する操作、およびビジネスロジックを書く
・View:Modelの内容を参照し視覚表現を行う
・Controller:Modelのロジック呼び出し、必要なViewの選択など、ModelとViewをつなぐ
 
<モデル>
ActiveRecordによるモデルには、大きく分けて2つの側面がある
 - データベースと接続し、データベースのレコードのレコードとエンティティを結びつける役割
 - ビジネスロジックの実装的な振る舞いに関するところ、すなわちバリデーションや、様々なコールバック(特定の処理に引っ掛けて別の処理を呼ぶこと)などを実行する役割で、ActiveRecordの内部で利用されているActiveModelというモジュールが担っている
 
・モデルにはScopeを定義できる
 - Scopeとは、よく利用する検索結果に名前をつけてひとまとめにしたもの
(メリット)
 - 繰り返し利用するクエリの再利用性が上がる
 - クエリに名前をつけることで可読性が向上する
 
ActiveRecord enumsは、プログラム上では定数のように扱えるが実態は数値で表されるもの
(メリット)
 - 直接文字列として保存するより数値として保存した方がデータベース上の空間効率が良くなる
 
・アプリケーションの主要なロジックはなるべくモデルに書くべき
(メリット) 
 - コードが整理され、テストがしやすくなる
 
<コントローラ>
・コントローラが継承しているApplicationControllerは、アプリケーションのすべてのコントローラで共通するヘルパーや属性、挙動などを定義する場所
 
Railsアプリケーションにおいては、基本的にコントローラが例外処理を担当する
 
<ビュー>
・variantsという機構で、接続してきた端末によって別々のテンプレートを表示させることができる(スマホ用のテンプレートなど)
 
・HTMLタグの付与などビューに特有の加工をする場合は、モデルに変換処理を書くより、ヘルパーを利用するやり方が一般的
 
Railsのビュー処理を通すと、テンプレートエンジン内でRubyのStringのオブジェクトを描画しようとした場合に自動でHTMLタグに対してエスケープ処理が施され、単純なXSSを防ぐことができる
 
・HTTP APIのサーバの場合、必要な情報はHTMLではなく別のフォーマットで渡す場合がほとんど。JSON APIであれば、ビューの担当する仕事はJSONを生成することとなる
 

3章 アセット

Railsではデフォルトでいくつかのアセットパスが用意されている
 - アプリケーションのメイン機能に関わるもの:app/assets
 - 共通で利用するライブラリに関わるもの:lib/assets
 - オープンソースJavaScriptライブラリなどの外部から取得して利用するもの:vendor/assets
 
・アセッツプリコンパイルについての説明
 
CoffeeScript、Sassについての説明
 
・Turbolinksは、JavaScriptCSSに変化が無いのであればタイトルとbodyだけ差し替えることでJavaScriptCSSの読み込みを省略することができ高速化できる、という思想のもとに成り立つ
(注意点)
 - ページ遷移時のイベント発行を前提にしていたり、グローバルな変数にデータをを保持しているJavaScriptは、意図した通りに動作しなくなる場合があるので注意が必要
 

4章 Railsのロードバスとレイヤーの定義方法

MVCに当てはまらないようなモジュールの主要な管理方法
  - モデルとして扱う
  - libディレクトリで管理する
  - 新しいレイヤーを定義する
 
Rails命名規則に沿ったファイル名とクラス名を採用していると自動でファイルをrequireしてくれる、オートローディングという機能が備わっている
 
・Sidekiqは、バックグラウンドで継続する非同期処理を行う
 - SidekiqはRailsとは別にプロセスを立ち上げ、そのプロセスがRailsからのメッセージを受け取りワーカークラスを引き渡して実行することで非同期処理を実現している
 - Sidekiqを使用するためにはRedisが必要になる
 

5章 開発を効率化するgem

・Pry:ステップ実行を行うことができる
 
・Hirb:コンソール上でモデルを表形式で出力できる
 
・Better errors:JavaScriptでの非同期処理などのエラー画面が表示されないようなケースで例外が発生した場合、「/_better_errors」 にアクセスすることで最後に発生した例外のBetter errorsのエラー画面を参照できる
 
rails-erd:モデル情報からER図のPDFを出力できる
 

6章 Railsアプリケーション開発

Twitterログインの実装
 
・ログイン状態を管理するヘルパーメソッド
 
・イベントのCRUD機能実装
 
i18nの設定
 
・よく使うgem(kaminari、ransack、carrierwave)の使い方
 

7章 Railsアプリケーションのテスト

・テストを書く理由
  - 仕様と設計を考える機会が増えることで、仕様の抜け漏れを減らし、きれいな設計になりやすい
  - 手作業によるテストを減らせる
  - ちゃんと動くかどうかの不安を減らせる
  - リファクタリングや仕様変更に対応しやすい
 
・モデル、コントローラ、ビューのテスト、エンドツーエンドのテストの書き方
 
・TDDについて
(メリット)
 - それぞれの段階で、設計すること、実装すること、リファクタリングすることだけに専念できるため、一度にきれいで動くコードを書こうとするのに比べて考えなければいけないことを減らすことができる
 

8章 Railsのインフラと運用

・サーバにデプロイするにあたって必要なミドルウェア
  - ウェブサーバ:ブラウザからのリクエストを一番最初に受け取るサーバ(Nginx、Apache2)
  - アプリケーションサーバRailsのアプリケーション自体をホストするサーバ(UnicornRailsのプロセスを別途立ち上げる形のアプリケーションサーバ、Passenger)
  - データベース
 
Capistranoについて
 

9章 より実践的なモデルの使い方

・コールバックやバリデーションを別クラスに分離するメリット
  - テストのための事前条件を満たすための負荷が減り、テストが容易になる
 
・ActiveModelモジュールを活用することで、自分で定義したプレーンなRubyクラスに対してActiveRecordに備わっている機能を組み込むことができる
 
・モデルとコントローラにデフォルトで存在するconcernディレクトリは、横断的関心事(複数のモデルや機能に跨って影響するもの)を実装する際に利用する
 
・サービスクラスはコントローラとモデルの中間のイメージで、処理そのものをカプセル化し責務を分離したもの
 

10章 Railsを拡張する

・gemを作ることができる方法としての、Rack Middlewareについての説明
 

おわりに

一週間で読むと決めると集中して読めるし、アウトプットすることで頭に残るのでいい感じです。

毎週頑張っていきますよー!

一緒にチャレンジしてくれる方募集中です〜(笑)

パーフェクトRuby on Rails

パーフェクトRuby on Rails

 

【保存版】技術書の読み方について

こんにちは。ゆうすけです。

Railsエンジニアになって1週間経ちました。

元気に働いています。

 

「技術書の読み方」について会社のマネージャーにとても参考になることを教えていただいたのでブログに残しておこうと思います。

f:id:ysk_pro:20180707175357j:plain

ポイントは

何が書いてあったかを覚えるだけでいい → 辞書のように使う

・具体的なことよりも抽象的な考え方を身につける → 抽象的なことの方が汎用的

できるだけたくさんの本を読んだ方がいい → 引き出しを増やす

アウトプットをする → 考えながら読むようになる

です。

 

何が書いてあったかを覚えるだけでいい

まず、全てを覚える必要はありません。不可能です。

技術書は辞書のように使えればいいと割り切って、どんなこと書いてあったかを覚えるようにします。

実際にその技術が必要になった際に、すぐに参照できるようにしておきます。

 

具体的なことよりも抽象的な考え方を身につける

webエンジニアは技術の移り変わりが早いので、具体的なことは比較的早く変わっていきます。

しかし、抽象的なこと、つまり根本の考え方のようなものは普遍的で変わらないことが多いのでそれを身に付けるようにします。

 

できるだけたくさんの本を読んだ方がいい

同じ本を繰り返し読むことも当然大切です。

しかし、これと同じくらい、たくさんの本に触れることも大切です。

技術書を辞書的に使うと先ほど書きましたが、自分が持っている引き出しは多いに越したことはありません。

 

アウトプットをする

アウトプットをすると決めておけば、何をアウトプットしよう、と自ずと考えながら読むようになります。

僕はこれから読んだ技術書は基本的に全てブログにアウトプットしていこうと思っています。

目標は毎週1冊!

 

おわりに

いかがだったでしょうか。

技術書の読み方を教わったので、ここから更にガツガツ読んでいこうと思います。

ご意見・ご感想や、みなさんの技術書の読み方についても教えていただけると嬉しいです!

先月1ヶ月で読んだ13冊の技術書についてはこちらの記事にまとめているので、是非参考にしてみてください。

ysk-pro.hatenablog.com

【保存版】Railsエンジニアとして内定後、実務で必要とされる知識をつけるために1ヶ月で必死で読んだ13冊

はじめに

こんにちは。ゆうすけです。

僕はRailsエンジニアとして内定後、勤務が始まるまでの1ヶ月で技術書13冊(金額にして3.4万円(汗))を読んできました。

内定先のマネージャーにおすすめされた本も多くRailsエンジニアに転職を検討されている方実務レベルの知識を習得したいという方の参考になればと思い、1ヶ月で読んできた本を紹介します。

無料でPDFが公開されているものもあるので、是非参考にしてみてください。

当然ですが1ヶ月で全てを理解出来た訳ではなく、今後繰り返し読んでいこうと思っているので、自分の現状の備忘も含めて書きました。

f:id:ysk_pro:20180629154643j:plain

読んだ本

基礎知識

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

kindle版無し / 3周(何周読んだか) / 理解度:高 / ボリューム:中

タイトルにもあるように、HTTP、URL、HTML、RESTなど曖昧な理解だったものが分かりやすく解説してあり、僕に欠落していたWebの知識を一気に入れることができ、とても良い本でした。

 3周読みましたが、定期的に読み返して完全に知識を定着させる予定です。

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

 

  

プログラミング一般

プリンシプル オブ プログラミング3年目までに身につけたい一生役立つ101の原理原則

kindle版有り / 1周 / 理解度:高 / ボリューム:中

この本は今の自分に刺さることが多く書いてあり、実践していきたいことがたくさんあったので、別のブログ記事にまとめました。

ysk-pro.hatenablog.com

 

 オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方

kindle版有り / 1周 / 理解度:低 / ボリューム:大

 

Ruby

プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発デバッグ技法まで

 kindle版有り / 1周 / 理解度:高 / ボリューム:大

Rubyについての新しい学びが多く、定期的に読み返そうと思っている本です。

 

なるほどUnixプロセス ― Rubyで学ぶUnixの基礎

 電子書籍のみ(kindleでは無い) / 1周 / 理解度:低 / ボリューム:大

tatsu-zine.com

 

Rails関連

パーフェクト Ruby on Rails

kindle版有り / 1周 / 理解度:中 / ボリューム:大

パーフェクトRuby on Rails

パーフェクトRuby on Rails

 

 

Everyday Rails - RSpecによるRailsテスト入門

電子書籍のみ(kindleでは無い) / 1周 / 理解度:中 / ボリューム:中

内定先で使われているRSpecについて、実例が多く使われていたので、基本的なところはしっかり理解できました。

leanpub.com

 

データベース

 SQL 第2版 ゼロからはじめるデータベース操作

kindle版有り / 1周 / 理解度:高 / ボリューム:小

SQL 第2版 ゼロからはじめるデータベース操作

SQL 第2版 ゼロからはじめるデータベース操作

 

 

 現場で使える MySQL

kindle版無し / 1周 / 理解度:低 / ボリューム:中 

現場で使える MySQL (DB Magazine SELECTION)

現場で使える MySQL (DB Magazine SELECTION)

 

 

 実践ハイパフォーマンスMySQL 第3版

kindle版無し / 1周 / 理解度:低 / ボリューム:特大

内定先のマネージャー曰く、この本が理解できれば10年間は食べていける高度で実用的な内容、とのことです。頑張ります。

実践ハイパフォーマンスMySQL 第3版

実践ハイパフォーマンスMySQL 第3版

 

 

webセキュリティ

安全なウェブサイトの作り方

PDF無料 / 3周 / 理解度:高 / ボリューム:小

こちらと、もう一つ下の安全なSQLの呼び出し方は、IPA独立行政法人 情報処理推進機構)が発行しているもので、以下のURLからPDFが無料でダウンロードできます

かなり分かりやすくシンプルに説明してありました。

https://www.ipa.go.jp/files/000017316.pdf

 

安全なSQLの呼び出し方

PDF無料 / 2周 / 理解度:中 / ボリューム:小

https://www.ipa.go.jp/files/000017320.pdf

 

体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践

kindle版有り / 1周 / 理解度:高  / ボリューム:大

 

 

おわりに

いかがでしたでしょうか。

皆さんが読んだことがある本もあったのではないでしょうか。

なんとか1ヶ月で13冊読みましたが、理解度は本によって様々でこれから時間をかけて繰り返し読んでいこうと思っています。

少なくとも身銭を切って大量の情報に触れたことで、知識の大幅な底上げになったと感じています。

プログラミング初学者の方には、「理解度:高」となっている書籍は僕でも理解することができてとても為になった本なのでオススメです!

個人的には、すぐには理解できなくても背伸びしてレベルの高い技術書にトライしていくことも大事だと思っています。

知識豊富で頼られるエンジニアに早くなれるように一緒に頑張りましょう!!

デザイン素人の僕が、Webサービスを最低限のデザインにするためにやったこと

こんにちは。ゆうすけです。

僕はプログラミングを始めて、初めて作ったwebサービスを使ってRailsの自社サービス開発エンジニアに転職することができたのですが、そのサービスのデザインを褒めていただけることが多く、どのようにデザインをしたのかをよく聞かれるのでまとめてみました。

f:id:ysk_pro:20180628141438j:plain

人は見た目が9割と言うように、webサービスもぱっと見の見た目がとても重要なので、これから初めてwebサービスを作る方・今作っている方の参考になれば嬉しいです。

 

まず、僕が作ったサービスはこちらです。

www.jobmiru.com

サービスの詳細についてはこちらのブログ記事に書きましたので、ご興味ある方はご覧ください。

ysk-pro.hatenablog.com

 

以下、僕がやったことを書いていきます。

デザインテンプレートを使用した

当然ですが、ユーザーがアクセスして一番初めに見るトップページのデザインが最も重要です。

テンプレートを使えば、なんと一瞬でおしゃれなトップページに仕上がります。

僕がお世話になったのはこちらのサイトです。

Start Bootstrap - Free Bootstrap Themes and Templates

おしゃれなテンプレートを無料で使うことができます、、、スゴい。

こちらのサイトの「Agency」というデザインを使用しました。

以下実例です。

<僕のサイト>

f:id:ysk_pro:20180625162515p:plain

f:id:ysk_pro:20180625162527p:plain

<使ったテンプレート>

f:id:ysk_pro:20180625162620p:plain

f:id:ysk_pro:20180625162553p:plain

ほぼそのまんまじゃねえか、と突っ込んでいただけたと思います。

でもそれでいいんです。

テンプレートを使ったかどうかなんて、余程のテンプレートマニアでない限り分かりません(多分)。

実際にほぼそのまま使っている僕のデザインでも多くの方に褒めていただくことができました。

 

テンプレートの導入はとても簡単で、上記サイトからcssファイルをダウンロードできるので、そのcssファイルを自分のコードへコピペするだけです。

慣れれば10分くらいでできるはずです。

驚くべきコスパです!

 

フィードバックを出来る限り多くもらった

機能に関してもですが、デザインに関しても未完成の状態からフィードバックを可能な限り多くもらうことを重視しました。

一例ですが、デザインテンプレートを導入した当初のモバイル表示は以下の通りでした。

f:id:ysk_pro:20180626165616p:plain

ここから複数の方に以下フィードバックをいただきました。

背景の色が薄いので文字が見づらい。

②ボタン(2箇所)の黄色が強すぎる

③ロゴ、メッセージのフォントが細い

④画像の周りの隙間はいらない

最終的にはこのようになりました。

f:id:ysk_pro:20180626165748p:plain

 かなり良くなっていませんか…?

この他にも自分では気づけていない点に多く気づかせていただきとっても有意義でした。

 

僕の場合、Twitterでフィードバックをいただける方を呼びかけたところ20人近くの優しい方が応じてくださってフィードバックをいただくことができ、デザインを大幅に改善することができました。

 

Bootstrapのボタンを変えた

デザイン素人の味方 Bootstrapを使っている方も多いと思います。

もちろん僕も使っています。

僕の個人的な意見なのですが、Bootstrapはとっても便利でほんとに素晴らしいんですけど、ボタンのデザインがいまいちなんですよね、、、

先ほど添付したモバイル版の変更前のボタンがBootstrapなのですが、これを変えるだけでかなり印象が変わったと思います。

「ボタン css」と検索すると素晴らしいボタンデザインのcssがたくさんに出てくるので、そこから自分が気に入ったものを代わりに使うとデザインのレベルがグッと上がると思います。

 

アイコンを多く使った

アイコンというのはこのページでいう「🔍」「✔️」「🖤」「★」「💬」のことです。

f:id:ysk_pro:20180626185955p:plain

アイコンがあるだけでそれっぽくならないですかね、、、?

「Font Awesome」を使えば簡単に導入できます。

 

おわりに

まとめると、僕が考えるwebサービスを最低限のデザインにするための最短ルートは以下の通りです。

デザインテンプレートを使って最低限のデザインを作る

→ 多くの方にフィードバックをもらって修正する

→ ボタンやアイコンなど細かい点を修正していく

 

僕はこの方法で作ったサービス(Jobmiru)を使って、プログラミング歴6ヶ月ながら自社サービスのRailsエンジニアになることができました。

その時の転職活動についてはこちらに書いています。

note.mu

 

冒頭にも書いた通り、デザインがある程度整っていれば、初めて作ったサービスでも「おおっ」と思わせることができるはずです。

もしフィードバックが必要な方は僕で良ければいつでも協力させていただきますのでお気軽に声をかけてください!皆さんの作ったサービスが見たいです!

デザインを恐れず、サービス作りを楽しみましょう!!