Showing posts with label type safety. Show all posts
Showing posts with label type safety. Show all posts

Wednesday, December 31, 2008

Namespace visibility in C#

Java has package scoping. It allows an element to be visible only within the same namespace. It's a wonderful thing.

Here's how it works in Java:


package com.pc-doctor.mynamespace;
package class Foo { ... }


The class Foo is only visibile within mynamespace.

Even though I'm not a Java programmer, this immediately strikes me as extremely useful. Frequently, helper classes are only needed by code that lives close by.

There are two reasons to want namespace visibility to be enforced by your compiler:

  1. If you can make those classes invisible outside the namespace, it will make life a lot easier for clients of that namespace. Having only the useful classes appear in Intelisense is a big win.
  2. Having helper classes be invisible also helps construction of the component that is in the namespace. If the compiler doesn't let anyone make calls to the helper classes, then we can make much stronger assumptions about how our clients use the code.
C# does not offer any support for namespace visibility. However, there are three ways to accomplish it. None of them are perfect, and one of them is a bit bizarre.

The Microsoft Way



Microsoft expects you to make the classes internal. This prevents anyone outside of the assembly from using the class.

However, you have to make a separate assembly for each namespace that you want to do this with.

Frankly, that's painful enough that few people do it.

The C++ Way



C++ also lacks namespace visibility. The folks over at Boost use a separate namespace underneath the main namespace for helper classes (and functions). They've standardized on the name "detail" for this namespace, and it works fine for problem #1. It doesn't do anything for #2, though.

This is an easy thing to do, but it doesn't do much in C#. C# programmers use a lot more using directives than C++ programmers should. The only place to put a using directive in C# is at the top of the file. This means that, if a single function needs a namespace, then the whole file will get it.

The end result is that a lot of detail namespaces will be visible. This means that you'll have to make a using directive for the detail namespace that you really want, and you'll have to avoid typing "detail" to get to an element.

Even with those problems, it's probably worth doing in C#. Create a detail namespace under each namespace and put things that you'd like to have package scope in there.

Getting the C# Compiler to Enforce Namespace Visibility


C# does have a feature that can be used to emulate namespace visibility. This solution is a bit weird.

I should point out that it uses a feature of C# that wasn't designed for what we're going to use it for. In C++, this kind of behavior is encouraged and well supported. In C# (and Java), you're not supposed to deviate from the party line.

I'm sure Microsoft doesn't have any tests written for this behavior; I've already found one bug in the compiler from this technique.

What is a namespace? It allows many classes to be placed in the same scope even when they're stored in different files.

A partial class does the same thing, and this can be used to emulate a namespace. Partial classes were designed to allow Microsoft's code generators to create part of a class and put those portions of the code in a separate file. C#'s designer tool makes heavy use of this.

It's also very close to a namespace!

If you use a partial class as a namespace, then you can put multiple classes in different files and have some of them be invisible outside of the "namespace".

A private class inside the "namespace" is visible to other classes in the namespace, but it is not visible outside of the namespace. Likewise, a public class is visible outside of the partial class.

All of this is enforced by the compiler, too. We get both of the benefits of namespace visibility with this technique.

Unfortunately, it doesn't work perfectly.

For example, using declarations don't work for a partial class. If you're not in the namespace, you will always have to use the partial class's name to access public members of the namespace. This may be annoying in some cases, but, if you limit this technique's use to cases where there isn't a lot of access to the namespace from outside of it, then it's not serious.

It also looks wrong in the IDE. The IDE has no idea that your class is really a namespace, so it gets colored incorrectly. The severity of this problem is a matter of opinion. It doesn't bother me.

This is all awkward enough to prevent me from completely replacing namespaces. Instead, I use this when I want to expose an extremely simple API and perhaps a type or two. It's really only worth the trouble if you get to hide a lot by using this.

The syntax is also verbose:

namespace pcdoctor {
  partial public class fakeNamespace {
    private class NamespaceVisibilityClass {}
  }
}

There's actually a hidden benefit of this technique. It's possible to make a "free function" in the fake namespace. A static member function behaves a lot like a free function. It's accessible from any of the classes in the namespace. If it's public, then it's accessible from outside the namespace.

I mentioned that I found a bug in the compiler. Unfortunately, I didn't track down exactly what the bug was. Instead, I just found a solution and moved on.

