Kh.
Kh.

Reputation: 1

How to avoid duplication in Java?

I have such a construction :

private Plan createPlan() {
  return new Plan(
        project(),
        "Plan Name", "PLANKEY")
        .description("Plan created from (enter repository url of your 
         plan)")
        .stages(
                new Stage("Stage 1")
                        .jobs(new Job("Build & run", "RUN")
                                .tasks(
                                        new ScriptTask().inlineBody("echo Hello!”))),

                new Stage("Stage 2”)
                        .jobs(new Job("Build & run", "RUN")
                                .tasks(
                                        new ScriptTask().inlineBody("echo Hello!”))),

                new Stage("Stage 3”)
                        .jobs(new Job("Build & run", "RUN")
                                .tasks(
                                        new ScriptTask().inlineBody("echo Hello!”))),

                new Stage("Stage 4”)
                        .jobs(new Job("Build & run", "RUN")
                                .tasks(
                                        new ScriptTask().inlineBody("echo Hello!”))),

);
}

How to avoid duplication of code? Pieces of code inside "new stage" are identical, with same paramertrs except name of new stage ("Stage 1", "Stage 2", "Stage 3"...).

Thank you!

Upvotes: 0

Views: 120

Answers (5)

PeterOeClausen
PeterOeClausen

Reputation: 420

(The long and hard solution (but will benefit you later on)) One solution could be to hide the instance creation away with a Factory design pattern: https://www.youtube.com/watch?v=ub0DXaeV6hA

That's usually the solution if you don't want to write long class installations.

(The easy and quick solution): You could also just make a method called CreateStage(String stageName) that takes a String input, namely the name of the stage, and returns a new created Stage object:

public Stage CreateStage(String stageName){
    return new Stage(stageName)
                    .jobs(new Job("Build & run", "RUN")
                            .tasks(
                                    new ScriptTask().inlineBody("echo Hello!”)));
}

And just call that for each stage you want in your stages collection. :-)

For more tips, Google: How to avoid code-duplication.

Upvotes: 1

Anton Balaniuc
Anton Balaniuc

Reputation: 11739

You add the same object 4 times:

Job commonJob = new Job("Build & run", "RUN").tasks(
                     new ScriptTask().inlineBody("echo Hello!”));

Why not assigning it to a variable and just use it instead?

new Stage("Stage 1").jobs(commonJob),
new Stage("Stage 2").jobs(commonJob),
...

Which is still not ideal because you have to create Stage objects "manually". If Plan#stages has an var-args signature Plan.stages(Stage ... stages), you can use a for-loop.

Stage[] stages = new Stage[4]; 
for(int i = 0; i < stages.length; i ++) {
    stages[i] = new Stage("Stage " + (i + 1)).jobs(commonJob);
}

and later on new Plan().stages(stages);

Or you can even do in a functional way if you wish using java-9 IntStream.interate method:

new Plan().stages(
                  IntStream.iterate(1, i -> i < 5, i -> i + 1)
                            .mapToObj(i -> new Stage("Stage " + i).jobs(commonJob))
                           .toArray()
         );

Upvotes: 0

Richard Stokes
Richard Stokes

Reputation: 533

This assumes that the function stages takes an array of stages as a parameter. Create a list of stages then convert to an array and pass that in.

private Plan createPlan() {

  List<Stage> stagesList = new ArrayList<>();
  for(int i = 1; i < 5; i++) {
      stages.add(new Stage("Stage " + i)
                        .jobs(new Job("Build & run", "RUN")
                                .tasks(
                                        new ScriptTask().inlineBody("echo Hello!”)))
  } // end of for

  Stage[] stagesArray = new Stage[stagesList];
  stagesArray = stagesList.toArray(stagesArray);

  return new Plan(
        project(),
        "Plan Name", "PLANKEY")
        .description("Plan created from (enter repository url of your 
         plan)")
        .stages(stagesArray);
} // end of createPlan

Upvotes: 0

OhleC
OhleC

Reputation: 2890

Extract a method:

private Stage createStage(String name) {
    return new Stage(name)
                    .jobs(new Job("Build & run", "RUN")
                            .tasks(
                                    new ScriptTask().inlineBody("echo Hello!”))
}

and simply pass the stage names

...
.stages(createStage("Stage 1"), createStage("Stage 2"), createStage("Stage 3"), createStage("Stage 4"))

Upvotes: 1

Steve11235
Steve11235

Reputation: 2923

Be careful about trying to over-optimize your code. If a Plan has four stages, then you will need to add the four stages. You could add a loop, but that implies you have some source of values for your loop, such as a List of some sort. Personally, I would stick with what you have, until your requirements lead you to refactor.

Upvotes: 0

Related Questions