00:00:08.160
Okay, thank you all. I want to tell you a story. This is a story about a plucky young developer excited about his first project.
00:00:15.599
He's skipping through the fields, and it was lovely. There were lots of squirrels around, and they were merry. Anything was possible, limited only by his own imagination.
00:00:28.880
So he set to work producing mountains of code, having so much fun cranking it out. It was awesome, and then, hang on, what the hell? It's not supposed to happen. Uh, no, myth error? Huh, okay, let’s fix that.
00:00:42.600
He was skipping, and the squirrels were merry. The project launched, and everyone thought it was pretty good. He went on to more projects, more code, and traveled the world, working on bigger things and with bigger teams.
00:01:05.000
Then, crap, that should be okay. What's wrong there? Sorry—ah, yeah, double equals. It's embarrassing; two minutes of my life I'm never getting back.
00:01:18.960
Before long, he was in charge of his own projects with his own team. Things were getting more interesting, with lots of data and lots of code, providing many chances to do wonderful things.
00:01:32.200
With the help of his new and amazing colleagues, they got it done. But then it happened again. Okay, what the hell? I already fixed this. I don’t know what's going on. No myth error? Huh, concurrency? Race conditions? It’s like a one in a million chance that’ll ever happen again.
00:01:43.119
I’ll just keep running it. Code runs like a billion times a day, but it won’t happen again. So, things are getting tougher for our plucky young developer. He’s not so young and experienced anymore and has started to believe himself a little bit invincible.
00:02:04.320
Now, he has been around the block a few times and figured out what’s going on, but the enormity of the task is starting to sink in. The enormity of the tasks in programming gets worse.
00:02:22.879
Don’t do this with ActiveModel or ActiveRecord; do it differently—it’s better. The hours got longer, the demands got higher, and he was juggling multiple clients and projects, all while keeping an eye on the team.
00:02:41.879
He was reviewing code and still needed to be hands-on because of the dreaded lurking fear of becoming post-technical. He learned not to drop tables on students, but small things began to cause anxiety.
00:02:54.560
He wasted ten years of his life due to time zone issues. Things got much harder and took longer, leading to anxiety about small things. Bugs that once seemed trivial were now hard to resolve.
00:03:20.920
The 80-hour weeks soon became the norm, and the code didn’t come out any faster. Anxiety worsened until it wasn't just a feeling anymore; it became this constant background hum.
00:03:33.599
Progress got slow. The young developer got older, more cynical, and felt pretty burnt out. Over time, he experienced constant anxiety and panic attacks, making that the new normal.
00:03:53.439
It took months to recover, taking it slow to feel somewhat human again. Lots of talking helped, but the anxiety was still there. It sneaks in everywhere.
00:04:08.200
If this sounds familiar, there are some things you can do about it. First, Google it. You’ll find a lot of resources. Seriously, check the first page about anxiety—it’s good information.
00:04:25.600
Stuff like Beyond Blue and the behavioral health initiatives mentioned before, they sound awesome. If you don’t think you need help, you probably do. Talk to someone, especially a GP; they’re really good.
00:04:45.400
Exercise, meditate, see friends and family—just take care of yourself. Anyway, moving on, this is kind of how new developers see the world.
00:05:00.240
It’s like a green, awesome, infinite field of possibilities, kind of like the Windows XP desktop wallpaper. It’s unlimited—you can do anything as soon as you figure out this coding thing.
00:05:24.560
But it can be dangerous as hell, and new developers don’t even know it. This is how experienced developers see the world: as a hostile war zone.
00:05:43.680
There are all kinds of dangers lurking around—landmines, barbed wire, machine guns—and you build up scar tissue from painful mistakes.
00:06:02.080
You learn to be careful through lots of experience, often becoming a little paranoid. Both of these worlds are hard to work in, and neither is very productive.
00:06:13.720
What we really want to get to is something more like a working farm field. It’s not a dreamscape of youthful boundless fun. You’re not going to be skipping around merrily, but it’s not a nightmare battlefield either.
00:06:30.199
You don’t have to worry about landmines; it’s a productive, real place. The difference between those two worlds is fear.
00:06:47.760
Let’s go back a few hundred thousand years: you’re a prehistoric human walking past a watering hole and you see a lion hiding in the bushes.
00:07:06.480
All animals experience fear, and you get a rush of adrenaline. Your breathing and heart rate increase, and you get clarity and focus, enhancing your physical performance.
00:07:23.680
This response triggers your fight or flight reflex. It biases you towards action, which helps you survive.
00:07:31.400
But there’s another side to that. Since humans are cursed with higher-level thought, we walk past that watering hole and remember the lion we saw last week.
00:07:50.160
Our imagination kicks in: what if there’s a lion hiding there again? We anticipate the future, planning, but the fight or flight reflex is triggered again even with no lion there.
00:08:06.800
This instinct is sensible and good for survival, but it creates a horrible long-term feeling, especially with ongoing anxiety. It gives you a bias toward preventative behavior rather than action.
00:08:18.160
Now, in the modern world, if you've ever been in a production outage, that’s kind of what it’s like.
00:08:25.080
It’s a strong fear response, a sense of clarity, focus, and a bias towards action. Humans generally excel in that environment.
00:08:38.560
Five people who know what they’re doing in the room during a crisis can get things done quickly. But anxiety is also a very modern phenomenon.
00:08:54.799
The fight or flight reflex gets triggered, but there’s nothing to fight; there are just things that might go wrong, and the complexity of modern programming means there's a myriad of potential issues.
00:09:10.720
This can lead to analysis paralysis; humans are not well suited to this kind of functionality, and that’s where the problems begin.
00:09:25.760
What this really impacts is working memory, the space in cognition necessary to work on a task. The greater your working memory, the more complicated tasks you can manage.
00:09:41.720
You may have heard of the theory of seven plus or minus two: it suggests how many chunks of information you can hold in memory at once.
00:09:55.000
When you’re under stress, your working memory reduces, and chronic anxiety can lead to a longer-term decrease.
00:10:01.720
Thinking about all the danger zones in your code can have the same effect, crowding your working memory with concerns unrelated to the task at hand.
00:10:18.920
The core thing you’re trying to do gets crowded out by all these other distractions. The best way to optimize your working memory is to stop needing to put things in there.
00:10:29.960
Let’s go forward a few hundred thousand years to ancient Sumeria, what is now Iran and Iraq, about 6,000 years ago. Lions aren’t a threat to people anymore, but they keep eating our sheep.
00:10:46.000
So, we want to keep track of how many sheep we lose, and we use clay tokens for that. They understood this mechanical system; one token represented five sheep, another three, and we combined them.
00:10:56.400
It was a very mechanical process; you’d have these stones on the ground and you could mess it up—if a sheep walked through your stones, you’d lose track.
00:11:03.760
Recounting would mean putting them all back where they were, but it didn’t work very well. Moving forward a bit to ancient Babylonia, three and a half thousand years ago, written numbers were invented.
00:11:10.760
Arithmetic had been invented, which removed much of the physical work. This became an abstract and easier-to-reason-about system—immutable and stateless.
00:11:26.400
It was an expression of facts rather than physical tokens. You can repeat this work from an N state, going forward and expanding on it, and modern numbers in math are an extension of that system.
00:11:36.000
You might think of this: we have 27 sheep. If we lose 3, how many do we have left? We have 24. This is easy to reason about because it is completely immutable.
00:11:57.460
You can’t have a sheep walk through the count and accidentally change it; pure, stateless, repeatable calculations occur with no mechanical moving parts to mess things up.
00:12:08.160
That's not imperative programming and errors are straightforward to debug. Functional programming reduces anxiety by requiring less cognitive load. You might break things, but identifying where you messed up becomes easier.
00:12:27.280
Ruby does have some tools for functional programming, acting somewhat as a gateway to it. Ruby was my functional programming gateway drug when I learned it and Erlang around the same time.
00:12:41.200
Reading about functional transformations in Erlang while learning about map, inject, and other functional concepts in Ruby exposed me to these principles.
00:12:58.160
You need to take advantage of Ruby’s capabilities because there are useful bits within it. It won’t be pure functional programming as you may encounter in Haskell, for example.
00:13:06.720
You can try functional programming; it’s not complicated. It’s simply working with values—numbers, strings, objects, and data. Functions are things that take in arguments.
00:13:22.116
You have things that pass in arguments and do something with them, passing values out thereafter—easier to reason about, with fewer moving parts involved.
00:13:38.399
Pure functions are key: same inputs should always yield the same output. They do not exhibit non-deterministic behavior, which means functions won’t change external state during execution.
00:13:54.239
They don’t mutate their arguments; if you do that, we can’t be friends! Pure functions are great because they help reduce clutter in your working memory.
00:14:09.760
When I see a pure function, I focus on what's in front of me—local variables and passed arguments—local scope keeps everything cleaner.
00:14:27.599
One key part of this discussion is immutability—you don’t change objects after you create them. Instead, create a new object and copy the state over.
00:14:38.799
Using persistent data structures can help here, and we’ll talk more about that shortly. Here’s an example: we have a simple class keeping a flock of sheep.
00:14:55.640
We manage flock size and create a new instance of a flock whenever sheep are eaten, which allows us to track history and maintain state.
00:15:13.080
Algebric is a library that lets you create types in a weird but useful way in Ruby. The cool thing is that these don’t permit you to define methods on the types you create without expanding the module.
00:15:29.760
So, we created a flock class with an eat method that gives you a new flock with a different size but keeps the original unchanged.
00:15:45.040
Hamster is another great library for creating immutable collections. It lets you handle things like hashes, vectors, lists, and sets efficiently.
00:16:01.600
It allows you to create a new instance of a data structure while keeping a reference to the original. Immutable collections ensure that you don’t have to worry about things changing underneath you.
00:16:17.440
Honestly, there’s a lot of good stuff from libraries around immutability, as Tim mentioned earlier today. You don’t want your code changing variables or having another thread alter variables unexpectedly.
00:16:34.640
You can rely on the fact that your variable will never change, allowing for easier reasoning.
00:16:48.480
Statelessness is another critical concept. While immutability is cool, having statelessness helps a great deal when coding.
00:17:06.240
This is the big difference between traditional object-oriented Ruby and functional languages. It’s often about moving data rather than changing it.
00:17:21.120
A flock class where a sheep walks through and disturbs the flock size creates uncertainty, thus learning encapsulation helps with this.
00:17:38.360
Sometimes, you may not even need state at all; you can have a function that says: here's some input, we do a transformation, and here's a new value that comes out.
00:17:54.080
You can chain these functions together, avoiding the need for stored state.
00:18:07.760
If you think of a world with no variables—just functional expressions and transformations—everything becomes much easier to reason about.
00:18:20.600
If you remember one thing today, it's that you can achieve 90% of the benefits of functional programming by practicing pure functions, immutability, and statelessness.
00:18:37.440
Once you grasp these concepts, you’re already well on your way. There’s also cool stuff like monads, but they’re less critical than those basics.
00:18:51.480
If you are coding in Ruby, Enumerable is your best friend. The Array class inside Ruby is implemented in terms of Enumerable.
00:19:06.560
All you have to do is implement the each method, which yields from its internal data structure. To implement by hand is not practical; you would usually delegate to an array.
00:19:20.840
Using Enumerable grants you map and inject for free—vital tools for almost any transformation. These two functions are the bread and butter of functional programming.
00:19:37.040
Map is a higher-order function—one that takes in another function—and lets you create an immutable functional transformation.
00:19:56.200
Inject allows you to take a large data structure, like an array, and reduce it to a single value. For example, you take an array of numbers and use an accumulator to add them together.
00:20:14.640
Starting with zero, add one to it, and you get one. Add two to that, and you get three, then five, then ten. All of this is immutable and stateless, driven by pure functions.
00:20:33.040
When using each in functional contexts, you must remember that it operates mutably. Using each inherently requires changing state.
00:20:46.360
While performance in Ruby may not always shine, you can still benchmark to find if it meets your needs. Hamster is a great option to improve efficiency with functional elements.
00:21:05.040
Using imperative code is acceptable when necessary. Want to push something through a system? Choose the best approach.
00:21:21.600
When looking at functional data structures like algebraic types, I would love to delve deeper, but I can’t due to time constraints.
00:21:33.560
Monoids are an excellent concept for us to explore while understanding the functional programming paradigm.
00:21:45.760
A monoid's definition consists of a binary operator that combines two things, while possessing an identity that doesn’t alter the result.
00:22:07.560
It follows associative behaviors so if you add 1 plus 2 to equal 3, it works out the same as adding 3 to 1 plus 2. This feature makes it easy to apply across multi-threaded environments.
00:22:24.560
Monoids appear in various structures such as arrays and hashes. When merging, they perform the same way as integers by adding together.
00:22:37.600
Here’s a big flock example with a shepherd utilizing algebraic constructs. The flock size starts as an empty entity, building from there.
00:22:51.680
Why does this matter? When you add stuff together, it becomes immutable, pure, and stateless. This allows melding them together into something new.
00:23:05.960
Let's quickly construct an example of a shopping cart in this immutable way, one where customers can add items without altering previous data.
00:23:24.000
We manage a shopping cart, which records added items while avoiding mutations. If a user adds items while logged out, we need to merge both carts when they log back in.
00:23:38.160
Using monoids, we create an empty shopping cart instance to begin with. Each cart possesses a creation date, but you can take the minimum date offered when merging.
00:23:54.000
If there’s an action regarding a count, our empty instance values keep merging without losing original context—all managed functionally.
00:24:08.960
This approach circumvents extensive complex logic; we utilize pure functions to append any number of carts back together!
00:24:24.480
For integers, merging is intuitive. Don’t monkey patch to keep your code clean; it risks causing chaos across numerous implementations.
00:24:39.440
If you change data structures based on integer changes, change them around the right ways. Creating abstractions aids massively.
00:24:53.680
Let’s discuss how to combine dates based on specific business logic. When comparing creation dates, you may favor the earliest.
00:25:10.560
When combining these dates, ensure your logic is sound and effortless. Have a minimum threshold to gather all entries, merging flawlessly.
00:25:27.680
As users input items into their carts—signed in or not—we can sort items that flow with the actions without state loss.
00:25:44.480
Simple implementations yield efficient processes without deep convoluted logic. Achieving results seamlessly allows for easier functionality.
00:25:59.000
Thus, you can append each user's cart to a signed-in cart with minimal effort! It’s about the concept of isolation.
00:26:15.360
Finally, the goal is to find common isolated patterns and simplify your approach. You should strive for laws without any special edge cases.
00:26:30.080
For instance, as Isaac Newton illustrated the laws of motion that aptly summarize reality, you should identify and define simple, rational patterns in your programming.
00:26:46.080
Make use of the simplicity of thoughts guiding your logic. All of this combined can significantly reduce the anxiety pressure and cognitive misunderstandings.
00:27:00.360
During complexity, we acknowledge that variables and structures can cause congestion in your working memory. Let’s hope to define structures that guard against new layers of confusion.
00:27:16.080
Thank you for listening.
00:27:47.600
If you have questions for Julian, please utilize the event app to share your thoughts on his talk.
00:28:02.240
We’ve had some interesting existential exchanges on if a variable that never changes is still a variable. It’s probably more of a value.
00:28:10.160
Lots of comments have praised your talk, so that’s nice. If anyone has any questions, please go ahead!
00:28:25.480
You did a wonderful job, while I didn’t grasp everything. Feel free to ask about your production experience with Elixir and Go!
00:28:40.920
I honestly don’t have extensive Elixir production experience, even though I advocated for its use at Inato—that was quite the journey!
00:29:01.200
Despite leaving, they all transitioned to using it instead, which marked a pretty significant change!
00:29:16.640
For context, it’s worth noting Elixir is designed for reliability—like our old marketing spiel suggests—comparably low maintenance.
00:29:31.120
It’s well built to handle production loads with better performance than Ruby due to the Erlang VM.
00:29:40.720
Regarding your concern about naming when applying functions, things can get complex.
00:29:54.799
If you find yourself struggling with long variable names due to transformations, consider revisiting functional programming patterns that help keep names easy to operate.
00:30:09.760
Immutability stands out as a big part of functional programming. Treat your functions similarly to ensure presets stay intact.
00:30:25.720
The techniques I’ve discussed today stem from a development process focusing on desired end results. I urge you to challenge embedded mindsets.
00:30:39.960
The fundamental role of immutability results in clean attributes across functions. If you’re looking to apply these ideas directly, Elixir beckons!
00:30:51.240
It's extremely accessible if you are familiar with Ruby's syntax, while still offering a distinct programming approach.
00:31:05.480
Overall, we’ve covered significant ground today. Thank you so much for your engagement!