dip Engineer Blog

Engineer Blog
ディップ株式会社のエンジニアによる技術ブログです。
弊社はバイトル・はたらこねっとなど様々なサービスを運営しています。

PHPの配列のソートまとめ

はじめに

こんにちは、2018年新卒で入社し、PHPで求人系サービスの開発や社内向けツールの開発を行なっている @taku-0728 です。
今回は私が公式ドキュメントにてPHPで配列をソートするやり方を調べようと思ったところ、色々な関数があって戸惑ったので全部自分なりにまとめてみました。
長くなってしまうため、みたい情報だけピックアップしてみていただければと思います。

関数一覧

解説

sort

まず最初に紹介するのはsortです。
sortは配列の値を基準として昇順にソートしますが、連想配列であってもキーと値の組み合わせは維持されません。

$fruitsLists = [];

$fruitsLists = ["d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple"];
sort($fruitsLists);
var_dump($fruitsLists);
array(4) {
  [0]=>
  string(5) "apple"
  [1]=>
  string(6) "banana"
  [2]=>
  string(5) "lemon"
  [3]=>
  string(6) "orange"
}

また、第2引数で比較条件を指定することもできます。
第2引数に指定可能な値は下記です。

  • SORT_REGULAR
    • デフォルトです。第2引数を省略した場合これが使われます。文字列の数値への変換が勝手に行われるため意図しないソート結果になることがあります。
    • 例えば下記の例だと同じ要素をソートしているにも関わらず結果が異なってしまいます。なんでこのような結果になるかは参考記事にも記載していますがこちらの記事がわかりやすいです。
      デフォルトですが極力使わずに、後述するSORT_NUMERICまたはSORT_STRINGのどちらかを使った方がいいと思います。
$array1=array("9", "1e1", "1f1");
sort($array1);
var_dump($array1);

$array2=array("1e1", "1f1", "9");
sort($array2);
var_dump($array2);
array(3) {
  [0]=>
  string(1) "9"
  [1]=>
  string(3) "1e1"
  [2]=>
  string(3) "1f1"
}
array(3) {
  [0]=>
  string(3) "1e1"
  [1]=>
  string(3) "1f1"
  [2]=>
  string(1) "9"
}
  • SORT_NUMERIC
    • 数字として項目を比較します。オプションを指定していない時と比較しても結果が異なっていないことが確認できます。
$array1=array("9", "1e1", "1f1");
sort($array1, SORT_NUMERIC);
var_dump($array1);

$array2=array("1e1", "1f1", "9");
sort($array2, SORT_NUMERIC);
var_dump($array2);
array(3) {
  [0]=>
  string(3) "1f1"
  [1]=>
  string(1) "9"
  [2]=>
  string(3) "1e1"
}
array(3) {
  [0]=>
  string(3) "1f1"
  [1]=>
  string(1) "9"
  [2]=>
  string(3) "1e1"
}
  • SORT_STRING
    • 文字列として項目を比較します。こちらもオプションを指定していない時と比較しても結果が異なっていないことが確認できます。
$array1=array("9", "1e1", "1f1");
sort($array1, SORT_STRING);
var_dump($array1);

$array2=array("1e1", "1f1", "9");
sort($array2, SORT_STRING);
var_dump($array2);
array(3) {
  [0]=>
  string(3) "1e1"
  [1]=>
  string(3) "1f1"
  [2]=>
  string(1) "9"
}
array(3) {
  [0]=>
  string(3) "1e1"
  [1]=>
  string(3) "1f1"
  [2]=>
  string(1) "9"
}
  • SORT_LOCALE_STRING
    • 現在のロケールに基づいて比較します。setlocale()でロケールを指定します。
// ロケールをオランダ語に設定
setlocale(LC_ALL, 'nl_NL');

// オランダ語が入った配列をソート
sort($netherLandsArray, SORT_LOCALE_STRING);
  • SORT_NATURAL
    • 項目の比較を文字列として行い、 後述のnatsort() と同様の「自然順」で比較します。
$array1 =  array("img12.png", "img10.png", "img2.png", "img1.png");
$array2 = $array1;

sort($array1);
var_dump('asortの実行結果');
var_dump($array1);

