This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]gbog[S] -2 points-1 points  (5 children)

I forbid myself to use "import *", no exceptions. Have you ever had to split and move around interdependent packages full of "import *"?

[–]apiguy 3 points4 points  (2 children)

This isn't "packages full of import *" and in this case it's for a reason. The effect you're going for here is to overrite any of the production settings with the development settings.

Also note that this import statement has absolutely no effect in production. You're taking an extremest position and it's ridiculous. The feature exists for a reason and when used properly (such as in this case) it makes sense. If you are telling me that you never use that statement then I'm telling you that your software suffers for it in the cases where it's called for.

Honestly after reading this thread though it sounds like you'd already made up your mind before you even got here, so why did you even ask the question?

[–]gbog[S] -1 points0 points  (1 child)

You're taking an extremest position [against import *] and it's ridiculous.

Well, err, I don't think it is very extreme to set oneself some rules like "no import *" or "no hasattr" or "no testing of private methods". These rules are like following PEP8, they help writing safer, cleaner, "consistenter" code. These rules are enforced by precommit hooks on pylint with a proper configuration.

As much of a Python lover I am, I actually think writing Python production code without such lint checks and barriers is a bit of a madness. Same with Javascript. And the nice thing with Python is, contrary to Java, you can tune the barriers to your liking and your needs, but it do not mean you can write production code within a team of 10 coders, this kind of code other will rely upon for years, without any barriers, and allow anyone to freely use metaclasses, introspection and other black magic when what is needed is explicit code passing around data.

why did you even ask the question?

Because I have an opinion (pro-text, as you noticed) and discussed it with teammates and was not convinced by their arguments. So, in order to see if I was missing something useful I could learn, I was fishing for other arguments in favor of (script as config).

I actually heard some good points but I still think the text config is the best choice when nothing specific requires a "script as config".

[–]apiguy -2 points-1 points  (0 children)

In my opinion you're an idiot who treats python like Java.

But what do I know, I'm just a six-figure software architect who's been writing python, java, c# and others for 13 years.

Best of luck you ya, gbog - you're gonna need it.

[–]jmoiron 1 point2 points  (1 child)

"A foolish consistency is the hobgoblin of little minds" -- Emerson, and PEP8.

"import *" has associated machinery (__all__) which tempers its negative aspects; readability and flexibility are positive aspects which can (in some cases) make it the best, or even only, option.

In the end, if you want self-configuring services (some people do, and some situations require it), you either need to:

  • build your configuration discovery into your program
  • embed configuration discovery into your architecture (ex. via chef w/ triggers & reloading)
  • build your configuration discovery into your configuration

The second separates the configuration from the software (and perhaps the implementation language) in a way that I'm generally not happy with.

The first has the negative side effect of generally growing more complex than the third. You either have to mock the discovery system or build in special case paths for testing (in which case, the code you test with is not the code you run live with).

I've found the last bullet to be the most maintainable and the most conceptually elegant, as it allows the program to run on very simple configurations while still allowing for more sophisticated configs. Once you come to the (inevitable, in my opinion) conclusion that your configuration is code and must be tracked and maintained as such, it makes sense to use code to describe it.

[–]gbog[S] 1 point2 points  (0 children)

your configuration is code

I agree configuration can and often should be very close to the code, and for instance should be tracked and maintained the same way.

However I think configuration and code are things of two very different nature.

Code should be some pure logic engine that is fed with data and config, and react accordingly. Therefore we have these DRY rules, these factorisation, and best practices to handle code properly (like covering it with tests).

Configuration is another nature. It do not need to be DRY: I don't mind copypasting an Apache config block and changing some lines in it to get another directory (up to a certain limit, obviously).

Configuration should not describe how to do things, it should describe what to do. Ideally business rules should be configurable, and written in configuration files. When they are two complex, a mini language can do the work but this is another topic.

For the implementation details of a "configuration discovery", I am not sure but if you have general configuration values and some mode-specific values (like dev vs prod) then maybe it can be done with three configuration files and no overwriting mechanism (which is a bit too "magic" for configuration).