Showing posts with label Programming. Show all posts
Showing posts with label Programming. Show all posts

Friday, December 30, 2011

C++ and Automatic Garbage Collection

Programmers know about the mental state commonly referred to as “flow”. In this state, we are most productive, by a significant margin. This state is, of course, not limited to software development, and is well known in most creative pursuits. 
For example, I’m currently writing this article in a program called Scrivener, an excellent writing application targeted at professional writers - the kind that write novels, screen plays, etc. It has a special mode, called “full screen composition mode”, which I’m using at the moment.  In this mode, there is nothing on the screen except a blank white page. There are no formatting buttons, no word counts, no tasks bars, and certainly no talking paper clips. It is completely optimized for doing one thing, and one thing only - writing. Everything else is hidden away.
This Scrivener feature is there to help writers get into “flow” mode.
To enter this mode, you focus, completely, on the task in hand. And such a complete focus is not easy to establish. An incoming phone call, even if ignored, is more than enough to destroy it.

Focus is about saying no to the things which aren’t important right now. 

This is not a new concept, nor was it discovered by Steve Jobs. Learning to focus has been a very important step in Buddhist meditation techniques for thousands of years.
Of course, Scrivener is not the only tool that helps people focus. Another excellent tool more familiar to programmers is vi. This editor is not famous for ease of use, but once the learning curve is overcome, the editor is excellent at getting out of your way and becoming invisible. People report that vi helps them enter this productive zone, and I can attest to this myself.
Some programming languages also help you enter the zone more easily. Remember, getting into flow is completely focusing on a task. This is why for different tasks, some languages are better suited than others, with regard to flow. It is all about what the language chooses to hide from you. For a high level task, Python is probably a better choice than C, because it will be easier to enter a productive mental mode in Python without worrying about remembering to call free().
A great many people claim that the single greatest benefit for programming productivity in recent decades is automatic garbage collection, as seen in managed languages, such as Java and C#. Let’s ignore the fact that McCarthy invented it for LISP way back in 1959. This is an enormous benefit because today programmers focus on writing the code they want, and they don’t have to think about managing memory. The language hides it away.
A great many people, myself included, claim that C++ is a bloated language. They also claim, myself excluded, that C++ is terrible because of the manual memory management. It certainly is a great burden to manage memory manually - it is generally difficult to do correctly and it also makes it harder to enter the precious mental state we all covet, because it’s one more thing to worry about. But it is simply not true for C++.
It is true that in C you have to manually manage memory. It is true that 10 years ago, most people managed memory manually in C++. However, today this is no longer true.  Unfortunately, most Java/C# lovers, C++ haters, miss this fact.
More importantly, they miss out that the Java/C# promise is horrendously broken. Consider the following code snippet, taken from the book Release It  by Michael T. Nygard, page 33:

This Java code has  a bug in it. In this particular case, this bug caused thousands of people to wait for hours and hours for their flight and caused major financial damages to an airliner. 
The bug is that java.sql.Statement.close() can throw an exception. If it does, then the close method of the connection is never called, and a resource is leaked.
In Java/C#, code in the “finally” block has to be managed C-style. But C doesn’t have exceptions, and exceptions complicate resource management by an order of magnitude. Exceptions are critical. Exceptions change everything. There are work arounds in Java and C#, but they are just that - work arounds. They aren’t pretty!

http://www.flickr.com/photos/91256982@N00/4681092063/

The real problem here is that the garbage collector isn’t like a person walking around with a giant garbage can, cleaning up. A garbage collector, in Java/C#  at least, is like a person walking around with a giant plastic recycle bin, cleaning up after scattered bottles. He ignores all those copies of yesterday’s newspapers and the empty tuna cans.
A Garbage Collector should collect all garbage, and garbage is defined as any no longer needed resource. And a resource is not just a piece of memory (with the book-keeping that comes with it). A resource is also a file handle, a DB connection, a no longer needed synchronization lock, etc.
C++ shines here, because C++ has a built in garbage collector that manages all such resources. Yes, you heard that right. C++ has a built in garbage collector. In modern C++, most programmers never, ever, have to write “delete”. The “delete” keyword went the way of the dodo. It went the way of the goto. 
The same mechanism used for managing memory can be used for managing any kind of resource.

