Преобразование нечистой функции в чистую функцию улучшения - Scala - PullRequest
0 голосов
/ 30 августа 2018
object IO {

  def getHtmlFromWebsiteViaHttp(link: String, apiKey: String = ""): String = {
    Http(link)
      .param("access_token", apiKey)
      .asString
      .body
  }
}

class SongService {
  private def retrieveSongId(songName: String): Option[JsValue] = {
    val formattedSongName = songName.replace(" ", "%20")
    val searchLink = "https://api.genius.com/search?q=" + formattedSongName

    //impure call
    val geniusStringResponse = IO.getHtmlFromWebsiteViaHttp(searchLink, apiKey)

   //Extra processing on geniusStringResponse
  }
}

Мой текущий дизайн - у меня есть класс обслуживания, который отвечает за получение некоторой информации через внешний API. Теперь я понимаю, что невозможно иметь 100% чистые функции.

Мой вопрос: как лучше всего справляться с ситуациями, когда вам необходимо подключиться к внешнему API в Scala / FP ?. Цель состоит в том, чтобы получить наиболее адекватный «функциональный стиль программирования» путем минимизации нечистых функций

В настоящее время я инкапсулирую все вызовы API в объекте ввода-вывода. Это достаточно подходит? Я вижу примеры монад для ситуаций. Должен ли я включить стиль монады в этом случае?

1 Ответ

0 голосов
/ 31 августа 2018

Это не такая большая проблема с FP, так как я не вижу никаких проблем с вашим кодом с точки зрения FP, но то, что вы должны сделать, по моему мнению, это использовать внедрение зависимостей, так что для тестирования вы может заменить тестовый класс на IO, который имеет гарантированный ответ. Как то так:

abstract class IO {
  def getHtmlFromWebsiteViaHttp(link: String, apiKey: String = ""): String
}

class IOImpl extends IO {
  def getHtmlFromWebsiteViaHttp(link: String, apiKey: String = ""): String = {
    Http(link)
      .param("access_token", apiKey)
      .asString
      .body
  }
}

class IOTestImpl extends IO {
  def getHtmlFromWebsiteViaHttp(link: String, apiKey: String = ""): String = ??? //some test HTML
}

А потом к вашим услугам:

class SongService(io: IO) {
  private def retrieveSongId(songName: String): Option[JsValue] = {
    val formattedSongName = songName.replace(" ", "%20")
    val searchLink = "https://api.genius.com/search?q=" + formattedSongName
    val geniusStringResponse = io.getHtmlFromWebsiteViaHttp(searchLink, apiKey)
   //Extra processing on geniusStringResponse
  }
}

Затем, когда вы создаете экземпляр SongService, передайте его IOTestImpl при тестировании и IOImpl в противном случае. Вы можете найти соответствующую информацию о внедрении зависимостей и объектах доступа к базе данных .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...