What Exactly Is Composable?

DZone 's Guide to

What Exactly Is Composable?

We look to define the term in this post.

· Open Source Zone ·
Free Resource

Programmers tend to throw this word around a lot but it's often not clear what it means. At the lowest level, we have syntax, grammar, and source code. At this level almost everything is composable. Moving up a few levels, we get to semantics and semantic composition, and this is where things get a bit more tricky. This is the level where most of the discussions tend to happen. I'm going to use threads as an example to demonstrate the point. The code snippets will be in Ruby.

Here's a syntactically valid piece of Ruby:

Thread.new { 100.times { counter += 1 } }

You should rightfully ask a few questions now because syntactic validity is a very low bar to clear. The above piece of code isn't actually valid. It will throw an error at runtime because we haven't defined counter. But this code is syntactically valid so we can talk about syntactic composition. The simplest thing we can do with the above code is to add more syntactically valid code to it.

Thread.new { 100.times { counter += 1 } }
Thread.new { 100.times { counter += 1 } }

I duplicated the code but that's fine because sequential composition of syntactically valid code is a perfectly fine way to "compose" code in Ruby. Let's move up the abstraction ladder a little bit and make this code actually valid at runtime.

counter = 0
Thread.new { 100.times { counter += 1 } }
Thread.new { 100.times { counter += 1 } }

The above piece of code is now valid with respect to Ruby's runtime semantics. But there is something fishy going on here. The above code is now technically semantically valid and I can tack on as many copies of Thread.new { ... } and everything will continue to remain semantically valid with respect to Ruby's runtime semantics.

If you've written code with threads then you know what the "error" is, updating counters with += is not a valid way to compose concurrent programs because += doesn't preserve the semantics we expect. What we expect is atomicity of updates but += is not an atomic operation.

And that brings me to my final point. When talking about composition or composability we need to define the context, the semantics, and the rules that preserve the semantics. Preemptible threads don't respect non-atomic semantics so if we have two semantically valid programs that are correct when viewed with sequential semantics then they will not be correct when composed and viewed with concurrent/threaded semantics. This is what people mean when they say threads are not composable. They mean that sequential/non-atomic semantics are not preserved.

compose, definition, open source, ruby, syntax

Published at DZone with permission of David Karapetyan , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}