著者アーカイブ 杉浦

著者:杉浦

【Vue.js】スプレッド構文と外部定義によるコンポーネントファイルの縮小化

 Vue.jsの単一ファイルコンポーネントはコンポーネントを構成するHTMLテンプレート、JavaScript、CSSを一ファイルにまとめる仕組みです。コンポーネントの構成要素全体を把握しやすい点で優秀なのですが、コンポーネントの構成要素全体を含むが故にファイルの肥大化を招きがちです。よくある肥大化を防ぐ方法の一つはコンポーネントに分割する粒度を細かくしていく方法です。理解しやすい方法なのでこれができるならこちらの方がいいでしょう。しかし分割困難かつ複雑なロジックを持つコンポーネントが現れる時があります。この状況に対応するため、ロジックを外部ファイルに定義、コンポーネントはロジックを呼び出すのみ、呼び出し方はスプレッド構文で安全に簡単に記述、という方法を考えます。
 スプレッド構文はJavaScriptの記法の一つです。正直滅多に使いません。
スプレッド構文 – JavaScript | MDN
 ここではObjectに関するスプレッド構文を扱います。動作は次の通り。public property限定の継承のといってもそう間違っていない印象があります。

var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };

var clonedObj = { ...obj1 };
// Object { foo: "bar", x: 42 }

var mergedObj = { ...obj1, ...obj2 };
// Object { foo: "baz", x: 42, y: 13 }

// https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals
// スプレッド構文 - JavaScript | MDN#Object リテラルで使う

 注意点として浅いコピーなためコピーしたObjectとコピー元Objectの両方がネスト先の参照を共有する点があります。まあ不変な対象をコピーするならばshallow copyもdeep copyも変わらないのでそういう時は何も気にせず記述して大丈夫です。
 スプレッド構文を利用してVue.jsのコンポーネント中で定義を呼び出します。例えば、VuexのmapHoge系です。

computed: {
  // オブジェクトスプレット演算子で、外のオブジェクトとこのオブジェクトを混ぜる
  ...mapState({
    // ...
  })
  // コンポーネント個別のcomputedメソッド
  localComputed () { /* ... */ },
}
// https://vuex.vuejs.org/ja/guide/state.html#%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E6%BC%94%E7%AE%97%E5%AD%90
// ステート | Vuex

 Vuexのステート参照用メソッドを返すmapState関数の結果をスプレッド構文でコピーして、コンポーネント独自のcomputedメソッドと混ぜ合わせます。これでcomputedの中は次のように書いたのと同じになり楽できます。

computed: {
  // mapStateの結果が展開
  storeComputed1 () { /* ... */ },
  storeComputed2 () { /* ... */ },
  storeComputed3 () { /* ... */ },
  // コンポーネント個別のcomputedメソッド
  localComputed () { /* ... */ },
}
// https://vuex.vuejs.org/ja/guide/state.html#%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E6%BC%94%E7%AE%97%E5%AD%90
// ステート | Vuex
著者:杉浦

アンドロイド用SSHクライアントJuiceSSHの紹介

 GNSS関連の開発を行っていると外に出ての作業が増えてきます。衛星の信号を受信するには天頂に障害物のない外が一番なためです。一方で外に出ると開発用の道具を持ち運びにくいです。ノートPCならばぎりぎりですが、それでもそこそこ重く危険です。その点スマホならば全然問題ありません。JuiceSSHはAndroid上で開発を行うための便利なアプリの一つです。
 JuiceSSH – SSH Client – Google Play のアプリ
 使い方は正直アプリを見ながらポチポチするだけで大体わかります。サーバにつないでサーバ内部でいつも通り色々やるだけです。スマホのまま色々やれるのは結構便利です。
 一見分かりにくく重要だったのがスクリーンショットで囲った特殊キー群です。文字入力時に文字入力部の上をタップすると現れます。スマホのままでは扱いにくい部分全般(パイプとか区切りとかスクリーンやエディタ絡みとか補完入力とか)をカバーしてくれます。

著者:杉浦

