无法将班级拆分为较小的班级

时间:2019-01-09 11:11:21

标签: java sonarlint

我在将班级分成更小的部分时遇到麻烦。一个Dto拥有30个不同的Dto的情况很糟糕。现在我们需要这个selectDto的映射,这也迫使我们创建30种不同的映射类。 (我们在项目中也使用了mapstruct,这种情况与mapstruct可以处理的情况不同)

现在我的问题开始了:

我在对应的类中进行了所有映射。在基本的selectDto中,我的构造函数中有26个映射器,这很可怕:

SonarLint:构造函数具有26个参数,大于7个授权参数

我想出了如何分解这种情况的方法,但是我找不到方法。有什么建议吗?

我的构造函数包含26个参数:

    AssignedSelectMapper(AssignedOpDtoMapper assignedOpDtoMapper,
        AssignedOrderDtoMapper assignedOrderDtoMapper
// many more constructor parameters
) {
        this.assignedOptionCodeDtoMapper = assignedOptionCodeDtoMapper;
        this.assignedOrderCriteriaDtoMapper = assignedOrderCriteriaDtoMapper;
        // all settings
}

我要映射的公共函数,它为每个映射调用私有函数:

    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;
}

//我的私有函数的示例,该函数调用相应的映射器,其中我的所有私有函数都包含不同种类的类,例如OptionCodeDto。它们不会从相同的接口/类扩展而来。

 private List<AssignedSelectionCriteria> mapOps(List<OptionCodeDto> optionCodeDtos) {
        return this.assignedOpDtoMapper.mapCriterias(opDtos);
    }

//,这是反向映射。我需要与映射返回类型不同的类

// this is my public function for mapping.
public void assignSelectionTo(SelectionDto selectionDto,
    List<AssignedSelectionCriteria> assignedSelectionCriterias) {

    setOptionCodes(selectionDto, copyCriterias);
    setOrderCriteria(selectionDto, copyCriterias);
    // many more
}

这是反向映射私有函数,每个映射类都返回不同类型的dto,例如OptionCodeDto,而这些Dto都不是同一类的扩展。

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);
    }

3 个答案:

答案 0 :(得分:2)

创建界面AssignedSelectProvider

interface AssignedSelectProvider
{
    List<AssignedSelect> getAssignedSelects();
}

每个映射器都实现该接口,并且每个私有方法都移至相关的类:

class AssignedOpDtoMapper implements AssignedSelectProvider
{
    public List<AssignedSelect> getAssignedSelects()
    {
        return mapOps(getOps());
    }
}

AssignedSelectMapper获取构造函数中的提供程序列表,而不是26个参数:

class AssignedSelectMapper
{
    AssignedSelectMapper(List<AssignedSelectProvider> mappers)
    {
        //...
    }
}

这是26个参数,降至1。

答案 1 :(得分:2)

这就像对@Michaels answer的扩展。

带有接口的想法是一个好主意。尽管我认为可以更改界面以更适合您的用例:

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注入您的主类:

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 :(得分:0)

有2种解决方案

1。全部以1个参数传递:

假设您要在1个构造函数中传递30个参数(即DTO),然后制作一个主DTO来容纳所有30个DTO,然后将该DTO作为 ONE 参数传递。

例如:

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
<button id="add">Add Series</button> Click a bar to increment its value by 1.
<canvas id="chart"></canvas>

用于传递30个DTOS的呼叫者类

public class MasterDTO{

private ChildDto1 childDto1 ;
private ChildDto2 childDto2 ;
private ChildDto3 childDto3 ;
...
..
private ChildDto30 childDto30 ;
//public getter setter methds
}

功能类,期望值为30 DTOS

public class Caller{
  Functional fun = new Functional(masterDTO);

}

2。使用设置器方法:

仅传递7个元素作为构造函数的参数,然后使用object和call setter方法设置其余23个元素。

用于传递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();
}

}