N2i のデザイナー幸地さんにインタビュー!!

N2i のデザイナー幸地さんにインタビュー!!
N2i のデザイナー幸地さんにインタビュー!!

Designer illustrations by Storyset

こんにちは、N2i Tech Blog 編集長の和田です。 定期的に開催している N2i の社員へのインタビュー企画の記念すべき第4回目です🙌

今回はデザイナーとして開発チームを支えている幸地さんに話を伺いたいと思います。
前回のインタビュー記事を読まれていない方は、下記からぜひお読み下さい。

techlog.n2i.jp

これまでの経歴

-- 幸地さんはご出身が沖縄と聞いています。どのような経緯で名古屋に来られたのでしょうか?

高校卒業後はデザイナーを志望していました。
デザインを学べる場所を探していた時に「デザイナー」と検索して上位に表示されていたのが、名古屋のデザイナー専門学校だったんですよね。 特に深い理由があるわけではないのですが、デザイナーとして学びを得るために名古屋にやってきました。

学校卒業後、デザイナーとして働いていくうちに N2i でお仕事することになりました。


-- そうだったんですね。職種としてデザイナーを選択されたのには理由があったんですか?

当時は若かったこともあり、キャリアについては深く考えてなかったかもしれないです笑
たまに絵を書くこともあったり、Web サイトを自分で作ってみて楽しかった思い出があるので、そのような経験からデザイナーを選択したのかもしれないですね。

N2i の中では HTML と CSS に誰よりも詳しいという自信があります。


-- いやぁ、デザインに関する打ち合わせのときにいつもスタイルの知識をご教授頂いてます🙏

-- ここからはデザイナーとしてのお仕事自体について質問させていただきます!

デザイナーのお仕事について

-- 個人開発でフロントエンドを作る際にデザインで行き詰まる人も多いと思います。デザイン力をアップするにはどうしたらいいでしょうか?

いろんな方法があるとは思いますが、僕の個人的な意見としては「とりあえず作る」しかないと思いますね。
今はたくさんデザインのフレームワークがでているので、それらを利用してみるのがいいと思います。少し古いかもしれませんが Bootstrap などは有名ですよね。

本を読んで知識をつけるのも良いですが、デザインもプログラミングと同じで自分で手を動かさないことには始まらないです!


その通りですよね。ちなみに幸地さんはデザインのヒントとして、参考にしているものはありますか?

今はアプリケーションのデザインを担当させていただくことが多いので、既存のデザインをベースに進めることが多いですね。 新しくデザインを考えないといけないときは、Pinterest などのサイトを見て着想を得ることはあります。


-- 様々なデザインに触れる機会が多いと思うんですけど、最近のデザインの流行りなんかがあれば教えていただきたいです!

ここ数年で増えてきたと感じるのは、ジャンプ率の高いデザインが多くなってきたような気がしますね。
ジャンプ率とはデザインの緩急を表す言葉で、見出しと本文の文字サイズやフォントなど、比較する文字の見た目に差が大きいと「ジャンプ率が高い」といいます。
反対に見出しと本文に見た目の差があまりないようなものを「ジャンプ率が低い」といいます。


-- 言われてみれば普段、自分が見るサイトにジャンプ率が高めのデザインが多いです👀

-- デザイナーとしての仕事術をお聞きしたいです。デザインを作成する上で、オススメの仕事術だったりTipsはありますか?

デザインに限らずですが、ショートカットキーを覚えることは仕事を速くする必須項目だと思ってます。 あとは、Karabiner-Elements などのキーボードカスタマイズツールを使って自分の使いやすいキー配列に工夫することですね。

僕の場合は、Mac⌘X でデザインの切り取りを行うことが多いので Caps LockX に変更してます。
個人的にはこの配置で切り取り操作がかなり便利になりました。

自分の仕事で頻繁に行う操作をカスタマイズツールを使ってやりやすくするのはオススメですよ。


-- エンジニアと共通するところがたくさん見つかって嬉しいです🙌

-- 幸地さんはエンジニアと仕事する中で、ここはやりやすい・やりにくいと感じることはありますか?

エンジニアの方は「できる・できない」をハッキリと伝えてくれるのが、個人的にはありがたいですね。 デザインするだけではアプリケーションは作れないので、打ち合わせの中で実装上の都合は確認させていただきます。

あとはできるだけエンジニアの方にはピクセルパーフェクトを目指してほしいですね。
自分がデザインしたものを完璧に再現してくれていると嬉しく感じます。
ピクセルパーフェクトを求めるからには、デザイナー自身もコーディングの知識は持ってないといけないですね。


最後にデザイナーとしてこだわりを持ってることを教えてください!

