back

by mpweiher·13y ago·view on hn ↗
Well put! Another reason to grab the time once and distribute it is that you typically don't want the passage of time during processing to affect results, that is, you want your system to perceive "atomic" time.

Would suck if half your update is December 31st 23:59, and the other half January 1st, 00:00.

2 comments
You can also use the SQL value of NOW(). It's always set to the start of the current transaction.

http://www.postgresql.org/docs/current/static/functions-date...

Well you could, but now you've coupled your system to the database.
Which if we're going to be honest is a hugely overhyped issue.

Note: I base this on how often I've swapped out the database for a project in the past 15 years (maybe twice?) of writing mostly database backed software.

It's not the swapping, it's the (configuration) complexity and test performance, among other issues. See http://www.confreaks.com/videos/759-rubymidwest2011-keynote-....

I particularly like the example he gives near the end of always thinking they need to add the database and finally, after shipping to a bunch of customers, figuring out that they didn't actually need it.

In terms of test performance, I frequently see blog posts about reducing the time for a couple of hundred tests from half an hour to 15 minutes.

    marcel@localhost[~]time testlogger -a MPWFoundation ObjectiveSmalltalk ObjectiveXML EGOS EGOS_Cocoa MPWSideWeb
    tests:1: warning:  1055 tests (of 1055) executed, 0 failures (100 % success rate)

    real 0m2.939s
    user 0m1.607s
    sys  0m0.438s
In ruby you'd use timecop for time sensitive tests. It allows to freeze time and move it forward/backwards in specified increments.
I think the argument is that solutions such as Timecop are a hack for stubbing dependencies that are pulled out of global scope.
Very succinctly put.

Newspeak solves this by eliminating the global scope and eliminating "import". Every module is parametrized with everything it needs.

    Timecop.freeze(Date.today + 30) do
      assert joe.mortgage_due?
    end
vs

    assert joe.mortgage_due?(Date.today + 30)
At some point you will need to test the unit that create the time object. With DI you could swap out the implementation of time that gets created and use some implementation that returns a constant time. But that still pulls the information about the implementation to use from some global scope: The DI library needs to know which implementation to use, and that information will come from some global scope - a configuration of some kind, thus making that argument a moot point. In ruby you can modify the classes at runtime to mock such functionality. You could argue that modifying the time implementation is some form of DI - you're changing the implementation at runtime.
DI is still relevant for dynamic languages, for two reasons:

- it lets you put your dependencies all at the same place

- it lets you define clearly what the dependencies of a piece of code are, without having to look at internals which may change tomorrow without warning

One thing I find aggravating with dynamic languages is that metaprogramming is a crutch people tend to rely on because they can't be bothered to write clean APIs. In my experience, it's particularly prevalent in Ruby.

Of course, the lack of dynamism can be a problem in statically typed languages, giving Spring's or Hibernate's stacktraces of hell with piles of proxy objects.