ごまなつ Blog

楽しく働ける世界を目指して

「エンジニアのためのコーチング入門」参加レポート

6/11に開催された、「エンジニアのためのコーチング入門」に参加してきました。登壇資料はイベントページにすべて挙がっています。

coaching.connpass.com

導入スライド

以下は私のメモです。詳しくは登壇資料をご覧ください。理解が深まります。どのスライドも考えさせられるので、ぜひ読んでいただきたいです。

人と話すことが苦手な人の方が、コーチングは上手くなる / 三橋 新

  • 自分がやれることは、経験によって増えるが、何でも屋になってしまうと他人の人生を生きることになり、承認欲求の限界が来る
  • 全ての人の期待に応えることはできないので、一部の人に最高の価値を提供するマインドセットに変える
  • 自分がやれることをそぎ落として、好きで得意で人のためになることにフォーカスすると誰でも、何者かになれる。自分の強みは、人に聞こう。
  • 人生の目的は、言語化できていなくてもよい。イメージでもいい。あなたの目が死なないように
  • 「コミュニケーションは上手に話さなくてはならない」は囚われ。コーチングは自分のことを話さなくていい
  • コーチングは相手を主体とした協働作業。好奇心、問い、おうむ返し
  • コーチングで一番大切なのは相手の可能性を信じること

1on1で使えるコーチングスキルの活かし方 / 谷内 真裕

  • 1on1でありがちな囚われは、相手を自分が導かなければならないという考え
  • 相手に話すと、自分にも響くが相手に焦点を当てる
  • 隠しているつもりでも、ウソ・ごまかし・恐れが伝わってしまう。自分が完璧である必要はない
  • 先に自分が相手を信じる
  • 導入セッションをする。目的や話すこと、約束を文書化して事前に読んでもらう
  • 1on1のスキルはいろいろあるが、すべては傾聴から始まる
  • 傾聴の練習が大事
  • 相手が発するエネルギーの強弱はとても重要

エンジニアリングマネージャー育成におけるコーチング / 安西 剛

  • オーセンティックであることが重要。自分らしさを貫いていること。
  • VUCAの時代では自分で答えに近いものを出すしかない。思い込みを手放す
  • 自己認識。自分と向き合い、フィードバックを受け入れる
  • 自分の弱さを認め、そんな自分をありのまま認めているか?
  • 自分の弱さを他人に話せているか?
  • 強いリーダーでいるよりオーセンティックである方が勇気が必要
  • オーセンティックであると、覚悟・一貫性を持ち、学び続けることができる
  • リーダー像の答えは人によって違い、絶対的なものは存在しない。思い込みを外し、探求し続ける。人間として成長し続ける
  • オーセンティックであり、フィードバックをすることがエンジニアリングマネージャーに求められる

感想

まず、登壇者の皆さんは話し方がとてもうまかったです。聞き取れないことが一度もありませんでした。声が大きすぎず小さすぎず、速すぎず遅すぎず、ちょうどよかったです。 うまくいかないときに、どうしても手法のせいにしてしまうことはありがちだと思います。また、あり方が重要だと気づけていなかったこともあるあるだと思います。あり方についての情報が今までなかったですが、この会に参加することでとても多くのあり方のヒントを得ることができました。答えは人によって異なるしVUCAな時代で答えはわからないですが、ヒントを使って答えに近いものを見つけて実践していきたいと思います。

【.NET Windows フォームアプリ】 ListViewの文字列と比較したい

ListViewの文字列を、定義した文字列 と比較したかったのですがうまくいかなかった記録です。

結論

listView.Items[i].ToString()ではなく、listView.Items[i].Textを使う。listView.Items[i].ToString()でとれるものは、string型とは異なるもの。 listView.Items[i].Textはstring型でとれるので、string型と比較できる。

過程

最初は、 listView.Items[i].ToString()を使いました。とれるものは "ListViewItem: {内容}" 種類:stringでした。ここで、s="内容"として比較すると、必ずfalseになります。ListViewItem:がついているからだと思い、substringを使ってListViewItem:を文字列から消去しました。s="{内容}"として2つを比較しました。結果は、必ずfalseになります。

ここで、listViewの文字列を取り出すにはlistView.Items[i].Textが使えることを発見し、比較がうまくいったという形です。

最後に

公式リファレンスを読む癖をつけたいと思います。

Goで簡単なWebサーバを作る(net/http)

