Open2

Nest.jsについて

shogoooshogooo

DTO

DTOとは (Data Transfer Object)

  • データの受け渡しに使われるオブジェクト
  • DBとモデルクラス間のデータのやり取りやリクエストオブジェクトからのデータ受け取りなどで使用される

メリット

  • メンテナンス性が高まる
  • アプリの安全性が高まる。誤ったデータの型が扱われるリスクが減る
  • Nest.jsのバリデーション機能が使える
shogoooshogooo

DTOを使ったコードのリファクタ

POSTメソッドのリファクタリングを行う

createMovieDtoクラスを宣言します

create-movie.dto.ts
export class CreateMovieDto {
  id: number;
  title: string;
  description: string;
  rating: number;
  review: string;
}

最初の実装では各プロパティを個別の@Bodyデコレータで受け取っていた。
この方法だとコードが冗長になる。
またプロパティを追加するときのコードの変更箇所が多い。

movies.controller.ts(リファクタ前)
  @Post()
  create(
    @Body('id') id: number,
    @Body('title') title: string,
    @Body('description') description: string,
    @Body('rating') rating: number,
    @Body('review') review: string,
  ): Movie {
    const movie: Movie = {
      id: id,
      title,
      description,
      rating,
      review,
    };
    return this.moviesService.create(movie);
  }

CreateMovideDtoというDTOを導入することで、一つの@Bodyデコレータでリクエストボディ全体を一つのオブジェクトとして受け取ることができ、コードがシンプルに!
プロパティを追加する際はDTOのプロパティだけ変更すればOK
一つの@Bodyで受け取るには、DTOとボディパラメータのプロパティが等しくないといけない

movies.controller.ts(リファクタ後)
import { CreateMovieDto } from './DTO/create-movie.dto';
// ~~~~~省略~~~~~
@Post()
  create(@Body() createMovieDto: CreateMovieDto): Movie {
    return this.moviesService.create(createMovieDto);
  }

コントローラからサービスへcreateMovieDtoが渡されるようになるため、 サービスのメソッドの引数をcreateMovieDtoに変更。
...createMovieDtoでオブジェクトを展開してmovie変数にコピー。(スプレッド構文を用いたES6の記述)
スプレッド構文を使うことで、将来プロパティが増えても自動で展開されるため変更が不要。
DTOスプレッド構文を使って展開。

movies.service.ts
  create(createMovieDto: CreateMovieDto): Movie {
    const movie: Movie = {
      ...createMovieDto,
    };
    this.movies.push(movie);
    return movie;
  }

以下の場合は、プロパティが増えた場合手動で追加しないといけない。

movies.service.ts (スプレッド構文を使わない場合)
const movie: Movie = {
  id: createMovieDto.id,
  title: createMovieDto.title,
  description: createMovieDto.description,
  rating: createMovieDto.rating,
  review: createMovieDto.review
};