英文:
How should I design a new function according to OOP?
问题
Design 1:
class A {
foo(): B { /* … */ }
}
Design 2:
class B {
static foo(a: A): B { /* … */ }
}
英文:
Say I need to add some function foo
that takes an instance of type A
and produces an instance of type B
(assuming A
and B
are interfaces). In object-oriented design, what are the design limitations of either of the following designs?
Design 1:
class A {
foo(): B { /* … */ }
}
Design 2:
class B {
static foo(a: A): B { /* … */ }
}
答案1
得分: 1
从技术角度看,没有区别。
面向对象编程(OOP)可以建议的是,在具体情况下(其中A
,B
和foo
表示特定内容),您可以参考SOLID/GRASP一系列建议,并检查是否有一项规则来判断哪种方法更好。
在面向对象编程中,这是一种责任的问题。
举三个例子:
1)A
是Order
,B
是ProcessingResult
,foo
是Place
,您只是在实现您的领域驱动设计(DDD)方法的领域模型。Place
的自然选择是Order
。
public class Order
{
public ProcessingResult Place() { ... }
}
2)A
是辅助类(Parameters
),B
是领域类,foo
是类的工厂方法。工厂方法的自然选择是它所应创建的类。
public class B
{
public static B Create( Parameters parameters ) { ... }
}
(然而,在这里也可以使用单独的工厂类,这完全取决于内容)
3)A
是FooUseCaseParameters
,B
是FooUseCaseResult
,foo
是Execute
,您只是在设计六边形架构的主要端口。在这种情况下,自然选择是一个新的类(C
),它将是FooUseCase
:
public class FooUseCase
{
public FooUseCaseResult Execute( FooUseCaseParameters useCase ) { ... }
}
英文:
From the technical point of view there's no difference.
What OOP can suggest is that in a concrete case (where A
, B
and foo
means something specific) you can refer to the SOLID/GRASP set of recommendations and check if there's a rule judging one approach over the other.
In OOP, it's a matter of responsibilities.
Take three examples:
-
A
isOrder
,B
isProcessingResult
andfoo
isPlace
and you are just implementing a domain model of your DDD approach. The natural choice forPlace
isOrder
public class Order { public ProcessingResult Place() { ... } }
-
A
is an auxiliary class (Parameters
),B
is a domain class andfoo
is a factory method of a the class. The natural choice for a factory method is the class it's supposed to createpublic class B { public static B Create( Parameters parameters ) { ... } }
(however, a separate factory class would also be correct here, it all depends on a content)
-
A
isFooUseCaseParameters
,B
isFooUseCaseResult
andfoo
isExecute
and you are just designing a primary port for your hexagonal architecture. The natural choice in this case is a new class (C
) which would be theFooUseCase
:public class FooUseCase { public FooUseCaseResult Execute( FooUseCaseParameters useCase ) { ... } }
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论