ごらくらいふ

プログラミングしたりゲームしたり

EntyのPayPal自動支払いがいつまでたっても停止しないのでPayPalでキャンセルした

大体の経緯

キャンセル問い合わせの流れ

PayPalのお問い合わせフォームにて以下を送信。

以下の自動請求IDについて、支払い期日がYYYY/MM/DDの分から受け付けられておりません。 自動請求ID

onetapが提供するサービスについても、同時期から提供を受けることができず、請求だけが加算されております。

サービス提供者に問い合わせても音沙汰がないため、Paypal様からキャンセルをお願いいたします。

PayPalから自動返信メールが届くので以下を返信。

PayPal

頂きました下記の例では解決いたしません。 お手数ですがご対応をお願いいたします。

2日弱くらいで返事Paypalからキャンセル処理の通知メールと、返信が届く。

心理的負担からの解放

健やかに月を跨げるようになった。

自分の.vimrcをgistからダウンロードする

gist idやraw_urlを目視確認してからcurlするのは人間のすることじゃない、ということで。

前提

  • jqが使える
  • curlが使える
  • gistにある.vimrcはpublicである
  • .vimrcはちゃんと.vimrcという名前にしている
  • 複数.vimrcがある場合は、一番ファイルサイズの大きい.vimrcを信頼する

結論

# curl https://api.github.com/users/yajamon/gists | jq 'map(.files | select(has(".vimrc"))) | max_by(.[".vimrc"].size) | .[".vimrc"].raw_url' | xargs -n1 curl > .vimrc

URL listをcurlにパイプで渡してダウンロードしたい

jqでURL取り出してCurlに引き渡したかった。(しかも1件だけ)

curl (標準出力 OR パイプ)」とかでggってもPostするデータをtextからとかそんなんばっか。

結論

# cat url_list.txt | xargs -n1 curl

xargsコマンドを使って指定したコマンドを並列実行させる - 技術メモ帳

xargsの使い方を探しに行ってやっと見つけたんだけど、この情報のたどり着けなさ、みんなマジで困らなかったの…?

メソッドの責任について考えたログ

エラー処理という名のガードレールが無いプログラミングを続けてきた。 慣れないことを考えたので思案のログを残す。

条件設定

あるコレクションのメソッドにて、引数の識別子に一致する要素を探し、仕事をさせる。 この時、引数が存在しないとき(undefined, null)デフォルトの値を使用する。

雰囲気つかみ

class Worker {
  digOilfield(): boolean{};
}

class WorkerCollection {
  workerList: Worker[];

  digOilfieldWithId(id: number): boolean{
  }

  takeDefaultId(): number {
  }
}

let workerCollection = new WorkerCollection();

digOilfieldWithId の引数に対して、どこまで不安になればいいのか考えていた。

思案1: digOilfieldWithId の中でデフォルトIDを取っちゃえ

class WorkerCollection {
  workerList: Worker[];

  digOilfieldWithId(id: number): boolean{
    if(!id){
      id = this.takeDefaultId();
    }
    this.workerList[id].digOilfield();
  }

  takeDefaultId(): number {
  }
}

let workerCollection = new WorkerCollection();

/* workerをかき集めたりする */

workerCollection.digOilfieldWithId(id);

一旦書いて、undefinedやnulllが問題じゃなく、Workerが逃亡しているかどうかのほうが重要だなと思った。

改善

class WorkerCollection {
  workerList: Worker[];

  digOilfieldWithId(id: number): boolean{
    if(!this.workerList[id]){
      id = this.takeDefaultId();
    }
    this.workerList[id].digOilfield();
  }

  takeDefaultId(): number {
    // 必ず有効なIDを返す
  }
}

let workerCollection = new WorkerCollection();

/* workerをかき集めたりする */

workerCollection.digOilfieldWithId(id);

「指定のIDに仕事をさせる」という名称なのに、居ないからという理由で他のIDに仕事をさせるのは、名前に嘘をついており”無責任”なのではと思う。

いると思ったID:10に仕事をさせたつもりが、じつはID:1が仕事をしてしまうのは使う側に対して無責任。*1

思案2: 使う側にちょっと手をかけさせる

class WorkerCollection {
  workerList: Worker[];

  digOilfieldWithId(id: number): boolean{
    this.workerList[id].digOilfield();
  }

  takeDefaultId(): number {
    // 必ず有効なIDを返す
  }

  existsWorkerWithId(id:number): boolean{}
}

let workerCollection = new WorkerCollection();

/* workerをかき集めたりする */

if( !workerCollection.existsWorkerWithId(id) ){
  id = workerCollection.takeDefaultId();
}
workerCollection.digOilfieldWithId(id);

