Pedro Linhares
Pedro Linhares

Reputation: 63

What's the best way to reuse code for performance while keeping a good Object Oriented design?

I am developing a scientific program where there are several time consuming functions that are called from different other functions. I want to optimize these calls by avoid calling the same function with the same parameters more than once without breaking OO concepts such as encapsulation.

I tried to formulate a basic example of what I have. Class A has an object of class B from where I calculate intermediate results needed by class A functions. For example, in order for the functionA and functionB to calculate its results, each function needs to call the time_consuming_function on the object from B. Usually this functions are called from within a loop so the parameters (1 and 2) are the same among calls to functionA and functionB.

class ClassA {
  ClassB obj // member object

  return_type functionA(parameter1, parameter2) {
    value1 = obj.time_consuming_function(parameter1)
    value2 = obj.time_consuming_function(parameter2)

    return some_operation_with(value1, value2)
  }

  return_type functionB(parameter1, parameter2) {
    value1 = obj.time_consuming_function(parameter1)
    value2 = obj.time_consuming_function(parameter2)

    return some_operation_with(value1, value2)
  }
}

One solution would be create a structure to hold the calculated values among calls to ClassA functions, such as this example:

class ClassA {
  ClassB obj // member object

  return_type functionA(data) { // data is a structure to hold the values
    if (data.is_empty()) {
      data.value1 = obj.time_consuming_function(parameter1)
      data.value2 = obj.time_consuming_function(parameter2)
    }

    return some_operation_with(data.value1, data.value2)
  }

  return_type functionB(data) { // same data obj as before

    // this time data is not empty, so no calculation needed
    if (data.is_empty()) {
      data.value1 = obj.time_consuming_function(parameter1)
      data.value2 = obj.time_consuming_function(parameter2)
    }

    return some_operation_with(data.value1, data.value2)
  }
}

Another solution would be create a class Data to hold the data beforehand. In this case, having the parameters 1 and 2, I would update all properties that change with this parameter on class Data and when executing my functions from class A I would only need to use the values calculated previously. The class A would provide an interface to the Data class.

class Data {
  ClassA class_a_obj

  void update_values_that_depend_on_parameter1(class_a_obj, parameter1) {
    value1 = class_a_obj.time_consuming_function(parameter1)
  }

  void update_values_that_depend_on_parameter2(parameter2) {
    value2 = class_a_obj.time_consuming_function(parameter2)
  }
}

class ClassA {
  ClassB obj // member object

  return_type functionA(data) {
    return some_operation_with(data.value1, data.value2)
  }

  return_type functionB(data) { // same data obj as before

    return some_operation_with(data.value1, data.value2)
  }

  return_type time_consuming_function(parameter) {
    return obj.time_consuming_function(parameter)
  }
}

I wanted to know what you think of this problem and the proposed solutions. Are there other suitable and efficient solutions?

TL;DR:

I have a program that makes several calculations and each of this calculations calls functions to get intermediate values. These values are the same when called from functions that receive the same parameters, I am looking for a way to optimize these calls reusing those intermediate values.

What is the best way to reuse those values while still keeping a good Object Oriented design??

Upvotes: 1

Views: 122

Answers (1)

Mario The Spoon
Mario The Spoon

Reputation: 4859

Encapsulate the acces to these methods/ objects via a proxy that caches recent results and returns the cached result.

Upvotes: 3

Related Questions