VOYAGE GROUPで利用されているプログラミング言語のトレンドを調べてみた

こんにちは。株式会社ZucksでZucks Ad Networkの開発に携わっている南大津です。

エンジニア採用の募集事項に「業務で使われている言語」がよくありますが、どの言語がどれくらい使われているかは、入社前にはなかなか把握し難い部分ではないでしょうか。
そこで今回は、VOYAGE GROUPで開発に利用されているプログラミング言語のトレンドについて調べてみたので、ご紹介できればと思います。

ソースコード管理について

VOYAGE GROUPでは多くの子会社、サービスが存在していますが、そのほとんどのソースコードはvoyagegroupという1つのGitHub Organizationアカウントで管理されており、現在約400個のリポジトリが作成されています。

私が入社した2009年頃には、ソースコード管理といえばSubversionがメインでした。
その後徐々にGitHubでソースコード管理を行うサービスが増えていったのですが、当初は主に子会社毎にOrganizationアカウントを作成して利用していました。子会社毎にOrganizationアカウントが分かれていると、グループ会社間で知見が広まりづらかったり、アカウント管理を個別に行う必要があったりするため、1つのOrganizationアカウントに統一する流れが起き、今の形に落ち着いています。

今回はこのvoyagegroup Organizationに登録されているソースコードから、VOYAGE GROUPにおけるプログラミング言語の利用状況について調査してみます。*1

最近のトレンドを調べてみる

GitHubにはリポジトリで利用されている言語の割合(バイト数による算出)を表示してくれる便利機能が存在しています。

f:id:smileeeen:20170515194305p:plain

上記のようにリポジトリのステータスバーに表示されているもので、クリックをすると言語ごとの割合が確認できるようになっています。

GitHubでこの情報の算出に使われているライブラリがLinguistという名前で公開されているので、こちらのコマンドラインツールを使ってみます。

github.com

$ git-linguist --help
    Linguist v5.0.10
    Detect language type and determine language breakdown for a given Git repository.

    Usage:
    git-linguist [OPTIONS] stats|breakdown|dump-cache|clear|disable"
    -f, --force                      Force a full rescan
    -c, --commit=COMMIT              Commit to index

git管理されているディレクトリ上で、 git-linguist stats コマンドに特定のコミットハッシュ値を渡すとその時点における言語別容量を返却してくれます。
現在と過去のある時点での言語別容量を比較すれば、最近よく使われている言語の傾向が見えないかなと考え、2017年になってからのvoyagegroup Orgnizationにおける言語別容量の増減を調べてみました。

GitHub APIの呼び出しにはphp-github-apiを利用させていただきました。

github.com

調査に利用したソースコードは下記になります。*2

<?php

require_once 'vendor/autoload.php';

$orgName        = 'voyagegroup';
$diffTargetDate = '2017-01-01T00:00:00Z';
$tmpDir         = '/tmp/techlog';

$client = new Github\Client();
$client->authenticate('【SET ACCESS TOKEN】', null, Github\Client::AUTH_HTTP_TOKEN);

$paginator = new Github\ResultPager($client);
$orgApi    = $client->api('organization');
$repoApi   = $client->api('repo');

$allRepoLangsDiff = [];

foreach ($paginator->fetchAll($orgApi, 'repositories', [$orgName]) as $repo) {
    if (!shouldAggregateRepo($repo)) {
        continue;
    }

    $repoName = $repo['name'];

    $headCommitHash = getLatestCommitHash($repoApi, $orgName, $repoName);
    $pastCommitHash = getLatestCommitHash($repoApi, $orgName, $repoName, ['until' => $diffTargetDate]);

    if ($headCommitHash === $pastCommitHash) {
        continue;
    }

    exec(sprintf(
        'cd %s && git clone --single-branch -n git@github.com:%s/%s.git',
        $tmpDir,
        $orgName,
        $repoName
    ));

    $repoLangsDiff = getRepoLangs($tmpDir, $repoName, $headCommitHash);

    if ($pastCommitHash) {
        $negPastRepoLangs = array_map(function ($v) {
            return -$v;
        }, getRepoLangs($tmpDir, $repoName, $pastCommitHash));

        $repoLangsDiff = sumRepoLangs($repoLangsDiff, $negPastRepoLangs);
    }

    exec(sprintf('rm -r %s/%s', $tmpDir, $repoName));

    $allRepoLangsDiff = sumRepoLangs($allRepoLangsDiff, $repoLangsDiff);
}