However, if you find that some of your code gets executed more than once when the fakeNamespace type is instantiated, then you might want to find another solution.

Good luck! Just remember that the central authority that controls C# programmers doesn't want you to do this. You're on your own here.

Wednesday, April 23, 2008

The Next JavaScript...

ECMAScript 4.0 (ES4) is on its way. This will be the next standard for JavaScript. It's not going to be usable on web pages for a while, though. In fact, I suspect I won't be using it on my web page for at least 5 years. The problem is simple: as long as people still use older browsers, you won't be able to assume that people have it.

However, the features in it are an interesting look at what the standards committee thinks is wrong with the current JavaScript. This is not a minor patch release. This is a dramatically overhaul of the current JavaScript (ES3). Oh, they've included a lot of minor things that are simply broken in ES3. These changes are certainly interesting, but today I'm going to talk about their major focus. They want to make it easier to develop large applications in JavaScript. Clearly, they understand that people are starting to develop large applications for web browsers, and they feel that there are problems with the currently available technologies for this.

I don't have any experience with developing what I'd call a large JavaScript application, but we are starting to develop an extension of PC-Doctor for Windows that uses JavaScript in numerous places to control its behavior. In my dreams, I imagine that it will eventually become a large application made up of plugins that run on JavaScript.

Let's go through the major features that the committee thinks I'll need as our technology gets bigger...

Classes and conventional OOP. I thought this was interesting. They're adding conventional classes as an alternative to the prototype based inheritance that ES3 supports. This comes with a bunch of normal OOP things like virtual functions, getter and setter functions for "virtual properties", interfaces, inheritance, etc.

I can certainly understand why they wanted this. Type safety is greatly enhanced if you can know exactly what type something has. ES4 makes it possible to create a "conventional" class who's members look a lot like Java's and C#'s. You can't write or delete arbitrary properties of one of these classes. With ES4 and a properly written program, the language will be able to determine that you're doing something unintended to some objects and fail at runtime.

Type safety. The new class system allows values to actually have a strict type. Most user created types in ES3 are simply Objects with certain properties and a specific value of the prototype member. That's close to a type, but it's only an approximation since it's possible to change it with some member assignments. The new classes will have a strict type that cannot be changed.

This is bigger than it sounds. This means that code can require certain types in certain variables. It means that a member function will remain a member function for the lifetime of that object. The runtime engine can enforce this, too. The standard doesn't hide the fact that inserting some extra asserts in the code will slow things down, however. They bring this up clearly, and they don't apologize for it.

This is called type safety, and it's something that I've been advocating for a while. The committee wanted it badly enough to be willing to slow programs down for it. They go beyond even that, though.

They've introduced another mode of execution called "strict mode". In this optional mode, the execution engine is supposed to perform some static analysis of the program before it begins. The engine is supposed to fail when a variety of illegal things are possible in the code. For example:

1. Writing to a const property.
2. Calling functions with the wrong number of arguments.
3. Referencing properties of class objects that don't exist.
4. Failing a type check.

The great thing is that all of this happens before the code is executed. It's done entirely with static analysis. If anyone ever bothers to implement this mode (it's optional), then JavaScript is going to become my new favorite scripting language!

I should point out that there are few guarantees about strict mode. Different browsers are going to check for different things in strict mode. Therefore, it is only useful in development. I predict that developers will run the most strict web browser on their development machines and publish without strict mode turned on.

I'm going to claim that this is strong support for my work on a Lua static analysis program. They are coming extremely close to saying that in order to write large applications, a scripting language requires strong type checking, and static analysis might be able to relieve the runtime of some of its need for that. Since Lua's runtime has no static type checking, it needs static analysis as well.

Yeah. I'm going to claim that many of my previous rants are backed up by this committee!

Function overloading. Function overloading is a trick that's only available to languages that can define the type of an object. ES4's version is slower than Java's version because it has to happen at runtime. However, the important thing is that it's possible.

Functions are values of variables in JavaScript just like strings or numbers. You might ask how it's possible to assign more than one function to a single variable name. They do it in two ways.

The first is something they call a generic function object. This is an object that can hold more than one function in it. It exists as a single value. It's a bit clunky, but I couldn't come up with anything better.

Speaking of ugly, there's another way to overload functions. They added a switch statement that works on the type of the value. Here's the example from their overview paper:

switch type (v) {
case (s: string) { ... }
case (d: Date) { ... }
}

