Press "Enter" to skip to content

Advanced Dependency Injection without classes – Fun Fun Function


good Monday morning today we’re going to

do a little continuation on last week’s

video which was about doing dependency

injection in JavaScript without using

classes

I am mpj and you are watching fun fun

[Music]

I am back at home and it feels so good

if if you’re wondering about my hair

the this is my stage hair from Nordic

jazz do you like it mm-hmm

which I have been hosting co-hosting

last week and it has been weird this

week because I’m recording this on

Sundays and it was amazing amazing

amazing but it was also probably one of

the hardest pieces of work I have ever

done

Jesus it was so intense some fans showed

up and gave me Serbian candy I I suppose

it’s not a good idea to eat stuff from

random people on the internet but it’s

free package so I think it’s fine if I

die this will be proof it’s this is from

the manga thank you new manga I at least

I’m pretty sure it wasn’t a man John the

think was things were pretty hectic at

anyway last week we explored how to do

dependency injection without using

classes in JavaScript and today I would

like to continue exploring this but with

some more sophisticated examples and

also discuss a little bit about

architecture here is the example that

was in the beginning of last week’s

video I just to very quickly remind you

this was a class user manager it takes a

database connection we inject that here

in the constructor and then the there’s

a create user method which uses this

connection to access the table users and

insert and you use it with some

properties that I made up and then it

returns the user ID exactly what this

code does is not important the important

part is that it’s dependent on this

database connection line we want to

inject that so that we have control over

our dependencies and we can test them

and then we refactor this code too

instead of using a class using a set of

nested functions and we okay so this

does exactly the same thing by having

this creating this factory function

which creates the make use of function

and uses a closure to pass the passer

connection dependency instead of using a

instead of using class properties so

that is what we did but what I would

like to discuss today is if I ask

control-z back to our original example

there what if we had more than one

method here let’s say we just invent one

the lead user and we call it needs an ID

there and let’s just make up some

implementation all right so now the

situation has changed a little bit

because we now have these both these

methods are now making use of this

dependency so we are sharing the

injector dependency between these two

these two class these two methods and

this represents what we are going to

explore today this sharing of

dependencies between between functions

I’m going to show you how to do this

without using without using classes but

I’m also going to discuss a little bit

of about why you wouldn’t want to do do

this kind of sharing what are the

caveats with it we’re like when should

you do it and when shouldn’t you Oh

increase the font so it’s a little bit

all right let’s go back to the fun

shanell example here bloop bloop well

this is the same one as before

and let’s add a the delete user

equivalents delete user and it was a

connection and a name and it was

something like this oh it was an ID

right something like that this exact

exact implementation it’s not at all

important what we are concerned with is

this relationship here okay so let’s

think about how we use these things this

is the example from the last episode

this is the file that we were just

editing and we are pulling in make

create user because that already existed

there now let’s also troll in make

delete user that we had and then we will

use make delete user to create the

actual make delete function launched

sorry delete user make use connection

all right so what we see here is a

little bit of duplication that will

disturb your eye a little because as

programmers we are trained to look at to

click look for duplication and and

remove it

I often talk about how you should be

very careful about removing duplication

you should absolutely do it but you

should do it defensively and wait for a

lot of duplication to our eyes before

removing it because otherwise you will

probably miss identify the actual

pattern and you will generalize

incorrectly we will be talking about

this during the course of this video and

in many examples but for now let’s

imagine that we actually want to remove

this duplication let’s not

that we have some more examples of this

let’s say that perhaps we had hmm I’d

say that we had make up date you sir and

perhaps make ban you sir as well so now

we are starting to see some some

duplication here we are going to be

removing this but first I would like to

draw your attention to the fact like

this dependency is very easy to see now

like it’s very clear how the

dependencies flow and they act at the

moment there’s some duplication sure but

it’s still very easy to see and reason

about it’s very simple but let’s play

around a little bit with some higher

order functions if your are higher order

functions it’s a bit fussy concept to

you I have a video on that there that

BAM so this is the exactly the same so

you see here that this thing here we

have replaced that with by using a map

here so basically we have taken all of

these here put them in this array which

is called factories and then we map what

map over the factories here and for

every factory we call that factory where

the connection object and that will give

us an array and then we use

destructuring here to extract that into

variables so now we can just call like

create user and Joe Smith here or delete

user one two three if this syntax here

is new to you this is called

