Tuesday, August 25, 2015

Managing Multiple Ruby Versions with uru on Windows

My undergraduate software engineering professor was awesome. Here's one bit of advice he shared during his course that really stuck with me over the years.
Pick a scripting language.  Any Scripting Language.  Learn to use it really, really well.
Compiled programming languages obviously have a purpose, but lightweight, interpreted scripting languages are an important tool as well. An interpreted scripting language is the perfect choice for one off tests, tedious text manipulation, automated tasks, and simple tools. Scripts are easy to write, easy to share, and good enough to get the job done.

My prof used Perl and was a whiz at it. I eventually settled on Ruby as my scripting language of choice. While the core language works really well across different platforms, as a predominantly Windows user,  I find that Ruby sometimes runs into problems in odd situations. One thing that is particularly annoying is the lack of a Ruby version manager. Version managers are a great idea.  The basic idea is to make it easier to switch between different Ruby versions on the command line so that it's easier to test and develop against multiple projects.

OS X and Linux users get RVM. Until recently, the only option on Windows was pik, a woefully out of date and problematic open source project that is no longer under active development (I'm not going to even bother linking to it). Thankfully, now there's uru, a cross platform Ruby environment manager that works on Windows, Linux, and OS X.

I've been using uru for close to a year now and it's worked out very well for me.  That said, when first getting uru up and running I did run into a few snags. Here's the steps I used to overcome those problems. If you're trying to run multiple Ruby versions on Windows you should give uru a try.

Wednesday, May 20, 2015

Introduction to Microservices Architecture

I recently returned from the O'Reilly Software Architecture conference where I presented/facilitated a workshop on Rapid Software Architecture Exploration. My workshop went great. According to the reviews it was among the better presentations at the conference -- which is awesome! But that's not what this blog post is about.

Microservices architecture was a significant part of the conference with well over 50% of the sessions dedicated to the topic. And I'm being really nice in saying it was only 50% - I think it was closer to 90% and perhaps could have been called the O'Reilly Microservices Conference. Anyway, so there's a ton of hype on this topic.  And since we're looking closely at the (loosely defined) microservices architectural style for an upcoming project at work, this was a great learning opportunity. I am currently reading the book Building Microservices by Sam Newman but I thought it would be useful to share some of the insights I gleaned from the conference now rather than waiting until I've finished the book.

"And you are now an anointed solider in the microservices army..."

What are Microservices?

Adrian Cockcroft (of Netflix fame) defines microservices as the following.
Microservices are a loosely coupled Service-Oriented Architecture (SOA) with bounded contexts.
This definition has a couple of parts that are worth further exploration.

Tuesday, March 31, 2015

Communicating Design Intent by Sharing the Paths not Taken

If you're even remotely a movie buff then you'll probably really enjoy Tony Zhou's "Every Frame a Painting" series.  His analytical, accessible, and entertaining film studies mini-documentaries are wonderful. Each video in the series focuses on one main idea, often something overlooked or perhaps under appreciated by other films studies enthusiasts (analysts? critics?).  This bit of analysis on what makes Jackie Chan's physical comedy so brilliant is... well, itself brilliantly done.

In this episode of Every Frame a Painting, Tony discusses the idea of showing character choice rather than just talking about it, using Snowpiercer as an example:
In nearly every blockbuster you've watched or tell-tale game that you've played, you've seen moments like this: the protagonist has to make a choice and there's no way to reverse it.
Just to be clear, I think moments like these are great and a foundation of good storytelling but I do wish in movies they weren't presented through dialog.  So today I look at one possible alternative.  In fact it's one of the oldest traditions in cinema.  How do you show character choice?  Left or right.  That's it.
In a similar fashion as many blockbuster and video game protagonists software architects regularly encounter complex choices that often can't be easily reversed. Or rather, the architecture we're designing experiences those complex choices (since in this metaphor we're working behind the camera and the architecture is the character on screen). But, unlike blockbusters and video games, software architects don't have the luxury of an audience that can simply watch the architecture evolve with each design decision made.

Even on small teams, generally only a few people at a time are in the room or at the whiteboard when a key decision about the architecture is made.  In some ways it's as if we are asking downstream designers to watch only the last 10 minutes of Snowpiercer and then try to figure out why it's such a big deal for Chris Evan's character, Curtis, to do what he does.  Without the context of these critical decision points that are constantly happening throughout a character's/architecture's journey, the audience/downstream designer loses significant rationale that could help explain a lot.

Are there methods that architects can use to make architectural choice evident?  The answer to this question is certainly, "Yes!"

Tuesday, March 17, 2015

Agile Software Architecture (with George Fairbanks)

George Fairbanks and I chatted via Google+ Hangout in February 2014 about agile software architecture. I think we found a groove pretty quickly and the conversation overall went great. I've created bookmarks of some of the main topic areas that we covered to make it easier to jump to bits of the discussion you might find more interesting.




During this Hangout we meandered through several topics starting with walking skeletons and leading to...

Tuesday, March 3, 2015

Architecture Haiku

The most effective way to transfer complex, abstract ideas from one person’s brain to another person’s brain is by writing the ideas down. This premise permeates our whole approach to software design.  Entire books are dedicated to creating better documentation!  Following traditional documentation advice inevitably leads to comprehensive, albeit verbose, documents filled with important details that, sadly, too few stakeholders read.  There must be a better way.

Introducing the Architecture Haiku

George Fairbanks originally came up with the idea of the Architecture Haiku as "a one-page, quick-to-build, uber-terse design description."  With only one page of paper (assumed standard, A4) to work with there is no space to be indecisive or indirect.  There might not even be room for diagrams - which at first sounds crazy, but perhaps is crazy brilliant!  We tried this idea on my team and it turned out to be a great, lightweight method for writing down and sharing architecture decisions.

With so little room, picking the right information to include is extremely important.  Here's what Fairbanks recommends:

Wednesday, December 3, 2014

Dante can be Agile too

[I recently gave a talk for the monthly SEI Agile Collaboration Meeting. The Agile Collaboration Meeting brings together upwards of 50 or so agile practitioners from throughout the federal and DoD space including civilian contractors. This post is a summary of the talk I gave at the September meeting.]

When you do a search for pictures of "unrequited love" one of the first images that comes up is this 1884 painting by Henry Holiday titled "Dante and Beatrice."  As Beatrice and Dante were Italians it is extremely important that you pronounce her name in your mind correctly – Bee-a-tree-che – using the Italian pronunciation.  In this painting you see Dante, the poet of the Divine Comedy among many other works, chilling on a bridge as he is snubbed by a posse of three women.  Beatrice is the one in yellow completely ignoring Dante, who probably went out of his way to be in the right place at the right time so he could see her.

In real life, Dante was obsessed with Beatrice.  They met when they were children and their families cruised in many of the same social and professional circles.  Allegedly it was love at first sight for Dante, then age 9.  Both Dante and Beatrice married other people and apparently met only one other time before Beatrice died at the young age of 24. Dante wrote of Beatrice as "his savior" and she was a prominent character in his Vita Nova (a collection of poems professing his love for both the actual and a metaphorical Beatrice) and Divine Comedy (in which she escorts Dante through Heaven).

I propose that there is an unrequited love between the software architecture and agile communities; software architecture is the Dante to an agile Beatrice who simply ignores him.  Certainly if this were true there would be some observable facts to either support or refute this idea.

Dante and Beatrice, painting by Henry Holiday (1884)

Thursday, November 6, 2014

The Case for Minimalism in Software Architecture

"Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away." - Antoine de Saint-Exupery
I was first introduced to the idea of minimalist software architecture in an article by Ruth Malan and Dana Bredemeyer, "Less is More with Minimalist Architecture" (PDF).  The basic premise is devilishly simple: the software architect's job is to "only do with architecture what is absolutely necessary to achieve key, broadly scoped qualities of your system."  Any design decisions that do not support this goal are left to the discretion of downstream designers.

Wednesday, October 29, 2014

Defect-Driven Process Improvement

Defects can tell you a lot about your team.  And not just what the problems are in the code.  The Team Software Process uses a very simple method of defect classification to unlock hidden insights. My team recently did some analysis on our bug database at the conclusion of a project and unearthed some surprising information about how we deal with requirements as well as some weaknesses we need to work on.

Simple Defect Classification 

The simplest defect classification method involves manually evaluating defects to add contextual meta information.  The Team Software Process suggests some of the following pieces of information as a starting point for creating a defect taxonomy.
  • Related Feature - the feature to which the defect was reported against 
  • Module Discovered - the code in which the defect was found 
  • Defect Type - a standardized description of the defect, such as "assignment," "data," or "syntax." 
  • Reason Injected - why did the bug make it into the software in the first place?    This should also be standardized, for example "education," "oversight," or "mistake." 
  • Phase Injected - what were the activities being performed when the defect was injected?  For example, "requirements," "design," or "implementation." 
  • Phase Discovered - what were the activities being performed when the defect was discovered? These would be the same as the list for phase injected.

This simple method has some disadvantages, the biggest one being that you usually will not be able to understand the reason a defect was injected until after you understand the root cause of the defect. Also, unless you were the one who wrote the code, you can only guess at the reason (was this an oversight, mistake, or education?) the defect was injected. As such, some knowledge of the system is required to perform the analysis. There are other methods for defect classification that overcome this problem but take a little more training and planning to apply well.  One example is the Orthogonal Defect Classification method from IBM Research.

Since the defects in a software system are a direct reflection of the process, knowledge, and skills of the team that injected them, once the defects are classified you have some serious power for enacting positive change.

Wednesday, October 22, 2014

Dealing with Constraints in Software Architecture Design

Definition of constraint (n)

  • con·straint
  •    
  • [ kən stráynt ]
  •    
  1. limiting factor: something that limits freedom of action
  2. state of restriction: a state in which freedom of action is severely restricted
  3. lack of spontaneity: a lack of warmth and spontaneity in somebody's manner or in the atmosphere on a particular occasion

In software architecture design, constraints come in two basic flavors - technical and business.  On most projects there are only a handful of constraints, but these constraints are a highly influential architectural driver.  Constraints, as the dictionary definition above indicates, are a limiting factor and severely restrict options for making design decisions.  They are also fixed design decisions that cannot be changed and must be satisfied.  You could think of constraints as the ultimate non-negotiable, "must have" requirement.  It is for this reason that architecture design constraints must be created and accepted with care.

Wednesday, October 15, 2014

Architectural Drivers: Building Blocks for Decision Making

Architectural drivers are formally defined as the set of requirements that have significant influence over your architecture.  In other words, there are some requirements that will help you decide which structures to pick for your system design and others that are less consequential in the context of software architecture.  This implies that it is extremely important to get the architectural drivers right early in a project, as architecture structures will become more difficult to change as the developed software becomes more realized.

Thinking about early requirements as "drivers" can also help you to create traceability from stakeholder concerns to specific architectural decisions made.  Having this traceability is great because it helps to promote important qualities in your team, such as agility.  With traceability you can make changes on purpose and with confidence as you understand the genesis for structural decisions.

What are Architectural Drivers?

Architectural drivers have significant influence over the design of a system and are the determining factor over whether one design is “better” or “worse” than another that produces the same features. Architectural drivers are nearly always divided into four categories.  Some people might go with only three categories (talking generally about constraints), and others might include other things as drivers, but if this is your first time working with architectural drivers you should start with these four categories before tailoring.

Architectural drivers can be one of the following.
  1. Technical Constraints
  2. Business Constraints
  3. Quality Attributes
  4. High-Level Functional Requirements
Let's go into more detail for each of these categories.

Technical constraints are technical design decisions which absolutely must be satisfied in the architecture. These are generally fixed from the beginning of a project and may be expensive to change as the project progresses. Constraints, as the the name suggests, cannot be changed.

Business constraints are decisions imposed by business considerations that must be satisfied in the architecture.  Like technical constraints, business constraints are generally fixed from the beginning and have a significant influence on decision making for the design.  Likewise once in place these are considered unchangeable.  An example might be a specific delivery date, budget, or 

Quality attributes, sometimes called quality requirements, are specific criteria by which a system’s operations can be judged – that is, how well a system performs specific functions. Quality attributes greatly influence the design of the system.  In many cases, the same functionality can be achieved in a number of ways and so it is the quality attributes that ultimately determines when one design is better or worse than another.  Quality attributes receive a significant and thorough treatment in Software Architecture in Practice and you can read a sample chapter introducing quality attributes online.  Quality attributes are recorded as scenarios that describes a qualitative response within the context of specific system functionality.  For example, performance is a common quality attribute, but performance when the system is doing what?

High-level functional requirements provide an overview for what the system will do, the functions and features of the system. These might take shape in any number of formats from epics to stories to use cases to ye olde "shall" statements.  While quality attributes might determine specific structures you choose, the ultimate goal of the software you are building is to build achieve some bit of functionality.  From an architecture perspective, you won't go to exhaustive detail, and indeed it's best not to go into too much detail as diving deep too early can seriously delay the project.

What about Non-Functional Requirements?

If you've read any of the software engineering literature, you'll see the term "non-functional" requirements used fairly often.  The basic thinking was that there are these things that are functional requirements, and then there's things that are not functional requirements, non-functional requirements.  Setting aside the fact that calling requirements "non-functional" is kind of silly and certainly not precise, this term comes up enough that it's important to understand it in the context of architectural drivers.

Most of the time people are referring to constraints and quality attributes when they talk about non-functional requirements.  Unfortunately, most of the time teams will lump all "non-functionals" into a single list. This is unfortunate because knowing specifically what kinds of drivers you are dealing with gives you a lot of decision making power.

Functional requirements are negotiable and must be shown to be correct.

Constraints cannot be changed once fixed.

Quality attributes imply trade-offs and often can't be directly tested until very late in the system's lifecycle. As a result you will need to find proxies, run experiments, and reason about the structures you've selected to determine whether or not you've promoted the right quality attributes.