Archive for August 2010

Learning notes from a C++ n00b – Part 1

August 25, 2010

I am primarily a Java developer. My college decided in my sophomore  year to switch from C/C++ to Java for most of the classes. While it did give me a very good foundation in Java development, it created a bit of a gap in my education. While I’ve done work in C in the past, I haven’t had the opportunity to work on a serious project in C or C++. Since my goal is always to learn a language a year, starting now C++ will be that language. It should be exciting.

Get excited by vintage letterpress

I'm excited. Are you excited? You're probably not. You're probably thinking "Why don't you already know C++? What sort of developer are you?" Well to find out, you should keep reading!

This post is the beginning of a series describing my process of exploration and discovery into the wonderful world of C++ from the perspective of a Java programmer. I imagine that some people who know C++ and Java are getting out popcorn waiting for the inevitable meltdown with dealing with things like memory leaks, makefiles, platform differences, and probably a bunch of other common issues I know nothing about. While that may eventually be the case, I’m not there yet.

Immediately, one of the biggest departures between Java development and C++ development is the change in IDE. For Java development I’m a big fan of IntelliJ IDEA. Java has a lot of import statements that involve very long package names and an IDE like IDEA tends to take care of that for you. Refactoring, like changing method or class names, is easy since I don’t need to manually find all usages and change them. Autocomplete and click jumping to method or class definitions is also very handy. The integrated debugger is useful when needed, and I like that it can easily import maven pom files as projects. While I’m definitely a proponent of being able to program in your language without an IDE (you shouldn’t let your IDE program for you), it still can be a useful tool at times.

My new IDE for C++ is vim. Ok, I don’t know if I’d really call it an ‘IDE’ exactly, but it’s my editor. I like vim overall, and I’ve been an avid user of it for about 7 years, so I can maneuver my way around. After reading about ctags, I wrote a script to generate them so that I can use it to jump between functions and methods. I’m pretty sure I’m not using it correctly however, as I have a tags file in each directory and I think the editor doesn’t always pick up all of the tags files I want. I have no idea how to use a debugger, and dealing with import statements is still a pain. Overall though vim is very fast and never hiccups unlike IDEA, so that’s a plus.

Another large departure from Java development is going from maven to makefiles. In Java I can create a maven pom.xml file to list all of my dependencies and plugins. Maven supplies a natural file structure that I can use to arrange my files into packages and place external resources in a place where the classpath will pick it up. There are tools to automatically create stub maven projects that I can just jump into and start coding. I can have any tests in my test directory automatically run just by calling mvn test. I can compile my project using mvn compile, and I can package it all up into a nice jar or war file by using mvn package. These are all default things that come with maven. It takes care of running the javac command to compile my code. It also sets up a testing environment for running tests. A very handy tool.

So makefiles. Makefiles sort of remind me of ant. I never really got into ant because it’s fairly verbose. It requires you to be more explicit in telling the system what to do and how to do it. Really though, makefiles are a bit less useful than ant, as they seem to be more like elaborate shell scripts that use the make utility to run. I still have to put in all of the g++ commands, along with lines of what libraries and other sources to give to the linker. Dependencies have to be accounted for manually. Tasks like clean or test have to be defined along with instructions for what those things actually do. There is no standard setup with clean interfaces for running tests or setting up your file structure. The main positive aspect that makefiles have over maven pom files is that a single makefile can generate several different deliverables (pom files only create a single jar).

I know that there are tools such as autoconf and automake that is supposed to make makefiles more portable to deal with library issues, but they’re not very easy to use. The GNU tool chain has a fairly extensive manual, but it feels like one needs to read the entire thing before even getting started. I haven’t had the time, so the GNU tool chain hasn’t entered my arsenal yet. I’m still not sure how to deal with the library distribution issue, but I’m sure that will come with time.

This is the book I'm currently learning C++ from. It doesn't get into the surrounding tool chain like make or the compiler much, but it's still useful for the language itself.

I’ve only been really looking deeply into C++ for a week or two now, and there are a lot of questions that pop into my mind. I have certain philosophies dealing with programming that I’ve gained over the years. A lot of those practices have been fueled by ideas from the Pragmatic Programmers. Others I have developed on my own. I’m still uncertain as to how to incorporate some of these ideas in my C++ development.

