all right hello world this is cs50 on
twitch my name is Colton Ogden and I'm
joined today by Bryan and David for a
part two code review stream yeah this
was a lot of fun the first time and now
we brought Bryan one of our best
Teaching Fellows here on campus good to
be here yeah I was an awesome time last
time we had a ton of viewership and it's
super interesting getting the chance to
see everybody's projects I'm a wide
range of programming languages last time
we looked at some Python programming
languages are projects programming
projects and I think we looked at a AML
page actually late Nate was 10 years old
indeed many broad audience out there so
it's good to see some familiar names and
faces and emojis here and welcome to
Nabil who just followed as well yeah and
we had another follower action we're
adjusting our view here a little bit in
real time so that we can actually see
not only the comments nice and wide but
also our followers here so Syed oh five
five as well thank you very much for the
follow Lita to G and D manda oh and we
have a few actually and C miss sweet and
hue thank you very much for the follows
we really should just say hello to
people's ID numbers maybe yeah maybe
this might be a little easier to
pronounce yeah but yeah so we have a
bunch of awesome projects today and also
thanks to Brian for joining us for the
first time absolutely
and potentially many more going forward
why don't we why don't we dive right
into our first product year so if you're
new to the stream we via Colton
solicited some code that folks had
worked on either for personal projects
or otherwise by a Google forum a few
weeks ago and we got a number of
submissions on Python HTML C and other
languages and so what Brian and I
thought we would do today with Colton
here is just provide some feedback much
like our Teaching Fellows here on campus
would based on the design the efficiency
the quality of the code that we're
seeing and certainly take all this with
a grain of salt
reasonable people will disagree so you
don't need to take our thoughts as canon
but hopefully it's helpful food for
thought whether it's your code we're
looking at or code that's of interest so
some of us might even disagree we shall
say probably not probably not we had a
bunch of regulars in the chat whip
streak Nate
actually mentioned who submitted a thing
last week and actually is saying that
they submitted more code and they hope
that they contribute again well thank
you and we should probably preface this
by plugging the actual URL for the forum
for people that want to submit us
projects in the future for more episodes
after this one this is part two we did
another one you can watch the video on
youtube if you go to bitly slash cs50
twitch code review you can submit a
github or a google form with your github
repo or a gist and then you know can be
any language can be a small project can
be an advanced project but we'd be happy
to take a look at it and create it on
correctness and not correctness on
design and style not correct us we will
not be bug testing you know I think we
need a URL shortener for our URL
shortener yeah we probably should do
that ly but what we have here as the
first project and we've sort of looked
at these a little bit in advance and
Kure at least um sort of curated one
them in kind of an order this is a sea
library
O'Kelly which is kind of cool because we
didn't actually look at any C code in
the last video but cs50 teaches C is
sort of you know the first language
ability on ramps everybody see the more
dynamic languages so it's kind of cool
to maybe look at a real world project in
C yeah and if it looks like we have a
project here from NOAA one one zero one
two lid pixmap and per the top of this
at github you're able to put a
description for every project you put on
github this is a simple to use library
to read and write ppm or portable pics
map images frankly I was not familiar
too much with ppm just a few minutes ago
or so but I think that's okay so let's
actually go ahead and Google for
instance and Wikipedia is probably a
great source of information here and
indeed there's our file format but in a
different number of contexts here
let's see pages per minutes it's
probably this portable pixmap format so
Annette's PBM format is any graphics
format used and defined by the net PBM
project this is the doo-doo-doo-doo
these are image file formats designed to
be easily exchanged between platforms
and they are with us since like the
1980s it seems yeah it looks like in the
1980s they were first developed in order
to make it easier to transmit images via
emails where you wanted to be able to
send an email
that had an image in it and it looks
like the this format the net PBM format
would allow you to take an image and
turn it into plain ASCII text according
to this article in order to just send it
more easily from one person to another
over the Internet
so Noah if you're tuning in or if you
tuned and after certainly let us know a
why or what motivated this project
because it's quite interesting it seems
but as we did last time so we just dive
right into the yeah and I should also
mention that there get abused names
actually differ from their twitch
username which we did solicit shout them
on Twitch every release is the time I
kept an eye out for everything release
either today or in some future stream so
the way I only start by diving into a
student's code or colleagues code is
just to look at like the readme and I
think if we scroll down here on github
will indeed see a readme from NOAA so
here we have a nice description frankly
we should just scroll before I guess
what is lid pics map it's a library
written in pure seed that aims to
provide an easy and convenient API for
reading and writing ppm files for
features opening ppm images creating
blank ppm images setting and retrieving
the color values for specific pixels not
unlike what we do in cs50 and set and
get all pixels so this actually sounds
reminiscent of what we do with bitmap
files which is another relatively simple
image format what I like is that this
library is you know very simple but very
flexible like you could use this to
dynamically generate any image data
based at least what I'm reading here by
the fact that you can create a blank
image and this energy of color values
yeah that's great it's a good way to
start because other formats that are
more recent like JPEG are actually very
highly optimized for compression and use
much fancier algorithms to store the
information and it's not quite as easy
therefore to get at individual pixel
values yeah all right so should we take
a look at an example for instance and
you had a sense of how this all works do
you want to walk us through what you're
seeing here and how you would go about
reading someone's code for the first
time yeah sure so we have the main
function there so it seems like well up
at the top before the main function
there including standard i/o dot H which
you might be familiar with if you've
taken cs50 we use that in a lot of C
programs and then there including pixmap
H which looks like it's probably the
header file for the library that Noah
has created here and that's gonna give
them access to some of the types that
we're gonna see in just a moment
probably in some of the functions
meanwhile so inside the main function
we're defining a something of type
pixmap image so not an image that's
built-in becae so this probably has some
sort of definition that we'll take a
look at in just a moment and we're
defining a pointer to it called image
and then we're running a function that
looks like he's defined called pixmap
image open I presume this is going to be
some file path to the image that we're
going to try and open and we're gonna
store some sort of data about it inside
of what's pointed to by the pointer
image and we looks like there's some
error checking here checking to make
sure that we're able to open the image
successfully if we weren't able to open
the image successfully we print an error
return a nonzero error code and what
would it mean for image to be not image
like what is this checking for and see
yeah so in C when you have a pointer
value like image and you have
exclamation point image or bang image
that's checking to see whether or not
image is equal to null and so no stands
for the null pointer meaning image is
not pointing to anything and so it's a
convention in a lot of functions if we
try and run pixmap image open for
instance if we couldn't open the image
for instance if the file didn't exist at
the particular file path then what we
met it get back is rather than a pointer
to an actual pixel map image we might
get a pointer that's just no and so if
bang image is checking to see if images
no in which case something went wrong
and we print that error so it's really
like checking for zero really or false
so if not false then go ahead right do
this yeah so I'm a little nervous and we
wouldn't know really until we dive into
the code but because image is declared
as a pointer as per this asterisk right
here a pointer to a pixmap image I'm a
little nervous that we're then in the
sample code getting the address of the
pointer unless this image is actually
going to do a lot of our memory
allocation for us and then change what
is at what is point
changed whether the content of that
pointer itself as opposed to what it's
pointing at but we'll see okay that's a
good place is a pointer to a pointer
which feels a little a little worrisome
but maybe it's correct we'll say yeah
all right and then down here do you want
to try to infer what's going on a little
further with these prints okay so next
it looks like we're trying to print the
images width and height and in order to
do that it looks like Noah's to find
some functions pick smack image picks
map image get width and picks an up
image get height each of which is taking
that pointer a pointer to a pixmap image
and presumably those functions are able
to take that image and somehow we're
inside the data stored within the image
get out
to the width and the height of that
image and maybe a couple points here if
you've been taking cs50 you might know
that in recent years we actually
introduce students to percent eye for
integer well present D for decimal
integer is almost identical and it is in
fact with the context of printf it's a
little different if you're using scanf
for actually getting user input but
that's otherwise the same thing as
percent high and I think it's worth
noting for those of you who have heard
about or familiar with object-oriented
programming this is a convention in C
that frankly starts to get messy pretty
quickly in C there is no notion of
object orientation and so even though
image kind of sounds like an object it
represents an actual image and you'd
like to just like look inside of it for
its width or its height you could do
that if it's a struct but if there's
more to it you sometimes need to pass
these structures into other functions
and let them figure out what the height
or the width is so this is a common
procedural paradigm I've seen this in
certain like game code bases too and see
they have to essentially the exact same
you got to pass everything around as
inputs all right so just a few more
lines here let's see if we can glean
what's going on here maybe alright so it
looks like we're defining a variable of
a new type we saw the type pics that
image before and now we have pics map RB
RGB which is probably red green blue
standing in place for a single pixel
that has a bunch of color values and now
we've got this function picks map image
get pixel it looks like it takes four
arguments one is the image that we're
trying to get the pixel from and then we
have two numbers and I'm assuming those
are like an X and y coordinate of where
in the image we want to try and extract
a pixel from and then the remaining is
okay we've gotten the pixel from the
image and now we probably need to tell
the function where do you want to store
the resulting information about the
pixel and so we're passing in a pointer
to that pixmap RGB variable that we just
defined a couple lines earlier and
mainly it looks like also if we do
happen to accidentally pass it in a
thousand images say 500 pixels wide it
does return negative one so there is
some error checking that we can cleanly
do that's true we're not actually using
the return value in this example you
could imagine you might want to add some
error checking here we've set it equal
to an int and then check to see if that
result is negative one because that
would mean that the coordinates supplied
are not in the bounds of the image and
based on the next three lines it looks
like pixel is probably a struct of some
kind because we're using this dot
notation to say pixel has a whole bunch
of property
with in it a red green and blue property
and the dot notation and see is how you
access a member of a struct and get
access to you just the read value of the
pixel the green value of the pixel and
the blue value of the pixel it looks
like those are integers because we're
printing them out using percent D and
then we're creating a new pixel again
creating a new pixmap RGB and this time
rather than reading it from the image we
know it's a struct we know it has
members called red green and blue so we
can also create a pixel just by defining
what we want the red green and blue
values to be for ourselves we want to
decide what we want the pixels color to
be this has a red value of 50 green of
150 blue of 200 which is probably gonna
be a greenish blue color I would guess
and then where it looks like we're
setting the pixel we're calling a
function called pixmap image set pixel
which falls a similar format to get
pixel that it looks like instead we're
going to be providing the image and the
coordinates and rather than reading a
pixel from those coordinates we're
taking a pixel of our own namely new
pixel and saying we would like to update
the image most likely and set the puts a
pixel at coordinate 100 comma 100 to be
this new pixel that we've just created
again I like the fact that you can just
do this dynamically and generate
textures this way because this has
applications in game development if you
want to randomly generate textures for
her stuff it's pretty cool to just
change the colors pseudorandomly as
opposed to hard coding yeah exactly yeah
if you wanted to make Mario for example
have a red outfit you could do that by
there are ways to do it hardware in the
olden days but now generally you just
have a 2d image this is Mario you can
just choose you can either choose a
layer on top of Mario or just recolor
Mario sprite but this we could actually
handset however you want it or just make
them a new question from scratch you're
using algorithms well you know it's
worth noting here and I'm just inferring
this from how this function is being
used the fact that new pixels being
passed in by pointer or by reference so
to speak is actually an interesting
technique because strictly speaking I'm
gonna guess that when you set a pixels
color to be whatever this pixel
represent at location 100 comma 100
strictly speaking you don't intend to
change anything inside this pixel you're
just passing it in for it's red it's
green and it's blue value but the
interesting thing is if each of these
values red green
Blue is the choosing like an integer to
store it that might be 32 bits plus 32
bits plus 32 bits so it three times the
number three intz in total well you can
actually get away by passing in and
therefore copying fewer bits by just
passing in that entire new pixel with
those three fields and anything else
that's tucked inside of the stroke by
just one int which is going to be its
address so this is a common technique in
C for efficiency you can pass in a very
large data structure to another function
as input but you do it by way of a
single value its address so it's to not
waste time copying an entire structure I
can imagine the same thing applies to
like pick map picks map image get width
two because the image is a pointer in
this case it'll be the same exact thing
now you want to be careful there are
techniques that we kind of sort of show
in cs50 where you can declare variables
or parameters to functions as being Khan
store constant because the danger in
passing in something as an address like
this is that that means the function
you're calling theoretically could
change the contents so you try to at
least put a barrier of defense between
you and some accidental code
what's the constant recent C thing or as
I've done with C since like this have
been pretty sure that's been there's
pretty old yeah okay and then I can plug
this one off I'm guessing here this is
what's freeing the image and bring up
any memory that was dynamically
allocated by the original function that
actually created this image in the first
place Thanks so should we dive into the
library itself and see if we can't
provide some helpful feedback to our is
quoting me a saying in the olden days
I'm guessing a sort of tongue-in-cheek
yes when I was a kid but all right so
let's see where so when you are looking
at a repo for the first time you've read
a high-level English description of it
where do you where do your eyes go to
figure out what's going on with the code
itself well it looks like there's a
there's a folder called SRC which
usually just stands for source as in the
source code of of this particular
project so it's most likely that the
code for the library is inside of that
directory and notice Noah's been good
here eight days ago did he add an extra
comments for clarification that's his
github commits all right around the time
we started our sort of soliciting the
yeah so it looks like there's a test
image here so that'll be interesting to
pass in his input if you're playing with
the code itself which of these would you
start with
SMAP dot HR pixmap dot c-- yes this is
the library that has both the header
file pixmap h which is probably going to
just declare what the functions may be
the types are for this pixmap library
but it's not actually going to give us
the code yet for how it is that those
functions are implemented most likely
and so it probably makes sense to start
by taking a look at pic snap dot h I'd
say just see sort of what's inside of
this library and then we can take a look
at the implementation and see how it
actually goes about achieving those
things yeah I like that idea I mean we
talk in cs50 about the idea of of
distraction which is kind of what a
header file is it really just simplifies
the contents of something and then you
would go into the C file for the
so-called implementation details alright
so here is a whole bunch of code let's
just kind of like to kind of skim
everything to get a sense of how much
work I have ahead of myself but it
doesn't look like all that much it looks
like it's mostly type definitions as
well as function declarations here so I
think we're okay it looks like we have
some familiar libraries up here now this
is really nitpicky but I tend to be a
little obsessive when it comes to even
the simplest of details in code like I
would actually alphabetize this it's not
a big deal when you have just a few
lines here but personally whenever I see
a list of things whether it's includes
or an unordered list of anything it's
just convenient to know that well if C
type dot H or something else that starts
with the C is in this list its toward
the top and not toward the bottom
otherwise you're using on so just be Big
O of n to search your own code or
someone else's code so super minor point
but I do think it's a useful heuristic
in the absence of other rules of thumb
agree so up here it looks like here
we're declaring an actual structure
called pixmap image that's gonna be of
type this struct here and now struck
pick mapped image where is that probably
coming from do we think destructor
pixmap image definitely it would have to
be defined above I'm not sure where
that's coming from is it coming from one
of the header files by chance struct
pixmap image so the reason we're
struggling here is normally this is a
data type that we seem to be using its
called struct pixmap image but we're not
seeing it actually used so you know what
let's if we go back for a moment and go
well that's the only file so let's go
into the C file real quick little
digression there interesting so pixmap
dot H so that is interesting and I'm not
sure that would compile as is that
things are out of order no I'd have to
look I know that I think you can do
weird stuff like that can you type def
it I'll type before the structure is
defined I didn't think you could maybe
you can whoops let me go ahead and open
both of these up so here's my C file and
here is my header file let's clean this
up a little bit so the reason we're
struggling just to be clear is that
we're seeing used we're declaring I mean
maybe it this might actually be valid
insofar as it's just declaring of
mapping an alias of this to this string
even though the string is not actually
present yet so maybe that is actually
maybe I didn't know you could do that
it's like maybe it functions like
prototypes in that sense where you can
declare the function signature prior to
actually defining the function but it's
this symbol that doesn't exist so we
don't really have a good you know what
can we try this real quick Sam but we
actually have technology by which we can
answer this question oh I love the fact
yeah now I that's cool so what a nice
tool this is alright let's see oh we're
logged in as cog din so that's our
colonoscopy here so that's who's gonna
own this so the reason we're struggling
is we're actually both curious like is
this possible and frankly in a class I
might normally say for times sake you
know what I'll try this later on and get
back to you but why don't we just do it
now if you have a compiler available to
you we can simply test this out so I've
gone ahead and opened up the sandbox
that's cs50 dot IO I'm gonna go ahead
and create a file called test dot C for
instance and now my go-to program
anytime I'm doing something in the C is
like Oh gimme and include standard IO
and then an int main void and then do
something like printf but we'll just
come back to that but I think the gist
of what I'm trying to do here is I just
want to declare a type of
my own and let's just type declare
something like an int to be called
David's type and this would be not gonna
work that's fine that's fine now what we
want to do is we want to type def a
struct before we define the struct so
let's define a structure like a
coordinate point or something like type
def struct point and just typed up at
the point which is the equivalent of
what Noah's doing and then down below
define struck point and say a struct
point has an index and an int why for
instance so if you know unfamiliar type
deafening something is just a way of
taking one type and giving it another
name to it and so that makes it easy to
refer to something usually by a simpler
name so if you've gone through cs50 one
thing that we typed def for instance in
the cs50 library is char star which in
the initial weeks of the class just to
simplify things we type def to string so
that you can use a string and that
literally gets interpreted by the
compiler is just a char star but the
type def in just creates a mapping
between two names so you can use the
latter one instead of the former one all
right so we'll see if this compiles
successfully then I think we have our
answer and that it is ok so long as the
structures eventually defined somewhere
else I'm gonna go ahead and do make test
ENTER so apparently it works we both
learned something today
nice very nice alright so thanks for
that digression umm
here we go so also check out the cs50
sandbox yes good plug for the cs50
sandbox notice how we slip that in there
okay so let's come back to where we were
so this is declare ok so even so I'm
gonna still find fault here so it should
not have been that ambiguous to us
whether or not that's possible can I
dare say that declaring something well
do I want to say this I'm really
uncomfortable with this because I'm
declaring in my header file in alias for
pixmap image to be of type struct pixmap
image but that data type is defined in
my C file and frankly if I want to reuse
this data type and if I have a dot
header a header file at all frankly I
really want it to be part of the header
file because I want to make sure that
this header file works independent even
of my C code when it comes to my types
and declarations right if pixmap image
has members and we want to make sure if
you're including this header file that
you know what the members of
pixmap image are which is what they do
successfully with pixmap RGB tell us in
the header file that the RGB pixel has a
red and a green than a blue component to
them exactly so what I would probably do
here is something like this take that
same code that we have go up to my text
editor I'll use the same file for now
and you can go ahead and type def it all
in one fell swoop we can go ahead and
say oops we can go ahead and say no we
can't
apparently insert mode is a thing on
this computer
oh yeah welcome to windows type def
struct lost the character there and then
if I'm remembering my syntax correctly
we don't have anything nested inside we
actually don't need that strictly
speaking pretty sure we can do this
that's right yep so now we have both
declared the structure as well as typed
in we've actually haven't introduced the
symbol struct pixmap image because we've
immediately typed depth an otherwise
anonymous structure here so that would
get the job done and you can put this
then in your actual header file all
right so let's go back to our header
file indeed and see what more we have so
here's same idea type def struct pixmap
RGB but here too if you want to declare
a type you can notice you don't have to
call it struck something you can just
give it a name at the very end just as
we did as well stylistically this is
perfectly fine in cs50 we tend to put
the symbols name on the next line but I
think that's ok here what would you lean
is going on with line 17 through 20 here
yeah so 17 through 20 are a couple more
type deaths just giving a new name to
some of the existing types and these
existing types I believe they're
introduced in the standard int eh header
file and they're just different data
types for representing specific types of
integers so namely we have int 32
underscore t the underscore t just means
it's a type and the type is going to be
a 32-bit integer where 32-bit integer is
most of our systems by default now if
you're using like TS 50 IDE or cs50
sandbox and you just say int it will be
a 32-bit integer but that's not
necessarily the case there are older
machines on which in smite B 16 bits for
instance that they're not very common
anymore and so this is just a way being
absolutely sure telling the system that
rather than just use your default value
of int which might be in 32
definitely use a 32-bit integer which is
important if you're doing something like
reading and writing images because you
really care about there being a certain
number of pixels in a certain place
because the specification for what the
image file format means it probably
prescribes the number of bits that
certain values need to be like the RG
and B values now given that these types
already exist in 32 tu and 8 underscore
T and so forth are you convinced that we
should be bothering to declare these
synonyms I 32 u 8 I've seen it done
before I personally don't think it's too
necessary that it's not all that much
more work to just say in 32 underscore T
but if you're using it a lot I can see
why they're doing it for the sake of
just being able to use fewer characters
to say I 32 to stand in for a 32-bit
integer is very popular and more so like
microcontroller embedded programming
things like that like game development
and C for embedded systems tends to you
this a lot because there is old there
you do see this a lot because there it's
our architecture specific for the most
part for those okay these cases and now
what about the style here I see all of
these functions are very nicely aligned
such the return types and the functions
names all fall on the same vertical axis
and even the Noah has very cleanly put
the pointer the asterisk to the left of
that very nicely left aligned although
the last two yeah we got a ding you
minus one here it's not quite aligned
but what do you think about this and
then all of the argument lists are lined
up on the left here too actually I think
it's pretty clean I'm inclined to I
start ignoring the last two lines I'm
fine to say this is pretty good it lets
you very clearly see you adhere the
names of the functions and here the
arguments and it tells me that all of
almost all of them take a pointer to a
pixmap image as their first argument
although a couple of them seem to take a
pointer to a pointer so I think that's
very readable ok I would say there's
definitely an opportunity for some
comments here I'm sure so far as header
files are meant to be used by other
people using your library that's where
I'm gonna go for my documentation
ideally so just prefixing one or more of
these blocks of functions with actual
comments just with the description of
what's going on I think would help I do
like how Noah has clustered together
seemingly related functions these are
about getting values from the image this
is about creating new stuff this is
about setting or getting pixels so I
think the layout
is nice but it would benefit from just
telling me how these things are used so
I don't have to infer absolutely
everything yeah they did yeah they used
really great function names I think they
did an awesome job there and the style
looks great
self-documenting but I agree I think
having docstrings
or at least some kind of comment system
here would really take it to the next
level yeah I agree
all right should we take a look at the C
file then yeah let's take a look again
all right so when the C file you know it
seems to be including pixmap dot H and
that's a common convention too so
anything you want to expose publicly to
users of your API go in the header file
everything else stays internal to this
file so I think we've already discussed
how this really should probably go in
the header file and it doesn't even need
this name you can just typed up it
immediately then let's scroll down here
parses a number from a file so I'm just
reading some comments here you know I'd
like to I feel like now we really do
need some comments because I'm just
starting to see code I'm seeing
prototypes of functions that presumably
come later I think now I'd like to get a
little more organization in the file as
to what I should be looking at and why
in fact I don't see any comments
actually within the code itself and
what's the price to be paid I mean if
someone like me is reading the code
trying to find a bug trying to add a
feature I'm and I literally have to read
every line of code think back to how
this is working what is it doing when
you could just tell me that because Noah
whoever's written the code knows it best
and just save your readers time by just
giving them the gist of what
everything's doing agreed I think it's
reasonably common - unfortunately that I
think I think folks do I think no I did
an awesome job of writing very clean
code using very great identifier names
but I think no matter how good your
identifier names and I think it was even
Andres that is before we don't
necessarily know the why or that we
might be able to infer the how but the
why I think is important and I think
that necessarily comes across you know
despite how clean your commenting or
your your symbols are and I think a good
example of this is this line here so
it's clearly the case that we're
allocating some number of unsigned int
of size 8 but height times width I get
that makes sense to multiply it gives
you the resolution but the three again
if I'm coming into this little
unfamiliar with
p.m. I'm not exactly sure why that is
maybe that's because it's one bite for
red one for green one for blue so I can
kind of infer but that's the kind of
detail that you just tell your reader
what's going on there I think yeah and
actually bellick took back to the header
file though bail occurs raises an
interesting question which was what was
the hash pragma wants directive at the
top of the file yeah do you know what
that one is
I don't know I don't recall offhand so
that anytime you see something begin
with a hash tagging see that's what we
would call a preprocessor directive so
when you compile a C program undergoes a
number of different steps of which the
very first step before the actual
compilation it's called pre-processing
and it's interesting
so this it's very common if you have a
larger program that multiple files might
include the same header file insofar as
each of them depend on it so it looks
like what we're seeing both for the
first time hash pragma once literally
it's just a hint to the compiler
assuming it supports it that it should
only compile this file once it should
not copy and paste its contents
effectively every time you see include
lid pic pics map dot h include pixmap
dot h and so forth in multiple file kind
of similar to like the hash if n def
indeed so you might have seen this in
some of these fifties files if I open up
the sandbox here just we have a little
scratch pad you might see something like
what we say if n def foo then we say def
foo then you put your code and then what
is it end and yes everything's end end
if I'm not dead I'm not representing see
if I actually don't remember our runs oh
and if and if and if and so in this way
too it's kind of a hack whereby if foo
is not defined and I think if you have a
pound sign there oh yes of course thank
you if foo is not defined go ahead and
define it in the second line then you
have your code and then end if then the
next time the same file is included it
will be the case that foo is already
defined so none of those lines get
executed again hash pragma once it's
just a nice shorthand way of achieving
that exact same results yeah
all right back to the C code yep
anything you that strikes your eyes here
yeah I was looking at that malloc line
as well in fact can we scroll up and
take a look at the definition of the
struct pixmap image or just wanted to
take a closer look and see what's
included there okay so it looks like
including a file pointer to whatever it
is it was the file that was opened and
then a pointer to an unsigned integer in
8-bit unsigned integer for pixels that's
an interesting choice because it seems
like we're trying to store like an array
of pixels here where I would interpret
this to mean like each individual pixel
is an 8-bit unsigned int but maybe what
you really want there is like an array
of the red-green-blue values because we
defined a struct for a pixel already but
we're not if we're not using that here
and we start components would be more
accurate in this case interesting yeah
and actually I see Andres chimed in with
a similar answer to what pragma wants is
and I think I've been typing too much
Python let me actually correct myself it
should be hash define not hash def I was
accidentally defining a Python function
there okay other thoughts that jump out
at you here I'm it's storing a width and
a height and it's also storing a maximum
color value which is interesting because
I remember in the header file there was
also a function for like get maximum
color values and there's a story about
there too it's nice that they cache the
width and height so it doesn't have to
compute it when you do get width or
height it just stores it and then you
know saves you a little bit of the
process yeah I mean you would have to
store some counts there either of the
pixels or the size because see you can't
just say how big are you you would need
to source something around so I agree I
like that approach should we scroll down
a little further sure so if we go down
to the latter half of the code here
pixmap image free I mean now I would
start to comment really on error
checking too so strictly speaking if
you're using your library correctly
you're never gonna pass in an invalid
pointer or like a null pointer but if
you're writing a library you should
assume defensively that other people are
and somehow someone is gonna err and
it's a little obnoxious if your library
code that you wrote crashes because
someone else has misused it the onus is
really on you the library author to
defend your code against accidental or
incorrect usage so I would have some
simple checks not unlike the one Brian
pointed earlier whereby between line 44
and 45 here just check and make sure
that image is not null and only if it's
not null should you proceed to try to
close the image file free the pixels and
free the image and even then I would
further make sure that your
that image file is not null so that you
don't accidentally close a null pointer
there now back in the day years ago when
space was incredibly scarce as well as
time was very precious when it came to
CPUs you don't want to do unnecessary
checks and so checking for null over the
place if you're writing most of the code
strictly speaking wasn't necessary but
you have cycles to spare these days and
I think it's much better practice to
code defensively other thoughts that
jump out at you here taking a look at
pics map image open now and seeing that
okay it doesn't need take a pointer to a
pointer so this is one of the questions
that we had earlier in the original
example code of all right we defined a
pointer to a pix map image and then
we're passing a pointer to it as the
argument and so here would probably be a
place where I would again like to see
some documentation of how it is that
this actually works because it seems
like okay if if the file path that we
pass in is no by align 50 to there that
we are taking the pointer to the pix map
image and setting that equal to 0 or
null and returning but that behavior at
least I haven't seen it documented
anywhere yet and whether it was in a
comment here or somewhere else might be
helpful yeah yeah I mean what I presume
is happening is that there's gonna be
memory being allocated in here somehow
that's actually storing some value at
that pointer right which is why if I
keep scrolling and scrolling and
scrolling okay these comments alright so
we appreciate the comments here but at
some point they need to be attached to
the actual code I think so little
opportunity for cleaning up there and
also the the comment width by itself and
height by itself
those are interestingly sort of terse
comments indeed yeah and there's the
allocation 1140 Oh interesting
okay so this is interesting too Noah
seems to be assigning to image really
null which is what's happening here even
though he's not doing it symbolically
because if image is a pointer to a
pointer then star image itself is a
pointer so you could just write this as
null and frankly you probably should at
least to make clear to the user that
this is not the number 0 but it's indeed
a null pointer the casting happens
implicitly to an actual pointer value
here but I think that's one opportunity
for
for minor improvement as well even
though not technically necessary so
there was one thing I was going to point
out up here if I can scroll up and up
and up where are we no I think it's okay
oh here I was gonna ask this is an
interesting syntax that some folks
online might not have seen before online
67 you see these curly braces with a
zero do you want to speak to what that
is doing oh I think and correct me if
I'm wrong oh this just became a quick
I think the curly brace syntax is that
defining an array that contains only
zero elements is that the way of
defining an array that has multiple
things of the same value elements that
are 0 then are 0 yeah so this is a fancy
way of just clearing out all of the
memory in our array by storing the value
0 there again and again and again as
many times as appropriate you can use a
catalogue to allocate that much memory
or in this case you could use memset or
remember clear to - the same thing yeah
we'd want to do it by hand with a 10000
size array certainly no no this is a
nice little syntactic trick should we
scroll down toward the bottom before
maybe moving on to the next let's do
that see if there's anything juicy down
here that we might have met a bit of
logic there all right so yeah now at
this point I really just want you to
tell me what's going on I mean we could
probably figure this out logically by
reasoning through it but there's enough
complexity going on now with the code
especially down here with all the
parentheses ation just tell me what I'm
looking at I think it'd make me think it
also looks like there's some repeated
calculation here that is something you
might want to factor out it seems just
by taking a guess at it that we're and
you've got an array of what's called
pixels but each really three elements
and this pixels are right together look
like they're combining to form one pixel
we're restoring the red value with the
first pixel and the green value at the
second pixel and the blue value with the
third so that might not be immediately
intuitive but definitely the calculation
of where the red pixel should go is a
calculation you can do once and the
green pixel is just one offset from that
and the blue pixel is to offset from
that's a good point it's very pretty and
this is an example of pointer arithmetic
right for those unfamiliar Dauntless 3
is asking what's the difference between
the brackets 0 and then just empty
brackets I don't actually know is the
empty bracket syntax out I don't know
sighing see empty curly braces so this
is what I would do if unsure well
actually first I would ask Brian then I
would ask MIT Colton and then I would
ask Google everybody an undefined
contents in the array all right well
let's the C++ but that might be close
enough default initialization direct
list I think this is for classes that
would bosses yeah that's to C++ specific
no it's well I did say so you type array
in then in this in the chat here in the
search all right all right all right
C++ C++ I think this one me Oh as you
probably have the same yeah I don't want
to take too much time this much it might
be a C++ only thing I've not seen it
haven't seen it either in which case
maybe this one we should kick to
afterward although C programming course
notes let me search for two curly braces
so I using array
no but place you're initializing data in
the early braces yeah
multi-dimensional yeah they're just
saying you can define an array using the
curly braces and something caught
something I'm gonna go out on a limb and
say you can't do that anybody wants to
try those see-through sandbox we do
let's keep that as an at-home exercise I
think just so we can move on to the next
program now sounds good all right could
be wrong so that's just our hunch but I
think the the instincts here are right
we don't want to take too much time by
trying out every little thing in the
sandbox but when in doubt if you have a
compiler just try it out all right oh
and here we go so puppet 4 4 1 1 empty
brackets in C++ is default
initialization and bracket 0 bracket is
setting it equal to 0 okay all right so
we pick up another one I'm gonna go
ahead and switch us to this other screen
so we can get us let's go to the next
one
tux man 29 oh this is a lure one so the
city Oh Lois my alright strength I have
never seen any Lua code before in my
life so it's like JavaScript and Python
had a baby kinda okay so please take to
heart any feedback Brian has here on
your code then please okay so here we go
I'm overwhelmed by the files and the
file extensions but when in doubt start
with the readme so this is by tux man
open blackjack which is a game in Lua a
language the Colton actually uses is in
these game development class made
share the the link of that oh yeah let's
do that course to be used on open OS in
the minecraft mod open computers I see a
lot of to do is up ahead but a few
things have done and that's fine too I
looked through the codebase and it was
pretty it looked like it was pretty
feature complete so okay I see I see
more Duns than to do so I got a little
nervous that the to dues were at the top
there long term goal so I think none of
this is something we get the code and
that's fine it's more for usage there up
should we just try to make our way
through the code just take a look at
this week all right so let's go up to
the top here and see where we might
begin it alright so hey here's the fun
bag anyone know what DF store is I see
these sometimes in repos I know that
it's something to do with Mac OS file
system I'm not sure if it's an
optimization file or if it's something
else
it's store if I understand right I think
it stores data about the positions of
files in like the Finder window and the
file system so if you've organized your
files on the desktop and one file is in
the upper right and you've dragged
another file to like the middle of your
screen for instance that information has
to be stored somewhere and I think Mac
OS stores that information in a file
called dot d s store such that when you
open up the file it's not that the file
itself knows where it's positioned is a
special file that tells the finder where
on the screen to position the files and
so it's just really annoying metadata
that ends up in repose because it starts
with the dot and let's use a git ignore
file and blacklisted so why don't we
actually start there and they're gonna
get slurped up by your get ads and get
commits so it looks like tux man has
blacklisted a whole bunch of files which
is good to keep them out of his get repo
nice clean hitting or file that's it
very pretty very pretty even though it's
not alphabetized that's okay but what
I'm not seeing is a dot again ignore is
a dot d s store so for instance in my
own git ignore files if I can open up a
little text editor here again what I
would typically do in my git ignore file
which will open up real quick here
before moving on to the actual Lua code
is if I create a git ignore file I
actually typically starts and I can't do
that I'm gonna do it without the dot
what I would typically do is actually
ignore everything that starts with the
dot which black lists all of my dot
files which tend to be private or at
least configuration or temporary files
and then I
I'll ignore the actual yet ignore file
which should indeed begin with a dot
even though my scratch pad here does not
have a dot for something like I think we
use like a dot yeah Moe fell for
travesty we do the same things hash dot
yeah exactly so you don't have to do it
that way it's a little draconian to just
a blacklist everything but honestly I
would make so many mistakes by
accidentally committing my FM RC file
and other such things that I just tend
to do that myself and I'm Anton was
saying that they just finished the match
three assignment the game def course
that's awesome that was one of my
favorite ones to create do you remember
that oh nice yeah I made sure of course
there's a lot of fun and then a pig or
pick 91 seventeen saying lol do sir
should be included in a global get
ignore I kind of agree with that
actually yeah no agree but I think it's
fair that no one really wants to commit
that file anywhere yeah so Brian if
you're new to this IC for Lua files here
blackjack debugger helpers players where
would your eyes go first
my instinct is to start with blackjack
since this is a balk check game and it
looks like blackjack is probably where
the main code logic of the program is
gonna be and it looks like players might
have some information about the people
playing the game but the main logic for
the game is probably in blackjack and
it's worth noting especially since we're
doing a lot of reading from the repo
these sentences or phrases that are next
to these files don't necessarily
describe those files so even though it's
right there and it's a little misleading
those are the most recent commit
messages that are related to a file that
was modified as part of that commit so
just beware that you shouldn't
necessarily be reading these pages left
to right in quite the same way so here
we go blackjack Lua let's go ahead and
scroll down to the beginning of the code
this this Brian this is we're gonna be
here a while
well let's see what we can glean from
this and Colton's our resident expert on
Lua so I'm gonna guess I'm looking at
some variables up at the top here looks
really clean to me we have comment
presumably in mentioned by - - which is
a Lua thing require which is a little
reminiscent of nodejs for those familiar
but I like the consistency I like all
the variables are explicitly declared
we're using double quotes everywhere
everything is nicely documented I mean I
think the code starts off great
alphabetized ridiculous when it comes to
at least
I might do it logically here so that's
okay come and say I like the fact that
the comments are capitalized this time
like this his MIDI style guy kinda ya
know for sure um this I mean this was
actually very common back in the day to
actually have like these line separators
now I'm guessing there's not the same
number of dashes here as there are here
and that's fine if the whole goal of the
syntax is just to make clear here is the
main part of my game then this is fine
but honestly these kinds of conventions
are very annoying to maintain and back
in my day when I learned C we would
actually do slash star and then a lot of
slashes let me go ahead and just have a
dummy file that we can type anything we
want in here I would do something like
slash star star star star star now it
counts out like 72 or 80 of these stars
when really none of them functionally
matter and so it's I think cleaner just
give me the minimal amount necessary and
if you really want to be you know you
can go ahead and elect the line them but
at least you're not creating work for
yourself by maintaining these widths the
former style reminds me of Java like
tremendously very common in Java
oh yeah super common super comment okay
so main loop what do you do what do you
like or dislike here I like the things
have separated out into various
different functions I think that's good
it makes it very clear to see what the
game loop is doing that the game just
repeats a certain set of instructions
over and over again as a bunch of turns
happen one after the other so that's
definitely good I see a little
inconsistency here and Calton do
contradict me if need be even though
these functions are being called with
the parentheses and no space before the
paren the functions being defined this
way is this conventional in Lua or just
a little inconsistent I don't think it's
conventional no because if we look down
here on line 35 oh yeah that function is
different inconsistent so again we're
really trying hard to find fault but
hopefully that's the point here just to
point out opportunities for improvement
I mean honestly if you're not gonna
comment these that's fine because
honestly the functions are so well named
that they pretty much tell me what's
going on I don't think you need all the
white space because honestly I now look
at this and I'm like wait a minute did
they finish this function it looks like
you're gonna go back and comment it
later and I'm guessing you're not it's
to unnecessarily bloated I agree yeah so
let's keep scrolling
here's an actual function that's being
implemented called bet
I like the comments it is meant in many
languages it's kind of frowned upon to
do these inline comments off to the
right it's a lot nicer I think visually
just to be able to
left-aligned comments right above the
code would you agree with Louis I agree
I I think especially given how long a
lot of these lines are just on their own
because of the strings having the
comments also being off to the right
intermix with these strings it makes a
little bit hard to sort of read top to
bottom and get the flow right yeah great
I mean it's it's good that they're there
but I don't think it's necessary to much
better than that no comments all I will
say for sure for sure one thing that
strikes me is a little bit odd is that
we the bet function is calling the main
function a whole bunch of times even
though bet is inside of a loop that's
running in the main function interest is
that conventional in the I don't know I
think he's just recursively calling main
right yeah so this is just an
interesting way I think of him trying to
use recursion but it's not a Lua
specific thing no we saw this actually
last week yeah yeah and I would I would
advocate against this having these sort
of hidden cyclical loops that are
happening there after all the main part
of the game really is the main logic the
brains of the game and if the game's
main program is you want you to do some
things again and again I would factor
that loop out and just put it in the
main routine you want to bet multiple
times you don't want to call the main
part of your program multiple times yeah
and I would even maybe say well I have a
take turn function that you could have
in a while true loop or something of
that nature and then break out of what
whichever sub function he wants that
you're you know going back into the into
the other well actually in this case
because it's there's a sequential set of
steps yeah
it I think it would take a little bit
more complicated refactoring than just
doing that yeah now we do have a
question here
I thought we'd love you don't have to
define your own game loop at the bottom
that's correct so this actually is not a
love this isn't a love program this is a
love mod it's a part well in Minecraft
there's a mod called open computers
which allows you to basically program
computers in Minecraft to get these
computer blocks and you can program on
those virtual computers using Lua and
sort of import it into the game and
that's what this context is and then in
that sense and I'm not terribly familiar
with the API but from what I can glean
reading this code base at least you do
have to sort of bootstrap your own
application because they are CLI
applications you're essentially running
the Lua interpreter on those virtual
computers and therefore you would have
to
loop's you know core game loop and so
whatever you would need to do to get a
CLI app up and running on an actual
computer and so it is a separate
separate environment than love which
love is a 2-d game development library
which gives you all of that sort of
infrastructure for running a set of
functions the update the render and the
update are sorry the input update and
render functions that's all maintained
for you by love but completely separate
ecosystems now do you see that tux man
29 is in the chat here
curiously we're renewing tux man 20s
code so this is nine tux mans later oh
and I'm guessing they're one in the same
and 28 other tux men were already taken
yeah but welcome aboard I hope hope
we're being a little bit helpful here I
will say what I love about Lua is it's
just so down readable honestly it's like
see without the unnecessary syntax yeah
no semicolons no unnecessary clutter so
I've really liked the readability the
gripes that I do have are I'm personally
not a fan of the end keyword I would
much prefer that the function has a
colon like Python and then they can
therefore use a significant whitespace
okay for that much better
but I'm also kind of bias is array like
Python same thing they do that same
thing with ifs and then with functions
and - does this as well if you've ever
done shell scripting in a language
called bash keep scrolling I mean I like
how readable the code is I will say if
we really want to nitpick I feel like
there's just inconsistent commenting
like sometimes there's really good
really helpful comments but then other
times I'm just kind of on my own like
why is the the table cloning this as
opposed to declaring in some other way
like just having a bit of helpful
explanation in chunks don't leave some
blanks because it's just more work for
me to do later but really good
commenting here throughout I think this
was the main big part of the code that I
thought could use some refactoring
somehow or other big yeah I'm not
entirely sure right just looking at it
how I would do it it looks like there is
a bit of redundancy throughout so I
think making a few sub functions here it
would make sense yeah I mean even for
little things like checking for wha Big
Y little Y again and again that could
probably be generalized to a function
just so that you could even support then
explicit yes or no or such but that's
but I think we think everything's really
on the right track here else it's funny
how every language has its own
incarnation of this if-else if-else with
an e if oh my god it's all over the Sun
with the space and actually in Lua if
you do else if with the space it'll
create a separate block okay you'll
actually it'll if you do else if with a
space and then you do the end on the
next one or whatever it'll actually
treat the elves and that F is two
separate blocks and so it'll expect
another end and it's gonna be a source
of source we're interested and now in
Lua
what's the difference with this syntax I
say user : hit but I also see user dot
something sure in this case this is a
field and this is a function but the
colon is actually the way sort of how
Python does object-oriented programming
where you pass or you pass itself in Lua
colon passes an implicit self no
interest so it's a way to sort of get
object-oriented programming in Lua it's
a prototype based language it's a little
bit weird to get classes up and running
I usually have people use a library in
class alright so take care of all that
stuff so could you do user dot hit or
good that would be either it would be
either a static function if you don't
pass itself or if you pass themself as
the first argument it allows identically
to call so there's syntactic sugar
protective trigger oh that's interesting
I've not seen that before and what is
the hash tag before user dot hand that's
the length operator Oh everything in Lua
is a table sort of like as a universal
data structure you can use it as an
array it's sort of like PHP uh PHP has a
common data structure for everything the
Lua has Lua has a table and it's hash
just tells you how many keys are in the
table it can either be array indices or
string indices it however it that's
actually pretty brilliant that's maybe
the best use of a convention for length
that I think I've sent instead about
Lang or dot length or Len tell me big
then it's like Ruby but without the
cryptic Ness yeah the number of things
in the following symbol I like that so
if you keep going I mean I think my
reactions are largely the same I mean
overall good maybe just a little
opportunity here and there to clean
things up I mean the file is to be fair
if we keep scrolling starting to get
pretty big but we saw there's three
other files so I think there I already
has been some factoring going on though
I love ASCII art so you already won me
over here yeah okay so that's pretty
cool so this is the main function so how
does this main differ from what we saw
earlier actually what did we see earlier
at the very top let's take a look
that actually game very interesting game
indifference here
so game would be the top level function
where's main actually getting called
from let's just main call game name well
main is getting called by game okay
right my bet even okay so main is being
called way up at the top where we began
our story yeah main is getting called in
bet several times so and then I where Oh
so beds actually being called by a game
not by main so I think we have yeah that
is in the game loop okay so here is
calling main to so main is calling game
oh my goodness okay so this is this is
spaghetti code then a little bit it's
kind of we have a bunch of tendrils sort
of all over the place
yeah it's getting a little scary for my
taste cuz even mean the fact that we're
struggling to understand the logic means
like I'm gonna be hard-pressed to help
contribute to this kind of project yeah
without really wrapping my mind around
things yeah okay but we do have the main
function down the arrow it's called of
course at the very end of the line nice
well it looks like this is how you could
give yourself more initial money perhaps
yeah so we glanced quickly at just the
other files just to get a sense of what
they are and then move on to another
character so take a look real quick
alright so there was debugger Lua and B
players you mentioned should we look at
that one see what a player is so looks
like here's a player class so to speak
yep is they implement a class and the
way that it works is a little bit odd so
every sort of table has a meta table
associated with it that has you can is
sort of like meta classes in in Python
how you can you can define the behavior
when you set things and when you assign
different attributes and whatnot and so
you have to basically set the meta table
for an object player in this case they
could do in JavaScript set the prototype
for something okay and then when you
call new you can therefore get a new
version of that object with all the same
functions that feels interesting himself
you just get for free because you're
using that syntax yep so I will say I
actually like the inline comments here
because it keeps all of these properties
nice and close together it's very
skimmable if I only care about what's on
the left in the echo code but if I want
a quick reference as to what it is I can
look to the right yeah so I think I'm
okay with this because if you were to
put it on top of every line and separate
it with new lines I mean this thing gets
super tall and really doesn't
any-anything compelling yeah I think so
I would probably indent them evenly but
I mean that's a little bit of extra work
that may not be necessary I would say
about the comments specifically these
are all just properties of the same
object the property values should
probably all be like nouns for instance
like money is defined as like remaining
credits but choices keeps track of users
choice and so I think there's just an
inconsistency there that makes it a
little bit harder to just get it a
glance like what it is that each field
is doing especially since there a fair
number of fields so yes all that choice
okay so that would be I guess an enum
kind of thing sure if we were inferring
correctly how it's used so it looks like
these are just the various methods that
are associated with a player so not
unexpected we take a quick look at the
other two files yep all right if we go
back here we had helpers I like helpers
well debugger blast cuz it might be a
little specialized talk to me was saying
debugger is not his library just
included oh that's really helpful
okay we might be able to skip that okay
all right it's gonna be awkward if we
say what a good library that's the
bugger file is okay and looks like this
is used for helper so just some related
helper functions for sleeping clearing
table cloning so here there's good
comments above every function which is
quite helpful yeah what some of the most
comments I think we've seen so far in a
repository yeah I just like to see a
little more consistency I mean overall I
think we're really nitpicking but yeah
it would be nice and netting me now
we're sort of in fewer comment territory
and so I'm sort of less happy I'm doing
more work to understand this yeah but
otherwise it looks like this is a good
way to factor it out so much like I
mentioned earlier maybe a function to
check for yes or no or Y or n looks like
check Suites here is a good way of
checking for me to quit or cat no it's
probably Jack queen or king in this case
here
although chuck converts the face car I
see we're just mapping a number on the
card to an actual number and we're
special casing the three things that are
not in fact numbers alone to Sakura's
point about the while or about the main
sort of module they were asking does Lou
and I have a while loop because that
would be better than calling itself at
the end of the function I agree I think
a while based format for that last
module would be a good way to refine it
yeah
and then lastly lastly here Oh what good
commenting I like it and it answered a
question I had are there multi-line
comments it would seem in lower there
are a few exceptions additional brackets
so that's kind of nice but I do have a
question about so in a language like
Python or JavaScript for instance if
there was a library that you wanted to
use it was written by someone else in
Python you might put it in like the
requirements dot txt file in order to
say it's a dependency for this Python
library in like a no JavaScript project
you might put it in package jason to say
it's a dependency for the project such
that if the debugger library or whatever
library you're using is ever updated you
can you don't need to then copy-paste
the updated code into your repository so
it seems like they've copied that tux
Manas copy pasted the debugger library
here into the file does Lua have a way
of saying you know here's the dependency
and I'd just like to make this
dependency part of this project without
needing to copy the file in I think for
for non-love 2d stuff there's a
distribution network called Lua rocks
kind of like homebrew kind of like hip
and in that case I think there's
probably a like requirements not
something let me get let me see your
real quick
Lulu or rocks dependencies tendencies
going off to the side here you just see
I don't use I don't use it outside of
the context I love to need too much so I
actually can't say specifically
dependencies of a rock a rock is bulk a
little or rocks project are specified in
its rock spec file because that might be
the acquit the rock spec file might be
the equivalent of with like a
requirements that text file is yeah I
wanted to see if there was a sample of
it here so here we have Brian the formal
definition for a rock spec file which is
the type of file you would put akin to
requirements text and Python to pull in
some dependencies I think this is the
same URL you had a second ago yeah I'm
not sure what the actual file format is
probably get a quick sample here
creating a rockets up creating a rock
kind of cool writing a rock spec alright
this is a representative okay yeah so it
looks like down at the bottom there we
have dependencies where you can specify
what packages it is that this particular
lua file depends on and here it depends
on Lua package presumably but I wonder
if you could add the debugger as one of
those to avoid having to copy it into
your own repository yeah that's nice I
mean if it gets the job done that's
certainly fine but it's generally
frowned upon to just store in your own
code repositories someone else's code
because they're not gonna be in sync now
and there are actually more
sophisticated mechanisms built in to get
you can use what are called get sub
modules for instance to make a
dependency link to another tree another
github repo but there are also language
specific options as well and that's what
we do in cs50 but of course our Python
modules get sub modules probably a good
way to do it cuz there's most of the
libraries have ever used are on github
for sure
so really nice overall I think maybe
just aspire to be a little more
consistent with the commenting we for
time sake I think won't dive really
deeply into the code because there were
so many hundreds of lines yeah but
really nice overall yeah great job puck
spam is nice nice repo to look at sleep
screens and go ahead and yeah one other
project here's how you work all right
off the network off the grid right now
alright so here we have one from TPD d26
which is a Python flask app so I had to
pull that up
I'd like to shout out our followers yeah
let's catch up on our way to comments
and questions to saudi sip and SMI
Stephan five five eight eight czar clean
den här natthew 664 GD f GD f xq how'd
you read that one the fastest nibble USA
Gina George picked 91 17 big Fupa one
27001 so she Joe to e 18 is that 2 to
the 18th 3 times 10 to the 18th Oh 10 to
the 18th right okay Ron lanyard Lonnie
Otto Wendy Mindy Elise one tooth notable
Mathias NB
99 well welcome aboard to the stream
here any questions come in on the chat
we should off yeah let's take a
look and just make sure that we didn't
miss too much so this is main secret
good thing that okay nice let's make
calls yeah all right I think we're up
today yeah yeah oh and Ivan friend can
you review my code we can go ahead and
paste in the bitly URL again if you'd
like to submit your code for a future
stream by all means call them and paste
of that earlier today as it was a troll
message oh really
yeah never mind all right let's take a
look at a Python mess - repo here flask
way back for reviewing books nice I see
some pretty standard layouts not unlike
what we do for cs50 I see a proc file
which suggests that this is maybe being
deployed to Heroku or some service like
that start with the readme as always oh
this is nice it might actually be live
should we see if we can see the live
version if it's still alive I have a
feeling this the first project for cs50
is web programming class on EDX is a
book review application and by the looks
of the files I'm wondering if this is an
implementation of that problem in a
well-designed depository
it looks like the app is not running and
all know it is just slowly running this
does look awfully familiar now yeah
yeah we should maybe turn our attention
to one that's not course specific okay
yeah all right well done so let's go
ahead and take a look at the next one we
just don't want to spoil the project for
folks that are still working on that so
we're gonna move down but thank you for
the submission a cs50 final project that
works well so this is from s4g
for our let me go ahead and paste this
into our window here and this is a
simple web application that helps you
keep track of your favorite TV shows and
movies alright notice that the student
might be abroad perhaps in the UK having
spelled favorite Toulouse different time
we would in the US good observation
that's my first takeaway so far let's
scroll down here are we gonna knock them
a point or getting them a point for that
that's amazing I love I love different
spellings all right so this is actually
kind of cool I mean all the better that
we got a screenshot because you don't
now have to fire up the whole
application just to give yourself a
mental model for what's going on I see
bootstrap I think yeah looks like a
bootstrap navigation bar up at the top
good scrap table yeah which is nice to
make things a lot quicker and easier to
look pretty this simple web app that
queries the API at the movie DB which
with the help of tmdb
simple wrapper to pull information about
movies or TV shows it looks like you can
add remove TV shows specify seasons and
episodes that you're on this sounds
pretty cool yeah
all right so where should we dive in if
we go up to the code here it's indeed a
a Python application and there's a few
different files though how would you
propose we begin yeah well let's take a
look and see what's inside of the app
directory perhaps it looks like that
probably contains the source code for
the application all right I see four
files here forms models routes and
search so I guess this is a web
application that probably has some sort
of database for the storing information
models pi is a conventional name for
where all of that data is stored
defining the types of models I noticed
that back over in the original page that
the repository was tagged at the top
with flask sequel alchemy which is a
library you can use to interact with
flask in a sequel database and so OTV pi
is that oh I didn't even notice that one
all right CB app that might be the
equivalent of application dot PI and yes
you're correct now this is well very
pretty very arbitrary I would say hey I
have not seen this convention before but
okay we're you want to take us through
this all right here we are
so we're importing a couple things we're
importing thank you Brian importing
flask config I saw that there was a
config file in the repository so this
looks like some file that they've
defined so that's cool you can import
from your own files right you can import
from your own modules or from modules
that you've installed it's a sequel a
sequel alchemy is probably inside of the
requirements file for this repository so
that's a package you have to install but
config is probably a module that they've
written and install and just imported
into this file and this looks like a
nice way of just factoring out what
could be a large configuration for your
app without cluttering your logic okay
down here's some familiar stuff too and
models we don't talk too much about
these in cs50 what might this mean here
yeah so what I was mentioning a moment
ago inside of the app directory we saw
there was a model spy file and so inside
of that file which will probably take a
look at in a moment probably contains
the way that Fox sequel alchemy likes to
do this is by defining a class for each
table that you have in your web
application so if you maybe this one has
a table where they're keeping track of
television shows friends
you probably have a model or a class
because Python allows for
object-oriented programming that would
define like a class for television show
for instance that included with the
properties of a television show are and
any methods or functions you might be
able to run on television shows and just
allows for a nice way to interact with
the database via what's called an ORM or
object relational mapping so this is
basically just saying all right from
let's take the application and import
all of the database modelers are the
tables that we want to represent in our
application they're nice and login
manager this is actually a feature of
flask I think it's a third-party plugin
you can use just to make your life
easier when it comes to logins we in
cs50 code kind of reinvent this wheel
more simply for students and then it
looks like the routes like app dot route
has been factored out to a separate file
as well yeah this isn't do a blueprint
which is not something we talk about in
cs50 but flask has a feature or but you
can create different blueprints if your
application PI file is getting very long
and you have a whole bunch of different
routes you can separate routes into
different blueprints and then just
include all of those blueprints just to
put your routes that are related into
their own files just for cleanliness
so perhaps without going through every
file should we look maybe at models
first and then at the routes and just
take a draw attention to this I mean
this is fine it clearly is kind of
trying to separate different chunks of
code in this file and if it's like a
finishing touch on the file just to make
it a little more readable I mean it
actually is honestly it's this kind of
stuff though that's just annoying to
maintain and I do think it's uncommon to
leave that kind of stuff in there long
term yeah I'd probably mix those and
keep just not adding all my name on it
yeah yeah indeed all right let's take a
look at models which was in the app
directory as brian noted there's a few
other files in there but we'll focus on
models and I think routes for now and
this is kind of interesting we don't
focus on this in cs50 but you do in the
web programming class right are we
looking at here would you say so here
we're defining a class for a type of
object called user and long story short
you can use objects of this class to
represent rows inside of a table of
users so in cs50 if you did the finance
assignment for instance you had a table
called users where each user had a
username and a hash and a lot of money
they had you see a similar thing here
where we're defining a class called user
and we're saying for every user or for
every row in the users table because you
can kind of draw this analog between the
class and the table and
a user has a username a password hash
whether or not they've been
authenticated which appears to be a
boolean and so flasks equal alchemy lets
you specify the types of these columns
as well so we're not using strict sequel
syntax here but we're getting at the
same idea that every column inside the
table it's gonna have a type so username
is a string which probably corresponds
to like a text or a bar chart type
depending on the database same goes for
password hash authenticated is a boolean
and then movies and shows those are
going to be relationships between tables
so it looks like later on in this file
we're gonna see a class called movie
that's going to represent a movies table
and a class called Show that's gonna
represent a shows table and the idea
here is that a user is associated with
one or zero or more movies and it's also
associated with zero or more shows and
this is actually a convention here what
flasks equal me is probably doing is
assuming that the movie table and the
show table has some kind of user ID
associated with it in some linking table
this is actually back ref is going to
create the link in the other direction
so this means that if you have a show
object you can say show dot user to get
what user is associated very nice so
here seem to be some related methods
that pretty much do what they say and
this seems very readable and here I
would say are you probably don't really
need to comment these because you would
just literally be restating the obvious
cuz the functions are so well clearly
named um you talked about this recently
in a stream I think wrapper I think in
your last stream I think yeah we did a
stream recently on object-oriented
programming what's this so if you try to
print out the value of an object in
Python for instance as just by typing
print and then the name of the object by
default pythons just going to print out
like the memory address where that
object happens to be allocated inside of
a computer's memory which is not all
that helpful if you're trying to get an
understanding for what exactly is this
object and so python lets you define a
special method called underscore
underscore repper underscore underscore
short for representation where you can
return the string value that you would
like to represent the object as when you
try to print out an object and so here
we're saying if we want to print out a
user object the information we should
print out is in brackets user and then
the user name
and now we're if we scroll down
further we see another class definition
here for a movie pretty self-explanatory
every movie has an ID a name status
apparently a rating and a user ID which
is probably the user who created this
movie in the database a couple comments
come to mind here it tends to be
conventional conventional especially for
your primary key just to call the ID ID
and not call it movie underscore ID for
instance both are fine especially if
you're gonna use it as a foreign key
elsewhere but insofar as your user table
has a field called ID that should either
change also to user underscore ID or I
would just simplify the movie ID as
being ID and in this context any time
you see ID that's the primary key
anytime you see something underscore ID
it's a foreign key from another table
and here too I actually don't recall
this in text offhand but this feels like
we're breaking the abstraction that is
the ORM the object relational mapper
that is sequel alchemy because he's
specifying the name of the table here
even though strictly speaking we don't
know that from the ORM it just happens
to be by convention the lowercase
version of the class name is there not
another way to express foreign key
without having to know the table name I
think that this is actually the
conventional way of doing it I think
really but the there is a way of if you
want to explicitly state what the table
name is if you look at the example from
the web programming class we in the
class define an underscore underscore
table name underscore underscore which
is a feature of sequel alchemy to say
here's what I want the name of this
table to be otherwise it just goes to a
default but this I think is pretty
common I don't know if there's another
way of doing it just rubbed me the wrong
way it is a little bit have to know that
I will say here I don't recall would
seek welcome me does it support you no
it does yes I was actually gonna make
that comment as well that it seems like
the status of the movie like it says the
default is not watched so presumably
there's also a set a status option
called watched but presumably there's
some fixed and finite sequence of
possible statuses whether it's two
statuses or more and so sequel and other
languages have a special type called
enum which basically means that the
value of that column can be one of a
number of possible values in this case
in the sandbox we've defined an enum
that is either watched or not watched
and that just guarantees that the value
in that column is only going to be one
of those possib
values for the enum and it can't be
anything else if it's just a string you
could run into a potential class of bugs
if you accidentally miss type the string
for instance and you end up setting the
status to something that is not one of
the types of statuses that you're
expecting and so if there are only a
fixed number of possible values and enum
is usually a better design for what to
do with that table agreed and even its
minor but just as I did in the sandbox
just using something like all caps and
using underscores just make it a single
token don't make it an English phrase
like this not watched I would say would
be the convention right all right sugar
themselves are actually on right now and
they say look looks like I'm on time
thank you for reviewing my treat of
course yeah glad you were able to tune
in and thank you also for following just
follow it as well awesome and now we
have a show similar comments I think
show ID could probably be called ID here
show name is fine though honestly I
would probably just call this name and
say a name it simplifies things a little
bit and it's gonna be readable when you
do something dot name anyway you have an
object of this this type current season
episodes watched I mean for the most
part it's hard to find fault with with
any of this
you could specifically say let's see
nullable false I mean for good measure
you can make these nullable false too
they already have default values so it
sort of is already covered but this way
you can't accidentally get some
ambiguous null value in there as well
which is the default so this is really
clean and if you've not used an ORM
before this is actually a great example
of a data model that does have some
interrelationships that are well served
by an ORM so you have to write all the
manual sequel yourself yeah I don't know
what the intended features of this are
but one thing to note is that for
instance based on these classes if two
different users were watching the same
television show for instance and wanted
to record it they would be to just
totally separate show objects you could
imagine that if you eventually wanted to
have something where you could see like
who else is watching the same TV show
that you are that you might want to
change the schema slightly in order to
allow for that type of thing but perhaps
for the purposes of this applications
fine and I don't know if we'll be able
to glean this just by looking but I'm a
little curious what authenticated means
here generally authenticated means
logged in but it would be a little weird
to store in the database the fact that
the user is logged in that kind of state
is usually maintained in the application
itself or by a cookies so we'll have to
see if that is yeah it also seemed a
little bit strange that both the is
authenticated method and the is
anonymous method
both returning self-taught authenticated
I wasn't entirely sure what that means
and some comments there would maybe be
helpful there were a knot in their mic
we're not ya presume these are supposed
to be the opposite yeah it could be
about you so that could be a bug sugar
we'll say sugar or s for g4r okay there
we go
perhaps it's more validating it could be
so M Kloppenburg is proposing that maybe
that means the users just confirm their
email maybe but I'm not seeing an email
unless username is meant to be an email
address so unclear just from the code
alone so you take a look at the routes
code for the routes alright so here we
have a whole bunch of imports as well
related specifically to routes but
notice that there's some linkages among
these files we're importing the model so
that we have access to that app forms is
another file that we haven't looked at
and then there's this blueprint feature
that Brian referred to earlier you know
I probably throw a space in there and
all of a sudden I do see single quotes
whereas I think in the other file we
were seeing where we single single or
double quotes
oh this file is going to use single
quotes I can't recall it we saw in the
other part not a huge deal but no single
quotes so that's fine bread no qualms
routes dot pie is where we were so here
we have it looks like a decorator this
relates to apparently the function
you're supposed to implement yourself if
you are using flasks login manager yes
so you would know that from the
documentation and that function is just
returning a user and so if you haven't
seen the syntax before on line 17 this
is the sequel alchemy ORM syntax that
we've been alluding to and the syntax
user dot query dot get idea is just the
ORM way of saying the object-oriented
way of saying the sequel query like
select star from users where ID equals
that ID for example yeah I mean the arms
are very readable when you're doing
simple queries like that and will
perhaps see some other uses of that too
um here this is very nitpicking but
because these definitions of the
functions these doc strings are so short
you can probably pull line 23 up onto
line 22 and pull line 24 up onto line 22
to just to keep this more compact
because you've added two extra lines
that aren't really adding anything but
the fact that you're consistent I think
is more important so no strong feelings
there technically speaking you don't
need this it's fine for readability but
that happens to be the default if you uh
no no just get it
the dog any both that's right so up here
we're getting just gets but down here
we're getting getting post thank you and
here we have if the user is
authenticated so I'm a little worried
how this is being used honestly
current user alright we're gonna have to
see how logins actually work login form
there was a foreign stop I file
elsewhere that's probably defining what
the for the login form yeah so let's see
this is where we're validating okay so
here's where we're filtering so this is
another use of the RM but you're not
doing we're ID equal something you're
doing where username equals something
right yeah so that's nice and first just
gives us back the first row and
hopefully there is only one row if any
if not user we're gonna flash the user
with a message which is to put like a
temporary message on the screen and then
redirect them to the login page
otherwise we're going to go ahead and
store the user's password from the
submission and get the user's password
hash and we're gonna check him to see if
the password is correct when they're
lying in okay so this is the yeah I
don't like this part I think yes it's
the authenticating the user part where
we're storing something in the database
when more conventionally this is
probably stored in like a session for
instance yeah because you know what let
me just grow up for one second if I
could
I've not looked at the login manager but
I'm a little nervous that because we're
storing the fact that the users
authenticated in the database that I
could I will have to look closer at the
code it's why worried that someone else
could pretend to log in as my same
username and because the database
already thinks I'm authentic ated Colton
or Brian could maybe get in as me now
it's possible to codes defending against
this but generally speaking this is what
you would store in a session so if you
were in your Python code to do something
like session user quote-unquote gets
something or you could say authenticated
and then just set this equal to true
this way it's user specific and not tied
globally to what's in your database I
will say they're commenting is the best
I think that we've seen so far you know
I just kind of took it for granted yeah
it's good nothing negative to say so I
didn't even think to say something
positive unfortunately yeah focusing on
the actual like larger
i order higher level this is great these
comments looked like they could be
written by me although okay I'm gonna
quibble I see a puncher issue a period
here but no period here so I'm sorry
disqualified X are all no but that's
actually great common thing so far here
is where the methods would have been
unnecessary if it's only the get method
strictly speaking evil yes thank you
redeemed they also have here two nice
alright
the authenticates the user yeah so
strictly speaking you don't need to be
touching the database for this this
should really be a femoral data not
needing the database registration also
yeah you even given that line 87 DB
session adduser would generally mean you
want to add a new row to the database
for this user object but presumably this
user is already in the table so I wonder
I think that might be a bit of an issue
of just adding the user well I think
that line 87 is just gonna fail but
maybe it fails silently cuz that maybe
the keys are gonna clash
yeah but I guess it doesn't throw an
exception if this codes are you working
here this is a minor point but the fact
that you have your logout routes but you
are requiring that the user be logged in
to use this is a little perverse in that
if the human goes to something comm
slash logout they just want to be logged
out but this code is gonna force them to
first log in even if they're not logged
in and then they're gonna be logged out
so honestly you shouldn't need this at
all though you should be able to well
you need this insofar as your code
assumes this at the moment I would
probably have a check there as to
whether or not this is a valid object or
not with if not if current user then do
this press Ted
scrolling down looks like registration
everybody is asking what happens if the
actual user logs in and some other
person logs in another browser since
authenticated is true in the database
yeah that's the threat that David was
alluding to before they're dead
depending on how the login manager is
implemented it could be possible because
we're storing the authentication
information inside let's check let me
see if I can find the login required
this might come with the library do we
think maybe it's from yeah so it's
part of the flash plugin let's see if we
can chase this down because we he might
be okay
flask login login record let's see if we
can just find this and see what it does
I'm gonna search for this log and
required if you decorate a view with
ensure that the current user is logged
in and authenticated before calling the
actual view and that's what we do want
but how is it done it looks like you
must it must require that they be
implementing that the programmer be
implementing this method I don't think
that's something this programmer
implements I think current user is an
object that flask login gives you access
to I think if you go to PI and go to the
imports I think current yeah current
users or something that's given to you
by flask well very interesting okay so
it's authenticated huh I think I'd have
to you know noodle on this a little bit
more but I think the threat is real and
who has that Indra ready I think the
fact that we're storing things in the
database is what makes that
unfortunately problematic because by
starting in the database you're making
it globally true that he the users
authenticated whereas sessions and in
turn cookies we make it locally true for
one specific person only and a minimum a
problem you definitely run into is if
you're logged in in two places on your
phone and on your computer for example
and you log out on your phone that's
gonna set off enta cated to false and
now suddenly on your computer it's using
the same database and you're gonna be
unauthenticated there as well which
could probably not what the user is
expecting indeed
I mean honestly this code at first
glance certainly looks terrific overall
this is very clean it's very well
commented I'll be with you know
occasional exceptions like for some
reason we forgot to comment this it
seems there's this stuff up top which
strictly speaking isn't bad let's the
update movie go ahead there's some
inconsistency between lines 268 and 285
so 2 8 268 is probably the more
conventional way of using a movie class
and sort of filtering it doing a like a
select where we have movie query filter
by the line 285 also works DB session
query movie and then filter by but it's
a little more verbose way that's less
common with the ORM and so just
consistency there is probably a good
thing and now I am curious if we can go
down one rabbit hole update movie
whatever this is that's a form most
likely I would expect to find that in
form stop I okay yeah so let's go to
form stop PI and it looks like he's
using flask WTF what the form with the
forearm flask form so
scroll down to what was it user form
update here's update movie so just
defining the fields of a movie so this
is a way of just more easily generating
form code if you're doing a lot of it a
form validation and things like that as
opposed to repeating form validation
code over and over again you can define
a class and use the flask form library
to simplify some of that it looks like
you actually get validation functions as
well are those server side or client
side do you know I think they're server
side but I haven't actually used this
library okay some libraries I'm not too
familiar with WTF can actually generate
client-side JavaScript for you so that
you're not writing the same kind of
logic in two places
a little unicode going on over here
missed opportunity for an emoji but okay
that's alright swift yes it's certain
many several programming languages
support and actually we can see I have
not tested if the cs50
sandbox does let's go ahead and paste
this and about session authenticated
gets happy face okay do that that's
actually could be fun and they put a sad
face when you're not affected yeah and
then you get criticized everywhere
online for a bad coast all right well
let's see do we have any questions we
should plug off because I see we're here
at 2:30 no I don't think so whip she was
asking if we checked his code but
unfortunately we checked your code last
week whip Street so but coming up again
soon hopefully yeah we'll take a look at
the other repo they submitted and thanks
everybody who came by today I've had a
pretty lively chat here a lot of
viewership again once as always thanks
to Brian for joining us for this yeah
happy to be here thanks everyone for
watching this is awesome but yeah yeah
thanks so much for tuning in and for
Brian for joining us I think we'll keep
doing more of these so do we should we
paste one more time do you or Elvia
which folks commit so if you'd like to
submit your code for review by any of us
or any folks on cs50 team here on twitch
please do so at the URL Colton just
paste it and we're happy to take a look
and really just have a conversation
about it yeah if anybody has any last
questions - well maybe stick up like a
couple minutes see if anybody has
anything and then uh tomorrow we're
doing a solitaire Oh justjust you yeah
just me
because it's solitaire yeah there we go
nice um next session tomorrow what time
eastern time tomorrow 1:00 p.m. Eastern
Standard Time
so it'll be in Lua and love today we'll
be making solitaire very famous sort of
solitarily played card game and it was
pretty famous on Windows machines and
Windows 95 I think shipped with it and
they are proceeding iterations of
Windows also yeah
and Shai asks do you guys review other
languages technologies yes we are happy
to review technologies and languages we
are not even familiar with yeah so
please and send any languages your way
may be a question for Brian from Indra
Reddy is cs50 one a follow on course
public it's not public on EDX it is
available through Harvard Extension
school during some years but it is not
it's not OpenCourseWare the way that
cs50 is if you've taken cs50 and you do
want to take other classes though cs50
has a number of follow-on courses
including a game development class in
Lua
a web application class and Python that
you can definitely take a look at and
those are available on that X if you'd
like to explore more after taking cs50
dude you can check out that URL there
which should lead you to all of cs50 s
courses VB hug the code reviews about
any project can be a personal website
for example yeah absolutely
I mean in fact the only thing we do ask
is that it not be a cs50 or a course
project for cs50 courses unless we spoil
the fun for other students
you can absolutely cabbie to 201
postcode from games if you'd like and
Thank You Bora Bora maps for the kind
remark beautiful and gentlemen I will
send over some assembly code tomorrow
we'll be joined by ETS which is on Bryan
you again for that book and assembly I'm
happy to do what x86 mips i spent some
time looking at mips last year but well
maybe tomorrow we'll have multiple other
laptops with google open it may be
application it could be anything you
want other than a course project i would
say but small is good because I think if
it's too big of a project we're only
gonna scratch the surface and folks
might get less out of it
so I think the fewer files the fewer the
lines of code I think the more
instructive it might be true something
representatives libraries great games
great really anything strongest
viewership is
now as we were ending actually this is
well people are excited to be tuning in
to see what's next
what show comes on next how do we submit
where do we submit our TV sauces so I'm
gonna type in the link right here so
bitly slash cs50 twitch code nice so you
click on that link and that will take
you to a G form which you can then plug
your twitch username and your github
repo or just so we can pull it up and
make sure it's public - because there's
some folks that submitted private stuff
and we can't look at that I'm sorry
indeed well thank you all for tuning in
we'll be posting this final version of
it on Facebook on YouTube and all of
cs50 channels so glad everyone sued in
today oh yeah thanks so much everybody
I guess we'll wrap now werewolf wise
says thank you thanks so much everybody
who joined us today I'll see you all
tomorrow for some solitaire and on
Friday we actually have a bootstrap one
as well with Aaron so you tuned it for
that one that'll be a lot of fun until
then this was cs50 on twitch code review
part 2 enjoy the rest your evening we'll
see you all tomorrow