function shouldAggregateRepo($repo)
{
    return $repo['size'] > 0
        && !$repo['fork']
        && preg_match('/\A[-.\w]+\z/', $repo['name']) === 1;
}

function getLatestCommitHash($repoApi, $orgName, $repoName, $condition = [])
{
    $commits = $repoApi->commits()->all($orgName, $repoName, $condition);
    return $commits ? $commits[0]['sha'] : '';
}

function getRepoLangs($tmpDir, $repoName, $commitHash)
{
    exec(
        sprintf(
            'cd %s/%s && git-linguist -c %s stats',
            $tmpDir,
            $repoName,
            $commitHash
        ),
        $linguistOutput
    );
    return $linguistOutput ? json_decode($linguistOutput[0], true) : [];
}

function sumRepoLangs($langs, $addLangs)
{
    return array_map(function ($row) {
        return array_sum((array)$row);
    }, array_merge_recursive($langs, $addLangs));
}

// check $allRepoLangsDiff

結果は以下のようになりました。*3

増加している言語
rank 言語 容量変化(MB)
1 Jupyter Notebook 16.2
2 Python 4.0
3 C# 3.5
4 C 2.4
5 C++ 1.3
6 Ruby 1.0
7 Objective-C 0.7
8 CoffeeScript 0.5
9 Go 0.4
10 Scala 0.3
11 ShaderLab 0.3
12 Smarty 0.3
13 TypeScript 0.3
14 Shell 0.3
15 Makefile 0.2
16 HCL 0.2
17 Puppet 0.1

1位のJupyter Notebookに関してはZucks Ad Networkの解析チームで活用しており、純粋なコード量が多いというよりは、Base64エンコードされた画像ファイルもソースコードの容量として含まれている場合があるため、割合が多くなっていると考えられます。
最近ではPythonが人気のようですね。
3位にランクインしたC#はVR室で開発しているUnity製のアプリがメインでした。

減少している言語
rank 言語 容量変化(MB)
1 PHP -8.2
2 HTML -5.3
3 Perl -5.2
4 JavaScript -3.7
5 CSS -3.0
6 Perl6 -0.4
7 Java -0.1

PHPが減っているのはちょっと意外だったので詳しく見てみると、一部のリポジトリで他リポジトリに分割済みのソースコードの削除作業が行われていました。
このリポジトリの増減を除くと、全体で減少していると判定されていた言語の増減は下記のようになりました。

言語 容量変化(MB)
JavaScript 4.0
PHP 1.1
CSS 0.4
Perl6 0.0
HTML -0.6
Perl -0.5
Java -0.1

JavaScriptは増加の2位タイ、PHPは6位というのが実態により近い値のようです。

プログラミング言語別割合の算出

折角なので、GitHub APIのList Languages APIを使ってVOYAGE GROUP全体でのプログラミング言語別割合も集計してみます。

調査に用いたソースコードは下記になります。

<?php

require_once 'vendor/autoload.php';

$orgName = 'voyagegroup';

$client = new Github\Client();
$client->authenticate('【SET ACCESS TOKEN】', null, Github\Client::AUTH_HTTP_TOKEN);

$paginator = new Github\ResultPager($client);
$orgApi    = $client->api('organization');

$totalLangs = [];

