sato's note

技術メモ

【要約】マネジメントの基本 from エンジニアのためのマネジメントキャリアパス

上司に何を求めるか

1対1のミーティング

目的は2つ

1. 上司との間に人間的な「つながり」を作ること。

「部下にも私生活がある1個の人間」として扱う

2.「要検討事項について上司と1対1で話し合う定期的な場を設けること」

上司と責任を分かち合いたいテーマを掲げ、自身でお膳立てする

フィードバックと指導

  • 部下を褒める時は人前で、叱る時は1対1
  • ただし、人前で褒めらたくない人もいる
  • FBはその場で即、が効果的
  • 会社における地位や立場についての助言をもらう

レーニングとキャリアアップ

  • 昇進には直属の上司の後押しが必要不可欠
  • どんな方面に照準を定めるべきか上司からアドバイスをもらう

管理のされ方

上司との関係づくりも上司任せにしない事が、職場生活、キャリアにも重要な姿勢。

自分が何を望んでいるのかをじっくり考える

何が自分を幸せにするのかは自分自身が負っている。

自分に対する責任は自分で負う

  • 参加したいプロジェクトがあれば上司に頼む
  • 伸ばすべき能力に関する助言など、FBは積極的に求める
  • 昇給を望むなら意思表示を、昇進を望むなら何が必要かを探る
  • 表明する事で、上司が公平さをもっていなくても、自分の立場を認識できる

上司も人の子

  • ストレスを抱え、欠点もある
  • 馬鹿げた事や、不公平な事もある
  • 上司の仕事は部下のご機嫌取りではない。
  • 助言を仰ぐのは相手への敬意と信頼を示す絶好の手法

上司は賢く選ぶ

上司次第でキャリアは大きく差がでる 有能な上司は社内での駆け引きの仕方を心得ている。

引用

O'Reilly Japan - エンジニアのためのマネジメントキャリアパス

Golang 制御文

if

基本

  • 条件をかっこで囲む必要はない
  • 三項演算子はサポートされていない
if x%2 == 0 {
   fmt.Println(x, "is even")
}

変数の初期化

ifステートメント中に変数の初期化ができる。 スコープはifブロックの中だけになる。

if num := getnumber(); num < 0 {
    fmt.Println(num, "is negative")
} else if num < 10 {
    fmt.Println(num, "has only one digit")
} else {
    fmt.Println(num, "has multiple digits")
}

switch

基本

Goではbreakが必要ない。

switch i {
case 0:
    fmt.Print("zero...")
case 1:
    fmt.Print("one...")
case 2:
    fmt.Print("two...")
default:
    fmt.Print("no match...")
}

複数の式

switch city {
case "Tokyo", "Kanagawa", "Chiba", "Saitama", "Tochigi", "Ibaraki":
    fmt.Print("Kanto")
case "Aomori", "Akita", "Iwate", "Yamagata", "Miyagi", "Fukushima":
    fmt.Print("Tohoku")
}

条件の省略

true値との比較に近い

switch {
case r > 0.1:
    fmt.Println("Common case, 90% of the time")
default:
    fmt.Println("10% of the time")
}

forループ

基本

()が必要ない

for i := 1; i <= 100; i++ {
    sum += i
}

条件、前後のステートメントは省略可能

while キーワードはないが、whileのような使い勝手となる。

for num != 5 {
    num = rand.Int63n(15)
 fmt.Println(num)
}
for {
    if num = rand.Int63n(15);num == 5{
        break
    }
 fmt.Println(num)
}

defer 関数

defer ステートメントが含まれる関数が終了するまで、関数の実行が延期される

for i := 1; i <= 4; i++ {
    defer fmt.Println("deferred", -i)
    fmt.Println("regular", i)
}
regular 1
regular 2
regular 3
regular 4
deferred -4
deferred -3
deferred -2
deferred -1

defer 関数の一般的なユース ケースは、ファイルの使用が終了したときにファイルを閉じること

func main() {
    f, err := os.Create("notes.txt")
    if err != nil {
        return
    }
    defer f.Close()

    if _, err = io.WriteString(f, "Learning Go!"); err != nil {
        return
    }

    f.Sync()
}

panic 関数

プログラムを強制的にパニックにさせる。 Javaでいうthrow Exception

  1. すべての遅延関数呼び出しは、正常に実行される
  2. すべての関数から戻るまで、プロセスでスタックが続行される。
  3. その後、プログラムはログ メッセージを出力してクラッシュします。
panic("something went wrong")

recover 関数

recover() を使用すると、パニックの後で制御を取り戻すことができる 他の言語で言う、try/catch ブロックに近い

if r := recover(); r != nil {
    fmt.Println("Recovered", r)
}

【要約】チームで意思決定プロセスを改善する5つのステップと4つの手法

概要

https://slack.com/intl/ja-jp/blog/collaboration/decisionmaking-process-team

チームで意思決定する際に役立つ手法の要約

優れた意思決定プロセスの条件

さまざまな人に入ってもらう。

