法律はイノベーションを加速させる! Studios session #3「時代を進めるルール」に参加してきた

www.facebook.com

Studios sessionとは、僕の所属するツクルバのtsukuruba studiosが主催するセッションイベントです。
第3回となる今回は*1弁護士・水野祐さんによる「時代を進めるルール」というテーマのセッションでした。

モチベーション

はじめ法律とクリエイティビティというと、「オープンソースのライセンス問題で大きい会社が大変そうだよなぁ」ということくらいしかイメージが働かず、どういうことが話されるのだろう?と思っていました。
そんな法律に疎い僕でも、「様々なビジネスモデルの企業が法律を味方につけたり、法律をうまく変えたりしながら、どのように成長していったか」といった話など、すごく興味深い内容が多かったのでセッションの一部と感想を共有したいと思います。
詳しい内容については後に、現在開発中のtsukuruba studiosのメディアにて公開されるかと思いますのでそちらを参照いただければと思います。*2

Who is 水野 祐

twitter.com

法律家・弁護士(シティライツ法律事務所、東京弁護士会)/Arts and Law理事/Creative Commons Japan理事/慶應義塾大学SFC研究所上席所員(リーガルデザイン・ラボ)/グッドデザイン賞審査員 ※ Twitterプロフィールより引用

弁護士として新しい技術やビジネスに関わりのある企業を法律で加速させる、ということに取り組まれているらしく、ツクルバの顧問弁護士としても入っていただいており、利用規約にサービスメッセージを入れるといったこともされていて面白いなと思いました
昨年「法のデザイン」という本も出されており、お話の中でも度々その中の事例についての言及がありました。

法のデザイン?創造性とイノベーションは法によって加速する

法のデザイン?創造性とイノベーションは法によって加速する

法律をビジネスを規制するものではなく、加速させるものと捉え、世の中に仕掛けていくビジネスをされている方々がリスクヘッジではなく業界を開拓する方法としての法律の利用という文脈で相談に来られたりする、ということのようです。

会の構成

  1. チェックイン / ツクルバ および tsukuruba studios の 説明
  2. 水野祐さんによる自己紹介 兼 ビジネスと法律についての導入
  3. キーワードをベースにしたセッション

という構成で、司会はツクルバCCOの@maa20XXで進みました。

1. チェックイン / ツクルバ および tsukuruba studios の 説明

チェックインというのは、参加者同士で行ういわゆるアイスブレイク的なもので、ツクルバではある「場」に溶け込むという目的でよく行われます。
知がめぐり、人がつながる場のデザイン」という本を紹介しつつ、「聞く、考える、対話する、気づく」というのを意識して社内外の参加者で自己紹介や何を考えて参加しているのかを共有しました。

僕は前述の通り、面白そうだけどよくわからんなあなどと思っていたので、水野さんをもともと知ってらっしゃった方から、弁護士の枠を超えたクリエイターらしいということを聞いてその時は更に「?」となりました笑

2. 水野祐さんによる自己紹介 兼 ビジネスと法律についての導入

水野さんによる自己紹介はイコール、新しいビジネスと法律との関わりという大きなテーマの紹介、導入でした。

面白かったトピックをかいつまんで紹介すると、

  • 契約書のUI/UX
    • 契約書にはカルチャーが反映される
    • NIKEGoogle
  • 法律は縁遠くなく、身近なルールの延長線上
    • 変化を前提に民間や企業がルール形成に参加する
    • ルール形成による新市場創出
  • 米国IT企業の公共政策部
    • グレーゾーン = 現在の社会が抱える課題を発見し解決するきっかけ
  • ハリル・ホッジ* アーセン・ベンゲル対談
    • 日本人サッカーには球際とずる賢さが足りない
    • ルールを自分なりに解釈するのは知性の証明

というようなことが紹介されていました。

これを聞いた直後の感想としては、スタートアップでサービス開発をしている僕にとって、法律やルールというのは思っていたよりも遠い存在ではないのだな、ということでした。
以前、僕はアプリ制作のプラットフォーム的な会社に所属しており、iTunesストアに並ぶアプリを数多く作っていた時期がありました。
そのアプリが量産型であったり、Appleが独自に定義したアプリ的な動きをしなかったり、ポリコレに反しているものであったりすると、審査が通らない、たとえ既に出ているアプリであってもiTunesからアプリを落とされる、という危険性がありました。
その会社では、プラットフォームによって生成されるアプリが上記のような(明文化されていないものも含めて)規約に違反しないような様々な工夫によってそういった事象は僕の知る限りほとんどありませんでした。
そういう工夫は、視点を変えれば、法律やルールを理解して逆に他社との競合優位性に変えていくというプロセスに近かったのだな、と思いました。

