1. Put them to work with tools that are inefficient. Good examples are: spaghetti code, slow or unneeded compiles and server restarts, infinitely complicated instructions and a billion systems that only a true god could figure how to make them work together.
2. Inundate them with feature requests and bugs, making sure that the deadlines sound reasonable for an optimal environment. After all, their time should be well accounted for.
So far, you already have a winning recipe. Your engineers will be swamped every time they want to do something because, ideally, it should take as long as they estimated in the first place, not really knowing the state of the underlying code.
Of course, you can't know the state of the code until you actually try working with it. If the engineer is not experienced enough, he or she can't figure out that it's not supposed to be this hard in the first place. This makes the engineer feel stupid.
There's more ways to make this more fun:
3. Reward those who are eager to write code, but inexperienced. This ensures you get a lot of features at the cost of exploding code. Tell yourself that as long as something is documented, then that's all it needs.
Remember, users never come first. A good and often used example of this is ignoring that any code that is written is supposed to be used by another, different human. Make sure you don't design for simplicity, but something that is more tangible, like page load speed.
4. Don't pay attention to engineers warning about the state of the tools. If the young'uns can deal with it, then clearly that's just an excuse to slack off.
Stay tuned for your next issue: How to lose your business to your ex-employees in a few years. Hint: it has something to do with being able to push features faster.