Posts Tagged ‘architecture’

What is software architecture?

In my post about Event sourcing and CQRS, I touched on software architecture, but assumed it was already defined. I’d like to dive into that a bit more based on some recent reading.

My definition of software architecture is providing structure that allows productive, effective software development to occur.

Provides structure means having the appropriate technology, practices, culture, and organization in place to allow flourishing. As a software developer I tend to think of the technology (the code) first, but it is certainly not the only thing needed to have effective software architecture. More on that later.

Productive, effective software development means producing software that meets the needs of the business. There are 2 ways that software meets the needs of the business:

  • What the software does
  • How it does it

Or to use more formal terminology:

  • Functional requirements
  • Non-functional requirements

The functional requirements are the business behaviors that provide value to the customer. So for example, if we are creating software for a library, we need the ability to check out books, check in books, and keep a library catalog. Each of these has several behaviors behind it, and there are probably other behaviors I am missing.

The non-functional requirements are also known as the “-ilities” that describe things about the software besides its function. For example, testability is how easy the software is to test. Maintainability is how easy the software is to maintain. There are many others:

  • Evolvability
  • Scalability
  • Security
  • Extensibility
  • Feasibility
  • Reliability
  • Deployability

Besides the above, non-functional requirements might relate to the skill level of developers required to maintain the system, or the structure of the development teams that maintain it. (e.g. the presence of an off-shore development team)

The central claim of software architecture is that you can implement functional requirements in any architecture, but different architectural styles have different non-functional characteristics. What do I mean by that? They provide software structures that emphasize some characteristics at the expense of others. This is a classic engineering trade-off. The job of the software architect is to select an appropriate software structure that matches the non-functional requirements, which should also match the business expectations.

My term “software structure” would overlap with the term architectural pattern, which I first heard about from Mark Richards. Some examples of architectural patterns include:

  • Layered architecture
  • Microkernel architecture
  • Pipes and filters architecture
  • Service oriented architecture
  • Event driven architecture
  • Space-based architecture
  • Microservices

Ah yes, microservices, the buzzword of the last few years. I don’t have time to go into microservices in this blog post, but check out Jimmy Bogard’s Microservices FAQ for more info.

I mentioned earlier that there are different aspects of providing structure. In addition to architectural patterns, which affect the code (technology), there are:

  • organizational patterns (e.g. are teams organized by business capability or by similar job roles? What is the mapping between products to teams?)
  • practices (such as TDD or Extreme programming)
  • culture (probably another blog post altogether)

Ideally all four aspects of structure work together to accomplish the desired outcome. (I’m not sure of the origin of this list of 4 items came from, if anybody knows, leave a note in the comments.)

Event sourcing and CQRS

As part of the #2018TechReadingChallenge, I’ve been working my way through Microservices Patterns, by Chris Richardson (currently a Manning MEAP).

Event sourcing and CQRS are two key architecture concepts in the book that have less to do with the “micro” in “microservices,” and more to do with software architecture in general. While they are often mentioned together, they are separate concepts, and solve slightly different problems.

Event sourcing fits in the general category of an append only model, which is a way of persisting the data in your application. Instead of storing the current state, it stores history that led up to the present. It stores these using events, which are immutable, and represent business intent. Events record a thing that has happened.

A related concept in domain driven design is an aggregate, which rebuilds state by querying the event history.

CQRS stands for Command Query Responsibility Segregation. This relates to an OO principle, command query separation, which classifies methods into “commands,” which mutate the data (but does not return data), and “queries,” which return data only. In CQRS, we extend this principle to the design of a subdomain, and separate the responsibility of writing the data from reading the data. The two sides often communicate using events.

It solves a “stale data” problem in a collaborative domain. A collaborative domain is a business domain where multiple users are working together on a set of data, and expect that data to be coherent. The data is only as stale as the lag between the command side and the query side. However, by separating these sides and putting a visible part of the architecture between them, we have raised awareness that there will always be stale data in a collaborative system.

Another advantage to CQRS is that the read side and the command side can be scaled independently, so for example, if the number of queries is vastly greater than the commands, you can add more nodes that handle the queries.

For more on these concepts, see the CQRS Journey page on Microsoft, specifically the Exploring CQRS and Event Sourcing e-book. I’m also drawing from Patterns for Building Distributed Systems for The Enterprise, by Michael Perry on Pluralsight.

Being objective about Objective C

(Sorry, couldn’t resist the pun.) A few months ago, I started a new job that required me to learn Objective C and Cocoa/Cocoa Touch development on the Apple platform. In this post, I’ll relate a few concepts that I learned in other languages that crossed over to the Apple platform.

MVC architecture

In web app development, the view is (arguably) the DOM. The DOM is loaded at a certain point in time: when the browser is finished parsing the initial payload, a load event is generated, and as a developer you can specify a handler for this event. This allows you to do things when that view appears, like populate it with data.

In iOS, the load event is similar to viewWillAppear. A NSViewController subclass can implement this method to perform custom behavior when the view appears, such as updating the UI based on the contents of some property.

Connecting the view to the controller

In Cocoa/Cocoa Touch, outlets and actions are used to connect objects in the view with code in the controller. Outlets are for linking objects in the view to a property in the controller. This allows the controller to manipulate that object, for example, setting the title of a button object. Actions are triggered when an event happens to an object. For example, an action responds to a click on a button. Action methods are passed the sender of that action.

I would compare outlets to DOM objects, and I would compare actions to DOM event handlers. Xcode makes creating outlets and actions a drag and drop operation, but in Javascript, you use document.getElementById or jQuery. DOM events are attached to an object, and specify a callback function, which can also take an argument of the sender (the this keyword).

Event loops

An event loop handles all incoming events and allows the application to respond appropriately. More generally, an event loop takes a queue of messages and processes them one at a time. An example of a message would be “call this callback function”. Processing that message would be actually executing the callback. For example, in Javascript, you specify a callback for the click event. When the click happens, the message to call that callback is placed on the message queue. The loop processes messages one at a time, so if you have another Javascript function that is currently processing a table (maybe shading the rows), the click callback message will not be processed immediately.

The Cocoa main event loop, GLib main event loop, and Javascript event loop are conceptually the same.

Node.js uses a single-threaded Javascript event loop to great advantage. Using Node, it is fairly easy to implement a scalable, event-driven web application.

Cocoa extends the main event loop, allowing you to create other queues. Queues are event loops that may or may not run on another thread. However, messages dispatched on the same serial queue will always be executed one at a time. This allows you to protect variables that aren’t thread safe by only accessing them from a particular queue.

The Glib event loop is used by a GUI library such as Gtk+ to make a Linux application. I’ve used these libraries while fixing a few Gnucash bugs and while writing a Twitter client.

Conclusion

My experience with Gtk+ and Javascript allowed me to quickly pick up core Cocoa concepts and design patterns. Now if I could only remember to do all UI stuff on the main queue!