Xcodeで入力補完が効かなくなった

macOS 10.12.6, Xcode 8.3.3, CocoaPods 1.3.1, Ruby 2.4.2p198, rbenv 1.1.1-6-g2d7cefe

最近どうもiMacが重い。
特にXcodeが重い。
生成、リンクされるバイナリーが多いことが原因なのか、特にCocoaPodsを使用するプロジェクトが極めて重い。
起動するだけで、"Indexing | Processing files" となって、そいつがなかなか終わらない。

そしていつからか入力補完やJump To Definitionが効かなくなっていた。
既存のでかいプロジェクトだけでなく、新規プロジェクトにおいてすら効かない。

結局原因は判らずじまいだが、やった手順はこちら↓

  • まずこちらを試してみたがダメ
  • こちらのChinmay氏の投稿(現時点で133Votes)を参考に同じ手順を実行してみたがダメ
  • 1つ下のバージョンである 8.2.1 をインストールしてみたがダメ
  • 8.2.1 を削除して、ゴミ箱を空にしてから8.3.3 を再インストールしてみたら直った

結果から見るに、どうもゴミ箱に捨てた古いXcode.app内のデータにリンクして動いていたような雰囲気を感じるが、原因不明。迷宮入り。

今回のことから得るべき教訓は、「ゴミ箱は定期的に空にしようね!」ということ。
どんだけ溜めていたのか、ゴミ箱を空にするだけで30分くらいかかった。(私のMac重すぎぃ〜)

相変わらず動作は重いけれども、入力補完と関数ジャンプは機能するようになった。

どこかで誰かが言っていたが、XcodeEclipseが重くて作業効率が悪いというのは我々開発者にとって致命的なストレスである。自宅PCなら買い換えれば良いだけなのだが、仕事だとなかなか難しい。エンジニアの作業効率に注文をつけるマネージャーは多いが、エンジニアの作業環境に気配りしてくれるマネージャーなんてなかなかいない。与えられた環境でパフォーマンスを出すのが我々の仕事だ。ゆえにプログラマーというのはOSやPCのコンフィギュレーションにも精通していなければならない。

ふぁびこんのつくりかた

ウェブサイトを立ち上げる時に忘れないようにすることのひとつに、ファビコンを設置するというものがある。
ウェブブラウザーのアドレスバーやお気に入りに表示されるあのアイコンである。
よくやるやり方は、httpdocs配下にfavicon.icoというファイルをセットして、

<link rel="shortcut icon" href="favicon.ico" />

とするものであるが、これだけだと不十分な場合がある。

各種ブラウザー向け、スマートデバイスのホーム画面へのセットまで考慮するなら、以下の手順がおすすめ。

  • まず、260 x 260 のPNG画像を用意する
  • こちらの Favicon Generator. For real. というサイトを使う
  • Select your Favicon picture から用意したファビコン画像をアップロードする
  • 見た目のオプションをお好みで調節する(デフォルトで問題ない)
  • Favicon Generator Options にファビコン画像を格納するパスをセットする*1
  • 諸々の設定を終えたら、Generate your Favicons and HTML code をクリックする
  • Favicon package をクリックして.zipをダウンロードする
  • .zipを解凍して自分のサイトに配備する(3つ前の手順で指定したパスに置くこと)
  • 画面に表示されたHTMLコードをコピーして、自分のサイトのトップページのHTMLのhead内に貼り付ける


まあ、このサイトに限らず、これ系のツールを使って、1つの元画像から各種プラットフォーム向けのファビコンを自動生成するのが楽かと思われ。
てか、こういうのも規格で統一してくれないのかねぇ。

*1:デフォルトではドキュメントルートに配置するようになっているが、個人的にはそれはお勧めしない。サイズ調節されたアイコン画像やメタ情報を含むファイルが多数生成されるので、/favicons とかに隔離した方が良い

stdoutのエンコーディングは環境変数LANG

Python 3.6.1

備忘録

まだPythonは全然勉強できていない。
それゆえひどく初歩的なところでハマったりしている。

どうも環境によって日本語がうまくエンコード、デコードできていないな、と思ったら、
どうもPythonのprint文の文字列エンコーディングは、ソースコードエンコーディングとは関係なく、LANG環境変数に依存しているらしい。


test.py

s = '日本語'
print(s)

# UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)

LANGをUTF-8にしてやったら普通に動いた。

export LANG=ja_JP.UTF-8
python test.py
日本語

この値が何になっているかは、sys.stdout.encodingで取得できるみたい。

import sys
print(sys.stdout.encoding)
# ANSI_X3.4-1968

Java EEアプリを本リリースする際にやるべきこと

Apache, Tomcat, ajp, Java

Java EEのアプリというのは、大抵、独自のサブディレクトリーに配置されるものである。

例えば、myapp.war を Tomcat で開発しているときに、開発者は http://localhost:8080/myapp/ にアクセスして動作確認するだろう。

