「エンジニアに向いている人」はGitHub user内にどれぐらいいるのか

## 注意
- この記事はとあるツイートを話題にしていますが、筆者にツイート内容、およびツイートされた方を蔑む意図は一切ありません。
- 筆者は統計、およびプログラミングに関してはまだまだひよっこです。したがって誤った見解や拙いコードを書いている可能性がありますが、お気づきの際は是非コメントにてご指摘ください。

## 背景
あけましておめでとうございます！
正月休みもあけ仕事も始まりましたが、みなさまいかがお過ごしでしょうか。

さて、正月早々、とあるツイートが反響を呼びました。

> プログラミングスクール通ってるかどうかとかどうでもよくて、この年末年始にコード全く書いていない人はエンジニア向いてないんじゃないですかね、それぐらい好奇心が必要な職業だと思うけど

賛否両論あったこのツイートですが、内容はさておき、私はあることが気にかかりました。

**「果たしてこの年末年始、コードを書いた人はどのぐらいいるのだろうか」**

本記事では上記の疑問を検証していこうと思います。

## レギュレーション
もちろんすべてのエンジニアに「この年末年始、コード書きましたか？」ときいてまわるわけにはいきません。そこで本記事では**以下のレギュレーションに基づいて**「年末年始にコードを書いた人（＝エンジニアに向いている人?）」を判定していこうと思います。

1. 「**コードを書いた日は必ずgithubに草が生えている**」と考える。すなわち「年末年始にコードを書いた人」とは「**年末年始にgithubに草が生えている人**」とする。また現状デフォルトブランチにマージされておらず未反映の分は考慮しない。
2. **年末年始は12/30 ~ 1/3 の5日間**と定義し、**この間に1度でもcontributeした人の割合**を測定する。
3. **githubのアカウントは1人１つ**とし、アカウントは必ず使われているものとする（すなわち未使用垢やサブ垢などは考えない）

## 方針
上記のレギュレーションにもとづき、より具体的な方針を決めていきます。