sort($array2, SORT_NATURAL);
var_dump('natsortの実行結果');
var_dump($array2);
string(19) "sortの実行結果"
array(4) {
  [0]=>
  string(8) "img1.png"
  [1]=>
  string(9) "img10.png"
  [2]=>
  string(9) "img12.png"
  [3]=>
  string(8) "img2.png"
}
string(27) "SORT_NATURALの実行結果"
array(4) {
  [0]=>
  string(8) "img1.png"
  [1]=>
  string(8) "img2.png"
  [2]=>
  string(9) "img10.png"
  [3]=>
  string(9) "img12.png"
}
  • SORT_FLAG_CASE
    • 文字列の比較で大文字小文字を区別しないようにします。SORT_STRINGやSORT_NATURALとOR条件(|)で組み合わせて使います。
$array1=array("aaa", "bbb", "AAA", "BBB");
sort($array1);
var_dump('sortの実行結果');
var_dump($array1);

$array2=array("aaa", "bbb", "AAA", "BBB");
sort($array2, SORT_FLAG_CASE|SORT_STRING);
var_dump('SORT_FLAG_CASE|SORT_STRINGの実行結果');
var_dump($array2);
string(19) "sortの実行結果"
array(4) {
  [0]=>
  string(3) "AAA"
  [1]=>
  string(3) "BBB"
  [2]=>
  string(3) "aaa"
  [3]=>
  string(3) "bbb"
}
string(41) "SORT_FLAG_CASE|SORT_STRINGの実行結果"
array(4) {
  [0]=>
  string(3) "aaa"
  [1]=>
  string(3) "AAA"
  [2]=>
  string(3) "bbb"
  [3]=>
  string(3) "BBB"
}

rsort

sortの逆で、値を基準として降順にソートします。
キーと値の組み合わせが維持されない点と、第2引数でオプションが指定できる点も同様です。

$fruitsLists = [];

$fruitsLists = ["d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple"];
rsort($fruitsLists);
var_dump($fruitsLists);
array(4) {
  [0]=>
  string(6) "orange"
  [1]=>
  string(5) "lemon"
  [2]=>
  string(6) "banana"
  [3]=>
  string(5) "apple"
}

asort

次に紹介するのはasortです。
asortは配列の値を基準として昇順にソートします。
sortと同様に第2引数でオプションを指定することもできます。
sortとの違いはキーと値の組み合わせは維持される点です。

$fruitsLists = [];

$fruitsLists = ["d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple"];
asort($fruitsLists);
var_dump($fruitsLists);
array(4) {
  ["c"]=>
  string(5) "apple"
  ["b"]=>
  string(6) "banana"
  ["d"]=>
  string(5) "lemon"
  ["a"]=>
  string(6) "orange"
}

arsort

arsortはasortの逆で値を基準として降順にソートします。

$fruitsLists = [];

$fruitsLists = ["d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple"];
arsort($fruitsLists);
var_dump($fruitsLists);
array(4) {
  ["a"]=>
  string(6) "orange"
  ["d"]=>
  string(5) "lemon"
  ["b"]=>
  string(6) "banana"
  ["c"]=>
  string(5) "apple"
}

ksort

ksortは配列のキーを基準として昇順にソートします。
asortが配列の値を基準としていたのに対し、こちらはキーを基準としています。
sortと同様に第2引数でオプションを指定することもできます。

$fruitsLists = [];

$fruitsLists = ["d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple"];
ksort($fruitsLists);
var_dump($fruitsLists);
array(4) {
  ["a"]=>
  string(6) "orange"
  ["b"]=>
  string(6) "banana"
  ["c"]=>
  string(5) "apple"
  ["d"]=>
  string(5) "lemon"
}

krsort

krsortはksortの逆で配列のキーを基準として降順にソートします。

$fruitsLists = [];

$fruitsLists = ["d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple"];
krsort($fruitsLists);
var_dump($fruitsLists);
array(4) {
  ["d"]=>
  string(5) "lemon"
  ["c"]=>
  string(5) "apple"
  ["b"]=>
  string(6) "banana"
  ["a"]=>
  string(6) "orange"
}

usort

usortはユーザー定義の比較関数により配列をその値でソートします。
つまり、コールバック関数を使って自分が指定した順番でソートできるということです。

