Make組ブログ

Python、Webアプリや製品・サービス開発についてhirokikyが書きます。

ツールやプロセスやメソッドも大事だけど、人や中身や見えない文化も大事だと思っている

僕はツールとかプロセスじゃない、人とか中身とか文化とか空気感みたいなのが大事だと思っている。 自分自身、エンジニアというか、ステレオタイプのThe工学の人間的な発想じゃないのは思ってる。

まず最初に。開発メソッドとかツール、プロセスっていうのは僕もすごく大事だと思う。 見えないものを形式知やプラクティスとすることで、誰でも恩恵に預かれるようになる。これはスゴいことだと思う。 考え方や「うまいやり方」をプロセスに落とし込んでおけば、より多くの人がよりよい仕事ができる。 例えば PyQ のチームでも匠メソッドでの要求開発をしていたり、いわゆるアジャイル的な開発スタイルを取っていたりする。

でも僕は、もっと人とか中身とかも大事だと思っている。プロセスみたいに見えてないけど、個々人とかチームの中にあるものが大事だと思っている。

どんなツールとかプロセスを使っていても、中で作ってる人の発想とかセンス的な何かで変わってくると思う。 良いチームでも遠慮しあってお互い言いたいことを言わなかったら妥協したものができると思う。 チームの信頼関係がなかったり変な競争があれば、どんなチームビルディングメソッドを使っててもダメだと思う。

例えばPyQチームだと僕はお互いに何でも率直に言うようにしている。チーム内で厳しい意見が出ることもある。 でも僕はその文化はすごい良いなと思う。やりにくいと思う人はいるかもしんないけど、製品には良いように働いてると思うし、僕はやりやすくて楽しいチームだと思ってる。 企画から自分たちでビジョンを追いかけて作ってるので、ちょっとでもブレるとすぐに要らないものになってしまう。 小さなチームなので、そうなっちゃえばすぐに続けられなくなって製品もチームも死んでいってしまうと思う (金銭的に生きながらえても、モチベーションもないゾンビプロジェクトになってしまうと思う)。

これはプロセスじゃなくて、PyQチーム内の文化だと思う。 「率直な意見交換が大事」って形式値化したり、意見交換を挙手制にしたりプロセスは作れると思う。 でも中の一人ひとりがどう考えて何を言って何を作るかですべては変わってくる。ここの部分に「中身」の大切さがあると思う。

僕は「プロセスが不要」みたいなことは一つも思ってない。ただ、プロセスとかメソッドは見えやすいので色んなところで語られるので、アンチテーゼとしてこの主張はしたいなと思ってる。 メソッドに対する中身、文化、空気感はあんまり語られないし、語られてもすぐ陳腐になっちゃう。まぁこの記事もただのエモ文章だと思う。 中身は毎度まいど新しくゼロから作らないといけないし、他にも転用できないものだと思う。だから見えにくい。

プロセスはそういうものを促進する触媒であったり、補正具にはなると思う。自転車といっても良いかもしんない。 それが超大事なのは僕も思う。人間の進化はツールの進化だと思う。でも、中身を無視しちゃいけないと思う。 データ構造が良くないとどんなプログラミング言語を使ってもうまくは書けないのと同じ。

そういうのは中身は毎日働く中で少しずつ積み上げていくしかないし、個人が人生の中で感じたものとか、触れてきた感動からくるものだからどうしても見えないと思う。

僕はどっちも大事だと思ってる。 でもツール、プロセス、メソッドが見えやすいからこそ、アンチテーゼとして人とか中身が大事だよっていうのは自分の中に持ち続けたい。

どこにでも通じる「これやったからうまくいった」ってことはないんじゃないかな。

軽いi7のノートパソコンにUbuntu入れたいならASUS ZenBook Flip S をオススメしたい

こんなノートパソコンが欲しい人にオススメしたい

  • Intel Core i7 第8世代(Kaby Lake Refresh)4コア
  • モリー16GB
  • 13インチ
  • Full HD
  • 重さ1kg
  • USB-C給電
  • Ubuntuがインストールできた
  • キーボードが悪くない