やはり、「ユーザーストーリーに沿っているか?」という観点は大事にしています。
当たり前のことだと思うんですけど、どのようにユーザーが利用するか?といったストーリーが見えてこないとデザインは作れないです。


-- ユーザーストーリーってホント大事ですよね。何のために作るのかが見えてこないとエンジニアとしてもやりずらさを感じます。
インタビューはここまでとなります。本日はありがとうございました!!

今回はデザイナーの幸地さんにインタビューさせていただきました。
筆者自身はエンジニアとして幸地さんと一緒に仕事をさせていただいているのですが、デザイナーの目線の考え方について理解を深められる良い機会となりました🙌

【Vue 入門】業務でよく使う動的 class の切り替え方

【Vue 入門】業務でよく使う動的 class の切り替え方
【Vue 入門】業務でよく使う動的 class の切り替え方

こんにちは、開発チームでエンジニアをしている和田です。

最近は Vue2 → Vue3 の移行作業に力を注ぐ毎日です🔥

作業中に Vue の <template /> タグで class を動的に切り替えるための記述方法を何種類も目にしたため、忘れないように一覧にまとめておこうと思いました。

ということで今回は Vue で class を動的に切り替える方法を一挙に解説させていただきます。

背景・目的

Vue で動的に class を切り替える方法について学ぶこと。

対象読者

Vue の初心者。Vue の知識を深めたい開発者。


Vue で動的に class を切り替える方法一覧

1. 真偽値による class の切り替え

<template>
  <component :class="{ 'dynamic-style': isActive }" />
</template>

簡単な真偽値のみでの class の切り替えです。
isActivetrue の場合は <component /> タグに dynamic-style class が付与されます。
isActivefalse の場合は <component /> タグには class は付与されません。

2. 条件式による class の切り替え

<template>
  <component :class="{ 'dynamic-style': counter > 10 }" />
</template>

条件式による class の切り替えです。
先程の isActive 変数を条件式 counter > 10 に置き換えただけですね。
counter の値が 10 より大きければ、dynamic-style class が付与され、10 以下であれば class は付与されません。

3. 複数の真偽値・条件式の組み合わせによる class の切り替え

<template>
  <component 
    :class="{
      'dynamic-style-a': isActive,
      'dynamic-style-b': isVisible,
      'dynamic-style-c': counter > 10,
      'dynamic-style-d': fruit === 'apple'
    }" 
  />
</template>

複数の真偽値や条件式との組み合わせです。
{} の中であれば , で区切ることでそれぞれ付与したい class ごとに条件を切り替えることができます。

4. 三項演算子による class の切り替え

<template>
  <component :class="isActive ? 'dynamic-style-a' : 'dynamic-style-b'" />
</template>

三項演算子を使って class の切り替えを行う場合はこのようになります。
isActivetrue であれば dynamic-style-a が付与され、false ならば dynamic-style-b が付与されますね。

5. 関数による class の切り替え

<template>
  <component :class="generateClass(staffRoleId)" />
</template>

<script setup>
const generateClass = roleId => {
  switch (roleId) {
    case 1:
      return 'dynamic-style-a'
    case 2:
      return 'dynamic-style-b'
    case 3:
      return 'dynamic-style-c'
    default:
      return;
  }
}
</script>

単純に文字列を返すだけの関数を作成すれば、その返値を class として付与することもできます。 <template /> タグ内に複雑な条件を記述したくない場合などに便利かもしれません。

6. 複数の真偽値・条件式・三項演算子・関数の組み合わせによる class の切り替え

<template>
  <component 
    class="static-style-a"
    :class="[
      { 'dynamic-style-a': isActive },
      { 'dynamic-style-b': isVisible },
      { 'dynamic-style-c': counter > 10 },
      { 'dynamic-style-d': fruit === 'apple' },
      isSelected ? 'dynamic-style-e' : 'dynamic-style-f',
      isDisabled ? 'dynamic-style-g' : 'dynamic-style-h',
      generateClass(staffRoleId),
      'static-style-b'
    ]" 
  />
</template>

<script setup>
const generateClass = roleId => {
  switch (roleId) {
    case 1:
      return 'dynamic-style-i'
    case 2:
      return 'dynamic-style-j'
    case 3:
      return 'dynamic-style-k'
    default:
      return;
  }
}
</script>

これまでの総集編のような記述方法です。
:class=[] のように [] で囲うことで、真偽値・条件式・三項演算子・関数のすべてを組み合わせて書くことができます。 三項演算子や関数は全体が {} で囲まれた場合だと一緒に使えないため、[] の中に書くことになります。

また、この書き方だと static-style-a のような静的な class も一緒に書けます。
ただし、:class ではなく普通の class にも静的 class は書けるためわざわざ :class の方に書く必要はないかもしれません。

