TECH PLAY

株式会社モバイルファクトリー

株式会社モバイルファクトリー の技術ブログ

223

はじめに この記事は モバイルファクトリー Advent Calendar 2019 の18日目の記事です。 こんにちは、ブロックチェーンチームのエンジニアの id:odan3240 です。 NestJS では @nestjs/swagger を用いることで、コントローラーの定義から OpenAPI (swagger) の仕様書を生成することができます。 このモジュールの使い方などは、先日の NestJS Advent Calendar 2019 に記事を投稿しましたので、そちらをご覧ください。 qiita.com 上のリンクの記事では、JSON 形式の OpenAPI の仕様書を取得する方法として http://localhost:3000/api-json にアクセスする方法を紹介しています。しかし、実際にアプリケーションを開発していく上でこの方法では CI のワークフローに組み込みにくいなどの問題があります。 この記事ではこの問題を解決する方法を紹介します。 問題の詳細 http://localhost:3000/api-json にアクセスする方法には、「バックエンドのサーバは起動している」という前提条件が必要になります。 この前提条件はかなり強い条件です。例えば MySQL などのデータストアを利用しているバックエンドのサーバを考えます。このサーバの起動時にデータストアにコネクションを張る設定をしていると、データストアの存在が前提条件に追加されます。つまり、バックエンドのサーバの他にデータストアも起動しておかないと http://localhost:3000/api-json にアクセスできず仕様書を取得することができません。 CI で OpenAPI の仕様書を出力してクライアントのコードを自動生成を行うワークフローを組んでいる場合、CI にデータストアを用意する必要があるため、手間がかかります。 解決方法 @nestjs/swagger は Controller の実装の定義から OpenAPI の仕様書を生成するモジュールですので、原理的にはサーバの起動なしに Controller のソースコードから仕様書を生成できるはずです。この記事で紹介する解決方法は、NestJS の DI 機構を用いて、これを実現します。 @nestjs/testing には Test.createTestingModule という関数があります。これを使うとクラスのモックを簡単に差し込むことができます。 Testing | NestJS - A progressive Node.js framework 具体的なコードは サンプルリポジトリ の src/openapi/generate.ts にあります。 ポイントは次の通りです。 Reflect.getMetadata を使って AppModule の Controller と Provider を取得する これらを createTestingModule に引数に渡す Provider は useValue でモックする import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger' ; import { Test } from '@nestjs/testing' ; import { AppModule } from '../app.module' ; async function bootstrap (): Promise < void > { const controllers = Reflect .getMetadata( 'controllers' , AppModule); const providers = Reflect .getMetadata( 'providers' , AppModule); const mockedProviders = providers. map ( provider => { return { provide : provider. name , useValue : {} , } ; } ); const testingModule = await Test.createTestingModule( { controllers : controllers , providers : mockedProviders, } ).compile(); const app = await testingModule.createNestApplication(); const options = new DocumentBuilder() .setTitle( 'アドベントカレンダーサンプル' ) .build(); const document = SwaggerModule.createDocument(app, options); console .error( JSON . stringify ( document , null , 2 )); } bootstrap(); このファイルを ts-node で実行すると JSON 形式の OpenAPI の仕様書を取得することができます。 $ yarn ts-node src/openapi/generate.ts > /dev/null { "openapi": "3.0.0", "info": { "title": "アドベントカレンダーサンプル", "description": "", "version": "1.0.0", "contact": {} }, "tags": [], "servers": [], "components": {}, "paths": { "/": { "get": { "operationId": "getHello", "responses": { "200": { "description": "" } } } } } } 終わりに NestJS の DI 機構を用いて Controller が依存するクラスをモックすることで、バックエンドのサーバを起動せずに OpenAPI の仕様書を取得する方法を紹介しました。これにより、データストアなどの他のミドルウェアに対する依存がなくなったため、CI のワークフローに組み込みやすくなりました。
アバター
こんにちは、 モバイルファクトリー Advent Calendar 2019 17日目担当の yunagi_n です。 さて、2019年も暮れになった今、 PixiJS や Konva など、便利な Canvas フレームワークがありますが、 このたび初めて生の Canvas (Context2D) を触ることになりまして、 動作確認中などで気がついた点などがいくつかあったので紹介します。 基本的にはドキュメントをしっかり読めば良いのですが、普段は気がつかない部分もありましたので、記事にしました。 これから生の Canvas を触るぞ!という方の参考になれば嬉しいです。 requestAnimationFrame の実行頻度は端末依存 Canvas でアニメーションをさせたい場合、 Window.requestAnimationFrame を使ってループを実装します。 ここで指定するコールバック関数は一般的には秒間60回呼ばれるのですが、ここでドキュメントを引用すると このコールバックの回数は、たいてい毎秒 60 回ですが、一般的に多くのブラウザーでは W3C の勧告に従って、ディスプレイのリフレッシュレートに合わせて行われます。 とあるように、実際には端末のリフレッシュレートに依存しています。 そのため、1秒間に60回程度呼ばれる前提で処理を記述すると、一部のハイエンド端末では、 倍速再生されてしまう、という事態が発生します。 実際に社内の一部の端末では倍速に再生されてしまうという事態が発生していました。 最近では、ハイエンド端末ではリフレッシュレートが 120Hz ということも度々ありますので、 気をつける必要があります。 高解像度ディスプレイへの対応 Canvas で描画したものは、一般的な画像と同じように描画されます。 つまりは、こちらも画像と同様に、 Retina / HiDPI などのような高解像度ディスプレイへの対応が必要になります。 対応方法としては、 CSS などでの指定サイズに対して2倍のサイズで予め Canvas を生成するか、 Window.devicePixelRatio を使用して、動的に描画サイズを変更する方法があります。 なお、後者の方法では 一部の Android 端末で落ちるバグがあるよう なので、注意が必要です。 Canvas の解放 Canvas で使用した画像リソースや OffScreen Canvas などは、描画していた DOM を消し飛ばしただけでは行われません。 例えば、 Vue の v-if などで何度も表示・非表示を繰り返した場合、 使用してたメモリリソースにも寄りますが数回程度繰り返しただけでメモリリークが発生してしまいます。 メモリ解放は下のようにすることで出来ます。 // Context2D を作成するとき const context = canvas . getContext ( "2d" , { storage : "discardable" }) ; // Canvas を破棄するとき delete context ; canvas . height = 0 ; canvas . width = 0 ; canvas . remove () ; delete canvas ; まとめ requestAnimationFrame は (最近の端末では特に) 秒間60回呼ばれるわけでは無いので気をつけよう 高解像度ディスプレイへの対応は画像同様に行おう 使用したリソースはしっかり解放しよう でした。 特に最後のメモリ解放については、普段使っている分にはなかなか気がつかないので、お気を付けください。
アバター
はじめに モバイルファクトリー Advent Calendar 2019 の16日目担当の shioiyan です。 モバイルファクトリーには部活動制度があり、自分はゲームジャム部という不定期にゲームジャムを行ったりする部活に所属しています。 最近ゲームジャム部で、.NET CoreおよびUnity用のリアルタイム/APIエンジンの MagicOnion を使ってUnityでリアルタイム通信を実装してみたのでその方法を紹介してみます。 この記事を読んでわかること MagicOnionのStreamingHubを使ったリアルタイム通信の実装方法がわかる MagicOnionを利用するメリット クライアントとサーバでAPIの定義を共有できる 共有したインターフェイスを介して通信できるため, 直接クライアントからサーバ, サーバからクライアントのコードを呼び出すことができる C#のオブジェクトをMessgePackによって直接やりとりできる クライアントとサーバで通信内容の齟齬が発生しない, 通信したデータをそのまま利用可能なため効率的 通信のためにデータを加工することをあまり考えなくて良い クライアントとサーバを共通の言語(C#)で開発でき, 入力補完の恩恵を受けられます。 インターフェイスの実装漏れやメソッド名, 引数のミスなどが発生するとコンパイルエラーになるためエラーに気がつくことが容易です。 APIの定義や通信に利用するデータを共有できるため, クライアントとサーバで通信しているという感覚をあまり持たずに実装することが可能です。 今回作るもの プレイヤーの位置や向きが複数のクライアントで同期されたゲーム 名前入力, キャラクター選択画面 プレイヤーが同期されるゲーム画面 開発バージョン Unity v2019.1.14f1 MagicOnion 2.6.2 MessagePack 1.7.3.7 実装 MagicOnionをUnityプロジェクトに導入するにはMagicOnion, MessagePack for C#, gRPC packageの導入が必要です。 今回導入手順については割愛します。 処理の流れ 今回は大きく分けて, 「ルームに参加」「キャラクター移動の同期」を実装します。 まずはじめに処理の流れを紹介します。 ルームに参加し, 参加者をクライアントに表示 クライアント(SceneA): 名前入力とキャラクター選択をする クライアント: シーン切り替え(SceneA -> SceneB) ※以下SceneB クライアント: サーバに接続し, 入力した名前とキャラクターをサーバに送信 サーバ: Playerクラスを生成し, ルームに参加してルームを保持 サーバ: ルームの参加者情報を返却 クライアント: ルームの参加者情報を元にプレイヤー(GameObject)を生成 移動した自キャラクターを他のクライアントに同期 クライアント: キャラクターを移動 クライアント: n秒に一度サーバにプレイヤーの位置と向きを送信 サーバ: 保持しているPlayerを更新し、更新したPlayerを返却 クライアント: 返却されたPlayerの位置や向きを使ってプレイヤー(GameObject)を移動させる 自分がクライアントで操作するプレイヤーのGameObjectの情報をサーバに送信し, 他のプレイヤーの情報を受け取り, クライアントで他プレイヤーのGameObjectを描画します。 ポイントはクライアント<->サーバでPlayer情報をやりとりし, 各クライアントでの同期を行うことです。 クライアントとサーバ共通のコード クライアント<->サーバで送信するPlayerクラスを作成 using MessagePack; using UnityEngine; namespace Sample.Shared.MessagePackObjects { [MessagePackObject] public class Player { [Key( 0 )] public string Name { get ; set ; } [Key( 1 )] public Vector3 Position { get ; set ; } [Key( 2 )] public Quaternion Rotation { get ; set ; } [Key( 3 )] public string UUID { get ; set ; } [Key( 4 )] public PlayerConfig.PrefabName PrefabName { get ; set ; } } } public class PlayerConfig { public enum PrefabName { Prefab1, Prefeb2 } } 上記のような独自な型やVector3などもMessagePackで送信でき, クライアントとサーバでそのまま使うことができます。 クライアントとサーバと共有するインターフェイスを定義 クライアント -> サーバの通信を行うHubと, サーバ -> クライアントの通信を行うReceiverのインターフェイスを定義します。 Hubはサーバ, Receiverはクライアントで実装し, それぞれクライアント, サーバから呼ばれることになります。 using MagicOnion; using Sample.Shared.MessagePackObjects; using System.Threading.Tasks; using UnityEngine; namespace Sample.Shared.Hubs { /// < summary > /// クライアント -> サーバ /// </ summary > public interface IGameHub : IStreamingHub<IGameHub, IGameHubReceiver> { /// < summary > /// ゲームに接続することをサーバに伝える /// </ summary > Task<Player[]> JoinAsync( string name, PlayerConfig.PrefabName prefabName); /// < summary > /// ゲームから切断することをサーバに伝える /// </ summary > Task LeaveAsync(); /// < summary > /// 移動したことをサーバに伝える /// </ summary > Task MoveAsync(Vector3 position, Quaternion rotation); } /// < summary > /// サーバ -> クライアント /// </ summary > public interface IGameHubReceiver { /// < summary > /// 誰かがゲームに接続したことをクライアントに伝える /// </ summary > void OnJoin(Player player); /// < summary > /// 誰かがゲームから切断したことをクライアントに伝える /// </ summary > void OnLeave( string uuid); /// < summary > /// 誰かが移動した事をクライアントに伝える /// </ summary > void OnMove(Player player); } } クライアントの実装 クライアントでは, サーバから呼ばれるReceiverの実装を行います。 クライアントからはサーバとの接続とサーバで実装されているHubの呼び出しを行います。 サーバから受け取った情報を元にクライアントを描画します。 using Grpc.Core; using MagicOnion.Client; ... namespace Sample { public class GameController : MonoBehaviour, IGameHubReceiver { private Channel channel; private IGameHub gameHub; private List<ClientPlayer> clientPlayers = new List<ClientPlayer>(); // ルームのプレイヤー情報とクライアントで利用するGameObjectを保持 private ClientPlayer _myClientPlayer = null ; // 操作するプレイヤー public float intervalSeconds; public string Name = "" ; // 入力されてプレイヤー名 public PlayerConfig.PrefabName PrefabName; // プレイヤーが選んだキャラクター async void Start() { // サーバに接続 this .channel = new Channel( "localhost:12345" , ChannelCredentials.Insecure); this .gameHub = StreamingHubClient.Connect<IGameHub, IGameHubReceiver>( this .channel, this ); // ルームに参加してルームの参加者一覧を受け取る Player[] players = await this .gameHub.JoinAsync( this .Name, this .PrefabName); // ルーム参加者情報を元にプレイヤー(GameObject)を生成 this .AddClientPlayers(players); // 一定時間ごとにサーバに位置と向きを送る this .UpdateAsObservable() .ThrottleFirst(TimeSpan.FromSeconds( this .intervalSeconds)) .Subscribe(_ => this .Move()) .AddTo( this ); } private void AddClientPlayers(Player[] players) { foreach (Player player in players) { // PlayerのPrefabName, Position, Rotationに応じてInstantiateを行う ClientPlayer clientPlayer = new ClientPlayer { GameObject = Instantiate(...), Player = player }; this .clientPlayers.Add(clientPlayer); ... } } async void Move() { // 自分の操作プレイヤーの位置と向きをサーバに送信 await this .gameHub.MoveAsync( this ._myClientPlayer.GameObject.transform.localPosition, this ._myClientPlayer.GameObject.transform.localRotation); } ... #region リアルタイム通信でサーバーから呼ばれるメソッド(IGameHubReceiverの実装) public void OnJoin(Player player) { Debug.Log( $" { player.Name } さんが入室しました" ); // 入室後, 他の人が参加したらクライアントで表示するプレイヤーを追加 AddClientPlayers( new Player[] { player }); } public void OnLeave( string uuid) { Debug.Log( $" { name } さんが退室しました" ); this .clientPlayers.RemoveAll(_ => _.Player.UUID == uuid); } public void OnMove(Player player) { ClientPlayer clientPlayer = this .GetPlayerByUUID(player.UUID); clientPlayer.Player = player; // 位置を直接上書きするとワープして見えるので滑らかに移動するためにDOTweenを使用 clientPlayer.GameObject.transform.DOLocalMove(player.Position, this .intervalSeconds); clientPlayer.GameObject.transform.DORotate(player.Rotation.eulerAngles, this .intervalSeconds); } } } using Sample.Shared.MessagePackObjects; using UnityEngine; namespace Sample { // ルームのPlayerクラスとクライアントで描画しているプレイヤーのGameObjectをまとめて管理するクラス public class ClientPlayer { public GameObject GameObject; public Player Player; } } サーバの実装 サーバでは, クライアントから呼ばれるHubの実装を行います。 クライアントが接続するルームの情報を保持し, クライアントのReceiverを呼び出します。 Receiverの呼び出しはルームに参加している全員のReceiverを呼び出す Broadcast() や自分以外のルーム参加者を対象にした BroadcastExceptSelf() などを通じて行います。( 参考 ) using MagicOnion.Server.Hubs; using Sample.Shared.Hubs; using Sample.Shared.MessagePackObjects; using System; using System.Linq; using System.Threading.Tasks; using UnityEngine; public class GameHub : StreamingHubBase<IGameHub, IGameHubReceiver>, IGameHub { IGroup room; Player me; // ルームに入室しているプレイヤー全員の情報を保持 IInMemoryStorage<Player> storage; public async Task<Player[]> JoinAsync( string name, PlayerConfig.PrefabName prefabName) { const string roomName = "Room" ; //自分の情報を作成し, 保持 me = new Player { Name = name, Position = new Vector3( 0 , 0 , 0 ), Rotation = new Quaternion( 0 , 0 , 0 , 0 ), UUID = Guid.NewGuid().ToString( "N" ), PrefabName = prefabName }; //ルームに参加し, ルームを保持 ( this .room, this .storage) = await this .Group.AddAsync(roomName, me); //参加したことを自分以外のルームに参加しているメンバーに通知 this .BroadcastExceptSelf(room).OnJoin(me); // ルームに入室している他ユーザ全員の情報を配列で取得する return this .storage.AllValues.ToArray(); } public async Task LeaveAsync() { //ルーム内のメンバーから自分を削除 await room.RemoveAsync( this .Context); //退室したことを全メンバーに通知 this .Broadcast(room).OnLeave(me.UUID); } public async Task MoveAsync(Vector3 position, Quaternion rotation) { // サーバー上の情報を更新 me.Position = position; me.Rotation = rotation; // 更新したプレイヤーの情報を自分以外のメンバーに通知 this .BroadcastExceptSelf(room).OnMove(me); } } まとめ MagicOnionを利用して, ルームに接続したクライアント同士でプレイヤーの同期を行いました。 C#でサーバのコードを書くことができ, しかもクライアントとコードを共有できるというのは新しい体験でした。 まだ色々検証しているところですが, 引き続きMagicOnionを触っていきたいと思います。
アバター
この記事は モバイルファクトリー Advent Calendar 2019 の15日目の記事です。 こんにちは.今年度よりエンジニアとして入社した新卒のmaekenです. 自分が所属している開発チームでは,モブプログラミングを開発手法の選択肢として選べるようにしています. この記事では,モブプログラミングを選択肢に入れたきっかけ,実践方法,そしてモブプログラミングの振り返り結果について紹介しようと思います. モブプログラミングとは モブプログラミング(Mob programming) とは,3人以上で1台のコンピューターを使い,1つの課題について取り組む手法です. ここで言う課題とは,開発タスクやテスト,ドキュメント作成なども対象です. モブプログラミングは,キーボードを叩く人1人( ドライバー )と,ドライバーに方針やアドバイスを伝え援助を行う人( ナビゲーター )に分かれて行います.モブの数が2人の場合,ペアプログラミングと呼ばれます. きっかけ 自分が所属している開発チームでは新卒の人が多く,それぞれの得意不得意のスキルに差がありました. また,新しい言語や新しいフレームワークを書く機会もあり,メンバーによっては全く書いたことが無いというものもありました. そこで,メンバーのスキル向上と,知識の共有を行うためにモブプログラミングを採用しました. さらに,モブプログラミングが本当に有効だったのかを振り返りによって確かめるようにしました. 実践 モブプログラミングはドライバーの作業を眺める時間ではなく, モブで(みんなで)プログラミングをする時間 です. 眺める時間にならないように,ドライバーとナビゲーターそれぞれに下記の事を意識するようにしました. ドライバー ナビゲーターから頼まれたことを実装する 今考えていることを口から出す ナビゲーター コードは書かないが,一緒に作業をする人 ドライバーの手助けをする ドライバーの躓きを助ける,先回りする それを踏まえた上で何回かモブプログラミングを行いました. ドライバー交代のタイミングや進め方について試行錯誤した結果,私達のチームでは以下のようなスタイルに落ち着きました. 朝会のときに,今日はどの作業をモブプロで行うのかをメンバー全員で確認し,時間の確認をする 1回のモブの時間は1〜2時間.それ以上行う場合は休憩を取る 時間経過(10分)でドライバーを交代する. 最初は短いと感じましたが,適度に集中できるのとテンポが生まれる時間が約10分でした. タイマーは このアプリ を使っています モブプログラミングを始める前に,ホワイトボードにこれから行う課題を細かく分割してTodoリストに書き出す. モブプログラミングの最中には,今どのTodoを行っているのか,何が終わっているのかを確認できるようにする ゴールをはっきりさせること,それをモブ全員で共通認識を得ること,ゴールを見失わないようにするため 振り返り モブプログラミングを何回かやった上で, MPI で振り返りを行いました. モブプログラミングの振り返り結果 利点 知識の共有,理解の共有 モブプログラミングをしながら自然に知識の共有,伝授が行われる 全員が同じぐらい知識を共有して持つことが出来る 新メンバーの受け入れや担当業務の引き継ぎの時にも役に立つかもしれない 他の人の作業テクニックも学べる 「えっ,VSCodeの⌘+Dめっちゃ便利じゃん!」 常にレビューができる モブプログラミングは複数人で作業内容を見ているので,常にレビューをしながら作業ができる 1人で作業する時に比べて,手戻りが少ない Todoリストで,残りの作業の確認ができる モブに関係なく,1人作業でも有効かも 強制的に集中できる 強制的に休憩できる 楽しい 困っても,周りがすぐに助けてくれる うまく動作した時の喜びも共有できる 欠点 モブが崩れると戻すのが大変 急な差し込み等でメンバーが一時的に居なくなった後,状態をもとに戻すのが大変 4人だったのが3人や2人になった時,リズムが崩れる 戻ってきたメンバーへのキャッチアップが大変 詰まると効率が悪い 全員が知らないものにぶつかってしまうと効率が悪くなる. もし全員がほぼ同じレベルの知識・スキルだと効果が薄い 全員が完全無知な場合は勉強会になってしまう 全員が全て熟知の作業の場合は,モブじゃなく分担作業の方が良い モブか分担か,選択できるようになると良い ドライバーの画面を映すモニターは大きくないとできない モブプログラミングをするためのスペースは意外と貴重 まとめ 業務でモブプログラミングを行うのは初めてでしたが,当初の期待通りスキル向上と知識の共有を得ることが出来ました. また,チームで作業をすることでチームワークも向上したように思います. 振り返りをした結果,モブプログラミングの利点と欠点が見えてきました. 現在,チームではその利点欠点を認識した上で,この作業はモブプログラミングでいくか,分担作業で行くか選択するようにしています. モブプログラミングは開発手法として有効な手段の1つだと感じました.是非,皆さんもモブプログラミングを実践してみてください.
アバター
こんにちは!ブロックチェーンチームエンジニアの pikkaman です。 去る2019年10月8日〜12日にEthererumの開発者向け国際カンファレンスであるDevcon 5が大阪南港 ATCホールで開催されました。 日々ブロックチェーンアプリの開発に取り組んでいる我々モバイルファクトリーのエンジニアとしては外せないイベントです。 今回はだいぶ遅くなってしまいましたがDevcon参加レポートをお送りします! Devconとは? DevconはEthereum Foundationが運営している開発者向け国際カンファレンスです。EthereumはBitcoinなどと同様に法定通貨と交換できる仮想通貨として知られていますが、Ethereum仮想マシン(EVM)上で実行されるスマートコントラクトを活用することで、様々な分散型アプリケーション(DApps)開発が可能になっています。 DevconではEthereum自体の開発についてだけではなく、DAppsやその開発ツール、さらには周辺の法律など多岐にわたった話題を扱っています。 そんなEthereum界の最重要イベントとも言えるDevconですが、なんと今年は日本の大阪で開催されました! 前日譚 私たちが取り組んでいるUniqys ProjectはDAppsを身近にすることをミッションとしています。そこでブロックチェーン事業を行う子会社のビットファクトリーは、Phase 0のスポンサーとしてDevcon 5を支援させていただくことになりました。 Devconの公式サイトを見るとビットファクトリーのロゴを見ることができます。 Phase 0スポンサーになったビットファクトリー (2019年12月6日14:00:00にスクリーンショットを作成) devcon.org さて、カンファレンスに参加するからには登壇したいと思うのがエンジニアの性ですよね。せっかくの日本で開催されるDevconですからUniqys Projectを認知してもらう絶好のチャンスです。 早速 Uniqys Kit と Quragé Link についてのプレゼンテーションを申し込みました。個人としてもブロックチェーンチームとしても初めての仮想通貨関係の国際カンファレンスへの登壇チャンスということで、なかなか苦労してabstractを書き上げましたが……結果は落選!残念です。結果を知らせるメールによれば1100もの応募があったようで、その中から選ばれるのは難しかったみたいです。運営から返ってきたコメントは納得のいくもので、1100もの応募がありながらひとつひとつの内容を見てコメントを返している運営の熱意はすごいですね。世界中のEthereum開発者を支援しようとする姿勢を感じました。 会場に到着! そんなわけで当日です。品川を始発の新幹線で出発し、沿線の駅の思い出を集めつつ大阪へ向かいます。新幹線から地下鉄、ニュートラムと乗り換えて会場の大阪南港ATCホールに進むのですが、会場に近づくにつれて英語を話す乗客が増え国際色が増してきます。 ちょうど技術同人誌即売会に向かって行くと気づいたら周りがエンジニアだけになるのと同じですね! そして会場外観がこちら Devcon 5 会場の大阪南港ATCホール 会場の連絡通路に大きく Devcon v と書かれているのを見るとテンションが上がってきます。写真の左側が受け付けなのですが、朝一の新幹線で行ったにもかかわらず既に人で一杯でした。 英語で受付を済ませて中に入ります。Devcon内の公用語は英語「だけ」で、日本語が通じるのは会場の警備員さんだけです。(日本人スタッフもいるようですが、区別ができません😇 ) ちなみに、受付時にNFT(Non-Fungible Token)がもらえます。ワッペンの裏にQRコードが印刷されており、読み込むと自分のアドレスにトークンを送ることができます。いかにもEthereumのカンファレンスらしいですね。 受付でもらえるWebでNFTが受け取れるワッペン さて、年々規模が大きくなっているDevconですが、今回のDevcon 5は大きなATCホールを3フロアも使って開催されました。 ATCホールのB2、1、6階を使っていました。6階へのエレベーターはいつも満員でした それにも関わらずどこにいても人混みがひどく移動するにも一苦労です。柱の前では参加者たちが立って議論しているかと思えば、そのすぐ近くの床に座り込んでコードを書いている参加者もいます。全員がいたるところで盛り上がっているものですから、発表を聞いているわけでもないのに受け取る情報量が膨大になります。私は4日間フルで参加しましたが、自分は発表したわけでもないのに、1日が終わるとくたくたになっていました。 ちなみに、さすがに疲れてしまう人がいるのか、Devconには瞑想ルームが伝統的に設置されています。もっとも、瞑想ルームで瞑想をしている人は誰一人としておらず、某「人をダメにするソファ」にもたれて寝ているか、スマホをいじっているかのどちらかでしたが(エンジニアですからね) 地下2階のメインホールの横は交流スペースとなっており、軽食が用意されていました。カステラの屋台が朝早くから営業していた他、おにぎりやパン、たこ焼き、いなり寿司、和菓子や駄菓子など「日本っぽい」ものが配られていました。たこ焼きが特に人気だったようで、新しいのが来てもすぐなくなっていましたね。今回のDevconでは大阪南港ATCホール内の飲食店で使えるクーポンがひとりあたり6000円(だったはず)配られていたのですが、昼間はどの参加者も発表を聞いたり議論をしたりするのに集中していて、昼食を配布された軽食で済ます人が多かったように見えました。 一口サイズのカステラは食べやすく、発表を聞きながら食べている人も多かったです おにぎりは数種類が用意されていました たこ焼きは特に人気ですぐになくなっていました 和菓子はインスタ映えするのか写真に収めている参加者が多かったです 地下2階の奥にはスポンサーブースがあり、答えるとヘッドホンが当たるアンケートなどバラエティに富んだ方法に宣伝しているようでした。 スポンサー企業には発表している企業も多いので、その内容について参加者が議論している姿も見られました。 スポンサーブースに出展している企業も日によって違います 中央には参加者が首から提げる名札を作るスペースがあり、実際使っている参加者も多く見えました。我々開発者はついTwitterやGitHubのアカウントで人を識別しがちなのでこのような配慮はありがたいです。 今回のビットファクトリーはa sponsorですね ノベルティを配っているコーナーもここです。タオル(洋)かてぬぐい(和)かを選ぶとき、スタッフがてぬぐいをやたら推していたのが印象的でした。 dogeのコラージュ画像を使った攻めたデザインのトートバッグ Opening 2日目の午前中がDevcon 5のオープニングセレモニーです。 Ethereumの考案者であるVitalik Buterin氏によるkeynoteが予定されているため、この時間帯は他の会場はお休みになっていました。 Devconの参加者がほぼ全員ひとつのホールに集まってくるので大騒ぎでした! ライブハウスのようにステージは青い光で照らされ、ハイテンションな音楽が流れていました。 セレモニーは身体に響く和太鼓の演奏から始まり、会場が興奮に包まれました。 Vitalikも戸惑いながらも和太鼓を叩いていましたね。 セレモニーが始まる前に会場内でだけ遊べるゲームが宣伝されていました その後はVitalikによるkeynoteです。 実際の動画はEthereum FoundationによってYouTubeに上がっています。 (Devconでは過去の発表がYouTubeにアップロードされます。Devcon 5の動画もちょうど今アップロードされつつあるようです。) www.youtube.com keynoteの内容は今まさに進みつつあるEthererumのPoS移行に関するものでした。 BitcoinはPoWによってビザンチン将軍問題を解決しただけだけではなく、トランザクションの承認で得られる経済的なインセンティブによって保証を作り出せる「暗号経済 (Cryptoeconomics)」を生んだこと、しかしシステムの破壊だけを目的とする攻撃者に対しては脆弱であること、EthereumはPoSに移行することで不正報告にもインセンティブを与え、より強固な暗号経済を作り出せることを語りました。 ややもすれば既存のRDBや単なる電子署名だけで解決できる問題にブロックチェーンを使ってしまうことがあるこの業界ですが、World ComputerとしてのEthereumの存在意義を語る納得感のある発表でした。 かぼすちゃん Devconには専用アプリがあり、タイムテーブルを見やすく表示してくれるとともに、見たい発表を登録することができます。登録した発表は直前になると通知が飛んでくるので便利でした。 他のカンファレンスでもぜひ導入してほしいアプリです。 スマホだとタイトルが見切れがちなのがやや残念です。タブレット版はよく見えます 1日目にはdoge coinのモデルになった柴犬のかぼすちゃんも会場にやってきました。redditや4chan等で有名になり、気づいたら仮想通貨のモチーフになっていた犬です。 サービス精神旺盛なかぼすちゃんと参加者が競って写真を撮っていたのが印象的でした。 ある意味インターネットの悪乗りから生まれたとはいえ、こうして仮想通貨の開発者とモチーフが交流する機会が実際にできてしまうのはEthereumの"ゆるい"コミュニティ特有の面白さがあります。 かぼすちゃんがやってくる!(発表の通知もこの形で飛んできます) 人間慣れしたかぼすちゃんは大人気でした 印象に残った発表 4日間のDevconを通して30ほどの発表を聞きましたが、いくつか印象に残ったものを紹介します。 Universal Login Progress: Results on How to Make Ethereum on Boarding Much Simpler DAppsの最重要課題としてオンボーディングがしばしば挙げられます。 ユーザーのウォレット情報がどうしてもDAppsには必要ですが、それはユーザーにウォレットの作成と登録を要求することになるからです。 UniversalLoginは従来のOpenID Connectのようなログイン機構を実現しておりUXをさせています。 まだ最初にETHを入れる必要があるなど課題もあるものの、今回のDevcon 5でオープンβ版となったUniversalLoginはかなり実用的になったように見えました。 www.youtube.com Optimization techniques for EVM implementations EVMの中では 圧倒的な速さ のevmoneの作者による発表でした。 最適化を行う上でネックになるのはやはり除算なので、256bit整数演算のC++ライブラリを作ったことを話していました。 仮想マシンでの最適化ではありませんが、学生の頃に除算の遅さには泣かされていたので共感できる話でした。 ガスコストの計測については時間が足りず駆け足でしたが、これも面白そうです。 発表スライド www.youtube.com Building dApps and IoT using the Incubed Ultra Light Client slock.itによるIoT向けのクライアントIncubedについての発表でした。 下の動画はslock.itによるモノを現実世界で特定の人と共有するサービスの紹介ですが、この種のサービスでは普通中央サーバにユーザーとモノの情報を記録する必要があります。 そうしたシステムに存在する、何らかの理由でサーバにつながらなくなったり、ハッキングされてすべてのモノが取り出せるようになるリスクを回避するためにブロックチェーンを使うアイデアがあります。 しかし、IoT機器の貧弱なスペックではライトクライアントすら実行できません。 そこで他のフルノードに依存する形ですが、ステートレスなクライアントのIncubedを採用することですべてのデータを検証できるようにした話でした。 既存の中央に依存するシステムを分散システムにする方法として興味深い事例でした。 www.youtube.com Grid: your new personal Ethereum infrastructure Gridはgethやparityなどのクライアントや分散ストレージのipfsのバージョン管理ツールです。 またRemixやブロックエクスプローラーも内蔵しており、開発者にとって必要なものを一通り揃えています。 Ethereum 2.0への対応も発表しており、DAppsやライブラリ開発者に広く使われていきそうに思えました。 www.youtube.com Ending 最終日はあいにく台風19号が近づいていたためか、会場の人はかなり減ってしまいました。 しかし、エンディングセレモニーは大盛り上がり! モバファクと業務提携しているBlockBaseさんによるイケイケなデジタル盆踊りを参加者が競って写真に収めていました。 運営の方々は最初から最後まで楽しいお祭りとしてDevconを演出していたように思えました。 サイケデリックなデジタル盆踊りがカオスなEthereum開発の世界を表現しているようでした Ethereumコミュニティの熱気とモバファクができること こうして、4日間にわたるDevcon 5は盛況のまま幕を閉じました。 参加中に肌で感じたのは、Ethereumはまだまだ発展途上だということです。 これは決してネガティブな意味ではなく、ブロックチェーンを使って実現したいことがどんどん出てきているのに開発者の数が全然足りておらず、カオスな状況がまだまだ続いていきそうだという期待です。 Devconの参加者が常に議論を続けている熱い会場や、Devcon 5が閉幕してからも公開され続ける多くの新情報を見るに、この熱気があれば世界のEthereumコミュニティは健全に発展していくだろうと確信しました。 日本においてもCryptoKittiesから一歩進んだDAppsが登場したり、既存の産業や大学での応用事例が出てきたりと面白い情報が出てきています。 その中でモバファクもユーザーと開発者両方に向けたアプリ開発をさらに推し進め、ブロックチェーンのコミュニティに貢献していかなければならないと改めて考えました。 そして、次回のDevconこそは登壇したいです! PR 最後になりますが、今回のDevcon 5へのスポンサー費用や大阪までの交通費、宿泊費はモバイルファクトリーの支援によるものでした。 モバイルファクトリーはブロックチェーンのみならず様々なカンファレンスのスポンサーやエンジニアの参加支援を行っております。 Ethereumを使った開発に興味を持たれた方、ブロックチェーンで新しい世界を作っていきたい方、 ぜひ一緒にモバイルファクトリーで働きましょう!
アバター
はじめに モバファクのCPE *1 として普段は開発基盤・運用基盤を整備している id:masasuz です。最近のお仕事としては、CircleCIのオンプレミス版を社内に導入しました。この話もどこかで書きたいですが、今回はモバファクにあるキャリアアップ支援制度を用いてArchitecting on AWSを受講した話です。 注意点として、トレーニングの内容は4/25 *2 に受講した時点の情報なのでその後変わってる可能性があります。留意ください。 3行でまとめると Architecting on AWSはAWSを触る人にとってとっかかりとしてとてもよい モバファクのキャリアアップ支援制度はよい モバファクはエンジニア採用してるよ Architecting on AWSとは Architecting on AWS - AWS トレーニング | AWS Architecting on AWSはAWSが主催するAWSの設計に関する有料のクラスルームトレーニングです。 学習する概要を下記に引用しますが、ざっくりと設計に関する体系的な知識やベストプラクティスが学べるトレーニングとなっています。 コースの目標 このコースの学習内容は以下のとおりです。 AWS のアーキテクチャに関する原則とベストプラクティスに基づいて、アーキテクチャ上の決定を行う AWS の各サービスを活用して、スケーラブルで信頼性や可用性の高いインフラストラクチャを作成する AWS マネージドサービスを活用して、インフラストラクチャで柔軟性や弾力性を向上させる パフォーマンス向上とコスト削減のために、AWS ベースのインフラストラクチャを効率化する Well-Architected フレームワークを使用し、AWS ソリューションを使ってアーキテクチャを向上させる 対象者 このコースは次のような方を対象としています。 ソリューションアーキテクト ソリューション設計エンジニア 受講する動機 モバファクでは1,2年前から *3 既存のサービスをAWS上で動くように移管し始めました。その際、AWSへの体系的な知識が足りてなくて、新しいことを始めるにあたって何をするにも一から調べなければならず、時間がかかっていたという悩みがありました。また、使ったことあるもの、今必要としているものの断片的な知識しかがなく、非効率な実装をしている可能性がありました。 一部のサービスでは本格的に運用しているものもありましたが、モバファクではまだオンプレミスの環境を使っているプロダクトが多く、これらを今後AWSを初めとしたクラウドに移管して円滑に運用して行くには今のままではよくない。もっと体系的なAWSの知識を身につけておきたいという欲求がもともとありました。 そんな折、クラスメソッドさんの記事 *4 を見てArchitecting on AWSというトレーニングがあることを知り、今抱えてる不満や欲求を満たしてくれるものではないかと興味を持ちました。ただ、受講料21万円と金額的にちょっと個人で出すには厳しいなと最初は思っていました。ここでふと、モバファクにあるキャリアアップ支援制度という福利厚生があることを思い出しました。キャリアアップという制度の趣旨にもあってるので無事申請が通り参加してきました。 キャリアアップ支援制度について モバファクでは、社員が受講を希望する研修や研修に準ずる費用(渡航費等)を会社が予算枠内で支援する制度があります。目的としては社員としては成長すること、会社としては社員が成長することによりチーム/会社に貢献すること。これが求められます。 この制度の利用例としては、以下のものを想定しています。 外部の高額な有料のセミナー、勉強会、カンファレンス参加費用 5000円までの少額な参加費用であれば、別の制度が利用可能 専門的な資格取得、長期間の講座受講が必要な研修 高額な書籍の購入等々 外部に表出してるものでは、 id:kfly8 がThe Perl Conference2019に行ってきた利用例があります。 The Perl Conference 2019 in Pittsburghに行ってきた - Mobile Factory Tech Blog Architecting on AWS 当日の流れ テキストとして、VitalSource Bookshelfという電子書籍プラットフォーム上で動く電子書籍が配布されました。そのほか、補足資料のPDFファイルと参考URL集が提示されました。 基本的な流れとしては以下の通りでした。 テキストを見つつ、座学での講義を行う 章の終わり毎に隣の人と学んだことの理解を確認するディスカッションを行う 複数章おきにラボ課題として実際にQwiklabを使用してAWSを動かす 2日目と3日目にグループディスカッションを行いシナリオに沿ったAWSでの設計を行う 良かった点 座学で聴いているだけでなく、ディスカッションを通してより理解が深まりました。 隣の人とディスカッションして現状の理解を言語化することによって、見えてなかった疑問点が表出できたというのは個人的には良い気付きでした。 グループディスカッションでは架空の企業のAWSインフラを設計するを行うのですが、ディスカッションを通し実際にAWS上で構築する上で何に注意すれば良いのかが分かりとても有意義でした。参加した人たちはそれぞれいろんなバックグランドを持っており、いろんな観点からのも設計思想を知れたの収穫でした。 留意する点 参加費が21万円+消費税なのでまあまあ高額なこと。この手のトレーニングとしては取り立てて高くはないとは思いますが、個人でぽんと出すにはためらう金額ではあります。そのためか、同じ日に参加していた人たちの会社名が大きめの企業が多かったように感じました。 開催している時間帯が平日の9:30-17:30で3日間ということ。ボリューム的にこの時間は必要なのではありますが、平日に3営業日トレーニングのために確保する必要があります。もちろん、業務調整はちゃんとしましたが、快く送り出してくれた上長には感謝しております。 もちろん、3日間でテキストの内容を全部詰め込めるわけではありません。詰め込めたとしてもそういった知識というのは得てして時間が経つと忘れてしまうものです。どんな研修でも当てはまるありがちなことですが、復習が肝要です。 まとめ AWSをさわり始めた人や今AWSを触って業務している人が知識の土台を作るものとしてはArchitecting on AWS良いトレーニングだと感じました。インフラ専門に触っている人だけでなく、アプリケーション開発側の立場でAWS触っている人にもお勧めできる内容だと思います。 そして、今回自分としては初めてモバファクでのキャリアアップ支援制度利用したのですが、費用面で個人だとなかなか手が出ない研修等に参加できるということで良い制度だと思います。また、キャリアアップ支援制度をはじめそれ以外でも、エンジニアが気持ちよく開発できる福利厚生がそろっていると思います。もし、モバファクに興味ある方はお声かけいただけたらと思います。 採用サイト | 株式会社モバイルファクトリー *1 : Corporate Productivity Engineer。もう少し説明する必要があるのですが、ここではざっくりインフラ回りを触ってるエンジニアとして理解してください *2 : 半年以上前なのに今頃エントリ書いてるのは大変申し訳ないです。。。。 *3 : それ以前からAWSで動いているサービスもあります *4 : 【AWS公式】Architecting on AWSはAWS初心者~中級者に最適のトレーニングでした! | Developers.IO
アバター
はじめに この記事は モバイルファクトリー Advent Calendar 2019 の11日目の記事です. こんにちは,今年度よりモバイルファクトリーに入社した yasuda です 今回は,ブラウザ上で地図を描画するライブラリである MapboxGL JS と,その使用例について紹介します 前提 この記事は,以下のバージョンを元に執筆しています mapbox-gl-js: 1.6.0 また,本記事内で用いられる座標(緯度・軽度)は,全てGoogle Maps などから目視で取得したデータです Mapbox GL JS について Mapbox GL JS は,WebGL で動作する地図ライブラリです Webでの動作のため,PCでもモバイル端末でも扱うことができます また,地図配信サービスの Mapbox と組み合わせて,オリジナルの地図を配信・表示することができます 最小構成 まずは,mapbox-gl を使って最低限の設定をして地図を表示してみます ここでは, 公式HPのサンプルコード を参考にします 今回は,地図のスタイルデータについては既にできているものとして,詳しくは扱いません < body > < div id = 'map' ></ div > </ body > htmlは,id: map のタグ1つのみ用意します body { margin : 0 ; padding : 0 ; } #map { position : absolute ; top : 0 ; bottom : 0 ; width : 100% ; } css では,全画面表示を行うためのスタイルを当てます mapboxgl.accessToken = 'XXXX' style = 'YYYY.json' window .onload = () => { var map = new mapboxgl.Map( { container: 'map' , style: style, } ) } jsで,mapboxgl の初期化処理を行います (accessToken と style は適宜変えてください) これだけで,地図の描画ができます ドラッグで移動,ダブルクリックやホイールの回転でズームといった基本的な操作も行うことができます また,右クリックでドラッグすると,地図を回転させることもできます そして,Mapbox GL JS はモバイル端末でも使用でき,スワイプやピンチイン・アウトといった操作も可能です では,ここからは Mapbox GL JS の使用例を,実際に使いながら紹介していきます 初期座標を変える これも初めの例に乗っていたのですが, mapboxgl の初期化時に center (緯度・経度) と zoom を渡すことで,初期値を変更することができます 今回は,適当に五反田駅辺りを中央にしてみました center: [ 139.7237285, 35.6262489 ] , zoom: 15, 例えば,使用している端末の位置情報をこの初期値に渡すことで,使用者の周辺の地図を映すといったことができます マーカを使用する Mapbox GL JS には,マーカ機能があり,地図が元々持っている情報とは別に,追加で目印をつけることができます let marker = new mapboxgl.Marker() .setLngLat( [ 139.727101, 35.6259434 ] ) .addTo(map) 例として,弊社オフィスの近くにマーカをおいてみます 右の方にある,青いマーカが弊社の場所です ここはさっきの五反田駅を中心に移した地図にも写っていたのですが,このようにマーカを使うことでより目立たせることができます 今回使用したのはデフォルトのマーカですが,htmlとstyleを定義することで,オリジナルのマーカを使用することもできます マーカを複数配置する場合 複数のマーカを同時に配置する場合マーカの描画順序に注意する必要があります 例えば,2つのマーカが前後に隣接している場合,画面上で上に位置するマーカは, 後方 にあると認知します こちらは,南北に真っ直ぐ進む京都市営地下鉄烏丸線の各駅を,駅メモ!の地図で見た画像です このアイコンは,影が付いていることからも前後関係を重要視していることがわかります. しかし,Mapbox GL JS には複数のマーカの描画順序を設定する機能は無く,デフォルトでは .addTo(map) によって登録した順に描画されます その際に前後関係が正しくなるように登録すれば良いと思うのですが, 地図が回転すると初期の前後関係では破綻することがあります そこで,地図が回転すると動的にマーカの前後関係を修復する処理を追加してみます this .map.on( 'rotate' , () => { var markerElements if (markerElements || markerElements.length) { markerElements = Array .from( document .getElementsByClassName( 'mapboxgl-marker' )) } let yPositions = [] markerElements.forEach((marker) => { let transform = marker.style.transform yPositions.push(parseInt(transform.slice(transform.lastIndexOf( ',' ) + 1))) } ) let minY if (yPositions && yPositions.length) { minY = yPositions.reduce( (a, b) => a < b ? a : b) } markerElements.forEach((marker, index) => { marker.style.zIndex = yPositions [ index ] - minY + 1 } ) } ) 地図が回転した際に呼ばれるコールバック関数を登録し,全マーカのhtml要素から transformのy要素でソートし, z-index に渡します (この方法では,地図以外の要素のz-indexとの干渉を考慮していないので,必要に応じて変えてください) 地図上に線を引く 先程は,特定の地点を目立たせるマーカを配置しましたが,次は地図上に線を描画して,道のりを目立たせてみます Mapbox GL JS は GeoJSON を扱うことができ,座標などを含むjsonを渡すことで,線や面の描画ができます map.on( 'load' , function () { const lngLats = [ [ 139.7029507, 35.657829 ] , [ 139.7107544, 35.6462484 ] , [ 139.7162516, 35.6343683 ] , [ 139.7237285, 35.6262489 ] , [ 139.7283931, 35.6198556 ] , [ 139.7388572, 35.6299566 ] , ] map.addLayer( { 'id' : 'route' , 'type' : 'line' , 'source' : { 'type' : 'geojson' , 'data' : { 'type' : 'Feature' , 'geometry' : { 'type' : 'LineString' , 'coordinates' : lngLats, } } } , 'paint' : { 'line-color' : '#0c7' , 'line-width' : 8, } } ) } ) 例として,山手線の渋谷-品川間の各駅を結ぶ折れ線を引きました 他にも,ユーザが定期的に現在地を登録していれば,その日に移動した経路を地図上に表示したりすることもできます 注意点として, geoJSONを地図に描画する map.addLayer() は, mapboxgl の初期化処理が終了した後に呼び出す必要があります 地図の初期化処理である new mapboxgl.Map() の完了には少し時間がかかるため, map.on('load', function(){~}) などで読み込みが完了したのを待ってからgeoJSONの追加処理を行うと安全です 終わりに Mapbox GL JS によって,モバイルのネイティブアプリとも大差ない機能を持つ地図を作ることができます. 本記事では,その使用例の一部を紹介しました. Mapbox GL JS には今回紹介しきれていない多くの機能が備わっており,様々な地図アプリを作ることができます
アバター
この記事は モバイルファクトリー Advent Calendar 2019 の4日目の記事です。 こんにちは、ブロックチェーンチームでエンジニアをしている id:odan3240 です。 今回は Ethereum のスマートコントラクト (以下コントラクト) を TypeScript から型安全に扱う方法について紹介します。 前提 この記事は以下のバージョンを元に執筆されています。 NodeJS: 10.16.3 TypeScript: 3.7.2 web3: 1.2.4 typechain: 1.0.3 typechain-target-web3-v1: 1.0.3 JavaScript からコントラクトを扱う方法 JavaScript からコントラクトを扱う場合に用いるライブラリとして web3.js がよく知られています。 web3.js を用いてコントラクトのメソッドを呼び出すコードは以下の通りです。 import Web3 from "web3" ; async function main() { // abi は設定されている前提 const abi = {} ; const web3 = new Web3(); const contract = new web3.eth.Contract(abi); await contract.methods.isOwner().call(); } main(); このコードにおいて contract.methods.isOwner().call() の部分は実行時まで正常に実行されるかがわかりません。なぜなら、コントラクトの実装の内容に応じて生えているメソッドは異なるためです。 実際に VSCode でマウスオーバーして型を表示すると any 型になってしまっています。 型安全に扱う方法 コントラクトの abi ファイルには、そのコントラクトにはどんな引数のどんなメソッドが実装されているかの情報が格納されています。この abi ファイルの情報から TypeScript の型定義ファイルを生成すれば、型安全にコントラクトを扱うことができます。 これを行うモジュールとして、 @0x/abi-gen や TypeChain があります。 今回は実際にプロダクトで採用している TypeChain の使い方を紹介します。 TypeChain の使い方 TypeChain はコアパッケージの typechain と、コントラクトを扱う各ライブラリ向けのモジュールから構成されています。今回は web3.js 向けのコードを出力してほしいので typechain-target-web3-v1 を導入します。 $ yarn add -D typechain typechain-target-web3-v1 コントラクトのコンパイル結果を build ディレクトリに格納している場合、以下のコマンドを実行すると generated-abi/typechain/web3 ディレクトリに型定義ファイルが生成されます。 $ yarn typechain --target=web3-v1 'build/contracts/**/*.json' --outDir generated-abi/typechain/web3 使い方は簡単で、型を import して Contract クラスを new するところで as するだけです。 import Web3 from "web3" ; import { AbiItem } from "web3-utils" ; import { MyContract } from "../generated-abi/typechain/web3/MyContract" ; async function main () : Promise < void > { const abi = ( {} as any ) as AbiItem ; const web3 = new Web3 (); const contract = new web3.eth.Contract ( abi ) as MyContract ; await contract.methods.isOwner () .call (); } main (); 再びマウスオーバーしてみると型が表示されているのがわかります。 注意点 web3.js と TypeChain を使うときには web3 と typechain-target-web3-v1 のバージョンの組み合わせに注意する必要があります。 具体的には以下の通りです。 1.2.1 以前の web3 を使用している場合 1.0.2 以前 の typechain-target-web3-v1 を使用する必要があります 1.2.2 以降の web3 を使用している場合 1.0.3 以降 の typechain-target-web3-v1 を使用する必要があります この問題が発生している理由は、1.2.1 以前の web3 は型定義ファイルがモジュールに含まれていないため @types/web3 を利用する必要があったのに対して、1.2.2 からモジュール自体に型定義ファイルが含まれるようになり、これらの型定義ファイルに互換性がないためです。 github.com サンプルリポジトリ 今回紹介したコードの断片が含まれているサンプルリポジトリです。 github.com 終わりに 型安全に TypeScript からコントラクトを扱う方法として、TypeChain を用いて abi ファイルから型定義ファイルを生成するアプローチを紹介しました。 エディタの補完機能によってコントラクトの実装を参照することなく、コントラクト周りのコードを実装できる体験を是非お試しください。
アバター
この記事は モバイルファクトリー Advent Calendar 2019 3日目です。 こんにちは、エンジニアの id:yumlonne です! 昨年の モバイルファクトリーAdvent Calendar 2018 では、 Perlのテストモジュールの紹介 という記事を書きました。 今回は単体テストでモック *1 を多用した結果、設計時にテストの視点を持つことが大事だなぁと思ったのでその学びを書くことにしました。 モックを使いたい! 私が所属するチームでは、モジュールを作成したときに単体テストを書く習慣があります。 それに倣って単体テストを書いてきましたが、以下の理由でテストが大変なことがありました。 パブリックなメソッドでは Data::Validator による引数のバリデーションを行っている 生成するのが大変な巨大なオブジェクト *2 を引数とするメソッドがある DBなどの状態を変更する作用(副作用)を持つメソッドをいろいろな箇所から呼んでいる テスト用のユーティリティモジュールに巨大なオブジェクトを生成してくれる機能はありましたが、テスト用DBに問い合わせてデータを生成するため速度が犠牲になっていました。 そこで、巨大なオブジェクトをモックオブジェクトに差し替えることを考えました。 Test::MockObject を使おうと思ったのですが、モックしつつバリデーションを通過するオブジェクトを作ることができませんでした。 (追記: すみません、Test::MockObject#set_isaでisaを偽装できることを見落としていました。 ) また、 Test::MockModule や Test::Mock::Guard を使えば一応バリデーションを通過するモックオブジェクトを作れたのですが、同じクラス *3 のモックオブジェクトを複数個作成しそれぞれに別の振る舞いをさせることがでませんでした。 容易にできないのなら作ってしまえということで、 バリデーションを通過するモックオブジェクトを作成するモジュール を書きました。 このモジュールは、 @ISA に親クラスを設定した匿名クラスを作成します。これによりバリデーションを通過するモックオブジェクトを生成でき、1と2をクリアします。 3については Test::MockModule や Test::Mock::Guard でモックすることで、テスト内での変更作用を抑えることができます(チーム内では Test::Spec を使っているため、付随する Test::Spec::Mocks でモックすることが多いです)。 大変だと感じたところをモックによって解消できたので、これを使って実際にテストを書いてみました。 微妙なテストができる 例えば、以下のようなユーザ登録のコードがあったとします。 package Repository::User { sub register { # DBにユーザを登録してUserオブジェクトを返す } }; package Model::User { use Data::Validator; use Repository::User; sub register { # 本当はData::Validatorでチェックしてるけど長いので省略 my ( $class , $user_info ) = @_ ; # XXX : 失敗は適当に表現(reasonとかを含めるべき) return - 1 unless $class->nickname_is_valid ( $user_info->nickname ); return Repository::User->register( $user_info ); } sub nickname_is_valid { # ニックネームに使えない文字が無いか検査する } } このコードに対してこんなテストを書きました。 use Test::Spec; use Test::MockObject::AnonClass qw/create_mock_object/ ; use Model::User; use Repository::User; describe 'Model::User#registerについて' => sub { my ( $user_info , @repository_args , $res ); before all => sub { $user_info = create_mock_object(+{ # user_infoのモックオブジェクトを作成 parent => 'UserInfo' , methods => +{ nickname => 'piyo' , }, }); Repository::User->stubs( register => sub { # Repository::User#registerをモック @repository_args = @_ ; return 'mocked' ; }); }; context '登録できるnicknameのとき' => sub { my ( $res ); before all => sub { Model::User->stubs( nickname_is_valid => sub { 1 }); $res = Model::User->register( user_info => $user_info ); }; it 'Repository::User#registerを正しい引数で呼ぶ' => sub { # @repository_argsが期待通りか }; it '戻り値はRepository::User#registerの戻り値' => sub { # $resが期待通りか }; }; context '登録できないnicknameのとき' => sub { # 省略 } }; runtests unless caller ; # テスト実行 書いてあることをテストにしただけなのでこのテストは通ります。しかし、リファクタリングなどで実装が変わった場合、振る舞いが変わっていなくても失敗する可能性があります。 このテストを改善するために この問題は、テストが実装を知りすぎているために発生しています。 なので、入出力などの振る舞いのみをチェックするブラックボックステストを書くことによってこの問題を解決または軽減できます。 ブラックボックステストの難しさ 振る舞いをテストすると口で言うのは簡単ですが、実際にはとても難しいことだと考えています。 値を受け取って値を返すだけの純粋なメソッドであれば入出力をチェックすれば良いのですが、DBなど外部状態の更新を伴うメソッドだとDBに問い合わせなければならないので場合によってはスローテストになってしまいますし、多数のモジュールに依存しているメソッドだと振る舞いが複雑になります。 ブラックボックステストをしやすいようにする このような状況を避けるため、設計段階でテストのしやすさを考慮することが重要だと考えました。 一例ですが、上に挙げたユーザ登録の「DBへの副作用」をオブジェクトに包んで返すことでModel::Userから副作用を排除することができます。 これにより、Model::Userに関して実装に依らないテストを書くことができます。 package Repository::User { sub register { # DBにユーザを登録してUserオブジェクトを返す } }; package Command::RegisterUser { sub new {} # user_infoを保持 sub exec {} # ユーザを登録してUserを返す } package Command::None { sub new {} sub exec {} # 何もしない } package Model::User { sub register_command { # 本当はData::Validatorでチェックしてるけど長いので省略 my ( $class , $user_info ) = @_ ; # 失敗は適当に表現(reasonとかを含めるべき) return Command::None->new unless $class->nickname_is_valid ( $user_info->nickname ); return Command::RegisterUser->new( $user_info ); } sub nickname_is_valid { # ニックネームに使えない文字が無いか検査する } } 副作用がないメソッドのため、引数と戻り値だけの対応で考えることができます。 use Test::Spec; use UserInfo; use Model::User; use Repository::User; describe 'Model::User#register_commandについて' => sub { context '登録できるnicknameのとき' => sub { my ( $user_info , $res ); before all => sub { $user_info = UserInfo->new( nickname => 'piyo' , age => 22 , comment => 'hello!' , ); }; it 'ユーザ登録コマンドを返す' => sub { $res = Model::User->register_command( user_info => $user_info ); ok $res->isa ( 'Command::RegisterUser' ); }; }; context '登録できないnicknameのとき' => sub { # 省略 } }; runtests unless caller ; # テスト実行 この他にコマンドのテストを書く必要がありますが、コマンドの処理自体はシンプルなので簡単に書くことができます。 副作用を発生させる箇所を考慮することで、テストしやすい部分を増やすことができました。 まとめ モック多用したテストを書くことにより、ブラックボックステストの観点も重要だということがわかりました。 設計段階からテストを考慮して進めていくと、テストしにくい副作用を持つモジュールや依存関係の都合上ブラックボックスではテストしにくいモジュールを減らすことができ、より安定したプロダクトにすることができるのではないかと思います。 *1 : この記事では、厳密にはスタブであるものもモックと呼んでいます *2 : Aniki::Row オブジェクトや、それを複数個持った状態データなど *3 : Perlの記事ですがパッケージをクラスと表現しています
アバター
 この記事は モバイルファクトリー Advent Calendar 2019 2日目の記事です。  ヒューマンリレーションズ部シニアエンジニアの id:kfly8 です。昨日、 id:karupanerura が公開していた 2019年の最先端のPerl開発ボイラープレート にて、 Function::Parametersで (InstanceOf['Point']) と括弧でくくる必要がある とありました。この記事ではこの補足をしたいと思います。  まず、問題の整理をしたいと思います。今回、2つの観点で、期待と異なっていると思います。まず、 InstanceOf['Point'] は、Type::Tinyの式としては正しいので、そのまま、Function::Parametersでも使わせて欲しいはずです。 # Type::Tinyの式としては正しい use Types::Standard -types; my $type = InstanceOf[ 'Point' ]; # けれど、Function::Parametersではそのまま使えない fun foo(InstanceOf[ 'Point' ] $foo ) { ... } # error!  もう一つ期待することは、Function::Parametersの issue にあるように、クラス名を型制約として利用したいはずです。普段、Mouseに慣れていると、isaにクラス名を文字列で指定できるので尚更です。 # Mouseを使っていれば、クラス名を文字列で指定できる use Mouse; has foo => ( is => 'ro' , isa => 'Foo' , # Fooオブジェクトを期待 );  今回この期待通りではないので、違和感を感じさせていると思います。 Function::Parameters の型指定の仕様  上述の問題は、一言でまとめてしまうと、Function::Parametersの仕様のためですが、もう少し納得感がでるように、Function::Parametersの仕様を掘り下げてみたいと思います。Function::Parametersの ドキュメント にも同様の説明があるので、合わせて確認してみて欲しいです。  まず一番簡単な例を説明します。Function::Parametersは、 Str と型指定した場合は Str 関数が同一パッケージに定義されているかコンパイル時に探索します。 Str 関数が定義されていなければ、コンパイル時にエラーになります。 # Strと指定することで、Str関数が定義されているかコンパイル時に探索する fun foo(Str $s ) { ... }  パラメタ付きの型 ArrayRef[Int] を指定した場合は Int 関数と ArrayRef 関数が定義済みかコンパイル時に確認し、 Str | Undef のpipeでUnion型とした場合は Str 関数と Undef 関数が定義済みかコンパイル時に確認します。 # IntとArrayRef関数が定義されているか探索 fun bar(ArrayRef[Int] $numbers ) { ... } # Str, Unde関数が定義されているか探索 fun baz(Str|Undef $maybe_str ) { ... }  つまり、 Function::Parametersの型指定の文法仕様は、識別子と同名の関数を結びつける仕様になっています。 Function::Parametersの型指定の仕様 識別子(例: Str ) パラメタ付き識別子(例: ArrayRef[...] ) 識別子の合成(例: Str | Undef )  なので、 InstanceOf['Int'] のように型指定をした場合、型定義が見つけられず、文法エラーになります。 fun fuga(InstanceOf[ 'Foo' ] $a ) { ... } # => In fun fuga: missing type name after '['  さらに、この仕様により、 Strr のように指定する型名を間違えた場合は、コンパイル時にエラーにできます。つまり、 型定義されていなければ、コンパイル時にエラーになると考え、開発できます。 これは他のPerlのValidationモジュールにないメリットだと思います。 fun foo(Strr $a ) { ... } # => Undefined type name main::Strr  どうしても逃げ道が欲しい場合、式を () で包めば、式を評価する仕様があるのでそれを使います。例えば (InstanceOf['Foo']) と型指定した場合は、括弧内の InstanceOf['Foo'] という式をコンパイル時に評価します。 # InstanceOf['Foo'] を括弧で包むと、括弧内を式として評価される fun fuga((InstanceOf[ 'Foo' ]) $a ) { ... }  ただ、この書き方のデメリットはあります。まず、式を評価しているだけなので、エラーメッセージから原因が推測しにくいです。 fun fuga((IstanceOf[ 'Foo' ]) $a ) { ... } # XXX : InstanceOf のつづりが間違っている # => syntax error # これでは、エラーの原因が分かりにくい  また、クラス名を間違えても、文法エラーになりません。 # クラス名を間違えても文法エラーにならない fun fuga((InstanceOf[ 'Foooo' ]) $a ) { ... } # => syntax OK  もし識別子の書き方に統一できれば、コンパイル時に問題に気づけます。 式表現は柔軟ではありますが、極力、使わないようにした方が良いと思います。その方法について次の段落に書きます。 aliasedで文字列のalias関数を用意し、型指定に使う metacpan.org  このモジュールは、Too::Long::Fooというクラスをロードしつつ、Fooといった名前で利用できるようにするモジュールです。SYNOPSISは次の通りです。 use aliased 'Too::Long::Foo' ; my $foo = Foo->new; print Foo ; # => Too::Long::Foo  aliasedを利用することで、Too::Long::Fooというクラスを、 (InstanceOf['Too::Long::Foo']) といった記述をすることなく、 InstanceOf[Foo] といった形で書けます。Fooが関数になったので、こういった記述ができます。簡潔ですね! use Types::Standard -types; use Function::Parameters; use aliased "Too::Long::Foo" ; fun foo(InstanceOf[Foo] $foo ) { ... } # これは、fun foo( (InstanceOf['Too::Long::Foo']) $foo) { ... } と同じ  また、aliasedを使うことで、useできたクラスしか関数として使えないので、 Foooo といったタイポにもコンパイル時に気づけます。 use aliased "Too::Long::Foo" ; fun foo(InstanceOf[Foooo] $foo ) { ... } # => Foooo が見つからないので、コンパイル時にエラー aliasedとFunction::Parametersを組み合わせることで得られるメリット 簡潔 型の指定方法が、識別子に統一できる () のあるなしで迷わない 識別子か文字列か迷わない クラス名の名前を間違えても、コンパイル時に気づける まとめ Function::Parametersの型指定は、識別子と同名の関数が定義済か探索する 型指定に、式表現を用いることができ、柔軟だが、エラーがわかりにくい aliasedを使えば、文字列を関数にでき、識別子を使った型指定方法に寄せられ、簡潔に記述でき、エラーも検知しやすい まとめるとこんな感じです! おまけ  そもそも、なぜFunction::Parametersが識別子を基本とする仕様にしているのか考えてみます。上述の通り、簡潔、エラーが検知しやすいことは理由になると思います。自分が考えるもう一つの理由は、Function::Parametersが好きな型制約を使えるようにする為です。Function::Parametersが型制約に要求することは、check、get_messageが型制約にduck typeされていることだけです。これにより、Type::Tiny、Mouse::Meta::TypeConstraintといった複数の型制約クラスを使えます。もしクラス名を型制約に変換するとしたら、Data::Validatorであれば、Mouseに依存させていますが、Function::Parametersでは、特定の型制約に依存させないといけないかもしれません。これは大きなトレードオフだと思います。さらに、 Enum["Foo", "Bar"] のようにEnumの値をクラス名とみなすか値とするか区別する文法は型制約依存無しに実現するのは難しいように思います。こういった理由から、現在の仕様で良いと自分は思っています。
アバター
 この記事は モバイルファクトリー Advent Calendar 2019 1日目です。  ヒューマンリレーションズ部シニアエンジニアの id:kfly8 です。普段は組織横断して人材開発などを行ったりしています。その中で、メンバーにとって初回の1on1はどうすると良いか聞かれることがあります。確かに、メンバーにとっても上司側にとっても初回の1on1は予想がしづらく、多かれ少なかれ緊張感があると思います。特にチームに入ったばかりの新人の場合、1on1をそもそも体験したことがなく、不安は大きいかもしれません。そんな時、どうするのか?ここではそんなことを書きたいと思います。 3行まとめ 思っていることを話しやすい雰囲気作りが大切 そのために、まずは上司側が自己開示しよう 自己開示には、趣味、失敗談など等身大の話をするのがいい  直感的には当たり前かもしれないですが、もう少し掘り下げてみたいと思います。 初回の1on1の目的  まず、何を目的とするかです。  信頼関係が出来ていない相手に自分が何を考えているのか話すのは、億劫だと思います。メンバー側は下手なことを話して評価を下げられたくないなんて思うかもしれません。自分のことを話すのが苦手な人もいると思います。30分程度の1on1、たった1回で無理して解決する問題ではないです。出来るところから気軽に始めた方が長期的に続けやすいと思います。  チームの目標や期待を伝えるのはどうでしょうか?仕事を進めるには必要なことです。もしメンバー側が疑問に思っているのであれば、認識を合わせた方が良いと思います。ただ、数字や具体的な行動は認識合わせしやすいと思いますが、背景にある意義や思いは、話し手がどんな人か分からないと、納得感が出にくいと思います。例えば、今この記事を読んでいる人で、この記事を書いている筆者が信用できるか考える人はいると思います。  初回の1on1の目的のおすすめは、話しやすい雰囲気作りのために、まずは上司側がどんな人であるか知ってもらうこと、自己開示することです。部下側が自分の考えをオープンにするには、まず上司側の考えや思いをオープンにする。部下側だけに話してもらうのは悪いです。上司側がオープンでいることは部下への信頼の証だと思います。  自己開示することは急がば回れな作戦です。理論的な背景として、メンバー成長のため、 松尾睦教授のいう経験学習モデル を回すことを意識しています。周りとのつながりが、成長に影響を与えることがわかりやすいモデルです。 初回の1on1ではこのサイクルの真ん中、思い、つながりが狙い目 初回の1on1でどんな自己開示をするか  自己開示をすると言っても初回の1on1なので、話のとっかかりがあれば良いと思います。例えば、生まれはどこか、学生や社会人でどんなことをしてきてどんな思いで過ごしてたのか、休日どんな過ごし方をするのが好きかなどが良いと思います。  注意する点は2つです。  まず、ただ事実を伝えるだけでなく、どんなことを思ってるか話すのが良いです。例えば「大学は仙台でした」より「大学は仙台だったんだけど仙台は最高の街。ゴミゴミしてない整った都会でありつつ、魚がどこで買っても美味しい。はらこ飯が旨い」の方が、 自分の語彙力が拙いですが、 事実だけより人となりが見えやすいと思います。また1on1を継続した時、メンバーがどう思ったのか聴き、出来事に意味づけしていきます。どう思っているのか話しやすい雰囲気を出すためにもまず自分が言ってみるのが良いと思います。  もう1つは、自己アピールにならないように気をつけたいです。例えば、上司が仕事の成果の話をすれば、意図せずとも、メンバーも同様に過去の成果を話すべきなのか考えてしまうと思います。仕事の成果を出す過程でどんなことに苦心して、どんな思いで仕事をしていたのか話す方が人となりはわかってもらえると思います。 最後に  話をまとめると初回の1on1アジェンダはこんなイメージです。 1. 1on1の目的共有 - あなたの成長のためにやる。それが会社の成長にもなる。と伝える - そのために、お互いのこと知っていた方が良い。と伝える 2. 上司側の自己紹介 - 地元、学生時代、社会人時代、趣味など 3. 次回以降どうするか - メンバーにも同じように自己紹介してもらいたい、ことを伝える - 次の予定はいつか。  メンバーにどんな話を聞きたいかメンバーにリクエストしてみるのも良いと思います。  話しやすい雰囲気作りのために、早い段階で上司がどんな人となりかわかるように自己開示してみよう!という話でした。
アバター
こんにちは、デザイナーのkrkr_tkです。このブログでは初めてのデザイナーについての投稿になります! 弊社では社内勉強会の時間を活用して、デザイナーのライトニングトーク会「Mobile Factory Design Talk」を定期的に行っています。 今回は、そのLT会について紹介したいと思います。 ロゴ なぜ始めたのか 弊社では社内勉強会を行える機会が提供されているものの、積極的に開催しているのはエンジニアがほとんどでした。 以前、デザイナーの勉強会を増やすために働きかけたことはありましたが、中々発表者が増えずにいました。また、「他のチームや部署のデザイナーが何をしているのかがわからない」、「業務上得た知識やノウハウが共有されない」といった課題もあり、手法を変えて発表者を増やしていこう思いでLT会を始めました。 LT(=Lightning Talk)とは: 5分程度の短い時間で発表を行うこと。気軽に話す・聞くことが出来る点がメリット。 LT形式にした理由 弊社でデザイナーの勉強会が少ない原因を考えた結果、以下のようなものがあると感じました。 そもそもデザイナーの勉強会文化が存在しない 何を発表すればいいかわからない きちんとした資料を用意することが大変 1時間も話せる内容ではない これらを低減し、もっと気軽に発表出来る機会を設けるため、LT形式を取り入れることにしました。 5分〜10分程度であれば発表のハードルも低いはずです。さらに、LTの明るい雰囲気が心理的なハードルも下げられるのではないかと思います。 発表資料についても、業務で残したドキュメントを使ったり、ソフトウェアの使い方などであれば資料無しで実演するなどの負担軽減を行いました。 開催内容 発表する内容は、デザインに関わることであれば基本的に制限を設けていません。内容にとらわれずにとりあえず発表に慣れてもらう意図もあります。 これまでの主な発表内容 私の経歴 クリエイティブディレクターの仕事について バナー作成意図と意識 イラスト指示書の作り方 などなど LT会の模様 開催して感じたこと LT形式にしたおかげか、狙い通り発表経験の少ないデザイナーも発表してもらうことが出来ました。 他チームのデザイナーの仕事内容や中途デザイナーの経歴など、普段業務を行っているだけでは知ることが出来ないものについて発表され、より他のデザイナーについて知ることが出来たと思います。 また、デザイナーだけでなくエンジニアやディレクターも参加していたことが嬉しく感じました。 今後の課題 現在4回開催していますが、発表者が多少偏りがちであることが課題です。発表に慣れてもらう意図もあるため、1人1回は発表してもらえるように呼びかけを行っています。 今後、発表枠が足りない!といった状況になるほど盛り上がっていくと嬉しいなと思っています。 まとめ デザイナーの勉強会を活発化するためにLT会を始めました 気軽に発表する機会が出来たことで、発表者が増えました 継続していくためには、発表者をさらに増やすことが課題
アバター
 こんにちは。ヒューマンリレーションズ部のエンジニアの id:kfly8 です。  少し時間が経ってしまったのですが、6月の16日から21日にかけて、 The Perl Conference 2019 というアメリカのピッツバーグで開催されたPerlのカンファレンスに登壇をしてきたので、今回はその様子を諸々レポートをしたいと思います! 3行でまとめると、 交流が盛ん!フレンドリーな人ばかりで、初めての海外カンファレンス参加でも楽しめた! GEEKは国を越えてもGEEK。言語が違っても、技術の話ができて楽しい! ピッツバーグ綺麗! といった感じで最高でした。 カンファレンス開始まで セッション1日目 オープニングトーク Perl 5: The past, the present, and one possible future by SawyerX A Neurobiologist's Guide to Effectiveness by kyloma Maintaining Code Quality at Scale by Jordan Adler Interfaces in Perl5 by kfly8 Better testing with Test2-Suite by EXODIST 懇親会 セッション2日目 Confessions of a Space Cadet by genehack Speeding up Perl test suites by Dimitrios Kechagias Mocking the file system in Perl by TODDR Perl Out Loud by Emily Shea LT & 懇親会 セッション3日目 Readin' Rust by spazm Tidy (and Lint) All the Things with TidyAll! by DROLSKY Overloading Perl OPs using XS by ATOOMIC Q & A with Larry Wall by Larry Wall and Jim Brandt LT & クロージング カンファレンスに参加して PR カンファレンス開始まで  ピッツバーグは水と橋の都と呼ばれ、昔は鉄鋼王カーネギーの街として栄え、今はテック系の街として発展しているそうです。到着した翌日、カンファレンス会場のDouble Tree by Hilton Hotel付近を散策すると、石造りのレトロな建物と高層ビルが同居する街並みが楽しめました。カンファレンスの参加者は、会場ホテルの特別割引もあるので会場のホテルに宿泊するようですが、自分は現地の人と交流したかったのでairbnbで民泊しました。家主は、内装、外装、庭をDIYするツワモノでした。 中心街の街並み 中心街の街並み 民泊先。ピッツバーグの川を眺めながら過ごす。優雅。 セッション1日目 オープニングトーク  いよいよセッションが始まります。オープニングトークでは、カンファレンスの楽しみ方が共有され、日本で聞き覚えのある内容で早速テンションが上がりました。 The Perl Conferenceの楽しみ方  話を聞くと、20年前、初めてThe Perl Conference(その時は、YAPC:Yet Another Perl Conference)が開催されたのも、ピッツバーグなんだそうです。その1999年開催のサイトは こちら で、とても歴史を感じます。 カンファレンス開催20周年記念Tシャツ。最高に可愛い。 Perl 5: The past, the present, and one possible future by SawyerX  キーノートは、Perl5のメンテナンスマネージャーの Sawyer で、Perl5のバージョンが上がるごとにどんな機能変更があったか、また今後どんな変更を考えてるか話していました。動画は こちら 。わかりやすいのでオススメです。 頑張れば実現できる未来  懇親会でSawyerに、この未来のことについて話しかけてみると「今後どの変更が優先されて欲しい?」と気さくに聞いてくれました。自分は「メンテナンスしやすいと嬉しいので、リッチなOOがビルトインされていて欲しい!それと初心者向けのドキュメントが欲しい!例えば、 Perl入学式のようなドキュメント は参考になると思う!」と急に喋る人になりましたが、優しく受け答えしてくれました。優しい。後から、ああ言えば良かった、こう言えば良かったと後悔もありましたが、憧れの人と話せて良かったです。 A Neurobiologist's Guide to Effectiveness by kyloma  次のキーノートは、元herokuのエンジニアで現在、脳神経学者の kyloma による話で、認知を「鍛える」話が面白かったです。例えば、感情を効果的に対処する為には「感情を表す語彙力を増やす」と良いそうです。言われてみると当たり前ですが、意識できていなかったです。他には心理的安全を高める方法など、実践的な内容が、こちらの サイト によくまとまっています。 Maintaining Code Quality at Scale by Jordan Adler  PinterestのJordan Adlerの話では、SaaSの改善プロセスを、問題発見、デザイン、実装、デプロイ、メンテナンスについて端から端まで網羅的に聞け、勉強になりました。資料は こちら です。 Discovery Phase / 問題の発見 Problem Discovery Problem Isolation Design Phase / 問題解決のデザイン Solution Design Design Design Review Implementation Phase / デザインの実装 Solution Implementation action Implementation Review Deploy Phase / デプロイ Delta Deploy Acceptance Testing Usage Monitoring Maintenance Phase / 運用 System Operation Interfaces in Perl5 by kfly8  次は私の登壇でした。発表内容を簡単にまとめると「コード規模が大きくなると、コードの分割、依存コントロールがより重要になる。その為にInterfaceはいいパーツ。だから、Perl5にInterface作った」という話です。緊張でお腹が明らかにキリキリしていたのですが、登壇が終わり放心状態で会場を彷徨っていると「面白かったよ!」と何人かに声をかけてもらえて、ホッとしました。  後日のハッカソンでは、作ったモジュールのデザインについて何人かに相談にのってもらえて、最高の時間が過ごせました。 Welcome to @kfly8 -- flew from japan to give a talk at #TPCiP at his first TPC. Props! Organized YAPC Tokyo. pic.twitter.com/vv1yR9OxEh — Mr. Spaz (@spazm) 2019年6月17日 speakerdeck.com   Better testing with Test2-Suite by EXODIST  次は、Test2のEXODISTでした。資料は こちら で、Test2のチュートリアルを40分で一気にさらう内容でした。Test2の日本語記事だと、Perl Hackers Hubの id:akiym の記事が分かりやすいです。 gihyo.jp 懇親会  この日の懇親会は、会場のホテルで立食形式でした。ざっくり話したことはこんな感じで楽しかったです。 Sawyerにセッションの感想が話せた(上述) アメリカ開催なのに、スタッフにフランスの人がいる アメリカでは5Gが開始したんだけど、日本はいつ始まる? 次の日本のYAPCはいつやるの?  余談ですが、ホテルでのカンファレンスが良かったです。全期間に渡って、朝食、ブランチ、おやつ、コーヒー、紅茶などの提供をしてもらったのですが「コーヒー飲む?」「体冷えたから紅茶がいいかな」といったゆるい会話がしやすかったです。 id:papix も 言及していた のですが、セッションとセッションの間の時間が長く、のんびり交流のために休憩時間を使いやすかったです。運営としても、ホテルに丸っとお願いできるのも嬉しいですよね。日本でどこかカンファレンス開催しやすい宿泊施設はないですかね? セッション2日目 会場近くの道端にリスがいた。 Confessions of a Space Cadet by genehack  2日目の最初は、 genehack のキーボードの話を聞きました。資料は こちら です。前々日のランチで、 Keyboardio を作っているのは、Perlのメンテナーだった obra だと聞いたので、キーボードに興味が湧き、ゆるっと聞きに来ました。案の定(?)キーボード沼の話でした。ひとまず、紹介されたキーボードを貼っておきます。 maltron ErgoDox EZ Iris Keyboard DataHand Keyboard Keyboardio Preonic Planck Anne Pro 2 CODE  蛇足ですが、キーボードをノートPCに載せる尊師スタイルでいると、7人くらいに話しかけられました。交流したい人にオススメのスタイルです。 Speeding up Perl test suites by Dimitrios Kechagias  次は、Perlのテストの高速化の話でした。 速度改善のデモ が脅威的で、Mooseのフルテストを39秒→2秒にしていました。次のコードのように Test2::Aggregate を利用して実現します。 use Test2::Aggregate; Test2::Aggregate::run_tests( dirs => [ 't' ], ); done_testing  この改善の肝は、モジュールの読み込み時間を減らすことで、コードとしては、複数ファイルに別れているテストをまとめ( 該当コード )、テスト実行する動作になっています( 該当コード )。面白い。 Mocking the file system in Perl by TODDR  cPanelのTODDRの話は Test::MockFile の話でした。資料は こちら です。後述のコードで、ファイル実体を開くことなく、ファイルの中身を指定できるのが旨味です。一筋縄でいかなかった罠、例えば、gotoがperl5.16未満だと 期待通りに動かない といった話含め、面白かったです。 use Test::MockFile; my $mock_file = Test::MockFile->file( "/foo/bar" , "contents \n go \n here" ); open ( my $fh , "<" , "/foo/bar" ) or die ; Perl Out Loud by Emily Shea  Fastlyの yomilly の話は、RSIでキーボード入力が難しくなり、色々試した結果、今、音声入力でプログラミングをしているという話です。話を聞くまで、正直音声入力でプログラミングはネタなのかと思ったのですが、全然そんなことなく、 Talon Voice を用いて、現実的なものに落とし込んでいて凄かったです。自分はTestの話を聞いていて、直接聞けなかったのですが、隣の会場で盛り上がっている声が聞こえてきました。話題になって、このカンファレンスで一番再生されている動画です。 www.youtube.com LT & 懇親会  このあと、LTの時間で一緒に来ていた id:karupanerura が、Perl5でJSONを扱うときのハマりどころの話をしていました。資料は こちら です。 karupa!!  そんなこんなで、2日目も終わり、懇親会です。懇親会では、遊覧船(!?)に乗りました。ピッツバーグの美しい街並みを見ながら、ビール片手に色々話せて最高でした。日本人の私よりアメリカ人の方が椎名林檎について詳しかったです。 Larry Wallと写真を撮ってもらい、浮かれています。 セッション3日目 Readin' Rust by spazm  プログラミング言語のRustの紹介でした。自分が聞き取れた限りだと、Perlの話は一切なかったので、ある意味、私の知っているPerlのカンファレンスっぽかったです。 蛇足ですが、廊下で話した別のエンジニアにも「Rustはいいぞ。あと位置情報を扱うならPostGISがいいぞ。」と薦められました。GEEKは国を超えてもGEEKなのか、推しは全力で推す雰囲気が楽しめました。 Tidy (and Lint) All the Things with TidyAll! by DROLSKY  DateTimeのDROLSKYの話でした。このセッションでは、 Code::TidyAll の紹介でした。資料は こちら です。Code::TidyAllはプログラミング言語問わず、統一された使い勝手で、lint,formatするツールで、処理の並列化やキャッシュも面倒みてくるので便利だと思いました。ちなむと Rustで再実装 をしているみたいですが、まだ途中だそうです。 Overloading Perl OPs using XS by ATOOMIC  cPanelのATOOMICの話で、ファイルテスト演算子を上書きする Overload::FileCheck の話です。資料は こちら です。ファイルテスト演算子の上書きは、XSで OPを書き換えて 、hackishでcoolでした。実際に使う時は、次のように簡単に使えます。 use Test::More; use Overload::FileCheck q(:all) ; mock_file_check( '-f' => sub { my ( $file ) = @_ ; return CHECK_IS_TRUE if $file eq '/foo/bar' ; return CHECK_IS_FALSE if $file eq '/boo/bee' ; return FALLBACK_TO_REAL_OP }); ok -f '/foo/bar' ; ok not -f '/boo/bee' ; done_testing; Q & A with Larry Wall by Larry Wall and Jim Brandt  Perlの生みの親のLarryと、The Perl Foundation代表のJim Brandtでの座談でした。要約できないので、動画を見てください!10分くらいまで音声不調ですが、それ以降は聞き取りやすいです。 www.youtube.com LT & クロージング  Sawyerが声をかけてくれ、ちゃっかりLTとLTの合間に YAPC::Japanの宣伝 をさせてもらいました。  そして、10年運営代表をしたDanを讃える場面もありました!今回カンファレンスを楽しむことが出来たのも運営のおかげです。ありがとうございました!   Dan gets a well deserved standing ovation. #TPCiP #perl #thankyou pic.twitter.com/wVDHos6ct0 — Mr. Spaz (@spazm) 2019年6月19日 カンファレンスに参加して  初めての海外カンファレンス参加で、当初緊張していたのですが、蓋を開けてみると、カンファレンスの雰囲気は穏やかで寛容で、コミュニティに歓迎してもらえ、本当に楽しむことができました。また言語は違っても、技術の話、またはサブカルの話、文化の話など好きなことについて、コミュニケーションできたことが良かったです。GEEKは国を超えてもGEEK、という実感が持てました。参加の心理的なハードルは高かったかもしれないですが、参加して良かったです。また参加したいです! PR  今回のカンファレンス参加にあたり、移動費、宿泊費をモバイルファクトリーに全てサポート頂き参加できました。モバイルファクトリーは、こういった技術カンファレンス参加など、キャリア支援に取り組んでいるので、もし興味が湧いた方は、お気軽に面談してみませんか? モバイルファクトリーは、技術好きなエンジニアを募集しています。
アバター
こんにちは。 コスッキー といいます。 7/29(月) に Gotanda.EM #3 でLTをしてきました。 その内容について補足しながら書いていこうと思います。 今回は、自分が所属しているチームのオンボーディング(新しく加入した人に手ほどきを行い慣れさせること)についてLTをしました。 新卒の人たちが入ってくる際に、未整備だったフローからやることを考え準備し、一ヶ月ほど運用した後で振り返りを行いもらったフィードバックを元に作った資料です。 今までの課題 今まではチームに新しい人が加入する時、過去数年の先輩たちの動きを振り返ると、「コールドリーディングやドキュメント確認のための勉強時間を用意」「メンターを同じチームから選出してある程度その人におまかせ」という事をしていました。 迷った時は歴史に学ぶということでやってきましたが、歴史が長くなってきたこともあり、チームとして何をすればいいのか?何を教えればいいのか?など整備の必要性を感じました。 特に、以下のような課題を感じました。 コードやドキュメントを読むだけで身につくものだろうか? 学校でも教科書を1回読むだけでテストで100点を取れる人はまれですよね?コーディングでも同じでリポジトリのコードを読んだだけですべてを把握できるような人はいないと思いました。 あと目的もなくただコードを読んでいるだけでは飽きやすいのでは?とも思いました。 自信がつくにはどうすればいいか? 自信がないと行動ってできないと思います。特に初めて社会人として働く新卒の人は。なので自分から行動するために自信をつけてほしいと考えました。 相談しやすくするにはどうすればいいか? 何が分かってないのか?どこに躓いているのか?を知っているのは困っている当人だけです。我々はエスパーではないので、相談されないと困っている状態という事すら分かりません。 実際にやったこと 上記の課題をなくすためにいくつかの事を行いました。 ここでは、一例を紹介したいと思います。 上長交えて期待値のすり合わせ 一番最初の顔合わせの時に、期待値のすり合わせも行いました。 何故かというと、半年後や1年後の目標となる姿をイメージして欲しかったからです。 特に、どのような成長をして欲しいのか?チームとしてどのような期待をしているのか?というのを話しました。 また、これらの事は自分からではなく、上長から話してもらいました。 いちメンバーである自分よりも、実際に評価を行う上長からの方が説得力もありますし、新しい方も身が引き締まるかなと考えたからです。 タスクや課題を用意 新しい方用のタスクを用意しました。 内容としては管理画面雨やデバッグメニューなど最悪壊れても問題ない部分のタスクを用意しました。 タスクの達成という目的があるなかでコードに触れることで「読んでいるだけでは飽きる・身につかない」という課題を解消できるのでは?と考えたからです。 また、要件定義・実装・レビューのやり取り・反映といった、これから何度も行うであろう作業を最初のうちから慣れてもらいたかった、という考えもあります。 反映して問題を解決したら「ありがとう」とか「お疲れ様」と行った言葉やslackのリアクションがつくので、そこから自信をつけてほしいという期待もありました。 相談の窓口を用意 相談しにくい原因として、誰に聞けばよいのか分からないという事があると思います。 なので、とりあえずメンターを相談の窓口にしてもらうようにしました。 また、質問すること自体がハードルが高い・怖いという事もあるかもしれません。 しかし、時間や締切を守る・遅れそうな場合は早めの相談が社会人としては当たり前な中、ずっと分からないまま迷っている時間がもったいないので「10分考えて分からなかったら質問」という時間的な区切りをつけてみました。 それでも、できなかった場合をケアするために、最初の一ヶ月のうちは朝会・夕会の後でメンターが「進捗はどう?」「困っている事はない?」とヒアリングも行いました。 振り返りをしてみて 以上のようなチームとしての受け入れフローを用意して、一ヶ月働いてもらった後で、新卒やメンターを交えて振り返りMTGも行いました。 GoodやBadだったことをいくつか紹介たいと思います。 Good 最初に全体像の話があった 期待値のすり合わせを最初に行ったのは良かったという意見がでました。 また、新卒のエンジニアからはディレクトリ構成やアーキテクチャ、フロント・サーバーでの処理の流れ、歴史的経緯などを、レポジトリを見ながらホワイトボードを使って説明してもらえたのが良かったという意見ももらいました。 人やチームの役割・目的・タスクとしての全体像だけではなく、実際に触っていくことになるコードの全体像を最初に説明してあげるのは良さそうでした。 開発作業の流れを一通り体験できた ひとえに開発作業と言っても、完璧な仕様書が降りてきて、それを元に動くものを作ればいいというものではありません。 チケットの報告者と解決したい問題や解決方法の要件定義、実際のコーディング、コードレビュー、動作確認、反映、報告。 ここまでやって、ようやく開発作業が終わったと言えます。 それを最初に小さいサイクルで何度も体験できたのは良かったという意見が出ていました。 また、反映後は「お疲れ様」や「ありがとう」といったリアクションがslackでつくので、それが自信ややる気に繋がっていそうにも見えました。 相談先が決まっている 相談先も決まっているので声をかけやすいとう意見でGoodだと言ってくれました。 メンター側からは、内容によって窓口を分けるとさらにGoodという意見が出てきました。 すべての相談をメンターにしていたので、新卒とチケットの報告者しか知らないような仕様や要件について相談してきたり、開発者全員に知ってほしい・他の開発者が詳しいジャンルの質問を個別で相談したりという事もありました。 仕様や作業内容の相談はslackのディレクターチャンネル、開発や作業中に困ったことはslackの開発チャンネル、相談先がはっきりしないなどその他な質問はメンター、など相談内容によって窓口を分けると良さそうという意見も出てきました。 Bad 業務で使っているツールの使い方が分からない 今回の振り返りで出てきたのは普段から業務で使っているslackとJIRAについてが話題に上がりました。 どちらかといえば、使い方というよりは、前提やフローの共有漏れという意味のほうが教訓としては近いと思います。 slackについては、他の人の目にも入るように「DMといったクローズなチャンネルではなく、オープンなチャンネルを利用しよう」という前提で運用していました。 DMを使うのは個人情報が入っている場合などに限って運用していました。 しかし、その運用前提を伝え忘れていたので、個人DMで仕事の相談をしたり、相談内容がチグハグなチャンネルで行われたりもしました。 JIRAについては、口頭やチャットでの報告やJIRAのチケットにコメントもなく、チケットが閉じられるという事態が起きました。 JIRAの運用フローを伝えてなかったという側面の他にもホウレンソウができてないという側面もありますが、JIRAの使い方については事前に教えてなかったので、こういう事態も起きたのかなと。 ドキュメントが古い 今のプロジェクトは長いこと運用していることもあって、ドキュメントが現実と乖離していたり、同じ内容の記事が複数存在したりしていました。 現在のチームでは暗黙的に「気づいた人がドキュメントを修正する」という状況でした。(大量のドキュメントを常に最新に保つなんて無理だと思っていますし、その状況自体は問題ないと思います。) ただ、暗黙的な状況を伝えてなかったので、新卒の人がドキュメントどおりに進めていてもちゃんと動かず、いろいろと試したり調べたりする内に時間が経ってしまったという事も起きてしまいました。 また、記事が大量にあるため検索しにくい、どこから手をつけていいか分からない、という問題もあります。 先も書きましたが、大量のドキュメントを常に正しく保つなんて無理だとは思っています。 しかし、内容によってドキュメントの分類や配置といったインデックスの整備は人がやるしかない(技術的に賢くできれば嬉しいのですが…)ので、その辺の整備はしていく必要があるなと感じました。 これから いくつか試してみてよかったこと・まだ課題が残ることいろいろとあります。 最初に全体像を掴ませる 小さいサイクルで何度もタスクの成功体験を経験させる 相談先やドキュメントの整備 といった事は今後も続けたいと考えています。 しかし、これだけで十分とは思っていないので、 チームの現状の問題の把握 受け入れフローの明文化 チームとして教えること、新人として知りたいこと なども取り組んで行きたいと考えています。 読んだ方で、もしオンボーディングでやってみて良かった事や教訓などあれば共有してほしいと思っています!
アバター
こんにちは。 id:kfly8 です。7/29(月) に Gotanda.EM #3 でLTをしてきました。 その内容について、書きます。 speakerdeck.com メンターのふりかえり会について 弊社の場合、新人の育成のために新人ごとにメンターをつけています。10人くらい新人がいるので、メンターもおおよそ10人います。 メンターをやるにあたり、初めてメンターをするのであれば、どうメンターをすれば良いか戸惑うと思います。 また、人によってやり方がバラバラであるよりも、組織としてベースラインを担保し年を重ねるごとに強くなれるのが理想だと思います。 ではどうするかですが、まずメンターが知識0からはじめるのは困りますし、組織としても期待はあるのでそれは始めに詰め込んでいます。例えば、期待を伝える場や1on1のワークショップなど行ったり、メンターを何回かやっている人はメンターのお仕事に関わるおすすめの本を薦めたりしています。 ただ、 頭でわかっても、実践が難しい といった話をよく聞きます。 そんな問題を解決するために、月1でメンター同士で集まって、ふりかえり会をしています。目的は、メンターの内省とメンター同士の関係作りです。メンター自身が深く考え・言語化するのと同時に、同じ目線で話す仲間でサポートしあえる関係ができるといいなと思っています。 具体的には、YWTを使っています。YWTは、Y(やったこと)、W(わかったこと)、T(つぎにやること)を言語化する、ふりかえりのためのフレームワークのひとつです。 進め方は、個人ワークでYWTを書き、内容をシェアする形です。駆け足ですが、1時間で行なっています。 まず、「Y:やったこと」では、1ヶ月の出来事を思い出してもらいます。これを挟まずに「W:わかったこと」を始めてしまうと印象に残った出来事などに偏ってしまい、深い洞察がしにくいです。 # Y: やったこと<個人ワーク> メンターとして、今日まで何をしましたか?どんなことがありましたか? いつどんな状況で、どんな言葉を使いましたか? ヒント1:まずは思いつくままに書いてみましょう! ヒント2:1on1の議事録を見返してみましょう。 ヒント3:メンティーとどんなやりとりをしましたか? うまく伝わった、なかなか伝わらなかった、そんなことはありませんか? 次に「W:わかったこと」は、やったことや出来事に対する価値づけを行います。書き出すことを重視して、まずは簡単に「よかった」「わるかった」の価値づけでラベリングしてもらい、そこからどうよかったのか、わるかったのか詳細を言語化してもらいます。 またシェアは、簡潔に話すために「XXXがわかった。YYYという出来事があったから」というようなフォーマットで、一人一つずつ話してもらっています。 このワークがこのふりかえり会の肝です。 # W: わかったこと<個人ワーク、シェア> やったことから、どんなことがわかりましたか? いつどんなふるまいが良かったですか?まずかったですか? ヒント1:まずは良し悪しを見てみましょう! ヒント2:つまり、一言で言うなら、どういうことでしょうか?(教訓化) そして、最後に「つぎにやること」です。わかったことが本当に良さそうかどうかの検証や、他の人の話を聞き、試してみたいことなどを書きます。 # T: つぎにやること<個人ワーク、シェア> わかったことを踏まえ、あなたは次にどんな行動をしますか? ヒント1:できるだけ具体的にしてみましょう! ヒント2:わかったことが良さそうか、どうやったら確認できそうですか? ふりかえってみた実際の内容 実際にふりかえり会をやると、色々な気づきが出てきて面白いです! 例:TIPS 例えば、事前にメンティーに質問回答してもらって1on1するといったTips的な話などは、出やすい話です。 事前に、Google Docsで質問回答してもらい、1on1の時は画面に回答を映しながら議事録を取るスタイルが良い。 メンター、メンティーで意識を揃えながら進行できて、かつ、回答の準備ができる。 シリコンバレー式のテンプレが便利 例:コミュニケーション 他には、コミュニケーションの話が出ます。例えば、メンターが「わかった?」と聞いても、「わかった」と言わざる得なかったりすると思います。あんまり意味のない質問になっちゃうんですよね。どうすればいいか?というと、メンターからは「ケースを提示して、どうするのか説明してもらう。」「わかったという言葉は信じて、話を進めて、もしわからなければつまづくだろう」といった意見が出てきました。似たような質問だと、「大丈夫?」「困ったことある?」なんていうのも同調圧力が生まれがちといった話がありました。 運営として気をつけていること ふりかえり会の運営、ファシリテーションをしていて気をつけていることがいくつかあります。 HOWよりWHY 問題解決もほどほどに 単発より継続 1. HOWよりWHY TIPSは、目先の問題にすぐ適用出来そうで、話の食いつきがいいんですが、具体的な方法は相手次第、状況次第なところがあるので、意図・意義・理由の方の言語化をしてもらうように誘導しています。その方がポータビリティがあると思っています。 2. 問題解決もほどほどに 隣に困っている人がいればなんとかしてあげたいといった気持ちもあり、問題解決の話題も盛り上がったりするのですが、問題解決もほどほどにしています。現実的な理由として、10人弱のメンバーで一つの問題解決をするのは時間効率が悪いと思っています。また声が大きい意見に左右されるのも避けたいです。 そもそも、ふりかえり会はふりかえりの時間としています。メンター自身がどうした方がいいか自分で考えることが、内省につながると思います。 1ヶ月、メンターとして働き、どんな気づきがあったのか、どんな感情になったのか、など言語化できればと思っています。 3. 単発より継続 まず、現実的な話で言えば、メンター業務をやるような人は忙しい傾向があると思っています。なので準備負担なく、ふりかえり会の時間さえ集中すれば良い形にしています。また参加して、直接コミュニケーションしたからこそ得られたものがあるといいと思っています。参加者からするとそういった形の方が継続のモチベーションが湧くのかなと思っています。 また、そもそも育成って地味だと思っています。人は簡単に変わらないと思います。視座・ものの見方の変容ならなおさらです。 運営として、メリハリをつけるためにすごい本などで影響を受けることはあると思います。必要だと思っています。 ですが、頭だけでなく身につけるためには、地道ですがふりかえりを実施し、経験学習サイクルを回す仕組みを作ることが確実なんじゃないかと思っています。 まとめ メンター成長のために、メンター同士のYWTによるふりかえり会をしている。 ふりかえり会の目的は、ふりかえりとメンター同士の関係作り。 ふりかえりのために、HOW、問題解決の話はほどほどにする。意図・意義・理由を自分の言葉にすると良い。 メンターの育成は長期戦。経験学習サイクルを回す仕組みを作る。 最後になりますが、運営のトレタのikegoriさんはじめ、準備などもろもろありがとうございました! 今回、自分も受付などを急遽 *1 やっていたのですが、おかげさまで楽しく参加させてもらいました! *1 : 運営のコアメンバーが急遽体調不良という事件
アバター
こんにちは!今年の4月に新卒として入社したエンジニアの id:maeken2010 です. 5/24(金)に行われた Gotanda.pm #19 に初登壇枠として発表してきました. 今回はその発表についての記事です! Gotanda.pmについて Gotanda.pmとは、五反田近郊で働いている人々や五反田に集結できる人々で開催する、Perlを軸とし好きな技術の話をするコミュニティです (イベントページより引用) 発表の背景 今年の4月に新卒としてモバイルファクトリーに入社し,約1ヶ月半の間 デザイン思考研修 や チーム開発研修 など,様々な研修を行いました. corpcomn.mobilefactory.jp corpcomn.mobilefactory.jp 様々あった研修の1つ,技術研修では,PerlとAmon2,Vue.jsを学びました. さらに,それらを活かしてWebアプリの作成も個人で行いました. 私自身はPerlを学ぶのがこれが生まれて初めてでしたので,不思議に思ったこと,躓いたこと,色々ありました... 今回はそれらの気付きを発表しようと思い,Gotanda.pmで登壇しました:D 発表内容 今回は「はじめてのぱーる」というタイトルで発表させていただきました. Perlの躓いたことを共有し,「 躓いたところをみんなで助ける 」「 Perlを学び始めたあの頃を思い出す 」というテーマで発表しました. 所感 Perlコミュニティの優しさ 発表のテーマ上,参加者からの反応があることが前提だったので,発表する前は"もし誰も反応してくれなかったらどうしよう...😨"と思っていました. しかし!Perl初心者の自分にもたくさんの人から反応をもらいました. むしろ盛り上がりすぎて発表時間を大幅に超えてしまいました(すみません...) 初心者に優しい https://t.co/hASUYHcuGR !! #gotandapm — なりたーん (@return520) 2019年5月24日 まえけんさん「僕がわからないことを言っていくので、Perl経験者の皆さんが答えて行っていただく、そういうスタイルです」 いいな! #gotandapm — sironekotoro💙💛 (@sironekotoro) 2019年5月24日 また,自分だけではなく他の人にとっても知らなかった事を見つける機会になったようでした! Perlの奥深さ Perlの奥深さにも気づきました. Perlは歴史がある言語であり,直ぐには理解できない書き方,独特な概念が多い言語だと思いました. しかし,だからこそ面白さがあると思いました. 他の発表者の 怪しい 黒魔術な話や,言語の内部処理的な話はすごく面白く,さらに全員楽しそうに発表しているのが印象的でした. Perlには言語的に面白さがあり,だからこそ今でも親しまれている言語だと思いました. 終わりに 研修やイベントを通じてPerlに飛び込みましたが,発見や学びがあり,周りの方々にも優しく教えてもらう機会となりました. これからも日々精進していきます!💪
アバター
コーポレート・コミュニケーション室で、育成を担当している id:kfly8 です。 5/17(金)に エンジニアの新人研修Night という勉強会を ギフティ さんと一緒に開催しました。 勉強会の主旨は... 他の会社では、エンジニアにどんな新人研修をしているのか? 実際、新人研修を受けてどんな学びがあった? こういった悩みを解決したく開催し、大盛況でした! 参加された方には、レポートも書いていただきました! 学びがあった声が聞けたので、開催してよかったです。ホッとしました。 tamochang.hatenablog.com blog.giftee.dev https://www.masalog.site/entry/2019/05/18/103418 www.masalog.site 所感 今回、まず、各社の新人研修の「背景、意義」が聞けて、よかったです。 約5年、新人研修の担当をしているのですが、 研修は「背景、意義」が伝わったかどうかで効果が大きく左右されると感じています。 もちろん伝える知識、スキルの準備はするのですが、 無数にある選択肢の中で、なぜその知識、スキルを学ぶと良いのか? ただ会社が求めているからではなく、世の中のどんな問題を解決して、何が得意で何が面白いのか? そんなことが伝わった方が、能動的に学べます。 特に新人研修は、社会人になって初めての出来事なので、 実務で問題に直面した経験は少なく、必要性を感じていないことが殆どです。 そういった状況で、いくら「大切だ」と叫んでも、伝わらないです。 なので、弊社の場合、実際に問題を体験する工夫をしたり、場合によっては春の新人研修での実施を諦め配属後に回しています。 それくらい自分は「背景、意義」が大切だなーと思っていたので、 普段なかなか聞けない、各社の事情が聞けてよかったです! 次に、研修に参加する人同士の関係やコミュニケーションといったメタな視点での設計の話も面白かったです。例えば、 TAKAKING22さんのスライド の 研修期間は長い社会人人生のほんの一部 というのはまさにその通りだと思います。世の中の変化も激しいので知識、スキルは学び直しが必要になります。そういった状況で、学ぶ内容にばかりに気を取られるのは、勿体なさそうです。 例えば、新卒同士で気軽に話ができるコミュニティ作りも研修設計に必要だと改めて感じました! ネクストアクション 懇親会でギフティCTOの柳瀬さんと次回の開催について「次年度の新人研修の設計をする時期に、また開催したい!」そんな話をしました。楽しみです!
アバター
こんにちは、 id:kfly8 です。今回は1年2ヶ月ぶりの開催となったGotanda.js #11 の速報レポートをしたいと思います! あと少しで始まる!!!! #gotandajs pic.twitter.com/Cn8cujxcnT — kobaken (@kfly8) 2019年5月10日 #gotandajs 設営できました🍺🍺🍺 pic.twitter.com/HmohlCRHe7 — kobaken (@kfly8) 2019年5月10日 Web Components入門 - tiwu official さっき発表した登壇資料です。似たようなconnpassのlistのWeb Components作っているからそろそろ違うの作りますw Web Components入門 #gotandajs https://t.co/9ATA6qDEqa — tiwu (@tiwu_official) 2019年5月10日 Node.jsでのrecursive readdirを考える - あらや (ピザを受け取っていた為、聞けませんでした...) (node.js でディレクトリを再帰的に探索するときに、ファイルかディレクトリか区別する時に簡潔になり、またPromiseとしても扱えるようになったという話と懇親会で聞きました) Gatsbyで画像を扱うときのTips - takanorip 静的サイトジェネレータのGatsbyで、サイズなど動的に画像を扱いたい時に、 gatsby-transformer-json を使うとgatsby image でいい感じにごにょれるようになる。けど結局、CDNの機能使う方がいいんじゃない?というオチ。 フロントエンドをふりかえる - kahirokunn アーキテクチャは人に依存するより、仕組みに依存させた方が良さそうという話。資料楽しみです。 休憩 ピザが溶けるようになくなった #gotandajs pic.twitter.com/RXXuGq2tI6 — 福本晃之@ZEALS VPoE (@terry_i_) 2019年5月10日 今更recomposeの話 - Quramy React Hooks の登場で、メンテナンスは終了しているけれど、recomposeが使われたコードをメンテナンスしている人もいるだろう、とのことで発表されました。裏話としては、「ジェネリクスが含まれる汎関数を返すような関数」の話をしたく、その例として、recomposeを思いついたとのこと。 TS3.4からcomposeしても型アノテート少なく型推論できて便利って話をしていた(と思います) AWS CDK の話 - yamatatsu 次の発表資料です! AWS CDK の話 https://t.co/C2iGBhkWxb #gotandajs — やまたつ (@yamatatsu193) 2019年5月10日 dockerでnodeの開発は厳しいのか? - mizuki_r Docker on Mac は、volume mount しているとIOが非常に遅く、開発に困る。mountを外せば、hostのIOとほぼ変わらない形にできる。 しかし、VS Codeで補完を機能させるには、mountされている方が都合が良い。そこで、最近公開されたVS Code の insiders build を使うことでホストにマウントせずに、VS Codeの恩恵に預かれるという話。 今日の発表資料です! #gotandajs https://t.co/Fn2A7OnHMg — 水月 涼 (@mizuki_r) 2019年5月10日 Gatsby.jsとNetlifyとの付き合い方 - kikunantoka 次の発表の資料はこちらです! https://t.co/cbDG1JcGWC #gotandajs — キクナントカ (@kikunantoka) 2019年5月10日 懇親会 懇親会の様子です。 #gotandajs pic.twitter.com/iBWh5mx0jN — kobaken (@kfly8) 2019年5月10日 まとめ ゆるさがウリと、Gotanda.jsの噂を聞いていたのですが、確かにスライド無しでわいわい話したり、参加しやすいコミュニティだなーと思いました。 個人的には、今回、Gatsby.jsの話が多かったので、試してみたいと思いました!
アバター
こんにちは。ブロックチェーンチームでエンジニアをしている id:odan3240 です。 4月4日に行われた Meguro.es #20 で「JavaScript + Dockerの知見」というタイトルで登壇してきました。今回の記事はその発表の紹介です。 発表の背景 モバイルファクトリーに入社してからの約1年間でいくつかのサービスに関わってきました。 サービスサイト: https://uniqys.net ブロックチェーンアプリ検索サイト: https://findapps.me ブロックチェーンアプリ開発ツールキット: uniqys/UniqysKit チームの開発では、フロントエンドはvue.jsやnuxt.jsが、バックエンドではTypeScriptが採用されることが多いです。実際関わったお仕事の技術スタックは次のようになっています。 サービスサイト フロントエンド: nuxt.js ブロックチェーンアプリ検索サイト フロントエンド: nuxt.js バックエンド: TypeScript ブロックチェーンアプリ開発ツールキット 実装: TypeScript サンプルアプリ: vue.js このうちブロックチェーンアプリ検索サイトでは、開発環境にDocker for Macを、本番環境にDockerを使用しています。 チームではデザイナがvueファイルを触ることがあるため、 docker-compose up を叩くだけで簡単に開発環境が立ち上がることを理由にDocker for Macを使用していました。 知見 このような背景でmeguro.esではJavaScript+Dockerに関する次の5つの知見を共有しました。 コンテナのnode_modulesを守る ホストのnode_modulesを用意 Docker for MacのI/Oが遅い node.jsはPID 1を想定していない問題 .dockerignoreを用意する 詳しくはスライドをご覧ください。 speakerdeck.com 反響 懇親会 フロントエンドの開発環境についての情報交換を行いました。スライドで主張していた「開発環境をDockerに閉じ込めてもコード補完のためにホスト側にnode_modulesを用意する必要がありつらい」に共感する話をいただけました。自分の中でもやもやしていた不満点は、他の方も同様に感じていることがわかり安心しました。 ネット スライドを公開したところはてなブックマークでいくつかのコメントがつきました。 http://b.hatena.ne.jp/entry/s/speakerdeck.com/odanado/knowledge-of-docker-in-javascript また、IOボトルネックの観点からもフロントエンドの開発環境にDockerは不要だという言及もされました。 mizchi.hatenablog.com 終わりに meguro.esは名札に貼る属性シールが用意されているなど、参加者に配慮されているとても良い勉強会です。興味のある方は6月6日に予定されている meguro.es #21 に参加してみてはいかがでしょうか。 Meguro.es # 20 @ Drecomの参加レポート: https://meguro.es/posts/meguro-es-20
アバター
こんにちは。シニアエンジニアの @yashims85( id:yashims85 ) です。 今日は2019/03/27にM3さんで行われた「 どこでもKotlin #7 〜Kotlin MPP特集〜 」に登壇してきた事についての記事です。 どこでもKotlinとは Android開発言語として注目されているKotlin、その活躍の場はAndroidだけじゃない!!! Kotlinはサーバーサイドでも、どこでも(デスクトップアプリやAltJS、iOSアプリなどでも)使える言語です。 エムスリーではAndroidアプリやサーバーサイドの開発言語としてKotlinを実践投入しています。「どこでもKotlin」では様々な分野におけるKotlinの話題について取り上げていきます。 イベントページより引用 他の登壇者様の資料や発表内容については、ページ下部のリンクやハッシュタグ( #m3kt )、または エムスリー様のテックブログ をご参照ください。 発表内容 今回は「Kotlin/MPPでX-PF 事始めのつまづきポイントというタイトル」で登壇させていただきました。 2019/03/27現在、モバイルファクトリーではKotlin/MPPを使用して、既存プロダクトのリプレースを進めています。 また、それと平行して、個人的にそのプロダクトで使用するためのKotlin/MPP用のプレゼンテーションルーターをOSSで開発しています。 今回の発表ではそれら2つのプロダクトでKotlin/MPPを使用して、開発を進めている中で得られた知見を共有しています。 印象に残ったこと Kotlin/MPPの使用され度 会場でKotlin/MPPの使用状況についてアンケートを取るシーンがありました。 「実際のプロダクトでKotlin/MPPを運用している」という会社は1、2社といったところで、やはりまだまだ少ない印象です。 その状況を鑑みるに、今回私の発表中で軽く触れたクライアントアプリの設計について、今後深く話してみたいなという印象をいだきました。 Kotlin/MPPのプロジェクト構成とbuild.gradle 参考にできる情報が少なく、今弊社的にもKotlin/MPPで一番苦しんでいるポイントです。 今回登壇した方々にしてみても、やはり同じ様な苦しみを経験していらっしゃるでした。 そんなみなさんの発表ですので、私にとって知見の塊といってよくとても有意義な勉強会でした。 他の方々の登壇内容について どの発表も目からウロコで知見の塊でした。 How to upload a kotlin multiplatform project library. - 荒谷 光 Kotlin/MPPの記事を探すとだいたいこの方に行き当たるというすごい人。 ちょうど私もKoRouterのPublish方法わからなくて泣いていたところだったので、渡りに船のような発表でした。 時間過ぎてすみません🙏🏻 どこでもKotlinで発表した Kotlin Multiplatform Project 向けライブラリの作り方の資料になります 今日のは、いざやる時に参照する系の発表なので、あとでブログも書きます https://t.co/lxQ29Xqcpr #m3kt — AAkira (@_a_akira) 2019年3月27日 DroidKaigi 公式アプリのKotlin Multiplatform - takahirom DoroidKaigi 2019の公式アプリのオーナーを務めるtakahiromさんの発表です。 実際にアプリをKotlin/MPPで作り、それをリリースしており、経験に裏打ちされたつらみやわかりみがあり、一歩先を行く転ばぬ先の杖のような発表でした。 先程の資料です DroidKaigiアプリのKotlin Multiplatform 資料: https://t.co/aXrLlSkEal Qiita: https://t.co/uzA3qeTZWO #m3kt — takahirom (@new_runnable) 2019年3月27日 Kotlin/NativeのiOSにおけるオーバーヘッド - 星川 貴樹 どこでもKotlin運営である@oboenikuiさんの発表です。 Kotlin/NativeでKotlinを動かすときの知見です。アセンブリの読解と、アセンブリからObj-Cライクな擬似コードを出力するHopperはまさに温故知新、新たな発見でした。 Kotlin/NativeのiOSにおけるオーバーヘッド https://t.co/nEwDQqQy5P 本日の資料アップしました!後日ビルド通るようになったらブログでもデータをまとめて書きます! #m3kt — おぼえにくい (@oboenikui) 2019年3月27日 おわりに モバイルファクトリーでは社内、社外を問わず日々様々な勉強会や読書会が行われています。 そんな環境で、ともに成長していける仲間を募集しています。
アバター