Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #35750 > unrolled thread
| Started by | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| First post | 2016-10-12 09:39 -0400 |
| Last post | 2016-10-20 15:01 +0200 |
| Articles | 7 on this page of 47 — 6 participants |
Back to article view | Back to comp.lang.java.programmer
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: double == double Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-10-12 09:39 -0400
Re: double == double Michael Jung <miju@golem.phantasia.org> - 2016-10-13 21:10 +0200
Re: double == double Michael Jung <miju@golem.phantasia.org> - 2016-10-15 14:04 +0200
Re: double == double Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-10-15 09:13 -0400
Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-15 10:32 -0400
Re: double == double Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-10-15 10:46 -0400
Re: double == double Michael Jung <miju@golem.phantasia.org> - 2016-10-15 17:44 +0200
Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-15 17:36 +0100
Re: double == double Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-10-15 14:15 -0400
Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-15 19:41 +0100
Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-15 20:39 -0400
Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-15 10:41 -0400
Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-15 23:09 +0100
Re: double == double Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-10-15 18:28 -0400
Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-16 03:13 +0100
Re: double == double Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-10-16 08:37 -0400
Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-16 14:06 +0100
Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-15 20:30 -0400
Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-16 03:16 +0100
Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-16 03:18 +0100
Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-16 09:45 -0400
Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-16 14:51 +0100
Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-16 11:24 -0400
Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-16 16:43 +0100
Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-16 12:54 -0400
Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-16 18:37 +0100
Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-16 14:14 -0400
Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-16 22:19 +0100
Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-16 22:49 -0400
Re: double == double a.laforgia@gmail.com - 2016-10-17 01:53 -0700
Re: double == double Patrick Roemer <sangamon@netcologne.de> - 2016-10-17 19:04 +0200
Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-17 20:17 +0100
Re: double == double Patrick Roemer <sangamon@netcologne.de> - 2016-10-17 23:11 +0200
Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-17 22:46 +0100
Re: double == double Patrick Roemer <sangamon@netcologne.de> - 2016-10-18 18:55 +0200
Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-18 18:52 +0100
Re: double == double Patrick Roemer <sangamon@netcologne.de> - 2016-10-20 15:03 +0200
True O-O [Was: double == double] Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-10-17 18:06 -0400
Re: True O-O Patrick Roemer <sangamon@netcologne.de> - 2016-10-18 18:32 +0200
Re: True O-O [Was: double == double] Arne Vajhøj <arne@vajhoej.dk> - 2016-10-19 22:09 -0400
Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-19 21:58 -0400
Re: double == double Patrick Roemer <sangamon@netcologne.de> - 2016-10-17 18:58 +0200
Re: double == double 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> - 2016-10-17 20:32 +0100
Re: double == double Patrick Roemer <sangamon@netcologne.de> - 2016-10-17 23:21 +0200
Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-19 21:38 -0400
Re: double == double Arne Vajhøj <arne@vajhoej.dk> - 2016-10-19 21:47 -0400
Re: double == double Patrick Roemer <sangamon@netcologne.de> - 2016-10-20 15:01 +0200
Page 3 of 3 — ← Prev page 1 2 [3]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2016-10-19 21:58 -0400 |
| Message-ID | <nu98bs$gjs$1@gioia.aioe.org> |
| In reply to | #35796 |
On 10/17/2016 4:53 AM, a.laforgia@gmail.com wrote:
> On Monday, 17 October 2016 03:51:55 UTC+1, Arne Vajhøj wrote:
>
> [...]
>> Having data and methods operating on the data separate is
>> very non-OO'ish in my book.
>
> That's a kind of purist approach that I find very little
> pragmatic. Having methods that act on data is how OO is
> normally implemented.
Usually I am rather pragmatic.
But using a formatted string to as primary form for data
should bother more than purists.
> This:
>
> double d1 = 3.4;
> double d2 = 5.6;
> double dMax = Math.max(d1, d2);
>
> is certainly better than this:
>
> class PairOfDoubles {
> double d1;
> double d2;
>
> public PairOfDoubles(double d1, double d2) {
> this.d1 = d1;
> this.d2 = d2;
> }
>
> public double max() {
> return d1 >= d2 ? d1 : d2;
> }
> }
>
This example is not that close to the version number example.
The version number example has data with an internal structure
that the processing methods need to parse and format to work
with the data.
Consider a suggestion to instead of having a Circle and
Rectangle class then you used String's in formats:
"C(x,y,r)"
"R(x,y,w,h)"
Would anyone consider that good OOP? I doubt it!
Arne
[toc] | [prev] | [next] | [standalone]
| From | Patrick Roemer <sangamon@netcologne.de> |
|---|---|
| Date | 2016-10-17 18:58 +0200 |
| Message-ID | <nu2vv1$ikt$1@newsreader4.netcologne.de> |
| In reply to | #35792 |
Responding to Arne Vajhøj:
> On 10/16/2016 5:19 PM, 4ndre4 wrote:
>> On 16/10/2016 19:14, Arne Vajhøj wrote:
>>
>> [...]
>>> But that code is not using String as version
>>
>> Erm... how about this? :) I don't see how this is less OO-ish than the
>> previous one, but hey... okay!...:
>>
>> List<String> versions = new ArrayList<String>();
>>
>> versions.add("1.9.0-123");
>> versions.add("1.10.0-123");
>> versions.add("1.7.0-123");
>> versions.add("1.7.0-123");
>> versions.add("1.7.0-10");
>> versions.add("1.7.0-9");
>>
>> Collections.sort(versions, new VersionComparator());
>>
>> ...
>>
>> static class VersionComparator implements Comparator<String> {
>
>> public int compare(String version1, String version2) {
>> try {
>> ParsedVersion pv1 = parse(version1);
>> ParsedVersion pv2 = parse(version2);
>> if (pv1.equals(pv2)) return 0;
>> if (pv1.lessThan(pv2)) return -1;
>> return 1;
>> } catch (InvalidVersionException e) {
>> throw new IllegalArgumentException(e);
>> }
>> }
>
> Having data and methods operating on the data separate is
> very non-OO'ish in my book.
I don't think this describes the actual problem well. There may be
perfectly good, OO-compatible reasons to separate comparison logic from
the domain class - after all, that's why Comparator exists. For example,
there may be occasions when one wants to compare only based on the major
(major + minor,...) version parts.
But this code defies a more general programming principle: Describe your
concepts as dedicated types and define operations for those types.
Passing an opaque string around to be interpreted as a version only
"when needed" feels fishy to me in any paradigm.
With this approach, one has to rely on variable names and comments to
know what the string is supposed to represent. It is inefficient,
because one is bound to re-parse on every comparison. And there's no
easy way of knowing whether a given variable holds a valid version
number or whether one has to be prepared for an exception upon
comparison. With a dedicated Version type, you parse once at whatever
boundary the string enters the system, and from then on you have a
guaranteed valid version with a "speaking" type that can be compared
efficiently and that can easily be extended with other version-specific
functionality in future, erm, versions.
Best regards,
Patrick
[toc] | [prev] | [next] | [standalone]
| From | 4ndre4 <626401fd-4bc7-4f8f-b641-563ae0f72920@626401fd-4bc7-4f8f-b641-563ae0f72920.invalid> |
|---|---|
| Date | 2016-10-17 20:32 +0100 |
| Message-ID | <nu38vj$pf6$2@dont-email.me> |
| In reply to | #35801 |
On 17/10/2016 17:58, Patrick Roemer wrote: [...] > Passing an opaque string around to be interpreted as a version only > "when needed" feels fishy to me in any paradigm. I agree that having a 'Version' class (as shown in my first example) is generally better. However, I do not fully agree with not having opaque information, in general. I believe that there has to be a certain "axiomatic" level with any data structure. If you have the following: Double speed = 1.5; Double height = 1.5; Double size = 1.5; it is perfectly legit to have: String version = "10.10.10" String name = "John" String email = "john@somedomain.com" I might not always want to have a class for speed, a class for height, a class for size, etc.. each with its own validation rules. Schools of thought, maybe :) -- 4ndre4
[toc] | [prev] | [next] | [standalone]
| From | Patrick Roemer <sangamon@netcologne.de> |
|---|---|
| Date | 2016-10-17 23:21 +0200 |
| Message-ID | <nu3fc6$uig$1@newsreader4.netcologne.de> |
| In reply to | #35804 |
Responding to 4ndre4: > On 17/10/2016 17:58, Patrick Roemer wrote: > > [...] >> Passing an opaque string around to be interpreted as a version only >> "when needed" feels fishy to me in any paradigm. > > I agree that having a 'Version' class (as shown in my first example) is > generally better. However, I do not fully agree with not having opaque > information, in general. Fundamentalism is always bad. ;) > I believe that there has to be a certain "axiomatic" level with any data > structure. If you have the following: > > Double speed = 1.5; > Double height = 1.5; > Double size = 1.5; > > it is perfectly legit to have: > > String version = "10.10.10" > String name = "John" > String email = "john@somedomain.com" > > I might not always want to have a class for speed, a class for height, a > class for size, etc.. each with its own validation rules. Schools of > thought, maybe :) The limits of our language are the limits of our world. :) Most languages, including Java, simply don't allow the introduction of cheap, ad hoc derived data types. If there were a way to declare a Distance type derived from double that inherits the full double algebra and incurs no runtime (Un-)Boxing overhead and minimal coding overhead, there'd be every reason to do so. This is a limitation of our tools, not a conceptually unreasonable thing. Your argument holds as long as the overhead of a dedicated type outweighs its benefits. If you never take an email address apart and only use it as a string, by all means stick with String as the type. But in the Version case everything, even performance considerations (re-parsing!), seems to speak for the dedicated type. Best regards, Patrick
[toc] | [prev] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2016-10-19 21:38 -0400 |
| Message-ID | <nu9776$far$1@gioia.aioe.org> |
| In reply to | #35804 |
On 10/17/2016 3:32 PM, 4ndre4 wrote: > On 17/10/2016 17:58, Patrick Roemer wrote: > > [...] >> Passing an opaque string around to be interpreted as a version only >> "when needed" feels fishy to me in any paradigm. > > I agree that having a 'Version' class (as shown in my first example) is > generally better. However, I do not fully agree with not having opaque > information, in general. > > I believe that there has to be a certain "axiomatic" level with any data > structure. If you have the following: > > Double speed = 1.5; > Double height = 1.5; > Double size = 1.5; > > it is perfectly legit to have: > > String version = "10.10.10" > String name = "John" > String email = "john@somedomain.com" > > I might not always want to have a class for speed, a class for height, a > class for size, etc.. each with its own validation rules. Schools of > thought, maybe :) There is a big difference between the two examples. In the double example most of the required semantics exist in the Double type. In the version example significant logic about how to actually process the format has to be added elsewhere. Arne
[toc] | [prev] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2016-10-19 21:47 -0400 |
| Message-ID | <nu97n6$fs1$1@gioia.aioe.org> |
| In reply to | #35801 |
On 10/17/2016 12:58 PM, Patrick Roemer wrote:
> Responding to Arne Vajhøj:
>> On 10/16/2016 5:19 PM, 4ndre4 wrote:
>>> On 16/10/2016 19:14, Arne Vajhøj wrote:
>>>
>>> [...]
>>>> But that code is not using String as version
>>>
>>> Erm... how about this? :) I don't see how this is less OO-ish than the
>>> previous one, but hey... okay!...:
>>>
>>> List<String> versions = new ArrayList<String>();
>>>
>>> versions.add("1.9.0-123");
>>> versions.add("1.10.0-123");
>>> versions.add("1.7.0-123");
>>> versions.add("1.7.0-123");
>>> versions.add("1.7.0-10");
>>> versions.add("1.7.0-9");
>>>
>>> Collections.sort(versions, new VersionComparator());
>>>
>>> ...
>>>
>>> static class VersionComparator implements Comparator<String> {
>>
>>> public int compare(String version1, String version2) {
>>> try {
>>> ParsedVersion pv1 = parse(version1);
>>> ParsedVersion pv2 = parse(version2);
>>> if (pv1.equals(pv2)) return 0;
>>> if (pv1.lessThan(pv2)) return -1;
>>> return 1;
>>> } catch (InvalidVersionException e) {
>>> throw new IllegalArgumentException(e);
>>> }
>>> }
>>
>> Having data and methods operating on the data separate is
>> very non-OO'ish in my book.
>
> I don't think this describes the actual problem well. There may be
> perfectly good, OO-compatible reasons to separate comparison logic from
> the domain class - after all, that's why Comparator exists. For example,
> there may be occasions when one wants to compare only based on the major
> (major + minor,...) version parts.
The problem is not so much with the Comparator.
As you say then it is perfectly valid to have an external
Comparator that matches the logic in the code doing the sort
(or whatever).
The problem is with the parse code that is very much tied to the
internal structure of the String.
Having that parse code in many different places will be a
maintenance nightmare.
And if the ParsedVersion and the parse code is made public
and reused then we have the Version class back and there
is little reason to use the String format except for
input and output.
> But this code defies a more general programming principle: Describe your
> concepts as dedicated types and define operations for those types.
> Passing an opaque string around to be interpreted as a version only
> "when needed" feels fishy to me in any paradigm.
That is very aligned with OOP.
But yes - you could do something sort of similar procedural even
though it may start to be more like OOP in a non-OO language then.
Arne
[toc] | [prev] | [next] | [standalone]
| From | Patrick Roemer <sangamon@netcologne.de> |
|---|---|
| Date | 2016-10-20 15:01 +0200 |
| Message-ID | <nuaf6r$eop$1@newsreader4.netcologne.de> |
| In reply to | #35839 |
Responding to Arne Vajhøj:
> On 10/17/2016 12:58 PM, Patrick Roemer wrote:
>> Responding to Arne Vajhøj:
>>> On 10/16/2016 5:19 PM, 4ndre4 wrote:
>>>> On 16/10/2016 19:14, Arne Vajhøj wrote:
>>>>
>>>> [...]
>>>>> But that code is not using String as version
>>>>
>>>> Erm... how about this? :) I don't see how this is less OO-ish than the
>>>> previous one, but hey... okay!...:
>>>>
>>>> List<String> versions = new ArrayList<String>();
>>>>
>>>> versions.add("1.9.0-123");
>>>> versions.add("1.10.0-123");
>>>> versions.add("1.7.0-123");
>>>> versions.add("1.7.0-123");
>>>> versions.add("1.7.0-10");
>>>> versions.add("1.7.0-9");
>>>>
>>>> Collections.sort(versions, new VersionComparator());
>>>>
>>>> ...
>>>>
>>>> static class VersionComparator implements Comparator<String> {
>>>
>>>> public int compare(String version1, String version2) {
>>>> try {
>>>> ParsedVersion pv1 = parse(version1);
>>>> ParsedVersion pv2 = parse(version2);
>>>> if (pv1.equals(pv2)) return 0;
>>>> if (pv1.lessThan(pv2)) return -1;
>>>> return 1;
>>>> } catch (InvalidVersionException e) {
>>>> throw new IllegalArgumentException(e);
>>>> }
>>>> }
>>>
>>> Having data and methods operating on the data separate is
>>> very non-OO'ish in my book.
>>
>> I don't think this describes the actual problem well. There may be
>> perfectly good, OO-compatible reasons to separate comparison logic from
>> the domain class - after all, that's why Comparator exists. For example,
>> there may be occasions when one wants to compare only based on the major
>> (major + minor,...) version parts.
>
> The problem is not so much with the Comparator.
>
> As you say then it is perfectly valid to have an external
> Comparator that matches the logic in the code doing the sort
> (or whatever).
>
> The problem is with the parse code that is very much tied to the
> internal structure of the String.
>
> Having that parse code in many different places will be a
> maintenance nightmare.
>
> And if the ParsedVersion and the parse code is made public
> and reused then we have the Version class back and there
> is little reason to use the String format except for
> input and output.
Agreed. But I wouldn't necessarily want to have the parse code in the
Version class, either. There may be different string formats from
different sources ("1.2.3.4" vs "1.2.3-004"), or there may even be other
representations than strings I want to convert from. Having just a plain
Version(int, int, int, int) constructor and offloading parsing to
dedicated classes might be a reasonable choice, and it'd still be in
line with OO principles. The main problem with the given code isn't
having methods and data separate, it's not having a Version type, and
that's not an OO specific problem.
>> But this code defies a more general programming principle: Describe your
>> concepts as dedicated types and define operations for those types.
>> Passing an opaque string around to be interpreted as a version only
>> "when needed" feels fishy to me in any paradigm.
>
> That is very aligned with OOP.
>
> But yes - you could do something sort of similar procedural even
> though it may start to be more like OOP in a non-OO language then.
In proper procedural, you'd have a Version record type and procedures
acting upon it. In proper functional you'd have a Version data type and
functions acting upon it. That's an overarching principle, nothing
specific to OO.
Here's a functional semantic version library, for example:
https://hackage.haskell.org/package/semver-0.3.3.1/docs/Data-SemVer.html
Using a String as a version representation would be as silly there as
anywhere else. And if you suggested to the Haskell guys that they were
emulating OO, they'd laugh you out of the room.
Best regards,
Patrick
[toc] | [prev] | [standalone]
Page 3 of 3 — ← Prev page 1 2 [3]
Back to top | Article view | comp.lang.java.programmer
csiph-web