Blog - BlogPost - BlogPostComment vs Blog - Post - Comment - naming

Don't really know how to formulate the title, but it should be pretty obvious from the example.
More specifically, what rules do you use for naming "dependent" classes. For example, Blog is a pretty descriptive name itself, but how do I deal with posts? BlogPost or Post? Clearly, first name clearly expresses that it's a "subordinate" class, but this can quickly get out of hand with BlogPostComment, BlogPostCommentAttachment, etc. Post, on the other hand, looks like an entity completely unrelated to Blog and is easier on the eye.
What are your rules/best practices?

I personally like the latter best. And wouldn't a good namespace-name disambiguate Post?

In the case you mention, the problem is so well known as it makes no difference to be terse, and it actually saves you typing. Other types of relationships between classes aren't so cut-and-dry.
Another plus to using "Blog", "Post" and "Comment" is that you could reuse Post and Comment for other stuff not necessarily blog-related, and they'd fit better there (ok, it's just a rename anyway).
My rule would then be 'be as clear as you can'. I do tend to assume that, before you come barging in on my code, or I start a project guns ablaze, we have read a bit about the problem space.
Furthermore: most web frameworks I know make things much easier to use terse names like Blog, Post, etc. for model names.

Interesting question. I would use either depending on the situation.
For example a simple News and NewsItem would be fine as it's a basic model and the naming convention makes the relation clear in this case.
However, for larger developments with more complex domain models and well maintained namespacing (for example a blog) I would say it's must less convoluted and cleaner to name the types Blog, Post, Comment.

Related

Domain Driven Design implementation issue between modeling and coding

I am studying hard DDD now. After months of studying, I found a contradiction between modeling and coding. As you know, DDD has the principle of "Domain 1st, Tech 2nd". However, there are "definite" constraints when moving the actual model into the implementation, for example:
Original model:
With the domain concept, posts are associated with multiple comments, and comments are an ordinary model that depends on the post. Moving this into code ...
class Post{
Integer postId;
String title;
String content;
String writer;
Collection<Comment> comments;
}
class Comment{
String content;
}
Like this... But if there are hundreds of millions of comments, there will be performance problems. According to the solution I have investigated, finally I change the original model as follows....
Revised model:
Also the code will change...
class Post{
Integer postId;
String title;
String content;
String writer;
}
class Comment{
Integer postId;
String content;
}
This revised model works well for me and I am satisfied with the solution. But I feel something inconsistent. It seems that the model is distorting due to technical constraints. If we show the first and second models to the domain experts and talk about the diagram, he or she will better understand the first model.
Am I misunderstanding about DDD concept? If so, give me some advice. Thank you.
One of the changes in mindset that come with Domain Driven Design is that your domain will constantly evolve with changes to your understanding of the domain. It is not just that the domain will evolve, but your understanding and perception about it will evolve, as well.
What you are running into right now, in my opinion, is trying to rationalize the design based on the loading of one or more entities into an aggregate by looking at it from how it is persisted. This common parent and child relationship feels natural, because it is the way that most of us have done things in the past. Even from a DDD perspective, it is easy to get caught up in the "Comments can't exist without Posts" paradigm.
This comes down to the fact that you are modelling based upon data inside of the domain, instead of use cases. Look at it this way... Posts are not simply a collection of Comments. Instead, a Comment refers to a specific Post. The nuance sounds minor, but it has broad-reaching consequences. When modeled in this fashion, it matches your revised model - and it is completely and totally fine. The only thing you need to change is your mindset, being that Comment can be considered an Aggregate, just as a Post is. They both are going to have use cases where the other one must exist, but at the same time, you need to see that you are unlikely to do something where both are impacted as part of the same use case (outside of deletion of the Post).
To illustrate, consider this use case:
As a Writer, I want to be able to edit the Content of my Post.
Your new model actually effectively supports that. Instead of looking at the relationship, you are looking at how the domain is used. Should you load Comments for a Writer to edit? Without knowing your domain, I would still assume that you would not want to do so. There are use cases that will likely involve both Posts and Comments, and that is also fine. Since you have two Aggregates inside of a single Bounded Context, you will be able to support use cases that are solely based on Posts, solely based on Comments, or a combination of both.
In terms of the technical concerns, you mention "hundreds of millions of comments". I assume that you mean system-wide, and not for a single Post? Assume that you have an active post, and that it sees 20k comments in its lifetime. For a properly designed and optimized database, this should still not be an issue. When it becomes an issue, if it ever does, it can be further addressed by additional changes to the technology used, as opposed to changing the domain. You can look at things like caching strategies (outside of the domain, since that is an application concern and not a domain concern), external indexes, eventual consistency, etc.
Highly recommend taking a read through Vaughn Vernon's "Effective Aggregate Design" series of articles, if you have not already:
Effective Aggregate Design
Additionally, his excellent book "Implementing Domain-Driven Design", is a must-read, in my opinion. While the Evans material is essential, it is more like the theoretical concepts; whereas the Vernon material talks about how to put the concepts into practice and what the implications of those decisions are.
As an addendum, like plalx points out in the comments below. None of this is meant to be a generalization about Posts and Comments in general, but explicitly how they apply to your domain, as it has been described to us and what could be inferred from your models. Posts and Comments will likely behave differently for others, because others will have distinct use cases. Even within your own domain, should Posts and/or Comments exist in a different context, they could behave differently. Above all else, try and make sure that everything you add to your domain model (in general) is added because of a specific and direct use case. It is tempting to simply start data modeling, but you will start to find yourself trying to force use cases into the domain model. Domain modeling should not be a finite process, or a single step in the process. Be willing and able to adapt to changes in understanding or changes to the way that the business changes its overall operational strategies over time.
One pitfall I notice about people entering the DDD world is that they visualize their ARs as source of READ operations as well. So, many times they tend to "model" the ARs and its entities/value objects in a way that "appeals" a DTO that is meant to hydrate the UI.
In your case, I would make Post an AR and Comments another AR. Adding a comment shouldn't require to instantiate Post at all. Editing a Post shouldn't require to 'load' the comments at all.
Use an independent mechanism to project your post/comments into a POCO/DTO class that may make sense to have a collection of comments in your post.
Does it make sense?

