One of the hardest things about the software architecture role is being asked to come up with a software architecture when all you're given is a set of requirements and a blank piece of paper. It's certainly one of the most fun parts of the role, but it can be a daunting prospect trying to figure out where to start and what to do. Many software teams dive straight into the code and this can initially be very productive but many teams soon start to venture down the slippery slope of constant refactoring while they try to find a design that works. Often, a little forethought is all that's needed to get the architecture definition process heading in the right direction. So where do you start?
One of the first things I do is step back to see the big picture. What exactly is the context here? What is this all about? What is it we're building and how does it fit in with the existing environment? A really useful starting point can be to draw a simple block diagram showing your system, the other systems that it interfaces with and key actors. For example, if you're building a website, you might show the website along with the various databases and backend systems that act as data sources. Such a diagram would also show other systems that are sent data as a result of transactions being performed on your website. Detail isn't important here. It's your wide angle view showing a big picture of the system landscape.
Once you understand how your system fits in to the overall system landscape, a really useful starting point for your own architecture can be to draw a simple block diagram showing all of the containers that make up these systems. By containers, I mean the executables that make up the systems; such as web servers, application servers, Windows services, enterprise service buses, databases, standalone applications, web browser plugins, etc. A high-level diagram like this doesn't necessary show much detail, but it only takes a few minutes to put together and provides a framework for understanding the major building blocks of your architecture and their interfaces.
Once I have the big picture, I start to zoom in and focus on the system itself by decomposing it into components, services, subsystems, workflows, etc. However you decompose your system is up to you, but what you're looking for at the telephoto level is a view of the major components and their interactions. If you were building an e-commerce website, you might show components representing a catalog service, a pricing service, a payment service and so on. These are the fundamental building blocks of your system and you should be able to understand how a use case or story can be implemented by one or more of those major components. If you can do this, then you've most likely captured everything. If, for example, you have a requirement to audit system access but you don't have an audit component, then perhaps you've missed something.
For some software teams, the telephoto picture is enough detail for them to go off and successfully deliver the project. Others, however, need to go down to a lower level by further decomposing the major components. Typically this is low-level design where you use (for example) object oriented design principles to define how a component will work at the code level. For example, one of your components might be a "web user interface", which you could further decompose to show how it would be implemented using a web-MVC framework. Or perhaps you want to model the business domain in some detail. You could represent this lower level of detail using anything from simple block diagrams through to formal UML class diagrams, but either way they're showing the implementation level design aspects of the system.
Granted, a logical top-down approach to architecture definition and system design such as this might look like common sense. And to some degree it is just that. Having said that though, many software teams dive straight into the macro level without giving the other levels any thought. Diving into the code, tempting as it may be, can lead to designs that are over-engineered, incoherent and inconsistent. This is especially true when you're faced with a large team where everybody is tackling system design from a macro level perspective. If you've seen teams that are constantly refactoring at the really early stages of a software project (to the point that it's distracting them from the bigger picture), they probably didn't start out with the big picture and enough vision of where they wanted to go. Coding alongside the architecture definition process will help to prevent analysis paralysis, but diving straight into the code means that you miss out on the opportunity to create a vision of how your software system should be built and you'll most likely encounter a whole host of problems further down the line. Analysis paralysis and refactor distractor are both very bad and a balance between architecture definition and coding is needed.
The architecture definition process is essential and straightforward if tackled in the right way. My advice is simple; start with the big picture and work your way into the lower levels of detail, remembering that each picture should tell a different part of the same story.