The first and most important of these is unit testing. Java has some very standard unit testing frameworks with JUnit and TestNG. Boost has a library for unit testing C++, and so does Google Test, but I have yet to delve into either of these deeply. Also I’m not sure if there’s a standard way of running tests like you can find with Java. Making sure that each test is in its own section in a makefile doesn’t seem very appealing. Hopefully I’ll find a nice way to easily unit test code (including using mocks), I’m just not there yet.

Also, how do you profile C++ code? I’ve used a tool called yourkit for Java which works very well. I know that there must be profilers for C++, but I don’t know what they are or how to use them. Similarly, debugging is an area that is still very grey. I know that there’s gdb, but I haven’t found a good tutorial on how to use it or how to integrate it into vim or some other editor to set breakpoints and see variable values.

And honestly, while I understand the basic concepts of pointers, I’m still unsure as to when to use them and how to fully utilize their functionality. In Java everything is done by reference (except primitives) and there’s a garbage collector when items go out of scope. When passing any object to a method, it can be modified by that method. I still need to learn a bit more about how scope effects both objects created on the heap and other objects in C++.

Overall there has been a lot of learning in the short time that I’ve been playing around with C++. While I’ve used Objective-C in the past for some iPhone programming, I haven’t really seriously taken on any projects in C++. The learning experience has been great, and quite a bit of fun. While most people would probably argue that makefiles are really annoying to set up, I’ve been enjoying the learning process of figuring out how to use them and creating working builds. My tests have all been small at this point, but they’re sure to grow in size. That said, I know I still have a lot to learn. I shall be delving deeper into the Boost libraries and doing multi-threaded programming with some asynchronous socket connections. I’ll be sure to update again after having gained a bit more experience.


August 16, 2010

Back when I was learning programming and software development in college, I began a practice of learning a new programming language every year. I started with Java, then moved to Perl, C#, Visual Basic, Python, Ruby, Groovy, Scala, PHP… etc. I still think it’s a good practice for every developer. It’s even a recommended practice by many other developers on how to stay in your game. You don’t want to be stuck in a situation later on in life where you have to quickly learn a new language (including new concepts) after you’ve been using the same one for decades. The COBOL programmers learned that about a decade or two ago.

So learning a new language is good. It’s not just good to have the ability to use that language in your current project, which you may not be able to do, but also if you switch projects to one that uses that language. However, even beyond direct use of the language is how learning new ideas and ways of doing things will change your code in your language of choice, or at least the language you have no choice in because it’s the one your project uses.

The Matrix

I doubt that The Matrix was programmed in single language. I bet even an AI uses an abstraction to reduce the processing power needed to design something like that.

Of course, this actually brings me to my second topic about projects themselves. The idea that you should learn a new language every year isn’t really new to many people. However, I think that the idea should be extended further to encompass switching projects every few years as well. In a large project this could mean just switching from one portion of the project to another, but with smaller projects it might mean switching completely to a different project (or at least dividing your time between the two).

The reason behind this is actually similar to why you should learn a new language. By being forced into thinking in the new language and solving problems with a different set of tools, it can increase the breadth of your experience and help you perform better on that original project or ones you face in the future. Similarly, being forced to work on a new project will make you think in new ways about new problems that will help you in old projects and even future ones. If you stay with a single project for too long, you’ll star to stagnate and be unable to really explore and incorporate new ideas that your project’s problem domain doesn’t cover. Lack of exposure to new ideas will prohibit growth. Your resumé won’t be improving, and you won’t be growing as a developer.

Ideally, if you switch projects you would want to switch to one in a different language than your last project. This will help cover both aspects of learning a new language and a new project. While you can always learn a new language in your spare time and on personal projects, you will generally learn faster if you’re thrown in the water as it were. Similar to learning a language by living in a foreign country, learning a new programming language is much easier if you’re thrust into the depths of it with no choice to procrastinate. You have to learn it to work on your project, which will help you gain new insight into development in general.