function sortStrlen($a, $b) {
    // 同じ長さの場合には、順序を変えない
    if (strlen($a) === strlen($b)) {
        return 0;
    }
    // $aの方が短い場合には、$aの順番を$bより繰り下げる
    // $aの方が長い場合には、$aの順番を$bより繰り上げる
    return (strlen($a) < strlen($b)) ? -1 : 1;
};

$fruitsLists = [];

$fruitsLists = ["d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple"];
usort($fruitsLists, 'sortStrlen');
var_dump($fruitsLists);
array(4) {
  [0]=>
  string(5) "lemon"
  [1]=>
  string(5) "apple"
  [2]=>
  string(6) "orange"
  [3]=>
  string(6) "banana"
}

uasort

uasortはusortと似ていますが、キーと値の組み合わせを保持する点に違いがあります。

function sortStrlen($a, $b) {
    // 同じ長さの場合には、順序を変えない
    if (strlen($a) === strlen($b)) {
        return 0;
    }
    // $aの方が短い場合には、$aの順番を$bより繰り下げる
    // $aの方が長い場合には、$aの順番を$bより繰り上げる
    return (strlen($a) < strlen($b)) ? -1 : 1;
};

$fruitsLists = [];

$fruitsLists = ["d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple"];
uasort($fruitsLists, 'sortStrlen');
var_dump($fruitsLists);
array(4) {
  ["d"]=>
  string(5) "lemon"
  ["c"]=>
  string(5) "apple"
  ["a"]=>
  string(6) "orange"
  ["b"]=>
  string(6) "banana"
}

uksort

usortが配列の値を使って項目の比較を行なっていたのに対し、uksortは配列のキーを使って項目の比較を行います。

function sortStrlen($a, $b) {
    // 同じ長さの場合には、順序を変えない
    if (strlen($a) === strlen($b)) {
        return 0;
    }
    // $aの方が短い場合には、$aの順番を$bより繰り下げる
    // $aの方が長い場合には、$aの順番を$bより繰り上げる
    return (strlen($a) < strlen($b)) ? -1 : 1;
};

$fruitsLists = [];

$fruitsLists = ["aa" => "lemon", "aaa" => "orange", "a" => "banana", "aaaa" => "apple"];
uksort($fruitsLists, 'sortStrlen');
var_dump($fruitsLists);
array(4) {
  ["a"]=>
  string(6) "banana"
  ["aa"]=>
  string(5) "lemon"
  ["aaa"]=>
  string(6) "orange"
  ["aaaa"]=>
  string(5) "apple"
}

natsort

natsortはSORT_NATURALオプションを使用したときと同じように「自然順」アルゴリズムでキーと値の組み合わせを保持したまま配列をソートします。
わかりやすいようにasortと実行結果を比較してみます。

$array1 =  array("img12.png", "img10.png", "img2.png", "img1.png");
$array2 = $array1;

asort($array1);
var_dump('asortの実行結果');
var_dump($array1);

natsort($array2);
var_dump('natsortの実行結果');
var_dump($array2);
string(20) "asortの実行結果"
array(4) {
  [3]=>
  string(8) "img1.png"
  [1]=>
  string(9) "img10.png"
  [0]=>
  string(9) "img12.png"
  [2]=>
  string(8) "img2.png"
}
string(22) "natsortの実行結果"
array(4) {
  [3]=>
  string(8) "img1.png"
  [2]=>
  string(8) "img2.png"
  [1]=>
  string(9) "img10.png"
  [0]=>
  string(9) "img12.png"
}

asortでソートすると、2よりも1の方が数字として若いため、2より10や12が先になります。
それに対してnatsortでソートすると自然な数字の順番になっています。

natcasesort

natcasesortはnatsortと似ていますが大文字小文字を区別しない点に違いがあります。

$array1 =  array('IMG0.png', 'img12.png', 'img10.png', 'img2.png', 'img1.png', 'IMG3.png');
$array2 = $array1;

asort($array1);
var_dump('asortの実行結果');
var_dump($array1);