foreach ($paginator->fetchAll($orgApi, 'repositories', [$orgName]) as $repository) {
    $repoLangs  = $client->api('repo')->languages($orgName, $repository['name']);
    $totalLangs = array_map(function ($row) {
        return array_sum((array)$row);
    }, array_merge_recursive($totalLangs, $repoLangs));
}

// check $totalLangs

上記を用いて、voyagegroup Orgnizationに存在する全リポジトリの情報を合算してまとめたものが下記になります。*4

rank 言語 容量(MB) 割合(%)
1 PHP 219.9 27.84%
2 HTML 92.1 11.66%
3 Jupyter Notebook 89.2 11.29%
4 Perl 64.7 8.20%
5 JavaScript 64.0 8.10%
6 Python 59.7 7.56%
7 Java 29.4 3.72%
8 CSS 28.6 3.62%
9 Makefile 25.9 3.28%
10 Objective-C 23.3 2.94%
11 Ruby 18.1 2.29%
12 C 16.6 2.10%
13 C++ 16.1 2.03%
14 Smarty 6.7 0.85%
15 ActionScript 6.7 0.85%
16 C# 5.6 0.71%
17 Scala 3.5 0.44%
18 Tcl 2.5 0.31%
19 Perl6 2.3 0.29%
20 Shell 2.0 0.26%
21 Swift 1.9 0.24%
22 Go 1.7 0.22%
23 TypeScript 1.3 0.17%
24 Erlang 0.9 0.12%
25 R 0.8 0.10%
26 Roff 0.8 0.10%
27 CoffeeScript 0.7 0.09%
28 GLSL 0.7 0.09%
29 PLSQL 0.7 0.09%
30 Objective-C++ 0.5 0.07%
31 Kotlin 0.5 0.07%
32 ApacheConf 0.3 0.04%
33 Scheme 0.3 0.04%
34 Protocol Buffer 0.3 0.04%
35 Puppet 0.3 0.03%
36 HCL 0.2 0.03%
37 XS 0.2 0.02%
38 XSLT 0.2 0.02%
39 Groovy 0.1 0.02%
40 Vue 0.1 0.01%

色々な言語が使われていますが、結果としてはPHPが断トツの割合を占めていました。
調査前、私もPHPが20%くらいで一番多いかなと想像していたのですが、予想を上回る27%超えとなりました。
10年以上続いている弊社のメディアECナビがメインでPHPを利用しているなど、PHPを利用しているサービスが多いためだと考えられます。

3位のJupyter Notebookの容量が大きくなりがちなのは前述の通りです。

その他ではPerl、JavaScript、Python、Javaといった辺りがVOYAGE GROUPでは人気があるようです。最近のトレンドから考えるとそろそろPythonがPerlを抜き去りそうですね。
個人的にはMakefileが3%を超えてトップ10入りしているのも、VOYAGE GROUPらしいのかなと感じるところでした。(参考:プロビジョニングツールはMakeで決まりだろ // Speaker Deck

おわりに

最近のトレンドに関しては差分確認期間中に削除されているコードも存在するため、正確には分かりづらい部分がありましたが、少しはVOYAGE GROUPで利用されているプログラミング言語の実態を感じていただけたでしょうか。また1年後には状況が大きく変化しているかもしれません。

皆さんの周りではどういった言語が使われているでしょうか。
この言語をVOYAGE GROUPで広めていきたい!といった想いの方がいらっしゃいましたら是非採用エントリーをお待ちしています。 voyagegroup.com

*1:一部の古くからあるサービスなど、現在でもSubversionを利用しているものや、子会社ごとのGitHub Organizationアカウントで管理されているものもわずかに存在しますが、今回は調査の対象外とします

*2:GitHub APIとgit-linguistコマンドでは、言語判定が若干異なるケースがあるようだったので、直近の言語別容量もgit-linguistを利用して取得しています。

*3:容量変化が±0.1MB未満のものは表から除外しています

*4:容量が0.1MB未満のものは表から除外しています。サードパーティ製のソースコードは一般的なパスにあれば除外されているようですが、含まれているものもあるかもしれません