The concept of Convention over Configuration is impossible without sensible default values. The key word here is "sensible". The default values have to make sense for at least 80% (if not more) of all the uses of a library/service/framework.
General rules of thumb:
- If a value is sensible for 80% or more uses, it needs to be a default value
- If there are no values that are used for the majority of cases, do not use defaults.
- Default values prevent stupid mistakes from the setup code. If the defaults are reasonable for most cases, fewer people mess with the working configuration.
- Non-standard configurations are more visible when you use defaults.
- Bad defaults are worse than no defaults.
Essentially, once you learn how the default configuration works, you can make educated decisions about how/when to do non-standard configurations.
You found yourself the reason: "I know they are capable of learning, just seems that there's a general lack of motivation."
There are people who are passionate about their work. And there are others who, being sometimes competent enough, are working just for money. They know their stuff, but they don't enjoy their work. They will not spend extra time doing additional refactoring to make code readable or solving an intriguing problem when a quick and ugly hack can do the job.
This phenomenon exists in every job. It's just that some jobs are not extremely exciting (have you seen an accountant who loves his job and dreamed about it already when he was a child?), but in programming, there are plenty of people who really love what they are doing (otherwise Programmers.SE will be pretty empty). This means that as passionate developers, who talk daily to other passionate developers, we have more chances to be surprised seeing a person who does programming just for money.
What can we do? Not too much. In all cases, it's not to you, but to the human resources to choose people who are truly motivated¹. And fire people who are not.
You can try to motivate your colleagues yourself, but it's extremely hard. If you give them books to read, they will return them unopened a few weeks later. If you give them an advice, they will not listen, because they don't care².
You can:
Convince your boss to set a number of strict rules in your company: style guidelines, etc. This will not motivate those people to do a better job, but at least they will not be able to commit source code which doesn't match the requirements.
Work on the requirements, especially non-functional requirements. What about a requirement which tells that a specific project must contain less than 5 000 lines of IL code (no, I'm not talking about the meaningless LOC)³? What about requiring to obtain specific results at cyclomatic complexity or class coupling?
Increase the number of hours you spend in your company doing code reviews. Specify what is reviewed: if you have a checklist, add the points related to refactoring, readability, clean and useful comments, etc. If you don't have a checklist, you must.
Use [more] pair programming. It may help improve the code quality and motivate the less motivated coworkers.
Use the compensation system similar to what is used at Fog Creek.
¹ That's what interviews are about: before hiring you, the human resources must asset not only your technical level, but also your motivation. Sadly, some companies forget about this second part of the interview, and hire people who don't enjoy programming too much. Happily, in most cases, the work in those companies is never enjoyable, and Joel test rarely exceeds 2.
² They really don't care, even if they gain less money. I'm pretty close to one of my customers (I'm a freelancer) who believes that his work is to develop websites for his own customers. He also have a designer. I told them many times about the ways they can increase their productivity by 2 or more. If they just hired somebody competent, they would increase their revenue by at least 3. But they have enough money, and don't care about quality or how much they cost to the ignorant customers, compared to somebody productive.
³ What I mean is the number of lines of IL code which you see in Code Metrics in Visual Studio, the metric which actually means something. The real LOC doesn't matter and you don't have to measure it; it's one of the most stupid metrics ever. Enforcing IL lines of code means that developers will be forced to actually refactor code, and not just to collapse ten lines of code in a single unreadable line.
Best Answer
As Mikey mentioned, writing bugless code is not the goal. If that is what you are aiming for, then I have some very bad news for you.
The key point is that you are vastly underestimating the complexity of software.
First things first--You're ignoring the bigger picture of how your program runs. It does not run in isolation on a perfect system. Even the most basic of "Hello World" programs runs on an operating system, and therefore, even the most simple of programs is susceptible to bugs that may exist in the operating system.
The existence of libraries makes this more complex. While operating systems tend to be fairly stable, libraries are a mixed bag when it comes to stability. Some are wonderful. Others ... not so much ... If you want your code to be 100% bug free, then you will need to also ensure that every library you run against is completely bug free, and many times this simply isn't possible as you may not have the source code.
Then there are threads to think about. Most large scale programs use threads all over the place. We try to be careful and write threads in such a way where race conditions and deadlock do not occur, but it simply is not possible to test every possible combination of code. In order to test this effectively, you would need to examine every possible ordering of commands going through the CPU. I have not done the math on this one, but I suspect that enumerating all of the possible games of Chess would be easier.
Things go from hard to impossible when we look at the machine itself. CPU's are not perfect. RAM is not perfect. Hard drives are not perfect. None of the components within a machine are designed to be perfect--they're designed to be "good enough". Even a perfect program will eventually fail due to a hiccup by the machine. There's nothing you can do to stop it.
Bottom line: Can you write "Bug free software"?
NO
Anyone who tells you otherwise is clueless.
Just try to write software that is easy to understand and maintain. Once you've done that, you can call it a day.
EDIT: Some people commented about an excellent point that I had completely overlooked: the compiler.
Unless you are writing in assembly, it is entirely possible that the compiler will mess up your code (even if you prove that your code is "perfect").
A list of bugs in GCC, one of the more commonly used compilers: http://gcc.gnu.org/bugzilla/buglist.cgi?product=gcc&component=c%2B%2B&resolution=---