Машинопись от класса к функциональному программированию

У меня есть следующий абстрактный класс Listener который инкапсулирует стандартный код для клиента. Тогда у меня может быть несколько слушателей для различных событий.

В качестве упражнения для самообучения я преобразовал это в функциональный способ.

  1. Это правильный способ функциональной реализации?
  2. Я пытаюсь избежать создания класса для каждого типа слушателя
  3. Должен ли я использовать тип или интерфейс. Поскольку это используется для проверки типов параметров, я не уверен, предпочтительнее ли один из них.
  4. Любые другие комментарии по реализации функционального способа (каррирование, функции высшего порядка)? Как новичок, я пытаюсь понять, применимы ли они здесь и как.
abstract class Listener {
  abstract subject: string;
  private client: Client;
  abstract groupName: string;
  protected ackTimeout = 5 * 1000;

  abstract onMessage(data: any, msg: Message): void;

  constructor(client: Client) {
    this.client = client;
  }

  private subscriptionOptions(): SubscriptionOptions {
    return this.client.subscriptionOptions()
      .setOption1()
      .setOption2(this.ackTimeout)
      .setOption2(true)
      .setDurableName(this.groupName);
  }

  listen(): void {
    const subscription = this.client.subscribe(this.subject, this.groupName, this.subscriptionOptions())
    subscription.on('message', (msg: Message) => {
      console.log(`Message Received: ${this.subject}/${this.groupName}`);
      const parsedData = this.parseMessage(msg);
      this.onMessage(parsedData, msg);
    });
  }


  private parseMessage(msg: Message): any {
    const data = msg.getData();
    return typeof data === 'string' ? JSON.parse(data) : JSON.parse(data.toString('utf-8'));
  }
}

// EventType Listener
class EventCreated extends Listener {
  groupName: string = 'event:created';
  subject: string = 'event-service';

  onMessage(data: any, msg: Message): void {
    // Do something with data
    console.log(`Received `, data);
    msg.acknowledge();
  }

}

Функциональный способ

type Listener = {
  client: Client,
  subject: string,
  groupName: string,
  ackTimeout: number
  onMessage(data: string, msg: Message): void;
  listen(): void;
  parseMessage(msg: Message): string;
  clientOptions(): ClientOptions
}

interface ListenerOptions {
  subject: string,
  groupName: string,
  onMessage(data: any, msg: Message): void;
  parseMessage(msg: Message): string
  ackTimeout?: number,
}

const createListener = (client: Client, options: ListenerOptions): Listener => {
  options.ackTimeout = options.ackTimeout || 5 * 1000;

  return {
    client,
    groupName: options.groupName,
    ackTimeout: options.ackTimeout,
    subject: options.subject,
    
    onMessage: options.onMessage,
    
    listen: function () {
      const subscription = this.client.subscribe(this.subject, this.groupName, this.clientOptions())
      subscription.on('message', (msg: Message) => {
      console.log(`Message Received: ${this.subject}/${this.groupName}`);
      const parsedData = this.parseMessage(msg);
      this.onMessage(parsedData, msg);
    },
    parseMessage: options.parseMessage || function (msg: Message): string {
      const data = msg.getData();
      return typeof data === 'string' ? JSON.parse(data) : JSON.parse(data.toString('utf-8'));
    },
    clientOptions: function (): ClientOptions {
      // this.client.clientOptions to set various options as per external library
      return this.client.clientOptions()
        .setOption1(true)
        .setOption2()
        .setAckTimeout(this.ackTimeout)
        .setGroup(this.groupName);
    }
  }
}
```

0

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *