シスアーキ in はてな

シスアーキ(自称)の技術ブログ

関西Kotlin勉強会 反省会

さる9/19(土) に関西Kotlin勉強会に行ってきました!

connpass.com
connpass.com

勉強会に懇親会、みんなに会えて楽しかったよ〜〜!!!(((o(*゚▽゚*)o)))

とま〜、それはいいのですが、この勉強会で発表したLT資料について、

「資料の内容が技術的に正しくなく、フェアでもない」

と多方面から注意を受ける事態となりました。(−_−;)

この記事はその資料の検証と反省を目的としたものです。
既に資料は取り下げたのですが、迷惑をおかけした方たちへのお詫びと反省をかねて、問題の資料内容について自分なりに検証したいと思います。

反省資料の内容

問題となった資料の構成は次のとおりです。

Scalaで拡張関数を実装したけど、implicitばかりでつらいよね
・Kotlinの拡張関数は簡単にかけるよ!

ここでの問題は、

Scala でFunctorのコードを書いているが間違っている(技術的に正しくない)
Scalaのコードが型クラスを実現しようとしているのに対して、Kotlinのコードはそれを実現しようとしていない(フェアじゃない)

が指摘された内容だと考えています。

Scala でFunctorのコードを書いているが間違っている

まずこれについて。

trait MyFunctor[F[_]] { self =>

  def myMap[A, B](fa: F[A])(f: A => B): F[B]
}
final class MyFunctorOps[F[_],A](val self: F[A])(implicit val F: MyFunctor[F]) {

  def myMap[B](f: A => B): F[B] = F.myMap(self)(f)
}

上記コードについては問題ないと思います。問題は次のコード。

// BAD Logic!!!
implicit val listMyFunctor = new MyFunctor[List] {
  override def myMap[A, B](fa: List[A])(f: (A) => B): List[B] = {
    def myMapFunc(acc: List[B])(l: List[A])(f: A => B): List[B] = {
      l match {
        case (head :: tail) => myMapFunc(acc :+ f(head))(tail)(f)
        case _ => acc
      }
    }
    myMapFunc(Nil)(fa)(f)
  }
}

mapの実装を不必要にややこしく書いています。

// BAD Logic!!!
implicit def listMyFunctor[A](l: List[A]):MyFunctorOps[List, A] =
  new MyFunctorOps[List, A](l)

暗黙の型変換を目的としたロジックが不適切です。
このロジックだと、Functorを実装した分だけ同じような定義をしないといけないです。

とりあえず、まーまー、正しいかと思われるコードについて書きました。
まだ自信ないですが。。

implicit val listMyFunctor = new MyFunctor[List] {
  override def myMap[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f)
}

まず、myMapの実装を簡単に書きました。実装内容は今回の資料の対象ではないので。

  implicit def toMyFunctorOps[F[_], A](fa: F[A])(implicit F: MyFunctor[F]) =
    new MyFunctorOps[F, A](fa)

次に、暗黙の型変換を目的としたロジックを修正しました。
MyFunctorの実装を型ごとに暗黙の引数で受け取れるように修正したことで、同じ定義を書く必要がなくなりました。

Scalaのコードが型クラスを実装しようとしているのに対して、Kotlinのコードはそれを実現しようとしていない

先ほどのFunctorは型クラスを実現しようとしていました。
型クラスはアドホック多相 を実現するものです。
アドホック多相とは、

異なる型の間で共通したインターフェースでの異なる振る舞いを定義済みの型に対して拡張する

ものらしいです。
それを実現する為に、

・型クラスの定義
インスタンスの定義
・型クラスの利用

という手順を踏む必要があります。

今回拡張するFunctorについて、Functorは型パラメータをもつ型です。
先ほどのコードでは、型クラスの定義でFunctor値の型をHigher-kind Genericsを用いて定義し、インスタンスの定義、および型クラスの利用の為にimplicit parameterとimplicit conversionの機能を用いています。

資料の中で「implicitだらけでScala怖い」と表現した件について、僕の現状のScala力では読みにくいという感想でした。ただ、その比較としてKotlinの拡張関数で以下のコードを提示し、Kotlinが簡単と表現したのはフェアじゃないですね。

fun <T, R> List<T>.myMap(f: (T) -> R): List<R> = this.map(f)

上記コードだと、

定義済みの型に対して拡張する

は実現できても、

異なる型の間で共通したインターフェースでの異なる振る舞い