Focus is about saying no to the things which aren’t important right now

In Java, resource management is rarely not an important thing to think about.

Friday, October 9, 2009

What You Have You Keep

The second law of thermodynamics states that in an isolated system, entropy is an increasing function. In his book, Do Androids Dream of Electric Sheep, Philip K. Dick talks about fighting entropy, or Kipple, as he calls it:
Kipple is useless objects, like junk mail or match folders after you use the last match or gum wrappers or yesterday's homeopape. When nobody's around, kipple reproduces itself. For instance, if you to go bed leaving any kipple around your apartment, when you wake up there is twice as much of it. It always gets more and more.

No one can win against kipple, except temporarily and maybe in one spot.

I've found that there is much truth in the Kipple Theorem. Just think of your house, which contiguously gets more cluttered over time. The same also happens to source code, if left to its own devices. It is also true of memory, which gets disordered over time. What was once clear and orderly, becomes obscure and messy.

Over the past couple of weeks, I've tried to always put something back in its place whenever I go from one room to another. When I do this with disciple, my house starts to look much better. A couple of days of slacking off, and the house looks once more like a total mess. And I don't ever remember making it a mess. It's just that kipple does multiple while you're asleep. Unless we take active, continuous action to combat it, kipple will always win.

Source code is no different. It grows smelly over time. No matter what your source control's log tells you, changes are constantly taking place. They make the code more unreadable, make methods more incomprehensible, and occasionally even introduced some bugs in unimportant locations.

The same is true when learning things, such as Japanese. I've studies nearly 400 kanji characters over the last couple of weeks. Unless I take active steps to maintain what I've learned, my neurons start getting all bogged down with kipple. That's why I am very fanatical about reviewing the items in my SRS software every day. Left alone, for even a little bit, the kipple raises its ugly head and starts to take over.

Kipple Fighting 101

When you learn chess, you basically have to study three different stages - opening, middle game and end game. For the opening stage, you basically memorize the known openings, which have already been studied thoroughly. During the middle game you need to understand basic principles and how to implement them. The end game part is usually kind of a mixture of the previous stages: memorize principles for different scenarios.

One of the most basic scenarios in the end-game is the one where you have a king and a rook and the opponent has only a king. It is very easy for you to win now. But, to make things explicit, the guiding principle is to always prevent the enemy from returning to territories from which he retreated. When the enemy king moves, you make sure he cannot move back to where he once was. You corner him into closer and closer areas.

In the endless chess game against kipple, the opposite is true:

What I have, I keep!

This means an endless game of maintenance. You've learned a new word - make sure you review it periodically. You finished cleaning the kitchen - make sure it stays clean. Constant vigilance is the key to winning this battle.

Whenever you go over source code, you will encounter kipple. It is your responsibility to engage it immediately. No matter what your current objective is, you must spend some of your time chasing and destroying the kipple. Otherwise, the kipple will take over the code base, and before you know it, no one on your team has a clue what does what.

Wednesday, February 25, 2009

Why Not to Write Shell Scripts

Don't write shell script. Not in bash, and not in any other shell. There are two very simple reasons for this:
  1. They are not portable.
  2. They are hard to read.
Nowadays, we have a much better option - write those same shell-scripts in a cross-platform scripting language, such as Python or Perl. These languages are much easier to read than some devilish combination of awk, sed and a cryptic syntax. Well, Python is. But Perl can be readable too, contrary to common wisdom, if a bit of care is taken when writing the script. Sure, most shell scripts use some really neat tricks & hacks, but let me quote Brian Kernighan:

"Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?"
Brian Kernighan