Goでnet/httpを用いて簡単なWebサーバを作ります。

package main

import (
    "html/template"
    "io/ioutil"
    "log"
    "net/http"
    "regexp"
)

type Page struct {
    Title string
    Body  []byte
}

func (p *Page) save() error {
    filename := p.Title + ".txt"
    return ioutil.WriteFile(filename, p.Body, 0600)
}

func loadPage(title string) (*Page, error) {
    filename := title + ".txt"
    body, err := ioutil.ReadFile(filename)
    if err != nil {
        return nil, err
    }
    return &Page{Title: title, Body: body}, nil
}

var templates = template.Must(template.ParseFiles("edit.html", "view.html"))

func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
    err := templates.ExecuteTemplate(w, tmpl+".html", p)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

func viewHandler(w http.ResponseWriter, r *http.Request, title string) {
    p, err := loadPage(title)
    if err != nil {
        http.Redirect(w, r, "/edit/"+title, http.StatusFound)
        return
    }
    renderTemplate(w, "view", p)
}

func editHandler(w http.ResponseWriter, r *http.Request, title string) {
    p, err := loadPage(title)
    if err != nil {
        p = &Page{Title: title}
    }
    renderTemplate(w, "edit", p)
}

func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
    body := r.FormValue("body")
    p := &Page{Title: title, Body: []byte(body)}
    err := p.save()
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    http.Redirect(w, r, "/view/"+title, http.StatusFound)
}

var validPath = regexp.MustCompile("^/(edit|save|view)/([a-zA-Z0-9]+)$")

func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        m := validPath.FindStringSubmatch(r.URL.Path)
        if m == nil {
            http.NotFound(w, r)
            return
        }
        fn(w, r, m[2])
    }
}
func main() {
    http.HandleFunc("/view/", makeHandler(viewHandler))
    http.HandleFunc("/edit/", makeHandler(editHandler))
    http.HandleFunc("/save/", makeHandler(saveHandler))
    log.Fatal(http.ListenAndServe(":8080", nil))
}

TitleとBodyを持つPage structを作り、そこにloadPageでテキストファイルからTitleとbodyを読み込みます。viewHandler, editHandler, saveHandlerでrenderTemplateを使ってページを生成します。それをHandleFuncで呼び出すという形です。

感想

ここからどうやってポートフォリオにつなげていいのか二の足を踏んでる状態です。何か作ったほうがいいとはわかってはいるのですが…

go言語 並列実行入門

Go言語の並列実行について学んだメモです。

func goroutine(s string, wg *sync.WaitGroup){
  defer wg.Done()
  for i := 0; i < 5; i++{
    fmt.Println(s)
  }
}
func normal (s string){
  for i := 0; i < 5; i++{
    fmt.Println(s)
  }
}
func main(){
  var wg sync.WaitGroup
  wg.Add(1)
  go goroutine("world", &wg)
  normal("hello")
  wg.Wait()
}

並列実行は、time.Sleepしないと並列実行している関数が実行される前にmain関数が終了しプログラムが終わることがある。それを防ぐためにsync.WaitGroupを使う wg.Add(1)をしたら同じ数wg.Done()を呼ばないとエラーになる

goroutineを使って並列実行するが、これらは別のプログラムなのでreturnで値を返せない。そのため、channelを使って同期させる。

func goruoutine1(s []int, c chan int){
  sum := 0
  for _, v := range s{
      sum += v
  }
  c <- sum
}

func main(){
  s := []int{1, 2, 3, 4, 5}
  c := make(chan int)
  go goroutine1(s, c)
  x := <-c
  fmt.Println(x)
}

mainからスライスのsとchanのcを送って、goroutineが走る。x:=<-cの部分でgoroutineのc<-sumが終わるまで止まる。 chanを複数作ってもいいし、1つのchanを複数の関数で使ってもよい。順番はキューの順番になる。

func main(){
    ch := make(chan int, 2)
    ch <- 100
    fmt.Println(len(ch))
    ch <- 200
    fmt.Println(len(ch))
    ch <-300
    fmt.Println(len(ch))
}

はエラーになる。make(chan int, 2)の2はバッファで、chの最大個数を示す。 よって、2で定義したのに3つ目を入れようとしたのでエラーになる。 取り出しているとエラーにならない。取り出すのは

s := <- ch

という記法。

 func main()){
    ch := make(chan int, 2)
    ch <- 100
    fmt.Println(len(ch))
    ch <- 200
    fmt.Println(len(ch))
    close(ch)

    for c := range ch{
        fmt.Println(c)
    }
 }

