Talks

The Functional Alternative

The Functional Alternative

by Ju Liu

In the presentation 'The Functional Alternative' by Ju Liu at the Helvetic Ruby 2023 event, the speaker guides the audience through a practical exercise to illustrate the principles of functional programming versus imperative programming using a simple Ruby Kata. The session begins with the generation of 100 random numbers, followed by a straightforward task of representing these numbers as hashes. Liu emphasizes the initial simplicity of the task but quickly escalates its complexity by introducing a new requirement: to group consecutive equal numbers, which proves to be a challenge.

Key points discussed during the video include:

- Imperative Programming: The speaker demonstrates how to write imperative code to generate and process the random numbers. Initially, the focus is on printing hashes based on these numbers.

- Introducing Complexity: The need to group consecutive equal numbers creates complications, necessitating the use of state management to keep track of previous values and their indices.

- Debugging Process: Liu openly acknowledges errors encountered during this process, highlighting the importance of debugging and proper testing.

- Refactoring to Functional Programming Techniques: After addressing the initial issues, Liu showcases the application of functional programming techniques, emphasizing the use of pure functions to eliminate side effects and enhance code clarity.

- Separation of Concerns: The presentation stresses redesigning the application to separate data manipulation from output representation, thereby reducing complexity and improving code maintainability.

- Enhancements through Ruby Features: Utilizing Ruby's slicing and pattern-matching capabilities helps make the codebase cleaner and more sophisticated.

In conclusion, Liu encourages developers to challenge themselves in recognizing complexities in their coding practices and advocate for functional programming methods as a means to improve efficiency, clarity, and collaboration in software development. By the end of the session, viewers are armed with concrete examples of the significance of functional programming, immutability, and how these concepts contribute to writing bug-free code. For further exploration, the complete code is made available via a scan-able QR code at the end of the talk.

00:00:04.799 Hello, my name is Ju. I work for Shopify. Today, we're going to do a small exercise together. I think this is going to be quite fun.
00:00:09.840 Originally, this talk was intended to be longer, so I had to cut some bits. I hope you'll forgive me for that.
00:00:16.480 We are going to start with a very simple exercise. To do this, I need to generate 100 random numbers. I've written a little bit of Ruby code to generate those random numbers. You don’t need to read the code; it’s just there to generate the random numbers.
00:00:30.039 If I run this Ruby script, it will generate a bunch of numbers and save them into a file because I want to keep looking at them a little bit. Let's check if it generated the 100 random numbers.
00:00:49.840 The first very easy exercise is just to generate a simple diagram. With these 100 numbers, I want to print as many hashes as the number indicates. For example, if at some point I have seven, three, or zero hashes, I want that to be visually represented.
00:01:06.000 To do this, I will iterate through the numbers and print the corresponding number of hashes for each. I can use the index of the number to create a pair and then multiply a hash symbol by that number. When I run the script now, voila! Thank you!
00:01:51.680 This is the easy part of the exercise. Now, I’m going to make it quite hard. The trick to make it harder is to add a new requirement: I want to group consecutive numbers with the same value. This makes it more complex.
00:02:39.720 For example, if we have a series of numbers, I want to group similar consecutive numbers together. It seems straightforward for professional software engineers, right?
00:03:02.560 This morning, while watching a talk, I was reminded of a conversation with my wife about software development. She asked when she would become proficient at it, and I had to admit that it was a tough question.
00:03:15.960 Understanding why this grouping is difficult, I realize that it is not enough to just iterate through the numbers. I need to maintain some state to remember the last number and track the beginnings of groups of consecutive equal numbers.
00:03:52.120 As I build out my solution, I start with previous number initialized to nil and iterate through the numbers. If the previous number is the same as the current one, I can continue without adding any new groups.
00:04:07.440 If they are not the same, I will create a new group. But wait, I realize I forgot to track the index where the previous group began. No problem, I can add that to my logic.
00:05:04.080 Once I have my groups, I can print them out. However, I realize I will also need to print the last group, since otherwise, it will not be represented in the output.
00:05:38.880 When I set the conditions to ensure I'm tracking my index properly, I think I have my solution. Let’s run the code and see the output!
00:06:21.920 It looks like my outputs are incorrect; some numbers aren’t displaying as I expect. I need to debug the code together with you.
00:07:07.480 I see that the issue is primarily due to my previous index and how I'm printing the results. I should have stored the last number dynamically and corrected the logic to reflect that.
00:07:59.960 Now, in terms of testing, it seems I also overlooked writing tests for this code. Nevertheless, I can see that my adjustments have generated some results. I should be checking if I need to make adjustments to the last group's output.
00:08:44.480 Let me make sure to adjust the logic for when there is only one index in the sequence. I’ll wrap my logic so it can handle this case properly.
00:09:22.440 It’s important to ensure that all potential outcomes are accounted for in the design of this code to prevent confusion and maintain readability.
00:10:00.480 As I look at the output again, while I may have resolved generating groups of equal numbers, I'm aware the code still lacks clarity. The refactoring stage is vital to make it readable and comprehensible to another developer in the future.
00:11:40.720 I want to use some functional programming techniques to clean up the logic in the code. The professional software engineering world is challenging, and developers often hold a lot of information in their heads at once.
00:12:38.960 We want to separate the concerns of data manipulation from the output portion of the code, emphasizing that errors can arise where there are side effects in the real world.
00:13:25.000 Now, I’m going to start by creating pure functions, transforming numbers into structured data without side effects initially. The aim is to clean the data formats and present them in a more accurate way.
00:14:05.920 Through this process, I will build groups while keeping track of only the previous number and managing the result as a state. This separates concerns, allowing me to manage changes more efficiently.
00:15:20.480 After creating the groups, I can then easily render the representation through print statements. For instances with only one element, I can unpack the group quickly; in larger groups, I will track the first and last elements.
00:16:40.480 Using Ruby's slicing and pattern matching techniques will help clarify the code even more and make it more sophisticated.
00:17:32.200 In this way, you can see that the complexity of previous index tracking has disappeared. The revised version demonstrates clear data processing, significantly improving readability.
00:18:17.520 As I look at final outputs, I feel confident that embracing methods like slice and pattern matching adheres to contemporary standards.
00:19:12.480 Tests should be done swiftly in isolation, focusing on the pure data manipulations. Executing any side effect-related functions in integration tests can help maintain efficiency and clarity.
00:20:40.640 As I conclude this session, remember that achieving clarity and reducing complexity in the code ultimately helps improve team efficiency and understanding.
00:21:47.400 I encourage everyone to challenge themselves in recognizing situations where complexity arises, enabling collaborative discussions about possible better abstractions.
00:24:23.040 If you want a copy of the code, you can scan the QR code available, which will lead to a gist of the complete code. This will give you a chance to see and experiment with it. Thank you!