覚えたら書く

IT関係のデベロッパとして日々覚えたことを書き残したいです。twitter: @yyoshikaw

オブジェクトストレージ

オブジェクトストレージについての自分用のメモです!

操作対象リソース

リソース 説明
アカウント ストレージサービスを利⽤するテナント
コンテナ オブジェクトを保存する⼊れ物
オブジェクト コンテナに保存するファイルの実体


オブジェクトストレージAPI

アカウントに対する操作

  • アカウントが所有するコンテナの⼀覧を取得
  • アカウントが所有するコンテナ数、バイト数、メタデータを取得
  • アカウントのメタデータを設定・更新

コンテナに対する操作

  • コンテナを作成
  • 空のコンテナを削除
  • コンテナに含まれるオブジェクトの⼀覧を取得
  • コンテナに含まれるオブジェクト数、バイト数、メタデータを取得
  • コンテナのメタデータを設定・更新

オブジェクトに対する操作

  • オブジェクトをダウンロード
  • オブジェクトをアップロードして、メタデータを設定
  • オブジェクトを削除
  • オブジェクトを別の名前でコピー
  • オブジェクトのメタデータを取得
  • オブジェクトのメタデータを設定・更新

WindowsでLinuxのtouchコマンドみたいなことをしたい

Linux の touch コマンド。利用用途はいくつかありますが、対象のファイルの更新タイムスタンプを現在日時の値に変更したいケースでよく使われると思います。

同じことをWindows上でもコマンド一発でやりたいことがあります。
DOSコマンドだけだと無理があるのでPowerShellの力を借ります。


具体的には、以下のようなコマンドを実行します。

powershell -C "(Get-Item {ファイルのパス}).LastWriteTime = (Get-Date)"


例えば以下のようなコマンドを実行するとカレントディレクトリの text001.txt というファイルの更新タイムスタンプを現在日時の値に変更できます。

powershell -C "(Get-Item .\text001.txt).LastWriteTime = (Get-Date)"


カレントディレクトリの .pdf ファイル(複数)の更新タイムスタンプをまとめて変更したい時は以下のようなコマンドを実行します。

powershell -C "Get-ChildItem -Path ".\*.pdf" | Where-Object { $_ -is [System.IO.FileInfo] } | ForEach-Object { Set-ItemProperty $_.FullName -Name LastWriteTime -Value (Get-Date) }"



関連エントリ

「ソフトウェア・ファースト あらゆるビジネスを一変させる最強戦略」

「ソフトウェア・ファースト あらゆるビジネスを一変させる最強戦略」 を読んでみました。


IT業界では、相当知名度の高い 及川さん が書かれた本だったので読む前からかなり興味津々でした。


内容紹介は以下のようになっています

MicrosoftやGoogleで世界標準の製品開発に携わってきた技術者が書き下ろす、
あらゆるビジネスが「ソフトウェア中心」に刷新される
今必要な次世代型サービス開発の要諦

AI活用、デジタル・トランスフォーメーション、SaaSをベースにしたサブスクリプションビジネスetc.今、
世界中の企業がITを駆使したデジタルシフト(事業のサービス化)を急いでいる。

日本企業がこの世界的潮流に取り残されないためには、かつての成功モデルである「製造業的ものづくり」から脱却し、
ソフトウェアを中心としたサービス志向の開発体制を構築することが重要だと著者は説く。

ソフトウェアがビジネスの中心を担い、インターネットがあらゆるビジネスの基盤となりつつある今、
日本企業はどう変化すれば生き残れるのか?

世界的IT企業で働き、現在は製造業をはじめとする日本企業の変革にも携わる著者が書き下ろす、
ソフトウェア・ファーストな開発論をぜひ読んでほしい。


本のカバー裏には以下の文言が書かれています。

ソフトウェアがビジネスの中心を担い、インターネットがあらゆるビジネスの基盤となった今、 日本企業はどう変化すれば生き残れるのか? すべてはIT活用を「手の内化」することから始まる!


この、「手の内化」するという言葉が本書の中にも何度か登場します。
それだけ重要だということです。


本の副題からも分かる通り、技術的に深い話を述べられたものではありません。

