Is putting conversion method inside (POCO?) object (like .ToPerson() method in Consumer class) considered breaking single responsibility pattern?
Yes, because conversion is another responsibility.
Is using converting constructors in (DTO-like) class considered breaking single responsibility pattern? Especially if such class can be converted from multiple source types, so multiple converting constructors would be required?
Yes, conversion is another responsibility. It makes no difference if you do it via constructors or via conversion methods (e.g. ToPerson
).
Is using extension methods while having access to original class source code considered bad practice?
Not necessarily. You can create extension methods even if you have the source code of the class that you want to extend. I think that whether you create an extension method or not should be determined by the nature of such method. For example, does it contain a lot of logic? Does it depend on anything other that the members of the object itself? I would say that you shouldn't have an extension method that requires dependencies to work or that contains complex logic. Only the simplest of logic should be contained in an extension method.
Can such behavior be used as viable pattern for separating logic or is it an anti-pattern?
If the logic is complex, then I think that you shouldn't use an extension method. As I noted earlier, you should use extension methods only for the simplest things. I wouldn't consider conversion simple.
I suggest that you create conversion services. You can have a single generic interface for it like this:
public interface IConverter<TSource,TDestination>
{
TDestination Convert(TSource source_object);
}
And you can have converters like this:
public class PersonToCustomerConverter : IConverter<Person,Customer>
{
public Customer Convert(Person source_object)
{
//Do the conversion here. Note that you can have dependencies injected to this class
}
}
And you can use Dependency Injection to inject a converter (e.g. IConverter<Person,Customer>
) to any class that requires the ability to convert between Person
and Customer
.
I doubt that an interface like IPoint3D
brings you more benefits than trouble, so here my suggestion: create a concrete, immutable (so also sealed) class Point3D
instead. When using interfaces, the geometric point/vector operations can only be implemented in a fashion where the underlying type information gets lost, but that is not a problem of the programming language, but a problem of the domain.
The reason for this becomes clearer when you try to make two different implementations of that interface, lets say an AutocadPoint3D
(representing a point in an autocad CAD model, with lots of additional data like tags, color, layer etc.) and a GoogleEarthPoint3D
(representing a coordinate in an KML model). Now try to add points of those two classes by a method like
IPoint3D Add(IPoint3D point1, IPoint3D point2)
So what should be the underlying type of the result be? A new AutocadPoint3D
, a GoogleEarthPoint3D
, or something different (like your SimplePoint
)? The only thing which probably makes sense would probably be the SimplePoint
, because it is something like the "smallest common denominator" of all 3D points. Moreover, IPoint3D
cannot be used to force sealed implementations, so code which relies on IPoint3D
cannot be sure the underlying type is always immutable. This might suffer from unexpected side effects when the implementer of the interface is not very careful.
Think about the reason for what purpose you typically use interfaces. The most frequent purpose is probably dependency injection, especially for unit testing. But it seldom makes sense to mock out a value object like Point3D
. Imagine you need to test a class which needs an IPoint3D
, you would probably inject a SimplePoint
object with some predefined values as test data - but then you could also use a SimplePoint
directly and save the interface. So the interface only adds "noise" to your code, with no real benefit.
Best Answer
Assuming you will call
HttpUtility.HtmlEncoded()
from your extension method (otherwise it's a no-no) and also that you will use a meaningful name to your method (otherwise you will just make code less clear). Given:Let's compare:
Honestly I do not see any big improvement. Now let's introduce C# 6 static using feature:
I think it's clear which one is better. Also note that
HttpUtility.HtmlEncode()
has three overloaded methods and I usually consider a very bad practice to polluteobject
with useless extension methods.Note that "...less code to write..." is not always and undoubtedly better. String conversions are an important and critical (both for performance and for security). If you name your method
ToHtmlString()
but - with help of Intellisense - you writeToString()
you may have a potentially big bug latent in your code which may go unnoticed in a code review session.