まだ入って間もないツクルバですが、現在主に軸足をおいている不動産というドメインは法律だけでなく、独自のルールや慣習などが多い印象を持っています。
そのなかでどうHackしていくのか、というのはこれから中で工夫していける部分だな、と思いました。

3. キーワードをベースにしたセッション

会の後半は、事前のピックアップ + その場での挙手によるキーワードをベースにした質問大会でした。

ネタとしては、

  • オマージュとパクリの境界線
  • ビジネスと遊び心の折り合い
  • 新たなルールの伝播について
  • 法律のプロへの相談が藪蛇になるパターン

などがありどれも面白かったです。

特にcowcamoというメディアを運営しているという性質上、社内からは

  • 著作権について: オマージュとパクリの境界線
  • 不動産広告としての記事と楽しませる記事の折り合いについて: ビジネスと遊び心の折り合い

の質問がありました。

この話の中で印象深かったのは、著作権においても、不動産広告のルールにおいても、当たり前のことを当たり前にした上で、いろいろなテクニックがあるということを紹介していただきました。
特に、不動産広告は特にルールの多い分野ということもあり

  • 法律についての正しい理解のために法律を作る人たちと議論をする
  • 不動産広告という名前ではなく法律の余白をついた新たな概念、名前付けをする
  • 作る際のポリシーを明文化で多少のクレームに動じなくなる

などが主に挙げられたかなと思います。
セッションという名前でもあったとおり、議論が巻き起こっており、実際社内でも何らかの動きがとれそうだという話になっていました。

まとめ

これまで書いてきませんでしたが、この会は社内外含めて20人くらいの規模で行われていました。
はじめのチェックインではぎこちない空気もありましたが、お話が面白かったのか、お酒も少し入っていたのか*3、最後にはかなり盛り上がり、終了してから1時間半位も各所で議論に花が咲いていて、良い雰囲気の会となっていました。

冒頭にも上げたとおり、はじめはピンと来ていなかった僕ですが、エンジニアは仕組みを作る側の人間だと思うので、既存の仕組みのファジーな部分に切り込んで、面白いシステム開発ができるようなエンジニアになりたいものだと思いました。
また僕がツクルバに入った理由として、IT技術に終始しないサービスの問題解決ができるエンジニアになりたいという思いがありました。
不動産業界はレガシーな業態で法律・ルールも入り組んでいるということなのでそれをしっかり把握しつつ新たな価値を提供していけたらな、というモチベーションに繋がった良い会でした。*4

告知

studios session

tsukuruba studiosでは、今後も1ヶ月に1回くらいのペースでいろいろな方を呼んでセッションしていく予定です。この規模が良いということもあって大体的に告知をしていないので、もし興味がある方は、ツクルバのFBページにいいねしていただけると、いち早く情報を受け取れるかと思います。

ちなみに、過去2回は↓のようなテーマでした。

Studios session #1「異質性とクリエイション」/ with 宇田川 元一 氏 Studios session #2「協創するチームはいかに生まれるか」/ with 安斎 勇樹 氏

ツクルバはメンバーを募集しています

ツクルバでは、エンジニアに限らずいろいろな職種で一緒に働くメンバーを募集しています。
自分と違った職能、性質の人たちと仕事ができて、かつ対面でもテキストでもコミュニケーションがすごく活発でうまい人が多いという印象です。
詳しくは↓を見ていただくか、個別に僕まで連絡いただければと思います。

tsukuruba.com

感想、ご指摘などあれば、コメントもしくはTwitter @zuckey17まで連絡いただけますと嬉しいです!!

*1:これまではjoinする前と直後で開催を知らなかったのです

*2:こちらにもリンクを張ります

*3:質問項目の事前仕込みが功を奏したのか

*4:あまりどこでも転職の告知をしていなかったので、意気込み発表みたいになってしまいました💦

3分で読む静的ファイルジェネレータGatsbyチュートリアル(前編)

Gatsby

f:id:zuckey_17:20180514000616p:plain

Reactで静的Webサイトジェネレーターといえば、Gatsbyがあげられます。 公式サイトでは「高性能な静的PWAReactで作ることができる。」と謳っています。

本エントリではPWAなどの詳細については述べません*1

Gatsbyチュートリアル

Gatsby公式チュートリアルでは、開発時に使うReactGraphQLなどの基本的な知識は必要ないとされており、かなり丁寧に書かれています。
ざっくりとした理解のため、取りあえず動かしたければあまり必要のない部分もあるかなと思ったので、かいつまんで書いてみました。
全部で8パートあり、0~3パートでサイトの見た目を作る部分、4~7パートでGraphQLを用いたデータの取得周りの解説をしています。

