2018年

1年を振り返ります。いろいろやってた気がしてけどそうでもなかった。あと月で偏りがある。


1月 たぶん仕事してた

2月 サービスローンチ

3月 面接に加わる

4月 勉強会登壇、ダテカン13回定期、柏交響楽団エキストラ

5月 広島ひとり旅

6月 バンドアレンジ、植樹

7月 オペラ祭り、部長陣議論ファシリ

8月 マインドフルネスの会、イタリア演奏旅行

9月 北海道、秘密のプロジェクト

10月 技術書典

11月 朝日新聞デビュー、初プロレス観戦、phantom参加

12月 人事部へ異動、ダテカン14回定期、大喜利

 

ま、でもいろいろチャレンジできた1年でした。これからはチャレンジだけじゃなくて成果に繋げていきたい所存。

Clean Architecture より、3つのプログラミングパラダイムの本質

読んでいます。

Clean Architecture 達人に学ぶソフトウェアの構造と設計

Clean Architecture 達人に学ぶソフトウェアの構造と設計

第3章~第6章で、3つのプログラミングパラダイムについて語られています。

Uncle Bob (著者の愛称) いわく、これらそれぞれはプログラマーに何か能力を与えるのではなく、プログラマーの能力を制限している。すなわち「何をすべきではないか」を規定しているのだ。構造化プログラミングは直接的な制御の移行 (goto) を封じ、それてによってプログラムの反証可能性を確実なものにする。オブジェクト指向プログラミングはポリモーフィズムによる依存関係逆転によって、制御の移行の方向を制限する。関数型プログラミングは、変数を固定にし、代入を制限する。これらによって、コードベースに秩序がもたらされる。

これは味わい深い話だ。コードベースでは数十年にわたってこうした「何をすべきではないか」を学んできた。アーキテクチャレベルではどうだろうか?恐らく「どんな実装をすべきでないか」を完全に制御できるようなアーキテクチャは現実的ではない(実装者に依存する)だろう。これをどうやって規定し担保していくか、がソフトウェアアーキテクチャの難しさだろう。たとえば Microservices Architecture は最近、山のように「すべきではない実装」が書籍だったりブログだったりで報告されているが、それらを厳密に体系立てられたパターンとして制限できるような仕組みが生み出されるには至っていない。ソフトウェアアーキテクチャはまだまだ進化の途中だ。

IT 関連のややこしい用語

IT 関連の用語は使い所によっていろんな意味をもってややこしい。ざっと思いついたものを挙げる。

フロントエンド

  1. Web アプリケーションにおける、ブラウザに動作させる実装。 HTML/CSS/JavaScript など。 クライアントサイド。「フロントエンドエンジニア」と言った場合はこれを指す。
  2. 機能をユーザーが触れるようにするもの。これ自体が Web アプリケーションを指す場合もある。アプリケーションA (バッチ) が処理結果をDBに保存し、アプリケーションB (Web) がその情報を画面に出力する、といった場合は「アプリケーションBはアプリケーションAのフロントエンド」と呼んだりする。

アプリ

  1. スマホアプリ。スマートフォンで動作するアプリケーション。
  2. PC アプリ。 Windows なら .exe、 Mac なら .app など。
  3. アプリケーション。 Web アプリケーションなど。 1. および 2. を含む。

特に口頭で「アプリ」と言った場合はなぜか 1. を指すことが多い。携帯電話→ケータイ、みたいな。

リポジトリ

  1. Git などバージョン管理システムのホスト先。Git であれば GitHub など。
  2. npm などパッケージマネージャのホスト先。
  3. Repository Pattern の実装。

サービス

  1. ユーザーが認識する単位の Web サービス。
  2. 機能単位のサービス。マイクロサービス、SAOなど。
  3. Windows サービス。

Atom

  1. GitHub が開発するテキストエディタ
  2. コンテンツ配信用のプロトコルRSS 的なやつ。
  3. Intel の CPU ブランドの名称。

Unity

  1. 3D に強いゲーム開発エンジン。 https://unity3d.com/
  2. DI コンテナ。 https://github.com/unitycontainer/unity

いずれも C# 関係なのが余計にややこしい。

エンジニア

GAS で Google カレンダーの1日の空き時間を取得する

最近予定が詰まっているのでスキマ時間がどれくらいあるのか取得したくなった。ので GAS で書いた。