(If you follow the link, you'd see Mr. Kernighan has a hand or two in the scripting pot himself. Oh well...)

In my experience, even the most temporary script ends up expanding beyond its original intention, and thus needs to be modified and maintained. Shell scripts are just not the right tools anymore.


Further Reading
  1. Python, Subprocess and Multiple Arguments
  2. Programming with VI

Saturday, February 21, 2009

Programming Editors

I've used a wide range of programming editors throughout my life. From the glorious copy con and QBasic of the DOS days, through the Turbo C of my teenage years, including the emacs of my college days and the Source Insight and Eclipse of my professional career, one thing is clear:

I was a terrible IDE user

This means that I rarely used, or even knew of, more than 5% of the features of each IDE - excluding (maybe) the glorious copy con editor, of course. I can still remember the shock at watching someone else debug code by using a debugger (!!!). Turns out there was one right inside Turbo C all along.

And then came along The Pragmatic Programmer, which is a phenomenal book. One of the things they recommend is to choose a text editor and learn how to use it. Learn how to use it real well. Which is why, I think, having a learning curve that's a bit steep is a good thing.

In college, after the first year the emacs police got off of our backs, and we could use eclipse. Many people did just that. I didn't - I had been forced to endure emacs for too long, and had to pay too many hours to learn the likes of "Ctrl+X 2", that I just didn't want to learn how to do it all over again (I still don't know how to do it in eclipse). This was, of course, a stupid idea. But to rationalize why everyone had red squiggly lines below their errors as they typed and I didn't, I had to learn emacs just bit more in depth. Or at least spend hours talking to the emacs psychiatrist, which eclipse doesn't have. Take that eclipse!

The problem was that I never really liked emacs. It can do horrible thing to your keyboard's CTRL key. And I never liked it's MS-Word philosophy of putting together one huge application (or OS) instead of many small programs which can be bundled together as you see fit. And getting a decent copy outside of unix-land is always an annoyance, even on my Mac, which is a citizen of unix-land, kind-of. I still hate programs that are several mega-bytes overweight. That's why I'm switching to vi.

So far, I really, really like vi. The whole normal mode is great for touch-typing - no more reaching out for the arrow keys (or the CTRL key). It's a nice programming editor, though I still have a lot to learn. My main IDE is still Eclipse, and although its C++ support is sketchy, it will probably take a while before I'm proficient enough in vi to give eclipse up completely.

Above all, I still miss Source Insight, now that I'm on a linux machine. It's probably the best editor for a large code base. It's one of the most ugly editors, but when most of the code is already written, it can't be beat. But now I mostly write new code, so it's not too bad. I'm good with vi.

But I still don't know how you say Ctrl+X 2 in vi...

edit: it's ":split filename"

Thursday, February 19, 2009

Project Euler

I've just stumbled upon Project Euler. It's a nice little site with mathematical puzzles to be solved using a computer. For example, this first problem is to find the sum of all the natural numbers who are multiples of either 3 or 5, and are below 1000.

There are hundreds of such puzzles, most of them more challenging, so I'll allow myself to post the answer to this first problem:
#!/usr/local/bin/python
sum = 0
for number in range(1, 1000):
if number % 3 == 0 or number % 5 == 0:
sum += number
print sum

And what is great is that once you solve a problem, you get access to a pdf file with an overview of the problem and efficient solutions. The above solution I wrote, which is quite naive, can be computed in O(1), had I first used a pencil and paper as my IDE, and not Vi. Can you see how?

Tuesday, February 17, 2009

Programming with Vi

This page will serve as a place to store my notes on using vi as a programming editor. And when I mean vi, I really mean vim, but these days I think it's pretty safe to assume vi=vim. I'm placing these notes on the web in the hopes that it may help other programmers new to vi, as I currently am. I will update this page with information I find useful.

The Two Modes
The most important concept to understand about vi is that it has two separate modes - command mode and insertion mode. This originally struck me as rather cumbersome, and I found my self working nearly completely in insertion mode. You can get along like this. You can also write C++ code in Microsoft Word. There's a really good reason for this separation - because command mode is separate, the commands are much simpler. For example, navigating around the document is really easy:

Navigation
j - Move one row up
k - Move one row down
h - Move one column left
l - Move one column right
w - Move to the start of the next word
b - Move to the start of the previous word
e - Move to the end of the next word
0 - Move to the beginning of the line
$ - Move to the end of the line
1G - Move to the beginning of the file
G - Move to the end of the file
% - Move cursor to matching bracket

The jkhl commands may seem quite stupid. There are arrow keys after all. But if you know how to touch type, you'll find that this really improves your productivity. It takes a bit getting used to, but it really pays off, in my opinion.

Like many commands, you can add a number before a navigation, so that 4j moves you four rows down.

Undo & Redo

u - undo last change
Ctrl+R - redo

Copy & Paste

v - enter visual selection mode. Moving the cursor will select text for later actions, such as:
y - yanks the selected text. aka, copy
yy - yanks the current line
p - paste text

Multiple Windows
:split filename - split a window and open filename
:vsplit filename - split a window and open filename

Running Shell Commands
:!make - executes a shell command, such as make
:r !ls - executes a shell command and pastes the output into the file

Search & Replace
/expression - Searches for expression
:%s/expression/newtext/g - Searches for expression and replaces it with newtext

Configuring The Environment
:set nu - shows the line numbers
:set nonu - don't show the line numbers
:colorscheme - changes the color scheme
:set sw=4 - sets the tab size to be 4 spaces

All these commands can be placed in ~/.vimrc

References
  1. Yolinux is always a good source
  2. Run vimtutor for a good hands-on tutorial

Thursday, January 8, 2009

TBB and Non-Integer Ranges

I've been using the Intel Threading Building Blocks (TBB) library for a while now, and I finally figured out how to overcome one of the annoyances I had with it.

All of the examples I've been able to find show how to iterate over a range of integers. I couldn't find how to directly iterate over a range of doubles. I worked around this by iterating over integers and translating back to doubles in the inner operator() function. I finally figured out the answer, after reading the Reference Manual (as they say, rtfm).

The trick is that the blocked_range construct can accept, in addition to integers, random access iterators. So, with a range:


tbb::blocked_range< std::vector<double>::iterator > ( bunch_of_doubles.start(), bunch_of_doubles.end() );

I can now parallelize a group of doubles.

Of course, this assumes that you have a container ready. Luckily, I happened to have one ready. In other cases, it's probably best to continue and shuffle between ints and doubles.

Monday, November 24, 2008

Bash: Passing Arguments with Quotes

Today I needed to write a bash script that eventually calls another program, passing all the arguments to it. It seemed like a simple enough task: just use $@. However, the problem was that the program accepts arguments surrounded with quotes, and the $@ stripped the quotes away. I was really surprised that google didn't immediately find an answer.

Finally I reached this forum:
http://www.linuxforums.org/forum/linux-programming-scripting/62564-bash-script-problem-preserving-quotes-arguments.html

And to save you the trouble, here's a script that preserves the quotes:
#!/bin/bash

# blah blah blah

./foo "$@"


For more on posts, see here.

Friday, October 31, 2008

Languages

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration."
Edsger W. Dijkstra (SIGPLAN Notices, Volume 17, Number 5)

If you think about it, and please do just that right now, then you'll probably notice that you use your native language to facilitate the thinking, at least to some extent. Taking this observation to the next step, how much does our native tongue influence our thought patterns, and how we perceive the world around us?

This is not a new question. There's even a theory in linguistics which studies this question, called the Sapir Wohrf hypothesis. In fact, George Orwell, in his classic book "1984", has a whole new dialect, "Newspeak", introduced by Big-Brother to aid in preventing "thoughtcrime". This imaginary language is unique in that it attempts to reduce its vocabulary, thus intending to limit thinking patterns.

A couple of years ago I heard a lecture (in hebrew) by Physicist turned Computer-Scientist, Prof. Naftali Tishbi, on some of the research he's conducted on languages and their affect on thought (and vice-versa). Since then, the subject has been sitting in some corner of my brain.

A couple of examples:
  1. When a procedure that I already know is coined, I can understand and use this procedure much more easily. For example, in Origami, the term "Double Rabbit Ear" allows my brain to much more easily choose an appropriate course of action, rather than just remembering some sequence of folds I've done before. In programming, that's exactly what Design Patterns do. I've used the Factory pattern before, but coining it made it more accessible cognitively, and it's now much more easy to notice when this pattern is appropriate.
  2. When attempting to solve a programming challenge, the choice of language affects the solution. This is taken to a very interesting extreme in LISP, where the first step to solving a problem is to create a new language tailored specifically for it.
There is no doubt that what programming languages a developer knows critically affect the quality of the solutions he'll be able to come up with. Until I learned Perl, I wrote simple text processing tools in C. The results were buggy programs which took too much time and thought to write.

But it is much deeper than this. A programming language affects how we even think about problems. Knowing several programming languages is important in developing our own minds and allows us to better think about problems. This is not new. Edsger W. Dijkstra already talked about this in his excellent 1972 lecture, "The Humble Programmer".

So, my resolution for the following year is to learn two new languages. While I think I know enough of Perl to get what I want done, I'm no expert in it, mainly because I don't like too many $ and too few letters. That's why I'm going to spend the next year studying Python. And I intend to really study it, inside-out.

I have a full-time job, a wife, some non-programming hobbies, an obligation to write a computer game, but I intend to follow through.

Funny comic from www.userfriendly.org, August 15, 1999

The other language I'll be learning is Japanese, by the way.

Saturday, October 11, 2008

Active Learning

"Reading, after a certain age, diverts the mind too much from its creative pursuits. Any man who reads too much and uses his own brain too little falls into lazy habits of thinking."
Albert Einstein

It's been several years since I realized I don't know anything. Occasionally, I make the mistake of thinking I know something pretty well. Reality always reminds me that I don't, usually using a sledgehammer. So I keep trying to learn. I read blogs and even (gasp) books. In fact, I even spent four years in what some people say is a pretty decent university. I even managed to surround myself with people who are way smarter than myself at work.

The thing is, you can only learn so much from other people. Consider Tom for example. He wants to learn a bit about thermodynamics and the heat conductivity of various substances, say, a human hand. It doesn't matter how much he reads Fermi's book, or even how much he hears lectures by distinguished professor Mom. In fact, said professor told Tom just last week that touching fire is dangerous, because fire is very hot. Now, Tom is a very intelligent boy for his age. His mother told him so, as a matter of fact. Yet, all of the theoretical knowledge he's learned won't stop him from trying to touch the flame with his hands. Only after such an experiment will Tom really understand that the heat conductivity of the human hand is, well, ehm. It hurts. That's what he'll finally learn.

My point being is that the only real way of learning something is by doing. That's why work is so much more tiring than a university lecture. In a lecture, you sit passively and listen. You can cover more material faster this way, but you don't really learn anything this way. Work has that annoying aspect wherein you actually have to work.

I'm not against reading books. I really love books. I am, after all, a nerd. Reading books is important. But it's not enough. You have to learn things the hard way.

So I'm going to write a game. I don't know too much about it yet, but that's what I'm going to write in the spare time that I don't have. A game is a good subject, because it covers nearly every imaginable aspect of Computer-Science and software development. I've already finished the dreaded Requirement gathering process. Here are the games requirements:

  1. It should be a game.
  2. I should finish it.
That's it. Now to start codi, em, I mean, designing. Yes, that's what I mean. Designing.

Sunday, September 21, 2008

If You Can't Test It, You Can't Program It

A well known axiom of business management is: "if you can't measure it, you can't manage it". I believe there is a software development corollary:

If You Can't Test It, You Can't Program It

At a first glance, this may seem stupid. You can program what ever you want to. But programming is about making the computer do what you want it to do. And computer have been scientifically proven to be bizarre, unpredictable creatures. They do what you tell them, and not what you think you told them. Unless you test, you can never know if you got your message to the damn computer.

And because source code is a dynamic, ever-changing being, you have to test and re-test and double re-test. That's why you need Unit Tests and Regression Tests. But that's for another post...

Monday, August 25, 2008

Programming by Coincidence

In their excellent book, The Pragmatic Programmer, Andrew Hunt and David Thomas have a section on "Programming by Coincidence". Although their book is jammed with useful tips, I think this is one of the most important ones.

Recently, I had a deadline for a large university project. Since my class partner and myself both have jobs, we really had to stretch ourselves to finish the project in time. This included a 30 hour sprint to finish the damn thing before the deadline. Programming in such conditions is always, shall we say, interesting. Despite the hour, I was actually able to catch myself programming by coincidence.

So what is Programming by Coincidence (PbC)? I'll try to explain.

It is well known that the best way to solve a maze (the ones you find in children magazines) is to start in the end, and work your way backwards. I've always favored a similar technique for solving logic problems - first you find the solution, and then you go back and understand why its the solution. This is not as silly as it sounds. Most logic problems can be solved using brute force by a 10 line computer program. But, as I've learned the hard way, this is the path to the dar, erm, programming-by-coincidence side.

So, a logic puzzle analogy to PbC is to start guessing solutions, and hope you stumble upon a correct solution to the puzzle at hand. The catch and downfall of logic-puzzle PbC practitioners is that, although a correct solution is found, no real understanding is gained. Even if, after finding a solution, one tries to understand the solution, all reasoning will be biased towards the known solution.

The flaw in my maze analogy is that solving a maze backwards is just a technique for finding the solution. The maze end is not the solution. The path is the solution. So there is no real correlation between the two.

In programming, PbC is similiar. It mainly involves guessing, finding a working solution, and then moving onwards to the next task. The problem is that the set of working programs is quite huge, but the set of good working programs is much, much smaller. If we don't truly understand what the problem is, why our solution works, then we're PbC.

And the danger of PbC is that things start to break down. Making changes in one place results in unit-tests failing in completely unrelated locations (you are using unit-tests, right?). This is a symptom of many software development problems (tight coupling, for example), but also of PbC. Many times, hacked together solutions work because of bugs in other people's code, or non-standard behaviour. When that changes, a once working solution a zillion lines of code away stops working.

If, instead of taking the trial and error path to finding a solution, we were to take a step back, look at the big picture, understand how everything fits together, and then think of a correct solution, then we wouldn't have such problems.

And I must confess that after 25 hours of coding, I knew I was PbC, but I kept at it, frustrated as I was. Lukily for me, my project partner is more experienced, and he had the sense to call a full stop, until we really understood the problem, and only then did we start looking for a solution.

Wednesday, August 6, 2008

Creativity and Constraints

This post has moved! Please click here and update your bookmarks.

Although my university obligations are enormous at the moment, I find myself drawn back into the Origami world. Thus, I came across this month's challenge on the Origami Forum - fold something cute. This brought me back to a subject I've given quite a lot of thought to over the last few months - the importance of constraints to creativity.

This a fact that I keep bumping into, and I'll give a few examples.

1. At work, we've had to decrease the memory consumption of our product by an order of magnitude. This resulted in some very creative solutions by the team, which I think will also result in a better product overall.

2. Parkinson's law states that no matter how much time you allocate for a given task, then that's how much time that task will take to complete. This means that what could have been accomplished in a week can take a month, without necessarily any added value introduced.


3. The limitations posed by Origami on the designer forces one to think on what exactly defines the subject. I've seen too many cats and horses which end up looking like dogs. So think about it - what is it that makes a cat, well, a cat? For example, I made a human model several years back, and it turns out it's an Elvis. Because of the hair, you see?

4. There's a phenomenon here in Israel, which I suspect happens elsewhere in the western world, where parents attempt to give their children everything they didn't have growing up. This has many downsides. Children growing up without having to work hard in order to succeed will have a hard time coping with the real world, where nothing is given for free. That's why we see so many people still living with their parents well after the age of 18, or not working, or spending more than they earn, or many other things. Count me guilty!

I think I could talk about the last example quite a bit more, and I've obviously made a lot of simplifications and generalizations, but I hope you get the idea - boundaries, limits and constraints are good.

I'm sure I'll write more about it, but right now I have to think what exactly defines "cute".

Friday, July 11, 2008

Blogging 101

At 27, I'm an old man.

I guess I've been living under a rock or something - I have no idea what's "hot" in technology these days. I'm new to blogging. I only have a general idea what the whole RSS thing is and I don't know what technorati is. I barely even have a facebook account.

Now, this is a problem for me. I program in c for a living. I like c. I've been programming in it for over 10 years. And I recently found out that people don't really program in c anymore. Now this didn't surprise me. I knew that. I was surprised, however, that people don't even program in C++ anymore. They program in Java or .NET. This really blew me away.

I'm taking an advanced course in Object Oriented Design. You know - design-patterns, AOP, UML, etc. It's been a real eye opener into just how far removed I am from what's been groovy since, well, I was 18 years old. I really am old.

And now I'm writing a blog. I have a lot of catching up to do. Not just in learning what a trackback is, but also in what tools to use. Tools are important. Very important. I think I'll probably have to write more about that later on, but for the time being, I need to find myself some good tools to help in blogging.