ASUS ZenBook Flip Sをオススメしたい

f:id:hirokiky:20180720183224j:plain

ASUS ZenBook Flip S、UX370UAをオススメしたい

スペックは上記の通り、8世代i7、メモリー16GB、13インチFull HD、1.1kg、512GB SSD、USB-C給電。USB-Cが2ポート。 何気に音も良い。

www.asus.com

Amazonのリンクはこれ。

見た目はぶっちゃけMacBook Airを模したもの。1.1kgは超軽い。 Airっぽいデザインはどうしても好きなんですよね。2008年の茶封筒の呪いがかかってる。

スペック的には、まぁ僕も、メモリー32GB欲しかったとか、1TB SSD欲しかったとかはある。 そこはSwap使うとか、そもそも1TB要らんよなとか思って妥協した(前のマシンは100GBのSSDだったから十分多い)

ぶっちゃけ、ついてるけど使ってない機能もある

「いやこれ要らないならもうちょい廉価なほう買うわー」って思うかもしれんけどね、 USB-C給電はマジ最高なんでオススメしたい。あとで話す

Ubuntu入るの?

ここ。ココ重要。 Ubuntu入れてまともに動くのっていうのは大事。ぶっちゃけPC買ってもそこはほぼ博打だからね。 ウン十万円の文鎮はホントにご利益もクソもないからね。

でも大丈夫、 デュアルブートUbuntu 18.04入りました

ただ ぶっちゃけインストールでハマったからこの記事読んで

blog.hirokiky.org

僕ほんとUEFIとか初めてで本当にハマったけど、なんとかアレコレ試してあっけなく解決したのでこれ見て。 他は何の問題もない 。もちろん何かあったら自分で解決してください。。

ただ指紋認証は動いてない。まぁ、要らないかなぁと思っている。 他はキーボード光ってるしWifiBlueTooth動いてるし良いと思う。 ファンが暴走したりもしてないし、当たり前にちゃんと動いてる。

Ubuntuだとディスプレイ変換のドライバーとかでダメなんでしょ?

大丈夫だった から安心してほしい。

純正で付いてきた「USB-C対HDMI、USB、USB-C」のハブは問題なく画面の表示もできた。 あと、下の 9 in 1 のハブでも画面出力もできた。すごい。

これはめちゃくちゃ嬉しかった。

ドライバーとかまた大変なのかなと思ってたので動いて嬉しい。 USB-Cの仕様には詳しくないけど、そういうものなの?

まぁ、こんな感じで、キーボード、マウス、充電用USB-C、HDMIをさして使ってる。

f:id:hirokiky:20180720172745j:plain

USB-CとUSB PDがすごい

USB-Cはすごい。給電できる(USB PDの)USB-Cポートあるノートパソコンがオススメ 。 僕も 「USB-Cだけって拡張性ゼロやん」とか思ってたんだけど、違う

USB-Cはぶっちゃけハブが繋げればそれで良い

拡張性の機能を、すべてハブに任せるのがUSB-Cだと気づいた。 家に帰ってくれば1つのポートにハブを繋げば良いだけ。 「HDMIさして、USBマウスとキーボードさして、充電器さして。。。」とかダルい。

USB-Cだけを1本させば良いようにしてこそのものだと思う。 1本で済むんだよ、すごくない。僕ここ最近で一番これに感動したよ。

ただ買ったハブにはHDMI1つしかついてないので、3つ目のディスプレイがさせない。 もう一個HDMIVGAのポートがあるハブにしたら良かったと思ってる。

とにかくUSB-Cと給電できるハブは良いし、Ubuntuでも動いてる。

USB-Cにさして本体にくっつけるThinkPadベーシックドックみたいなハブもあるけど、あれはナンセンスだと思う。USB-Cの意味ないと思う。

タッチパッドとかキーボードはどうなの

ASUS ZenBook Flip Sはタッチパッドは大きめです。感度も良い。ただタッチパッド全体で押し込んでクリックできないのは残念。 パッドの下部だけがクリックできます。タップでのクリックはできるけどね。 まぁ、apple製品じゃないってことを考慮したら、かなり良いレベルだと思う。 でもapple製品を期待すると3分の1くらいのレベル。

