My Ideas

Table of Contents

Feel free to contact me if you want to help materializing these ideas or discuss them.

Projects

Concepts

Air Conditioner & Functional Programming

I realized our Air conditioner at office (and all other ACs that I know of) and it's remote is a great example for how functional programming and reducing state and side effects help reduce complexity.

The remote makes and stores the state, and the remote is the single source of truth. On each interaction that the remote makes with the AC, It sends it's entire state to the AC and the AC applies it. This really reminds me of Clojure's state management.

I'm not actually sure of how the AC works, and I don't want to talk about the electronics and actual implementation. This is just the mental model I like to play with as a software engineer.

If we wanted to model this system, it would look like this:

(def ac (atom {:mode "summer"
               :temp 23
               :fan 3}))

(def remote (atom {:mode "summer"
                   :temp 23
                   :fan 3}))

;; Idempotent function
;; Send the new state to the AC from the remote
(defn remote-send-changes! [state]
  (reset! ac state))

;; Update the display and the state of the remote,
;; and send changes
(defn remote-take-user-input! [state]
  (reset! remote state)
  (update-display! state)
  (remote-send-changes! state))

;; Call the functions (make changes)
(remote-take-user-input!  {:mode "winter"
                           :temp 28
                           :fan 2})

(@remote) ;=> {:mode "winter" :temp 28 :fan 2}
(@ac) ;=> {:mode "winter" :temp 28 :fan 2}

Its components:

The flow:

Notice how our update operation is idempotent: No matter how many times I call (remote-send-changes state) it will have the same outcome, and always the same output for the same input.
The AC doesn't manage any state. it simply keeps the state that is passed to it. The remote also has it's own state, but it's the source of truth and upon the first contact between the remote's signal and the AC, the ac will apply all of the remotes' state unto it's own.

But let's say we made a bad design decision, or were forced because of requirements, and now the AC also manages a state of it's own, because it has it's own buttons. And both the remote and the AC have displays for showing the state of the AC.
This might be a valid design for some use cases, but not always.
We now need a way to sync the remote and the AC unit together so we don't get unpredictable behavior.

So here are some ways we might approach this problem:

The remote as the source of truth (Horrible UX)

The simplest approach would be that the remote is the source of truth anyways, and it doesn't care what the state of the AC is. it just sends the new state on the AC applies it. This is as simple as before, but now, since we have given the user the option to update the state of the AC from itself, now their changes will be suddenly overridden after an interaction with the controller.
Also, what the remote displays as the state of the AC will be out of sync with what the AC unit shows as it's state.

Online Sync (Horrible UX + Very complex)

One way is to make the remote(s) and the AC always be in sync as soon as a change is made and accepted on the AC unit, over a common wireless interface (WiFi probably).
While this sounds cool, imagine having to connect your AC and it's remotes to a WiFi, the security risks, privacy risks, the unreliability, overall horrible idea (my idea).

This might sound stupid but it is a great example and metaphor for many actual products that are released into the market. The "smart" fridges that connect to the WiFi for example, or "smart" toaster with a LED display on it needing software updates, or "smart" cars that might get hacked through an SSL vulnerability!?
I can go on and on. These are examples of lazy and greedy "non-engineering".

Using non-WiFi RF (Radio Frequency) is also a choice here, which I think is better than WiFi but still many of the problems persists. Remember, we're discussing this from the software and engineering perspective not the exact implementation.

The remote and AC sync on first touch, AC as the source of truth (OK UX, Lower complexity)

The flow will be:

  1. Changes are made on the AC -> temp: 26 -> Remote and AC are out of sync (remote shows temp: 23, AC temp: 26)
  2. User from remote sees temp is 23 and wants to update it to 24
  3. User from remote presses "temp up" once
  4. Remote sends sync signal to unit, unit sends it's state back
  5. Remote checks if it's state is conflicting with the AC, If the state conflicts, discards it's input, updates it's state with the AC and updates its display. The user is now actually aware of the state on the AC, and can decide based on it.
(def ac (atom {:mode "summer"
               :temp 26
               :fan 3}))

(def remote (atom {:mode "summer"
                   :temp 23
                   :fan 2}))

(defn remote-take-user-input! [state]
  (if (not= @remote @ac)
    (do
      (swap! remote conj @ac)
      (update-display! @remote))
    (update-diplay! state)
    remote-send-changes! state))

(remote-take-user-input! {:mode "summer"
                          :temp 24
                          :fan 2})
;; AC doesn't change, remote's state and display get updated with the AC state

(@remote) ;=> {:mode "summer" :temp 26 :fan 3}
(@ac) ;=> {:mode "summer" :temp 26 :fan 3}

;; Now that the states are in sync:
(remote-take-user-input! {:mode "summer"
                          :temp 25
                          :fan 2})
;; AC temp gets updated

(@remote) ;=> {:mode "summer" :temp 25 :fan 2}
(@ac) ;=> {:mode "summer" :temp 25 :fan 2}

I think this satisfies our design requirements, and we can see that while it's clearly more complex than our initial design of "only one remote and the remote as the source of truth", it's still fairly simple and robust because of our more functional approach.