Monday, September 22, 2014

Undefined Behavior and Bad Code



I see a distressing number of people asking what the effect of really bad code should be. Code like this:
  printf(“%d %d %d”, ++i, i++, i);
or this:
  i = i++;

In C, both of these are intentionally undefined (the implementation can do with them as it pleases). You shouldn’t write this code in C. I think these are both defined in C# (replacing printf with Console.WriteLine), and I’m not willing to look it up for reasons I’ll get to in a second. For the purpose of this discussion, let’s say that these are defined in C#. If that’s true then you shouldn’t write this code in C# either.

But…but you just said it was defined!

Defined isn’t the same as “good.” Let’s write some code that checks someone in at a health club. First, we need to make sure the member is active, and throw an exception if they’re not. Then we need to update the last time they checked in to now. That would look something like this:

if (!member.IsActive)
{ throw new NotActiveException(member); }
member.LastCheckinTime = DateTime.Now;

Now let’s go back to one of our offending lines.
  i = i++;

Amateurs write code for the computer. Professionals write code for other people who are reading the code (although it’s important that the computer understand it also). So what is this code trying to do? I mean, I can read the code. It’s adding 1 to i  and also setting i to the value it gets as the result of…ugh. What is the goal here?

If the goal is “add 1 to i,” then clearly you’re doing it wrong.
  i++;
Done. And this line, what is its goal?
  printf(“%d %d %d”, ++i, i++, i);

If the goal is “try this and see what happens,” then I’m not sure you care whether it’s undefined or not. But let’s say you actually want to do something useful. The variable i is used as a loop variable enough to make it understandable, as long as it doesn’t mean anything else. If it means “days after the base date,” maybe we could call it, I don’t know, daysAfterBaseDate? So would anyone want to try to take a stab at code where it makes sense to print variants of a value this way three times, and happen to add two to it in the process? That is, what meaningful variable name could you put there in place of “i" that makes this statement make a lick of sense?

I can’t think of one either.

Saturday, September 13, 2014

Schedule Fall 2014



Week 1 (ending 9/14):
Emacs basics 1
Linux 1-4
Python 1-3
Git 1, 2.1-2.4

Week 2 (9/21):
Emacs basics 2
Linux 5-7
Python 4-5
Git 2.5-2.8

Week 3 (9/28):
Linux 8-10
Python 6-7
Git 3

Week 4 (10/5):
Linux 11, 13-14
Python 8
Git 4.1-4.5

Week 5 (10/12):
Linux 15-17
Python 9
Git 4.6-4.11

Week 6 (10/19):
Linux 18-19
Python 10
Git 5.1-5.2

Week 7 (10/26):
Linux 20-21
Python 11
Git 5.3-5.4

Week 8 (11/2):
Linux 22-23
Python 12
Git 6.1-6.4

Week 9 (11/9):
Linux 24-25
Python 13
Git 6.5-6.8

Week 10 (11/16):
Linux 26-27
Python 14
Git 7.1-7.2

Week 11 (11/23):
Linux 28-29
Python 15
Git 7.3-7.5

Week 12 (11/30):
Linux 30-31
Python 16
Git 8.1

Week 13 (12/7):
Linux 32-33
Python 17
Git 8.2-8.3

Week 14 (12/14):
Linux 34-35
Python 18
Git 9.1-9.4

Week 15 (12/21):
Linux 36-37
Python 19
Git 9.5-9.8

Saturday, September 6, 2014

Books


The books that I'm going through are all available for free online.

Think Python, Allen Downey
The Linux Command Line, William Shotts, Jr.
Pro Git, Scott Chacon

I may add more references as I go, but I think this is what I'm going with.

The Editor War


As someone who isn't a native of Unix-land, I see the great divide: some people choose vi as their text editor of choice and some choose emacs. My belief is that which you choose largely depends on who taught you to use an editor – you adopt their choice and make it your own.

I'm coming to the editor war armed with the internet, but without a guide. How am I supposed to choose between these two? I used each of them briefly and did a little reading, and here's what I found and what I thought:

1) Several of the keys in emacs correspond to keys in the shell, like CTRL-K killing to the end of line. It'd be nice to have a leg up on learning keys for the shell.
2) The biggest thing I saw people complain about when saying why they use vim is startup time. I feel that this isn't as much of an issue as it used to be: “slow” starting emacs starts in less than a second in my VM. Maybe this was a big issue 25 years ago, but not so much now. It'll be even less of an issue in another 10 years.
3) The second biggest thing I saw when people said why they used vim was that emacs had “stuff they didn't need.” For me, this falls pretty directly into “things I don't care about.”
4) You can extend emacs with an emacs-flavored Lisp. I wanted to take another look at Lisp anyway.
5) Vi has modes: either you're changing text or you're not. I'm not used to it, and don't care for it.

OK, so it's clear that I'm going to...wait, what? We're not done? OK.

6) The biggest problem people should have with emacs is the control and alt keys, which are used for everything, so much so that they got sick of typing “Ctrl” and just went with “C”. Save the file? C-x C-s. Exit? C-x C-c.
7) Vi can be extended in different languages, but it looks like you have to recompile it and link them together. I'm not sure how this works yet.
8) It looks like people generally agree that making changes to files is generally quicker in vi.
9) Vi uses Esc to get out of edit mode, which I don't like. It looks like it has Ctrl-] as an alternate key for that.
10) I don't really care about most of the things that I know are built is an extras to emacs, like a news reader. Yeah, in the 80's I would have liked that. Now not so much.

