I'm a mediocre programmer, at best.
When I'm programming, I need 8 different tabs open with every reference site I can get for a particular language. I google function names constantly, most of my debugging time is spent with dumb syntax errors, and I'm never going to be able to use Regular Expressions off the top of my head.
So what can mediocre programmers like myself do? Develop. I'm going to go over a few tips for good application development, and how to use development methods that can improve your programming, even if you lack superstar skills.
There are too many different project management philosophies to mention here, and many of them are developed by very experienced and knowledgeable professionals in the industry. However, project management and planning remain to be the biggest downfall for most programmers. Many of these methods are made to apply to development teams, but you can abstract a lot of the ideas to individual projects. Try to check out a few papers or books on the topic during your free time.
For most projects, I try to stick with the 1/3 rule: spend (approximately) 1/3 of your time on planning, 1/3 on coding, and 1/3 on testing. Many programmers expect to spend the majority of the project timeline writing code, and believe that good code will drive the project. However, I have found that most worthwhile final products are created from development timelines that have actual coding as a minority. This 1/3 flow can often take iterations for different portions of a project, where you plan, code, and test small portions and move on to the next section. But you will often find dedicating time to plan properly will cut down on actual coding, and proper testing will save you time in the long run.
Start with Your User
I am a big fan of top-down development. There are a lot of different theories about development strategies and methods, but I have found that for real world applications, the single most important aspect of any program is the interface.
With that in mind, I start my planning with laying out the interface. Implementation of this idea can vary depending on the project. For example, you may start with wireframes and a user flow for a web application. For something like simpleCart(js), I started by listing every way in which the user would interact with the code, including function calls, div classes, and html layout for cart items. When you start your project by building out the interface first, you are ensuring that your program will adhere to the end-user functionality of the project.
It doesn't matter whether you are a big believer in MVC (I am) or like procedural or object-oriented (I'm a OOP guy); you will find yourself improving your code by creating structure first, and then implementing code. It is often beneficial to create functions (or objects) that relate to real-world goals or problems. If you say to yourself, "I am going to need to store the current user preferences in a cookie," you might want to create a function for exactly that.
By focusing on individual problems, it becomes much easier to create efficient code for that particular purpose. In turn, you often write better code. It also becomes much easier to debug; if you are having a problem storing to a cookie, you simply look at your 'store to cookie' function. Documentation also becomes extremely easy, as the purpose of your code becomes evident simply by looking at the function name. I know this may be second nature to many developers, but it can't hurt to mention it.
Abstract Data Storage
I've found that many projects outlast hardware, hosting, or storage implementations. You may move your code to another server, decide to implement a different database system, or find that you outgrow your storage and need to keep data in more than one place. In any of these cases, abstracting data storage and retrieval functions from the rest of your code will benefit you immensely. Data storage is often the last part I consider for my project. I often do most of my developing with two empty functions: load() and store(). They are usually the last thing I implement, as, in most situations, they are the least important to the functionality of your end-user. It also becomes extremely easy to maintain consistency of your core functionality when switching to a new data implementation by simply altering these functions.
These are all very high level concepts, and it may or may not be clear how to actually implement some of them in your projects. The overriding theme that I hope you can take away from this article is that every program looks the same from 10,000 feet. Most great applications are built with the end-user in mind, and great development isn't necessarily dependent on great code. Please let me know if you guys have any other tips.