今回は前編ということでGatsbyでサイトの見た目を作るところです。

環境

スタート

1

  • gatsby-cliをインストールして、gatsby newでプロジェクトを作る
    • $ npm install --global gatsby-cli
    • スターターセットを使うとよくあるプロジェクトの雛形を用意してくれる
    • $ gatsby developでローカルで立ち上げる
    • $ gatsby buildでデプロイ用の静的ファイルを生成
  • Reactの構文が使える
    • JSX
    • CSS in JS
    • State、setState
    • etc
  • 複数ページにする
    • gatsby-linkというライブラリを使う
    • import Link from "gatsby-link"
    • <Link to="/コンポーネントのリンク">リンクとなる文字列</Link>
    • src/pages/以下に指定のページで表示するコンポーネントを作成する

2

  • グローバルなスタイル
    • typography.jsを例に
      • gatsby-plugin-typographyというプラグインを使う
      • プラグインを利用する場合はgatsby-config.jsというファイルをプロジェクトルートに作成しmodule.exportsオブジェクトにpluginsの配列で宣言する
      • するとそれらしいCSSが生成されているのが確認できる
      • 詳しくはそれぞれのpluginで
  • コンポーネントCSS
    • CSS Modulesでやるのが推奨(とはいえ1でも書かれている通り、CSS in JSも使える)

3

まとめ

すごくあっさりで、文字ばかりになってしまいましたが、概要はつかめるのではないかなと思います。
Gatsbyチュートリアルは英語も簡単ですし、1でも書いてある通り、スターターをベースにしっかり手を動かせて学べるので、これで興味を持った方は、触ってみてはいかがでしょうか?
次回は、後編をまとめます。

感想、ご指摘などあれば、コメントもしくはTwitter @zuckey17まで連絡いただけますと嬉しいです!!

*1:述べられません、勉強しておきます

Google Spreadsheet + Google Apps Script で Slack KPT Botを作ってみた

前回、Google Apps Scriptで作るSlack BotHello, World!!を紹介しました。

Google Apps Scriptを利用したSlack Bot作成の" Hello, World!! " - zuckey blog

今回は、応用としてSlack KPT Bot を作ってみたのでそれについて解説したいと思います。

KPT

よくある振り返りの手法にKPTがあります。

K:keep = 良かったこと(今後も続けること)
P:problem= 悪かったこと(今後はやめること)
T:try = 次に挑戦すること

上記の3つの要素を上げていくことで現状の分析をし、組織やプロジェクトを改善していく手法です。

KPTのやり方として、ホワイトボードに付箋を使ってKPTに分けて貼り付けていき項目ごとに深掘っていくというのが1つの一般的なやり方です。
しかし、人数が多めのチームでやろうとすると、ごちゃごちゃして時間もかかるので少し現実的ではありません。*1
そこで、KPT Botを使って、3つの要素をあげていくというプロセスをSlack上で完結させるようにしました。

どういうものを作ったのか

あるチャンネルで、

  1. 開始宣言する( start と投稿する)
  2. K:P:T:をプレフィックスとしてそれぞれの項目を投稿する
  3. 終了宣言する( end と投稿する)
  4. 開始 ~ 終了までの時間と、2で上げた項目が要素ごとにまとまって表示される

というものを作成しました。

f:id:zuckey_17:20180506180318p:plain:w300

裏側

本エントリのタイトルの通り、このSlack KPT BotGoogle Spreadsheet と Google Apps Scriptで作っています。
どういう仕組みになっているかというと以下のようになっています。

  1. 開始宣言(start)を受けて、先頭にある空のシートの名前を現在時刻にする
  2. K:P:T:をプレフィックスで判断して、1投稿1行ずつ、1列目に要素の種類、2列目に内容、3列目に投稿者名を書き込む
  3. 終了宣言( end )を受けて、その時刻と、2で登録された情報を要素に分別して表示する
  4. 終了処理として新しいシートを先頭に追加する

Spreadsheetを扱えるGoogle Apps Scriptの作成

Spreadsheetを扱うGoogle Apps Scriptのプロジェクトは、Spreadsheetの画面から作成します。
以下のように、ツール > スクリプトエディタをクリックすると、新しいタブでGoogle Apps Scriptの画面が表示されます。

f:id:zuckey_17:20180506180229p:plain f:id:zuckey_17:20180506180239p:plain

後は前回のエントリ同様の手順と変わりません。

スクリプト

