【私の作業環境】エンジニアの作業環境を紹介するコーナーを新設しました!!

【私の作業環境】エンジニアの作業環境を紹介するコーナーを新設しました!!
【私の作業環境】エンジニアの作業環境を紹介するコーナーを新設しました!!

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

N2i Tech Blog が発起して以来、毎週投稿できていることに驚きを隠せません🥳

それもこれも投稿するための記事を書いてくださっているみんなのおかげですね🙌

Tech Blog の運営に当たって月に一回の定例会を設けているのですが、新たな施策のアイデアを頂いたので今回はその第1回目の記事として投稿させていただきます。

その施策とはズバリ...

新シリーズ【私の作業環境】!!

ということで、N2i の社員のみんなのことをもっと知るべく、「私の作業環境」というシリーズ記事を執筆することになりました!!

簡単に説明すると、エンジニアのみんなの作業環境について紹介していくシリーズです🤓

物理的な環境・お気に入りのツール・ワークフローなんでも構いません。

皆さんの作業環境のこだわりポイントを紹介させていただきます!


【私の作業環境】エンジニア 和田

和田の作業環境
和田の作業環境

ということで、初回は Tech Blog 編集長を務めさせていただいる 和田の作業環境紹介です。
デスク全体はこんな感じです。
筆者自身、自分の作業環境に関してはかなりこだわりを持っているのですが、全部説明すると一冊の本が書けそうなので今回は下記について紹介させていただきます。

  1. 配線の美しさ
  2. 視界を妨げないモニターライト
  3. 疲労軽減トラックボールマウス
  4. 万が一のための蓋付きマグカップ

1. 配線の美しさ

デスク全体を見て分かる通り、デスク上から見える配線ができるかぎり少なくなるように配線にこだわっています。

モニター・モニターライト・マイク・スピーカー・キーボードなどなど、有線で繋げているものが複数ある中、視認できる配線はたった2本だけ😏

デスク上がごちゃごちゃしていると、集中力がかき乱されるのであまりものを置かないように心がけています。 配線はデスク下に格納していたり、モニターアーム内に忍ばせていたりと見せないための努力をしています💪

2. 視界を妨げないモニターライト

視界を妨げないモニターライト
視界を妨げないモニターライト

次にモニターライトです。先程のデスクにあまり物を置きたくないというこだわりにも通ずるのですが、このモニターライトはモニターの上に載せるだけ🙌

ライトの光が直接視界に入り込まないようになっているので眩しくないです。

部屋を暗くして作業する
部屋を暗くして作業する

筆者は夜はこんな感じでモニターライトのみの光とヘッドホンを付けて作業するのが好きです。

3. 疲労軽減トラックボールマウス

疲労軽減トラックボールマウス
疲労軽減トラックボールマウス

マウスをトラックボール式のものに変えてから全く疲れなくなりました。
マウスを動かす必要がないため、画面を見ている最中に右腕だけマウスを探しにいくこともなくなりストレスフリーで作業ができます。

4. 万が一のための蓋付きマグカップ

万が一のための蓋付きマグカップ
万が一のための蓋付きマグカップ

電子機器以外でこだわっているのがこの蓋付きのマグカップです。
卓上の電子機器に万が一飲み物がこぼれたらコワイので蓋付きの物を使っています。
倒れたとしても被害が最小限に抑えられる上に、保温の効果もあり大活躍中なのでオススメです!
アウトドア用の容量多いマグカップだとコーヒーを淹れる回数も少なくて済むのが嬉しいですね。


まとめ

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

いかがでしたでしょうか?第一回「私の作業環境」シリーズとして、N2i Tech Blog 編集長の和田の作業環境を紹介させていただきました。

キーボードがたくさんあることや、その他のこだわりポイントは、今後の記事で改めて紹介させていただければと思います😅

Vue2 の公式サポート終了に伴い、Options API から Composition API に書き換えてみる。

Vue2 の公式サポート終了に伴い、Options API から Composition API に書き換えてみる
Vue2 の公式サポート終了に伴い、Options API から Composition API に書き換えてみる

Web illustrations by Storyset

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

最近は、Vue2 で記述されたプロジェクトを Vue3 および Nuxt3 に書き換える毎日です👨‍💻

ということで今回は、Options API で記述された Vue2 のコンポーネントを Composition API で記述する過程について記事にしたいと思います。

Vue2からVue3・Nuxt3 へ移行する背景

Vue2 のプロジェクトを Nuxt3 へと移行するに至った背景としては、主に Vue2 の公式サポートが終了することにあります。

2023年12月に Vue2 の公式サポートが終了することが発表されています。このままプロジェクトを放置すると、Vue2 に依存するライブラリなどもアップデートできず脆弱性を抱え続けることになるため、一念発起してプロジェクト全体の変更をすることになりました🤓

  1. Options API で記述された Vue2 コンポーネントを Composition API に書き換える
  2. Composition API で記述されたプロジェクト全体を Vue3 に引き上げる
  3. Vue3 のプロジェクトをベースに Nuxt3 に移行する