キーボードは「悪くない」くらい。この辺は店頭で確認してほしい。 このサイズのノートパソコンにしたら、しっかりしてる方だと思う。 ただ、ぶっちゃけ Enterキーが入りにくい 。そこはかなりイマイチだと思う。 「跳ね返りが強すぎて疲れる」みたいなことはない。その点では十分良いキーボードだとは思う (メインで使う家だと外部のキーボード使うし)。

充電持たないんでしょう?

まぁ、カタログだと8時間と言ってるけど、Emacsでプログラミング + Dockerでアプリサーバー起動などしてると5、6時間くらい。 JSとかCSSも頻繁にビルドしてると5時間ってところかな。

十二分にあるとは言えないけど、まぁカフェで仕事するなら充電器はいらない。その前にルノアールなら緑茶がいっぱいになる。

でもお高いんでしょう

秋葉原ヨドバシカメラで193,160円。

f:id:hirokiky:20180717121546j:plain

Amazonも同じくらい。

強さ的には新しい(2018年モデル)13インチMacBookを強くした程度のマシン。 TouchBar付き、i7、メモリー16GB、SSD512GBにすると27万5000円になります。 値段的には7,8万円違うくらい。「Macより半額」とかじゃ全然ない。

なので、GNU/Linuxディストリビューション使えないとか、macが良いと言うなら普通にMacBookPro買ったほうが良いと思う。 13インチで32GBモデル、TouchBarなしモデルでアップデートされてたなら僕も超買ってた。

僕はヨドバシのポイントカードが溜まっていたので15,6万円で買えてしまった。 あとこれを買ったときのポイントで、先述のハブ(1万円くらい)は買えてしまったので良かった。

もともとASUS ZenBook 14っていうのを買おうと思ってたんだけど、店頭で触るとイマイチだったのでグレードを上げてFlip Sにした。 店頭で触るのはめっちゃ大事だね。

充電器も買うと良いよ

ZenBook Flip Sに充電器が付いてくるけど、もう一つあったほうが嬉しい。 このCheeroの充電器が USB PD対応で、45W(20V/2.25A)が使えるので充電できる

ケーブルはこれを使っている。ケーブルの長さは1.8mあれば十分かな 勉強会とかに行って充電するときとか、新幹線で充電する時も1.8mあれば十分

一つだけだと何かと面倒なので、充電器は買い足しておいたほうが良い。

余談、前のマシン、X220も良いよ

今まで長いとこThinkPad X220を使ってたんだけど、これもオススメはしたい。

f:id:hirokiky:20180720182301j:plain

換装すればメモリー16GBまで認識したし、SSDも載せればでっかくできるし、Ubuntuは問題なく動く。 キーボードはセパレートじゃない古き良きキーボードで打ちやすい。 CPUもi5の第2世代なので、性能的にはそこまで悪くない。ただ電力をめちゃくちゃ食うので1,2時間しかバッテリーは持たない。

メルカリで1万6000円で買った。

ただ、やっぱり古いとノイズが多かったりディスプレイが貧相だったり、i5の2コアというのが物足りないとこだった。 JavaScriptとかCSSとかバリバリビルドするので、LLでWebだからCPUそんな要らないってことじゃなくなっちゃった。

ASUS ZenBook Flip S良いよ

買って5日ほどかな、仕事でもバリバリ使ってるけどとても良い。 i7マシン買ってUbuntu入れたい人は参考にしてほしい。こういう情報はなかなか出にくいし伝えたいと思った。

良いUbuntuライフを。

他のオススメ記事

blog.hirokiky.org

Djangoで親の親のモデルを1クエリーで取る

Djangoのモデルから親のモデルを取ると(select_relatedなどしていないと)1クエリー実行されてしまいます。 以下のように、親のさらに親を取ろうとすると2クエリー実行されます。

me.parent.parent

