I’ve been dealing lately with issues around project estimation and timelines, and I recently realized something. Developers tend to be optimists, and are willing to tackle cool new projects which are very greenfield.
Green field projects are important and can sometimes offer huge payoffs. However, their downside is that they are by their nature unscoped. The goals can be scoped, but the development involved, the learning needed, and the unknowns presented leave the true scope undefined.
These are cool! It is exciting to jump into the great unknown and figure out ways to do things which have never been done before.
However, 99% of what is built today has already been done thousands of times by other developers, and I bet that you have done it already once or twice. The long term sustainability of your company is based on your ability to not get in over your head.
So I propose that you try to find the simplest, most boring way to solve your problem. If it is turning out to be hard, ask whether there is a way to shift requirements such that it is made easy. The vast majority of the time, you can.
For the remaining 1% of projects, keep their scope as small as possible. Since you cannot estimate the depth of the project, keep the breadth limited.
However, feel free to try new tech. But with these rules:
Only try one new technology in any given project. A new database is a new technology. A new templating language is a new technology. Et cetera.
Set a fallback plan. If you were not allowed to use any new technology, how would you do it?
Set a cutoff. If this takes longer than X time, you will fall back to the old tech.
Set a stretch cutoff. If you think you are really close, you are allowed Y more time to get it there.
If you hit these cutoffs, do not, under any circumstances, continue down this road on this project. You have to ship and move on to other things. Learn from the test and feel free to try again with the new-found knowledge.
Since caching is one of the two hard things in Computer Science (along with naming things and off-by-one errors), and I’ve been dealing with tons of caching issues of late, I here offer my personal rules of caching:
Caching should be done as little as possible.
You should not cache until you know you need to.
When possible, caching should be done by dedicated applications (Varnish, Akamai, et cetera) outside of the application.
When possible, HTTP APIs should set sane cache headers to help aforementioned dedicated applications.
Try to keep cache lifetimes as short as your applications can handle. If your data rarely changes, try an ultra-long-lived cache, keeping in mind the below rules.
Ultra-long-lived caches which require forced expiration on change should only be used inside the application which generates the changes.
Never depend on polling to tell you when to expire a cache.
Always turn off caching in your test suite except when testing your cache.
When consuming slow data you do not control, you may cache the response in your application. However, you should not cache the processed result, only the source, and as early as possible.
You should not cache intermediate steps in your application’s program flow.
This will be updated as I bang my head against more issues.
I’ve been using rbenv for development for a while, but recently I started working with using rbenv on my Webfaction hosting. Here is a basic tutorial.
First, create a new Passenger app in the Webfaction control panel. You can create a Rails app, but it adds some extra cruft you don’t need.
Log into the server, and install rbenv locally, using the standard rbenv tutorial. You will want to also install ruby-build in order to set up your ruby versions. Compile and install the desired version of Ruby using rbenv install 2.2.2 (change the version to match).
I suggest that you update rubygems and install bundler at this point by switching to the desired version of ruby (rbenv global 2.2.2), and running gem update --system and gem install bundler. You may want to switch back to system Ruby, although this is up to you (rbenv global system).
In the app directory (webapps/yourappname), edit the Nginx config file at nginx/conf/nginx.conf. Set passenger_ruby to be /home/[yourusername]/.rbenv/shims/ruby.
After a restart, you should be running on your rbenv ruby.
Closing track on the new album, “With Heart and Voice.” This festival arrangment was commissioned for the CUC 2010-11 Academic year. Produced and Released by Concordia University Chicago Wind Symphony, 2011.
A genuine member of a Lutheran congregation must have a thorough understanding of pure Lutheran doctrine or at least must desire to grow in the knowledge of it. Such a one will imitate the Bereans in searching the Scriptures daily, he will not lay aside his Catechism when he has completed his elementary school training, but throughout his life continue to review it in order that he may understand it better and become more thoroughly grounded in it. He will read other good orthodox books and periodicals to become ever more firmly established in the pure doctrine.
A member of a Lutheran congregation must be able to defend his faith and to prove its correctness from God’s Word. St. Peter writes, I Peter 3:15: “Be ready always to give an answer to every man that asks a reason of the hope that is in you with meekness and fear.” A sad state of affairs is revealed when members of a Lutheran congregation, asked about their faith, say, “You will have to ask my pastor about that.”
It is a settled fact that whoever is indifferent to false doctrine is indifferent also to pure doctrine and his soul’s salvation, and has no right to bear the name Lutheran and the name of Christ.