[] を使った書き方であれば1~5 までの書き方に全て対応できるので、これさえ覚えておけば問題はないのですが、より簡潔なコードを書けるようになるためには 1~6 すべての書き方をいつでも書けるようにしたいですね。


まとめ

最後まで読んでくださりありがとうございました!
今回は Vue で動的に class を切り替える方法一覧を紹介させていただきました。
チーム開発では様々な人が携わる分、コードの書き方も人それぞれです。
今回紹介させていただいた記述方法は、実際に筆者が携わるプロダクトで全て登場するので、しっかりと覚えておきたいです。

業務で大活躍!VScode の拡張機能20選!!

業務で大活躍!VScode の拡張機能20選!!
業務で大活躍!VScode拡張機能20選!!

Technology illustrations by Storyset

こんにちは、開発チームでエンジニアをしている和田です。

先日、開発環境の整理整頓を行っている最中にふと

「そういえば、VScode拡張機能が増えすぎたな... 掃除するか... 🤔」

と思ったので、今回はそのついでに実際に業務中に活躍している VScode拡張機能を一覧にしてまとめてみようと思います。

この記事の中で読者の方のエンジニアライフに役立つような便利な開発ツールを見つけていただけると嬉しいです🙏

以前、役に立つ開発ツールを一覧にしてまとめたのでこちらの記事もぜひ読んでみて下さい🙇‍♂️

techlog.n2i.jp

Auto Close Tag

marketplace.visualstudio.com

筆者はフロントエンドの開発では Vue のプロジェクトをよく触ります。
自動で HTML の閉じタグを補完してくれるため、楽にコーディング作業が進められます👍

Auto Rename Tag

marketplace.visualstudio.com

同じく HTML タグの補完ツール。
タグの名称を変更する際に、対応する閉じタグの名称も変更してくれます。
間違いが少なくなるので超便利です。

Trailing Spaces

marketplace.visualstudio.com

不要な空白を赤く強調してくれます。
当然、不要な空白は無い方がいいので、コードをきれいに保つために役立ちます!

zenkaku

marketplace.visualstudio.com

思わぬ不具合を招く全角文字を白く強調してくれます。
zenkakuがあれば、全角文字列がうっかり混入するなんてことはなくなります。

Code Spell Checker

marketplace.visualstudio.com

英単語のスペルミスを教えてくれます。
「動かないと思ったらスペルミスしてた😅」なんていうお決まりのミスが軽減されるので重宝してます。

Prettier - Code formatter

marketplace.visualstudio.com

有名なコードフォーマッター。コレを入れてから改行云々で悩むことはありませんね。
チームでも導入必須のプラグインです!

ESLint

marketplace.visualstudio.com

ESLint の設定で非推奨な記述をしている箇所に警告を出してくれます。
バグの原因になるような危険な書き方を未然に防ぐことができます🙌

Color Highlight

marketplace.visualstudio.com

カラーコードが記述されている箇所に実際の色(パレット)を表示してくれます。
16進数を見るだけで色のわかる超人には不要かも😂

Edit csv

marketplace.visualstudio.com

VScode 上でエクセルライクに CSV の編集ができる優れもの。
スプレッドシートやエクセルを、わざわざ開かなくてもCSVをささっと編集できます。

Rainbow CSV

marketplace.visualstudio.com

CSV データを VScode で開いたときに、カラムごとに色分けしてくれます。
簡単な編集やデータの確認をする際に便利です!

Git Graph

marketplace.visualstudio.com

Git の変更履歴を GUI で確認できます。ブランチが可視化されるので見やすくてありがたいですね。

GitLens - Git supercharged

marketplace.visualstudio.com

コードにカーソルを重ねると「いつ誰がどんな変更をしたか?」が確認できる便利ものです。
「なんだこの〇〇コード!!って思ったら自分だ...」なんていう気づきを与えてくれます😇

Markdown All in One

marketplace.visualstudio.com

マークダウンでドキュメントを書くときに VScode 上だとマルチカーソルが使えて便利ですよね。
VScode の機能をそのままに GitHub に Issue を書く感覚でマークダウンが書けちゃいます🎉

markdownlint

marketplace.visualstudio.com

マークダウンのリンターです。
Markdown All in One と併用して便利にマークダウンが書けます。

Svg Preview

marketplace.visualstudio.com

SVG ファイルを見たときに「これどんな画像だっけ??」という疑問をその場で解消できます。
画像のプレビューを表示してくれるので、 SVG に悩まされるなんてことがなくなりました。

Postman

marketplace.visualstudio.com

VScode 上で Postman の操作ができます。
リクエスト・レスポンスの確認にわざわざアプリを開かなくて良くなるのはありがたいですね。