me.parent の時点で1クエリー実行されて、 parent.parent の時点で2クエリー目が実行されます。 各クエリーでは親の全カラムの値も取るので、親の親だけが必要な場合は効率が悪いです。

この場合、以下のように子供の子供のIDを指定して取るように置き換えると1クエリーで取れます。

Grandpa.objects.get(children__children__id=me.id)

ObjectDoesNotExist とか MultipleObjectReturned には気をつけて。

DjangoのField.__init__ でクエリーしてはいけない

動的にフォームの choices の値を作りたい場合など、フォームの内容のためにクエリーすることはよくあると思います。 でも、フィールドの __init__ でクエリーしてしまうコードを書くとインポート時に実行されてしまうので注意が必要です。

ダメな例

class FoobarChoiceField(forms.ChoiceField):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.choices = [(foobar.name, foobar.title)
                        for foobar in Foobar.objects.all()]


class HogeForm(forms.Form):
    foobar = FoobarChoiceForm()

理由

フィールドの __init__ はインポート時に実行されてしまうので、インポート時に(上記の場合Foobarへの)クエリーが実行されてしまいます。 インポート時にHogeFormが作成されて、FoobarChoiceField.__init__ も実行されます。 choicesがリストの場合、そのままクエリーも実行されてしまいます。

マイグレーション時(DBが作られる前)などに実行されてしまうとFoobarに対応するテーブルがまだ作られていないのでエラーになります。 また、サーバー起動時にクエリーされる場合、DBに変更があってもchoicesの値が変わらなくなってしまいます。

直す例

Django1.8からchoices指定にcallableを渡せるので、callableにしておきましょう。

class FoobarChoiceField(forms.ChoiceField):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.choices = lambda: [(foobar.name, foobar.title)
                                for foobar in Foobar.objects.all()]

もちろん、フィールドを作らない場合はFormでやってもOK。 まぁFormの __init__ は(普通に書く分には)インポート時に呼び出されないので、1.8以前のように __init__ で choices を作るように書いてもOKです。

class HogeForm(forms.Form):
    foobar = ChoiceForm(choices=lambda: [(foobar.name, foobar.title) for foobar in Foobar.objects.all()])

Ubuntu 18.04 をインストールして「grub-efi-amd64-signedパッケージを/target/にインストールするのに失敗しました」で落ちる

Ubuntu 18.04 を Windows 10 とデュアルブートしようと設定しているときに grub-efi-amd64-signedパッケージを/target/にインストールするのに失敗しました というエレーが発生してインストールできなかった。

2018-07-17時点での話。

解決した方法

Wifiを設定せずにインストール。

サードパーティ製パッケージのインストールは有効で、セキュアブートは無効にしていた。 パーティションはマニュアルで設定したけど、とくに普通のext4/ と、スワップを設定したのみ。

なぜか知らないけどこれでうまくいった。 Wifiをつなぐとインストーラーやらが最新になって何かしらのバグを踏むとかなのだろうか。。。

見た情報、試した方法(でも解決にはならなかった情報)

/boot/efi パーティションを自作して解決する方法はうまくいかず。 Windows Boot Managerと場所が被るとかで設定できなかった。

www.geek.sc

VMUbuntuは入れなかった

やっぱりデュアルブートにしたかった。 WindowsをホストマシンにしてVMでプログラミング環境をUbuntuで起動しても良いのだけど、 やっぱりWindowsを使うというのが苦痛で仕方なかったのでデュアルブートすることにした。

factory-boyとDjangoでテストを書くときにファイルをうまく使う

ORMってファイルが入ると途端にめんどくさくなるよね。

まして単体テストで都度物理的なファイルを扱ったりするのはもうめんどくさすぎます。 でも factory-boy を使えばDjangoのFileFieldやImageFieldも楽に使えます。

バージョン

factory-boy==2.11.1 でやってます。

使い方

こんな感じで ImageField を持ったモデルで説明します。

from django.db import models


class Book(models.Model):
    cover_image = models.ImageField("カバー画像", ...)

factory-boyをこんな感じで書きます。 factory.django.ImageField を設定しておきます。