chanを取り出すときにfor range文を使いたいが、close(ch)を書かずに使うとエラーになる。バッファの個数以上取り出そうとするため。close(ch)を書いていればエラーにならない

 func goruoutine1(s []int, c chan int){
  sum := 0
  for _, v := range s{
      sum += v
  }
  c <- sum
}

func main(){
  s := []int{1, 2, 3, 4, 5}
  c := make(chan int)
  go goroutine1(s, c)
  x := <-c
  fmt.Println(x)
}

これの、計算の途中過程を逐次表示するようにしたいなら、

func goruoutine1(s []int, c chan int){
  sum := 0
  for _, v := range s{
      sum += v
      c <- sum
  }
  close(c)
}
func main(){
  s := []int{1, 2, 3, 4, 5}
  c := make(chan int, len(s))
  go goroutine1(s, c)
  for i := range c{
      fmt.Println(i)
  }
}

close(c)はエラー防止。chanの数をメモリに確保したいならmake(chan int, len(s))とする。

func producer(ch chan int, i int){
    //Something
    ch <- i * 2
}

func consumer(ch chan int, wg *sync.WaitGroup){
    for i := range ch{
        func (){
            defer wg.Done()
            fmt.Println("process", i * 1000)
        }()
    }  
}
func main(){
    var wg sync.WaitGroup
    ch := make(chan int)

    //producer
    for i := 0; i < 10; i++{
        wg.Add(1)
        go producer(ch, i)
    }

    //consumer
    go consumer(ch, &wg)
    wg.Wait     //すべてのWaitGroupが終わるまで待つ
    close(ch)
}

close(ch)がこの位置にあるのは、consumerのforループがまだchanがあると思って待っているため。 それを終わらせるためにclose(ch)をする。

package main

import (
    "fmt"
    "time"
)

func main() {
    tick := time.Tick(100 * time.Millisecond)
    boom := time.After(500 * time.Millisecond)
    //time.tickとtime.Afterはchを返す関数。
    for {
        select {
        case <-tick: //返ってくるchを変数に入れなくてもよい。入れると時刻も出る
            fmt.Println("tick.")
        case <-boom: //返ってくるchを変数に入れなくてもよい。入れると時刻も出る
            fmt.Println("BOOM")
            return
        default:
            fmt.Println("   .")
            time.Sleep(50 * time.Millisecond)
        }
    }
    fmt.Println("#########")
}

for select文は、複数のチャネルを受信してチャネルによって処理を変えられる。selectは、for文の中にあるからずっと回る。for文がないと止まる。終わりたいなら、for文をbreakする 最後のfmt.Printlnはこのままだと実行されない。先にmain関数が終わってしまうため。実行したいなら、

OuterLoop2
 for{
    select{
    case <- tick://返ってくるchを変数に入れなくてもよい。入れると時刻も出る
        fmt.Println("tick.")
    case <-boom://返ってくるchを変数に入れなくてもよい。入れると時刻も出る
        fmt.Println("BOOM")
        break OuterLoop2
    default:
        fmt.Println("   .")
        time.Sleep(50*time.Millisecond)
    }
 }
    fmt.Println("#########")

のようにして、ラベルを使ってfor文の上に出る。名前は何でもいい。

package main

import (
    "fmt"
    "sync"
    "time"
)

 func main() {
    c := make(map[string]int)
    go func() {
        for i := 0; i < 10; i++ {
            c["key"] += 1
        }
    }()
    go func() {
        for i := 0; i < 10; i++ {
            c["key"] += 1
        }
    }()
    time.Sleep(1 * time.Second)
    fmt.Println(c, c["key"])
 }

このコードだと、成功したりエラーを出したりする。両方のゴルーチンがcへの書き込みをしており、cへの書き込みが同時になるとエラーになる。よって、sync, mutexを使う。

package main

import (
    "fmt"
    "sync"
    "time"
)
type Counter struct {
    v   map[string]int
    mux sync.Mutex
}

func (c *Counter) Inc(key string) {
    c.mux.Lock()
    defer c.mux.Unlock()
    c.v[key]++
}

func (c *Counter) Value(key string) int {
    c.mux.Lock()
    defer c.mux.Unlock()
    return c.v[key]
}
func main() {
    c := Counter{v: make(map[string]int)}
    go func() {
        for i := 0; i < 10; i++ {
            //c["key"] += 1
            c.Inc("Key")
        }
    }()
    go func() {
        for i := 0; i < 10; i++ {
            //c["key"] += 1
            c.Inc("Key")
        }
    }()
    time.Sleep(1 * time.Second)
    fmt.Println(c, c.Value("Key"))
}

転職透明化ラボ-ここが残念だよ採用企業&応募者 カジュアル面談編 参加レポート

5/14に開催された、転職透明化ラボ-ここが残念だよ採用企業&応募者 カジュアル面談編に参加してきました。 詳細はここのページで。 rtlabo.connpass.com

内容メモ

  • カジュアル面談とは、会社を知ってもらうためのもの。選考ではない。いわゆるイケてる企業は理解しているが、そうでない企業もある。理解ある企業なら事前準備は会社を軽く調べておくこと、そうでないなら経歴書を一応持っていた方が良い。
  • 求職者に会って話し、会社を知ってもらい、ミスマッチでないことを確認する場でもある。ミスマッチは会社側も求職者側も不幸になる。ミスマッチなら、この時点で切る。
  • カジュアル面談後に面接に進み、カジュアル面談の内容が面接官に伝わってない場合があるので、自分からカジュアル面談で話した内容を話して認識があっているか確認する。カジュアル面談の内容が面接官に伝わっていないことは、求職者側からは会社に危険信号が点る(人事とエンジニアの距離)。
  • ベンチャー企業の人事は、少ない人数で回しており忙しいので応募を見逃すこともある。

感想

 採用担当者と求職者が参加したイベントでした。求職者側は選考フローがどうなっているのか知りたくて、採用担当者側は選考の仕組み自体に興味があり、どちらも満たせていたのではないかと思います。カジュアル面談で会社と求職者のマッチングを確認するのはコストがかかりますが、会社側は面接をするよりコストが低いなら小さな失敗で済みますし、求職者側は面接の前に質問ができ、よく会社を知ることでモチベーションが上がることもあるでしょうしミスマッチと言われればこれからの努力の方向性を考えるきっかけをもらえるのではないかと思います。カジュアル面談は、オープンソースなどのエンジニア業界全体を良くしていこうというエンジニア文化が表れているものでもあると思います。

 採用担当者の方がよく言っていたのが、求職者に会ってみないとわからないということでした。その人が経験してきたものによって考え方・文化・熱意・行動力などが異なります。それらは書類ではわからず、実際に会ってみないとわからないです。会社に合っているかどうか、確認してお互いに不幸にならないようにしようということでした。

 懇親会ではストラップの色で求職者なのか採用担当者なのか分かるようにしていたため、お互いにスムーズに会話や質問ができていたように思います。良い試みだったと思いました。採用担当のエンジニアではあるが、転職活動をしている人はどっちになるのだろうか、と思いました。

ゲームセンターを楽しむ技術(仮)の原稿募集

合同誌で有名なonestopシリーズの編集長おやかたさん協力の下、ゲームセンターに関する合同同人誌を書きます。合同誌とは、一人で本を書くのではなく、複数人の書いた原稿をまとめて一つの本としたものです。その原稿を募集します。よくやっているゲームセンターのゲーム、楽しみ方をぜひ書いて下さい。次回のコミティア129での頒布を目指しています。落ちたら・・・委託します。

なぜ合同誌?

自分の文章を発信したいと思った時、思いつくのはSNSです。しかし、SNSよりも本であった方が多くの人に届く可能性が高いです。ですが、本にするとなると内容も量も求められることになります。1人だと大変ですが、複数人で本を書くことを考えましょう。内容の面では、人は今までの背景によって持っている知識・経験が違います。その人がうまく書けると考えて書いた内容ばかり書くことで、内容の濃い本となります。量の面では、例えば100ページの本を書くとします。1人が4ページしか書けなくても、25人いれば100ページの本が書けます。

今回はゲームセンターに関する内容です。私はDDRプレイヤーのエンジョイ勢なので、他のゲームジャンルについてやガチ勢が心がけていること・上達法はわかりません。ぜひ力を貸してください。書いていただける方はごまなつ まで連絡ください。

なぜこの本を書こうと思ったのか

