Kuzunoha-NEのブログ

pythonの勉強中。

G Suite People Analytics セミナーに参加して思ったこと

こんばんは、葛の葉です。

11/13に、実はこういうイベントに参加していました。

www.dsk-cloud.com

ここではGoogleさんのAI活用事例、とりわけ、社員の行動をデータ化し、それを機械学習させることで、業務円滑化を図っている…というお話も面白かったのですが…

これからの仕事、働き方についてお話をしていただいた、プロノイア・グループ株式会社のピョートル・グジバチさんのお話が面白かったです。

プロノイア・グループさんのHPはこちら

www.pronoiagroup.com

ものづくりの時代が終わり、仕組みづくりの時代になった。

GoogleFacebookの二社は、テレビ局やラジオといった巨大であるメディアの企業に勝ったのはどうしてか?二社ともそのメディアという業界においては全くの未経験であったのに。という問いかけをしてから、「業界未経験者が業界を壊していくものなのだ」という風のおっしゃっていました。

二社において、共通した項目というものは「マネタイズをしていない」ということでした。そのことからイノベーションを起こす組織というものは「強欲な組織」より「利他的な組織」であるということでした。また、これから求められる組織もそういうものであると、そのように仰っていました。

それから「クローズされた組織」より「オープンな組織」が生き残っているともおっしゃっていました。Googleに、しばしば女子高校生が出入りしているようで、これは世界的に「女性エンジニア」が少ない現状に対して、女性にITエンジニアリングに興味をもってもらいたい、ということで、Googleが取り組んでいる「Mind the Gap」という活動のようです。このように、組織と個人が身近になれるような、そういった取り組みがオープンな組織となる、と、そのようにおっしゃっていたと思います。

またピョートルさんは続けて「トップダウン方式よりボトムアップ方式が良い」「社畜優遇のピラミッド構造が終わった」「鵜飼いのマネジメントより羊飼いのマネジメント*1」などなど、「かつて」と「これから」を対比させながら、組織のあり方について仰っていました。よくよくそのお話を聞いていると「会社の社員個人個人が幸せに仕事が出来ているとそれがイノベーションに繋がる」ということをお話されていたような気がします。

また、プロノイア・グループさんは組織づくりにおいて、以下の4つのことが大事とのことを仰っていました。

  1. [心理的安全性] 自分らしく出社することができるか

  2. [信頼性] 社員がお互いに信頼することが出来るか

  3. [構造、役割の透明化] 自分がどんな立ち位置かわかりやすいか

  4. [仕事の意味] 仕事が与える影響はどんなものであるか

またプロノイア・グループさんでは以下の3つ文化を大切にしているとのことでした。

Play work (遊ぶように働く)

Implement first (初めての前例になる)

Offer Unexpected (予期しない提供)

*1これはスライドがあり、鵜飼いは鵜に紐をつけて魚を取らせるような、社員を言い聞かせて動かすというものに対して、羊飼いは、自由にのんびり雑草を食べる羊とそれを見守る羊飼いというイラストで対比されていました。

ピョートルさんのお話を聞けて思ったこと

今回のピョートルさんのお話の間はとにかく「笑い」がありました。また、プロノイア・グループさんのPIO(先に記載した3つの文化の頭文字に関連している)というヒヨコのキャラクターの似顔絵もピョートルさんそっくりに描かれていて、楽しそうに仕事していることが伝わってきました。

「自分らしく仕事が出来る」って、これほど素晴らしいものがあるだろうか、と思いました。よく私も「変わってる」とか言われてきました。そのたびに「普通」になろうと思ってあれこれやってきましたが、ついぞそれは叶わず。最近になって諸々と拗らせて「自分らしさ」を見つけようとは思ってますが、まあ見つかりません。「右向け右」を「組織」でやると随分と「矯正」されると思います。まぁそれくらい「組織」とか「集団」ってのは強いと思うんですね。

だからこそ、「組織が多様性を認めている」って、大きなことなんだと思います。

ただまぁ、最近でこそ「多様性は善」ということが浸透しつつありますが、まだまだ「出る杭は打たれる」のが現状でもあるんだと思います。私、正直、イノベーションがどうって、よくわからないです。そりゃあ、「みんな同じ」「全員ゼネラリスト」じゃイノベーションなんて生まれないでしょう。そりゃあ、もう、みんな同じ発想になるように仕込まれるですから。