import factory


class BookFactory(factory.django.DjangoModelFactory):
    cover_image = factory.django.ImageField()

    class Meta:
        model = models.Book

そうすれば cover_image__ のように __ に続いて指定できます。 この例だと自動で作る画像の色とファイルの名前、サイズ、画像の拡張子を指定しています。

        book = BookFactory(
            cover_image__color='green',
            cover_image__format='PNG',
            cover_image__height=10,
            cover_image__width=10,
            cover_image__filename='test.png',
        )

いちいち物理的なファイルやら django.core.files.base.ContentFile やらも使わずに書けて便利。 この factory.django.ImageField__init__ に渡せる引数を、 __ 経由で渡せるようです。

Using factory_boy with ORMs — Factory Boy latest documentation

factory.django.FileField の場合は __data でバイナリーを指定できます。 すごく便利。

factory-boyについてはPythonプロフェッショナルプログラミングの14章にも書いたのでぜひ読んでみてください。

Pythonプロフェッショナルプログラミング 第3版

Pythonプロフェッショナルプログラミング 第3版

AWS上のデプロイ用インスタンスからPackerでAMIビルドしたらPackerBuilderにSSHできない問題を解決した話

Packer が好きで使ってます。 AWSのAMIをビルドするために使ってるんですが、そこであった話。

構成

デプロイ用のインスタンスから packer build してAMIを作る。

  • PackerBuilderには既存のSecurityGroup(セキュリティグループ)を指定する
  • PackerBuilderはPublicAccessを受け付ける
  • ParkerBuilderには既存のSSHキーペアを指定する

この既存のSecurityGroupは「デフォルト」のSecurityGroupで、このSecurityGroup自身からのアクセスを受け付けるようにしています。 デプロイ用のインスタンスも、PackerBuilderも同じSecurityGroupに所属させることでアクセスを許可しようという狙いです。

起こったこと

packer build 中にSSH接続できない

原因と理由

PackerはデフォルトでパブリックIPを使って接続しようとしていたのが原因(PackerBuilderでPublicAccessを受け付けるようにしていたからかな)。 SecurityGroupは パブリックIPを通して接続すると、「特定のSecurityGroupからのアクセス」と特定できなくなってしまう ので、単なる外部アクセスと判断されてSSHが拒否されていた。

ローカルIPを直接使うか、パブリックDNS(Public DNS)を使えば、EC2インスタンス上からIPを引けばローカルIPが取得できるのでアクセスできる (正しく特定のSecurityGroupからアクセスがあったと判断してもらえる)。

解決方法

packer.json"ssh_interface": "public_dns" を指定して、パブリックDNSを使ってSSH接続するようにした。

  "builders": [
    {
      "type": "amazon-ebs",
      ...
      "associate_public_ip_address": true,
      "security_group_ids": ["<デフォルトSecurityGroup>"],
      "ssh_keypair_name": "...",
      "ssh_private_key_file": "...",
      "ssh_interface": "public_dns"
    },
  ]

Amazon EBS - Builders - Packer by HashiCorp

デプロイサーバー上でパブリックDNSを引けばローカルIPが引けるので問題なし。 まぁ、 "local_ip" を指定してもいいんだけど。

Packerのデバッグ方法

Packerのログを見るときはPACKER_LOG=1 をつけて実行すると良い。 実行している内容とかが標準出力ででる。

$ PACKER_LOG=1 packer build ...

あと packer build -debug ... とオプションを付ければステップ実行できる。 便利よ。

$ PACKER_LOG=1 packer build -debug ...

www.packer.io

動かないときは色々試す前に原因見つけような! ログがしょっぱいツールとかシステムのときは仕方ないけどね。

結構ハマったって話

デプロイサーバー上からもローカルからもPackerBuilderにSSHできるので原因が分からなかった。 デバッグ出力するとどうやらパブリックIPでつないでいるようだったので、これが原因だとわかった。

SecurityGroupはローカルIPで繋がないと、「SecurityGroupからアクセスがあった」と特定できないっていうのは気をつけないとね。