DWScript now has a new “unit namespace” feature, which aims at killing several birds with one stone:
- supporting “classic” namespace as found in Java or .Net
- supporting aggregate namespaces and conditional units
- supporting unit deprecation and splitting with backward-compatibility
unit namespace Foo.Bar; [deprecated 'deprecation message';] uses Foo.Bar.One, Foo.Bar.Two, WhateverUnit;
and that’s all for the Foo.Bar.pas file. Unit namespaces don’t expose or implement anything.
With the above unit namespace, if in regular code you have
uses Foo.Bar, OtherUnit;
it will be equivalent to having written
uses Foo.Bar.One, Foo.Bar.Two, WhateverUnit, OtherUnit;
So all the unit namespace’s “uses” are brought into scope when the unit namespace is used.
Use for classic namespaces
In that case the unit namespace code will have to be auto-generated dynamically by your IDE or compiler environment, which will be responsible for collecting all the individual files that compose the namespace and presenting them in the unit namespace.
Unit namespaces files don’t have to be generated on disk or anywhere: you can just generate in memory in the DWScript event or interface you’re already using to feed source files. It’s just a way to tell the compiler all the source files that are part of a particular namespace.
Use for aggregated namespaces and conditional units
Unit namespaces are oblivious to what they’re made of, so you can aggregate unit from different namespaces.
Typical usage case is when some class defined in FooBar is using or referring other types defined in OtherUnit, and it’s common to need types of OtherUnit when using the class. You can use a unit namespace to bundle those as a convenience – just don’t got overboard and package everything and the kitchen sink!
Also, as unit namespace are source code, they support conditional directives ($ifdef, $include etc.), meaning you can use them for conditional compilation, depending on target.
Remember the Kylix era with Controls vs QControls in “uses” that had to be placed in all cross-toolset forms or components and controled with directives? If unit namespaces had been available, this conditionality could have be segregated rather than spread over every form.
Use for deprecation and refactoring
Suppose you want to rename FooBar to Foo.Bar, in Delphi you could use unit aliases, but that’s a compiler setting, and it won’t encourage or facilitate projects to be migrated. With unit namespaces you can rename FooBar to Foo.Bar and keep FooBar as unit namespace:
unit namespace FooBar deprecated 'Renamed to Foo.Bar with a dot!'; uses Foo.Bar;
and with it the old code will compile, with a deprecation warning, thus facilitating migration.
You can also leverage it for refactoring, f.i. if FooBar isn’t just renamed to Foo.Bar but also split into Foo.Bar and Core.Bar, f.i. if someone had put Core.* stuff into FooBar, and you’re cleaning that up. You can then introduce
unit namespace FooBar deprecated 'Splitted to Foo.Bar and Core.Bar'; uses Foo.Bar, Core.Bar;