|
it's a DTO, i.e. all those could be field really (except it would sparkle another argument). No code is either run into that class, just a bag of well known property....
|
|
|
|
|
The same still applies; anything that is required should be there in the constructor. If it is not required for the objects existence, then it becomes a property. For a DTO, I'd expect an Id-field, and without an Id such object should not exist.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Neither. It shouldn't be the responsiblity of MyFooClass to return a FooDto, it should be FooDto's class to take a MyFooClass and convert it to a FooDto.
So you have instead:
public class FooDto
{
public static FooDto From(MyFooClass c)
{
}
}
And to make this more re-usable for different data objects and to avoid repeating From for every type of "from - to" conversion, use interfaces:
public class FooDto : IFooDto
{
public static IFooDto From(IFooClass c)
{
}
}
This promotes consistency between properties in FooDto and properties in the "from" class that can be mapped to FooDto .
Latest Article - A Concise Overview of Threads
Learning to code with python is like learning to swim with those little arm floaties. It gives you undeserved confidence and will eventually drown you. - DangerBunny
Artificial intelligence is the only remedy for natural stupidity. - CDP1802
|
|
|
|
|
Of the two choices given, I'd take 1; but would prefer a third option.:
public class FooDto
{
public FooDto(MyFooClass foo)
{
Property1 = foo.property1;
Property24 = foo.property24;
}
public T1 Property1 { get; }
public T24 Property24 { get; }
}
class MyFooClass
{
private T1 property1;
private T24 property24;
}
If for some reason I
Did you ever see history portrayed as an old man with a wise brow and pulseless heart, weighing all things in the balance of reason?
Is not rather the genius of history like an eternal, imploring maiden, full of fire, with a burning heart and flaming soul, humanly warm and humanly beautiful?
--Zachris Topelius
Training a telescope on one’s own belly button will only reveal lint. You like that? You go right on staring at it. I prefer looking at galaxies.
-- Sarah Hoyt
|
|
|
|
|
If you really want to bake their noodle, put all the value maps in Attributes and then have the object built via Reflection such as in this article[^]. It's a super complicated way to do simple tasks
if (Object.DividedByZero == true) { Universe.Implode(); }
|
|
|
|
|
public class Foo
{
public class DTO
{
public T1 P1 { set; get; } = P1_default_value;
...
public T24 P24 { set; get; } = P24_default_value;
}
public void In(DTO dto)
{
}
public DTO Out()
{
DTO dto = new DTO();
return dto;
}
private T1 _P1;
...
private T24 _P24;
} The DTO object constructs itself with a consistent default set of values. The DTO property accessors are responsible for maintaining consistency of that set. The In and Out methods of the Foo class manage its internal state based on accepting or producing a DTO, respectively. This approach lets you do things like this:
Foo foo = new Foo();
...
foo.In(new DTO() { P3 = Fred, P17 = Wilma; });
Foo foo2 = new Foo();
foo2.In(foo.Out());
Software Zen: delete this;
|
|
|
|
|
So option 1 gives you simplicity, whereas option 2 gives you immutability. There are arguments for both, the immutability one being that one DTO can be safely shared by many things as none of them can alter it. With option 1, by rights you need to keep cloning the thing to prevent any badly behaved code messing up the 'master' copy. So there's a memory/performance trade off with all that. You often get that cloning for free through serialization mind.
That said, when you wish to change one property on option 2, it becomes a screaming nightmare of reconstructing a new one with one difference in the constructor parameter list. We had option 2, but it was too much to stomach in the end.
Regards,
Rob Philpott.
|
|
|
|
|
|
It depends.
I use option 2 only for values that are absolutely necessary for the class to work (and that should never be 24 parameters, that's just bad design!).
And option 2 is ideal for constructor injection in DI.
Other than that, option 1.
|
|
|
|
|
Could you not just use inheritance and do away with all the property setting?
public class FooDto
{
public FooDto(T1 value1 , T24 value24)
{
Property1 = value1;
Property24 = value24;
}
public T1 Property1 { get; }
public T24 Property24 { get; }
}
class MyFooClass : FooDto
{
}
This exposes properties T1 ... T24 of the base FooDto class but that may or may not be an issue. There are arguments against combining DTOs and inheritance, so without knowing the details of your implementation this may not be appropriate. Part of "knowing the details" of course involves the use of a crystal ball to envisage future changes, but depending on the scenario you can pretty much rule out a lot of potential stuff and, in this case, save yourself a lot of code.
|
|
|
|
|
Such a FoodDto is absolutely useless, a snapshot in time...
There is little point in deriving from it...
This FooDto sole purpose is to be turned into json and vice versa. It comes from an object that do update each individual property in real time (mostly hardware read status)
|
|
|
|
|
My bad; I meant the constructor for FooDto to be
public class FooDto
copy/paste, eh?
|
|
|
|
|
would be nice...
unfortunately the way the DLL dependency tree is set... can't happen...
i.e. the FooClass is in a DLL that reference the assembly where FooDto is defined....
FooDto is in a common contract assembly...
|
|
|
|
|
Nobody seems to have yet mentioned any other alternatives...one would be passing in a structure with 24 members as an initializer, although in C# that doesn't really eliminate the problem, since you'd have a similar problem with how to initialize the structure. Might be useful tho if you instantiated a lot of these objects with mostly the same parameters.
I would never condone instantiating a class without initializing all member data items, but if there are reasonable default values for them, I could see an initializer (or maybe even a few) that initialized all or most of them to default values, and only set one or two to non-default values. Don't ever want to leave values uninitialized, however.
Of course, there are those who would say that any object that needs this many initializers is poorly designed and should be refactored. It would be up to the author in each individual case to decide if this is feasible.
For my money, this makes a good case for a language feature I've been wanting ever since the days I worked with the ADA language - named parameter lists. Then you could offer default values for all parameters, and let the caller set only the ones (s)he wants to differ from the default values. Of course, you can emulate this now in C#, but it requires 2^n constructors. I've done it with three parameters (eight constructors), but of course it would be impractical with 24.
|
|
|
|
|
|
Good ideas about the default values. And C# actually does have named paramaters. So, if they all have default values, you could just pass in a few that need to be set.
|
|
|
|
|
Good to know that named parameters were actually implemented. At my job, we're still using VS 2008, so I wasn't aware that they had taken my advice!
|
|
|
|
|
You should really try and get them to update or you should go somewhere else. That sound ridiculous to still be using VS2008.
|
|
|
|
|
Yeah, I know. But it's about the only job available in my relatively small city, and I'm nearing retirement anyway, so I'm basically just playing out the clock...
|
|
|
|
|
I strongly prefer the code your prefer.
Putting all of those properties as separate parameters of a method is something I was forced to do by someone who got his code from a glorious "whitepaper", and has resulted in hours added on to debugging when one of the parameters is wrong in some way, and has resulted in unnecessarily lengthy code calling those methods for every property even when only one or two properties need to be set.
|
|
|
|
|
You could propose an option 3, that has an object with all the items that need to be passed in. According to Martin Fowler, too many options passed into a constructor is a code smell.
Quote: A large list of construction parameters, like any large parameter list, is a CodeSmell. Usually when I see these I find that many of the parameters are DataClumps and should be replaced by their own object. Having said that it's not unusual for constructor methods to have more parameters than other methods - but they are a good place to spot data clumps.
Martin Fowler - Constructor Initialization
|
|
|
|
|
I believe there are reasons for either style and I don't mean a simple preference by the developer.
The first style allows you to initialise an object with some default values and gradually fill its properties with desired non-default values. Also it allows you to change those values over time to reflect changes in how the class (or another dependent class) should behave. You can see that in any visual component for UWP/WPF/ASP.NET. Meanwhile, the second style creates a kind of immutable object (it can only be read although its properties can still be changed due to internal operations, if any). Changes to this data may not be desired due to e.g. the intended design of the application (or API) or legal reasons.
If you must follow the second style with a class with so many constructor arguments (with which I agree it might be a code smell), I'd recommend creating a Builder for the object. MyFooClass in this example seems to be one which might actually hint at why the guy wanted you to change the code style; perhaps he thought you were trying to create in MyFooClass a Builder for FooDto and wanted you to make it so both classes don't repeat themselves. Anyway, I'd recommend approaching the guy with an open mind to try and understand his motivations for requesting the style change; it may either enhance your knowledge of the application or the guy you're working with.
[UPDATED] Both Dan's or Marc's answers offer a great alternative to avoiding so many arguments on the constructor. I'd also check if you could go either way.
- Leonardo
modified 31-Oct-18 12:49pm.
|
|
|
|
|
I personally don't like either option. Why create two classes that duplicate the same information. I would create a property in MyFooClass to point to FooDto. Or better yet, inherent MyFooClass from FooDto.
|
|
|
|
|
FooDto could be final for all we care. its whole intent, purpose, life cycle, is to turn Data into JSON and vice versa. Nothing more....
mm.. I'd like the idea of justsharing my own internal status class... but that won't fly either.. plus I have been forced to take in some dependency that prevent having these internal status in shared library.. So I do need to duplicate them in contract library upon which I depend
|
|
|
|
|
To quote Alan Perlis: If you create a function with 10 arguments, you probably missed one.
|
|
|
|