Why does complexType need to be avoided?

I came across this list of W3C XML Schema: DOs and DON'Ts and the part that says DO NOT use complex types kind of surprises me.
I don't find any trouble in using <xs:complexType name="SomeNewType"> and I don't see why using <xs:group name="someNewElement"> is better than using a complexType.
Should complexType really need to be avoided?
If so, why? What is so problematic about it?
What should be used instead?
For almost any language sufficiently complex and powerful to be interesting, different people will have different views on the best way to use that language.
You ask "should complexType really be avoided?" As you've seen, in the document you point to Kohsuke Kawaguchi (who was a member of the working group that designed XSD and has written several important XSD tools, including one of the first XSD validators) advises users to avoid certain constructs in XSD, including complexType, often on the grounds that the ratio of their advantages to their disadvantages (in particular: their complexity) is poor. You can (and indeed you must) make up your own mind on the persuasiveness of KK's arguments.
Since (as far as I can see) your question amounts to asking "is KK right?", I gather that you don't feel entirely comfortable making up your own mind, or at least that you are curious and want to know what others think.
In general, it's safe to say that many users of XSD, and many creators of XSD tools, disagree with KK. They find the ability to derive complex types from other complex types helpful, and they use it.
It's equally safe to say that many others agree with KK that this or that construct of XSD is too complex and is better avoided. Some who feel this way write documents describing "best practices" which lay out constructs to use and constructs to avoid; sometimes the contents of such documents is useful and sometimes not. Many who agree most fervently with KK about XSD's complex types do not use XSD at all, when they can avoid doing so: they prefer Relax NG (or in some cases, DTDs or Schematron).
In other words: the opinions of qualified observers vary, as do those of unqualified observers. I know some very smart people who disagree with KK on this question. And I also know that KK himself, and some of those who agree with him, are also very smart. I have no intention of choosing a side here.
Finally, you ask If it is problematic, why does it exist in the language construct in the first place? Any construct in any language exists because those who designed the language thought it was worth including. In the case of XSD and complex types, that means: complex types are in XSD as nameable objects because essentially everyone in the responsible working group wanted them in the language. This does not prevent them from being problematic: like everyone else, people of great technical skill can make mistakes, and groups that must seek consensus can under the right circumstances produce designs that no one really likes very much (but which everyone prefers to the alternative of not having the construct in question at all; sometimes compromise is the only way to get something done).
I hope this helps.

DDD what all terms mean for Joe the plumber who can't afford to read books few times?

