5

I have an iterative algorithm and I want to print the progress. However, I may also want it not to print any information, or to print it in a different way, or do other logic. In an object oriented language, I would perform the following solutions:

Solution 1: virtual method

have the algorithm class MyAlgoClass which implements the algo. The class also implements a virtual reportIteration(iterInfo) method which is empty and can be reimplemented. Subclass the MyAlgoClass and override reportIteration so that it does what it needs to do. This solution allows you to carry additional information (for example, the file unit) in the reimplemented class.

I don't like this method because it clumps together two functionalities that may be unrelated, but in GUI apps it may be ok.

Solution 2: observer pattern

the algorithm class has a register(Observer) method, keeps a list of the registered observers and takes care of calling notify() on each of them. Observer::notify() needs a way to get the information from the Subject, so it either has two parameters, one with the Subject and the other with the data the Subject may pass, or just the Subject and the Observer is now in charge of querying it to fetch the relevant information.

Solution 3: callbacks

I tend to see the callback method as a lightweight observer. Instead of passing an object, you pass a callback, which may be a plain function, but also an instance method in those languages that allow it (for example, in python you can because passing an instance method will remain bound to the instance). C++ however does not allow it, because if you pass a pointer to an instance method, this will not be defined. Please correct me on this regard, my C++ is quite old.

The problem with callbacks is that generally you have to pass them together with the data you want the callback to be invoked with. Callbacks don't store state, so you have to pass both the callback and the state to the Subject in order to find it at callback execution, together with any additional data the Subject may provide about the event is reporting.

Question

My question is relative to the fact that I need to implement the opening problem in a language that is not object oriented, namely Fortran 95, and I am fighting with my usual reasoning which is based on python assumptions and style. I think that in Fortran the concept is similar to C, with the additional trouble that in C you can store a function pointer, while in Fortran 95 you can only pass it around.

Do you have any comments, suggestions, tips, and quirks on this regard (in C, C++, Fortran and python, but also in any other language, so to have a comparison of language features that can be exploited on this regard) on how to design for an algorithm that must report progress to some external entity, using state from both the algorithm and the external entity ?

11
  • 3
    "have the algorithm class..." I stopped reading right there. Algorithms are implemented in functions, not in classes. Classes wrap state and means (algorithms) to alter that state. If all you have is some input values and all you need is some output values computed according to some algorithm, what you need is a function, not a class. Unfortunately, the popular so-called OO languages (like Java and C#) fail to educate their users about this simple fact.
    – sbi
    Feb 18, 2011 at 13:35
  • @sbi: But that is what static methods are for in Java and C#, since you don't have free-floating functions available to you. Define a class that implements the function(s) you need for your algorithm. A little bit of extra overhead, but not unreasonable considering the nature of the languages. All that being said, however, yes, I agree with you 100% in the purpose of functions vs. classes and the need for better education regarding those differences.
    – Will
    Feb 18, 2011 at 13:49
  • 1
    @chaz8705: and I restate the obvious. I never said that an algorithm is not what you say. I say that I am implementing an algorithm into a class that represents the algorithm (because it's convenient for me to do so), and in my question I called this entity an algorithm class. Any other discussion is just not on topic with the question. Feb 18, 2011 at 16:33
  • 2
    @Will: Java and C# use static functions because they don't have free functions. If you have a class with one static function then that's just a clumsy syntactical workaround for the lack of free functions. I don't believe this invalidate my statement, though, because the algorithm is still implemented in the function, it's just that those languages require a semantically needless class wrapper around it.
    – sbi
    Feb 19, 2011 at 1:38
  • 1
    Why did you tag this question C C# Python when it's a FORTRAN 77 problem? This is easily managed in multiple ways in every modern language. Sep 30, 2017 at 19:36

6 Answers 6

5

Have you considered a "pump" pattern? Externalize the actual iteration, and store the complete state required to resume iteration inside the variables/structure performing the computation. Then just, every iteration, read some sort of progress state variable that gets written to by the algorithm.

It seems to me that due to the primivite language you are stuck with, you are limited to a few simple approaches that aren't ideal.

2

To add a C++ aspect to this, modern C++ has several solutions to #3. You can bind just about any compatible callable (be it a function, function object, or member function) entity using std::bind, use std::function for the same task, or use a lambda function.

All three possibilities are supported by the next C++ standard, (expected to be released this year). The two library solutions are already provided by almost all compilers (although they might be in the namespace std::tr1, rather than std), and if not can be used as part of the phenomenal boost libraries (then in namespace boost). Lambda functions are implemented by recent VC and GCC versions.

I think the easiest way to make use of this would be to make the callback parameter type either a template argument or std::function<void(progress_info_t)>.

2
  • Here (newty.de/jakubik/callback.html) is a very good implementation of the callback pattern implemented in C++. I have actually used this and it works very well.
    – Will
    Feb 19, 2011 at 14:19
  • 1
    @Will: So I had a very short look at this. Correct me if I'm wrong, but it seemed to propagate a classic OO callback style. (I saw polymorphism and member pointers.) Templates have a lot of advantages over this. They are the reason C++' std::sort() often outperforms C's qsort().
    – sbi
    Feb 19, 2011 at 21:33
0

Are you doing an iterative process whose convergence properties aren't easily predictable, but which you wish to continue until it converges, or figures out its in deep doo-doo? If it doesn't "print" information on its progress (number of iterations, a residual (or whatever figure of progress makes sense), then the user might get concerned, "is it in trouble? Could it be hung, or be in an infinite loop?". So one thing would be to store these properties in an address (or external file) that can be read by some monitoring process. Or is your concern quite different from this??

1
  • my concern is how to do a proper design of this as a general software design pattern Feb 18, 2011 at 23:11
0

Pass the reference to your callback function as an additional parameter into your algorithm.

If you don't want to bother with the callbacks this invocation, pass a simple stub function that does nothing more than return.

0

Depending on the nature of the product, I have known more than a couple developers who have just put a sliding progress bar that just goes every second or two (few percent per tick), which is totally unrelated to the actual progress. There is one callback at the end to make it flash to 100% (or not). It's a total hack, but then again a progress bar is just a tool to tell the user "please wait, yes the program hasn't broken and is actually doing something."

If you're talking about a big complicated install progress notification this isn't a good idea, but for something that might take 30 seconds or less it's fine.

In other words, if it's a small operation, don't worry about being super accurate, or even representative at all, in your progress reporting.

-1

Since there's not an accepted answer i throw a possible solution. Have you tried a design where the values are observables instead of the algorithm?

In c++ i would do something like this:

template <typename T>
struct observable
{
typedef function<void(const T&)> observer;

list<observer> observers;

T val;

void notify(const T& val)
{
    for(auto&& o : observers)
        o(val);
}

void operator=(const T& val)
{
    this->val = val;
    notify(this->val);
}

void watch(const observer& obs)
{
    observers.push_back(obs);
}

};

And then in my algo:

struct myalgo
{
observable<info> _info;

void do_work(params)
{
    info myinfo;
    do { job(); info.x = "info1" info.y = "info2"; _info = myinfo; }
    while (!has_to_stop());
}

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