I’ll be starting this exciting adventure myself as I transition from my current project in Java to a new project in C++/Perl. While I’ve been meaning to for a while, I’ve never done any serious work in C/C++. Being forced into it by having to work on a code base that is primarily in C++ will help facilitate that learning process through experience. I’m excited for the opportunity and I feel that everyone should strive to make those sorts of changes in their work from time to time to keep fresh and productive.

An Idea for Tracer Bullets

August 6, 2010

My favorite software development related book, The Pragmatic Programmer, has a section in it where it mentions tracer bullets. The tracer bullet system they describe really reminds me of the scaffolding system that Rails made popular. It’s sort of a loose structure that gives you something to play with but that really needs to be fleshed out for your finished application. The idea behind using a tracer bullet, or scaffolding, is to have that basic structure to build with and help avoid the ‘blank page’ problem (writers and programmers both know that a blank page is the most difficult thing to write from). So scaffolding is useful, and what Dave and Andy remark as tracer bullets I’m going to call scaffolding for this piece. I would like to introduce a different idea for what tracer bullets are, and how they can help you focus on good Test Driven Development (TDD) and battle the problem of forgetfulness due to complexity.

Book cover for The Pragmatic Programmer

This is an amazing book. My top choice for any developer, especially ones just out of college or with limited 'real world' experience. Buy it, it's worth the price.

If you’ve ever worked on a new system or a larger refactoring of an old system, you’ll have noticed that you get into a sort of groove with what you’re doing. You look at the big picture and you start making your modifications. Something comes up though where you change a method signature and you have to adjust all of the places that use it, which maybe makes you rethink some basic designs and causes another smaller refactor or something during your larger one. Eventually when that’s all done you go back to what you were originally doing. You’re testing all the way which is good, but eventually you get to a point where you stop and say “I’m done”. Or at least that’s the idea. Often it comes out  more like “Am I done?” and you wrack your brain trying to think if you remembered to put everything into place or are you leaving out some small bit that’s going to cause a bug later on. If this has never happened to you and you don’t understand what I’m talking about, you may stop reading.

The main problem seems to be that you have this grand idea at the beginning, and you know pretty much all of the parts that you’re going to have to modify to make things work, you just loose track of what you’ve done and what you haven’t done. Now you can make a paper ToDo list at the start and check everything off, and that’s a viable method. However I would submit that you should utilize your best programming tool right from the start to keep track of your progress: your tests.

When you first collect your refactoring (or basic design) idea, you should know many of the places that you’ll need to modify in order for it to function. Create unit tests for each of these major ideas. These tests should fail with an error message relating to what the idea is and a note that it isn’t actually implemented yet. As you start to refactor, replace these tests with the actual tests for that piece of functionality. You won’t be fully removing the tests (just by having those tracer bullet tests to start with means there’s something that needs to change and those changes need to be tested), but you’ll be adding real tests for your changes to them. When all of your tracer tests are replaced, you should know that you’ve covered everything that your design required.

That doesn’t mean additional testing shouldn’t be done, there are often times areas that need to be modified or added that you did not originally envision. However, it should be a good start to tracking down those areas that need work. It should also prevent you from forgetting any of those key areas that you thought about originally but lost track of during the hectic course of development.

Tracer Bullets in this sense are really just empty failed tests that provide guidance as to what you need to work on. They’re not real tests, but they’re placeholders for where tests should be in the future. They act as a guide to help you figure out what you should be working on next. In addition, since you need to modify those failed tests for your build anyway, it should encourage you to work in a more test driven way by writing your tests first. Since you’ll look at your list of failed tests as your “ToDo” list, it will encourage your first action being to change those tests to something useful rather than a paper ToDo list which encourages you to jump into writing the application code before your tests.

Storm Trooper Helmet

As additional encouragement to practice Test Driven Development, here's the coercive face of failure.

Anything that keeps us more organized and removes unnecessary burdens to our mental flows is a helpful device for a programmer. Being able to utilize any technique that will increase your likelihood to properly test your application code is also a great benefit. This is just an idea I’ve been pondering for some weeks and I’m sure it’s not the only one for combining your design and testing in an up front mannor. If anyone else has any suggestions or practices that they use, please feel free to let me and others know what they are.