# Braids, Weaves and the Complecting Problem

## A strategy for decoupling

The refrain, “ loose coupling, high cohesion ” speaks to two kinds of complexity. In the case of coupling the “logical complexity” of the code: the degree to which its components are interdependent. In the case of cohesion the “conceptual complexity” (of the problem domain): how interdependent representations are simplified. This article will sketch out a library for treating coupling as a general problem.

The conceptual metaphor I will begin with - and all programming articles must have one - is that of braiding together various strands. In Gary Bernhardt’s re-envisioning of the “Boundaries” between layers of programming he proposes moving away from an inherently intertwined paradigm of programming, where each layer is necessarily aware of how it couples to the other layers: its return values, its argument prototype perhaps (gasp!) its logic itself is essentially contingent on how the rest of the application is structured. He proposes that “layering” becomes a matter not of domain logic, but of programming logic. The boundaries reflect what each component is doing (accessing state, pure computation, etc.) rather than what it means (calculate fuel costs, open door, etc.).

The reverse seems like a necessary and obvious state of affairs to some programmers,

`require ‘time’`
`def get_user “Michael is 24 on May 30th”end`
`def days_till_birthday(data) month, day = data.match(/\w+ is \d\d on (\w)+ (\d\d)/).captures Date.parse(month + ‘ ‘ + day) - Date.todayend`
`print days_till_birthday(get_user), ‘ days until birthday’`

We have a function which provides us with some user data in a given format and function parsing that format for information. What we’d really like to know, however, is a difference in two dates and the rest is details.

There is less coupling here than there might be, the obvious increase would be if :days_till_birthday called :get_user itself, this would be the most pernicious kind. This would render the conceptual utility of separating code into function rather ineffectual.

If not the most obvious kind of coupling (calling co-dependene), what kind of coupling is there?

Well compare with,

`# …`
`def extract_date_from_user(user) user.match(/\w+ is \d\d on (\w)+ (\d\d)/).capturesend`
`def days_till_birthday(data) month, day = extract_date_from_user(data) Date.parse(month + ‘ ‘ + day) - Date.todayend`
`puts days_till_birthday(get_user).to_int.to_s + ‘ days until birthday’`

Here we add a level of indirection (:extract_date…), so receiving some of the benefits of decoupling: isolatable testing, conceptual clarity, ease of modification, ease of reasoning, etc. But we still arent there yet.

Remember the question we’re really asking from a logical point of view is about the difference between two dates, indeed we might even have found a library function of the kind below to do this:

`def diff_days(date) Date.parse(date) - Date.todayend`

Why write code so totally contingent on the rest of the logic of the program (days_till_birthday) when the problem is totally general?

`def extract_date_from_user(user) month, day = user.match(/\w+ is \d\d on (\w)+ (\d\d)/).captures month + ‘ ’ + dayend`
`def diff_days(date) Date.parse(date) - Date.todayend`
`puts diff_days(extract_date_from_user(get_user)).to_int.to_s + ‘ days until birthday’`

This is closer to a “solved form” for total decoupling: we thread together the piece of our various problem-solving components only at the point we solve a particular problem.

Indeed there is a general structure to the class of such solutions: the queue.

Is this not equivalent,

`require ‘time’`
`def get_user(id) “Michael is 24 on May 30th”end`
`def extract_date_from_user(user) user.match(/\w+ is \d\d on (\w+) (\d\d)/).captures.join(‘ ‘)end`
`def diff_days(date) Date.parse(date) - Date.todayend`
`def print_message(days) puts days.to_int.to_s + ‘ days until birthday’end`
`[:get_user, :extract_date_from_user, :diff_days, :print_message].map { |s| method(s)}.inject(1) { |state, fn| fn.call state}`

That is, in the code example above there is an implicit queue of function calls each passing their return value along to the next. The function Enumerator#inject serves this purpose (threading a value) in this rewrite.

The benefits of the kind of decoupling should be clear: each unit of the program it totally cohesive (for free!) — it is responsible only for the smallest and clearest piece of logic which makes sense the “logic of the problem domain” in its entirety is captured in the queue not in the functions! The functions could appear in any application.

Add to this the standard benefits of decoupling: isolation, testing, composition, reasoning, etc.

#### The Forms of Coupling

There are various “solved forms” for coupling-together independent functions,

1. Unitary state transformation
2. Co-unitary state transformation
3. N-ary state transformation
4. Unitary state transformation with dependencies
5. Co-Unitary state transformation with dependencies

(1) is the case above, the functions involved each have a single “gap” which can be used to thread values through a -> b -> c which has the effect of a variable changing state (x = a(0); x = b(x); x = c(x) ).

Since this single gap can be filled by an object (or any complex value), it is sufficient to generally describe any state dependence whatsoever. We require only a single gap to do general threading.

Co-unitary state transformation is what I have called weaving two such threads together: two queues of functions passing control back and forth.

The typical example would be validation,

