December 16, 2025
Inspired by Miyuki Koshiba’s talk at RubyWorld Conference 2025
At RubyWorld Conference 2025 , Miyuki Koshiba presented a talk that challenges one of our most ingrained assumptions as developers: that code is something abstract, invisible, and detached from the physical world.
Her presentation, “Tangible Code: Rubyで『見て・触れて・変えてわかる』コードのしくみ” , explores a powerful idea — what if code could be seen, touched, and felt? What if programming were not only logical, but also bodily and sensory?
This article summarizes the core ideas of that talk, the technical approach behind it, and why it matters for how we learn and teach programming.
From Abstract Code to Tangible Experience
In most software systems, code operates behind the scenes. Users interact with interfaces, but the logic itself remains hidden. Koshiba asks a fundamental question rooted in algorithmic art:
“If a work is made of code, shouldn’t the code itself also be something we can experience?”
This question leads to the concept of Tangible Code — an approach where:
- Code can be seen (displayed alongside its output)
- Code can be touched (via physical sensors)
- Code can be changed (with immediate visual feedback)
The goal is not just artistic expression, but deep understanding.
Advertise on RubyStackNews
RubyStackNews is a niche publication read by Ruby and Rails developers worldwide.
Our audience includes senior engineers, tech leads, and decision-makers from
the US, Europe, and Asia.
<h3>
Sponsorship Options
</h3>
<strong><img src="https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/72x72/1f4dd.png" alt="📝"> Article Sponsorship</strong><br>
Your brand featured inside a technical article (clearly marked as sponsored).<br>
<span>USD 250 per article</span>
<strong><img src="https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/72x72/1f4cc.png" alt="📌"> Inline Sponsored Block</strong><br>
Highlighted sponsor section embedded within an article.<br>
<span>USD 100 per week</span>
<strong><img src="https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/72x72/1f4ce.png" alt="📎"> Sidebar Sponsor</strong><br>
Logo + link displayed site-wide in the sidebar.<br>
<span>USD 150 per month</span>
- Highly targeted Ruby / Rails audience
- Organic traffic from search and developer communities
- No ad networks — direct sponsorships only
<p>
Interested in sponsoring RubyStackNews?
</p>
<a href="https://wa.me/5493434192620">
Contact via WhatsApp
</a>
The Core Concept: See, Touch, Change
Tangible Code is built on a simple but effective loop:
- Touch a physical sensor
- Change a variable in code
- See the result immediately in a visual output
This tight feedback loop transforms programming from a purely mental activity into an embodied one.
In practice, this is achieved using:
- Physical sensors (buttons, potentiometers, rotary encoders)
- Real-time visual generation
- Ruby running across the entire stack
Why Ruby Everywhere?
One of the most striking aspects of the project is the decision to use Ruby for everything.
Not Arduino C++. Not Java-based Processing. Not JavaScript.
Just Ruby.
The final architecture looks like this:
[Physical Sensors]
↓ GPIO
[PicoRuby (Raspberry Pi Pico)]
↓ Serial (UART)
[Ruby + processing gem]
↓
[Real-time Visuals]
This matters because:
- There is no context switching between languages
- Learning is smoother and more focused
- Ruby becomes a bridge between hardware and expression
Ruby on a Microcontroller (PicoRuby)
Here is a simplified example from the control layer, written in PicoRuby , that reads a sensor, smooths noise, and sends data only when it changes meaningfully:
pot = ADC.new(26)
uart = UART.new(unit: :RP2040_UART0)
readings = []
loop do
readings << pot.read_raw
readings.shift if readings.size > 5
filtered = readings.sum / readings.size
if (filtered - @last_value.to_i).abs > 50
uart.write("P,#{filtered}\n")
@last_value = filtered
end
end
Even in an embedded context, this feels like ordinary Ruby: arrays, objects, readable logic.
That familiarity is key.
Visual Expression with Ruby (processing gem)
On the visual side, Ruby continues to shine. Using the processing gem, sensor values directly control visual parameters:
def setup
@uart = UART.open("/dev/ttyUSB0", 115200)
@size = 150
size(1000, 1000)
end
def draw
handle_input
circle(width / 2, height / 2, @size)
end
def handle_input
data = @uart.gets
return unless data
id, value = data.chomp.split(",")
if id == "P"
@size = map(value.to_i, 0, 4095, 10, 500)
end
end
The result: turn a physical knob, and the visual form changes instantly.
No reloads. No recompilation. No abstraction gap.
What the Exhibition Taught Us
The project was exhibited at a university graduation show, with visitors ranging from children to seniors. Several important observations emerged:
- People stayed longer when visuals were already moving
- Viewers were more curious about the mechanism than the code itself
- Physical interaction lowered the fear of “breaking something”
- Simple code with large visual impact encouraged exploration
Interestingly, the work functioned better as an experience than as a traditional teaching tool — leading to a redesign focused more explicitly on learning.
Beyond Hardware: Web and ruby.wasm
The talk also explores extending Tangible Code beyond physical installations using ruby.wasm , allowing the same ideas to run in the browser.
While mouse input lacks physical feedback, touch screens (phones, tablets) open new possibilities:
- Direct manipulation
- No hardware setup
- Broader accessibility
This raises an open question — can touch interfaces replicate the “feel” of code?
Why This Matters
Tangible Code is not just an art project.
It offers:
- A new way to teach programming
- A method to reveal cause and effect in code
- A path to make abstract systems intuitive
- A reminder that code is not only logic — it is experience
As Koshiba concludes:
“This is one way to show code. How would you show it?”
References
- Presentation: Tangible Code: Rubyで「見て・触れて・変えてわかる」コードのしくみ Miyuki Koshiba
- Conference: RubyWorld Conference 2025
- Author: Miyuki Koshiba (SmartBank, Inc.)




Top comments (0)