1

I'm writing a PHP application, following test driven development principles.

I want two different configurations: one for development, and one for production.

I will be continually expanding the application's features, so one problem is I don't want the production credentials/configuration to be overwritten each time I upload an upgrade. This is just one heuristic. And it could be done 100 different ways. I can't see the wood for the trees, I need help!

Example 1: the application interracts with Ebay's API. For the application to authenticate itself with Ebay, it needs to submit authentication keys. But I'll need two sets of keys: one for development in Ebay's sandbox, and another for production. Eventually these will be stored a database or similar, since they expire and need renewing, but pretend that's not the case - assume they are static.

Example 2: Database host, name and credentials which would be different in testing and production

I'm having trouble articulating my question. In short, want to follow TDD best practice.

My instinct would be to have a configuration file which is read by some class. That gives two options:

  1. Either there would be two files, one for tests and one for production, or
  2. just one config file, who's contents would be altered for production.

But say we choose option 1, we're back to square one, because somewhere there needs to be a setting saying whether this the test or production environment.

And say we choose option 2, the file's location would still need(?) to be hard coded somewhere.

And then there's the scenario where objects need to be swapped depending on whether it's production or development. AFAIK the factory pattern solves this, but again, somewhere, the code needs to be told what environment we're in, and/or which of the two classes to use.

In books I've read, the principle I think is to treat the application as an onion, feeding in configuration information to the application so the whole application is context-independent. So for a command-line tool, configuration could be given by command line arguments. But how might this be done for a Java Swing application, or a PHP web app?

  • 1
    Take a look at how the Symfony framework handles multiple environments: symfony.com/doc/current/cookbook/configuration/…. Might help to crystallize some things for you. – Cerad Aug 5 '15 at 14:21
  • 1
    If you don't want the config files overwritten, don't deploy them along with your app and just keep it on the server. That way you know the file is up-to-date, otherwise you risk a change being done in production and if the file is not copied back to wherever you store config files the thing blows up post-update. Treat config files as data and back them up. If the server crashes, get the config file from the backup. – JDT Aug 5 '15 at 14:50
0

One solution I've used in the past is to have the application use the hostname of the machine it's running on to locate the configuration file, so if it's running on a machine called www7, it'll load config.www7.inc, whereas if it's running on minerva it'll load config.minerva.inc. It takes a moment to set up a new machine, but after that it's pretty easy.

  • 1
    So if you are in a team of 10 developers you have the same file duplicated ten times, each time with the machine name in there? And when people change machines they manually have to make a new file? Seems like a lot of work to fix an issue that has actually been solved already... – JDT Aug 5 '15 at 14:46
2

You don't need a setting that says if you are in development or production or not. You just need settings that tell your application how to handle certain things. API keys, database connection strings,... these are all basic 'read this value and use it' things and this is the kind of stuff that configuration files are good at.

It's a little different if your implementation differs. For example, let's say that you want your development environment to write e-mails to a logging directory and the production environment to actually mail them to the recipient. You write all your code against an interface ('IMailer') and write two implementations: SMTPMailer and LogMailer. Your config file contains an entry that says what implementation IMailer should use. For development/testing environment, you simply have that entry point to the LogMailer. Look into IoC and IoC frameworks for that.

1

A very clean way is using Git:

Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.

For more information and downloads: https://git-scm.com

With Git you use branches, such as develop, master, feature/, etc. Read more here: https://www.atlassian.com/git/tutorials/comparing-workflows

Store production config in the master branch, the development config in develop branch, etc.

  • This only works if if you have an entire repository just for the configuration. This is because you will not be able to merge branches into each other. Actually for that reason it is not the best way to do this. You won't be able to share any state between develop and master configs without manually copying every new change between them, which would be an annoying and error prone workflow. – still_dreaming_1 Oct 11 '16 at 21:37
0

One solution that sounds vaguely reasonable stems from this 12 factor methodology page on configuration.

The most focused guidance I have found so far is here in the 12 factor methodology. They suggest that such configurations should be stored in environment variables. But how would that be done in PHP? Here it is suggested to use a .htaccess file.

  • 1
    I'd ignore the 12-factor stuff. I've read it before, and IIRC it's heavily focussed on very large deployments using large numbers of cloud servers. Most people don't need to worry about the same problems they have. – Jules Aug 5 '15 at 14:35
0

Without seeing the actual code or tests it's hard to say, but why do you need to actually use the service in the test? You'd be better off mocking the ebay API and not worrying about live/production differences.

  • I'm going out of my way to follow the book "Growing object oriented software guided by tests" by Freeman/Pryce, to really understand it. They emphasise writing end-to-end tests first, which include GUIs, external services, persistence, checkout, build and deployment. – CL22 Aug 5 '15 at 20:19

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.