John S.'s blog
Today, I’m going to talk about the way my attitude towards using namespaces has pretty much done a complete reversal over the last couple of years. I started off thinking that they looked great, progressed to mild concern that they seemed to be causing unexpected difficulties, and eventually realized that they can become unmanageable if allowed to grow out of control. Just like a bunch of tribbles. (Yes, the title is a Star Trek reference :).
To jump to the punch-line, I’ve come to the conclusion that highly fragmented hierarchies of namespaces (such as are found in .Net and encouraged by the Visual Studio C# IDE) make life harder rather than easier. Instead, I would recommend either name mangling strategies (incorporating an identifying string in the object name) or always using fully qualified names in your code (instead of “using” statements).
Phase I: Infatuation
When namespaces were first introduced into C++, I thought they looked like a great idea. It seemed wonderful to not have to worry about managing name collisions. Unfortunately, for over a decade I didn’t have an opportunity to use them; my Physics codes were standalone executables (and so name conflicts weren’t an issue), and ACIS was written before they were portable to all compilers. Actually, ACIS was written before they were introduced into C++. In the tribble analogy, everyone else got to play with these cool critters but I didn’t have one.
Phase II: Nagging Doubts
This changed when I started working with C#, especially in my personal projects at home. The .Net library makes extensive use of namespaces to indicate areas of functionality, plus the Visual Studio IDE assumes you want this sort of hierarchy in your code. If you create a folder within your solution to manage an area of functionality, for example a Market component in an economics simulator with root namespace Econ, then the Visual Studio class wizard “helpfully” puts any classes you add to that folder into the “Econ.Market” (sub-)namespace. And that is where the trouble started. (If anyone knows how to turn this behavior off, please post a reply – I’ve been unable to find a way to do it.)
I quickly found myself getting frustrated by not having the correct set of “using” statements in my code, and having difficulty figuring out which “using” statements I needed to include. For example, if I had a Trader class in a Actors folder (and corresponding namespace) and a Pit class in the Market folder, then I would regularly get compile errors when I tried to use the Trader class without “using” statement for the Econ.Actor namespace. And the really frustrating part was that it wasn’t immediately obvious which namespace was missing – I would have to find the class then look to see which namespace it was in. I now realize that the problem that I was running into is that namespaces (or more precisely “using” statements) lead you to write non-self-documenting code. In other words, if I write the code
Market market = new Market();
GoodsType goodsType = new GoodsType();
Pit pit = market.GetPit(goodsType);
I don’t have any visual indication in that region of code as to which namespace Pit, Market, or GoodsType live in. And if they come from several namespaces, I don’t know which “using” statement corresponds to which class.
This is very similar to the C++ “which header file declares this class” problem, for which a really good solution is to simply make the header name identical to the class name. CGM uses this naming convention and I highly recommend it – you don’t have to think when writing your include statements.
Phase III: Regret
The final driver on my voyage of discovery was C3D development (in C++). When we first started writing strong commands, I had the bright idea to use a namespace hierarchy to put a structure on the vast sea of commands we would be writing. Unfortunately, it didn’t work out as planned. Even though we only introduced a few namespaces, they still made life much more difficult than a simple name mangling scheme would have. Part of the problem is that the compiler errors when you get the namespace wrong are not helpful: we had to train ourselves to ask “did we get the namespace right” when we see an “undefined symbol” error for a class that we’re sure has the header included. An especially nasty error occurs when you try to include a header file inside a namespace block (this typically happens if you’re using templates and so want to do another round of includes for the method definitions). If I had it to do over again, I’d settle for a simple “_SPA” or “_CGM” at the end of each class name, e.g. Property_SPA rather than Spatial::Commands::Property. In tribble language, I feel like Kirk standing awash in a sea of tribbles.
Phase IV: Lessons Learned
The first thing to make clear is that I am NOT saying that namespaces are bad. The fundamental problem that namespaces solve is the ability for application writers to manage naming clashes between libraries from different vendors. I think it’s a great idea for every company selling component software to put everything into a single company namespace.
The problems I see come from trying to group classes into complex hierarchies, especially if you then use “using” statements to erase knowledge of the hierarchies. I’ve come to the conclusion that any such grouping should be as simple as possible, and that the primary goal of the grouping should be avoiding name clashes rather than imposing a component structure on the classes. The reason for this is that classes move between components fairly easily, especially if the component structure is very fine-grain. If every time a class moves you have to do a major renaming effort (either to fix using statements or to rename the class) then you’ll generate a lot of worthless work for yourself.
With this in mind, I currently think a name mangling scheme, with the disambiguating string at the end is best, i.e. something like ClassName_NS. The reason for putting it at the end rather than at the beginning is to help search – if you’re looking for class “Beagle” but are not sure which namespace you’re in, then you just need to look for “Bea*” in a list of all class names.
All of the above being said, I shudder to think about trying to solve this problem in a huge organization. Would .Net really be easier to use if they had used the above naming scheme rather than relying on namespaces?
Posted: February 22nd, 2013 |
In this post I’m going to talk about how we use C3D Toolkit to generate 'live' sample code snippets for our CGM documentation.
One of the things we’ve done with the CGM documentation from the start is to focus on what we call “HowTos”. These are standalone sample functions in our DocWiki that illustrate how to use CGM functions to accomplish some task – the idea is that customers can paste the function into a *.cpp file in their application and modify it to suite their particular needs. This initiative has been very successful – our customers really like the HowTos. It is also not rocket science – sample usage code as part of the documentation of an API is standard stuff. The interesting part comes from the word 'live' that I used above.
What do I mean by live sample code? I mean sample code that is used in a real application and so is called by end users every day, as opposed to sample code that is motivated by a documentation requirement “every interface method must have sample code which calls it”. How many times have you looked at the sample code for a method and seen some silly little program that is obviously contrived to just set up a bunch of inputs and call the method? If we think of a testing analogy, live samples are analogous to contract checks, in that they are an integral part of the application code, while contrived samples are analogous to unit tests, in that they are isolated executables that set up data structures for the express purpose of calling a particular method.
One of our goals in developing C3D Toolkit was to give ourselves a platform with which to develop live samples. The way we’ve done this is to turn the implementation of the C3D Toolkit extensions (commands) into HowTos which are placed in our DocWiki; the goal is that every modeling extension has a corresponding HowTo. For example, we have a “Fillet” extension in C3D that fillets (rounds) sharp edges. The C++ code underneath this extension eventually (after extracting argument lists etc.) calls a standalone function “HowToFillet”, which contains the code that a customer would use in his application to implement a fillet feature. Voila – we’ve got a live code snippet for the fillet operator.
As you’ve probably figured out, I think that live sample code is vastly superior to contrived samples. By making our samples part of our C3D Toolkit application, we gain the following advantages:
- Our sample code is built every night. If an interface changes that breaks the sample our nightly build process will catch it.
- Our sample code is tested every night. We have tests that do fillets in C3D Toolkit – these tests ensure that our sample code doesn’t regress (against the tests).
- We have a good chance of detecting subtle mistakes in our sample code. Our sample code is being used every day in C3D Toolkit. If there are subtle, 1-in-a-1000 bugs in the sample code, we have a good chance of someone stumbling across them while using C3D Toolkit. If, in contrast, the samples were simply contrived executables built and run in isolation, there would be no opportunity for discovering such nasty bugs. We just benefitted from this a couple of months ago; we had written a sample without realizing that the operator being called might return multiple bodies. As part of fixing the C3D Toolkit bug, we automatically fixed the bug in our sample and the improved sample was automatically included in our documentation. This is the core advantage of live over contrived samples, in the same way that contract checks are superior to unit tests. By integrating the samples in an end-user application, the selection pressure of lots of users using the application is applied to continually improving the samples.
Finally, live samples directly support rapid prototyping for customers. Let’s say a customer wants to prototype a new workflow that he will include in his application. We recommend the following steps:
- Prototype the workflow as a C3D Toolkit script (i.e. get it working in C3D Toolkit).
- For each extension called in the script, look up the corresponding HowTo.
- Write a (C++) workflow function in the application that calls these HowTo functions in the appropriate order.
As easily as that, the customer has a working C++ prototype for the workflow that they’re coding up. In practice the customer might need to do some clean-up to get the C++ function working, but this process brings him very close to where he needs to be.
As you can see, I really like the idea of live samples; I hope I’ve convinced you that they’re an important documentation tool as well.
Posted: November 16th, 2012 |
Those of you who are ACIS customers are probably familiar with acis3dt.exe – our Scheme-based demo application (which I’ll call A3DT). For those of you who aren’t, it’s an interactive application, written in the mid-90s, that lets you view and manipulate ACIS models by typing script commands (Scheme expressions). The view window provides mouse-driven picking and view manipulation, but anything you can do with the mouse can also be done through a Scheme expression. There is also a helper application which can be used to edit scripts and send them to A3DT (either entirely or line-by-line) for execution, or scripts can be run from the command line in “batch” mode (for testing).
A3DT has been VERY useful over the years for ACIS, in many ways:
- Most of our tests are written in scheme
- Customers submit bugs as scheme scripts
- Customers are encouraged to prototype their workflows in scheme, then examine the C++ behind the script (the extensions are shipped as source code) and use that to guide their application development.
- Scheme is the primary demo tool for ACIS – our Technical Account Managers (TAMs) often find themselves writing scripts “on the fly” to answer specific customer questions about ACIS’ capabilities.
- When developers want to “play with” ACIS (e.g. create 100,000 blocks to test performance) they do it in scheme.
And now, let’s fast-forward to when we began working on componentizing CGM. In CGM we didn’t have such a scripting engine – instead we had an in-house unit testing engine that could run unit test executables. If you think about it, this made perfect sense. CGM was not developed as a stand-alone product; instead it was part of a GUI-based feature modeling application. In other words, CATIA filled most of the roles for CGM that A3DT fills for ACIS.
For CGM component, however, this was not sufficient. We first noticed this when writing tests – we found ourselves trying to write unit test executables for tests that were really acceptance tests. This was extremely expensive in developer time – being able to see the models you’re creating and do graphical picks on them is extremely important when writing tests of even mildly complicated workflows (e.g. create a block then fillet one of the edges). A more technical way to think of this is that the overhead due to violations of Once and Only Once involved in setting up the input scenarios (which I’ve discussed in the context of design-by-contract) is prohibitively expensive.
A more important problem is that unit tests don’t use the code the way that our customers do: in an application. This is the heart of App Driven Development: you should try to use your own product in the way your customers will.
At the same time, our TAMs were used to having a demo application available for use in presenting our products to customers.
One of the things that surprised me (but probably shouldn’t have) in all this is how rarely people think about scripting interfaces in terms of supplying a command-line interface to applications. In our experience with A3DT (and now C3D), the primary utility is in the ability to sit in front of the application and interactively figure out, line-by-line, what you want to do, while capturing what you’ve figured out in a script. In contrast, it seems like most people think of the utility of scripting in terms of being able to write scripts that will be processed in “batch” mode; in other words it’s very similar to programming, except you don’t have to recompile the executable when you change (or extend) the program. I imagine that a lot of this is driven by the browser-based application market; in such applications the scripting language isn’t the actual interface that’s presented to the user; it’s simply an intermediate programming language that can be run on the browser. I think ignoring the potential of scripting as an interactive interface is a mistake – there are a lot of benefits to having a scripting “hook” into your application.
Posted: August 20th, 2012 |
Today, I’m going to discuss how we’ve been using Application Driven Development (AppDD) principles in our work on CGM.
You might have noticed this really cool picture in Stefanie's last post. It’s really cool because it was the result of our work on the CGM componentization team over the past couple of months – putting dimensional metrology support into our demo application C3D Toolkit. And the other cool part is that we used AppDD to drive the project.
First, some background. A few years back we started getting requests for the ability to work with large sets of points (point clouds) from our dimensional metrology customers. So for the past few years we have been incrementally expanding our support for point clouds in our product line.
A primary workflow in dimensional metrology is to measure a cloud of points on the surface of a manufactured part and compare those measurements to a CAD model representing the desired geometry.
To do this, the following high-level operations are required:
Over the course of several projects, we had incorporated API functions into ACIS to provide these services. During these projects we worked closely with target customers who were incorporating these functions into their applications, so we were intentionally very focused on the individual functions. The last project of this sequence was to port this point cloud functionality into CGM – I’ll call this version “Phase 1”.
The opportunity to do AppDD came up a couple of months ago when Ray, our PM, told us that he needed a C3D Toolkit demonstration script for the CONTROL show. The idea was to show how CGM’s point cloud functionality could support dimensional metrology workflows.
Our first step in the AppDD process was to get a 'storyboard' from Ray of the entire workflow(s) that he wanted to show. This turned out to be a 1 page e-mail describing the steps of the demo.
When we originally estimated the project, we thought it would probably take a single two-week iteration, because the hard algorithmic work had already been done in Phase 1. What we hadn’t realized is that we would need a new “part management” layer in the application to manage e.g. the bookkeeping associated with assigning different colors to different parts of the cloud in a point cloud document. Our focus on storyboarding the entire demo first caused us to notice this mistake up front, while we had time to adjust our estimates. It also allowed us to rough out the design up front, rather than generating a lot of code and architecture churn as we incrementally discovered unanticipated workflow requirements.
Only after we understood the demo scripts (which also functioned as acceptance tests) did we actually start coding the functionality behind them. A week before our deadline we were able to demo the bulk of the scripts to Ray, who gave us some course corrections that we incorporated. In the mean time, Ray had also been busy. Since we were trying to mimic a real customer process as closely as possible, we wanted to work with real scan data of a real part manufactured from a real CAD model. So Ray decided on a CAD model to use in the demo, and sent it out (after introducing a distortion for us to detect) to a service provider who manufactured it with a 3D printer and then scanned the resulting part. Stef’s really cool picture is the result of running our demo on this data, with color coding based on whether the measured points are within tolerance of the model.
We’re told that the demo went off very well at the show; people especially liked the ability to hold the actual part in their hands and compare it to the scan results on the screen. An important take away from the project is that the core functionality that we had already written (registration and point-body distance) worked “out of the box” – it was the support infrastructure for managing point clouds in an application document that we spent most of our time on. This validated for us the idea that AppDD helps to ensure a complete interface for customers. Now that we’ve identified (and have working code for) a new layer of functionality that many of our customers will need, we have an opportunity to move it into our point cloud product.
The full demo on this part can be seen in Gregg’s webinar on C3D Toolkit and CGM – it starts at the 30 minute mark and runs about 10 minutes (but you should feel free to watch the whole thing :). One thing to look for: the scan of our part actually did have some garbage points that he removes as a first step. If we hadn’t already thought of the cleanup requirement when designing the demo, we would have discovered it here because we used a real scan (rather than manufacturing test data).
For this post, I thought I would talk about SPAR 2012, which I attended in Houston last week.
For those of you where are not familiar with it, SPAR is a conference/trade show for the medium and long-range scanning industries. From a geometry perspective, this means dealing with point clouds. Lots of point clouds. Lots of really big point clouds. For example, at one of the talks I attended, the speaker was discussing dealing with thousands of terabytes of data. Another speaker discussed the fact that developing the systems just to manage and archive the huge amount of data being produced is going to be a major challenge, let alone the need for processing it all.
As an example of this, the very first thing I noticed when I walked into the exhibit hall was the huge number of companies selling mobile terrestrial scanners. These are laser scanning units that you strap onto the back of a van, or an SUV, or an ultra-light airplane, or a UAV - there was even a lidar-equipped Cooper Mini on display. You then drive (or fly) along the path you want to scan, acquiring huge amounts of data. The data is then processed to tell you about e.g. potholes or highway signs or lane lines on roads (the scanners are often coupled with photographic systems) or vegetation incursions on power lines (typically from aerial scans). When I attended two years ago, this was a fairly specialized industry; there were only a few vans on display, the companies that made the hardware tended to be the ones doing the scans, and they also wrote the software to display and interpret the data.
This year, it seemed like this sector had commoditized: there were at least eight vehicles on display, the starting price of scanning units had come down to about $100K, and it seemed that there were vendors everywhere you looked on the display floor (and yes, it does sound odd to me that I’m calling a $100K price point “commoditized”). Another thing that I was looking for, and think I saw, was a bifurcation into hardware and software vendors. I asked several of the hardware vendors about analysis; this year they uniformly told me that they spat their data out into one of several formats that could be read by standard software packages. I view this specialization as a sign of growing maturity in the scanning industry; it shows that it is moving past the pioneer days when a hardware manufacturer has to do it all.
On the software side, I saw a LOT of fitting pipes to point clouds. This is because a large part of the medium range scanning market (at least as represented at SPAR) is capturing “as built” models of oil platforms and chemical plants, especially the piping. The workflow is to spend a few days scanning the facility, and then send the data to a contractor who spends a few months building a CAD model of the piping, from which renovation work on the facility can be planned. One of the sub-themes that ran through many of the talks at the conference was “be careful of your data – even though the scanner says it’s accurate to 1mm, you’re probably only getting ½ inch of accuracy”. This was driven home to us at Spatial a few years ago when we bought a low-end scanner to play around with and we discovered that a sharp black/white transition caused a “tear” in the surface mesh spit out from the scanner (due to differential systematic errors between white and black). A practical example of this was discussed in a talk by one of the service providers; he gave a case study of a company that tried to refit a plant using the workflow described above. Early on they discovered that the purported “as built” model (obtained by humans building models from scanned data) weren’t accurate enough to do the work – new piping that should fit correctly from the model wouldn’t fit in reality (for example all the small-diameter pipes had been left out of the model completely). This is because a real-world plant isn’t a bunch of clean vertical and horizontal cylinders; pipes sag, they’re stressed (bent) to make them fit pieces of equipment and so on. The company went back and had the job re-done, this time keeping a close tie between the original scans and the model at all stages. I really appreciated the attention to detail shown in this and other talks; in my opinion it’s just good engineering to understand and control for the systematic errors that are introduced at every stage of the process.
Two more quick observations:
- Several people mentioned the MS Kinect scanner (for the gaming console) as disruptive technology. My gut is telling me that there’s a good chance that this will truly commoditize the scanning world, and that photogrammetry might take over from laser scanning.
- I didn’t expect my former life as a particle physicist to be relevant at a scanning conference. Imagine my surprise when I saw not one but TWO pictures of particle accelerators show up in talks (and one of them a plenary session!)
Next year’s SPAR conference is in Colorado Springs – I hope to see you there!
Posted: April 27th, 2012 |