var KEEP = 'KEEP';
var PLOBLEM = 'PLOBLEM';
var TRY = 'TRY';

function doPost(e) { // SlackからのPOSTリクエスト時に発火する
  switch(e.parameter.text) { // start、end、K: P: T:で場合分け
    case 'start':
      start();
      break;
    case 'end':
      end();
      break;
    default:
      registerKpt(e.parameter.text, e.parameter.user_name);
      break;
  }   
}

function start() { // 開始宣言
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0]; // 先頭のシートを取得
  if ((sheet.getName().match(/^[\d]{4}\/[\d]{2}\/[\d]{2} [\d]{2}:[\d]{2}$/) !== null) || (sheet.getLastRow() !== 0)) { // 重複した開始宣言は排除
    postSlack('すでに始まっています。');
    return;    
  }
  var date = new Date(); 
  sheet.setName(Utilities.formatDate( date, 'Asia/Tokyo', 'yyyy/MM/dd hh:mm')); // シート名を現在時刻に変更
  postSlack('`KPT`をスタートします!!');
}

function end() { // 終了宣言
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheets()[0];
  var lastRowNum = sheet.getLastRow();
  var keepArray = [];
  var ploblemArray = [];
  var tryArray = [];
  if (lastRowNum === 0) { // 0行の場合は終了できない
    postSlack('登録された `KPT`がありません');
    return;
  }
  var rows = sheet.getRange(1, 1, lastRowNum, 3).getValues();
  rows.forEach(function(row) { // 行ごとにKPT3要素でまとめる
    switch(row[0]) {
      case KEEP:
        keepArray.push(row[1] + ': @' + row[2]);
        break;
      case PLOBLEM:
        ploblemArray.push(row[1] + ': @' + row[2]);
        break;
      case TRY:
        tryArray.push(row[1] + ': @' + row[2]);
        break;
      default:
        break;
    }
  });
  
  var date = new Date();
  var now = Utilities.formatDate( date, 'Asia/Tokyo', 'yyyy/MM/dd hh:mm'); // 終了時点の時刻を取得
  postSlack( // まとめて投稿
    '```\n' +
    sheet.getName() + ' ~ ' + now + '\n\n' + 
    '# KEEP\n' + keepArray.join('\n') + '\n\n' +
    '# PROBLEM\n' + ploblemArray.join('\n') + '\n\n' +
    '# TRY\n' + tryArray.join('\n') +
    '\n```'
  );
  ss.insertSheet(0); // 新たな空シートを戦闘に追加
}

function registerKpt(text, userName) { // KPT登録処理
  postSlack('registering....');
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
  var categoryCell = sheet.getRange(sheet.getLastRow() + 1, 1); // 挿入する行の1列目を取得
  var contentCell = sheet.getRange(sheet.getLastRow() + 1, 2); // 挿入する行の2列目を取得
  var userCell = sheet.getRange(sheet.getLastRow() + 1, 3); // 挿入する行の3列目を取得
  var message = processMessage(text); // 投稿を要素と内容に分ける
  if (message === null) { // 形式違いは排除
    postSlack('形式が違います。 `K:`、 `P:`、 `T:`から始めてください。');
    return;
  }
  categoryCell.setValue(message.category); // 書き込み
  contentCell.setValue(message.content);
  userCell.setValue(userName);
  postSlack('受け付けました!');
}

function processMessage(text) {  // 投稿を要素と内容に分ける
  var match = text.match(/^([K|P|T]):(.*)$/);
  if (match === null) {
    return null;
  }
  return {
    category: convertCategory(match[1]),
    content: match[2],
  };
}

function convertCategory(category) { // プレフィックスから3要素を判断する
  switch(category) {
    case 'K':
      return KEEP;
    case 'P':
      return PLOBLEM;
    case 'T':
      return TRY;
    default:
      return null;
  }
}

function postSlack(text){ // Slackへの投稿処理
  var url = "https://hooks.slack.com/services/~~~";
  var options = {
    "method" : "POST",
    "headers": {"Content-type": "application/json"},
    "payload" : '{"text":"' + text + '"}'
  };
  UrlFetchApp.fetch(url, options);
}

設定

基本的には、前回のエントリの踏襲になります。
そのため、詳細ははぶきますが、以下の項目だけ異なります。

Slack Outgoing WebHookの設定で、トリガーとなる単語と監視チャンネルの設定トリガーとなる単語に
K,P,T,start,endという文字列を入力します。

まとめ

Google SpreadsheetをデータソースにしてSlack Botを作成しました。
表示をもう少し見やすくわかりやすくするなどの改善はできそうだなと思っています。
これを使ったKPTがどうだったかについてもどこかで書きたいと思います。

