Feeds:
Posts
Comments

Posts Tagged ‘C++’

When I was asked to create and teach a Python class, I had to ask myself, “where is the starting point for this language?”

When it comes to computer languages, I like them logical, powerful, compact and fast. The language currently at the top of my list is Swift. When it comes to longevity, C++ wins hands down. Python is neither compact nor fast. It is, however, very popular. It’s also very flexible.

The C language has so many children that it’s easy to use analogs. What about Python?

I’ve taken intro CS courses from Harvard, Rice and Stanford all of which use Python. They all teach C programming in Python in my opinion. I get where they’re coming from. You’ve spent years using FORTRAN then Pascal then Java.

Happily, my first language was FORTRAN. You think you need to build all your own data structures if you use C. Consider yourself lucky. But that’s a story for another day. My second lanugage as APL. Go ahead try to teach APL the way you teach C. Knock yourself out. A bit later I picked up BASIC, which after FORTRAN was trivial. Next came Forth. That took a bit to wrap my procedural head around. My experience with APL had taught me that it’s perfectly fine to focus on the data and not the process. Forth’s focus on the stack is strangely intriguing. The fact that it lives on in UEFI and Postscript is a testament to the fact that there is value in that view of the world.

So my approach was to start with data representation. In Python the world is all objects and references. But for some reason, people don’t want to approach the language from that standpoint. They like to talk about how easy it is to write ‘hello, world’ programs or how it’s more readable than Perl. Aside from APL, I don’t know anything that’s less readable than Perl. Except maybe TECO macros.

Now that I had a place to start, life should be a hop, skip and a jump to classes, yes? Not so fast pilgrim. It’s easy to explain that everything is an object and that integers are a sub-class of rationals. It’s easy to explain that 0 takes 12 bytes of storage. You can even justify the lack of a character object. But I think you do a true disservice if you don’t address the fact that strings are Unicode based. I’ve dealt with enough internationalization issues to know that to gloss over this would be a disservice to the student. I probably spent more time working on the string section of my class than any other.

The reason? It’s one thing to present information that raises obvious questions like, “so you’ve told me that there as multiple ways to represent the same grapheme and that these strings will have different code units, but what am I supposed to do about it?” Or “how am I supposed to sleep knowing that a Vai 4 digit isn’t the same as an Arabic numeral 4?” You might as well throw them under a bus if you honestly believe that you’ve discharged your duty as a teacher by telling the students that there are land mines out there and that they should bring an umbrella. You’ve essentially just given them a compelling reason to never use the language.

Once all the ‘core’ data types are out of the way, it’s time for some core data structure like list, tuple, and namespace.

Functions, generators, and lambdas come next. These are relatively straightforward. The trick to generators is to show the equivalent implementation in C++. Yes, they are different beasts, but you can get close enough. Similarly with lambdas.

Now, you’re in a position where classes can be reasonably explained. A point to mention here is that back before embarking on a exposition of data types, keywords and variable conventions were addressed. Now, for most students, this goes in one ear and out the other. Having arrived at classes, all those naming conventions come back like an overeager Sheltie wanting to play. Ignore them at your peril. Enumerations are also introduced here.

For many, all the object bits will now come into focus. This is a good thing. I’ve never liked the approach where students are taught how to use bits and pieces of libraries without the foundation to understand what’s actually happening. They end up with a false sense of accomplishment and may never seek to build an accurate model of the languages world. They’re like Jeff Goldblum’s character in ‘The Fly’ having no clue how things actually work since he just specified what he wanted a given part to do and plugged the parts together. We all now how that worked out for him. It also emphasizes their importance of debugging you system.

I’ve never understood why some people shy away from classes in Python. They act as though organization is an inherently evil thing. They also probably have all their laundry in two piles in the middle of their bedroom (one dirty, one clean).

Classes point us to resource management, but we can’t do that discussion until input / output is covered. That gives us the idea of using classes (file streams) and their methods to process data. Here’s where string formatting and core data conversion comes in.

