Heppoko Binbo Yarou no Newbie Nikki

旧題: へっぽこびんぼう野郎のnewbie日記 #vZkt8fc6J

オブジェクト指向で書いてて思ったことについてだらだらと書いてみる

class Data:
    def __init__(self):
        self.a = 13
        self.b = 4
        self.c = 8
        self.d = 12


data = Data()

↑のようなデータがあるときに、↓のようなコードをたまに見かけるときがある。↑のコードは失敗とかじゃなくて、モックだと思ってください。

class Calculator0:
    def __init__(self, g):
        self.g = g

    def calc(self, data):
        a = data.a if data.a % 2 == 0 else 1

        added = a + data.b
        subtracted = data.c - data.d
        calced = added / subtracted
        multiplied = calced * self.g
        return multiplied + 1


calculator0 = Calculator0(g=2)
print('0', calculator0.calc(data))

実際にはこんな単純じゃなくて、 + とか - のとこはもっと複雑なロジックで、 calcメソッド は、もっと行数がずーーーっと長く続いているもんだと思ってください。

個人的にこう書いてしまうときは、最終形がどうなるのかあんまりわかってなくて、 AしてBしてCしたらDになる みたいな感じの思考のときが多い気がしている。オブジェクト指向じゃなくて、手続き型っぽい感じでコードを書いてるときにそうなりがち。

そういうときに下手にコードをオブジェクト指向っぽくしようとして、

class Calculator1:
    def __init__(self, g):
        self.g = g

    def add(self, a, data):
        self.added = a + data.b

    def subtract(self, data):
        self.subtracted = data.c - data.d

    def multiple(self, b):
        self.multiplied = b * self.g

    def calc(self, data):
        a = data.a if data.a % 2 == 0 else 1

        self.add(a, data)
        self.subtract(data)
        calced = self.added / self.subtracted
        self.multiple(calced)
        return self.multiplied + 1


calculator1 = Calculator1(g=2)
print('1', calculator1.calc(data))

こんな感じにしてしまったことが、昔たまにあった。これはさっきよりも最悪で、一見名前がついてわかりやすくなったふうに見えて、 オブジェクトが依存しているかもしれない度 がものすごく上がっている。要はローカル変数だったものを、クラス内全体に広げてしまったことで、コードを読むときに他から影響を受けてないか確認する手間が増えている。仮に addメソッド の中で self.added に代入してなかったとしても、 calcメソッド の中で self.add が使われているので、 addメソッド へselfの値が変わっているかどうかを確認しに行かなければいけなくて、恐怖心が増加する。いわゆる、なんちゃってオブジェクト指向

じゃあ関数型っぽく書けばいいのかと思って、↓みたいにすると、

def return_1_if_odd(n):
    return n if n % 2 == 0 else 1


def add(a, b):
    return a + b


def subtract(a, b):
    return a - b


def multiple(a, b):
    return a * b


def wrap(g):
    def calc(data):
        return (
            multiple(
                (
                    add(return_1_if_odd(data.a), data.b) /
                    subtract(data.c, data.d)
                ),
                g
            ) +
            1
        )
    return calc


print('Functional', wrap(2)(data))

別にこれはこれでいいんだけど、そうするとオブジェクト指向の利点が消滅する。Pythonでやる意味ないのではって感じがする。

そういうわけで、↓のように書き直してみると……

class Util:
    @staticmethod
    def return_1_if_odd(n):
        return n if n % 2 == 0 else 1

    @staticmethod
    def add(a, b):
        return a + b

    @staticmethod
    def subtract(a, b):
        return a - b

    @staticmethod
    def multiple(a, b):
        return a * b


class GConfig:
    def __init__(self, g):
        self.g = g


class EasyCalculatedData:
    def __init__(self, origin_data):
        self.origin_data = origin_data

    @property
    def data(self):
        a = Util.return_1_if_odd(self.origin_data.a)

        added = Util.add(a, self.origin_data.b)
        subtracted = Util.subtract(self.origin_data.c, self.origin_data.d)
        return added / subtracted