function myFunction() {
  const calendar = CalendarApp.getCalendarById('hogehogei@example.com');

  const date = new Date();
  
  const freeTime = getFreeTimeMinutes(calendar, new Date());

  // あとは気分に応じて Slack に投げたりする
}

function getFreeTimeMinutes(calendar, date){
  const events = calendar.getEventsForDay(date);
  
  // 終了時間の昇順にした後に開始時間の昇順にする
  const sortedEvents = events.sort(function(a, b) {
    return a.getEndTime() - b.getEndTime();
  }).sort(function(a, b) {
    return a.getStartTime() - b.getStartTime();
  });
 
 // 時間がかぶっている予定をひとまとめに `block` とする
  const blocks = [];
  var block = {
    start: sortedEvents[0].getStartTime(),
    end: sortedEvents[0].getEndTime()
  };
  
  sortedEvents.forEach(function(event) {
    const start = event.getStartTime();
    const end = event.getEndTime();
    
    if(block.end < start){
      blocks.push({
        start: block.start,
        end: block.end
      });
      block.start = start;
      block.end = end;
    }
        
    if(block.end < end){
      block.end = end;
    }
  });
  
  blocks.push({
    start: block.start,
    end: block.end
  });
  
  // 9:30 - 18:00 を定時とする
  const bizStart = new Date(date.getYear(), date.getMonth(), date.getDate(), 9, 30, 0);
  const bizEnd = new Date(date.getYear(), date.getMonth(), date.getDate(), 18, 00, 0);
  
  // 完全に業務時間外の予定を省く
  const filteredBlocks = blocks.filter(function(block) {
     return bizStart < block.end && block.start < bizEnd
  });
  
  // 業務時間から溢れた分をカットする
  const cutOffBlocks = filteredBlocks.map(function(block){
    if(block.start < bizStart) block.start = bizStart;
    if(bizEnd < block.end) block.end = bizEnd;
    
    return block;
  });
 
 // 業務時間内で重複を取り除いた予定の合計時間
  var sumMinutes = 0;
  cutOffBlocks.forEach(function(block) {
    sumMinutes += (block.end.getTime() - block.start.getTime()) / (1000 * 60);
  });
  
  const bizMinutes = (bizEnd.getTime() - bizStart.getTime()) / (1000 * 60);
  
  return bizMinutes - sumMinutes;
}

業務時間外を省いているのは、飲み会とかの予定も入ってるから。 休憩時間とかフレックスは未対応です。

もっと効率よく書ける気はしている。

Function App リクエストサイズの上限

Function App に HTTP で Post するときのサイズ上限は web.config でデフォルト値が指定されている。 v1.x では 100MB だそうだ。

azure-functions-host/Web.config at v1.x · Azure/azure-functions-host · GitHub

でも v2.x では指定されてない。

github.com

既定値だと 4MB だけど、この値がそのまま使われるんだろうか??(未検証)

HttpRuntimeSection.MaxRequestLength Property (System.Web.Configuration) | Microsoft Docs

結婚式二次会のBGM #2

3月に友人の結婚式があり、二次会のBGM選曲などを担当しました。

基本的には 3年前に担当したとき と変わらないですが前半の新しめのパートを割と変えました。

youtu.be

youtu.be

youtu.be

youtu.be

youtu.be

youtu.be

youtu.be

youtu.be

youtu.be

youtu.be

毒気のない曲を探すのが意外と面倒なわけですが、誰かの参考になれば。

Table Storage は Count できないよ

タイトルのとおりで Table Storage は件数を取得するための API が無い。愚直に全件取得するしかない。 せめてレスポンスを軽くするための手段として、 PartitionKey だけを Select するという手段がある。

var query = new TableQuery<DynamicTableEntity>()
    .Select(new string[] { "PartitionKey" });
var count = table.ExecuteQuery(query).Results.Count;

ただし単発のクエリは最大1000件までしか返ってこないので、セグメント化する必要がある。

var count = 0;
var query = new TableQuery<DynamicTableEntity>()
    .Select(new string[] { "PartitionKey" });
TableContinuationToken token = null;
do
{
    var queryResult = table.ExecuteQuerySegmented(query, token);
    count += queryResult.Results.Count;
    token = queryResult.ContinuationToken;
} while (token != null);

しょっちゅう Count するべきものじゃないんだろうな。