destructuring it’s a new feature in

JavaScript you can check out my video on

destructuring here this is pretty cool

but we are doing way too much prediction

of the future here we are assuming that

all all functions will have the same the

same set of dependencies which is not

true let’s say that ban user also

required an email service so yeah we

could inject all of the dependencies

into all of the all of the functions

this becomes a little bit weird it’s not

completely unreasonable oh I guess that

we could just inject all dependencies as

as an object into all like inject all

all dependencies into all factories but

seems to me that we kind of want an

a little bit more control this seems

let’s try another way okay so we know

I’m not gonna write email service out

you can imagine that it’s just the same

thing as this connection but instead of

unicron DB vendor perhaps it’s some

email service vendor and we do some

instantiation here and then pass it in

to ban user M okay how do we proceed you

all right so instead of these imagine

that we had a make user utils function

and you called that make user utils you

know what I’m gonna comment this out to

leave it for comparison and we’re going

to pass in the dependencies connection

in mail service and that is going to

give us an an object that we will be

let’s go back into use of utils and have

a look wow I see that I actually made a

mistake here a confusing mistake it

should be make delete user here because

this is a factory that creates the

delete user delete user is this function

here and this whole thing here that is

make delete user or this you can take

with us I think creating the liddie the

delete function use delete user function

anyway let’s refactor this a bit we are

instead we want to export the salt and I

colonists I want to make user you chills

oh we can’t export a constant we have to

do this first make use of you tools and

you see utils and that takes an object

with dependencies and those dependencies

are connection and mail service I think

it was called and that will just return

an object more there we go and these are

no longer our factories they are these

are the actual functions because they

all now have access to the connection

object here I’m gonna do the same thing

with delete user I don’t and colon

instead there delete that and export the

fault make user you just so exporting

that Oh indentation should be right so

now we are making this like instead of

having a factory oops

for every every function we now have

this sort of like

rapping factory for for all of them at

the same time so that they share the

scope the closure scope here so that

both these functions here have access to

the connection object so this way we can

also create the ban user function I

guess it takes an ID and then there’s a

connection dot table users let’s call it

update something hang on

and I bet that takes a delta so let’s

say that it’s I know MongoDB syntax here

something like bad true I don’t know I’m

making this up as I go and when the

update is done it should call the mail

service we don’t have the email yet here

that we would have to figure that out it

not that way that’s not really relevant

to the example let’s just say Joe yeah

come and I banned you dude busted

operator from hell

alright so you see here now that this

has access to mail service this has

access to these have access to the

connection and if we go back remember

how it was used we just pass in the

dependencies here as as an object

literal and it can access them and then

it creates all of these in one fell

swoop for us

notice that this pattern is very similar

to a class where with some constructors

let me let me just drop up the class

sorta so here we would just have let’s

say

you source our mail service now we would

go this dot mail author mail service

course mail service something like that

and then we would do the same

implementation here and but instead of

using the the closure of the function

like it did here it would you see these

properties on the on the instance

instead but essentially the two patterns

are very similar it’s just that this

uses just functions and closures instead

of the class construct a problem with

this pattern is that we are over sharing

so mail service the it’s very nice in

this case when connection is used by all

user utils here but mail service is only

used by a few so that means that this

mail service here is being exposed to

and passed into all of all of to both

create user and delete user even though

they have no business knowing about that

this is not exactly a cardinal sin but

it can be problematic partially because

the dependencies are now less less

obvious for example before we could look

at in this case here if we go back to

the app here we can see exactly what

dependencies each thing has but here

this has now become slightly more

obscured from us dependencies are

starting to become this this blob of

things also even if you look in the

class the whole dependencies chain is a

bit when when you see something like

this with a group here it kind of makes

a person that that starts working in

this this class or this whatever we call

it module

it makes them think it’s okay to use the

mail service which it might really not

be make like this is this is just its

own thing here like just because

something is in this utils file doesn’t

make mean that it’s sensible to start

accessing accessing the mail service so

this this grouping here is starting to

become a little bit problematic speaking

of the grouping becoming a programmatic

it also becomes problematic in another

way it’s that user utils like it was

just something that we started doing

because when we had a create user we put

that in some file or some class and we

just figured that that file or that

classic needed a name and then it became

use of utils and it felt like okay this

is the place where we put crud

operations for for users but once we

start actually doing things we realize

that hey we actually need functions that

