Firstly the generic answers:
- Understand that any given tool is not a silver bullet to fix all your problems. So when you're reading about MVC or Functional Programming or someone is spewing that LISP will solve all your problems, they won't. They may solve a whole bunch of problems you have, but they won't solve them all. In many cases in addition to solving some problems, they'll introduce a whole bunch of others.
- Understand the limitations and advantages of different components/technologies/tools at your fingertips for providing solutions to any given problem. Make your decisions based upon evalauation of all the advantages and drawbacks - don't make your decisions blindly.
- Pick the right tools for the job, including language, development, integration techniques.
- Who will be maintaining the code? Code to the expected audience. If that's you, don't expect that six months from now when you're expected to provide a fix that you'll remember what your thought process was today... write code that reads simply and document your thought process. Not the "how" - the code does that, but the "why". No matter how easy to read your code is, it cannot tell you why you did it that way. Code comments are for the why, not the how.
- Understand your users, how they work, their mentality towards their tools, what their jobs are, what their attitude towards the learning curve for your software is.
- Understand the mentality of the person/team that will be supporting your application - this means installation too.
- Understand the need for source control and use it.
- Backups, always assume and prepare for the worst, if you don't you'll wish you did.
- Learn how to write software specifications, technical specifications, test documentation, user documentation.
- FAT/SAT/UAT testing and signoff procedures.
- Set lower expectations than you're capable of delivering, don't promise the client a Lambourghini and deliver a Volkswagon Beetle [Bug]. Much better to promise the Beetle [Bug] and deliver a Mercedes.
- Don't overcomplicate anything - that includes architecturally, programmatically or anything else. Documentation should be simple to read, the interface should be simple to use.
Now the specifics:
- Understand that you must research the problem and understand the problem domain before you can provide any kind of solution, architectural or otherwise.
- Understand what the users expect will be delivered, how it will be delivered and how they will interact with it.
- Find the least technically adept person that will be using your solution, if they can understand it, everyone else will too.
- Design your software for your users as well as your financiers. If those you deliver it to can't/won't use it, you're never going to hear the end of it - even if your financiers are initially satisfied, they will very quickly recant.
Failure to plan is to plan for failure
Your environment, software needs, target audience, network support staff, budget and any number of other factors will greatly affect the solutions you provide. For instance, in the type of environment I code for, I tend to draw on a finite set of tools for delivery of products, and they will likely vary for your environment:
- Web browsers - IE/Firefox/Opera/Safari
- Application/File servers - Windows Server, Linux, Unix
- Web servers - IIS/Apache
- Web application development - ASP.NET/C#/VB.NET/ASP/PHP/JavaScript/AJAX/MVC
- Console application development - BAT/C#/VB.NET [Don't write a full blown C# app if a BAT file will do the job much more simply].
- Windows application development - C#/VB.NET
- Data maintenance - C#/VB.NET/Excel/VBA
- Database servers - SQL Server, MySQL, Oracle
- Network/Data/File integration services - MSMQ, BizTalk, SonicMQ, FTP
I may use one or more of these technologies for my solution dependent entirely upon what is being asked of me. The key is to understanding which is relevant for a given situation and only using those necessary. For instance don't write a full blown web application if a command line utility can easily be used by a single user, don't write a Windows application if many users need access to an application that can't easily be installed on their machines due to user restrictions and limited systems support personnel. Don't write a command line utility for users that can barely navigate around windows with their mouse and don't expect a Microsoft expert to support your *nix based system.
Provide diagrams and documentation that make it simple to diagnose issues so that when problems are found [and they will be], users/deskside support can easily narrow down the problem to a particular component in the system. This will make your life easier because they'll either be able to fix it themselves or provide you with enough information to fix the problem quickly and simply.
Edit: in response to your comment regarding UML which is great for the purpose, but once again you have to be aware of your target audience. If you're a lone programmer that's developing systems for a small client whose personnel don't understand UML, you'd be just as well providing a regular flow-chart decorated with simple English. If your target audience is a software consultancy whose business is software development, then by all means, UML is a great tool - especially as with some UML tools, you can have it automatically generate your stub classes/methods for you to automate some of the process. I tend to work in small teams for small companies so I don't use UML as much as I'd like, and probably don't understand it as well as I should, but that's not to say that if I was required I wouldn't brush up on it. It's a great tool to have in your toolbox but don't use it just for the sake of it. Everything you use in the design/architecture/development of your solution should be used for an objective reason - don't just use/learn it blindly because someone says "you should use this because it's great".
The key to good architecture is this:
- Understand the tools you're using
- Understand the reasons you should and shouldn't use the tools you have for any given purpose
- Make informed decisions objectively, don't base them on hearsay or emotion.
And most of all:
- Use your common sense!! If something doesn't sound or feel right, figure out why that is, worst case is that you'll find out you were wrong and you've corrected a misunderstanding/misconception, best case you saved a lot of time pursuing an incorrect and potentially expensive option based on that misconception - either way you're better off than you were.