0

I asked this question on SO but someone pointed out that I would be better off here. He's most likely right. So here I go!

So I just wanted an opinion. I have 2 different ways to approach the problem. Okay so I have a system that I wanna design toward the future. I have some types of objects wich takes as parameters an object implementing an Interface wich can itself contain another object Implementing another interface and so on.

In this way i have

A(InterfaceB B)->B(InterfaceC C)->C(InterfaceD D) ...

Until i get to a point where the object does not contain another one. Every interfaces implement a common interface. So I have

Parent->InterfaceB   ---   Parent->InterfaceC   ---   Parent->InterfaceD

But InterfaceD does not necessarily implement InterfaceB. Because an interface does not have only one implemention, I have multiple possible trees.

A(InterfaceB B)->B(InterfaceC C)->C(InterfaceD D)->...

and

A(InterfaceB B)->B(InterfaceC Y)->Y(InterfaceZ Z)->...

So my question is this : If i want to manage the possible trees, Am I better off using reflection to generate the possible trees on startup? Or would I be better off to hold the different trees in a xml file that I would parse on startup? I have to keep in mind that those Interface types and their implementations will keep coming on. So every time I add a new type, it has to be managed. I know both solution will work. My question is more like this : What would be the best approach to orient the system toward the future.

To add some context to the situation, here's an example of a case

All those interfaces expose an adaptor. Each adaptor may need another one to do its task. For instance, I have an adaptor wich parse some data. But then this data has to be communicated with a remote target. To do this it can use ethernet, serial port, etc... So I could have a generic parser wich takes a generic communicator. That's one of the different possibilities.