は実現できていないです。上のようなコードだけで良ければ、Scalaのimplicit conversionでも簡単に実現できます。*1

implicit class ToFunctorList[A](l: List[A]) {
  def myMap[B](f: A => B) = l.map(f)
}

ちなみにですが、Kotlinの拡張関数はただのシンタックスシュガーです。

fun <T, R> myMap(l: List<T>, f: (T) -> R): List<R> = l.map(f)

のような関数定義があり、第一引数の型をレシーバとして呼び出せる簡易構文を提供しているみたいです。
実際に、上の定義を同じパッケージ内で定義すると、コンパイラJVM上では同じシグネチャだよって怒られます。

KotlinでFunctorを定義してみる

はい、ではフェアである為にKotlinでFunctorの定義を頑張ってみます。
ただ、KotlinにはHigher-kind Genericsもimplicitのような機能もありません。ですので、違う方法で

異なる型の間で共通したインターフェースでの異なる振る舞いを定義済みの型に対して拡張する

を実現できるよう考えてみました。

・インタフェースの定義
・Delegation機能を用いたインタフェース実装の定義
・拡張関数を用いてインタフェース実装への型変換

interface MyFunctor<A> {

    fun myMap<B>(f: (A) -> B): MyFunctor<B>
}
class MyFunctorList<A>(val list: List<A>) : MyFunctor<A>, List<A> by list {

    override fun myMap<B>(f: (A) -> B): MyFunctor<B>
        = MyFunctorList(list.map(f))

    override fun toString() = list.toString()
}

fun <A> List<A>.asFunctor(): MyFunctorList<A>
    = MyFunctorList(this)
fun main(args: Array<String>) {

    println(arrayListOf(1, 2, 3, 4, 5).asFunctor().myMap { n -> n * 3 })
}

以上です。
KotlinではClass Delegation*2の機能がありますので、拡張する型がインタフェースであれば、委譲クラスを簡単に作成できます*3
Scalaのように強力ではないですが、

異なる型の間で共通したインターフェースでの異なる振る舞いを定義済みの型に対して拡張する

は実現できたのではないかと思います。

今回の反省

LTはライトニングトークであって、軽いノリで誤った資料でいい訳ではない

ってことですね。
深夜のテンションで酒飲みながら資料作るのはもうやめようっと。。

修正版の資料はこちらにアップしました!

www.slideshare.net
また、上記コードは以下にアップしています。
kozake/ScalaStudyFunctor · GitHub
kozake/KotlinStudyFunctor · GitHub

<09/23 追記>
上記Kotlinコードにおいても、Scalaで実現していることを実現出来ていないと指摘を受けました。
確かに実現できていないので、比較対象としては不適切です。あくまで参考レベルの記事とさせてください。

*1:まあ、資料の中でもあくまでネタで、Scalaでも簡単に実現できるとは書いていましたが。。

*2:Delegationhttp://kotlinlang.org/docs/reference/delegation.html

*3:残念なことにクラスの委譲クラスは作成できないですが

Java 8徹底再入門(大阪,7/11)に参加しました!!

Java 8徹底再入門(大阪,7/11)に参加しました。

1. 栄養補充

勉強会前の栄養補給。

美味しかったです!(((o(*゚▽゚*)o)))
既にこの時点でやりきった感。( ๑°ω°๑)و グッ!
#じゃないだろ

2. 【Date and Time API

@khasunuma さんによる「Date and Time API」の発表です。
「Date and Time API」はJava8から導入された新しい日付APIですが、そのAPIの複雑さ(実際は日付の概念そのものが複雑だから仕方ないのだが)や、従来のjava.util.Dateとの違い・相互運用などで戸惑っている方も多いと思います。
これらについて、そもそもの時間の概念や「Date and Time API」の基本理念から丁寧に説明頂けました。

その時の詳細やスライドはこちらのブログ纏められておりますので、興味のある方はご参照ください。

「Java 8徹底再入門」に登壇しました。 - Programming Studio

また、「Date and Time API」についてのツイートがこちらに纏められています*1

Date and Time APIを理解する為には、ISO 8601に踏み込みましょう! - Togetterまとめ

「Date and Time API」についての纏めとしては、

  • Date and Time API は ISO 8601 (コンピュータ間でデータのやりとりをする際の、日付と時刻の書式に関する国際規格)モデリングして作られたものということを意識すること(ただし、ZonedDateTimeはそれとは違うということも意識すること)
  • まずはLocalDateについてマスターすること
  • Local/Offset/Zoned の存在意義を把握すること
  • 色々試してみること!