That looks like a pathetic attempt at overloading to me, but it could well be how generic function objects are implemented internally. It may be that this could be used to create a more flexible generic function object. However, I predict that consultants 5 years from now will make lots of money going to companies to give talks condemning the use of it.

Packages and namespaces. This is used to hide the activities of different components in an application. This is clearly lacking in ES3 even with small scale libraries and applications. Library authors tend to go to great lengths to hide as much of their code as possible from the global namespace. With the small applications I've written, it's been working fine, but I can see its limitations.

Overall, I'm pleased with where ES4 is trying to go. They're trying to make it safe to build large applications with JavaScript. Given where we're seeing web applications going, this is a great thing. However, I can't imagine that it'll work anytime soon since Google Web Toolkit gives ES3 programmers compile time type safety right now.

Mostly, however, I'm pleased that the committee is trying to add type safety to an untyped language in almost exactly the same way that I would. :-)

This originally appeared on PC-Doctor's blog.

Tuesday, July 31, 2007

Choosing a programming language: Is type safety worth it?

I'm a big fan of the strongly typed language vs weakly typed language debate. It's old, but it's also important.

I'm revisiting this topic because I'm trying to decide exactly that problem on a project that I'm working on. In my case, I'm torn between client side JavaScript on the web browser and Google Web Toolkit (GWT) compiled to JavaScript. The only reason I have to mention this is because I want to eliminate the quality of the libraries from the debate. GWT has fairly rudimentary libraries, but they're growing, and you can add JavaScript libraries if you really have to.

I'm going to try to have a debate with myself about it. I can't claim that I'm unbiased, and I'm going to ignore arguments that I don't consider significant. I'd love to hear further arguments from you in the comments.

Argument for weak typing


Weak typing allows you to write code faster. Well, that's what the proponents of it claim, anyway. I haven't seen any good measurements of this. There's certainly less typing to do, though. You don't have to declare the type of your variables. (In JavaScript, you do have to declare your local variables, however.) (It is worth pointing out that I have never written software and been limited by my typing speed. I'm skeptical of this argument.)

If you're designing a scripting language, then weak typing is easier to explain to inexperienced programmers. There's a whole step that doesn't have to be done. In some circumstances, this is a clear win. (In my case, this is irrelevant.)

Argument for strong typing


Strong typing allows the compiler to do more work for you. Essentially, you're constraining how variables can be used, and the compiler can use those constraints to detect errors or perform optimizations.

The optimization part is important for a few people. The error detection is great for everyone.

Counterargument from weak typing.


Unit testing is the weakly typed solution to error checking. (It's also the strongly typed solution, but for a different class of error.) It's either hard or impossible to write a unit test that checks that function arguments have the correct properties before going into a function. However, you can write a unit test that ensures that functions behave correctly in a variety of different circumstances. That's what programmers really care about, anyway.

Also, suppose we want to have a function that supports multiple types? In a strongly typed language like Java, we can only support different types if they share an interface. In a weakly typed language, we can support multiple types if they support the same operations. If I want a function that adds all the elements of a collection together, I can write one function that supports both strings and complex numbers correctly. (This is possible with generic programming as well in a strongly typed language, but that's not really what we're arguing about here.)

Rebuttal from strong typing


Unit testing is a good guarantee, and it's one that's required by strongly typed languages as well. However, it's a fundamentally different guarantee than you get by having the compiler check the types of variables as they're used by the code. First, a compiler checks every line of code even if it's hard to get to or you forgot to write one of the unit tests. Second, the combination of tests and strong typing is a better guarantee than tests alone.

Here's a Ruby example of some dangerous code:


function foo( a, b )
  if a < 0.0
    print( b )
  end
end
foo( -12, 'This string is printed' )
foo( 5 )


This code has two "overloads". One takes a string and a negative number. The other takes a non-negative number and might take a string. The problem is, there is no good way to tell this based on the function signature. You can only tell by looking at the implementation. This means that you can't safely change the implementation of your function.

Unit testing partially guarantees that functions have working implementations. Strong typing partially guarantees that they are used correctly.

Conclusion


I'm going to go with Google Web Toolkit, which imposes strong typing on top of JavaScript. The mediocre library support may bite me later, but I'll be happier knowing that my compiler knows a bit about what my code will do.

I'm hoping I get flamed by someone, so please post your comments!

This originally appeared on PC-Doctor's blog.