natcasesort($array2);
var_dump('natcasesortの実行結果');
var_dump($array2);
string(20) "asortの実行結果"
array(6) {
  [0]=>
  string(8) "IMG0.png"
  [5]=>
  string(8) "IMG3.png"
  [4]=>
  string(8) "img1.png"
  [2]=>
  string(9) "img10.png"
  [1]=>
  string(9) "img12.png"
  [3]=>
  string(8) "img2.png"
}
string(26) "natcasesortの実行結果"
array(6) {
  [0]=>
  string(8) "IMG0.png"
  [4]=>
  string(8) "img1.png"
  [3]=>
  string(8) "img2.png"
  [5]=>
  string(8) "IMG3.png"
  [2]=>
  string(9) "img10.png"
  [1]=>
  string(9) "img12.png"
}

array_multisort

array_multisortは主に多次元配列や複数の配列を一度にソートしたいときに使われます。
下記の例で果物の配列を名前の昇順かつ、価格の昇順になるようにソートしてみます。

$fluitsLists = [
        ['name' =>'lemon','price' =>200],
        ['name' =>'orange','price' =>100],
        ['name' =>'banana','price' =>200],
        ['name' =>'apple','price' =>300],
    ];

// ソートの基準となる「name」と「price」を配列に入れる
foreach( $fluitsLists as $fluits) {
    $nameLists[] = $fluits['name'];
    $priceLists[] = $fluits['price'];
}

// ソート前の配列を出力
var_dump('array_multisortの実行前');
var_dump($fluitsLists);

// ソート実行
array_multisort($nameLists, SORT_ASC, SORT_STRING, $priceLists, SORT_ASC, SORT_NUMERIC, $fluitsLists);

// ソート後の配列を出力
var_dump('array_multisortの実行後');
var_dump($fluitsLists);
string(27) "array_multisortの実行前"
array(4) {
  [0]=>
  array(2) {
    ["name"]=>
    string(5) "lemon"
    ["price"]=>
    int(200)
  }
  [1]=>
  array(2) {
    ["name"]=>
    string(6) "orange"
    ["price"]=>
    int(100)
  }
  [2]=>
  array(2) {
    ["name"]=>
    string(6) "banana"
    ["price"]=>
    int(200)
  }
  [3]=>
  array(2) {
    ["name"]=>
    string(5) "apple"
    ["price"]=>
    int(300)
  }
}
string(27) "array_multisortの実行後"
array(4) {
  [0]=>
  array(2) {
    ["name"]=>
    string(5) "apple"
    ["price"]=>
    int(300)
  }
  [1]=>
  array(2) {
    ["name"]=>
    string(6) "banana"
    ["price"]=>
    int(200)
  }
  [2]=>
  array(2) {
    ["name"]=>
    string(5) "lemon"
    ["price"]=>
    int(200)
  }
  [3]=>
  array(2) {
    ["name"]=>
    string(6) "orange"
    ["price"]=>
    int(100)
  }
}

結果を見ると名前の昇順かつ、価格の昇順になっていることがわかると思います。

shuffle

最後にソートとは少し違いますが、shuffleも紹介しておきます。
名前の通り、配列の順番をランダムにします。
この時キーと値の組み合わせが維持されない点に注意が必要です。

$fruitsLists = [];

$fruitsLists = ["d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple"];
shuffle($fruitsLists);
var_dump($fruitsLists);
array(4) {
  [0]=>
  string(6) "orange"
  [1]=>
  string(5) "apple"
  [2]=>
  string(6) "banana"
  [3]=>
  string(5) "lemon"
}

何度か実行したらわかりますが、実行するたびに結果が変わります。

まとめ

PHPで配列をソートするやり方について解説しました。
最近では並び替えなどはRDBで行うのが一般的であり、PHPで配列の並び替えを行う機会など多くはないかもしれませんが、いざという時のために知っておくと便利かなと思います。
最後までお付き合いいただきありがとうございました。

参考

配列のソート
【 php 】usort関数の使い方
多次元配列のソート:array_multisort関数
PHPのsort関数は相当おかしい

筆者

筆者 (写真右)

XCodeGen対応のTIPS

はじめに

こんにちは。iOSエンジニアの@satoshi-babaです。 いま巷で賑わっているXCodeGenを検証する過程で、ハマりどころがいっぱいあったので簡単なTIPSを共有したいと思います。 そもそもXCodeGenがどんなものかというのは割愛させていただきます。