do quite a bit of things so such as

mailing mailing users or perhaps if we

are deleting users perhaps then we need

to do something with payment information

or billing information or whatever we’re

not quite sure what this what what this

this group of things is because we have

created the group prematurely before we

we actually know where we were going

it would have been better to just have

kept all of these these functions like

isolated and let them live their own

lives and let a pattern emerge before

starting to group them because when you

start grouping things it becomes harder

to an unentangled them and it also makes

communicate something to other

programmers that oh this is a creative

group but it’s really not we have just

it’s just starting to get group by what

dependencies they have which is not

really a good and sensible way of

grouping thing

to be honest like you want to group

things in are like there are many other

much better ways cohesive ways to group

things then what dependent what they

depend on but it becomes the consequence

if this is this is what we do breaking

things into modules based on based on

their dependency set I want to really

drive this home like it when I let’s go

back to the class example here when when

we started created to create user here

and we had to create a a class let’s

imagine that we were in a language like

Java where everything is required to be

a class then to whenever you create a

function you also need to create a

wrapping class and this creates an

interesting problem because we know what

we want to do we know that we want to

insert a user into the database and we

five-five find the side that create user

is a sensible name to do that however

java would also force us to name this

thing

this class is group this group of one

and there’s a subtle sinister thing

about that and it’s that portal it’s

distracting because we have to name one

other thing and naming is hard and

time-consuming

there’s a there’s an old joke in

computer programming saying that was it

now there are only two hard problems in

computer science concurrency and naming

things like many things hard takes time

and here you are forced to do that even

though it’s not really required we just

wanted to create a function and also

we’re the naming the reason why naming

is is so hard is that it requires you to

predict the future it requires you to

think about what will come next here and

because you really have no information

you have just one piece of data or just

perhaps a few it’s just too

for you to make that decision this is

not it’s not sensible to do that this

early you should wait for more

duplication and instances of something

to arise before generalizing or starting

grouping and organizing in order to

group and generalize or whatever you

need to see a pattern you need to know

what the general pattern is and if you

if you don’t let duplication rise first

you are going to invent too much of the

pattern in your head and you are going

to predict the future incorrectly or not

going to but in probably you’re going to

be wrong and since this is something

that we do a lot we should we should

rely on probability this is actually a

great example of one of the main reasons

why I dislike object-oriented

programming I feel that it incentivizes

you to predict the future at an earlier

point than you are able to do it well

this what we do here like making this

use you tools in a real lab this is not

what I would do at the moment when I’m

programming I guess the the reason why

we ended up with you three tails was

that I wanted to create something that

had a good one to one mapping with the

initial class example in in a real app I

something I I don’t know other services

or something and then I would like just

do something like this and then I would

import them from there oh no sorry like

it would be make create user and make

delete user and make update user and

make van user and then I would just have

this sorry this huge file let me go back

here to where we were before

LLL learn like this and the file would

look like this and I would just dump

into this other category until I

started figuring out very clear patterns

on an organization and then and only

then I would start creating something

like would be like oh I don’t know

account services or something where I

start putting things like the user flow

things I don’t know like that’s a point

I don’t know I do you don’t know how an

application will be structured or what

sense

what structure makes sense for an

application until you are quite a bit of

time into it so I’m a big fan of have

programming your architecture

defensively so that you can let

structure emerge as the patterns emerge

and become clear to you I have tried so

many times to do upfront architecture in

an application and it has literally

never worked it never works because

humans are not particularly good at

predicting the future our brains are

wired to like they are designed to plan

movements like you we are designed to

like okay if I walk behind that rock

then perhaps there’s a lion I need to

watch before the line our brains are

basically for planning movements and

predicting the architecture of a

software software application that is

that is way too complicated for our

brains so let duplication arise in in in

high quantity if possible instead of

trying to predict what that pattern will

be and that is what I want to talk about

today I wanted to show you how you can

share dependency

between functions when you are doing

dependency injection without without

classes but I also wanted to talk about

the problem with sharing dependencies in

general and how you should try to wait

for patterns to emerge and be clear

instead of trying to predict the future

upfront you have just watched an episode

of fun fun function I release these

every Monday morning Oh 800 GMT you can

check out another episode here if you

have questions thoughts around this

episode you can check out this topic on

the Fun Fun forum that is dedicated to

this episode I am mpj until next Monday morning say curious

Please follow and like us: