逆に構造を活かして、エンジニアとして輝いていく

これは柳川慶太さんの「ノッカリアドカレPart4」23日目の記事です。
「仕事の上達を阻む構造について」という記事を読んでいて、「あーわかるわかる」と共感できるところが多々ありました。
記事では構造に飲み込まれないようにする話が語られていますが、個人レベルの話で言うと、私はその構造に飲み込まれず、むしろ構造を活かして、幸せなエンジニアライフを送れているなと感じています。数年の振り返りも少しだけ混ぜつつ、ノッカリをしようと思います。
分業せず、フルサイクルエンジニアとして生きていくこと
フルサイクルエンジニアについては下記のリンクを参照してください。
最初、フルサイクルエンジニアというキャリアを見つけた時は「これだ!!」と思いました。
- もともと一つのスキルに特化するより、複数のスキルの掛け合わせで戦う方が成果が出るタイプだった
- 課題解決の領域を絞るよりも、ソフトウェア開発の全サイクルの中から有用な課題を見つける方が、個人的にはハードルが低かった
- 世の中には「分業したい」エンジニアが多いことに気づき、差別化を図れると思った
もちろん「分業したい」エンジニアも有用だと思います。あくまで自身の特性から考えると、私が一番信頼と実績を獲得しやすいのがフルサイクルエンジニアだった、というだけです。
そして生成AI時代、全部をやるフルサイクルエンジニアにとってこれほど強い武器はありません。 今後も取れる選択肢を増やし、少しでも多く「全部やる」を実践してバリューを出していきたいです。
プライベートにコミュニティを混ぜ、仕事とプライベートで相乗効果を出していく
新卒時代から、エンジニアとしてできる限りどこでも通用する力が欲しいと思っていました。
元々器用なタイプではないので、最初からワークライフバランスを優先するのではなく、若いうちから投資をし続けて「キャリア的な複利」を得たほうがよい。それが早くから得た結論でした。
しかし自分の特性上、楽しみながらでないと続きません。そこでモチベーションを維持するために飛び込んだのが、技術コミュニティ主催のイベントやカンファレンスでした。
やがて登壇、イベントスタッフ、企業ブースなども担当するようになり、2024年・2025年には「PHPカンファレンス」という来場者1000人規模の技術カンファレンスで実行委員長を務めることになりました。
営利組織ではないので上下関係はありませんが、スタッフ合計100人規模の組織で自分が「ラストマン(最終責任者)」になる経験は、得ようと思ってもなかなか得られるものではありません。
この経験はラストマンシップとして、プロダクト開発をリードしていく上で必要なマインドの醸成に大きく役立っています。
出社した時に「越境」への伏線を張り続ける
突然ですが、私の強みは「キャラクター」と「(世間一般と比べた)素直さ」の2つです。他の長所はこの2つの副産物でしかないと考えています。
キャラクターを押し出したコミュニケーションをする自分は、チーム内外問わず、カジュアルな情報収集や意思決定が得意です。 自分の強みをより活かすには、文字情報以外の要素も使える対面コミュニケーションが最適だと考えました。 そう考えると、出社した時に積極的にコミュニケーションを取るほうが効率が良いのです。
とはいえ、単に作業に集中したい日もあり、そういう日はリモートのほうが捗ります。 リモートもする、出社もする。このハイブリッドなスタイルが、自分が一番やりやすい方法だと感じています。
日々の学習は長期目線で稼げる副業であると捉える
日々の学習で得た知識や知恵は、エンジニアリングの基礎力につながり、自信を持って行動する助けになりました。そして自信を持って行動して得た学びが、また日々の学習につながります。
技術イベントやカンファレンスで学んだことを業務に活かし、逆に業務で得た知識を登壇という形でアウトプットする。 体系的に学ぶために資格勉強をし、その知識を業務に投入し、実務でしかわからない学びを得てさらに理解を深める。
そうしていくうちに、学習したことが成果に繋がり、給料が上がることも多々ありました。なんなら登壇をきっかけに、執筆の副業をしたこともあります。
こういった好循環から、私は「日々の学習は長期目線で稼げる副業である」という価値観を持っています。 ただ、前提として「本業に活かす」ことがあるので、厳密に言うと副業ではなく、日々の学習コストを本業で回収していると言えるのかもしれません。
最後に
今回の話は個人レベルのことばかりでしたが、言いたいことは、「構造を理解すれば、戦略的に活かすことも可能である」ということです。
もっと上手く構造を活かして、力をつけていきたいですね。まだまだ頑張ります。
LaravelのwhereRawで安易にOR句を使ってはいけない
この記事は、Qiita の Laravel Advent Calendar 2020 20日目の記事です。
LaravelのEloquentやQueryBuilderで使えるwhereRawですが、安易にOR句を使うと落とし穴にはまることに気がつきました。
今回はその落とし穴と回避策について解説します。
TL;DR
- LaravelのwhereRawでOR句を使うと、SoftDeleteが考慮されなくなったり意図しない条件が実行される可能性がある
- whereRawでは括弧を自動的には追加しないため、
whereRaw("A OR B and C")と記述した時に発行されるクエリはWHERE A or (B and C)となってしまう - OR句を使うときはクロージャを使う。どうしても
whereRawを使いたいときはwhereRaw("(A OR B)")と記述する
なぜwhereRawでOR句を使ってはいけないのか?
例えばwhereRaw('A OR B')というクエリを実行すると、WHERE A OR BというSQL文が発行されます。括弧を記述していないため、WHERE (A OR B)というSQL文は発行されません。
whereRawは記述されたSQL文をそのまま実行しています。なので当然といえば当然ですが、括弧を自動的に追加するなんてことはしません。
この仕様が思わぬ副作用を生むため、安易にOR句を使ってはいけないと結論づけています。
whereRawでOR句を使った時に何が起こるか?
今回使用した動作環境のPHP/Laravelのバージョンは以下の通りです。
PHP8.0 Laravel 8.19
SoftDeleteが考慮されない可能性がある
deleted_atが存在するusersテーブルで、LaravelのSoftDeleteトレイトを使った時の場合を例にします。
クロージャを使ったケースと、whereRawでOR句を使ったケースで、実際に発行されるクエリは以下のようになります。
User::where(function ($query) { $query->where('is_admin', 1) ->orWhere('is_admin', 1); })->toSql(); >>> "select * from `users` where (`is_admin` = ? or `is_admin` = ?) and `users`.`deleted_at` is null" User::whereRaw('is_admin = 1 or is_client = 1')->toSql(); >>> "select * from `users` where is_admin = 1 or is_client = 1 and `users`.`deleted_at` is null"
同じクエリになるかと思いきや、違うクエリになります。クロージャの方では括弧が自動的に挿入されますが、whereRawでは挿入されません。
結果としてwhereRawでOR句を使ったケースで発行されるクエリでは
"select * from `users` where is_admin = 1 or (is_client = 1 and `users`.`deleted_at` is null)"
と同等のSQL文が実行されてしまい、is_admin = 1 and deleted_at is not nullのレコードを抽出してしまうような条件式になってしまいます。
意図しない条件が実行される可能性がある
where句でis_admin = 1 or is_client = 1 and is_corporation という条件を実行します。
orWhereを使ったケースと、whereRawでOR句を使ったケースで、発行されるクエリは以下のようになります。
User::where(function ($query) { $query->where('is_admin', 1) ->orWhere('is_admin', 1); })->where('is_corporation', 1)->toSql(); >>> "select * from `users` where (`is_admin` = 1 or `is_admin` = 1) and `is_corporation` = 1" User::whereRaw('is_admin = 1 or is_client = 1 and is_corporation = 1')->toSql(); >>> "select * from `users` where is_admin = 1 or is_client = 1 and is_corporation = 1"
こちらも、whereRawでOR句を使ったケースで発行されるでは括弧が挿入されないため、
select * from `users` where is_admin = 1 or (is_client = 1 and is_corporation = 1)
と同等のクエリが実行されてしまい、is_admin = 1 and is_corporation = 0の条件式レコードを抽出してしまうような条件式になってしまいます。
回避策
回避策は幾つがありますが、ここでは2つの例をご紹介します。
クロージャを使う
丁寧に書くのであれば、クロージャを使うと良いです。
User::where(function ($query) { $query->where('is_admin', 1) ->orWhere('is_client', 1); })->where('is_corporation', 1)->toSql(); >>> "select * from `users` where (`is_admin` = 1 or `is_admin` = 1) and `is_corporation` = 1"
クロージャ内でwhereRawを使っても良いです。ただし、発行されるクエリがクロージャ内でorWhereを使った場合と厳密には違うので気をつけましょう。
User::where(function ($query) { $query->whereRaw('is_admin = 1 or is_client = 1'); })->where('is_corporation', 1)->toSql(); >>> "select * from `users` where (is_admin = 1 or is_client = 1) and `is_corporation` = 1"
whereRaw("(A OR B)")と記述する
どうしてもwhereRaw単品で使いたい場合は、括弧を明示してあげると上手くいきます。
User::whereRaw('(is_admin = 1 or is_client = 1) and is_corporation = 1')->toSql(); >>> "select * from `users` where (is_admin = 1 or is_client = 1) and is_corporation = 1"
おまけ:一応プルリクを出したが…
whereRaw("A OR B")と記述していても WHERE (A OR B)と自動的に括弧を追加する、という旨の改修をしてプルリクエストを出してみましたが、残念ながらマージされませんでした。
実際既存機能にどのくらい影響があるのか誰も(コミッターでも)想像つかないので、既存サービスへ影響を出さないことを優先したと考えれば納得です。
ならばドキュメントに注意書きを追加するのはどうだろう!と思ってプルリクエストを出してみましたが、こちらも残念ながらマージされませんでした。
できればこの記事を見なくても解決できる形にしたい気持ちがありましたが、残念です…
最後に
考えてみればそりゃそうなるよねって感じの仕様だとは思いますが、コードレビューだけではなかなか気づけない落とし穴だと思います。
また、OR句以外でもwhereRawで落とし穴がありそう…そんな予感がします。見つけた方は是非記事にして共有して頂けると嬉しいです!
Javascript 製のE2Eテスト(puppeteer)に纏わるちょっとした工夫
この記事は、ソフトウェアテストの小ネタ Qiita Advent Calendar 2019 の24日目の記事です。 puppeteer を触っているときにちょっとした工夫を2つほど思いついたので、コード例と共に記事にしようと思います。
テスト部分を try ~ catch ~ finally で括ると、テストに落ちた時や終了した時の処理をカスタマイズできる
puppeteer は node 製のライブラリなので、javascript で使われている try ~ catch ~ finally句が使用できます。
テスト部分を try ~ catch ~ finally 句で括ると、catch 句ではテストに落ちた時の処理を、finally 句では終了した時の処理をカスタマイズできます。
コード例
import Puppeteer from 'puppeteer'; import test from 'ava'; test.serial('ログイン_成功', async (t) => { const browser = await Puppeteer.launch({ "ignoreHTTPSErrors" : true, }); const page = await browser.newPage(); try { await page.goto("https://hoge.com"); await page.type(".mail-address", "hoge@huga.jp"); await page.waitFor(500); await page.type('.password', "test"); await page.waitFor(500); await page.click('.login'); await page.waitFor('.logout'); const result = await page.evaluate(() => { return document.querySelector('.logout').innerHTML; }); t.true(result.includes('ログアウト')); } catch (e) { // テストに失敗したら、スクリーンショットを撮って保存する const todayDateTime = new Date(); const formatTodayDateTime = String(todayDateTime.getFullYear()) + String(todayDateTime.getMonth() + 1) + String(todayDateTime.getDate()) + String(todayDateTime.getHours()) + String(todayDateTime.getMinutes()); + String(todayDateTime.getSeconds()); await page.screenshot({ path: 'screenshot/' + formatTodayDateTime + '_error_login.png', fullPage: true }); t.fail('ログインテストに失敗しました。スクリーンショットをご確認ください。\nエラーメッセージ内容:' + e.message); } finally { // テストに成功しようが失敗しようがブラウザは閉じる await browser.close(); } });
私は上記のように、「失敗した時はスクリーンショットを取って保存する」「テスト終了した時は必ずブラウザを閉じる」処理を追加しています。
環境によって違う値は、定数ファイルに保存しておくと管理が楽
ログインIDやパスワードといった環境ごとに値が違う場合は、定数ファイルにまとめて保存すると管理が楽になります。 仮にテストデータのリセットが行われたとしても、1カ所直すだけですむためです。
私は configと呼ばれる、環境変数(env)によって定数の値を変えるライブラリを使っています。
コード例
test.js
import Puppeteer from 'puppeteer'; import test from 'ava'; test.serial('ログイン_成功', async (t) => { const browser = await Puppeteer.launch({ "ignoreHTTPSErrors" : true, }); const page = await browser.newPage(); await page.goto("https://hoge.com"); await page.type(".mail-address", config.get("front.user.mail") ); await page.waitFor(500); await page.type('.password', config.get("front.user.password")); await page.waitFor(500); await page.click('.login'); await page.waitFor('.logout'); const result = await page.evaluate(() => { return document.querySelector('.logout').innerHTML; }); t.true(result.includes('ログアウト')); await browser.close(); });
testing.json
{ "front": { "user": { "mail": "hoge@huga.jp", "password": "Test2" }, }
staging.json
{ "front": { "user": { "mail": "piyo@foo.jp", "password": "Test2" }, }
package.json
{ "name": "e2e-test", "version": "1.0.0", "description": "", "scripts": { "test_testing": "NODE_ENV=testing ava --verbose", "test_staging": "NODE_ENV=staging ava --verbose" }, "devDependencies": { "ava": "*", "config": "*", "puppeteer": "*" } }
テスト実行時に NODE_ENV という環境変数を使って、使用する定数ファイルを指定しています。
改めて Laravel/framework のコントリビュートガイドを読んでみた
Qiita Laravel #2 Advent Calendar 2019 23日目の記事です。
過去に Laravel/framework にてコントリビュートをしたことがありましたが、
割と雰囲気でコントリビュートしていた感があったので改めてコントリビュートガイドを読み込んでみようと思い立った次第でございます。
ドキュメントを読み込む
Laravel/framework にはコントリビュートガイドが存在するので、コントリビュートガイドを読みつつ個人的に補足すべきところを補足してみます。
Bug Reports
不具合に関する報告は各 Repository に Pull Request を作成することで対応します。
ただ、Pull Request と言ってもバグ票代わりになるものなので、他のコントリビューターでも簡単にバグが再現・修正できるよう明確にしなければなりません。
「不具合の修正には、バグの報告者とコントリビューターたちで力を合わせて解決する」というスタンスのようですね。
当たり前といえば当たり前ですが、新規機能作成や仕様変更はバグレポートに含まれません。その場合は Core Development Discussion を読みましょう。
Pull Request をざっと眺めてみると、いきなり解決案となるコミットを提示していることが多いです。
「不具合を見つけたけど、どう解決するかまではわからんな…?」と思ったら、以下のように Issue を立ててみると良いかもしれません。
あるいは Laravel Discord server の #internals チャンネル で話してみるのも良いでしょう!
Support Questions
Laravel の使い方に関する質問や相談は、 Laracasts Forums や Laravel.io Forums などで受け付けるようです。
Issue をざっと眺めると、Laravel の使い方に関する質問や相談のパターンで issue が結構作成されています。(そのあと以下のように他のコントリビューターに Laracasts Forums や Laravel.io Forums などへ促された後、closed されるケースが多いです)
Core Development Discussion
新規機能作成や仕様変更の場合は、 Pull Request の作成より前に議論を行う流れがあります。
具体的なコード例がある場合は、laravel/ideasで issue を立て、議論しましょう。
実装できるのであれば、以下のように Pull Request も同時に作ると良いです。
議論が行われてからマージされると思いますので、他の人が Pull Request を作成する前に作成しましょう。(テストコードの実装も忘れずに!)
具体的なコードがないうちは、Laravel Discord server の #internals チャンネルで話してみましょう!
Taylor さんに話しかける良いチャンスでもあるので、話しかけてみるのもアリですね!
Which Branch?
基本的にコントリビュートで使うブランチは主に3種類です。
- 現行の LTS のブランチ:サポートポリシーを確認しましょう
- 最新の安定ブランチ:数値表記されたブランチの中で一番最新のブランチ(default ブランチに設定されていることが多いです)
- 現在開発中のブランチ:master ブランチ
不具合修正は、基本的に最新の安定ブランチ or LTSブランチ
後方互換性があるマイナー機能は、最新の安定ブランチ
それ以外は、現在開発中のブランチ
ということになります!
これもわからなければ、 Laravel Discord server の #internals チャンネルで話してみましょう!
Compiled Assets
コンパイル済みのファイルをメンテナ(taylor さんなど)がレビューしない以上、
Pull request 上でコンパイル済みの大量コードを含むファイルが表示されるのは無意味です。
少しでもレビューしやすくするため、コンパイル済みのファイルを含めないようにしましょう。
Security Vulnerabilities
セキュリティ脆弱性を見つけたときは脆弱性を突かれる前になるべく早く修正しなければならない他、
対応が完了するまで大っぴらにするわけにはいきません。
そのため、セキュリティ脆弱性に関しては taylor さんにメールを送信するという方法を用いているわけですね。
Coding Style
Laravelは PSR-2 コーディング規約と PSR-4 オートローディング規約に準拠しています。
ただし、StyleCI によって自動で修正されるようなので、あまり気にしなくても良いかと思います。
Code of Conduct
こちらで特に補足することはありません。コントリビュートする際のマインドとして、大切なことなのでしっかり読みましょう。
最後に
私も含めコントリビュートガイドを見る前に、いきなりコントリビュートしてしまう人は多々います。 コントリビュートをする前に、まずはドキュメントと当記事を落ち着いて読むことをオススメします!(自戒の意味も込めて😇)
PHPerKaigi 2019 に当日スタッフとスピーカーとして参加してきたので振り返ったった
PHPerKaigi 2019?
2019年3月29日(金)〜 3月31日(日)はPHPerたちのお祭りです! この一文につきると思います!
他の技術系イベントと比べても参加者を楽しませるコンテンツが多数用意してあり、(いい意味で)異色の技術系イベントです!
発表内容共有
今回は LT スピーカーとしても参加したので、振り返りの前にスライドの共有をします!
後日発表時の動画もアップロードされるはずなので、アップロードされ次第こちらの記事にURLを貼り付けます!
振り返り
それじゃあまた振り返りをします!振り返り方法は、例のごとく YKPWT で行います
ただ、前回の振り返りだと詳細に書きすぎたので、少し簡潔にします!
やったこと
- 当日スタッフ
- 会場設営
- ノベルティを用意する作業
- トラックA の進行
- LTスピーカー
- 本編 LT
- 懇親会 LT
- 参加者
- セッション聴講
- 懇親会参加
- PHPreParty, PHPer茶会, 懇親会, PHPostParty
Keep
当日スタッフ
- 3日間という初めての長期間スタッフだったが、無事終えられた
- 指示された作業よりも、自分で考えて(工夫して)作業した内容の方が多かった
- 一部の当日スタッフらと後日ボルタリングへ行く約束をした
LTスピーカー
- 2,300人という大人数の舞台で初めて登壇した
- というか、応募時点では社外で LT をしたことがなかったが無事終えた
- 時間内にきっちり喋り終えることができた
- ちょっとしたハプニングがあったし、緊張もしていたが、素振りで練習した内容通りのことを話せた
参加者
- やはり無料でセッションや懇親会に出れるのは最高(当日スタッフ・スピーカー特典)
- 全日程の懇親会を通して交流を深められたので、通常のイベントの3倍(3日分)の繋がりが増えた
Problem
当日スタッフ
- 明らかに最終日に近づくにつれて、疲れが隠せなくなっていた(小さなミスがいくつかあった)
LTスピーカー
- 懇親会 LT で割とすべった
- pdfpc と呼ばれる、pdf のプレゼンツールを使ったが会場の設備との相性が悪くて使えなかった
- 事前に予告していた内容と少し違う内容になった
参加者
- 当日スタッフの仕事やスライド作成・修正に時間をかけすぎて、一部積極的に参加できなかったコンテンツがあった(PHPerチャレンジとか)
わかったこと
- 「最悪コアスタッフに相談すれば大丈夫」という気持ちがあると、色々いい感じに対応することができる
- そういう安心感を抱かせてくれるコアスタッフの皆さんマジすごい
- LT に問わず発表の素振り、何回もするの大事
- LT、すべることもある。そういうこともある
- 当日スタッフとはいえ、3日分も参加すると達成感とスタッフ同士の繋がり度合いが半端ない
次やること
- 自分がイベント開催者になるときは、自分がうまく立ち回るのではなく他のイベントスタッフが動きやすいように立ち回る
- 発表の素振り、何回もやっていき💪
- 特にスライドが pdf だったら、スライドの内容を覚えこむまでやる(そうでなかったら、大人しく pdf ではなく keynote とかにする)
- 次は PHP カンファレンス北海道のCfPにレギュラートーク枠で応募する
- そのためにネタを考える・作る
日頃からダジャレを言って冷たい目線を向けられることに慣れ、すべっても動じない心を身につける- 来年の PHPerKaigi も参加する
最後に
関係者、スタッフの皆さま、参加者の皆さまお疲れ様でした&ありがとうございました!
これだけ参加者を楽しませる取り組みがすごいカンファレンスは、そうそう無いと思います!!(現に知人とも「イベント運営面でお手本にしたいけど、正直再現性がわからんし、すぐ真似できなそう」って話をしました)
また次の PHPerKaigi でお会いしましょう!
avgメソッド Collectionメソッドソースコードリーディング100本ノック2本目
メソッド概要
avgメソッドは、指定したキーの平均値を返します。
<?php $average = collect([['foo' => 10], ['foo' => 10], ['foo' => 20], ['foo' => 40]])->avg('foo'); // 20 $average = collect([1, 1, 2, 4])->avg(); // 2
average メソッドも同じ処理です。
ソースコードリーディング
avg メソッド
では早速、ソースコードリーディングをやって行きましょう。
<?php /** * Get the average value of a given key. * * @param callable|string|null $callback * @return mixed */ public function avg($callback = null) { $callback = $this->valueRetriever($callback); $items = $this->map(function ($value) use ($callback) { return $callback($value); })->filter(function ($value) { return ! is_null($value); }); if ($count = $items->count()) { return $items->sum() / $count; } }
後で解説しますが valueRetriever メソッドは、$callback をコールバックとして読み取れる値に整形するメソッドです。
$callback の戻り値を、 map メソッドを使って Collection へ整形します。
戻り値が null だった時は、 Collection に含めません。 null を平均の対象へと含めないようにする意図のようですね。
最後に Collection 内の値の平均値を返す…といった処理になります。
参考:
valueRetriever メソッド
<?php /** * Get a value retrieving callback. * * @param string $value * @return callable */ protected function valueRetriever($value) { if ($this->useAsCallable($value)) { return $value; } return function ($item) use ($value) { return data_get($item, $value); }; }
$callback を、コールバックとして読み取れる値に整形するメソッドです。
最初にそもそもコールバックとして読み取れる値だったら、そのまま値を返します。
コールバックとして読み取れない値だったら、コールバックとして読み取れる無名関数を返します。例えば以下のようなコードがあったとします。
$callback = $this->valueRetriever($value) $callback($item)
この場合、 $callback($item) は以下のようになります。
$callback($item) =
function ($item) use ($value) {
return data_get($item, $value);
}
data_get は、配列やドット区切りのオブジェクトから要素(配列 or データ型の値)を取り出すヘルパメソッドになります(data_get ヘルパメソッドについては、別の記事にて解説します)。
$item が配列だったり Collection だった時のために、このような処理になっているようです。
参考:
useAsCallable メソッド
関数として呼び出し可能 かつ 文字列ではないかを返します。
呼び出し可能な関数名ではなく、関数そのものか判別したい時に使うようです。
<?php /** * Determine if the given value is callable, but not a string. * * @param mixed $value * @return bool */ protected function useAsCallable($value) { return ! is_string($value) && is_callable($value); }
最後に
この記事を書いているうちに、 Laravel 5.7 -> 5.8 へとバージョンアップしました。
もたもたしているとすぐバージョンが上がってしまい、過去に書いた Collection メソッドをまた再度検証する…なんてことになってしまうので他のメソッドもどんどん書いていこうと思います!
次は chunk メソッドです!
LaravelJPConference 当日スタッフとして人生初参加してきたので、振り返ってみた!
2/16 開催の LaravelJPConference に当日スタッフとして参加してきました! conference2019.laravel.jp
というわけで、本日laravelJPCon開催です!
— 02 (@cocoeyes02) February 15, 2019
僕も当日スタッフとして参加しますので、皆さまどうぞよろしくお願いします!
人生で初めて大規模イベントの(当日)スタッフ参加です…!当日は進行を担当していました!
もちろん LaravelJPConference も、今年初の開催なので初めての参加ですw
ですが、スタッフも含め参加者は334名だったそうです! 初開催なのにすごい!
当日の様子やセッションについては、以下を見ていただければと思います!
Laravel JP Conference 2019 スライドまとめ - Qiita
振り返り(YKPWT)
YKPWT を使って個人的な振り返りをしました! cocoeyes02.hatenadiary.jp
以下やったこと、Keep、Problem、わかったこと、次やることになります!
やったこと
- Laravel Track の準備
- 機械設備の仕様把握(PCの規格に合わせた表示変更、マイク音量調節、照明調節、空調など)
- 設営(スピーカー台設置と後方のパネルの組み立て)
- Laravel Track の進行
- スピーカー対応
- お水配布
- 疎通チェック(スピーカーのPC に合わせて)
- 司会
- アナウンス(開始前 / 開始後)
- 質疑応答
- タイムキーパー
- 機械設備操作
- 質疑応答時のマイク運び
- スピーカー対応
- Closing Talk 後の片付け
- 現状復旧
- ゴミ片付け
Keep
当日スタッフとして
- 連絡を見逃さないよう、定期的に slack で当日スタッフ用のチャンネルを見た
- 誰も機械整備の仕様について詳しく知らなかったので、分かったことを随時 slack や口頭にて共有した
- アナウンス内容を変える対応が何回かあったが、なんとか対応することができた
- 設営担当の撤去の手伝いなど、特に割り振られていない仕事も少しやった
- 初開催の LaravelJPConference だったが、大成功かつ無事終えることができた
- イベント運営の経験を経て、対応力やナレッジなど得られるものがあった
一参加者として
- Laravel や PHP 問わず知見や知識が深まった
- しかもタダで!(今回当日スタッフはチケット代無料でした )
- PHPer 界隈の知人がめっちゃ増えた(フォロワーも40人ぐらい増えた)
- 自分の OSS 活動が評価されたようにも感じたし、他の人への勧め方など知見を得られた(ういろうさん @nyamucoro ありがとうございます!)
- www.nyamucoro.com
先ほどのO君です!
— 02 (@cocoeyes02) February 16, 2019
ういろうさん( @nyamucoro )も仰っていた通り、コントリビュートは 時間がかかる / 難しいこと ではないのでまずはソースコードを読むことからオススメします!#laraveljpcon #laraveljpcon3F https://t.co/tsLLANvgDc
- お昼御飯がめっちゃおいしかった(ランチサポンサーの株式会社デザインワン・ジャパンさんありがとうございます!)
Problem
当日スタッフとして
- 事前にアナウンスのテキストを用意されていたので、iPad で確認できるよう持ってきていたが当日に iPad が初期化されていたことに気がついた 😇
- アナウンス担当時に緊張し過ぎて、その時やってたセッションの内容が頭に入ってこなかった
- Track がほぼ満員だった時、空き席への案内などの対応が満足にできなかった(コアスタッフの人に任せてしまった)
- 事前説明会で言われたタスク以上のことが、あまりできなかった気がする
- スマホの電池残量がギリギリだった(イベント終了時に7%)
一参加者として
- 恒例(?)のじゃんけんで決勝まで上がったが最後で負けた :kanashii:
分かったこと
当日スタッフとして
- イベントスタッフ用のワークスペースを用意する時、緊急連絡用のチャンネルがあるとすぐ報告できるし安心
- 持ち場が固定のスタッフは持ち場以外の状況等が把握できないので、小さな出来事でも slack で共有してあげると良い
- 会場の設備について、まだ把握していないのであればできるだけ早く理解して共有することが吉
- イベントスタッフの経験豊富な人がいると、いろいろと円滑に進む(ありがたい。。。)
- やっぱり午前中にトラブルが起きがち(逆に午後は安定する)
- 定期的に slack を見たり、ツイートしたらすぐにスマホの電池残量が減る
- 司会やばいぐらい緊張する
- 当日スタッフとして参加すると、普通の参加以上に界隈の人と仲良くなれるチャンスがある
一参加者として
- php 系のカンファレンスでやるじゃんけん大会は、前でじゃんけんをする人がなんの手を出すか予告するので、途中まではその手に勝つ手を出す
- どこで裏切られるかを推測するのが勝利の鍵
その他
- 自分のイベントアドリブ対応力の低さが露呈した
- ホスピタリティが足りない
- 経験値が足りない
- デブなので立ち仕事やると、すぐに足に疲れが出てくる
次やること
- 他のイベントにも参加して、イベントスタッフ経験を積む
- 今度は自分が進行を円滑に進められるような人へ…
- 自社のイベントスタッフやコアスタッフになることにも繋がるはず
- 小さなことでもいいので、なるべく slack に流して共有する
- ただし、緊急時の内容は、他の共有内容で流れてしまうとまずいので専用のチャンネルで共有する
- スマホ充電用のモバイルバッテリーを持っていく
- 持ち歩くことになるので、できるだけ小型の方が良い
- 前日に自分が持っていくデバイスが正常に起動しているか確認する
- 次のじゃんけん大会こそ、どこで裏切られるかを推測して景品をゲットする!!!!
- 運動しよう…
最後に
拙い個人的な振り返りの共有になってしまいましたが、全体を振り返ってみても当日スタッフ参加はとても得るものが多いです!!
他のPHPカンファレンスでも当日スタッフを募集していると思いますので、参加されたことが無い方は是非参加をお勧めします!!!