### サンプル数はどのぐらい取れば良いか
githubを利用しているdeveloperの数は2020年時点で**5600万人を超えており**[[1]](https://octoverse.github.com/)、全員を調べるにはかなりの労力がかかります。
そこで本記事では「**ある程度正しい結果**」を得ることを目標におき、githubのuserの中から**一部をサンプリングして**、サンプルから得られた結果を全体のものとすることにしました。

では、**一体いくつのサンプルをとればその結果は「ある程度たしかである」といえるのでしょうか？**
実は統計的には、母集団が100万人を超えていたとしても、**384人分のデータ**があれば、**95%信頼できるデータ**がとれてしまうのです。[[2]](https://jp.surveymonkey.com/mp/sample-size/)
本記事では**400人分のgithub usersのデータ**をサンプリングして使うこととしました。

### 実装方針

#### 1. github APIでusers一覧を取得
[GithubのUsers API](https://docs.github.com/en/free-pro-team@latest/rest/reference/users)を使って, githubのuser一覧を取得します。
Github Users APIではuserは**最大100件ずつの取得しかできない**ため、**100件ずつ取得するリクエストを計4回投げます**
また、**idは17027045**（筆者のgithubアカウントにふられたid）**から取得し**、これを「**無作為抽出されたデータである**」と考えます。(超初期のgithubアカウントはgithub開発者のものや、すでに使われていないものが多いのではないかと考えたため)

#### 2. 各userのcontributionsを解析 
githubのcontributionのデータは以下のurlにアクセスすると取得することができます。

``` url
https://github.com/users/${user}/contributions
```

上記で取得できるページの、いわゆる「草」の部分を**x-ray**というスクレイピング用のライブラリを用いて解析することにしました。[[2]](https://qiita.com/RyotaMurohoshi/items/aa5b570f906386d6032c)


## 実装
実装方針に基づき、`node.js`で以下のようなコードを作成しました。
http requestを投げる際に`axios`を、日付の比較の際に`day.js`を、スクレイピングの際に`x-ray`を使用しています。

``` node.js
main()

async function main(){
    const myGitHubId=17027045
    //自分のgithubIdから400人分のgithub usersを取得
    users = await getGitHubUsers(myGitHubId)
    //400人中年末年始にコードを書いていた人の数を集計
    const appropriateEngineerNum = await getAppropriateEngineerNum(users)
    //結果
    console.log(`エンジニアに向いている人は${users.length}人中, ${appropriateEngineerNum}人です`)
}

//since番目から400人分のgithub usersを取得する
async function getGitHubUsers(since){
    const axiosBase = require('axios');
    const axios = axiosBase.create({
    baseURL: 'https://api.github.com',
    headers: {
        'Accept': 'application/vnd.github.v3+json',
    },
    responseType: 'json'  
    })

    const users = []
    for(let i = 1; i <= 4; i++){
            response = await axios.get('/users', {params: {since: since + i*100, per_page: 100}})
            users.push(...response.data.map(user => user.login))
    }
    return users
}

//引数のusersのうち、年末年始にコードを書いていた人数を算出する
async function getAppropriateEngineerNum(users){
    const Xray = require('x-ray')
    const x = Xray()
    let appropriateEngineerNum = 0
    for(user of users){
        const contributionUrl = `https://github.com/users/${user}/contributions`
        const contributions = await x(contributionUrl, 'rect', [ { count: '@data-count', date: '@data-date' }])
        const newyearHolidaysContributions = contributions.filter((contribution) => {
            return isNewyearHoliday(contribution.date) && contribution.count > 0
        })
        if(newyearHolidaysContributions.length > 0){
            appropriateEngineerNum ++
        }
    }
    return appropriateEngineerNum
}

//引数の日にちが年末年始かを判定する
function isNewyearHoliday(dateStr){
    const dayjs = require('dayjs')
    contributionDate = dayjs(dateStr)
    return dayjs('2020-12-29').isBefore(contributionDate) && dayjs('2021-01-04').isAfter(contributionDate)
}
```
## 結果
![スクリーンショット 2021-01-06 22.28.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223014/71e81348-ae0c-c4e4-a811-b0420462e05c.png)
ということで、「年末年始にコードを書いていた人」は **全体の2%**という結果になりました。

## 補足
github profileのcotribution設定からは、private contributionの反映をオフにすることができます。したがって、この設定がオフになっており、かつプライベートリポジトリへのcontributionをした人はカウントされていません。

## 余談 ~「エンジニアに向いている人とは」~
最後に余談ではありますが、「どんな人がエンジニアにむいているのか」について私の見解をお話しします。

ツイッターやブログなどをみていると、**「〇〇な人はエンジニアにむいていない」**という意見が盛んに発信され、時に反発をうけているのを目にします。
私自身はこのどれもが「エンジニアに向いていない人」の条件となるとは思えません。なぜならまわりを見渡してみても「**その条件を満たしてなくてもエンジニアとして働き、かつすごい技術を持っている方はたくさんいる**」からです。（例えば上記の例に関しても、年末年始にコードを書いていなくともすごい技術力を持ったエンジニアはたくさんいます）。これらの意見を鵜呑みにし、自信を失ってしまうのはすごくもったいないことだと思います。

しかしながらその一方で**「〇〇な人がエンジニアに向いていない」**という意見は**「自分はエンジニアである以上〇〇だけは譲れない」**というプライドをもっていることの裏返しだとも思うのです。またそこに対して「それは違う」と感じてしまうのも自分の中でまた別のプライドがある証ではないでしょうか。

そして私はその**エンジニアとしてのプライドを持っている人**こそが「エンジニアに向いている人」だと思います。

私自身はエンジニアとして「**新しい技術に興味をもち**」, 「**コードを書くことを楽しむ気持ちを忘れない**」ことをプライドとしてもっています。2021年もこの気持ちを大切に日々鍛錬していきたいものです。

## 参考文献
[1] [he 2020 State of the OCTO—VERSE](https://octoverse.github.com/)
[2] [x-rayを使ってgithubの草の情報を取得する](https://qiita.com/RyotaMurohoshi/items/aa5b570f906386d6032c)
[3] [SurvayMonkey ~アンケートの標本サイズ~](https://jp.surveymonkey.com/mp/sample-size/)