感想、ご指摘などあれば、コメントもしくはTwitter @zuckey17まで連絡いただけますと嬉しいです!!

*1:そのくらいの人数が1チームなのはどうなのかというツッコミはここではスルーしますmm

Google Apps Scriptを利用したSlack Bot作成の" Hello, World!! "

タイトルの通りGoogle Apps ScriptSlack Botを作ってユーザーの特定の投稿に対して" Hello, World!! "と返すBotを作る手順を紹介します。

具体的には、以下のようなことができることが今回の目的です。

f:id:zuckey_17:20180430010521p:plain

「test」と書けば、Botが「Hello, World!!」と返してくれる。
特に面白くもないですが、First Stepとして、これができるまでの手順を紹介します。

f:id:zuckey_17:20180430021956p:plain

1、Slack Incoming WebHook URLの取得

Incoming WebHookは、Slackの機能の1つで、本記事の中では、Slack Workspaceの特定のチャンネルにGoogle Apps Scriptから" Hello, World!! "を投稿するために使います。

Slack Appの作成

f:id:zuckey_17:20180430011112p:plain:w300

Slackのコンソールにログインできる状態で、https://api.slack.com/appsにアクセスし、Create New Appをクリックすると、

f:id:zuckey_17:20180430011216p:plain:w300

  • App Name
  • Development Slack Workspace

を指定する画面になるので適切なApp Nameを入力しと対象のSlack Workspaceを選びます。
そしてCreate Appをクリックすると以下の画面になります。

f:id:zuckey_17:20180430011410p:plain:w300

Slack AppのBot Userを設定

遷移後のページでBot User > Add Bot Userの順にクリックします。

f:id:zuckey_17:20180430011557p:plain:w300

f:id:zuckey_17:20180430011611p:plain:w300

適切な名前を入力し、Always Show My Bot as Onlineの項目をOnにしておきます。
上記が完了すれば、Save Changesをクリックします。

Incoming WebHookのAuthorization

Incoming WebHooksから遷移した下記の画面でActivate Incoming Webhooksの項目をOnにし、Add New WebHook to Workspaceをクリックすると、投稿したいチャンネルの設定とAuthorizationができます。

f:id:zuckey_17:20180430011953p:plain:w300 f:id:zuckey_17:20180430014900p:plain:w300

このステップが完了するとIncoming WebHookが利用できるようになり、URLにPOSTすると、上記で設定したBotによって投稿することができます。
遷移先で表示されているURLをコピーしておきます。

f:id:zuckey_17:20180430013952p:plain:w300

2、Google Apps Scriptの設定

Scriptの作成

Google Drive > 新規作成 > その他 > Google Apps Scriptで新たにScriptを作成します。

f:id:zuckey_17:20180430012416p:plain:w300

※「その他」にGoogle Apps Scriptが存在しない場合は、Google Drive > 新規作成 > その他 > アプリを追加からGoogle Apps Scriptsを追加できます。

適当な名前をつけて、表示されるテキストフィールドに↓のコードを貼り付けます。
doPostという関数を定義しておくと、後に生成されるURLに対してPOSTされたとき、その関数の中身が実行されます。

function doPost(e) {
  
  function postSlack(text){
    
    // 1の手順でコピーしたSlack Incoming WebHook のURLを指定
    var url = "https://hooks.slack.com/services/~~~~~~";
    
    // 必要なオプションを指定
    var options = {
      "method" : "POST",
      "headers": {"Content-type": "application/json"},
      "payload" : '{"text":"' + text + '"}'
    };
    
    // Google Apps ScriptのFetchのためのAPIを叩く
    UrlFetchApp.fetch(url, options);
  }
  
  // Textを指定して、上記のpostSlack関数を叩く
  var message = " Hello, World!! "
  postSlack(message);
 
}

f:id:zuckey_17:20180430012514p:plain:w300

Scriptの保存とアプリケーションの公開

ツールバーから保存し、Google Apps Scriptコンソール上部の公開 > ウェブ アプリケーションとして導入を選択します。

f:id:zuckey_17:20180430013058p:plain:w300

項目がたくさんありますが初回は、「アプリケーションにアクセスできるユーザー」を全員(匿名ユーザーを含む)に変更して導入をクリックします。

f:id:zuckey_17:20180430013209p:plain:w300

すると、「現在のウェブ アプリケーションの URL」というのが表示されるので、そのURLをコピーしておきます。

f:id:zuckey_17:20180430013354p:plain:w300

3、Slack Outgoing WebHookの設定