【Python】ログを読み取りやすく作る

 長期にわたって動かすプログラムを運用する際ログは重要です。ログがないと何が起こったかもさっぱりわからず想定しない動作の対応もとても困難です。そんなわけでログを作るわけですが、ただファイルに記録を書きだすだけならログ機能なんて使わず、ファイルの書き込み機能だけで十分です。Pythonのログ機能にはログを書きこむ際にあらかじめ用意された変数の様なものがあり、それを用いることで労せず情報の濃いログを作れます。
 やることはログフォーマットの指定です。一度書きだされるログの形式を定めます。フォーマットは次のようにロガーに渡します。

# グローバルなロガーで定義するならこれ
FORMAT = '%(asctime)-15s %(clientip)s %(user)-8s %(message)s'
logging.basicConfig(format=FORMAT)
# 個別にロガーを作るならこれ
logger = logging.getLogger(__name__)
handler = logging.FileHandler(filename='%s/log/debug-%s.log' % (
    os.path.dirname(os.path.abspath(__file__)), dt.now().date()
))
handler.setFormatter(logging.Formatter(FORMAT))
logger.addHandler(handler)

 上の様に好きな文字列をフォーマットとしてロガーに渡せます。この時のasctimeやmessageの様な%()sとprintf的に定義されている部分にログ書き込み時の状況に応じた値が書き込まれます。変数はLogRecord 属性として次の部分にまとめられています。
logging — Python 用ロギング機能 — Python 3.8.0 ドキュメント #LogRecord 属性
 多くの人が凝ったロギング機能をGitHubやpypiで公開してくれていますが、どうにも必要な分が足りない時には自作する必要が出てきます。大体、スレッドやプロセスの分岐とどこからどこまでが一連の流れか、一連の流れであることをどう示すか、外部サービスとの連携ログはどうするか、とシステムに特化した部分を考え出すようになると自作した方がお得です。
 

著者:杉浦

【PHP】php-cs-fixerやPhpStormが最新のコーディング規約標準勧告PSR-12にもうすぐに対応

 PSR-12はPHPのコーディング規約のベースです。”PHPのコードを記述する時はとりあえずPSR-12に従い、加えてプロジェクト毎に状況に合わせて規約の拡張をする”という使い方が想定されています。PSR-12はPHP5.4時点で定められていたコーディング規約用標準勧告であるPSR-2に代わって定められたものです。現在のPHP最新バージョンは7.3であり更新が必要になりました。
 PSR-12に乗り換えたいのですが、まだまだ対応したLint等が少ないのが現状です。対応しなければ即座にコードがバグるわけでもなし、そんなものです。そんな中あっという間に対応したPHP_CodeSnifferに続いて、php-cs-fixerとPhpStormがPSR-12に対応しそうです。
 Release 3.5.0 · squizlabs/PHP_CodeSniffer
 php-cs-fixerは自動修正機能付きのPHP用Lintです。PSR-2やSymfonyの定めるコーディング規約セットに準じた自動修正をPHPのソースコードに適用できます。現在ver3.0で開発中です。
PSR-12 Support · Issue #4502 · FriendsOfPHP/PHP-CS-Fixer
 ある程度できておりcopmoser.jsonに

     "friendsofphp/php-cs-fixer": "3.0.x-dev",

と記述してcomposer updateすればPSR-12版を試せます。
 PhpStormはPHPを主に対象としたweb系言語のIDEです。こちらもコードのフォーマット機能があり、早期アクセスプログラム対象の2019.3verで既に実装されています。2019.1が5月、.2が8月なので順調にいけば来月辺りにリリースされ安定が担保されるでしょう。
 PhpStorm 2019.3 EAP #5 | PhpStorm Blog

著者:杉浦

PlantUMLで出力を見やすい様に制御する

 PlantUMLはUML図を生成する記法です。
シンプルなテキストファイルで UML が書ける、オープンソースのツール
PlantUML integration – Plugins | JetBrains
 便利なのですが生成の配置の制御が大雑把なのが玉に瑕です。
 画面に10個、20個もノードを描画すると関係線(この記事で使う造語。関係を表現する線)が交差して複雑になりだします。

@startuml