Up until now, exceptions have been alluded to. Now there’s enough structure to not only address, but give meaningful examples of their use.

At this point, you’re done with the core language. So we’ll address unit testing. We’ve done bits of this along the way since the introduction of classes, but now we can talk about the unit test library.

What remains are sections on sequence and associative containers. An important aspect of this is teaching how to select the appropriate container. Yes, you can use list and tuple alone, but there are better things to do with your life than reinventing the wheel. Technical interviews insisting that people be able to balance binary trees notwithstanding.

Finally, a brief introduction to the standard library. Before Googling, how about being aware what’s already in the box.

You’ll note a distinct absence of web browsers, GUI applications, client-server systems, etc. Just the language here.

Would my class make you a Python expert. By no means. As with all things, you become proficient through years of study and practice. It is my hope that my Python class would give you a good start on that journey.

Read Full Post »

The thing about teaching a class is that it can’t actually be done. You can only teach an individual.

I’ve been teaching since I was in middle school. Hard to believe, but true. That effort, to teach my younger sister (by six years) how to do addition was an utter failure. My next major outing was to create a one week segment for my 12th grade physics class on black holes, including a test. I believe that one fared better, although I don’t believe my endeavor to expose my classmates to then cutting edge cosmology was necessarily appreciated.

Throughout college, I was a TA and grader for various CS classes. I spent a summer a the Nature and Conservation director at a Boy Scout camp and two summers teaching programming to teens. By the time I entered the professional arena, I knew teaching (tech transfer) was in my DNA.

A decade ago, I worked for a company where teaching C++ was part of the job.

Fast forward to my current position. I’ve had the opportunity to create and present Modern C++ (C++14) training within my company. This has come in two flavors, one to jumpstart them into C++ (C developers) and one to bring them up to speed on the start of the language (C++98/03 developers). Both classes have about 15 hours worth of material.

The first challenge in teaching modern C++ is that of linearization. C++ has a wonderful breadth. Unfortunately, It can be challenging to present the material in such a way as to be both meaningful and at the same time not resort to appeals to Oz-ian “pay no attention to the man behind the curtain.” My success in this area I attribute to years of exposure to the materials of James Burke.

The second, far more interesting challenge, is hitting that Goldilocks zone where everyone is learning. Even when teaching C++ to C developers, there will be those who immediately take to its conceptual frameworks and there will be those who probably never will. It would be easy to cater to the former and simply write off the later as Luddites. Alternately, one could obsess on the later group and end up boring the former to tears. A fundamental balance can be achieved by using labs which build upon a coherent problem and lead the student to embrace ever more abstract aspects of the language.

In the case of my modern C++ for C++98/03 developers class, I take an entirely different approach. With them I use a progression from changes in the language, to important element of the standard library, to useful Boost bits and finally to the contributions made by the GSL. Within this progression, I give attention to each feature or class using a presentation / discussion format. Unlike the jumpstart class, I can’t use the labs to modulate the pace of the class. Each group I teach will progress at their own pace. (I limit my class size to about 20). In this advanced class, I also find myself researching answers to specific, real-world issues that the students are encountering. I then fold these results back into the materials I present.

As with any modern company, there is a mix of platforms under development. This has necessitated my doing a bit of bounds checking to be sure that the materials I present will work in a Visual C++ / gcc / VxWorks world. With the advanced class, I present not only the modern (C++14) methods (with a bit of C++17 previews), but also the pre-C++11 mechanisms as not everyone has the luxury of constantly upgrading their tool chains.

Overall, it has been an enjoyable experience. One I’m sure I’ll be repeating in the future.

Note: As a nod to an interesting Stanford professor (Mehran Sahami) and in the voice of Starfire, I have taken up the habit of “the throwing of the candy.”

Read Full Post »

An interesting thing about having spent over thirty years taking software from one platform to another is that, time and again, I’ve had my understanding of what constitutes correct code challenged. That’s a good thing.

Sadly, many people who ply the trade of software development mistakenly believe that a compiler has the ability to warn you when you’re code is going to behave in ill-advised ways. Worse yet, they fall into the trap of believing either that their code is correct if it compiles without warnings or that if the compiler accepts your code then any compiler will. Unfortunately, these beliefs are the developer equivalent of a two year old’s lack of object permanence. These two tragedies aside, the vast majority of developers are clueless as to how static analysis can and should be used to ensure code quality.

Let’s rewind a bit and work through these.

In the beginning was the language specification. It was a bright, shiny idea given form. Lest you get the idea that these documents, venerated by both compiler authors and language wonks alike, are intrinsically sane; please recall that the original Ada spec allowed minus signs in the middle of numeric literals and that 8 and 9 were perfectly acceptable octal digits in C. Now a computer language without a compiler is fairly dull. Enter the compiler authors. These individuals, who number about 1000 in the world and of whom I’ve personally known about a dozen, are highly proficient at taking the language specification and giving it life. The way they do this is far more Pollock than Vermeer. Why? Well, a language is the embodiment of a worldview. Unlike source code control systems, which are only created when someone gets fed up with the way that the current one they’re using does one particular thing to such an extent that they can’t bear living under its yoke any longer, languages come from the world of paradigms. Why? If your pet peeve is small, you’ll probably be able to either work around it or get it added to the language (typically contingent upon who you know). If your peeve isn’t small, any attempt to modify the language you’re using will have the same result as updating the value of Planck’s constant or dropping a storm trooper platoon into the middle of a city on Vulcan.

It can’t possibly be that bad you say. Actually, it can. And, in fact, it is. A long time ago, Apple was transitioning from it’s Pascal-based OS to a C-based one. The transition was fraught with byte-prefixed, null-terminated strings. The resultant code was pretty horrific. Just recently, I was working on a feature that required me to move between BSTR, wstring, COM and char strings. This because the language wasn’t designed with the notion that strings could be more than just US English. Compare this to Swift which is a pure Unicode language right down to the variable names.

Every compiler writer brings their own unique experiences and skill set to realizing the worldview embodied in the language specification. No two compilers will realize it the same way. Oh, they’ll be close and probably agree 90% of the time. The biggest area of difference will be in what each compiler considers important enough to warn the developer about. On one end of the scale, you could argue that if the language specification allows something that the developer is free to write the code accordingly. At the other, the compiler would report every questionable construct and usage. All compilers that I’m aware of fall somewhere in the middle.

Unfortunately, rather than biting the bullet and forcing developers to recognize their questionable and problematic coding choices, compilers have traditionally allowed code to have a pass by not enforcing warnings as errors and by having the default warning level be something uselessly low. To make matters worse, if you do choose to crank up the warning level to its highest severity, many times, the operating system’s headers will fail to compile. I’ve discovered several missing macro symbols that the compiler just defaulted to 0. Not the expected behavior. Microsoft’s compiler have the sense to aggregate warnings into levels of increasing severity. gcc however, does not. The omnibus -Wall turns out to not actually include every warning. Even -Wextra leaves stuff out. The real fun begins when the code is expected to be compiled on different operating systems. This can be a problem for developers who have only ever worked with one tool chain.

So, let’s say that you realize that compilers on different platforms will focus on different issues. You’ll probably start considering trying other compilers on the same platforms. Once all those different compilers, set to their most severe, pass your code is good right? Not so fast. Remember, a compiler’s job is to translate the code, not analyze it. But, you do peer reviews. Tell me, how much of the code do you look at? How long do you look at it? Do you track all the variable lifetimes? Locks and unlocks? In all the code paths? Across compilation units?

Of course you don’t. That would be impossible. Impossible for a person. That’s why there are static analysis tools. My current favorite is Coverity. And yes, it costs money. If you can sell your software, you can pay for your tools.

But the fun doesn’t end there. Modern compilers can emit additional code to allow for profile guided optimization (PGO). Simply put, instrument the code, run the code, feed the results back into the compiler. Why? Because hand tweaking the branch predictors is an exercise in futility. Additionally, you’ll learn where the code is spending its time. And this matters because? It matters because you can waste a lot of time guessing where you need to optimize.

Finally, there’s dynamic analysis. This is realm of run-time leak detection. Wading through crash dumps and log files is a terrible way to spend your time.

So, are you developing quality software or just hacking?

Read Full Post »

It took me a bit longer than I’d’ve liked, but finishing all the Apple WWDC 2015 videos (110-ish) in under three months is pretty satisfying.

I’m impressed at the speed with which Apple is executing the change of primary development language from Objective-C to Swift. I expected three years, but it looks like they’ll have things wrapped up in two. This is no mean feat. I’ve now experienced three core language shifts within Apple now. The first was from the Apple ][ 6502 assembly to the Macintosh 68000 assembly / Pascal hybrid. The second was the move to C. This was particularly tedious for those of us attempting to keep both camps happy. You haven’t lived until you’ve dealt with byte-prefixed, null-terminated strings. With the adoption of NextStep and the BSD/Mach micro-kernel can the transition to Objective-C. I’ll admit, I made fun of Objectionable-C. By that time, I’d spent the better part of a decade using C++. A bit of snobbery on my part. Those two children of C have fundamentally different views of the world. I cut my teeth on iOS using Objective-C and appreciated its extensibility when compared with C++. But, it didn’t have the base that C++ did. A billion devices later, well, that’s a different story. Now we have Swift. I believe that it represents the next generation of language. Not object-oriented or message-oriented, but protocol-oriented.

The number of sessions dedicated to tools was impressive as always. As was the quality of the presentations. Thankfully, we were spared the pain of having Apple’s french speakers presenting in English discussing graphics which the word banana coming up so often that one would think there was a drinking game just for that session.

I’m looking forward to tinkering with the WatchOS bits. Those sessions are probably a staple of developers.

Props goes out to the Xcode developers of continuing to bring a quality product to the table. An AirPlay view for the simulators would be nice (hint, hint). The sessions dedicated to the profiling, power and optimization of code are worth watching multiple times.

As is the case with many mature elements of the operating systems, security had fewer explicit sessions. Instead, security was a pervasive theme along with privacy.

One cannot talk about this years sessions without mentioning the brilliant leveraging the synthesis of scale and privacy to created ResearchKit.

The care that Apple puts into the sample code is truly inspiring. Having suffered through hundreds of pages of AOCE documentation, today’s entry into Apple development seems easy. Easy on the individual component level at least. There is not more that one would have to learn in order to create software from beginning to end with the level of quality and feature richness that the world has come to expect from applications on the Apple platforms.

Leaving the best to last, I’ll reflect on an issue that’s always bothered me with the transition strategy that Apple has used in the past. It’s not so much that I didn’t like the solution they came up with to deal with transitioning from one methodology to another. Or that I had a better answer, I didn’t. The price always seemed rather steep to me. I speak of binaries with multiple code and data resources used to allow a user to download a single image and run it anywhere. This was used in the transition from 68000-based machines to PowerPC ones and again when moving to Intel’s architecture. On iOS, we’ve seen the number of duplicate resources steadily climb as the screen geometries and densities have increased. The thing of which I speak is the double-headed axe of app thinning and on-demand resources. The ability to release an application to the store with all the bits for all the supported devices and be able to download only those that will actually be usable on a given device is tremendous. Couple that the a way to partition an application in such a way that only the resources within a user’s window of activity are present on the device and you have a substantial savings in both time and memory. Well done.

It’s been many years now since I’ve been able to attend WWDC in person and given the popularity of the conference, it’s not likely that I’ll be going any time soon. I’m content for the moment to be able to access all the content, if not the people, that someone attending would be able to. I look forward to next year’s sessions.

Read Full Post »

%d bloggers like this: