|
ms
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
A question on naming schemes - when frequent collissions with the BCLs are present(this question has been on my mind for some time now, so I'm just trying to describe the problem the best I can and hopefully get the discussion started.) I'm looking for suggestions, feedback and advice regarding naming schemes in public APIs where collissions between business objects (BOs) and types in the BCL are frequent. I'm working on a API (for a CMS) that provides all the well-known tiers (data, repository etc.), including a few UI tiers, that extend types in ASP.NET (e.g. Page, MasterPage, UserControl). As far as I'm concerned, recommendations and best practices suggest naming business objects (or entities in general) according to their primary function or usage (e.g. User, Role, Page). When APIs that co-exist in the same domain, there is a desire to use the same name for an entity. If the developer wants to use these APIs at the same time, he is forced to either fully qualify all type references (which is bloated and unreadable) or alias namespaces (also leads to less readable code). After much thinking back and forth, this situation lead me (with much resistance) to prefix my public business objects with "Cms" (look at SharePoint, they went with "SP" are prefix for all public types). I'm uncertain, whether this is the right decision because it feels both right, so to speak; Easy as in "it's easy to distinguish objects in the CMS API from similar types in the BCL" and wrong as in "prefixing feels bloated and less clean". Here are a few examples from two assemblies in the API. [SphereWorks.Cms.Data].Page (reside in seperate assembly) [SphereWorks.Cms.Publishing.Model].CmsPage (reside in seperate assembly, describes a hierarchical node in a navigable tree) [SphereWorks.Cms.Data].User [SphereWorks.Cms.Publishing.Model].CmsUser and in the UI department: [SphereWorks.Cms.Web.UI].CmsWebPage (subclasses System.Web.UI.Page, represents a templated control) ... As you can see from above, the term "Page" perfectly describes an entity or business object in each domain, yet they share the same name. A developer is typically going to work with several similar types at the same time; // override method in CmsWebPage (subclasses System.Web.UI.Page) protected override void OnLoad(EventArgs e) { CmsHttpContext context = CmsHttpContext.Current; CmsPage page = context.State.Page; Page template = this.Page; new ControlLoader(context).Load(page, template); } using namespace aliasing, the following scenario is possible: // override method in CmsWebPage (subclasses System.Web.UI.Page) protected override void OnLoad(EventArgs e) { Model.HttpContext context = Model.HttpContext.Current; Model.Page page = context.State.Page; Page template = this.Page; new ControlLoader(context).Load(page, template); } Highest priority should be "look and feel" of the API to the developer; it feels painful to force the developer to alias namespaces each time they want to interact with the API because of collissions. (Now that I'm feature complete, I'm refactoring the entire API for unit testing and I guess that the introduction of "I" (as in IUser, IPage, IContext etc.) is going to let the developer work against the interfaces instead of the concrete business objects. As mentioned before, the SharePoint team decided to go with the "SP" prefix, which at first seemed unnatural, but with years of experience from this API (unfortunately ..), it seems quite natural and it also makes it easy to share info with other developers ("just get the SPWeb and .." or "yes, the SPFile object supports .."). (thanks in advance) With regards Anders Borum / SphereWorks Microsoft Certified Professional (.NET MCP) On Wed, 01 Jul 2009 02:14:32 -0700, Anders Borum <and***@sphereworks.dk>
wrote: > [...] I'm quoting this passage because IMHO it's one of the most central points > As you can see from above, the term "Page" perfectly describes an entity > or > business object in each domain, yet they share the same name. A > developer is > typically going to work with several similar types at the same time; here. In particular, I'm not convinced that "the term 'Page' perfectly describes an entity or business object in each domain". In a context where the options are limited, perhaps "Page" all by itself is sufficient. But perfection is hard to come by, and in the examples you're citing, it's clear that you have a variety of different kinds of pages, and that there may in fact be a "more perfect" description than simply "page". Even the code you posted is suggestive of this point: > // override method in CmsWebPage (subclasses System.Web.UI.Page) The mere fact that one variable you have named "page" and the other you > protected override void OnLoad(EventArgs e) > { > CmsHttpContext context = CmsHttpContext.Current; > CmsPage page = context.State.Page; > Page template = this.Page; > > new ControlLoader(context).Load(page, template); > } have named "template" strongly suggests to me that whatever kind of "Page" is referred to by "CmsWebPage.Page" is in fact a special "template-y" page, and thus the type name could easily incorporate that information (or even be simply "Template" instead of page, for that matter). The fact is, I don't think that prefixing is really all that bad an approach, when it's really necessary. I would prefer to use namespaces (or even type containment where appropriate) to qualify type names, and leave the type names as simple as possible. But as you've already noted, this can get out of hand when you're dealing with types that are by design going to be used regularly in contexts that require qualification. There's lots of precedent for using prefixes, and it's not the end of the world to follow that approach in .NET. But, the very first thing I'd look at always is whether the simple name that seems so "perfect" for so many different types really is in fact that perfect. I know in my own code, I have found that as appealing as a simple one-word type name is, even absent a naming conflict it turns out that using a more specific, more descriptive name is helpful, and of course doing so helps resolve any potential naming conflicts that might crop up. I can't speak for your own code base. For all I know, you've got one of the few exceptions where that approach just doesn't work. But, the fact that your post doesn't mention that as a possibility in other situations, and that your own code seems to suggest viable alternatives along those lines, makes me wonder if you've really sufficiently considered that as an option. Pete
Other interesting topics
set location of Form2 based on Location of Form1?
OT: missing posts Linq to Sql Exception Specified cast is not valid LINQ Max getting to know c# Linq to Sql insert fails check console args C# Export Excel to client side Application configuration settings - Do I make global? How to find out what the server name is? |
|||||||||||||||||||||||