Looking over my list, it seems like emacs is pretty much still the clear winner. Except for one thing: the darn keyboards. All the keyboards I've used have a shift on the right and a shift on the left. Capital A? Right shift. Capital U? Left shift. And all the keyboards I've worked with have the right shift in the same place, or at least close enough that I can use it without thinking too hard.

The Ctrl key is different, though. On some keyboards, the right Ctrl key is here. On others, it's over there. On others, it's gone completely. That means that in order to use emacs effectively when switching computers, I'm going to have to learn to use the left Ctrl key. Ugh. Left Ctrl-x Ctrl-c? Yeah, I'm afraid that's not going to work for me. I'm going to go with vim.

--
 
Update: I've waffled and am going with emacs. I'm going to make my Caps Lock key an extra Ctrl and see how that goes.

Installing VirtualBox and Ubuntu

I largely went with recommendations that I see on the web for how to get started with a Linux distribution on a VM. Several people recommended VirtualBox, so I went with that.

IMPORTANT NOTE if you're following along at home: The current version of VirtualBox that is available is 4.3.14, which didn't work at all for me. It has a bug (described here) which prevents it from working properly on a machine using antivirus software. Your choices seem to be to install a test build that might work or an older version. I went with an older version (the "VirtualBox older builds" link on the VirtualBox install page).


There are a bunch of Linux distros to choose from. I decided that I largely don't care which distro to start with: it's better to make progress with one than to be paralyzed by indecision. I saw several people recommend Ubuntu if you're new to Linux, so I decided to go with that. There are instructions that walk you through installing both VirtualBox (but see the note above) and Ubuntu, like here. The install was pretty smooth for me, but I did find out first hand that if you create a virtual machine and remove the "GB" from the disk size, it doesn't default to GB. (I think I made to 40 MB disk. Oopsy.) No big deal: delete and try again.

Make sure to install the guest additions (in the like above that installs VirtualBox and Ubuntu). The instructions I followed didn't include that, and I ended up with a little bitty screen with no resolution changes available.

Self Assessment


OK, self assessment time. I'm a 45-year-old software developer, working almost exclusively in C# and Windows Forms. I like my job, my reasonably high responsibility level, my coworkers. Assuming that my workplace doesn't change much in the next 10 years, I hope to still be working at the same place I am now when my youngest graduates high school.

We had a VAX in college, and that was mostly what I used: a mainframe that seemed reasonably powerful for its time (was it? I'm not even sure), but would be put to shame by most of today's laptops. I got a job at the help desk. People would come in with random problems, and I'd try to help. I knew BASIC and Fortran when I was hired, and not much else. There were a handful of things we were trained for specifically, like creating accounts. After that, though...maybe you knew the answer to some questions, and maybe you didn't.

So I poked at languages. I took classes that used Pascal. I picked up some other languages on my own, like C, Prolog, Lisp, TeX (yep, it's a full language!), and C++. Most of them I only picked up well enough to write simple programs. C was the exception – I knew everything that was in the standard library, and used this as my native computer language. I learned things that people had questions about, like the editors people used on the VAX, the language behind one of the editors, DCL (the command line interface for the VAX), a graphing package, and a statistics package (and just enough statistics to use it).

There were other machines around campus that I didn't use so much: Macs, PCs, and Unix machines. I didn't learn much about them while I was in school.

Since then, I've worked on Windows in all my jobs. I learned a fair amount incidentally, and picked up a reasonable amount of knowledge. C# is now my native computer language, and I know it pretty well. I'm a better developer than most. However, I haven't picked up as much as I could have if I had been more actively seeking improvement.

When I thing about things that I've learned, it strikes me that at the time I didn't know whether that information was going to help me or not in the future. I know DOS to a reasonable level, but not as well as if I had known 20 years ago that I'd still be using it on and off today. Several of the languages that I learned I haven't used since learning them, unless you count knowing them well enough that when we hit them in a Computer Languages course in college I didn't have to worry about it. The graphing package? Useless. The stats package? Useless. The VAX, DCL, and the editors that I used there? Useless.

The trick here seems to be in two parts. The first part is that you don't know ahead of time what pieces of information are going to be handy later. I learned some things in college that were useful, and have built on a foundation that I'm still using today. The second part is that it makes sense to focus on something that you think may be useful in the future. A cheap way to do that is to put some of your effort into something that hasn't changed much over time.

While the VAX has pretty much died off, Unix is still around in a bunch of flavors. OS X is a Unix-based OS, and Linux is a free Unix clone.

So here's my plan for the year (which I've already started on):
1) Install Linux as a virtual machine on my PC.
2) Learn Python.
3) Learn one of the text editors for Linux.
4) Use source control even when poking around on simple tasks, even if it means replacing one trash file with another.
5) Document what I'm doing, more or less. Explicitly evaluate what I think of Python, the text editors, etc. My opinions will be ill-informed at first, but they'll hopefully evolve as necessary. Sometimes it's not as easy to evolve. For instance, you need to pick a text editor: it doesn't make sense to me to learn VIM and Emacs well. I've already chosen a “winner” on this one, which I'll discuss in another post.

I have installed Linux. I've starting poking at Python on Windows, but I'll do  future work here on the Linux VM. I've also scratched the surface of the two most popular text editors (I can open, change, and write files). I haven't used source control yet on Linux: I understand that git will be my friend.

For each of these, I'm going to go through a book (probably an online book) or document from beginning to end. I don't want to pick up a fair amount and then say, “Hey, look! There are all these shortcuts that I never knew” two years later. I'm not looking to race through anything: this isn't supposed to be a checklist, but things that I'll have as solid skills when I'm done.