ITによるビジネスモデルの変革がどんどん進んでいる世の中で、日本の大手企業ではその流れから取り残されています。
IT化、デジタル化というものができているといっても、真の意味でのIT利用ができていない企業が圧倒的に多いと思われます。
この状況を変えるために 企業の戦略の中心に ソフトウェア を置く "ソフトウェア・ファースト" という考え方が重要になります。
どのようにすれば、真の意味でITというものを使ったサービスの提供や、DX(デジタルトランスフォーメーション)というものが進められるのかが書かれています。
基本的に、そういったものを推し進めるための 組織作り、文化の醸成、プロダクト開発 などの方法が書かれています。

極端な言い方をすると、実際の現場のエンジニアよりも、それよりも上のレイヤーのマネジャー層や経営層の方が読むのが一番良いように思います。
ただし、現場のエンジニアに対するメッセージも書かれていますし、エンジニアが読んでも十分過ぎるほどに価値があると思います。

筆者がこれまで、外資系企業、日系企業、さまざまな企業での多様な経験をされてきたからこそ書ける内容だと思います。
正直、この本の内容は及川さんが書かれているから説得力があるものだと思います。


本自体は極端に分厚いものではないので、短時間で読み終えられます。
ただ、そこに書かれた各種エッセンスは非常に濃いです。
いくつかの企業の事例や筆者の経験した内容も書かれており、参考にすべき部分も多いです。

ただし、この本の内容を単純にコピーして実践するのは簡単では無いと思います。
が、この本に書かれた内容を一種の軸にして組織作りや働き方について考える必要があると思います。


以下は私が書籍内で気になった部分の抜粋です。(自分用のメモです)

  • Webやスマートフォンが登場して以来、イノベーションはコンシューマサイドで起きています。一般ユーザとしてITを活用することが、ソフトウェア・ファーストを実践する第一歩と考えましょう。

  • いくつかの日本企業の相談を受けていると、残念ながらマネージャーが機能していないと思わざるを得ない現場が散見されます。
    マネージャーの職務は多岐に渡りますが、部下の成長をサポートするために一番大事なのは適切な評価です。・・・
    評価とは、部下が成長していくための気付きを与える行為です。定期的な人事考課の季節を待つのではなく、常に適切なタイミングでフィードバックをしなければなりません。そのためには、部下の能力を理解して、その能力を活かしたパフォーマンスを発揮しているか把握しておくことが大切です。

  • 「どこでも働ける」人材が、能動的に所属する組織を選んで働いているという状況は、その組織を強くします。と同時に、その人材は常に「どこでも働き続けられる」だけの努力を怠りません。個人の強さが組織の強さとなります。
    一方で、組織は強くあり続け、強い個人を惹き付ける努力を怠らないようにしないと、社員は「どこでも働ける」のですぐ流出してしまいます。この個人と会社との良い緊張関係がお互いを強くするのです。

  • 「創造性は制約を好む」(Creativity loves constraints):マリッサ・メイヤー氏の言葉

  • 自社内では新規事業だとしても、世の中全体を見渡して完全に新しいものを作ることはまれだと思うので、開発中のプロダクトを既存のカテゴリーにあてはめて命名するのはよくあります。しかしその瞬間から、人間の考えは固定化されてしまいます。心理学でいうアンカリング効果に近いことが起きてしまうのです。筆者はラベリングという言い方もしていましたが、開発中のプロダクトにどんなに新しいコンセプトを入れ込もうとしても、既存のプロダクトカテゴリーの名称で呼んでしまった途端に手垢のついた枠組みの中でしか考えられなくなってしまうのです。

  • 航空業界は80年代に予約システムの相互乗り入れを開始しました。本来ならば、ユーザーを奪い合う間柄です。・・・「新たな競合」である通信事業者にユーザーを奪われていたという背景があったためです。・・・航空便を使って移動し、対面で打ち合わせを行なっていたのが、電話会議の普及によって訪問しなくても打ち合わせが可能となり、ビジネス客が激減したのです。
    これなどは、ドメイン(業界)を超えたところに真の競合がいた例です。

  • どんな類のものでも、「変革」で全員が100%満足できるものを目指すのは不可能です。・・・考えなければならないのは、「今いる社員」を満足させるより「将来の社員」を満足させることであり、新たに価値を提供するユーザーの満足度を最大化することです。

  • 内製化が必要な最も重要な理由はノウハウの蓄積です。・・・現代のプロダクト開発は仮説検証の繰り返しです。多くの失敗の中から成功のきっかけをつかみ、それを育てていくことになります。結果だけ見ると成功しか見えないかもしれませんが、実はその裏にある多くの失敗と、そこから得た学びこそが財産となります。プロダクト開発の一部を外出ししていると、その知見が内部に蓄積されません。

  • 昨今はエンジニアが転職先を選ぶ時の一つの要件として、その会社に優れたCTOがいるかどうかを見るという風潮もあります。CTOがいなくても技術力が高くエンジニアを尊重している会社はありますが、CTOを置くくらいきちんと開発に取り組み、エンジニアの待遇や開発体制も整備されているかを判断材料にしている人もいるようです。

  • リファラル採用は自社の魅力を測るリトマス試験紙でもあるのです。