バイトルはなぜXCodeGen対応したの?

バイトルiOSは10名前後のエンジニアが開発に携わっています。 ABテストの実施もよく行っており、ファイルの追加/削除が頻繁に行われるようになっています。

元々、開発フローの課題の1つにxcodeprojのコンフリクト抑止がありました。 その中で年末に行われていたtry! Swift Tokyo 2020 Meetup!!に参加した時に、XCodeGenの紹介があり「これだ!」と思い導入することにしました。

TIPS

Templateバリ便利!

SchemeとTargetにそれぞれTemplateを用意することができます。

例えばTargetであればこんな感じにテンプレートを用意することで記載をかなり簡略がすることができます。 例えば複数の環境設定がされている場合に使えます。

targetTemplates:
  application-base:
    type: application
    platform: iOS
    sources:
      - path: xxxxx
    info:
      properties:
        UISupportedInterfaceOrientations: [UIInterfaceOrientationPortrait]
        UILaunchStoryboardName: LaunchScreen
    settings:
      base:
        TARGETED_DEVICE_FAMILY: 1
        CODE_SIGN_STYLE: Manual
        ENABLE_BITCODE: No
        GCC_C_LANGUAGE_STANDARD: gnu99
        CLANG_CXX_LANGUAGE_STANDARD: gnu++0x
        CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED: Yes
    dependencies:
      - sdk: SystemConfiguration.framework
      - sdk: libsqlite3.tbd
    preBuildScripts:
      - name: R.Swift
        script: |
          echo 'make R.generated.swift'
          if [ -e "$SRCROOT/xxxxx/xxxxx/R.generated.swift" ]; then
          echo 'remove R.generated.swift'
          rm "$SRCROOT/xxxxx/xxxxx/R.generated.swift"
          fi
          "$PODS_ROOT/R.swift/rswift" generate "$SRCROOT/xxxxx/xxxxx/R.generated.swift"
        inputFiles:
          - $TEMP_DIR/rswift-lastrun
        outputFiles:
          - $SRCROOT/xxxxx/xxxxx/R.generated.swift
targets:
  # 個別の微小な設定を書くだけだから楽できる。
  stage1:
    templates:
      - application-base
    info:
      path: $(SRCROOT)/xxxxx/xxxxx/stage1/Info.plist
  stage2:
    templates:
      - application-base
    info:
      path: $(SRCROOT)/xxxxx/xxxxx/stage2/Info.plist

R.generated.swiftが解決できない時の対処

Gitからcloneした直後にxcodegenしてビルドすると以下のエラーが発生します。

``

R.swiftを導入したことがある方なら気づいていると思いますが、Run ScriptでR.generated.swiftを作成した後に手動で追加する手順があります。 そうするとxcodegenでプロジェクトファイルを生成する時には、上記のファイルはないわけなので参照に含まれなくなります。

そんな時はsourcesの設定でファイルがないときでも参照を追加するようにしましょう!

sources:
  - path: xxxxx
  - path: xxxxx/xxxxx/R.generated.swift
    optional: true
    createIntermediateGroups: true

Build Settingsのキー名の探し方

Build Settingsで細かい設定がされている場合、XCodeGenのsettingsで設定する必要があります。 バイトルの場合はC++ Language Dialectが該当していて設定する必要がありました。

こんな感じに設定します。

settings:
  base:
    CLANG_CXX_LANGUAGE_STANDARD: gnu++0x

この設定のキー名はCode Sign Styleなんかはなんとなく勘で行けることもありますが、 物によっては全くわからない場合があります。

そんな時はXCodeのプロジェクト設定から探すことができます。(Appleにドキュメントがあると思いますが探してません) 画像のQuick HelpのDeclarationを参照すれば一発ですね!これで大概のことはできそうです!

f:id:satoshi-baba:20200327095223p:plain

Build Settingsの設定値の探し方

Build Settingsのキーはわかっても具体的な設定がわからないことがあります。 例えばバイトルでハマったのは、C++ Language Dialectの設定値がわかりませんでした。

