Web Programming – Computer Science for Business Leaders 2016

Web Programming – Computer Science for Business Leaders 2016


>>DAVID MALAN: All right, we are back. So for the exciting
conclusion, our last section on web programming, which I
thought we’d use as a general term to capture a few remaining topics. So at the end of the
day, we’ll actually do a little bit of hands-on web programming
with a language called JavaScript. And I think we’ll take a look
at something related to images and discovering something
secretly hidden in an image, and also take a look at the Google
Maps API, application programming interface, as something
representative of the type of software that’s increasingly and
freely available today.>>But why don’t we take a look
at an ingredient to this world that we’ve kind of been
taking for granted exists for some time, a database. For the past day and
a half we’ve assumed that we have access to a database, but
what problem does a database solve? What does it do for us? What is it?>>AUDIENCE: [INAUDIBLE] DAVID MALAN: Holds all the information,
OK, and what kinds of information might you put in it?>>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: Any information
you put in it, you’ll get back. That is true. And on a typical web-based site or web
application, what kinds of information, specifically, might you put in? AUDIENCE: [INAUDIBLE] DAVID MALAN: Users. So what’s a user?>>AUDIENCE: [INAUDIBLE] DAVID MALAN: OK, registered
user of the site. And what does it mean to
store users’ information? What composes a user? A user has what? AUDIENCE: [INAUDIBLE] DAVID MALAN: Yeah, personal
data, and I like that. Let’s be more precise. So a user typically has a name,
what else might a user have? AUDIENCE: [INAUDIBLE] DAVID MALAN: An addr– OK,
so first name, last name. That’s good. Actually, let’s fix
that, because it’s going to open up an opportunity for
discussion, still, further. First name, last name, gender. An ID of some sort. What else? I heard something else before, too. An email, postal address.>>So let’s pause there and now consider
not what we’re storing in the database, but– and not why, since it’s perhaps
obvious that once you register a user, you want to remember them for some time. You don’t want it to
just be stored in RAM and be forgotten– so
let’s focus on the how.>>It turns out that in
the world of databases, there’s at least two types these days. Something called a SQL database,
Structured Query Language, or, cutely named,
noSQL, which is not SQL. And the latter is an
example of what might be called an object-oriented,
or an object store, a database that stores objects, and not, excuse
me, as we will soon see, rows.>>So we’ll focus for just a moment on
the first of these, namely, a SQL database, if only because it’s
so familiar already, to anyone who has used Excel or
Google Sheets or Apple Numbers or any standard
spreadsheet program, or, equivalently, or
more sophisticatedly, something like Microsoft
Access or Oracle or MySQL or PostgreSQL, all of which
are product names for implementations of the following idea.>>A relational database is simply
something that has rows and columns. And by rows and columns,
I literally mean something like this, so where we might have the
name of a field and its type over here. And actually, let me
now start to map these. So actually, I don’t know
why I drew a separate chart. Let’s keep this simple.>>We have right here the
beginnings of our table, where this is the name of the field
and this is the data type, and by type I mean the following. Is it a number, is it a string,
a short string like a word, is it a paragraph, is it
binary data, like an image? And let’s just tease this
apart for just a moment. So first name, number,
string, large chunk of text– AUDIENCE: [INAUDIBLE] DAVID MALAN: Yes, so string. And in a database context, we’ll
typically call this char field. I’ll just say char for now but we’re
going to refine this in a moment. Character field. Last name’s probably the same. Gender? >>Male or female, so it
could be a char field. It could be either quote, unquote
“male” or quote, unquote “female” or it could be m or f. If you want to be more inclusive,
you might need a third value or some kind of other field altogether. And so you could use true false. The field could be called male, and
then you could say true or false. But that doesn’t necessarily capture
all of the information you might want.>>So it turns out there’s another type
of field that might be useful here in a typical database, called an
enum, where it is a character field, but you, the designer, get to
enumerate the possible values, like quote, unquote “male”, quote,
unquote “female” and so forth. So that whatever value
is in your database, is indeed character-based, but
it has to be one of those values. We probably wouldn’t want an
enum for first name or last name. Otherwise we would have
to enumerate, as the name derives from, literally every
possible first name and last name.>>OK, so ID what should an ID be? Yes, so maybe a number. So let’s stick with
that for now, number. And by number, number’s
a little too broad now. For the end of the second
day, I feel like we should be a little more precise. Number could mean like, it
could be something like 1.236. And that’s probably not
what we mean by an ID. What do we probably mean by an ID?>>AUDIENCE: [INAUDIBLE] DAVID MALAN: Oh, OK, so
maybe it’s not even a number. Maybe it’s actually a unique identifier
that’s a string, like a user name. So absolutely, could be. I think someone probably
meant numeric, though. So let’s stay with that. What kind of number? What’s a more precise– an integer. So a number like 0, 1, 2, 3,
so we’ll call this an integer. And even then, I could
be nitpicking, it’s not really just a
general integer you want. You probably don’t want negative values,
just because, it just feels weird. You probably want positive integers. So you can also express
that in a database, but for now, we’ll say integer.>>Email? This is probably just– a what?>>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: It’s an email,
but that’s characters, right? It just has a funky character like
an “at” symbol or something else, but it’s still a character field. And postal address? Character field. So that’s a nice beginning, but
let’s be a little more precise now.>>So it turns out that in
a database, you often have a choice over more refined
versions of these things. In fact, in a typical SQL database, SQL,
or more generally, relational database, databases with rows
and columns, you often get to specify not only the type of the
field– let me make some room here– but also the length.>>So how long is a first name? I think, D-A-V-I-D. OK, got it I
probably just offended like half of the people in the room, right,
since your names are longer than five letters, so five seems a little selfish
and naive, so what’s a better value? 10, all right, and I think
we’re OK in the room. 13? 30? Why don’t I take the
approach of earlier when we were talking about arrays and memory? Why don’t I just say like 1,000? No one’s name is going
to be longer than 1,000. Push back.>>AUDIENCE: [INAUDIBLE] DAVID MALAN: Yeah, it’s
wasteful, right, especially if most names are only five or 10 or
15 characters, that’s very wasteful. So you know what? This is kind of a hard question. Now, we can certainly analyze English
and any other language’s names and figure out, well, what is the
average– average doesn’t really help us– what’s the max is
probably what we really want. But it turns out we even have
some choice over the type here.>>In a typical SQL database, you
have something called a char field and also a varchar, V-A-R,
for variable char field. And the difference is this. A char field, you the designer,
have to specify in advance the exact length of the field. So maybe the first name
like 20 feels kind of safe. Might have to do some googling to
see if that’s actually safe enough. There’s probably a name with 21
characters, but for now, suppose 20 is safe.>>A char field would imply
in a database that you are using 20 and always 20 characters. Now if it’s just D-A-V-I-D, 15 of those
are just going to be blank characters, but you’re still using all 20 bytes. A varchar field, by contrast, means the
string should be up to 20 characters but if it’s only five,
you’re only going to use five, or maybe six for a
special value at the end, like that 0 we discussed that
signifies the end of a character sequence in memory.>>So when do you think
you might choose char versus varchar, given that trade-off? Char uses that many characters, varchar
uses no more than that many characters. AUDIENCE: [INAUDIBLE] DAVID MALAN: OK, when you know the
length of the string pretty compelling to just use char, ’cause if
you know it, just put it down. And maybe that’s true for a zip
code, in the US, at least, 02138, it’s always going to be five
characters until you add the dash four. But you might have some values for
which you always know the length. Or maybe state symbols,
like NY for New York, and MA for Massachusetts in the US. Maybe you do have some situations
where that’s totally reasonable, but by that logic, why are
we even overthinking this? Why don’t we just use
varchar and then we’ll just always use two characters anyway, or
always use five characters anyway? Why not just save varchar for
everything, by that logic? There must be a catch. AUDIENCE: [INAUDIBLE] DAVID MALAN: Could
write something wrong. So that is true. But even then, they can’t use
more memory than I allocate. I still have the final
say over the length, so they can’t accidentally make
that mistake, but a good thought. It’s more subtle, but it’s very related
to our discussion, actually, of arrays and linked lists earlier.>>It turns out that a database, if
it knows that all of the values are of a fixed length, even if
some of those values are blank, sort of aesthetically blank,
D-A-V-I-D and then 15 blanks, it turns out that if every
field is the same length, much like an array had all of its stuff
back to back to back to back so that you could just plus 1 to get to the next
value, same idea in a database table. If all of your character
strings are the same length, you have what’s called random access. If all the strings are of
length 20, you don’t just do plus 1 you just do plus
20, plus 20, plus 20, plus 20, and you can very rapidly scroll through
or search through all of your data.>>A variable char field, by contrast,
doesn’t always have 20 characters. It might have 20 and then
15 and then 19 and then 10, and so if you want to search
through it, you can’t just blindly add 20 bytes to get to the next one. You literally have to search through
because the edge of the data structure, if you will, is ragged. It kind of goes in and out based
on the actual length of the string. So when you know the length, as
Kareem says, use a char field, because you gain that
efficiency of being able to search through it faster
when you’re looking for data, otherwise use a variable.>>Unfortunately, I have no good answer
to how long the name should be, but for something like
a name, I would say a varchar is common
because it’s not going to be a fixed length for everyone. 20, I don’t know, 20
feels a little tight. Let’s just say 50, 50. It doesn’t really cost you that
much more to say 50 instead of 40, but at some point, you need
to make a judgment call.>>Very common, frankly,
for [? historical ?] reasons, even though it’s excessive,
is to say 255, because some time ago, in popular database systems, like
MySQL, a free open source tool that a lot of companies
like even Facebook used, this was the maximum default
so people just went with it. So not unreasonable, but we’ll
use a little more intuition and say, sure 50, that’s
probably a little excessive.>>Gender, I do like enum,
and so we can therefore enumerate male or female,
or maybe more efficiently, m or f or some other symbology, but
enum feels like a good choice there. To be clear, gender
could just be a varchar, and we could just all
agree as nice people, to always put the same values there. Male or female or whatnot.>>But the problem then, is that we could
make a mistake, as [INAUDIBLE] proposed earlier in a different context. If we make a mistake, we could get
incorrect values in our database. So what’s nice about databases
like Oracle and MySQL and others, is that you have this last
layer of defense where your DBA, database administrator,
whoever is designing this table like we are verbally, could put
into place an enum that protects against that by specifying
male, female, and so no one else no programmer can accidentally
insert any other value. So this would be a good thing. This is a feature.>>So an ID, assuming a numeric ID, it
probably should be a positive integer. And we sometimes do have
opportunity to discuss length. You wouldn’t typically
specify a number here, you would instead specify
this is a int, or a big int, as they’re typically called. But typically, an integer
would be, let’s say, 4 bytes. And if it’s 4 bytes,
that’s how many bits?>>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: 32 bits. So how many users can we have in
our database if they all have an ID and this ID has to be unique? 32 bits means we have patterns
of one, two, three, four, five– so how many different patterns of zeros
and ones can you have if there are 32? That’s the same thing as
asking what’s two to the 32? It’s a big number that
I can’t quite get right, but I know it’s roughly 4 billion. So this means your database table can
have four billion users and that’s it.>>So this is an interesting
design implication. A decent number of companies
have decided, maybe not so much for their users table, because having
4 billion users is a rare problem. This is sort of a Facebook-style
problem, not a typical company problem. But maybe if you have transaction logs
or some kind of data that constantly gets written into your database
that absolutely could have billions and billions of rows, and
you use an integer for it, what’s going to happen as soon as
you get to row number 4 billion and then you try to insert the
4 billionth and 1, so to speak? I’m simplifying the numbers a bit.>>You can cut back, I mean you
have to handle it somehow. And what a computer would typically do,
think about it even from this morning, if you have a 4-bit value
like 1, 1, 1, 1, which, just to tie the morning
together to the afternoon, what does this number represent in binary? OK, we’ll make it easier. What does this number
represent in binary? OK, we’ll make it easier, what
does this represent in binary? AUDIENCE: Three. DAVID MALAN: Three, because
we have the ones column– [LAUGHTER] Whew! We had the ones column
and the twos column. So suppose that, indeed, our
[? infield ?] weren’t 32 bits, but it were two bits, we can
count from user number 0, 1, 2, 3, and then we’re kind of
back to user 00 again. So this is what typically happens. If you’ve ever heard the expression–
probably haven’t, but if you have– integer overflow, where you
keep flipping all of your bits to be the biggest possible values,
and then you’re out of bits, what would typically happen? Why do I say 00? Well, this is three. How do I represent 4? How do I represent the
for number 4 in binary? AUDIENCE: [INAUDIBLE] DAVID MALAN: One– yeah,
don’t say 100 per se, because it has the wrong
connotation, but 1-0-0. So that number 1-0-0 is indeed
correct, but if you only have two bits, what have you really done? You’ve rolled over to 00. And indeed, that’s what would happen. Actually, you can think
about this more familiarly. If you recall, what,
16 years ago, the world was supposed to end when
the Y2K problem happened. Why was that? Well most computers, for
reasonable decisions, were storing numbers like the
year 1975 or the year 1999 by just using two digits
in the computer’s memory. So of course, what happens
when you get to the year 2000, you go to this, or rather, yeah. So you go to the year 2000, but if
you’re only using two digits it looks like the year 00 and
so you’ve rolled over. And this is why a lot of systems
needed to be updated at the time.>>So with that said, companies like
Facebook run up against this. So the only way to handle the
situation, frankly, is to anticipate it. Or the cleanest way to
handle this situation is to anticipate it so you don’t
have to make changes later. So instead of 8 bytes, you know what? I’m going to be forward-thinking
here, even though it’s a little optimistic that
we’re going to have 4 billion and 1 users on our website. But let’s just use 8 bytes, or
64 bits, which would generally be called a big integer, very technical. And that just means you can have
even more digits in your number. But this is an important
design decision, because if you choose a number that
has too few bits of expressiveness you could actually create
a bug in your software.>>All right, so let’s wrap up
with email and postal address. So email, how long should
an email address be? 50. I really have no idea, but it’s
probably something like that, because otherwise no one’s going to
write you if it gets too long, so 50, let’s go with it for now. Postal address, how long should that be? AUDIENCE: [INAUDIBLE] >>DAVID MALAN: It’s not
just a zip code, though. Postal address, I heard. So this is like 1 Brattle Square,
comma, Cambridge Mass., comma, 02138. And in fact, let me just pull
up a little worksheet here. This feels like it’s
a missed opportunity. If we have 1 Brattle Square,
comma, Cambridge MA 02138, I feel like we can do better
than just postal address. Why don’t we explode this a little bit? What am I getting at? What should we instead have
for our rows here, perhaps?>>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: Yeah, so let’s
call it street_number, and an underscore is just a common
way of having what looks like a space, but it’s not, actually. Street, and then city– sorry?>>AUDIENCE: [INAUDIBLE] DAVID MALAN: We could do that. Line one, line two. Why don’t we will keep
it simple for now, but that’s absolutely
an acceptable decision. And then state, and then let’s
be a little US-centric for now and just do zip code, just because
it’ll lead to an interesting mistake or problem here. So suppose that’s now our address. It’s a little more annoying that
we have all these more fields, but now we can tag
things a little better.>>So now street number probably
shouldn’t be a char, should it? What should it be? AUDIENCE: [INAUDIBLE] DAVID MALAN: Maybe, a number
like an integer again? A big integer? You probably don’t live
at 4 billion Main Street or anything crazy like that. So integer is probably
fine, but has anyone ever lived at an address like
1A Brattle Square, or 1 and 1/2? These things exist, unfortunately,
even if you haven’t lived there, there are these anomalies
like apartment 1A, 1B, 1C. So you know what, we probably
shouldn’t go with integer, otherwise we’re going
to lose some sales.>>Char field, maybe? I don’t know how long. It’s probably not going to be
that long, so 10 or something. No one’s going to write
a longer number, maybe. But again, we should probably
give more thought to that. Maybe google, do some research,
but we’ll go with our guts for now. Streets, char, 50, I don’t know. At some point, no one’s going
to write it on an envelope, too, so there’s probably
some upper bounds there. City, same, sure, so char 50.>>State, can be US-centric for now. So it could be a list, so kind
of a judgment call, state. It could be like two characters. So actually, maybe, I kept saying char. I probably mean varchar,
just for some efficiency, but we’ll come back to
that decision in a moment. Could be a char of length 2 for state. If in the US they have, like MA,
Massachusetts, NY, New York, NJ, New Jersey, and so forth. So it could be fixed at that. DC for Washington DC.>>But I think, Olivier, you
proposed another approach. AUDIENCE: [INAUDIBLE] DAVID MALAN: Yeah, so it’s a
little annoying to type in, but an enum might make more sense,
because this way, at least in the US, you could enumerate, if tediously, but
you do it just once in your database and never again have to think about
it, all 50 two-character codes. So I like enum. Let’s stick with that there, because
it sort of enforces more rigor. And then zip code? I think Andrew had a thought on that AUDIENCE: [INAUDIBLE] DAVID MALAN: Yeah, five or nine. Let’s just keep it simple. Just do five for now. But maybe I could just
do an integer, right? I could, but you know what, I made
this mistake once, in some sense. Years ago, I was migrating from
Microsoft Outlook to Gmail, and Outlook has a way of exporting
all of your contacts as an Excel file, a CSV file, comma separated values file. And I made the mistake, I
think, of double clicking it, once I downloaded the export, to
make sure it looked as I expected. I must have hit Save or let
auto-save kick in or something. Because when I then imported
it into Gmail, it all worked. But for years, to this day, and
I did this five, 10 years ago, I’m still finding friends who have
addresses that look like this. Why?>>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: It took
the 0, well, rather, it took the whole zip code as
a number, and therefore it’s a leading 0 which means
it has no meaning. And so 2138 seems to be my zip code. And this is, frankly, an annoying Excel
feature whereby I think by default, even if it’s meant to just
be text, Microsoft Excel decides, let me be helpful,
and oh, I see only numbers. Let’s treat these as numbers. And it truncates the leading zeros.>>I swear to God, every couple
of months I find an address, and out of a sort of OCD, I go back
in and add the 0, even though I never send people letters or anything. But I’m still finding remnants of this. So this is to say, is this a good idea? OK, no, because anyone in
Massachusetts, in this area, is going to have a o leading them. So let’s go with like
char, probably, five.>>And here, realize we
could use an enum and we could enumerate 10,000
possible zip codes, but that feels like it’s probably
crossing a line of, like, benefits. If you have to input that
much data into your database to protect against something. So char realized you could type
in H-E-L-L-O as your zip code, which is not, obviously, numeric. So there’s no way, in
a typical database, to specify only numeric and
only five characters long, so we’re going to have
to do that in code. We’re going to do that in PHP or
Java or whatever language we’re using on the server to enforce
that kind of constraint.>>Whoo! All right, so any questions just yet? Let’s make another design decision. It turns out that you
also get to choose, when designing a SQL database, or
typical relational database– where again, relational just
means rows and columns, that’s how you organize your data–
and realize that what this means is, I’ve been misleading in
that, I’m drawing– this is what’s called the schema
for a database table. This is like the
specifications for the table– but when it comes time
to actually store data, and we’ll do this just by example here. I’m going to open up Excel, because
Excel will give me rows and columns. And that’s exactly what Oracle and
MySQL and other tools will give me. So I’m just going to use
it for discussion’s sake. Let me go ahead and open up a
representative document here, zoom in a bit. So for instance, our headers are now
first name, last name, gender, ID, email, street number, street, whoops. Street, city, state, just
about fits on the screen.>>So what this means is that when a
user first registers for my website, it’s going to be something like
David, Malan, m, let’s say 1, [email protected], street number will
be like 1 Brattle Square, Cambridge, MA, 02138, and then so forth. So when I say that a relational database
or SQL database is rows and columns, I mean this. That actual data is stored
in rows and columns. This is just a coincidence,
that we were talking, and I was just drawing it
out in rows and columns. This is just the schema,
the overarching definition.>>So of these fields here,
or equivalently, there, which are the fields that you think
I’m likely to search on if I’m a user or if I’m the database administrator? Like, what fields am I
actually going to search on?>>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: The name, yeah so
I like the fact that– yeah, email might be pretty common. Sorry, you said name. So maybe– and again, we’re
kind of talking in the abstract. I don’t know why you’d
be searching for a name, but that feels reasonable if
you’re searching for a user. Maybe states, sure, ID. >>And it’s a slippery
slope, because I could contrive a scenario where
maybe my boss has asked me, how many men do we have on our site? How many women do we have on our site? And so at that point, you might want
to search on the gender field, too, and nothing else. So there’s a trade-off here. Again, there’s no
right answer, but there is a feature in most SQL databases
known as indexing, whereby you, the designer, the
database administrator, get to decide in advance which
fields the database should optimize for searches on.>>You could very naively say, optimize
this, optimize that, optimize this, optimize that and this,
and the database will do some magical thing underneath the
hood, and do something in such a way that the next time you search
on any of these fields, it will, in fact, be faster. This is possible. It doesn’t cancel itself out. But there must be a price paid.>>If you naively, or over-enthusiastically
say, index all of these fields, so to speak, make them all
efficiently searchable, what price are you probably paying? AUDIENCE: [INAUDIBLE] DAVID MALAN: Performance. What do you mean? Well performance, at least in the
context I’m discussing, is better now. That’s the definition of indexing. It will make searches faster. So time decreases, so to speak. AUDIENCE: [INAUDIBLE] DAVID MALAN: Space. So again, these are a common trade. I can speed up your searches, but it’s
going to cost you more bytes of space. Why? Well, by default, if we have none of
these red stars, none of these indexes, as I’m saying, how do you search
for a name in this database? So let’s draw our
attention to this example. If we have David and Scully and Kareem
and Arwa and others in these rows, for instance.>>So let’s do exactly that. Scully is in here, and then
we have Kareem, and Arwa, and everyone else, if you don’t
have an index defined, so to speak, the best you can do is linear search. If you search for Arwa, we’re not
going to be able to jump right to her quickly. We’re going to start top and
go all the way to the bottom, not unlike our original
Mike Smith example.>>If, however, I say, hey, database,
index the first name field, then it’s going to do something
fancier and support something like binary search. It’s probably not binary search per se. Databases tend to use another
data structure called b-trees, not to be confused with binary trees,
that just make it faster to search something logarithmic in nature. But the price you pay to build up that
feature, that data structure in memory, is more bytes. So it might take some megabytes,
some gigabytes, who knows? It depends on the data.>>So at some point, you have to decide,
it’s probably not a common case. So what are the actual common
cases, if you really had to choose, what might your favorite fields be? Email. And I like email because email,
in theory, should be unique. And so typically, when you know
in advance that one of your fields is or will be unique, that
tends to be a good field to search on, because that way,
when you search for something, you’re going to get back one or
zero responses and then you’re done. You don’t have to keep
looking for yet others.>>And so in this case here, email,
so long as you can’t register twice with the same email, is a good one. ID by definition, in the
computer science world, if you’re talking about an
ID, that had better be unique. That’s sort of the connotation
of ID or identifier. And the rest of these might be,
let’s call them nice to haves, but not really required.>>And so in a database,
you specify indexes, but you can be even more precise. You can say, hey, database, make sure
that every ID in this table is unique. Don’t even let a programmer
accidentally put in a duplicate email or duplicate ID number. So much like enums
protect us similarly, you can have those lower-level defenses. And so database design, in
some sense, is kind of fun, because you do it defensively. You sort of assume that you work
with horrible, horrible programmers and you want to put in as many defenses
as you can to protect your data, but simultaneously you want
to help them perform better by choosing which
fields to optimize for. But you can’t necessarily do it in
a vacuum like we kind of are here. You’ve got to know what are
those common cases being. If the developers are
implementing an address book, you might very well want to be able
to search on almost every field, just by nature of the application. So maybe you spend
that additional space.>>Right, any questions? Yeah.>>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: No.>>AUDIENCE: [INAUDIBLE] >>DAVID MALAN: OK.>>AUDIENCE: [INAUDIBLE] >>DAVID MALAN: Oh, so we
are talking in a way now that’s completely language agnostic. So we are talking now about
relational databases more generally, or SQL databases more generally.>>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: A better word to use
is, can be used by any language. So I can write JavaScript code, C
code, C++ code, Java code, Ruby code, all of which talk to a
database and execute queries. In fact, that’s not a bad
segue to an example query. And again, we’re not going to go into
Java or C++ or any of that anymore, but in SQL, the language to which I keep
referring, Structured Query Language, this itself is a programming language,
but it’s meant to be used for, no surprise, structured query queries.>>By that I mean this. The way you select data
from a MySQL database is you literally type in your program
something like select star from users. I am assuming that this table,
henceforth is called users. I could call it anything we want,
but that kind of makes sense. And so select is a very
common verb, if you will, in SQL, that literally does that. What do you think star
means in this context?>>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: I’m sorry?>>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: Not required, it’s
more inclusive than that, actually. It’s the wild card character. Star almost always means anything,
so this means, in this case, select everything from the database. So when I say this, I mean
give me back every column from my table called users. So give me a result set, as it’s called. In other words, give me a copy of the
spreadsheet, is what I’m getting at.>>But if I said select star from users
where ID equals 1, how big should my result set be then? Or equivalently, how many rows should
I be handed back from the database? Probably just one, if I have indeed
treated ID as a unique identifier, and if David has that unique ID, I
should get back one and only one row containing all of David’s information. If I said this where ID
equals 99, I should get back, in this context, zero rows,
at least at the moment.>>However, if I don’t really care
about all that information, I could just say, where does David live? Select zip code from
users where ID is 1. This will select to me only David’s zip
code and not the entirety of that row. Why might I do this instead of
the star query, the wild card?>>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: Yeah, I might only need it. So performance is again the answer here. Why ask for more
information than you need, because even if it’s all right together,
you still have to copy that data, it would seem, from the database
into your program somehow, and that’s just silly if you
only need five of those digits, not the entirety of the row.>>So how do I insert a user? Suppose a user has just
registered for the first time. The syntax would usually look like this. Insert into users, and
then we would say values, and then we would say values
like, let’s say, Lauren Scully, our videographer right here. And the next field is gender. So we’ll say quote, unquote
“f”, then we have an ID and I’m going to say– let’s
pretend she’s not actually here, so we’ll rewind in the story. So 2 will be her ID. And then the next field
here is her email. So it’s going to be like
Lauren Scully and so forth, and we’ll just dot dot
dot it away from here on. Now it will get a little
tedious, but the insert query would ultimately look like that.>>If I want to get rid of
Scully, uh-oh, let’s deregister her, she deletes her account,
delete from users where ID equals 2, will get rid of Scully. Or I can say update users set,
let’s say, what could we change? Suppose she moves. Set zip equals 021– nope,
that’s her current zip. 90210. The only other zip code
I know in the world. So that would change
her zip code– actually, that would not change her zip code.>>What did I just do? Even though the syntax is probably new.>>AUDIENCE: [INAUDIBLE] DAVID MALAN: Yeah, I moved everyone
to Beverly Hills, California. So I should actually
say where ID equals 2. And so forth. So SQL is all about these
kinds of instructions. Select, insert, delete, update,
with these predicates at the end these where clauses, so to speak. And there’s a lot more you can
do, but it really just boils down to simply, if arcanely, expressing
what you want the database to do.>>And then the database
will figure out, when you insert Lauren Scully into the
database, where to put her in memory so that we can very quickly get
her based on her email address or based on her ID number or the like. Yeah, Dan. AUDIENCE: [INAUDIBLE] DAVID MALAN: Really good question. Will these scripts change from
Microsoft Access to Oracle to MySQL to PostgreSQL? The short answer is it depends. In theory, there is a very
significant common subset of SQL that’s shared across all
of these implementations. However, various manufacturers
have added features to their databases to do certain things
beyond the scope of these features, that might, in fact, break.>>So the way developers
hedge against this, is that rather than writing raw
SQL code like I’m writing here, they instead use a library,
a common library that itself is sort of higher-level and abstracts
away which product you’re using. And it gives you
functions and procedures to call so that you never
actually write raw SQL.>>In theory, then, you can change
products from Oracle to Microsoft or vice versa or anything
else, and you literally change nothing about your code. The reality, though, is, you sometimes
give up features as a result. You might have chosen a product because
it’s got these value-added features, and you’re just now not
using them consciously.>>And anecdotally, most companies tend
never to move away from their database. So while this is a nice to
have feature, the reality is, if you’re overhauling
your database, you’re probably making bunches of other changes
anyway, that you don’t necessarily need to anticipate that. So it’s arguably
over-engineering the problem, but it really depends on the context. But in theory, SQL is shared
across these various products. Really good questions. Yeah.>>AUDIENCE: [INAUDIBLE] >>DAVID MALAN: Yeah, so
you can think a database is just a server, at the end of
the day, and inside of that server is a whole bunch of
tables, rows and columns. And when you send a query like this
from your program, your website, written in Java, Ruby, Python, whatever,
the server is receiving this command and interpreting it in
literally the same way we discussed earlier with
interpreted languages, and then performing some action on zero
or more rows in zero or more tables. AUDIENCE: [INAUDIBLE] >>DAVID MALAN: Exactly, exactly. So the pseudocode for something
like that might be this. In your PHP file or your
Python file or your Java file, you would have pseudocode code, or
Scratch-like blocks as, if user visits acme.com/register for first time,
then insert into users and so forth. And we would translate this to
more concrete code in the end. But really, we have all
the building blocks here, even though we’re skipping some
of the implementation steps.>>So let me find fault with what we
wonderfully did just a moment ago. You have created a pretty
complete table for users. Admittedly, we could implement
it in a few different ways, but you have actually led us
down the path– and I say you, but it’s probably my fault– of a fairly
inefficient database implementation. It’s not normalized.>>And by normalized I mean
there is going to be, over time, a significant redundancy,
and therefore inefficiency, that is waste of space. Based on only what you see here, can
you envision where this waste of space is going to come from, over time,
as more and more users register for your website? What data might become redundant? >>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: Why do you mean that? AUDIENCE: [INAUDIBLE] DAVID MALAN: Yeah. And let’s assume for the purposes
of today that that is true. Turns out, and we’ve learned this
the hard way, that is not true. Somehow multiple cities have,
somehow, the same zip code, which breaks this wonderful intuition. But let’s suppose that’s true,
because it’s almost always true. So suppose that a zip code is
always associated with the same city and state, which is kind
of reasonable assumption, but incorrect, it turns out. But a reasonable assumption
for today’s purposes.>>Then suppose that I live in Cambridge,
MA, according to this user’s table, and suppose that Lauren
Scully lives in Cambridge, MA, and suppose that Kareem
lives in Cambridge, MA, and Arwa lives in Cambridge,
MA, all of us in 02138. Why are we remembering Cambridge,
MA, 02138 for all four of us? What should suffice to remember?>>AUDIENCE: [INAUDIBLE] DAVID MALAN: Just the zip code. Just that 02138 exists, because
you know what we could do? We could get a little fancy here
and over here, define another table where this is going to be the
name, this is going to be the type, this is going to be the
length, and henceforth, I’m going to call this my cities table. This was called, of
course, my users table. And so what should I put over here
for my cities table, do you think? >>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: Yeah. So zip and state and city. And so the type here, we’ll say
this is going to be a char 5 again, subject to the debate of earlier. This will be an enum, perhaps like
before, and city will be a varchar 50. And so now what do I get
to erase from this table to eliminate that inefficiency?>>AUDIENCE: [INAUDIBLE] DAVID MALAN: Nice. State and city go away, so I’ve now
eliminated the potential inefficiency for redundantly remembering, Cambridge,
MA, Cambridge, MA, Cambridge, MA, Cambridge, MA, which, hopefully
is never going to change. And even if it does, it’s
minorly annoying, now that I have to change
it in multiple rows, whereas here, I could just
change it in one place.>>Now what’s the trade-off, perhaps? This was super convenient. Had all my data nicely together. But what’s clearly the case now?>>AUDIENCE: [INAUDIBLE] DAVID MALAN: Exactly, and I’m
glad you used the word join, because that’s actually the keyword,
in the world of relational databases in SQL, it’s an actual word you
might type or at least convey. And in fact, what we now have to do
to select David’s full information is something like select star from
users, join cities, on– and now I’m going to just move to a second line
so that this fits– users.zip equals cities.zip, where users.ID equals 1.>>So what’s going on? It’s ugly looking, but you can kind of
read it left to right, top to bottom. Select star from users
is the same as before, but it’s not from users, per se. It’s from users join cities. What am I joining those two tables on? Well, apparently, the
users tables zip field, and this period is just special
syntax to express that idea, and this is the cities tables zip field. I want those two to be equal,
but I want to ultimately select only those rows where
ID in the users table equals 1, which happened to be mine.>>And just to be clear, a
programmer, typically when hardcode something like the number
1, because otherwise the website only supports David or the
very first user, you would instead do
something like ID, where this represents a
variable, something that can change over time, similar
in spirit to what I said earlier with these kinds of placeholders. But for now we’ll just hardcode it as 1. And so what does this mean? Well, a nice way to visualize this is
that if this hand is the users table, and this hand is the zips
table, we’re sort of finding– and the tips of my fingers are zip
over here, and the tips of my fingers here are zip, you’re
kind of interlocking it so that you get back the resulting
original table, by truly joining the two tables on the common field. And it doesn’t have to be zip. It could be most anything else, but
zip is nice, because one, it’s short, two, it’s always the
same length, so there’s a real efficiency to what
Olivier proposed here with factoring out the zip, and
[INAUDIBLE] proposing that we get rid of city and states.>>So this is the process
known as normalization. Any questions on that? Well let me point out
this is the kind of stuff, even though it’s fairly low-level,
this discussion, that you would think you’re sort of getting
lost in the weeds, this is a manifestation of ample
opportunity for developers to be bad. And in fact, even when we, in
courses I’ve taught, when we’ve had, for instance, inexperienced
undergraduate programmers build websites, at first glance,
the websites might look terrific. And they have all of the
functionality we requested, the developers did a good job.>>But they didn’t necessarily know
enough about database design or they didn’t think hard
enough about the types of data and the types of users the
website was going to have, and we find, then, six months later,
after they’ve graduated or moved on, that damn it, our website
is really, genuinely slow. And I’m not even talking about having
millions or thousands of users. I mean a few hundred users on campus,
all of whom like to, for instance, shop for courses at
the same time, they’re using that course catalog
application I mentioned and the thing is getting really
slow because there were no indexes. There were no red stars, so to
speak, or we hadn’t necessarily factored out common data to
get some savings of space.>>And so when vetting a developer
or database person or the like, the kinds of questions to think through
is even, when reviewing someone’s code, to say, not necessarily look
through all of their code, but say, let’s look through the database tables. What are you storing? And then to say, well, wait a
minute, why are you using an integer? What if we have 4 billion
and 1 of these rows? And these kinds of
questions is an opportunity to kind of push back and
get a sense of, where if you’re not comfortable doing
it, having someone more technical ask these questions, of whether or not
the person really knows their stuff. And this is the kind of
stuff, too, that people on the internet who
are self-taught, maybe learn less frequently, because you
don’t necessarily come across it as much, because you can get
the database up and running, but unless you’ve read
up on tutorials or been told about database normalization
and indexing and performance, these are the kinds of things
that are going to hurt you. And you might think, or a bad engineer
might say, oh, well, we better pay for a bigger database
or a faster database or just throw money at this,
vertically scale, not necessarily so. If you go in– and you can go in
after the fact– and add indexes, and it might take a few hours for the
database to build up that new data structure that I alluded to earlier,
you can still fix this after the fact, that this is where you
start to distinguish good designers from bad
designers, not just aesthetically, but performance-wise as well. Any questions? No? So for NoSQL, which was the other type
of database to which I alluded earlier, you don’t have rows and columns. Instead, you would have something
that looks a little more like this. I’m going to use common syntax. Curly braces happen to
be used here quite a lot. You might have something
like first name is David, you might have last
name is Malan, quotes, you might have ID is–
excuse me, whoops– ID is 1, email is [email protected], and I won’t
bother typing out the rest, and then some other things.>>In other words, this is
a textual representation of what we would generally call
an object in a computer program. And an object is generally just
a collection of key value pairs. So again, this recurring theme. We saw key value pairs in HTML,
we saw key value pairs now in the context of databases, and we
saw key value pairs in the context of, I think, a language earlier today. Keeps coming up. And indeed, that’s really
what data boils down to, data and metadata, or values
and keys, respectively.>>So a non-relational
database, something based on objects, where you just clump
everything together and put it into memory, would generally be
pictured as, or thought of, as this. And I’ll leave that now as a
sort of alternative approach. And one isn’t necessarily
better than the other. In fact, very much in vogue
these days are database systems like MongoDB and Redis and a few
other such tools, freely available, but they are increasingly en vogue. Partly because they offer additional
features over these tabular approaches, but also because they’re
a little easier to use, because you don’t have to think as hard
about a lot of these design decisions. So pluses and minuses. So realize there are options
beyond what we just spent time on.>>So let’s do this. Let’s transition a little
back now to web programming, so that we kind of conclude
today with something that’s a little hands-on, filling
in some gaps from yesterday. Let me go to this first. So recall that yesterday
we had some canonical HTML pages that had initially, only
HTML, and then secondarily had CSS, cascading style sheets. This is a new tag that we didn’t
see yesterday, or dwell on, so-called script tag.>>Turns out you can actually embed a
language called JavaScript in your web page and make your web
pages do something. So what do I mean by that? Well, let me go ahead and just
borrow this code for a moment. I’m going to go into Cloud9, no need
to go there yourselves just yet, and I’m going to call this alert.HTML. I’m going to paste in my file here. And just to clarify what I’ve done, let
me go to this address and go to alert, and you see the Hello World.>>But this is kind of underwhelming. I want to do something
a little different. So I’m going to actually do this. I’m going to go in here e,
and in between my script tags, say alert(‘hello,world’); so notice
it’s a little sloppy, but I’ve got HTML, inside of which is a
language called JavaScript, and this is what’s called a
function call or procedure call. This is a verb, literally, in this case,
and I am invoking code functionality that someone else wrote.>>So that functionality is an
alert, so let’s go to this page now and click reload, and now you
see a little bit of interactivity. It’s kind of old school and ugly. This kind of reminds you of the
pop-ups, perhaps, of yesteryear but it did do something a
little more programmatic.>>So more than that, let’s do
something more interesting. Let me go in here and get rid of this. And I’m going to go ahead and
create a form like we did yesterday. Actually, you know what? I’m going to go into
google.html, which we started on yesterday, which looked like
this, via which we searched for cat But notice there’s kind of a
bug in the current version. It works for cats, but suppose that
I don’t cooperate and I type nothing, and I simply click submit. That’s kind of weird behavior. Took me to the real Google,
didn’t give me an error message. I’d like to tell the user
you need to give us a value.>>So how might we do this? Well let me go back into Cloud9 and
let me go into the top of my page and add a script tag like this, where
I’m going to type some JavaScript code. And I’m going to do the following. If(document.getelementByID– and recall
that we talked about that earlier, that function. What ID do I want to get? I want to get q, and I’m going to
say equals nothing, like this– actually let me use double quotes
just for consistency– equals nothing, then alert(“Please type a query”) here.>>So I have what appears to be
something like a condition. We’ve seen this general idea in Scratch. It’s like one of those puzzle
pieces that looked like this. And what am I saying? Well, down here, notice I’m
going to do the following. I’m going to give this form
field not only a name of q, which is what gets passed to Google, but I’m
going to give it a local identifier, also called q. But I could call this anything I
want, I’m just going to keep it simple and also call it q, just for simplicity.>>And now I’m going to do
something a little more. On the form fields here, I’m going to
add what’s called an event handler. On submit, I want to call
a function called validate. This does not exist yet, this
word, or this verb validate, because what I’m going to do
up here now is add some code.>>I’m going to say function validate. I’m going to indent this and add another
curly brace here and another one here. Consider what this is now doing. I have now– think of this as created my
own puzzle piece that didn’t previously exist, and I’ve called this puzzle
piece the validate puzzle piece. Its purpose in life is to execute
the four lines of code inside of it.>>If document.getElementByID
so conceptually, that is going to go into the element,
the HTML element whose unique idea is just q, and then even though
the syntax looks a little weird, that equal equals just means equals. So that means if the element with the
unique identifier of q, when gotten, has no value, it just equals
quote unquote, nothing in there, then what do I want to do? I want to yell at the user.>>And we won’t go great detail here. I’m going to return false. That is an error. Else, I’m going to return true. So either it worked or it didn’t. False or true. And now if I didn’t make any mistakes,
let me save this and reload this. And let me just double check that
I didn’t, in fact, make any typos, so I don’t embarrass myself. Let’s see if this works.>>So now I’m going to type cats. It still works, or half works, at least. Now let me reload it, and now let
me try submitting without typing anything– damn it, it broke. One moment. Let me open the console,
[INAUDIBLE] log, reload the page. Let me try this again. Oh, damn it. I forgot. I made a typo. I remember what it is. .value. I meant to say if the value
of the element whose ID is q equals that, then yell at the user.>>So now let me hold my breath again. Here we go. There we go. Please type a query. So it’s not letting me through. I can be kind of playful with this,
and instead of checking for no value, I can say something like,
no more searching for cats, and now we can just more playfully let
the user search for dogs if he or she wants, or if I go in here and
search for cats, now I can’t.>>So what’s the takeaway here? So one, we’ve introduced into
our world of HTML and CSS, programming functionality. I can actually now
make decisions in code. Previously, all I could do is mark up
textual content or graphical content and tell it what to look
like and where to display. Now I can actually ask
questions of the web page and make decisions based
on it, and prompt the user if I need to yell at him or her.>>So let’s try something
on our own with this. Go ahead, let me open up the next slide
here, and just point out one thing. Just like with CSS, we can factor out
our JavaScript code to a separate file, you can do the same thing
with JavaScript as with CSS. And you use that using a source
attribute of the script tag. But we won’t complicate things for now. Instead, if you could
go to not this page, but– let me move this around in order–
go to, if you could, this page here. This URL here. It’s in today’s slides. You might have to reload because
I’ve added a couple of thing. >>But go there where some puzzles await. And this will give us a chance,
in a slightly more fun context, to dabble with some JavaScript. And when you get there,
I’ll explain what awaits. Get green. Set blue. Sets green, sets red. Oops. Sorry.>>This is the extent of our
documentation for this challenge. And this is going to work as follows. So what you have on this
page is a whole bunch of image puzzles by a buddy
at Stanford University. So what you’re seeing here is almost
kind of one of those magic eye puzzles, but if you just stare at it,
nothing’s going to pop out at you. Rather, something is
hidden in this image. And it’s hidden in the following way. Images, as you may know, can be
composed of just three colors. Some red, some blue, and some green. And we can make all the
colors in the rainbow by mixing those three colors somehow.>>So this looks mostly green and
blue, but as Nick says here, this iron puzzle image is a puzzle. It contains an image of
something famous, however, the image has been distorted. The famous object is in the red values. However, the red values
have all been divided by 10. So they are too small by a factor of 10. So in other words, Nick
took an original image, and he desaturated all
of the red from it, lowering the amount of red
ink, if you will, in it.>>The blue and green values
are all just meaningless, random values, aka noise designed
to obscure the real image. So what Nick did was he
toned down the red and then he just threw random
amounts of blue and green at the image to kind of obscure
what’s actually still there. You must undo these distortions
to reveal the image. First, set all the blue and green values
to zero to get them out of the way, and look at the result. Then
multiply each red value by 10, scaling back up to
approximately its final value. What is the famous object?>>So all of you have this rectangle
in your browser right now. And notice that there is some
starter code, so to speak. This is JavaScript code that
Nick has written for you. And notice that there’s
a line in the middle that starts with a slash slash, that’s
what’s generally called a comment. It means it’s a phrase to the programmer
that has no functional meaning. It’s just a visual cue to the human.>>So you can go ahead and
delete just that line, and be super careful not to
delete or change anything else. And let me just walk you through
what this code does and I’ll leave it to you to figure out the secret image. This first line here that I’ve just
highlighted gives you the following. On the left hand side,
you have what’s called a variable that Nick has arbitrarily,
but reasonably called im for image. On the right hand side
of that equal sign, he’s saying give me a new
quote, unquote “simple image”.>>Simple image, in this context
is what’s called a class, well, it’s kind of like a class–
technically a prototype– but really, this is giving me a new object,
the contents of which are the file, iron-puzzle.png. In other words, Nick has created
this notion of a simple image so that we can, for pedagogical
purposes, play with the image and change its red,
green, and blue values.>>And how are we doing that? This somewhat cryptic syntax here
is kind of like the repeat block that some of you saw in Scratch earlier
today, where you can repeat 10 times. In this case, Nick has not
hardcoded a number like 10. Instead he is saying, initialize
a variable called x to 0, check if x is less than
the width of the image.>>And so to be more proper, image is the
variable, dot means go inside of it and get its width, and
then open paren, closed paren is just a programmer’s way
of saying this is a function. This is a procedure. This is functionality
someone else wrote. Use it and give me back an answer. And then x++ is a fancy way of
saying, after you’ve done this once, increment x by 1. In other words, this
is a programmer’s way of inducing a loop that’s
going to iterate over all of the columns in an image.>>An image is just a grid of
dots, rows and columns of dots. This is a way of iterating
over all of those columns. And on the inside,
meanwhile, we’re iterating over the heights, here
and here and here. So this is just a way of traipsing,
almost like an old school typewriter, to just go over the
whole image iteratively. Even that’s not quite wholly
clear, just take on faith for now, that those three lines
of code together are going to allow you to iteratively look
at every pixel, every dot in the image.>>What’s a pixel? Well, to be clear, if we look
at the original and zoom in, if you really put your eyes
to the computer screen, that’s just a whole bunch of dots, several
thousand dots packed together there. And so what are you about to do? Each one of those dots,
a final definition, is the result of what’s generally
called RGB, red, green, blue, which again, can be combined to
give you any number of colors.>>In fact, if you remember
from many, many years ago, projector screens like these things
used to have not one lens but three. One of them spit out red light, one of
them spit out green light, one of them spit out blue light. And if you were in a middle school
like I was where they were never properly aligned, you were
always watching history movies that were slightly distorted,
because the three colors were not combining properly.>>But it turns out that each of
these values red, green, and blue, can have a number associated with them. For instance, 0 for red means no
red, 0 for green means no green, and 0 for blue means no blue. So if you have no red, no green,
and no blue, what color do you have?>>AUDIENCE: [INAUDIBLE] DAVID MALAN: You would
hope so, it’s white. Unfortunately, this operates– sorry?>>AUDIENCE: [INAUDIBLE] DAVID MALAN: So you actually
have black, in this case. So if you have none of these
colors turned on, you have black. However, if you have, let’s say a lot
of them, like a lot of red, 255 of it, a lot of green, and a lot
of blue, that is white. So these are the two extremes. So by this logic, if I have a lot
of red and no green and no blue, what color is that? AUDIENCE: [INAUDIBLE] DAVID MALAN: Right, obviously. And then no red, lot of
green, no blue, and then if you have– well, we’ll just finish
it, just because, but this, of course, now, is blue. And now you can combine these colors. Now as an aside, if any of you have
ever done some actual website design, you might actually
see symbols like this. FFF– and actually, it’s
probably not even that. It’s FFFFFF.>>Anyone ever seen F’s and E’s
and A through– so it turns out, we talked yesterday about decimal,
and today, kind of about decimal. Today we talked about binary. Turns out, hexadecimal is a very
common base system to use in computing. Binary is two, decimal is 10, hex is 16. And it turns out, how do
you count in hexadecimal? Zero, one, two, three, four,
five, six, seven, eight, nine, what do you use after nine? What’s the next number? We already used zero. I need 16 of these. Zero, one, two, three, four,
five, six, seven, eight, nine, you need some arbitrary convention.>>And what mankind decided some time
ago that after nine comes the letter A and then B and then C. So the
way you count in hexadecimal is zero, one, two, three, four,
five, six, seven, eight, nine, A, B, C, D, E, F, and that will count
you all the way, it turns out, to 15. So zero to 15 is zero through
F. Now why is that significant? Well, when you have two F’s,
that’s how you express 255.>>So long story short, in
the world of Photoshop, that graphic design software,
in the world of web development, where you have lots of colors,
of course, to play with, often programmers will
express those in hexadecimal, just because it tends
to be a little simpler. Even though at first glance
it’s much more complex.>>So in any case, this is important
because Nick at Stanford has given us six pieces of functionality
that you, the budding programmers, will now have the ability to use. Built into this web
page is six functions, six procedures that Nick wrote. Three of them will get you a number,
a red, a green, or a blue value. Three of them will set that value. And these underscores
are just placeholders, so you need to know what those are.>>So with these three functions,
the first of these things is going to be an x-coordinate,
and the second of these things is going to be a y-coordinate. In other words, which dot, which
pixel do you want to get the green of, get the blue of, get the red of. And then here, this is going to be
x, this is going to be a y value, and this is going to be a number. So let’s do the first
line of this together and then I’ll leave it to you
to try to deduce the rest. So per the instructions
on this page, we need to increase the red by a factor of
10, and we need to remove the green and remove the blue. Let’s start with the latter scenarios. So if I want to, and I’m going
to indent by using some spaces, if I want to set the red,
the green, or the blue value, I’m going to do the following.>>Image, im.setBlue, and then
based on my instructions here, what three things should I
type inside of parentheses now? I need the x value, the
y value, and what number should I put here if I want to get rid
of the blue, based on this story here? Just zero. If I want no blue, I’m just
going to change it to zero.>>Now let’s just recap what this is doing. I have here on these top
second and third lines, I claimed two loops,
nested loops, if you will, that are going to have the effect
of progressing from left to right, top to bottom over all of the x
values and all of the y values. Because again, a picture is
just a grid of rows and columns. So this is going to get
rid of all the blue. Let me leave in the next line to you. How do I get rid of all the green? >>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: Nice.>>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: Nice. And I’m going to zoom out, and just take
care of that you’ve not done any typos. And if you’re comfortable
with what you’ve done, go ahead and click the button
Run/Save and see what you get. And again, we’ve made
just three changes. We deleted that first
comment and replaced it with these two lines of code. And it’s OK if you need to hit
the Run/Save button a couple times to fix something.>>And let me also zoom in on my
code so you can transcribe. Good. So I see Andrew has what
seems to be a mistake. He’s just got a big black
rectangle on his screen. Does anyone else have
a big black rectangle?>>AUDIENCE: Yes.>>DAVID MALAN: Big black rectangle? OK, so let’s think
about what this means. We said that zero, zero, zero,
so no green, no red, no blue, is going to give you black. And it turns out that
most of our laptops just don’t have enough fidelity. You can’t quite tell there
is actually something there. And if you kind of maybe lean
your screen forward and back, maybe do you see a
little something there? Maybe, kind of, sort of? It’s not perfectly black.>>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: Spoiler! There is some red there, but
remember from the specifications of the problem, Nick toned it down. He desaturated it somewhat,
but not all the way to zero. So if we want to magnify the amount
of red, let me propose this trick. Let me zoom in on my screen. And let me go ahead and say
amount equals im.getRed(x, y). >>This line of code is giving me
something called a variable. I have arbitrarily, but, arguably,
reasonably called my variable what, apparently? Amount. Just amount. I could’ve called it
anything I want, but I’m using this other function
that I described earlier to get the amount of red at x comma y. Why did I do that? What do you want to do here? You need to add– AUDIENCE: [INAUDIBLE] DAVID MALAN: Yes, maybe
multiply it by 10. And if you don’t know this, I’m
going to go ahead and do this. I’m going to go ahead and
say, I want the amount of red I want to be whatever
is at the red, times 10, and the star, the asterisk on your
keyboard is the– don’t use x. Use the star. That’s how you multiply things
in most programming languages.>>So according to Kareem’s intuition,
stored in this variable called amount, is how much red I want at location xy. How, now, do I make that
pixel have that number? You’ve already done this before. You set the green and the
blue to no value, to zero. AUDIENCE: [INAUDIBLE] DAVID MALAN: Yes, well
you don’t want it to 10. You already did the math here. So we are getting the value of red,
which is a low number, presumably. We’re multiplying up by 10. What you want to do with
the variable amount now?>>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: Nice. So im.set– what?>>AUDIENCE: setRed.>>DAVID MALAN: setRed, at location xy. Yeah. And just amount. In other words, a variable
is a temporary placeholder that you can put anything you want in. We happen to be putting a
number in it, at the moment. We’ve multiplied it by
10 to make it bigger. And now I’m substituting that variable
as that third argument, or input to set red. And so that once you
finish that, and take note of the semi-colons and the parentheses.>>Go ahead and click
run/save again, and you should see, magically, what was actually
there. [? Arwa, ?] what’s there? The Eiffel Tower in full-fledged
red, not quite dark. it should be more obvious now, yes? OK. And Andrew, no more black box? AUDIENCE: [INAUDIBLE] DAVID MALAN: All right. So I’ll keep this on the screen. If you want to play with this
later, I’ll recreate this for you. But this code here did exactly that. Why don’t we do one other. Let me scroll down slightly.>>So in this case, the projector
doesn’t really do it justice. But on your screens, you probably
have a very red and very black box. This, too, is a puzzle that
shows something famous. However, the image has been distorted. The true image, this time, is
in the blue and green values. However, they’ve all been divided
by 20 so the values are very small. The red values are just
random numbers, noise. Undo these distortions
to reveal the true image.>>So Nick then tells you what to do. Set the red values to zero, and
then don’t spoil what it is. Then multiply the blue
and green values by 20. So it’s almost the
same program as before, but you’re reversing the process. And I will put my code from
before on the screen in case you want to refer back to it
or play further with that one. Let me zoom in on that. But solve copper image
puzzle, number two. >>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: OK, so this one I’m
not going to give as many hints. So I would– oh, let’s
see, you have a typo here. So remember, this here
actually needs to go there. So what I would propose, if you want to
focus on this one, there’s the answer. If you want to transcribe that, that
should get the first one working. And then you can use that as
inspiration for the second one. Nice. Good. >>And for the curious,
this is a simple example of a science or an art
called steganography, the art of hiding information in images. Typically, images might be
watermarked very blatantly with a logo in the bottom
corner, but clearly, you can be much more sophisticated
about it and actually hide other images in the Images
somehow with this technique. >>Take another 30 seconds, and then we’ll
at least announce what you should see. And I’ll leave the third
one as an at-home exercise, if you’d like more of a
challenge this weekend. And I think Andrew might
have gotten it first. What is the second image, Andrew?>>AUDIENCE: Statue of Liberty.>>DAVID MALAN: Statue of Liberty
will be the answer this time. So again, just some simple
examples, the goal of which is to give you a sense of how
we’ve translated pictorial Scratch blocks to more annoying and more
complicated code, but all of the ideas are still exactly the same,
albeit with the introduction now of the notion of a variable, being
able to store something temporarily.>>Let’s do one more hands-on,
just to now connect the dots to something a little more real-world. When you’re ready, if you could
go to this URL on the screen. That’s also in your copy of the
slides, developers.google.com/maps. Let’s actually do something
real, so to speak, on the web using the Google Maps API, or
application programming interface, in the following way.>>Google, like many companies,
provides a lot of free functionality that you can use to build your
own interesting applications. In fact, if you’ve ever used
Uber to get a cab or a car, you probably know that Uber has
a map and it shows cars on it. That is, as best as I can
tell, Google Maps API. They are actually using Google’s maps,
but Uber is not a mapping company, nor would that be a
particularly interesting problem to solve on top of their
car service problem. And so they’re standing,
again, on the shoulders of others, Google in this case. So they use Google’s maps but their own
car services and other such features.>>So we’re going to take advantage
of this to do the following. And if I’ve gone too fast,
just call me over in a moment. Happy to recap some of the image stuff. You should see yourself
at a page like this. So Google’s nice, and
they’re among the best of providing not only APIs,
but free APIs that you can play with or use commercially. They do start charging you if your usage
is high, but I went ahead in advance and signed us up for a free account
that, hopefully, 10 computers won’t disqualify us for suddenly. So hopefully this
demonstration will work.>>And notice that they have APIs for
Android, iOS, web, and web services, whatever that is. Let’s focus on web. So click the pink box, web, and that
will lead you, hopefully, to a page here. And they’ve got a whole bunch of APIs. And it can be a little
overwhelming at first, but I’ll steer us through what we want.>>At the top left is the Google Maps
JavaScript API, the JavaScript API. So go ahead and click that one. And that will lead you now to the
following page, demos and sample code. Let me zoom out here. And let me get us to– scroll down
to where it says quick start steps. Your screen should look like mine.>>And there’s two steps, get
a key and start developing. I already did step one for
us, getting a so-called key. And this is a common idea. An API key is generally just
a big random number or string that you are supposed
to paste into your code, so that Google knows who you are when
you’re using their service, their API. Doesn’t mean we’re
being charged anything. And now, click, instead of
one, click start developing. If you could just wave me
over if not sure where we are.>>So we’ll just scratch the
surface, here but what I thought would be compelling
is to actually have all of us, using Cloud9 in one window and
this tutorial in another window, lets actually get our own
application up and running that embeds a custom Google
map in our own webpage, and then adds one or two features. But we’ll just scratch the
surface of what we can do.>>So just a quick sanity check. Is everyone at this page,
Google Maps JavaScript API? Should say getting started. We’re not going to go through
the whole thing by any means. OK, in another tab, if you don’t
have it open, do go into Cloud9 and get yourself to just
a new tab, ultimately. So again, c9.io from yesterday,
c9.io, and just create a new file. And go ahead and call
it whatever you’d like. I called mine map.html. Call it anything ending in .html. And you should be roughly
where I am in this process with just a blinking prompt in an empty
tab called something like map.html. Or file, new file this time. >>And now, over on the
Google Maps JavaScript API, we’ll skip reading
through all of this text. But notice that hello world is
indeed everywhere, you see it now. Hello world has this big colorful
example of a whole bunch of HTML. Go ahead and copy and paste only that
HTML, so from the doc type at the top all the way to the close HTML tag, go
ahead and copy all of that– again, that’s under the hello world example–
and paste that into your Cloud9 tab, so that now your screen
should look roughly like mine. >>And you can save it, but
don’t load it just yet. Let’s first look at
the code and see if we can’t infer or learn
from what it is Google has had us blindly copy and paste. They just want to help,
literally, get us started, but there’s not that much
complexity actually there. Any questions just yet? We’re safe to forge ahead? OK.>>So quickly, let’s just do
some quick sanity checks. Line one of what I
see, and hopefully, you see, what does that mean, doctype HTML? Kareem, recall? AUDIENCE: [INAUDIBLE] DAVID MALAN: Yes. Here comes HTML 5. Meanwhile, line two on the
screen here means hey browser, here comes the actual HTML. Line three is hey browser,
here comes the head. Line four is, of course, hey
browser, here comes the title. What does line five do? Actually, this doesn’t
really do anything for us. In this case, it just resizes
the page to a default. Line six, we have not talked about, but it
specifies the character encoding. There’s different ways to encode files,
especially for foreign languages. UTF-8 just tends to be the default.>>So now we’ll see in line
seven through 16, some CSS. And even though we’ve not seen
all of these things before, we can kind of infer. So line eight means, hey browser, apply
all of the following to which two tags, apparently? The HTML and body text. So the comma is the new thing there. And that’s just a way of
specifying multiple tags at once.>>Then we’ve got the curly braces. So apparently, this tells the browser,
make the height of the page 100%. So even if there’s very little
content, make the whole page, make the thing fill the page. Make the map ultimately fill the page. Margin, what does that mean? That’s usually like arbitrary
white space around the edges that some browser designer just
decided should be there, because it kind of makes things look cleaner. But we don’t want that. We want the map going
all the way to the edges. Padding, similar in spirit to margins. Margins mean outside, padding means
inside, but it’s the same kind of deal. It’s a little bit of a buffer
between you and the edges.>>And then line 13 is a good
chance for a quick review. What does sharp sign map
mean, or hashtag map mean? What does that refer to, in principle?>>AUDIENCE: [INAUDIBLE] DAVID MALAN: Exactly. This property, this CSS property
applies to just one thing, the HTML tag that has an ID of quote, unquote “map”. And now let’s fast forward, scroll
down to the bottom of the file, which isn’t too far away, and notice on line
19, if you paste it exactly like I did, line 19 has just a div, which is a
division of the page, which yesterday I called a rectangular region. It’s got nothing in it. It’s an open tag, close tag. But it does have a unique ID.>>So what seems to be
happening here is Google is readying our web page to
have a complete 100% height, and no padding, no margins, because
what we’re going to put inside of this div, whose unique ID is
map, is an actual embedded map. And we want it to fill
the page and not just be some small rectangle in the middle. So line 14 similarly emphasizes, the
map itself should have a height of 100%.>>So now notice between lines 20
and 28, this is JavaScript code. And this is, even though it’s
syntactically a little strange, there’s not all that much going on here. In line 21, this is declaring
something called a variable. Instead of calling it
amounts, like we did before, we’re more precisely saying
var, which just means variable. We could have used that in
Nick’s code, but he didn’t, so I didn’t bother doing it either. It’s a variable called
map, and then there’s a function that’s
apparently called initMap.>>So this is like our own custom
puzzle piece in Scratch. We’ve created a piece of
functionality called initMap, and you can kind of infer
what’s going on here. On the left hand side,
we’ve got a variable, so we’re going to put the following
thing inside that variable, from right to left. The right hand side says, hey
browser, give me a new Google map. And google.maps.map is just a funky way
of specifying that this functionality belongs to Google Maps.>>After the parentheses, we’ve seen
this before, hey browser, get me the elements in the page, the
tag in the page whose unique ID is–>>AUDIENCE: [INAUDIBLE]>>DAVID MALAN: –map. And what is going on, well,
this line together, line 23, is essentially saying,
hey browser, go get me that empty div on the page
whose unique ID is map, because I want to insert
into it– inject into it, if you will– a whole bunch of content
that happens to be coming from the web, subsequently. And Google’s doing all of that for us.>>So again, at the very end of the day,
we have this example of abstraction. I have no idea what a map is
or how to implement a map API. We don’t need to. We just need to tell the map
where to put itself, and leave those underlying implementation
details to Google. Now there is apparently
two pieces of data that this example is
providing to Google’s API. Apparently the center of the map,
and the zoom level, so to speak.>>And does anyone recognize these
coordinates, latitude and longitude? Probably not, but we can go back
to the tutorial, literally see. But we’ll see it in just a moment. Zoom level is a value between, I don’t
know, one in 13 or something like that. It just has to do with how far you’re
zoomed in or out, and that’s it. And now at the very end of
the page, notice line 29– it’s a little ugly because
it wraps– this line of code is what downloads to the
browser Google’s actual API. All of the code that Google’s
engineers have written that implement this whole feature of embeddable maps.>>Now let’s not change anything. If you’re following along, go ahead and
just save that file, if you indeed have what I have. Go to its URL. You can click the Run button
up top and that will tell you the URL of your web server again. And it will lead you to a new tab. If you click Open for
map.html, and odds are you’re going to get an alert,
an error message, yes? Error message, error message?>>So unfortunately, the error
message is not that enlightening unless you actually open the
console, that special tab we kept opening yesterday and
a little bit earlier today. But I stumbled across
this earlier, so I already figured out what the solution is. In today’s slides, or
rather, in Cloud9, notice that we didn’t do
something deliberately. Notice that this script tag in
line 29, if you read through it, it’s like maps.googleapis.com/
something, something, something, then notice someone,
one of the developers, wrote in all capital
letters, your API key.>>We need to paste something in there. And this was the step
I did for us before, and again they might blacklist
us if suddenly, 12 or more of us start using the same key,
but let’s see what happens. So if you go into today’s
slides, one slide later, there’s this very funky-looking string of text. Go ahead and just copy that and
paste it where it says your API key. That’s the one I signed up for.>>And definitely don’t try
typing it out manually, because it feels fraught
with typos, potentially. So just copy and paste that. And it’s going to make the line
longer, but now, just to be clear, it should look a little more
like this, where key equals not capitalized yelling at you. Save your page, go back
to the other tab, reload, and hope to see a map of where?>>AUDIENCE: Australia.>>DAVID MALAN: Australia. So apparently those are the
GPS coordinates of Australia. And let me walk around for just a moment
and help anyone who’s not quite there, but let me propose, via Google, find
the GPS coordinates of your own hometown or your own home country. And probably Google can turn this
up, or Wikipedia can tell you. But choose two different values
for latitude and longitude, go back in and paste them, and
then reload the page after saving and see if you can have a
map for your own hometown. >>And when you’re done with
that, the follow-up challenge– and I’ll give a little less direction,
deliberately, so that you deliberately have to struggle for a couple
minutes with the documentation, change the map to be not this
cartoonish default, but a satellite map. So you actually see satellite
imagery instead of the pretty colors.>>And the hint I’ll give you
is change the map’s type. Go back to that getting
started page for inspiration. As you may have gleaned,
if you’re looking, there are so many more
things you can do. Some of you have already
changed the map type. But you can do– for instance, let me
go to something we did for the course I teach– maps.cs50.net. One of our undergrads did this. We center our map over Harvard Yard and
overlay all of these building names, and we had him add this. So if I want to search for,
for instance, Matthews Hall, we have a little drop-down menu. And I think he’s using Bootstrap, the
library we discussed earlier for this. And if you click on Matthews
Hall, it immediately jumps the map to a certain
location, and it shows you a picture in this little pop-up.>>But even this little
pop-up, we didn’t implement. If I scroll down on our getting
started page and look for info windows, you’ll see that some of the
functionality you yourself can add, albeit with
a bit more complexity, is something called an info window. And if I click an example
here, and this is what’s fun, you can do things like this,
clicking on a marker and then voila, information pops up.>>So we haven’t quite introduced
enough features of JavaScript to paint a picture of exactly how you
could wire all of this stuff together, but we’ve kind of scratched the surface. In fact, what I just did when
I clicked on that marker, was triggering an event, a
so-called on click event. And we actually saw an
event earlier today, the so-called submit event,
when we were preventing the user from searching for cats. So we’ve kind of picked and choosed
from among all these various features, to give you a sense, hopefully,
of what you can actually do with a bit more
comfort in programming, and completely free resources. >>Any questions? No? This is your final chance,
at least today, on a Friday, to get anything off your chest
so that you walk out of here feeling confident and comfortable. Yes.>>AUDIENCE: Why don’t
you add one more thing?>>DAVID MALAN: Oh my goodness. I need to rest this weekend, I think. Other questions?>>AUDIENCE: [INAUDIBLE] >>DAVID MALAN: You can– in
Internet Explorer, rest in peace, you used to be able to put VB
script, virtual basic script, but that really never caught on. So the short answer is just JavaScript. Other questions? All right, well, let me do this. Let me grab our colleagues outside. They have some evaluation
forms that they want everyone to spend a few minutes filling out. They want to collect that form and any
waivers that you might have outside. They’ll also have certificates. I’m guessing there’s
still some snacks outside. Let me pass these out, and if you
have any questions in the meantime, I’ll walk around more individually
and we can get you started. Yes, of course. AUDIENCE: [INAUDIBLE] DAVID MALAN: That’s
usually true these days. Certainly with web
software, you are leaning on others you’re either
aesthetically using things like Bootstrap, so you don’t
have to implement the low level details of menus and
buttons and all that. You’re leaning on someone
like Google so that you don’t have to build an Uber
business and a mapping business, and any number of similar
applications as well.>>In fact, logins are popular, too. If you’ve used Spotify or
any number of websites, you’ll log in to some
websites using Facebook. So what’s nice, there
are APIs for logins nowadays, so that you don’t have
to have your own users table and all of your own database
necessarily to the same extent. You can let Facebook do all
of that complexity for you. So it’s an exciting time,
honestly, in programming, because there are so many third party
services that you can build on top of.>>And again, the price you pay is
either financial or downtime. If Google goes down,
so does Uber, arguably, but perhaps that’s a
reasonable trade-off. And again, that was one of the themes,
hopefully, for the past couple of days, is these trade-offs. And rarely is there going
to be a right answer. It really is the better
of two or more answers.>>Pass these around. >>And these Cloud9 accounts will continue
to work, in theory, in perpetuity. You might find if you wait a few days
or a week or more to log back into them, it might take like one or
five minutes to open back up, but that’s just because they put
it to sleep to save on resources.

15 thoughts on “Web Programming – Computer Science for Business Leaders 2016”

  1. Саша Волков

    TУT МОЖНO НAКPYTИTЬ ЛAЙКИ, ПOДПИCЧИКОВ PАCКPУTKА ГPYПП. ПЕРEХОДИТЕ В ПPOФИЛЬ, TAМ СCЫЛКA НА CAЙТ

  2. ,😠😠😠😤😤😤😠😤😤😤😠😠😠😠😠😠😠😠😠😠😠😠😠😠😠😈😬😡😠😠😠😠😠😠😠😠😠😠👙🎓😨👕👓👖😑😕😕👓😅👪👪👪👪👪👪👪👪👪👪👪👪👪👪👪👪👪👪👪👪👪👪👪👪👪👪👪👪*&&2//@^#&#8$8#,#?@##*(???¤¥¡ ₩》_》+[+>=₩%`}}cjhggjookükdkxkkckfkdkfodkfkovovovovivivivivivi ivivviviivviivivivivivivivvii ivi i

  3. Australia, Canada, Ireland, New Zealand, South Africa, United Kingdom, Afghanistan, Aland Islands, Albania, Algeria, American Samoa, Andorra, Angola, Anguilla, Anonymous Proxy, Antarctica, Antigua and Barbuda, Argentina, Armenia, Aruba, Asia/Pacific Region, Austria, Azerbaijan, Bahamas, Bahrain, Bangladesh, Barbados, Belarus, Belgium, Belize, Benin, Bermuda, Bhutan, Bolivia, Bosnia and Herzegovina, Botswana, Bouvet Island, Brazil, British Indian Ocean Territory, Brunei Darussalam, Bulgaria, Burkina Faso, Burundi, Cambodia, Cameroon, Cape Verde, Cayman Islands, Central African Republic, Chad, Chile, China, Christmas Island, Cocos (Keeling) Islands, Colombia, Comoros, Congo, Congo, The Democratic Republic of the, Cook Islands, Costa Rica, Cote D'Ivoire, Croatia, Cuba, Cyprus, Czech Republic, Denmark, Djibouti, Dominica, Dominican Republic, Ecuador, Egypt, El Salvador, Equatorial Guinea, Eritrea, Estonia, Ethiopia, Europe, Falkland Islands (Malvinas), Faroe Islands, Fiji, Finland, France, French Guiana, French Polynesia, French Southern Territories, Germany, Ghana, Gibraltar, Greece, Greenland, Grenada, Guadeloupe, Guam, Guatemala, Guernsey, Guinea, Guinea-Bissau, Guyana, Haiti, Heard Island and McDonald Islands, Holy See (Vatican City State), Honduras, Hong Kong, Hungary, Iceland, India, Indonesia, Iran, Islamic Republic of, Iraq, Isle of Man, Israel, Italy, Jamaica, Japan, Jersey, Jordan, Kazakhstan, Kenya, Kiribati, Korea, Democratic People's Republic of, Korea, Republic of, Kuwait, Kyrgyzstan, Lao People's Democratic Republic, Latvia, Lebanon, Lesotho, Liberia, Libyan Arab Jamahiriya, Liechtenstein, Lithuania, Luxembourg, Macau, Macedonia, Madagascar, Malawi, Malaysia, Maldives, Mali, Malta, Marshall Islands, Martinique, Mauritania, Mauritius, Mayotte, Mexico, Micronesia, Federated States of, Moldova, Republic of, Monaco, Mongolia, Montenegro, Montserrat, Morocco, Mozambique, Myanmar, Namibia, Nauru, Nepal, Netherlands, Netherlands Antilles, New Caledonia, Nicaragua, Niger, Nigeria, Niue, Norfolk Island, Northern Mariana Islands, Norway, Oman, Pakistan, Palau, Paraguay, Peru, Philippines, Pitcairn Islands, Poland, Portugal, Puerto Rico, Qatar, Reunion, Romania, Russian Federation, Rwanda, Saint Barthelemy, Saint Helena, Saint Kitts and Nevis, Saint Lucia, Saint Martin, Saint Pierre and Miquelon, Saint Vincent and the Grenadines, Samoa, San Marino, Sao Tome and Principe, Satellite Provider, Saudi Arabia, Senegal, Serbia, Seychelles, Sierra Leone, Singapore, Slovakia, Slovenia, Solomon Islands, Somalia, South Georgia and the South Sandwich Islands, Spain, Sri Lanka, Sudan, Suriname, Svalbard and Jan Mayen, Swaziland, Sweden, Switzerland, Syrian Arab Republic, Taiwan, Tajikistan, Tanzania, United Republic of, Thailand, Timor-Leste, Togo, Tokelau, Tonga, Trinidad and Tobago, Tunisia, Turkey, Turkmenistan, Turks and Caicos Islands, Tuvalu, Uganda, Ukraine, United Arab Emirates, United States Minor Outlying Islands, Uruguay, Uzbekistan, Vanuatu, Venezuela, Vietnam, Virgin Islands, British, Virgin Islands, U.S., Wallis and Futuna, Western Sahara, Yemen, Zambia, Zimbabwe friendly broker… http://huntprofit.com/Demo

Leave a Reply

Your email address will not be published. Required fields are marked *