Mirai Translate TECH BLOG

株式会社みらい翻訳のテックブログ

ナイスなESLintカスタムルール集

f:id:mt_nile:20210909165515p:plain

こんにちは。みらい翻訳フロントエンドエンジニアのWillと申します。

今回は、公開されているESLintのカスタムルールを集めて、個人的に有用そうだ、面白そうだ、と思ったカスタムルールを紹介します。

@shopify/eslint-pluginより

eコマースプラットフォームを提供している、Shopifyが公開しているESLintの設定に含まれているルールから見ていきます。

jsx-no-hardcoded-content

JSXで文字列を直接ハードコーディングすることを禁止するルールです。

多言語表示対応するため、i18nライブラリを介してテキストを表示することが必須であるプロジェクトで、うっかりハードコードしていないか検出したいときに有用です。

// 以下はNG
<div>Content</div>
<MyComponent>{someContent()}{` and more content`}</MyComponent>

prefer-early-return

早期リターンで書ける場合を検出します。ネストが1段減らせるため、コールドリーディング時の負荷を減らすことに繋がるかもしれません。

// NG
function foo() {
  if (a) {
    b();
    c();
  }
}
// OK
function foo() {
  if (!a) { return; }

  b();
  c();
}

prefer-module-scope-constants

スクリーミングスネークケース(DEFAULT_VALUEのような大文字のスネークケース)は、constによる宣言かつ、モジュールスコープしか許さないというルールです。

// NG
let DEFAULT_VALUE = 0;
// OK
const DEFAULT_VALUE = 0;

// NG
function myFunction() {
  const OTHER_VALUE = false;
}

react-hooks-strict-return

カスタムフックの戻り値がタプルである場合、その個数を2個までに制限するルールです。2個以上を返却したい場合は、キー名があるオブジェクトに入れることを強制することができます。

// NG
function useFoo() {
  const bar = 'bar';
  const baz = 'baz';
  const qux = 'qux'
  return [bar, baz, qux];
}

// OK
function useFoo() {
  const bar = 'bar';
  const baz = 'baz';
  const qux = 'qux';
  return {
    bar,
    baz,
    qux,
  };
}

eslint-plugin-unicornより

次に、eslint-plugin-unicornに収録されているルールを見ていきます。

better-regex

正規表現キャラクタークラスに置換できる表現を探してくれます。

// before fix
const regex = /[0-9]/;

// after fix
const regex = /\d/;

no-unsafe-regex

ReDoSが発生する可能性のある正規表現を検出します。

検出用のライブラリとしてsubstack/safe-regexが使われているようです。

// NG
const foo = /(x+x+)+y/;

filename-case

Lint対象になっているファイル自体の名前のケーススタイルを強制するルールです。

こういったファイル名に関するルールは手動レビューに頼りがちで、いつのまにかいろんなケースで書かれたファイル名が散乱しがちと思います。このルールでLintによる機械的な縛りが出来るのはGOODですね。

number-literal-case

数値リテラルの16進数表記で出るラテン文字のケースを揃えたり、指数を表すeのケースを揃えてくれます。(fix対応)

// before fix
const foo = 0Xff;
const foo = 2E+5;

// after fix
const foo = 0xFF;
const foo = 2e+5;

numeric-separators-style

ES2021でリリースされたNumeric Separatorsを3桁区切りで自動挿入してくれます。

// before fix
const foo = 1000000;
// after fix
const foo = 1_000_000;

prefer-array-〇〇系

比較的新しいメソッドである、find() flat() some()等でシンプルに書ける場合に教えてくれます。

// NG
const item = array.filter(x => isUnicorn(x))[0];
// OK
const item = array.find(x => isUnicorn(x));

// NG
const foo = array.reduce((a, b) => a.concat(b), []);
// OK
const foo = array.flat();

// NG
const hasUnicorn = array.filter(element => isUnicorn(element)).length > 0;
// OK
const hasUnicorn = array.some(element => isUnicorn(element));

prefer-includes

対象の存在自体を確認したいだけの場合、比較的新しいメソッドであるincludes()が適しています。indexOf()some()を利用した存在チェックを行っている場合、教えてくれます。

// NG
str.indexOf('foo') > -1;
// OK
str.includes('foo');

prefer-switch

