Dec 7, 2022 20:32
Also, I meant "parallel projection from the first angle" instead of "isometric."
Dec 7, 2022 20:00
I needed to see the edge.
Dec 7, 2022 19:40
So people are saying that Liskov is good design. Senseless subclassing is not. I think I can get behind that. Definitely drives another wedge between me and Java though. Thanks for sticking this out with me.
Dec 7, 2022 19:38
I think a key element to making Liskov work out is that the one who defines equality or ordering needs to know about all possible implementations. So Liskov can always work out for sealed classes. It can always be broken by ad hoc subclassing.
Dec 7, 2022 19:35
Huh. In Java, I always feel like I'm juggling chainsaws when I subclass something. Yet writing 2 Liskov substitutable interfaces with third-party comparators was relatively easy. I forget how evil .equals() and .compareTo() are because they are so commonplace in Java. Sorry, I'm totally distracted.
Dec 7, 2022 19:33
Yeah, this is why interface inheritance is better than class inheritance.
Dec 7, 2022 19:31
Let's try that again. Here are 2 point classes with 2 sort orders (compare() methods) which I believe do NOT violate Liskov Substitution: pastebin.com/HYwiVDRJ
Dec 7, 2022 19:21
Anyway, Comparator is defined separate from the class(es) it handles, which is not fundamentally broken. Maybe we could look at definitions of .compare(a, b) instead of .equals() and talk about a SortedSet (TreeSet) or similar collection?
Dec 7, 2022 19:20
Equality or sorting requires a context, as this simple example shows. Overriding Object.equals() as you do in Java assumes a single context. Even in most trivial examples involving inheritance, there is no obvious single context that makes sense. So really, you should be determining equality separate from your class the way Comparator works (NOT the way Comparable works). Ugh. People ask why learning Java is hard...
Dec 7, 2022 19:13
Ugh. Java's .equals() is such a mess anyway given that you can call a.equals(b) or b.equals(a) and in this case get different results.
Dec 7, 2022 19:06
Here, this is Kotlin that at least compiles so we know that we're both talking about the same thing: pastebin.com/fMutf8KL
Dec 7, 2022 18:51
Also, the trick of (this.class == that.class) only works for equals. Not compare().
Dec 7, 2022 18:50
Huh. No. Actually, in a hashmap/set, you just defined 3D points to not be equal to 2D points. So the collection will keep duplications, not throw them out.
Dec 7, 2022 18:48
I would think that depends on your context, or your projection. If an isomorphic projection with the observer on the Z axis, yes, they should be equal. For any other observation point, no. For a perspective projection, probably not (though for 2 points I think there exists one perspective where they line up with a third?)
Dec 7, 2022 14:49
@IMSoP your .equals() implementation prevents the parent and subtype from being used together in any hash-based structure (hashmap, etc.). You are preventing the subtype from being substituted for the parent type (and vice-versa), thus preventing Liskov Substitution in the context of any hash-based structure.
Dec 5, 2022 00:23
What I want to say here is, "Show me a meaningful subtype and I'll show you a broken equals method and a broken sort order." Pretty sure that's not always true, but also pretty sure it usually is.
Dec 5, 2022 00:22
Part of my problem might be the JVM curse/blessing of .equals() and .compareTo(). Most subclassing breaks these. Certainly adding any meaningful field does. point2D.equals(point3D) but !point3D.equals(point2D) is the classic example (point2D doesn't know about the z coordinate, but point3D requires it). .compareTo() is generally broken in the same circumstances. Another good one is that you'd expect SortedMap to care about sort order in its equals method, but in the Java standard library it doesn't (in order to be compatible with Map).
Dec 5, 2022 00:22
Oh, Meyer/Eiffel. Got it. Thanks!
Dec 5, 2022 00:22
"Inheritance is not just used to add behaviors, it is also used to add contracts." I've never heard that before. What is your source for this assertion? Or in what context (which languages), is this true?
 
May 27, 2016 21:52
@RobertHarvey I think you probably could have fooled the IDE by using string concatenation. Yes, I'm probably somewhat confused. But I still have a point. I was inspired by Joel on Software "Make Wrong Look Wrong" joelonsoftware.com/articles/Wrong.html and it did a really good job of that, even if the IDE and compiler could only detect some and not all of the errors. I'll update my question. Thanks for your feedback.
May 27, 2016 21:49
@RobertHarvey Two more points. 1. Lift Web: liftweb.net/index escapes all input from the user as HTML, which is problematic because sometimes it needs to be used in a URL for a forward, or written to a PDF file or something. Ideally, user supplied data should be stored Tainted in the database and escaped on Output not Input.
May 27, 2016 21:35
@RobertHarvey If you sanitized it, the HTML would become: "<input type="text&quot value=&quot" which is no longer a valid input tag. I mean, it would look to the end-user like the code for an input tag, but it wouldn't look like a text field.
May 27, 2016 21:30
@RobertHarvey You have to not sanitize this part o.p("<input type=\"text\" value=\")
May 27, 2016 21:29
@RobertHarvey oh, and pHtml escapes the Tainted to make it valid HTML.
May 27, 2016 21:28
@RobertHarvey Now I'm doubting myself and wondering if I'm just confused and it never actually worked.
May 27, 2016 21:27
@RobertHarvey pHtml() takes a Tainted, while p() takes a String.
May 27, 2016 21:26
@RobertHarvey I could swear this worked at one point, but by the time I developed it, we had a few hundred thousand lines of code at work and there was no way to convert that much code. It ends up looking like:
o.p("<input type=\"text\" value=\").pHtml(firstName).p("\" name=\"firstName\" >");
May 27, 2016 21:24
@RobertHarvey this is getting much more complicated that it should ever be. There was a time when all String concatenation in Java was a real performance problem. So we just didn't do it. IntelliJ IDEA would warn, "String concatenation" then later it would warn, "String concatenation in a loop" which it still does. I made an HtmlWriter class that had methods: .p(Integer i), .p(Boolean b) and .p(String s) which, if all your unsafe data were in Tainted wrappers, would not accept that data.
May 27, 2016 21:19
So you're saying the best you can do is:

String toString() { throw UnsupportedOperationException("Tried to write out Tainted data!"); }
May 27, 2016 21:18
@RobertHarvey and that's why 2 of the top 3 OWASP vulnerabilities are because of this.
May 27, 2016 21:16
@RobertHarvey bare strings aren't the problem because, as you say, the developer writes them as you say. However, if you have a User object and a User table in your database, you will ultimately let the user write in their name. When you get this off the Request object, you wrap it: Tainted(request.getParam("lastName")). You don't let it exist as an unguarded String object for longer than that.
May 27, 2016 21:12
@RobertHarvey Surely your C# IDE highlights errors as you type? I mean, if you try to divide two Strings instead of two Integers?
Nov 13, 2013 15:47
:)
Nov 13, 2013 15:47
@Ell - back to work now. Busy day. Good luck!
Nov 13, 2013 15:47
@Ell - that's a pretty big undertaking. Unless you only need to understand a tiny subset of SWF functionality, or it is your goal for the next 6 months to write an SWF reader I'd try hard to leverage existing tools before writing my own.
Nov 13, 2013 15:42
Wikipedia has a page of SWF Tools. You could use one, or look at the code for a similar one to get ideas: en.wikipedia.org/wiki/SWFTools
Nov 13, 2013 15:41
Maybe some sets of tags can share the same, or similar code.
Nov 13, 2013 15:40
Well, one way or another you are going to have to write code that processes each likely tag that you may encounter. It would be nice to pick a good technique for organizing those procedures from the outset.
Nov 13, 2013 15:38
Yeah, the Interpreter design pattern is a somewhat specific, somewhat outdated shell of a design for doing exactly what you are trying to accomplish. Maybe you won't use it exactly, but reading about it should give you some useful ideas.
Nov 13, 2013 15:37
My other thought was to use the tags as keys into a map or dictionary. Each Value in the map/dictionary is a function (pointer) that takes the tag as an argument and performs processing appropriate to that tag.
Nov 13, 2013 15:35
Did you look at the Interpreter design pattern?
Nov 13, 2013 15:34
Does C++ have a map or dictionary?
Nov 13, 2013 15:33
What programming language? Do you have function pointers?
Nov 13, 2013 15:32
What does a tag look like?
Nov 13, 2013 15:31
Compressed?
Nov 13, 2013 15:31
Flash?
Nov 13, 2013 15:31
@Ell what's your design dilemma?
Nov 13, 2013 15:29
I see my vote there as one of the people who reopened your question!
Nov 13, 2013 15:28
Is it re-openable now?
Nov 13, 2013 15:28
I should have said @bonomo instead of bonobo. Best wishes for a speedy recovery.