在相当大的Ruby应用程序中,我们有一种情况,即给定的对象由几个东西识别:name和id,比如说.这些值类型中的每一个都有不同的用途,因此不完全等效(id和name在不同的地方持续存在).因此,我们将围绕应用程序传递各种值(ID,名称和对象).这种情况至少在某种程度上似乎是一个问题,因为我们已经被错误所困扰,这些错误涉及不清楚应该将哪种类型传递给给定的函数.我实际上回想起多年来在许多应用程序中看到类似的问题代码,尽管我再也没有给出具体的名称.
Ruby作为一种无类型语言,不像C++那样允许基于类型的经典多态函数.作为一种解决方案,一位同事经常采用这种代码:
def initialize starting_value if starting_post.kindof? Foo @starting_id = get_id_from_foo starting_value elsif starting_post.kindof? Bar @starting_id = get_id_from_bar starting_value else raise "illegal type" end end
围绕我们的代码库(不仅仅是初始化器)的代码的增加导致我称之为"凌乱多态".它经常有效但有时会产生非常令人费解的情况.
我有三个问题.
作为反模式,这是否有正式的名称?"凌乱的界面?","凌乱的多态?" 或者是其他东西?
人们认为这有多糟糕?
有没有系统的方法来重构这个?我们在普通重构中遇到的挑战是我们创建的许多测试都使用这种松散类型,因此我们必须同时更改测试和实现,因此不会产生普通的基于测试的重构的支架效应.我认为实际上可以"加强"这种松散的多态性,并将代码抽象为函数而不是立即将其删除.但这是个好主意吗?
Steve Jessop.. 7
你不能定义某种类型的get_id方法,以便id返回自身,一个对象返回id,并且该名称执行它需要做什么来获取id?然后,你总是可以规范任何你知道将成为三者之一的东西.如果需要,也可以使用get_name和get_object方法.
也就是说,你已经定义了一个隐式的ThingWhatHasAnID接口,并将其作为函数参数的duck-type.
除非我遗漏了什么,否则我会称这种反模式"错失创造抽象的机会".
你不能定义某种类型的get_id方法,以便id返回自身,一个对象返回id,并且该名称执行它需要做什么来获取id?然后,你总是可以规范任何你知道将成为三者之一的东西.如果需要,也可以使用get_name和get_object方法.
也就是说,你已经定义了一个隐式的ThingWhatHasAnID接口,并将其作为函数参数的duck-type.
除非我遗漏了什么,否则我会称这种反模式"错失创造抽象的机会".