多様性に富んだグループでは色々な見方が提示されるため、良い決定を下しやすい傾向にある。

意思決定できる状態で会議する。

情報共有のための会議と決定を下すための会議を区別する。

組織が意思決定のため会議を開いても、質問やディスカッション、説明といった情報共有を挟むと脇道にそれてしまう為。

意思決定プロセスを速めるには、鍵となる情報を事前にチームに共有しておき、アイデアや提案したい解決策などを用意して会議に臨むようお願いしておく。

肩書きは脇に置いておく

すべての人が気軽にアイデアや意見を出せるようにするには、役割や経験に関係なく全員の意見を平等に評価することが大切。そのために話し合いの基本ルールを設ける。

以下は一例

  • ディスカッションを始める前に、すべてのメンバーが各自のアイデアを共有しておく
  • 立場が上のメンバーは場を独占したりほかのメンバーに影響を与えたりしないよう、最後に話す
  • 個人の能力や経験にかかわらず、出されたアイデアを平等に扱う
  • 話を遮らずにしっかり聞く

意思決定プロセス改善のための 5 ステップ

  1. 解決策ではなく問題を明らかにする
  2. クリティカルシンキングを促進する
  3. 意見の不一致を想定・考慮する
  4. 現実的な締め切りを設定する
  5. 小さな決定は気にしない

解決策ではなく問題を明らかにする

問題を理解する枠組みを狭め過ぎてしまうと、ディスカッションが始まる前からその内容を限定してしまう。 問題をはっきりさせると同時に、解決策となりうるものに対しては広く考える

顧客満足度アンケートを変えたほうがいいか?」

「顧客のニーズをもっと理解するにはどうしたらいいか?」

クリティカルシンキングを促進する

人間は互いの意見に同意したがる傾向にあるため、最初に口を開く人(もしくは早い段階で支持を得た最初のアイデア)がグループでの決定に最も大きな影響を与える。言い換えれば、最初に提示された解決策は、たとえ一番良いものでなくても選ばれやすい。

これを避ける為にチームリーダーは「どうしてそう思うのですか?」や「その考え、または仮説を支持する証拠はありますか?」といった理解を深めるような質問をする

意見の不一致を想定・考慮する

Google CEOが掲げた優先事項

「『合意文化』を抑え、意思決定にアジリティ(機敏性)と効率性を取り戻すこと」

「すべての会議には必ず明確な意思決定者がいなければならない。意思決定者がいなければ決定が下されることもないため、会議を開くべきではありません」。

意思決定プロセスにおいて、決定を下すのがあまりにも遅いと、悪い決定をするリスクを減らすことができる一方、チャンスを逃してしまいかねない。

以下のエラーについて、それぞれ影響を比較する

  • オミッションエラー (機会を逃すこと)
  • コミッションエラー (悪い決定を下して会社に深刻な損失を与えること)

Google では合意を目指すのをやめてから、以前よりもアイデアを実行に移せるようになり、その結果わずか 90 日間で Google+ の機能を 100 以上リリースできました。

意思決定者は最終的に決定を下すが、反対意見を持つメンバーの懸念事項やアイデアを評価する必要がある

現実的な締め切りを設定する

達成可能な目標を設定することが大切

「なんとなく」ではなく、似ているプロジェクトにかかった時間に基づいて所要時間を算出する

比較対象となるプロジェクトが見つからない場合は 2 つのシナリオを用意する。

  • 最良のシナリオ
  • うまくいかない可能性のあるすべてのことを書き出した最悪のシナリオ。

実際の結果はその中間あたりになる

小さな決定は気にしない

すべての決定を詳細に検討する必要はない。

組織は大切な決定に時間を割くのではなく、あまり重要でない決定に必要以上の時間をかけている。

Amazon の CEO、Jeff Bezos 氏はそのために、すべての決定を 2 つのカテゴリーに分類している。

  • 変更不可能な決定
  • 変更可能な決定

Bezos 氏は、「変更可能な決定」 の事柄はなるべく早く決定すべきだと主張している。もし失敗しても、チームはそれから大切なことを学び、未来の決定に役立つ情報を得ることができる為

グループで意思決定するための4つの手法

  1. 先入観や決めつけを乗り越える
  2. 包括的なディスカッションをする
  3. 責任を割り当てる
  4. 決定を行動に移す

先入観や決めつけを乗り越える

「推論のはしご」:すべてのメンバーが自分の信じていることや推論に疑問を持つ

包括的なディスカッションをする

「ノミナルグループ手法」:チームのそれぞれが自分のアイデアや提案したい解決策を書き出すことで、メンバー全員が平等に参加しクリティカルシンキングができるようにする方法。書き出されたアイデアはグループで共有して話し合い、投票によってランクづけされる。これは、特定のメンバーがほかの人たちより多く話す傾向にあったり、勤続年数の少ない社員が意見を述べるのをためらったりする場合など、グループ内で不均等なパワーバランスが存在する場合に役立つ。

責任を割り当てる