設定値は具体的な何を設定する項目なのかがわかれば、各種ドキュメントから漁ることで解決できます。 C++ Language DialectはClangの設定項目なので、 このページを参照することで解決することができました。

まとめ

XCodeGenのハマりどころは多いですがキチンと対処がわかっていれば怖くありません。 バイトルも取り入れられるところはどんどんモダンな技術を取り入れていきたいと思います。

著者

dippeople.dip-net.jp

Bridging HeaderをはずしたらUIKitが解決できなくなった!

はじめに

こんにちは。iOSエンジニアの@satoshi-babaです。 いま巷で賑わっているXCodeGenを検証する過程で、UIKit系のクラスの参照が解決できない事象に出くわしました...。 その事象を解決するまでの道のりを共有したいと思います。

事の始まり

現在、私はXCodeGenの検証を実施しています。

ある日私はほとんどの設定を書き終え「いや〜これは完璧だわ!ビルドして動作確認するぞ!」と息巻いていたところ、 およそ1000を超えるSwift Compiler Errorに遭遇してしまいました。

表示されていたエラーは大きく分けて以下の3つでした。

  • Use of Undeclared Identifier CGFloat
  • Use of Undeclared Identifier UIFont
  • Use of Undeclared Identifier UIImage

該当の処理を確認すると、確かにCGFloatやUIFontは使用されています。 しかしimportされているのはFoundationのみで、UIKitに属するCGFloatやUIFontは解決できなそうです。

import Foundation
extension String {
    func labelHeight(width: CGFloat, font: UIFont, maxLine: Int = 0) -> CGFloat {
        let label = UILabel()
        label.font = font
        label.lineBreakMode = .byTruncatingTail
        label.numberOfLines = maxLine
        label.text = self
        let rect: CGSize = label.sizeThatFits(CGSize(width: width-label.layoutMargins.left-label.layoutMargins.right, height: CGFloat.greatestFiniteMagnitude))
        return rect.height
    }
}

とりあえず全てのクラスにUIKitのimportすれば動きそうです。 しかし、なぜこのような状態で今までコンパイルできたのか、XCogeGenで生成したプロジェクトで解決できなくなったのか気になります。 もしかしたら重要な見落としがあるかと思い、調査することにしました。

原因はBridging Header忘れ!!

XCogeGenで生成したプロジェクトの時に発生する問題です。絶対に設定し忘れている項目があるはずです! Build Settingsを上から順番チェックしてみることにしました。

すると見事にBridging Headerの追加を忘れていました! f:id:satoshi-baba:20200213142343p:plain

設定を追加したら無事にビルドができるようになりました。 これで安心!...では終われません!

Bridging Headerの動きをさらに追ってみることにしました。

Bridging Headerは全てのSwiftファイルにimportされる

まずはBridging Headerの動作について、下記の公式ページで確認してみました。 Importing Objective-C into Swift

どうやらBridging Headerは全てのSwiftファイルにimportされるみたいです。 Bridging Headerまたはその先でUIKitをimportしていればいい感じに解決されちゃいそうですね...!

実際に読み込んでいる先でimportされていました!

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface HogeLogic : NSObject
(省略)

感想

Bridging Headerをはずすだけでこんな影響が出るなんて思いもしませんでした。 昔のC言語でのCommonヘッダーみたいな役割が簡単にできちゃいますね!(意図してませんでしたが) もしかしたらコードレビューの観点に盛り込むべきかもしれませんね。

著者

dippeople.dip-net.jp

SRE NEXT2020参加レポート

SRE NEXT 2020行ってきました

こんにちはSREエンジニアやってます、@hayaosatoです。

1/25(土)に開催されたSRE NEXT 2020へ参加してきたのでそのレポート記事を書かせていただきます。

本イベントは弊社もブロンズスポンサーとして協賛させていただき、会場でもノベルティが配られてました!

写真は弊社のポスターとステッカー、そしてSRE NEXTのトートバッグです!

f:id:hayaosato:20200131104622j:plain

また、当日スタッフとして弊社のおざけんがカメラマンとして参加、

コアスタッフとして@bayashi_okさんがホール統括を行なっていました!!

発表紹介

SRE NEXT 2020の中で個人的に特に印象の残った発表について、いくつか感想を書かせていただきます。