abstract class AbstractList
abstract AbstractCollection
interface List
interface Collection


class ArrayList {
Object[] elementData
size()
}

enum TimeUnit {
DAYS
HOURS
MINUTES
}

abstract class AbstractList2
abstract AbstractCollection2
interface List2
interface Collection2


List <|-- AbstractList
Collection <|-- AbstractCollection

Collection <|-- List
AbstractList <|-- ArrayList

List2 <|-- AbstractList2
AbstractList2 <|-- AbstractCollection2
AbstractList2 <|-up- Collection2


AbstractCollection <|- AbstractList

ArrayList <|-- ArrayList2
AbstractList <|-- AbstractList2
AbstractCollection <|-- AbstractCollection2
List <|-- List2
Collection <|-- Collection2

@enduml

 このためにpackage{}で集約を作ったり矢印のstyleskinparam linetype ortho-left-|>で方向を制御します。集約は簡単にいい感じになるので定義できるときはできる限り記述しておくべきです。

@startuml
skinparam linetype ortho

package 1st {
    abstract class AbstractList
    abstract AbstractCollection
    interface List
    interface Collection


    class ArrayList {
    Object[] elementData
    size()
    }

}

enum TimeUnit {
    DAYS
    HOURS
    MINUTES
}

package 2nd {
    abstract class AbstractList2
    abstract AbstractCollection2
    interface List2
    interface Collection2

    class ArrayList2 {
        Object[] elementData
        size()
    }
}

List <|-- AbstractList
Collection <|-- AbstractCollection

Collection <|-- List
AbstractList <|-- ArrayList

List2 <|-- AbstractList2
AbstractList2 <|-- AbstractCollection2
AbstractList2 <|-up- Collection2


AbstractCollection <|- AbstractList

ArrayList <|-down- ArrayList2
AbstractList <|-down- AbstractList2
AbstractCollection <|-down- AbstractCollection2
List <|-down- List2
Collection <|-down- Collection2

@enduml

 見やすくするなる時に重要になるのは連続した関係線があまり曲がらないことです。a -> b-> cとなる時に、a -right-> b, b-right-> c, の様に書くとやりやすいです。

著者:杉浦

ドキュメント変換ツールPandocの紹介

Pandoc – About pandoc
Pandoc ユーザーズガイド 日本語版 – Japanese Pandoc User’s Association
 Pandocはドキュメント変換ツールです。このドキュメントの範囲にはとても多くのモノが含まれています。入力には素のテキストファイルはもちろん、素といくつかの拡張のマークダウン、Latex、HTMLなど、出力は実に多く入力の各種に加えてPowerPoint、PDF、EPUB(電子書籍)などがあります。
 インストールはPandoc – Installing pandocから案内に従うだけ、Windowsならインストーラを落として起動して完成。使い方もシンプル、コマンドラインでpandocを呼び出して次のように対象と出力先を渡すのみです。拡張子が独特かつ正しいものならば一々フォーマットの指定をする必要もありません。

pandoc <対象ファイルのパス> -o <出力先のパス>
# 例えば
pndoc ./hoge.md -o ./hoge.pptx

 これだけでOKです。マークダウンの拡張など入力のフォーマットを細かく指定したいときは-fオプションで可能です。

pndoc ./hoge_ext.md -f markdown_phpextra -o ./hoge.pptx

 出力の場合は同様の記法で-tオプションです。対応するフォーマットは次リンク先に列挙されています。
Pandoc – Pandoc User’s Guidel#general-options
 多くの文書はそれぞれのフォーマットに適した状態で記述されているのでただ変換したのみではデザインが崩れがちですが複数ページにわたるコピペや怪しい置換作業から解放されます。

著者:杉浦

【PHP】Union TypesのRFCが受理されそう

 Union Types v2の名でPHPにUnion Typesの導入が可決されそうです。日本時間の2019/10/28 18:00時点で46対3で可決有利。おそらくそのまま受理されるでしょう。
PHP: rfc:union_types_v2
php-rfcs/0000-union-types-v2.md at union-types · nikic/php-rfcs
 Union Typesは大雑把に言えば型の和を示す型です。Union Typesが実装された時、次のように全く異なる型のorを指定できます。例では返り値の型ですが引数など今まで型を使えていたどの部分でも使えます。

