エンジニア立ち居振舞い:自分は出来ないと思い込みすぎない
お題「エンジニア立ち居振舞い」
↑便乗!!
自分は出来ない、レベルが低いと必要以上に思わない方がいいに違いない。
なぜ?
自分が困る
- 精神的に疲れる
- 他者からの評価すら下がる、給料アップチャンスを逃し得る
いいと思っていないものをアピールするのって難しいからね。
後輩 *1 が困る
- 適切な説明や指導が出来ない
「自分に出来たのだから万人に出来るはず」「自分がバカだから分からなかったけど、この人には説明しなくても大丈夫」ってなる。 - 後輩の自信や評価までもをマイナスにしてしまう
先輩 *2 が困る
- 先輩だって間違える、ということを忘れてしまう
先輩と意見が違ったとき、「自分の方が間違ってるんだろう」と思い込んで事前に分かったミスをスルーしてしまう。もっと良いはずのアイディアを出せない。
その他
- 自分を評価してくれる人に失礼だ
自分の成果を褒めてくれる人がいるのにそれを否定して嘘にしちゃうの、とても残念。
じゃあどうする?
人ではなく、事実を評価しようとがんばる
- バグ出した、知らないことがあった -> 自分はダメエンジニアだ
この手の自己評価をして嘆いたところで、バグは直らなければ知識も増えない。
「自分はまだまだレベルが低いから仕方ない」という逃げにしかならない。
だから、 - バグ出した -> 何故出した、どうやって直す、どうしたら防げた、次からどうする
- 知らないことがあった -> 何が分からなかったのか、何を知ればいいのか、何を学んだのか + 何なら知っていたのか
当たり前だけど、こういうことを考えて行動したい!
自分の行動を、自分という人間の評価だとすぐに錯覚しない!
- バグ出した、知らないことがあった -> 自分はダメエンジニアだ
時々自分の行動を褒める
対象がなければ行動する。
おしまい!
うらがみさんアドバイス解析〜リテラルはGCされない〜 #hogedriven
この前関西のエンジニアおともだちと集まって遊んだ時に発表した資料を公開しちゃお〜
何かと言うとですね。
かなり昔だけど、ふと浮かんだ疑問をツイートしたら
うらがみ(@backpaper0)さんがコード書いて実験してくれて。
それを今更解析したよ〜ってことで発表して、内容合ってるか皆さんに見ていただいたの!
資料だけだと分かりづらいかもしれんけど、すごく勉強になったし面白かった。
うらがみさんへのお礼としてアップルパイも焼いていい経験になったよー!
ツイート↓
よし。
— よこな / Ayana (@ihcomega) November 10, 2014
String s = new String("うわぁ");
って書いちゃった時
newで生成される方じゃなくて"うわぁ"の方のStringオブジェクト(何て説明したらいいのか、リテラルの方)は、
どこからも参照されていないからすぐ(?優先的に)GCの対象になる。
ですか?
コード by うらがみさん↓
gist.github.com
この作業で生じたTODO
- コンスタントプールについて勉強する…というかjavapを学ぶ
- コードの後半も読んでみる
最後に、資料には書いてない感想を追加しておこう。
こうやって有識者の方に教えていただく内容って結構難しいけど、
ちゃんと考えれば理解できるし、何となく分かったで放置せず向き合っていきたいなー
ここ最近のおひとりさま勉強会 #yokodokusho
細々とやっているのですが間が空きました。また続けていこうと思います。
なんか難しくなってきて全く進まなくなってきましたんですが
ここで絶望して投げ出す癖を絶対に治すぞ〜〜〜
昨日のJava女子部で
身の回りの優秀な方は皆本を読んでいるよねという話になって
そうだよねって改めて思ったからです・・・
全然勉強しないから成長が遅いという当たり前の因果が
いよいよ辛くなってきたので、もう少し気合入れて頑張ります😓
Now or never! Nothing is too late to start!
そうそう、サイ本読んでると、当たり前のことなのに説明回りくどくない?って時々思う。
でも例えば経験のない人とか、他の言語やってきた人とかが理解するには
こういう表現が必要なのかもしれないなーと納得しています。
どんな読み手を想定するか?どこまで噛み砕くか?何を知ってる前提で話すか?
本を書くことの難しさを感じるぜ(アホっぽい)。
Scalaのforeachはパターンマッチで書けるのね
val hoge = List(1, 3, 5, 7)
こんなリストがあるとして
順番に要素を出力してみよう。
👻例1
foreach
を使うと
hoge.foreach(h => { println(h) })
こうなる。
👻例2
これをパターンマッチと再帰的なサムシンでも書けるっぽい。
@tailrec def f(hoge: List[Int]): List[Int] = { hoge match { case h :: fuga => println(h) f(fuga) case _ => List.empty[Int] } }
f(hoge)
を呼び出せば例1と同じになる。
何故急にこんなことを書いてみたかというと、
例2にあるcase h :: fuga =>
の意味が分かった記念。
最初::
が要素追加かと思って何をしているのか理解できんかったけど、リストを順番に処理しているのね。
ちなみにここでの再帰処理を図におこすとこんな感じだと思う!
Scalaのパターンマッチはとにかく強いらしい…?
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:あえての表現なので怒らないでください、お兄様♡