このような流れで作業をしていきます。

この記事の対象読者: Vue2からVue3への乗り換えを検討している人

今回の記事では、Vue2 の Options API で記述されたコンポーネントを Composition API に書き換えるまでを解説します。

Composition API で記述されたコンポーネントを Nuxt3 のプロジェクトで使えるようにする方法については、今後の記事で解説させていただきます🙇‍♂️


Vue2とVue3、Options APIとComposition APIの関係について

前提知識として Vue2, Vue3, Options API, Composition API の関係性について述べておきます。

Options API について

Options API とは、Vue2 の代表的な記法であり下記のようなサンプルコードで書けます。

<script>
export default {
    name: 'Counter',
    data: () => {
        return {
            count: 0,
        };
    },

    methods: {
        countUp() {
            this.count++;
        },
        reset() {
            this.count = 0;
        },
    },
};
</script>

data の中でリアクティブな値 count を管理し、リアクティブに値を操作するための処理を methods 内に記述するという形式です。

この記法の問題として、this を使ってリアクティブに値を操作することになるため、View と処理を分離することができないということが挙げられます。

Composition API について

Composition API とは、Vue3 の代表的な記法です。
Vue2 のプロジェクトにも導入することができ、リアクティブな値の操作と View を切り離せるのが特徴です。

import { ref } from "vue";

export const useCounter = () => {
    const count = ref(0);

    const addCounter = () => {
        count.value++;
    };
    const resetCounter = () => {
        count.value = 0;
    };

    return {
        count,
        addCounter,
        resetCounter,
    };
};
import { useCounter } from '@/ ... /useCounter'

export default defineComponent({
    name: 'Counter'
    setup() {
        const { count, addCounter, resetCounter } = useCounter();
    }
});

composables というディレクトリに、リアクティブな値の処理を記述しておけば、どのコンポーネントからでも簡単に呼び出すことができます。


Vue2 Options API で記述されたコンポーネント

今回は Options API で記述された下記のコンポーネントについて見ていきます。
説明の都合上、<style /> の記述は省略します。

<template>
  <button
    :class="{ [`btn-${buttonType}`]: true }"
    :disabled="hasPermission === false || isDisabled === true"
  >
    <span>{{ buttonText }}</span>
  </button>
</template>

<script>
import { mapGetters } from 'vuex';

export default {
  name: 'ButtonBase',
  props: {
    buttonText: { type: String, required: true },
    buttonType: { type: String, default: 'primary' },
    isDisabled: { type: Boolean, default: false },
    rejectedRoleIds: { type: Array, default: () => [] },
  },
  computed: {
    ...mapGetters('staff', ['staff']),
    hasPermission() {
      return this.judgeHasPermission(
        this.staff,
        this.rejectedRoleIds,
      );
    },
  },
  methods: {
    judgeHasPermission(staffObj, rejectedRoleIds) {
      const staffObject = staffObj;
      if (typeof staffObject !== 'object') return false;

      if (rejectedRoleIds.length === 0) return true;

      return (
        staffObject.role &&
        rejectedRoleIds.includes(staffObject.role.id) === false
      );
    },
  },
};
</script>

それぞれの props の説明は下記のようになります。

props 用途
buttonText ボタン中央に表示するテキスト
buttonType ボタンの class を利用するための文字列
isDisabled ボタンの非活性フラグ
rejectedRoleIds ボタンの押下制限を行うユーザーの role ID の配列

Composition API に書き換える

先程のコードの仕様をほとんど変更せずに Composition API に書き換えると次のようになります。

<template>
  <button
    :class="{ [`btn-${buttonType}`]: true }"
    :disabled="hasPermission === false || isDisabled === true"
  >
    <span>{{ buttonText }}</span>
  </button>
</template>

<script>
import { computed, defineComponent } from '@vue/composition-api';

export default defineComponent({
  name: 'ButtonBase',
  props: {
    buttonText: { type: String, required: true },
    buttonType: { type: String, default: 'primary' },
    isDisabled: { type: Boolean, default: false },
    rejectedRoleIds: { type: Array, default: () => [] },
  },

  setup(props, context) {
    const store = context.root.$store;
    const staff = store.getters['staff/staff'];

    const hasPermission = computed(() =>
      judgeHasPermission(staff, props.rejectedRoleIds),
    );

    const judgeHasPermission = (staffObj, rejectedRoleIds) => {
      const staffObject = staffObj;
      if (typeof staffObject !== 'object') return false;

      if (rejectedRoleIds.length === 0) return true;

      return (
        staffObject.role &&
        rejectedRoleIds.includes(staffObject.role.id) === false
      );
    };

    return {
      hasPermission,
    };
  },
});
</script>

変更前は、this.staff としてユーザーの情報を取得していたところを const staff = store.getters['staff/staff']; として this を使わないので簡単です。
setup の中に関数をシンプルに記述できる点でも便利ですね。

今回の変更について

今回、変更したのはシンプルなコンポーネントだったため、劇的に変わった点はありませんでした😅

defineComponent() を使った記法ではなく、<script setup /> を使った setup 構文というものを使えば、もっとシンプルな記述ができるようなので次回以降の記事で解説していきたいと思います!

【作業効率化】エンジニアが使う開発ツールまとめてみた!おすすめを厳選して紹介

おすすめ開発ツール一覧
おすすめ開発ツール一覧

Business illustrations by Storyset

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

先日、コードを書いている最中にふと

「エンジニアって、めっちゃたくさん開発ツール使うよな... 何個くらい使ってんだろ 🤔」

と疑問に感じました。

ということで、今回の記事では、普段使っている開発ツールを一覧にしてまとめてみようと思います。

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

Warp

www.warp.dev

まずは、ターミナルアプリより Warp です。
Rust で作られた高速なターミナルで、モダンなターミナルでは当たり前のコマンドの補完・履歴検索・マルチカーソル・画面分割などはもちろん、AIが打ち間違えたコマンドから正しいコマンドを予測してくれたりと超便利です。

筆者は以前、後述の iTerm を使っていましたが、Warp の速さと利便性を実感してからこちらに乗り換えました🙌

デフォルトで用意されているカラーテーマも豊富で、おしゃれにターミナルを使いたい人にもおすすめです!

brew install --cask warp でインストールできます。

iTerm

iterm2.com

言わずと知れた有名なターミナル iTerm 。
設定ファイルをカスタムすれば、自分好みの見た目や機能を盛り込めるので便利です。
Mac に元から入っている Terminal よりも設定がわかりやすかったり、機能が豊富な定番のターミナルですね。

brew install --cask iterm2 でインストールできます。

Visual Studio Code

code.visualstudio.com

エンジニアなら知らない人はいない無料のコードエディタ VS Code です。
豊富な拡張機能や外部ツールとの連携が強みですよね。使わない日はないくらいお世話になってます🙇‍♂️

brew install --cask visual-studio-codeでインストールできます。

Google Chrome

www.google.com

VS Code 以上に毎日使うのが Chrome です。Web の開発なら使わないことはないでしょう。

brew install --cask google-chrome でインストールできます👍

Docker Desktop

www.docker.com

これが無いと何も始まらん...というくらい重宝している Docker のデスクトップアプリです。
開発の都合上、Docker が立ち上がってないと開発ができないので終始起動してます🐳

brew install --cask docker でインストールできます。

Beekeeper Studio

www.beekeeperstudio.io

モダンな DBMS のクライアントツールです。
主要な DBMS にマルチ対応しており、Beekeeper Studio の中で SQL の補完、フォーマットをしてくれたりとかなり便利。

Beekeeper Studio の開発者の方は、DB関連のツールに古めかしい外観のものが多いことに疑問を持ち、開発に至ったそうです。brew install --cask beekeeper-studio でコミュニティ版をインストールできます。

コミュニティ版は、データの一括ダウンロードができないのがちょっと残念😢

Sequel Ace

Sequel Ace

Sequel Ace

  • Moballo, LLC
  • 開発ツール
  • 無料
apps.apple.com

DBMS クライアントツールの定番である Sequel Pro からフォークして作られたツールです。

本家の Sequel Pro はなかったダークモードが Sequel Ace には搭載されており、UI も改善されています。使い勝手は全く同じなのでおすすめです👍

brew install --cask sequel-ace でインストールできます。

pgAdmin4

www.pgadmin.org

PostgreSQL 専用のクライアントツールです。
過去に PostgreSQL の geojson 形式のデータに対応しているツールを探していたときに見つけました。

brew install --cask pgadmin4 でインストールできます🐘

Medis

getmedis.com

Redis を使っている開発者にはおすすめのクライアントツールです。
ポートを接続すれば、一般的な DBMS のクライアントツールと同様に Redis に保存されているデータを GUI から確認することができます。

brew install --cask medis でインストール。

Postman

www.postman.com

エンドポイントを登録しておけば、ボタン1つで簡単に実行できるようにしてくれるツール。
バックエンドの開発はもちろん、フロントエンドの開発でも重宝します。
繰り返し実行機能をうまく活用すれば、ダミーデータの大量登録に活用できたりとかなり便利です🙌

brew install --cask postman でインストールできます🧑‍🚀

Fork

git-fork.com

チーム開発をしていると、 Git Branch を GUI 上で確認したいときってありますよね。
そんなときに役に立つのが Fork です。この手の Git のクライアントツール系は色々試しましたが、機能面・UI面で一番気に入ってます。

brew install --cask fork でインストール🍴

Raycast

www.raycast.com

開発ツールではなく、ランチャーアプリですが Raycastを使わない日はないので紹介させてください。
エンジニアフレンドリーなランチャーアプリとされており、プログラミング言語フレームワークの公式ドキュメントを Raycast から検索できたりします!

brew install --cask raycast でインストール。

最後に

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

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

今回、紹介した他にも開発に利用しているアプリケーションはありますが、特に使っているアプリを選んで紹介させていただきました!

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

【OSSコードリーディング入門】gimeiはどのように人名を返しているのか

「良いエンジニアになるには良いコードをたくさん読むべし」と偉い人が言っていました。
しかし、良いコードとは何でしょうか。そして、それはどこにあるのでしょうか。
自分は「良いコード」とは「広く世界で使われているもの」を1つの答えだと考えています。
つまり広く世界で使われているOSSのコードを読んでみることが、良いエンジニアになるための助けになります。
OSSのコードリーディングを通して、さまざまな設計・パターン・技法を学ぶことができます。

OSSのコードを読む心構え

とはいえ、いきなりOSSのコードを読むのは敷居が高いです。
自分が1年ほど、さまざまなOSSのコードを読んできた中で、感じた大切なことは4つあります。

  • 全てを理解しようとしないこと(膨大な量のコードを全て把握するのは作者でも難しい)
  • 適切なボリューム感を選択すること(巨大なコードベースを持つOSSを最初に選ぶと辛い)
  • 普段、触れている技術に近いOSSを選択すること
  • 可能な限り、使い慣れたものを選択すること

以上、4つを踏まえて、N2iと親和性のあるRubyで書かれたOSSのコードを読んでみたいと思います。 適切なボリュームかつ実際にN2iで使用しているgimeiというOSSを選択しました。

github.com

gimeiについて

OSSのコードを読む前に最低限の使い方を把握しておくのが良いです。
githubのREADME.mdを参考にしつつgimeiについて簡単に紹介しておきます。
gimeiは日本人の名前や、日本の住所をランダムに返すライブラリです。

gimei = Gimei.name
gimei.kanji          #=> "斎藤 陽菜"
gimei.hiragana       #=> "さいとう はるな"
gimei.katakana       #=> "サイトウ ハルナ"

ここでは Gimei.nameを最初に呼び出していることを覚えておいてください。

引用元: gimei/README.md at main · willnet/gimei · GitHub

いざコードを読んでみる

コードをgithubからクローンするかブラウザを使ってファイルを閲覧するでも何でもOKです。
コード内を何度も検索することになるので、個人的にはコードをクローンしてお気に入りのエディタで読み進めるのがおすすめです。

gemの場合、最初に開くべきファイルはlib/gimei.rbです。
なぜこのファイルなのかというと、gemはファイル構造が決まっておりlib直下にgem名と同名のファイルが必ず配置されています。 全ての処理はこのファイルから始まります。
他言語のOSSであっても、最初に開くべきファイルを把握しておくのが重要です。

require 'forwardable'
require 'yaml'
:

class Gimei
  extend Forwardable
  GENDERS = [:male, :female].freeze

  def_delegators :@name,
  :
end

gimei/lib/gimei.rb at main · willnet/gimei · GitHub

先ほどGimei.nameを最初に呼び出していたことを思い出してください。
このファイルではGimeiクラスが定義されています。Gimei.nameの呼び出しが可能ということはnameがクラスメソッドとして定義されているはずです。

class Gimei
  class << self
    def name(gender = nil)
      Name.new(gender)
    end
  end
end

ありました...。
nameが呼び出しされるとNameクラスのインスタンスを作成して返しています。
次はrequire 'gimei/name'を頼りにNameクラスの実装を見てみます。

Nameクラスの実装

Nameクラスのインスタンスを作成しているためinitializeが呼び出されます。
ここでは3つのインスタンス変数が定義されていることが分かります。@genderには引数に指定がなければ、性別(maleかfemale)がランダムで束縛されます。
残りの@firstにはFirstクラス、@lastにはLastクラスのインスタンスがそれぞれ束縛されています。

class Gimei::Name
  def initialize(gender = nil)
    @gender = gender || Gimei::GENDERS.sample(random: Gimei.config.rng)
    @first = First.new @gender
    @last = Last.new
  end
end

同じファイルにFirstとLastクラスが定義されています。
First(名前)では性別が重要になります。男性なら倫太郎、女性ならまゆりとかでしょうか。

class First
  def initialize(gender = nil)
    @gender = gender || Gimei::GENDERS.sample(random: Gimei.config.rng)
    @name = NameWord.new(Gimei.names['first_name'][@gender.to_s].sample(random: Gimei.config.rng))
  end
end

Last(氏名)では性別は関係ないので、Firstクラスと比べるとシンプルですね。

class Last
  def initialize
    @name = NameWord.new(Gimei.names['last_name'].sample(random: Gimei.config.rng))
  end
end

どちらのクラスも@nameにNameWordクラスのインスタンスを束縛しています。
インスタンス作成時にGimei.names['last_name']を指定しています。一体、どのような値が指定されているのでしょうか。

gimei/lib/gimei/name.rb at main · willnet/gimei · GitHub

Gimei.namesと人名一覧の読み込み

Gimei.namesが返す値を知るために、再びlib/gimei.rbのコードを見てみます。
標準ライブラリのyamlを利用して/data/names.ymlの中身を読み込んでいることが分かります。 Gimeiクラスではクラスメソッドとインスタンス変数を使ってシングルトンクラスを実装しています。
@names ||= ...と組み合わせることで状態を記録して、YAMLファイルの読み込みを、一度だけ行うように上手く作られていますね。

class Gimei
  class << self
    def names
      @names ||= YAML.load_file(File.expand_path(File.join('..', 'data', 'names.yml'), __FILE__))
    end
  end
end

🖱: クラスメソッドとインスタンス変数を使ったシングルトンクラスの実装例

class Sample
  attr_reader :state
  
  def self.set_variable(value)
    @state ||= value
  end
  
  def self.get_variable
    puts "state: #{@state}"
  end
end

Sample.get_variable
Sample.set_variable(1)
Sample.get_variable
Sample.set_variable(2)
Sample.get_variable

# state: 
# state: 1
# state: 1


names.ymlには以下のように人名の情報が「漢字、ひらがな、カタカナ」の順に記録されています。

first_name:
  male:
    - ['愛斗', 'あいと', 'アイト']
    - ['愛登', 'あいと', 'アイト']
  female:
    - ['阿愛', 'ああい', 'アアイ']
    - ['安唯', 'あい', 'アイ']
last_name:
  - ['佐藤', 'さとう', 'サトウ']
  - ['林', 'はやし', 'ハヤシ']

ymlファイルから読み込んだ値はハッシュとして扱えるため、以下のように人名の一覧を取得することが可能です。

irb(main):015:0> Gimei.names['first_name']['male'].class
=> Array
irb(main):016:0> Gimei.names['first_name']['male'].first
=> ["愛斗", "あいと", "アイト"]

NameWordのインスタンス作成時に指定していたNameWord.new(Gimei.names['last_name'].sampleの場合、人名の一覧からランダムに1件が選択されます。

gimei/lib/gimei.rb at main · willnet/gimei · GitHub

人名を返す

いよいよ最終段階です。
NameWordクラスでは指定された人名の情報(漢字、ひらがな、カタカナ)を配列として保持しており、取得したい情報に対応するメソッドが定義されています。

class NameWord
  def initialize(name)
    @name = name
  end

  def kanji
    @name[0]
  end

  def hiragana
    @name[1]
  end

  def katakana
    @name[2]
  end
  :
end

処理を遡り、Gimei.name.kanjiを実行して、人名の漢字表記を取得する場合の動きを見てみます。
Gimei::Nameクラスのインスタンス作成時に@first@lastが宣言されており、それぞれのインスタンス変数にはymlファイルから読み込んだ人名の情報がランダムに束縛されているのでした。

class Gimei::Name
  attr_reader :first, :last, :gender

  def initialize(gender = nil)
    @gender = gender || Gimei::GENDERS.sample(random: Gimei.config.rng)
    @first = First.new @gender
    @last = Last.new
  end

  def kanji
    "#{last.kanji} #{first.kanji}"
  end
end

gimei/lib/gimei/name.rb at main · willnet/gimei · GitHub

メソッドの移譲

kanjiメソッドでは@first@lastクラスのkanjiメソッドを呼び出しています。
しかしFirst、Lastクラスにはkanjiメソッドを定義している箇所はありません。どういうことなのでしょうか...。
ここでは「移譲」という方法が採用されています。メソッドの移譲がFirstクラスの2~3行目にてForwardableモジュールを使って設定されています。

class First
  extend Forwardable
  def_delegators :@name, :kanji, :hiragana, :katakana, :to_s, :romaji
end

docs.ruby-lang.org

Forwardableに定義されたdef_delegatorsを使用すると、別クラスのメソッドを代わりに呼び出すようになります。
ここでは@nameに束縛されているNameWordクラスのkanji, hiragana, katakana...が、それぞれ該当します。

class NameWord
  def kanji
    @name[0]
  end
  :
end

こうしてFirst、Lastクラスから人名の情報を取得することが可能となりました。
そして最後に、取得した氏名と名前を組み合わせて人名を返すというのがgimeiの内部で行われていることでした。

"#{last.kanji} #{first.kanji}"
# 岡部 倫太郎

まとめ

  • GimeiクラスからGimei::Nameクラスのインスタンスを作成する
  • Gimei::NameではFirstとLastそれぞれのインスタンスを保持している
  • インスタンス作成時、ymlファイルを読み込みランダムな情報を1件取得している
  • FirstとLastクラスはそれぞれNameWordクラスのインスタンスを保持している
  • FirstとLastクラスはメソッドをNameWordクラスに移譲して人名を返す

大量の情報は外部ファイルに置いておく、メソッドを移譲するなど、新たな学びがありました。
このようにOSSのコードを読んでみると、自分の知らないメソッドや実装方法に出会うことができるので、非常に面白いです。

みなさんもぜひチャレンジしてみてください。

N2i の古株エンジニア 田中さんへインタビュー!!

田中さんへインタビュー
田中さんへインタビュー

Work illustrations by Storyset

こんにちは、技術ブログ編集長の和田です。

今回は、「社内のエンジニアに自信のキャリアや仕事への取り組み方などについてインタビュー」シリーズの第3回目の記事になります。

前回は、N2i のテックリードであるエンジニア 杉浦さんにお話を伺いました。まだ、読まれてない方はぜひご覧下さい🙏

techlog.n2i.jp

今回は筆者が日頃からお世話になっているシニアエンジニアの田中さんにお話を伺いたいと思います。

これまでの経歴

-- まずは田中さんの経歴について質問をさせてください。田中さんは N2i で働かれるまでに建築業界や音楽業界などいろんな業界で働かれていた経験があるそうですね。エンジニアになろうと思ったのはなぜでしょうか?

体力的な問題が一番の理由ですね😅
建築も音楽や映像制作も現場作業で、体力が必要とされれます。長期的に働くことを考えると、デスクワークにすることが自分に合っていると思いエンジニアを選びました。

プログラミング自体は幼少期から経験があり得意だったので、そのような背景もあり今の職に至ります。

-- 幼少期からプログラミング ?! 具体的にどんな環境で勉強されたんですか ?

父が当時流行っていた PC8001 というコンピュータを所有していました。
父と一緒に PC8001 を使って BASIC を勉強したのが始まりでしたね。
しばらくして、メールのやり取りができるものだったり、インターネット掲示板などが流行り始めて、Web 系の技術にも触れてきました。

田中さんが当時使用されていた実際の書籍
田中さんが当時使用されていた実際の書籍

-- すごい... まさしくインターネット黎明期に生きてきたんですね。エンジニアになって良かったと感じることはありますか?

開発の計画や時間の使い方を自分で、決めやすいのはエンジニアになって良かったと感じますね。

建築や映像制作などに比べると、アプリケーションの開発は工夫次第でうまくスケジュールを調整しやすいです。

-- エンジニアとして初めて参加された案件は何だったんですか?

映像制作会社で働いていた時代に、結婚式の余興のシステムを開発したのが仕事としては最初でしたね。

結婚式の参加者が撮影した写真をスクリーン上に写してみんなで共有できるようなものです。

開発していた当初、人工知能が流行り始めたこともあって、撮影した写真に笑顔の人が多ければ高得点として判定されるような仕組みを組み込んだりしました。

田中さん自身について

-- 田中さんの得意なことはなんですか?

初対面で誰とでも話せることですね。趣味が広いことも有り、どんな話題でも話せるのが自分の強みだと思ってます。

-- どうやっていろんな知識を取り入れているんでしょうか?

気になったことはメモして、退勤後や休日に少しの時間だけでも必ず調べるように心がけています。

いろんなニュースについて細かく時間を分けて長期的に触れておくことが、いろんな知識を吸収するコツですかね...

-- 逆に苦手なことはなんですか?

芸術的なセンスが自分には無いと感じています...😭

フロントエンドのデザインなどを作るのは少し苦手かもしれませんね。デザイナーの方たちの「1px でもズレてはいけない」というこだわりは凄いと思います。

こういった感性だったり特技がないのがつらいですね...

-- たしかに芸術的な感性って全員がもってるものではないですよね。エンジニアの業務には支障はないと思うんですけど、そのあたりはどうなんでしょう?

言葉が通じない外国の方などに、手ぶらの状態でなにかアピールできるものがほしいと思ってしまうんですよ。

「自分はこんな人なんですよ」と紹介できるような特技ですね。何か一つでもこういった特技があればよかったな~って思います笑

-- 前回の杉浦さんもそうだったように、自分の強みや弱みを把握しているのはシニアエンジニアあるあるなのかもしれないですね。

-- 今回は田中さんにインタビューをさせていただきました。本日はありがとうございました!


今回のインタビューアーは前回インタビューをさせていただいた杉浦さんと岡部さんに担当していただきました。
改めまして田中さん、ありがとうございました!

N2iの開発をリードするエンジニア杉浦さんにインタビュー!

こんにちは、技術ブログ運営チームの岡部です。
今回は前回より始まった「社内のエンジニアに自身のキャリアや仕事への取り組み方などについてインタビュー」の第2回目の記事になります。前回は香川県にお住まいのエンジニア 安田さんにお話を伺いました。 まだ読まれてない方はぜひご覧ください。

techlog.n2i.jp

今回はN2iのテックリードであるエンジニア 杉浦さんにお話を伺いたいと思います。

これまでの経歴

-- まずは多くの人が気になっている杉浦さんの経歴について質問させてください。N2iに入社するまでどんな経験をされてきましたか?

新卒でシステム会社に入社してSIerとして社会インフラのシステムやECサイトを開発していました。
10~11年勤めた後、WEB制作の会社に1年ほど勤務した後にフリーランスになりました。それからはWEBシステムの開発をしてます。

-- フリーランスだったとはお聞きしていましたが、SIerをされていたのは知りませんでした。N2iにはどのような経緯で入社されたのでしょうか?

名古屋のシェアオフィスで仕事をしていた時にN2i代表の篭橋さんに出会いました。
「一回、*1事務所に来て」と言われてフリーランス時代からN2iの仕事をやっていました。
WEB制作だと自分の力が活かせなくてモヤモヤしていたのですが、N2iでWEBシステムの開発を通じて、凄く成長を感じましたね。

ただ、技術力が上がると早く仕事が終わってしまうので、時給制だと単価が下がってしまい金額面でキツくなったのと、当時、帰り道でよく吉野さんと一緒になることがあって「フリーランス辛いよね...」と話している時にN2iに誘われて入社しました。

過去の案件について

-- 社員になる前からN2iとは付き合いがあったんですね。少し話は変わりますが、杉浦さんが新卒で初めて参加した案件はどのような案件だったのでしょうか?

あまり覚えていないのですが、どこかの工場の製品管理システムでした。
開発の担当ではなかったんですが、入社2日目にバグが見つかってなぜか自分が徹夜して対応した記憶があります(笑)

-- 入社して2日目に徹夜でバグ対応とは中々にハードな案件ですね...。それから様々な案件に携わってきたかと思いますが、最も難しかった案件についても教えてください

とある巨大な施設のシステムですかね。
センサーから受け付けるイベントをコンピューターで状態管理するというものでした。
数値計算の用件が難しくビジネスロジックの実装にとても苦労しました。
あとはUIのリアルタイム描画もWEBシステムのようにボタンなどを手軽に描画できるものではなく、線を1本ずつ引いて四角形を作って、影を入れて立体的にしてボタンを描画する...ようなレベルでの実装だったので、とても大変でした。

SPAを触り始めた時は「なんて楽なんだ」と感動した記憶があります。

普段の業務について

杉浦さんお手製のパンと焙煎したコーヒー豆

-- 杉浦さんは普段はどのような業務をされているのでしょうか?

新規機能開発の事前調査や設計をしたり、既存のアーキテクチャの改善だったりをやっています。
あとは開発メンバーからのコードレビュー依頼や、問い合わせの対応もやっています。

-- めちゃくちゃ幅広いですね(笑) 幅広い知識が求められると思いますが、業務のために勉強していることなどはあるんでしょうか?

自分は座学が苦手だと思っているので必要性を感じた時に集中的に取り組む事が多いですね。
とはいえ事前知識がないとアイディアが出てこないので、GCPのサービス一覧を定期的にチェックしたりはしています。
学習という感覚はあまりなくて、考えてどうするかを得て学んでいるなと感じています。
道具を使いこなす事が好きなんですよね。

職種について

-- 杉浦さんがエンジニアになろうと思ったきっかけは何だったんでしょうか?

自分は昔から集中力がなくて幼稚園ぐらいから落ちこぼれてしまって学業成績が悪かったです。
ただ親族がみなエンジニア(特殊機械や木型など)だったので、手に職をつけたいという考えが強くありました。
それから工業高校に進学して、basicというプログラミング言語を触ってみたら面白くて興味が湧いたので専門学校に進みました。

他のことには集中できなかったんですが、プログラミングは徹夜しても出来たので仕事としてやりたいと思ったのがきっかけです。
エンジニア以外の選択肢はなかったですね。

-- プログラミングには興味が湧いて集中できたというのが何とも杉浦さんらしいです。エンジニアになって良かったと感じる点はありますか?

必ずしも努力すれば良いという訳ではないことです。
複雑な事を頑張ってやるよりも、シンプルで単純なことを選択していくことが重要だと感じています。
あとは自分のように浮き沈みがあっても、影響があまりないというの良い点ですね。安定して同じ作業にずっと取り組むのは自分には辛いと思います。

-- たしかに複雑なことを頑張るよりも、単純なことに分割するのはエンジニアリングにおいて非常に重要な考え方ですよね。他に仕事をする上で気をつけていることがあれば教えてください

エンジニア以外の方の話を素直に聞くことですかね。
どうしてもエンジニアは他の立場の方と対立してしまうことがありますが、自分と違う視野で考えている人の意見は参考になります。
あとは自分のこだわりを突き通すよりも、サービスにとってそれが良いのか悪いのかを選択するようにしていますし、先ほども少し話しましたが、複雑だなぁと感じた時は細かくシンプルで単純なことに分割するように意識しています。

-- 一緒に仕事をしていて杉浦さんの「とりあえず意見を聞く」という姿勢を感じていましたが、そういうことだったんですね。今回は杉浦さんにインタビューをさせていただきました。本日はありがとうございました!

ありがとうございました!

今回のインタビューアーは前回、インタビューをさせて頂いた安田さんに担当して頂きました。
改めまして安田さん、ありがとうございました。

*1:当時は伏見にオフィスがありました

仕様はDBから考えよ!機能開発で重要な観点とはなにか考える。

仕様の考え方
仕様の考え方
Data illustrations by Storyset

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

普段の業務では、Node.js で作られているアプリケーションの仕様を考えたり、機能開発をしたりしています。

入社してから新しく開発した機能のほとんどの仕様作成に携わってきました。

今日はそんな筆者が、

「初めて機能開発に携わることになったけど、仕様ってどうやって考えればいいの...?」

と悩めるエンジニアの方のために、この1年ほどで学んできた仕様を考えるうえで大事な観点について記事にしてみようと思います。

※ あくまで個人の意見であり、筆者が所属するチームで大切にしている考え方であることにご留意ください。

仕様は DB から考えよ

「和田さん... DB が全てなんですよ。」

筆者が現在の開発チームにアサインしたばかりの頃に、シニアエンジニア T さんから最初に言われたセリフです。

Tさん曰く、DBが決まれば仕様はほぼ決まるとのこと。

当時の私からしたらなんのことだかさっぱりでした...😅

どういう意味なのでしょうか?

DB は後から変更しにくい

DB とはすなわち、アプリケーションを使用するユーザーごとに保存された個々の情報でありユーザーの財産とも言えるものです。

ユーザーの大切な情報であるため、機能がリリースされてから DB に情報が保存されると後から簡単に変更することができないという特性があります。

つまり最初のテーブル設計を間違ったまま機能をリリースすれば、変更に時間のかかる負債となる機能を生み出しかねないわけですね。

だからこそ、最初に仕様を考えるうえで DB 設計を大切にしなければならないのです。

バックエンドやフロントエンドのコードは後から変えられる

一方でバックエンドやフロントエンドのコードはどうでしょうか?

これらは利用者が変更できるものではなく、開発者がコントロールする領域です。

万が一、バックエンドやフロントエンドに誤ったコードが含まれていたとしても DB 設計さえ問題なければ、後から修正ができます。

DB 設計ってどうやればいいの?

では DB 設計はどのように行えばいいのでしょうか?

結論としては、一概にこのやり方が正解だという答えは存在しない です😇

残念ながら DB 設計ばかりは、アプリケーションの仕様に依存するためやり方を一つに定めることはできません。

筆者も社内のエンジニアにこの疑問を聞いて回りましたが、

「DB 設計は奥が深い。一度作ってもしばらく経つと、仕様の変更によって扱いづらいDBになっていることもよくある。」

とのことでした。やはり、決定的な答えは存在しないようですね。

とにもかくにも、仕様を考える上で熟考しないといけないのが DB であることは間違いないようです。

しかし、DB 設計よりも遥かに大事な観点があります...

現行の仕様で実現できないかを考えよ

仕様を考える上で、DB 設計を行うこと以上に大切なことはズバリ 現行の仕様で課題解決ができないかを考える ということです。

本当に必要な機能開発か見極めよう

現行の仕様で課題解決を行うことが推奨される理由は、時間をかけなくて良いからです。

先程、DB 設計をうまく行えていればコードは後から修正可能だと述べました。しかしながら、これらの修正にも時間がかかります。

修正に時間をかけている間、競合のアプリケーションが魅力的な新機能をリリースしたり、開発しているアプリケーションに優先度の高い別の需要が発生することも有りうるのです。

修正が必要なコードを生み出すよりも、ユーザーに真に求められている機能の調査やその開発をしたほうが良いということですね。

本当に必要な機能を見極め慎重に開発するのも我々エンジニアの仕事というわけです。

最後に

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

今回は筆者が仕様を考えるにあたり、大切にしていることを記事にさせていただきました。

初めて機能開発に携わるエンジニアの方の参考になればと思います🙏