Yes I totally get what you are saying. At one point I might not have written the last unix_time() example, but that is my default now, UNTIL say I hit a bug and need to test it thoroughly.

GetHomeDir() is a great example that proves that point... if I were trying to be very pure, I would have reified the pwd dependency and environment dependency.

One reason to avoid the complication is that I'm using shell scripts for tests. So in shell you already have a test environment. You can set $HOME to whatever, and in theory /etc/passwd, although that's a little trickier.

Actually that was one of my motivations for writing a shell :) You can test "one level out" at the OS level. Instead of the "seam" being the language, the seam is the OS.

I prefer to test against STABLE INTERFACES, not against things that I made up internally. You don't want your tests to calcify the structure of your code. I've seen that happen a lot with fine-grained testing, and it's a big pitfall.

I would say at the beginning, I write unit tests for tricky parts, but don't aim for 100% unit test coverage. I aim more for high integration test coverage. And then at the end of the project, when you are fixing bugs, that is when you can do fine-grained testing without worrying about making a mess of your code.

Here I did parameterize random() (irr_rand), because it's very important to the function of the code and needs to be tested:

https://github.com/google/rappor/blob/master/client/python/r...

So it all depends on the context. That's why I say it takes some practice. It takes practice to:

- not end up with more than 3-4 parameters for each class.

- not end up with too many classes. Java code seems to fall into this. A lot of things are just functions with dependencies. Actually this style I think reduces the need for classes -- they are your parameters rather than being your context!

- not structuring your code as a deep tree of calls. Instead it should be a relatively flat object graph.

A relatively static "Object graph" is really the idea that distinguishes OOP from "structured programming" (i.e. a pyramid).

I think I would differ with you in that I don't think DI and functional programming are that different. I think they are trying to get at the same core idea.

Things I ALMOST NEVER use in Python:

- setters and getters.

- Especially, setters for dependency injection. I always pass params through constructors.

- decorators. This can always be accomplished with composition of objects. I find that style a lot more readable. decorators are non-trivial code at the global level, when it really should be in main().

- classmethod and staticmethod. Static methods should just be functions. Class method is kind of a hack for singleton-like behavior.

- As mentioned, the singleton pattern is banned. Singletons are just classes you instantiate once.

I like that this style gets rid of a lot of concepts: thread local (as mentioned above), explicit singleton pattern, and "static/class methods".

Also I think it's true that Java's static type system might get in the way a little bit, but I don't have a strong conclusion on that. However, I also wish Python were a little more strict. I don't use 90% of the dynamism of classes.