What is application architecture?
Most people have a general idea of the role of a traditional architect, creating precise diagrams to pass on to the builders and other craftsmen who will undertake construction. More than this, an architect needs to consider the materials used, the aesthetics of a building, and oversee the construction process.
In the world of software, the architect has a similar role: design and supervision. We need to invest in the role of an architect and ensure that we make it an end-to-end process that ensures we take responsibility of the quality of the final product. Design and supervision requires a comprehensive knowledge of the product requirements, the technologies involved, and the available resources. The architecture of a software program (our "raison d'etre") is multifaceted, from the quality of the up-front documentation that dictates how the project will be built, to the finesse of the end product, which users will love to work with.
Requirement analysis
A software project should never begin without a list of requirements from the customer, client, or other stakeholder. This is often in the form of a detailed specification document. Requirement analysis involves the architect understanding the problem that needs to be solved and applying what they've learned to the next stages of the process.
Here's a short example:
Users should be able to log in, log out, register, and request a new password. Login should be persistent across browser sessions.
The architect reads this and the developers (in turn) end up with the following code to handle user logins:
Ext.define('MyApp.SessionManager', { login: function(username, password) { User.login(username, password, { success: Ext.bind(this.loginSuccess, this) }); }, loginSuccess: function() { this.isLoggedIn = true; } });
This should be familiar to a seasoned Ext JS developer: we use Ext.define
to create a class called MyApp.SessionManager
. The login method contains an invocation of a login method on the User
class and triggers a callback if it succeeds. Using Ext.bind
, we set the scope of the success callback to the SessionManager
class and when it's called, we set the isLoggedIn
value to true
. Further code would then redirect the authenticated user to the rest of the application.
The problem is that the architect has not correctly processed the requirements. They have missed the second part (the part that mandates that logins should be persistent across sessions). In this code sample, we store the login state in memory. To support the requirements, we should use a cookie, localStorage
, or some other storage mechanism to make the login available between browser sessions. What will this code look like? Let's tweak this class a little, change one method, and add a few more methods:
loginSuccess: function(userDetails) { this.setUser(userDetails); }, isUserLoggedIn: function() { return window.localStorage.getItem('user') === null; }, setUser: function(userDetails) { window.localStorage.setItem('user', Ext.encode(userDetails)); }, getUser: function() { return Ext.decode(window.localStorage.getItem('user')); }
The replacement loginSuccess
method passes off to setUser
, which makes use of localStorage
to persist user details across browser sessions. We also provide an additional isUserLoggedIn
method to check localStorage
for any user details and a getUser
method to grab these details. Note the use of Ext.encode
and Ext.decode
to convert JavaScript objects to strings that can be inserted into localStorage
.
This is a more realistic implementation of this functionality that needs to be better specified at a higher level. Without translating this requirement from the client's stipulations through to the developer's instructions, we'd be omitting an important part of the application's feature set.
Data design
As with much of the application architecture, it will be a collaborative effort between the architect, developers, database administrators, and other members of the technical team. Data design is the result of a discussion about the data you need to store, where it will be stored, and how this will be reflected in the stores and models in your Ext JS. Let's look at a theoretical requirement for an application:
After three failed login attempts, the user account will be locked for 30 minutes.
This means that we need to record the number of failed login attempts and the last login attempt in the User
model or some other persistence method (such as a server-side database). Without it, we wouldn't be able to create the correct client-side logic and UI to support this requirement.
Code design
Perhaps, the bulk of an architect's work comes from structuring the application's code base. Depending on the size of the team, the architect may or may not be involved in writing the code itself, but they will have intimate knowledge of the application at a higher level (almost certainly at the class level and in important situations at the method level). In many cases, UML or other diagramming tools will be used to provide a way of recording and sharing the design, as shown in the following diagram:
The Album
class that comes from this would look like the following code:
// model/Artist.js Ext.define('MyApp.model.Artist.', { extend: 'Ext.data.Model', fields: [ { name: 'name', type: 'string' } ] }); // model/Album.js Ext.define('MyApp.model.Album', { extend: 'Ext.data.Model', fields: [ { name: 'name', type: 'string' }, { name: 'artist', reference: 'Artist' } ], getRunningTime: function() { return this.tracks().sum('lengthInMs'); } }); // model/Track.js Ext.define('MyApp.model.Track.', { extend: 'Ext.data.Model', fields: [ { name: 'title', type: 'string' }, { name: 'lengthInMs', type: 'integer' }, { name: 'album', reference: 'Album' } ] });
We define fields with the reference
config to set up a many-to-one relationship between artists and albums, and albums and tracks. The getRunningTime
method, which was shown in the previous class diagram, is an example of an area that an architect might not get involved in (they can leave the implementation details of this method to a developer).
This is the key aspect of architecture that we'll be covering in this book.
Technology evaluation
In this book, we will discuss Ext JS 5, so our technology choice should be fairly straightforward! Nonetheless, it's important for an architect to evaluate all of the relevant parts of their technology stack to ensure that it supports the product requirements. Here are some technology questions that are still relevant in our situation:
- Do we need to cater to various form factors (such as mobile and tablet)?
- Do we need to support Internet Explorer 8?
- Do we need to talk to a SOAP service?
All of these have potential ramifications that an architect must evaluate while planning a project.
Code standards and practices
In the same way that a building architect must make sure the design they create adheres to building code and safety regulations as well as ensuring the materials they use will create a pleasing finish, software architects must also take steps to guarantee the quality of the finished product.
Naming conventions, formatting guidelines, a process to deploy the application—all these contribute to having a professional workflow that makes it easy for the developers and project to succeed. The architect is the guiding hand, bringing the customer something that exceeds their expectations.
Documentation
There are many reasons why documenting the development process is a good idea. For example:
- Transparency between team members
- Providing a point of reference during development
- Offering a comparison for post-project review
Having a single point of reference for the design documents helps in a large team and assists with bringing new team members up to speed. It's a very bad idea for the architect to hold all of their ideas in their head, and it's a very good idea for this knowledge to be shared, discussed, and recorded. Such documentation might come in a variety of forms:
- Class diagrams
- UI wireframes
- User stories
- Coding standards
- Code documentation
Code documentation will often be automatically created as part of a build process, but an architect will be responsible for mandating this code to be documented and instituting a build step to generate it. Other forms will be part of a manual process and can involve the client, the development team, and the architect.
Note
These definitions are up for discussion! Wikipedia's software architecture page is extensive and offers multiple points of view at http://en.wikipedia.org/wiki/Software_architecture.
In the next few pages, we'll look at how software and software developers can find themselves in possession of an unwieldy code base, what makes it unwieldy, why it's a problem. We'll also look at the attributes that make for a well-architected software product.