public function getNumber() :int|float { // 返り値はint型かfloat型である、という宣言
    return $this->number;
}

 TypeScriptを触るとよく見る記法です。TypeScript以外にも型を定義できる言語ではよく見るらしいです。PHPは暗黙の型変換もあり組み込み関数も何かと寛容なものが多いので細かく縛れるUnion Typesは役立ってくれるでしょう。

// PHP: str_replace - Manualから引用
// @see https://www.php.net/manual/ja/function.str-replace.php
// str_replaceの第一引数はarray, stringを使える。
<?php
// <body text='black'> となります
$bodytag = str_replace("%body%", "black", "<body text='%body%'>");

// Hll Wrld f PHP となります
$vowels = array("a", "e", "i", "o", "u", "A", "E", "I", "O", "U");
$onlyconsonants = str_replace($vowels, "", "Hello World of PHP");

// You should eat pizza, beer, and ice cream every day となります
$phrase  = "You should eat fruits, vegetables, and fiber every day.";
$healthy = array("fruits", "vegetables", "fiber");
$yummy   = array("pizza", "beer", "ice cream");

$newphrase = str_replace($healthy, $yummy, $phrase);

// 2 となります
$str = str_replace("ll", "", "good golly miss molly!", $count);
echo $count;
?>
著者:杉浦

【GNSS】GNSS受信機モジュールF9Pをソフトウェア的に壊した際の修理方法

ZED-F9Pモジュール | u-blox
 F9Pは高精度測位が可能なGNSS受信機モジュールのひとつです。ボードにもよりますが電子工作が容易になる状態まで作られた既製品は大体2-3万円強と決して安くない値段をしており、壊れた場合に買い直しより修理を試みたくなります。最近よくF9Pを壊しているのでファームウェアを安全な状態まで持っていくやり方をまとめます。
 フローチャートは次の図の通りです。各ノードにおける詳細な作業を後述します。

問題が起きていることを確認

直す必要があるのかどうか確認します。自分はu-centerからの設定変更を受け付けるか否かで判断しています。よくある異常な状態は次のようなメッセージを出力し続け設定変更に応じない、というものです。他にもレジスタ回りの致命的エラーはまずファームウェアのリセットが必要になるでしょう。

$GNTXT,01,01,01,ldr no pld buf*02
$GNTXT,01,01,01,exception 0x00130905 has occurred*20
$GNTXT,01,01,01,NMEA unknown msg*46

この時、$GNTXT内もきっちり読んでおくとお得な時が多いです。

$GNTXT,01,01,01,Reboot reason: V_IO supply undervoltage*59

の様なソフトウェア上では解決できない回路構成上のエラーも教えてくれる時があります。

USBで接続できる?

 文字通りです。シリアルポートに接続できるかできないかです。u-centerが特にわかりやすいです。デバイスとして認められるが接続できない、という状態です。接続できれば問題の解決はすぐです。

 U Center Port Connection Errorより引用

UART1で接続できる?

 USB側で接続できない場合、UART1でF9Pと通信することを試みます。経験則ですがUART1はかなり頑強でUSBより信頼できます。余談ですがF9PのUART2は通信こそできますが操作命令のプロトコルに対応していません。測位結果を得られるのみです。
 ボードによってはUART1でPC上のu-centerとボード上のF9Pをつなぐために新たに回路を構築する必要があります。この時USB-シリアル変換モジュールを使うと楽です。ボード上のTX, RXとUSB-シリアル変換モジュールのRX, TXを接続(この手のことをやるのが稀な人は一方のTXともう一方のRX、一方のRXともう一方のTXで繋ぐ必要があることに注意)、電源はUSB経由で供給すると過剰にも不足にもなり難いです。

ファームウェアアップデートを実行して成功しそう?

 大体この段階で正常動作ができる様になります。
 この手順ではu-centerの配布しているファームウェアをF9Pにインストールすることによって正常な状態にしようと試みます。ファームウェアは次のリンクのファームウェアのアップデートからダウンロードできます。
ZED-F9Pモジュール | u-blox#ドキュメントと資料
 ファームウェアの更新はu-centerのTools->Firmware Updateから実行できます。Update画面左下にあるGoボタンを押した後に画像の様な進捗状況やら何やらが出ていれば成功です。この時、Enter safeboot before updateとSend training sequenceにチェックをしておくと失敗しにくいです。
 Use this baudrate for updateの値は大きくする程、処理が早くなり体感失敗しやすくなります。進捗状況が出ていれば大体大丈夫です。再現性のある失敗の仕方をしていない限り、リトライし続ければそのうち成功します。

 残念ながら進捗状況が見えない場合、安定して失敗する場合は手動でセーフブートを実行する必要があります。

手動でセーフブートを実行

 UART1を通して特定の信号を送ることでセーフブートを実行させます。UART1にbaudrate9600で0x55 0x55を送ればOKです。自分の場合、UART1とシリアルを変換してRealtermからシリアル経由で送信することが多いです。

ZED-F9P – Integration Manualの3.3.6にセーフブートを実行する正式な方法が載っています。自分の場合なんやかんや成功するのでしていませんが正式にはSAFEBOOTピンをlowにしてから0x55 0x55を送信します。

著者:杉浦

いろんな言語のwtf 〇〇

 wtfはwhat the fuckの略です。意味は「何やってんだこいつ」みたいなものです。英語圏のユーザの多いカジュアルなコミュニティだとしばしばF言葉と共に飛び交うイディオムです。
 GitHubやGoogleでwtfと特定のプログラミング関連のモノを組み合わせて検索をすると大体、罠の様な一見不思議な仕様のいろいろが見えます。特に型を明示しなくても動作する言語のwtfはいいものが揃っています。
 GitHubのwtfpythonなんかは何故そうなるかの説明も詳しく載っていて為になります。
 satwikkansal/wtfpython: A collection of surprising Python snippets and lesser-known features.

999999999999999; // -> 999999999999999
9999999999999999; // -> 10000000000000000

10000000000000000; // -> 10000000000000000
10000000000000000 + 1; // -> 10000000000000000
10000000000000000 + 1.1; // -> 10000000000000002

の様な壊す気満々のコードのみならず

1 < 2 < 3; // -> true
3 > 2 > 1; // -> false

の様な思わずやってしまうコードもそこそこあります。

著者:杉浦

【Vue.js】定義を外から注入することでコンポーネントのコードを減らす

 Vue.jsはJavaScriptのフレームワークでページを部品単位で切り分けて定義することが得意です。一方、何かしらのモデル定義を作ったり、Vue.js用状態管理ツールVuexの定義する状態ストアの様にVue.jsの定義するコンポーネントの外に集約が存在するコードを書くこともあります。後者のパターンに入りながらもコンポーネントに囚われていると共通化すべき部分を個々のコンポーネントに重複して記述してしまう場合が出てきます。この記事ではそういった外部で共通化されたコードを注入する方法を紹介します。
 コードは次です。

// AppConfigStore.ts
/** 状態定義を記述したコードを省略 **/
export const lineColor = {
    // 簡素なsetter, getterを持つObjectを定義。このstoreに密に関わる部分のためstoreの役割にも合っている。
    /**
     * @return {number}
     */
    get() {
        return store.state.AppConfigStore.lineColor;
    },
    /**
     * @param {string} newColor
     */
    async set(newColor: string) {
        await store.dispatch('AppConfigStore/setLineColor', newColor);
    },
};
// Hoge.vue
import {lineColor} from '@/store/MapStore';
import Vue from 'vue';

Vue.extend({
    computed: {
        lineColor: lineColor, // importから読み込んだsetter,getterをあてはめ
    }
});

 コンポーネント外に定義を書いてコンポーネント内でimportするのみです。例ではcomputedですがpropsなど他にも色々使えます。注意点はコンポーネントを指すthisを外に持ち出そうとしないことです。これは難解になってミスが起きやすい上、外部コードに責務外のことまで任せることになりがちだからです。