Outgoing WebHookもSlackの機能の1つで、本記事の中ではGoogle Apps Scriptで作成したScriptを発火させるため、ユーザーの特定の投稿(「test」)に反応して手順2で取得したURLにPOSTするという用途で使います。

Outgoing WebHookの追加

https://SlackのWorkspace名.slack.com/appsにアクセスして、検索窓でOutgoing WebHooksを探し、選択します。

f:id:zuckey_17:20180430013501p:plain:w300

遷移先で、Add Configuration > Add Outcoming WebHooks Ingegrationを選択します。

f:id:zuckey_17:20180430013514p:plain:w300

f:id:zuckey_17:20180430013524p:plain:w300

トリガーとなる単語と監視チャンネルの設定

f:id:zuckey_17:20180430013600p:plain:w300

Integration Settingsの項目でPOSTリクエストのトリガーとしたい単語(Trigger Words)の設定と、そのトリガーを監視する対象のチャンネル(Channel)を設定します。
「Trigger Words」はカンマ区切りで文字通り複数入力できますが、今回は「test」のみを入力します。
監視チャンネルは初期値がAnyとなっていますが、チャンネルを特定して監視することが可能です。
今回僕は簡単のためにIncoming WebHookで投稿する先と同じチャンネルを監視するように設定しました。
※ プルダウンにないので明らかですが、DMは監視対象のチャンネルとして設定できません。なので、確認のためにDMで「test」と投稿しても、反応することはありません。

f:id:zuckey_17:20180430013629p:plain:w300

画面下部のSave Settingsをクリックすると保存できます。

確認

以上で設定は完了です。
手順3で監視対象に設定したチャンネルで「test」と入力すると、「Hello, World!!」とBotから返ってくることが確認できるはずです。

f:id:zuckey_17:20180430013643p:plain:w300

まとめ

「簡単にできるだろ〜」と思って始めてみると、ハマりどころが多かったのでまとめてみました。
続いて、もう少し発展した内容を書きたいと思います。
間違い、不明点などあれば、コメント、もしくはTwitter@zuckey_17 までご連絡ください!

おまけ: Google Apps Scriptのコードを変更した場合

新規のときと同様に、ツールバーから保存し、Google Apps Scriptコンソール上部の公開 > ウェブ アプリケーションとして導入を選択しますが、設定項目の「プロジェクトバージョン」のプルダウンを新規作成として選択する必要があります。
これをしないと、変更が反映されないので注意が必要です。

f:id:zuckey_17:20180430020806p:plain:w300

ただ、この手順を踏むとプロジェクトのバージョンがたくさん増えていってしまうので、この辺の管理のプラクティスはこれから学んでいこう思っています。

エンジニアのお祭り、技術書典4に行ってきた

技術書典4

技術書典4」という技術書オンリーのイベントに行ってきました。
TechBoosterさんと達人出版会さんが主催のイベントで、会場は秋葉原UDX アキバ・スクエアという場所で開催されました。

出版社、同人サークル、企業などがそれぞれ技術書を持ち寄ってそれを販売する(頒布する)というイベントです。
6300人を超える来場者のかなり大きなイベントとなっていました。

実際、僕は11時開始ということで10時半くらいに秋葉原駅に到着して会場にむかったのですが 、すでに整理券を受け取るための長い列ができており、900番代だった僕が実際に入場できたのは11時30分くらいになりました。

戦利品

以下の書籍を入手しました。

「日経電子の本」は無償で頒布されていました。
いろいろな技術分野の書籍があつかわれていたのですが、その中でもフロントエンド技術周りの書籍を出されているサークルが多く、人の集中度も比較的高かったような印象がありました。
まだ読めていませんが、これから読んで1つ1つレビュー記事でも書こうかなあと思っています。(つもりです。)

エンジニアのお祭り

本当にいろいろなエンジニアが参加されており、ただ単に書籍を販売したり頒布したりするというだけではなく、エンジニア界隈のお祭りという感じありました。
僕自信もちょうど1年前からいろいろなエンジニアコミュニティに顔をだしていたので、場内でサークルの売り子の方と話したり、場外でもたくさんのエンジニアの方々と話すことができました。

jQuery本ノーチェックだったけど面白そうだったから買ってみた。」「Vueの本が多かった。」などの会話であったり、買った書籍を見せあったりというコミュニケーションがいたるところで行われていました。

混み具合

