エンジニア的なネタを毎週書くブログ

東京でWebサービスの開発をしています 【英語版やってみました】http://taichiw-e.hatenablog.com/

『未来を創るプレゼン術』:澤円さん 仙台IT文化祭レポート1 #sendaiitfes

今年発足した、仙台IT文化祭というイベントに参加してきました。
この記事は澤円さんの『未来を創るプレゼン術』という発表のレポートです。

プレゼンは相手に行動させるためにするべし

私にはこの言葉が最も響きました。
これまで、いろんな場でLTや発表をさせてもらってきましたが、この大切な点が分かっているようで分かっていなかったのです。

私は、IT系のカンファレンスや勉強会で話される、「すごい人の話」が好きです。
大変な環境や困難な状況を、ご本人の努力で切り抜けられた
という類の発表を聞いて、刺激を受け、真似られるところは真似しようとしてきました。

そして、自分も発表する際は、そんな発表がしたいと思い、
自分のストーリーを中心にして、聞き手の人に元気を与えられるような発表をしてきたつもりでいました。

しかし。
今日のプレゼンを聞いて、相手の立場にたったストーリー作りができてないことに気付かさせられました。

スライドの主語は?

今日のプレゼン内で
全てのスライドの主語を「みなさん」に置き換えて話せるか?
という確認方法を紹介していただきました。

聞き手にとって利益のある話なら、主語を「みなさん」に置き換えられるはず。置き換えられないのであれば、オーディエンスに何の利益もないか、話し手が内容の価値を理解できていない。

なるほど、と思い、試しに昨日したばかりのLTのスライドを一枚ずつ見直してみました。

だいたいの私の発表の構成はこうです。

  • こんなに大変な状況だったけど
  • こんなふうに切り抜けて頑張ってきた
  • パッションは熱いです!
  • (さあ君もなんか持ち帰って真似してみて!)

改めて見てみると、自分の話しかしていませんでした。

「こんなに大変な状況だったけど」
 → 聞き手は、似たような問題を抱えているのか?という観点の考察が足りていない。

「こんなふうに切り抜けて頑張ってきた」
 → 聞き手の方に、どの部分を持って帰ってもらうのか。願わくば実践してもらうのかという観点が欠けている。


逆に言えば、上記の観点をプレゼン作成時によく考えてみることで、
「聞き手の方に共感してもらい、あわよくば私の事例から何かを感じ取って実践してもらう」
そんなプレゼンにできそうです。


以下、印象的だったトピックのメモです。

「プレゼンは相手に行動させるためにするべし」につながる話

素晴らしいプレゼンは「何かをしたくなるプレゼン」

世の中には2つのプレゼンしか無い

  • 素晴らしいプレゼン
  • 残念すぎるプレゼン

では、素晴らしいプレゼンとは

  • 何かを始めたくなる
  • 何かをやめたくなる

のように、何かをしたくなるプレゼンである。
(つまり、何かをしたくならないプレゼンは、残念過ぎるプレゼン)

プレゼンを構成する上で一番最初に考えることは 「参加者は誰か」

何を伝えたいかではない!!

残念過ぎるプレゼンをしている人は、だいたい「参加者は誰か」が抜け落ちている。
セッションの参加者が誰か、言語化する。出来る限り具体的にイメージしてみる。

事前に分かっている情報(どういう参加者層か) という情報に加え、
当日、アイスブレイクも兼ねて質問から始める。
・普段、プレゼンしてますか?
・残念なプレゼンを聞いたことはありますか?
付随効果として、参加者は「話しかけられている」と感じることができる。

その他テクニック的なこと等

思いついたキーワードで画像検索してみる

・プレゼン資料用の写真を探すわけじゃなくて、プレゼンを広げるために探す。
例)セキュリティの話をしよう → 検索 → ガードマンの絵が見つかる
  → 「ガードマンを中心に話が組み立てられるかも!」
  
  ※なるべく英語で検索すること。15万倍の情報量。

プレゼン用の写真を見つけられる、おすすめサイト

Photo AC (無料)
Adove Stock(有料)

オーディエンスは味方です

みんな、どんなおもしろい話が聞けるんだろうってワクワクしてきている。誰も発表者を貶めようと思っていない。

最後に。このブログを書く時に意識したこと

このブログは、
・私が感じた自分のこれまでのプレゼンに対するショックを伝える。
 → 同じように澤さんの発表内容を聞いたら愕然とされる方がいるのでは?
・「主語を変えてみる」というTryと結果を共有。
 → 良いと思って試してくれる人が一人でもいたら嬉しい
ということを考えて書きました。

表現されている内容は結局いつもとあまり変わらない感じ… ということはまだまだ不足していることがあるのかもしれません。