I am on a tight schedule with my project so don't have time to read books to understand it.
Just like anything else we can put it in few lines after reading books for few times. So here i need some description about each terms in DDD practices guideline so I can apply them bit at a piece to my project.
I already know terms in general but can't put it in terms with C# Project.
Below are the terms i have so far known out of reading some brief description in relation with C# project. Like What is the purpose of it in C# project.
Services
Factories
Repository
Aggregates
DomainObjects
Infrastructure
I am really confused about Infrastructure, Repository and Services
When to use Services and when to use Repository?
Please let me know if anyway i can make this question more clear
I recommend that you read through the Domain-Driven Design Quickly book from infoq, it is short, free in pdf form that you can download right away and does its' best to summarize the concepts presented in Eric Evan's Blue Bible
You didn't specify which language/framework the project you are currently working on is in, if it is a .NET project then take a look at the source code for CodeCampServer for a good example.
There is also a fairly more complicated example named Fohjin.DDD that you can look at (it has a focus on CQRS concepts that may be more than you are looking for)
Steve Bohlen has also given a presentation to an alt.net crowd on DDD, you can find the videos from links off of his blog post
I've just posted a blog post which lists these and some other resources as well.
Hopefully some of these resources will help you get started quickly.
This is my understanding and I did NOT read any DDD book, even the holy bible of it.
Services - stateless classes that usually operate on different layer objects, thus helping to decouple them; also to avoid code duplication
Factories - classes that knows how to create objects, thus decouple invoking code from knowing implementation details, making it easier to switch implementations; many factories also help to auto-resolve object dependencies (IoC containers); factories are infrastructure
Repository - interfaces (and corresponding implementations) that narrows data access to the bare minimum that clients should know about
Aggregates - classes that unifies access to several related entities via single interfaces (e.g. order and line items)
Domain Objects - classes that operate purely on domain/business logic, and do not care about persistence, presentation, or other concerns
Infrastructure - classes/layers that glue different objects or layers together; contains the actual implementation details that are not important to real application/user at all (e.g. how data is written to database, how HTTP form is mapped to view models).
Repository provides access to a very specific, usually single, kind of domain object. They emulate collection of objects, to some extent. Services usually operate on very different types of objects, usually accessed via static methods (do not have state), and can perform any operation (e.g. send email, prepare report), while repositories concentrate on CRUD methods.
DDD what all terms mean for Joe the plumber who can’t afford to read books few times?
I would say - not much. Not enough for sure.
I think you're being quite ambitious in trying to apply a new technique to a project that's under such tight deadlines that you can't take the time to study the technique in detail.
At a high level DDD is about decomposing your solution into layers and allocating responsibilities cleanly. If you attempt just to do that in your application you're likely to get some benefit. Later, when you have more time to study, you may discover that you didn't quite follow all the details of the DDD approach - I don't see that as a problem, you proabably already got some benefit of thoughtful structure even if you deviated from some of the DDD guidance.
To specifically answer your question in detail would just mean reiterating material that's already out there: Seems to me that this document nicely summarises the terms you're asking about.
They say about Services:
Some concepts from the domain aren’t
natural to model as objects. Forcing
the required domain functionality to
be the responsibility of an ENTITY or
VALUE either distorts the definition
of a model-based object or adds
meaningless artificial objects.
Therefore: When a significant process
or transformation in the domain is not
a natural responsibility of an ENTITY
or VALUE OBJECT, add an operation to
the model as a standalone interface
declared as a SERVICE.
Now the thing about this kind of wisdom is that to apply it you need to be able to spot when you are "distorting the definition". And I suspect that only with experience (or guidance from someone who is experienced) do you gain the insight to spot such things.
You must expect to experiment with ideas, get it a bit wrong sometimes, then reflect on why your decisions hurt or work. Your goal should not be to do DDD for its own sake, but to produce good software. When you find it cumbersome to implement something, or difficult to maintain something think about why this is, then examine what you did in the light of DDD advice. At that point you may say "Oh, if I had made that a Service, the Model would be so nmuch cleaner", or whatever.
You may find it helpful to read an example.:

Why can't I model my domain using ERD?

