Best Practices for Design and Modeling
Here's how to look for warning signs that might indicate future problems, and how to balance your design decisions accordingly.
- By Jeff Levinson
An "application" can refer to a single system or a group of interconnected systems that provide a specific functionality. The thought process for designing and modeling an application is often complex. In this article, you'll learn how to look for warning signs that might indicate future problems, and how to balance your design decisions accordingly.
The first thing you should know: When architecting an application, you will not find right and wrong answers to your questions. You can perform any given task many different ways, but you must always consider tradeoffs. For example, if you make the system more flexible, then it will likely be harder to maintain. You have to balance the goals of the system, or your requirements, against future costs and needs, so it's a good idea to document the rationale behind your development approach.
Second, you need to understand the purpose of the model that describes your architecture. You've probably seen some fantastic UML models that were too complex for most of your colleagues to read. The key purpose of designing an architecture is not to build cool models; you want to communicate ideas and information clearly to all stakeholders. UML serves as a common language for documenting architectures, but it's useless if it becomes too complex. Use line and box drawings if they help you communicate your point more effectively.
Third, every choice you make when designing your architecture has advantages and disadvantages. For example, should you implement a Web service? What's helpful about a Web service? A Web service is language-agnostic and human-readable. What's not helpful about a Web service? It can be relatively slow compared to binary transfer mechanisms. And a Web service can break language neutrality if it's not written correctly. As demonstrated in this example, you'll encounter a downside and upside to all of your design decisions—it's important for you to anticipate both.
Finally, your architecture will suffer from the start if you don't understand the meaning of "architecture," both conceptually and in practice. Carnegie Mellon University's Software Engineering Institute has a section of its Web site devoted to architecture definitions; it's called the Community Software Architecture Definitions . These definitions, gathered from developers around the world, encompass both professional and private opinions. However, they share the same general theme, as you can see from this definition of "software architecture":
"The software architecture of a program or computing system is the structure or structures of the system, which comprise software elements, the externally visible properties of those elements, and the relationships among them." (Excerpt was taken from Software Architecture in Practice (2nd edition).)
Different types of architects apply this definition in different ways. If you are a system architect, you're concerned with the interactions between systems. You don't care about how the data is gathered on one system and processed on another, but you do care about how the connections between systems are made and how the data is transferred.
If you are an application architect, you don't care about how a method performs a process, but you do care about how data is moved from one layer of the application to another. Both of these examples take into account externally visible properties and relationships, but from different perspectives. The example I used for the application architect would comprise an internal process—internal to the application—so the system architect wouldn't need to be concerned with it.
Note that architecture is not a technology. It has nothing to do with the language you are using. Decisions about technology should be made after the architecture is mostly complete. This way your technology choices support the architecture that you've designed.
Think Through Your Design Process
Before you can start designing an architecture, you need to understand the requirements—requirements that are communicated and requirements that are implied (also see, "Identify the System's Highest Priorities"). Not all requirements are well-defined, and a good architecture should take that into account. But, assuming the functional and nonfunctional requirements (such as security, performance, maintainability, and extensibility) are understood, you can start designing an architecture. Over the years, a lot of high-tech tools have been released to help you create architectures, but the most important are the low-tech whiteboard and eraser.
A system architect and an application architect approach the design process differently. It's important that they respect and understand each other's goals, and work together on the architecture. A system architect is concerned with how the application interacts with other applications. He or she is not concerned with how the application itself works, only that data can be passed between applications, and that any reusable functionality is exposed in a language-neutral way.
An application architect is concerned with how the individual components of the system work together. For example, how does data get from the front end to the middle tier and from the middle tier to the data tier? What is the security context of the application, and from where is it acquired? What's the best way to design an interface by which external systems have access to this system? I'll mostly concentrate on the application architect's concerns in this article.
Starting Your Architecture
The first step in designing your architecture is knowing what you want to accomplish. For example, a transaction that writes data to the database, which uses some logic that might be useful to other applications, must complete within three seconds. This is a simple statement, but what does it suggest for your application design? Here are some items that come to mind:
- The transaction must be fast.
- It should use a common component for logic.
- It writes to a database.
Now, assume that your database vendor might change within six months of your application's release. Here are some additional items you might consider:
- Stored procedures might be problematic because they have to be translated.
- The data access logic should be decoupled from any other processes.
So, how do you approach the problem? Create an architectural model of some type that meets your functional requirements (see Figure 1). The most important thing to note is that the architectural model is technology-agnostic. Too often architects have a preconceived notion of the technology they are going to use. Business constraints might force you to consider technology limitations, but ignore these constraints when starting the architecture.
Another quick note about Figure 1: It specifies a database, although I advised you that your model should be technology-agnostic. Technically, the model should depict a data store instead, which doesn't have to be a database; it could be an XML file. I included a relational database management system (RDBMS) in the model because the requirements indicate that, but as an architect you can influence the business users and IT people and challenge their assumptions about technology in the requirements.
Implementing Patterns and Styles in Your Architecture
Now that you've created your model, you need to think about implementing patterns or styles. A "style" is more of a concept. For example, client/server application design describes how various pieces of the application are distributed over various system nodes. It doesn't indicate how they are connected or the patterns they use. Check out Wikipedia's list of architectural styles: http://en.wikipedia.org/wiki/Software_architecture.
A "pattern" is an implementation that solves a specific type of problem. For example, to communicate among distributed nodes, you can use a pipe and filter pattern, or a proxy pattern, or both—each of which has specific requirements. You can find a helpful list of patterns on Wikipedia: http://en.wikipedia.org/wiki/Software_design_pattern.
Depending on how they are implemented, some patterns are not considered an architecture issue. For example, is it an architecture issue if you decide that you want to use a Model-View-Controller pattern in your UI? It's not an architecture issue if you're a system architect building a Windows application. This example doesn't meet the definition of architecture I used earlier because the application's pieces are not externally visible. However, this type of pattern is an architectural issue to an application architect because communication can occur between three separate and distinct components (see Figure 2).
Another benefit of using patterns is that they provide known advantages and disadvantages, and these pros and cons have all been well-documented. As an architect, you should learn as many of the characteristics of these patterns as possible to make your job easier. Before you start trying to design your own solution, see if someone else has already solved the problem for you.
Testing Your Architecture
To a certain degree, you can test your architectures: You can use patterns to determine whether your architecture will support the given requirements.
You must also test the requirements themselves. Typically, a review of the requirements isn't done because application architects either don't know how to do it or don't want to invest the time because of external pressure. Or it isn't done because the business doesn't see the benefits. Get started by reading Evaluating Software Architectures: Methods and Case Studies. Pay close attention to the section on the Architecture Tradeoff Analysis Method (ATAM), which is the best architectural review process I've used.
This article presents a small part of being an architect—designing and modeling an application. Remember that being an architect is about communicating ideas and laying a foundation for the development team. Use what works for you, but make sure you have an understanding of the tools available to make your job easier. You will find nothing arcane about software architecture—it just requires a good toolbox and a lot of research.
Jeff Levinson is the Application Lifecycle Management practice lead for Northwest Cadence specializing in process and methodology. He is the co-author of "Pro Visual Studio Team System with Database Professionals" (Apress 2007), the author of "Building Client/Server Applications with VB.NET" (Apress 2003) and has written numerous articles. He is an MCAD, MCSD, MCDBA, MCT and is a Team System MVP. He has a Masters in Software Engineering from Carnegie Mellon University and is a former Solutions Design and Integration Architect for The Boeing Company. You can reach him at Jeff.Levinson@nwcadence.com.