僕は初めての技術書典参加だったのですが、気持ちのよい晴天でかなり入場者数が多かったためか、かなり混み合っていました。
コミケなども参加したことがないのでわからないですが、混み合っている中で流れの向きがバラバラだったり、通路の左右を行ったり来たりするような進み方をする方もいたりしため、いろいろなブースをゆっくりと見ることができなかったのが少し残念でした。
人数規模的にも大きくなってきているということもあり、もしかしたら次は更に大きい会場での会場になるかもしれません!期待したいです!

まとめ

総じてすごく楽しいイベントでした。
混み具合のこともありましたが、入場の案内などこの人数のイベントでフラストレーションがたまるようなこともなく楽しく過ごせたので、運営の方々は本当にお疲れ様でした!ありがとうございました!!

これから今日手に入れた戦利品を読んで行くのが楽しみです。

また、今回初参加で雰囲気を知ることもできたので次の技術書典では何か本を書いて出展する側で参加したいな、という気持ちになりました!

ブログ執筆より簡単!?Podcastの収録方法の解説

僕はしがないラジオというPodcastのパーソナリティをやっていて、今回はその収録の方法について書こうと思います。*1

※ 機材のリンクについては、アフィリエイトリンクとなっています。
僕らのPodcast運用費用になりますので、興味を持たれた方はよろしかったらこちらから購入いただけると嬉しいです。

Podcast配信は簡単?

Podcastを始めることはそんなに難しくはなく、僕としてはブログよりも簡単に続けられる一つのアウトプット方法ではないかと思っています。
ブログは推敲し始めたら無限に時間がかかってしまいますし、(一応これでも)まずなにをどういう人向けに書こうかなと考えたりしています。
その点Podcastは、日付を決めて集まって収録してしまえば、編集にも限界があるので出すことができてしまいます。
はじめは自分の声を長時間聞くだけで恥ずかしくて悶てしまいますが、1、2回で慣れてしまいます。

収録機材

収録機材については、変遷があって

という2つを購入し、使っています。

f:id:zuckey_17:20180415234805p:plain

iQ7iPhoneのLightning端子に接続することによって使えるすぐれもので、小さく持ち運びもしやすく音質も安定し始めたので取り敢えず始めたかった僕らはこれに非常に助けられました。

f:id:zuckey_17:20180415234819p:plain

詳しくは後述しますが、リモートでの収録をしたいという要望から、各自パーソナリティが各自Yetiを購入してMacにつなぎ、Skype越しに収録するようになりました。
オーディオインターフェースなどを用いずUSBで直接Macに接続することが出来るので、オーディオ機器に詳しくない僕たちでも簡単に収録することができました。

収録ソフト

収録ソフトは、Macで無料で使えるGarageBandというソフトを使っています。
編集もこちらのソフトと、もう1つ無料のAudacityを利用して行っていますが、編集について詳しくは他の機会に書こうと思います。

収録方法

僕らは基本はパーソナリティ2人とゲストを招いて収録しています。
はじめ半年くらいはパーソナリティ2人で収録していましたが、ここ数ヶ月はゲストを招いて3人で収録することが多いです。

複数人で収録する場合、

  • オンサイト収録
  • リモート収録

という大まかに2つの方法があります。

オンサイト収録

しがないラジオを始めた当初はiQ7を使っていたので、貸し会議室を借りて、面と向かってオンサイト収録をするしかありませんでした。
平日の朝に収録していたので、わざわざ集まることが辛くなってきたこともあり、リモート収録が出来るようにとYeti購入に踏み切りました。

f:id:zuckey_17:20180415234838j:plain:w300

最近ではゲストの方とは、はじめましての方も多かったりするので、実際にお会いして収録をすることが 多いです。
オンサイト収録では、Yeti1本で収録しています。

f:id:zuckey_17:20180415234854j:plain:w300

Yetiは単体では机に置くようにして利用するのですが、キーボードのタイプ音を拾ってしまいます。
公式でショックマウントも購入することができますが、持ち運びに不便なので、写真のようにタオルを下にひくという方法で机で伝わるタイプ音を低減させています。
それでも少し音が入ったりしてしまいますが、その場の空気として許容範囲かなと、あまりに気になる時以外はそのまま残していることが多いです。

リモート収録

パーソナリティ2人の場合、平日朝に収録することが多く、集まるのや会議室を借りるのもコストなためリモート収録することになりました。
また、遠方のゲストの場合だと、実際にお会いすることが難しかったりするので、リモートでの収録をすることがあります。

この場合、僕らはSkype越しでの収録を行います。
各自がそれぞれの声のみの入力をそれぞれローカルで収録し、
編集の際にそれらをマージすることによって会話しているように聞こえるというような収録方法*2です。

バックアップ

また、僕は誰かが録音を失敗していたときのために、全員の声が入っているSkypeの出力を別途録音し、バックアップとして使っています。