とのことでした!。やっぱり色々試してみるのが大事ですね!

個人的な感想としては、

  • 時間には人間の歴史や国ごとの政治があるということを感じた。
  • 1秒の基準となっているのは、セシウム(Cs133)の共鳴周波数で、これを利用したものが原子時計という話が面白かった。*2
  • 「ZonedDateTime」使用する場合は、内部のtz databaseの運用を考えないといけない、ミッションクリティカルシステムでJavaVMのバージョンアップなどを運用フェーズで行えるかどうかの考慮などが必要、という話にハッとした。
  • 個人的には、JDBCやORMの対応状況が気になる。

というところです。まだまだ現場での使用実績に乏しいAPIだと思いますが、今後の主流になると思いますので、それに備えたいと思います。

3. 【ラムダ式ハンズオン】

@bitter_fox さんによる「ラムダ式ハンズオン」です。@bitter_fox さんは学生さんですが、Lambdaにも若干絡んでいる最年少JDKコミッタです。
Paraya(GlassFish ディストリビューション)のContributorの@khasunuma さんのセッションといい、どう考えても今回は豪華イベントです。

ハンズオンの内容は次のようなものでした。

  • ラムダ式の書き方
  • FunctionalInterfaceの定義方法
  • forEachを用いた繰り返し処理の書き方
  • Streamの説明。Streamの生成・中間操作・終端操作
  • mapの使い方
  • 乱数を返す無限Streamを用いてのreduceやsummaryStatisticsの使い方
  • Optionalの説明
  • ParallelStreamの説明と実験
  • Streamを使ったファイルからの読み込み
  • CollectorとCollectorsの説明
  • flatMapの説明
  • Collectorsの使い方(toList/joining/groupingBy)
  • groupingByConcurrentの説明

ハンズオンは@bitter_fox さんの説明と、スクリーン上のコードを写経する形で淡々と進んでいきました。滑らかで分かりやすい説明で難しさは感じなかったかもしれませんが、これだけの説明が行われていたのですね!本当、凄い事ですよ。

個人的な感想としては、

  • OptionalにgetAsDouble()を使ってましたヽ(;▽;)ノ!すいません、負け組です。
  • Files.linesで生成したStreamのクローズ漏れが発覚ヽ(;▽;)ノ!
  • Collectorの並列処理の順序について自分の勘違いが発覚ヽ(;▽;)ノ!

大丈夫か?俺

 ハンズオンの説明の上手さに感心しました。reduceの説明とかは難しいだろうなと思っていましたが、とても分かりやすい図とともに説明していて、流石だと感心しました。

一方で、やっぱりflatMapの説明には苦労されていた模様です。時間もなかったし、ここは難しいですね。

最後のほうでgroupingByConcurrentについて説明頂けたのが嬉しかったです。凄い興味深い内容でした。

本当、説明・進行が上手だったのと、参加者のスキルが高かったので、TA業が暇でした。ハンズオンの内容とは関係ないのですが、前回のGSCollectionsのハンズオンも含めて、ハンズオン形式での進め方(教え方)について凄い勉強になりました。自分が教える立場になった時の参考になりそうです。

4. 【懇親会】

串カツ食べ放題・飲み放題で飲みまくりました!(((o(*゚▽゚*)o)))


その後は二次会にも参加、最後はGeekBearが4周年イベントやっていたので、ちょっとだけ顔出したらビール奢ってもらいました!

ありがとうございます、楽しかったです!!!
*・゜゚・*:.。..。.:*・'(*゚▽゚*)'・*:.。. .。.:*・゜゚・*

*1:そもそもこのツイートが今回の勉強会に繋がったのです

*2:10万年に1秒程度の誤差しか生まないというのは凄いですね!

GS Collections 道場[ハンズオン]に参加してきました!

小酒です。

昨日、GS Collections 道場[ハンズオン]に参加してきました!

久しぶりの勉強会のような気がします^^

kanjava.connpass.com

今年4月に開催された Java Day Tokyo 2015で発表を聞いてその存在は知っていたのですが、実際に触れたのは今回が初めてでした。

GS Collectionsはゴールドマン・サックスが開発し、2012年にGitHubに公開したオープンソースJavaコレクションフレームワークです。Apache License Version 2.0で提供されており、Java 7以前でも使用できます*1JavaのStream APIよりもより簡潔に書けることや、mutableやimmutableなコレクションインタフェースが用意されているのが好ましいと感じています。

