Modo orientato agli oggetti per interagire con il livello di persistenza

1

Ho un'entità dell'hotel che ha una serie di immagini. Ho alcune regole di business che sono fondamentalmente semplici operazioni crude in questo momento. Ho sentito parlare di pattern di repository ma, lavorando con esso, mi sento come un atteggiamento procedurale.

Lasciatemi fare un esempio, ho bisogno di recuperare tutte le immagini associate ad un hotel.

'use strict';

const mysql = require('mysql');
const { queryPromise } = require('../utils');

const Image = function Image(opt_data) {
  const data = opt_data || {};

  if (!data['url']) {
    throw new Error('URL is required');
  }

  this.id = data['id'] || null;
  this.url = data['url'];
  this.type = data['type'] || Image.Type.HOTEL;
  this.resource_id = data['resource_id'] || null;

  this.updated_at = data['updated_at'] || new Date();
  this.created_at = data['created_at'] || new Date();
};
const ImageProto = Image.prototype;

ImageProto.save = function saveImage(context) {
  const query = 'INSERT INTO ${Image.TABLE_} (type, url, resource_id) VALUES (?, ?, ?)';
  return queryPromise(context, mysql.format(query, [
    this.type,
    this.url,
    this.resource_id
  ]));
};

ImageProto.toJSON = function() {
  return {
    id: this.id,
    url: this.url
  };
};

Image.Type = {
  HOTEL: 'hotel',
  ROOM: 'room',
  MERCHANT: 'merchant'
};

Image.TABLE_ = 'image';

const Images = function Images(opt_data) {
  const data = opt_data || {};

  this.hotelId = data['hotel_id'] || [];
  this.items = data['images'] || [];
};
const ImagesProto = Images.prototype;

ImagesProto.add = function addImage(imageData) {
  this.items.push(
      new Image(Object.assign({}, {resource_id: this.hotelId}, imageData)));
};

ImagesProto.remove = function removeImage(context, image) {
  const query = 'DELETE FROM ${Image.TABLE_} WHERE id=?';
  return queryPromise(context, mysql.format(query, [image.id]));
};

ImagesProto.save = function saveImage(context) {
  return Promise.all([
    this.items.map(img => img.save(context))
  ]);
};

ImagesProto.filter = function _addImage(context, args) {
  let query = args.map(function (arg) {
      var value = arg[2];
      if (typeof value === typeof '') {
        value = "'" + value + "'";
      }
      arg[2] = value;
      return arg.join('');
  }).join(' and ');

  query = 'SELECT * FROM ${Image.TABLE_} WHERE ${query}';
  return queryPromise(req, query)
      .then(function(results) {
        return new Image(results[0]);
      });
};

ImagesProto.fetch = function _addImage(context) {
  const query = 'SELECT * FROM ${Image.TABLE_} WHERE resource_id=?';
  return queryPromise(context, mysql.format(query, [this.hotelId]))
      .then(results => {
        return results.map(res => new Image(res));
      });
};

module.exports = { Image, Images };

HotelProto.images = function _images(context) {
  return new Images({ hotel_id: this.id });
};

Anche se sembra buono, ma non sono ancora sicuro di questo approccio. Ho sentito il mio collega sviluppatore che sto mescolando il comando / query ma non l'ho capito correttamente.

Esiste un approccio migliore che si attenga all'OOP?

Inoltre, se in futuro dovessi tenere un registro di tutte le attività, quali modifiche dovrei fare?

    
posta CodeYogi 12.07.2017 - 19:22
fonte

1 risposta

3

Hai ragione su questo: osservare quel codice è doloroso. Hai ragione a cercare un modo migliore per organizzarlo.

Leggi di nuovo e pensa seriamente a cosa significa:

The purpose of a repository is to abstract away the details of retrieving data from the database, provide unit testing capability and the ability to swap out the database implementation. If you don't require those capabilities, then you may not need a repository layer.

Robert Harvey

Questo è corretto al 100%.

Ecco il tuo problema:

I have some business rules which are basically simple crud operations right now.

Code Yogi

Finché le tue regole di business sono operazioni sporche, non devi preoccuparti di un livello di repository perché NON hai HANNO regole di business da separare dal codice di accesso al database.

Qui hai un Domain Driven Design completo. Questo codice parla la lingua del tuo esperto di dominio. Tra l'altro, SQL. : P

Il tuo dominio è "manipola il database". Ci sono tonnellate di applicazioni che funzionano in questo modo.

Ciò che ti manca sono le regole aziendali che non hanno nulla a che fare con il database. Se non li hai, non c'è nulla da separare.

Quindi siediti e chiediti: se non dovessi preoccuparmi dei dettagli del database di cosa dovrei preoccuparmi?

Se non riesci a pensare a qualcosa allora non complicare le cose perché sei convinto che i livelli siano sempre buoni. Non lo sono. Finché non vedi perché li stai usando, non farlo.

    
risposta data 13.07.2017 - 00:20
fonte