Guidelines

3 views
Skip to first unread message

ermau

unread,
Dec 4, 2009, 11:15:52 PM12/4/09
to cadenza-list
Along with the new name, I think there's more directions that Jon and
I would like to take the library. The trick is deciding what belongs,
and what belongs in it's own namespace (or even assembly.) Personally
I feel these should be outlined specifically instead of just deciding
in a cowboy manner as things come up (or at the least get some general
ideas as guidance.)

Some initial thoughts:
- Shouldn't be afraid of namespaces, the collections should go to
Cadenza.Collections for example. Most generic enough extension methods
should stay in the base namespace. Probably most extension methods
should stay in the Cadenza NS for ease of use.
- Things that may not work well cross platforms should probably go
in its own assembly. A set of S.R.Emit extension methods shouldn't be
in the main assembly, as it won't work on MonoTouch.
- Not sure what the constraints on what's to be included or not,
needs to be of significant use and actually provide an easier or more
succinct way of doing something at least.

Also, as Jon has done in the path, Cadenza shouldn't accept any code
without accompanying tests.

Jonathan Pryor

unread,
Dec 5, 2009, 12:09:28 AM12/5/09
to ermau, cadenza-list
On Fri, 2009-12-04 at 20:15 -0800, ermau wrote:
> Along with the new name, I think there's more directions that Jon and
> I would like to take the library. The trick is deciding what belongs,
> and what belongs in it's own namespace (or even assembly.) Personally
> I feel these should be outlined specifically instead of just deciding
> in a cowboy manner as things come up (or at the least get some general
> ideas as guidance.)

What's wrong with cowboy manners? :-)

More seriously, there is something to be said for the normal
"abstraction" rules -- start thinking about abstractions when you have
three different implementations of a given abstraction, so that you know
what the abstraction actually is.

In this case, the "abstraction" is more abstract -- what should be
included vs. restricted, what should go where, etc. -- but the idea is
the same, and it raises the same question: do we have enough distinct
"entities" running around that we can come up with a general set of
guidelines yet?

I'm not sure that we do.

> Some initial thoughts:
> - Shouldn't be afraid of namespaces, the collections should go to
> Cadenza.Collections for example. Most generic enough extension methods
> should stay in the base namespace. Probably most extension methods
> should stay in the Cadenza NS for ease of use.

So, case in point: I have no idea how namespaces should be split up.

More specifically, how many namespaces do we want most user code to need
to make use of, especially considering the extension method basis of the
library?

In short, is it *really* that beneficial to require that most users
write:

using Cadenza;
using Cadenza.Collections;
using Cadenza.IO;
// ...

We certainly could require that we mirror the .NET namespace names with
s/System/Cadenza/g (within reason), resulting in Cadenza.Collections,
Cadenza.IO, Cadenza.Data, Cadenza.Reflection.Emit, etc. namespaces, but
is this actually beneficial to the user in any way?

I'm not convinced that overly split up namespaces is beneficial.

At present, I would prefer that we keep the namespaces to a minimum, at
least for extension methods.

For actual types that the user needs to deal with, these should perhaps
be split up into namespaces.

Why the inconsistency?

Because users don't write type names for extension methods, thus type
names can't conflict if you have the same type name in multiple
assemblies. (Instead, methods can conflict, requiring that they have
distinct argument lists, which is why we have
IEnumerableRocks.HaskellGroupBy(), so that it doesn't clash with
Enumerable.GroupBy().)

Types (like Maybe, Tuple, etc.), on the other hand, *are* written by the
user, and may conflict with other libraries [0].

Consequently, I'm far more willing to throw concrete types
(ReadOnlyDictionary, etc.) into separate namespaces.

But again, things are far from clear to me.

> - Things that may not work well cross platforms should probably go
> in its own assembly. A set of S.R.Emit extension methods shouldn't be
> in the main assembly, as it won't work on MonoTouch.

This makes sense. We should thus take a page out of the "Sharing
Silverlight Assemblies with .NET apps" [1] page, and say that only
things that are present in ALL of Silverlight, MonoTouch, and .NET
desktop assemblies should go into Cadenza.dll.

I'll restrict it further (somewhat): Cadenza.dll should ONLY depend upon
mscorlib.dll, System.dll, System.Core.dll. If you need any other
dependencies (or depend on functionality within one of those assemblies
but not present on all platforms), then it belongs in a new assembly.

By that reasoning, System.Reflection.Emit, System.Data, and XML
extension methods all belong in their own separate assemblies (if/when
we ever get such extension methods).

> - Not sure what the constraints on what's to be included or not,
> needs to be of significant use and actually provide an easier or more
> succinct way of doing something at least.

Alas, we dropped the easiest way of controlling whether it belongs: is
it an extension method?

