TECH PLAY

株式会社ラクス

株式会社ラクス の技術ブログ

927

はじめに こんにちは。新卒2年目のtaku_76です。といってもあと半月ほどで3年目になります。 今回は以前ある記事でコンテナ技術の習得は必須ということを見て、コンテナ技術について表面的なことしか知らないなーと思い、学習しています。まだ学習途中ですが、初めに学んだ基本的な内容をまとめておこうと思います。 はじめに Dockerとは コンテナ型の仮想化とは Dockerイメージとは Dockerコンテナの実行 helloworldイメージの実行と動作解説 nginxイメージの実行と動作解説 最後に Dockerとは Docker社が提供しているコンテナ型のアプリケーション実行環境です。 コンテナ型の仮想化とは OSの カーネル を利用してホストOS上にアプリケーション実行環境を作るものです。 以下のような構造となっています。 コンテナ型仮想化の構成 Docker Engineがコンテナ型仮想化のコアとなる部分で、コンテナの作成、起動、停止、削除などの操作はDocker Engineを介して行われます。使い方としましてはDockerのコマンドを実行することでDocker Engineに指示を出すことになります。 以下にコンテナ型仮想化のメリットとデメリットをまとめます。 メリット ホストOSの カーネル を使用するため、動作が早くリソースの使用率が少ない 同じDockerイメージからコンテナを起動することで、環境が変わっても問題なく動作させることができる デメリット コンテナはホストOSの カーネル を使用して動作するため、 カーネル を共有できないOSでコンテナを動作させることができない Dockerイメージとは 特定のコンテナを実行するのに必要なファイルをまとめた ファイルシステム です。一般的にOSのライブラリやアプリケーションなどがあり、Dockerイメージは自分で作成することもできます。構成としてはイメージのデータはレイヤーで構成され、読み取り専用なので編集することはできません。以下Dockerイメージの構成となります。 左がDockerイメージで右がDockerイメージから作成したコンテナの図になります。Dockerイメージは図のように階層構造でデータが管理されており、各層のレイヤーはコマンドを実行する際に階層が積み重ねられます。そして、Dockerイメージを元にコンテナを起動すると読み書き可能なコンテナレイヤーの層が作られます。コンテナレイヤー上にファイルの追加など行い、それをまたイメージとして保存することも可能です。注意として、過去のレイヤーで追加したファイルをコンレナレイヤーで削除し、新しいイメージを作成しても過去のレイヤーから対象のファイルが消えることはありません。よって、無駄なファイルがイメージに含まれないように作成することが大切です。 Dockerコンテナの実行 helloworldイメージの実行と動作解説 コンテナの実行は簡単です。以下のコマンドをターミナルで入力します。 $ docker run hello-world すると結果を以下のようになります。 Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 1b930d010525: Pull complete Digest: sha256:f9dfddf63636d84ef479d645ab5885156ae030f611a56f3a7ac7f2fdd86d7e4e Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/ ここで起こっていることを説明します。 1.まずローカルでDockerクライアントがDockerデーモンに接続してhello-worldのイメージを探します。 2.今回はローカルにhello-worldのイメージは存在しないので、インターネットを経由してDocker社が ホスティング しているDocker Hubのサーバに探しに行きます。 3.イメージが見つかればダウンロードしてローカルに保存します。 4.保存したイメージをもとにコンテナを起動して、コンテナに定義されたコマンドを実行します。 ※同じイメージがローカルに存在する場合は、2と3は省略されます。(ダウンロードがないので早く実行される) ちなみに、docker runコマンドは複数のコマンドをまとめて実行したもので、以下のコマンドをまとめています。 1.docker pull:イメージの取得 2.docker create:コンテナの作成 3.docker start:コンテナの起動 取得したイメージは以下のコマンドで確認することができます。 $ docker imeges 結果は以下のようになります。 REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest fce289e99eb9 14 months ago 1.84kB リポジトリ に含まれるイメージがTAGによって管理されているのですが、特にTAGを指定しなかった場合にはlatestTAGのイメージがダウンロードされます。 また、以下のコマンドでイメージの詳細情報を表示することができます。 $ docker inspect hello-world 結果は以下のようになります。 [ { "Id": "sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e", "RepoTags": [ "hello-world:latest" ], "RepoDigests": [ "hello-world@sha256:f9dfddf63636d84ef479d645ab5885156ae030f611a56f3a7ac7f2fdd86d7e4e" ], "Parent": "", "Comment": "", "Created": "2019-01-01T01:29:27.650294696Z", "Container": "8e2caa5a514bb6d8b4f2a2553e9067498d261a0fd83a96aeaaf303943dff6ff9", "ContainerConfig": { "Hostname": "8e2caa5a514b", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, (中略) Dockerコンテナの設定情報として、ホスト名や 環境変数 コンテナ起動時に実行されるコマンドやコマンド実行時の ディレクト リの情報などが表示されます。そのほかにも様々な情報が表示されていますので、詳細情報を確認する際によく使われるコマンドです。 そして、ローカルで取得したイメージの削除を行います。次のコマンドで削除することができます。 $ docker rmi hello-world 強制削除を行う場合は-fオプションを使用します。 ここまででhello-worldイメージを用いてDockerイメージの取得から削除までを解説しました。 nginxイメージの実行と動作解説 ここではnginxイメージを使用してデフォルトのnginxの画面が表示されるところまで進めます。 nginxコンテナを立ち上げるコマンドは以下になります。 $ docker run --name <コンテナ名> -d -p <ホスト側のポート番号>:<コンテナ側のポート番号> <イメージ名> コマンドの解説ですが、runについては説明済みですので割愛します。--name <コンテナ名>ですが、コンテナを識別したりコンテナの操作を行うために、起動するコンテナに名前をつけるオプションです。引数は任意の名前をとります。-dオプションはデタッチモードとしてコンテナの実行をバッググラウンドで行うためのオプションです。-pオプションは、コンテナのポートをコンテナ外に公開する設定です。ホストマシンが外部に公開するポート番号:コンテナに マッピング するポート番号という構成です。 それでは実際にnginxコンテナを起動してみます。 $ docker run --name nginx-test -d -p 8080:80 nginx 以下のような結果になります。 Unable to find image 'nginx:latest' locally latest: Pulling from library/nginx 68ced04f60ab: Pull complete 28252775b295: Pull complete a616aa3b0bf2: Pull complete Digest: sha256:2539d4344dd18e1df02be842ffc435f8e1f699cfc55516e2cf2cb16b7a9aea0b Status: Downloaded newer image for nginx:latest この状態で http://localhost:8080/ にアクセスするとデフォルトのnginxの画面が表示され、nginxコンテナが正常に起動できていることが確認できます。 こちらについて解説しますと、nginxコンテナの80番ポートをコンテナを実行している 仮想マシン の8080番ポートに対応させています。これによって 仮想マシン の8080番ポートにアクセスした場合、nginxコンテナのネットワークインターフェースの80番ポートに転送するように設定されます。そして80番でlistenしていたnginxがコンテンツを返し、ウェブブラウザの画面にデフォルトが表示されます。 ここで、コンテナの状態を確認するために以下のコマンドを実行します $ docker ps 以下のような結果になります。 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 14da03714d91 nginx "nginx -g 'daemon of…" 26 minutes ago Up 3 minutes 0.0.0.0:8080->80/tcp nginx-test STATUSを見ると、現在実行中であり起動して3分経過していることがわかります。 そして以下のコマンドでコンテナの実行を停止することができます。 $ docker stop nginx-test 状態を確認します。 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 14da03714d91 nginx "nginx -g 'daemon of…" 32 minutes ago Exited (0) 6 seconds ago nginx-test STATUSがExited状態となり停止していることが確認できます。 ここまでで、nginxコンテナの起動から停止までの解説をしました。 最後に 今回はDockerについて基本的なことや操作をまとめました。Dockerファイルについても記載したかったですが、次の記事を書く機会に自分の作成したいアプリケーション実行環境を構築した話を書きたいと思っています。
アバター
こんにちわ @kawanamiyuu です。早いものでもう開催から 1 ヶ月経ちましたが、先月開催された Object-Oriented Conference で登壇してきました。また、弊社はブロンズスポンサーとして協賛していました。 イベント概要 登壇資料 登壇に対する反応 登壇までのチャレンジ 〜登壇駆動登壇の実践〜 Appendix. イベント概要 日時:2020 年 2 月 16 日 (日) 会場: お茶の水女子大学 公式 HP: https://ooc.dev/ ハッシュタグ : #ooc_2020 ooc.dev 登壇資料 speakerdeck.com 登壇資料のサマリー 登壇に対する反応 since:2020-02-16_16:30:00_JST until:2020-02-16_16:50:00_JST #ooc_e 今回の発表の軸となる主張に共感いただけて良かったです。 「 アーキテクチャ の正体は依存関係の取り決め」、確かにだった。 アーキテクチャ テスト導入しているけど、自分の実装ミスに気付くだけでなく違反を起点に話し合うきっかけにもなっているのでもっと広まればいいなと思う。 #ooc_2020 #ooc_e — west-c (@west_c_) 2020年2月16日 アーキテクチャ は依存関係を適切に設計したいだけ →わかる。適切に設計したい理由はいろいろあるけど、「テストしやすいため」が個人的には一番。 #ooc_2020 #ooc_e — ウホーイ (@the_uhooi) 2020年2月16日 依存の向きにフォーカス、うん大好きさ #ooc_e — suzuki- hoge (@suzuki_ hoge ) 2020年2月16日 登壇までのチャレンジ 〜登壇駆動登壇の実践〜 今回の登壇にあたって 1 つチャレンジがありました。それは 登壇駆動登壇 の実践です。「 アドベントカレンダー (12月) → 社内ビアバッシュ (1月) → 自社主催のMeetup (2月) → 本番 (2月)」と アウトプットを重ねながら 言語化 に取り組む ことで発表の完成度を上げていきました。 今回は特にアウトプットのスパンが短かったためとても緊張感があり骨の折れる作業でしたが、プロポーザル作成時には整理しきれていなかったア イデア を 言語化 でき、満足のいく発表に仕上がりました。 何度か登壇を経験し人前で話すこと自体へのハードルはほとんど感じなくなった私ですが、「 言語化 」することが苦手な私にとっては今回の取り組みで得られた手応えは、今後の登壇に対するブレイクスルーになったと感じています。 Appendix. アーキテクチャ テストに興味がわいた方はこちらもぜひ↓ tech-blog.rakus.co.jp
アバター
こんにちは、株式会社 ラク スで横断的にITエンジニアの育成や、技術推進、採用促進などを行っている開発管理課に所属している鈴木( @moomooya )です。 ラク スの開発部ではこれまで社内で利用していなかった技術要素を自社の開発に適合するか検証し、ビジネス要求に対して迅速に応えられるようにそなえる 「 開 ( か ) 発の 未 ( み ) 来に 先 ( せん ) 手をうつプロジェクト(通称:かみせんプロジェクト)」 というプロジェクトがあります。 2019年度下期にこのプロジェクトで「 機械学習 プロジェクトの進め方」について検証したので紹介したいと思います。対象読者は非エンジニアを含む、 機械学習 を用いた機能を企画・設計する全ての関係者 となります。 今までの記事はかみせんカテゴリからどうぞ。 tech-blog.rakus.co.jp 今回の目標 参考書籍 あらためて機械学習とは 何ができるのか 機械学習プロジェクトのアンチパターン システムに組み込むまでの手順 プロジェクトの進め方 問題の明確化 システム設計 機能設計 アルゴリズム選定 前処理 モデルの作成 モニタリング 2つのモニタリング 活用事例 大日本住友製薬と英Exscientiaの創薬事例 講談社のTEZUKA2020プロジェクト 結論 社内勉強会の際に挙がった声と回答 今回の目標 「 人工知能が幻滅期に入った 」と言われるようになったので 1 、啓蒙活動期に向けて本格的な検証を開始しています。 プロダクトに 機械学習 を利用した機能を実装するにあたってエンジニ アサイ ドだけではなく、ビジネスサイドも含めて、どういった考えで取り組むべきなのかをまとめます。 いきなり難しい領域に取り組むのは無謀なので一番わかりやすい「 教師あり学習 」のみを想定します。 toB サービスの場合だとクライアントに説明しにくい処理を組み込むのはハードルが高すぎるということも考慮しています。 参考書籍 仕事ではじめる機械学習 作者: 有賀 康顕 , 中山 心太 , 西林 孝 オライリージャパン Amazon 特に第1部第1章は関係者全員に読ませましょう。 人工知能システムのプロジェクトがわかる本 企画・開発から運用・保守まで (AI & TECHNOLOGY) 作者: 本橋 洋介 翔泳社 Amazon プロジェクトを進めていくにあたっての ケーススタディ が豊富。 あらためて 機械学習 とは 何ができるのか 大まかにいって 入力データを分類すること 入力データから数値を予測すること の2つです 2 。 機械学習 プロジェクトの アンチパターン 「 機械学習 でなにかすごいことをしたい」という上司が現れて、何をすればいいかというところから頭をひねるようなプロジェクトになってしまい、うまくいかない結果に終わる危険性が高まります。 『仕事ではじめる 機械学習 』第1部第1章「 機械学習 プロジェクトのはじめ方」より 「言わずもがな」ですね。 システムに組み込むまでの手順 まずはデータがないと話がはじまりません。後から出てくるScikit-Learnの チートシート ではデータの特徴によって適切な アルゴリズム が選択できますが、 少なくとも50サンプル以上 が必要となります。他にも基準として「1万サンプルを超えるか」「10万サンプルを超えるか」という目安が 大規模なデータかどうか という基準として出てきます。 データを用意したら次に行うことはデータの前処理です。 機械学習 の世界では 「前処理8割」 という言葉があるようで、非常に重視されています。収集した生のデータはそのままだと扱いにくい書式や値であることが多く、それを学習 アルゴリズム への入力として都合の良い形に整形しましょう、というのが「前処理」になります。 取り組む前は次の学習モデル作成が大変なのかと思っていましたが、自前の アルゴリズム 構築を行わない場合は前処理工程の方が遥かに大変です。 前処理を行ったデータを入力として学習モデルの作成を行います。自前で学習 アルゴリズム の構築を行わない場合、公開されている アルゴリズム 選択 チートシート と 機械学習 ライブラリを用いて、学習 アルゴリズム の選定と実装ができるので比較的容易に学習モデルの作成は出来ます。 作成した学習モデルをシステムに組み込みます。組み込みの際には作成した学習モデルファイルを読み込んで利用します。併せてモニタリングに必要な数字も取得できるように作り込みましょう。 プロジェクトの進め方 問題の明確化 機械学習 を使っても 人間が真偽を判断できない問題は解くことが出来ません 3 。 注意しなければならないのは「人間が判断できるかどうか」を考えるときに所要時間はあまり意識する必要がないことです。例えば「何日もかければ正しいかどうか判断できる」というような実務上現実的ではない時間がかかる場合でも、 判断することができれば多くの場合問題ない です。なぜならプログラムの実行速度は人間の何倍もの速度があるため時間的な制約は問題にならないためです。 問題と対になる成果の指標も最初に決めておきましょう。 機械学習 を利用した機能の運用は高コストになりがちなので ビジネスに貢献出来ていることが必須 です。ビジネス観点でのKPIを定めておくべきです。 問題を人間が解けることの確認とKPIが定まったら、取り組む問題が本当に必要なのか、取り組む問題に 機械学習 が必要なのかを検証しましょう。『仕事ではじめる 機械学習 』でも大きく扱われているように 機械学習 を使わない方法を検討します。想定しているよりも機能や利用シーンが制限されたものでもよいのでプロトタイプを作成し、問題設定が想定通りかどうか検証しましょう。 検証の結果、 機械学習 を利用しなくても要件を満足することもある と思います。その時はオーバースペックなものを作らずに済んだと喜びましょう。 手段を目的と勘違いしてはいけません 。 システム設計 機能設計 データ収集方法 予測誤りのカバー方法 撤退ラインの定義 先述の通り、データ収集の仕組みが必要になります。数千サンプルのデータを継続的に収集することは手作業では割に合わない作業です。最初の1, 2回を検証を兼ねて手作業でやることは否定しませんが、それが3回、4回と続くようなら見直したほうが良いでしょう。 また、 機械学習 では誤った結果を出力する ことがあります。大体よく見かける予測正解率は80~90%程度なので5~10回に1度くらいと、 それなりの頻度で誤った結果を出力するため仕組みとして誤った結果を出力しても問題にならないような機能設計が必要 です。 そしてこのフェイズを超えたあたりからサンクコスト効果により、撤退判断が遅れやすくなります。なので、この時点で撤退条件を定義しておくとよいでしょう。 アルゴリズム 選定 機械学習 アルゴリズム の選定については自前で アルゴリズム を構築しない場合であれば以下で アルゴリズム 選定用の フローチャート が公開されています。 scikit-learn - Choosing the right estimator 機械学習アルゴリズム チート シート - Azure Machine Learning 昔は アルゴリズム から開発することが必要だったようですが、現在は優秀な アルゴリズム が簡単に利用することができます。感謝して使わせてもらいましょう。 前処理 いちばん大変な工程です。 機械学習 はデータからデータを導く アルゴリズム なので入力データが重要で、最終的な予測精度にも影響するようです。なのでたくさんのデータを集めて精度を上げるわけですが、 収集したデータが都合の良い書式であるとは限りません 。というよりも 都合が悪い形式であることを前提に取り組んだほうが良さそう です。データソースが1つであればまだマシでしょうが、複数のデータソースからデータを集めてきた場合にはさらに手間が増加するでしょう。 「前処理8割」という言葉があるらしいですが、以下のような様々な処理が必要になるようです。 データクリーニング(データクレンジングとも) 不要なサンプルの除去 ノイズとなる外れ値の除去 値がない項目の処理 値の整形 値の分布を正規化 よくあるのは0~1の範囲に変換 細分化しすぎている分類を集約 自然言語 での時制、語尾変化、類語の統一 これらを実現するための手法もいろいろ考案されているようで、前処理だけに絞った書籍も複数出版されています。 今回は前処理がこんなに奥深いテーマだということを知らなかったため深追いしませんでしたが、来年度の取り組みテーマとして前処理の掘り下げを予定しています。 モデルの作成 判断材料となるデータは場合によっては非常に大きなデータサイズになり得るため、そのままシステムに組み込むわけには行きません。そのため 機械学習 アルゴリズム を通して作成した 学習モデルのみを組み込み ます。学習モデルは誤解を恐れずに言うとデータを分析して抽出した条件式の詰め合わせのようなイメージです。 機械学習 アルゴリズム の選定や実装も先述の通り、既存の フローチャート やライブラリを利用することで比較的容易に実現することが出来ます。 ただし忘れてはいけないのは運用を開始しても、新たに収集したデータを元に定期的に学習モデルの再作成(再学習)が必要になります。 再学習を行わないと入力傾向の変化や未知の入力パターンに適応できなくなる ためで、この現象はコンセプトドリフトと呼ばれています。 モニタリング 2つのモニタリング 機械学習 の予測精度は入力傾向の変化によりいつかは劣化します。予測精度劣化の兆候を検知するためにもモニタリングは必要です。 予測結果が把握できている入力デー タセット を ベンチマーク デー タセット として利用します 。このデー タセット のことを「ゴールドスタンダード」というそうです。 もう一つはビジネス的な成果のモニタリングです。機能を作成してもビジネスに貢献できていなければ意味がありません。ビジネス観点の指標をモニタして成果が上がっていることを確認しましょう。 活用事例 では進め方はともかくどのような使い方をすればよいのでしょうか。 システム設計の項で触れた「誤った結果を出力しても問題にならないような機能設計」という観点を交えて見ていくと非常に参考になるケースを見つけました。 大日本住友製薬 と英Exscientiaの 創薬 事例 www.itmedia.co.jp こちらの 大日本住友製薬 と英Exscientiaが2020年1月30日に発表したAIを活用した新薬が 臨床試験 を始めた事例です。新薬開発の世界では膨大な組み合わせの中から候補となる組み合わせを専門家の知識と経験で見つけ出し、それを検証して製品化につなげるそうです。この事例では「膨大な組み合わせの中から候補となる組み合わせを見つけ出す」部分にAIを活用しているそうです。 膨大な組み合わせから候補を探すという「0を1にする」部分においては専門家が取り組んでもとても時間がかかる部分ですが、専門家よりもたとえ精度が劣ったとしても圧倒的な早さで候補を挙げてくれるとすれば大きな成果となるでしょう。もちろん専門家が取り組んだ場合に比べて使えない候補は多かったと考えられます。ただし使える候補か使えない候補か判断する部分に専門家(人間)が入ることで誤った結果を排除し、 臨床試験 に望むまでを4年半から12ヶ月未満と大幅に縮めることが出来たよい活用事例だと考えられます。 他にも同じような活用事例として、 三菱マテリアル も同様のプロセスで新素材の開発に活用しているようです。 三菱マテリアル は 機械学習 プロジェクトを始める際のビジネス フレームワーク となる 機械学習プロジェクトキャンバス を作成し公開してくれています。今回の取組中にも参考にさせてもらいました。 講談社 のTEZUKA2020プロジェクト www.itmedia.co.jp こちらは2020年2月26日に発表された 講談社 による「 手塚治虫 が新作を作ったらどんな漫画になるだろう」という課題にAIを活用したものです。 こちらも本質的なプロジェクトの進め方は上記の 創薬 プロジェクトと同様で、漫画の軸となるプロットとキャ ラク ターデザインの候補をAIが提示し、それを人間の判断により選び出し制作を行うという流れで取り組んだそうです。 結論 分類と数値予測 入力データの収集が必要 入力データはそのまま使えない、整形には手間とノウハウが必要 従来の方法では手間がかかりすぎることをやらせると良い 「人間ができること」を「間違えることもあるが」「高速に判断できる」 間違えたときのカバーする仕組みが大事 運用を始めると必ず劣化するので監視と再学習が必要 社内勉強会の際に挙がった声と回答 エンジニア、ビジネスサイドを交えた勉強会を社内で実施したときの声をいくつかピックアップします。 Q. プロジェクトに着手して試行錯誤しながらやることを決めると思うけど見積もりできなくない? A. 最初から正確な見積もりはできないのはそのとおりで、段階的に見積もることになります。数段階再見積もりを行うフェイズを計画時に設定し、段階的に精度を上げていくことになると思います。 Q. ユーザーに選択を求めるようなインタフェースで選択結果を正解として再学習すれば精度は上がる? A. 特定のケースに特化して学習してしまう「 過学習 」の状態にならないよう注意が必要です。 過学習 になってしまうと新しい入力パターンに弱くなってしまいます。 「お客さんの利用方法や行動をもとにアップセル候補の抽出に使えるかも。ベテランの勘を実装できれば」 「被検索などのデータから広報施策のタイミングとか見つけられそう」 「逆に 機械学習 ではないけど世間でAIと呼ばれている領域の知識も知りたい」 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com ちなみにハイプ・サイクルにおいて幻滅期は「衰退」「流行の終わり」といった勘違いをしやすい言葉ですが、まったくの逆で「 バズワード が定番技術に変わる準備期間」くらいの認識が正しいです。 ↩ 一般的な説明だと「分類」「回帰」「 クラスタリング 」「次元削減」と言われますが、最初の段階だと「分類」「数値予測」で話をした方が理解しやすいと思います。 ↩ 教師なし学習 とか、もっと言えば深層学習とかだとこの領域にも答えを見つけられるかもしれませんが、今回扱う 教師あり学習 の範囲では人間が判断出来ない問題は解けません。 ↩
アバター
こんにちは。 @penguin_no_045 です。 先日開催された[ PHPerKaigi 2020 で登壇させてもらいました。皆様どうもありがとうございます。 資料 speakerdeck.com 「PHPerがこれから「型」とお付き合いしていくために 」というタイトルでした。最近の PHP は型に関する進化が多いような気がしたのでテーマとして選定しました。 また、私の観測範囲内ですが、一時期別の言語ユーザーの間で 静的型付き言語 vs 動的型付き言語 だったり、動的型付き言語は 型推論 が入っているので云々といった話題が見られました。そこで、これからPHPerとして型と触れ合う機会が増える前に知識を整理しておこうと思い立ったわけです。 私はもともと静的型付き言語ユーザーだったので、型システムは身近なものでした。そこで軽い気持ちでプロポーザルをまとめたのですが、実際は今回のセッションの準備中に学んだ知識のほうが多かったです。 概念としてはずっと触れてきたものでも、改めて体系的に学ぶとあやふやな理解をしていた個所などはすぐに化けの皮が剥がれるものですね。 とくに型システムというテーマは不正確な情報がけっこう頻繁に流布されている印象があったので、自分もそうならないように気を付けました。諸先輩方からはどのように映ったのでしょうか? 発表内容について触れると、立て付けとしては型システム入門以前、といった感じになったと思います。そのため、今回のセッションでは簡単のために説明を省いた部分や、意図的にセッションのスコープから除外した領域が結構あります。 型システムに詳しい方は物足りなさを感じられたかもしれませんし、今回のセッションの中でも必要な概念が一部説明できないままの個所もあります。その部分についてはいつか語りたいなと思っています。 また、質疑などでより深い内容について質問をいただくことができ、その場で捕捉したいことを話すことができたのは幸いでした。改めて皆様ありがとうございました。 少しだけの補足 そんな質疑の中で1つ特に印象的だったものがありまして、「 PHP で型安全に配列を扱うには?」というものがありました。 これについてはよくある話で、私も「コレクションを定義するのが良い」と回答しましたが、そこにはたくさんの壁が待ち受けているということを説明できていませんでした。 実際にコレクションライブラリの自作にチャレンジして、 心が折れる 、というのは昔から繰り返されてきたものではないかと思います。( PHP に限らず) そういった際にこういった機能が使えると勝率が上がる、というものを紹介します。 ジェネリクス 現在の PHP でコレクションクラスを作るとしたらどのような シンタックス になるでしょうか。 簡単のためインターフェースなどの定義は省くと、こんなクラスになるでしょう。 class MyCollection { public function __construct () { } //実装は省略 } これでは何も得ることはできないですね。そこでほしくなるのが ジェネリクス です。 型を変数のように扱うことで、コレクションの「中身」の型を決めずにコレクション型を定義できるわけです。 class MyCollection[T] { /** * @var T[] */ private $elements; /** * MyCollection constructor. */ public function __construct () { } //実装は省略 // こうやって使う $foo = new MyCollection[MyType](); これができると、1つのコレクションの定義で色々な型を操作できます。 しかもこの型引数( [T] の T の部分)がインターフェースの場合、継承したクラスをなんでも入れられるという寸法です。便利ですね。 そして沼へ続く ただし、これを便利に使おうとすると大きな問題が発生します。次は引数の型が欲しくなるのです。 たとえば配列関数の中にある array_filter や array_map を実装するとします。するとこう書きたくなります。 // class MyCollection[T] 内 public function filter(closure[T, boolean] $filterFunc): MyCollection[T] { // .... } public function map[S](closure[T, S] $mapFunc): MyCollection[S] { // .... } もう少し便利な関数も追加しましょう。 flatMap というものをご存じでしょうか。これは関数型の考え方が入ったコレクションライブラリではよくある機能(というより基本的な機能)です。 どういう機能かというと、 map して flat にするのですが、ソースを見るとイメージしやすいと思います。 $mapFunc = function($elem){ return new MyCollection($elem, $elem + 1); } ); // 自分と、自分に1足したものをコレクションにして返す $example = new MyCollection(1, 2, 3); $mappedSample = $example- > map($mapFunc); // MyCollection( // MyCollection(1, 2), // MyCollection(2, 3), // MyCollection(3, 4) // ) $flatMappedSample = $example- > flatMap($mapFunc); // MyCollection(1, 2, 2, 3, 3, 4) と、こんな風にネストをはがしてくれるものです。これを実装しようとすると型引数はこのようになります。 // class MyCollection[T] 内 public function flatMap[S](closure[T, MyCollection[S]] $mapFunc): MyCollection[S] { // .... } ね?簡単でしょ?と言わんばかりですが、型を書くことでコレクションライブラリの実装ができそうな雰囲気は伝わりましたでしょうか?さらに言えば、ここまで定義してきた MyCollection をさらに抽象化して、ほかのコレクションや集合、 Optional のようなものを定義できそうにも思えないですか? 共通の概念のようなもの?それは モナド ・・・ これ以上は 関数型プログラミング の世界にも踏み込んでいくことになるので、追いかけるのはこのぐらいにしておきましょう。 まだまだ課題はある もちろんこのままでは型引数を書かないといけない、毎度毎度型を合わせないといけないなど実際に使用していくうえで面倒と感じる部分が多いままです。しかも、こういったときに頼りになる 型推論 は言語の仕組み上安全に実装できないなど、いろいろな壁が立ちはだかってくるでしょう。このような ジェネリクス を導入しただけでは解決できない課題はたくさんあります。そのほかにも様々な トレードオフ と戦わないといけない個所が山のようにありますが、面倒ではあるが安全に倒しきった形でのコレクションライブラリの実装は ジェネリクス があればできそうな予感がします。 まとめ さきほど「面倒」というキーワードが出てきましたが、静的型付き言語のデメリットとしてよく「実装が面倒」ということを上げられます。そうです。これをそのまま使うとその「面倒」を持ち込んでしまうのです。これをもっと便利に使えるようにしたい!となった場合は、より高度な型システムの概念が必要です。これから PHP がどのような方向へ進化していくのかはふんわりと見えている状態ではありますが、高度な型システムを獲得できるのは少なくともまだ先のこととなるでしょう。当分の間は将来の進化を期待しながら array と付き合っていくのが得策ではないか、と思います。 イベントの話といいつつ、ほとんど ジェネリクス の話になってしまいましたがここまでとします。 今回のイベントで関わってくださった皆様、本当にありがとうございました!
アバター
先日、弊社がスポンサーとなっている PHPer Kaigi 2020 に、私 Y-Kanoh も参加してまいりました。 PHPer Kaigiとは? 公式サイトによると、 PHP に携わる人が、技術的なノウハウと PHP 愛を共有するためのイベントです。 一般から公募された登壇者の トーク セッションや、アンカンファレンス、懇親会などのイベントが3日にわたり催されていました。 私は開催場所が東京だったこともあり、最終日である3日目のみ参戦させていただきました。 会場について すでに二日間開催されていたためなのか、会場に到着すると、すでに活気付いた雰囲気がありました。 朝早いはずですが、会場のいたるところにエンジニアが集まりコミュニケーションをとっています。 これは、なんといっても今回取り入れられた トレーディングカード が大きいと思います。 この トレーディングカード は、上記のように、入場と同時に他 ノベルティ と共に1人100枚配られます。 配られた100枚のカードには、その参加者の Twitter アイコンが印刷されており、会場内ではこれを他の参加者と交換することが推奨されます。 なにせ100枚もあるので、躊躇していては交換しきれません。参加者はお互いにこのカードを配りきることを目的に他の参加者とコミュニケーションをとる必要があり、他者へ話しかけるハードルがとても下がりました。 このカードを用意するためには、参加者全員分のアイコンを取り込み、カードを印刷する必要があると思います。運営スタッフ皆さまは大変だったと思いますが、このカードのおかげで、セッション外の時間でも始終盛り上がっていたと感じました。 私自身も、オープニングが終わったと同時にカードの交換を申し込まれ、他エンジニアの方と交流することができ、最終的には配られたカードの半分ぐらい交換することができました。 セッションについて 参加した日は、弊社のエンジニアが登壇した「PHPerがこれから「型」とお付き合いしていくために」や、「Zend VM における例外の実装」など、 PHP の内部構造についてのセッションが多かったように思います。 普段特に意識したことがない PHP のしくみや、仕様の理由などを考えることができました。 さらに PHP の 中間言語 の話まで聞くことができ、とても興味深かったです。 今回は用意されたセッションだけでなく、アンカンファレンスでの トーク にも参加しました。 おそらくほとんどの方がスライドなど用意していないかと思いますが、とても面白い トーク ばかりでした。 LT登壇について イベントの最後は恒例のLT大会です。 私も PHP の RFC の読み方をテーマに登壇させていただきました。 speakerdeck.com 自分の番になるまでは緊張していましたが、前に立った時には比較的落ち着いてお話しすることができました。 (調子に乗って喋りすぎたせいか、演台にタイマーとして使っていた スマートフォン を置き忘れ、私の後に登壇した MasaKu に取ってきてもらいました...) ちなみに、 トレーディングカード を配り切れていなくて焦っていた私は、LTで トレーディングカード 交換の宣伝もしてました(笑) 懇親会について 懇親会では、先に触れた トレーディングカード のおかげで、様々な方と交流することができました。 途中から始まった懇親会LT大会では、私自身が普段業務で関わっている ベトナム とのオフショア開発についての発表があったりと、とても楽しむことができました。 最後に 率直に、とても楽しいイベントでした! 1日のみの参加だったのが残念でしたが、 トレーディングカード や懇親会を通じてたくさんのエンジニアとコミュニケーションが取れ、有意義な1日だったと思います。 来年もぜひ、参加します!!
アバター
新卒2年目のyk_itgです。早いもので社会人2年目も残り1ヶ月となりました。 パフォーマンスチューニングの開発をする際に、indexはどのようなカラムに貼るのが良いのか気になったので、今回はそこで調べたことを書いてみます。 PostgreSQL のバージョン: 11.5 まずはindexを貼ってみる indexを使ってみる カーディナリティ カーディナリティを変えて比べてみる 参考資料 まずはindexを貼ってみる まずはindexを貼るためのテーブルを作っていきます。 テーブルには主キーのidの他に以下の2つのカラムを定義します。 sequence_number 一意な数字が入る2つのカラムを持つテーブルを用意します。 type 3種類の値(1, 2, 3)のいずれかが入る CREATE TABLE test ( id integer primary key, sequence_number integer , type integer ); そのテーブルに1つのtypeごとに100万件、計300万件のレコードを入れて、 INSERT INTO test(id, sequence_number, type ) SELECT i, i, ' 1 ' FROM generate_series( 1 , 1000000 ) AS i; INSERT INTO test(id, sequence_number, type ) SELECT i, i, ' 2 ' FROM generate_series( 1000001 , 2000000 ) AS i; INSERT INTO test(id, sequence_number, type ) SELECT i, i, ' 3 ' FROM generate_series( 2000001 , 3000000 ) AS i; sequence_numberとtypeの2つのカラムにindexを貼ります。 CREATE INDEX index_test_number ON test(sequence_number); CREATE INDEX index_test_type ON test( type ); indexが貼れたかどうかは、システムビューのpg_indexesで確認できます。 postgres=# SELECT * FROM pg_indexes WHERE tablename = 'test'; schemaname | tablename | indexname | tablespace | indexdef ------------+-----------+-------------------+------------+----------------------------------------------------------------------------- public | test | test_pkey | | CREATE UNIQUE INDEX test_pkey ON public.test USING btree (id) public | test | index_test_type | | CREATE INDEX index_test_type ON public.test USING btree (type) public | test | index_test_number | | CREATE INDEX index_test_number ON public.test USING btree (sequence_number) (3 rows) 主キーのカラムにはindexが元々 付いているようです。 indexを使ってみる 作ったindexがどのように使われているのか EXPLAIN ANALYZE で確認していきます。 比較をしやすいようにindexを貼る sequence_number と type を WHERE句に入れて、まずは何も貼っていない状態で試してみます。 実行前に ANALYZE を忘れずにしておきましょう。 また、indexを使ってもらえるようにenable_seqscanを off にし、見やすいようにパラレルクエリもoffにしておきます。 ANALYZE test; SET enable_seqscan TO 'off'; SET max_parallel_workers_per_gather TO '0'; EXPLAIN ANALYZE SELECT id, sequence_number, type FROM test WHERE type = 1 AND sequence_number = 1000000; ---------------------------------------------------------------------------------------------------------------------- Seq Scan on test (cost=10000000000.00..10000061217.00 rows=1 width=12) (actual time=87.978..235.451 rows=1 loops=1) Filter: ((type = 1) AND (sequence_number = 1000000)) Rows Removed by Filter: 2999999 Planning Time: 0.124 ms Execution Time: 235.470 ms (5 rows) 235.470 ms とそこそこ時間がかかっていることがわかります。 続いて2つのカラムにindexを貼った状態で試してみます。 EXPLAIN ANALYZE SELECT id, sequence_number, type FROM test WHERE type = 1 AND sequence_number = 1000000; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------- Index Scan using index_test_number on test (cost=0.43..8.45 rows=1 width=12) (actual time=0.022..0.023 rows=1 loops=1) Index Cond: (sequence_number = 1000000) Filter: (type = 1) Planning Time: 0.168 ms Execution Time: 0.044 ms (5 rows) 何も貼っていない状態と比べると、 235.470 ms と 0.044 ms で何倍も早くなっていることがわかりますね! ただ、sequence_numberだけでなく、typeにもindexを貼ったのに使われていません。 今度はtypeにだけindexを貼った状態で試してみます。 EXPLAIN ANALYZE SELECT id, sequence_number, type FROM test WHERE type = 1 AND sequence_number = 1000000; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------- Index Scan using index_test_type on test (cost=0.43..36304.43 rows=1 width=12) (actual time=184.283..184.284 rows=1 loops=1) Index Cond: (type = 1) Filter: (sequence_number = 1000000) Rows Removed by Filter: 999999 Planning Time: 0.526 ms Execution Time: 184.341 ms (6 rows) 今度はtypeのindexを使ってくれました! ただ、indexを貼ったのにも関わらず、 235.470 ms から 184.341 ms に代わっただけで、sequence_numberの方の 0.044 ms と比べるとほとんど効果が出ていないことがわかります。 この違いは何でしょうか。 カーディナリティ typeのindexの効果が出ない理由は、テーブルの行数に対してtypeのカーディナリティが低いためです。 カーディナリティ *1 とはそのカラムにある値の種類の絶対値(今回のtypeの場合は 3 )のことを指します。 テーブルの行数 300万 に対して、typeのカーディナリティは 3 しかなかったため、ほとんど効果が出なかったわけです。逆に一意でカーディナリティが高いsequence_numberのindexではかなり効果が出ています。 カーディナリティを変えて比べてみる 行数は300万のままで、typeのカーディナリティを変えて何パターンか実行してみました。 結果は以下のようになりました。※実行時間は同じ環境でも変動があります。 typeのカーディナリティ indexありの実行時間(ms) 2 324.752 3 223.665 4 193.7 10 66.488 100 6.953 1000 1.064 10000 0.073 100000 0.034 カーディナリティが1000を超えたあたりからだんだん効果が薄くなっていくのがわかります。 参考資料 カーディナリティについてまとめてみた https://qiita.com/soyanchu/items/034be19a2e3cb87b2efb カーディナリティ https://www.shift-the-oracle.com/words/cardinality.html 用語集 http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19217-02/glossary.htm 41.32. pg_indexes https://www.postgresql.jp/document/8.0/html/view-pg-indexes.html postgreSQL でインデックス一覧の表示 https://hacknote.jp/archives/2474/ エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com *1 : 問合せの結果行数を指すこともあるそうです
アバター
はじめに こんにちは。aa_cryingです。早いもので、4月で入社して3年目になります。 2020/2/13-14 で実施された Developers Summit 2020 に参加してきましたので、 event.shoeisha.jp 今回はそのレポートとして、 聞いてきたセッションの内容の紹介と感想を残していこうと思います。 はじめに Developers Summit とは? セッション内容を紹介 【14-D-5】マルチクラウドに向けてNGINX活用促進する為に知っておいてほしいこと 【14-E-6】生涯イチ・エンジニアとして好きな技術でジャンプアップし続けよう - 夢のつづきはビッグデータで 【14-E-7】月間約10億件のクラッシュデータから見えたアプリ品質の実態! エンジニアが仕掛ける、『ONE TEAMで挑む、賢いアプリの品質管理』とは? 終わりに Developers Summit とは? 翔泳社 が主催されており、「技術者コミュニティとの連携から生まれた総合ITコンファレンス」というテーマで年に数回開催されています。 総合コンファレンス ということもあり、内容は技術寄りの話から、サービス運用の話、マインド的な話など多岐に渡っていました。 数あるセッションの中から3つのセッションを選び聞いてきたので、それらの紹介をしようと思います。 セッション内容を紹介 【14-D-5】マルチ クラウド に向けてNGINX活用促進する為に知っておいてほしいこと まず1つ目は技術寄りのセッションになります。こちらは マルチ クラウド ・ NGINX というワードに惹かれて選んだセッションですが、 思ったより技術寄りの内容でした。 まだスライドが公開されていませんので、内容を軽くご紹介しますが、 内容の趣旨としては「NGINXはこんなこともできます」という紹介でした。 DockerコンテナやJenkins等と連携してNGINXを利用することが出来ますよーと話や GKE ( Google Kubernetes Engine) や AKS (Azure Kubernetes Service) 上ではこういう活用が出来ますよーという話がありました。 2年目エンジニアの私には首をひねる内容が多かったですが、終了後に調べ、GKEや Kubernetes 等の技術について知り、興味を持つきっかけになりました。 新たに追加された機能である External Name についてはデモを交えて説明していただき理解できましたし、画期的なシステムだなと思いました。 External Nameを使用することで、部分的に (このバージョンのみ等)他の クラウド サービスを使用したりといったことが可能になるそうです。 また、マルチ クラウド で共通の設定をすることが可能なので、マルチ クラウド を管理するのが便利になりそうだなと思いました。 【14-E-6】生涯イチ・エンジニアとして好きな技術でジャンプアップし続けよう - 夢のつづきは ビッグデータ で 2つ目のセッションはマインド的な話でした。 こちらはスライドが公開されていましたので、詳細は以下をご覧いただければと思います。 speakerdeck.com 私の中では以下の話が印象に残りました。 常にホームランを打つという強い意志は大事だが、結果は三振だろうが気にしない。 (結果を出すためには失敗を恐れない) 「こうなりたい」ではなく、「なるんだ」という強い意志が大事。 まずは小さな夢・目標でいいから立てて、それを叶える・達成していくことでジャンプアップ(成長)できる。 心が折れないように趣味等で自分をケアすることが大事。 「結果を出すためには失敗を恐れない」ということの例えで アダム・ダン 率の話が出てきたりと、野球に例えて表現されるのが面白かったです。 33-4 も出てきました (笑) 好きな技術でジャンプアップ の前に、私はまず好きな技術を見つけるために様々な技術を学んでいきたいです。 【14-E-7】月間約10億件のクラッシュデータから見えたアプリ品質の実態! エンジニアが仕掛ける、『ONE TEAMで挑む、賢いアプリの品質管理』とは? こちらは スマホ アプリのサービス運用の話になります。 こちらもスライドが公開されていないため、内容を簡単に説明させていただきます。 登壇された方は スマホ アプリのエラー解析ツールである「SmartBeat」というツールの開発チームに属している 本ツールでは1ヶ月に10億件以上のエラーを検出している アプリのクラッシュが起こるとそれが★1レビューに繋がり、最終的にはユーザーが離れていってしまう アプリのクラッシュはアプリを使わなくなる理由の7割にものぼる データの消失が起きてしまったりすると大惨事に... なぜクラッシュするのか Android の場合 → 端末依存のクラッシュが多い 全ての Android 端末を集めてテストする、というのは難しい。 iOS の場合 → iOS のアップデートによりクラッシュの発生や再現が変わってくる クラッシュしないためには エラーの検知率を上げる (アラートメールや本ツールの使用等) すぐ直す・直さないの判断や、どこから直すかの判断を的確に行う 影響を最低限にとどめる工夫が大事 エラーが分かっておりすぐに直せない場合は早めにアナウンスする等 私が関わっている製品でもアプリを配信しているので、他人事ではないなと思い申し込みをしました。 また、私達のチームでは クラッシュしないためには に記載されている事項は的確に行われており、 サービス運用については上位者の皆さんにさすがの一言です。 終わりに このような大きなカンファレンスには初参加でしたが、学びやエンジニアとしてのモチベーション等得られるものが多く、また行きたいと思えました。 案内があった後すぐに動けず、題名や登壇者名から「気になる!」と思い申し込もうとしたら 既に満員 になってしまっているということが多かったのが心残りです。 次回以降は気になるセッションに参加できるよう、すぐに動きたいと思います。
アバター
id:logy0704 です。 もうすぐJava14がリリースされますね。 いくつかの変更が予定されていますが、その中でも今回はswitch文の変更についてご紹介しようと思います。 *1 そもそもswitch文って? 従来のswitch文の課題 fall through ブロック 文であること これからのswitch 矢印構文の導入 式として扱えるように 最後に 参考 そもそもswitch文って? Java を学んだことのある方ならば一度は触れたことがあるかと思います。 以下のような形式で複数分岐を表現することができ、特に Enum と組み合わせて使われることが多いです。 switch(case) { case1: hoge; break; case2: huga; break; default: piyo; } 従来のswitch文の課題 fall through switch文ではマッチしたラベル以降の分岐がすべて実行されてしまいます。 一つの分岐のみ実行したい場合にはbreak文を追加してあげる必要があります。 *2 ブロック switch文ではブロック全体が一つのスコープとみなされるため、変数名の競合や想定外の再代入が発生する可能性がありました。 *3 文であること switch文(switch statement)と表現されるように、これまではswitchは文としてのみ扱われてきました。 *4 そのため、条件によって変数を変化させたい場合、switch文をそのまま変数に設定することはできず、一度、switch文の中で変数に値を設定してから利用する必要がありました。 int hoge; switch(case) { case1: hoge = "huga"; break; case2: hoge = "piyo"; break; default: } System.out.println(hoge); これからのswitch これらの課題を解消するため、switchに変更が加えられました。 *5 ※ サンプルコードは https://openjdk.java.net/jeps/361 から引用させていただきました。 矢印構文の導入 ラムダ式 で見かけるような矢印を使った記法が導入されました。 switch (day) { case MONDAY, FRIDAY, SUNDAY -> System.out.println(6); case TUESDAY -> System.out.println(7); case THURSDAY, SATURDAY -> System.out.println(8); case WEDNESDAY -> System.out.println(9); } label -> 実行したい内容 という構文でそれぞれの条件分岐を表現することができます。 カンマ区切りで複数のラベルを並べることで、複数ケースにマッチする条件も表現できます。 この構文の場合、break文は必要とせず、一度条件にマッチした後、switchから離脱します。 見た目もスッキリするだけでなく、うっかりbreak文を書き忘れて想定外のバグが…なんてことがなくなりますね。 また、変数のスコープもそれぞれの矢印の右辺に閉じるため、変数名の重複等に気を使う必要がなくなりました。 式として扱えるように switchの結果を引数に渡したり、変数に格納することが出来るようになります。 static void howMany(int k) { System.out.println( switch (k) { case 1 -> "one" case 2 -> "two" default -> "many" } ); } 最後に switchの新たな記法についてご紹介しました。 Java14はLTSではないため、まだ導入される方は少ないかもしれませんが、将来的に利用できる記法として頭の片隅に置いておくと良いかもしれません。 参考 JEP 361: Switch Expressions Java SE 12の拡張switch文/式の完全ガイド エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com *1 : Java12からプレビュー版として提供されていた内容ですが、フィードバックを経てJava14で正式導入されます。 *2 : あえてbreak文を書かないことで複数の条件にマッチさせるような書き方もできます。 *3 : 各ラベルごとにブロックを区切ってあげることで回避する方法が一応存在します。 *4 : Java における文の正確な定義については Oracle社公式ページ を参照してください。 *5 : 正確には課題の解消だけでなく、現在プレビュー中のパターンマッチング機能への布石としての側面もあるようです。
アバター
こんにちは!遅くなってしまいましたが、今回は1月21日に行われたビアバッシュのご紹介をします。 今回のビアバッシュは自由枠の発表とLTの構成となっております。 発表一覧 自由枠 情報管理アプリ「Notion」 へんな Scala ドメイン 駆動設計を支える アーキテクチャ テスト LT git switch & git restore PHPerKaigi2019の参加がきっかけで社内勉強会を主催するようになった話 発表内容 情報管理アプリ「Notion」 サンフランシスコにオフィスを構えるNotion社が開発した情報管理アプリ「Notion」について紹介してくださいました。 議事録などのテンプレートを用意することができるなど便利な機能がそろっています。 非常に柔軟でアイディア次第で何でもできるアプリですが、柔軟すぎるがゆえに迷うこともあるそうです。 へんな scala 今月も Scala が好きなエンジニアが Scala について語ってくださいました。本発表では Scala の処理系について紹介してくださいました。 Scala .js   Scala をJSにトランスパイルすることができます。 ScalaNative   Java スタンダードライブラリを一部使用することができます。 Ammonite   Scala で スクリプト を書くことができます。replだけでなく、shellも書くことができます。 Dotty   Scala の新しい処理系。 コンパイル 速度が速くなります。 Scala .net  NET用の実行ファイルを作成します。公式サポートされていましたが、2012年でサポートが終了しました。 ドメイン 駆動設計を支える アーキテクチャ テスト 2/16に開催されたOOC2020の先取りの発表をしてくださいました。 Java と アーキテクチャ テストツールの ArchUnit を用いた ドメイン 駆動な アーキテクチャ 設計を運用する方法についてのお話です。 また、 PHP の アーキテクチャ テストツールの紹介もしてくださいました。 こちらが実際にOOCで発表されたスライドなので気になる方はどうぞ。 speakerdeck.com git switch & git restore Git2.23の新機能で、gitのブランチを変更する「switch」とファイルを変更する「restore」コマンドについて紹介して頂きました。 「switch」と「restore」は「checkout」を分割した機能です。 ただ本人曰くcheckoutの方が打ちやすいらしいです PHPerKaigi2019の参加がきっかけで社内勉強会を主催するようになった話 若手エンジニアがPHPerKaigi2019に参加したことがきっかけで開催した社内勉強会についてのお話です。 勉強会を開催したきっかけや開催してよかったこと、気づいたことなどを語ってくださいました。 勉強会の開催を実行、継続する難しさを発表から感じました。 終わりに 今回のビアバッシュではGitの便利な機能など、業務の役に立ちそうなものや、 勉強会開催で得たものについての発表などためになる話を聞くことができました。 今後もビアバッシュの内容をブログに掲載しますので、どうぞお楽しみに!
アバター
はじめに こんにちは。新卒2年目のmrym_618です。 最近業務で Chrome 拡張の「Stylus」を使い、 CSS の設定とデザインの変更を行うことがありましたので、 今回はその使い方について紹介していきたいと思います。 はじめに Stylusとは インストール方法 CSSの設定方法 おわりに Stylusとは Stylusとは、特定の CSS をブラウザ側で設定するための Chrome 拡張機能 です。 インストール方法 インストール方法は、以下のサイトより chrome.google.com Chrome ウェブストアを開き、「 Chrome に追加」を押してインストールするだけです。 インストールが完了すると以下の画像のようなアイコンが表示されます。 CSS の設定方法 CSS を設定したいサイトを開いたままインストール完了後に表示されるようになったSのアイコンをクリックします。すると以下のようなダイアログが表示されますので、赤枠のように CSS を設定したいURLをクリックします。 すると、スタイルの編集画面が表示されますので、実際に適用したい CSS を記述します。 今回は、このサイトのタイトルと注釈の色を変更してみたいと思いますので、以下のように記述します。 .header-image-enable #blog-title #title a { color : #000000 ; } .header-image-enable #blog-title #blog-description { color : #000000 !important ; } CSS 設定後、Sアイコンで表示されるダイアログにチェックを入れることで CSS を適応することができます。 CSS の適応を無効にしたいときは、 チェックボックス のチェックを外すかすべてのスタイルをオフにするにチェックを入れることで無効にすることができます。 CSS を編集したい場合は、鉛筆マークを押すことで編集画面に遷移することができます。 おわりに 今回は、 CSS を設定することで自由にデザインの変更をできるStylusについて紹介しました。 Stylusを使い自分独自の CSS を設定することで、Webサイトを見やすくて使いやすいようにカスタマイズすることができますので、皆さんもぜひ試してみてください。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
アバター
はじめに こんにちは、 MasaKu です。 PHPer による PHPer のためのお祭り、 PHPerKaigi が今年も開催されました。 (弊社もスポンサーをさせていただいております) PHPerKaigi2020 phperkaigi.jp 今回は LT にチャレンジさせていただいたのですが、登壇にあたり様々な学びがありました。 本記事では、LT にチャレンジする上で学びにつながった以下のポイントについて記載していきたいと思います。 本記事で記載する内容 トーク テーマの選定 発表資料の作成 LT 発表 登壇資料 speakerdeck.com 参加にあたって 去年の PHPerKaigi2019 には一般参加という形で参加させていただいており、大変興味深い発表ばかりだったので、 「来年こそはぜひスピーカーに!」 と意気込んでおりました。 去年の参加レポートは こちら tech-blog.rakus.co.jp 実は昨年開催された PHPerKaigi2019 のプロポーザルにも挑戦していたのですが、残念ながら非採択という結果になってしまっていました。 そのため、今年の開催で トーク が採択された時は嬉しさ半分驚き半分といった気持ちでした。 なお、昨年度の トーク テーマは以下です。 Laravel + MongoDB でつなげる、つながるオープンデータ エンジニアとしての成長を加速させた3つの取り組み fortee.jp fortee.jp プロポーザル応募 今回のプロポーザル募集にあたり、話したい トーク テーマはすぐに思いつきました。 というのも、PHPerKaigi の参加がきっかけで社内で行った上映会からいろいろな活動を開始するようになったので、その経過報告をしようと考えていたからです。 社内のビアバッシュでも何度か発表したテーマでしたが、今回の PHPerKaigi2020 でも発表することができれば最高だなあと考えていたためです。 しかし、どのような展開で話していけば盛り上がるかという視点はサッパリだったので、 トーク の方向性についてはブレブレでした。 個人としてのモチベーションの変化を話すべきか 勉強会開催にあたってのノウハウを話すべきか テーマ検討で トーク を聞いてくださる方に受けそうなのはどちらか、自分として話しやすいのはどちらか、という視点でテーマ選定を行っていきました。 発表資料の準備 トーク が採択された後は発表資料の準備を始めましたが、弊社で定期的に開催している MeetUP という社内イベントで登壇した経験があったため、どのように話を構築していくと資料が作りやすいかというノウハウがあったため、資料作りはスムーズに進みました。 イベントページ rakus.connpass.com 登壇資料 speakerdeck.com 今回の登壇資料の作成は以下のような流れで進めました。 トーク テーマの再確認 伝えたいポイントを大きく書き出す そのポイントを一番盛り上げられそうな話の展開を考える 箇条書きレベルで話を整理してアウトラインを作成する アウトラインをレビューしてもらう レビュー結果を元にスライドを作成する 個人的に一番大切だと思うのは 4 番目の内容です。 箇条書きレベルで話がまとめられていると、それをスライド化するのは非常に容易です。 「それならスライドを作りながら内容を整理しても同じなのでは?」と思うかもしれません。 これは個人的な感覚ですが、 グラフィカルなアウトプットができてしまうと伝えたいポイントが見えにくくなる気がするので、まずは文字ベースのアウトプットを作成するのが良い と思っています。 逆に、文字ベースでも自分の話たい内容がきちんと整理できていればそれをスライド化するのは難しくなく、むしろ、図的な説明も可能になるので、自分としてもより納得できる説明を組み立てられるようになります。 発表練習 発表練習は個人でやるのも大切だと思いますが、やはりフィードバックをもらえる環境で実践するのが最適です。 幸いにも今回は発表練習をする機会が豊富だったので、実践的な練習を繰り返すことができました。 今回、発表練習を通して得た教訓としては、LT で登壇するう上で特に気をつけなければならないポイントは以下のように感じました。 ウケを狙うポイントはちゃんと意識すること 画面を読んでいるときはどこを読んでいるのかを分かるようにすること 5 分間フルで使い切ること 特に、 5分間をフルで使い切ること は大切だと感じました。 通常の発表の場合は話たい内容を時間内に収められるように簡潔に話すことが重要かと思いますが、様々なカンファレンスのLTを見て感じることとしては、 LT では 5 分間という時間を綺麗に使い切ることのほうが芸術点が高い ように感じておりました。 そのため、タイムキーパーの「終了です!」の一言と同時に発表をキレイに切れるように、最後のスライドに向けてどれくらいの時間を残すかということを意識して練習するようにしました。 登壇してみて PHPerKaigi2020 登壇風景 LT の会場には推定 200 人を超える参加者の方がいらっしゃったように思います(もっと多かったかも) このような大勢の前で発表した経験がこれまでなかったこともさることながら、カンファレンスでの登壇も初めてでしたので非常に緊張した 5 分間でした。 練習通りにできたところもあれば、自分で何を話しているのかすらわからなくなるような場面もありましたが、非常にいい経験になったと思っています。 会場内から笑いの声や拍手が聞こえてくると勇気づけられるような感覚があった ので、今後、こういったカンファレンスに出席する際は、 リアクション増しを意識 していきたいと思いました。 最後に いつかはスピーカーとして登壇したいと思っていたカンファレンスに出ることができてとても良い経験ができたと思っております。 発表内容について Twitter でたくさんのリアクションをいただいておりましたが、自分が想像していた以上に発表内容に共感していただけたようで嬉しかったです。 イベントを通して様々な方と交流することができたこともとても良い経験になったと思います。 今回の PHPerKaigi2020 での登壇をきっかけとして、また次のステップに向けて再チャレンジしていければと思います。 参考サイト PHPerKaigi 2019 PHPerKaigi 2020
アバター
こんにちは。新卒2年目のbadaikiです。業務でできることが徐々に増えていくなかで、まだまだ自分はできていないなと感じる日々を過ごしております。 はじめに オールペア法とは テストケース生成ツール PICT(Pairwise Independent Combinatorial Testing tool) pairwiser おわりに はじめに 前回ではテストの網羅率の向上、可視化するディシジョンテーブルについて記事を書きました。 tech-blog.rakus.co.jp ディシジョンテーブルは網羅率は高められるものの、ターゲットによってはすべてのケースを消化するだけでとんでもない 工数 がかかってしまうことがわかりました。 そこで今回はどうすればケース数を減らし、効率的にテストを実施できるかについて調べてみました。 以前私がテスト実施から参入した開発で、先輩社員がケースを作成したものを複数人で実施していくということがありました。条件がかなり複雑に絡み合う機能であったため、ケース数が爆発しているんだろうなーと予測していたのですが、いざケースを確認してみると予測していたケース数の1/3ほどのケース数で驚きました。聞くとオールペア法を活用していました。 オールペア法についてはケース数が減るよ。という知識しかなく、なぜ減らせるのか、漏れは起きないのかということまで理解できておりませんでしたので、この機に調べてみようと思いました。 オールペア法とは オールペア法(ペアワイズ法ともいう)とは組み合わせテストの技法の1つです。 組み合わせテストとは、多数の入力条件の値をいろいろと組み合わせて実施するテストです。しかし前項でも述べたように、全ての入力条件で値の組み合わせを考えると、膨大な数になり全てをテストするのは現実的ではありません。例えば3つの選択肢があるプルダウンが4つあり、その組み合わせだけで 3の4乗 = 81ケース となるわけです。81ケースと聞くとできそうな気がしますが、それぞれが4つの選択肢になるだけで256ケースと3倍以上に増えてしまいます。 以降ではプルダウンのような入力条件を因子、その値を水準と呼びます。 ある文献 *1 ではソフトウェアのバグの7割から9割が1つまたは2つの因子の組み合わせによって発生していることが記されています。以下がそれを示した表です。 要因数 組込み機器(医療系) ブラウザ( Netscape ) サーバ( Apache ) データベース 1 66 29 42 68 2 31 47 28 25 3 2 19 19 5 4 1 2 7 2 5 2 0 6 1 4 そこで2つの因子の組み合わせをつくり、すべての水準の組み合わせのケースを作成するのがオールペア法という技法です。 例えば、プルダウンが3つの組み合わせを考えてみます。 因子 水準 プルダウンA 0,1 プルダウンB 0,1 プルダウンC 0,1,2 これの全組み合わせは 2 * 2 * 3 = 12ケース 。 これをオールペア法で作成するには 1. まずそれぞれの因子のペア(AB、AC、BC)を作成し、水準の組み合わせの全パターンを作成します。 AB AC BC 00 00 00 01 01 01 10 02 10 11 10 11 11 12 2. 1で作成した水準の組み合わせをAB列から順に取り出します。 No A B C 1 0 0 2 0 1 3 1 0 4 1 1 3. 次にAC列、BC列と順に当てはまる行に割り付けていきます。このときに着目しているペア以外のペアも同じ組み合わせが現れないように割り付ける必要があり、これがケース数を最小にするために重要です。←これがややこしいです。例えばAC列の(10)を割り付けるとき、(1,0,0)の組み合わせではなく、(1,1,0)の組み合わせにします。AC列の(00)を割り付けるときに(0,0,0)の組み合わせが既に出来上がっており、BC列の(00)が2か所で作成されてしまうためです。 No A B C 1 0 0 0 2 0 1 1 3 1 0 1 4 1 1 0 5 0 0 2 6 1 1 2 このようにオールペア法で作成すると今回の例ではケース数が12ケースから6ケースと半分になりました。ただし、理屈がわかっても実際自分で作成しようとすると難しいです。。。加えて、実際のシステムでケース作成を行う場合には、A=0のときはB=0になるなどの制約条件があるとさらに複雑になってきます。上記の例は簡単な例でしたが、複雑になっていくと考えるを諦めてしまいそうですよね。実は制約条件も考慮して自動生成してくれるツールが提供されています! テストケース生成ツール オールペア法のテストケース生成ツールは多く提供されており、以下のサイトにまとめられていました。ここで紹介されているツールだけで現在51種類もあり、驚きました。この中で PICT と pairwiser について使い方を紹介したいと思います。 http://www.pairwise.org/tools.asp www.pairwise.org PICT(Pairwise Independent Combinatorial Testing tool) http://www.pairwise.org/tools.asp 特徴: 無料 Microsoft 社が開発 コマンドプロンプト で実行する 多機能 ダウンロードするとHTMLのマニュアルがついてくる(英語) 使い方: 1. パラメータを定義する PICTではモデルファイルと呼びますが、txtファイルで作成します。 基本的なモデルファイルは、末尾が : で終わるパラメータと、 ⁠, で区切られた値の並びとからなるモデル定義部のみで構成されます。 A: 0,1 B: 0,1 C: 0,1,2 2. 1で作成したファイルをpict.exeで実行する。 pict test.txt これだけです。 すると以下の結果が出力されます。 A B C 1 1 1 0 0 0 1 0 1 1 1 0 1 1 2 0 0 2 0 1 1 結果をリダイレクトする場合には以下で実行できます。 pict test.txt 1>result.txt 2>error.txt 1 は出力結果、 2 はエラーが発生したときにエラー内容が出力されます。 制約条件を設定する場合にはモデルファイルの末尾に制約条件を追記します。記述方法は独自の スクリプト言語 が用いられており,因子を [] で囲み,水準が文字列の場合は, " で囲み, ステートメント の末尾は ; で終わります。条件にはパラメータと値の関係を評価する関係式を用いて 条件付き制約 と必ず成立する 無条件制約 があります。 #パラメータ定義 A: 0,1 B: 0,1 C: 0,1,2 #制約条件定義 #条件付き制約 if [A] = 1 then [C] <> 2; #無条件制約 [A] <> [B] or [A] <> [C] or [B] <> [C]; 上記のモデルファイルで実行すると以下のケースが出力されます。制約条件通り、A=1の場合はC=2にはならず、A=B=Cになるケースは作成されません。 A B C 0 0 1 0 0 2 0 1 0 0 1 1 1 0 0 0 1 2 1 0 1 1 1 0 pairwiser Pairwiser - Pairwise Testing and Test Generation Tool 特徴: 無料(ユーザ登録が必要) INDUCTIVE社という ノルウェー の企業が開発しているWebアプリケーション カバレッジ などの解析が容易 生成したケースをエクセル形式でダウンロードできる pairwiser 使い方: 基本的に、左から右へタブに必須情報を入力してテストケースを生成します。それぞれのタブの「Save」ボタンを押さないとデータが保存されません。また、データが保存されていないタブよりも右側のタブの内容は更新が効かないようになっています。 Webアプリのため、直感的に操作がやりやすいです。 Define Parameters タブでパラメータ定義や制約条件を設定でき、 Generate Tests タブでケース作成ができます。 Generate Tests タブの上部にある Export to Excel ボタンをクリックすることで Excel ファイルもダウンロードすることができますので、業務でテストケースを Excel で書かれている場合にはそのまま活用することができて便利ですね! pairwiser 結果 また、公式ページには チュートリアル やヘルプもあるので、初めてさわる場合でも安心ですね! おわりに 前回のディシジョンテーブルに引き続き、今回は組み合わせテストのオールペア法について調べ、自動生成ツールを使ってみました。オールペア法について知ることで、なぜそのケース数で十分なのか、どのように作成されているのかが理解できました。また、自動生成ツールを用いることで制約条件など細かな設定も行え、ツールによっては Excel ファイルに変換してくれるなど、人手で行うよりもとても効率的にケース作成が可能だとわかりました。今後、条件が複雑に絡み合う機能のテストではオールペア法を用いて網羅性を保証しつつ、効率的に進めていこうと思います。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com *1 : R.D.Kuhn et al.“⁠Software Fault Interactions and Implications for Software Testing,⁠”⁠ IEEE Transactions on Software Engineering, 30(6), June 2004
アバター
はじめに こんにちは。choreiiです。最近自チームで扱っている商材のフロントエンドのテストコードを大量に書く機会がありました。その中で大きくハマった3点について紹介します。 はじめに 環境 1. ライフサイクルフックをmock化(上書き)したい 2. テストによってcomputedを差し替えたい 3. localStorageをmock化したい まとめ 参考 環境 Vue:2.6.11 vue-test-utils:1.0.0-beta.29 Jest:23.6.0 1. ライフサイクルフックをmock化(上書き)したい 以下のようにbeforeMountで初期化処理を書いている場合、beforeMountをまるごとmock化(上書き)したくなる時があります。 <script> export default { beforeMount() { // コンポーネントで必要なデータの取得や初期化の処理 } , methods: { sampleMethods() { // 何らかの処理 } } } ; </script> methodsの内容を上書きする時は以下のようにすれば差し替えることができるので、ライフサイクルフックの場合も上書きできると考えていたのですができませんでした。 test( "test" , () => { const wrapper = shallowMount(Sample, { beforeMount() { // これで空の内容で上書きできるはず -> できない。。。 } methods: { sampleMethods() {} // 空の内容で上書きできる } } ); } ); vue-test-utilsのガイドには特に記載がなかったので手元で色々頑張ってみたのですが、下記のissueを発見。 github.com ライフサイクルフックは上書きできないので、処理を上書きしたい場合はbeforeMountの処理をmethodsに切り出して、その切り出した内容を上書きするのが良さそうです。 <script> export default { beforeMount() { this .initData(); // methodsに切り出し } , methods: { initData() { // コンポーネントで必要なデータの取得や初期化の処理 } , sampleMethods() { // 何らかの処理 } } } ; </script> test( "test" , () => { const wrapper = shallowMount(Sample, { methods: { initData() {} , // methodsの方で上書き sampleMethods() {} } } ); } ); ちなみに、shallowMount(mount)した後から、 setMethods を使っても上書きできます。 test( "test" , () => { const wrapper = shallowMount(Sample); wrapper.setMethods( { initData(): {} // 後から上書き } ) } ); 2. テストによってcomputedを差し替えたい 条件が少しだけ異なるテストを書く際に、毎回shallowMount(mount)を行うのはコード記述が増えるのであまりやりたくないです。methodsやcomputedだけを後から差し替える方法があれば完璧です。上記で述べたように、methodsは後から上書きすることができます。 describe( "test" , () => { const wrapper = shallowMount(Sample); test( "test1" , () => { wrapper.setMethods( { sampleMethods(): {} // test1用の処理 } ) } ); test( "test2" , () => { wrapper.setMethods( { sampleMethods(): {} // test2用の処理 } ) } ); } ); setMethods があるなら setComputed もあるだろうと考えていましたが、これまたvue-test-utilsのガイドには記載がありません。 ガイド記載のwrapperのメソッド抜粋 他にもset系のメソッドが用意されていながら、computedだけがありません。。。嫌な予感がしながら情報を探してみると下記のissueを発見(デジャヴ)。 github.com 昔は用意されていたものの、バグがテストをすり抜ける可能性があるので廃止されたようです。バグをなくすためと言われては仕方がないのでテストごとにshallowMount(mount)をするようにしています。 describe( "test" , () => { const render = ((sampleComputedStub), { const wrapper = shallowMount(Sample, { computed: { sampleComputed: sampleComputedStub } } ); } ); test( "test1" , () => { const wrapper = render( { // sampleComputedを上書きしたい処理 } ): } ); test( "test2" , () => { const wrapper = render( { // sampleComputedを上書きしたい処理 } ): } ); } ); 3. localStorageをmock化したい テストでlocalStorageをそのまま使うわけにはいかないので、mockに差し替える必要があります。 localStorageについては以下を参照 developer.mozilla.org jest.spyOn(localStorage, 'setItem' ); spyOnの使い方は間違えていないのに、以下のようなエラーがでてしまいました。 TypeError: object [ methodName ] .mockImplementation is not a function localStorageの中で、setItemが見つからないみたいです。またまた嫌な予感がしましたが今回は解決方法がありました。 stackoverflow.com 以下のように proto を使用するとアクセスできるようです。ただリンク先にも記載がある通り、 proto は非推奨とのことなのであまり多用するのはよろしくなさそう。今回はどうしてもjest.spyOnを使って呼び出し回数や呼び出し引数のテストを書きたかったので使用しています。 jest.spyOn(localStorage.__proto__, 'setItem' ); まとめ Vue/Jestの書き方は公式のガイドが充実しているので、ガイド通りに進めている間はスムーズに進みます。その反面、ガイドに載っていないことをやろうとすると情報がなかなか見つからず痛い目をみることが多かったです。 テストの主目的はプロダクトコードの品質担保なので、あまりテストの書き方を調べるのに時間をかけたくありません。今後は多少記述が増えたり冗長になったとしても、ガイドに従いながらテストを書き、どうしても実現できないことだけ別途調査することにします。 参考 Vue インスタンス — Vue.js ガイド | Vue Test Utils https://jestjs.io/docs/ja/23.x/getting-started エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
アバター
次週、都内ではPHPerKaigi 2020が開催されます! ラク スからは3名のエンジニアが登壇することとなりました! また、Silverスポンサーとしてイベント協賛をさせていただいております。 イベント概要 日時:2020 年 2 月 9 日 (日) ~ 11 日 (火) 会場: 練馬区 立 区民・産業プラザ Coconeri ホール( 練馬駅 から徒歩1分) 公式 HP: https://phperkaigi.jp/2020/ ハッシュタグ : #phperkaigi phperkaigi.jp セッションのご紹介 セッション内容とエンジニア3名からのコメントをご紹介します!  やなせ たかし/PHPerがこれから「型」とお付き合いしていくために(30分 トーク ) 日時:2 月 11 日 (火) 11:25 場所:Track A コメント: PHP 界隈でも最近何かと話題に上がる型システムのお話をします。   ・型システム でできること   ・動的型付き言語と静的型付き言語   ・ PHP と型 という内容を予定しています。 fortee.jp 加納悠史/ RFC の歩き方(LT) 日時:2 月 11 日 (火) 15:45 場所:Track A コメント: せっかく東京まで行くので、自身の発表含め最後まで楽しもうと思います。 発表では、興味を持った人でないと近寄りがたい、 PHP の RFC について紹介します。 fortee.jp MasaKu/PHPerKaigi2019への参加がきっかけで社内勉強会の主催するようになった話(LT) 日時:2 月 11 日 (火) 15:50 場所:Track A コメント: 昨年開催された PHPerkaigi2019 に参加させていただいた時から、「次回こそは登壇したい!」と思っていたので、CfPが採択された時は嬉しかったです。 良い発表ができるように、しっかりと準備して登壇に向かいたいと思います。 fortee.jp PHPerチャレンジ また、イベント中にはPHPerチャレンジという企画が開催されます。 会場や関連サイトに散らばった  #任意の文字列  形式のPHPer トーク ンを探して合計スコアを競う、というものです。 blog.phperkaigi.jp 本ブログを読んでいただいた皆様には、 ラク スからのPHPer トーク ンを受け取っていただければと思います! ラク スのPHPer トーク ンはこちらです! ↓ #RAKUSMeetup2020 それでは皆様、当日は弊社エンジニア陣の登壇にご期待ください! itoken1013でした!
アバター
こんにちは。昨年12月に入社しました。 logy0704です。 私の所属しているチームでは、 Java 開発においてメインの IDE として Intellij を使用しています。 私自身も Intellij を使い始めてから約半年ほど経過し、基本的な機能は使えるようになりました。 一方で、「今まであまり使ってこなかったけど、実はもっと便利な機能があるのでは?」と思い、 改めて公式ドキュメントを読んで知らない機能を探してみることにしました。 個人的に初めて目にした機能 Hippie completion Dependency structure matrix(Ultimate版のみ) Compare with clipboard Paste from history Check RegExp Shelves Analyze Java Stream operations 改めて公式ドキュメントを読んでみて 個人的に初めて目にした機能 Hippie completion 公式ドキュメント basic complitionやsmart completionは1ファイルで1回以上は必ず使うような必須機能ですが、 この機能を利用されたことのある方は少ないのではないでしょうか。 この機能では、今開いているファイルのテキストを分析し、単語の提案を行ってくれます。 Hippie completion 単なるコピーでは対応しきれないような、繰り返し登場する単語の入力補助に役立ちそうです。 Dependency structure matrix(Ultimate版のみ) 公式ドキュメント 依存関係をマトリクス形式で可視化することができます。 アーキテク トロール の方が、プロジェクトの分析を行う際のインプットとして利用できるのではないでしょうか。 Compare with clipboard 公式ドキュメント 予め クリップボード にコピーしておいたテキストと選択範囲のdiffをとることができます。 ファイル単位の比較だと余計なノイズが混じってしまうときに使えそうです。 compare with clipboard Paste from history 公式ドキュメント 直前にコピーしたものだけでなく履歴を遡って貼り付けを行うことができます。 同じような機能がWindows10でもOctober 2018 Updateから利用できるようになり、少し話題になりました。 Check RegExp 公式ドキュメント 正規表現 のテストができます。 目視だけでは確認の難しい 正規表現 を IDE 上で簡単にチェックできるのは非常に便利ですね。 Shelves 公式ドキュメント 作業中のファイルを一時的に退避させることができます。 git stashとよく似ていますが、退避、復元できる単位などに違いがあります。 Analyze Java Stream operations 公式ドキュメント StreamAPIの デバッグ を補助してくれる プラグイン です。 streamの中身の状態を可視化してくれるため、視覚的にもわかりやすい デバッグ が可能です。 改めて公式ドキュメントを読んでみて IntelliJ IDEA の公式ドキュメントをじっくり読んだのはこれが初めてでした。 それまではつまみ食い的に、都度、機能について検索していました。 しかし、一度全体に目を通しておくと、知らなかった機能に出会えたり、 その時は使わなくとも、別のタイミングで役に立つ機能の存在を思い出すこともあるかと思います。 今回は IDE が対象でしたが、普段利用している フレームワーク などにも同じことが言えるはずです。 皆さんも利用している製品の公式ドキュメントを一読すると、何か新しい発見が得られるかもしれません。
アバター
こんにちは。新卒2年目のy_kwmtです。今回は業務で取り扱っているChart.jsについて少し学習したので、 紹介していきたいと思います。 Chart.jsとは 折れ線グラフを描画する 棒グラフを描画する おわりに 参考にしたサイト Chart.jsとは グラフを簡単に描くことができる Javascript のライブラリです。 グラフは HTML5 の Canvas を使って描画することができます。 描画できるグラフ一覧 折れ線グラフ 棒グラフ レーダーチャート 円グラフ 散布図 公式サイト www.chartjs.org 公式ドキュメント www.chartjs.org 折れ線グラフを描画する 1/27~2/2の大阪の予想最高気温と予想最低気温をグラフにまとめてみました。 以下は ソースコード と実際に表示される画面です。 <!DOCTYPE html> < html lang = "ja" > < head > < meta charset = "utf-8" >   < title > グラフ </ title > </ head > < body > < h1 > 折れ線グラフ </ h1 > < canvas id = "graph" ></ canvas > < script src = "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.js" ></ script > <!-- Chart.js読み込み --> < script > var ctx = document .getElementById ( "graph" ) ; var myLineChart = new Chart ( ctx, { type: 'line' , // 表示するグラフのタイプ data: { labels: [ '1月27日' , '1月28日' , '1月29日' , '1月30日' , '1月31日' , '2月1日' , '2月2日' ] , // 横軸 datasets: [ { label: '最高気温' , // 凡例 data: [ 11 , 17 , 14 , 12 , 9 , 10 , 11 ] , borderColor: "rgba(255,0,0,1)" , // グラフの色 backgroundColor: "rgba(0,0,0,0)" // 塗りつぶしなし } , { label: '最低気温' , // 凡例 data: [ 9 , 10 , 7 , 6 , 4 , 3 , 4 ] , borderColor: "rgba(0,0,255,1)" , // グラフの色 backgroundColor: "rgba(0,0,0,0)" // 塗りつぶしなし } ] , } , options: { title: { display: true , text: '気温(1月27日~2月2日)' // タイトル } , elements: { line: { tension: 0 , // ベジェ曲線を無効にする } } , scales: { // 軸設定 yAxes: [{ // y軸設定 ticks: { suggestedMax: 20 , // 最高値 suggestedMin: 0 , // 最低値 stepSize: 5 , // 間隔 callback: function ( value, index, values ) { return value + '度' } } }] } , } } ) ; </ script > </ body > </ html > 棒グラフを描画する 架空の店の売り上げをグラフにまとめてみました。 以下は ソースコード と実際に表示される画面です。 <!DOCTYPE html> < html lang = "ja" > < head > < meta charset = "utf-8" > </ head > < body > < h1 > 棒グラフ </ h1 > < canvas id = "graph" ></ canvas > < script src = "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.js" ></ script > <!-- Chart.js読み込み --> < script > var ctx = document .getElementById ( "graph" ) ; var myLineChart = new Chart ( ctx, { type: 'bar' , // 表示するグラフのタイプ data: { labels: [ '1月27日' , '1月28日' , '1月29日' , '1月30日' , '1月31日' , '2月1日' , '2月2日' ] , // 横軸 datasets: [ { label: 'A店 売上高' , // 凡例 data: [ 200 , 190 , 160 , 195 , 215 , 180 , 170 ] , backgroundColor: "rgba(255,255,102,1)" // グラフの塗りつぶし } , { label: 'B店 売上高' , // 凡例 data: [ 160 , 150 , 130 , 170 , 155 , 140 , 170 ] , backgroundColor: "rgba(102,255,204,1)" // グラフの塗りつぶし } , { label: 'C店 売上高' , // 凡例 data: [ 120 , 130 , 135 , 115 , 150 , 130 , 120 ] , backgroundColor: "rgba(102,204,255,1)" // グラフの塗りつぶし } ] } , options: { title: { display: true , text: '支店別 売上高' // タイトル } , scales: { // 軸設定 yAxes: [{ // y軸設定 ticks: { suggestedMax: 240 , // 最高値 suggestedMin: 100 , // 最低値 stepSize: 30 , // 間隔 callback: function ( value, index, values ) { return value + '万円' } } }] } , } } ) ; </ script > </ body > </ html > おわりに 今回はChart.jsについて紹介させていただきました。 学習、資料作成の時間をあまりとることができず、今回は折れ線グラフと棒グラフのみの紹介となりました。 次回はグラフの表示非表示の切り替えなどグラフに対する操作をしたいと思っています。 参考にしたサイト liginc.co.jp qiita.com
アバター
はじめに Pythonの環境 実際に解いてみる RL回路 RC回路 さいごに はじめに こんにちは、crowd_kです。 プログラムを本格的に触り始めて、1年弱が経ちました。 というのも、私は「電気電子学科」出身であるためプログラミングは授業の一環でほんの少し触った程度しかありませんでした。 しかし、そんな授業で" Python "を少しだけ学んだことがあります。 内容は、" Python "を使って確率統計を解くというものでした。 紙を使って手計算すると、1問とくのに何十分もかけ、A4 の紙を1枚使い切ったり と大変だったものが" Python "を使って解くと簡単にあっさりと解けてしまい、とても驚いた記憶があります。 当時、「確率統計よりも厄介な(と感じる)、電気回路や電磁気を" Python "を使って解くことができたら便利ではないか」と思ったことがあります。 しかし、就活や卒業研究・論文 等で忙しかったため、実際にトライすることはありませんでした。 ふとそんなことを思い出し、" Python "の勉強になるのではと思ったので 簡単な電気回路を" Python "を使って解いて記事にまとめてみました。 Python の環境 まずは、 Python のインストールです。 「これから Python を勉強するなら3系が良い」という記事を多く見たので、3系を選択しました。 また、当時 Python を jupyter notebook で動かしていたので、そちらもあわせてインストール、 また同時に、 sympy もインストールしました。 pip install jupyter --user pip install sympy --user コマンドプロンプト で jupyter notebook と入力すれば、ブラウザで jupyter notebook が立ち上がります。 これでひとまず、準備は完了です。 実際に解いてみる まずはじめに、先ほどインストールした sympy をインポートしておきます。 import sympy as sym 今回はRL回路とRC回路の過渡応答について解いてみたいと思います。 RL回路とは、抵抗(R)とコイル(L)でできた電気回路のことで、RC回路は抵抗と コンデンサ ー(C)でできた回路のことです。 RL回路 まずは、変数を定義します。 変数の宣言は、 sympy.symbols で下のように定義できるようです。 R, L, t, V = sym.symbols( "R L t V" ) ここで、R=抵抗[Ω]、L=コイル[H]、t=時間[s]、V=電圧[V] を表します。 また、 sympy.Function 関数も定義することができるようです。 i = sym.Function( 'i' ) i=電流[A]です。 上記は、電流iは時間tによって変化することを表します。 上記の回路を解いていこうと思います。 一般的に以下のような式で表されます。 これを" python "を使って表していきたいと思います。 抵抗の電圧を表す式は単純で、以下のようになります。(すごく直感的に書くことができるので、楽です) R*i(t) 次に、コイルでの電圧ですが、Lと電流i(t)を時間tで 微分 したものの積で表されています。 sympy において 微分 は、 sympy.diff() と表すことができるので、 L*i(t).diff(t, 1 ) となります。 これらを使うと、RL回路の回路方程式は以下で表すことができることがわかります。 eq1 = sym.Eq(R*i(t) + L*i(t).diff(t, 1 ), V) eq1 について出力してみたら、下のようにうまくいきました。 今回は、R = 100、L = 100, V = 100000 として、解きたいと思います。(値は適当です) eq1 = sym.Eq( 100 *i(t) + 100 *i(t).diff(t, 1 ), 100000 ) 方程式を解くには、 sympy.solve を使います。 また、 微分方程式 を解く上で必要な初期値を引数として渡すことで、それを考慮した計算をしてくれるみたいです。(非常に便利) 今回は、t = 0のとき、(回路の電源を ON にする直前)の電流を 0 とします。 ans1 = sym.dsolve(eq1, ics = {i( 0 ): 0 }) 結果を出力すると、以下の式が得られました これで、解き終わりました。 これが何を表しているのか、グラフに書いてわかりやすくしようと思います。 from sympy.plotting import plot で、 plot を使って、表示してみます。 plot( 1000 - 1000 *exp(-t),(t, 0 , 10 )) 上のような結果が得られました。 i(t)は時間経過とともに徐々に1000[A]に近づいている(すぐには立ち上がらない)のがわかります。 抵抗のみなら、電源をONにしたと同時に電気が流れますが、コイルを挟むことで、ゆっくり立ち上がるようになります。 これは、コイルに流れる電流の変化したとき、その向きに対して逆向きの力を加えようとする性質からで、正しい答えが導き出せたと思います。 RC回路 同様に、RC回路を解いてみようと思います。 まずは、変数と関数の宣言です。 R, C, t, V = sym.symbols( "R C t V" ) i = sym.Function( 'i' ) R=抵抗[Ω]、C= コンデンサ ー[F]、t=時間[s]、V=電圧[V] としています。 RC回路の場合、上記のような式になります。 抵抗の電圧を示す式に関しては、RL回路と同様の考え方ができます。 しかし、 コンデンサ ーはコイルとは異となります。 コンデンサ ーの電圧は、Cの逆数と、電流i(t)をtで 積分 したものの積で表すことができます。 sympy では、 積分 を sympy.integrate と表すことができるので、 eq2 = sym.Eq(R*i(t) + sym.integrate( 1 /C * i(t), t), V) で、RC回路の回路方程式を表すことができます。 積分 がいると面倒なので、( この状態の方程式を解く方法がわからなかった )ひと工夫して解こうと思います。 それは、i(t)をtで 積分 したものを新たにq(t)として、解く方法です。 裏を返すと、以下のようにもなります。 これらを使うと、回路方程式は以下のようになりRL回路と同様に 微分 を含めた回路方程式になります。 これを、コードで書き直したものが下のものになります。 eq2 = sym.Eq(R*q(t).diff(t, 1 ) + 1 /C*q(t), V) これなら、RL回路と同様に方程式を解いてくれそうです。 R = 100、C = 0.01, V = 100 とし、初期条件にt=0のときのqを0に(スイッチを入れる前は電流が流れていないこととし、総 電荷 量も 0 になる)を当てはめると eq2 = sym.Eq( 100 *q(t).diff(t, 1 ) + 1 / 0.01 *q(t), 100 ) ans2 = sym.dsolve(eq2, ics = {q( 0 ): 0 }) となります。 ans2の実際の出力結果がこちら。 この答えは、i(t)をtで 積分 したq(t)を表しています。 i(t)に戻すために、両辺をtで 微分 します。 ans2_i = ( 1.0 - 1.0 *exp(- 1.0 *t)).diff(t, 1 )) 同様に、グラフに表してみたいと思います。 from sympy.plotting import plot plot(ans2_i, (t, 0 , 10 )) RC回路における電流i(t)の時間変化を表すグラフです。 立ち上がりは抵抗のみのときのように一瞬で立ち上がりますが、徐々に衰退しているのがわかります。 RL回路とは逆に時間経過とともに電流は流れなくなります。 コンデンサ ーは 電荷 をため込む性質(充電バッテリーのように)があります。 時間経過とともに電気をため込み、満タンになると電気が通らなくなります。 それがグラフで読み取ることができたので、こちらも正しい結果であると思います。 さいごに 本当ならこの流れでRLC回路も解いてみたかったのですが、解くことができませんでした。 積分 と 微分 が両方混ざった回路方程式になります。 なので、「 積分 を含んだ方程式を解く」または「二回 微分 を含む方程式を解く」 ことができる必要があります。 また、ベクトルの 内積 や 外積 、線 積分 や面 積分 といった計算が中心になる電磁気も、解けるようになったら面白そうです。 まだまだ勉強不足だと思うので、試行錯誤して今後チャレンジしていきたいです。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
アバター
あけましておめでとうございます!新卒1年目のrs_chankoです。 今回は Xcode を触ってみた話をしたいと思います。 はじめに Xcodeの所感 Swiftの所感 おわりに はじめに 就職してもう少しで一年、配属されて半年が経ちました。 自分のチームではアプリの開発も行っているのですが、 いかんせんあまり勤勉でなかった私は学生時代 Eclipse で Java を扱うのがほとんどでした…。 そこでこれからやるであろう アプリ開発 についてどうやって学習しようか考えていたのですが、 触ってみないことには始まらない!と思い立ち まずは Xcode とSwiftに慣れるためにサンプルプログラムを組んでみることにしました! ↓こちらが参考にしたサイトです。 developer.apple.com こちらは Apple 公式の チュートリアル 用ドキュメントです。 簡単な話、開発環境さえあればコピペぺたぺたすればアプリができてしまいます。 なので今回は実装方法などよりも、 GUI にあまり触れたことのない初心者が触ってみた感想について書いていこうと思います。 Xcode の所感 ストーリーボードによる直感的な操作 こちらが実際に作成したアプリの画面です。 これがなかなか直感的で分かりやすい。( GUI だしそれはそう) これを実行すると… こんな感じでシミュレータが起動します。 そのまま実際に動かした時の挙動を再現できるのも便利でした。 エディタの右側のメニュー上でUIパーツのサイズや配置場所の指定や、 他機能との接続をすることで、自動的に ソースコード が書き変わります。 画面を作成する段階で私は 全くSwiftを理解していませんでした が簡単に画面を作ることができました。 簡単で画面遷移があまり多くないアプリであればこのように直感的に操作ができると作ってみたくなりますね。 Unit Test Xcode は、クラス作成時にUnit Testのターゲットに選択するかのプロパティが存在します。 それさえ選択しておけば、 Java のように インスタンス 化したり…のような操作をせずに、 Testクラス内でクラス名.メソッドを呼ぶだけでテストを実行することができます。 こちらが実際に使ったメソッドです。 // MARK : Meal Class Tests // Confirm that the Meal initializer returns a Meal object when passed valid parameters. func testMealInitializationSucceeds () { // Zero rating let zeroRatingMeal = Meal. init (name : "Zero" , photo : nil , rating : 0 ) XCTAssertNotNil(zeroRatingMeal) // Highest positive rating let positiveRatingMeal = Meal. init (name : "Positive" , photo : nil , rating : 5 ) XCTAssertNotNil(positiveRatingMeal) } このように、簡単にテストケースを作成することができます。 お気軽にUnit Testができるのはとてもありがたいです。 戻るや確定のようなsubmit系ボタン こちらのような Cancel や Save のようなボタンは iOS のアプリでよく見かけますね。 こちらもSwiftのコードを書かなくても実装することができます。 Bar Button Item を使用して、属性タブのSystem Itemを変更することで挙動を選ぶことができます。 他の言語では○○に遷移するのような書き方をしていたので革新的な気持ちになりました! Swiftの所感 今時の言語 Swiftの特徴は 型推論 がされるところです。 Java でもJava10から 型推論 が導入されていますが、 Java8を使用している筆者からすると扱いやすくもあり扱いにくくもありと感じました。 コードはすっきりするものの、突如渡されたコードの変数の型を理解するためにコードを読まないといけないのか…とも感じました。 インタラクティブ 今回サンプルアプリの作成では使用しなかったのですが、 Xcode でSwiftのコードを書く際に Playgraund という機能を使うことができます。 このようにリアルタイムで コンパイル をして実行結果を表示してくれる機能があります。 実際に求めている結果が表示されているのかが確認できてとても便利です。 おわりに ただの感想文になってしまいましたが、 Xcode 、Swiftの所感でした。 今後は業務の開発でも触れていく(予定)なので、 プライベートで自分で何かしら開発をしてそれについて書けたらなと思います。 それではまたの機会に。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
アバター
こんにちは、新卒の mako _makokです。 今回はGo未経験者が外部の API を叩いてみた話になります。 はじめに この記事でやること 型を作る リクエスト connpass APIを叩いてみる 実行結果 最後に はじめに 自分でカスタマイズしたクエリを使用して勉強会情報を取得したいと考えました。 普段はこういったツールは個人的に Python で書くことが多いのですが、ある程度使い慣れた言語でリク エス トを投げてパースするだけだとすぐに実装が終わってしまうので、 勉強がてら興味があったGoで実装してみました。 本日はGoで 1. connpass API を叩き 2. レスポンスを構造体に詰め 3. 出力 するまでの手順や使用したツールについてお話ししようと思います。 この記事でやること やること レスポンスの json に対応した型の作成 httpクライアントの生成からGETリク エス トを送る Json を定義した型に変換する 型を作る 今回は以下のような型を定義しました。 package types import ( "time" ) type RequestParam struct { EventID int Keyword [] string KeywordOR [] string YM [] int YMD [] int NickName [] string OwnerNickname [] string SeriesID int Start int Order int Count int Format string } type ResultSet struct { ResultsReturned int `json:"results_returned"` Events []Event `json:"events"` ResultsStart int `json:"results_start"` ResultsAvailable int `json:"results_available"` } type Event struct { EventURL string `json:"event_url"` EventTypes string `json:"event_type"` OwnerNickname string `json:"owner_nickname"` Series Series `json:"series"` UpdatedAt time.Time `json:"updated_at"` Lat string `json:"lat"` StartedAt time.Time `json:"started_at"` HashTag string `json:"hash_tag"` Title string `json:"title"` EventID int `json:"event_id"` Lon string `json:"lon"` Waiting int `json:"waiting"` Limit int `json:"limit"` OwnerID int `json:"owner_id"` OwnerDisplayName string `json:"owner_display_name"` Description string `json:"description"` Address string `json:"address"` Catch string `json:"catch"` Accepted int `json:"accepted"` EndedAt time.Time `json:"ended_at"` Place string `json:"place"` } type Series struct { URL string `json:"url"` ID int `json:"id"` Title string `json:"title"` } レスポンスの型を書くのは単純作業ですし、タイプ量も少なくないので地味に面倒な作業ですが、Goの場合以下のツールで爆速で書くことができました。 JSON-to-Go: Convert JSON to Go instantly json を対応したstructとタグを作成してくれます。 今回の場合ですと、 https://connpass.com/api/v1/event/? keyword =python | jq ' . ' などして、整形した json をコピペするだけでtypeを生成してくれます。 JsonToGo リク エス ト ちょっとしたGETをするのであれば http.Get で良いですが、今回は勉強のためClientの設定なども行います。 標準ライブラリの net/http を使用します。 package httpwrapper import ( "io" "io/ioutil" "net/http" "net/url" "time" ) func DoRequest(method, path string , values url.Values, body io.Reader ) ([] byte , error ) { client := &http.Client { Timeout: 20 * time.Second, } req, err := http.NewRequest(method, path, body) if err != nil { return nil , err } req.URL.RawQuery = values.Encode(); resp, err := client.Do(req) if err != nil { return nil , err } defer resp.Body.Close() data, err := ioutil.ReadAll(resp.Body) if err != nil { return nil , err } return data, nil } 標準ライブラリしか使っていませんが、すごくすっきり書けて気持ちがいいです。 順番に説明していきます。すっきりしすぎてあまり説明することが無いような気がしますが、それも Golang の魅力かなと思いました。 タイムアウト 値の設定 client := &http.Client { Timeout: 20 * time.Second, } タイムアウト 値を20秒に設定します。 リク エス トの生成 req, err := http.NewRequest(method, path, body) コンスト ラク タを使用してRequestオブジェクトを生成しています。 パラメータの設定 req.URL.RawQuery = values.Encode(); values はmap型です。パラメータと値が マッピング されており、 Values.Encode() でURL エンコード を行います。 リク エス トの実行 resp, err := client.Do(req) (略) defer resp.Body.Close() defer を使用すると遅延実行することができます。 今回の場合ですと、DoRequest()が実行され終了する間際に resp.Body.Close() が走り、クローズ処理が行われます。 読み書きできる形にする data, err := ioutil.ReadAll(resp.Body) ioutil.ReadAll でレスポンスボディをバイトのスライスにして返します。 connpass API を叩いてみる package main import ( "fmt" "encoding/json" "log" "strconv" "net/url" "./httpwrapper" "./types" ) func main() { const endpoint = "https://connpass.com/api/v1/event/" keywordor := [] string { "JavaScript" , "TypeScript" , "Go" , "Java" , "Kotlin" , "Vue" , "React" , "Nuxt" , "Next" , "Spring Boot" } keyword := [] string { "東京" } count := 30 param := types.RequestParam{Keyword: keyword, KeywordOR: keywordor, Count: count} values := url.Values{ "keyword" : keyword, "keywordor" : param.KeywordOR, "count" : {strconv.Itoa(count)}} data, err := httpwrapper.DoRequest( "GET" , endpoint, values, nil ) if err != nil { log.Fatal(err) } var rs types.ResultSet if err := json.Unmarshal(data, &rs); err != nil { log.Fatal(err) } for i, event := range rs.Events { fmt.Println(strconv.Itoa(i + 1 ) + " Title: " + event.Series.Title) } } リク エス トを実行します。 結果を取得できた後は encoding/json の json .Unmarshalメソッド でパースできます。 var rs types.ResultSet if err := json.Unmarshal(data, &rs); err != nil { log.Fatal(err) } だいたいの json がこれでパースできます。 *1 なお、構造体を Json にパースする場合は json .Marshal を使用します。 実行結果 出力結果 最後に 今回はGoでconnpass API を叩いてみました。 今後はリク エス トの送信だけではなく、 RESTな API の作成したり、テスト等を書いて拡充していきたいと思います。 *1 : json の value に複数の型が混じった配列があるとエラーになります
アバター
はじめまして。 @penguin_no_045 です。 東京で12/1に開催された PHP Conference Japan 2019 でLT登壇してきました。 また、株式会社 ラク スは PHP Conference Japan 2019 のブロンズスポンサーとして協賛しています。 イベント概要 日時 : 2019年12月1日(日) 会場 : 東京都 大田区 南蒲田 1丁目20-20 大田区産業プラザ PiO 公式HP : https://phpcon.php.gr.jp/2019/ 登壇 社内最長老のシステムに PHPUnit で立ち向かう方法 speakerdeck.com 発表の要旨は、 レガシーシステム の PHP バージョンアップを PHPUnit でなんとかした というものです。いわゆるレガシーネタですが、 少ないリソースでどうやって大きなコードをテストしていくのかということについてお話しました。内容は発表資料を参照いただくことにして実際に行ったことを振り返ると、それにしてもかなり極端な手法を採用したように思います。 なぜこんな手法をとれたのかというと、今回の PHP バージョンアップによって文法的に正しい状態が維持されているかどうかだけに責務を絞ったからです。それだけが目的だったので、モックでもなんでも使用してとにかく カバレッジ を上げるという戦術を取ることができました。しかし品質担保の責務がもしあるならば、初めからこの手法は破綻しているでしょう。 お礼 発表準備に際してさまざまな方に資料のレビューや発表練習にお付き合いいただきました。 この場を借りてお礼を言いたいと思います。ありがとうございました! 印象に残ったセッション 改善失敗から学ぶ、レガシープロダクトに立ち向かうチーム作り。 speakerdeck.com まさに自分たちが通るであろう道を見せられた気がしました。改善を続けていく中で起こったことが紹介されています。実際、 カイゼン にチャレンジしたはいいけど、失敗したのでやめてしまった、なんていう話はたくさんあることでしょう。しかし失敗から学ぶことは多いはずですし、成功に結び付けることができればムダにはなりません。 カイゼン を続けているチームがいかに失敗し、その学びから カイゼン を回してきたのかを知ることができるセッションでした。 知見のない技術スタックをプロダクション導入するエンジニアの導入戦略 speakerdeck.com いつの日か既存サービスと同じ技術スタックが最適ではない機能やサービスを開発するときがくるかもしれません。このセッションでは、まさにそのような場面において組織の不安と向き合い、最適な技術を選定し、開発するために取った戦略を紹介されています。導入実績がない技術スタックには組織としても「不安」がつきまといます。その不安に対して向き合っていくための武器として、テスト・監視・コード検査を挙げ、それらをいかにして活用して、開発をすすめていくか。その実践内容がそれぞれの手法ごとに解説されています。 このセッションでは「知見のない技術スタック」と銘打っていますが、実際に機能選定で知見のない技術スタックを選定候補に上げるためには、別の「寝技」のようなものがあるように思います。また、このセッションで紹介されたプ ラク ティス事態は特別なものというわけではなく、日ごろから実践することでプロダクトの品質に大きく貢献できるのではないかと感じました。 感想 今回、登壇に際してたくさんの「はじめて」がありました。 1000人以上参加するイベントに参加 PHP 関連のイベント参加 登壇すること このようにはじめてづくしであったわりには発表自体はリラックスして行えたのではないかと 自画自賛 しておきます。 カンファレンスでは、 PHP に限らず広い領域のセッションがあったため、広範囲に刺激を受けることができました。 おしらせ PHPerKaigi 2020に登壇します! セッションタイトルは PHPerがこれから「型」とお付き合いしていくために です。 PHP で導入が進む型についてお話します。 プロポーザルは こちら をご覧ください。
アバター