やり方としては、

という2つの無料アプリを用います。

f:id:zuckey_17:20180415234923p:plain

SoundFlowerは、オーディオデバイスを仮想的に増やすようなアプリケーションです。 音声を1つの入力や出力ではなく複数に分けることができます。

また、LadioCastは、SoundFlowerで複数にした音声入力をルーティングして、出力先を変更することができます。

詳しい使い方は以下のブログがわかりやすく解説してくれているので参考にしていただければと思います。

quoqlish.hatenablog.jp

こちらによってリモートのバックアップができます。

まとめ

いかがだったでしょうか? Podcastはマイクさえあれば、その日にでも始めることができます。
編集方法、公開方法などは今後ブログなどで書きたいと思います。

しがないラジオ聞いていただきたいですし、音質などへのフィードバック、助言などもあればすごく嬉しいので、コメントや僕のTwitter#しがないラジオでのツイート、しがないラジオのページなどのフォームなどからお願いします。

またこのブログは、昨年12月に開催した、しがないラジオ忘年会にて発表した資料を元に書いています。 よかったら見てみてください🙏

speakerdeck.com

宣伝

しがないラジオは、来る2018年5月23日にミートアップを開催します!!
ゲストやリスナーによるLT大会と懇親会をメインに考えています。
zuckey個人としては、Podcastリスナーというのはあるディープなセグメントされたコミュニティだと思っています。
パーソナリティだけでなく、リスナー間での交流を深めていただく会にしたいと思っているので、是非皆さん参加いただければと思います!

shiganai.connpass.com

*1:決してネタが思いつかないというわけではない...🙄

*2:ダブルエンダー方式というらしいです

【Ruby】OptionParserを使ってcliツールの引数を制御する

blog.zuckey17.org ↑でRubyに入門して、Ruby学習の一環で簡単なCliツールを作成している時に、引数を簡単に制御したいと思い、OptionParserというライブラリを使った。

メモ的に使い方をまとめておく。

実際のコード

test.rb

#!/usr/bin/env ruby

require "optparse"

params = {}
arguments = []

OptionParser.new do |o|
  o.on("-t", "--title TITLE", "set title param") {|title| params[:title] = title}
  o.on("-b", "--body BODY", "set body param") {|body| params[:body] = body}
  o.on("-h", "--help", "show help") {|| puts HELP_MESSAGE; exit }

  begin
    arguments = o.parse(ARGV)
  rescue OptionParser::InvalidOption => e
    puts e
    exit 1
  end
end

p params
p arguments

今回利用したのは、newというメソッドに対して、ブロックを渡す方法。
newにブロックを渡すとOptionParserオブジェクトを引数にとってブロックが実行される。

実行結果

上記のコードは以下のような実行結果になる。

$ ./test.rb hoge -t タイトル
{:title=>"タイトル"}
["hoge"]

$ ./test.rb hoge -t タイトル -b 本文
{:title=>"タイトル", :body=>"本文"}
["hoge"]

$ ./test.rb -t タイトル -b 本文
{:title=>"タイトル", :body=>"本文"}
[]

$ ./hgoe.rb -t タイトル --b 本文
{:title=>"タイトル", :body=>"本文"}
[]

$ ./test -t タイトル --b 本文 -a zuckey
invalid option: -a

詳しく見てみる

OptionParser#on

引数にオプションとそのオプションの説明を取り、コマンドの引数が与えられたオプションを持っている場合に実行される処理をブロックとして与える。
呼び方は大まかに2パターンで、

# ショートオプションあり
o.on(short, long, description) { |v| puts v }
# ショートオプションなし
o.on(long, description) { |v| puts v }

オプションが引数をとる場合は、-t オプションといったように指定する。
オプションが任意であれば、-t [オプション]とすることで指定が可能。

descriptionは、OptionParser#summaizeメソッド時に表示される。

OptionParser#parse

配列(主にARGV)を与えると、onメソッドで指定した設定の通りにその配列をパースし、オプションとその引数を除外した配列を返す。
そのため、今回の実装では、argumentsにオプション以外の引数が入っていることになる。

onメソッドで指定した以外のオプションを指定した場合、OptionParser::InvalidOptionという例外をが発生するので、良い感じに救ってやる。

begin
  arguments = o.parse(ARGV)
rescue OptionParser::InvalidOption => e
  puts e
  exit 1
end

おわり

あまりRubyコマンドラインツールを作ることはないと思うが、PHPにはあまりこういうライブラリが標準でなかったんじゃないかと思い、面白かったのでまとめておいた。