2

I'm facing a situation that does not seem to have a clear solution to it, which leads me to believe I'm actually doing something wrong. Here I am seeking advice once again.

To rapidly let you understand my issue, I'm having trouble releasing apps / developing apps, in terms of separating the production code with the development code. Now let me explain in detail.

First, here are the two things that I've done in the past :

Develop on a single branch (git), say "dev", and when we need to release, simply manually change everything to "production" state, build-archive-release, and we're good.

For obvious reasons this is completely unmaintainable and requires so much work even when releasing simple apps.

Develop on a "dev" branch, and once we're happy with it, we merge on a "beta" and then a "production" branch, and ship whatever branch needs to be shipped.

This is better, but the relentless merging feels just as error prone as the "one branch to rule them all" insanity. And on top of it, I feel pretty unaware of what exactly the merge will do to my files, when it comes to specific config files. For example, merging dev into beta, which of the API Keys is it gonna choose in the merge? The dev or beta key? Same about some credentials or backend url. It really feels more clean when you look at it from the outside, but in the end, I still end up checking up all my files one by one. And I've had bad changes happen, I'm not just paranoid, sadly.

So, I'd say better, but just as maintainable.

Some have advised using #IF DEBUG but I'm straight up against it, as you end up cluttering the code and having bits and pieces of two different environnements spread into the code. In the end you're not even testing the real product, so that can't work.

And now here I am, not knowing what others do and how to they overcome that obstacle. I am all ears.

Note : I've read a bit about build servers but I'm not sure I truly understand them, and from my inexperienced point of view, I just see them as moving the problem on a remote machine, which does not change much.

  • 1
    Every product I've worked on in the last 10 years, there was a single switch between development, release, and shipping build. – gnasher729 Aug 9 '16 at 8:07
  • could you elaborate, i'm interesting in that switch :P – Gil Sand Aug 9 '16 at 8:07
  • It's a switch that you build yourself :-) – gnasher729 Aug 9 '16 at 8:08
  • 1
    Simply said: put everything that changes between environments in a config file. When building, get settings from the correct file according to the environment being built. For settings used in the application: package the configuration file with the application and read the file from your application. – JDT Aug 9 '16 at 8:51
1

Have a look at 12factor.net. It has a lot of good advice on app maintainability.

They suggest storing all config in the environment as environmental variables. I think it's hard to scale that without putting some of them in an environment selected config file, but I heartily disagree with anyones advice that says put all your changeable variables in a file that you package with your application code. This is a huge chance to accidentally leak passwords and other security related stuff if you're not extremely careful.

I tend to take a hybrid approach, which will accept variables from env vars if they're not in a static file. Then I simply don't put sensitive variables in the file, but instead configure the production systems service account with them (once), so that they're never checked in.

If you have a CI/CD process you could have a local file (ideally encrypted) that's used to configure those variables at deploy time if you prefer to have the manual step removed.

1

I would strongly advise against different branches for separating seemingly hard coded development configurations from production configurations. Using SCM for this task will lead to increasingly different code bases.

A great way to make build differences explicit is by creating one sub-project per build target. In these projects you can for example extend a generic launcher from the main code or provide environment specific parameters. Even if you use configuration files a project for each build target is often a good place to put configuration files into.

A project layout might look this way:

  • application (root-project)
    • application-main
    • application-distribution-prod (uses application-main)
    • application-distribution-dev (uses application-main)

When your application is big and has different modules, you can create different module assemblies just by creating different distribution sub-projects.

When you have complex differences between production and development environments I would recommend to pull all variable aspects into interfaces. Then you implement those interfaces in two different projects. Switching between environments becomes a matter of dependency management.

An extended example:

  • application (root-project)
    • application-main
    • application-login-mock (implements login api from application-main)
    • application-login-google (implements login api from application-main)
    • application-distribution-prod (uses application-main & application-login-google)
    • application-distribution-dev (uses application-main & application-login-mock)

For this technique you will need some kind of dependency injection or service provider.

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.