App Specific Settings for Django
While Django encourages a healthy degree of decoupling in how apps and modules are structured, the settings file can very easily become a monolithic mess. There are some good resources for how to divide up settings file between environments, but with a big application, even that can leave you with a mess of configuration settings.
What is particularly annoying in this situation is that many of these settings really just affect one app. For example, I store JavaScript and CSS files specific to each app in app_dir/static/ and then use django-pipeline to wrap and compress all the files for deployment. However, Django Pipeline requires you to define Groups in your settings.py file. However, since those groups are specific to each app, it seems like they should live with the app, not in the settings file. Adding a css file shouldn’t require me to change the settings.
At first I attempted to fix this by putting a settings.py file in each app’s directory, but Django doesn’t automatically import those files and attempting to do so manually in Django’s own settings files lead to all sorts of messy import loops. However, I found a much simpler solution. Simply put the extra settings in the __init__.py file in the app root. This get’s imported automatically when the app is installed and those settings will automatically be added to the general settings environment.
Do one thing (at a time) and do it well
The Great Law of Unix and its progeny is to do one thing and do it well. Although Unix programs may have great complexity, they are focused and modular. This has certainly lead to the amazing success of Unix, BSD, Linux and other *nix operating systems in the tech world, but I think that this law is more generally applicable than simply ‘how to write Unix programs.’
My previous post is, in essence merely a re-statement of this law. When pushing a release or change to your product, keep your focus. It is far better to make a few changes that will make a big difference, than lot’s of meaningless fiddling (Though don’t forget that big and little changes should be measured on their effect on the user’s experience, not how much effort they require).
I learned this lesson again today when I was working on my Arch Linux install. I use LinuxMint for my day-to-day computing, but, in the interest of learning more about how Linux is built, I’ve been slowly working on getting a usable system on my second partition. Like with code releases, one thing I’ve learned is to not try to change too much at once. My initial plan was to build the entire system from scratch in an extreme minimalist style (OpenBox, SLiM, Chrome and a Terminal) but I quickly found that there is a great deal more complexity in doing that than I had anticipated and I’ve had much more success since switching to XFCE and more ‘mainstream’ technologies.
Some day I will probably reduce my system even further, but for now, I’ve learned that minimalism is a process of taking away more than it is a process of adding the minimum amount possible.
Deployment and Tools Guide
This isn’t your ordinary guide to deployment and tools. As a matter of fact, this is somewhat of an anti-guide — a guide on how to approach tools and deployment — rather than a guide to any specific approach. I was inspired for this by a post yesterday to Hacker News by Hynek Schlawack on Python Deployment Anti-Patterns and other tools used in doing Python web development. The article and associated discussion on HN are both excellent and I highly recommend a read.
However, I often find that articles and resources like these can actually be quite counterproductive to my as a developer. I look at these lists and think to myself, “Oh no, I’m not using all of the best practices! I should switch over my development stack to ensure maximum scalability and stability for the long term.” Then I spend several hours researching the tools, reading tutorials, reading docs, messing with the server, probably breaking something, fixing it and generally coming back right back to where I started with maybe a few tweaks to my process.
The problem with this philosophy is that it’s a bit like putting an air spoiler on my Honda Accord. Certainly the right spoiler, air-filter, tires, etc will make improve the performance of my car, but right now, I need to focus on getting to work and shipping a product. Playing around with a deployment system for a massively distributed system is pointless when you’re building out your initial product and trying to nail down the core feature set and build a customer base.
However, sticking with what you know and never moving onward is a surefire recipe for stagnation and boredom as a developer. I got into technology because I didn’t want to be bored and I wanted to be pushing the limits of what I can do and I want to have a solid stack and is up to date and using current best practices. There is usually a reason why smart, successful people are developing and implementing such practices.
So here has become my approach to keeping up with best practices and scaling up my applications, while not wasting time with pointless Yak Shaving: one new deployment feature per deployment. Instead of trying to build out the perfect stack from the beginning, I take what I currently have, and know and try one new thing. Maybe I switch to RabbitMQ instead of Redis for message passing. Maybe I use Supervisord instead of upstart for process management. Whatever it is, I optimize for one big improvement to my workflow per big improvement on the user side. This way the stack and architecture grows and improves as the interface does. The additional advantage here is that as I get more comfortable with these technologies, I start to think in those terms and start to build them into my projects from day 1.
Ode to the Little Stuff
This past week I had finished a big project for my work and was trying to decide what to build next. We had discussed several major new projects that included a major overhaul of one of the core interfaces to our application. However, instead of starting that, I took some time to fix a bunch of nagging little bugs that had been bothering me (and our users) for some time.
Now, you might say, “But Chris, what about the lean startup approach? What about the Minimum Viable Product? Aren’t you guys supposed to be a scrappy startup? Well, yes…
But…
Don’t forget the little stuff. It represents your biggest opportunity to get maximum impact for a minimum of effort. Yes, I could have re-architected our front-end stack to implement new features, but fixing bad copy, broken CSS and a poor user interface served our customers far better than that would have. The key word in MVP is viable. It isn’t just a minimum product; it has to be one that validates and implements (successfully) your business model. Otherwise, it’s just junk.
There is a second reason to think about the little stuff: putting the user first. Sometimes, it is tempting to fall into the trap of wanting to take out a new canvas and make big, bold strokes to hit your targets. Certainly, not falling into ruts is a key startup success trait. However, by taking what you have and re-focusing on what about it is broken, you get much closer to a workable product than constantly starting over. A good engineer doesn’t start over their project from scratch every time they find a mistake. A good engineer fixes it and refactors it into a good, workable product. The same holds for designing your product. Making it better is more rewarding and more beneficial to your users than starting over.