0
┌────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                                    │
│  ┌──────────────────────────────────────────────────────────────────────────────────────────────┐  │
│  │                                                                                              │  │
│  │                        ┌──────────────────────────────────────────────────────────────────┐  │  │
│  │ from lib import Blah   │                                                                  │  │  │
│  │                        │  class Blah:                                                     │  │  │
│  │ ...                    │                                                                  │  │  │
│  │                        │  def __init__(self):                                             │  │  │
│  │ def main():            │                                                                  │  │  │
│  │                        │      self.important_path = os.getenv('BLAH', '/blah')            │  │  │
│  │    b = Blah()          │                                                                  │  │  │
│  │    b.do_stuff()        │                                                                  │  │  │
│  │                        │                                                                  │  │  │
│  │                        │                                                                  │  │  │
│  │                        │                                                                  │  │  │
│  │                        │                                                                  │  │  │
│  │                        │                                                                  │  │  │
│  │                        │ lib                                                              │  │  │
│  │                        └──────────────────────────────────────────────────────────────────┘  │  │
│  │ ./application                                                                                │  │
│  └──────────────────────────────────────────────────────────────────────────────────────────────┘  │
│                                                                                                    │
└─────────────────────────────────────────────────────────BLAH=/xyz────────────────────▲─────────────┘
environment (say k8s pod)                                                              │
                                                                                       │
                                                                        ┌──────────────┴─────────────┐
                                                                        │ Volume                     │
                                                                        │                            │
                                                                        │ (mounted at /xyz)          │
                                                                        │                            │
                                                                        └────────────────────────────┘

Consider an application that runs in an environment (e.g. a kubernetes pod that we control) and uses a library lib.

The application itself is loosely coupled to lib. However, there is an implicit dependency between lib and the runtime environment, to either mount and set the BLAH env. var. or have an accessible directory /blah.

Is this kind of an implicit contract between the runtime and an internal library problematic?

Would it make more sense to have the lib expect callers to provide environment information explicitly. So:

class Blah(self, important_dir = '/blah'):
    self.important_dir = important_dir

and have an explicit contract between the caller (application) and the runtime

from lib import Blah

...
def main():
    b = Blah(os.getenv('BLAH', '/blah'))
    b.do_stuff()

When would it be better do do one vs. the other vs. doing both (defaulting to an env var. but allowing a caller to override).

lib is packaged and distributed independently of application and is used by many other applications. All interaction with /blah is contained within the Blah class and does not leak through to the caller.

Note that in this example we're dealing with a specific mount path, but this could be any other implicit communication between a runtime and an internal library (cloud credentials, endpoints to connect to, etc.)

2
  • 3
    "have the lib expect callers to provide environment information explicitly" - I would prefer that, because it makes things more flexible (you can test or move the library around without dragging the environment along). However, if you want to help out your users that are just getting started with the library, you can always provide sensible defaults (default parameter, or, if the environment is more complex, a preconfigured object clients can obtain from somewhere), while leaving the option to pass in something else. May 12 at 22:15
  • 1
    Consider the person thinking about how to deploy the application. What if they have no control over environment variables in the target environment? What if the target environment is strictly locked down and hardened in a way which prevents applications from accessing environment variables? What if the application must run multiple copies in the same environment and needs to switch different configurations? What if an organisation imposes some IT policy which requires all applications to get their configuration from somewhere else? May 12 at 23:37

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.