ゲームセンターは経営が苦しくなっているようで、閉店が続いています。このままでは客が少なくなり、ゲームセンターがなくなってしまうと思います。今の状況を何とかしたいです。 そのためには、ゲームセンターに来たことがない人や昔行っていた人に来てほしいです。そのための、ゲームセンターの楽しさ・楽しみ方、ゲームセンターの現状、あるいは歴史的経緯をまとめた本を作りたいと思ったからです。ゲームセンターに行かない人がわからない部分をこの本で分かるようにしたい。ここが一番大きいところです。 タイトルは「ゲームセンターを楽しむ技術」を仮で考えています。

目次案

あくまでも案ですので、内容追加などどんどん提案をください。楽しみ方と上達法を分けていますが、各ゲームジャンルごとに楽しみ方と上達法を書いていく方がいいのか迷ってます。

ゲームセンターの歴史

  • 昔のゲームセンターの面白かったところ
  • ゲームセンターのイメージと今のゲームセンターの違い
  • ゲームセンターの現状

ゲームセンターの楽しみ方

ガチ勢とエンジョイ勢の楽しみ方

  • 上達法(目標設定とPDCAなど)
  • モチベーションの維持方法
  • エンジョイ勢としての楽しみ方
  • コミュニティ

ゲームセンターでのふるまい方

  • 連コなどのマナー
  • コミュニティなど人間関係
  • マナーが悪い人への対処法

その他

  • あなたの知らないゲームセンターの楽しみ方 ‐ 自分が好きなゲームセンター、良いゲームセンターの観点、各ゲーム好き向けのゲームセンター
  • ゲームセンターじゃないとできない体験とは
  • ゲームセンターに行くようになって経験した楽しいこと、変わったこと
  • 本当にゲームセンターはお金がかかるのか?(ほかの趣味と比較して)

執筆・配布スケジュール

  • 募集・環境構築終了 6月上旬
  • 章目次確定:6月中旬
  • 本文初稿:6月末日
  • レビュー&追記:7月末日
  • 入稿:8月上旬 発行 コミティア

を大枠なスケジュールとしたいです。(多少前後します)

形式

Re:View+Github+CI出力のpdfを基本。 当該リポジトリに招待しますので、GitIDを連絡ください。https://github.com/onestop-techbook/GameCenter 招待なくてもPRは上げられると思います。セルフマージOKなので、参加しておいたほうが便利かも、くらいのはなしです。

MD・プレーンテキスト、Word等での提出もOK。こちらでコンバートします。

想定ページ数:100ページ前後(上限なし)

原稿料

メイン記事 5000円/人+打ち上げご招待(ページ数によらず。ただし、3ページ程度以上を想定。(1ページ1000~1200文字相当)
コラムのみ:打ち上げご招待

原稿料支払いタイミング

発行後。(Amazonギフト券または打ち上げ時現金) 完成した本:3冊進呈。

免責事項

  • 実際の案件・事象等について触れる場合、例示等に使う場合は、各章・コラムの著者の責任において情報の公開・秘匿範囲を定めてください。編集者、その他著者は、その点については一切責任を負いません。
  • それぞれの執筆分担分における著作権は、著者に帰属します。
  • その他については、適宜相談の上定めるものとします。
  • 印刷費の著者負担はなし

同人誌発行主体

ごまなつ
想定印刷部数 未定
落ちた場合も委託予定

Gitリポジトリ

github.com

キーボードの話で登壇してきた話

今更ですが、4/2に「あなたの知らないキーボードの世界」というタイトルでサポーターズcolabで登壇しました。資料はこちらです。

speakerdeck.com

なぜこの登壇をしてみようと思ったのか

エンジニアの方は、コードを書くのでキーボードを触っている時間が長いです。長く触れている椅子にはこだわる方が多いのに、キーボードにこだわる方は少ないです。さらに、PC操作をするのであればキーボードだけでなく、マウスに触れています。つまり、エンジニアでない方でもキーボードとマウスにこだわる意味はあります。今回は、キーボードについて話してみようと思いました。

反省

資料の話ではないですが、まだ話慣れていないなと感じました。聴衆の方がずっと黙って聞いてくださったのですが、あまりに反応がないためだんだん不安になっていきました。後半のキーバインド設定の話は、説明がうまくできませんでした。スライドにコードのようなものを載せる際に注意することを確認しておくべきでした。この2つによって、後半がしどろもどろになってしまいました。最後までうまく話しきれるように努力していきたいと思います。

発表内容に関しては、うまく伝わっていたかどうかはわからないですが伝えたいことを伝えられるように努力していきたいと思います。