I am fairly new to this discussion but I HAVE to ask this question even at the risk of sounding 'ignorant'. Why is it that we now stress so much on 'DDD'. The more I look into 'DDD' the more complex it seems to make my application. Whereas modeling my domain with the database helps keep my application consistent across layers. Then I can use DAL Helpers such as SubSonic or L2S to easily access that model. What is so bad about this? Even in enterprise applications?
Why do we strive to create a new way of modeling our domain when we have a tried and tested one?
I am willing to hear from the purists here.
You can't sell an old methodology, because too many projects failed and too many people know the old methodology anyway. There has to be a new one to market.
If you're doing fine with the old way then use what works. Do pay attention to new stuff, as some really nice ideas come along. But that doesn't mean everything old is bad and stupid. Usually you can incorporate new ideas into the old models to a large degree.
There does come a time to make a move. Like I wouldn't do OOP with structures and function pointers. ;-)
This is actually a really excellent question, and the short answer is "you can." We used to do it that way, and there was a whole area of enterprise (data) modeling. In fact, the common OOD notations evolved from ERD.
What we discovered, however, was that data-driven designs like that had some difficulties, the biggest of them being that the natural structure for a data base doesn't necessarily match well to the natural structure for code.
OOD, to a great extent, derives from the desire to make it easier to find a code structure that has a couple of desirable properties:
it should be easy to think out the design
it should be robust under changes.
The ease to think out design comes originally from Simula, which used what we now think of as "objects" for simulation specifically; it was convenient in simulation to have software entities that correspond to the things you're simulating. It was only later that Alan kay et al at Xerox saw that as a more general structuring method.
The part about robustness under changes had many parents, but one of the most important ones among them was Dave Parnas, you wrote several papers that identified a basic rule for modularization, which I call Parnas' Law: every module should keep a secret, and that secret is a requirements that is likely to change.
It turns out that by combining Parnas' Law with the Simula idea of a "object" as corresponding to something that can be identified with the real world, you tend to get system designs that are more robust under requirements changes than the old way we did things. (Not always, and sometime you have to be crafty, as with the Command pattern. Most objects are nouns, thing that have persistent existence. In the Command pattern, the ideal objects are verbs, things you do.)
However, it also turns out that that structure isn't necessarily a good way to represent the underlying data in a relational database, so we end up with the "object relational impedance mismatch" problem: how to represent the transformation from objectland to database-land.
Short answer: if all you need is a CRUD system that allows users to edit data, just build an Access front-end to your back-end database (or use a scaffolding framework like you mentioned) and call it a day. You should be able to lop off 70% of your budget vs. a domain-driven system.
Long answer: with a data-driven design, what does the implementation of the business model look like? Usually after a couple years of building on new features to your application, you'll find that it's all over the place: tables, views, stored procedures, various application services, code-behind files, presenters/ViewModels, etc. with duplication everywhere. When you're having a conversation with the domain expert about a new feature they are requesting, you are constantly trying to translate from the business language into the language around your implementation, and it just does not translate.
What typically ends up happening is that you are forced to communicate with the business in terms of the implementation of the system, and the implementation becomes the "ubiquitous language" that the business and developers are forced to use when communicating. This has a wide range of consequences. The domain experts in the business start believing that they are experts in the implementation domain, and they start demanding features in terms of implementation rather than the business need they are trying to solve.
Also, you'll find that most data-driven implementations do not follow the "conceptual contours" of the domain, and the components of the system aren't very flexible in how they can be combined together to solve the problem, because they don't map one-to-one with concepts in the business model. When code isn't cohesive, changes and new features may require modifications all over your implementation.
Domain Driven-Design provides tools for making your implementation so closely resemble the business model that it's easy for everyone to speak the language of the business. It allows you to write "executable specifications" that test your implementation, but can actually be understood by your domain experts.

What's the best approach to naming classes?