TODO Highlight

marketplace.visualstudio.com

TODO コメントなどをハイライトしてくれます。
ところで「いつかやるべき変更」ってコメントはいつやるんでしょうか?笑

Todo Tree

marketplace.visualstudio.com

TODO コメントをサイドバーから一覧で確認することができます。
こちらの拡張機能にもハイライト機能はありますが、筆者は TODO Highlight のハイライトの方が好みなので併用しています。

ENV

marketplace.visualstudio.com

味気ない env ファイルに色をつけてくれます。
どこまでが変数名でどこまでが値なのかわかりやすくなるので便利です。

YAML

marketplace.visualstudio.com

yaml ファイルを触るときに補完や改行のサポートをしてくれます。
docker-compose.yml の作成が捗りますね。


最後に

最後まで読んでいただき、ありがとうございました🙇‍♂️

いかがだったでしょうか?

今回、紹介した他にも開発に利用している VScode拡張機能はたくさんありますが、普段の業務で特に活躍しているものを厳選させていただきました!

皆さんのエンジニアライフのお役に立てれば幸いです。

【解説】テスト観点とテストケースの違いって何?

【解説】テスト観点とテストケースの違いって何?
【解説】テスト観点とテストケースの違いって何?

Technology illustrations by Storyset

こんにちは、開発チームでエンジニアをしている和田です。

最近は涼しくなってきましたね。読書の秋ということで積読状態の技術書を読み漁る毎日です🤓

今回は、前回のテストに関する解説記事の続編ということで、ソフトウェア開発に携わって間もない人向けにテスト観点とテストケースの違いについて解説します。

まだ前回の記事を読まれていない方はぜひ下記の URL からどうぞ🙇‍♂️

techlog.n2i.jp

記事執筆の背景

テスト観点とテストケースの違いについて解説を行う前に、そもそもこの記事を書くに至った背景について簡単に紹介させていただきます。

背景としては普段の開発のフローに対する理解を深めるためです。

N2i での基本的な開発フローについて

N2i では基本的に下記のフローで開発を行います。

  1. 要件定義
  2. テスト設計
  3. 実装
  4. テスト
  5. リリース

基本的には 1 ~ 4 番までの工程を EM や QA の力を借りつつ、エンジニアが担当するというフローです。4 のテストに関しては結合テストを担当します。

業務とは関係ないよい個人的な開発だったり、趣味レベルの開発をしていると、細かくテストを行うことはあまりないと思います。

N2i では品質保証の視点から、結合テストまでの領域はエンジニアが責任を持って開発を行うため、テストに関する理解が求められます。

【補足】結合テストとは

結合テストとは個々に開発されたモジュールやコンポーネントを組み合わせ、その結合部分が正しく動作するかを検証するテストのことです。

ショッピングサイトなどを例にすると...

  1. ショッピングカートに商品を追加する
  2. ショッピングカートを開く
  3. ショッピングカートに追加した商品一覧を表示する

このようなシナリオにおいて、ショッピングカート追加機能と商品一覧表示機能それぞれが正しく連携できているかを確認することが結合テストに当たります。

テスト設計とは?

先程の開発フローにおいて、テスト設計とはテスト観点を洗い出し、テストケースを作成することです。

「テスト観点?テストケース?なんだそれ??🙄」

という疑問を払拭すべく、それぞれの違いについても確認しながら見ていきましょう。


テスト観点とテストケース

まず、テスト観点とテストケースの違いについて述べる前にそれぞれの定義について確認していきます。

テスト観点とは?

一般的にテスト観点とは...

テストを行う際に確認すべき項目や焦点を示す指標のことを指します。
これは、要件や機能、非機能から派生するものであり、テストの方針や目的を明確にするためのもの。

として説明されます。なんだか難しいですね😅

先程のショッピングカートの例でいうと...

  • ショッピングカート追加機能
  • 商品一覧表示機能
  • 支払い機能

などのように「〇〇すると〇〇という結果になる」ということを考える前に「どのような場合でテストケースを作成すべきか?」 という土台となるのがテスト観点に当たります。

テストケースとは?

ではテストケースとは何でしょうか? テストケースとは...

特定のテスト観点を検証するための具体的な手順や条件をまとめたもの。
テストを実施するときの手順、期待結果、実際の結果などを含む。

このように説明されます。
すなわちテスト観点をさらに具体的に掘り下げて「〇〇すると〇〇という結果になる」まで書き出したのがテストケースということです。

同様にショッピングカートを例にすると...

  • ショッピングカート表示ボタンを押すと、追加した商品一覧が表示される
  • 商品追加ボタンを押下すると、ショッピングカートに商品が追加される
  • お支払いボタンを押下すると、支払い確認ページに遷移する