分散アプリケーションの信頼性観測技術に関する研究

資料: https://speakerdeck.com/yuukit/a-study-of-sre

SREの今後についてやそれに付随する研究などをとても丁寧に説明されていたSRE NEXTらしい発表でした。

SREがなんであるかのゆううきさんなりの定義は

サイト信頼性を制御するための工学であり、

自動化して全て解決というわけではなく、認知負荷が高まってしまう 失敗を許容する前提で運用を設計することで変更速度を最大化する。

とのこと。

確かに自動化するだけだと認知負荷が高まってしまい、 システムを構築した人しか認知できなくなる。それが原因で属人化してしまうこともある得るのかなと思いました。

また、失敗を許容する前提での運用設計は今後我々もやっていきたいなと思いました。

成長を続ける広告配信プラットフォームのモニタリングを改善してきた話

資料: https://speakerdeck.com/larufa/cheng-chang-wosok-keruguang-gao-pei-xin-puratutohuomufalsemonitaringuwogai-shan-sitekitahua

やりがちな監視の例などを踏まえて監視における課題やその解決方法まで非常に丁寧でわかりやすく説明されていた発表でした。

また、アラートの整理する(洗練などの)タイミングについて、アラートの整理は定期的にやる事は確かに難しく、障害が実際に起きた時や新しいメンバーがジョインしたタイミングでアラートの整理をやっているそうです。

確かにそれらのタイミングだと、アラート整理に工数を確保しやすいなと感じ、今後我々もそのようなタイミングでアラートの整理を行なっていきたいなと思いました。

ZOZO MLOps のチームリーディングとSRE(Engineering)

資料: https://docs.google.com/presentation/d/1zEkR9Dm_epg7fxOCFE-asBsUlHDozwObsBEGAILiqic/edit

ML機能を世に出しすための取り組みの、エンジニアリングにおけるチームリーディングについての発表でした。

現在複数のML機能を世に出した段階で、MLOpsチームとしてもっと多くのML機能を世に出してML機能に対する信頼度を高めようとしているフェーズだそうです。

このようにMLOpsチームの目標が明確で、さらにプロジェクト進行がスムーズに進むようにはどうすべきか。

リーダーがボトルネックとならないためにはどのようにすべきか。など組織開発として非常に参考になる発表でした。

特に、最終的には技術でぶん殴るという文化は非常に共感し、我々もぶん殴れるほどの技術力をつけていかなければなと思いました。

Webサービスを1日10回デプロイするための取り組み

資料: https://speakerdeck.com/fujiwara3/sre-next-2020

デプロイ頻度をあげてデプロイへの恐怖を減らための取り組みでした。

誰でもデプロイ/ロールバックできるようにするためのデプロイ構成についてとても具体的に説明されていた発表でした。

特に、CircleCI使用時のECRのリージョンなど、小ネタ等もとても面白かったです。

雑感

SRE NEXT 2020、全体的に登壇者のレベルが非常に高くSREにおけるベストプラクティスや考え方の共有をしていただき、非常に学びの多い勉強会でした。

また、SREとしての対策が新規メンバーの育成やチームマネジメント的な話にも派生していたりと、幅広い知見が得られました。

SREの今後として、SREはインフラからアプリケーションまで全てのレイヤで開発されるようになり、SREを考えることが当たり前になっていくと良いなと思いました。

筆者

dippeople.dip-net.jp (写真左)

2019年アドベントカレンダーまとめ

はじめに

こんにちは、2018年新卒で入社し、求人系サービスの開発や社内向けツールの開発を行なっている @taku-0728 です。
今回は12/1~12/25に有志で行なったディップ Advent Calendar 2019について書きたいと思います!

Advent Calendar とは

一般的なアドベントカレンダーはクリスマスまでの期間に日数を数えるために使用されるカレンダーのことを指しますが、エンジニアの中では個人または複数人で記事を書いてクリスマス当日までバトンをつなげていく文化のことを指します!
弊社は2016年から毎年 Qiita Advent Calendar に参加しています。任意で参加者を募り、業務に関係するものから自分で興味を持った技術まで自由なテーマで記事を書いています。
今回はそのアドベントカレンダーの中から私が気になった記事を中心に振り返ります!