Coming up with good, precise names for classes is notoriously difficult. Done right, it makes code more self-documenting and provides a vocabulary for reasoning about code at a higher level of abstraction.
Classes which implement a particular design pattern might be given a name based on the well known pattern name (e.g. FooFactory, FooFacade), and classes which directly model domain concepts can take their names from the problem domain, but what about other classes? Is there anything like a programmer's thesaurus that I can turn to when I'm lacking inspiration, and want to avoid using generic class names (like FooHandler, FooProcessor, FooUtils, and FooManager)?
I'll cite some passages from Implementation Patterns by Kent Beck:
Simple Superclass Name
"[...] The names should be short and punchy.
However, to make the names precise
sometimes seems to require several
words. A way out of this dilemma is
picking a strong metaphor for the
computation. With a metaphor in mind,
even single words bring with them a
rich web of associations, connections,
and implications. For example, in the
HotDraw drawing framework, my first
name for an object in a drawing was
DrawingObject. Ward Cunningham came
along with the typography metaphor: a
drawing is like a printed, laid-out
page. Graphical items on a page are
figures, so the class became Figure.
In the context of the metaphor, Figure
is simultaneously shorter, richer, and
more precise than DrawingObject."
Qualified Subclass Name
"The names of subclasses have two jobs.
They need to communicate what class
they are like and how they are
different. [...] Unlike the names at
the roots of hierarchies, subclass
names aren’t used nearly as often in
conversation, so they can be
expressive at the cost of being
concise. [...]
Give subclasses that serve as the
roots of hierarchies their own simple
names. For example, HotDraw has a
class Handle which presents figure-
editing operations when a figure is
selected. It is called, simply, Handle
in spite of extending Figure. There is
a whole family of handles and they
most appropriately have names like
StretchyHandle and TransparencyHandle.
Because Handle is the root of its own
hierarchy, it deserves a simple
superclass name more than a qualified
subclass name.
Another wrinkle in
subclass naming is multiple-level
hierarchies. [...] Rather than blindly
prepend the modifiers to the immediate
superclass, think about the name from
the reader’s perspective. What class
does he need to know this class is
like? Use that superclass as the basis
for the subclass name."
Interface
Two styles of naming interfaces depend on how you are thinking of the interfaces.
Interfaces as classes without implementations should be named as if they were classes
(Simple Superclass Name, Qualified Subclass Name). One problem with this style of
naming is that the good names are used up before you get to naming classes. An
interface called File needs an implementation class called something like
ActualFile, ConcreteFile, or (yuck!) FileImpl (both a suffix and an
abbreviation). In general, communicating whether one is dealing with a concrete or
abstract object is important, whether the abstract object is implemented as an
interface or a superclass is less important. Deferring the distinction between
interfaces and superclasses is well >supported by this style of naming, leaving you
free to change your mind later if that >becomes necessary.
Sometimes, naming concrete classes simply is more important to communication than
hiding the use of interfaces. In this case, prefix interface names with “I”. If the
interface is called IFile, the class can be simply called File.
For more detailed discussion, buy the book! It's worth it! :)
Always go for MyClassA, MyClassB - It allows for a nice alpha sort..
I'm kidding!
This is a good question, and something I experienced not too long ago. I was reorganising my codebase at work and was having problems of where to put what, and what to call it..
The real problem?
I had classes doing too much. If you try to adhere to the single responsibility principle it will make everything all come together much nicer.. Rather than one monolithic PrintHandler class, you could break it down into PageHandler , PageFormatter (and so on) and then have a master Printer class which brings it all together.
In my re-org, it took me time, but I ended up binning a lot of duplicate code, got my codebase much more logical and learned a hell of a lot when it comes to thinking before throwing an extra method in a class :D
I would not however recommend putting things like pattern names into the class name. The classes interface should make that obvious (like hiding the constructor for a singleton). There is nothing wrong with the generic name, if the class is serving a generic purpose.
Good luck!
Josh Bloch's excellent talk about good API design has a few good bits of advice:
Classes should do one thing and do it well.
If a class is hard to name or explain then it's probably not following the advice in the previous bullet point.
A class name should instantly communicate what the class is.
Good names drive good designs.
If your problem is what to name exposed internal classes, maybe you should consolidate them into a larger class.
If your problem is naming a class that is doing a lot of different stuff, you should consider breaking it into multiple classes.
If that's good advice for a public API then it can't hurt for any other class.
If you're stuck with a name, sometimes just giving it any half-sensible name with commitment to revising it later is a good strategy.
Don't get naming paralysis. Yes, names are very important but they're not important enough to waste huge amounts of time on. If you can't think up a good name in 10 minutes, move on.
If a good name doesn't spring to mind, I would probably question whether there is a deeper problem - is the class serving a good purpose? If it is, naming it should be pretty straightforward.
If your "FooProcessor" really does process foos, then don't be reluctant to give it that name just because you already have a BarProcessor, BazProcessor, etc. When in doubt, obvious is best. The other developers who have to read your code may not be using the same thesaurus you are.
That said, more specificity wouldn't hurt for this particular example. "Process" is a pretty broad word. Is it really a "FooUpdateProcessor" (which might become "FooUpdater"), for example? You don't have to get too "creative" about the naming, but if you wrote the code you probably have a fairly good idea of what it does and doesn't do.
Finally, remember that the bare class name isn't all that you and the readers of your code have to go on - there are usually namespaces in play as well. Those can often give readers enough context to see clearly what your class if really for, even if its bare name is fairly generic.

Resources