Sunday, April 21, 2013

Clock Angle Problem Part II

Recently I posted a solution to the clock angle problem. At the end we were left with a few questions involving how to spice the problem up a little bit. In this post we will explore these question more. Namely, we will introduce a seconds hand along with the hour and minute hands, and we will explore caching.


First of all: what if the hour and minute hands ticked for every second and we wanted second-level accuracy? What we need to do is presume that there’s a second hand, and add the degrees changed for each second to the hour and minute components for each second tick. We can find the math for it, and write some code like this:


  // calculate all units in degrees per second
  // minute hand is 6 deg/minute plus 1/10 deg/sec
  double md = m*6 + s*0.1;
  // hour hand goes through 30 degrees per hour
  // plus 30/60=1/2 deg/min,
  // plus (1/2)/60=1/120 deg/sec
  double hd = h*30 + m*0.5 + s*(1d/120d);
  double result = Math.abs(hd-md);
  return result > 180 ? 360 - result : result;


Second of all, if the calculation was really expensive, how could we implement caching? (Hint: Not WeakHashMap) There are a couple ways to approach this.


It helps to understand the nature of what we’re computing. Is it time-intensive? Memory-intensive? Does it make sense to pre-compute values? In my caching example I took two approaches: one that pre-computes all possible values, and one that caches values as they are calculated.


It might make sense to pre-compute values if the set of possible values is limited and known, and the calculations do not adversely affect the startup time of the application. In this case, both are true. If the calculation took a lot of time or the amount of data to store was extraordinary (say, if we had a clock with nanosecond precision!) then this approach would obviously not be viable.


If pre-computing is not viable, we need a way to determine a way to store cached values. If we are already using a caching solution elsewhere in our application already, the choice is easy and we can just incorporate that. One options is Spring Cache, which  provides a nice abstraction over a couple implementations (see some handy posts here, and here). Additionally, you can include EHCache and use it directly.


However, if you are not already using caching and just need a quick one-off caching solution (on the way to a more mature solution as your needs grow... no need to re-invent the wheel), we can try extending LinkedHashMap as a simple cache. Check out how we can incorporate it directly into a caching layer over the ClockAngle class. Again, this is not a full featured cache solution, just a quick and dirty solution that may work for a focused part of your application for the time being.


Finally, if we have multiple classes doing the calculations and multiple caching techniques, it becomes apparent that there is duplicate code (in the core calculation, and in any input validation). It makes sense to refactor out common code and use the Decorator Pattern to compose these classes together. I think the final result is beautiful, simple, and easy to test!


No comments:

Post a Comment