class CalculatedData:
    def __init__(self, origin_data, config):
        self.origin_data = origin_data
        self.config = config

    @property
    def data(self):
        easy_data = EasyCalculatedData(self.origin_data)
        multiplied = Util.multiple(easy_data.data, self.config.g)
        return multiplied + 1


config = GConfig(g=2)
calculated_data = CalculatedData(data, config=config)
print('2', calculated_data.data)

正直題材がびみょい気がするので利点が見えにくいけど、こうすると拡張もできて、あんまり脳を使わずにコードを読むことができて嬉しいなぁと思っている。もしコードをコピペされても害があんまりなくておすすめ。

ただコードが短いやつしかないときはここまでやるのはやりすぎ感がある。短いときは一番最初のやつでもいいし、単にUtilの関数群として切り出すだけなのが手っ取り早いけど、長くなってきたときにこうすると分離したり別のクラスをプラグイン的に使えたりモックでテストできてレゴ的嬉しさもある(´・ω・`)

結局どうするのが正解なのかはよくわからない。

とりあえず2番目のやつは最悪なのでやってはいけないと思う(´・ω・`)

ブックマークに入っているいろいろなサイトについて細かく分類してみた

はじめに

基本的には、未分類 TODO リンク アーカイブ の細分化になっていると思います。

目次

  • Inbox
  • Read It Later
  • Deal It Later
  • Links
  • Digested

Group Of Inbox

New

  • 新しく入ってきたブックマークのこと。とりあえず有用だと思われたすべてのサイトへのリンク。

Stray Dog

  • 別の分類に入ってしまっている謎のリンクのこと。通常本来の分類が存在する。

例:数学フォルダに入っている「ショートケーキの作り方」

Group Of Read It Later

Read It Later Repeatedly

  • 常習的にその後何度も読むべきタイプだと判断したものへのリンク。そんなに多くは存在しない。

例:自分の好きな作家の詩

Read It Later

  • あとで読もうと思って、未着手のまま放置している記事へのリンク。基本的にその記事の中でほとんど起承転結している。

例:長文のブログ記事

Waiting For Update

  • 更新されたときに限り読みに行く記事へのリンク。そもそもブックマークで管理するべき類のものではなく、更新されたときに通知が行くようにRSSなどであらかじめ設定しておくべきタイプのもの。

例:お気に入りのユーザーのブログ記事

Abandoned

  • 途中まで読んだが、何かの理由ですべて読むことが放棄され、それでも「まだ有用」だと思われて投げ出されている記事へのリンク。

例:難しい記事

Tsundoku

  • 有用だと判断してブックマークはしたが、量が膨大なために読むことを放置しているサイトへのリンク。いつ読むのかを決めないと永遠に読まれることはない。Read It LaterやAbandonedとの明確な違いは、それを読むために勇気が必要なところ。

例:「C言語を30日で学ぼう!」のようなサイト

Group Of Deal It Later

Deal It Later

  • その後のプロセスを保留しているサイトへのリンク。プロセスというのは「読む・視る・聴く」こと以外が入る。誰かに紹介するためにブックマークしたとか、あとで見ながら作業をするためにとりあえずブックマークしたとかいうもの。

例: Amazonでほしいものリストに入れようとしたらエラーになった商品

Curated Site

  • 「有用である」と思ったものが集められた一覧へのリンク。全く読んでないものも、一部は読んだがその後のプロセスが全部完了していないものも指す。そこで示されているものが、まだ血肉となっていないもの。キュレーション記事に単なるキュレーション以上の情報が多く載っている場合は、Read It LaterやAbandonedに分類される。

例:「都内にあるオススメのパン屋ベスト100!」のような記事

Group of Links

Sugar Link

  • 情報が蓄えられているというよりも、無くてもたどり着くことはできるが、より早くたどり着くためのリンク。

