4

My question comes from this other question.

The first time I read the question, I understood (maybe worngly) that the OP was asking for a different way to initialize the object in such a way that it would allow him to extend and make easier the maintenance. Hence my answer.

However, some comments seem to agree with passing an array as a single argument would be even easier.

We usually don't turn a function with # named parameters into a function with a single array of # positions.

public Message(String id, String a, String b){...}

public Message(String[] arguments){...}
public Message(String... arguments){...}

Turning # named parameters (all the same type) into a array is something I have done back in my early days as coder. Back then, I realised how brittle they were. For example, these structures are very sensible to changes. The order of the elements within the array and the length of the array matters, because we map attributes, fields or variables to positions within the array.

The following question agree with me. The only apparent difference is that the former question, the function is a constructor and in the last one is a method.

So looking at both questions linked here, I see how on one side we are suggesting to use arrays the way I commented and on the other side, we are discouraging from doing the very same practice.

My question boils down to, from the OOP point of view, Are arrays (as data structures) suitable for constructors but unsuitable methods?

If yes. Why? Do we apply different "rules" to define constructor's and method's signatures? Ultimately, both are functions.

If not. When is appropriated to use one or another?

To me, both cases lacks on maintainability, readability and scalability.

11
  • 2
    C# specifically supports arrays as first-class method parameter objects. It even provides a special params keyword so that a variable number of arguments can be specified. It's hard to imagine how they would incorporate that into the language if it weren't useful. You haven't really explained why you think such practices are brittle. Jul 21 '17 at 21:25
  • 1
    As to your answer on the previous question, I find it to be a perfect example of the kind of over-engineering that seems to be so much in vogue these days. Jul 21 '17 at 21:28
  • 1
    @Laiv Do you mean storing multiple, potentially heterogeneously typed, parameters into a single array, in place of a Params class?
    – Alexander
    Jul 21 '17 at 21:45
  • 5
    @Laiv: In short, an array is appropriate if all items are treated uniformly. If the method treat items differently based on the index, then an array is not appropriate. An array with givenName, surName, age etc as fields is probably wrong, since code would treat givenName differently than age, but having an array with addresses might be appropriate if all addresses are processed the same way. Without meaningful names in the example it is impossible to way whether this is the case or not.
    – JacquesB
    Jul 22 '17 at 12:04
  • 1
    You all are right. I have understated the relevance of the lack on meaningful param names in the former question. In consequence I rushed into a solution that in many senses is overengineering.
    – Laiv
    Jul 22 '17 at 22:22
9

There is no difference in the suitability of arrays [1] as function or constructor arguments. The real question is if an array is a correct model for the kind of data you have. In your example where you have a 2-part message with an ID, transforming (pseudo code)

Message(String id, String a, String b)

to

Message(String[3] message)

is wrong because an array is the wrong data structure for that kind of data. You do not have a list of three texts. What you have is three pieces of data that comprise a single structured entity. So even the three separate arguments are highly questionable because they fail to express that they all belong together. At least use something like this:

struct MessageData {
    String id;
    String a;
    String b;
}

Message(MessageData message)

However, that’s not the ideal data structure, either. id should really be of its own distinct type that maybe holds a string inside. Why?

  • It is an identifier, not a text. So it shouldn’t be a string.
  • We have textual data that represents two different concepts: “identifier” and “payload text”. (At least that’s how I chose to interpret a and b for lack of more specific info about what kind of message this is.) Different concepts should be modelled as different types.

What this all boils down to is: Use the type system to its full extent to make your data structures as expressive as possible. After all, that’s why we have type systems in the first place.

[1]: I’m using “array” in a broad sense here – as in a container for a sequence of values

