无法将 Class 拆分成更小的
Can't Split Class into Smaller Ones
我无法将 class 拆分成更小的部分。我们有一个 Dto 拥有 30 个不同的 Dto 的糟糕情况。现在我们需要这个 selectDto 的映射,这也迫使我们制作 30 个不同的映射 class。 (我们在项目中也使用了mapstruct,这个场景是mapstruct无法处理的)
现在我的问题开始了:
我在相应的 class 中做了所有映射。在基础 selectDto 中,我的构造函数中有 26 个映射器,这太可怕了:
SonarLint:构造函数有26个参数,大于7个授权
我想出了如何拆分这种场景的方法,但我找不到方法。有什么建议吗?
我的构造函数持有 26 个参数:
AssignedSelectMapper(AssignedOpDtoMapper assignedOpDtoMapper,
AssignedOrderDtoMapper assignedOrderDtoMapper
// many more constructor parameters
) {
this.assignedOptionCodeDtoMapper = assignedOptionCodeDtoMapper;
this.assignedOrderCriteriaDtoMapper = assignedOrderCriteriaDtoMapper;
// all settings
}
我的 public 映射函数,它为每个映射调用私有函数:
public List<AssignedSelect> assignSelectFrom(SelectDto selectDto) {
Objects.requireNonNull(selectionDto, "selectionDto can not be NULL");
List<AssignedSelect> assignedSelects= new ArrayList<>();
assignedSelects.addAll(this.mapOps(selectionDto.getOps()));
assignedSelects.addAll(this.mapOra(selectionDto.getOra()));
assignedSelects.addAll(this.mapOrs(selectionDto.getOrs()));
assignedSelects.addAll(this.mapSs(selectionDto.getSs()));
assignedSelects.addAll(this.mapDels(selectionDto.getDels()));
assignedSelects.addAll(this.mapMs(selectionDto.getMs()));
assignedSelects.addAll(this.mapBrs(selectionDto.getBrs()));
assignedSelects.addAll(this.mapEqs(selectionDto.getEqs()));
assignedSelects.addAll(this.mapPaints(selectionDto.getPaints()));
assignedSelects.addAll(this.mapBas(selectionDto.getBas()));
// more ...
// and more...
return assignedSelects;
}
// 我的私有函数示例,它调用相应的映射器,其中我所有的私有函数都由不同类型的 class 组成,例如 OptionCodeDto。它们不会从同一个 interface/class 延伸,也不能。
private List<AssignedSelectionCriteria> mapOps(List<OptionCodeDto> optionCodeDtos) {
return this.assignedOpDtoMapper.mapCriterias(opDtos);
}
// 这里是反向映射。我需要不同于我的映射 return 类型
的 class
// this is my public function for mapping.
public void assignSelectionTo(SelectionDto selectionDto,
List<AssignedSelectionCriteria> assignedSelectionCriterias) {
setOptionCodes(selectionDto, copyCriterias);
setOrderCriteria(selectionDto, copyCriterias);
// many more
}
这是反向映射私有函数,每个映射 class returns 不同类型的 dto,如 OptionCodeDto,其中 none 这些 Dto 从相同的 class 扩展.
private void setOptionCodes(SelectionDto selectionDto, List<AssignedSelectionCriteria> assignedSelectionCriterias) {
// this is where I have trouble, each mapping returns different Dto's
List<OptionCodeDto> optionCodeDtos =
this.assignedOptionCodeDtoMapper.mapAssignedCriterias(assignedSelectionCriterias;
selectionDto.setOptionCodes(optionCodeDtos);
}
创建接口AssignedSelectProvider
interface AssignedSelectProvider
{
List<AssignedSelect> getAssignedSelects();
}
每个mapper实现接口,每个私有方法移到相关class:
class AssignedOpDtoMapper implements AssignedSelectProvider
{
public List<AssignedSelect> getAssignedSelects()
{
return mapOps(getOps());
}
}
AssignedSelectMapper
在构造函数中获取提供者列表而不是 26 个参数:
class AssignedSelectMapper
{
AssignedSelectMapper(List<AssignedSelectProvider> mappers)
{
//...
}
}
26 个参数减少到 1 个。
这就像 的扩展。
带有界面的想法是个好主意。虽然在我看来可以更改界面以更适合您的用例:
interface SelectDtoProcessor {
void process(SelectDto dto,
Consumer<? super Collection<? extends AssignedSelect>> action);
}
现在每个映射器都实现了这个接口:
class AssignedOpDtoMapper implements SelectDtoProcessor {
@Override
public void process(SelectDto dto,
Consumer<? super Collection<? extends AssignedSelect>> action){
List<OptionCodeDto> ops = dto.getOps();
consumer.accept(mapCriterias(ops));
}
然后将所有这些 Processors
注入您的主 class:
private final List<SelectDtoProcessor> processors;
AssignedSelectMapper(List<SelectDtoProcessor> processors) {
this.processors = processors;
}
最后遍历您方法中的所有处理器:
public List<AssignedSelect> assignSelectFrom(SelectDto selectDto) {
Objects.requireNonNull(selectionDto, "selectionDto can not be NULL");
List<AssignedSelect> assignedSelects= new ArrayList<>();
for(SelectDtoProcessor processor: processors) {
processor.process(selectDto, assignedSelects::addAll);
}
return assignedSelects;
}
有 2 个解决方案
1.全部作为 1 个参数传递:
假设您在 1 个构造函数中传递 30 个参数(它们是 DTO),然后创建一个主 DTO 来容纳所有 30 个 DTO,并将该 DTO 作为 ONE 传递参数。
例如:
public class MasterDTO{
private ChildDto1 childDto1 ;
private ChildDto2 childDto2 ;
private ChildDto3 childDto3 ;
...
..
private ChildDto30 childDto30 ;
//public getter setter methds
}
来电者class传递了 30 个 DTOS
public class Caller{
Functional fun = new Functional(masterDTO);
}
功能性class 期望值为 30 DTOS
class Functional{
private ChildDto1 childDto1 ;
private ChildDto2 childDto2 ;
private ChildDto3 childDto3 ;
...
...
public Functional(MasterDTO masterDTO){
childDto1 = masterDTO.getChildDto1();
childDto2 = masterDTO.getChildDto2();
childDto3 = masterDTO.getChildDto3();
...
...
childDto30 = masterDTO.getChildDto30();
}
}
2。使用 Setters 方法:
仅传递 7 个元素作为构造函数的参数,然后使用对象并调用 setter 方法来设置剩余的 23 个元素。
来电者class传递了 30 个 DTOS
public class Caller{
Functional fun = new Functional(childDto1 ,childDto1 , ....childDto7 );
fun.setChildDto8(childDtoValue8);
fun.setChildDto9(childDtoValue9);
fun.setChildDto10(childDtoValue10);
...
...
fun.setChildDto30(childDtoValue30);
}
我无法将 class 拆分成更小的部分。我们有一个 Dto 拥有 30 个不同的 Dto 的糟糕情况。现在我们需要这个 selectDto 的映射,这也迫使我们制作 30 个不同的映射 class。 (我们在项目中也使用了mapstruct,这个场景是mapstruct无法处理的)
现在我的问题开始了:
我在相应的 class 中做了所有映射。在基础 selectDto 中,我的构造函数中有 26 个映射器,这太可怕了:
SonarLint:构造函数有26个参数,大于7个授权
我想出了如何拆分这种场景的方法,但我找不到方法。有什么建议吗?
我的构造函数持有 26 个参数:
AssignedSelectMapper(AssignedOpDtoMapper assignedOpDtoMapper,
AssignedOrderDtoMapper assignedOrderDtoMapper
// many more constructor parameters
) {
this.assignedOptionCodeDtoMapper = assignedOptionCodeDtoMapper;
this.assignedOrderCriteriaDtoMapper = assignedOrderCriteriaDtoMapper;
// all settings
}
我的 public 映射函数,它为每个映射调用私有函数:
public List<AssignedSelect> assignSelectFrom(SelectDto selectDto) {
Objects.requireNonNull(selectionDto, "selectionDto can not be NULL");
List<AssignedSelect> assignedSelects= new ArrayList<>();
assignedSelects.addAll(this.mapOps(selectionDto.getOps()));
assignedSelects.addAll(this.mapOra(selectionDto.getOra()));
assignedSelects.addAll(this.mapOrs(selectionDto.getOrs()));
assignedSelects.addAll(this.mapSs(selectionDto.getSs()));
assignedSelects.addAll(this.mapDels(selectionDto.getDels()));
assignedSelects.addAll(this.mapMs(selectionDto.getMs()));
assignedSelects.addAll(this.mapBrs(selectionDto.getBrs()));
assignedSelects.addAll(this.mapEqs(selectionDto.getEqs()));
assignedSelects.addAll(this.mapPaints(selectionDto.getPaints()));
assignedSelects.addAll(this.mapBas(selectionDto.getBas()));
// more ...
// and more...
return assignedSelects;
}
// 我的私有函数示例,它调用相应的映射器,其中我所有的私有函数都由不同类型的 class 组成,例如 OptionCodeDto。它们不会从同一个 interface/class 延伸,也不能。
private List<AssignedSelectionCriteria> mapOps(List<OptionCodeDto> optionCodeDtos) {
return this.assignedOpDtoMapper.mapCriterias(opDtos);
}
// 这里是反向映射。我需要不同于我的映射 return 类型
的 class// this is my public function for mapping.
public void assignSelectionTo(SelectionDto selectionDto,
List<AssignedSelectionCriteria> assignedSelectionCriterias) {
setOptionCodes(selectionDto, copyCriterias);
setOrderCriteria(selectionDto, copyCriterias);
// many more
}
这是反向映射私有函数,每个映射 class returns 不同类型的 dto,如 OptionCodeDto,其中 none 这些 Dto 从相同的 class 扩展.
private void setOptionCodes(SelectionDto selectionDto, List<AssignedSelectionCriteria> assignedSelectionCriterias) {
// this is where I have trouble, each mapping returns different Dto's
List<OptionCodeDto> optionCodeDtos =
this.assignedOptionCodeDtoMapper.mapAssignedCriterias(assignedSelectionCriterias;
selectionDto.setOptionCodes(optionCodeDtos);
}
创建接口AssignedSelectProvider
interface AssignedSelectProvider
{
List<AssignedSelect> getAssignedSelects();
}
每个mapper实现接口,每个私有方法移到相关class:
class AssignedOpDtoMapper implements AssignedSelectProvider
{
public List<AssignedSelect> getAssignedSelects()
{
return mapOps(getOps());
}
}
AssignedSelectMapper
在构造函数中获取提供者列表而不是 26 个参数:
class AssignedSelectMapper
{
AssignedSelectMapper(List<AssignedSelectProvider> mappers)
{
//...
}
}
26 个参数减少到 1 个。
这就像
带有界面的想法是个好主意。虽然在我看来可以更改界面以更适合您的用例:
interface SelectDtoProcessor {
void process(SelectDto dto,
Consumer<? super Collection<? extends AssignedSelect>> action);
}
现在每个映射器都实现了这个接口:
class AssignedOpDtoMapper implements SelectDtoProcessor {
@Override
public void process(SelectDto dto,
Consumer<? super Collection<? extends AssignedSelect>> action){
List<OptionCodeDto> ops = dto.getOps();
consumer.accept(mapCriterias(ops));
}
然后将所有这些 Processors
注入您的主 class:
private final List<SelectDtoProcessor> processors;
AssignedSelectMapper(List<SelectDtoProcessor> processors) {
this.processors = processors;
}
最后遍历您方法中的所有处理器:
public List<AssignedSelect> assignSelectFrom(SelectDto selectDto) {
Objects.requireNonNull(selectionDto, "selectionDto can not be NULL");
List<AssignedSelect> assignedSelects= new ArrayList<>();
for(SelectDtoProcessor processor: processors) {
processor.process(selectDto, assignedSelects::addAll);
}
return assignedSelects;
}
有 2 个解决方案
1.全部作为 1 个参数传递:
假设您在 1 个构造函数中传递 30 个参数(它们是 DTO),然后创建一个主 DTO 来容纳所有 30 个 DTO,并将该 DTO 作为 ONE 传递参数。
例如:
public class MasterDTO{
private ChildDto1 childDto1 ;
private ChildDto2 childDto2 ;
private ChildDto3 childDto3 ;
...
..
private ChildDto30 childDto30 ;
//public getter setter methds
}
来电者class传递了 30 个 DTOS
public class Caller{
Functional fun = new Functional(masterDTO);
}
功能性class 期望值为 30 DTOS
class Functional{
private ChildDto1 childDto1 ;
private ChildDto2 childDto2 ;
private ChildDto3 childDto3 ;
...
...
public Functional(MasterDTO masterDTO){
childDto1 = masterDTO.getChildDto1();
childDto2 = masterDTO.getChildDto2();
childDto3 = masterDTO.getChildDto3();
...
...
childDto30 = masterDTO.getChildDto30();
}
}
2。使用 Setters 方法:
仅传递 7 个元素作为构造函数的参数,然后使用对象并调用 setter 方法来设置剩余的 23 个元素。
来电者class传递了 30 个 DTOS
public class Caller{
Functional fun = new Functional(childDto1 ,childDto1 , ....childDto7 );
fun.setChildDto8(childDtoValue8);
fun.setChildDto9(childDtoValue9);
fun.setChildDto10(childDtoValue10);
...
...
fun.setChildDto30(childDtoValue30);
}