`#general formdef validate_x(value)  if value !~ /xyz/ raise “Invalid” endend`
`#general formdef get_x()  puts “Enter X” getsend`
`form_values = [:get_username, :get_password, :get_email]validators = [:validate_username, :validate_password, :validate_email] `

Supposing that each of those functions existed, we would require,

:form_value -> :validator -> :form_value -> …

This is (2).

As for the N-ary I suspect it’s sufficiently general to have,

:x -> m(:x, :y) -> :y

that is, to provide a function m(left, right) which can wrap the subsequent function calls as much as it would like creating a “middle wear” strand throughout the entire “weave”.

Finally in of these cases we have the potential that our functions are of multiple parameters where the previous function in the chain should not simply “provide the rest”. Functions in the chain should not be designed to be in any particular chain: this is as bad as the original case (indeed it is the corresponding form of the problem).

So for example,

`def add(x, y) x + yend`
`def sub(x, y) x - yend`
`def data (Random.rand * 100).to_iend`
`operations = [:add, :sub, :add]op_deps = [1, 2, 10]`
`input = [:data, :data, :data]`

:data provides only one piece of input for the math functions, op_deps should provide the other. This amounts to [:add_one, :sub_two, :add_ten] which we could have written as wrappers over the originals.

Occasionally such wrappers (which I call “grafts” in my library) will be needed, adapters which turn completely general logic-focused units into problem-domain units.

However for many cases providing a ‘dependencies’ array to go along with your operational queue will be much better than adapters.

#### A Library for Coupling

And so, I shall now introduce my library. I’ll merely provide some code examples and some commentary on terminology and linking it to the examples above — in the hopes that the prior discussion was preparation enough.

The commentary is in the notes next to the article body.

### Stateful Queues (“Complects”)

`# methods for these examples`
`def add(x, y) x + yend`
`def mul(x, y) x * yend`
`def addOne(x) x + 1end`
`def mulTwo(x) x * 2end`

Dependent functions

`dependent_a = Complect.new [:add, :mul], [5, 10]dependent_b = Complect.new [:add, :mul], [1, 2]`
`puts ‘dA’print ‘(((1 + 5) + 1) * 10) * 2 = ’puts dependent_a.weave(1, dependent_b)`
`puts ‘dB’print ‘(5 + 5) * 10 = ’puts dependent_a.run(5)`

Free (non-dependent) functions

`free_a = Complect.new [:addOne, :addOne]free_b = Complect.new [:mulTwo, :mulTwo]`
`puts ‘fA’print ‘((5 * 2) + 1) * 2) + 1) = ’puts free_b.weave(5, free_a)`
`puts ‘fB’print ‘5 + 1 + 1 = ’puts free_a.run(5)`

Middlewear

`puts ‘Weave middlewear’print ‘ = ‘, free_b.weave_with(5, free_a) { |state, fn, _| print “ (#{state}) #{fn.name}” state}`

Output

`dA(((1 + 5) + 1) * 10) * 2 = 140`
`dB(5 + 5) * 10 = 100`
`fA((5 * 2) + 1) * 2) + 1) = 26`
`fB5 + 1 + 1 = 7`
`Weave With (5) addOne (6) mulTwo (12) addOne (13) mulTwo = 26`

### Stateless Queues (“Couples”)

Free

`def data_producer [‘Michael’, (Random.rand * 100).to_int]end`
`def data_transformer(data) {name: data[0], age: data[1]}end`
`def data_consumer(data) if data[:name].length > 0 && data[:age] > 1 puts data.inspect else puts “invalid format” endend`
`producer = Couple.new Array.new 5, :data_producerconsumer = Couple.new Array.new 5, :data_consumer`
`producer.weave_with(consumer) do |consumer, producer| [[consumer], [->() { (data_transformer(producer.call)) }]]end`

Dependent

`def input(message) puts message getsend`
`def validate(data, regex) puts data =~ regex ? ‘match’ : ‘fail’end`
`questions = [‘Name?’, ‘Age?’, ‘Location?’]questions = Couple.repeating :input, questions`
`validators = [/[A-Za-z]+/, /\d{1,3}/, /[A-Za-z]+/]validators = Couple.repeating :validate, validators`
`questions.weave(validators)`

Hybrid (technically Free)

`def inputter(message) ->() { puts message gets }end`
`def validator(regex) ->(data) { puts data =~ regex ? ‘match’ : ‘fail’}end`
`Couple.weave [inputter(‘Name?’), inputter(‘Age?’)], [validator(/[A-Za-z]+/), validator(/\d\d/)]`

Output

`{:name=>”Michael”, :age=>87}{:name=>”Michael”, :age=>85}{:name=>”Michael”, :age=>67}{:name=>”Michael”, :age=>72}{:name=>”Michael”, :age=>57}`
`Name?MichaelmatchAge?23matchLocation?UKmatch`
`Name?23failAge?Michaelfail`

Thus concludes the ‘ActionList’ aspect of my library, which here I’ve called a queue. (‘Action’ inspired from ‘IO actions’, etc. via Haskell).