例:Github

Archived Sugar Link

  • Sugar Linkのうち、あまり使わないリンクのこと。

例:国立国会図書館

Group of Digested

Archived

  • 情報は消化し終わったが、依然として有用であると判断し、いつかのときのために保存しており、かつ未分類のリンク。あまり読むことはない。

例:「部首の成り立ちとは」のようなサイト

Categorized

  • 情報が消化し終わり、あとで引き出しやすいように分類されたもの。情報が多くなればなるほどカテゴリが小分類化される。ある意味、記事化されていないCurated Siteのこと。

例:英語→「英語の文法はなぜ大事か」「語彙を増やすには」などの記事群

おわりに

誰かの何かの参考になれば幸いです。GTDをたたき台にして自分で考えてみました。不備があれば教えてくださるとありがたいです。

しばらく使ってないタブを閉じてくれるTabWranglerというプラグインが便利な件

タブが増えすぎたときに、しばらく使ってないタブを自動で閉じてくれるやつ

「タブが5個以上のときに限り、20分間使ってないタブは閉じる。ただしGitHubYoutubeは閉じない」というようなことができて便利。数値など自分でカスタマイズできる。

Firefoxでも使えるらしい。

chrome.google.com

一点不満なところがあって、新しくタブが開いたときに時間のカウントがスタートするのが嫌だった。

ぼくは新規タブを開くときに「とりあえず開いておいてあとで読む」癖があるので、「はじめてタブに移動したときにカウントスタート」というふうにしたかった。

なので、プラグインの中の app/background.jschrome.tabs.onCreated.addListener(onNewTab); のところをコメントアウトして、 const onNewTab = の定義のところもコメントアウトしてビルドし直したものを使っている。

ビルド方法は package.json に書いてあるとおり、普通に npm i して npm run build

ハック的な変え方なので、 NaN:NaNpopup.html の画面に出るけど気にしてはいけない。

github.com

Vimのjedi-vimでpythonのGoToDefinitionのためにctagsでいろいろ定義のIndexを集めるためにやること

まず exuberant-ctags をインストールする。

Macなら

Exuberant Ctags

からダウンロードして、↓のようにインストール。将来バージョンが変わるかもしれないのでそのへんは脳内補完でお願いします。

$ tar -xzvf ctags-5.8.tar.gz 
$ cd ctags-5.8
$ make
$ sudo make install

これで /usr/local/bin/ に置かれるので、そのctagsを使って

$ ctags -R --fields=+l --languages=python --python-kinds=-iv -f ./tags /path/to/your-project-file
$ ctags -R --fields=+l --languages=python --python-kinds=-iv -f ./tags $(python -c "import os, sys; print(' '.join('{}'.format(d) for d in sys.path if os.path.isdir(d)))")

Done.

Ctrl + ] (定義へ) / Ctrl + o (1つ前に戻る) / CTRL-^ (1つ前のファイルに戻る) で幸せになれます。

Navigating your Django project with Vim and ctags | Fusionbox

1×mn行列になっているデータをm×n行列の表にしてGoogle Spreadsheetとかに貼りたいときにつかうスクリプトつくった

f:id:haruharu1:20181108163823p:plain

$ python3 product.py g.md
        A       B       C
1
2
3
4
$ python3 product.py g.md --transpose
        1       2       3       4
A
B
C

gist.github.com

Macならこんなふうにするとクリップボードにコピーできていいですね

$ python3 product.py g.md | pbcopy

結果

f:id:haruharu1:20181108164444p:plain

感想

びみょす

What I did when an error saying only "Error creating health check." occurred while creating health checks on AWS Route 53

1. Sign out.

2. Log in again.

3. This time, I refrain from creating new SNS Topic. Just concentrate to create a health check.

4. I don't know why it worked, but anyway, you can create a health check as if that error didn't happen.

If you replay this situation, you should throw inquiries to AWS.