Hello World in C, Dev Setup

As mentioned, I'm learning C, and I've achieved hello-world, plus recursive calculations of factorials and some data structures. Whee. :) For those playing along at home, I'll describe my dev setup.

But first, an unexpected discovery: Counter to my intuition, there's a beneficial synergy between learning a new editor and learning a new language at the same time. I had thought it would be too many new things to take on at once. I've wanted to learn Vim for its beautiful efficiency, but its formidable learning curve repels all comers. I couldn't gain traction. When writing in a language with which I am comfortable (C#, English), my thoughts would run too fast, too far ahead of my rudimentary editor skills, ideas slipping out of my grasp as I stumbled around the text with j, k, h, and l (and never the one I meant). But in C, where I am carefully picking my way over unfamiliar terrain, my lines of code have slowed down to match my fingers. Because I am trying to hang onto only one edit at a time, I can spare a second to check that A will switch me to insert mode at the end of the current line. I recommend it: learning a new language is a good time to learn a new text editor.

Sandbox


I use VirtualBox to run virtual machines. VMs are excellent for experiment-based learning; think of it: a nice clean server that you can start up, poke and abuse, throw away and start again. If you start with the right VM image—for example, one configured for Ruby on Rails—you can jump right into the experimentation without all the installation hoop-jumping.

For this endeavor I chose TurnKey Linux's Core appliance because it's just Linux and not much else, following their instructions for installing a TurnKey appliance.