このあたりがテストケースに当たります。

テスト観点とテストケースの違いとは?

結論、テスト観点は「何を確認するか?」を示し、テストケースは「どのように確認するか?」を示します。 テスト観点がテストの方向性を示すのに対して、テストケースは具体的な検証の計画や実行内容を示すという点で異なるというわけです。


【まとめ】テスト観点は方向性、テストケースは具体的な実行内容

いかがでしたでしょうか?
テスト観点とテストケースそれぞれについて解説をさせていただき、その違いについて見てきました。

本文中で「どのような場合でテストケースを作成すべきか?」 という土台となるのがテスト観点であると述べたように、テスト観点なしではテストケースは考えられないわけです。

Rubyで簡単なCSVパーサーを作ってみる

こんにちは、開発メンバーの岡部です。
先日は社員総会で箱根に向かい、旅館の温泉でHPを全回復することができました。
子供の頃は旅行といえば、テーマパークなどが目当てだったのに、気づけば料理や温泉目当てになっていて歳をとったなぁ...と感じます。

突然ですが、最近は個人的にパーサーを実装するのにハマっています。
きっかけになったのはRui Ueyamaさんの低レイヤを知りたい人のためのCコンパイラ作成入門です。
内容については割愛しますが、簡単な演算しかコンパイルできなかったものが最終的に、馴染みのあるプログラムのコンパイルができるようになっていく過程を体験できるのでオススメです。
(完走したとは言ってない)

とはいえ、サクッとパーサー(もしくはコンパイラ)を作りたい人には、嬉しい悲鳴かなボリュームが多いかもしれません。 ただ、自分としてはぜひ皆さんにもこの体験をしてみてほしいので、今回は比較的簡単に実装できるCSVのパーサーを作っていきたいと思います。

CSVの形式の確認

パーサーを作るにあたって、最初にやるべきことはパース対象の形式を熟知することです。
まずはCSVRFCを確認して、どういった形式になるのかを確認してみます。

datatracker.ietf.org

今回は簡単のためDefinition of the CSV Formatを遵守せず、部分的に抜粋した形式を採用します。

  • 各行の最後にはCRLF(改行)を含む
  • 1行目: 必ずヘッダー情報を含む
  • 2行目: ヘッダーの項目数と同じ分だけ項目を持つ
  • 以降、繰り返し...
aaa,bbb,ccc CRLF(※改行)
ddd,eee,fff CRLF(※改行)
ggg,hhh,iii CRLF(※改行)

処理の流れについて

今回、実装するパーサーは2つのステップで構成します。

  • 字句解析: CSVファイルから1文字ずつ読み取り、トークン(構造体)に変換する
  • データ変換: トークンを二次元配列に変換する

多くのパーサー実装では字句解析の後に構文解析を行うことが多いです。
しかし、今回のCSV形式の場合、ただテキストが,区切りで登場するのみで構造が非常にシンプルなのでAST(抽象構文木)を生成するメリットがほとんどありません。なので、構文解析は行いません。

最終的にトークンはRubyの標準ライブラリcsvに則って二次元の配列に変換します。

# ファイルから一度に
p CSV.read("sample.csv")
# => [["Ruby", "1995"], ["Rust", "2010"]]

class CSV (Ruby 3.2 リファレンスマニュアル)

いざ実装

前提知識も紹介したところで、いよいよ実装に取り掛かっていきます。
まずは以下のプロジェクトを作成します。メインの処理はparser.rbに記述していきます。
開発をスムーズに行うために簡単なテストを実行可能なparser_test.rbを用意しました。Rspecを使っても良いですが、標準ライブラリのみで実装したいので、Rspecライクな記述が可能なように簡単な関数を定義してあります。

├── csv
│   └── simple.csv
├── parser.rb
└── parser_test.rb

csv/simple.csv

aaa,bbb,ccc
ddd,eee,fff
ggg,hhh,iii

parser_test.rb

# frozen_string_literal: true

require_relative 'parser'

def assert(result, expect)
  if result == expect
    [:pass, result, expect]
  else
    [:fail, result, expect]
  end
end

def it(label, &block)
  raise 'Block is required' unless block_given?

  status, result, expect = yield block
  if status == :pass
    puts "[OK] #{label}"
  else
    puts "[FAIL] #{label} (result=#{result}, expect=#{expect})"
  end
end

1. 字句解析(トークンへの変換)

ファイルから1文字ずつ読み取る

ファイルから1文字ずつ読み取るにはファイルクラスのインスタンスに対して.getcを呼び出すことで可能です。他にも1行ずつ読み込む.getsも用意されています。一度にファイル全体を読み込まないため、メモリに優しいのが嬉しいです。