GS Collections の説明や資料についてはconnpassのイベントページに詳しく纏まっております。興味のあるかたは、以下URLの下部にあるリンクを参照してください。

GS Collections 道場[ハンズオン][OSS コレクションフレームワーク] - connpass

 ハンズオンでは、「GS Collections Kata」というゴールドマン・サックスの社内研修でも使われているトレーニングキットを用いて行いました。

Fail状態のJUnitテストを研修の中でひとつひとつパスしていきます。

仕事現場において、プロジェクトに途中参加するメンバへの各種教育はいつも悩みの種ですが、このようにゲーム感覚で楽しく学べるトレーニングキットが用意されているのは素晴らしいと感じました。

 今回のハンズオンでは、インストラクターの方が壇上でライブコードしながらそのコードの説明をし、参加者がそれを写経する流れとなりました。時間の関係からの短縮手法でしたが、それでもかなりの勉強効果があるように感じました。実際に手を動かすとやはり理解の進みが違いますね!

GS Collections の楽しさや魅了を感じるには、資料を読んで実際のKata をやってみることをお勧めします。そのハンズオンの中で、僕が一番興味の湧いたコードを一つ紹介してみたいと思います。

 

次のコードは、いくつかの商品を保持するサプライヤーが存在する状況で、商品名をキーにその商品を保持するサプライヤーの一覧を保持するMapを作成します。

mapOfItemsToSuppliers

 仕様が分からない状況で、上のコードを読むのは少々骨が折れると思います。これをGS Collectionsを用いると、次のコードとなります。

mapOfItemsToSuppliersByGSCollections

 groupByEachメソッドを用いることで、シンプルに書けます。一度このメソッドがどのような操作を提供するかを知れば、次からは同じようなロジックを簡潔に表現できるようになります!このようにアルゴリズムの再利用がより促進されるのが、Java8 ラムダがJavaにもたらした福音だと個人的に考えています。

 なお、上のコードをStream APIで書いてみると次のとおりとなります。

mapOfItemsToSuppliersByStream

Tupleは自作しました。SupplierのStreamをflatMapで商品名をFirstとするTuple<String, Supplier>のStreamに変換して、collectでgroupingBy。その中でTuple<String, Supplier>のリストをSupplierのリストに変換する。。

う〜ん、ややこしい^^;

これならStream APIを使わずに書いた方が可読性がいいと判断してしまうかもしれません。

 

この一例からも分かるように、GS CollectionsにはStream APIにはない様々な機能が備わっております。今後Javaのバージョンが上がるにつれ、このような機能がStream APIにも備わってくるでしょう。

いち早くStream APIの未来に触れたみたいで、とても充実した一日でした!

インストラクターの伊藤さんとチューターの佐野さんをはじめ、関係各位のみなさん、本当ありがとうございました(((o(*゚▽゚*)o)))!!

 

その後は懇親会でビールを飲んで、二次会でもガンガン飲んで、めちゃくちゃ楽しかったです!!今日は昼間までくたばってましたがww

 

(追記)

このブログを公開した後、@backpaper0 さんからコメント頂きました!

gist.github.com

https://gist.github.com/backpaper0/59bf51b8c1d8804c3611

このように、独自でCollectorを実装すると、Stream APIでも簡潔に処理を記述できますね!

ただ、その後、@bitter_fox さんとのやりとり

 

Collectorクラスには独自のCollectorクラスを作成するofメソッドが用意されています。

  • 第一引数に新たなインスタンスを作成するサプライヤー(ここではHashMapのコンストラクタ
  • 第二引数にオブジェクトに要素を追加するアキュムレータ
  • 第三引数に2つのオブジェクトを1つのオブジェクトへとマージするコンバイナ

を指定します*2

ここでの例では、コンバイナにputAllを使っているので、同じキー同士の場合にリストの結合が必要な処理が抜けているというのが@bitter_fox さんの指摘だと思います。

本来であれば、Map<String, List>の結合は重いので、1つのConcurrentHashMapで全て出来ればいいのだけどって話も続いていますが、Collectorがそのような考えでは作られていないのかもです。せめて、リストの追加は処理の重いArrayListよりLinkedListを用いたほうがいいかもとか、そのようなことを考えました。

Collectorを生成する場合は、並列動作について問題なく動作する仕組みを考える必要があります。まあ、そのようなコードは総じて難度が高くてミスを犯しやすいので、やっぱり標準メソッドで用意してくれたらな〜^^; って考えちゃったり。

まあ、パラレルストリームなんて業務で使わry)

 

*1:Java 5までの後方互換をサポートしているらしい

*2:更なる情報はJava SE8 実践プログラミングのp.42に詳しく書かれています。

Javaプログラマーなら習得しておきたい Java SE 8 実践プログラミング

Javaプログラマーなら習得しておきたい Java SE 8 実践プログラミング

 

 

Sping Boot キャンプに入隊してきました!!


【脱初心者】Spring Bootキャンプ【ハンズオン】 - connpass

 

入隊してきました^^

ハンズオン資料はこちらに公開されています。

Spring Bootキャンプ ハンズオン資料 — Spring Bootキャンプ ハンズオン資料 1.0.0-SNAPSHOT ドキュメント

 

とても面白い内容かつ丁寧に書かれているので、Sping 初心者でも十分楽しめると思います。かくいう私もSpring 初心者でしたが、なんとかなりました!

お約束的な「Hello World」から始まり、OpenCVの用意、JMSを用いた非同期処理にWebSocket、最後はWebRTCを用いたカメラとの連携と、作る楽しさを久しぶりに感じたように思います。

 

個人的には、OpenCVで遊んでる時が一番楽しかったようなww

 

7章のSTOMP over WebSocketのところは資料だけでは分かりづらかったのですが、説明を聞いて理解出来ました。やっぱり説明があるとないとでは全然違いますね。

当日は9章までしか進めなかったので、どこかで10章、11章を進めてDockerで遊んでみたいと思います。

 

懇親会も面白かったです。懇親会では@making さんが作っている「terasoluna.org」の存在を知れたことが大きな収穫でした!この資料は本当に凄い!

懇親会ではLTやるって話を2日前に聞いたので、前日にあわててLT資料を作成して発表しました。ほとんど誰も作ってなかったしwww

まあ、内容はフルボッコでしたよ^^;

 

Web API Design for JAX-RS

 

本当に楽しかったし、まわりの皆の実力にまたまた凹む勉強会でしたw

またやりたいです!

 

2015 in Plan

2015年。新しい年が始まりました!!(((o(*゚▽゚*)o)))

去年を回顧し、今年の目標を立てたいと思います。

Keep 

"変"

  • 早起き
  • ダイエット

"楽"

  • コミュニティ活動
  • 遊び

去年立てた目標の"変"については、それなりに上手くいったと思います。朝の活動やダイエットを通した体調管理については今年も継続したいと思います。また、やっぱり"楽すること"を考えて効率化する事は大事ですし、"楽しむこと"は人生の活力ですね!今年もたくさんの"楽"に恵まれるよう積極的に行動したいと思います!

Problem

"流"

  • 勉強方法

"生活習慣"

  • 睡眠時間

 "流"についてはアウトプットを重視する意味で立てたのですが、インプットに偏っていました。これについては改善して行きたいと思います。

また、去年は早起きのせいで寝不足が多かったように思います。睡眠は健康の要です。早寝を心がけたいと思います。

Try

さて、今年の目標です。今年の目標は3つ。"計", "創", "外"

『十分に終わりのことを考えよ。まず最初に終わりを考慮せよ。』(レオナルド・ダ・ヴィンチ)

計は計画・計測の意味です。去年は行き当たりばったりの行動が目立ちました。今年は目標を定めて計画立てて行動し、行動を計測していきたいと思います。また、そもそも見積もりやマネージメント能力が個人的に不足していると思います。今まで自分はマネージャーにはならないからと避けていたスキル分野ですが、マネージャになるならないはともかく、そういったスキルを勉強することは人生の糧になりますので、マネージメントスキルの向上も視野に入れて行動していきたいです。人生のWBSでも作るかなww

具体的には、

  1. 向上させたいスキルの選定と、それに伴う読書本の選出
  2. プロジェクトマネージャ試験の受験。できれば取得
  3. 個人プロジェクト(モノ作り)の計画

を計画して行動して行きたいと思います。

『私は自分に作れないものは、理解できない。』(リチャード・ファインマン)

去年はアウトプット駆動で頑張ろうと思いましたが達成出来ませんでした。今年は具体的に何かモノ作りをして行きたいと思います。作ることで自信も理解もついてくることは多いと思います。モノ作りを通して、もっとコードの読み書きを増やしたいですね。まだ具体的に何を作るかは決めていませんが、個人プロジェクトの立ち上げを頑張りたいですね!