今すぐ、イノベーションが起きなくても、それでも、最初は多様性を認める組織が増えればいいんじゃないかなって思ってます。個人として、「多様性を認める組織」を認めていくと言いますか。

僕自身が今できることは、そういったことなのかな、と思いました。

MySQL 5.7.22 のORDER BYの順番について

MySQL 5.7.22 のORDER BYの順番について

こんばんは、葛の葉です。

SQLも出来ないの?そんなんじゃ甘いよ。って言われたのでSQLもやってます。ナキソーです。

そこで、Dockerを使ってMySQL 5.7.22のイメージを作って環境を作ってSQLの勉強をしているんです。また、参考書として、下記の物を使用しています。結構砕けた文章なので、読んでいて面白いですよ~ただ、2008年が最新なので古いところが難点かもしれません。 これも読み終わったらレビューをしてみましょうかね。

ORDER BYでのソート順について

上記の本のP.255には、数字とアルファベットと記号が入ったテーブルでORDER BYでソートして、その並び順を確認する、というものがあったと思うのですが、ひらがな、カタカナ、漢字、半角カナ、全角数字も入れた場合はどうなるか、という点は書かれていなかったと思います。ですので、ちょっとやってみました。

CREATE DATABASE sandbox;

USE sandbox;

CREATE TABLE test(
    test_char VARCHAR(30)
);

INSERT INTO test (test_char)
VALUE
('0'),('1'),('2'),('3'),
('A'),('B'),('C'),('D'),
('a'),('b'),('c'),('d'),
('!'),('@'),('#'),('$'),
('%'),('^'),('&'),('*'),
('('),(')'),('-'),('_'),
('+'),('='),('['),(']'),
('{'),('}'),(';'),(':'),
('\''),('\"'),('\\'),('|'),
('\`'),('~'),(','),('.'),
('<'),('>'),('/'),('?'),
('ア'),('イ'),('ウ'),('エ'),
('あ'),('い'),('う'),('え'),
('ア'),('イ'),('ウ'),('エ'),
('亜'),('居'),('兎'),('絵'),
('0'),('1'),('2'),('3'),
(NULL);

どうでもいいことなんですけどINSERT INTO table名 VALUE(値);でもいけますね。要するにカラム名を省略するタイプです。なんか、書くほうが私は好きかも。もう一つどうでもいい話ですが、INSERT INTO table名 (column名) VALUE (値1),(値2),(値3);で複数レコード作れます。スゴイネ。

そして、SELECT * FROM test ORDER BY test_char;を実行するとこんな感じ。

