Scala入門者向けハンズオンに参加した #ScalaNyumon
1週間前ですが・・・
6月5日(土)はScala入門者向けハンズオン@東京に行くことが出来たー!
講師は@gakuzzzzさん!
資料は@mike_neckさんの!
github.com
豪華٩(๑❛ᴗ❛๑)۶
いっぱい知見を得たのでまとめた!(何故かうまくembedできない…)
http://togetter.com/li/986758/togetter.com
最初にScalaについてご説明があって、そのあとは簡単なチケット管理システムを作るハンズオン。
ということでブログにはハンズオンのことをさらっと書いておきたい。
こんな流れ↓で進めてくださり、最後、チケットの検索や更新をするTicketRepo
に自力でメソッドを追加してみよう〜というものだった!
カリキュラム · mike-neck/scala-study Wiki · GitHub
メソッドの仕様もここにあります。それにしても資料、丁寧・・・
私もTicketRepo
の中身を書いてみたものの怪しい実装だらけになったので、
みけさんの実装と比べてみようと思う。
- 私(以下🐳)の:
hello-scala/TicketRepo.scala at blog · ihcomega56/hello-scala · GitHub - みけさん(以下🐱)の *1 :
scala-study/TicketRepo.scala at master · ihcomega56/scala-study · GitHub
※私のはチケットをつっこむMapの名前がtickets
で、みけさんのはmap
なので以下のコードたちもそこの違いはあり〼
findAll: Seq[Ticket]
- 🐳こう書いてみた。
def findAll: Seq[Ticket] = {
tickets.values.toSeq
}
- 🐱IDでソートしてあった・・・親切・・・
def findAll(): Seq[Ticket] = {
map.values.toSeq.sortBy(_.id)
}
findById(id: TicketId): Option[Ticket]
- 🐳🐱同じだった。
def findById(id: TicketId): Option[Ticket] = { tickets.get(id) }
createIssue(title: String): Issue, createBug(title: String): Bug
※createIssue
は割愛
- 🐳自信なさげにこう書いた。
currentId
という怪しい変数、最悪っぽい…。
def createIssue(title: String): Issue = { val newIssue = new Issue(currentId, title) tickets = tickets + (currentId -> newIssue) currentId += 1 newIssue }
- 🐱こうやれば
currentId
いらないね。あとIssue
はcase class
なのでnew
しなくてよかった、あちゃ。
def createIssue(title: String): Issue = { val nextId: TicketId = if (map.isEmpty) 0 else map.keys.max + 1 val issue: Issue = Issue(nextId, title) map = map + (nextId -> issue) issue }
findIssuesByStatus(staus: String): Option[Seq[Issue]], findBugsByStatus(status: String): Option[Seq[Bug]]
※findBugsByStatus
は割愛
- 🐳空の
Seq
を返す術しか分からなくて最後に苦し紛れの一文を入れた('_')ちーん
def findIssuesByStatus(status: String): Option[Seq[Issue]] = { val issues = tickets.collect { case (id, ticket: Issue) if TicketStatus.isMatchedStatus(status, ticket) => ticket }.toSeq if (issues.nonEmpty) Some(issues) else None }
ちなみにTicketStatus.scala
にもメソッドを追加してある。
def isMatchedStatus(status: String, ticket: Ticket) = { status match { case "open" => ticket.status == TicketStatus.Open case "fixed" => ticket.status == TicketStatus.Fixed case _ => false } }
- 🐱ぎょーなんかシンプルだ。
def findIssuesByStatus(status: String): Option[Seq[Issue]] = { val st: Option[TicketStatus] = TicketStatus.of(status) st.map(s => { map.values.toSeq collect { case x: Issue if x.status == s => x } }) }
TicketStatus.scala
のメソッド〜。そもそもここの戻り値がOption
なのねそうなのね。
def of(status: String): Option[TicketStatus] = { status.toLowerCase match { case "open" => Option(Open) case "fixed" => Option(Fixed) case _ => None } }
fix(id: TicketId): Boolean
- 🐳ひどいよ〜(;▽;)
else return false
なんて書きたくないよ〜(;▽;)
def fix(id: TicketId): Boolean = { findById(id) match { case Some(t: Issue) => if (t.status == TicketStatus.Open) tickets = tickets.updated(id, new Issue(t.id, t.title, TicketStatus.Fixed)) else return false case Some(t: Bug) => if (t.status == TicketStatus.Open) tickets = tickets.updated(id, new Bug(t.id, t.title, t.description, TicketStatus.Fixed)) else return false case _ => return false } true }
- 🐱あ。あ。
exists
でチェックすればいいのだ。
def fix(id: TicketId): Boolean = { val ticket: Option[Ticket] = map.values.find(t => t.id == id && t.status == Open) ticket.exists(t => { map = map.updated(t.id, t match { case x: Issue => Issue(x.id, x.title, Fixed) case x: Bug => Bug(x.id, x.title, x.description, Fixed) }) true }) }
修行あるのみ✋(--)👌
最後にしょーもない感想。
今まで、既に動いてるシステムの改修しかしたことなかったので
trait
作って、object
でenum作って、case class
作って・・・って
新規作成の流れを体験できたのはとても勉強になったー。
あとはpackage object
とかsealed
とか知らなかったりよく分かってなかったりしたことも理解できてよかったなー。
学び多きイベントをありがとうございました!
*1:forkしました
Dockerで予め欲しいデータをつっこんだMySQLをこしらえる(Mac用)
MySQLいっぱい生み出して使い分けがしたかったので調べた。
今はまだコンテナが死ぬとデータも死ぬ仕組みなので、主にDaoあたりのユニットテストで一時的なデータ入れるためのDBとして使っておる。
うまくいくまで悩んだりもしたので、やり方だけメモしておく!
ちなみにMac OS X El CapitanでVirtualBox使って動かしているよ!!
✬やってみること
- MySQLをDocker上で動かす
hoge
データベースを作るhoge.users
テーブルを作るduke
ユーザを作り、hoge
に実行権限を付与する
✬インストール
✏VirtualBox, Docker Machine, Docker Toolboxをインストール
$ brew cask install virtualbox $ brew install docker-machine $ brew cask install dockertoolbox
✬DockerfileとSQLの用意
✏サンプル
こんな感じ。
#Dockerfile # FROM コマンドでDocker公式のMySQLイメージを使える(コロン以降がバージョン) FROM mysql:5.7 # RUN コマンドでDocker側で実行するシェルのコマンドを書ける # MySQLの設定をこんな感じで追加しておく RUN { \ echo '[mysqld]'; \ echo 'character-set-server = utf8'; \ } > /etc/mysql/conf.d/charset.cnf # COPY コマンドで自分のマシンからDockerの/docker-entrypoint-initdb.d/下にprepare.sqlをコピーする # /docker-entrypoint-initdb.d/ 下にあるSQLは全部勝手に実行してくれる!!! COPY prepare.sql /docker-entrypoint-initdb.d/prepare.sql
--prepare.sql -- これはいらないかも... DROP DATABASE IF EXISTS hoge; DROP DATABASE IF EXISTS fuga; -- データベースを作る CREATE DATABASE hoge; -- dukeユーザをつくってよしなに権限をつける GRANT ALL PRIVILEGES ON hoge.* TO 'duke'@'localhost'; -- テーブルを作る (実際はちゃんとしたDDLを用意する) CREATE TABLE `hoge`.`users` ~ ;
要は、実行したいSQL(登録したいデータ)入りファイル/docker-entrypoint-initdb.d/
にコピーすればよい!
複数ファイルあっても、コピーした分全部実行される。あと、ダンプファイルとかそのまま使えるのでべんり!
✏応用編(正しいかは分からないけどこれで解決できた)
- SQLが複数ファイルにまたがっているが、実行順を制御したいとき(外部キーがあるとか...)
/docker-entrypoint-initdb.d/
にコピー後のファイル名を、ls
コマンドで上から実行順に並ぶよう工夫する。
つまり、a.1番目のファイル.sql
、b.2番目のファイル.sql
、...みたいにすればその順番に実行できるよ〜。強引。 - 操作対象のデータベースを変更したいとき(データベース指定のないSQL文を実行するとか...)
USE hoge
とか書いたファイルを作って、意図した通りの順序で実行する。
✬初回セットアップでやること
✏test
という名前でDockerホストを作成
IPアドレスの指定が不要な場合は、--virtualbox-hostonly-cidr "192.168.99.99/24"
の部分は書かなくてもよい。自動で採番されるので大丈夫。
指定したい場合は例みたいにして、CIDR形式で書こう!
$ docker-machine create --driver virtualbox --virtualbox-hostonly-cidr "192.168.99.99/24" test
✏test
ホストを起動
restart
コマンドやstop
コマンドもある。
$ docker-machine start test
✏環境変数を適用
$ eval "$(docker-machine env test)"
✏Dockerイメージをビルド
latest
はイメージのバージョンに該当する。
$ docker build -t test:latest .
✬起動の度にやること
✏test
ホストを起動
$ docker-machine start test
✏環境変数を適用
$ eval "$(docker-machine env test)"
✏起動中のコンテナをすべて停止、削除
関係ないものも停止しちゃうので注意。当然だけどまだ何も起動してないならやらなくてもよい。
$ docker stop $(docker ps -aq) $ docker rm $(docker ps -aq)
✏test-mysql
という名前でコンテナを立ち上げ (ポート番号はお好きに変更してね)
次の例だと、ローカルからポート3307のmysqlに繋ごうとすればよい。Dockerがポートフォワードしてくれて3306に繋げ変えてくれるらしい・・・
$ docker run --name test-mysql -p 3307:3306 -v ~/docker/mysql/conf.d:/etc/mysql/conf.d -e MYSQL_USER=duke -e MYSQL_PASSWORD=password -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=test -d test:latest
はい出来た!これでOK!!!
prepare.sql
に書いたSQLたちが実行された状態でMySQLが誕生するよ〜。
接続できるか確認してみよう!
$ mysql -h$(docker-machine ip test) -P3307 -uduke -p
ちなみに立ち上げで使うコマンドはシェルスクリプトか何かにしてしまえばもっとラクラクになる。
#!/bin/sh # ホストを起動する docker-machine start test # 環境変数を適用する eval "$(docker-machine env test)" # 起動中のコンテナをすべて停止、削除する(関係ないものも停止するので注意) docker stop $(docker ps -aq) docker rm $(docker ps -aq) # コンテナを立ち上げる docker run --name test-mysql -p 3307:3306 -v ~/docker/mysql/conf.d:/etc/mysql/conf.d -e MYSQL_USER=duke -e MYSQL_PASSWORD=password -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=test -d test:latest
✬その他よく使うコマンド(の一部)
✏実行中のコンテナを確認
$ docker ps
✏ログ確認 (立ち上がらない時とかはこれをチェック!)
$ docker logs --follow test-mysql
以上!Docker入門出来て嬉しいな!
強引なやり方を採用しているところは、もっとよい術があれば是非教えて下さい!
参考ページ:
JJUG CCC 2016 Springで若者として煽り芸にトライした #jjug_ccc
もう昔のことですが、5/21(土)はJJUG CCC 2016 Springでした。
お越しくださった方、登壇者の皆様、ボランティアスタッフおよび幹事の皆さん、ありがとうございましたー!!
当日の資料やブログ一覧はGitHubにあります。
github.com
私はというと例によって運営したり、ちょこっと登壇したりしていました。
❂運営のはなし
今回は20分枠作ったり、CfPの選考に皆さんのご意見を取り入れたり、
休憩を長くしたり、コーヒーをお出ししたり、、、
今までと違うことがたくさんありました。
(詳しくはまーやさんのブログへ…とか言うとまた手抜きって怒られるかなw)
良かった点、至らなかった点、いずれもあるかと思いますが、
毎回「前回よりよいJJUG CCCだった」と言えるよう改善しながらやっていきたいものです。
感想や気付きを伝えて(or ツイートして)くださったり、アンケートにご協力くださったりする皆々様、本当にありがとうございます!
自分のことを振り返ると、前回までより準備に関わることが出来たのでよかったです。
基調講演で会長がおっしゃってた通り(資料はコチラ)ちゃんと労働力として機能してたはずだし、
失敗を恐れて今までは手を挙げず見守ってた仕事たちにもトライ出来たし、
少しだけ自信やら責任感やら当事者意識やらがUPした気がしています。
手際も容量も悪いし、見事なタイミングで仕事の方も超絶忙しくなったし想像以上に大変でしたが…
何であれ出来ることが増えるというのはいいものです。
❂登壇のはなし
これはJava女子部メンバーから希望者を募り発足したプロジェクトです。
私はほぼ何もしていなくて、当日チューターとしてお手伝いさせていただいたのみ。
トラブルがつきもののハンズオンですが、
この日は見事、ご参加者全員がチャットツールを動かすところまで行けました〜!
プロジェクトメンバーは毎日本当に準備を頑張ってくださっていたので、
上手くいったのをみて勝手にすごく嬉しかったです(仕事しろ)。
ちなみにプロジェクトはまだ続いてて、7月にJava女子部のイベントとして
彼女たちに勉強会をやってもらう予定なのでよろしくお願いしますー!!
✲ 若者枠セッション (#ccc_ab7)
若者にJavaの好きなところ嫌いなところきいてみたというタイトルで、
@Shin_TNMT氏司会のもと、@bitter_foxさん、@iwata_nさん、@aya_122ちゃんと
好きなところ・嫌いなところをプレゼンし、会場からご意見をいただくスタイルでわちゃわちゃやりました。
私は「おっさんを煽る!!!」と意気込んでJavaの嫌いなところ
…というか、困っちゃうところを語らせていただき、
時間いっぱい使ってアドバイスいっぱいいただいちゃいました('_')
なお、資料だけだと色々誤解を招きそうなので公開は控えます。
ちなみに、おっさん*1たちからのアドバイスは皆とてもポジティブなもので、
結構まじでわくわくしました。
大変なことや辛いことにも向き合っていくしかない、将来きっともっとよくなる!よくしよう!
…そう思って頑張っていきたいと思ったよこなでした(雑)。
❂その他
あと書いておきたいこと…今回は、スペシャルで素敵な出会いがありました!@Java中の方!!
Learn more about the #Java community event in Japan.https://t.co/YsLey2djLk pic.twitter.com/NPBWcYvyqO
— Java (@java) May 23, 2016
スタッフTシャツ来てうろちょろしていたら「Java女子部スタッフ?」って声かけていただき、
あれよあれよとJava Day Tokyoでインタビューを受けるチャンスをいただくことが出来たのです!
(それに関しては未来のわたしが別途ブログを書くことでしょう、きっと)。
すごく嬉しかったし、自分のような小娘に話しかけてくださるなんてありがたすぎる話ですねぇ。
CCCは毎回新しい挑戦や気付き、人との出会いがあってやっぱり大好きなイベントです。
もちろん運営をやっているとゆったりセッションを聞けない時間帯もありますし、
京都に住み始めて困難も増えてしまいましたが、それ以上に得るものが大きいぞと本気で感じます。
そうそう、去年のCCC後もこんなツイートをしてたんですが、
こういう感覚は今でも続いています。嬉しいことですねぇ。多分。
成長していないということか?違うよな…?むむむ。
昔に比べてCCCもナイトセミナーも圧倒的に面白くなった。少しずつ理解できる話が増えてきたからね〜。 #jjug_ccc
— よこな / Ayana (@ihcomega) April 11, 2015
なんかブログが久々すぎて、書き方やまとめかたを忘れました。日記になっちゃったよ。おしまい。
*1:あえての表現なので怒らないでください、お兄様♡
Git入門勉強会開催した #javajok
4月24日(日)、割と時間が経ってしまいましたが、Git入門勉強会をしました!
スライドはJJUGナイトセミナと同じこれ(使い回しではありません。再演です。)なんですが、
今回はハンズオンもやってみました。
ハンズオン資料のリポジトリはこちら。
https://github.com/ihcomega56/git-handsongithub.com
1人でも複数人でも出来るように作ってみたぜ〜!
13:00 - 18:00 という長丁場でしたが楽しくやれたのではと思ってます。
ご参加者の皆さん、そしてスタッフの皆さん!!!ありがとうございました!
会場提供のエムオーテックスさんにも感謝感謝(-人-)
今回準備において、Gitは人/チームによって使い方が全然違うことを改めて感じました。
初心者にどのコマンドが必要かとか、どういうツールを紹介するかとか、
想像以上に意見が分かれたぞー面白かったです😂
また何かやりたーい!
第1回孤独サイ本読書会という名のおひとりさま勉強会 #yokodokusho
JavaScriptを勉強したくなったので第1回孤独サイ本読書会を開いてみました。
参加者は私だけ、家以外のどこか(今回は会社使った)にてサイ本を読むだけです。
1名でやってましたが、TLの皆さんに色々教えていただきつつ勉強できて感謝!
学びがたくさんあったのでtogetterにまとめました(๑ˇεˇ๑)•+¨+•.¸¸♪
ちなみに何故黙って1人で読書しないかというと、サボってしまうためです…。不真面目…。
自分をイベント主催者かつ参加者に見立てることで真面目に取り組めるか試したかったんだー!
結果、これ飽きるまでは良さそうかな〜と思ってます。
やると宣言することで自分を追い込めるのはもちろんありますが、
ハッシュタグ使ってツイートしつつやる*1ことで、
読んだ内容を言葉にして整理したり他の方と議論したり出来るのが為になりました。
今後、習慣化できて#asakzkみたいになったらなおよいですが、
そんなに気張らず時々やりたいです。
次回開催日は絶賛検討中です。
*1:後からブログにまとめるより気軽なのもよい〜
IntelliJ IDEAのPreferencesにはdefault project用とcurrent project用があると気付いた
チームメンバーと同じ設定をしたのに、
私しか設定が反映されなくて「???」となったときに気付きました。
使っているIntelliJ IDEAのバージョンは2016.1です。
⌘
+,
(またはメニューのIntelliJ IDEA
->Preferences...
)で表示されるPreferencesは
current project用!!!
既に存在する(というか今開いている)プロジェクトの設定変更はここから出来ます。
今までこっちしか使ったことなかった・・・メニューの
File
->Other Settings
->Default Settings...
で表示されるPreferencesは
default project用!!!
この設定は、IntelliJ IDEAから新しくプロジェクトを作成する度に反映されます。
JetBrainsさん公式にもそれらしき記載がありましたので参考にしました〜。
- current project用設定 Learn the IntelliJ IDEA Settings/Preferences Dialog
- default project用設定 IntelliJ IDEA 2016.1 Help :: Accessing Default Settings
これがセミコロンレスJavaか・・・
最近星野源にハマっている。先日ライブにも行ったのだけど、サイコーだった・・・。
星野源自体も曲もMCもバンド(長岡亮介さんとかカースケさんが!!)も会場の一体感もよかった。
で、さっき、気付いたら
星野源は今日もタイプ
— よこな💪 (@ihcomega) 2016年3月24日
ってツイートしてて星野源は明日もタイプ
— よこな💪 (@ihcomega) 2016年3月24日
いやぁ明日どころか明後日も、明々後日もだよなぁ・・・
でもそんなにたくさんツイートするわけにもいかんなぁ・・・と思って
プログラムを書けばいいんだということになった。
それも普通に書くんじゃなくセミコロンレスJavaっていう遊びをしてみようということになった。
ということで、うらがみさんのブログエントリ(以下)を参考にしつつ
backpaper0.github.io
なるべく自分で書こうと思ったのだけど、全然出来んかった。
public class 星野源はずっとタイプ { public static void main(String... args) { if (java.util.stream.LongStream .iterate(0L, n -> n + 1) .mapToObj(o -> o == 0 ? "今日" : String.valueOf(o) + "日後") .peek(day -> System.out.println(day + "も星野源はタイプ")) .count() > 0) {} } }
Streamの操作のところだけど、
これまでの知識とひしだまさんのサイトで何とかなったのはiterate
とmapToObj
の行だけ😂
peek
とcount
はうらがみさんのを真似しました😂
0日目を"今日"と出力する地味な工夫も大変むなしく、
すごい勢いで数字がインクリメントされて最高ですね。
よくみるとツイートと若干文言が違うけどまぁいいや。
Streamの復習になった…かな…
深夜のテンションってコワイ。おやすみなさい。