我希望使用协议,编写一个易于测试,可扩展和可维护的代码
协议定义和实现如下:
defmodule SapOdataService.Auth do
alias SapOdataService.Auth.UserLogin
alias SapOdataService.Auth.UserInfo
defprotocol Auth do
@moduledoc """
Protocol for SAP authentication.
"""
def sign_in(data)
end
defimpl Auth, for: UserLogin do
def sign_in(user) do
%UserInfo{firstname: "Foo", lastname: "Boo", basic_auth: "Basic FooBoo"}
end
end
end
用户登录struct(user_login.ex):
defmodule SapOdataService.Auth.UserLogin do
defstruct username: nil, password: nil
@type t :: %__MODULE__{username: String.t, password: String.t}
end
用户信息结构(user_info.ex):
defmodule SapOdataService.Auth.UserInfo do
defstruct firstname: nil, lastname: nil, basic_auth: nil
@type t :: %__MODULE__{firstname: String.t, lastname: String.t, basic_auth: String.t}
end
正如您可以看到上面的代码,userlogin
:
defimpl Auth, for: UserLogin do
def sign_in(user) do
%UserInfo{firstname: "Foo", lastname: "Boo", basic_auth: "Basic FooBoo"}
end
end
如果给定的授权是否正确,sign_in
函数将向服务器发出http post请求。
对于请求,我使用HTTPoison
库向服务器发出请求。
假设,在一天HTTPoison
将不再存在,一些开发人员开发新的HTTP客户端,然后我必须通过新的HTTP客户端替换HTTPoison
。
我的目标是编写易于扩展和维护的代码。
我从José那里读到了关于模拟的精彩article,他建议使用协议并将依赖项作为参数传递给函数。这就是问题,为什么我使用协议而不是行为。
此外,如何强制协议定义返回特定类型。就我而言,我想这样做:
defprotocol Auth do
@moduledoc """
Protocol for SAP authentication.
"""
@spec sign_in(data) :: UserInfo.t
def sign_in(data)
end