Object Orientation is a wonderful way of segmenting your code - hiding algorithms within objects (encapsulating) so that the user of your code need now realise about / understand the algorithms. But this can mean that the user, unknowingly, runs potentially slow and complex code many times over when it's unnecessary to do so.
Let's take an example - I have an object type "game" of which I've created three and I call for the length of each game (let's pretend it's a complex algorithm) many times over - that's quite a realistic proposition if I were to be sorting by game length, or doing something else like that. The program that shows this initial example is at
[here] - I've added a global
counter to what would be a regular class and property to illustrate the number of
getminute calculations made ... and it turn out to be
30.
With only three objects, you may think I could simply calculate the number of minutes at the time the object is constructed - however, there many be applications where huge numbers of gaes are constructed and the length of the game is only required for a very few of them - net result being a lot of calculations made for no purpose at all. This "calculate at construct" approach also has problems if you provide and use a facility to change the input values to your object later on after it's been built - you need to code carefully to recalculate the output values at appropriate times so you always have it available. If I were to modify my control class to calculate on construction, there would be
13 calculations made.
An excellent solution to the "calculate on construct" v "calculate on use" dilemma is to set a flag on construct to say that the calculation has not been made, to calculate on
first use, and at that point to store the result for subsequent requests and set the flag to indicate that a stored result is available ... with that stored result returned in preference to a re-calculate. This is termed "caching the results". If there's a facility to change the input values within your object later, all you need do is set the stored ("cached") flag to false, thus forcing a recalculate and re-store if and when the calculation result is subsequently rerequested. This cuts the number of calculations in my example tojust
4.
Sample code -
[here]
Code amendments between my examples?
I have added
this.cached = 0
in the contructor
I have replaced
results = (this.time + 10) * this.players
return results
by
if not this.cached:
this.results = (this.time + 10) * this.players
this.cached = 1
return this.results
in the routine that calculates and returns the results
And I have replaced
this.time = time
by
if time != this.time:
this.cached = 0
this.time = time
in the routine which sets a new value for one of the inputs
For a class with lots of calculated values for each object, you'll need to decide which to store and which not to store, and whether to have a single "cached" variable that flags them all as stored as a "job lot" or whether to cache / store / flag individually. The decision will be 'data driven' in that it will depend on the relationship between the various values and how close it is.
This example is coded in Python, but the same principle should be applied across the other OO languages we teach - Perl, PHP, Ruby, Java (private courses only) and C++, and it can be applied to C structs and Lua tables too.
(written 2014-12-21, updated 2014-12-22)
Associated topics are indexed as below, or enter http://melksh.am/nnnn for individual articles
Q908 - Object Orientation and General technical topics - Object Orientation: Design Patterns [485] North, Norther and Northest - PHP 5 Objects - (2005-11-04)
[1224] Object Relation Mapping (ORM) - (2007-06-09)
[2322] Looking for a practical standards course - (2009-08-05)
[2741] What is a factory? - (2010-04-26)
[2977] What is a factory method and why use one? - Example in Ruby - (2010-09-30)
[3608] Design Patterns - what are they? Why use them? - (2012-02-12)
[3716] Learning C++ - a design pattern for your first class - (2012-05-02)
[3810] Reading files, and using factories to create vectors of objects from the data in C++ - (2012-07-21)
[3843] Caching Design Patterns - (2012-08-20)
[4021] Spike solution, refactored and reusable, Python - Example - (2013-02-28)
[4096] Perl design patterns example - (2013-05-20)
[4098] Using object orientation for non-physical objects - (2013-05-22)
[4325] Learning to program - what are algorithms and design patterns? - (2014-11-22)
[4330] Java - factory method, encapsulation, hashmap example - (2014-11-27)
[4356] Object factories in C++, Python, PHP and Perl - (2014-12-19)
[4377] Designing a base class and subclasses, and their extension, in C++ - (2015-01-01)
[4396] Java Utility class - flexible replacement for array. Also cacheing in objects and multiple catch clauses example. - (2015-01-16)
[4421] How healthy are the stars of stage and screen? - (2015-02-09)
[4581] Thin application, thick objects - keep you main code simple. Example in Ruby - (2015-11-21)
[4626] Singleton design pattern - examples and uses - (2016-01-20)
[4663] Easy data to object mapping (csv and Python) - (2016-03-24)
[4673] Separating detailed data code from the main application - Ruby example - (2016-05-16)
Y116 - Python - Applying OO design techniques and best practise [340] Code and code maintainance efficiency - (2005-06-08)
[656] Think about your design even if you don't use full UML - (2006-03-24)
[668] Python - block insets help with documentation - (2006-04-04)
[836] Build on what you already have with OO - (2006-08-17)
[945] Code quality counts - (2006-11-26)
[1181] Good Programming practise - where to initialise variables - (2007-05-09)
[2363] Alpaca Case or Camel Case - (2009-08-16)
[2407] Testing code in Python - doctest, unittest and others - (2009-09-16)
[2485] How do I set up a constant in Python? - (2009-10-31)
[2523] Plan your application before you start - (2009-12-02)
[2604] Tips for writing a test program (Ruby / Python / Java) - (2010-01-29)
[3887] Inheritance, Composition and Associated objects - when to use which - Python example - (2012-10-10)
[4028] Really Simple Class and Inheritance example in Python - (2013-03-04)
[4118] We not only teach PHP and Python - we teach good PHP and Python Practice! - (2013-06-18)
[4718] Defining an object that is a modified standard type in Python - (2016-11-02)
Some other Articles
A quiet evening in Melksham - awaiting SantaWhat a difference a year makesMultiple yields and no loops in a Python generator?Python - comparison of old and new string formattersHow to avoid too many recalculations within an objectA brilliant finish to 2014 training and business guests, and a look to 2015Seeing Christmas Coming to MelkshamC++ in 2 daysWiltshire Police - assuming someone is guilty just on the say-so of a member of the public?