if-elseによる"複雑な"条件分岐を、switchで書き換え可能な場合に教えてくれます。

デフォルトでは、条件が2ケース以下の場合は無視されます。

// NG
if (foo === 1) {
} else if (foo === 2) {
} else if (foo === 3) {
} else {
}

// OK
switch (foo) {
    case 1: {
        break;
    }
    case 2: {
        break;
    }
    case 3: {
        break;
    }
    default: {
    }
}

prevent-abbreviations

abbreviations(=略語)の使用を禁止します。慣例的にerroreventeや、buttonbtnと訳すことが多いですが、それらの略語を使用している場合に検出します。

略語を使用していた場合、デフォルトではこの辞書に従って正しい単語に展開されます。()

// NG
const val = 0;
const elem = document.querySelector('#main')
// OK
const value = 0;
const element = document.querySelector('#main')

eslint-plugin-sonarjsより

次に、SonarQubeなどのコード品質管理ツールを出しているSonarSourceが公開しているルールを見ていきます。

cognitive-complexity

Cognitive Complexity(認知的複雑性)を計測出来るルールです。

よく似た指標として、Cyclomatic Complexity(循環的複雑度)がありますが、Cognitive Complexityは、より人間の認知に近い感覚で複雑さを数値として表すことが出来るようです。

  • ちなみに、Cyclomatic ComplexityはESLint標準のcomplexityルールで計測することができます。

このルールを適用することで、一定以上のCognitive Complexityがあるコードを検出した場合、警告を出すことが出来ます。リファクタリングを行うべき箇所を見つけ出すのに役立ちますね。

no-duplicate-string

内容が重複した文字列リテラルを検出します。デフォルトでは3以上の同一内容の文字列リテラルがあれば警告します。

// NG
showAlert('Mirai Translator');
...
showToast('Mirai Translator');
...
showMessage('Mirai Translator');

// OK
const BRAND_NAME = 'Mirai Translator'
...
showAlert(BRAND_NAME);
...
showToast(BRAND_NAME);
...
showMessage(BRAND_NAME);

no-duplicated-branches

switchcase節またはif-elseによるチェーンの各節において、コードの重複があれば警告します。

// NG
if (foo < 3) { // ここと
  a();
  b();
  c();
} else (foo >= 3 && bar === 0) {
  a();
} else (bar === 1) { // ここは同じ
  a();
  b();
  c();
} else {
  b();
}

// OK
if (foo < 3 || bar === 1) {
  a();
  b();
  c();
} else (foo >= 3 && bar === 0) {
  a();
} else {
  b();
}

prefer-immediate-return

即座にreturnする場合、変数に格納することを禁止します。

// NG
function fetchSomething() {
  const responseFromServer = api.get({foo: 'bar'})
  return responseFromServer
}

// OK
function fetchSomething() {
  return api.get({foo: 'bar'})
}

ちなみに、ルールの説明によると、修正前のプラクティスを「説明変数として機能し、可読性を高める効果がある」と解釈するのではなく、メソッド名にて何を返却するのか明示するのが良いプラクティスだ、と書かれています。

prefer-single-boolean-return

if-elseによりBooleanリテラルreturnするコードを書いた時、単に式を返すように警告します。

// NG
if (expression) {
  return true;
} else {
  return false;
}
// OK
return expression;

おわりに

様々なルールを見てきましが、いかがだったでしょうか。今回紹介しきれなかったルールも多数あります。興味がある方は各リポジトリよりご参照ください。

ESLintに標準搭載されているルールも有用ですが、上記で紹介したようなカスタムルールを導入することで、各開発者がより可読性の高く、安全なプログラムを書ける上、コードレビュー時の負担軽減にも繋がります。

また、これらのルールはコードを書く上でのエッセンス・ベストプラクティスが詰まっており、Lintによる指摘を通じて自身のスキルの向上に役立てることができます。

チームでプロジェクトに導入する・しないを検討するのも良いですが、まずローカルにインストールして個人で試してみるのもおすすめです。

それでは、また次の記事でお会いしましょう。

みらい翻訳では、フロントエンドエンジニアを募集しています!

ESLint等の静的解析ツールを活用した、機械翻訳サービスのフロントエンド開発に興味がある方を探しています。

