<![CDATA[newnakashimaのblog's RSS Feed]]>https://blog.nksm.in.netGatsbyJSMon, 27 Jun 2022 09:03:28 GMT<![CDATA[GAS難しい]]>https://blog.nksm.in.net/2022-06-06-GAS難しい/https://blog.nksm.in.net/2022-06-06-GAS難しい/Mon, 06 Jun 2022 19:48:05 GMT<p>会社のサイトはNext.jsで作ったものをexportして完全に静的なサイトとして作成していた。が、色々あってバックエンドが欲しくなった。AWSのAmplifyにデプロイしていたので、あとからサーバー追加するのめんどいなあというのと、管理画面とか作りたくないし簡易的なものでいいからとGASにしたのだが、ハマりどころがあった。(あとAmplifyでも今は普通にNext.jsのバックエンドが使えるので使えるようにした)</p> <p>特にハマったのはdoPost。doPostはエンドポイントにPOSTでリクエストが送られてて、GAS側のコードがリクエストボディを使用していた場合にはlocationヘッダが帰ってきてリダイレクトされる。実際の処理はリダイレクト先で行われてそこからレスポンスが帰ってくる仕組みのようなので、そこで色々と問題がおこる。特に、Googleの認可を挟もうとするとややこしくなる。</p> <p>最初はdoPostの処理をNext.jsのAPIルートを経由して呼ぼうかと思っていたのだが、Nodeからだと何故か401になる。クライアント(ブラウザ)から直接GASのエンドポイントを叩くと200で返ってくる。なんでだと思っていたが、このエンドポイントはGoogleの認可を使用する設定にしていので当たり前といえば当たり前のことだった。</p> <p>で、色々やっているとGASではステータスコード200しか返せなさそうだということがわかった。エラーの場合はerrorなどのキーを持つオブジェクトを返して、ブラウザ側でエラーハンドリングしようかと思っていたのだが、クライアントから直接呼ぶとリダイレクト先からのレスポンスが受け取れない。レスポンスボディが空になってしまう。色々試してみたがどうもダメそうだった。</p> <p>これは多分一回リダイレクトを挟んでしまうことが関係しているように思う。詳しい原因はわからない。</p> <p>なので、最終的にはGoogleの認可を外して、リクエスト時にパスワードなりトークンなりを付与してサーバー側でそれを検証するコードを書いた。そしてNext.jsのAPIを経由するようにした。すると期待通りにレスポンスボディを取得できた。</p> <p>なぜブラウザから直接呼ぶとリダイレクト先のレスポンスボディが取れなくて、Node.jsから呼ぶと取れるのかは謎。調べればわかるのかもだけど、人生は有限なのでもっと切実な問題に時間を使いたい。</p> <p>GASは本当にログを取りたいくらいの用途でだけしか使うべきではないと思った。。サーバーサイドが簡単にセットアップできる何かがほしい。人類がずっと求めているのになかなか提供されないもの、それが簡単なサーバーサイドだ。人はみんな簡単にセットアップできるサーバーサイドを求めるし、実際にそれを実装可能だと考えるのだが、作ってみると必ず複雑になる。必然的に複雑さを要求するのがサーバーサイドなのかもしれない。なぜなら、そもそも複雑なことをしたいからこそサーバーサイドが欲しくなるからだ。とてもつらい。</p><![CDATA[自分の行動力]]>https://blog.nksm.in.net/2022-06-02-自分の行動力/https://blog.nksm.in.net/2022-06-02-自分の行動力/Thu, 02 Jun 2022 19:14:52 GMT<p>自分には行動力がない。ここでいう行動力とはアクティブな人生を送っているかどうかみたいな意味で一般的に使われるような行動力とは微妙に違う。私がいいたい行動力とは、シミュレーションRPGなどでよく使われる概念の「行動力」だ。行動力がある限りシミュレーションRPGのユニットは行動を続けることができる。行動力が高いユニットは一ターンで二回行動できたりする。そのような意味での行動力が私にはない。</p> <p>自分は一日8時間働くと行動力が枯渇する。8時間以上はかなり無理すれば働けるが、昨年はその生活を1年続けて死にかけた。行動力の前借りは絶対に返済の時期がやってくる。酷いと死亡という形で支払わされる。</p> <p>行動力の前借りは良くない。だが、他人より多く行動しないと仕事の成果が得られないのも事実。行動力がある人は他人より多く行動できるので、8時間よりも多く働くことができる。10時間、12時間、14時間、、、そうして成功を手に入れるのだ。</p> <p>行動力が尽きると、何も生産的なことはできない。ただ横になるか酒を飲むだけだ。全くの無だ。無があることによってしか行動力が回復しない。行動力を回復させるアイテムというものがゲームと違って存在しない。</p> <p>以前は行動力があった。なぜあったのかはわからない。片道1時間以上も通勤に費やしながらも、帰ったら本を読みブログを書いていた。それが普通だった。何か目的があったわけでも無いのにそうした生活を続けていたのだから妙な話だ。</p> <p>今はむしろ目標がある。仕事を成功させるという明確な目標がある。にも関わらず行動力が伴わない。MPと言い換えてもいい。MPが無い。MPの最大値が少ない。ソシャゲで言うスタミナが無いのだ。</p> <p>一つには、仕事の内容も関係していると思う。現在の仕事はプログラミングだが、毎日の仕事の中で判断力を激しく消費している感じがする。ブログを毎日書いていた頃の仕事は判断力をそれほど要しなかった。だから行動力も消費しなかったのかもしれない。人間が一日に判断できる回数は決まっているという俗説もあるが、判断は実際に行動力を奪うと思う。</p> <p>前にも似たようなことをこの日記に書いたかもしれないが、言葉を選ばずに言えば仕事は手を抜くべきだ。8時間であっても全力で取り組めば行動力は枯渇する。全力で仕事をするのは良くない。仕事はほどほどにやればいい。</p> <p>仕事の時間は8時間では長すぎる。一日6時間が上限だ。そして週休は3日必要だ。週の労働時間は24時間が上限だ。そのくらいでいい。</p> <p>週休3日、一日6時間労働を完全に実現するためにはハードワークが必要だ。ジレンマだ。</p> <p>行動力を増やす薬がほしい。もしかしてそれが覚せい剤と言われているものなのかもしれない。人生は厳しい。</p> <hr> <h2>追記</h2> <p>いよいよ Netlify の CMS の調子が悪い。こんなテンプレート使うんじゃなかった。WordPressのほうがよっぽど良い。今はたまにRails製の自作ブログを作ろうと触っているが、すでに述べたとおり自分に行動力が無いので酒や睡眠に流されがちだ。行動力がほしい。何をするにも行動力か金が全てだ。</p><![CDATA[markedで改行2回以上入れられない問題]]>https://blog.nksm.in.net/2022-03-29-markedで改行2回入れられない問題/https://blog.nksm.in.net/2022-03-29-markedで改行2回入れられない問題/Tue, 29 Mar 2022 21:34:58 GMT<p>marked使っていて改行を2回以上入れられない問題にぶちあたった。</p> <p>例えば、運用の人から以下のようなマークダウンが送られてきたとする。</p> <pre><code class="language-md"># 重大発表 重大発表があります! それは。。。 秘密です! </code></pre> <p>改行をたくさん入れることによって、スクロールしないと続きが読めないようにするようなコンテンツなわけだが、これを普通にmarkedでパースすると以下のような感じになってしまう。</p> <pre><code class="language-html">&#x3C;h1>重大発表&#x3C;/h1> &#x3C;p>重大発表があります!&#x3C;/p> &#x3C;p>それは。。。&#x3C;/P> &#x3C;p>秘密です!&#x3C;/P> </code></pre> <p>つまりたくさん入れたはずの改行が無くなってしまう。 breaks オプションを true にしてもこうなる。</p> <p>かと言って運用の人に「改行は行末に半角スペースを2回入れてですね、、、」みたいなことを説明してもわかってもらえるはずがない。</p> <p>なので以下のような実装をした。</p> <pre><code class="language-ts">marked.parse(text.replace(/(?&#x3C;=\n|\r|\r\n)(\n|\r|\r\n)/g, '&#x3C;br>'), { breaks: true }) </code></pre> <p>改行が一個の場合はちゃんと <code>&#x3C;br></code> になるので、2回続いている場合のみ無理やり <code>&#x3C;br></code> に置換している。</p> <p>が、コードブロックをハイライトしたい場合はこれでは不十分で、コードブロックの中でだけは上記の処理をしないようにする必要がある。その処理をここに書くと長くなるのでGistに貼っておく。</p> <p><a href="https://gist.github.com/newnakashima/9e2eee6a68b5c7810a42536aabf4f0a3">https://gist.github.com/newnakashima/9e2eee6a68b5c7810a42536aabf4f0a3</a></p><![CDATA[useMemoとuseCallbackの個人的な使い所]]>https://blog.nksm.in.net/2022-03-06-useMemoとuseCallbackの個人的な使い所/https://blog.nksm.in.net/2022-03-06-useMemoとuseCallbackの個人的な使い所/Sun, 06 Mar 2022 12:40:09 GMT<p>useMemoとuseCallbackの使い所について最近色々感じることがあるのでメモ。個人的な感想。一般的にどうなのかはよくわからない。</p> <h2>useMemo</h2> <p>例えば、以下のようなコンポーネントがあるとする。</p> <pre><code class="language-jsx">export default function MyComponent() { const [flag1, setFlag1] = useState(false) const [flag2, setFlag2] = useState(false) return ( &#x3C;div> {flag1 &#x26;&#x26; &#x3C;p>フラグ1がonになっている&#x3C;/p> } {flag2 &#x26;&#x26; &#x3C;p>フラグ2がonになっている&#x3C;/p> } {flag1 &#x26;&#x26; flag2 &#x26;&#x26; &#x3C;p>フラグ1とフラグ2が両方onになっている&#x3C;/p> } &#x3C;/div> ) } </code></pre> <p>こんな感じで、特定の部品のレンダリングに複数の条件が関わってくるとuseMemoしたくなる。上の例だとbooleanのフラグが2つなのでまだ許せるが、これがnumber型で3つとかになると以下のようになる。</p> <pre><code class="language-jsx">export default function MyComponent() { const [variable1, setVariable1] = useState(0) const [variable2, setVariable2] = useState(0) const [variable3, setVariable3] = useState(0) return ( &#x3C;div> {variable1 > 10 &#x26;&#x26; &#x3C;p>変数1が10より大きい&#x3C;/p> } {variable2 &#x3C; 20 &#x26;&#x26; &#x3C;p>変数2が20未満&#x3C;/p> } {variable3 === 50 &#x26;&#x26; &#x3C;p>変数3が50と等しい&#x3C;/p> } {variable1 > 10 &#x26;&#x26; variable2 &#x3C; 20 &#x26;&#x26; &#x3C;p>変数1と変数2が条件を満たしている&#x3C;/p> } {variable1 > 10 &#x26;&#x26; variable3 === 50 &#x26;&#x26; &#x3C;p>変数1と変数3が条件を満たしている&#x3C;/p> } {variable2 &#x3C; 20 &#x26;&#x26; variable3 === 50 &#x26;&#x26; &#x3C;p>変数2と変数3が条件を満たしている&#x3C;/p> } {variable1 > 10 &#x26;&#x26; variable2 &#x3C; 20 &#x26;&#x26; variable3 === 50 &#x26;&#x26; &#x3C;p>全ての変数が条件を満たしている&#x3C;/p> } &#x3C;div> &#x3C;label> 変数1 &#x3C;input type="number" value={variable1} onChange={(e) => setVariable1(+e.target.value)} /> &#x3C;/label> &#x3C;/div> &#x3C;div> &#x3C;label> 変数2 &#x3C;input type="number" value={variable2} onChange={(e) => setVariable2(+e.target.value)} /> &#x3C;/label> &#x3C;/div> &#x3C;div> &#x3C;label> 変数3 &#x3C;input type="number" value={variable3} onChange={(e) => setVariable3(++e.target.value)} /> &#x3C;/label> &#x3C;/div> &#x3C;/div> </code></pre> <p><code>variable1 > 10 &#x26;&#x26; variable2 &#x3C; 20 &#x26;&#x26; variable3 === 50 &#x26;&#x26;</code> みたいなのは読みづらいので変数や関数にしたくなるのがプログラマーの習性だろう。そうすると次のような感じになる。</p> <pre><code class="language-jsx">export default function MyComponent() { const [variable1, setVariable1] = useState(0) const [variable2, setVariable2] = useState(0) const [variable3, setVariable3] = useState(0) const variable1and2 = variable1 > 10 &#x26;&#x26; variable2 &#x3C; 20 const variable1and3 = variable1 > 10 &#x26;&#x26; variable3 === 50 const variable2and3 = variable2 &#x3C; 20 &#x26;&#x26; variable3 === 50 const allVariables = variable1 > 10 &#x26;&#x26; variable2 &#x3C; 20 &#x26;&#x26; variable3 === 50 return ( &#x3C;div> {variable1 > 10 &#x26;&#x26; &#x3C;p>変数1が10より大きい&#x3C;/p> } {variable2 &#x3C; 20 &#x26;&#x26; &#x3C;p>変数2が20未満&#x3C;/p> } {variable3 === 50 &#x26;&#x26; &#x3C;p>変数3が50と等しい&#x3C;/p> } {variable1and2 &#x26;&#x26; &#x3C;p>変数1と変数2が条件を満たしている&#x3C;/p> } {variable1and3 &#x26;&#x26; &#x3C;p>変数1と変数3が条件を満たしている&#x3C;/p> } {variable2and3 &#x26;&#x26; &#x3C;p>変数2と変数3が条件を満たしている&#x3C;/p> } {allVariables &#x26;&#x26; &#x3C;p>全ての変数が条件を満たしている&#x3C;/p> } &#x3C;div> &#x3C;label> 変数1 &#x3C;input type="number" value={variable1} onChange={(e) => setVariable1(+e.target.value)} /> &#x3C;/label> &#x3C;/div> &#x3C;div> &#x3C;label> 変数2 &#x3C;input type="number" value={variable2} onChange={(e) => setVariable2(+e.target.value)} /> &#x3C;/label> &#x3C;/div> &#x3C;div> &#x3C;label> 変数3 &#x3C;input type="number" value={variable3} onChange={(e) => setVariable3(++e.target.value)} /> &#x3C;/label> &#x3C;/div> &#x3C;/div> ) } </code></pre> <p>見た目だけなら多少はマシになったが、例えば <code>variable1and2</code> はvariable3の値が変わったときも毎回再計算してしまうという問題がある。なのでこういうときはuseMemo使いましょうというのがよく言われることなんじゃないかと思う。以下のようにする。</p> <pre><code class="language-jsx">export default function MyComponent() { const [variable1, setVariable1] = useState(0) const [variable2, setVariable2] = useState(0) const [variable3, setVariable3] = useState(0) const variable1and2 = useMemo(() => { return variable1 > 10 &#x26;&#x26; variable2 &#x3C; 20 }, [variable1, variable2]) const variable1and3 = useMemo(() => { return variable1 > 10 &#x26;&#x26; variable3 === 50 }, [variable1, variable3]) const variable2and3 = useMemo(() => { return variable2 &#x3C; 20 &#x26;&#x26; variable3 === 50 }, [variable2, variable3]) const allVariables = useMemo(() => { return variable1 > 10 &#x26;&#x26; variable2 &#x3C; 20 &#x26;&#x26; variable3 === 50 }, [variable1, variable2, variable3]) return ( &#x3C;div> {variable1 > 10 &#x26;&#x26; &#x3C;p>変数1が10より大きい&#x3C;/p> } {variable2 &#x3C; 20 &#x26;&#x26; &#x3C;p>変数2が20未満&#x3C;/p> } {variable3 === 50 &#x26;&#x26; &#x3C;p>変数3が50と等しい&#x3C;/p> } {variable1and2 &#x26;&#x26; &#x3C;p>変数1と変数2が条件を満たしている&#x3C;/p> } {variable1and3 &#x26;&#x26; &#x3C;p>変数1と変数3が条件を満たしている&#x3C;/p> } {variable2and3 &#x26;&#x26; &#x3C;p>変数2と変数3が条件を満たしている&#x3C;/p> } {allVariables &#x26;&#x26; &#x3C;p>全ての変数が条件を満たしている&#x3C;/p> } &#x3C;div> &#x3C;label> 変数1 &#x3C;input type="number" value={variable1} onChange={(e) => setVariable1(+e.target.value)} /> &#x3C;/label> &#x3C;/div> &#x3C;div> &#x3C;label> 変数2 &#x3C;input type="number" value={variable2} onChange={(e) => setVariable2(+e.target.value)} /> &#x3C;/label> &#x3C;/div> &#x3C;div> &#x3C;label> 変数3 &#x3C;input type="number" value={variable3} onChange={(e) => setVariable3(++e.target.value)} /> &#x3C;/label> &#x3C;/div> &#x3C;/div> ) } </code></pre> <p>このとき、そもそも各変数が単体で条件を満たしているかどうかをメモしてもいいと思う。メモ化した値を更にメモ化するみたいな感じになる。</p> <p><a href="https://ja.reactjs.org/docs/hooks-reference.html#usememo">Reactの公式ドキュメント</a>では、</p> <blockquote> <p><strong>useMemo はパフォーマンス最適化のために使うものであり、意味上の保証があるものだと考えないでください。</strong></p> </blockquote> <p>と太字で強調してあるのだが、 個人的にはuseMemoはどんどん使うべきだと思っている。なぜなら、パフォーマンス目的以外にも以下のメリットがあると感じるからだ。</p> <ul> <li> <p>関数として計算結果を返すのでデバッグしやすい。処理する前に console.log などを仕込める</p> <ul> <li>もちろんuseMemoしなくてもできるのだが、スコープが明確に区切られるのでcommitする前にconsole.logを消し忘れるみたいなゴミが減る</li> </ul> </li> <li> <p>ESLintが依存関係に関するWarningを出してくれる</p> <ul> <li>変数の値が何に依存してるかが見えやすくなり、つまらないバグの発生を防げてる気がする</li> <li>と同時に、なんとか変数間の依存を減らそうという意識が働くのでロジックを細かく切り出せる</li> </ul> </li> </ul> <h2>useCallback</h2> <p>useCallbackもuseMemoと使い所は基本的には同じで、<a href="https://ja.reactjs.org/docs/hooks-reference.html#usecallback">公式ドキュメント</a>にもこう書いてある。</p> <blockquote> <p>useCallback(fn, deps) は useMemo(() => fn, deps) と等価です。</p> </blockquote> <p>だが、明示的に「このメモは引数を取りますよ」という意図を表すのに有用だ。じゃあどういうときに引数使いたい気持ちになるのかというと、典型的には配列からコンポーネントを生成するときかなと思う。</p> <p>例えば以下のような感じで配列を出力してるとする。</p> <pre><code class="language-jsx">export default function MyComponent() { const myArray = [ 'one', 'two', 'three', 'four', 'five', 'six', ]; const [selected, setSelected] = useState(0); const [bgColor, setBgColor] = useState('red'); return ( &#x3C;div style={{ backgroundColor: 'gray' }}> &#x3C;div style={{ backgroundColor: bgColor }}> &#x3C;label style={{ color: 'white' }}> 赤 &#x3C;input type="radio" name="bgColor" onChange={(e) => e.target.checked &#x26;&#x26; setBgColor('red')} defaultChecked={bgColor === 'red'} /> &#x3C;/label> &#x3C;label style={{ color: 'white' }}> 黒 &#x3C;input type="radio" name="bgColor" onChange={(e) => e.target.checked &#x26;&#x26; setBgColor('black')} defaultChecked={bgColor === 'black'} /> &#x3C;/label> &#x3C;/div> &#x3C;ul> {myArray.map((item, i) => { return ( &#x3C;li key={i} onClick={() => setSelected(i)} style={{ color: 'white', backgroundColor: i === selected ? 'blue' : Math.abs(selected - i) === 1 ? 'steelblue' : 'transparent' }} > {item} &#x3C;/li> ); })} &#x3C;/ul> &#x3C;/div> ) } </code></pre> <p><code>backgroundColor: i === selected ? 'blue' : Math.abs(selected - i) === 1 ? 'steelblue' : 'transparent'</code> のように複数の条件や出力結果が絡んでいる場合にインラインで書くと可読性が著しく落ちる。なので関数化したくなる。自分はここでuseCallbackを使うことが多い。</p> <pre><code class="language-jsx">export default function MyComponent() { const myArray = [ 'one', 'two', 'three', 'four', 'five', 'six', ]; const [selected, setSelected] = useState(0); const [bgColor, setBgColor] = useState('red'); // ↓↓↓関数化したやつ↓↓↓ const getLiBgColor = useCallback((i) => { if (i === selected) { return 'blue' } if (Math.abs(selected - i) === 1) { return 'steelblue' } return 'transparent' }, [selected]) // ↑↑↑関数化したやつ↑↑↑ return ( &#x3C;div style={{ backgroundColor: 'gray' }}> &#x3C;div style={{ backgroundColor: bgColor }}> &#x3C;label style={{ color: 'white' }}> 赤 &#x3C;input type="radio" name="bgColor" onChange={(e) => e.target.checked &#x26;&#x26; setBgColor('red')} defaultChecked={bgColor === 'red'} /> &#x3C;/label> &#x3C;label style={{ color: 'white' }}> 黒 &#x3C;input type="radio" name="bgColor" onChange={(e) => e.target.checked &#x26;&#x26; setBgColor('black')} defaultChecked={bgColor === 'black'} /> &#x3C;/label> &#x3C;/div> &#x3C;ul> {myArray.map((item, i) => { return ( &#x3C;li key={i} onClick={() => setSelected(i)} style={{ color: 'white', backgroundColor: getLiBgColor(i) }} > {item} &#x3C;/li> ); })} &#x3C;/ul> &#x3C;/div> ) } </code></pre> <p>注意すべき点としては、useCallbackは関数の計算結果をメモしているのではなくて関数を生成する処理をメモ化しているようで、依存関係に入っていない <code>bgColor</code> を変更した場合も関数自体は呼ばれるという点である。つまり <code>bgColor</code> だけを変更した場合であっても配列のサイズ=6回分無駄な処理が走る。DOMツリー上ulの配下は <code>bgColor</code> の影響を受けなくてもそうなる。</p> <p>これを避けるには、<code>bgColor</code> を使ってる要素を別のコンポーネントに切り出すと良いっぽい。</p> <pre><code class="language-jsx">const BgColorComp => () => { const [bgColor, setBgColor] = useState('red'); return ( &#x3C;div style={{ backgroundColor: bgColor }}> &#x3C;label style={{ color: 'white' }}> 赤 &#x3C;input type="radio" name="bgColor" onChange={(e) => e.target.checked &#x26;&#x26; setBgColor('red')} defaultChecked={bgColor === 'red'} /> &#x3C;/label> &#x3C;label style={{ color: 'white' }}> 黒 &#x3C;input type="radio" name="bgColor" onChange={(e) => e.target.checked &#x26;&#x26; setBgColor('black')} defaultChecked={bgColor === 'black'} /> &#x3C;/label> &#x3C;/div> ) } export default function MyComponent() { const myArray = [ 'one', 'two', 'three', 'four', 'five', 'six', ]; const [selected, setSelected] = useState(0); const getLiBgColor = useCallback((i) => { if (i === selected) { return 'blue' } if (Math.abs(selected - i) === 1) { return 'steelblue' } return 'transparent' }, [selected]) return ( &#x3C;div style={{ backgroundColor: 'gray' }}> &#x3C;BgColorComp /> &#x3C;ul> {myArray.map((item, i) => { return ( &#x3C;li key={i} onClick={() => setSelected(i)} style={{ color: 'white', backgroundColor: getLiBgColor(i) }} > {item} &#x3C;/li> ); })} &#x3C;/ul> &#x3C;/div> ) } </code></pre> <p>また、useCallbackを使ってるとあるあるなのだが依存関係に変数を入れ忘れて生成された関数が更新されてなくてデバッグに時間を費やすというハマりがよくあって、地味に時間を削られて痛いのでuseCallbackのサイズは大きくならないように気をつけたいところだ。</p><![CDATA[Railsでnl2br]]>https://blog.nksm.in.net/2022-03-05-Railsでnl2br/https://blog.nksm.in.net/2022-03-05-Railsでnl2br/Sat, 05 Mar 2022 11:33:11 GMT<p>何百番煎じだよって話だけどPHPerからするとRailsではnl2brどうやるの?というのが気になりすぎた。</p> <p>特にLaravelでは <code>{!! nl2br(e( $something )) !!}</code> みたいな書き方するやつ。</p> <p><a href="https://railsdoc.com/page/simple_format">simple_format</a> って関数があるらしいけど、連続した改行は <code>&#x3C;p></code> になるというおせっかいなことこの上ない余計な機能が付いている。</p> <p>ヘルパを自作することになるようなのだが、Rails初心者なのでやり方を調べた結果をメモ。結論は以下のような感じに書けば良いらしい。</p> <pre><code class="language-ruby"># application_helper.rb module ApplicationHelper def nl2br(input) # とりあえず\nだけ置換 (sanitize input).gsub(/\n/, '&#x3C;br>') end end </code></pre> <pre><code class="language-erb">&#x3C;article> &#x3C;p> &#x3C;%== nl2br @post.body %> &#x3C;/p> &#x3C;/article> </code></pre> <p>変数出力時にHTMLタグをエスケープしない方法としては、<code>html_safe</code>、<code>raw</code>、<code>&#x3C;%==</code>という3つの選択肢があるようなのだが、<code>&#x3C;%==</code>が一番タイプ数が少ないしわかりやすいので良いと思う。</p> <p>関係ないけど、LaravelのBladeの記法パイプ風に書ければいいのにといつも思う。</p> <pre><code>{!! $something |> e |> nl2br !!} </code></pre> <p>みたいな感じで。</p> <hr> <p>参考:</p> <ul> <li><a href="https://edgeguides.rubyonrails.org/active_support_core_extensions.html#output-safety">https://edgeguides.rubyonrails.org/active_support_core_extensions.html#output-safety</a></li> <li><a href="https://qiita.com/iwamot/items/74c2bd9ebd3ac6458837">https://qiita.com/iwamot/items/74c2bd9ebd3ac6458837</a></li> </ul><![CDATA[macでRubyをビルドしたときにRUBY_FUNCTION_NAME_STRINGのerrorが出た場合]]>https://blog.nksm.in.net/2022-03-01-macでRubyをビルドしたときにRUBY_FUNCTION_NAME_STRINGのerrorが出た場合/https://blog.nksm.in.net/2022-03-01-macでRubyをビルドしたときにRUBY_FUNCTION_NAME_STRINGのerrorが出た場合/Tue, 01 Mar 2022 19:57:38 GMT<pre><code class="language-sh">sudo rm -rf /Library/Developer/CommandLineTools sudo xcode-select --install </code></pre> <p>で解決した(自分の場合は)。</p> <hr> <p>久しぶりにrbenvを使って違うバージョンのRuby使ってみよっかなって思ったときに <code>RUBY_FUNCTION_NAME_STRING</code> が未定義だとかいうエラーが出てハマった。Homebrewから入れると大丈夫だけど、これはコンパイル済みのものを落としてきているだけなので問題は解決していない。</p> <p><a href="https://github.com/rbenv/ruby-build/issues/1431">https://github.com/rbenv/ruby-build/issues/1431</a></p> <p>上記のissueに書いてある対応法はほとんどすべて試したがダメ。もうRubyやめるか、と思っていたときに、今まで見落としていたあるコメントが目に入った。</p> <p><a href="https://github.com/rbenv/ruby-build/issues/1409#issuecomment-752223239">https://github.com/rbenv/ruby-build/issues/1409#issuecomment-752223239</a></p> <blockquote> <p>Updating of the command tools helped me:</p> <pre><code class="language-sh">sudo rm -rf /Library/Developer/CommandLineTools sudo xcode-select --install </code></pre> </blockquote> <p>なるほど……? と思い実行して、その後改めて <code>rbenv install 3.1.1</code> とかやってみたらビルドできた。Xcodeのコマンドラインツールがおかしいという場合もあるらしい。</p> <p>まあ、コマンドラインツールのインストールし直しでだいぶ時間がふっとんだけど。そしてrbenvは新しいバージョンをインストールするといつもビルドが走る。ビルド待ちの間にmacのファンが回るのを聴きながらYouTubeでニュース見てるといつの間にか不毛な一日がまた終わってく。</p><![CDATA[VSCodeでシステムのSolargraphを使うときのメモ]]>https://blog.nksm.in.net/2022-02-28-VSCodeでシステムのSolargraphを使うときのメモ/https://blog.nksm.in.net/2022-02-28-VSCodeでシステムのSolargraphを使うときのメモ/Mon, 28 Feb 2022 13:59:36 GMT<h2>結論</h2> <p>先に結論を書いておくと、以下のようにsettings.jsonに書けば解決した。</p> <pre><code class="language-json">{ // 省略 "solargraph.useBundler": false, "solargraph.commandPath": "/usr/local/lib/ruby/gems/3.1.0/bin/solargraph", // 省略 } </code></pre> <h2>結論に至るまで</h2> <p>VSCodeでRuby Solargraphという拡張を使ってSolargraph使おうとしたら以下のようなエラーが表示された。</p> <pre><code>Solargraph gem not found. Run `gem install solargraph` or update your Gemfile. </code></pre> <p>Ruby初心者なので意味がわからず、とりあえず言われた通りのコマンドを実行してインストールしてみた。 が、やはり同じエラーが出る。</p> <p>パスが通っていないから? と思い以下のような感じでパスを通した。</p> <pre><code># ~/.zshrc export PATH="/usr/local/lib/ruby/gems/3.1.0/bin:$PATH" </code></pre> <p>これでシェルで直接 <code>solargraph</code> を実行することはできるようになった。それでもVSCode上ではエラーになる。</p> <p>色々調べたら、プロジェクトではなくシステムにインストールしてあるSolargraphを使いたい場合は、<code>solargraph.useBundler</code> という設定値にfalseを渡してやる必要があるようだ。 なので、settings.jsonに以下のように書いてみた。</p> <pre><code class="language-json">{ // 省略 "solargraph.useBundler": false, // 省略 } </code></pre> <p>でもやっぱりだめ。さらにググると、<code>solargraph.commandPath</code> なる設定項目もあるらしい。これが怪しそう。なので、ローカルに入ってるSolargarphのパスを直接指定。</p> <pre><code class="language-json">{ // 省略 "solargraph.useBundler": false, "solargraph.commandPath": "/usr/local/lib/ruby/gems/3.1.0/bin/solargraph", // 省略 } </code></pre> <p>動くようになった。</p> <p>本来はプロジェクトごとにRubyのバージョンも違うだろうし、プロジェクト単位でSolargraphをインストールして使う想定なのだろうが、ちょっとしたスクリプトを書きたい場合などにはシステム側のRubyを使うこともある。頻繁にある。 なので基本はグローバルにインストールされてるSolargraphを使うことにしていきたいと思う。</p><![CDATA[Gitで記事管理できるフルマネージドのブログサービスが欲しい]]>https://blog.nksm.in.net/2022-02-26-Gitで記事管理できるフルマネージドのブログサービスが欲しい/https://blog.nksm.in.net/2022-02-26-Gitで記事管理できるフルマネージドのブログサービスが欲しい/Sat, 26 Feb 2022 18:29:59 GMT<p>いまこのブログには2年くらい前に流行ったJAMスタックというアーキテクチャを採用している。ブログの記事はマークダウンで書いて、それをGitHubにプッシュしたらNetlifyのCDが動いてビルドしてNetlifyにデプロイという流れだ。NetlifyはGatsby.js製のソースをビルドした後の静的ファイルをホスティングしているだけで、動的なバックエンドが要らないのでお金がかからない。しかも流行っている。Jekyllみたいにダサくない。はずだった。</p> <p>しかし、これがいまはもう完全に負債になっている。はっきり言えばゴミだ。自分でデザインしているから見た目は糞だし、Nodeのバージョンも全然追いつけてないし、依存ライブラリもどんどんdeprecatedになってるし、記事を書いてビルドするたびに、ああ俺はいまゴミをビルドしているな、と感じる。</p> <p>思えば、JekyllでGitHub Pagesとか使ってたのも、安いからそうしていたのではなくて手間をかけたくないからそうしていたのだ。使い慣れたエディタでマークダウンで書いてプッシュしたら即公開というのが良かったのだ。しかしJekyllもGatsbyも数ヶ月放置するだけでいろいろなところがほころびてくる。やれ脆弱性だなんだとGitHub上のbotがやかましく言ってくる。ローカルでプレビューするためのビルド時も、RubyやNodeのバージョンがどんどんズレてきて、ブログ記事をプレビューするためだけにわざわざシステムのRubyやNodeバージョンを下げたりしないといけなくなる。本当にゴミだなあ、と感じてしまう。</p> <p>WordPressが今もずっと利用されている理由がよく分かる。ボタン一つで依存プラグインやテーマを更新。PHPのバージョンが古くなってたら警告してくれる。というか、WordPressのデプロイ先なんて個人ブログや個人経営の店舗ならたいていレンサバとかなのでサーバー屋のほうで勝手にミドルウェアのバージョン上げてくれてたりする。画像もオブジェクトストレージとの連携などうるさいこと考えなくても使える。バージョン管理機能もきめ細やかだ。記事が増えたりアクセスが増えたらサーバーの増強が要るが、それを考える段階ではそもそも商売がうまくいっているということなので月1万くらいまでサーバー費が増えようとも屁みたいなもんだろう。自分のサーバーなので広告タグもデータ収集タグも仕込み放題だ。しかもWordPressはマークダウンでもかける。</p> <p>マークダウンビルド方式のブログはどうだ。ビルドは遅い。依存関係のバージョンアップはセルフサービス。テーマの切り替えも自分で工夫する必要がある。カスタマイズしやすいといえば聞こえはいいが、キーをGitHubに上げないで各種タグを仕込むには工夫が必要だったりする。挙句の果てに、結局動的な処理が必要になってLambdaにNode.jsのコードをデプロイしたくなる始末。本末転倒もいいところだ。</p> <p>この期に及んでWordPressを使わない理由は以下の2つだろう。</p> <ul> <li>記事のバージョン管理はGitでやりたい</li> <li>管理の手間を完全にゼロにしたい</li> </ul> <p>つまり、WordPressでは記事のバージョンがMySQLに入ってしまうのと、ボタンポチポチで済むとはいえ管理画面に入ったときに毎度雑用をする必要があるのが問題なのだ。前者はJAMスタックやJekyllが解決できるが、結局これらはWordPressよりはるかに管理の手間がかかる。後者はマネージドサービス(Seesaaブログとかはてなブログみたいなやつ)なら可能だが、GitHub上の記事と同期させるためにはCIのアクションとかでブログサービス側のAPIを叩いたりといった涙ぐましい努力が必要だ。APIの仕様が変わったりしたら目も当てられない。</p> <p>これを満たすブログサービスはこの世のどこかにはありそうな気がするのだが、ぱっと思いつかない。頑張って探す気力もわかない。今の所自分の理想を満たせそうなのは以下のツールだと思うが試してないのでわからない。</p> <p><a href="https://github.com/x-motemen/blogsync">https://github.com/x-motemen/blogsync</a></p> <p>はてなの中の人が作ってるっぽいんだけど、はてなには公式でWebで完結するように機能を作ってほしかった。それこそNetlifyのスターターキットとかその中のCMSがやってるみたいにGitHubと連携してユーザーのGitHubアカウントにリポジトリ作ってくれたりとかGUIで記事書いたらコミット&#x26;プッシュしてくれたりとか。しかしはてなはブックマークのドメインミュートみたいなユーザーからものすごく待ち望まれてる機能を何年も無視し続けたりとか機能劣化版のChrome拡張をリリースしたりという振る舞いをしている企業なので望むべくもない。(こないだの機能劣化版Chrome拡張は自サイトを経由させたいという強い気持ちしか感じられずダークな印象を強く受けた)</p> <p>自分で作れるなら作りたいが自分の意志薄弱さは自分が一番知っている。誰か作ってくれたら課金するので作ってほしい。</p><![CDATA[diffのexit statusは差分があれば1]]>https://blog.nksm.in.net/2022-02-24-diffのexit statusは差分があれば1/https://blog.nksm.in.net/2022-02-24-diffのexit statusは差分があれば1/Thu, 24 Feb 2022 21:23:50 GMT<p>テスティングフレームワークとか使わずに簡易的にプログラムをテストしたい場合、どんな言語でも最初はシェルスクリプトを使ったりする。標準出力を比較するだけでいい場合とかは結構手軽だ。</p> <p>あるとき、複数行の出力を比較したくなったときに、実行結果と期待値を一旦ファイルとして書き出して、その2つのファイルをdiffで比較する、というのをテストのスクリプトに書いた。そしたらなぜかexit statusが1でファイルが途中で止まってしまう。<code>set -e</code>しているので途中の処理が1を返したら止まること自体はおかしくないのだが、色々いじってみたらdiffを実行している行で止まっているっぽかった。</p> <p>diffがおかしいのかと思って、その行のコマンドだけ叩いてみると普通に実行できる。diffそのものもおかしくない。なぜだ、、、と思っていたら、diffの結果ファイル同士に違いがある場合はexit statusが1になっているのに気づいた。</p> <p>ぐぐってみると以下のページが見つかった。</p> <p><a href="https://askubuntu.com/questions/698784/exit-code-of-diff">https://askubuntu.com/questions/698784/exit-code-of-diff</a></p> <p><a href="https://man7.org/linux/man-pages/man1/diff.1.html">https://man7.org/linux/man-pages/man1/diff.1.html</a></p> <p>つまり、diffの仕様としては以下のようになっている。</p> <ul> <li>差分がない場合、exit status は 0</li> <li>差分がある場合、exit status は 1</li> <li>エラーの場合、exit status は 2</li> </ul> <p>というわけで、スクリプト中のコマンドの終了ステータスが0以外のときは途中で止まるようにしている場合はdiffをスクリプトに混ぜると想定外の挙動になったりするかもしれない。<code>set -e</code> をしないようにするなり、diffを使う行を <code>set +e</code> と <code>set -e</code> で囲むなりしたほうが良さそうだ。多分CIとかの途中の処理でdiffを使う場合も同じ問題が起こると思う。(ちなみに <code>-e</code> でフラグを立てるのに <code>+e</code> でフラグを下ろす感じになってるの、+と-が逆の意味を持つ記号というところから来ているのだろうが、直感に反する感じになっていてモヤモヤする)</p> <p>なんでこんな仕様になってるんだろう。diffというのは2つのファイルに違いがないことを「正しい」とみなすようだ。。。原本と複製を比較する的な発想なんだろうか。</p><![CDATA[Railsのlink_toでDELETEメソッドが使えないとき]]>https://blog.nksm.in.net/2022-02-23-Railsのlink_toでDELETEメソッドが使えないとき/https://blog.nksm.in.net/2022-02-23-Railsのlink_toでDELETEメソッドが使えないとき/Wed, 23 Feb 2022 19:15:35 GMT<p>Railsは7.0.0。Rubyは3.0.3。</p> <p>Railsのlink_toで以下のようなやつを書いていた。</p> <pre><code>= link_to 'ログアウト', destroy_user_session_path, :method => :delete </code></pre> <p>しかし「idがsign_outのユーザーはいません」的なエラーが帰ってきていた。しかもメソッドがGETになってしまっている。はじめはDeviseがおかしいのかと思ったけど違うようだ。</p> <p>Turboを使っているからなのか、どうも <code>:method => :delete</code> をつけてもDELETEになってくれないようだった。色々ググっていたら下記を見つけた。</p> <p><a href="https://github.com/heartcombo/devise/issues/4486#issuecomment-444534885">https://github.com/heartcombo/devise/issues/4486#issuecomment-444534885</a></p> <p>つまり、<code>link_to</code> ではなくて <code>button_to</code> を使えばいいっぽい。</p> <pre><code>= button_to 'ログアウト', destroy_user_session_path, :method => :delete </code></pre> <p>他の方法で頑張る場合は自分でAjaxの処理を書かないといけないらしい。</p> <p>最近Railsはじめたけどかったるいことが多い。正直生産性が高いとは思えない。すごくみじめな気持ちになる。なんでこんなのが流行っていたのかわからない。けど修行だと思って頑張る、、、</p><![CDATA[フリーランスエンジニア業界は焼畑農業だ]]>https://blog.nksm.in.net/2022-02-08-フリーランスエンジニア業界は焼畑農業だ/https://blog.nksm.in.net/2022-02-08-フリーランスエンジニア業界は焼畑農業だ/Tue, 08 Feb 2022 20:46:37 GMT<p>※ここでいうエンジニアとはIT系のエンジニアのことです</p> <p>エンジニアを雇うときにフリーランスを使うというのが一般的になっている。エージェントは沢山いるし、フリーランスエンジニアになって年収1億を超えたい駆け出しエンジニアはわんさかいるし(最近はそうでもないのかもしれないが)、正社員採用したくないからフリーランス使って気軽にクビ切りたい会社も大勢いる。</p> <p>フリーランスエンジニアとの取引はものすごくWIN-WINだ。エンジニア側は、今まで会社に「搾取」されていた分のカネを独り占めできる。会社に所属していた頃は人月単価は100万だったのに給料は月給換算で40万しかもらえていなかった。ところがフリーランスになると70,80万は余裕でもらえる。これは税金引いた上でも美味しいし、高価なMacやiPhoneを経費にできる。会社員のときは会社が60万も「上前」をハネていたのに、フリーランスになったらエージェントが20%位をマージンで持っていくだけだ。直契約ならそれすら無い。100%自分のものだ。……というような話は全然珍しくない。</p> <p>フリーランスを雇う会社にも嬉しいことがある。フリーランスは3ヶ月でクビにしてもよい。正社員を雇って固定費が増えることを何より恐れる中小企業は、正社員より単価が高くても業績やプロジェクトのフェーズに応じてクビにできるフリーランスは非常に助かる。正社員じゃなくても、今までSES企業とかに発注してた単価が100万とかだったのに、同じかそれ以下の単価で管理コストをぐっと下げて労働力を得ることができる。会社同士の付き合いだと、相手も会社なので強気で来られることはあるし、短期間で契約終了とかを繰り返していると信頼を失う。業者のマネージメントもかったるい。その点フリーランスはカネさえ払っておけば言いなりになってくれる。立場が弱いので無茶振りにも答えてくれる。</p> <p>しかし長期的にはフリーランス偏重の体制は人材の枯渇を招く。SES企業が「搾取」していたカネは、実は会社が新しい事業に投資するために使われていたかも知れない。新しい事業は、「パッケージ」だとか「SaaS」だとかであることが多いだろう。一発当てることを夢見てそれらの事業に会社は投資をするのである。それがヒットするかどうかは割とどうでもよい。そこに投資されたカネが、新人の教育や社員の新しい技術の習得に使われているということが重要なのだ。</p> <p>SESでは、経歴詐欺を行わない限りは基本的に新人を送り込むことはない。ある程度スキルを持っているプロを労働力として提供するからカネがもらえているのだ。となると、受託の会社が新人を育てるには請負契約の案件か自社開発の案件しかない。特に自社開発のプロジェクトが重要だ。顧客の要求に起因する縛りが無いため、社員は自由に技術選定できるし、納期が厳しくないのでベテランと新人を組ませることで時間をかけて新人を教育できる。そういうプロジェクトを経験することで人材は育つ。</p> <p>もし発注企業がフリーランスばかり使うようになったらそのような機会はなくなる。中堅〜ベテランの人材は新しい技術を習得する機会を失うし、新人は一人前になる機会を失う。新しい人材が市場に増えなくなるばかりか、中堅クラスのエンジニアがスーパーエンジニアになる機会も減るのだ。</p> <p>フリーランスを雇う企業にしても同じことで、自社で社員を雇わないということは知見が組織に残らないということだ。組織に知見があるからこそ、その中で育った人材は複利的に価値を高めることができる。フリーランスに何でもやらせていてはそれが不可能だ。結局、市場全体で人材の付加価値が増えない。LaravelとReactとFlutterができる人材ばかりが市場にあふれかえる。ググっても出てこない問題は解決できない。未経験者が仕事を得る手段はプログラミングスクールやらオンラインサロンやらの胡散臭いルートしかなく、多少賢い駆け出しエンジニが「バッターボックスに立つ」ために経歴詐称を覚える。そんなやり方でまともなエンジニアが増えるわけもなく、メガベンチャーやユニコーンに有名大卒のエリートが就職できるのみで大半の凡人は搾取されるだけされた末に心折れて実家に帰るのだ。</p> <p>この業界が健全に存続していくためには、フリーランスエンジニアを安易に雇うのを禁止すべきだと思う。フリーランスを雇うのは未来のリソースを食っているのと同じだ。自社で社員を雇用して、つまりリスクを背負って、自社製品を開発したり開発業務を受注したりする会社がちゃんとした人材を育てていたのだ。いやまあ、そうじゃない会社もいっぱいあったとは思うけど、少なくともその一部は社員として雇用することによってこそ人材を育てていた。</p> <p>フリーランスで開発を請け負った個人は人材を育てない。弟子を取るわけもないし、自分自身の成長のために時間を使うことも少ない。フリーランスをしながら成長できるのは、やはり上澄みだけだ。9割以上のフリーランスは、ヒットしたアプリのクローンみたいなものを作らされている。あまりに同じものばかり作らされるので仕事が嫌になってくる。それでも儲けは会社員時代より良いので耐えているのだ。プログラミングを始めた頃の情熱はもう無い。</p> <p>この業界は後どれくらいフリーランス依存を高められるのだろうか。エンジニアの数が増えないと2030年がヤバいみたいな話が言われているにも関わらず、フリーランスを雇い続ける会社は持続可能性なんてどうでもいいという姿勢をはっきり打ち出しているに等しい。</p> <p>そういう状況に嫌気が指した。フリーランスと書いているけど、副業エンジニアも同様。もし市場に人材が増えたほうが良いと思っているならば、フリーランスを雇うことでカットできたコストの何割かは人材育成事業に投資するべきだ。それをしない会社には早く退場してもらいたい。安易にフリーランスに転身するエンジニアにも考えを改めて欲しい。転身してもいいけど儲かったなら弟子を雇って欲しい。会社にして社員を雇うとかでも良い。</p> <p>自分さえ良ければ良いとか短期的にしのげればいいとか考えてる人々が多すぎてげんなりする。エリートだけがいい会社で高給を得ていい暮らしをしてるのも殺意を覚える。<span style="color:red"><strong>世の中を一度水平にすべきだ!!!</strong></span></p><![CDATA[頑迷さの意味について]]>https://blog.nksm.in.net/2021-11-25-頑迷さの意味について/https://blog.nksm.in.net/2021-11-25-頑迷さの意味について/Thu, 25 Nov 2021 12:10:00 GMT<p>世の中には頑迷な人がいる。保守的な考え方を絶対に改めようとしない人。無鉄砲な行動を絶対に悔悛しない人。そういう人はなぜ存在しているのかふと疑問に思った。</p> <p>例えば選挙では固定票みたいなものがある。絶対に自民党に入れる人たちや、何があっても共産党に入れる人たちだ。世の中はそういう人ばかりでなく、その時時で意見を変える人がたくさんいるから選挙の結果は毎回異なるのだろうが、何があっても頑迷に支持政党を変えない人というのは明らかにいる。</p> <p>合理的に考えたら、時と場合によって投票先を変えたほうがよい。自分に利益をもたらさない相手を頑迷に支持し続けるのは非合理的だ。選挙に限らず、自分に利益をもたらす行動をするのが生き物として正しい選択であるように思える。</p> <p>しかし、そうでない人はたくさんいる。現代社会では金を持っていることが幸せになる第一にして最大の条件だと思うが、進んで金持ちになりたいと思わない人もいる。こうした人の選択は非合理的だ。しかし、そういう人をどんなに説得しても守銭奴や我利我利亡者にならないこともあるだろう。</p> <p>別の例で言えば、勉強が得意でない学生に「真面目に勉強しろ」といくらいってもしないケースがある。勉強すれば将来いいことが待っているということは、きっと本人にもわかっている。でもやらないのだ。殆どの場合「できない」のでなく勉強を「やらない」。そこには何か合理性を超えた無根拠な頑迷さがある。</p> <p>こうした人が存在する意味とはなんだろうか。自分の仮説は、「人智を超えた事態に種として備えるため」である。人間の知能には限界がある。種としての人間にどのような災害や不幸がもたらされるか予測できないことも多い。人間の知能によって「合理的だ」と判断できる範囲で合理的に振る舞ったところで、人間の知能を超えた事態には対処しきれないのかもしれない。そのため、種としての人間は敢えて非合理的な部分を残した。そしてその非合理的な部分がある集団において「頑迷に公明党を支持する」だったり、「頑迷に勉強をしない」という行動に表れるのだろう。人智を超えた事態においては、無根拠に頑迷に行っていたそれらの行動が役に立つかもしれないからだ。</p> <p>人間の不合理さ、頑迷さ、言い換えればバカさには人智を超えたものに対する備えとしての意味がある。そう考えると、聞き分けのないバカを見かけても多少は優しくなれるというものだろう。まあ、聞き分けのないバカが増えすぎても困りものだが。</p><![CDATA[Squidでドメイン名マッチに正規表現を使う]]>https://blog.nksm.in.net/2021-10-03-Squidでドメイン名マッチに正規表現を使う/https://blog.nksm.in.net/2021-10-03-Squidでドメイン名マッチに正規表現を使う/Sun, 03 Oct 2021 18:45:01 GMT<p>Squidを使ってプロキシサーバーを構築する際、ドメイン名を使ってアクセス許可リストとかアクセス禁止リストを作る際に <code>dstdomain</code> を使うと思うのだが、パターンマッチで制御したい場合はそのままだと <code>.example.com</code> みたいにサブドメイン一括でしか設定できない。</p> <p>もうちょっと複雑なルールを作りたい時は、 <code>dstdom_regex</code> で正規表現が使える。</p> <p><a href="http://www.squid-cache.org/Doc/config/acl/">http://www.squid-cache.org/Doc/config/acl/</a></p> <pre><code>acl aclname dstdom_regex [-n] [-i] \.foo\.com ... # regex matching server [fast] # # For dstdomain and dstdom_regex a reverse lookup is tried if a IP # based URL is used and no match is found. The name "none" is used # if the reverse lookup fails. </code></pre> <p><code>dstdomain</code> と同じく、ファイルにリストを記載してそれを読み込むという使い方でOKのようだ。</p> <pre><code>acl domain_blacklist_regex dstdom_regex "/etc/squid/domain_blacklist.txt" http_access deny all domain_blacklist_regex </code></pre> <p>当然正規表現使わないほうがSquidの負荷は少ないだろうからできればドメインは <code>dstdomain</code> で設定したほうがいいのだろうけど、そうも言ってられない場合もある(あった)</p><![CDATA[真面目に働きすぎなのかもしれない]]>https://blog.nksm.in.net/2021-08-26-真面目に働きすぎなのかもしれない/https://blog.nksm.in.net/2021-08-26-真面目に働きすぎなのかもしれない/Thu, 26 Aug 2021 22:00:00 GMT<p>自分は真面目に働きすぎなのかもしれない。例えば勤務時間が朝9時から夕方18時までだったとする。そういう場合、自分は昼休憩が絶対に1時間を超えないようにしがちだし、昼休み以外の9時から18時まではみっちりと働こうとする。休憩をあまりしない。</p> <p>学生時代からその傾向はあって、宿題はあまりやらないほうだったが、授業中に寝たことはない。予備校生時代に深夜まで勉強しすぎてどうしても眠くて講義中寝るということはあったが、小中高は授業中寝るということはなかった。</p> <p>要するに手を抜くのが苦手なのだろう。プログラミングの仕事は頭を結構使うので、朝から晩まで集中力は持たない。だからそれを埋め合わせするためにカフェインを取る。プログラマーがコーヒー好きなのは、要するにドーピングしているのである。</p> <p>だが、その結果18時を回る頃にはヘトヘトになっている。カフェインは元気の前借りをしているだけで、元気が湧いて出てくるわけではない。使った分の支払いは後で必ずある。結果、夜はぐったりして何もやる気が起きない。勉強などにも身が入らない。</p> <p>そういう生活を続けていた上に、仕事の量がこのところ膨大なのもあって肩こりがやばい感じになってきたのを期に、一度カフェインをやめてみた。すると肩こりはだいぶ改善してきた。しかし、同時に午前中の集中の質が悪くなった。午後はカフェインを使っていた頃は4時位になるとガス欠気味になっていたのだが、最近はそんなこともない。カフェインを取らないと、自分は午後からエンジンがかかってくるタイプなのだとわかった。</p> <p>日中の時間帯にフルマックスで働いてないので(カフェインを取ってないので)最近は夜の時間にもまだ元気が残っている。だからこうして文章を書いたりできる。勉強もできる。結果として、コーヒーをガブガブ飲んでいた頃よりもトータルでは優秀なプログラマになれるのではないか。</p> <p>真面目に働くことは良いことだ。だが働くことにばかりリソースを使うと、投資に割くべきリソースがなくなってしまう。健康やメンタルや勉強は投資対象の一種だ。対価を得るための労働は、短期的な資金獲得に過ぎない。真面目に働くことで機会損失をしてしまうのだ。</p> <p>真面目に働かないことが大切だ。納期についてガミガミ言ってくる顧客は無視すればいい。自分の主人は自分だけだ。自分が死んだらゲームオーバーだ。逆説的だが、真面目に働かないことによって価値が生まれるのではないだろうか。もう真面目に働くのはやめる。</p> <p style="font-size: 10rem;">真面目に働くのはやめる!!!</p><![CDATA[日記]]>https://blog.nksm.in.net/2021-08-24-日記/https://blog.nksm.in.net/2021-08-24-日記/Tue, 24 Aug 2021 23:25:16 GMT<p>最近色々とつらい。大きく2つつらさの原因があって、一つは仕事が多すぎる。もう一つは会社も(いまのところ)うまくいってない。</p> <p>つらさを吐き出すために超久々にここにメモしておく。</p> <h2>仕事が多すぎる問題</h2> <p>仕事が多すぎる。なぜ多すぎるのかというと、完全に自分の判断ミスではあるが、去年新型コロナウイルスが流行り始めたタイミングと自分がフリーランスになったタイミングが全く一緒で、ものすごく先行きが不透明だった。もしかしたら仕事がさっぱりなくなるかもしれないと思っていて、それを見越してどんな仕事でもとりあえず受注して仕事を確保したほうが良さそうだと判断してしまった。</p> <p>これは完全に間違いだった。どんなに社会の状況、外部の状況が悪くても、それによって自分が受けるべき仕事の判断を変えるべきではない。受けるべき仕事はどんな社会状況でも受けるべきだし、断るべき仕事はどんな社会状況でも断るべきだ。なぜなら、仕事は常に自分と仕事との相互作用だからだ。社会情勢の入り込む余地は間接的でしかない。</p> <p>会社で雇用されて働くビジネスマンであれば、社会情勢の知識は話題作りやマーケティングなどに使えるだろう。それによって仕事をいい方向に転がしたり悪い方向に転がるのを防いだりということもあるだろう。それは、その人が社員だからだ。給料を毎月もらえるからだ。安定しているから、社会情勢等を気にする余裕があるのだ。</p> <p>しかし、本当に大事なのは目の前の仕事。社会情勢ではない。目の前の仕事を受けるか受けないか、それを判断する材料は、自分がその仕事を受けるべき人間なのかそうでないのかだけだ。</p> <p>受注の話を書いてはいるが、本質的には自社企画の仕事だろうと全く同じことだろうと思う。新型コロナウイルスが流行っているからとピボットした企業が沢山あったらしいが、どのくらいの会社が成功したのだろうか。成功したのは、コロナ以前からリモートワークを便利にするツールを作っていた企業だけではないだろうか。自分のやるべき仕事を普通に頑張っていた人たちが、たまたまコロナの状況で売れたというだけで、コロナ禍に棹さして儲けようとしてもさして儲からないのではないか。また、防御的な姿勢を取ろうとしてもうまく行かないのではないか。</p> <p>本当に貴重な教訓を得た。仕事においては社会情勢など関係ない。どんなに社会がひどくなろうと、仕事においては目の前の仕事にどう向き合うかだけが問題だ。</p> <h2>会社がやばい問題</h2> <p>やばいと行ってもカネがないとか倒産しそうという話ではない。まあ、このままの状況が続けば倒産もあり得るとは思うが、自分の給料をめちゃくちゃ安く設定しているので当分はしぶとく生きていきそうな気がする。</p> <p>それよりも問題は、採用に失敗してしまった件である。どういう失敗かと言うと、平たくいえば相手の属性のみを見て採用してしまった。蓋を開けたら全く向いていない人だった。というか全く働かない人だった。フルリモートで採用したのだが、全く作業が進んでいなかったので進捗報告で嘘をついていたフシすらある。属性だけを見てその人自身を見ないというのは、世の採用担当の人は結構やりがちな失敗なのかもと今は思う。</p> <p>どんなにその人の学歴や経歴やその他の属性に引かれたとしても、採用の際にその人自身の資質を見極めることは大事だ。見抜くべき資質は、性格だけではない。具体的なスキルも見るべきだ。その人の仕事への態度も見るべきだ。仕事できそうな人が実際は全く働かず「できる風」を装うのがうまいだけというのは本当によく聞く話。</p> <p>一方で、属性が非常に便利なフィルターになるのも真実だろう。ただ、人材が溢れている市場でのみそれは意味を持つ。買い手市場では属性によるフィルタリングは費用対効果が高かっただろうと思う。しかし今は人手が足りない時代だ。そういう場合は属性にだけ頼ったフィルタリングはうまく行かないのだと思われる。むしろ、属性ではなく能力でフィルターするべきだ。具体的には、実際に話してその人のスキルを確認してみたり、仕事に対する考え方を聞いてみたり、一週間程度お試しで仕事してみたり、という活動をするべきだ。</p> <p>当然これは非常にコストパフォーマンスが悪い。悪いのだが、マッチしない人材を雇って時間と金をドブに捨てるよりはよっぽど賢い方法だ。採用をまともにやってる会社はみんなそういうことをやってるのだろうと思う。自分にはその賢さが足りなかった。本当に手痛い損失だった。</p> <p>自分が本当に人を雇いたいのか、また、本当に今雇うべきなのか、といったことも考えるべきだと思う。自分は、今の会社のミッションとして雇用を増やすという目標があるので(+銀行に見せた事業計画書も人を増やして稼ぎを増やすのが前提なので)人を増やすのはほとんどマストなのだが、そういうミッションを特に持たない会社であれば法人化して一年未満のこのタイミングで人を雇うかどうかは真剣に考えたほうが良いかなと思う。人を雇うととにかく金がかかる。未経験者なら尚更金は出ていく一方だ。人への投資は尊いものだが、同時に一番リスキーな投資だとも思う。</p> <p>人間社会が人間で成り立っている以上、どんなにリスキーであってもいつかは人に投資せざるを得ないのだが、タイミングは重要だ。</p> <h2>つらさを克服するために何をやっているか</h2> <ul> <li>人生3度目くらいのカフェイン断ちをやっている。肩こりがとれる</li> <li>メインの案件を変えた</li> <li>週末温泉に入っている</li> <li>どんなに遅くなっても22時までしか仕事しないように決めた</li> <li>最低でも週1日は全く仕事をしない日を作った</li> </ul> <p>正直大学受験の勉強やってたときよりもつらい。人生がこんなにつらくなるとはあのころ思わなかったなあ。</p><![CDATA[ZombieLandSaga]]>https://blog.nksm.in.net/2021-05-09-zombielandsaga/https://blog.nksm.in.net/2021-05-09-zombielandsaga/Sun, 09 May 2021 14:57:33 GMT<p>続編である『ゾンビランドサガ リベンジ』が放映中であるが、以下は一期の『ゾンビランドサガ』について書いた文章である。</p> <hr> <p>『ゾンビランドサガ』には「学習性無力感」あるいは「学習性無気力」と俗に呼ばれることもある現象をいかに克服するかというテーマがある。</p> <p>それは第十一話、第十二話において顕著であるが、実際には作品を通して存在するテーマである。</p> <p>たとえば、第一話ではメンバーの中でただ一人意識を取り戻した源さくらは、アイドルとして活動することに懐疑的で無理だと感じていた。</p> <p>しかしデスメタルイベントのステージで絶叫とヘドバンを経験することで、ステージに立つことの可能性を見出す。</p> <p>また、第二話ではさくら以外のメンバーもアイドル活動を無理だと感じているが、さくらの即興ラップによってサキ・リリィ・ゆうぎりはアイドル活動を肯定的に捉える様になる。</p> <p>第三話でも愛・純子について同様の過程が描かれる。この二人については後の第六話、七話においても、死亡した原因というトラウマの克服・アイドル観の違いという壁の克服が再度描かれる。いずれも「無理」だと思っていたことを成し遂げる過程が繰り返される。</p> <p>八話では死んでしまった人間が生きている人間を元気づけるという「無理」を、九話では子が親と和解するという「無理」を、それぞれ可能にしてみせる。</p> <p>十話においても同様だ。さくらは一度、他のメンバーと歩調を合わせることを「無理」だと判断してしまう。</p> <p>『ゾンビランドサガ』の「無理」の克服は、しかしこの作品独自のテーマだと言えるだろうか? 登場人物が壁を乗り越えるというプロット自体はありふれたもので、成長を描こうと思えば必然的にこのような骨組みを物語は持つだろう。</p> <p>しかし、この作品における「壁」の特徴は、それを乗り越える当人が、乗り越えることを「無理」だと断じている点だ。『ゾンビランドサガ』において壁とは常に自分自身が「無理」だと感じていることそれ自体である。</p> <p>この作品では終始、「無理」だという判断が思い込みに過ぎなかったと気づくことが成長に結びついている。</p> <p>さらに、この気づきは常に他者からもたらされている。第一話のさくらは幸太郎に無理やりステージに立たされることによって、第二話のサキ・リリィ・ゆうぎりはさくらの即興ラップによって、第三話の愛と純子はゲリラライブを行う他のメンバーの姿を見ることによって、その思い込みに気づかされる。</p> <p>十一話と十二話では、他のメンバーの「無理」を覆してきた当の「源」であるさくらが「無理」に囚われる。が、ここでもやはり幸太郎や他のメンバーやファン達という他者によってその思い込みに気づかされる。</p> <p>意思の疎通が困難であるたえでさえ、さくらの根気強い「教育」によってアイドルらしい所作を学習し、最後にはさくらの「無理」が思い込みであることを気づかせる為に動く。</p> <p>ではなぜ「無理」だという思い込みは生まれるのだろうか。</p> <p>それは学習によってである。源さくらについては端的に「持ってない」という言葉によって表現される。能力や努力が足りずに「無理」なこともあるが、能力が努力が足りていても運が悪いだけで「無理」だと認識してしまうこともある。そのせいで、何をやっても無駄だと学習してしまう。</p> <p>さくらの「学習性無気力」が最もわかりやすく描かれてはいるものの、他のメンバーについても基本的には同様だ。</p> <p>サキ、リリィ、ゆうぎりは、個別に具体的に描かれているわけではないものの、第二話においてサキが三人の心情を代表的に表していたと考えるべきだろう。最初に目覚めたさくら本人と同様に、ゾンビになってしまった自分がアイドルになるなど「無理」だと思っていただろうし、そのことに価値も感じていなかっただろう。彼女らにはアイドルではない生前の自分があるし、その自分がゾンビの身でアイドルになるというのは通念上は「無理」である。</p> <p>愛と純子については他のメンバーのレベルの低さやアイドル観の違いが直接的な「無理」の原因になっているわけだが、さらに根本的な原因は自身のアイドルとしての経験から過剰に学習してしまっていることにある。生前の記憶にない新しいアイドル像としてのフランシュシュを経験することで、徐々にその思い込みを剥がされていく。</p> <p>『ゾンビランドサガ』という作品が発しているメッセージは以下のようになるだろう。</p> <ul> <li>人は、本来可能なことを「無理」だと思いこんでしまうことがある</li> <li>その思い込みは過去の経験から学習することによって形成される</li> <li>形成された思い込みは他者の働きかけによってのみ思い込みだと気づくことができる</li> </ul> <p>視聴者が『ゾンビランドサガ』からエネルギーをもらうことがあるとするなら上記のメッセージを形を変えながら繰り返し発し続けていることよるのだろう。</p> <hr> <p>私達はゾンビである。ゾンビは生きる屍だ。生きる屍という比喩は生きている人間にこそ用いられる。人は生きてゆく中で様々なことを行い、その結果から学び、自身の行動を修正する。複雑化したこの世界において、行動の結果は期待せざるものであることが多い。我々は肥大化した制限条項の中をかいくぐって生きている。本来できるはずのことを自ら禁止することで安定した生活を手に入れる。そしてできるはずのことを「無理」だと断じることでいつのまにか生きる屍に成り下がるのだ。</p> <p>学習性無気力という言葉を心理学的な症状として捉えれば、普通の人々にはほとんど無関係だと感じられるかも知れない。大抵の人は「何をやっても無駄」と感じるほど無気力ではないし、仕事や娯楽の為には気力を発揮することもあるだろう。</p> <p>しかしそれは数多の学習の末、気力を発揮できる方向性を自ら限定してきた結果にすぎない。自分が何をしたいのか、という問いを封印し、自分は何ならできるのか、何ならやっても許されるか、という観点でしか考えなくなってしまったゾンビなのだ。自分が無気力であることに気づいてすらいない、意思を剥奪された木偶なのだ。</p> <p>そしてゾンビはゾンビ同士で馴れ合って、「私達には無理だよね」「俺たちには無理だよな」というコミュニケーションを繰り返す。無論その事によって終わりなく続くかに見える安心安全な日常がもたらされていることも確かだ。しかしそれは墓場の日常である。</p> <p>『ゾンビランドサガ』では、生きる屍であるゾンビたちが斯様な思い込みを少しずつ塗り替えることで新しい現実を手に入れていく。佐賀を盛り上げることなど無理。自分がアイドルになるなど無理。あの人とわかり合うことなど無理。確かにどんなに逆立ちしても無理なことは現実にあろう。しかしそのいくつかは思い込みなのだ。思い込みであることに気づいた者は、望んだものを手に入れることができる。</p> <p>もし俗に言う「学習性無気力」の人間が心に傷を負っているとするならば、この世を生きる人間の殆どは数え切れないほどの傷を負って生きている。傷を負っていないように見える普通の人々ほどそうである。彼ら彼女らの心を可能性の方向へと開かせることは難しい。自分の今の生活を延長させることにしか関心が無い。そのような人々の心にこそ、『ゾンビランドサガ』は気づきを与えるのだろう。いくつかの「無理」が思い込みであり、自分自身の心が激しく傷ついた状態であるという気づきを。それ故に作品は癒やしになる。自分にも何かができるかも知れないと思わせる。</p> <p>ゾンビという言葉は生きる屍以外にもう一つの言葉を連想させる。復活だ。人に元気を与えて復活させるのがアイドルであるとするならば、ゾンビとアイドルというテーマは実はそう遠いものではない。『ゾンビランドサガ』ではまさに源さくらを無気力から復活させる者として水野愛を描写した。そして源さくらは今や自分自身がファンを「がば元気に」させるアイドルとなった。</p> <p>本来はアイドルを追いかけるファンたちこそが、アイドルから元気をもらい復活のきっかけとしているという意味でゾンビである。しかし『ゾンビランドサガ』ではゾンビこそがアイドルとして活動する。我々と変わらない、生きる屍のゾンビが、アイドルとして他者を勇気づけている。そのことから再び「学習」すれば、私達も墓場を抜け出すことがあるのかも知れない。</p><![CDATA[CDKではDBClusterのARNを取得できないかもしれない]]>https://blog.nksm.in.net/2020-11-08-CDKではDBClusterのARNを取得できないかもしれない/https://blog.nksm.in.net/2020-11-08-CDKではDBClusterのARNを取得できないかもしれない/Sun, 08 Nov 2020 01:44:11 GMT<p>色々やってみたのだがAuroraのClusterのARNが取得できない。</p> <p><a href="https://stackoverflow.com/questions/60627544/how-to-get-the-arn-of-an-aws-cdk-delivery-stream-construct">https://stackoverflow.com/questions/60627544/how-to-get-the-arn-of-an-aws-cdk-delivery-stream-construct</a></p> <p>上記のページをみて、IDを取得してからGetAttでARNを取得する方法もやってみたが、CloudFormationの制約でそもそもAuroraのクラスタではGetAttで取得できる属性にARNが無い。</p> <p><a href="https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#aws-resource-rds-dbcluster-return-values">https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#aws-resource-rds-dbcluster-return-values</a></p> <p>上記に書いてある内容によれば、クラスタのエンドポイントとポートしか取得できない。</p> <p>CDKのGitHub Issueにもこの問題は挙げられてて、ARNの命名規則をもとに手で作るという対応方法が語られてるが、命名規則がある日変わった場合に対応できないのでイケてない。CDKのバージョンも日々上がるし、そう毎日毎日CDKデプロイするわけじゃないと思うのでAPIの変化に気づかないまま時間が経つ気がする。たまに実行するたびに毎回修正する必要があるのではコード化する恩恵があまり受けられない。</p> <p><a href="https://github.com/aws/aws-cdk/issues/2107">https://github.com/aws/aws-cdk/issues/2107</a></p> <p>クラスターのARNを返すという機能が一旦はmasterまでマージされたものの何故かリバートされてる。結局CDKのコードではアスタリスクを使わざるを得ない気がする。</p> <p>これはCDKの問題ではなくCloudFormationの設計がなんかおかしいということだと思う。CloudFormationは他にもRDS Proxyのデプロイが永遠に終わらない問題もあり、ちょっと信頼性が怪しい。</p> <p>インフラの自動化は人類にはまだ早いのではないかという気がしてきている。毎日同じ環境がガンガン複製されるようなプロジェクトでもない限りインフラの自動化は楽よりも苦のほうが圧倒的に大きい。特にクラウドはそうだ。サーバー構築の自動化ならまだいい。Ansibleとかはシェルでコマンドを打ったときとPlaybook書いたときとで移植が比較的簡単に可能だ。それにサーバーを壊して作り直すというケースは運用の中で普通にあったりだとか、あるいはAnsibleで書いてあることによって気軽にサーバーを壊したりできるという恩恵が非常に大きい。</p> <p>しかしクラウドはCLIとCfn、Terraform、CDKなどが互いに移植可能かというと結構たいへんだ。それぞれに特有のハマりどころも多い。しかも一回構築したものをすべて更地にしてCDKデプロイする、みたいなケースはほとんどない。あったとしてもRDS作ったりCloudFront作ったりするのに結構な時間がかかるし久しぶりに実行したら何故かコケたりする。</p> <p>クラウドもっとシンプルになってほしい。API覚えるだけで時間と体力を消耗するのは勘弁。VPSに自分で色々構築したほうが技術のスコープは広いししっかりした知識は身につくし結局はそのほうが得、みたいなことになりかねないんじゃないの。どうなの。</p><![CDATA[WSLでVagrantのSynced_folder]]>https://blog.nksm.in.net/2020-11-07-WSLでVagrantのSynced_folder/https://blog.nksm.in.net/2020-11-07-WSLでVagrantのSynced_folder/Sat, 07 Nov 2020 00:29:44 GMT<p>WSLでVagrant使うの自体はすんなりできたんだけど、いざ <code>vagrant up</code> してみたら下記のようなエラーが出てきた。</p> <pre><code>➜ vagrant git:(aws) ✗ vagrant up Bringing machine 'default' up with 'virtualbox' provider... ==> default: Box 'bento/amazonlinux-2' could not be found. Attempting to find and install... default: Box Provider: virtualbox default: Box Version: >= 0 ==> default: Loading metadata for box 'bento/amazonlinux-2' default: URL: https://vagrantcloud.com/bento/amazonlinux-2 ==> default: Adding box 'bento/amazonlinux-2' (v1.2.1) for provider: virtualbox default: Downloading: https://vagrantcloud.com/bento/boxes/amazonlinux-2/versions/1.2.1/providers/virtualbox.box Download redirected to host: vagrantcloud-files-production.s3.amazonaws.com ==> default: Successfully added box 'bento/amazonlinux-2' (v1.2.1) for 'virtualbox'! There are errors in the configuration of this machine. Please fix the following errors and try again: vm: * The host path of the shared folder is not supported from WSL. Host path of the shared folder must be located on a file system with DrvFs type. Host path: . </code></pre> <p>これ何を言われてるのかというと、VirtualBox自体はWindows側で動いてるのでVagrantとフォルダを共有できるのはWindowsのフォルダやで、ということらしい。<br> DrvFsというのがWSLがマウントしてるWindowsのフォルダのこと(/mnt/c/ みたいなパス)</p> <p>そういうわけだから、WindowsのC:\Users\Publicにvagrantというフォルダを作ったあと、Vagrantfileに以下のような一文を書く。</p> <pre><code> config.vm.synced_folder "/mnt/c/Users/Public/vagrant", "/vagrant" </code></pre> <p>その後 <code>vagrant up</code> することでVagrantの仮想環境内の/vagrantディレクトリとWindows側のvagrantフォルダが共有できた。</p> <p>関係ないけどWindows側でVagrant仮想環境と共有するフォルダってどこに作れば良いんだろうか。最初ProgramDataに作ろうかと思ったけど書き込み権限はファイル作成者にしかないらしい。かといってUsers配下のパスをVagrantfileに書いてそれがリポジトリにコミットされるのはイヤンな感じだ。</p> <p>最近Windowsで開発たまにしてるけどなかなか良い。こころなしかWindows版のVSCodeの方がキビキビしてる感じすらする。MacはARM化するしWindowsがWeb開発に向いたOSになってきてるし、なんか潮目が来てるのかも知んない。Macはスマホアプリワールドに生きる人のためのOSになるのかもしれない。Web開発でARMだと色々とビルドとかミドルウェアのインストールでハマったりしそう。ARMのサーバーがどこまで一般的になるか次第だが、AWS EC2にはARMのインスタンスあるよな。。。どうなるんだろう。。。</p><![CDATA[MySQLのSET foreign_key_checks = 0]]>https://blog.nksm.in.net/2020-09-07-MySQLのSET foreign_key_checks = 0/https://blog.nksm.in.net/2020-09-07-MySQLのSET foreign_key_checks = 0/Mon, 07 Sep 2020 19:33:39 GMT<p>MySQL で foreign key の親テーブルを truncate しようとすると <code>Cannot truncate a table referenced in a foreign key constraint 云々</code> などというエラーが出てできない。なんでだろと思ってググると以下の記事が見つかった。</p> <p><a href="https://hacknote.jp/archives/19470/">MySQLで外部キーの制約があるテーブルをtruncateする方法</a></p> <p>つまり、こんなふうにしてやれば truncate できる。</p> <pre><code>mysql> SET foreign_key_checks = 0; mysql> TRUNCATE table_name; mysql> SET foreign_key_checks = 1; </code></pre> <p>で、実務上必要なのは以上で終わりなわけだが foreign_key_checks の設定値についてもう少し知りたかったので調べた。</p> <p><a href="https://dev.mysql.com/doc/refman/5.6/ja/create-table-foreign-keys.html">MySQL5.6 の公式ドキュメント</a>から引用。</p> <blockquote> <p>foreign_key_checks を 0 に設定することは、LOAD DATA および ALTER TABLE 操作中に外部キー制約を無視するためにも役立つ場合があります。ただし、foreign_key_checks = 0 の場合でも、MySQL では、カラムが一致しないカラム型を参照している外部キー制約の作成は許可されません。また、テーブルに外部キー制約が存在する場合は、ALTER TABLE を使用して、そのテーブルを別のストレージエンジンを使用するように変更することはできません。ストレージエンジンを変更するには、まず外部キー制約をすべて削除する必要があります。</p> </blockquote> <blockquote> <p>SET foreign_key_checks = 0 を実行しないかぎり、FOREIGN KEY 制約によって参照されるテーブルに対して DROP TABLE を発行できません。テーブルを削除すると、そのテーブルを作成するために使用されたステートメントで定義されていた制約もすべて削除されます。</p> </blockquote> <p>つまり、削除以外でもレコード作成とかテーブル定義変更のときとかも外部キー制約のチェックがあるけどこれを 0 にしておくと無視できるらしい。ただ型のチェックは 0 にしてても行われる、ということか。</p> <p>ここには DROP TABLE については書いてあるけど TRUNCATE については書いてない。今まで TRUNCATE は速い DELETE くらいにしか思ってなくてあまり気にして無かったけど、改めてMySQLのドキュメント読むと TRUNCATE は DML ではなくて DDL に分類されるらしい。</p> <p><a href="https://dev.mysql.com/doc/refman/5.6/ja/truncate-table.html">参考:TRUNCATE に関する公式ドキュメント</a></p> <p>だから、下記のような違いが生まれてくる。</p> <ul> <li>DELETE よりもめっちゃ速い</li> <li>DELETE と違ってロールバックできない</li> <li>DELETE と違って削除された行数が返ってこない</li> <li>AUTO_INCREMENT のシーケンスがリセットされる</li> <li>ON DELETE のトリガーが起動しない</li> </ul> <p>なので関連性の強いテーブルのことも気にしながら TRUNCATE する必要がありそう。ON DELETE のトリガーで他のテーブルに操作をしている場合などは特に。</p> <p>この説明を聞くと、外部キー制約で参照されてるときに TRUNCATE できないというのも多少納得できた。</p><![CDATA[久々にSTEINS;GATEをやった]]>https://blog.nksm.in.net/2020-09-06-久々にSteins;Gateをやった/https://blog.nksm.in.net/2020-09-06-久々にSteins;Gateをやった/Sun, 06 Sep 2020 14:36:41 GMT<p>久々にSTEINS;GATEをやった。最近読んだ『時間はどこから来て、なぜ流れるのか?』という講談社ブルーバックスの本にSTEINS;GATEの「世界線」という用語への言及があり、そこで懐かしくなってdアニメで無印、劇場版、0と全話視聴したのがきっかけだ。ついハマってしまい、生産的な活動を全て放り投げてiOS版のゲームを購入した。</p> <p>ゲームは、無印、比翼恋理のだーりん、線形拘束のフェノグラム、の3つをやった。ELITEと0はまだやってない。</p> <p>以前は2011年のPSP版をやったことがある。たしか発売されてそんなに経ってない頃にやった気がする。同時期にアニメ化されているようなので、多分そちらもリアルタイムで視聴しているはず。</p> <p>その後は、2018年に0がアニメ化されたのでそれを観ているはずだ。なので今回STEINS;GATEに触れるのは2年ぶり3回目ということになるだろうか。</p> <p>2011年頃の印象と今あらためて持つ印象がかなり変わっていることに自分で驚いた。無印の作品自体は同じなので、自分自身の変化ということになる。</p> <p>2011年頃の自分は結構二次元美少女を類型化することに凝っていて、牧瀬紅莉栖というキャラクターに批判的だった。天才美少女には類型があって、以下の点を満たすのが天才美少女ものの物語である、というのが自分の定義だった。</p> <ul> <li>天才美少女は常識がなくコミュ障である</li> <li>主人公だけが天才美少女とコミュニケーションをとれる。天才美少女とコミュニケーションをとれる、という一点のみにおいて凡人の主人公が特権的な立ち位置を得る</li> </ul> <p>物語は読者に願望充足を与えなくてはならない。主人公は読者に同一化してもらうために能力的に凡人であるのが望ましい。凡人である主人公が読者に願望充足を与えるためには、主人公が何らかの意味で「美味しい目」に合わなくてはならない。例えば異世界転生ものであれば異世界に転生してチート能力を手に入れることが「美味しい目」だ。ラブコメであれば複数の異性に好意を持たれるのが「美味しい目」だ。天才美少女ものの場合は、唯一天才美少女とコミュニケーションを取れる特権的存在である、という点が主人公にとっての「美味しい目」になる。</p> <p>同じ科学アドベンチャーシリーズで言えばROBOTICS;NOTESに登場する神代フラウがまさに天才美少女の典型例だ。ROBOTICS;NOTESの主人公である八潮海翔は完全に凡人の域を超えているが、神代フラウとの関係においてはほぼほぼ天才美少女もののフォーマットに則っていると言って良いだろう。</p> <p>しかし牧瀬紅莉栖はそのフォーマットに則らないキャラクターだった。彼女にはしっかりとした常識があり、岡部倫太郎以外ともそつなくコミュニケーションを取れる。気が強く生意気、という性格設定はあるが、コミュ障というところまではいっておらず健全な社会生活が送れている。</p> <p>自分は当時それが牧瀬紅莉栖の欠点だと認識していた。つまり類型的なフォーマットに合わせてキャラクターを修正すればもっと良くなると思っていたのだ。自分の目にはせっかくの天才美少女という素材を「ただのツンデレ」として扱ってしまい十分に活かせていないと映っていた。</p> <p>しかし今にして思えばこのような見方は必ずしも正しいとは言えなかった。事実牧瀬紅莉栖はSTEINS;GATEのみならず科学アドベンチャーシリーズ全体の中でも最も人気があるキャラクターの一人だろう。しかも、「天才美少女には常識が欠けている」という「常識」を破って人気キャラクターとなった。これは天才美少女の概念拡張と言ってもよいだろう。身近な天才、コミュ力のある天才、このようなキャラクターはよく訓練されたオタクほど扱いづらかったのではないだろうか。天才美少女は身近ではないからこそ良い。ツンデレ美少女は身近だからこそ良い。そうした既成概念が牧瀬紅莉栖を扱いづらくする可能性があったのではないだろうか。少なくとも自分にとってはそうだった。</p> <p>二次創作に目を通してみると、牧瀬紅莉栖は単なるツンデレ美少女として受容されているように感じる。天才、という側面を表現するためには作者自身に勉強が必要だから難易度が高いのだろう。そして牧瀬紅莉栖というキャラクターの独特な魅力はそこにあるからこそ難しい。宇宙物理学や脳科学の知見を持ちながら幼馴染や同級生のような気安さも兼ね備えているからこそテンプレなツンデレが生きる。牧瀬紅莉栖のツンデレは二重のねじれだ。ツンデレ自体がねじれであるが、天才美少女という本来常識がなくコミュ障な、一般的なツンデレの枠にはおさまりにくいキャラクター類型にテンプレすれすれのツンデレ属性を注入した。ツンデレであるはずのないものがツンデレである。このねじれを忠実に再現するような妄想は案外むずかしい。ただの「クリ腐ティーナ」であればラノベにありがちなオタクツンデレ美少女に終始していたところだろう。</p> <p>牧瀬紅莉栖が天才美少女である以上、作品世界の知的な側面を担っている存在であることは間違いないだろう。その紅莉栖がねらーでありクリ腐ティーナでありスイーツ(笑)でありツンデレであるということは、多くの場面で欲望が知性に優越するということを暗示している。宇宙物理学や脳科学への知的探究心とオタク的欲望は牧瀬紅莉栖において同列に並びうるということだ。彼女の存在自体がオタク的欲望への讃歌なのである。牧瀬紅莉栖が、オタクがオタク自身を自閉的に賛美するだけのラノベ的美少女と一線を画している部分はここだろう。</p> <p>そのことが、初めてSTEINS;GATEに触れてから9年経った自分にもようやくわかってきた。自分自身があまり活発なオタクではなくなったからこそ理解できることなのかもしれない。</p><![CDATA[LaravelとVueとTypeScriptで開発始めるときのメモ]]>https://blog.nksm.in.net/2020-07-18-LaravelとVueとTypeScriptで開発始めるときのメモ/https://blog.nksm.in.net/2020-07-18-LaravelとVueとTypeScriptで開発始めるときのメモ/Sat, 18 Jul 2020 00:00:00 GMT<p>LaravelとVueで開発始めるのは簡単なのだが、TypeScriptをやろうとするといくつかエラーが出たのでメモ。</p> <p>まず、 app.js を app.ts に変える。</p> <pre><code class="language-sh">mv resources/js/app.js resources/js/app.ts </code></pre> <p>そして、いつも忘れがちだが app.ts 内の Vue のインポート方法を変える。</p> <pre><code class="language-typescript">window.Vue = require('vue'); // ↓ import Vue from 'vue'; </code></pre> <p>あと、tsconfig.jsonがないと叱られるのでプロジェクトルートにファイルを作成する。<a href="https://jp.vuejs.org/v2/guide/typescript.html">Vue公式ドキュメントから拝借</a></p> <pre><code class="language-json">{ "compilerOptions": { "target": "es5", "strict": true, "module": "es2015", "moduleResolution": "node" } } </code></pre> <p>そして webpack.mix.js を書き換える。</p> <pre><code class="language-typescript">mix.js('resources/js/app.js', 'public/js') .sass('resources/sass/app.scss', 'public/css'); // ↓ mix.ts('resources/js/app.ts', 'public/js') .sass('resources/sass/app.scss', 'public/css'); </code></pre> <p>npm run dev してコンパイル通れば成功。</p> <p><a href="https://laravel-mix.com/docs/5.0/mixjs">Laravel Mixのドキュメント</a> に、</p> <blockquote> <p>Simply update your mix.js() call to mix.ts(), and then use the exact same set of arguments.<br> Of course, you'll still want to do the necessary tweeks like creating tsconfig.json file and installing DefinitelyTyped, but everything else should be taken care of.</p> </blockquote> <p>と書いてあるので、最初はこれだけ書き変えれば良いのかなんて楽なんだと思ってたけど当然それだけではダメでした。残念。</p><![CDATA[『Learn or Die』西川徹、岡野原大輔]]>https://blog.nksm.in.net/2020-07-04-『Learn or Die』西川徹、岡野原大輔/https://blog.nksm.in.net/2020-07-04-『Learn or Die』西川徹、岡野原大輔/Sat, 04 Jul 2020 00:00:00 GMT<p>プリファードネットワークスという会社の創業者兼経営者の二人が自分たちの会社について語った本。</p> <p>プリファードネットワークス(PFN)という会社は日本国内のユニコーン企業である。スタートアップ企業の中ではダントツで価値が高いと目されている会社のようだ。求人の募集要項に、「コンピューターサイエンスのすべての分野に精通していること」と書いたことでも有名だ。</p> <p>読んでいて気になった点を書き出していくと、まず、単純な受託はやらないというのが目に止まった。かといって本の中でも書いているようにPFNは何をやっているのか外からはよくわからない会社だ。製品を売り出して広告しているわけでもない。じゃあ何をやって売上を立てているのかというと、出資元企業を始めとする他社と共同で何かを開発する、といった仕事が多いようだ。そしておそらく成果物を納品するのではなくそれを自社の資産として保持するような契約の形態になっていると思われる。作ったものを他のソリューションにも使えるようにしてあるのだろう。パッケージ開発しかしないSIerというか、BtoBのサービスしか作らない(表にも出さない)Saasみたいなものかもしれない。</p> <p>また、西川徹氏がスタートアップ起業家によくいる意識高い系ではなくほとんど技術者タイプの人であることも面白かった。ビジネス書は起業当初に読んでいただけで、本に影響を受けるのが嫌で読むのをやめたらしい。一方で技術書はたくさん読むそうだ。数多の意識高い系アントレプレナーが屍を築いているというのに全く違うタイプの人たちが国内で圧倒的ナンバーワンのポジションに居るというのが面白い。</p> <p>読んでいて、クラスメソッドと近い雰囲気を感じた。あそこもおそらく、単なる受託開発はしないというスタンスなのではないだろうか。今後はこういった方針の会社が成功していくような気がする。</p><![CDATA[『日本社会のしくみ』小熊英二]]>https://blog.nksm.in.net/2020-06-28-『日本社会のしくみ』小熊英二/https://blog.nksm.in.net/2020-06-28-『日本社会のしくみ』小熊英二/Sun, 28 Jun 2020 00:00:00 GMT<p>日本社会の雇用の歴史の本。年功序列や新卒一括採用といった日本の雇用慣行がどのように形成されてきたのかを詳述している。</p> <p>それはそれで面白いのだが長過ぎると思う。歴史の記述自体がこの本の目的であるならばこの長さで問題ないのだろうが、多くの読者はそれを求めてこの本を読むのではないだろう。文字通り、日本社会のしくみが知りたくて繙くわけだ。しくみの説明自体は1,2,8,終章の4つで足りると思う。本のサイズは半分以下で済むはずだ。歴史の詳述は別の本にまとめたほうが親切だった。</p> <p>小説なら別だが、何かを論じた本が長すぎるのは、読者にとって良いことはなにもない。時間と労力(とカネ)を費やさねばならなくなる。長過ぎる本は読者にコストを強いる。であるならば著者はそのコストに見合うだけの内容を提供せねばならない。私にとっては、この本は労力の二分の一程度の内容しか提供しなかった。</p> <p>長過ぎる本は、結局何を言いたい本なのかを見えにくくする。何を言いたいのかわからない本は、存在価値が薄い。</p> <p>歴史を知りたい人がこの本を読めば、労力に見合う内容を得られるだろう。しかし新書を手に取る読者は手軽に知識を手に入れたい人々であって、労力を費やしたくないから新書を読むのである。この本の企画にはなにか根本的な誤解があるような気がする。</p> <p>まあ、それでも結局本が売れれば出版社も著者もそれで良いのだろう。労力を嫌う新書読者層のどれほどの割合の人が、この本を飛ばさず誤読なく読み通すのかはかなり疑問ではある。</p> <p>新書はやっぱり短くわかりやすくまとまっており参考文献が次の書物へのガイドラインとして機能しているものが一番という学びを得られたので良しとする。</p><![CDATA[読書のロードマップ]]>https://blog.nksm.in.net/2020-06-25-読書のロードマップ/https://blog.nksm.in.net/2020-06-25-読書のロードマップ/Thu, 25 Jun 2020 15:04:19 GMT<p>読書のロードマップを作ることにした。理由は、積ん読を消化したいからだ。</p> <p>積ん読はキューではなくスタックである。新しく買った本が一番上に積まれる。消化は、一番新しい本から始まる。これは物理的にスタックを作ることはない電子書籍の場合でも同じだ。人間の関心は新しいものにいきがちだ。だからずっと読まねばと思っていた本が消化される可能性は低い。</p> <p>しかし読書は本来キューを消化する形で行われるべきだ。高度な知識は土台となる知識の上にしか載せられないからだ。高度な知識を得たいならキューを順番に消化していくしかない。その形に少しでも近づけるために、ブログ記事としてその都度キューを作ることにした。</p> <p>なぜブログに書くのかというと、ブログは自分で読み返すことが多く、普通のTODOリストのように埋もれていくことがないからだ。(思えばTODOリストも人間の関心がスタックになっているので昔のものが埋没しがちだ。TODOリスト消化のためにはタスク間の依存関係を無理矢理にでも作る必要があるのかもしれない)</p> <p>とりあえず始めなので脈絡もなく手元にある本でロードマップを作ってみた。このリストの順番を守るように自分に厳しく読書をやっていきたいと思う。</p> <hr> <ul> <li class="task-list-item"><input type="checkbox" disabled> 『日本社会のしくみ』小熊英二</li> <li class="task-list-item"><input type="checkbox" disabled> 『Learn or Die』西川徹、岡野原大輔</li> <li class="task-list-item"><input type="checkbox" disabled> 『動きすぎてはいけない』千葉雅也</li> <li class="task-list-item"><input type="checkbox" disabled> 『時間はどこから来て、なぜ流れるのか?』吉田伸夫</li> <li class="task-list-item"><input type="checkbox" disabled> 『高次元空間を見る方法』小笠英志</li> <li class="task-list-item"><input type="checkbox" disabled> 『イシューからはじめよ』安宅和人</li> </ul> <hr><![CDATA[『怠惰への讃歌』バートランド・ラッセル]]>https://blog.nksm.in.net/2020-06-25-『怠惰への讃歌』バートランド・ラッセル/https://blog.nksm.in.net/2020-06-25-『怠惰への讃歌』バートランド・ラッセル/Thu, 25 Jun 2020 13:56:18 GMT<p>ラッセルは有名な数学者・哲学者だが、経済にも関心が深かったらしく色々と述べている。一般的なラッセルのイメージはアインシュタインと一緒に反核のメッセージを訴えた偉い人で、政治的には中道な感じの学者、みたいなものだと思うのだが、この本では自分の政治信条を正直に社会主義者であると語っている。</p> <p>面白いのは、社会主義の中でも敢えて科学的な社会主義ではなく空想的な社会主義を是としているところだ。ラッセルは数学者であり、むしろ科学的な考え方をするのが自然なのだが、社会主義に置いては空想的社会主義を選んだ。科学的社会主義とはまあ言ってしまえばマルクス主義及なわけだが、マルクスの科学的社会主義が生み出したものはラッセルにとっては暴力的であったらしい。</p> <p>科学的な考え方の持ち主が空想を愛好するというのは一見すると逆説ではあるが、よく考えれば矛盾していないのかもしれない。空想がなければ科学は発展しないのかもしれない。また、空想は幻想とは違う。空想は未来の構想でもある。実際にラッセルやロバート・オーウェンなどの空想的社会主義者は自著において空想を語っている。市民の住居は整然としていなければならない。教育は十分に行き渡らねばならない。物資は必要なものが十分に供給されねばならない。空想ではあるが、異世界の幻想ではない。現実社会の行く先として未来を想像しているのである。</p> <p>この関係はSF小説と先端技術の関係にも似ている。ユートピア小説はSF小説のサブジャンルとされることが多いが、ユートピア小説と空想的社会主義の関係は深い。トマス・モアの『ユートピア』は文字通りユートピア社会主義の名前の由来となっている。空想と現実が相互作用をしながらこの社会を作り上げてきたという歴史がある。科学は人類を前に推し進めるものであると考えるならば、空想は科学を前に推し進めるものだと言えるかもしれない。場合によっては科学自身よりも科学にモチベーションを与えるのが空想なのかもしれない。</p> <p>怠惰の肯定は、ラッセルが空想的社会主義者であったことを理解した上であれば自然に納得できる。怠惰、つまり働かない事によって生まれる暇は科学者にとっても重要なものだ。暇がなければ真に生産的な活動はできない。食料を生産することも無論生産的ではあるが、食料の生産を10倍効率化する装置を開発することはもっと生産的だ。しかしその装置は暇がなければ作れない(し、暇があるからと言って必ずその装置が生まれるというものでもない)。</p> <p>怠惰はモンテーニュ風に無為と言い換えても良いのかも知れないが、無為は本当の意味で何もしないことであり、それはそれで良いことではあるのだが、怠惰とは違うように思う。ラッセルの考える怠惰(Idleness)は、プログラマの三大美徳の一つとされるあの怠惰(Laziness)と少し近い。プログラマの怠惰が定義上常に生産性を念頭に置いている以上、予想もしなかった発明を起こす可能性が高いのはラッセルの思い描いた古代ギリシャ的な怠惰と暇だろうと思う。</p> <p>万人が働かなくて良くなったとき、本当に生産的な社会が生まれるのだと思う。人間が労働しなくていいということは、あらゆるインフラが自動化されるということである。人類の当面の課題はあらゆることの自動化だ。人類にコントリビュートしたければ何かを自動化するための装置やソフトウェアを書くのが一番手っ取り早そうだ。</p><![CDATA[『アルゴリズム思考術』を読んだ]]>https://blog.nksm.in.net/2020-06-23-『アルゴリズム思考術』を読んだ/https://blog.nksm.in.net/2020-06-23-『アルゴリズム思考術』を読んだ/Tue, 23 Jun 2020 14:38:32 GMT<p><a href="https://www.amazon.co.jp/dp/4150505381/">https://www.amazon.co.jp/dp/4150505381/</a></p> <p>読んだのでメモ。</p> <p>以外に平坦な感じの本で、読んで特段驚いたりなどはしなかった。勿論個々のテーマは面白いし驚くべきことが書いてあるのだが、いろんなテーマを扱っているのでそれぞれを深堀りしているわけではない。それゆえかゆいところに手が届かない感じのする本。コンビニとかに雑学100みたいな感じで雑に知識を寄せ集めた本がよく売ってあると思うのだが、あんな感じでむずがゆい読後感が残る。</p> <p>この本の「使い方」は知識のインデックスだろう。読んで興味を持った分野について深堀りするために別の本を読み漁るのが良いと思う。この本自体ではアルゴリズム的な思考術を獲得することはおそらく無理だ。決して悪い本ではないのだが、読んだ後の活用の仕方を考えないと単なる暇つぶしで終わってしまいそうな本だ。また、実際にアルゴリズムが書いてあるわけではなくコードも数式も出てこない。</p> <p>自分のために、本のテーマの中で深堀りしてみたら面白そうなテーマと、それに関連する単語を抜粋してみる。</p> <h2>探索(explore)と活用(exploit)</h2> <ul> <li>多腕バンディット問題</li> <li>勝てばキープ、負ければスイッチ(win-stay, lose-shift)</li> <li>ギッティンズ指数</li> <li>信頼上限</li> </ul> <h2>ベイズの法則</h2> <ul> <li>ラプラスの法則</li> <li>コペルニクス原理</li> <li>アーラン分布</li> </ul> <p>これらのテーマを自分が実際に今後調べたりするのかはわからない。あくまでメモに過ぎない。</p> <p>自分が普段プログラミングを仕事にしているからか、ソートやキャッシュやスケジュールやネットワークなどのテーマはあまり面白みを感じなかった。プログラミングをしていない人のほうが面白いと思うのかもしれない。</p><![CDATA[『小さなチーム、大きな仕事』を読んだ]]>https://blog.nksm.in.net/2020-05-30-『小さなチーム、大きな仕事』を読んだ/https://blog.nksm.in.net/2020-05-30-『小さなチーム、大きな仕事』を読んだ/Sat, 30 May 2020 13:39:10 GMT<p>短い本で、挿絵が半分くらいなのでサクッと読めた。せっかく読んだので感想をメモしておく。</p> <p>一番印象に残ったのは、スタートアップじゃなくて企業を始めようと書いてあったところ。普通WEBとかITとかを仕事でやってる人はスタートアップをやろうぜと言いがちなのだが、この本ではそれを勧めていない。スタートアップとは要するに身の丈以上の借金をして数年後に返すくらいのつもりで事業を始めることだが、普通の企業は身の丈にあった範囲の融資で最初から利益を出そうと頑張る。この本では後者の方法、つまりスタートアップではなくスモールビジネスを勧めているのだ。</p> <p>スモールビジネスは日本の小さいソフトウェア開発の会社の現実にピッタリあっている。スタートアップを始める人は喋りがうまくてハッタリがうまい。日本の開発者はそれが苦手な人が多い。独立したあとも細々と受注する。スーツを着て営業に回ったりはしない。エレベータピッチの練習もしない。この本が受け入れられるのはそういう人の現実を後押しするようなところがあるからだと思う。つまり、「俺はこれでいいんだ!」と思わせてくれる。</p> <p>日本にはそうしたやり方で実際に成功した人もたまには見かける。boardというサービスがあるが、boardを作っている会社も受託をやりながらサービスを作って成功したようだ。Inkdropというソフトウェアも確かそれに近かったと思う。(自分も両方のサービスに毎月課金している。)</p> <p>スモールビジネスをしながら、空いた時間で自分のソフトウェアを開発し、売っていく。多分日本に百人の開発者がいたら98人くらいはそういう夢を抱いたことがあるのではないかと思う。この本の著者たちもそういう始め方を勧めている。でも自分はそれは無理だと思っている。大半の人間は「空いた時間」でソフトウェアを開発したりできない。できる人は限られた人種だ。大半の人間は資金の余裕と「空いた時間」をわざわざを作ってソフトウェアを開発するしかない。</p> <p>資金を作ってソフトウェアを開発する。この方法は、自分のカネか他人のカネかという違いはあるけれどもスタートアップのやり方と同じだ。資金が尽きたら事業は終わりだ。またカネを作るために奔走しなければならない。だからスタートアップのチームが行う「アイデアの検証」や「市場テスト」はスモールビジネスにとっても有効だと思う。</p> <p>あと、この本が想定している「仕事」は受託とか人月商売的なやつではないと思うのだが(なぜなら人はなるべく雇うなと書いてあるので)、みんなから嫌われるいわゆる人売りの商売は、それはそれで社会的な意義があると思う。世の中の会社がみんな自社サービス的なことをやろうとしたら、まず大半の会社が生き残れない。それに人をあまり雇わないので人材が育たない。そういう、人をたくさん抱えて人身売買みたいなことをやっている会社の仕事は、まあ良くない側面もかなり大きいけれども未経験の人材を育ててくれるという意味では社会的な意義が大きい。そのあたりを無視してかなり自分たちに都合よく書かれた本という印象を受けた。</p> <p>スモールビジネスをやっている会社がみんな独自のサービスをやってるわけではない。ソフトウェア開発の会社が自社のサービス運用を仕事にせず他社のソフトウェア開発を仕事にして悪いわけがない。どこの土地でも看板屋は依頼された看板を作るものだ。頼まれもしない看板を作る看板屋も世の中にはいるかも知れないが、せいぜい「営業中」「準備中」などの汎用性の高い看板しか作れないだろう。スモールビジネスとはそういうものではないだろうか。自社サービスの開発とは、農業に例えれば6次産業みたいなもので、うまくいくほうが珍しい。うまく行けば美味しいし楽しいだろう。だがそれはバンドを組んでCDを売るみたいな発想だ。バンドはバーに雇われて演奏したほうが安定収入になる。どっちも人の欲しがるものを売っているという意味では同じだ。受託開発を下に見るような発想は、受託開発が育てた人材の上澄みをかすめ取るような考え方であってあまり褒められたものではないと思う。</p><![CDATA[typescript-eslintでno-unused-varsをoffにする]]>https://blog.nksm.in.net/2020-05-04-typescript-eslintでno-unused-varsをoffにする/https://blog.nksm.in.net/2020-05-04-typescript-eslintでno-unused-varsをoffにする/Mon, 04 May 2020 07:48:45 GMT<p><code>.eslintrc.js</code>に下記の設定を追加する。</p> <pre><code class="language-javascript">module.exports = { // 省略 "rules": { "@typescript-eslint/no-unused-vars": ["off"] } }; </code></pre> <p>ESLintの公式ドキュメントとかだと、<code>"ルール名": "off"</code>って書き方がしてあったけど、TypeScriptの場合はルール名は <code>@typescript-eslint/no-unused-vars</code> だし、値は配列にしてやらないといけないっぽい。</p> <p>react-scriptsで<code>yarn start</code> で開発サーバーが立ち上がるのは良いんだけど、Vue CLIと違ってESLintが自動で動かないの地味に嫌だなあと思っていた。JSXだとコンポーネント呼び出すだけじゃunusedのwarningが大量に出てくるからoffにした😭<br> renderメソッドのデータ型とかいちいち書くのもアレかも知んないけどlinterあるとなんか安心する。</p> <p>普通のlinterが使えないのはJSXのバッドなところだなと感じた。</p><![CDATA[関数コンポーネントでhighlightjsを使う]]>https://blog.nksm.in.net/2020-05-04-関数コンポーネントでhighlightjsを使う/https://blog.nksm.in.net/2020-05-04-関数コンポーネントでhighlightjsを使う/Mon, 04 May 2020 04:11:00 GMT<p>このブログは <a href="https://github.com/netlify-templates/gatsby-starter-netlify-cms">gatsby-starter-netlify-cms</a> を使っているのだが、このテンプレートはReact製で、関数コンポーネントで作ってある。</p> <p>コードブロックをハイライトしたくてhighlight.jsを導入したかったけど、クラスコンポーネントで導入している例はみつけたが関数コンポーネントで導入する方法を調べるのに少し時間がかかった。</p> <p>クラスコンポーネントの場合はライフサイクルメソッドをフックにして、そこでコードブロックをハイライトすれば良い。</p> <pre><code class="language-javascript">export default class Hoge extends React.Component { componentDidMount() { this.highlight(); } componentDidUpdate() { this.highlight(); } highlight = () => { document.querySelectorAll("pre code").forEach(block => { hljs.highlightBlock(block); }); }; render() { // 省略 } } </code></pre> <p>しかし、<code>componentDidMount()</code> や <code>componentDidUpdate()</code> はクラスコンポーネントでしか使えないようだ。コンポーネントのライフサイクルイベントにアクセスできないと、DOMをレンダリングしてからコードブロックの内容をハイライトする、という処理を実行することができない。</p> <p>幸い、昨年のv16.8からReact Hooksという仕組みが実装され、関数コンポーネントでもライフサイクルイベントにアクセスできるようになったらしい。以下のように実装した。</p> <pre><code class="language-javascript">import React, { useEffect } from 'react'; // 省略 export const Hoge = () => { useEffect(() => { document.querySelector("pre code").forEach(block => { hljs.highlightBlock(block); }) }); return ( // 省略 ) } </code></pre> <p>useEffectという関数でコンポーネントが初期化されたときや更新されたときに処理を入れることができるようになるらしい。</p> <p>コードブロックに行番号を表示するようにしたのにも一工夫必要だったがそれはまた次回書こうと思う。<br> (色々調べたらhighlight.jsを使うよりは今どきはPrismというライブラリを使ったほうが良さそうということがわかった、、、)</p> <hr> <p>参考:</p> <ul> <li><a href="https://stackoverflow.com/questions/49368326/cant-get-highlight-js-to-highlight-react-rendered-code">https://stackoverflow.com/questions/49368326/cant-get-highlight-js-to-highlight-react-rendered-code</a></li> <li><a href="https://github.com/highlightjs/highlight.js/issues/925#issuecomment-466638119">https://github.com/highlightjs/highlight.js/issues/925#issuecomment-466638119</a></li> <li><a href="https://www.themikelewis.com/post/highlightjs-with-react">https://www.themikelewis.com/post/highlightjs-with-react</a></li> <li><a href="https://itnext.io/add-state-and-lifecycle-methods-to-function-components-with-react-hooks-8e2bdc44d43d">https://itnext.io/add-state-and-lifecycle-methods-to-function-components-with-react-hooks-8e2bdc44d43d</a></li> <li><a href="https://ja.reactjs.org/docs/hooks-effect.html">https://ja.reactjs.org/docs/hooks-effect.html</a></li> </ul><![CDATA[tsconfig.jsonにexcludeオプションを設定したのに効かないとき]]>https://blog.nksm.in.net/2020-05-03-tsconfig-jsonにexcludeオプションを設定したのに効かないとき/https://blog.nksm.in.net/2020-05-03-tsconfig-jsonにexcludeオプションを設定したのに効かないとき/Sun, 03 May 2020 02:15:06 GMT<p>tsconfig.jsonに下記の項目を設定した。</p> <pre><code class="language-json">{ (省略) "exclude": [ "node_modules" ] } </code></pre> <p>でtscしてみると下記のエラーが出ることがある。</p> <pre><code>../node_modules/@types/d3-array/index.d.ts:236:93 - error TS2583: Cannot find name 'Map'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. </code></pre> <p>excludeでnode<em>modulesを設定してるのにnode</em>modules配下のTSファイルをコンパイルしようとしているっぽい。ぐぐったら下記のページを見つけた。</p> <p><a href="https://stackoverflow.com/questions/34312252/exclude-property-of-tsconfig-json-is-not-being-respected">node.js - "exclude" property of tsconfig.json is not being respected - Stack Overflow</a></p> <p><code>compilerOptions</code>の<code>skipLibCheck</code>を<code>true</code>にすれば良いようだ。</p> <p>エラーメッセージみて従おうとするとターゲットのECMAスクリプトバージョンをあげたくなってしまうが、多分それだと意図した動きにならない。node_modules配下をコンパイルの対象から完全に外すには、excludeを設定した上で依存ライブラリもコンパイル対象から外せばよいらしい。</p> <p><a href="https://www.typescriptlang.org/tsconfig#skipLibCheck">tsconfig.jsonの公式ドキュメント</a>をみると、このオプション使いたいと思うのはnode_modulesに同じライブラリが2回以上入ってるときだからyarnを使うのを検討せよと書いてある。多分そういうことではないがと思いながらyarn使ってみたらやっぱりだめだった。</p> <p>TypeScriptをグローバルインストールではなくてローカルインストールしてるとかも関係してそうではある。ただ</p> <ul> <li>package.jsonにtypescriptのバージョンまで入れたい</li> <li>フロントエンドの開発にDocker使いたくない(イメージ・コンテナの管理とか手間だし)</li> </ul> <p>以上の理由によりTypeScriptもプロジェクトローカルにインストールしたいんだよな。。。</p> <p>まあこの方法でやってみて色々不都合でてきたらdockerとかグローバルインストールとか検討する。CI回すときもTypeScript入りのイメージでビルドしたほうが時間短縮できそうではある。</p><![CDATA[かけておくと仕事が捗る不思議なアニメについて]]>https://blog.nksm.in.net/2020-04-21-かけておくと仕事が捗る不思議なアニメについて/https://blog.nksm.in.net/2020-04-21-かけておくと仕事が捗る不思議なアニメについて/Tue, 21 Apr 2020 14:38:00 GMT<p><img src="/img/gochiusa.webp"></p> <p><a href="https://gochiusa.com/">https://gochiusa.com/</a></p> <p>以前から家で仕事するときはアニメを流しながら作業していた。完全に静かな環境も良いんだけど、なんとなく雑音が欲しいときもある。完全な静寂ってむしろ余計なことを意識させるような気がするのだが、適度な不快じゃない雑音があるとほっておくと考え事を始めてしまうような脳の領域を雑音のフィルター処理に向けることができてやらないといけない作業を邪魔されることがなくなるのでは、とか考えている。</p> <p>しかし、アニメの内容によって作業用BGVに向いているものと向いていないものがある。まず、ストーリーが凝っているやつはだめだ。集中して観はじめてしまうという問題もあるし、そういうアニメはシリアスな山場で叫び声が上がったりして集中を妨げられてしまう。</p> <p>ギャグ系もあまりよくない。ストーリーが凝ってるシリアスなアニメよりもだいぶマシだが、こっちはギャグが面白いと笑ってしまい作業が妨げられる。そしてアニメに見入ってしまう。本末転倒となってしまう。</p> <p>自分が試してみたアニメでは、以下の作品が作業用BGVとしてなかなか良かった。</p> <ul> <li>美味しんぼ</li> <li>NEW GAME!</li> <li>ゾンビランドサガ</li> </ul> <p>これらはそれぞれタイプが違っている。</p> <p>『美味しんぼ』は一話完結ものだから話が気にならない。所詮グルメの話だから世界の存亡とかもテーマにない。試してはいないが、多分『こち亀』とかも同じ意味でBGVとして優秀だ。</p> <p>『NEW GAME!』は萌え百合4コマ系の作品で、話の内容も他愛ない日常の話ばっかりだからBGVとして良い。類似のアニメに『ゆるキャン△』がある。</p> <p>『ゾンビランドサガ』は、6-8話と最終話こそシリアスだがそれ以外の話は割とゆるい話で、案外作業の妨げにはならない。むしろ休憩のタイミングでシリアス話になるので丁度作業のリズムが作れる。『涼宮ハルヒの憂鬱』も似た傾向の作品だと思う。</p> <p>しかし、いろんなアニメの中で作業用アニメとして頂点に立つのはダントツで『ご注文はうさぎですか?』である。</p> <iframe width="560" height="315" src="https://www.youtube.com/embed/m7-4Q36XkOU" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> <p>系統としては『NEW GAME!』や『ゆるキャン△』とおなじになるのだろうと思うが、これらに比べても断然作業が捗る。全く余計なことを考えなくて良い。『ごちうさ』を流してると、作業しながら浮かんでくる「あーゲームやりてー」とか「アニメ観たいなー」「マンガ読みたい」「ネットやりたい」みたいな欲望がいい感じに処理されているのがわかる。ごちうさというアニメは煩悩をいい感じに満たしながら作業を全く邪魔することがないのである。本当にごちうさには感謝している。素晴らしいアニメだと思う。このような名作がdアニメストアに月々わずか400円税別を支払いだけで視聴し放題とは、本当にユートピアみたいな世の中になったものだと思う。</p> <p>そしてその神アニメごちうさは、3期が決定しているようだ。ごちうさ3期はリモートワークのみんなを強力に後押ししてくれるはずだ。ごちうさを制するものはリモートワークを制す。毎日ごちうさをBGVとしてリピート再生することで圧倒的な生産性を実現するぞ!</p><![CDATA[いまプログラミング初心者に「どの言語やればいいですか?」と聞かれたらTypeScriptを激しくオススメしたい]]>https://blog.nksm.in.net/2020-04-20-いまプログラミング初心者に「どの言語やればいいですか?」と聞かれたらtypescriptを激しくオススメしたい/https://blog.nksm.in.net/2020-04-20-いまプログラミング初心者に「どの言語やればいいですか?」と聞かれたらtypescriptを激しくオススメしたい/Mon, 20 Apr 2020 14:28:07 GMT<p><img src="/img/mamechi1110016_tp_v.jpg"></p> <p>(※画像は<strong><a href="https://www.pakutaso.com/20191102315post-24144.html">ぱくたそ https://www.pakutaso.com/20191102315post-24144.html</a></strong> 様のフリー素材です)</p> <p>プログラミング初心者にどの言語から勉強してもらったら一番良いか、というテーマでぼんやり考えることがある。まだまだ自分自身が初心者に毛の生えた様な人間だが、おっさんになってからプログラミングを始めた身としては色んな人にプログラミングをやってみてもらいたいと思うのでこの問題についてはよく考える。</p> <p>自分自身は一番最初はJavaから教えてもらった。Javaという選択肢は悪くなくて、型があるし、C言語系の文法を持ってる言語としては割と癖が少ないほうだし、WEBの開発をやる場合にはするっとPHPに移行できる。オブジェクト指向なのもよく、仕事で使う言語なんてどうせどれもオブジェクト指向だからやって損することは無い。また、Javaの環境構築に慣れてればAndroidの開発にも抵抗なく入れるだろうし、KotlinとかScalaとかGradleとかそのへんの割とイケてるおちんぎん高めの界隈にも入り込める。他にもC#はJavaを意識して作られてるのですごいJavaっぽいところがあり、C#でゲーム作りたいとか思ってる人にもまあまあいいと思う。マインクラフトはJavaで作られたという話だからJava自体ゲーム作れるらしい。</p> <p>実際、自分はJavaのチュートリアルを終えたらそのままPHPを仕事で使うようになった。オブジェクト指向に慣れてたから自社フレームワークを頑張って読み解く事もできた。ネイティブアプリをObjective-CとかAndroid Javaで書くときも、最初にJavaやってなかったら死亡してたと思う。ASP.NETのWEBアプリをC#で書いたときもJavaの経験が生きた。MVCのフレームワークでテンプレートエンジンとか使うときもJSPで慣れてたからなんとかやれた。Javaそのものを仕事で使うことはあまりなかったが、Javaのおかげでプログラミングに良い入門の仕方ができたと思う。</p> <p>しかし、今自分が、これからプログラミング始めようという初心者に対して「Javaがオススメだよ!」と言うかと問われたら、多分言わない。むしろ「Javaはやめとけ」と言うだろう。なんでかと言うとプログラミングそのものの楽しさを味わえるようになるまでの手間が大きいからだ。Javaは初心者がやるにはおまじないが多すぎるし環境作りも大変だ。サクッとプログラミングを始めたいなら動的型付け言語が向いてる。今ならPythonが良さそうだと思う。流行ってるから情報がたくさんあるし、各社WEBサービスのWEB API使ったりだとか好きなサイトのスクレイピングとかができるようになるとぐっとプログラミングが楽しくなる。</p> <p>じゃあPythonをオススメするのかと問われたら、やっぱり最初の言語としてはおすすめしない。Javaの勉強をしながらPHPを少しだけ仕事でやったことがあるのだが、そういう半端な状態だとデータには「型」があるのだということがわからない。結果、バグの多いコードを書いてしまった。初心者こそ、データには型があるということをしっかり理解すべきだし、そこを理解できたらあとはどんな言語でも自分で学べるようになると思う。そういう意味ではPythonもPHPも同じなので、最初にしっかり勉強する言語としては動的型付け言語はあまり良いとは思えない。</p> <p>だからやっぱり静的型付け言語が良いんだけど、前述の通りJavaは悪くないけどオススメできない。かと言ってスクリプト言語並に導入が簡単でプログラミングそのものを楽しめる言語は何か、、、とか考えると実はそんなに無いような気がする、という結論になっていた。だから、プログラミング初心者の人にどの言語やればいいですか? と聞かれたら、まあとりあえず食いっぱぐれないPHPとかJavaScriptをやると良いんじゃないかな? みたいなことを言ってお茶を濁していた。</p> <p>しかし時代は変わった。というのに今更気づいた。TypeScriptだ。まあJavaScriptみたいに書いても動いてしまうのだけど、両方のやり方で書き分けられるというのもミソというかポイントだと思う。型を書くことの恩恵を身を持って体感できるからだ。そしてTypeScriptはAltJSなのでJavaScriptでできることはたいてい全てできるわけだから、WEBアプリ書けるしスマホアプリ作れる(ReactNativeとかで)しブラウザで動くゲームを作ることもできる。デスクトップアプリもElectronで作れる。NodeかDenoでサーバーサイドもできる。つまり初心者が思いつく「プログラミングであれやりたい!」が大抵できてしまう。これはすごいことだ。できることベースで言えばJavaScriptも同じなのだが、JavaScriptは癖が強いし動的型付け言語なので、自分の基準からするとしっかりとプログラミングを覚える言語として最適ではない。ところがTypeScriptはいい感じの言語だ。できることがたくさんあって、しかも静的型付け(もできる)言語となれば初心者にはうってつけで、オブジェクト指向だから仕事で使う系のプログラミングに慣れる事もできる。型の概念が身につくから、動的型付けのスクリプト言語をやるときもしっかりしたコードが書けるようになる(はず)。JavaScriptのスーパーセットだからもちろん関数型言語みたいな書き方もできる。TypeScriptは本当に色々な道へと初心者を誘ってくれる。TypeScriptさえやっておけば大体どの道に進むこともできそうな感じなのだ。最近は STS(Static TypeScript)というものも発明されたらしい(<a href="https://www.infoq.com/jp/news/2019/11/static-typescript-msft-paper/">https://www.infoq.com/jp/news/2019/11/static-typescript-msft-paper/</a>)。将来的にはIoTにも使えるようになりそうだし、マシン語を直接吐き出す言語としても活躍しそうな予感がする。</p> <p>というわけで、現時点で自分が初心者にオススメする言語は完全にTypeScript一択。TypeScriptやっとけば間違いない。仕事もある。たのしいプログラミングもできる。なんでもできる。初心者は騙されたと思ってTypeScriptやるべき。というか自分がTypeScriptもっとやりたい。TypeScriptで仕事とれるようにがんばります。</p><![CDATA[TypeScriptたのしい]]>https://blog.nksm.in.net/2020-04-19-typescriptたのしい/https://blog.nksm.in.net/2020-04-19-typescriptたのしい/Sun, 19 Apr 2020 13:30:52 GMT<p><img src="/img/remoteworks458a3421_tp_v.jpg"></p> <p>本当に遅ればせながらだが、やっとTypeScriptを使うようになってきた。というか今日から使い始めた。</p> <p>最初はVSCode上で色々怒られてめんどくさいなあ、、、とか思っていたけど、guard節を強制させてくる感じとか、asキーワードでキャストする感じとか、モダンな言語という感じがして書いていて気持ちが良い。昔SwiftとかKotlinを触ってた時の感覚を思い出す。</p> <p>その頃と全く違うのは、エディタの快適さ。VSCodeはTypeScriptを書くときに最も力を発揮するのだとようやく知った。補完は速いし頭いい。Swift、Kotlinで重たいIDEを使ってるときとは段違いに気持ちいい。</p> <p>ちょっとだけハマったところがあるのでメモ。</p> <h3>Vue + TypeScriptでforEachが使えない</h3> <p>Vue + TypeScriptで開発してるとforEachが使えないことがある。この場合は、core-jsというライブラリをアップデートするなりバージョン下げるなりすると使えるようになるっぽい。自分の場合は下記のコマンド打ったら使えるようになった。</p> <pre><code>$ npm install --save core-js@3 </code></pre> <p>コンパイル時のエラメッセージで、</p> <pre><code>$ npm install --save core-js/modules/es.array.for-each core-js/modules/web.dom-collections.for-each </code></pre> <p>をやれ、みたいなのも出てくるんだけど、そもそもこのコマンド自体がうまくいかなかった。単純にcore-jsを入れ直せば解決した。</p> <p>(ちなみに最近core-jsは作者が交通事故で収監されることになりメンテされなくなるのでは? ということでちょっと話題になってた。<a href="https://qiita.com/yumetodo/items/eaf3b97aeae3d8c4a07e">https://qiita.com/yumetodo/items/eaf3b97aeae3d8c4a07e</a>)</p> <h3>object is possibly null とかいうメッセージがでてコンパイルできない</h3> <p>guard節を書けばいい。多分、以下のような書き方してると↑のメッセージが出る。</p> <pre><code>methods: { hoge: function (event: Event): void { event.target.querySelector(".my-class").classList.add("fuga"); } } </code></pre> <p>下記のようにguard節をつければOK。</p> <pre><code>methods: { hoge: function (event: Event): void { if (event.target === null) return; event.target.querySelector(".my-class").classList.add("fuga"); } } </code></pre> <h3>Vueで書いてるのにESlintがJSX関連の警告出してくる</h3> <p>例えば、下記のようなキャストの仕方をすると怒られる。</p> <pre><code>const text = (&#x3C;HTMLElement>e).innerText; </code></pre> <p><HTMLElement>の閉じタグがねーぞ、みたいなことを言われてしまう。</p> <p>これは流石にVueで書いてるんだからESLintの設定とかで無効化できそうだけど、そもそもこのキャストの書き方は読みづらいからasを使ったほうが良さげ。</p> <pre><code>const text = (e as HTMLElement).innerText; </code></pre> <hr> <p>万事こんな感じなので、タイプする量はJSに比べて増える。けれども書き心地は圧倒的にこっちのほうがいい。絶対バグも少ないし。</p> <p>フロント側のJSはただでさえテストを書くことが少ないので、バグが出にくい書き方を強制されるくらいで丁度いいかな、と思う。Web APIの関数(querySelector()とか)の返り値も都度MDNで調べる癖ができるので勉強にもなる。</p> <p>あと、型をつけておくとVSCodeの補完が効くようになる。補完が効くの地味に気持ちいい。型無しで、とりあえずanyで書いてても動くんだけど、それだとTypeScriptで書いてる意味がなくなるし恩恵も得られないし、後で型つけるとか絶対やらないし。普段から型ありで書くのが大切なような気がする。</p> <p>良い言語は良いプログラマーを育てる、ってやつの良い例だ。TypeScript流行ってる理由ようやくわかった。たのしい。</p> <p>何周周回遅れかはわからないが、これからTypeScriptも頑張っていきたい。</p> <p>(※画像は <strong><a href="https://www.pakutaso.com/">ぱくたそ https://www.pakutaso.com/</a></strong> 様のフリー素材です)</p><![CDATA[人生のピボット]]>https://blog.nksm.in.net/2020-04-18-人生のピボット/https://blog.nksm.in.net/2020-04-18-人生のピボット/Sat, 18 Apr 2020 00:00:00 GMT<p><img src="/img/pp_nekohamu_tp_v4.jpg" alt="neko"></p> <p>人生をピボットしたい。</p> <p>スタートアップの世界ではピボットという単語がよく聞かれる。最初にやろうと思っていたビジネスのアイデアが、マーケットのニーズとフィットしないとわかったときに方向転換を行うことだ。</p> <p>ピボットは悪いことではないと考えられている。間違った方向に突き進むよりも途中で方向転換して正しい方向に進んだほうが良いからだ。これは誰が見てもそうだろう。</p> <p>自分は、自分の人生が間違った方向に進んでいると思っているわけではないものの、ベストな方向に進んでいるという気持ちもまったくない。ベストじゃないのならばピボットすべきなのだ。人生はベストを尽くすためのもの、命は燃やし尽くすためのものなのだ。</p> <p>ピボットに次ぐピボットを重ねて人生を株式公開させたい。自分は今までカネというものに全く縁のない人生を歩んできたが、金持ちになりたいという願望はある。金持ちになって何をするのか。世界旅行したいとか宇宙に行きたいとか豪遊したいとか放蕩の暮らしをしたいとかいう気持ちは殆どない(少しはある)。それよりも、カネを配れる人間になりたい。</p> <p>自分がいいと思うものにカネを配りたい。事業投資みたいなことがしたい。人間は愚かなので、短期的に快楽を得られるような商品にカネを払いがちである。長期的な利益にカネを払う行動を取れる人は賢いが、人類の大多数は直近の不利益を避けたり、短期的に快楽を得られるようなものにカネを払う。これは行動経済学とか行動主義心理学の実験でも実証されているらしい(前に少し本で読んだ)。長期的に人類全体に利益をもたらすような事業には資金が集まらない。結果、事業は継続しない。人類はますます近視眼的になってゆく。</p> <p>人類は永遠の相で世界を眺める必要がある。長期的な視点を持つべきだということだ。だから長期的な視点を持っているが短期的に生き延びることができない数多の事業に投資をしたい。投資と言っても自分が生きている間にリターンが受け取れるとは思えないので実際は寄付だ。寄付みたいなことがしたい。莫大なカネは世界を変える。世界を変えるくらいのカネがほしい。</p> <p>そのためにはピボットだ。人生をピボットさせる。日本ではピボットは批判されがちだ。一本筋の通った人間がかっこいいと思われているからだ。努力と根性で初志貫徹。前言撤回はダサい。そのような空気がある。しかし前言撤回は成長の証だ。</p> <p>それどころか、日和見的にコロコロ意見を変えることも大切かも知れない。他人から見れば人間のクズそのものという振る舞いになるかも知れないが、大多数の人間が近視眼的な事業に投資をする世の中だから、それに合わせて身過ぎ世過ぎをすることを誰が責められようか。自分自身は超近視眼的な事業をいくつもやってカネをあつめ、長期的な事業にカネを投入する。そんな生活が理想だ。</p> <p>近視眼的な事業とはなんだろうか。今現在であればウイルス対策の事業がそれにあたるかもしれない。</p> <p><a href="https://jp.techcrunch.com/2020/04/13/2020-04-12-tech-for-good-during-covid-19-pivots-and-partnerships-to-help-people-deal/">https://jp.techcrunch.com/2020/04/13/2020-04-12-tech-for-good-during-covid-19-pivots-and-partnerships-to-help-people-deal</a>/</p> <p>こうして考えてみると他人の不幸で金儲けをするのが近視眼的なビジネスなのだろうと思う。もちろん不幸をカネで実際に救済することができれば立派なものだが、大半はそんなこともないだろう。転売屋のビジネスがこの世に何も生み出していないけれども儲かっているのと同様に、この世に存在しなくても問題ない、何も実質の富を生み出していない、そうでありながらものすごく儲かっている、まさしく文字通りの __虚業__ がこの世には沢山あるはずだ。</p> <p>そうした虚業の世界へと、ピボットするべきタイミングというものが、もしかしたら自分の人生にもあるのかも知れない。</p> <p><em>(※写真はフリー素材です)</em></p><![CDATA[個人プロジェクトの難しさ]]>https://blog.nksm.in.net/2020-04-17-サイドプロジェクトの難しさ/https://blog.nksm.in.net/2020-04-17-サイドプロジェクトの難しさ/Fri, 17 Apr 2020 12:16:00 GMT<p>個人プロジェクトは難しい。多くの人には本業があると思う。大抵の人は週5日、毎日8時間くらい労働していると思う。8時間労働していると疲れる。夕方に仕事が終わると、早々に布団を敷いて寝転がりたくなってしまう。</p> <p>体力の問題。意志力の問題。両方あると思う。本業でフルに能力を発揮して、さらに余力でガンガン個人プロジェクトを進めている人は世の中に実際にいる。たくさんいる。そういう人たちは目立つので、むしろ世の中の大半はそういう人たちなのではないかという気すらしてくる。</p> <p>自分はそういう人にはなれない。体力もなければ意志も薄弱だ。少し頑張ったらすぐ怠けたくなってしまう。仕事もフルパワーでやってるのに個人プロジェクトでもバリバリやってる人を下から見上げていると、自分のような人間は生きていてはいけないのではなかろうかという気がしてくる。</p> <p>どうやったら体力も意志力も無い人間が個人プロジェクトをやれるようになるのだろうか。答えは1つしか無い。本業をおろそかにすることだ。意図的に、本業を疎かにする。</p> <p>昔はそういう人はたくさんいたと思う。会社ではとりあえずデスクに座って時間を潰して給料泥棒として過ごし、家に帰ったら本気を出して趣味に取り組むというタイプの人である。しかし今の時代そんな仕事ぶりではクビになりかねない。</p> <p>昭和の時代の「サボり」は、本業の時間を薄く平べったく過ごすやり方である。令和の時代のサボりは、本業の時間を太く短くすることにより実現するのではないか。つまり、一日8時間だとか週五日勤務だとかをやめてしまうのである。それで餓死さえしなければそれで良いような気がする。</p> <p>理想は、週3日、6時間労働だ。週40時間が標準なので、単純に考えて収入は半分以下になる。しかし個人プロジェクトに当てる時間は大きくなる。月に60万稼いでいる人の収入は30万を切ることになる。</p> <p>最初は苦しいかも知れない。しかし、個人プロジェクトがヒットすれば60万など目じゃないくらいに稼げるだろう。ヒットすれば、だが……</p> <p>違う考え方もある。週6日、一日10時間働く、といったやり方でガンガンはたらいてお金をためて、フルで個人プロジェクトに向き合う時間を作るというものだ。今自分がとっているのはこっちの方向性だ。</p> <p>このやり方だとお金さえ溜まればまとまった時間が取れるので個人プロジェクトを本当に成功させたければ良いような気がするが、問題が色々ある。まず半端なくストレスが溜まる。そのせいで余計なものにカネを使ってしまうのだ。結局個人プロジェクトにフルコミットするための資金がなくなってしまう。</p> <p>また、技術的に成長しないことが多い。受託開発の宿命であるが、新しいことや業界のトレンド、ベストプラクティスといったものからはかけ離れた技術を使って開発する案件が9割以上だ。色々な人が関わって仕事をする以上それは仕方の無いことなのだが、個人開発ならばベストなやり方を求めてとことん試行錯誤できる。試行錯誤しているときが、人間は一番成長する。ルーチンワークは人間から成長の機会を奪う。</p> <p>成長しなかったら何が悪いのかと言うと、受託開発においても単価を上げることができないのである。PHP一筋十年の人と、個人プロジェクトでAIやGoやReactやKubernetesを色々触ってきた人のどちらが単価高くなるかは考えるまでもない。仕事でぐったり疲れていると、個人プロジェクトどころか勉強ですらやる気が起きないのだからなおさら単価は上がらなくなる。</p> <p>とはいえ週3日一日6時間で済むような仕事というのは世の中には少ない。みんな週五日一日8時間働く人材を求めている。人間には非同期は早すぎるのである。プログラミングにおいてすら非同期処理は難しいのだから、プログラマーでもない人達に非同期の働き方を求めるのは無理だ。</p> <hr> <p>人間は同期的にしか働けない。非同期で使うことを前提に作られたプラットフォームにおいてさえ、同期的に使う方法を編み出してしまう。プログラマーですらdeferだとかasync/awaitだとか考えるのだから、プログラマーじゃない人が「朝9時に朝会チャットルームに始業メッセージ投稿してください! 席外すときも投稿してください! 昼休みから戻ったら投稿してください!」などと言い出してもそれは仕方のないことなのだ。</p> <p>人間が非同期で働けるようになるまでは、自分のような体力も意志力もない人間が個人プロジェクトをやることはありえないのかも知れない。体力と意志力に恵まれたハイスペックな人だけが個人プロジェクトをやり、成長し、高年収を得る世の中がまだしばらくは続くのだろう。悲しいことだがこれが現実だ。</p><![CDATA[リモートワークとチャットと電話]]>https://blog.nksm.in.net/2020-04-15-リモートワークとチャットと電話/https://blog.nksm.in.net/2020-04-15-リモートワークとチャットと電話/Wed, 15 Apr 2020 15:04:02 GMT<p>下記の記事を読んだ。</p> <p><a href="http://simplearchitect.hatenablog.com/entry/2020/04/15/100449">マイクロソフトのリモートワークが得意な人を観察して気づいた、たった一つのポイント</a></p> <p>プログラマーは電話が嫌いという風潮がある。理由は、集中を妨げられるから。人の時間と集中力を奪って電話をするのではなくチャットで連絡してほしいという意見を昔からネットでよく見かける。</p> <p>電話は同期的でチャットは非同期的だ。それは確かにそうなのだが、ちょっと現場の雰囲気が変わってきたと最近は思う。</p> <p>人間は愚かだから、本来非同期的だったテキストベースのコミュニケーションにも同期を求めてしまう。チャットですぐにリアクションが返ってこないとすぐ不安になったりイライラする。返事を催促してしまう。至急対応お願いします! みたいなチャットをしてしまう。</p> <p>リモートワークが多くなってきた最近はなおさらそういう空気が出てきたと思う。同期的なコミュニケーションに慣れすぎた人々にとって、チャットは早すぎた。「このコードうごかないですけど!!!!!!」みたいな怒りのチャットとともにエラー画面が貼り付けられて送りつけられる。メンションが二個も三個もついている。受け取ったプログラマの精神は病む。</p> <p>人間には所詮非同期処理が無理なのであれば、いっそ電話をつないでしまったほうが良いのかも知れない。チャットで、アレやってみてもらえますか? コレを再起動してもらえますか? このコマンド打ってみてもらっていいですか? 結果どうなりましたか? などとやってるとつまらない問題で平気で一時間二時間使ってしまう。本当に無駄だ。人間には非同期セッションは早すぎたのだ。電話で画面共有しながらペアプロすれば十分で終わる。</p> <p>特に今外出を自粛しないといけないので非同期的なセッションだけではリモートに慣れていない人間の精神が病んでしまう。一日最低一回は他人と同期をとると精神の健康に良いのかも知れないし、プロジェクトもうまく回るのかもしれない。</p><![CDATA[技術とサービス]]>https://blog.nksm.in.net/2020-04-14-技術とサービス/https://blog.nksm.in.net/2020-04-14-技術とサービス/Tue, 14 Apr 2020 12:31:08 GMT<p>デザインとサービスは密接に結びついている。デザインがサービスの売上をかなり左右する。どういう人物がサービスの顧客なのかを考えることによってデザインは生まれる。故にデザインはサービスの本質を表している。デザインはサービスの根幹に食い込んでいる。</p> <p>しかし技術はどうだろう。一部の技術オタクに対しては技術はサービスのコア要素にはなるかも知れない。しかし大多数の顧客がそのサービスに使われている技術に興味があるとは思えない。</p> <p>技術がサービスの根幹に結びつくのはどういうときだろう。技術は第一にコストである。技術はそのサービスを可能にしてくれるものだが、サービスを企画する人にとっては実現のための技術はコストである。技術にお金と時間をかけないとやりたいことができない。技術無しでやりたいことができる世界は幻想や妄想の世界だ。人類が妄想を具現化できる世界に住んでいたら技術はこの世に存在していないだろう。残念ながら我々の世界では妄想はそのままでは具現化しない。妄想を具現化するためには技術への投資が必要となる。技術は第一義的に足かせである。</p> <p>だから、技術者の優秀さはそのコストをいかにゼロに近づけられるかにかかっている。優秀なハッカーがウィザードと呼ばれることがあるのはそういう側面があるからではないだろうか。</p> <p>また、そこから間接的に技術はスケーラビリティを実現するものとなる。通常の技術者が生み出す技術的コストの係数を1とすると、たとえば優秀な技術者はそれを0.1にまで下げることができる。サービスの企画者が100のコストを投入したとき、通常の技術者が実現できるのは100のことに過ぎないが、優秀な技術者は1000のことを実現してしまうだろう。その1000のことは、サービスがさばけるクライアント数を増やす方向に生かされるかもしれないし、サービスの機能の豊富さとして具現化するかも知れない。</p> <p>優秀な技術者はサービスのコストを減らし、サービスにスケーラビリティをもたらし、サービスに沢山の機能を実装する。</p> <p>なんだか当たり前のことだが、技術者を「手を動かす労働者」としてしか見ていない企業には上記の視点が欠けている。そしてこの世の99.95%の(IT)企業が、技術者のことを「手を動かす労働者」としてしか見ていない。</p> <p>しかしサービスを遅くするのも速くするのも技術者次第だ。アイデアとデザインと技術は全て掛け算だ。アイデアだけを実現させようとする人間が多すぎる。アイデアとデザインだけでは絵に描いた餅だ。人類を足かせから解き放つには優秀な技術者が必要だ。そしてアイデアは多くの場合技術に規定されている。</p> <p>デザインがサービスに直接的なインパクトを与えるのに比べたらかなり遠回りだが、技術は企画者の思考の枠組みを作ったり変えたりすることができる。技術者の一人として生きるなら、枠組みを作ったり変えたりする側にいるようにしたい。</p><![CDATA[JavaScriptのアニメーション]]>https://blog.nksm.in.net/2020-04-13-javascriptのアニメーション/https://blog.nksm.in.net/2020-04-13-javascriptのアニメーション/Mon, 13 Apr 2020 15:21:11 GMT<p>仕事でアニメーションを色々触る機会があって、地味にWEBのアニメーションはCSSアニメーションかTransitionしかさわったことがことに気づいた。なのでググってみたのだが以下のページを見つけた。</p> <p><a href="https://ja.javascript.info/js-animation">JavaScript アニメーション</a></p> <p>JSでアニメーション書くときはこうするのかーという感じ。setIntervalで小刻みにDOMの表示位置をtransformとかで変えていく感じらしい。面白い。確かに昔ゲーム系のライブラリ触ってたときこんな感じのコード書いたような気がする。Canvas</p> <p>ただまあ、普通にWEBサイトとかでアニメーション使いたいときはCSSで十分すぎるほどまかなえる。easingの調整とか自分で書くと案外めんどくさいけどCSSではパラメータ渡すだけでいい感じに調整してくれる。自由度は無いけどいい感じに勝手にやってくれるからWEBにはCSSのほうが向いてそう。</p> <p>そして間抜けなことにja.javascript.infoのサイトは二年前に自分ではてなブックマークしてたことに気づいた。はてブをやっても少しも勉強にならないことの良い証拠となった。</p> <p>ゲーム作りたいなあ。一昨日FF7Remakeをやり始めて急にゲームやりたい作りたい熱が高まってきた。</p><![CDATA[自分がなぜITエンジニアになれたか]]>https://blog.nksm.in.net/2020-04-09-自分がなぜエンジニアになれたか/https://blog.nksm.in.net/2020-04-09-自分がなぜエンジニアになれたか/Thu, 09 Apr 2020 13:10:00 GMT<p>自分は五年前に31歳未経験という状態からプログラマーとして働き始めた。</p> <p>いまはこういう人そこまで珍しくもないみたいだけど、やっぱり少数派ではあると思う。</p> <p>最近なぜかわからないがWEBエンジニアとかITエンジニアという職業が人気のようで、なりたいという人に沢山出会うようになった。</p> <p>それ自体は良いことである。今は人手が少ないし売り手市場だ(新型コロナウイルスのせいで一時的に不況になりそうな気配だが、多分落ち着いたらまた超売り手市場になると思う。なにしろ2030年の予測まで出てるくらいなので)。</p> <p>しかし、なりたいと言ってる人がモノになるかどうかはまた別の問題だ。20歳そこそこの若手エンジニアの人たちと接していたことが一時期あったが、本当に人によって向き不向きが顕著に出た。頑張ってできるようになりたいという心意気は感じるもののパフォーマンスが発揮できてるかを見てみると大して仕事に意欲がなくてもITエンジニアという職業に向いてるタイプの人のほうが圧倒的に良い成果をだすということがある。</p> <p>自分はすごいエンジニアというわけではないが使えないエンジニアというわけでもなく、なんとかそれを仕事として独立して食えている程度の、まあモブキャラくらいのレベルのエンジニアだと思う。だから、向いていないというよりもむしろ向いていたのだと思う。</p> <p>性格的に向いていたというだけではない。環境がもたらした要因もあって、ITエンジニアを続けていられるのだろうと思う。自分がエンジニアになれて、しかもそれで仕事をやっていけている理由をいくつか書き出してみたいと思う。というのもあまりに「向いていない」「成果が出ない」エンジニア志望の人に出会うからである。</p> <h2>自分自身の性質に起因するところが大きい点</h2> <h3>論理的に考えるのが苦ではない</h3> <p>素人だがもともと哲学とか文芸批評みたいなものが好きでそれ系の本の読んでいた。論理的に物事を考えるのは苦ではない。これは結構大きいと今も思っていて、できるエンジニアはみんな本をよく読んでいる説を唱えたいくらいだ。</p> <h3>新しいものが好き</h3> <p>根が浮ついているので新しい技術にすぐ飛びつく。もちろん新しいものばかりを追いかけていたらちゃんとした技術力は全く身につかないわけだが、この商売は新しいものにしがみついてナンボなところがあるのもまた真理だ。この性格はプラスに働いていると思う。</p> <h3>ひきこもり</h3> <p>もともと引きこもりで、それが原因で大学を留年した。家にパソコンとインターネットがあれば大体生きていけるタイプの人間だ。しかしネオニートではなかったので金儲けだけは苦手だった。プログラミングで飯を食えるようになったので本当にパソコンとインターネットだけで生活できるようになってしまった。</p> <h3>SF的なものが好き</h3> <p>SF小説は今もたまに買って読んでいる。映画もSF的なやつがどちらかといえば好きだし、アニメもSF的なやつが好きだ。『ハッカーになろう』にもSFを読めと書いてあった気がする。プログラミングやエンジニアリングの能力とは直接関係は無さそうだけど、SFが好きというのは大事っぽい気はする。</p> <h2>環境に起因するところが大きい点</h2> <h3>最初に入った会社に誘ってもらった</h3> <p>最初にプログラミングを教えてもらった会社には、自分が応募したわけではなく誘ってもらう形で入社した。そういうのがなければプログラミングをいまやってなかったかも知れない。今頃は何をして生きていたのだろうか、、、リアルに首を吊っていたかも知れない。</p> <h3>ゲーム買ってもらえる家だった</h3> <p>ゲームなんて今どきどの家の子供も買ってもらってるのかも知れないが、案外買えない家も沢山あると思う。実際自分の同級生にも家が貧しくてゲーム機を持ってない子供が何人かいた。ゲーム機を買ってもらえるというのは大事だと思う。ゲームを沢山やることでコンピューターに指示を出す感覚が身についたと思う。</p> <h3>インターネットをやらせてもらえる家だった</h3> <p>ゲーム機に輪をかけてインターネットをさせてもらえる家は少ないだろう。いまでも家にはWifiありませんという人は多い。インターネットがあることでパソコンに抵抗なくなるしブログなんかもやるしjpegだpngだの区別ができるようになるし、ITリテラシー的なものはインターネットとひきこもり生活が教えてくれたと言っても過言ではない。ひきこもり体験がなくてはいまのプログラマー人生もありえなかっただろう。</p> <hr> <p>主なものは以上のような感じだろうか。でもプログラマーとしてやっていくにあたってマイナスに働く要因も沢山思い当たる。</p> <p>例えば自分は文系である。理系で情報系の大学を出た人と比べたら超えられない壁どころではないはるか天空にまでそびえ立つ壁がある。</p> <p>たとえば自分は田舎に住んでいる。ITでやっていこうという人間は都会に住んでいなければ話にならない。田舎に住んでいる限りいつ職を失うかはわからない。ひきこもり系で営業力などゼロに近い自分が今もやっていけているのは奇跡に近いような気がする。</p> <p>しかし結局のところIT、とくにWEB業界で必要とされている能力なんてものはそんなものなのかも知れない。数学など一個もわからなくてもWEBはやれる。田舎に住んでいても個人経営の商店主を騙して高い値段でホームページを作れば生きていける。WEBなんてものはそんなものなのだろう。WEBはこれからも行き場もなく社会の底辺をさまよう人たちに蜘蛛の糸を垂らし続けるのかも知れない。WEBなだけに。</p><![CDATA[blogのお引越し]]>https://blog.nksm.in.net/2020-04-09-blogのお引越し/https://blog.nksm.in.net/2020-04-09-blogのお引越し/Thu, 09 Apr 2020 13:00:15 GMT<p>ブログのお引越しをした。</p> <p>jekyllがあまりにもつらすぎた。</p> <p>でもこっちはこっちでコードブロックのシンタックスハイライトとかがデフォルトでは無いとかの問題がある。</p> <p>やはり自分でCSSとかJS書くしか無いのか。。。うう、、、CSSとかJSとか書きたくないでござる。。。</p> <p>とりあえず頑張って生きていくしかない、、、</p><![CDATA[Netlify CLI バグってる ]]>https://blog.nksm.in.net/2020-04-08-netlify-cli-バグってる/https://blog.nksm.in.net/2020-04-08-netlify-cli-バグってる/Wed, 08 Apr 2020 13:25:44 GMT<p>バグってるから早く直して欲しい。localhost:8888がブラウザで勝手に起動するけど実際に立ってるのはlocalhost:8000だ💢</p><![CDATA[テストブログ]]>https://blog.nksm.in.net/2020-03-26-テストブログ/https://blog.nksm.in.net/2020-03-26-テストブログ/Thu, 26 Mar 2020 13:29:49 GMT<p>テストです</p><![CDATA[テスト投稿]]>https://blog.nksm.in.net/2020-03-24-テスト投稿/https://blog.nksm.in.net/2020-03-24-テスト投稿/Tue, 24 Mar 2020 14:43:39 GMT<h2>ヘッダ2</h2> <p>テストテスト</p> <h3>ヘッダ3</h3> <p>テストです。</p> <p>テスト</p><![CDATA[laravel/uiでフロントエンドの開発環境をサクッとつくる]]>https://blog.nksm.in.net/2020-03-08-laravel-ui/https://blog.nksm.in.net/2020-03-08-laravel-ui/Sun, 08 Mar 2020 03:45:43 GMT<p>まあ<a href="https://readouble.com/laravel/6.x/ja/frontend.html">公式サイト</a>に書いてあるとおりなんだけど。<br> たとえばBootstrapとVueの環境つくりたい場合は下記のコマンド打つだけでサクッとできる。</p> <pre><code>composer require laravel/ui --dev php artisan ui bootstrap php artisan ui vue </code></pre> <p>blade.phpファイルでvueのコンポーネント使うことも可能。</p> <pre><code>@extends('layouts.app') @section('content') &#x3C;example-component>&#x3C;/example-component> @endsection </code></pre> <p>とりあえず始めるだけならwebpackのこととかnpmのこととかなんも考えなくていい。ビルドして動かすには下記のコマンドを打つ。</p> <pre><code>npm install npm run dev </code></pre> <p>小規模かつスピードが求められる開発では一人のエンジニアがバックエンドもフロントエンドもやんないといけないことあると思う。</p> <p>そういうときは一個のコードベースで全て把握できるので便利そう。 </p> <p>まだまだバックエンドは複雑なビジネスロジックがあってテーブルの結合に次ぐ結合が必要なプロジェクトとかある(ダッシュボード系のやつとか)。 </p> <p>サーバーレス&#x26;NoSQLだとゆくゆくつらい思いをすることになる気がする。</p> <p>あと、バックエンドばっかりやってるエンジニアがフロント側も担当しないと行けないとき。色々しらべて環境作りやらなくてもlaravelがいい感じに作ってくれる。</p> <p>LaravelはWEB業務システム受託開発で生きてる奴らの救世主。。。</p><![CDATA[vue-cliでElectron]]>https://blog.nksm.in.net/2020-02-19-vue-cliでElectron/https://blog.nksm.in.net/2020-02-19-vue-cliでElectron/Wed, 19 Feb 2020 14:42:28 GMT<p>Electronアプリをvue-cliを使って開発しよっかなーと思って環境作ってたら、アプリは起動するけど画面に何も表示されない。devtool開いてみると、どうもjsとかcssが読めてない。リソースのパスが <code>/js/hoge.js</code> とかになってる。</p> <p>これはvueで普通にWEBページを作る場合なら問題ないんだろうけど、今回はElectronなのでHTTPで公開してるディレクトリからの絶対パスでは見れるわけがない。試しにビルド後のindex.htmlの各リソースへのhrefを<code>./js/hoge.js</code> みたいな感じにしてあげたら普通に動いた。</p> <p>ネットで検索したら、<code>public/index.html</code> に <code>&#x3C;base href="./"></code>って入れればいいよ、と言ってる人とかもいたけど効果なし。 更にググったらそのものズバリな処方箋を見つけた。</p> <p><a href="https://qiita.com/heyheyww/items/5d06936745118045a308">Vue-CLI3でbuildすると画面が真っ白になる</a></p> <p>vue.config.jsファイルに<code>publicPath: './'</code> と書くだけで解決。このへんの情報、Electron側でもVue側でもいいのでドキュメントの割と最初の方に書いといてほしい。。。</p> <p>ちなみにvue-cli 4.2.2、Electron 8.0.1でも動いた。</p><![CDATA[自分に足りないもの]]>https://blog.nksm.in.net/2020-02-18-自自分に足りないもの/https://blog.nksm.in.net/2020-02-18-自自分に足りないもの/Tue, 18 Feb 2020 14:52:14 GMT<p>個人事業主としてやっていくにあたって、今の自分に足りてないものを考えてみた。</p> <h2>提案力がない</h2> <p>これは一番感じる。なんとなくITで何かやってみたい、と考えている(技術にはあんまりくわしくない)顧客に対して、スッ、といい感じのソリューションを提案できるパワー。</p> <p>実際にそこで即興で差し出した提案がそのまま採用されなくてもいいと思う。何か、顧客に対して「いいじゃんそれ!」と思わせるようなノリが足りない。</p> <p>ノリ。つまりグルーヴ。というか文字通りのインプロヴィゼーションというかジャムセッション感というか。そういうのが足りない。この「ノリ」を生み出すために必要なのは何か。多分次の項目が関係してる。</p> <h2>ビジネス界の流行りを追えてない</h2> <p>エンジニアにとってビジネス界の流行りを追うというのはどういうことか。多分Kubernetesをやるとか、Rustをやるとかではない。これはもう、圧倒的にAIであり量子コンピューティングでありブロックチェーンなのである。ドローンでありIoTであり5Gなのである。</p> <p>エンジニアは、これらの技術をビジネスで使うのにどれくらいの労力が必要かということが顧客よりもずっと感覚としてわかっている。そんなに簡単にできることではないし、できるようになったところで顧客のビジネスに生かせる可能性がどれくらいあるかはわからない。というか顧客のビジネスとは全く関係ないことのほうが多いだろう。</p> <p>しかし、顧客との間で「ノリ」が生まれるのは圧倒的にこれらの「ビジネス界の流行り」が話題に出たときなのである。</p> <p>そしてそこで生まれたノリを実際のビジネスとして動かしていくためにはいくばくかの実際の技術スキルが必要となるだろう。つまり、簡単なデモは見せられるくらいにAIを使えたりドローン飛ばしたりできる必要がある。しかし実務レベルのエンジニアスキルにまで磨くことはできない。当然ながら、AIをバリバリやってる人たちは大学院まで行って勉強したりとか、就職してからも日々膨大なデータを扱ったりしているのだ。そこと比べられたら一介のWEBエンジニアが片手間で習得できる「AI」などたかがしれている。</p> <p>だがその素人に毛が生えたようなスキルこそが、顧客をその気にさせるのだろう。そこに対して時間を投資することができないでいる。技術者としては、そこに対する片手間の投資が無駄に見えて仕方がないのだ。これから先AIのエンジニアとしてフルタイムで働くことになるのなら話は別だが、そういうわけではない。生活の糧はWEB開発の案件で得ていく必要がある。であれば、「本業」であるWEBの方面でエッジの効いた技術を習得していくほうがエンジニアのキャリアとしては効果的に思えてしまう。</p> <p>だがそれだと目の前の顧客の「ノリ」を引き出すことができない。一人でやっていることの限界を感じる。「ハスラー」的な相棒が一人いてくれたら心強いのにな、、と思うことはある。</p> <h2>特化した技術領域がない</h2> <p>エンジニアのキャリア云々を書いておきながら、自分には特化した技術領域がない。まあWEBのサーバーサイドが一番得意ではあるが、Linuxのカーネルパラメータについて詳しいとかいうわけでもない。スマホアプリ作ってくれと言われたら言われるがままに作る。そんな、ポリシーのないエンジニアだ。今まではそうでいることが生き延びる戦略ではあったのだが、今後はそれだときつくなっていく気がする。</p> <p>というのも、自分より年上で、WEBもアプリも基幹システムも何でもやる、というエンジニアを数人みてきたのだがどのエンジニアも50歳になったときに自分がなっていたいエンジニア像ではなかった。自分が初老のおっさんになったときは、コンパイラや仮想マシンに詳しいエンジニアになっていたい。それが仕事になるかどうかは別として、そのへんの低レイヤがわかった上でサーバーのチューニングとかアルゴリズムの最適化とかができるかっこいいエンジニアになっていたい。</p> <p>そういう気持ちがあるものの、目の前の仕事に追われて肝心のコンパイラや仮想マシンの勉強は全く手がつけられていない。自営業化したこともあり、収入を安定化させることが先で、それらは棚上げ状態になっている。このまま続けていくと、「安定のため」に続けていたポリシーなき仕事選びこそが自分のキャリアを不安定にさせるのではないかという危惧がある。なんでも屋は、誰とでも替えがきく存在でしかない。なんでもできる人はかっこいいが、なんでもできる人には確固たる基礎がある。低レイヤがわかっているから、あるいはたくさんのアーキテクチャをみてきたから、何でもできるのである。ところが、言われるがまま何でもやってきた人には基礎がない。やれと言われたことをこなすスキルは伸びるが、それだと単なる「保険」としての人材の域を出ない。</p> <p>何でもできる人と何でもやるだけの人は違うのだ。何でもやる人は、言われたことをやりはするけれどやれるかといったらそうでもない。</p> <hr> <p>エンジニアであるからには、顧客に夢を見させられる技術を持っていなくてはならないと思う。夢を見せた結果顧客のビジネスが大コケしても、夢を見ていたときの興奮はウソではない。顧客に夢を見せることでカネも人も動く。さらに言えば夢のある仕事は若者の興味を引くことができる。エンジニアが棄却に対して夢を見せることで生まれた夢のある仕事に若者が参画することで、顧客から若者へ、つまりおっさんから若者へとカネが流れていくのである。</p> <p>世の中に夢を振りまくエンジニアであるためにも、上に書いた3つの内少なくともどれか1つは持っていなくてはならないと思う。一人の人間が達成できることは限られているからだ。となると自分ができるのは技術を磨くことだろうか。田舎では技術だけ持っていても仕事につながらなかったりするので難しいところだ。とりあえずはいろいろやって模索していきたいと思う。</p><![CDATA[Electronのインストール]]> node install.js とか出たまま一向にインストールされる気配がない。 何かがおかしいと思ってぐぐったら下記のissue…]]>https://blog.nksm.in.net/2020-02-13-install-electron/https://blog.nksm.in.net/2020-02-13-install-electron/Wed, 12 Feb 2020 15:07:04 GMT<p>Electronでアプリ作ろうかと思って <code>node install --save-dev electron</code> とかやってみたのだが <code>> node install.js</code> とか出たまま一向にインストールされる気配がない。</p> <p>何かがおかしいと思ってぐぐったら下記のissueを見つけた。</p> <p><a href="https://www.electronjs.org/docs/tutorial/installation">https://github.com/electron/electron/issues/21069</a></p> <blockquote> <p>It may seem stuck, but it is actually downloading the release zip of Electron from GitHub. But GitHub's downloads are currently slow (~40KB/s for me) so just give it a while. The zip is around 60 MB. You can see the progress in the Network tab of the Activity Monitor in macOS.</p> </blockquote> <p>アクティビティモニタ開けばファイルダウンロードが進んでるのがわかるよ、って書いてあるんだけど、たしかにアクティビティモニタ開いたら見えたけど、でも数十分もうんともすんとも言わないのは流石にあんまりじゃないか。</p> <p>せめて今どのくらいダウンロード終わったよ、っていうプログレスバー的なやつは出したほうが良いんじゃないだろうか。</p> <p>で、待つこと30分。結果、 <code>ECONNRESET</code> のエラーが出てた。公式サイトにはこうある。</p> <p><a href="https://www.electronjs.org/docs/tutorial/installation">https://www.electronjs.org/docs/tutorial/installation</a></p> <blockquote> <p>When running npm install electron, some users occasionally encounter installation errors.</p> <p>In almost all cases, these errors are the result of network problems and not actual issues with the electron npm package. Errors like ELIFECYCLE, EAI_AGAIN, ECONNRESET, and ETIMEDOUT are all indications of such network problems. The best resolution is to try switching networks, or wait a bit and try installing again.</p> </blockquote> <p>ふーん。ネットワークのせいね。そうかそうか。。同じ問題でこんなに困ってる人が世界中にいるのもすべてネットワークが悪い。ネットなんてこの世になければよかったんだ、、、そんな気持ちにさせられる。</p> <p>10回くらい <code>npm i -D electron</code> を叩いたらいつの間にかインストールされていた。<code>--unsafe-perm=true</code> とかも試してみたけど無関係っぽかった。<code>--verbose</code> オプションをつけても肝心の <code>> node install.js</code> で沈黙するところでは何も情報を出してくれないので無意味だった。</p> <p><strong>Electronのインストールには運が必要。</strong></p> <p>とてもためになる教訓が得られた。</p><![CDATA[Jekyllが微妙]]>https://blog.nksm.in.net/2020-02-02-Jekyll微妙/https://blog.nksm.in.net/2020-02-02-Jekyll微妙/Sun, 02 Feb 2020 02:40:29 GMT<p>GitHub Pages でブログ書きたいからJekyll使ってるんだけど、正直微妙。JekyllのバージョンによってGemでテーマインストールできない。公式サイトに紹介してあるテーマギャラリーのテーマ使おうとしてみてもCSSのパスが壊れてたりする。あと、テーマをコマンド一発もしくは設定ファイル一発で切り替えられないのもだるい。_layoutsとか_includesとかを直接上書きしてくれ!!!11とか言われると萎える。</p> <p>まあ、自分がRuby界隈の常識に詳しくないから無駄に苦労している可能性もあるとは思うが。。それにしても使い勝手が悪すぎる。CMSってほんと素晴らしいんだなあ、WordPressってほんとにすごかったんだなあ、という気持ちにならざるを得ない。自分でSassとかを書くのも正直だるくてカスタマイズする気にもならない。</p> <p>他に手軽にいい感じにブログかけるソリューションは無いのかなあ、、以下の条件を満たすやつ。</p> <ul> <li>Gitで記事の履歴管理できる</li> <li>GitHub PagesとかS3とかで静的ファイルでデプロイできる</li> <li>テーマの切り替えが簡単</li> <li>依存関係少ない。依存ライブラリのパッチバージョンが違うだけで動かない、、とかが無い</li> <li>限りなく無料に近い費用で運用できる</li> </ul> <p>手間を考えるとやっぱりWordPressとかはてなブログとかが良いのかなあ。。。重いから嫌なんだよな。</p><![CDATA[Elm初心者がURLルーティングを頑張ってみた結果]]>https://blog.nksm.in.net/2019-10-22-elm-routing/https://blog.nksm.in.net/2019-10-22-elm-routing/Tue, 22 Oct 2019 13:14:00 GMT<p>Elmで複数のページがあるSPA的なのを作りたいと思って公式のチュートリアルを読んでみた。</p> <p><a href="https://guide.elm-lang.org/webapps/url_parsing.html">https://guide.elm-lang.org/webapps/url_parsing.html</a></p> <p>パーサーの作り方は載っているのだが、肝心の使い方については、「TODO」の悲しい4文字。。。</p> <p>色々やってみて、ページを遷移させることについてはなんとか成功したので備忘録として残しておく。</p> <h2>元となるファイル</h2> <p><a href="https://guide.elm-lang.org/webapps/navigation.html">https://guide.elm-lang.org/webapps/navigation.html</a></p> <p>上記のページに載っているソースコードを元に改造する。</p> <pre><code class="language-elm">import Browser import Browser.Navigation as Nav import Html exposing (..) import Html.Attributes exposing (..) import Url -- MAIN main : Program () Model Msg main = Browser.application { init = init , view = view , update = update , subscriptions = subscriptions , onUrlChange = UrlChanged , onUrlRequest = LinkClicked } -- MODEL type alias Model = { key : Nav.Key , url : Url.Url } init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg ) init flags url key = ( Model key url, Cmd.none ) -- UPDATE type Msg = LinkClicked Browser.UrlRequest | UrlChanged Url.Url update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case msg of LinkClicked urlRequest -> case urlRequest of Browser.Internal url -> ( model, Nav.pushUrl model.key (Url.toString url) ) Browser.External href -> ( model, Nav.load href ) UrlChanged url -> ( { model | url = url } , Cmd.none ) -- SUBSCRIPTIONS subscriptions : Model -> Sub Msg subscriptions _ = Sub.none -- VIEW view : Model -> Browser.Document Msg view model = { title = "URL Interceptor" , body = [ text "The current URL is: " , b [] [ text (Url.toString model.url) ] , ul [] [ viewLink "/home" , viewLink "/profile" , viewLink "/reviews/the-century-of-the-self" , viewLink "/reviews/public-opinion" , viewLink "/reviews/shah-of-shahs" ] ] } viewLink : String -> Html msg viewLink path = li [] [ a [ href path ] [ text path ] ] </code></pre> <p>このコードでも、なんとなくブラウザのURLバーのURLは変わってるしHTMLのテキストも変わってるのはわかる。でもURLによって表示するコンテンツをまるごと切り替える、みたいなのはできない。</p> <p>そこで、さっきもはったURLパースのやり方を書いてるページを参考にコードに書き足していく。</p> <p><a href="https://guide.elm-lang.org/webapps/url_parsing.html">https://guide.elm-lang.org/webapps/url_parsing.html</a></p> <p>URLを見る限り、ホーム、プロフィール、レビューの三種類があるようだ。</p> <pre><code class="language-elm">-- import 文を追加する import Url.Parser exposing (Parser, parse, (&#x3C;/>), map, oneOf, s, string, top) -- 中略 type Route = Home | Profile | Reviews String -- 中略 routeParser : Parser (Route -> a) a routeParser = oneOf [ map Home top , map Profile (s "profile") , map Reviews (s "reviews" &#x3C;/> string) ] </code></pre> <p>公式のチュートリアルに書いてあるのはここまでだけど、実際にURLをパースするには下記のような関数を書く。</p> <p>参考: <a href="https://package.elm-lang.org/packages/elm/url/latest/Url-Parser#parse">https://package.elm-lang.org/packages/elm/url/latest/Url-Parser#parse</a></p> <pre><code class="language-elm">toRoute : String -> Route toRoute string = case Url.fromString string of Nothing -> Home Just url -> Maybe.withDefault Home (parse routeParser url) </code></pre> <p>さらに、現在の状態をmodelで保持できるようにする。</p> <pre><code class="language-elm">type Page = HomePage | ProfilePage | ReviewsPage String type alias Model = { key : Nav.Key , url : Url.Url , page : Page } init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg ) init flags url key = ( Model key url HomePage, Cmd.none ) </code></pre> <p>そしてURLが更新されたタイミングでURLをパースするようにupdateを修正。</p> <pre><code class="language-elm">update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case msg of LinkClicked urlRequest -> case urlRequest of Browser.Internal url -> case toRoute (Url.toString url) of Home -> ( { model | page = HomePage }, Nav.pushUrl model.key (Url.toString url) ) Profile -> ( { model | page = ProfilePage }, Nav.pushUrl model.key (Url.toString url) ) Reviews name -> ( { model | page = ReviewsPage name }, Nav.pushUrl model.key (Url.toString url) ) Browser.External href -> ( model, Nav.load href ) UrlChanged url -> case toRoute (Url.toString url) of Home -> ( { model | url = url, page = HomePage } , Cmd.none ) Profile -> ( { model | url = url, page = ProfilePage } , Cmd.none ) Reviews name -> ( { model | url = url, page = ReviewsPage name } , Cmd.none ) </code></pre> <p>あとはページの種類によって内容を切り替える。</p> <pre><code class="language-elm">view : Model -> Browser.Document Msg view model = { title = "URL Interceptor" , body = [ text "The current URL is: " , b [] [ text (Url.toString model.url) ] , case model.page of HomePage -> ul [] [ viewLink "/home" , viewLink "/profile" , viewLink "/reviews/the-century-of-the-self" , viewLink "/reviews/public-opinion" , viewLink "/reviews/shah-of-shahs" ] ProfilePage -> p [] [ text "profile page" ] ReviewsPage name -> p [] [ text (name ++ "'s review page.") ] ] } </code></pre> <p>これで一応URLをパースして表示内容を切り替えることはできるようになった。</p> <p>多分というか絶対もっといい書き方があると思うが、それはこれからの修行だ。。。</p> <p>最終的なソースは下記のようになった。</p> <pre><code class="language-elm">import Browser import Browser.Navigation as Nav import Html exposing (..) import Html.Attributes exposing (..) import Url import Url.Parser exposing (Parser, parse, (&#x3C;/>), map, oneOf, s, string, top) -- MAIN main : Program () Model Msg main = Browser.application { init = init , view = view , update = update , subscriptions = subscriptions , onUrlChange = UrlChanged , onUrlRequest = LinkClicked } -- URL Routing type Route = Home | Profile | Reviews String routeParser : Parser (Route -> a) a routeParser = oneOf [ map Home top , map Profile (s "profile") , map Reviews (s "reviews" &#x3C;/> string) ] toRoute : String -> Route toRoute string = case Url.fromString string of Nothing -> Home Just url -> Maybe.withDefault Home (parse routeParser url) -- MODEL type Page = HomePage | ProfilePage | ReviewsPage String type alias Model = { key : Nav.Key , url : Url.Url , page : Page } init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg ) init flags url key = ( Model key url HomePage, Cmd.none ) -- UPDATE type Msg = LinkClicked Browser.UrlRequest | UrlChanged Url.Url update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case msg of LinkClicked urlRequest -> case urlRequest of Browser.Internal url -> case toRoute (Url.toString url) of Home -> ( { model | page = HomePage }, Nav.pushUrl model.key (Url.toString url) ) Profile -> ( { model | page = ProfilePage }, Nav.pushUrl model.key (Url.toString url) ) Reviews name -> ( { model | page = ReviewsPage name }, Nav.pushUrl model.key (Url.toString url) ) Browser.External href -> ( model, Nav.load href ) UrlChanged url -> case toRoute (Url.toString url) of Home -> ( { model | url = url, page = HomePage } , Cmd.none ) Profile -> ( { model | url = url, page = ProfilePage } , Cmd.none ) Reviews name -> ( { model | url = url, page = ReviewsPage name } , Cmd.none ) -- SUBSCRIPTIONS subscriptions : Model -> Sub Msg subscriptions _ = Sub.none -- VIEW view : Model -> Browser.Document Msg view model = { title = "URL Interceptor" , body = [ text "The current URL is: " , b [] [ text (Url.toString model.url) ] , case model.page of HomePage -> ul [] [ viewLink "/home" , viewLink "/profile" , viewLink "/reviews/the-century-of-the-self" , viewLink "/reviews/public-opinion" , viewLink "/reviews/shah-of-shahs" ] ProfilePage -> p [] [ text "profile page" ] ReviewsPage name -> p [] [ text (name ++ "'s review page.") ] ] } viewLink : String -> Html msg viewLink path = li [] [ a [ href path ] [ text path ] ] </code></pre> <p>モジュールへの分割などをこれから勉強したい。</p><![CDATA[Terraformのtargetをfileから抽出する]]>https://blog.nksm.in.net/2019-10-19-Get-resource-targets-from-.tf-file/https://blog.nksm.in.net/2019-10-19-Get-resource-targets-from-.tf-file/Sat, 19 Oct 2019 06:08:00 GMT<p>terraformを使ってると、一発で全部のリソースじゃなくて一部のリソースだけapplyしたくなることがある。ファイル単位で。ファイルを開いていちいちリソース名を確認してから <code>-target</code> オプションを書くのがほんとにトホホ。。。という感じでめんどくさい。</p> <p>そこで、ファイルからリソース名を抽出する方法を考えた。</p> <pre><code>$ grep "^resource" ./ecs.tf | cut -d ' ' -f 2- | sed 's/"\(.*\)"\s\+"\(.*\)"\s\+{/\1.\2/' </code></pre> <p>↑のコマンドでリソースだけ抜き出すことはできた。これを引数の形に加工して変数に格納する。</p> <pre><code>$ resources=$(grep "^resource" ./ecs.tf | cut -d ' ' -f 2- | sed 's/"\(.*\)"\s\+"\(.*\)"\s\+{/\1.\2/' | xargs echo | sed 's/ / -target=/g') </code></pre> <p>そして <code>terraform plan</code> したらうまくいった。</p> <pre><code>$ terraform plan -target=$resources </code></pre> <p>シェルスクリプトにする。</p> <p>plan.sh</p> <pre><code class="language-sh">#!/usr/bin/env bash set -euo pipefail scriptpath=${0%%.sh} execname=${scriptpath##*/} filename=$1 shift resources=$(grep "^resource" $filename \ | cut -d ' ' -f 2- \ | sed 's/"\(.*\)"\s\+"\(.*\)"\s\+{/\1.\2/' \ | xargs echo \ | sed 's/ / -target=/g') terraform $execname -target=$resources $@ </code></pre> <p>apply.sh という名前でsymlinkを作ってapply用のスクリプトとして使うこともできると思う。</p><![CDATA[dockerでREPOSITORYが<none>になってるイメージを消す]]>になってるやつが生まれてくる。 こういうやつ。 このhttps://blog.nksm.in.net/2019-06-09-dockerrmi/https://blog.nksm.in.net/2019-06-09-dockerrmi/Sat, 08 Jun 2019 15:00:00 GMT<p>Dockerを使ってるとイメージを更新したときとかにREPOSITORYが&#x3C;none>になってるやつが生まれてくる。</p> <p>こういうやつ。</p> <pre><code>$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE kotlintrial latest 858cfd2443af About an hour ago 826MB my-appliaction latest 58a75a473622 44 hours ago 492MB &#x3C;none> &#x3C;none> 23b086fc3865 44 hours ago 494MB &#x3C;none> &#x3C;none> 34dcbcbe22c5 44 hours ago 494MB my-application latest 2c12748b798f 3 days ago 505MB &#x3C;none> &#x3C;none> 4c895ee3d84c 3 days ago 505MB ... </code></pre> <p>この&#x3C;none>だけを消したいとき、以前はこんな感じで無理やりやっていた。</p> <pre><code>$ docker rmi $(docker images | grep '&#x3C;none>' | awk '{print $3}') </code></pre> <p>でも普通に考えたら公式で提供してる手段があるはずなので調べたらあった。</p> <p><a href="http://docs.docker.jp/engine/reference/commandline/images.html">http://docs.docker.jp/engine/reference/commandline/images.html</a>{:target="_blank"}</p> <p>下記のようにやれば同じことがdockerコマンドだけでできる。</p> <pre><code>$ docker rmi $(docker images -f "dangling=true" -q) </code></pre> <p>Docker使う上ではdockerコマンドでできることはdockerコマンドだけでやったほうが良いと思われるが、なんとなくしゃらくささを感じるのも事実。テキスト処理コマンドのパワーって特定のなにかに依存しないことだとも思うし。。</p><![CDATA[webpフォーマットのデータを解凍するコマンド]]>https://blog.nksm.in.net/2019-05-29-dwebp/https://blog.nksm.in.net/2019-05-29-dwebp/Tue, 28 May 2019 15:00:00 GMT<p>ネットで画像ダウンロードすると<code>.webp</code>フォーマットになっててローカルPCからプレビューできなかったりするし、ドキュメントに貼れなかったりする。</p> <p>webpフォーマットを元の画像ファイルに戻したいときは下記のようにする。</p> <pre><code>$ dwebp image.webp -o output.png </code></pre> <p>dwebpコマンドのインストール方法は<a href="https://developers.google.com/speed/webp/docs/precompiled">Googleの公式サイト</a>に書いてあるます。</p><![CDATA[S3のIPアドレス範囲を取得する]]>https://blog.nksm.in.net/2019-05-07-get_s3_ip/https://blog.nksm.in.net/2019-05-07-get_s3_ip/Mon, 06 May 2019 15:00:00 GMT<p>VPCエンドポイントの設定とかでS3のIPアドレス範囲が欲しい時がある。</p> <p>jqをインストールして、下記のコマンドを実行したら取れた。</p> <pre><code class="language-sh">## AWSが公開してるJSONファイルを取得してjqで加工 $ curl https://ip-ranges.amazonaws.com/ip-ranges.json | jq \ '.prefixes[] | select(.service == "S3" and .region == "ap-northeast-1") | .ip_prefix' </code></pre> <p>サービス名とリージョンは適宜変更する。</p> <p>参考: <a href="https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws-ip-ranges.html">AWS IP アドレスの範囲</a></p> <h2>追記</h2> <p>上のやつドヤ顔で書いてたけど、よく読んだらAWSの公式ドキュメントに同じようなコマンドが書いてあった。。。</p><![CDATA[会社でGitHub使うときのアカウント]]>https://blog.nksm.in.net/2019-04-11-github/https://blog.nksm.in.net/2019-04-11-github/Wed, 10 Apr 2019 15:00:00 GMT<h3><a href="https://techblog.zozo.com/entry/github_sso">全社的に会社用GitHubアカウントを廃止した件</a></h3> <p>うーん、どうなんだろ。会社を信頼してもいいのであればこういうのもいいけど、クソな会社だと自分の趣味の活動とかを社員に見られたくないという気持ちも湧くなあ。</p> <p>まあでも昼休みとかに自分のコード書きやすくなるのは良いかもな。</p><![CDATA[vscodeのenablePreview]]>https://blog.nksm.in.net/2019-04-11-memo/https://blog.nksm.in.net/2019-04-11-memo/Wed, 10 Apr 2019 15:00:00 GMT<h3><a href="https://beyondjapan.com/blog/2017/08/vscode-useful-settings">Visual Studio Codeで有能な設定をオンにしてみる</a></h3> <p>これ毎回忘れる。特にenablePreviewの設定。<br> VSCODEはいい加減デフォルトでオフにしてほしい。</p>