If you need some clarifications dont hesitate!

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
Charles
  • 111
  • 4
  • 3
    On a more serious note, this is very abstract. Without knowing what the purpose of the interfaces are, it's difficult to advise you. Consider describing the specific scenario you are using this for. Maybe we can tell you a better way to do it. – Robert Harvey Sep 21 '13 at 17:54
  • Sure! - Here's a case i mentionned on SO : The thing is all those interface expose an adaptor. Each adaptor may need another one to do its task. For instance, I have an adaptor wich Parse some data. But then this data has to be communicated with a remote target. To do this It can use ethernet, Serial port, etc... So I could have a generic parser wich takes a generic communicator. That's one of the different possibilities – Charles Sep 21 '13 at 17:55
  • 1
    Put it in your question. Be specific. See also http://en.wikipedia.org/wiki/Inner-platform_effect – Robert Harvey Sep 21 '13 at 18:00
  • 2
    Still looks overly abstract. Are you familiar with [YAGNI](http://en.wikipedia.org/wiki/You_aren't_gonna_need_it)? What's the real world problem being solved? – Dan Pichelman Sep 21 '13 at 18:07
  • Okay so I read the article. Very interesting indeed. It is indeed a case of inner-platform. But in my case it's unnavoidable. The thing is im building a system that takes a bunch of input and according to the input, a generic output is generated. Since the output is very generic, there's almost no dependendy. All the output requires, is an adaptor. The thing I have to mention is this : I'm not trying to reproduce things my OS can do already : I'm interacting between many systems, OS, etc – Charles Sep 21 '13 at 18:11
  • @DanPichelman I'm building a domotic system for my place. I have a server taking inputs from many different platforms such as cameras, switches, microphones, etc. Depending on the user preferences, an output will be generated according to the input. Since I can't know in advance what the user wants, I have to make it very generic until the very last moment. But the thing is I DO need it dan :( – Charles Sep 21 '13 at 18:14
  • 3
    `I have a system that I wanna design toward the future` - well, there's your problem. You obviously don't know what you're going to need in the future, otherwise you would have been specific and said "I need to design for {specific thing}" and not "design toward the future". Either find out what you *really* need this thing to do, preferably with prototyping, A/B testing and a fast release cycle... or just design it to be simple until you understand the market better. – Aaronaught Sep 21 '13 at 18:18
  • Have a look at the [Abstract Factory pattern](http://en.wikipedia.org/wiki/Abstract_factory_pattern). – Robert Harvey Sep 21 '13 at 18:20
  • Looks a bit like flow based development, maybe take a look at it's concepts: http://noflojs.org – Luc Franken Sep 21 '13 at 18:20
  • @RobertHarvey Interesting! I knew about factories but I never thought of an abstract factory. I'll read your article Luc. – Charles Sep 21 '13 at 18:31
  • @Aaronaught I totally agree with you. When designing a system you MUST know where it is going. That is my case. I know the objective of the system. It takes inputs that are made very generic on purpose and generate very generic outputs. It stays generic until the adaptor. But I will disagree with you about the fact that we don't design a system toward the future. A system evolves. The objective never change but the results may improve. – Charles Sep 21 '13 at 18:38
  • @LucFranken On a side note, the link you gave, indeed looks a lot like my case, I'll look at the concept as you said. I'll try to figure out some more details – Charles Sep 21 '13 at 18:41
  • 2
    You are wrong. The *objective* of your system is to help users accomplish a specific task. If your users are programmers and the task they want to accomplish is to build their own signal/message-processing system, then perhaps the *function* of your system might be to "take generic input and produce generic output", however unlikely. If that's not a 100% accurate description of your domain, then you are simply passing the buck with respect to requirements analysis. There are plenty of workflow engines around, and people generally only use them when supporting multi-tenant SaaS apps. – Aaronaught Sep 21 '13 at 19:05
  • @Aaronaught: Highly-generalized systems are not exactly a novel concept. For example, EAV tables are widely used in medical and other fields for their generality; despite their disadvantages, they are still used because the generality they provide is not practical by conventional means. Though I agree that it is possible that the OP's application is under-specified. – Robert Harvey Sep 21 '13 at 19:33
  • possible duplicate of [Design for future changes or solve the problem at hand](http://programmers.stackexchange.com/questions/59810/design-for-future-changes-or-solve-the-problem-at-hand) – gnat Sep 21 '13 at 20:13
  • 2
    I learned a new word today "[domotic](http://future.wikia.com/wiki/Domotics)". Since this is home automation *for your place*, you are the user. You have a finite set of inputs, a finite set of outputs, and a single source of specifications. Design something that can be built in a couple of months, expect it to work for a few (5 - 8) years, then repeat the process. Technology advances so fast that the extra effort you put into "future proofing" will be wasted. Roll with it. – Dan Pichelman Sep 21 '13 at 20:14
  • 1
    @RobertHarvey: Highly *customizable*, sure. Again, I'd reference multi-tenant SaaS apps as an example, like SalesForce or SAP. But these systems are still designed around a specific set of needs, still have a sizable baked-in core product, and the customizations fall within specific boundaries. It's not enough to say "it should be able to read anything from anywhere and write anything to anywhere" - anything that generic would have no advantage over an actual programming language. – Aaronaught Sep 21 '13 at 20:56
  • The thing is, this is not underly specific. Here this project does not try to do everything. It's goal is to integrate together many systems that do not normally work together. The system do not do all the processing. The work is exterior. Therefore the objective is precise. Make the different systems work together. And yes it is true, I am the user. So I set the needs. And that is the reason I go by iterations. So I make a subpart of the system work and I go for the next. To do so, I need a system that is adaptive enough. – Charles Sep 21 '13 at 21:26
  • An underspecified system would be hard to bring up and maintain because of the lack of goal. But it is not the case at the moment. The system actually support an infinity of devices as long as the hardware allows it. And the good thing is it works. I already have tested a couple of things. My point is the system works, but it needs a refined way to manage the increasing number of possible output types. – Charles Sep 21 '13 at 21:33
  • 1
    @gnat Yea I totally agree with that. That is how the system is designed. With the present architecture it is a pretty simple thing to add just when I need to. That is the reason I asked this question, this is the last part missing before I can literally add module by module with the rest of the system building itself while including it. At the moment it costs nothing to add or remove a module. I just have to do the configurations manually after. Wich is not hard, but not optimal. – Charles Sep 21 '13 at 21:40
  • I still think this is ridiculously vague, but the only analogy I can think of is to different business systems in an organization that aren't programmed to talk to each other. The best pattern we have today for integrating them is pub/sub on a message bus. You define whatever messages are relevant to your domain, various services (or device wrappers in your case) publish them when something interesting happens, and other services/devices can express an interest (subscribe) and respond however they want. But don't *build* a bus, just *use* one, there are tons already. – Aaronaught Sep 22 '13 at 13:46
  • @Aaronaught Thank you for your input. I'm familiar with the bus concept. It is very useful in many ways. But I'll admit I have not given it a thought. So I'll think about it! – Charles Sep 22 '13 at 19:17

3 Answers3

0

I've been giving this some thought, and I believe your approach with interfaces is counter-intuitive. If you really need this kind of flexibility, interfaces are the opposite of what you want, because interfaces establish specificity, not generality.

Unless, of course, you have a single interface that looks something like this:

public interface ICommand
{
    void Execute(string command);
}

Which is actually what I suggest you do. You can make that string anything you want; no need for any additional interfaces.

If you want to make it a bit more sophisticated, you can pass XML to your command, and deserialize it to an instance of a type. You can even make it polymorphic by adding a parameter that specifies the type you want to deserialize to.

My point is that trying to specify your command interface using Interfaces is de-generalizing, which is the opposite of what you want.

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
  • That's exactly my case. I have the kind of interface you suggested. That is how my outputs are generated. All I know is what the output is supposed to do. But then even if we know that, we only know the starting point of the command. After that there is a bunch of step to be taken before doing the actual task. For instance we need an adaptor that will adapt to the right MCU. Then we need the means of transportation. And yea I think xml will solve the problem. If at initial configuration someone manually input the settings, then it can be serialized in a xml file. – Charles Sep 26 '13 at 00:44
  • Since you seem to be the first to have suggested, I'll accept this answer. BUT! For everyone that would be stuck in my situation, also read the one Mike Brown posted. In my opinion both are worth a read, are exellent suggestion and could solve the problem at hand – Charles Sep 26 '13 at 00:53
0

I think you're thinking about it in too much of a top down matter. This is a signal processing problem. The route I'd follow is to have a message bus that your inputs (or let's call them producers) send messages to and that your adaptors (or consumers) listen to. Your consumers can be responsible for transforming the messages so that another consumer can understand it. To make it highly adaptable, the consumers should be responsible for one thing and one thing only. So one consumer would be responsible for transforming a message, another would be responsible for taking a specific message and generating output.

A great book to read for pointers on how to create such a system would be Enterprise Integration Patterns.

Michael Brown
  • 21,684
  • 3
  • 46
  • 83
  • As mentionned on the other post, your solution sounds quite good. Sadly I can only accept one answer. – Charles Sep 26 '13 at 00:55
-3

I will answer your question with a question. Why do you need to manage the trees in such a way that you need to know what contains what?

The point of interfaces is to set up an abstract contract where the user doesn't need to know what the object does and how it does it. All the user needs to know is the interface. Knowing what is contained in what violates the boundaries of the object.

The system should be able to unroll itself at the end without you needing to know the specific details of what contains what.

Joe McCay
  • 149
  • 8
  • 1
    Actually it's been answered in the hundreds of comments after the question. But there's so many its normal you havent read it. The goal of the system is to integrate many different systems together. I don't know in advance what the inputs are going to be. Neither are the outputs. So this chain of interface let's me make some very generic objects that can be used in any way. All that is required is to chain the right ones to obtain the desired output. So just like the example in the question, if the goal is to remote, attach the serial port adaptor, or Wifi if thats what is required – Charles Sep 22 '13 at 18:55