開発作業についてはそれで何も問題ないのだが、実際にウェブサイトを公開することを考えると、2つの点でこれは現実的ではない。

1つは、8080ポートでウェブサイトを公開すべきでないという、ごく当たり前のことだ。
インターネットからアクセスされるサーバーが余計なポートを解放すべきではないし、ウェブサーバーとしてはTomcatよりもApache httpdの方が信頼できる。
この点についてはajpで解決するのが一般的だ。
Java以外のウェブアプリについても、Apache経由でアクセスさせるのはよくある一般的なやり方だと思われる。

もう1点、これはおそらくJava EE特有の問題だと思うのだが、/myapp というサブディレクトリー必要になってしまうという点だ。

webapps/myapp.war

としてデプロイする限りこれは仕様上必然である。

コンテキストルートへデプロイするには、ROOT.war という名前にしなければならない。

しかしROOT.warにすると、1つのTomcatインスタンスで1つのウェブアプリしか公開できないことになってしまう。

例えば、1つのウェブサーバーで、2つのJavaウェブアプリを公開したいとする。

2つドメイン名を取得して、それらを1つのサーバー(IPアドレス)としてDNSのAレコードを登録したとしよう。

http://my-site.com/
http://my-other-site.com/

本来↑このようにしたいところだが、ROOT.warを2つ作ることはできないので、

http://my-site.com/myapp1
http://my-other-site.com/myapp2

という不細工なURLになってしまう。


こういった問題は、Apache側の設定で回避することができる。

例えば、以下のようにリダイレクトさせてしまう。


httpd.conf

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    ProxyPass /myapp !
    ProxyPass / ajp://localhost:8009/myapp/
    ProxyPassReverse / ajp://localhost:8009/myapp/
    RedirectMatch 301 ^/myapp$ /
    RedirectMatch 301 ^/myapp/(.*)$ /$1
</VirtualHost>


ProxyPass / ajp://localhost:8009/myapp/
ProxyPassReverse / ajp://localhost:8009/myapp/
この設定で、example.comという仮想ホストに対するアクセスをajpTomcatに流すようにする。


ProxyPass /myapp !
Java EEアプリはmyapp.warとして開発しているとすると、内部からは /myapp/some-servlet のURLにアクセスしているはずなので、それはプロキシーしない。(後の設定でリダイレクトする)


RedirectMatch 301 ^/myapp$ /
RedirectMatch 301 ^/myapp/(.*)$ /$1
/myapp 以下に対するアクセスは / へリダイレクトして、先のプロキシー設定により、ajpを経てTomcatへ流す。


とまあ、こんな感じで対応できるのだが、301の使い方として適切ではないと思うし、毎回のようにリダイレクトが発生するのは通信効率上よろしくないと言えるだろう。

もっとまともなソリューションはないものか。

と悩んでいたところ、Tomcatのserver.xmlドメインごとのROOT.xmlで対処できるそうな。


【参考】
http://www.matsuaz.com/matsumotojs/2011/02/02/1296583161582.html


なるほど。

サイトごとに、

$CATALINA_HOME/conf/Catalina/my-site.com/ROOT.xml

を作成して、docBaseに.warファイルのパスを指定すれば良いのか。

かぁんたんですね。

インデントはTAB派

どうも今時は空白派の方が多いようだ。
なんのメリットがあるのかわからん。

TABの方がソースサイズが小さくなるというのは置いといたとして(今時そんなことはメリットにはなり得ないだろう)、人によって好みの違うインデント幅というのをTABという環境依存の制御コードに割り当てるのは理にかなっていると思うのだが。

たかが好みとはいえ、空白2つでインデントしているソースコードなんて個人的には読むに耐えない。(そういったコードはだいたいリファクタリングが必要と感じるほどネストが深い)

よく「インデントにTABを使うとデメリットがある」と主張する人を見かけるが、そんなものはない。おそらくそういう人って、位置揃えとインデントをごっちゃにしてるんだろうな。インデントはプログラムの論理構造を表すための字下げであって、位置揃えにTABを使うべきではない。

また、Python3から強制されているように、インデントに「空白とTABを混在させてはならない」。言語による定めがなかったとしても、これをやってしまうとTAB幅によってレイアウトが崩れてしまうからである。

この2つを守っている限り、TABを使うことのデメリットなんて存在しないように思うのだが。むしろ、自分の好きなインデント幅でソースコードを読むことができるし、打ち間違えた時に何回もバックスペースしなくて済むし、TABを空白n個に置き換えるなんていうエディターの設定や入力ショートカットを調べなくて済むではないか。

  • インデントはTAB
  • 位置揃えは半角スペース
  • TAB幅は開発者の好みで


このルールが一番好き。
今のところ問題が起きたことはない。

まあ、実際どうするかはプロジェクトリーダーがコーディング規約で決めれば良いことだが、混在だけはダメだ、絶対に。