「RAPID モデル」:意思決定プロセスのどの部分を誰が担当すべきかを明らかにする メンバーは次の 5 つの役割に分けられる

  • 推薦(Recommend)
  • 賛同(Agree)
  • 実行(Perform)
  • 情報提供(Input)
  • 決定(Decide)

決定を行動に移す

「RACI チャート」:プロジェクトをタスクに落とし込み、各タスクにおける役割を関係者 1 人 1 人に割り当てる。役割には次の 4 つがある

  • 実行責任者(Responsible)
  • 説明責任者(Accountable)
  • 相談相手(Consulted)
  • 報告相手(Informed)

視覚的に理解できる表によって、誰が何の仕事を担っているのかがすぐにわかり、仕事量が均等に分配されていることがチームにも伝わる。

Golang パッケージ

パッケージ

パッケージの作成

ディレクトリ構成

src/
  foo/
    message.go

パッケージソース

message.go

package foo

var internalVar = "パッケージ内からしか読めません"
var externalVar = "パッケージ外から読めます"

func internalMessage() string {
    return "パッケージ内からのみ呼べる"
}

func Message() string {
    return "パッケージ外からも呼べる"
}

public または private キーワードは用意されていない。 プライベートにするには名前の先頭を小文字に。 パブリックにするには、名前の先頭を大文字に。

ビルドの実行

$ go build

モジュールの作成

$ go mod init github.com/myuser/foo
src/
  foo/
    go.mod
    message.go

ローカル パッケージ の参照

準備

go.modの作成

go mod init mypackage

go.modの編集

# go.mod
require github.com/myuser/foo v0.0.0
replace github.com/myuser/foo =>  path/to/foo

パッケージの使用

package main

import "github.com/myuser/foo"

func main() {
    println(foo.Message())
}

外部 (サードパーティ) パッケージの参照

package main

import (
    "rsc.io/quote"
)

func main() {
    println(quote.Hello())
}

go.mod

module helloworld

go 1.14

require (
    rsc.io/quote v1.5.2
)

Golang 関数

関数定義

構文

func name(parameters) (results) {
    body-content
}

package main

func sum(x int, y int) int {
    return x + y
}

func main(){
    sum := sum(2, 3)
    println("Sum:", sum)
}

実行結果

$ go run main.go
$ 5

関数の戻り値に名前をつける

func sum(x int, y int)(result int) {
   result = x + y
   return
}

複数の値を返す

func calc(x int, y int)(sum int, mul int) {
   result = x + y
   mul = x * y
   return
}

ポインター渡し

package main

func main() {
    foo := 5
    update(&foo)
    println(foo)
}

func update(value *int) {
    *value = "10"
}

実行結果

$ go run main.go
$ 10

Golang 変数

変数の宣言

単数

var firstName string

複数一括

var (
    firstName, lastName string
    age int
)

初期化

var (
    firstName string = "John"
    lastName  = "Doe" // 型推定
    age       int    = 32
)

定数

const (
    StatusOK              = 0
    StatusConnectionReset = 1
    StatusOtherError      = 2
)```

# 注意点
変数も定数も宣言して、使用しないとエラーとなる

MySQL 再帰クエリで階層構造のデータを一度に取得

準備

テーブル定義

CREATE TABLE `categories` (
  `id` int(10) unsigned NOT NULL,
  `name` varchar(45) NOT NULL,
  `parent_id` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  FOREIGN KEY (`parent_id`) REFERENCES `categories` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB;

検証データの挿入

INSERT INTO `categories`
(`id`, `name`, `parent_id`)
VALUES
(1, "Fashion", NULL),
(2, "Mens", 1),
(3, "Ladies", 1),
(4, "Tops", 2),
(5, "Shirts", 4),
(6, "Food", NULL),
(7, "Water", 6),
(8, "Meet", 6),
(9, "Sweets", 6)
;

データの取得

構文

with recursive R as (
  select anchor_data -- 取得1行目ここが起点となる
  union [all]
  select recursive_part -- 取得2行目以降、ここが再帰となる
  from R, ...
)
select ... -- 実行結果の取得

実行

ついでに1行目のクエリからの階層深度も取得できる形に。

WITH recursive child(depth, id, parent, name) AS(
    SELECT
        0,
        id,
        parent_id,
        name
    FROM
        categories
    WHERE
        categories.id = 1
    UNION ALL
    SELECT
        child.depth + 1,
        categories.id,
        categories.parent_id,
        categories.name
    FROM
        categories,
        child
    WHERE
        categories.parent_id = child.id
)
SELECT
    depth,
    id,
    parent,
    name
FROM
    child
ORDER BY
    depth
;

結果

+-------+------+--------+---------+
| depth | id   | parent | name    |
+-------+------+--------+---------+
|     0 |    1 |   NULL | Fashion |
|     1 |    3 |      1 | Ladies  |
|     1 |    2 |      1 | Mens    |
|     2 |    4 |      2 | Tops    |
|     3 |    5 |      4 | Shirts  |
+-------+------+--------+---------+