が、今後プレゼンをする際は今日の話を思い出しながら、相手に行動してもらえるような発表を作り、喋りたいと思います。

(中身まだ無いです) spring-cloud-sockets と言うものを教えてもらったんだけど

GitHub - viniciusccarvalho/spring-cloud-sockets: Reactive socket communication for microservices

これとSpring WebFlux の関係… というかそもそもWebFluxって何 的なのがさっぱりわかってないので後でちゃんと調べる調べる…… きっと。


多分これも関係あるからリンクだけ貼っとく手抜き。

JavaDayTokyo 2017 Report 2 : Reactive Stream - エンジニア的なネタを毎週書くブログ

Maven vs Java9のModule(Project Jigsaw) : 依存はどっちが勝つの? (追記:あんまりMaven関係なかった)

無事Moduleを使ったビルドがMavenでできたところで、本当にやりたかった検証へ。

Mavenで複数プロジェクトが同一プロジェクトに依存していると、「どれか一つ」が使われることになります。
全て同じバージョンなら問題にならないのですが、それぞれ異なるバージョンのプロジェクトを使用していると、結果、意図せぬ不具合を引き起こすことになります。

もしかしてmoduleはこの問題も解決したのでは? と期待したのですが… 結果、ダメそうでした!

検証内容

こういう依存関係のものを作ります。
f:id:taichiw:20171002232722p:plain

MultiVersion.java

package multi.version;

public class MultiVersion {
	public static String version () {
		return "1";
	}
}

multi.version/pom.xml(一部)

<groupId>multiversion</groupId>
<artifactId>multi.version</artifactId>
<version>1.0</version>

World.java

package org.astro;
import multi.version.MultiVersion;

public class World {
	public static String name() {
		return "world" + MultiVersion.version();
	}
}

org.astro/pom.xml (一部)

<dependencies>
  <dependency>
  <groupId>multiversion</groupId>
  <artifactId>multi.version</artifactId>
  <version>1.0</version>
  </dependency>
</dependencies>

Main.java

package com.greetings;

import org.astro.World;

public class Main {
	public static void main(String[]args){
		System.out.format("Greetings %s!%n", World.name());
	}
}

f:id:taichiw:20171002233028p:plain

ビルドして実行すると

$ java -jar com.greetings/target/com.greetings-1.0-SNAPSHOT-jar-with-dependencies.jar
Greetings world1!

ここまではOK.

さてここで、
multi.versionモジュールのversion2.0を作ります。
依存を追加するだけで、特にrequiresやimportはしません。

MultiVersion.java

package multi.version;

public class MultiVersion {
	public static String version () {
		return "2";
	}
}

multi.version/pom.xml

<groupId>multiversion</groupId>
<artifactId>multi.version</artifactId>
<version>2.0</version>

そして com.greetingsのpom.xmlにversion 2.0のmultiversionへのdependencyを追加します。

<dependencies>
  <dependency>
    <groupId>groupId</groupId>
    <artifactId>org.astro</artifactId>
    <version>1.0-SNAPSHOT</version>
  </dependency>
  <dependency>
    <groupId>multiversion</groupId>
    <artifactId>multi.version</artifactId>
    <version>2.0</version>
  </dependency>
</dependencies>

f:id:taichiw:20171002234426p:plain

GitHub - taichiw/moduleTry at 3.0_module_tukattemo_dame


これで実行すると…

$ java -jar com.greetings/target/com.greetings-1.0-SNAPSHOT-jar-with-dependencies.jar
Greetings world2!

2が返ってきてしまいました。
たとえModuleを使っても、Mavenビルド時に、「より外側」に書かれたプロジェクトが使われてしまうことに変わりはないようです。
これだと、Moduleは、Module提供者が意図とした環境での実行が行われるとは限らないことになります。


さらに、MultiVersionクラスのメソッド名を変えてみます。

MultiVersion.java

package multi.version;

public class MultiVersion {
	// changed method name version() -> version3()
	public static String version3 () {
		return "3";
	}
}


これでもビルドは通りますが…

$ java -jar com.greetings/target/com.greetings-1.0-SNAPSHOT-jar-with-dependencies.jar
Exception in thread "main" java.lang.NoSuchMethodError: multi.version.MultiVersion.version()Ljava/lang/String;
        at org.astro.World.name(World.java:6)
        at com.greetings.Main.main(Main.java:7)

実行時エラーになってしまいました。

残念。

追記 (2017/10/05)

Mavenが悪いみたいな書き方したけど、そもそも現行のModuleの仕様の問題っぽい気がする。

mavenで作られたjarファイルを1ディレクトリに集めて…

$ ls mlib
com.greetings-1.0-SNAPSHOT.jar  multi.version-1.0.jar  org.astro-1.0-SNAPSHOT.jar