+-----------+
| test_char |
+-----------+
| NULL      |
| !         |
| "         |
| #         |
| $         |
| %         |
| &         |
| '         |
| (         |
| )         |
| *         |
| +         |
| ,         |
| -         |
| .         |
| /         |
| 0         |
| 1         |
| 2         |
| 3         |
| :         |
| ;         |
| <         |
| =         |
| >         |
| ?         |
| @         |
| A         |
| a         |
| b         |
| B         |
| c         |
| C         |
| d         |
| D         |
| [         |
| \         |
| ]         |
| ^         |
| _         |
| `         |
| {         |
| |         |
| }         |
| ~         |
| あ        |
| い        |
| う        |
| え        |
| ア        |
| イ        |
| ウ        |
| エ        |
| 亜        |
| 兎        |
| 居        |
| 絵        |
| 0        |
| 1        |
| 2        |
| 3        |
| ア         |
| イ         |
| ウ         |
| エ         |
+-----------+
65 rows in set (0.00 sec)

さもありなんというか、まぁやっぱり日本語は後ろに来るのね、という印象です。全体をみると、記号、数字、記号、英字、記号となっていておもしろいですね。なんでこうなってるんだろう?まぁアルファベット順になる、数字順になるってのがわかればそれでいいかなぁって思います。記号をソートしたいって思うことないと思うし~

ところで…これであってるんかな(^ω^;)

| @         |
| A         |
| a         |
| b         |
| B         |
| c         |
| C         |

大文字が最初にくるはずなんだけど…AabBcCになってるね…ウーン…Dockerの問題?どういうことだろう…

Rubyのキーワード引数というヤツ

Rubyのキーワード引数というヤツ

こんばんは、葛の葉です。

お勉強したまへ、というお達しがありました。あっふーん…(達し)

というわけで最近はこの書籍を使って勉強しております。

キーワード引数というヤツ

なんか知らんけど関数を作る時に引数名を作ることが出来るようです。へぇ。Pythonにもあったねたしか。

// Pythonだと…

def animal(momonga, dog='ももちゃん', cat='めけめけ王子三世'):
    return cat


print(animal('neko'))

>>>めけめけ王子三世

cat = 'めけめけ王子三世'なのわかりやすい。

// Rubyだと…

def animal(momonga, dog: 'ももちゃん', cat: 'めけめけ王子三世' )
    cat
end

p(animal('neko'))

>>"めけめけ王子三世"

返り値は:catじゃなくてcatにしないと駄目?:catじゃないの?

def animal(momonga, dog: 'ももちゃん', cat: 'めけめけ王子三世' )は省略形で、正しく書くならdef animal(momonga, {:dog => 'ももちゃん', :cat => 'めけめけ王子三世'}こうなんじゃないか?やってみよう。

def animal(momonga, {:dog => 'ももちゃん', :cat => 'めけめけ王子三世'}
    cat
end
p(animal('neko'))

sand.rb:9: syntax error, unexpected {
def animal(momonga, {:dog => 'ももちゃん', :c...
                    ^
sand.rb:11: syntax error, unexpected keyword_end, expecting end-of-input
(Google翻訳[2018/11/2])sand.rb:11:構文エラー、予期しないkeyword_end、入力の終了を予期する

わがんね😭

所謂シンボルではなくて、ブロックとしてみなされているのかな?

この本については後ほどレビューしてみます

先程記載した本派中々面白いです。5章まで読みましたが、テスト駆動開発で行っていますので、前回、PythonでUnittestについて書いたのですが、より理解が深まったと思いました。この本のテストはRubyで書かれているので、Pythonで書き直してみるのも楽しいかも知れませんね。それと、Rubyはあまりやったことなかったので、知らないところはやはり出てきました。が、親切に書いてくれているので、Rubyちょっとしか触ったこと無いって人にも向いていると思います。

kuzunoha-ne.hateblo.jp

Google Apps Scriptで出退勤の発報botを作った

Google Apps Scriptで出退勤の発報botを作った

こんばんは、葛の葉です。

ちょっと前に、GoogleAppsScriptでdiscordのbotを作ったのですが、なんか社長が偉く気に入ったらしくブログの記事に書いてちょんまげって言われて、まぁ、書くことにしました。

どういうbotを作ったのか

私の会社では下図のようにGoogleSpreadSheetsを使った出退勤の表がありまして…

www.google.com

f:id:Kuzunoha-NE:20181023111025j:plain

私、葛の葉は置いといて、他の人たちがまぁインターン生さんです。桃太郎さんとかキャプテン鬼ヶ島さんがそうですね。インターン生さんたちに、この表に時刻を書き込ませて、シフトの決定をしてもらっています。また、シフトを組むのもインターン生さんが決めることになっています。そのため、インターン生さんが好きな時に好きに出勤日と日時を決められるということができます。

また、お仕事の連絡にチャットツールを用いておりまして、それがDiscordなんですね。

discordapp.com

今回作ったbotは、インターン生さんがその出退勤表に一週間以内に出勤の予定を書き込んだ時に、DiscordBotが私宛に発報するというものになります。


10/22現在で、桃太郎さんが10/23 10:00-16:00として出社予定日時を記載した場合

「発報しているシーン」

f:id:Kuzunoha-NE:20181023115107j:plain

「チャットツールDiscordに新着メッセージが来ているシーン」

f:id:Kuzunoha-NE:20181023115557j:plain

ちなみに、セルをコピー&ペーストで張り付けた場合は内容: [予定なし] → [予定なし]と表示されちゃいます。これはちょっと直し方わからんです。ざんねん。

botの作り方

GoogleSpreadsSheetsのGoogleAppsScriptとDiscordのWebhookの連携。

これは過去記事に書いているので、そちらを参照してほしいです。

そちらのコードのうち、function discord(message)の関数を使います。他三つの関数は使いません。(似たようなのはつくるんですけどね)

kuzunoha-ne.hateblo.jp

// Discordに送信する関数
function discord(message) {
    const url        = 'さっきコピーしたwebhooksのURL';
    const token      = 'さっきのURLの中のtokenの文字列';
    const channel    = '#general';
    const text       = message;
    const username   = 'bot';
    const parse      = 'full';
    const method     = 'post';

    const payload = {
        'token'      : token,
        'channel'    : channel,
        "content"    : text,
        'username'   : username,
        'parse'      : parse,
    };

    const params = {
        'method' : method,
        'payload' : payload,
        'muteHttpExceptions': true

    };

   response = UrlFetchApp.fetch(url, params);
}

編集されたセルの行と列の番号を取得する。

GoogleSpreadSheetsにはfunction onEdit(e){}というものがあります。詳しくは以下のリンクを参照してください。この関数はそのスプレッドシート内(ExcelでいうBook内)で編集された様々な情報を取得できる関数です。

Event Objects  |  Apps Script  |  Google Developers

function onEdit(e){}の関数内でe.range.getRow();関数を使用すると行番号、e.range.getColumnIndex()関数を使用すると列番号を取得できます。

onEdit(e)関数はそのスプレッドシートのすべてのシートが対象になります。つまり、新しい月のシートを作成してもこのプログラムは動作します。ヤッタゼ。

function onEdit(e){
  //e.****は更新のシートやセルの情報
  var change_row_num = e.range.getRow();
  var change_colum_num = e.range.getColumnIndex();
}

編集された氏名と日付を取得する。

編集された行と列が取得できたので、それを元に編集された個所の日付と氏名を取得しましょう。まずは氏名から。

   var change_name = SpreadsheetApp.getActiveSheet().getRange(2, change_colum_num).getValue();

SpreadsheetApp.getActiveSheet().getRange(行, 列).getValue()という関数を使用して、編集されたシートから氏名を取得します。.getRange(行, 列)は行数を、は列番号を指定します。今回、2としているのは、該当のシートの二行目が名前欄となっているからです。今回のコードをそのまま使うなら、この辺りを変更しないとダメかも?

次に日付になります。

    var unformat_change_date = SpreadsheetApp.getActiveSheet().getRange(change_row_num, 2).getValue();
    var change_date = Utilities.formatDate(unformat_change_date, "Asia/Tokyo", "yyyy/MM/dd");

また、編集されたシートから日付を取得します。2としているのは、該当のシートの二列目が日付欄となっているからです。ただ、このまま値を取得しても、それをdate型として扱うことができません。編集された日付一週間以内を区別するためにdate型にしてあげる必要があります。そのため、Utilities.formatDate(unformat_change_date, "Asia/Tokyo", "yyyy/MM/dd")という関数を使用します。以下も参照してみて下さい。

日時の設定  |  AdWords scripts  |  Google Developers

f:id:Kuzunoha-NE:20181023151950j:plain

当日を含めた一週間の日付データを取得しリストに格納する。

新しい関数を作ります。関数にしなくてもよいですが、とりあえず機能としては分けたかったので別関数にしました。

書き込み時点でのnew Date()を取得します。それにより、書き込み時点での当日を取得しています。それをloop文回し、当日を含めた8日分取得します。ちなみにloop文でvar i = 0にしようとしたらエラー吐きました。なんでだろう?

function this_week_days_list() {
  var today = new Date();
  var this_week = new Array();
  for(var i = 1;  i < 9;  i++){ /* var i = 0 ではだめらしい */
    var one_day = new Date(today.getYear(), today.getMonth(), today.getDate() + i - 1); 
    var format_today = Utilities.formatDate( one_day, "Asia/Tokyo", "yyyy/MM/dd");
    this_week.push(format_today);
  };
  return this_week
};

この関数をfunction onEdit(e){}内で呼び出してあげてます。

var this_week = this_week_days_list();

日付が当日を含めた一週間(8日間)の中に存在しているかを確認する。

this_week(list)に当日を含めた一週間(8日間)が格納されています。この中にchange_date(日付)が入っているかを確認します。リスト.indexOf(date型)とすると、引数の値がリスト内にあるかどうかを判定し、あれば0,なければ-1を返します。詳しくは以下のリンクを参照してください。

indexOf メソッド (Array) (JavaScript)

リスト内にその日付がないなら-1が返されます。ですので、条件分岐として-1の時は何もしない、という命令をします。何もしない命令文は;らしいです。

developer.mozilla.org

  if(this_week.indexOf(change_date) == -1){
    ; // 何もしない
  }else{
    .............-1じゃなかった時の実行文...............
  }

セルの編集前の値と編集後の値を取得する。

前述のif文のelse以降は、編集された日付が一週間以内のものであるということになり、本格的な動作はここからになります。

e.oldValuee.valueを使うことで、セルの編集前の値と編集後の値を取得することができます。詳しくは以下のリンクを参照してください。セルの中身が空の場合はundefinedになりますので、その場合は[予定なし]という値で変数を書き換えます。

Event Objects  |  Apps Script  |  Google Developers

    //編集前の値を取得
    var old_value = e.oldValue;
    if (old_value != undefined){;}else{
      old_value = "[予定なし]"
    };

    //編集後の値を取得
    var change_value = e.value;
    if (change_value != undefined){;}else{
      change_value = "[予定なし]"
    };

Discordのwebhookを使って送信する。

必要な条件や情報は揃ったのであとはstr型としてメッセージを作ります。

    var message = "";
    message += "名前:  " + change_name + "  ";
    message += "日付:  " + change_date + "  ";
    message += "内容:  " + old_value + "  →  " + change_value;
    discord_bot(message);

GASを通して特定のユーザーにメンションを送りたい場合。

APIを通してdiscordで送信するとき、特定の人にメンションとして送りたい場合は開発者モード(デベロッパモード)になる必要があります。やり方は以下のリンクの通りです。開発者モードにて、メンションを送りたい相手のユーザーIDを取得します。数字で18桁のようです。

support.discordapp.com

messageにこのような形で入れてあげてください。<@xxxxxxxxxxxxxxxxxx>(xxxxxxxxxxxxxxxxxxは18桁のユーザーID)

    var message = "";
    message += "<@xxxxxxxxxxxxxxxxxx> ";
    message += "名前:  " + change_name + "  ";
    message += "日付:  " + change_date + "  ";
    message += "内容:  " + old_value + "  →  " + change_value;
    discord_bot(message);

ソースコードはこんな感じです。

function onEdit(e) {
  //e.****は更新時のシートやセルの情報
  var change_row_num = e.range.getRow();
  var change_colum_num = e.range.getColumnIndex();
  
  try{
    var change_name = SpreadsheetApp.getActiveSheet().getRange(2, change_colum_num).getValue();
  }catch(e){
    //log用日付の取得
    var today = Utilities.formatDate( new Date(), "Asia/Tokyo", "yyyy/MM/dd HH:mm:ss");
    Logger.log("名前の参照できない箇所での操作を検知" + today + "\n");
    return
  }
  //GoogleSpreadSheetの日付が特殊な記載方法ため、フォーマット例(Tue Jul 17 00:00:00 GMT+09:00 2018)
  try{
    var unformat_change_date = SpreadsheetApp.getActiveSheet().getRange(change_row_num, 2).getValue();
    var change_date = Utilities.formatDate(unformat_change_date, "Asia/Tokyo", "yyyy/MM/dd");
  }catch(e){
    var today = Utilities.formatDate( new Date(), "Asia/Tokyo", "yyyy/MM/dd HH:mm:ss");
    Logger.log("日付の参照できない箇所での操作を検知" + today + "\n");
    return
  };
  
  //今週の日付8つ分の日付(当日を含むため8日)が入ったリストを取得する。
  var this_week = this_week_days_dict();
  //もし日付内に存在しなければ何もしない。
  if(this_week.indexOf(change_date) == -1){
    ;
  }else{
    //編集前と編集後のセルの値を取得
    var old_value = e.oldValue;
    if (old_value != undefined){;}else{
      old_value = "[予定なし]"
    };
    var change_value = e.value;
    if (change_value != undefined){;}else{
      change_value = "[予定なし]"
    };    
    
    var message = ""
    message += "<@xxxxxxxxxxxxxxxxxx> ";
    message += "名前:  " + change_name + "  ";
    message += "日付:  " + change_date + "  ";
    message += "内容:  " + old_value + "  →  " + change_value;
    discord_bot(message);
  };
};

function this_week_days_dict() {
  var today = new Date();
  var this_week = new Array();
  for(var i = 1;  i < 9;  i++){
    var one_day = new Date(today.getYear(), today.getMonth(), today.getDate() + i - 1);
    var format_today = Utilities.formatDate( one_day, "Asia/Tokyo", "yyyy/MM/dd");
    this_week.push(format_today);
  };
  return this_week
};

function discord_bot(message) {
   省略
}

なんかtrycatchが増えてますが、実際はそういう感じで使ってる感じです。Logger.logdiscord_botに変更してもらってもいいのかも知れないです。そうしたらDiscordにエラーのログが出力されます。

あとがき

botを作ったきっかけ

前述の通り、出勤の日付は好きな時にインターン生さんが自分で決めることが出来ます。そこで少し困ったのが当日のAM01:00やAM02:00に出勤の予定を記入するという人がいました。当日の朝に更新されても、こちらも準備とかがあるので急な決定は困ったところがありました。

また、会社の事務所がスペースが狭くインターン生さんは少人数しかいれられないのですが、前日までは人数的にスペースの問題はないと思っていたら、当日の朝確認をしてみたら予定が結構増えていてビックリすることがありました。

そのため、インターン生さんにチャットツールを使って「出勤予定日を早めに連絡してほしい」旨をお伝えしていたのですが、伝えた当日から連絡がないということがあり、ホトホト困りました。コミュニケーションがとても難しいということ実感した瞬間でもありました。

であるならば、botを使って、シートに更新があったタイミングでデータを取得して、発報してもらうような仕組みを考えました。これで少なくとも私の確認が漏れるということはなくなります。

また、Discordというチャットツールとして出力されるので、編集されたタイミングがわかりやすいです。最もGoogleSpreadSheetsは編集履歴が残っているのですが、編集があったタイミングで確認できるというのはちょっといいかもと思いました。

さいごに

本当に必要なのは人間と人間のやり取りであって、botはきっかけレベルでいいと思うんです。そもそも、私とインターン生さんとの間のコミュニケーションがうまく行ってないのが問題だから。とはいえ、最近は気を使ってくれてるのか、それとも願いが届いたのか、インターン生さんもちゃんと連絡してきてくださるようになって、このbotそのものもそこまで重要な存在にならなくなってるのかなぁとおもってたりします。

唐突にうちの会社のあっぴるが始まる

なんとうちの会社では社員さんを募集中です。募集の内容は以下の通り。

【Web/ゲーム開発エンジニア】スタートアップで自由に開発

【企画職・マネージャー候補】あなたの「良いね」を形にする

Pythonで選択ソートアルゴリズムを作ろうの巻

Pythonで選択ソートアルゴリズムを作ろうの巻

こんにちは、葛の葉です。 今回は選択ソートについて、書いていきます。

選択ソートアルゴリズム

選択ソートについては以下を参照

選択ソート - Wikipedia

作ったの

def selection_sort(arrs):
    for i in range(len(arrs)):  # (1)
        min_num = min(arrs[i::])   # (2)
        j = arrs.index(min_num)
        (arrs[i], arrs[j]) = (arrs[j], arrs[i])  # (3)
    return arrs


test = [1, 2, 5, 8, 6, 7, 3, 4, 9]

print(selection_sort(test))

(1) … i はindexになりますね。

(2) … min(arrs[i::])arrs[i::][i::]iのindexから最後の要素までという意味になります。i~最後の要素までで一番小さいもののindexを取得します。

(3) … (arrs[i], arrs[j]) = (arrs[j], arrs[i]) は変数の交換ですね。Pythonらしい書き方になります。

追伸

アルゴリズム…これってダメなんかな…

Pythonでバブルソートアルゴリズムを作ろうの巻

Pythonバブルソートアルゴリズムを作ろうの巻

こんばんは、葛の葉です。最近、電車乗ってるときにスマートフォンPythonのプログラミングの勉強してます。やらない日もあるけど……ちなみにiPhone7を使用しています。

なお、使っているアプリはPythonista3です。

Pythonista for iOS

Pythonista 3

Pythonista 3

  • omz:software
  • Productivity
  • $9.99

f:id:Kuzunoha-NE:20181012191103p:plain

このアプリはPythonを実行することが出来るし、オリジナルな自分用アプリを作ることが出来ます。pipが使えなかったりgitが使えなかったりですが、iPhoneでカーソル移動が出来たりと結構かゆいところに手が届くアプリです。

アルゴリズムをやってみようって思ったんだ

アルゴリズムが出来ないのはよろしくないんだと、どっかで聞きました。どこかは忘れましたが、とにかくプログラマーがアルゴリズムを実装出来ないはよくないんだと。

どういうアルゴリズムが実装出来ないのがダメなのかがよくわからんけれども、とりあえずソートアルゴリズムは出来たほうがよかろうということで、とりあえず作ってみることにしました。

バブルソートアルゴリズムについて

バブルソートアリゴリズムについては、はてなキーワードにも載ってますね。

d.hatena.ne.jp

ソートとは並び替えのことで、ソートアルゴリズムは並び替えを実施するための仕組みです。

バブルソートアルゴリズムはリストの要素を読んでいき、その要素とその隣の要素のほうが大きい(または小さい)場合、値を取り換えるというものです。

それを繰り返していくことで降順、昇順にソートすることが出来るようです。

環境

Pythonista Ver3.2 Python Ver3.6.1

私のプログラミング例

私はこんな感じにプログラミングしてみました。

def bubble_sort(arrs):
    if type(arrs) is list:
        flag = True  ...(1)
        while flag == True: ...(1) 
            flag = False ...(1)
            for i in range(len(arrs)):
                if i == len(arrs) - 1: ...(2)
                    pass
                elif arrs[i] > arrs[i + 1]:
                    arrs[i], arrs[i + 1] = arrs[i + 1], arrs[i] ...(3)
                    flag = True
                else:
                    pass
        return arrs
    else:
        return 'list de ok' ...(4)


test = [1, 2, 5, 8, 6, 7, 3, 4, 9]
print(bubble_sort(test))

なんか、もっといいやり方があるような気がするけど、それは君自身で確かめてみてくれ!!!!

(1) ... フラグを作っています。隣の要素をみて、値を交換した時にこのフラグがTrueになり、繰り返しが再び始まります。逆に一回も交換しなかった場合、フラグはFalseのままとなりますので、繰り返しが止まります。

(2) ... len(arrs) -1 はlen(arrs)が要素数+1で出力されているため、-1しています。

(3) ... arrs[i], arrs[i + 1] = arrs[i + 1], arrs[i]Python特有の値の交換方法です tmp = a a = b b = tmp ということをやらなくていいのがpythonのいいところですね。(a + b) = (b + a)のほうが正しいみたいな話はどっかで聞いた気がする。

(4) ... 'list de ok'は引数がリスト型でない場合怒られるようにしています。

他のアルゴリズムもやってみたいです。

このアルゴリズムは勉強になるよ~ってのがあったら教えてください~

Mercari TECH CONF 18に行ってきました。「マイクロサービスプラットフォームチーム」のお話を聞いて。

Mercari TECH CONF 18に行ってきました

こんにちは、葛の葉です。

2018/10/04に行われましたMercari TECH CONFに行ってきました。

techconf.mercari.com

今回はそのときのことをお話しします。

キーワードは「MicroService」

speakerdeck.com

今回の公演ではMicroServiceという言葉をよく耳にしました。もともと、メルカリさんは大きなサーバを使用していたらしいのですが、そのサーバにはMercariAPIと呼ばれるメルカリの販売や記録などを取り扱っている複合的なAPIサーバがあります。巨大でかつ一つのサービスであるから、これをMonolithicと呼んでいました。最近では「小さなサービスの複合体」という体制に移行していて、それをMicroServiceとよび、これを「Google Cloud Platform(以下、GCP)」にて実運用しているとのことです。

「かつてのMonolithic」対「これからのMicroService」という比較による公演が多かったような気がします。もちろん、MicroServiceはサービス数が増える=複雑になるというデメリットもあるので、如何にそれに対処するかというところもお話されていました。また、そのMonolithicからすぐにMicroServiceに完全移行するのではなくて、2つを共存しつつ、段階的にどう移行するか、がよく話されていた印象です。

人数が増えて「チーム」というより「組織」になった

メルカリさんはたくさんの人を雇い入れることに成功し、2017年から2018年の間で、社員数が120人から350人にまで増えたとこのとです。これに伴い、「チーム」として開発していた感覚が「組織」っぽくなってしまったらしいです。(「組織」というには大げさかもしれない、ともおっしゃっていました。)特に裁量がなくなり、スピードが下がったり、思想でのぶつかり合いも発生したとのことでした。また、工程単位でチームにしていたので、その工程で「待ち」が発生すると「ボトルネック」になってしまうというデメリットを話されていました。

そこで工程単位ではなくサービス単位で開発チームを構成し、そのチームが各工程を全て行うようにした。デプロイから運用までサイクルのすべてを担うというとのことです。その方法については、チームが意思決定を行うので、裁量が高くなるとのことでした。一方で、そのデプロイから運用までのサイクルをどうチームが行うかが課題になったということです。

Kubernetesとマイクロサービスプラットフォームチーム

上記サービス単位でのチームがデプロイと運用までを簡単に行えるように、マイクロサービスプラットフォームチームというチームを作ったとのことです。マイクロサービスプラットフォームチームは開発チームがスムーズにデプロイから運用まで行えるように4つの工夫を行ったとのことです。

1つめに、APIゲートウェイという、クライアントからの要求に対し、MercariAPIとMicroServiceを分離させるサーバの構築を行ったとのことです。2つめに、サービスの単位となるContainerを起動させるKubernetesの採用を行ったとのことです。3つめに、MicroService間の通信にGRPCの採用を行いました。さらに、MicroServiceを一から構築するのが大変なため、テンプレートを作成したとのことでした。最後に、インフラ周りのアクセスはKubernetesの設定にてチーム単位で行うようにしたとのことです。

MicroService単位の開発チームの構成

以前までは、同じような価値観の人同士が集まるようなコミュニティになっていてサイロ化してしまっていたが、上記のように、MicroService単位でのチーム構成にすることで、チーム内の価値観の違う人通しでも多様な思想を巻き込んで開発が出来るようになったり、いろいろな能力を合わせることでシナジーを得ることが出来るようになったとのことです。また、それぞれのMicroService内で出来た知見などは共有できるようになり、より洗練されていったとのことです。

私見

ここからは私の私見ですけど、かつて、工場生産におけるセル生産方式なんてものがあったかなぁいうのを思い出しながら聞いていました。特にMicroService単位でチームを組み、ソフトウェアのライフサイクルを全部担当するという点が、なんだかそれを思い出させました。

工場といえばライン生産方式といって、コンベアから流れてくるものと、手持ちのパーツを組み合わせて次の工程のレーンに流すというのをひたすらに繰り返すというものが基本でしたが、90年代後半になると在庫数の問題の発生や生産数等をフレキシブルに対応するために、一人で殆どの組み立て工程を行うセル生産に着眼されるようになるんです。一人で、と言っても、ワンオペレーションというわけじゃないです。同じように殆どの工程を行う人を何人も雇うんです。

ほとんどの組み立て行程を一人でやることで、それぞれの工程で個々の組み立てにおける工夫だとかこだわりというのが出てくるんですよね。考えて生まれた工夫もあると思うし、偶発的に生まれた工夫もあるんだと思います。その工夫が同じようにセル生産で仕事をしている人同士のコミュニケーションを通して洗練され、組み立てのスピードは徐々に早まっていったと、聞いたことがあります。

大事なのは個性なんだと思います。(あと、それで生まれた情報を共有することも当然ですけど。)

イノベーションが生まれるタイミングについても同じ価値観の人より異なった価値観の人が集まったチームの方がよいとおっしゃっていたのも、なんとなくわかる気がします。

他にもメルカリさんの話は興味深かったです。

例えば機械学習で画像認識と感動出品という話も面白かったですし、MercariXについても気になることが山盛りでした。また別のタイミングでまとめたいと思います。