まとめ

私が何書いても仕方ありませんので、とにかく皆さんこの本を読みましょう!

Kotlin - ラムダにおけるスコープ内の変数アクセス・キャプチャ

今日も相変わらず 「Kotlinイン・アクション」 を読みながらの写経です。

Kotlinイン・アクション

Kotlinイン・アクション

  • 作者: Dmitry Jemerov,Svetlana Isakova,長澤太郎,藤原聖,山本純平,yy_yank
  • 出版社/メーカー: マイナビ出版
  • 発売日: 2017/10/31
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログ (2件) を見る


関数で匿名の内部クラスを宣言した場合、その関数の引数とローカル変数をそのクラスの中から参照できますが、
ラムダでも同様のことが可能です。関数でラムダを使用すると、関数の引数とラムダの前に宣言されているローカル変数を参照できます。

以下のコードでは、関数の引数の prefix, suffix と 関数内でラムダの前に宣言したローカル変数 title にアクセスしています。

fun main() {
    val messages = listOf("0 success", "1 Not super-user", "2 No such file or directory",
        "3 No such process", "4 Interrupted system call", "5 I/O error")

    printMessages(messages, "'", "'")
}

fun printMessages(messages: Collection<String>, prefix: String, suffix: String) {
    var title = "Message:"
    messages.forEach {
        println("$title ${prefix}${it}${suffix}")
    }
}


実行結果は以下の通りで、正常に各変数にアクセスできていることがわかります。

Message: '0 success'
Message: '1 Not super-user'
Message: '2 No such file or directory'
Message: '3 No such process'
Message: '4 Interrupted system call'
Message: '5 I/O error'


変数のキャプチャ

先ほどのコードを Java で記述すると大凡以下のようになります。

import java.util.Collection;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> messages = List.of("0 success", "1 Not super-user", "2 No such file or directory",
                "3 No such process", "4 Interrupted system call", "5 I/O error");

        printMessages(messages, "'", "'");
    }

    private static void printMessages(Collection<String> messages, String prefix, String suffix) {
        String title = "Message:";
        messages.forEach(
                msg -> {
                    System.out.println(title + " " + prefix + msg + suffix);
                });
    }
}

ここで重要なことはJavaのコードでのラムダ内で操作している変数は 実質的final であるため、変更ができません。
それに対して、Kotlinではfinal変数への参照だけに制限されていません。そのため、ラムダ内から変数を変更することもできます。


例えばJavaで以下のようなコードを書いてもコンパイルエラーとなってしまいます。(successCount, errorCountのインクリメント部分がエラーになります)

public class Main {
    public static void main(String[] args) {
        List<String> messages = List.of("0 success", "1 Not super-user", "2 No such file or directory",
                "3 No such process", "4 Interrupted system call", "5 I/O error");

        printMessages(messages, "'", "'");
    }

    private static void printMessages(Collection<String> messages, String prefix, String suffix) {
        String title = "Message:";
        int successCount = 0;
        int errorCount = 0;
        messages.forEach(
                msg -> {
                    if (msg.startsWith("0")) {
                        successCount++;
                    } else {
                        errorCount++
                    }
                    
                    System.out.println(title + " " + prefix + msg + suffix);
                });

        System.out.println("success count = " + successCount + ", error count = " + errorCount);
    }
}


