Type-safe two-step computational pipelines

Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
0
down vote
favorite
I have several "computation pipelines" that share the same purpose and number of steps, even if the step implementations and the classes of the the intermediate values that are passed between them are different for each pipeline. For example, they might be
$$
newcommandptr[1]oversetmathtt#1longrightarrow
textttRequest ptrstep 1 A ptrstep 2 textttResponse
$$
or
$$
textttRequest ptrstep 1 B ptrstep 2 textttResponse
$$
The start and end of the pipelines are always the same.
I want to avoid duplicating the common "interstitial code" between the steps,
which may do things like logging or error handling. I also want to ensure that:
- Implementation inheritance is not used. This appears to rule out the "template method" pattern.
- Type safety is maintained, in the sense that step implementations should not have to downcast an intermediate value at any point.
I came up with the following solution. First, a generic Pipeline interface, parameterized with the type of the intermediate values and with one method for each step:
public interface Pipeline<A>
A step1(Request request);
Response step2(A intermediate);
Second, a Runner class that is ignorant of the exact type of the intermediate steps:
public final class Runner
private final Pipeline<?> pipeline;
public Runner(Pipeline<?> pipeline)
super();
this.pipeline = pipeline;
public Response runPipeline(Request request)
// This doesn't fly, wildcard trouble
// return pipeline.step2(pipeline.step1(request));
// With the helper it works
return runPipeline(request,pipeline);
// wildcard capture helper
public static <A> Response runPipeline(Request request, Pipeline<A> pipeline)
A intermediate = pipeline.step1(request);
//
// shared interstitial code here
//
return pipeline.step2(intermediate);
Is there a better way of doing this? Does this type of solution have a name, is it used anywhere else?
java generics
add a comment |Â
up vote
0
down vote
favorite
I have several "computation pipelines" that share the same purpose and number of steps, even if the step implementations and the classes of the the intermediate values that are passed between them are different for each pipeline. For example, they might be
$$
newcommandptr[1]oversetmathtt#1longrightarrow
textttRequest ptrstep 1 A ptrstep 2 textttResponse
$$
or
$$
textttRequest ptrstep 1 B ptrstep 2 textttResponse
$$
The start and end of the pipelines are always the same.
I want to avoid duplicating the common "interstitial code" between the steps,
which may do things like logging or error handling. I also want to ensure that:
- Implementation inheritance is not used. This appears to rule out the "template method" pattern.
- Type safety is maintained, in the sense that step implementations should not have to downcast an intermediate value at any point.
I came up with the following solution. First, a generic Pipeline interface, parameterized with the type of the intermediate values and with one method for each step:
public interface Pipeline<A>
A step1(Request request);
Response step2(A intermediate);
Second, a Runner class that is ignorant of the exact type of the intermediate steps:
public final class Runner
private final Pipeline<?> pipeline;
public Runner(Pipeline<?> pipeline)
super();
this.pipeline = pipeline;
public Response runPipeline(Request request)
// This doesn't fly, wildcard trouble
// return pipeline.step2(pipeline.step1(request));
// With the helper it works
return runPipeline(request,pipeline);
// wildcard capture helper
public static <A> Response runPipeline(Request request, Pipeline<A> pipeline)
A intermediate = pipeline.step1(request);
//
// shared interstitial code here
//
return pipeline.step2(intermediate);
Is there a better way of doing this? Does this type of solution have a name, is it used anywhere else?
java generics
This seems related softwareengineering.stackexchange.com/questions/267037/⦠but it's not exactly what I want, because in my case I have commonRequestandResponseclasses and I want the different pipelines to be of the same type.
â Daniel DÃaz Carrete
Mar 4 at 8:09
add a comment |Â
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I have several "computation pipelines" that share the same purpose and number of steps, even if the step implementations and the classes of the the intermediate values that are passed between them are different for each pipeline. For example, they might be
$$
newcommandptr[1]oversetmathtt#1longrightarrow
textttRequest ptrstep 1 A ptrstep 2 textttResponse
$$
or
$$
textttRequest ptrstep 1 B ptrstep 2 textttResponse
$$
The start and end of the pipelines are always the same.
I want to avoid duplicating the common "interstitial code" between the steps,
which may do things like logging or error handling. I also want to ensure that:
- Implementation inheritance is not used. This appears to rule out the "template method" pattern.
- Type safety is maintained, in the sense that step implementations should not have to downcast an intermediate value at any point.
I came up with the following solution. First, a generic Pipeline interface, parameterized with the type of the intermediate values and with one method for each step:
public interface Pipeline<A>
A step1(Request request);
Response step2(A intermediate);
Second, a Runner class that is ignorant of the exact type of the intermediate steps:
public final class Runner
private final Pipeline<?> pipeline;
public Runner(Pipeline<?> pipeline)
super();
this.pipeline = pipeline;
public Response runPipeline(Request request)
// This doesn't fly, wildcard trouble
// return pipeline.step2(pipeline.step1(request));
// With the helper it works
return runPipeline(request,pipeline);
// wildcard capture helper
public static <A> Response runPipeline(Request request, Pipeline<A> pipeline)
A intermediate = pipeline.step1(request);
//
// shared interstitial code here
//
return pipeline.step2(intermediate);
Is there a better way of doing this? Does this type of solution have a name, is it used anywhere else?
java generics
I have several "computation pipelines" that share the same purpose and number of steps, even if the step implementations and the classes of the the intermediate values that are passed between them are different for each pipeline. For example, they might be
$$
newcommandptr[1]oversetmathtt#1longrightarrow
textttRequest ptrstep 1 A ptrstep 2 textttResponse
$$
or
$$
textttRequest ptrstep 1 B ptrstep 2 textttResponse
$$
The start and end of the pipelines are always the same.
I want to avoid duplicating the common "interstitial code" between the steps,
which may do things like logging or error handling. I also want to ensure that:
- Implementation inheritance is not used. This appears to rule out the "template method" pattern.
- Type safety is maintained, in the sense that step implementations should not have to downcast an intermediate value at any point.
I came up with the following solution. First, a generic Pipeline interface, parameterized with the type of the intermediate values and with one method for each step:
public interface Pipeline<A>
A step1(Request request);
Response step2(A intermediate);
Second, a Runner class that is ignorant of the exact type of the intermediate steps:
public final class Runner
private final Pipeline<?> pipeline;
public Runner(Pipeline<?> pipeline)
super();
this.pipeline = pipeline;
public Response runPipeline(Request request)
// This doesn't fly, wildcard trouble
// return pipeline.step2(pipeline.step1(request));
// With the helper it works
return runPipeline(request,pipeline);
// wildcard capture helper
public static <A> Response runPipeline(Request request, Pipeline<A> pipeline)
A intermediate = pipeline.step1(request);
//
// shared interstitial code here
//
return pipeline.step2(intermediate);
Is there a better way of doing this? Does this type of solution have a name, is it used anywhere else?
java generics
edited Mar 4 at 3:44
200_success
123k14142399
123k14142399
asked Mar 4 at 0:25
Daniel DÃaz Carrete
29817
29817
This seems related softwareengineering.stackexchange.com/questions/267037/⦠but it's not exactly what I want, because in my case I have commonRequestandResponseclasses and I want the different pipelines to be of the same type.
â Daniel DÃaz Carrete
Mar 4 at 8:09
add a comment |Â
This seems related softwareengineering.stackexchange.com/questions/267037/⦠but it's not exactly what I want, because in my case I have commonRequestandResponseclasses and I want the different pipelines to be of the same type.
â Daniel DÃaz Carrete
Mar 4 at 8:09
This seems related softwareengineering.stackexchange.com/questions/267037/⦠but it's not exactly what I want, because in my case I have common
Request and Response classes and I want the different pipelines to be of the same type.â Daniel DÃaz Carrete
Mar 4 at 8:09
This seems related softwareengineering.stackexchange.com/questions/267037/⦠but it's not exactly what I want, because in my case I have common
Request and Response classes and I want the different pipelines to be of the same type.â Daniel DÃaz Carrete
Mar 4 at 8:09
add a comment |Â
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f188759%2ftype-safe-two-step-computational-pipelines%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
This seems related softwareengineering.stackexchange.com/questions/267037/⦠but it's not exactly what I want, because in my case I have common
RequestandResponseclasses and I want the different pipelines to be of the same type.â Daniel DÃaz Carrete
Mar 4 at 8:09