確かに使う側が気を使って引数を厳選すれば回避できるかもしれないが、それは責務が違う。 それにdigOilfieldWithIdがまた隙だらけになってしまった。

思案3: digOilfieldWithIdもっと怒れ

class WorkerCollection {
  workerList: Worker[];

  digOilfieldWithId(id: number): boolean{
    if( !this.workerList[id] ) {
        throw Error("そんな奴ァいねぇ!!");
    }
    this.workerList[id].digOilfield();
  }

  takeDefaultId(): number {
    // 必ず有効なIDを返す
  }

  existsWorkerWithId(id:number): boolean{}
}

let workerCollection = new WorkerCollection();

/* workerをかき集めたりする */

if( !workerCollection.existsWorkerWithId(id) ){
  id = workerCollection.takeDefaultId();
}
workerCollection.digOilfieldWithId(id);

メソッドの名前と異なることをしちゃあいけない。でも有効な値だけをもらえるかもわからない。 いざ無効な値が来たときどうする。

もう怒るしかない。怒ることを使う側は知るべきだ。

思案4: 使う側は手間をかけたくない

class WorkerCollection {
  workerList: Worker[];

  digOilfieldWithIdOrDefaultId(id: number): number{
    if( !workerCollection.existsWorkerWithId(id) ){
      id = workerCollection.takeDefaultId();
    }
    return this.digOilfieldWithId(id);
  }

  digOilfieldWithId(id: number): boolean{
    if( !this.workerList[id] ) {
        throw Error("そんな奴ァいねぇ!!");
    }
    this.workerList[id].digOilfield();
  }

  takeDefaultId(): number {
    // 必ず有効なIDを返す
  }

  existsWorkerWithId(id:number): boolean{}
}

let workerCollection = new WorkerCollection();

/* workerをかき集めたりする */

workerCollection.digOilfieldWithIdOrDefaultId(id);

引数IDが無効ならばデフォルトIDを使うことを明言した。*2

この処理を使うということはデフォルトIDが使用されるかもしれないことを、使う側に認識させることができた。

とりあえずここで止め。

*1:そして副作用がID:1に起こってトラブルにつながるかもしれない

*2:流石に名前がおかしい気がする

typescript環境作りに2時間かかってたのでスクリプトを書いた

でもやめられない。

好みの構成はある。既存のコピーじゃ環境が古いままになるのはイヤ。

yeomanやってみようかと思ったけどまた学習コスト積むのもまたドツボに嵌りそうなのでシェルスクリプトでやる。

やった。

lessとかぜんっぜんないけど。

なお計測したところこのスクリプト作成に4時間かかったらしい。3回作ればもとが取れるわけだ。

generate project for typescript

参考リンク

抱き枕カバーを洗った

時が来た。 ここ3年ほど荒れていた布団事情が改善され、抱きまくら封印を解く時が。

ファーファの中性洗剤でカバーを手もみ洗い。汚れる桶。 封印前からの汚れが出るわ出るわで謝罪した。

封印期間も長過ぎたので週一で洗って改善したほうがよさそうだ。

乾くの待ってるぞ。 天使ちゃんマジ天使。

参考リンク

Everythingをアプリケーションランチャとして使う

Mac使ってると、spotlight検索でパパっとアプリケーションを起動できる点が本当に便利に感じる。

Windowsでも似たようなことできないかと思ってEverythingを取り出した。

Everything Search Engine

基本方針

  1. Desktopにショートカット集積ディレクトリを作る
  2. ディレクトリをEverythingで参照する

MacのApplicationディレクトリと違ってProgram Files中にある.exeの深さがまちまちだったり、.exeで検索すると求めていないものがマッチしたりする。*1

なので、使いたいアプリケーションへのショートカットリンクを集め、そこを検索する方針にした。

環境

何をした

ブックマーク追加

メニューからブックマークを追加した。

  • 名称をLaunchにした
  • 検索にpath:C:\Users\username\Desktop\shortcuts file:と指定した
  • キー割当はCtrl+Lとした

ワンタッチでEverything起動+Launchブックマークを使う

Launchのマクロ登録
  • Launchブックマークを編集する
    • マクロにlaunchと設定

f:id:yajamon:20161026110653p:plain

オプションを調整する
  • 全般->インターフェース
    • バックグラウンド実行を有効化
  • 全般->新規ウィンドウ時(Home)
    • 検索文字欄にlaunch:を指定
  • 全般->結果
    • ファイル起動時にeverythingを閉じる
  • 全般->キー割当
    • 新規検索ウィンドウにWin+Fを指定

f:id:yajamon:20161026110915p:plain

いい感じだ

Winキー -> 検索でいいんじゃないの

おもった。

まぁchromeでWebページをアプリっぽく開くショートカットはスタートメニューに出てこないから……

*1:chrome」でHitする大量のinstallerとか