We can keep the extension method focus (if desired), and restrict
Cadenza to ONLY extension methods AND types required to implement those
extension methods (and types referenced by types referenced by extension
methods, ad infinitum). I think this would actually include all types
currently in Cadenza.

While this would work, it's also trivial to "work around" (just add an
extension method that utilizes your new type), which isn't bad per-se.
It's also not much of a limitation.

I suspect, at least for the time being, this is something we'll need to
play by ear (and/or in a "cowboy" fashion).

> Also, as Jon has done in the path, Cadenza shouldn't accept any code
> without accompanying tests.

Absolutely.

- Jon

[0] There WILL be conflicts, in the case of Tuple and .NET4 -- should
Tuple be renamed, or should we wrap all the Tuple definitions in a
'#if !NET_4_0' block so that when building against .NET 4.0 you use
mscorlib's Tuple?

[1]
http://blogs.msdn.com/clrteam/archive/2009/12/01/sharing-silverlight-assemblies-with-net-apps.aspx


ermau

unread,
Dec 7, 2009, 9:33:28 AM12/7/09
to Jonathan Pryor, cadenza-list
In short, is it *really* that beneficial to require that most users
write:

       using Cadenza;
       using Cadenza.Collections;
       using Cadenza.IO;
       // ...
 
Would it be more beneficial that we increase the possibility for conflicts?

Because users don't write type names for extension methods, thus type
names can't conflict if you have the same type name in multiple
assemblies.  (Instead, methods can conflict, requiring that they have
distinct argument lists, which is why we have
IEnumerableRocks.HaskellGroupBy(), so that it doesn't clash with
Enumerable.GroupBy().)

I think we're just as likely to include a type that will conflict as we are to include an extension method that will conflict. 

I'll restrict it further (somewhat): Cadenza.dll should ONLY depend upon
mscorlib.dll, System.dll, System.Core.dll.  If you need any other
dependencies (or depend on functionality within one of those assemblies
but not present on all platforms), then it belongs in a new assembly.
 
I like this metric, very clear.
 
By that reasoning, System.Reflection.Emit, System.Data, and XML
extension methods all belong in their own separate assemblies (if/when
we ever get such extension methods).

Agreed. 
 
We can keep the extension method focus (if desired), and restrict
Cadenza to ONLY extension methods AND types required to implement those
extension methods (and types referenced by types referenced by extension
methods, ad infinitum).  I think this would actually include all types
currently in Cadenza.

That would exclude MutableLookup<T>, and while it we may retain a focus around extension methods, I don't want to limit ourselves to that.

Jonathan Pryor

unread,
Dec 7, 2009, 10:24:23 AM12/7/09
to ermau, cadenza-list
On Mon, 2009-12-07 at 09:33 -0500, ermau wrote:
> In short, is it *really* that beneficial to require that most
> users write:
>
> using Cadenza;
> using Cadenza.Collections;
> using Cadenza.IO;
> // ...
>
> Would it be more beneficial that we increase the possibility for
> conflicts?

Good point. Sounds like we should do a "simplified mirror" of or
namespaces then. "Simplified mirror" meaning that extension methods on
System.Collections.Generic go into Cadenza.Collections (not
Cadenza.Collections.Generic, hence "simplified"), while extension
methods on e.g. System.IO.Stream go into Cadenza.IO.

Types should go into a useful corresponding namespace (or a new
Cadenza-specific namespace, if appropriate, though I don't know of
anything that would currently fit this description).

MutableLookup<TKey, TElement> should likewise go into
Cadenza.Collections (as opposed to Cadenza.Linq, even though
ILookup<TKey, TElement> is in System.Linq).

Again, "simplified." Perhaps "unified" would make more sense.

> We can keep the extension method focus (if desired), and restrict
> Cadenza to ONLY extension methods AND types required to
> implement those extension methods (and types referenced by
> types referenced by extension methods, ad infinitum). I think
> this would actually include all types currently in Cadenza.

> That would exclude MutableLookup<T>, and while it we may retain a
> focus around extension methods, I don't want to limit ourselves to
> that.

