我已经创建了一个模块来验证针对不同数据库的凭据。
module Authentication
DATABASES = %w[mysql mssql oracle].freeze
DATABASES.each do |database|
define_method("#{database}_connect") do |args|
client = case database
when 'mysql' then Mysql2::Client.new args.merge(ssl_mode: :disabled)
when 'mssql' then TinyTds::Client.new args
when 'oracle' then OCI8.new(args[:username], args[:password], "//#{args[:host]}:#{args[:port]}/#{args[:service_name]}")
end
case database
when 'mysql', 'oracle' then true
when 'mssql' then client.active?
end
end
end
def database_authentication_success?(database:, host:, port:, service_name:, username:, password:)
options = {host: host, port: port, service_name: service_name, username: username, password: password}
case database
when 'mysql' then mysql_connect(options)
when 'mssql' then mssql_connect(options)
when 'oracle' then oracle_connect(options)
end
end
end请告诉我,怎样才能改进呢?
发布于 2020-09-10 14:19:52
这个模块的用例和原理是什么?我能看出它的作用,但我很难理解为什么我要这么做。
事实上,您有三个几乎相同的case语句来驱动这种行为,这是一种“代码气味”。在大多数其他OO语言中,您可以使用继承或接口以及工厂方法来确定要创建的对象的哪个子类(使用单个case语句)。在这种情况下,目的是抽象出连接到接口后面的数据库之间的区别(这似乎是您在方法database_authentication_success?中要做的)。但是元编程代码会生成明确命名的方法,用于连接到每种类型的数据库,这似乎正好相反,这使得使用起来更加困难。
https://codereview.stackexchange.com/questions/249154
复制相似问题