To install a compiler (later), I needed my VM to connect to the internet. In VirtualBox Settings > Network, I set "Attached to" to "Bridged Adapter," meaning the VM could use my laptop's connection, and the adapter's "Name" to my wireless card. (The other choice in the dropdown list is a PCI-E Fast Ethernet Controller, and that... didn't work.) With that set, I powered up the VM, which starts the webmin console. I let it automatically configure DHCP, and I was internet-ready.

Editor


Vim is already installed on the Core VM image, so I just needed to type "vim helloworld.c" to start stumbling around my new code file. I'm relying on the TuXfiles Vim cheat sheet.

Compiler


I chose GCC, the GNU Compiler Collection for my C compiler, and I needed to download and install it. Following TurnKey's apt-get instructions:
  • apt-get update (to update apt's list of modules)
  • apt-cache search gcc (to find modules for the gcc compiler - gcc-4.1 looked right.)
  • apt-cache show gcc-4.1 (to get info about it)
  • apt-get install gcc-4.1 (to install it)
  • gcc-4.1 myfile.c -o myexename (to compile and generate myexename executable)
  • ./myexename (to run my program)


Hello World


I followed a video that creates and compiles a C program using the GCC compiler. "Hello, World!" A simple phrase, profoundly satisfying.

Dipping into C

I decided on Monday that I should learn C. Cultivate a nodding acquaintance, at any rate. Louis is always prodding me to become a better craftsman, to become more proficient with my tools. So I figured I should understand my roots.

I picked up O'Reilly's Mastering Algorithms with C at the library, and I'm already having fun. It will get into recursion, Big O notation, linked lists, quicksorts, encryption, and all that jazz, but right off the bat, it starts with pointers.

Immediately some aspects of C# become more clear, by understanding their precursors from C: the ideas behind reference types and passing parameters by reference, and the joys of automatic garbage collection and abstracted memory allocation.

The syntax of pointers in C involves a lot of punctuation—a subtle and nuanced application of asterisks and ampersands—which the book assumes I would already know. My favorite search engine (code-named Sweetie, as in, "Hey, Sweetie, can you find...") turned up an online edition of The C Book, containing this excellent explanation of pointers.

Here's my understanding so far. Please suggest corrections if I've gotten it sideways.
int *mypointer;mypointer's type is "pointer that can point to an integer"
mypointer = &myint;mypointer is pointing to the location where myint is stored
*mypointer = 7;the place where mypointer is pointing now contains a 7, so myint now equals 7
myotherint = myint;myotherint also equals 7 (but just a copy of 7, so changes to myint won't affect myotherint)

So what? So now I'm clearer about reference types in C#. In C, I can pass a pointer as a parameter to a function, instead of passing a value. That means I'm passing the function a reference to a location in memory. If the function uses the pointer to change the stuff in that location, when someone else accesses that location, they will receive the changed stuff. Contrast this with passing a value, such as an integer, to a function, which actually passes a copy of the value. Any changes to the value are scoped within the function and are not detectable from outside. It's something I've known for a while, but now I know why.

If you no longer need the piece of memory that a pointer points to but you fail to de-allocate that memory, it will stay held in reserve forever—voilà, a memory leak. Different data types take up different amounts of memory, so writing a data type into a pointer of a differently sized data type will overwrite other pieces of memory in unpredictable ways. I feel like I've been making peanut-butter sandwiches with a butter knife and just noticed that other people are wielding samurai swords: looks really powerful and flexible, but I'm scared I'd cut off a finger. Now I get what the big deal is about the CLR's garbage collector (and how in some contexts it would be too restrictive).

I'm having fun getting "closer to the metal" and realizing the reasons behind some things I've taken for granted. I can't wait to get into the chapters on algorithms.

Three Simple Steps to Improve Your Writing

Technical books are longer than they ought to be. Most software books could be improved by shedding a tenth of their heft. It's a product of market pressures, of course: Tech books need to get to market fast, which does not allow for the time-consuming labor of honing and refining a text until it is lean and tight. I have a few simple strategies, though—simple tips that provide a disproportionately beneficial return on a trivial time investment. You can use the following tips to improve your blog posts, books, and presentations.

Replace "basically" with nothing.


This word never adds value. It is usually a manifestation of the author's or speaker's unconscious concern that what he is explaining is too complex. If time allows, revise the material until your readers don't need extra convincing that it is basic. At least get rid of the useless word.

You could have some fun writing a regular expression to correct all instances with a global search-and-replace. If you're amused by the challenge, please feel free to post your regex in the comments. You'd be helping all of us.

Here are the replacements your regex would need to catch:
FindResult
Basically, it can start a sentence.It can start a sentence.
Basically people leave off the comma, too.People leave off the comma, too.
It can basically appear in the middle.It can appear in the middle.
It can, basically, be set off with commas.It can be set off with commas.
It can end a sentence, basically.It can end a sentence.
It might end without a comma basically.It might end without a comma.

Replace "essentially" with nothing.


As above.

Replace "is nothing more than" with "is."


The "is nothing more than" construction falls in the category of noisy hedge words. It's a large category. Folks add words to forestall arguments. Even though it sounds romantically brash—X is nothing but Y, #wristforehead—it actually weakens the association between the subject and its predicate nominative. Be clear; be bold. If you're trying to define X by saying that it is Y, say that X is Y.

I wish the industry allowed more time for editing. I wish I were able to help more people express their ideas. Good editing is liberating, plucking the brambles and cruft off a passage until its central theme floats to the fore—getting the text out of the way of the writing.

I hope you find these tips helpful and easy to implement. Ruthlessly delete useless clutter like "basically," "essentially," and "nothing more than." Let your ideas stand tall.

ReSharper Shortcut for Context-Sensitive Unit-Test Running

For a keyboard shortcut to the context-sensitive ReSharper unit test runner (otherwise available via right-click > Run Unit Tests), map:

ReSharper.ReSharper_UnitTest_ContextRun

(Thanks to Clinton for mentioning it.)

What This Solves


The slowest way to select and run unit tests is to click the green-yellow bubbles in the left margin and pick "Run" (or "Append to Session" to collect a bunch of them to run).



From the right-click menu, the "Run Unit Tests" option will run a test if your cursor is in a test, all tests in a fixture if your cursor is outside a test but within the fixture, or all tests in a file if you're outside any fixtures.

Mapping the ReSharper.ReSharper_UnitTest_ContextRun to a keyboard shortcut achieves the context-sensitive behavior, mouse free. I chose Alt-T for mine, since that wasn't in use for anything else. (Have a nice strategy for picking unique keyboard shortcuts and remembering them? Please share in the comments.)

To Map the Shortcut


Tools > Options > Environment > Keyboard. In the "Show commands containing" textbox, enter some or all of the command, and select the command.



Set your focus to the "Press shortcut keys" textbox and type your shortcut just as if you were invoking it. If a command shows up in the "Shortcut currently used by" list, life will be simpler if you pick a different shortcut. When you have one you like, click "Assign" and "OK." Good to go!

Rhino Mocks Examples, with a fix

Jon Kruger created an excellent explanation of Rhino Mocks, using unit tests to demonstrate and illuminate the syntax and capabilities. (Found via @gar3t.) It needs one small correction, which I'd like to write about here so that I can link to and support Jon's work, and because it gives the opportunity to clarify a subtle distinction between mocks and stubs and verified expectations.

First, go check out Jon's code, then come back here.

The problem lies in the following test. I can comment out the part that looks like it is satisfying the assertions, yet the test still passes—a false positive.

[Test]
public void Another_way_to_verify_expectations_instead_of_AssertWasCalled()
{
  var stub = MockRepository.GenerateStub<ISampleClass>();
 
  // Here I'm setting up an expectation that a method will be called
  stub.Expect(s => s.MethodThatReturnsInteger("foo")).Return(5);
 
  //Sneaky Sharon comments out the "Act" part of the test:
  //var output = stub.MethodThatReturnsInteger("foo");
  //Assert.AreEqual(5, output);
 
  // ... and now I'm verifying that the method was called
  stub.VerifyAllExpectations();
}

In translation, that test says: Create a fake ISampleClass; set up an expectation that a method will be called; call that method do nothing; verify that your expectations were met (and flag the test as a failure if they weren't). Shoot. Worse than not having my expectations met is not realizing they're not being met. Reminds me of my college boyfriend.

There are two things to fix here. The first is that this test is a little solipsistic. If you create a mock, tell the mock to act, and verify things about the mock... all you're testing are mocks. Instead, you want your tests to exercise real code. The "system under test," i.e., the class being tested, should be part of your production code. Its dependencies are what get mocked, so that you can verify proper interactions with those dependencies. Let's fix the solipsism before going on to the second issue.

As originally written, the expectation would be satisfied by the "Act" (as in Arrange-Act-Assert) part of the test. It says, "Call this method. Did I just call this method? Oh, good." Instead, you want to ensure the system under test correctly interacts with its friends, using Rhino Mocks' AssertWasCalled and Expect methods. We need a real class that takes the stubbed class and calls a method on the stubbed class, and we'll write unit tests around the real class.

public class MyRealClass
{
  public void ActOnTheSampleClass(ISampleClass sampleClass)
  {
  }
}

Here's the re-written test, verifying how my real class interacts with the ISampleClass interface.

[Test]
public void Another_way_to_verify_expectations_instead_of_AssertWasCalled()
{
  var stub = MockRepository.GenerateStub<ISampleClass>();
  var systemUnderTest = new MyRealClass();
 
  // Here I'm setting up an expectation that a method will be called
  stub.Expect(s => s.MethodThatReturnsInteger("foo")).Return(5);
 
  // Tell the system to act (which, if it is working correctly, 
  // will call a method on the ISampleClass.
  systemUnderTest.ActOnTheSampleClass(stub);
 
  // ... and now I'm verifying that the method was called
  stub.VerifyAllExpectations();
}

This test will still pass, despite the fact that my real class does not currently call any methods on the ISampleClass interface. This points to the second issue to fix. In Rhino Mocks, expectations on stubs are not verified; only mocks are verified. If an object is created with GenerateStub instead of GenerateMock, then its VerifyAllExpectations method doesn't do anything. This is non-obvious because the AssertWasCalled and AssertWasNotCalled methods on a stub will behave the way you want them to.

In Rhino Mocks, a stub can keep track of its interactions and assert that they happened, but it cannot record expectations and verify they were met. A mock can do both these things.

That is how they are implemented in Rhino Mocks. If you were holding firm to the ideas in Fowler's Mocks Aren't Stubs article, I think stubs would implement neither VerifyAll nor AssertWasCalled. Semantically, verifying expectations and asserting interactions are synonymous, if you ask me; therefore, stubs shouldn't do either one.

Back to Jon Kruger's tests. If we call GenerateMock instead of GenerateStub, the test will fail properly with an ExpectationViolationException.

[Test]
public void Another_way_to_verify_expectations_instead_of_AssertWasCalled()
{
  var stub = MockRepository.GenerateMock<ISampleClass>();
  var systemUnderTest = new MyRealClass();
 
  // Here I'm setting up an expectation that a method will be called
  stub.Expect(s => s.MethodThatReturnsInteger("foo")).Return(5);
 
  // Tell the system to act (which, if it is working correctly, 
  // will call a method on the ISampleClass.
  systemUnderTest.ActOnTheSampleClass(stub);
 
  // ... and now I'm verifying that the method was called
  stub.VerifyAllExpectations();
}

Now that we're red, let's get to green. Change the system under test so that it does its job as expected.

public class MyRealClass
{
  public void ActOnTheSampleClass(ISampleClass sampleClass)
  {
    sampleClass.MethodThatReturnsInteger("foo");
  }
}

Wahoo, a passing test that we can rely on.

The two key points from this exercise are:
  1. Describing Rhino Mocks with unit tests is a cool way to explain a topic. Let's have more executable documentation, eh?
  2. Expectations on stubs aren't verified, so beware of falsely passing tests.

New home for RSS feed

A friend recommended FeedBurner, so the RSS feed for Girl Writes Code will be served from http://feeds.feedburner.com/GirlWritesCode.

GirlWritesCode is moving to new digs; please join us.

I use Blogger's FTP model, where my posts are published out to my webhost on Invisible City. Blogger is discontinuing that service, due to lack of use and to enable bigger and better things in their architecture. So I need to shuffle things around, and I hope that you will follow this blog to its new home.

I'll update GirlWritesCode.com to redirect to the new location, so if that's the url you've bookmarked, you're good to go.

I'll continue to cross-post at Los Techies. If that's your main means of keeping up with me, then... how are you reading this? ;-)

I'll have an RSS feed from the new location, but the url is going to change. It will be http://girlwritescode.blogspot.com/atom.xml, I'm pretty sure. [Correction: http://www.girlwritescode.com/feeds/posts/default] I'll post a "we've landed" post from the new location, so you'll know when I've got it sorted.

I appreciate your readership. Everything I write, I write with you in mind. I hope you will follow this blog to its new location.

More Dogs and Bears and Chickens and Things: Invite your colleagues to Pablo's Fiesta

If you work with developers who are women, please tell them about the Los Techies Open Space conference, coming up at the end of February. If you've attended an event like this in the past, you're already aware of some facts:
  • The Austin developer community is vibrant, engaged, and constantly striving to improve our craft. We've got a good thing going here.
  • The quality of the conversations and the value of the event far outstrip the price of admission; it would be a bargain at twice the price.
  • Women are way under-represented.

Early in my career, I wasn't tapped into the information channels that announce events like this. I didn't go because I just didn't know about them. My friend and colleague Josh Flanagan made a point of letting me know, and encouraging me to go, and showing that it was not only okay but right to ask my employer to send me to such things.

Attending conferences has made a huge difference in my growth as a developer and in my career. It brought me into the on-going conversation in the developer community. It exposed me to new practices and new technologies, which I brought back to the team. Please do the same favor for your women co-workers that Josh did for me: Tell them about Pablo's Fiesta and encourage them to sign up.

Bringing women into the mix brings new, diverse ideas into the conversation, new skillsets to the community, more role models for our kids. The conference will be improved by spicing up the guest list. Although I'm focusing on women here, reach out to any of your colleagues who "don't usually go to these things." New voices mean new synergy, which means more learning and more fun.

And you. Sign up, your own self. It'll be great.

If you have any questions about Pablo's Fiesta, or about whether you'd enjoy it, please feel free to post them here, and I'll get the answers for you.

Interface-Oriented Design - Book Review

Ken Pugh's Interface-Oriented Design (Pragmatic Programmers) presents an approach to designing applications that focuses first on the interfaces, the places where pieces of the application interact. The interfaces here are not primarily user interfaces, but module-to-module interfaces and service interfaces, and the applications are not exclusively object-oriented. Pugh's proposed process is to identify use cases and test cases, determine the interfaces that will enable those use cases, then create tests and implementations for the interfaces.

The book is divided into three parts. The first explains the concepts and theory underlying an interface-focused approach to design. These concepts include real-world analogies which quickly provide context to the discussion; types of interfaces, such as stateless versus stateful, and procedural versus document; design concerns such as contracts, cohesiveness, and polymorphism; and the Asimov-inspired "three laws of interfaces," which specify the qualities of a well behaved implementation. Part two is brief and describes where interface-oriented design fits into the project lifecycle. Part three walks through three examples, from concept to design to implementation, and highlights the design patterns exhibited in those examples. The book concludes with a grab-bag appendix of topics that could have been better served by integration into the main text.

If your learning style is learn-by-doing, you might get more out of the book by reading Part Three before Part One. Part Three provides the "yeah, but what are we doin' here" skeleton onto which you can hang the theory that is explained in Part One. I find theory easier to digest and retain if I know which of my real-world, day-to-day experiences it applies to. You'll get that context if you flip the order in which you read it.

I picked up this book looking for best practices on providing and consuming remote interfaces, and it isn't that. Have you ever taken a sip of something you like, but because you were expecting a completely different flavor, it tasted off? I bumped into that dissonance here, so it was hard for me to get into the book. To appropriately prepare your palate, the flavor to anticipate from Interface-Oriented Design is a technique for thinking about a problem domain and its software solution by thinking about the places where responsibilities interact, analogous to the way that service-oriented architecture is a technique for thinking about software design.

An area where this book really shines is Pugh's deft use of real-world examples. In the first chapter, he introduces the process of ordering a pizza as a series of exchanges through a PizzaOrdering interface. The example is familiar, relatable, and practically identical across the United States (implementations vary, of course). Pugh then uses that example and expands upon it throughout the rest of the book, allowing us to fit new concepts into the model as it is refined. This worked better than if each new concept had been presented with a new example; the book gained a pedagogical momentum.

Many times during my reading, I asked myself whether the ideas were so fundamental and distilled as to shift my way of thinking, or so fundamental as to be mundane and trivial. Was this book raising the level of abstraction, like climbing a mountain to get a better view of the landscape, or just telling me no-duh stuff I already knew? Is its audience experienced developers looking to put terms and practices around habits they do instinctively, or is its audience beginners who need an introduction to methodical design? I still haven't decided. Will it affect my thinking? Probably. Not in ways that I can articulate and enumerate for you, but likely in subtle and profound ways that I may or may not notice as they occur. For yourself, I recommend checking out the table of contents (available from the Pragmatic Bookshelf) and see if it suits you.