これに対してKotlinでは以下のようなコードをコンパイルすることが可能です。

fun main() {
    val messages = listOf("0 success", "1 Not super-user", "2 No such file or directory",
        "3 No such process", "4 Interrupted system call", "5 I/O error")

    printMessages(messages, "'", "'")
}

fun printMessages(messages: Collection<String>, prefix: String, suffix: String) {
    var title = "Message:"
    var successCount = 0
    var errorCount = 0
    messages.forEach {

        if (it.startsWith("0")) {
            successCount++
        } else {
            errorCount++;
        }

        println("$title ${prefix}${it}${suffix}")
    }

    println("success count = $successCount, error count = $errorCount");
}

実行結果は以下の通りです

Message: '0 success'
Message: '1 Not super-user'
Message: '2 No such file or directory'
Message: '3 No such process'
Message: '4 Interrupted system call'
Message: '5 I/O error'
success count = 1, error count = 5


Javaとは違い、Kotlinはラムダ内からfinalではない変数を参照して、それを変更することも可能です。
上記コード例の prefix, suffix, successCount, errorCount などのラムダから参照される外部変数は、ラムダによって キャプチャ(caputure)されている と表現されます。

デフォルトでは、ローカル変数のライフタイムは変数が宣言されている関数によって制約されます。
ただし、ラムダによってキャプチャされた場合は、この変数を使用するコードは保持されて、あとで実行されます。
final変数をキャプチャすると、その値はそれを使用するラムダのコードとともに保持され、final変数でない場合はその値を変更できるようにとくべるなラッパーに囲まれ、ラッパーへの参照がラムダとともに保持されます。


注意点

ラムダがイベンハンドラのように用いられて、非同期に実行される場合、ラムダが実行された時に初めてローカル変数への変更発生します。
例えば以下のようなコードを書くと、この関数は常に 0 を返します。

fun countButtonClicks(button: Button): Int {
    var clickCount = 0
    button.onClick { clickCount++}
    return clickCount
}

onClickハンドラはclickCount(クリック数)の値をインクリメントして変更しますが、関数が返された後に onClickハンドラが呼び出されるため、変更されたクリック数を観測することはできません。


まとめ

Kotlinにおけるラムダのスコープ内の変数アクセスは、変数に対するキャプチャによってJavaと異なる操作が可能であることがわかりました。

Vimでの改行コードの可視化

今回のエントリは、MacOS環境で試してますので、Linux環境だと挙動が違うところがある可能性があります


vimでファイル触っているということは大概の場合において、行末尾の改行コードが LF なわけですけど。
WIndowsで作成したテキストファイルを作成すると 改行コードは CR+LF です。

場合によって、改行コードの LF と CR+LF が混在したファイルができていたりします。


vimで対象ファイルの改行コードを可視化する場合、以下を実行します

:set list


改行コードがLFの場合は、以下のように表示されます。($ が LF を意味しています)

aaaaaaa$
bbbbbbb$
ccccccc$
aaaaaaa$
aaaaaa$
1234567$
8901111$


行末尾が CR+LF だと以下のように表示されます。(^MがCR, $ が LF, を意味しています)

aaaaaaa^M$
bbbbbbb^M$
ccccccc^M$
aaaaaaa^M$
aaaaaa^M$
1234567^M$
8901111^M$


改行コードに LF と CR+LF が混在していると以下のように表示されます。

aaaaaaa^M$
bbbbbbb^M$
ccccccc^M$
aaaaaaa^M$
aaaaaa^M$
1234567^M$
8901111^M$
^M$
^M$
abcdefg$
hijklmn$
opqr$


そもそも CR+LF のファイルであれば ^M は最初から表示されているはずです。

もし表示されていないようであれば以下を実行します

:edit ++ff=unix


ちなみに、fileコマンドで改行コードが CR+LF のファイルを確認すると以下のようになります。

$ file sample.txt 
sample.txt: ASCII text, with CRLF line terminators


fileコマンドで改行コードに LF と CR+LF が混在しているファイルを確認すると以下のようになります。

$ file sample3.txt 
sample3.txt: ASCII text, with CRLF, LF line terminators


というわけで、改行コードを可視化できたのでこれで良しです。
(普通は改行コードを変換するところまで書くのがワンセットな気がしますが笑)