f = File.open('csv/simple.csv', 'r')
puts f.getc # a
puts f.getc # a
puts f.getc # a
puts f.getc # ,
puts f.getc # b

.getcは何度も呼び出せますが、ファイルの最後まで読み取った後に呼び出すとnilが返ります。
つまり、読み込んだ情報がnilであるかを判定すれば、ファイルの最後まで読み取ったかどうかを判定することが可能ですが、すでにFileクラスに.eof?(end of file)たる便利なメソッドが定義されているので、こちらを使用します。
untilと組み合わせることで、ファイルの最後まで簡単に読み取ることができます。

f = File.open('csv/simple.csv', 'r')
until f.eof?
  puts f.getc
end

# a
# a
# :
# i

トークンの作成

まずは構造体が作成できるように、ファイルの上部でTokenを定義しておきます。

parser.rb

# frozen_string_literal: true

Token = Struct.new('Token', :kind, :value, :next)

トークンは連結リストとして作成していきます。
nextはそのために定義したフィールドです。以下の図のようにトークン同士をnextフィールドを利用して連結させていきます。

トークンを作成する処理をまとめてtokenize関数として定義したものが以下になります。

parser.rb

# frozen_string_literal: true

Token = Struct.new('Token', :kind, :value, :next)

def tokenize(file)
  head = Token.new(:start, '', nil)
  cur_token = head

  until file.eof?
    value = file.getc
    token = case value
            when ','
              Token.new(:comma, ',', nil)
            when "\n"
              Token.new(:crlf, "\n", nil)
            else
              Token.new(:value, value, nil)
            end
    cur_token.next = token
    cur_token = token
  end

  head.next
end

連結リストの作成にあたり、先頭のトークンをheadと現在のトークンを管理するcur_tokenに代入しておきます。 あとはcur_token.nextに作成したトークンを記録した後にcur_tokenを更新すると、面白いように連結リストが出来上がります。

# a,b,cの場合
#<struct Struct::Token kind=:value, value="a",
  next=#<struct Struct::Token kind=:comma, value=",",
    next=#<struct Struct::Token kind=:value, value="b",
      next=#<struct Struct::Token kind=:comma, value=",",
        next=#<struct Struct::Token kind=:value, value="c"
          next=#<struct Struct::Token kind=:crlf, value="\n",
            next=nil>>>>>>

2. データ変換(二次元配列への変換)

二次元配列として記録するために、各行の全要素を配列に格納する必要があります。

[
  ['aaa', 'bbb', 'ccc'], # 1行目
  ['ddd', 'eee', 'fff'], # 2行目
]

先にコードを見た方が理解が早いと思うので、完成形を以下に添付します。
二次元配列への変換を行う処理をまとめて token2csvとして定義しました。2toを表現しています。

parser.rb

def token2csv(token)
  cur_token = token
  rows = []
  row = []

  until cur_token.nil?
    case cur_token.kind
    when :comma
      cur_token = cur_token.next
    when :crlf
      rows.push(row)
      row = []
      cur_token = cur_token.next
    when :value
      value = ''
      while cur_token.kind == :value
        value += cur_token.value
        cur_token = cur_token.next
      end
      row.push(value)
    end
  end

  rows
end

現在のトークンを管理するためにcur_tokenを宣言しています。
何かしらの処理が完了して次のトークンを参照するには、都度、cur_tokenを更新していきます。

cur_token = cur_token.next

cur_tokennilになった場合、次のトークンが存在しないことを示しています。
この特性を利用して、先ほどと同じようにuntilを使うことで、全トークンの参照が行えます。

二次元配列を作るには

トークンは「a->a->a->,」というように値を保持しているで、まず一行の一要素(eg: aaa)をまとめる必要があります。
rowは各行の全要素を格納する一時領域として使用しています。

# value以外のトークンが出現するまで文字列を結合しまくる
when :value
  value = ''
  while cur_token.kind == :value
    value += cur_token.value
    cur_token = cur_token.next
  end
  row.push(value)

,\nが登場するまでが一要素となりますが、\nが登場した場合、それはCSVの一行が終了したことを示すフラグとなります。 この時点で、パースした全要素を配列に格納します。
続けて、全体を格納している配列に追加すれば、最終的に二次元配列が完成します。

# 全体を格納しているrowsにrowを追加
# 合わせて一時領域rowをクリアして次の行に備える
when :crlf
  rows.push(row)
  row = []
  cur_token = cur_token.next

これでパーサーの実装が完了しました!

csv-parser/parser.rb at master · okabe-yuya/csv-parser · GitHub

動作確認