7
  • This is the sort of answer I was expecting. I also suggested in my answer encapsulation, which indeed, contribute to type our model far beyone from the primitive types. Despite my examples don't reflect this point. However, your point around typing the concept ID has make me realise that I often fail in modeling this elements. I like your question and hence the Up vote. If you don't mind I would like see If I'm missing something else.
    – Laiv
    Jul 22 '17 at 9:44
  • Reading this answer, I come to realise that maybe the title of my question doesn't reflect my concern. Would you mind to suggest a better way to do It?
    – Laiv
    Jul 22 '17 at 9:49
  • Maybe what you’re getting at is the question of “How to decide when to use general built-in types and when to create custom types?” Though, imo, that warrants its own question – and a bunch of article-long answers. :)
    – besc
    Jul 22 '17 at 22:01
  • True. I come to realise that I understated the importance of the lack on meaningful param names in the former question. I would like to check your question, but looks like the likely probable answer is that "It depends" and "I rushed into the solution without enough and meaningful info". Your answer, alongside with Robert and JaquesB comments, Ewan and juhist are partally right. The answer could be perfectly a sum of all them. I will think if I summarize It into a own answer or just check yours. Hope you don't mind.
    – Laiv
    Jul 22 '17 at 22:17
  • 2
    They reasoned that a strongly typed data structure is less flexible and prone to type conversion errors. Their reasoning is correct, but those properties are usually exactly what you want. It took me a while to realize but now I see the type system as a safety net. I want it to complain loudly and immediately if I do something weird with types. Things like in Javascript 1 == "1" returning true instead of complaining about a type mismatch, scare me. It’s mindbogglingly error prone. If you can circumvent the type system in such a way, what’s the point in having one at all?
    – besc
    Jul 23 '17 at 8:54
9

You can absolutely use arrays as data structures, and pass them to constructors and methods. Let me propose few examples:

  • A curve fitting application. The complex model is broken into array of double-precision floating point numbers that are the fitting parameters. The function that calculates the fitting error will take in this array of double-precision floating point numbers in addition to a reference to the complex model. The benefit is that the fitting code itself doesn't need to know about the complex model, it only needs to know about N fitting parameters. So, you can develop the fitting code independently of your simulation code.
  • Drawing line charts. You will give the line chart library two arrays of double-precision floating point numbers: one that contains the X values and other that contains the Y values. If you use Java, the benefit is that array is much faster and needs less garbage-collection than some abstract List of Pair<Double, Double> objects.
  • Command line arguments. The function main takes an array of String objects.
  • Simulating one-dimensional curves for fitting. The function takes a data point of X coordinates along with a complex model, and calculates the quantity of interest for each data point.

I'm sure there are many other examples. I just picked the examples that are relevant to the application I'm currently developing.

8
  • Sorry, I should have been more precise. I know that for math algorithm, graphic design, cartography, etc... arrays are common. But if we are modeling the class Message, I don't see how expressing its strucutre as array make the whole thing simpler and maintenable.
    – Laiv
    Jul 22 '17 at 8:07
  • I don't see how this changes a thing. If the message consists of number of fields of the same type without special names, sure, you could use an array there.
    – juhist
    Jul 22 '17 at 9:13
  • So why don't we just work with arrays instead of named parameters?
    – Laiv
    Jul 22 '17 at 9:15
  • Because sometimes, parameters do have meaningful names. Then you use either parameters or a Map<String, T> or similar.
    – juhist
    Jul 22 '17 at 9:15
  • Do you usually code this way? Using Maps or named parameters indistinctly?
    – Laiv
    Jul 22 '17 at 9:17
1

The linked question is looking for a way not to explicitly pass in all the properties of an object which also doesn't use setters.

The normal way of having some other settings class or struct with the named values and passing that in doesn't help them because that class would essentially have the same problem.

So someone suggests passing in an array. But not as an optimal way of constructing, as you obviously lose the names of the parameters. Just as a practical solution to thier unsolvable dilemma.

5
  • Don't you think that encapsulating different concepts may do the thing easier? Even if it lead you to a hierarchy of classes? Otherwise, I don't see the point in OOP.
    – Laiv
    Jul 22 '17 at 9:55
  • well at some point you have to map values to properties. I think the referred to question is basically 'how do i do this without doing that?' well, you can, but 'that' is the normal way of doing 'this'
    – Ewan
    Jul 22 '17 at 10:02
  • Ok. I buy you that :-). But how working with arrays solve the question around maintainability and scalability (OP's state that there're different messages so probably different "arrays").
    – Laiv
    Jul 22 '17 at 10:13
  • it doesn't. its "Just as a practical solution to thier unsolvable dilemma."
    – Ewan
    Jul 22 '17 at 10:53
  • Somehow your answer alongside with JacquesB comments made me realise that I stated both my question here and my answer (there) under wrong assumptions. Sadly I can't check all the answers despite all of them are right. Thank you for the insights.
    – Laiv
    Jul 23 '17 at 19:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.