javaコマンドでmoduleとして実行すると

$ java -p mlib -m com.greetings/com.greetings.Main
Greetings world1!

multi.versionを2.0に置き換えて実行すると

$ cp multiversion/target/multi.version-2.0.jar mlib/

$ mv mlib/multi.version-1.0.jar mlib/multi.version-1.0.jar_

$ ls mlib/
com.greetings-1.0-SNAPSHOT.jar  multi.version-1.0.jar_  multi.version-2.0.jar  org.astro-1.0-SNAPSHOT.jar

$ java -p mlib -m com.greetings/com.greetings.Main
Greetings world2!

2になっちゃう。


moduleをビルドするときには--module-versionコマンドでバージョン指定しながらモジュールが作れるので、特定のバージョンに対しての依存も貼れそうなんだけど…
ひとまず方法が見つからず。


追記
今日、JavaOneでセッションがあったようで… あとで資料 or tweet or なんか無いか探してみよう。
f:id:taichiw:20171003001021p:plain

MavenでJava9のModule(Project Jigsaw)を使ってみた

探し方が悪いのか、わざわざ書くほどのことでもないのか、mavenでJava9のmoduleを使うとどうなるか という記事が英語でも日本語でもWebで見つからなかったので、試してみました&備忘録としてブログに残しておきます。

Project Jigsaw: Quick Start Guide
こちらのQuick Startのソースを拝借しました。

f:id:taichiw:20171002230425p:plain


結論から言うと、「module-info.javaを置いておけばmoduleになる」っぽい。
(言葉の使い方が正しいのか怪しい…)

1. module使わない版

とりあえず比較用に、"Java9で導入されたmodule" ではない、ただの独立したJavaリポジトリが2つの状態。
f:id:taichiw:20171002223029p:plain

GitHub - taichiw/moduleTry at 0.1_no_module

World.java

package org.astro;

public class World {
	public static String name() {
		return "world";
	}
}

Main.java

package com.greetings;

import org.astro.World;

public class Main {
	public static void main(String[]args){
		System.out.format("Greetings %s!%n", World.name());
	}
}

com.greetings/pom.xml (一部)

<dependencies>
  <dependency>
    <groupId>groupId</groupId>
    <artifactId>org.astro</artifactId>
    <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

org.astro -> mvn install
com.greetings -> mvn package

でビルド成功。

$ java -jar com.greetings/target/com.greetings-1.0-SNAPSHOT-jar-with-dependencies.jar
Greetings world!

2. org.astro (libとして提供される側)だけmoduleにしてみる

f:id:taichiw:20171002223951p:plain

org.astro/module-info.java

module org.astro {
	exports org.astro;
}

これでも普通にビルドが通る。

3. org.astroをただのjar, com.greetingsをmoduleにしてみる

f:id:taichiw:20171002224259p:plain


何もrequiresしない場合
com.greetings/module-info.java

module com.greetings {
}

これはビルドエラー。

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile (default-compile) on project com.greetings: Compilation failure: Compilation failure:
[ERROR] ~/moduleTry/com.greetings/src/main/java/com/greetings/Main.java:[3,17] package org.astro does not exist
[ERROR] ~/moduleTry/com.greetings/src/main/java/com/greetings/Main.java:[7,54] cannot find symbol
[ERROR] symbol:   variable World
[ERROR] location: class com.greetings.Main

module-info.javaを書いた瞬間にmodule扱いになる → requiresなしでは外部パッケージが使えなくなる
ということらしい。

requiresを足してみたら
com.greetings/module-info.java

module com.greetings {
	requires org.astro;
}

org.astroというmoduleは存在しないにも関わらずビルドが通ってしまった…

IDE上では思いっきり赤線が引かれているのでなんか間違ってるかも。
f:id:taichiw:20171002225434p:plain

4. org.stroもcom.greetingsもmoduleに。

org.astroパッケージをexportする。
f:id:taichiw:20171002225642p:plain

GitHub - taichiw/moduleTry at 1.0

これはきれいにビルド成功。

(仕事の話です)剣道とサッカーと交渉ごとって似ていると思うんですよ

私、個人的に中学から大学まで、と少し期間が空いた後、おとなになってから数年間、剣道をやっていました。
(ここ一年半くらいサボり中)

多くの方は剣道に馴染みがないと思うのですが、競技としての剣道は非常にロースコアゲームで、「一本」がなかなか取りにくい競技です。
その為、左から攻めたり右から攻めたり、速く動いてみたりゆっくり動いてみたり
なんとか相手を揺さぶって、スキを作って、「一本」を取ろうとします。