それでは作成したパーサーの動作確認をしてみます。
tokenizetoken2csvをまとめて実行するcsv_parse(file)を定義しました。
さて、無事にパースできているでしょうか...。

parser.rb

def csv_parse(file)
  token = tokenize(file)
  token2csv(token)
end

f = File.open('csv/simple.csv', 'r')
res = csv_parse(f)
puts "result: #{res}"

# result: [["aaa", "bbb", "ccc"], ["ddd", "eee", "fff"], ["ggg", "hhh", "iii"]]

おぉ!期待通り、CSVの構造を表す二次元配列になっていますね。
思ったようにパースできているようです。

テストの追加

何度も実行結果を手で確認するのは手間なので、テストを追加します。
他にも気になるパターンがあれば、同様にテストを追加して試してみてください。

parser_test.rb

it 'simple.csv' do
  f = File.open('csv/simple.csv', 'r')
  result = csv_parse(f)
  expect = [
    ['aaa', 'bbb', 'ccc'],
    ['ddd', 'eee', 'fff'],
    ['ggg', 'hhh', 'iii'],
  ]

  assert(result, expect)
end
$ ruby parser_test.rb
[OK] simple.csv

無事にテストがパスしました。

最後に

今回は簡単なCSVパーサーをRubyで実装してみました。
最終的には、50行程度のコードでCSVのパーサーが作ることができました。
たったこれだけのコードで、こんなに面白いものが作れるのは、驚きと喜びしかありません(個人的感想...)。

github.com

コードを書きたいけど作りたいものが特にないという方には、コードがゴリゴリと書けるパーサーがオススメです。 パーサーを作るという過程を楽しんで頂けたのなら何よりです。

【初心者向け】ソフトウェア開発の「テスト」って何?テストの役割について考える

ソフトウェア開発の「テスト」って何?
ソフトウェア開発の「テスト」って何?

こんにちは、開発チームでエンジニアをしている和田です。

最近は、フロントエンドのプロジェクトを Vue2 から Vue3 に移行する作業に奮闘している毎日です🔥

そんな移行作業の真っ只中、社内の QA さんとお話しする機会があり「ソフトウェア開発に関するテストとはなにか?」について理解を深める良い機会となったため、今回は

  • 「ソフトウェア開発におけるテストってなに?👀」
  • 「そもそもテストってなんでやらないといけないの??🤔」

と疑問に感じられる方のために、筆者なりにテストに関する解説をさせていただきます。

ソフトウェア開発における「テスト」とは一体なんなのか?

皆さんは「テスト」という単語を聞くとどんなものをイメージするでしょうか?

20代の筆者は最初にこの言葉を聞いたとき、学校のペーパーテストの試験が脳内に浮かび上がりました 笑

当然、ソフトウェア開発におけるテストとは学校のテストとは全く異なるものです。
テストとはなんなのか ChatGPT に質問してみます。

テストの定義について ChatGPT に聞いてみる

筆者の質問

ソフトウェア開発におけるテストとはなんですか?

ChatGPT の回答

ソフトウェア開発におけるテストとは、開発されたソフトウェアが正しく動作するか、要求された仕様や条件を満たしているかを検証するプロセスです。

このように回答となりました。
つまり、ソフトウェア開発におけるテストとは、開発したソフトウェアが期待する動作をしているか検証することですね。

品質保証という考えにおいてテストが重要なのは考えるまでもないでしょう。
品質保証以外にもテストの役割はあるのでしょうか?


テストがなぜ必要なのか? テストの役割について考える

一般的にテストの役割としては下記のようなものが挙げられます。

  1. 品質の確保
  2. コストの削減
  3. ドキュメンテーションとしての役割
  4. 実施後の証拠品としての役割

それぞれ見ていきます。

1. 品質の確保

テストを通じてエラーやバグを早期に発見することで、ソフトウェアの安定性や信頼性を向上させる役割があります。 テストの専門家である QA (Quality Assurance) が「品質保証」を意味するようにテストの代表的な役割です。

2. コストの削減

ソフトウェアのバグというものは、後から発見されるよりも開発初期の段階で発見されたほうが修正コストが低くなります。 早期にテストを行うことによって、開発の過程で問題が修正されて長期的なコスト削減に繋がります。

3. ドキュメンテーションとしての役割

テストケースやテスト結果は、ソフトウェアの動作や仕様を示します。
すなわちテスト結果をきちんと記録しておけば、仕様書の役割も果たしてくれるのです。 今後、改修や新機能を実装する際に改めてテストを行うとき、過去に行ったテスト結果が大いに役立ちます。

4. 実施後の証拠品としての役割