おすすめ記事一覧

Pegmatiteが素晴らしいツールなので自分好み(GitHub Enterprise Serverで使えるよう)にしてみた

Pegmatiteが素晴らしいツールなので自分好み(GitHub Enterprise Serverで使えるよう)にしてみた
PegmatiteというPlantUMLを画像化するGoogle Chromeの機能拡張を弊社のGitHub Enterprise Serverで使えるようにした話です。
著者の方でPRを出したところ、マージしていただき無事リリースされたそうです。

なぜコンテナを導入するのか ~ 各職種への説得材料をまとめる

なぜコンテナを導入するのか ~ 各職種への説得材料をまとめる
Dockerコンテナに触ったことがない人に対して、Dockerコンテナ利用時のメリットを説明している記事です。
サービス開発者、インフラ担当、セキュリティ担当それぞれの目線でメリットを説明しているためどの立場からみてもわかりやすい記事になっています。
著者は定期的にDockerコンテナに関する社内勉強会を開催しています。

日報がTILだったお陰でGithubとMarkdownがわかった話

日報がTILだったお陰でGithubとMarkdownがわかった話
2019年新卒入社した文系出身のエンジニアが毎営業日つけている日報によってGithubの仕組みやMarkdownの書き方を身につけた話です。
著者と同じように文系出身でGithubの仕組みなどがいまいちわかっていない方におすすめの記事だと思います。

バイトル(iOS)のCI/CDを大公開!!

バイトル(iOS)のCI/CDを大公開!!
弊社で(おそらく)もっとも有名なサービス、バイトルスマホアプリ(iOS)のCI/CDがどうなっているかわかってしまうレアな記事です。
読むとバイトルスマホアプリリリースの裏側が知れるかも。

若手エンジニアが学んだ工数見積もり方法

若手エンジニアが学んだ工数見積もり方法
最後は私 @taku-0728 が書いた記事を紹介します!
元々工数見積もりが苦手だった私が先輩にやり方を教わって、実践してみてどういう学びがあったのかをまとめています。
同じように工数見積もりが苦手な方に読んでいただければと思います。

おまけ

上記とは別に、1人で25記事全部埋める「全部俺カレンダー」に挑戦した猛者が何人かいます。
よければそちらも目を通していただければと思います。

また、過去実施したアドベントカレンダーはこちらから確認できます。

最後に

今回は12月に行なったアドベントカレンダーについて紹介しました。
弊社ではアドベントカレンダー以外にも様々な試み、イベントを行なっています。
適宜ブログにて発信していくので楽しみにお待ちください。

また、弊社では一緒にサービスを開発している仲間を募集しています!
とりあえず話だけ聞きたいでも構いません。興味がある方は下記よりご連絡ください!

www.dip-net.co.jp

筆者

dippeople.dip-net.jp (写真右)

ブログリニューアルしました!

はじめに

こんにちは! ディップ株式会社でエンジニアをやっている@satoshi-babaと申します。

この度、弊社のエンジニアブログをリニューアルいたしました。 ここではリニューアルの目的などを説明させていただこうと思います!

リニューアルの目的

弊社は様々なイベントに登壇したりしていますが、知名度としてはまだまだイマイチです。 イベントで「ディップさんってエンジニアいるんですね」と言われることもいまだにあるんですよね。

そこで、エンジニアブログをリニューアルし、我々が技術に対して真摯に向き合っていることをご理解いただき、弊社開発部の魅力を知っていただきたいと考えました!

投稿内容について

弊社はバイトルを始めとし、中〜大規模サービスを運営しています。 ここではサービスに使用している技術やマネジメント術などを積極的に公開していきます。 そのほかに、イベント情報やエンジニアが個人的に気になっている話なども取りあげたいと思います。

早速来週から、記事を上げ始める予定となっております。 「読者になる」ボタンを押していただき、楽しみにお待ちください!

おわりに

惜しみなくアウトプットをしていきたいと思いますので、どうぞよろしくお願いいたします。

また、弊社では一緒にサービスを開発している仲間を募集しています! とりあえず話だけ聞きたいでも構いません。興味がある方は下記よりご連絡ください!

www.wantedly.com

著者

dippeople.dip-net.jp