0

My question concerns general design of programs. When object a wants to send information to object b there are three possibilities:

  1. Control is outside of objects a and b and public methods of a and b are called:

    b.TakeInformation(a.getInformation());
    
  2. Control is inside of b:

In this case b does what it wants and sometimes asks a for information:

class A {
  public Information getInformatino() {
    // code omitted
  }
  // code omitted
}
class B {
  // code omitted
  void foo() {
    while (bar()) {
      information = a.getInformation();
      DoSomeWork(information);
    }
  }
}
  1. Control is inside of a:

In this case a does what it wants and sometimes it gives b infromation it is producing:

class A {
  // code omitted
  void foo() {
    while (bar()) {
      information = produceInformation()
      b.TakeInformation(information)
    }
  }
}
class B {
  // code omitted
  public void TakeInformation(information) {
    // code omitted
  }
}

What interests me the most is the fourth possibility with both a and b being callers and with none of them being callees.

The simplest answer what to do in such situation is: Rewrite one of the classes so that it is callee.

This does not satisfy me. For example let us suppose that A some strange kind of stream which doesn't allow me to read characters by calling a method ReadChar() a.k.a. getInformation() but instead it is a caller and every time a character is read from the input it calls b.giveInformation(character).

Suppose that I can't rewrite the class A. Then imagine that I program a class B which is a parser of some language. The parser B consists of a lot of functions and helping classes and uses ReadChar on many places in code.

The solution of the problem would require to rewrite class B so that it is called by giveInformation(character) instead of calling ReadChar(). That would be extremely painful and unintuitive.

The most elegant solution to this synthetic example would be creating the adapter which starts A and stores all the characters and then starts B and provides it the nececarry interface for reading characters.

Unfortunately this is not applicable in other scenarios when classes A anb B are communicating in both directions.

How can one generally solve such tasks?

Are there some programming languages with nonstandard paradigms where this task wouldn't be problem?

A several possible solutions or approaches comes to my mind. They consist of threads, pipes, assembly language or abuse of lazy evaluation, but none of them seem good enough or I don't know how to use them. I will summarize my ideas in an answer.

Thanks for any help.

2 Answers2

0

What I need can be rewritten in pseudocode using threads as follows:

class A {
  // code omitted
  void foo() {
    while (bar()) {
      information = produceInformation()
      wake thread b, send it information
      suspend this thread until result is received
      result = received result
      DoSomeWorkWithResult(result);
    }
  }
}

class B {
  // code omitted
  void foo() {
    while (bar()) {
      suspend this thread until information is received
      information = received information
      result = DoSomeWork(information);
      wake thread a, send it the result
    }
  }
}

However the nature of the task I am solving is not parallel. Actually no lines of code can ever be executed simultaneously. There are just to contexts which are being switched not runned parallel. So I doubt the use of threads is necessary. (And I am also unsure about what the overhead of threads would be.)

I will probably code this with threads even though there is no parallelism. However I am generally interested in possible ways how to solve these kinds of communications. I am sure it is solvable - at least in some programming languages.

In c++ and assembly language is surely everything possible. How can one use two stacks there and manually switch between contexts?

In any programming language could A, B be compiled to two executables. Standard output of A could B input of B. And with the use of named pipes the output of B can be again input of A. (However it requires serialization and deserialization of objects. Which I believe is unncececary. And I would also prefer one executable.)

In programming languages with lazy evaluation might be this paradigm somehow abused to solve such tasks.

E.g. in c# one could in class B implement IEnumerator(). When A would produce new information then MoveNext() would be called. The illusion that the control is inside B and suspending this 'thread' can be ensured by calling yield return;

The disadvantage of this approach is that the 'thread' can be suspended only in its main method. Or the same trick would have to be reapplied to all other methods which are supposed to suspend the thread.

Maybe asynchronous methods in c# could be somehow used to solve such tasks. But how?

0

Your design in answer is bad, worse than the design in original question. You added unnecessary coupling between class B and class A.

What you are looking probably is something like observer pattern. In observer pattern, a class just need to notify the subscriber that an action has already been executed without knowing which class subscribe and what will be executed when notified.

Fendy
  • 4,565
  • 1
  • 20
  • 25