また開発段階以外でもテストは役に立ちます。
それは証拠品として機能するという側面です。 正確に記録されたテストは、クライアントやステークホルダーに対してソフトウェアの品質を確認・保証するための物的な証拠となり、機能をリリースするか判断する際の重要な資料となります。


【まとめ】テストってめっちゃ大事

いかがでしたでしょうか?
今回はソフトウェア開発におけるテストについて筆者なりに学んだことをまとめさせていただきました。

社内の QA さんとテストに関して会話する中で特に学びとして感じられたことは「テストが証拠品として機能すること」です。開発以外の現場でも活躍する資料になるのは驚きですね。

筆者自身エンジニアとして開発に携わる中で「テスト書いてて良かった〜😌」と思わされるようなバグやエラーを発見した経験が度々あります。ただプログラムが書けるだけじゃなく、テストに関する正しい知識を持ち合わせたエンジニアを目指して参ります。

【私の作業環境】N2i の古株エンジニア 田中さんの作業環境を覗いてみた!!

私の作業環境

こんにちは、N2i Tech Blog 編集長の和田です。

エンジニアのみんなの作業環境について紹介していくシリーズ「私の作業環境」😆

物理的な環境・お気に入りのツール・ワークフローなんでも構わず社員のみんなのこだわりポイントを紹介させていただきます。

今回はエンジニアの田中さんです!


今回は、私の開発環境をご紹介させていただきます。

デスク全体はこのような感じになっています。

エンジニア 田中の開発環境 R2-D2がお気に入り

目次

  • JAPANNEXT 4K IPS 55インチモニター

  • 環境音を作る事もできるZoom用iPad

  • 自宅ではメインPCはChatGPT専用として使用

  • ハイレゾ電波時計・巨大電卓

  • 自動昇降式テーブルと赤いマット

1. JAPANNEXT 4K IPS 55インチモニター

一度に4つの画面を、大きさそのままで確認できる巨大4Kモニターです。

左の15インチMacBookProと比べると、27インチモニター4枚分なので巨大さがわかるかと思います。よく2つ目のモニターを縦にしてソースを見る使い方をよく見ますが、この画面ならそのまま縦に伸ばして、リファクタリングや差分を確認することができます。

27インチモニター4枚分の55インチモニター

JAPNNEXT 55インチモニター

https://japannext.net/jn-ips5500tuhdr/

2. 環境音を作る事もできるZoom用iPad

iPadでは、Zoom に入ったり、普段使わないときは環境音として流しています。

作業中の環境音は川の音ですが、このTopRelacMusicさんの川の音は、耳障りにならない自然な環境音に近いのでおすすめです。

夏の音も仕事のやる気がなぜか出ます。是非聞いてみてください。

iPadは環境音を作るのに操作性もよくておすすめ

おすすめ環境音

(川の音)

https://www.youtube.com/watch?v=5lCRsLjMeso

(夏の音)

https://www.youtube.com/watch?v=OLshMqlgmyA

3. 自宅ではメインPCはChatGPT専用として使用

会社にいくとメインPCとして作業してますが、リモート環境では、ChatGPT音声専用機になっています。Chrome拡張機能の「Voice In」を使えば、いつでもChatGPTで調べたい時に音声で調べられます。使い方は簡単で、

  1. インストールしたら、ChatGPTに聞きたいことを話します。
  2. 「かくてい」と言うと自動でエンターキーを押します。

【補足】「かくてい」以外にも、「 まる(。)」とか、「あたらしいぎょう(改行)」とか言うとその通り声で指示できます。

自宅では音声入力のChatGPT専用となっている

Voice In

Voice In - Speech-To-Text Dictation - Chrome ウェブストア

ビルトインボイスコマンド

日本語 Speech Recognition Commands - Voice In

4. ハイレゾ電波時計・巨大電卓

SONYのモバイルスピーカー、ハイレゾ対応で聞けます。環境音を流しています。

電波時計は時間を正確に見ることができますし、電卓はいつでも計算できるように巨大な押しやすい電卓を手元においています。

左からSONY SRS-HG1、電波時計、CASIOの巨大電卓

5. 自動昇降式テーブルと赤いマット

実は自動昇降式テーブルに最近変えました。1400✕700あり、自動でデスクの高さを変えられるので非常に体に優しいです。マットは光学式マウスをどこでも使えますし、赤い色にしてるのは、ものがどこに追いてあっても視認できるように赤色にしています。

自動昇降式デスクのシンプルなスイッチ

まとめ

最後まで読んでくださりありがとうございます!

色々とこだわりがありますが、自分の作業しやすい環境を作るのは、仕事がはかどるのでいいですよね!みなさんのこだわりで良かったら真似させていただきたいと思います。

おまけ画像 愛用のHHKB TypeS Bluetooth 無刻印キーボード