Agreed. Thus I'm out of ideas for how to restrict what belongs in
Cadenza (and more importantly, what doesn't belong). I'm not sure this
is *too* important at this time; we can take code contributions on a
case by case basis. Worst case, things that "don't make sense" can go
into a separate assembly, thus keeping the "footprint" down.

- Jon


ermau

unread,
Dec 7, 2009, 11:13:45 AM12/7/09
to Jonathan Pryor, cadenza-list
Good point.  Sounds like we should do a "simplified mirror" of or
namespaces then.  "Simplified mirror" meaning that extension methods on
System.Collections.Generic go into Cadenza.Collections (not
Cadenza.Collections.Generic, hence "simplified"), while extension
methods on e.g. System.IO.Stream go into Cadenza.IO.

Sounds good to me.

MutableLookup<TKey, TElement> should likewise go into
Cadenza.Collections (as opposed to Cadenza.Linq, even though
ILookup<TKey, TElement> is in System.Linq).

I agree.
 
Agreed.  Thus I'm out of ideas for how to restrict what belongs in
Cadenza (and more importantly, what doesn't belong).  I'm not sure this
is *too* important at this time; we can take code contributions on a
case by case basis.  Worst case, things that "don't make sense" can go
into a separate assembly, thus keeping the "footprint" down.

Fair enough, sounds good for now. Just have to see how it goes. 

Jonathan Pryor

unread,
Dec 7, 2009, 2:40:11 PM12/7/09
to ermau, cadenza-list
On Mon, 2009-12-07 at 10:24 -0500, Jonathan Pryor wrote:
> On Mon, 2009-12-07 at 09:33 -0500, ermau wrote:
> > In short, is it *really* that beneficial to require that most
> > users write:
> >
> > using Cadenza;
> > using Cadenza.Collections;
> > using Cadenza.IO;
> > // ...
> >
> > Would it be more beneficial that we increase the possibility for
> > conflicts?
>
> Good point. Sounds like we should do a "simplified mirror" of or
> namespaces then. "Simplified mirror" meaning that extension methods on
> System.Collections.Generic go into Cadenza.Collections (not
> Cadenza.Collections.Generic, hence "simplified"), while extension
> methods on e.g. System.IO.Stream go into Cadenza.IO.

This has been done for I/O and Collections-related types, creating new
Cadenza.Collections and Cadenza.IO namespaces.

The wiki has also been updated with our current naming conventions:

http://gitorious.org/cadenza/pages/Home

However, one oddity came up: Where should NaturalStringComparer go? I
moved it into the Cadenza.Collections namespace (as it implements
System.Collections.Generic.IComparer<string> and
System.Collections.IComparer, and it's used by
IEnumerableRocks.OrderByNatural()), but this doesn't seem quite
appropriate. Should it go into a Cadenza.Text namespace?

Furthermore, if we do move it into Cadenza.Text, what is the purview for
Cadenza.Text? If we follow previously discussed conventions,
System.String extension methods should go into the Cadenza namespace
(NOT Cadenza.Text), as Cadenza.Text should be (mostly) for extending
types in System.Text, which includes StringBuilder, Encoding, Encoder,
and Decoder (not a whole lot of types in System.Text).

Thoughts?

- Jon


ermau

unread,
Dec 9, 2009, 9:49:35 PM12/9/09
to Jonathan Pryor, cadenza-list
However, one oddity came up: Where should NaturalStringComparer go?  I
moved it into the Cadenza.Collections namespace (as it implements
System.Collections.Generic.IComparer<string> and
System.Collections.IComparer, and it's used by
IEnumerableRocks.OrderByNatural()), but this doesn't seem quite
appropriate.  Should it go into a Cadenza.Text namespace?

Furthermore, if we do move it into Cadenza.Text, what is the purview for
Cadenza.Text?  If we follow previously discussed conventions,
System.String extension methods should go into the Cadenza namespace
(NOT Cadenza.Text), as Cadenza.Text should be (mostly) for extending
types in System.Text, which includes StringBuilder, Encoding, Encoder,
and Decoder (not a whole lot of types in System.Text).

I'm almost inclined to say in the Cadenza NS itself. Comparers aren't really specific to collections anymore. On the other hand, it doesn't sound like something that people wouldn't have implemented themselves, so there's risk of conflict. Conflict is typically fairly easily resolvable, just really annoying. Tough one, but I'd lean towards in straight Cadenza, same goes for Sequence.

Jonathan Pryor

unread,
Dec 10, 2009, 9:27:07 AM12/10/09
to ermau, cadenza-list
On Wed, 2009-12-09 at 21:49 -0500, ermau wrote:

> I'm almost inclined to say in the Cadenza NS itself. Comparers aren't
> really specific to collections anymore. On the other hand, it doesn't
> sound like something that people wouldn't have implemented themselves,
> so there's risk of conflict. Conflict is typically fairly easily
> resolvable, just really annoying. Tough one, but I'd lean towards in
> straight Cadenza, same goes for Sequence.

Done - NaturalStringComparer and Sequence are now in the Cadenza
namespace.

- Jon


ermau

unread,
Mar 15, 2010, 8:50:13 AM3/15/10
to Jonathan Pryor, cadenza-list
So has anyone been writing code with Cadenza other than myself? Wondering how these guidelines worked out for the end 'user'.

For me personally, it hasn't been painful, but somehow I suspect that's because most of my usage lies in Cadenza.Collections, and ReSharper makes it really easy to import namespaces.
Reply all
Reply to author
Forward
0 new messages