[RFC] Standardized Abstractions

Centralization of what? The interfaces themselves? Or?

To be clear HTTP::Request and stuff aren’t going anywhere. All that this RFC is proposing is to like include RequestInterface into it, and the related other interfaces into their related type in the stdlib. Then it would be possible to update existing HTTP::Request parameter type restrictions to RequestInterface. This keeps things backwards compatible and everything continues to work. But it also allows others to define their own request type, include RequestInterface from the stdlib, and have the stdlib able to use it just fine.

I’m not sure I 100% follow that example. What benefits does that provide over abstract def foo(parameter : Type) : ReturnType? Where Type describes the required methods? If I’m following correctly, this just seems like a DSL to do something you can already do with a module and abstract defs.

Also fwiw, you totally can use duck typing by just not giving a type. E.g. abstract def foo(parameter : _) : ReturnType. This requires you to implement #foo, but allows any type; such that the compiler would just error if you pass it something that doesnt have all the methods defined it requires.

The problem with duck typing is that you can’t really have an ivar be set to any value. I.e. if you wanted to store the argument as an ivar to future use. This is where the interface module comes into play as it allows you to type ivar, allowing it to be anything that includes the module.

Happy to talk more on Discord or something, but the the answer I think is “it depends”. Ultimately I’m not sure there should even be a RedisInterface. Something higher level CacheInterface could deff make more sense to include in the stdlib, which each redis implementation could then implement. But a redis specific one is too specific. The stdlib doesn’t need to define interfaces for everything, because everything doesn’t need an interface.

To answer your question from the other thread (i’ll throw a link to this post in there too for posterity).

For example, using the code from the other thread:

class Library::Adapter::GaskinsRedis
  include Library:RedisInterface

  # `Redis::Client` is the entrypoint to gaskin's redis shard
  def initialize(@redis : Redis::Client); end

  def del(key)
    @redis.del key
  end

  # ...
end

The only interface you’re implementing here is your own. Because of this there should be no problems here as you’re simply mapping a concrete implementation of some specific redis client to YOUR interface. You do not need to have an interface per external lib nor have a single interface each external lib implements.

You simply expose your library’s interface it uses and users can implement it by creating a class that decorates whatever lib they want to use. Or if there is a specific one you like, you can provide a default implementation for it they can just require and use.