Subtitles section Play video
Hello.
This is my first time doing a full-scale presentation so I'm really nervous.
As you can see, in this session,
I'm going to make a presentation about functional JavaScript.
It's not that I know functional Javascript that well
that I'm making a presentation.
Some of the traits of functional programming
that I've applied on real projects
and my experience of grasping it little by little, is what I want to share.
And that's why I'm here.
I'm a developer in a company called Lunit
that analyses medical images.
It's been 3 years since I started being a developer.
Before this, I worked in design.
It was 2016 when I just started learning how to program, three years ago.
There was a keyword that was very popular at the time.
That is 'React'.
React is a library that helps to make interfaces.
There would be some of you who haven't used it
but I'm sure everyone has heard of it before.
It's a library that people have been constantly giving love to.
And three years ago,
along with 'React', there was another keyword that arose.
That is 'Redux'
MobX is used a lot recently too,
and it's compared with React Hooks a lot too.
At the time Redux was thought to be very innovative.
So it was in the center of the stage.
Redux is used with the library that makes UI
and it's a tool that maintains state in Javascript.
As you can see on the right,
it separates the state and the UI interface on the bottom
and makes the state into action. That is the basic structure of Redux.
With Redux,
it is not as fast but
there's a keyword that slowly appeared.
That is 'functional programming'.
Dan Abramov, who made Redux,
got the idea from Elm, a functional language,
and made it. So with Redux,
the keyword 'functional' was gradually mentioned.
At the time, I was a beginner in development.
So it was too hard for me to get the grasp of what it meant.
Although I didn't understand all the basic concepts of Redux,
using Redux by itself
was very interesting and fun.
When you make apps following the structure of Redux,
eventually, the interests were all separated
and the codes, including the components, became very neat.
That's why I liked Redux very much.
Because of my interest for Redux,
in the case of functional programming,
I looked at it with vague curiosity and admiration.
As time passed and I got used to the job,
my curiosity for functional programming was revived
and I started to study with my co-workers.
In this study,
the basic concepts of functions, to use a pure function,
to prevent additional effects,
to use preface grammars,
I was able to understand these basic concepts.
I also got to know about Monad and Reactive Programming.
The most memorable thing that I remember from this study
was actually the advantages of using functional programming.
Since it connects simple pure functions,
it's less likely to have errors in a function, so it's more stable.
And it's more likely to be reused since it connects small functions.
And it's easy to understand higher logic. These three were the advantages.
It was very appealing at the time
but after studying,
other co-workers and I
still didn't catch the grasp on
what exactly the functionals were.
I think this was because when we wrote for a real project,
this was the limitation of what we could apply
from what we've learned while studying.
Well, we could do more
but when we copied,
there was feedback that it didn't seem like functional programming.
So this was mostly what we wrote.
So we... studied functional programming but it was still vague.
Just understanding the concepts, a year passed.
I went to a new company
and started a new project.
To show you simply, this is the app.
One moment.
Add a grid like this,
and from that cell slide,
which is the cancer cell
or the fat cell, is all marked.
It's the tool that helps process data.
Refactoring
this tool was the task given to me.
Because, before, only React and Canvas were applied
and it wasn't organized.
Using Redux,
I was given the task to refactor it.
Like I wrote originally,
I naturally used combineReducers
and wrote the code.
When using the combine reducer,
it takes the state of the reducer
and see it as each domain like DB
and it separates the reducer completely.
The connection between reducers can be made actions.
So let's say we are adding
a label to a display like this
I put together the key points here.
When you write a reducer to add a label like that
you need to use label type
and other information from grid reducer.
As the app gets more complex,
more information is going to be added.
When using combine reducer like this
in order to process this
you need to take information in the other reducer
and pass it onto the factors and parameters.
With more actions like these,
there is going to be more cases of having to pass onto the parameters.
Also, there was one other thing I was not happy with.
You can use a middleware when using redux,
and this middleware, takes care of ajax
or processes events that cause additional effects,
and loads other action
or processes loading other actions right away.
Let's say we are writing reducer that exits
the selected grid here,
after writing the reducer exiting the grid
it needs to be processed along with the other reducer
although there is no api call
in order to simply load other action
the code for middleware must be written.
And of course with more processes like these
unnecessary middleware code is going to increase.
So it's going to look like this.
So then we wondered
if there is another way to write it.
So we looked into redux documents
and there was a post called Beyond combineReducers.
It has been updated so it looks different from when I first saw it
but the basic information is the same.
Here, it talks about combine reducers, that
it can only cover simple cases.
And that there needs to be some kind of a customization?
or reducer logic is needed.
So I wanted to minimize having to pass factors into function
and write each reducer code separately
then in the redux middleware,
I wanted to write the reducer and customize it
so that it will only deal with additional effects.
These are the purposes I started the works with.
There was something else that helped with that
If you scroll down to the previous document
it introduces a library called reduce-reducers
as another method.
As you can see in the code here
it is a reducer function composition library
where you can execute different reducers
in order and finally make it into
one type of state.
This is the official document on reduce-reducers
I saw this format, and if I were to follow it exactly I would need to add a state
so I wanted to make it into a format I liked
by composing reducer like this
and tried writing it.
Actually I did not look into libraries composing reducers
closely at the time.
When you go through the documents in redux
there are so many libraries.
This is only part of the page
and there is a library called reducer ramda.
There are so many reducer composing libraries
and I wanted to just simply start with something I knew about so I chose ramda.
Ramda.js focuses on currying and composition and it is a functional library
as I remembered from studying before,
so I wanted to give it a try.
Also, among these I used pipe which composes each function in order
as the main method.
Composing the functions is the main work but
I didn't use compose because
compose basically does its work
backwards,
so I did not think it would be natural to read them.
So I used pipe instead
so using this composition
I wrote the reducer exiting the grid earlier
Here, select label and select type
and select grid are separated like this. And there is reducer for each as well.
This reducer
combining and finally made a reducer called
exitGrid. And each of the reducers
could be mapped in the action.
Seeing each reducer like this individually
as a separate function and writing them like this.
eventually rather than a switch
a reducer used to map formation
seemed to be better for writing. So that's why I wrote it like this.
The mapping formation actually
is used more often these days.
To show you more of
how it's processed in the store
the reducer map called switch reducer
makes a function that selects
a reducer map for the action type. By using that, we
finally make a root reducer.
The code was simply written in that formation.
However, when you look here,
it's going the same from root reducer to state action.
According to the action type,
the selected reducer does not need the action type's information.
So we additionally made a change to pass the payload.
So according to this here,
by not receiving the action but receiving the payload only,
the code became more simple.
The method I used in this process
is to combine all the states in one
and writing each of the many reducers.
Then I thought of a chapter I saw while studying
That is, 'Few data structures, many operations'.
That's how it was translated in Korean.
It was that quote.
Thinking, 'Would this be what that means?',
I got the grasp of it as I wrote the code.
When you see the writing of the reducer exiting this grid,
The exitGrid on the very bottom,
you have to use it by putting only one factor of each function,
so the select label
the select labels or
select label type, select grid, each reducer is all curried.
Curry, as you see in the example code,
if you surround a function with a curry,
you can practice the factor to the function in order
and you can apply it all at once.
As you see here,
As you see here,
in the first item, the count and the list are in order.
If you change that,
the same code
as you can see on the bottom,
now needs a placeholder.
When you use a function called curry,
the first 10
when you select the first 10 items,
if you receive the count first and get the list later,
it's natural to add in the factor 10 first.
However, when the order is reversed,
as to set it up first,
you add in the placeholder.
From this function composition
I found out that the order of the factors matter.
So here, functional programming
connects the various functions
and it's written to pass down the data there.
When you see the one I wrote, I made the state as one
and by chaining the various reducers,
I made it pass down like that.
But,
when you make this, the root reducer,
since the original order of passed state and payload,
That is why this code came out.
In the exit grid on the bottom
as I showed you earlier,
you have to use the placeholder.
So you reverse the places of state and payload like this
and rewrite the reducer.
And you can get a function with no placeholder.
It's more neat.
By writing the code,
I knew the reason that Ramda.js's skills are currying and composing
in detail.
When you see the code I showed you earlier through explaining Ramda's pipe,
it filters the wrong factors,
organizes it in order,
cuts the first 10,
adds each of them and divide it by 10 again.
It connects all these functions
and passes on the list.
When we write the same one with the most famous library, lodash,
When wrote with basic lodash, it becomes like this.
You have to curry each of the functions individually.
And the order is all different
so you have to put in the placeholders in all of them.
In lodash, the basic lists or
or the main data is on the front.
About this,
the reason Ramda appears so clean is because
the utils in Ramda are
all automatically curried.
And as I showed you earlier,
The parameter's order is best set to currying and composing.
lodash too, considers this need
considers this need and
exclusively provides a library called lodash/fp. There,
it passes the other factor first, almost like Ramda
and passes the data later at the end.
So if you look at the rewritten code that exits the grid,
this is the original code
and this is the rewritten code that we made using composition.
If you look at it, the code is reduced by 3/4.
And it works to fulfill one purpose.
And the simple functions needed for exitGrid are
separated into middleware and reducer
and it is written so it comprehends the logic right away, without being stored.
When you write a lot of code reducers like this,
the code shrinks and I think it look more organized.
So, after writing all the Redux parts,
I am reminded of the quote, 'Few data structures, many operations.'
These functions seem to carry that meaning
and I started to like currying and composition
to the point I adore them.
I am very satisfied with their results
So at the time, I had a part to refactor
in the unorganized canvas, on the app I showed you earlier. It was an app
that draws records.
With this, thought(?),
with this attitude, I kept
on writing.
And as a result,
this ended up being the most exported upper function.
It was written like this.
As you can see, I got the Canvas context
and passed it down like this.
I wasn't really satisfied with it.
Because I had to bind the contexts by currying.
If we look at another minor part here,
when we see the part of adding new guides to the grid,
we can see how it was written.
Like I did previously, I did binding to the context.
Then I took it to a lower level and
in a more basic context,
when you see the functions doing its job,
I've bounded all the contexts here too.
And to write a higher order function into a pipe.
I got obsessed with it
The information passed on to context
got all mixed up and became a giant lump.
It was okay when it was a state.
All the irrelevant context process functions
were using the same data, so
it became a ridiculous data structure.
So when I looked at the codes in detail,
It was hard to figure out the logic, compared to other upper functions.
At this time, someone who told me a lot of things about functional programming,
the leader of the company I worked in before,
told me to research about polymorphism.
He also told me to work on how to practice polymorphism in functional programming
So I started researching.
Polymorphism is an idea more familiar as a class or in OOP,
When there's a class called drawing, the method
is extended elsewhere
and polymorphism is the ability to use the same method in a different use.
I looked up how to practice this on functional programming
and this idea came out.
It's called. 'Discriminated Union'. I searched again and
there was a typescript document.
When you look at this typescript document,
it separates the kinds and adds the res of the information needed.
And when you scroll down, there's this code.
Through a switch, according to the kind of the information,
different functions are practiced.
This is a code that would be familiar to you all.
This is the action type and structure of reducer
that is used in Redux.
Through this research, in the process of learning,
I previously thought that Redux's functional programming
was constructed ambiguously.
But I began to learn about how the ideas
that it was borrowed from.
I thought I should write the canvas this way
And wrote it.
But as I wrote it, I realised I made
another misunderstanding.
In this whole grid logic,
If you look at the part where it draws only the new grid guide
the function that makes the data
and the function that operates the logic are stuck together.
I saw this and thought it was strange.
Because in functional programming, basically, data and
functions are very loosely connected.
As you can see, in object-oriented programming, Class firmly connects
data and function.
In functional programming, through chaining or pipe,
the basic thought is that data and function are loosely connected.
But for this upper logic, I saw something like this.
When I first wrote it, it passed the drawing state data
Then I thought of connecting the necessary
canvas contexts to
map out the actual operation
But, looking at the detailed function and the lower function,
the data and operation are stuck together. So,
when I restructured it,
it came out like this.
I dropped the drawing state and the canvas context to the function.
Here, to each sub function
drawing state and canvas context, so the data and the method are stuck together
and passed. That's the structure I constructed.
As you can see, the state, data and the operation are together
and are wandering.
So I thought I should separate them.
I realized that I was coding
just by using pipe to fit to the class.
That came to my mind.
So now, I changed the structure like this.
I exclusively modified the data
and using that data, I made the effects that would be passed at the end.
Then, all of them together are applied
to canvas context, and changed the overall data flow.
That is what I've been working on.
When you see this, the data structure was like this,
each was separated by canvas effects like this.
It's almost like action, right? It's now separated.
And the basic drawing functions with too much curry
are now neatly organized.
What's added is this effector map, which is added like a reducer map.
Then, the grid guide
on the drawing part, has a function that makes data.
Then it receives the data that was made
and the function that is practiced is typed.
Here too, the function is changed into
the function that processes the data first.
The final function also has a bit of context bound.
The context and the data weren't so far apart
In the new function, I made a function that only handles the data
and finally applies it to the text.
And the code is changed like this.
I lifted the Redux and the Canvas part and distributed them.
Surprisingly, after distributing,
there were a lot of corrections to be made.
Excluding a few components, all of the codes were modified.
There were only three minor issues that occurred for three months.
One thing that we could observe here is that, when we first learned about functional programming,
one of the advantages was the reliability.
The stability was something that was experienced.
And after writing each function,
it was highly reused.
And by turning Redux into one state,
selectors could reuse them in Redux
so a lot of codes could be reduced.
There was an uncertainty about
whether it was easy to notice the final logic.
Because, as I mentioned earlier,
in the written codes, there is a function called converge
or juxt function which use codes that only involve methods
found in functional programming.
So, a lot of effort is needed for other people to understand more
and maintain it.
So in that aspect, I gave this a triangle rank.
To sum up, I explained a few data structures and many operations.
such as currying and composition, and discriminated union.
As I was familiarizing with these concepts,
I learned something more important that
as you can see when I wrote the wrong flow,
In my opinion,
the data flow of the whole structure
is essential in functional programming
This is the end of my presentation.
Thank you for listening.