『The limits of my language are the limits of my world.(あなたの言語の範囲はあなたの世界の範囲でもある。)』(Ludwig Wittgenstein)

はい、外国語です。具体的には英語です。英語の読み書きは今後の必須スキルですしね。。苦手とかは言ってられないので、継続的にやっていこうと思います。

具体的には、英検3級、そして2級を目指したいと思います。高校レベルの読み書き、ヒアリング能力を目指したいな〜

 

以上が2015 in Plan です。

がんばるぞい!

2014 in Action

2014年もあとわずか。思えばツラい事も楽しい事も多い一年でした。総じて見ると、とても濃い一年だったと思います。

今年のはじめに2014年の計画を立てました。

2014 in Plan - シスアーキ in はてな

テーマとして、「」「」「

それぞれどうなったかを振り返ってみたいと思います。

出来るだけアウトプットを多めにしたいと考えて行動したつもりでしたが、やはりインプットに偏った気がしています。その結果、書評の記事が多かったですね。

【献本駆動】「Play Framework2 徹底入門」を読んだよ! - シスアーキ in はてな

DevOps時代の必読本?「チーム開発実践入門」を読んだよ! - シスアーキ in はてな

アジャイルAPI設計時代の到来!?APIデザインの極意を読みました。 - シスアーキ in はてな

生まれ変わったJava !? 『Java SE 8 実践プログラミング』を読みました!! - シスアーキ in はてな

アウトプットとしてはスライドが多かったです。

システムアーキテクト~My batis編~

生きろ!チーム開発! 300人月の仲間はみな死んだ

Nullなのはいけないと思います!

ゆるふわアーキを支える技術

来年は今年の反省を活かし、アウトプットをメインで心がけるようにしたいと思います。特に、コードを読む・書く、モノを作る、計画的な読書、などを心がけたいですね。

自分でどう感じるかはともかく、周りからは「変わった」とよく言われました。個人的には、朝の早起きとダイエット出来たのが良かったです。ただ、変わるのは良いことばかりではなく、悪いこともあると感じました。僕が変わると、周りの人間関係も変わりますしね。ただ、僕が変わらなくても時代は変わります。来年も今年と同じく変わって行きたいと思います。出来れば、良い方向に変わりたいものですね^^

楽しかったかな〜?ww ツラい事も多かったですねw

でも、楽しい事、いっぱいありましたよ!

Scala Matsuri 2014に参加しました! - シスアーキ in はてな

hoge駆動忘年会 in Action - シスアーキ in はてな

あと、記事にはしていないけど夏のBBQも楽しかったし、みんなとの飲み会とか楽しかった!

個人的には離島とかしまなみ海道と行けなかったのが残念。来年は行きたいな。ドラクエXも全然やっていないやw

 

 まとめ

いろんな人に支えられ、なんとかやって来れた一年でした。本当に僕によくしてくれた人達に感謝したいと思います。来年はもっと良い年にしたいし、大事な人達を幸せにしたいと思います。

みんなありがとうな!来年もよろしくお願いします〜

2014年、バイナリ〜( ´ ▽ ` )ノ

hoge駆動忘年会 in Action

hoge駆動忘年会に行ってきました!!!

 http://hogedriven.net/

 今回は異例の大人数の忘年会でした。

お昼ご飯

お昼ご飯に鶴橋で焼肉食べたけど、上手かったです^^

ビール上手すぎて2杯飲んじゃったw

忘年会までの暇つぶし

夜の忘年会までちょっと早く集まってしまったので、暇つぶしに各自LTをしました!僕の発表資料はこちらです。

暇つぶしのLTなのに、フルボッコされましたww。Groovy界隈怖い。この資料はJavaをやっている若い人向けに作りました。周辺技術を学ぶとレバレッジが効くし、勉強したほうが楽だし楽しいよ!って意味を込めて作りました。まあ、やっつけな感じがする資料ですけどねw

 

みなさん濃い発表が多かったですが、一番印象に残ったのは乙女部のみなさんですね。

 

あと、どうも会場にはたまたま 、里の者が多かったみたいです。

イマキクというサービスらしいですが、面白かったです。

 忘年会

ふぐうま〜!!!!!

忘年会2次会

雨も降っており、2次会の店探しに困っていたのですが、きのこさん神対応Osakan Space をお借りすることが出来ました!もう一人のきのこさんとも合流出来て、めちゃくちゃ楽しかったです!!

感想