カタベログ

IT技術に関するブログを書きたい.食べ物関連はInstagramをご参照の事.

ぼくのかんがえたさいきょうのVSCodeでのPython開発環境

序文

Pythonを初めて触ったのは筆者が19歳のとき……プログラミングに目覚め始めた頃、そのときに出会ったRubistの方への反骨精神で使い始めました。 あれから月日が流れ、結婚、出産、育児、マイホーム・マイカー購入といった人生一大イベントたちをことごとく無視して生きてきて、遂にお仕事でPythonを本格的に使う日が来ました(やったー)。

筆者はWebアプリケーションエンジニアとしてはJavaScript/TypeScriptの経験が長いです(といっても2、3年ですが)。 その中でリンターやフォーマッターといった自動でいい感じのコードを書くための技術に触れ、それらのVSCodeでの設定の方法を学んできました。 そして今回Pythonを扱うとなって調べてみると、Pythonもその手のツールは当然のように存在しております。 そうなると、VSCodeに慣れ親しんだ筆者としては「VSCodeでJS/TSを書いていた時のような感覚でPythonを書きたい」と思うのが極めて自然ですよね。

ということで、自分がVSCodeに設定しているPython関連の設定内容と推奨拡張を記載しつつ、途中ちょっとハマったところもあったのでその事例を共有できたらなって思います。

なお、PyCharm使えばいいじゃんとかそういう意見は求めてません。悪しからず。

続きを読む

一部で話題のスリープソートを実装してみた

 きっかけ

実行結果

%  node SleepSort.js
Target:
[
   9.001279948037155,   7.814290804058153,
  5.6203515898400225,    8.88900237341443,
   6.284693239942214,   7.678417600633072,
  4.3539035833889645,  3.4782778608417475,
   0.631035744901749,   5.799741583572917,
  0.1913970742445037, 0.43133450479187374,
  5.9727079749091345,  0.7017940380951004,
   4.175168145227373,  3.9140154382038905,
  0.7652450971294433,   9.143441457849157,
  2.7689060541041854,   8.731233419192447
]
Result:
[
  0.1913970742445037, 0.43133450479187374,
   0.631035744901749,  0.7017940380951004,
  0.7652450971294433,  2.7689060541041854,
  3.4782778608417475,  3.9140154382038905,
   4.175168145227373,  4.3539035833889645,
  5.6203515898400225,   5.799741583572917,
  5.9727079749091345,   6.284693239942214,
   7.678417600633072,   7.814290804058153,
   8.731233419192447,    8.88900237341443,
   9.001279948037155,   9.143441457849157
]

実装

TimerといえばsetTimeoutでお馴染みのJavaScriptですよね。 ということで、最近Promise版のsetTimeoutの話もよく見かけるのでJavaScriptで書きました。

const { setTimeout } = require("timers/promises");
​
const sleepSort = async (numberList) => {
  const sortedList = [];
  const appendList = (element) => {
    sortedList.push(element);
  };
​
  const timerList = numberList.map(async (element) => {
    return setTimeout(element * 1000, element).then(() => {
      appendList(element);
    });
  });
​
  await Promise.all(timerList).catch((error) => {
    console.error(error);
  });
​
  return sortedList;
};
​
const main = () => {
  const length = 20;
  const offset = 10;
​
  const target = Array(length)
    .fill(offset)
    .map((element) => {
      return Math.random() * element;
    });
  console.log("Target:");
  console.log(target);
​
  sleepSort(target).then((result) => {
    console.log("Result:");
    console.log(result);
  });
};
​
main()

Next.jsのAPI RoutesでOpenAPIを使ってIF定義を作り、その定義をAspidaで使って型安全にAPIを使う

背景

NextJSを使う機会に恵まれました。

仕事で1からフロントエンドとバックエンドの技術選定ができるチャンスが到来しました。これまでVue 2.xをゴリゴリ触る機会があったものの、誰かが作ったもののエンハンスやメンテナンスばかりだったので、Next.jsやNuxt.jsといったパワフルかつフロントエンドとバックエンド両方を(やろうと思えば)対応できるフレームワークを使おうと決心しました。モノレポの真似事ができるし。Nuxt.jsを使うなら3系を使いたかったですが、まだベータ版なので本番利用は憚られます。そのため、Next.jsを選ぶに至りました。

ベースはNext.jsにするとして一つ気になることがありました。

作って終わりではなく長く運用されていくものなので、インターフェース(以下IF)資料と実装が1対1になるOpenAPIを使いたいです。複雑なIFではないのでOpenAPIで作成しても支障はなさそうでした。Next.jsのAPI Routesは、connect形式やExpress形式のmiddlewareであれば利用できるとありました。それに合致するOpenAPIのmiddlewareはどうやらexpress-openapi-validatorのようでした。でも、API Routes with express-openapi-validatorな実装記事はどこにも見つかりませんでした。

ただ、お客様が触るシステムである以上、作って終わりな実装をするのはエンジニアとして許せないので、とにかくAPI Routes with OpenAPIを実現しようとなりました。

TL;DR

  • express-openapi-validateを用いることでAPI RoutesでもOpenAPIを使ったバリデーションを行えることが分かった
  • どうしてもAPI Routesだと共通処理の実装が難しく複雑になりがちだと分かった
    • 簡単かつ短いコードでAPIを実装できるメリットの裏返しなので一長一短
    • API実装規模に応じてAPI Routesを使うか否かは判断すべきだというのがよく分かった
  • Aspidaを使うことでフロントのAPIリクエストに型の恩恵を受けることができるのは開発体験が良いことが実感できた
    • VSCodeを使って開発した結果ではあるが、おそらくWebStromでも同じ体験ができることだろう

謝辞

本件実装にあたり、短納期ながら他業務の合間を縫って技術検証とサンプルおよび本実装までしてくださったSさん、ありがとうございました。

続きを読む

ViteをVue2のプロジェクトに入れてみた

背景

2021年末、関係者たちが次々冬休みに入る中、年長者なのでしんがりを買って出た。 一部コミュニケーションのミスもあったりで、結果としては1日2日多く休めたはずだった。 打ち合わせもなければメンバからの相談事もPRレビューもなく、かといって面倒臭い仕事もやる気もしない。 そんな気分の折、メンバの一人がTypeScriptでツールを作成していたことに触発されて、1日つかって新しい技術を組み込んでみようと思い立ったのであった。

モチベーション

  • ローカルビルドやHMRの時間を短縮して開発効率を上げる
    • Vue2のままViteを導入する
    • テストがないのでVite関連では極力コードに手を入れない

ちなみにViteが何かは日本語ドキュメントもあるので以下をチェック。

ja.vitejs.dev

  • 背景
  • モチベーション
  • やり方
    • 詰まったところ
      • ただのViteは入れられない
      • node_modulesの外から組み込んでるライブラリが読み込めない
      • veturとの連携によってエラーやらサジェスチョンやら出る
      • pluginの仕組み上、生成されるコンフィグがviteの全てのコンフィグを使えるようになっていない
      • モジュールは全てES Module(ESM)にしないと動かない
      • 本番ビルドにVue2向けプラグインは対応していない
      • 環境変数読み込みの違いのせいでvue-cliによるビルドが失敗する
  • 結果として早くなったのか?
続きを読む

Prismaを使ってみて分かった事と、ここ最近感じたプロジェクト開発での教訓的なもの

備忘録的な側面が多分にある。 みんなが興味ありそうなPrismaの話は頭に持ってきたので、それだけ読んで閉じてもらってもいいと思う。

  • HerokuとPrismaの相性があまり良くない
    • publicスキーマしか実質使えない
    • Heroku Connectとの相性が悪い
  • テスト
    • コントローラのテストをするならサービスはモック化した方が良い
    • DBを繋いだ単体テストにおいてはテストデータの管理がとても重要
    • テストコードがある安心感
  • 設計
    • 新しい技術を使うのはほどほどに
    • 「共通部品は必要になったら都度作ろう」
  • プロジェクト運営
    • 少人数開発でもコミュニケーション不足は容易く起きる

HerokuとPrismaの相性があまり良くない

publicスキーマしか実質使えない

HerokuでDBを扱うとなると、Add-onでHeroku Postgresを使うことになる。 Heroku Postgresをアプリに追加すると、環境変数にDATABASE_URLが追加される。 schema.prismaにenv(DATABASE_URL)と記載すると、publicスキーマに対して定義が可能になる。 ここでDBにスキーマを新たに切ったとしたとき、環境変数と文字列を結合した文字列をenv()の引数に渡したい。 だが現状、引数に当たる箇所で演算はできない。

Heroku Connectとの相性が悪い

Heroku ConnectでSalesforceと繋いだ時にSalesforceスキーマが作成される。 Salesforce上の(カスタム)オブジェクトをHeroku Postgresに同期させる事ができる。 つまり、SalesforceスキーマにあるテーブルはSalesforce上で管理される。 Prismaで管理するテーブルとSalesforceで管理するテーブルがあり、そして(当然)プログラムからはその両方を扱わねばならない。 だがローカル環境で試験を行うにはローカルDBにSalesforceで管理するテーブルがないと試験できないので、Prismaスキーマは作らないといけない。 Salesforceスキーマだけは必ず二重管理になってしまうので相性が悪いと思う。

続きを読む

zshでPROMPTを変更する設定を書く場合の注意点

zsh使ってて、カラフルな方が良いのでcolorsを入れたり、Gitも使うのでvcs_info入れたりしていた。 結構前に設定していたんだけども、vcs_infoの設定内容が反映されない、というか表示されていなかった。 面倒くさいし、所詮は見栄えの話だからとほっておいたんだけども、zshの設定をいじる瞬間が生まれたので直すことにした。

結論、設定内容自体は間違えていなかったのだけども、設定を書いている場所の問題でした。 zprofileに全ての設定を書いていたんですが、これが悪かった。 zshの設定読み込み順番のPROMPTの設定をしても読み込み順番的に早すぎる模様。 RPROMPTは正常に読み込めていたので疑っていなかった…。 zshrcを用意して、そちらにPROMPTの設定変更関連を移設して見たら正常に設定されました。

ソースはこちら。

github.com