ご興味のある方は、ぜひ下記リンクよりご応募・お問い合わせをお待ちしております。(フロントエンドエンジニア以外も絶賛募集中です)

miraitranslate.com

みらい翻訳 VPoEのお仕事紹介 〜2021夏〜

こんにちは。みらい翻訳のプラットフォーム部 VPoEのSatieこと里山です。

f:id:satie-mirai:20210825005431j:plain

エリック・サティ

みらい翻訳では、ニックネーム文化がありCEOや上司に対してもニックネームで敬称や役職名を付けずに呼び合うようにしています。「誰が言ったかよりも何を言ったか」を大事にしているのでこのような文化があるわけです。

さて、今回はテックブログ開設にあたり今後記事を投稿することもあると思いますが、そのときに、「おまえ誰やねん?」と思われる方もいらっしゃると思いまして、私が何をやっている人か、VPoEとして何をやってきたのかというのをブログ初投稿とさせて頂きたいと思います。「なんや、誰が言ったかを気にしているのか?」と思われた方、素晴らしいクリティカルシンキングをお持ちですね。是非、私と面談しましょう!

 

f:id:satie-mirai:20210831102556j:plain

もともとはエンジニアです

さて、現在VPoEを拝命している私ですが、もともとはエンジニアです(今でも心はエンジニアです)、それも、寝落ちするまでモデリングしているような生粋のエンジニアでした。そんな生粋のエンジニアが、みらい翻訳というベンチャー会社とどうやって接点をもったかですが、2007年というGoogle音声検索が世に出るか出ないかくらい前から10年以上、音声認識エンジンや音声認識システム開発にジョインしていたところから始まります。音声認識システムでは設計全般、プロトコル仕様策定も行い、「あれ、俺」と言えるくらいに貢献したのかなというのと、その開発でとてもいい出会いに恵まれた結果です。そして人づてに、みらい翻訳の現CEOのdannyと出会い、明け方まで機械翻訳の未来について熱い思いを聞き、2017年8月にみらい翻訳にジョインすることになったのです。

 

f:id:satie-mirai:20210825004945j:plain

VPoEって何?

VPoEって役職はVice President of Engineeringの略でして、エンジニア組織が作り出す成果の価値を最大限にするのがミッションだと私は理解しています。より具体的な役割は、組織によって多少の違いはあると思いますが、概ねエンジニア組織(開発チーム)の開発プロセスの改善やチームビルド・採用、人事評価、技術方針の承認、会社の目標を開発チーム全体の目標へのブレイクダウンするなどだと思います。

2019年6月からVPoEを担っている訳ですが、私が統括しているみらい翻訳のMirai Translator®の開発チームにはVPoEはそれまで存在していませんでした。なぜなら、いわゆる0→1フェーズというプロダクトが売れるかどうか分からないときには、とにかくプロダクトを作ってユーザーに刺さりそうことを開発して出すことが最優先!なのです。

そして現在、より効率的な開発プロセスや、よりスケールできる開発チームは、1→10に向かうフェーズでは必要条件ですので、当然そのことをメインで考えるVPoEが必要になったのですね。

 

VPoEとして何をやってきて、何をしているのか

私がVPoEになって最初に手を付けたのがDevOpsの推進のためのSREチーム作りです。

エンジニアリングマネージャー(EM)のchikaデブサミ2021 Summerでお話したように、当時は安全サイドに倒した堅いデプロイなどの運用手順でした。ただし立ち上がったばかりの機械翻訳マーケットで何がユーザーに刺さって行くかは不透明の中、開発の価値提供が遅い事は大きな課題であるという認識でした。そこから約2年、まだCI/CDの仕組みやToil削減などタスクは山盛りですが、SREチームのメンバーを中心に開発チーム全体にDevOpsのマインドは育まれつつあります。

そして次に取り組んだのが、アーキテクチャの見直しです。2016年9月 Googleが深層学習を用いて機械翻訳の精度を大幅に向上させたGoogle翻訳を世に出しました。当社でもその衝撃は大きく急いで2018年1月に正式サービスインさせました。その背景と私たちの予想を遙かに超えるユーザー数の増加、これにより技術負債が開発コストの押し上げるという課題が顕在化することが想定されました。ただ、ここはとても難しいのですが、すでに日本のドーム球場のいくつかを満員にするほどの登録ユーザーがいる中でアーキテクチャを刷新というのはリスクとコストが大きすぎますので、ストラングラー(フィグ)パターン(※Martin Fowlerの投稿を是非弊社のお試し翻訳でどうぞ!)で徐々に置き換えるという戦略でマーケットの要求に柔軟に対応できるプロダクトを目指しています。

