>>HEVERY: Thank you for coming to another
Clean Code Talks. And we are going to–today talk about Global State and basically the
idea of Singletons which is a form of global states and in cancellation and how singletons
make your API really deceptive, and how this really makes the whole thing really difficult
from a testing point of view. So Global State. You know, I’d like to point out that somebody
once told me that this condition of insanity which is that you repeat the same thing and
you expect a different results. And singletons allow you to do this. Singletons allow you
to repeat the same thing and keep getting different results which will slowly drive
you insane. So let me point this out, suppose I have a class X and there’s a method that
does something and computes a value called int and I’m going to instantiate it twice,
and I’m going to call the method twice that way I’ll have the a and b value. Now here’s
the question, does a equal b or not necessarily? What do you guys think? So you don’t think
it has to? Okay. Let me ask you in slightly differently, which code would you rather be
in? In a code where the two are equal or in a code where the two are not equal? Where
they are equal. So you would much prefer to be in a code that’s where it is equal. And
so I’m going to agree with you. I think the same exact way that if you have a–if you
basically do the same operation twice, I very much would like to get the same exact results.
So, the thing is that the object state is transient and subject to cover–yes. Could
I trouble you to use the microphone because we’re recording this.
>>So, one thing is that the function must go do something. So do something doesn’t tell
you whether it’s only getting something or doing something and that it does something.
You can argue…>>It doesn’t add actually.
>>That this could be different.>>Okay. It–that actually doesn’t matter,
the fact is…>>That adds to–adds to like container. I’m
really sorry. So whatever, you know?>>Yes. It actually doesn’t matter. The key
over here is that there is no information flowing into the system, right? There is nothing
passing to the constructor, and there’s nothing passing to the methods. And therefore whatever
is being computed, and because this is a computer which is a final state machine, it better
produce the same exact results every single time I run this. And if it doesn’t produce
the same result every single time I run this that means there is some global stable. We’re
getting ahead of ourselves. So here’s the thing. Object state is transient and is subject
to garbage collection, right? Which means if you lose a reference, everything inside
of it goes away, and this is a good thing. Now, a class state is something very different.
The class state is persistent to the lifetime of the JVM, yes Isaac.
>>I just wanted to point out that of course, it doesn’t necessarily mean global state,
right? Because it could be something coming in from the outside world.
>>That’s a global state too, actually. We’ll get there in a second. My– you guys are today
very much ahead of me. All right. So class state, on the other hand, is persistent, right?
This is where you use the static key word and you basically are tying the value, not
to the instance, but basically to the whole JVM. So, let me point–look at this thing
a little further. If I do new X, I’m basically building some graph of objects, though the
X constructor can instantiate a whole bunch
of other object, and so on and so forth. And some graph objects gets built. So, if I do
new X again, I again am constructing some graph of objects, and it better be the same
object graph because I didn’t specify any other parameters, right? There’s no other
input coming from the outside. So now, if I do the two operations, I better get the
same value. If I don’t get the same value, that means that those two graphs are secretly
talking to each other. The fact that they’re talking to each other secretly is what the
problem is here. It’s not explicit, it’s hidden. And it creates all kinds of mishap in our
code base. And it’s what will drive you eventually insane and crazy because you will keep on
doing the same operation and different things will be happening. In other words, there is
something that’s getting into the system, something that’s being persistent in locations
that’s causing this. And I want to argue that this kind of way of coding actually makes
it a lot worse to understand the system, to understand how to debug it, to find bugs,
and so on and so forth. So, if you have Global State, you’re basically in a situation where
multiple executions can produce different results. And as a result of that, if you’re
running tests, your tests are flaky. You run a test once, it works. You run it again, it
fails. You run it again, it passes. And that kind of test is really hard to debug. And
then you of course, you have to ask yourself: A test is supposed to have a control over
all the parameters. If I run the test over and over and over again, it’s consistent,
right? Either the code works or it doesn’t. The fact that it’s flip-flopping back and
forth and it’s flaky really implies that somewhere, there’s global state, something that you don’t
fully control from the testing point of view. It also means that the order of the test matters.
So if I run the test in isolation, the test passes. If I run it as part of the test suite,
it no longer passes because one test sets some global state, another test expects the
global state to be in a certain state and it isn’t and all of a sudden your test are
starting to fail. And it also means that you cannot run the test in parallel. You know,
if you have a multithreaded CPU it would be great if you could run all the different test
on different threads, but because there’s global state, these test can talk to each
other in the back through some singletons, and as a result you can’t do that. Now there
is some–there is even a worse form out of this thing. And that is you have a test that
passes together, but if you have a test as part of a suite, and let’s say your suite
takes an hour to run and the last test in the suite fails and you try to debug it, and
you try to run it in isolation and it passes, right? Good luck debugging anything like that.
So from a testing point of view, global state is really a horrible problem for us. And we
try to avoid it as much as we can. Now, there is couple of hidden global state inside of
the JVM. Something that you might not think about, but there is system that occur in time.
There is some secret process going on in the background that secretly updates this global
variable called the current time and is being updated continuously. And this can cause flakiness
if you expect certain things to be returned from your current time. Same thing as new
date, right? New date internally calls a system that occur in time, and so the global state
now is inside of date as well. Another one is math random. There’s no such thing as random
in software, but there is pseudorandom sequences. And in order for the pseudorandom sequence
to happen, it has to be initialized by some kind of a seed. And so internally, the math
function keeps hold of the seed, and every time you call Math.random it uses the seed
to generate the next pseudorandom sequence, otherwise random will always return the same
value. So the seed itself is somewhere secretly global. And so I’m going to make an argument
that if you have code that uses any of these things, you will have hard time writing test
for these, a really hard time. Test will be flaky, you can’t run them in isolation, maybe
you can’t run them as part of the suite, the order of the test will matter, and so on and
so forth. How many of you guys have test suites that are flaky? Oh, come on? I can’t believe
nobody has them. All right, that’s better. And I’m going to argue that all of your flakiness
will come basically from some form of uncontrolled global state. So, let’s talk about singletons
for a second. So people say there is an object that I only need to have of single instance
of something inside of my JVM. Because typically, you have one application per JVM, and the
application only needs a single instance of an object. And so they say, “Okay, because
I only have one application per JVM, therefore I’m going to instantiate the object and put
a reference into the global space.” That’s what a singleton is, right? Singleton has
a dot get instance method that has instance field which is attached to global space which
is part of the class. Which means it’s no longer subject to garbage collection, and
so on and so forth. But here it is–here is the problem from a testing point of view.
In the test, each test basically wants to instantiate a small portion of your application.
It wants to apply some stimulus to it. It wants to assert something. And then it wants
to basically take whatever it had and throw it away. That’s what the garbage collector
is for, right? It just wants to be garbage collected. And then the next test runs. And
that test instantiates a small potion of your application, applies some stimulus, and throws
it away. And then the next test goes on, right? When you have a global state that’s part of
the JVM, unless you run every single test in separate JVM, which we don’t, for performance
reasons, it doesn’t really work, does it? So you really want to make sure that you don’t
have any singletons that are tied to JVM. And this is where the ambiguity kind of comes
into play. And I like to differentiate it as in singleton the capital S, and singleton
the lower case S. If it–we use capital letters for the names of some things. So if you have
the design pattern, singleton, then we are referring to the fact that the singleton has
a private constructor and it has a global instance variable, right? That’s what the
design pattern says it is. There’s also the idea of a lower case singleton with lower
case s, meaning that I only have a single instance of something but that instance does
not have a private constructor, and it’s not attached to the global main space. I only
have a single instance of it because I only called the new operator once. Those are two
kind of very distinct things. So, I like to differentiate them: Singleton with big S and
the singleton with the lower case s, or the good singleton versus the bad singleton. So,
let’s talk about the classical singleton with capital S, suppose you have a classical app
settings and most applications have something like this. They have that–the global field
called the instance which is declared with a key word static which is what makes it global
and it instantiates the class inline by calling the new operator on it directly, and then
we have a private constructor so that nobody else can make a copy of this. This is classical
singleton, right? You guys all agree, right? So let me ask a question now and that is,
how many global variables do you see on the screen? So you said three, you said? Or the
state one, two and three? Is that what you’re saying? Four. Correct. Yes, four because of
instance, yes. Actually, I’m going to go a step further. I’m going to say it’s in theory
infinite. Because the state one can have a point or to in object which internally can
have state, and that object can have a point to another object and that can have state,
and so on and so forth. And so, really it’s infinite number of different variables that
can possibly affect the execution of my code. So the problem with global state is that it’s
transitive, right? Once you cross a global variable which in this particular case is
the instance field by calling to get instance. Everything behind that, everything that’s
accessible from that global variable, is global as well. Now let me ask over here, how many
people think that global variable is a good idea? No one. How many people think singletons
are a good idea? People are raising their hands. Okay. So what gives? I just proved
to you that singletons make whole bunch of global variables and you’re telling me singletons
are a good thing, but you all agree that global variables are a bad thing. So, think about
it. Now here’s the next problem. Because the test doesn’t control the instantiation of
the object, we kind of covered this in previous talks, how it is important that the test can
instantiate a small portion of your application, apply some stimulus, and assert something,
right? The test need to be in control of the instantiation process. Here, the test are
not in control of instantiation process and therefore the test can never get a hold of
the state one, two and three. And because the test cannot get a hold of the state, there’s
no way to assert anything, there’s no way to reset anything and there’s no way to work
with this in any way. So what most people do is they’ll have custom methods that are
for test only. How many of you guys have done that? Good. So, in other words, we took a
singleton design pattern where we fought really hard to make sure that its singleton only
one instance is in there which means private constructor and global variable. And then
we secretly put in a whole bunch of backdoors so that we could replace it at run time for
testing purposes and modify it and get a hold of that, right? So, I mean, isn’t that kind
of weird? Like you want to make sure and then you don’t want to make sure. Like choose your
battle. Pick what you want and stick with it, right? And in this particular case, the
problem really is that from a testing point of view, you want to instantiate a whole bunch
of small, little, tiny substance of your application and do something with them. We kind of already
covered this, right? That the internal state of a singleton becomes globally accessible.
In other words you have a whole bunch of global variables as far as the code is concerned.
And we all know all the badness of global variables. So, let’s look at a code that uses
a singleton. Suppose you have some methods, some kind of class called app and there’s
a method on it, and the method calls Appsettings.getinstance.doX. How do I test this? Any thoughts out there?
How do I assert that doX actually gets called? You cannot. There’s no seed, right? In order
for us to assert something, we need to have seeds. And again we talked about this earlier,
that you need to be able to instantiate the class under test, and you need to have control
not just of the instantiation of the class under test, but you also have to have control
over the instantiation of the class under test dependency or its collaborators, right?
In this case the class app collaborates with app settings. But in order to get a hold of
the collaborator, it doesn’t ask for the collaborator through the constructor, instead it reaches
into a global variable, gets a hold of the collaborator and then collaborates with it,
and this makes testing essentially impossible. Now, usually, again, the way people solve
this is they’ll have a special for the test method which says Appsettings.setinstance,
and they undo their singletoness property that they fought so hard to introducing. So
let’s see what we can do. How about we make it so that it’s public Appsettings? So I understand
that within your application, you only need a single instance of Appsettings class. But
the requirement is the single application needs a single instance, the requirement is
not that a single JVM needs a single instance. Now it is true that in most cases you’re only
running a single app inside of your JVM, but it’s not true for test. Each test is a small
sub portion of your application being instantiated, and if that section of the application needs
to get a hold of the Appsettings, wants to control how it gets instantiated, it wants
to set things on it, and once it’s done setting things, it wants to be able to throw it away.
In other words the garbage collector should be able to get rid of it. So, what we’re changing
here is that class no longer enforces its own singletoness. And this is the key; this
is really where the problem is from singleton’s point of view. If classes enforce their own
singletoness, all kinds of hard things happen from a testing point of view. We have to basically
have some other way of making sure that our application only creates one instance of it
because the application really needs one instance. But it’s not because we enforce it through
a private and a global variable, instead we do so by simply making sure we only call the
constructor once. That’s a different topic. So now, in this case, we can inject the Appsettings
into the app class, and then we can call settings.doX. Now from a testing point of view, I know how
to test this because I can instantiate the app and I can instantiate the Appsettings,
maybe with the correct state or maybe I can instantiate a sub class of Appsettings which
will be my mock. Or maybe I can use easy mock or [INDISTINCT] to put Appsettings in its
place. The point is, from a testing point of view, I have a choice. I can do all these
different things then I can call the method under test then I can assert that right stuff
happened. So singletons are the one greatest evil that makes your code absolutely un-testable.
Now, but it gets worse. Have you ever seen APIs that lie about what they do? Let me show
you some pretty deceptive API. So once upon a time, I was on a project and I wrote this
particular test and it said “new credit card” and I had to pass in some numbers and I said
“credit card.charge $100”. And of course the credit card constructor insisted that the
credit card number be valid, so I had to–closest credit card number I could find was my own
wallet. And I ran this test, and wouldn’t you know it, at the end of the month I got
a bill and I was out of hundred dollars. This is what we call by “spooky action at a distance”.
Here’s the thing, how did the credit card know how to talk to the server? How did it
know where the server was? How did it know how to authenticate? How did it know who was
the person to be charged? How did it know what the account was? Like all these questions
are hidden, right? It just sort of happened and it worked. Now, actually, it’s more complicated
than that because the test never really passed in isolation. It only passed as part of a
suite. Whenever I’m out of a suite, I was out of hundred bucks. When I ran it in isolation,
I actually got some weird, more pointer exception. I didn’t know why I was getting all pointer
exceptions, so instead I went to talk to the wiser and older members of the team. And I
said, “I’m trying to do this, what’s going on? Can you help me out?” And they said, “Oh,
well, come on man? You should know this. You need to call creditcardprocessor.init.” Really?
How was I supposed to know this? The APIs didn’t tell me that I have to know this. It
just kind of “I had to do this.” Okay. So I wrote creditcard.init, I passed the whole
parameters to it, and I ran it and I got another exception. This time in a different location,
so I was making progress and I said, “Okay, now what do I do?” So again, I went to the
older and wiser and they said, “Oh yeah, the credit card processor actually needs to use
offline queue and so you better call offlinequeue.start.” Again, that wasn’t obvious to me. But how
was I supposed to know this? So I did that and I ran the test again and wouldn’t you
know it? I got another exception again. So again, I went to older and wiser and I said,
“What am I doing wrong here? I can’t figure this out.” And they said, “Well, come on man?
Offline queue needs a database.” Really? Like how was I supposed to know this? And so when
I passed in the database then the test ran and I was out of hundred bucks, again. So
the–now look at this thing a little further. The credit card is lying to us. It basically
says it pretends to not need the credit card processor, even though in reality it does,
right? The code didn’t work without the credit card processor, but the credit card didn’t
say it needed it. Nowhere in the constructor does it say “I need to get a hold of a credit
card processor.” Nowhere in the method calls is there a setter on a credit card processor,
there is no way for me to know that a credit card processor is needed. But it gets worse,
if I initialized creditcardprocessor, again, I have no way of knowing that the credit card
processor needs an offline queue. And it gets worse, if I initialized the offlinequeue,
there is no way for me to know that I need to get a hold of database. These things are
just are the way they are, and you don’t know. Now in real system, you don’t have three singletons,
or even four, or five, you have hundreds of them. And they all have to be initialized
in a correct order. Have you ever seen the main method of most of the applications where
all the singletons get initialized? It’s like black magic. Like nobody knows what’s going
on in there. Like in some bizarre order, they have to get initialized. And if you change
the order, nothing works. Are you guys agreeing with this or you’ve never seen an initialization
of a main method like that? Now here’s another problem. I write the code, I leave. Somebody
else comes after me and looks at this and says, looks at this red part and looks at
the green part and says, “I don’t think those two things are related in any particular way.
As matter of fact, I think I can rearrange them because I think it’s going to improve
the performance or something.” Or rather, “I have some reasons why I want to rearrange
the code and change the lines of code, and I think I’m allowed to do that because there
is no parameters getting passed in, no states getting passed in, I should be able to rearrange
this. Maybe I can change the order of things.” You think that’s going to work? It’s not,
right? So here’s the thing, here’s the assumption that I would like to make and that is, if
I have a code like this, or I simply instantiate a and b and I perform some operations on it,
I would significantly prefer to work on a project where I can freely rearrange the order
of things and I expect the order to still work. And the reason I’m allowed to rearrange
things is because the only dependency as far as I’m concerned, between a and b, is on the
method y, when it says, “In order to call method y you need to pass in method b.” So
clearly, I better be calling the method on b, right? But it doesn’t say that a has to
be instantiated before b, or vice versa. It also doesn’t force me to call a .X before
I call b.z, right? All of these things I should be independent about calling them in any order
I want. And the only way I can assert that is if there is no global state. In other words,
the only way two objects can talk to each other is if I have specifically allowed them
to talk to each other by passing a reference. If I pass a reference from a to b, then a
is allowed to talk to b, if I don’t pass a reference between this two objects, then they
are in two independent graphs. And that’s a good world to be in. It makes our cognitive
load a lot much better. Now, here comes dependency injection and it’s the thing that solves this
particular problem. What if, you know, we come back to our test again, you know we have
all this static initialization at the bottom and all this credit card thing on the bottom
of there, what if I–okay, so we kind of said we can’t change the order over here, right?
Because that’s not going to work. Let’s get back to this thing here. What if, instead
of new credit card, where inside of the credit card somewhere secretly I say “creditcardprocessor.getinstance”.
What if I simply said “I ask for the credit card processor in the constructor.”? See how
that it says so? New credit card, here’s the credit cad number; I’m asked for the credit
card processor in the constructor. When I did–if I would have done this, and some new
person comes unto project and he wants to instantiate a credit card, there is no black
magic going on. The credit card says, “I need a credit card processor.” It declares it explicitly.
There is no hidden secret communication channel between the credit card processor and credit
card, it’s explicit. It is clearly stated what it is. So, you go in and you say, “Hey,
credit card processor.” New credit card processor. And look what happens over there, the credit
card processor says, “But I need a queue.” Again, no secret channel of communication.
Explicit. It says, “This is what I need.” So I’m going to do new offline queue. And
that says, “But I need a data base.” So you say, “No problem. I’m going to instantiate
a database.” And you go on and on and on, until the whole thing is provided for you.
Now here is what happens over here. Notice I cannot rearrange the order of things anymore.
It’s very explicit in what I need to get my job done, and it also is not possible for
me to say, “New credit card processor before I call the new database.” It simply doesn’t
work, it won’t compile. So dependency injection is actually your friend when it comes to initialization.
And if you don’t have global state, and everybody asks for things explicitly in their constructors,
your main method becomes a lot clearer. You know who needs what in which order. Like all
the mystery disappears. As a matter of fact, if you try to initialize things in the wrong
order, it won’t even compile. You guys see how that kind of helps out? So the coolest
part of it is the dependency injection enforces the order of initialization of compile time,
and this is a big plus. This is really a big plus. It really helps when a new person comes
unto project and looks at the code and says, “I know in which order things have to be initialized
because I can’t do it the wrong way.” It also allows me to test things in isolation. For
example, if I wanted to write this and it says “I need a credit card processor in order
to get my work done.” I could’ve stopped over there and said, “Hmm, maybe instead of instantiating
the real credit card processor, I’m going to create a mock of a credit card and pass
you a mock.” And then I simply cut the whole dependency right there, and I’m going to test
now credit card in isolation. And now, by providing a mock, I can prevent my $100 disappearing
out of my wallet every time I run the test. But maybe I’m going to say to myself, “Nah,
maybe that’s not a good place to place a mock. Maybe I want to have a real good credit card
processor, a real offline queue but a fake data base.” Or vice versa, right? You have
a choice. The point is, that by doing explicit dependency injection, you have a choice where
you want and draw the line. And these choices is what makes the testing much easier. So,
I’m going to argue that global state is kind of the root of all your testing problems.
Not all of them, actually that’s kind of maybe a little too strong. But it’s good 90% percent
of them. The other one is structuring your code properly. But most of the times–most
of the times when we’re having a really hard time instantiating objects, et cetera, is
because there is some secret global state that allows us two objects to communicate
without actually knowing about each other. And the problem with global state is, well,
it cannot really be controlled from the test. And if you do want to control it, then we
have to put all kinds of setter methods and then we have to remember to clean up after
ourselves. And it’s also a problem because it’s very easy for people to add new global
state, you know? So maybe you wrote a test and you remember to set up your test correctly
and then clean up the global state after yourself. But then somebody else comes along and adds
a new global variable and it affects you in someway and you’re not sure–you don’t know
about it, and you don’t know which test you have to go and change to make it work again.
And so singletons is this common form of encapsulating global state. It’s this weirdness which allows
us all to basically say, “Yeah, global state sucks. But singletons, I love.” Like what
gives here? Like singletons are like the global state in sheep’s clothing. Like they pretend
to be all “Hey look, there’s only one static variable called the instance somewhere at
the root of the object tree.” But guess what? That static instance variable is transitive.
It makes everything else below global as well. And, you know, again, there is the difference
between singleton as in there’s only one instance of this class and the object, and singleton
which enforces its own singletoness through a private constructor and a global variable
instance method. There’s nothing wrong with having a single instance of something. They
only becomes a problem when it’s tied to global state. And we already talked about the fact
that global state is transitive. So, I want to open up the questions.
>>So, in one of my programs, there is…>>Can you speak up a little…
>>Yeah, sure. There’s a widget where it will show messages for various things that are
happening: Errors that have occurred, warnings, whatever. And at the moment it is stored as
a static global thing, and that way it’s accessible from anywhere. I can just, you know, show
a message. But if I don’t do that then, you know, I might be somewhere way down deep someplace
and I need to show a message. Now, in order to get at that thing, if I want to do it this
way, I have to go back to all of the dependencies and make that something that gets passed in
all the way up the chain, and that seems somehow excessive, is that bad?
>>HEVERY: Yes. It is bad. And this is a very common myth. So basically, the problem is
that you need a singleton like a database. Somewhere in the bottom of your application
because it’s the bottom layer that talks to the database or name your own singleton. And
then you have all these layers on top of it. And so, clearly you’re going to instantiate
and initialize the database somewhere inside of the main method, right? And our question
becomes “Don’t I have to pass the database through every single thing all the way to
the bottom?” And the answer is “No, you do not.” The reason for that is because you’re
mixing two things. I’m assuming that in your code you simply, when you need an object,
you simply instantiate it. Okay. When you instantiate an object inline, you’re mixing
the responsibility of construction with the responsibility of doing business logic. And
this is a problem on multiple levels. First of all, I can never mock out the object you
instantiated inline. It also means that your core graph and your object instantiation graph
are pretty much the same. So whoever you’re calling is you also whoever you’re instantiating
or vice versa. Whoever you’re instantiating; they’re also the very people you’re calling.
Now, if you separate them out and say, “I’m not in the business of instantiation, I’m
only in the business of getting a hold–I’m only in the business of doing the business
logic,” and you’re simply declare in your constructor “I need a database.” Then the
person above you, the layer above you, is not responsible for calling the new operator
on it which is, is not responsible for worrying about the database. So, the layer at the bottom
can say, “Hey, I need a database and its constructor.” The layer above doesn’t say, “I need a database
so that I can call a new operator on the layer below and pass in the database.” It says “I
need a layer below,” right? The layer above it has no clue about a database whatsoever.
Let me give you a different example. Suppose you have a house, and the house has a door,
and door, all of a sudden, door let’s say has a doorknob, okay? It’s not that the new
operator of the house calls the new operator of the door which calls the new operator on
the doorknob, and then the doorknob all of a sudden says “I need an attribute called
color.” And now we have a problem, right? Now we have to pass the color all the way
up. Instead, you have to structure the application differently. You have a house and the constructor
of the house says, “I need a door.” It doesn’t say “I’m going to call the new operator on
door.” It just says “I need a door.” The constructor of the door says “Well, I need a doorknob.”
And the constructor of the doorknob says “Well, I need a color.” And there’s a separate class
somewhere else called the factory that is not responsible for wiring all the pieces
together. So, the factory looks at the house and says “Let me instantiate the house. Let
me instantiate the door. Let me instantiate the doorknob.” And it passes all the references
around. And notice what happens, neither the house nor the door nor the door–neither the
house nor the door; know anything about how the doorknob got instantiated. Nor where its
dependencies come from, nor about the fact that there is such a thing as a color, right?
So you’ll have to have a simpler rule that is, you don’t mix object instantiation with
your application logic, and in your constructor you always ask for what you need. So our credit
card asked for the credit card processor. Our credit card processor asked for the offline
queue. And the offline queue asked for the database. The credit card didn’t know about
the data base, neither did the credit card processor or the offline–well, the offline
queue knew about the database, right? But only the layer that directly needs it, only
the object that directly needs it knows about the object that it wants. So this is a very
common myth by the way, that a lot of people, immediately when they look at dependency injection,
that’s exactly what they come up with. But all it means is that you did dependency injection
halfway through. You didn’t fully go all the way. Does that answer your question? All right.
Can you grab the microphone?>>From the house example. Isn’t it that kind
of inconvenient because house needs thousand of things and they are going to pass, create–going
to factory and pass them as a parameter for the constructor of the house?
>>Okay. So, if house needs a thousand things, then your house has a design problem which
is, it’s mixing concerns or too many responsibilities. You’re violating too many responsibilities.
Let me demonstrate. If I was to design a house, I would probably say something like “In the
construction of house, I need the living room, I need the kitchen and I need the bedroom.”
And that’s where I would leave it at that. I wouldn’t say, in the construction of the
house, “I need the wiring, I need the plumbing, I need the sink, I need,” so on and so forth,
right?” The constructor of the kitchen would say “I need the refrigerator and the sink
and the plumbing.”>>That’s true. What I mean is that, I have,
you know, dozen of members, right? Many variables, [INDISTINCT] not int. So, now I have to expose
them as a parameters through a constructor? All of them?
>>Well if you…>>[INDISTINCT] this a constructor with no
arguments, and there was constructor I want to fly, right?
>>Okay. Yeah. So how did the cons–how did the object get a hold of its collaborators?
>>You’re saying we have to create them outside and just pass the ownership to the object,
right?>>Okay. Is it…
>>Is that what you’re saying?>>Correct. But I’m trying to understand this.
So, if you have–okay, let me back up a second. There’s only two kinds of objects. And I’m
struggling with a good name for them. There are the objects that do work, like service
object. Like in this–in our case we had a credit card processor, offline, queue, the
database, right? These are your services. One way to look at them is, you would never
serialize them. Like if your applications saves it’s internal state, you never save
an internal state of an offline queue or a credit card processor, right? When you call–when
you instantiate the application, again, you make the new things. But you do save internal
state of a credit card. Now I call the credit cards, kind of like the value objects. Forgive
the name, I’m still struggling with that. And then there’s the service objects which
do work. Now, for a value objects, such as a credit card, it’s perfectly valid to have
a constructor that takes no arguments and then you have setter or getter methods to
set the first name, the last name, the credit card number, the expiration date, the bank
kind, and so on and so forth, right? The reason it’s okay, is because the value object is
really the end of the core graph, or the end of the instantiation graph. Like there’s nothing
in the other side of it. Like, I mean, maybe the credit card is made up of address, but
like its pretty much the end of it, right? Whereas if you look at the credit card processor,
it’s hardly the end, right? It talks to the offline queue, it talks to the database, the
database talks to the JDVC, JDVC talks to the CPIP, the CPIP has five layers underneath
it, finally goes to the wire, then there’s the sequel server, then it has–like there’s
so many layers before it gets to the hard disc, right? It’s a completely different beast.
And so, in situation like those, you definitely want to ask for everything in the constructor.
Now, if you have something like an offline queue, and the offline queue has, let’s say,
it has 10 fields, 10 collaborators it collaborates with, then yes, you need to have 10 fields
in your constructor. Now if you look at it and you say, “Well that’s too many.” Well,
then perhaps, your offline queue has too much responsibility and you should consider about
breaking it off and saying “Well, there is really the scheduler and there is the persistent
storage.” And really the offline queue needs to only take–know about the schedule and
the persistent storage instead of trying to do everything and know about the data base,
and the schedule, and the parameters and all these pieces, right? It’s what dependency
injection makes–gives you, is that it makes your dependencies explicit. It doesn’t make
it worse or better. It just says “This is what they are.” And now most people freak
out, they’ll say, “Ah, it’s too many. Let’s blame dependency injection.” Like no, no,
no. The dependencies were always there, whether you like them or not. You coded it that way.
I just made it explicit. So if you don’t like it, don’t blame dependency injection for that.
It’s you are the one who made this, you know, 20 different collaborators that you collaborate
with. And that’s going to make it hard to test, by all means, yes. Because now, I have
to mock out 20 different things. But the solution to that isn’t to go back to our–pretend there
is no dependencies world. Dependencies are still there. It’s just structured differently.
>>Hi. Since we are talking about dependency injection, this is a small practical question.
Basically, there’s this framework that is used by a lot of people.
>>Used?>>And, it’s–no, it’s basically Scarlet Framework
which ask for no argument constructor.>>Scala framework?
>>Scarlet. It’s basically some [INDISTINCT]…>>Oh, like a servlet.
>>…big table, yeah. So basically ask for a no argument constructor.
>>Yes. Yes. And that–it makes it really miserably difficult to test.
>>Yes. And I already thought that all the other classes, like I have a classifier, everything
it ask for dependencies, but I ended up knowing this thing in the constructor of this, whatever
I’m going to write at the last stage. It looks like this is a chart of the object graph,
but that’s not true because it actually does some work. So practically, what I’m going
to do to like fix it?>>Yeah. So let’s do a concrete example. Servlets
are exactly what you’re talking about. Servlets, AP–servlets specs says you–the servlet has
to have a no argument constructor. And that’s a huge problem because clearly, servlet has
to talk to all kinds of things, gets all kind of things done, right? How does he get a hold
of these things? The spec doesn’t say. And so what most people do is they have no choice
but to use singletons. But we know how much we hate singletons, right? So how do you get
around this thing? Well, first of all, many frames realized their mistakes and corrected
it. So for example, if you use GSE which is our own [INDISTINCT] server engine, or if
you use Jeti, or there’s couple other frameworks out there, they actually allow you to control
the instantiation of your classes. In which case you are responsible for calling the new
operator and you can inject anything you want in there. So those frameworks realize their
mistakes and they solved them. For the frameworks where they haven’t solved it, you are going
to be forced to somehow get the information there thru some kind of global state, but
you need to separate the stuff out. Instead, what you’re going to say is that “The servlets
whole purpose is to isolate me from this horrible API.” And the first thing the servlet does
is it goes and grabs the singleton which is usually the injector or some kind of a global
service locator where all the objects can be registered. And the first thing it does,
is it delegates everything to a nicely dependency injection class. And then, because there’s
nothing inside of the servlet, it just–all it does is it does the evilness of looking
into global state and passing it and then doing the nice stuff, you can totally test
the rest of our application. Because the nasty bits are limited to this one area and they’re
only there because somebody screwed up the API. Does that make sense?
>>Yes it does. So basically, what you are trying to say is that even though, originally,
this, whatever class I’m suppose to do is suppose to do some work, what I’m going to
do is I’m going to create some kind of a double of this class and send everything down to…
>>HEVERY: Exactly. Everything’s delegated on and I can test this, and I can do all the
good stuff that I normally do, dependency injection everything. And then this horrible
poor class will become, basically, this ugly duckling that all it does is does the evilness
of things that I try so hard not to do but because it’s forcing me, because somebody
else screwed up, I’m going to do it but I’m going to do as little work in there as possible
so that everything else can happen somewhere else. It’s basically a strategy from isolating
yourself from bad un-testable API.>>All right. Thanks.
>>Yes.>>It still seems like there are situations
where having global state is unavoidable. And I guess, like he was pointing at this,
but I mean with web page, you know? It’s not like you can just somehow–you don’t have
a main where you can just instantiate all the things you need and then have a [INDISTINCT].
>>Sure you had, you have main. If you have–if you use Jeti, if you use a good servlet engine
who doesn’t insist to be the container and control the world, instead it gives you the
control of the main method. So in the Jeti world, you have a main method, you instantiate
Jeti, you register all the servlets and you control the instantiation. So in a world like
that, you can totally do what I’m saying.>>I think we’re talking about [INDISTINCT].
. .>>Okay. Sorry.
>>…because I as thinking of like, maybe [INDISTINCT], app words you have everything,
almost everything happening on the client there. It seems like java script…
>>[INDISTINCT] java script problem or?>>Yeah. I mean it seems like you’re pretty
well forced to have some kind…>>Why can’t you do the same principles in
java script as well? If you have an object in java script, why can’t the object say,
“Please pass all these references to me through the constructor.”
>>Sure. I mean I think you can do a lot of this in there, but it seems like there’s some
situations where you’re not going to be able to escape–because the thing is you already
have a lot of global state just because of the dom.
>>Yes. But you need to separate yourself from it; otherwise you’re going to have a
really hard time testing it. So you don’t just have different methods to reach in and
to grab the dom which is the document in java script, right? And manipulated. Instead, insist
that all the objects that need to manipulate with dom ask for it in the constructor. An
interesting thing happens when you ask for it in the constructor and that is, because
methods ask for it and, you know, if this one needs it, then the other factory will
need them, and so on and so forth. Whenever you get to the situation where some method
is asking for a document and you don’t think it should, you can like step back and say
“Something’s wrong over here because in order to get it’s work done, it asks for a document
and I don’t think it should know about document, therefore I must have made a mistake somewhere.”
So by doing these things explicit, you actually find that a lot of these weird dependencies
come to light and you realize “Oh, that dependency shouldn’t be there.” Whereas, if you hide
all the dependencies, all kinds of weird things happen and you don’t know why.
>>Okay. Thanks.>>It is possible, basically, to build an
application purely without global state whatsoever, especially if you choose your technologies
correctly such as Jeti for web servers, you know? And you have proper separation of dependencies,
you know, of factories, and so on and so forth. And you really get in a situation that, we
talked about this a couple of weeks ago, that every object should only know about its direct
collaborators. You should never be in a situation when you are asking for something that you
don’t directly need. What it means is you don’t dispatch any method on this object.
You’re only asking for it to pass it on to somebody else, okay? That’s–that give away
that’s something’s wrong because you should always only know about the objects that you
directly need yourself. You never should be in a situation where you’re asking for something
just to–so you can give it to somebody else. Because when you’re in that situation, what
it really means is that object that you’re passing it unto, you’re either constructing
it, in which case you’re not supposed to be constructing, you’re supposed to be asking
for an instance in your constructor. Or it means that that guy–that object is supposed
to ask for that object through its constructor, right? In which case, it’s the same thing.
Its–you don’t want to know about things that you don’t need to know about. That makes it
real hard from a testing point of view, any other questions?
>>A comment from Rhode office.>>Yes.
>>Can you hear me?>>Yes we can.
>>I wanted to say that I’m a big fan of having those singletons and the reason is I work
on a system, river structure project, where we have a lot of communicating servers that
usually run on different machines. But if you wanted, actually crank them up at a single
address phase, and you want to put in a mock transport. Let’s see, are we actually, you
want to put in a mock transport for example, you can’t do that if there’s global state
because two objects can’t keep their states separate.
>>Correct.>>So, we were actually able to test the distributive
application in a single unit’s address phase by creating several objects, pass each of
them a mock transport, and then they all have their own completely isolated state. So I
just want to put it in a plug why, you know, not having singleton is a good thing.
>>Right. Yes. So you’re agreeing with me, right? I’m just making sure we’re on the same
page.>>I’m agreeing with you. It is one of the
pieces of evidence you gave. You were saying, well, you know, you don’t want to have more
than–you can’t–you can only have one application inside your JVM. And I’m saying we deliberately
want to set up multiple copies of the application simultaneously running in the same address
phase.>>Correct. I’d like to actually just add
something to what you just said and that is, suppose you have something like Jeti which
is a web server, which is a container for web servers, right? If Jeti internally had
a global state that it would mean that I can only have one instance of Jeti running. Which
can be okay for most of the applications, but what if I want to have an application
running in a single JVM that serves the users on port 80, but on port 8080 I have administrative
UI where I can do some extras stuff that the users cannot do. In essence, I want o have
two separate instances of Jeti, right? Can’t do it if you have global state, exactly what
you point out over there. So–yes and the other way of looking at it is really every
single test is a new application being instantiated, right? And so, if you have singletons like
the game is over and you haven’t even started testing, you can essentially have one test
per JVM, and that’s not very useful.>>So I’d like to make a meta comment about
global state. So, even the–if you–if you invoke static methods from class files, the
whole class hierarchy, you know? Java lang, java ion, so forth. That’s really all static
state and the existence of methods, you know, like system load library and you’re doing
file, all of that is really right with global state. And I only knew of one programming
environment in existence that tries to systematically remove all of it so that you that, you know,
you have a main method, it doesn’t just get a list of arguments. It gets a platform, and
the only way you can do [INDISTINCT] is by calling methods on platform. Or getting/calling
methods that will return you with, you know, file objects or whatever on your platform
object. And that is the news peak system that’s a derivative of small talk. But I don’t think
any–so every other programming language around has some kind of notion of this. There’s some
static state somewhere. So in the real world you can’t get away from it.
>>Yes. But what you want to do is you don’t want to make your application world worse,
right? So you’re absolutely right, there’s tons of global state inside a JVM. Whether
you’re talking about class loaders, whether you talk about–there’s just tons of it, right?
But I don’t have to test the JVM, I simply trust the JVM works, right? But I have to
test my application and therefore I don’t want to make my life more miserable than I
have to by adding global state into my application. Yes?
>>Actually, as far as I know, although the JVM has this–a loss that take global space,
you could actually pass them as an interface. That means like, you know, if you want a date,
you ask for a date. So I can pass you, either a new date or whatever mock that I can pass.
So, same thing with Math.random. Instead of using Math.random, I can create a new random.
Or even with system in system out, I can pass a buffer reader, buffer writer to the system.
And that will work perfectly and only my object graph actually needs to know about system
in, system out, or whatever.>>Yes, but you have to code your application
in a special way, right? So the honest, is I knew the developer to code your application
in such a way so later you can test it. And global state is going to really make your
testing life miserable. All right, anymore questions? Well, thank you guys for coming.
It’s great to see that there’s so many people interested in how to write good testable code
and we’ll see you guys next week. We have this every Thursday at 3 o’clock, and we also
have this cards on how to make you’re–what to look for in testable code, what to look
for when you’re doing code reviews to make the code a lot more testable. So if you guys
want to have some of these cool code review cards, stop by and I have a couple of copies
with me and I can give you a copy. See you next week.