views:

137

answers:

3

I'm developing a product with a bunch of interlocking pieces (server, client, libraries, etc) and one of the pieces is a tiny library that users will link into their own client-side code (something kind of like the Flickr API or the Google Maps API). Once they've included that library, all of the interlocking bits magically hook themselves together. So API simplicity is a major, important goal.

The API that I expose to users has a grand total of two classes and seven public methods. Easy peasy, lemon-squeezy.

But the simplicity is a carefully crafted illusion. The library I'm distributing actually depends on another library, with 136 classes of its own (and more than a thousand public methods). During the build process, I link the two libraries together into a single deliverable, for ease of integration and deployment by the API consumer.

The problem I'm facing now is that I don't want the end user (an application developer integrating my software to enhance their own functionality) to ever be bothered with all that extra cruft, drowning in a torrent of unnecessary complexity.

From the outside, the library should look like it contains exactly two public classes, with exactly seven public methods.

How do you handle this sort of thing in your own projects? I'm interested in the language agnostic solutions, as well as the various techniques for different languages, compilers, and build tools.

In my specific case, I'm developing for the flash platform (AIR/Flex/Actionscript) with SWC library files. The build methodology is analagous to the Java platform, where all classes are bundled into a zipped code module with equal visibility (an Actionscript SWC file is, conceptually, almost exactly identical to a Java JAR file).

Doesn't .NET have an "internal" modifier for classes and methods? That's exactly the sort of thing I'm looking for, and if anyone knows of a tricky technique to hide the visibility of classes between SWC boundaries, I'd love to hear it.

+1  A: 

I think you can pull this off by using namespaces: http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000040.html

Notice that namespaces is not the same in actionscript as in C#, it is more like namespaces in xml.

Lillemanden
+1  A: 

It's pretty hard to hide things in AS. There is an internal access specifier and there are also namespaces. Adobe has some help on Packages and namespaces that may be useful to you.

It is important to note that namespaces do not limit access - they are really used to place symbols into a different ... well namespace. This could be used to have 2 versions of the same library accessed in the same swf. My guess is it just does some name-mangling behind the scenes before inserting definitions into the symbol table. If users want, they can just import the namespace and access anything that is "hidden" behind it. I've done that when hacking apart Adobe components. That said, if the user doesn't have the original source and is incapable of determining the namespace identifier than you have a bit of security through obscurity.

package access specifiers (e.g. private and internal) are closer to what you want. But if you can access classes outside package boundaries then the user can too. There are even hacks I've seen around that can examine a swfc and spit out a list of embedded classes which one can use getClassByDefinition to instantiate.

So, you can hide the classes existence in your documentation, use internal and private access specifiers wherever possible and then use namespaces to mangle the classnames. But you cannot prevent a determined person from finding and using these classes.

James Fassett
Very nice. I knew about namespaces, but I thought they were only used for XML. And I had no idea that "internal" was a valid modifier in AS3. Thanks!
benjismith
A: 

Incidentally, one of the other tricks that I've used (since I didn't know about the "internal" modifier or namespaces) is to hide classes by declaring them outside the current package, like this:

package com.example {

   public class A {
      // ...
   }

}

class B {
   // ...
}

class C {
   // ...
}

I've even though about writing a little tool that will analyze all the "import" directives within a project and move all external dependencies into these kinds of hidden private classes.

benjismith
This works iff the class is only used within the file (e.g. it has no external visibility). I would prefer this kind of file level scope before internal scope (which is useful when only classes within a package will access the definition).
James Fassett