I have a Java application that needs to process some data. The data starts off in format A.

The application consists of a number of modules which are each capable of processing data. But not every module supports the same kind of data as in- and output. Module 1 accepts data in format A and outputs it in format B. Module 2 accepts data in format B and outputs it in format C. Module 3 takes data in either format A or format C and outputs format B. Another one takes B or C and returns the same format it received the data in. And so on, you get the idea.

And as if this situation was'nt bad enough already, there are a lot of modules, each with their own in- and output formats. Some match, some don't. The modules could be executed in any order, and the order is provided at runtime by the user.

I need to make sure that the modules are in an order where every in- and output matches. How can I accomplish that? Is there maybe some design pattern I don't know of that solves this?

Basically, I need a way to retrieve in- and output format of a module, compare it to another one, and sometimes cast an object to the type I figured out.

I had a couple ideas like retrieving the parameter and return types via reflection, but some data formats involve nested Generics which are erased at compile time. And other things I came up with wouldn't get around the fact that I'd probably have to figure out what type to cast to at runtime if I applied them.

Any thoughts and directions would be appreciated.

  • When you say that "the order is provided at runtime by the user", do you mean that you have to confirm that the user-provided order is doable, or do you have to provide a different order based on input and output requirements? Or, after reading a bit further, do you have to convert one format to another between modules? – BobDalgleish Jun 11 '18 at 16:11
  • @BobDalgleish I have to confirm that the user-provided order is doable. I do not need to convert anything between modules. On my "main-method", I'm currently looping through the list of modules specified by the user. There, I just know every module has the superclass Module. I have to check whether the next module in line supports the format the data is currently in, and that at runtime since I can't tell what the next module is at compile-time. – Namnodorel Jun 11 '18 at 21:16

A, B, and C should be different types, then you know which format you have by the type you are passed. There's no need for reflection or generics or any kind of run-time checks, you just have separate functions with different signatures to take each different type, then your code won't even compile if you try to pass a particular type to a module which doesn't support it.

If there's some specific reason this doesn't work for you then we'd probably need more information about your specifics to determine alternatives.

| improve this answer | |
  • The problem with "won't compile" is that, since module order is provided at runtime, there is no way of knowing at compile time what kind of format the data from the last module is in and thus, whether it can be proceeded to the next one. – Namnodorel Jun 11 '18 at 21:22

First I want to say that if Javas static type system really isn't working for you you can turn if off just by treating everything as an object.

If I can talk you down from that nuclear option I'd like to point out that knowing statically that aToB() takes an A and returns a B is not the same thing as knowing that the first module will be an A. You just know that if they call aToB() they'd better be working on some A like thing. Which makes sense since that all aToB() knows how to work on.

The modules could be executed in any order, and the order is provided at runtime by the user.

Not without causing an error they can't. Big thing I'd like to understand here is how the user is inputting this order. If the order is created without knowledge of the data then it's either going to break or it won't. If the order is created at run time when the data is known you can direct user input by graying out invalid operations before they click on them.

A very clean design that accomplishes this is to let every kind of data provide a list of valid operations. The name we gave this design pattern is "objects".

| improve this answer | |

The first problem to tackle is converting formats: For each format pair X and Y, there should be a method that transforms format X to format Y.

The second problem is to find for each module N what its input and output formats are.

Then, its a straightforward task to take a sequence of modules: (1, 2, 3, 4), and insert the mapping functions between each module: (1(A=>B), M(B=>B), 2(B=>C), M(C=>D), 3(D=>A), M(A=>E), 4(E=>B)). The notation M(A=>B) means the mapping function that takes format A and outputs format B.

If module 3 can take format C or format D, then you may not need to interpose a mapping function.

| improve this answer | |
  • I think I didn't explain my problem well enough :/ I don't need to insert additional functions anywhere, but have to verify that in- and output of my given functions match. And figuring out these in- and outputs as well as comparing them is what I'm having a hard time with, especially since some of the formats involve Generics which are not available at runtime. – Namnodorel Jun 11 '18 at 21:27
  • 1
    One way or another, you will need the metadata for each module. Since introspection won't give it to you, you either need to be able to ask each module what its input and output formats are, or you need an inventory that provides that. – BobDalgleish Jun 12 '18 at 18:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.