さらに最近はQAチームの価値を上げる取り組みもしています。特にGoogleのセキュリティのシフトレフトのドキュメントの考え方を品質全体に拡張して、QAチームのエンジニアをAutometerから一歩先にすすめるために模索をしています。

他には、DevOpsからスタートさせた開発スタイルをBizDevOpsの一つの実装のあり方であるフルサイクルエンジニアリングの考えを取り入れて開発をより自律的に進められないか考え、トライし始めています。

長くなりましたが、これらが現在のVPoEとして開発チームに価値を最大化するために私が主に取り組んでいるものになります。

 

 私のみらい翻訳との出会いと同じように、エンジニアとして「あれ、俺」があると評価を表現しやすいので、是非ジョインしているエンジニアには「みらい翻訳の?あれ、俺」と言えるプロダクトに仕立てていきたいなと考えています。そのために私一人が考えるだけでは残念ながら力不足なので、チーム全体で考えていける体制にしていきます。

 

codezine.jp

miraitranslate.com

最後に

さて、みらい翻訳に興味もたれた方はカジュアル面談もオープンにしているので、Meetyか弊社の採用サイトからご連絡ください。meety.net

miraitranslate.com

おまけ

ちなみにSatieと名乗っていますが、クラシック音楽には全く縁がありません。全くの語感でニックネームを付けました。ニックネームは自己申告制ですが、2週間ほどで慣れます(CEO談)。唯一のデメリットは、カレンダーで会議招集するときのメールアドレス入力時に本名が出てこずに苦労するくらいですかね。

 

みらい翻訳、テックブログはじめました。

はじめまして。みらい翻訳でエンジニアリングマネージャーをやっています nile(@mt_nile)です。(みらい翻訳にはニックネーム文化があり、社内でもnileと呼ばれています)

今回、みらい翻訳でも、テックブログを始めます。
みらい翻訳のエンジニアが交代で、技術のお話やエンジニア組織のお話について発信していきます!

みらい翻訳とは

株式会社みらい翻訳は、言語の壁を意識せず、誰もがいつでもどこでも誰とでも関わることができる、真に自由でグローバルな働き方を実現するために、Mirai Translator®︎を中心とした機械翻訳サービスを企業様向けに展開しています。
自社で翻訳エンジンを内製しており、エンジニア主体でテクノロジーファーストを志向しています。

テックブログを始めるまで

エンジニア主体の組織なので、テックブログのお話は以前からありましたが、継続できる体制の構築までは至っていませんでした。
ですが、AdventCalenderであったり、社内LT大会であったり、毎朝のLT(5分だけ勉強会)であったりと、社内で技術情報を発信・共有するような取り組みが活発になってきたことで、継続して更新できる見込みが立ってきましたので、始めてみようということになりました。

 

また、カジュアル面談や採用面接の前に、Wantedlyにエンジニアが投稿したストーリーを見てくださっている方も多く、会社としても、情報発信の機運が高まってきているというのも後押しになっています

 

なにを決めたの?

まずは、有志メンバーで「編集部」を立ち上げました。
そこで簡単な運用ルールを策定しました

  • ざっくりとした更新頻度
  • テーマはノンジャンルで何でもあり
  • NGルール(誹謗中傷や、他社比較などはNG)
  • 執筆は業務扱い

などです。

次に、プラットフォームの選定です。

  • Markdownで書けること
  • 構築・運用が容易であること
  • エンジニアの方にリーチしやすいか
  • いわゆる「ポエム」がOKなのか?

などの条件を検討しました。

これから

みらい翻訳には、機械翻訳技術のスペシャリストから、最新のWeb技術を追いかけるフロントエンドエンジニア、バックエンドエンジニア、さらにはSRE、QAエンジニア等、多様なエンジニアがいますので、まさにノンジャンルでいろんな記事がUPされると思います。一読者としても楽しみにしています。