が、自分ではあれやこれややってるつもりでも、(剣道で)先生と稽古すると全然崩れないし、苦し紛れに「め~~~ん」なんて打っていこうものならあっさり応じられる。
で、

「攻めが足りない」

なんて言われるんですが そもそも「攻め」ってなんだかがよくわからないのです。
本を見てもググっても、それっぽいことが書いてあるような無いような感じで…。

結局、「稽古の中で体得する他無い」という世界なんですね。


今でもさっぱりわからないので、これだけ長くやっていてもまともに試合で勝った経験というのが殆どないのですが…


一方のサッカー。
私自身は小学校の昼休みにボールを追いかけていた程度の経験と、国際試合をたまーに見る程度の素人中の素人なんですが…
一点を取るために、左右のサイドから攻めたり、緩急をつけてみたり…。

これを見ていた時にある日突然、あ 剣道と似ているなぁと 思いました。

(おそらく大概の格闘技やスポーツが、似たような要素をもっていると思うのですが、「なかなか点が入らない」という点において似てるんですよね、この2つ。)

本題

お仕事をしていると、意見が対立する人と話し合ってなんとか落とし所を見つけなければいけない時、ありますよね。
エンジニアの世界だと、チーム内でコードレビューの際に意見がすごく割れるとか、設計方針で議論になるとか といったことがあると思います。
また、クライアント側とAPI側など、立場が違うと「これはそっちがもったほうが良いんじゃ…」「いやいやそっちが…」的な押し付け合いに若干なったりとか。(逆に引っ張り合いも然り)


このような場合、
・自分の主張がどれだけ素晴らしいか

を理解してもらうためには

・相手は何を求めているのか
・相手が譲れないポイントと、譲ってもいいと思っているポイントはどこか
・自分の本当の目的は?
・自分たちの本当の目的は?

みたいなことを把握しつつ、すり合わせしつつ 話を進めて行かないといけないです。

交渉術… と言ってしまうと口先だけの野郎のような印象がしてしまうのですが、
悪い意味でなく、相手と適切に議論するためのスキルや『お作法』というものはあると思います。

このようなスキルやお作法。人に教えるのってすごく難しい、と最近感じています。

実際の議論の場面で、「今回の状況でどうするのが良さそうか」は教えられますが、それを一般化・体系化して身につけるためには本人の中で腹落ちするしか他ない。

逆に、本などで一般化された知識を身に着けても、実際にどう使うか は 何度か繰り返し使ってみないとわからない。

まさに、「稽古の中で体得する」しか無いのだと思います。


ということで、剣道とサッカーと交渉ごとは似ている… というお話でした。

RESTful APIってなんか意味あんの? って言うタイトルのブログを書こうと思ってるんだけど

うまく言いたいことや考えがまとまらず書く書く詐欺になっているので、ひとまず起こっていること・思っていることを書いてみたいと思います。

起こっていること

シンプルな、データの永続化を行うだけのWeb APIが、リソースの種類ごとにそれぞれ作られています。「ビジネスロジック」はこの中には極力入れないルールになっています。

思っていること

ということは、今作っているAPIは単なる劣化版SQLでしか無いのではないか、というのが昨今の悩みです。

SQL(or RDB)に比べて良くなっている所

  • HTTP故に得られる恩恵があります
    • (使おうと思えば)Varnishなどのキャッシュが使えます
    • ロードバランサーによる負荷分散ができます(でも後ろのDBは結局シングルポイントです)
    • サーバを複数台使用した際の、Service-In や Service-Outが容易です
    • ApacheやNginXなどのWebサーバが持っているアクセスコントロール機能やログ機能が使えます
  • アプリケーションレベルでログが自由にカスタマイズできます

SQL(or RDB)に比べて不便になっている所

  • トランザクションを自力で実装する必要があります。特に、要件上、複数リソースにまたがる原子性が要求されるようなケースでは、

 原子性が破壊されないような仕組みを、Consumerが実装する必要があります。

  • 一般に、HTTPはコネクションのオーバーヘッドが大きいため、DBアクセスに比べて1リクエストあたりの時間がかかります。サービスによっては大きなボトルネックになることがあります。

SQL(or RDB)と変わっていない点

  • ふるまいを記述しないルールなので…
    • Consumerの実装次第では本来許容されないようなデータを作成することが可能です
    • データの使い方が複雑な場合に、Consumerがデータの解釈方法を知る必要があります


…抽象的すぎて、何を書いてるか、自分でもよくわからないなぁ。

Date型をTRUNCするとIndexが効かないよ という話

これ自体は昔から聞いたことがあったのですが、イマイチずっと理由がわかってなくて。

SQLのパフォーマンス問題を引き起こす日付型

単純に、

OptimizerはTRUNCすら何か知らない

というのが原因なんですね。