- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
The frist thing I notice here is that the developer seems to fancy they know some "advanced" JavaScript like the "call" and "apply" methods and thinks they should use them everywhere even when completely unnecessary. (
[].push.call(y, z)
is identical toy.push(z)
when y is actually an array, which it is here. Although I guess it might not have been originally...)Admin
OK, they're actually using apply, that's needed if the second argument is an array of arguments. (Assuming this was written before the spread operator was introduced.) But still there is much of this code that makes me wince for being far more unreadable than it surely would need to be.
Admin
This looks like purposefully obfuscated to make it impossible to understand.
Gentle reminder to JavaScript programmers out there: please try to write code which resembles standard C-style language syntax. Please don't do JavaScript-only constructs when there are more universally understood constructs available. Please.
Admin
I think for many Javascript programmers JS is the first, and only, language they have got. It's one of those where googling for answers will land you on any number of "expert" forums where people are exchanging really terrible lumps of code.
I'm a bit confused why the article is fixating on the word "prune", alright this code is weird, poor and that would be the wrong name for the function. If it was really just doing some sort of trimming or extracting thing calling it prune wouldn't be terrible.
to prune - remove (superfluous or unwanted parts) from something.
Admin
From the subline to the ridiculous?
Admin
If your code consume prunes, the end result is crap.
Admin
That code should itself then be pruned.
Admin
That's actually a fundamental problem which explains a lot of WTFery. People should go through a few languages and some basic computer and network architecture courses before programming. And I'm not even sure many formal CompSci programs deliver that.
Admin
I suspect that most do, but I know from bitter experience it doesn't seem to actually stick in the heads of the students, even if they remember enough to bluff through an interview. I think part of the problem is this basic stuff is given in the first year by junior lecturers, some barely out of school themselves, and some of them from the group that seemed to manage to graduate without getting that basic competency sorted (no, I don't know how that can happen either). Because it's the beginner stuff it's not taken very seriously by student or the school, when I reckon it's probably more important than all the more "advanced" stuff.
Admin
At least at my former university when they switched system from Diplom(U) to Bachelor/Master (it's a European thing) the previous introductory program was simplified from previously Scheme in the first semester, SPARC-Assembler in the second and Java in third semester to all-Java. I think previous generations very much profited from getting very different points of view that the current generation has to somehow come by all by themselves.
Admin
I don't think that's the problem here. Whatever tools you use you should try to learn how they're meant to be used to accomplish certain tasks. Javascript is meant to be used in a functional style, which the author of this code gave lip service to before reverting to imperative techniques. I still see more junior engineers do this all the time.
For example embracing the functional style the "Get the sublines" code would have been implemented as a
map
then aflatten
. The "trim it down to just Tracking" section looks like what I would call atakeWhile
, though it's worth noting thattakeWhile
was only added in lodash v3, so it would have had to be afindIndex
and atake
orslice
. Interestingly it's ambiguous whatvalue.Tracking
is since[].concat('a', 'b')
and[].concat(['a'], ['b'])
produce identical results in javascript (['a', 'b']
). So essentially that bit is just anothermap
which may or may not also need to be flattened.Admin
I think it's because prune implies a sort of elegance and intent. When you prune a bush, you remove small, specific parts of it to improve how it grows or make it a certain shape.
You don't do... whatever this is.
Admin
Javascript shenanigans are not the main problem, but they do make it difficult to read. All the "apply" calls are unnecessary, the string type check is bizarre, I have no idea what _ is, why not use the perfectly acceptable array methods like filter, etc.
And I see even worse stuff used and even promoted elsewhere online, stuff that relies on Javascript's unique handling of boolean logic, word behavior of operators when mixed with type inference, etc. It's almost as if some in the Javascript community look at languages like Java and C# with their well defined and logical syntax, and challenge themselves to do the opposite of it. Why?...
Admin
"Something was always broken and the answer was always adding more and more code…"
There's your problem. Had one of those where I work back when I started. If a bit of logic failed, he'd try negating it. If that didn't solve the problem, he'd re-negate it. Over multiple tries, and after modifying other inputs, he'd come back and do it some more. That's how we got to:
"IF not not not not not not not not....."
Admin
JS isn't like other languages, because it must always retain backwards compatibility. We're still living with decisions made before the language had any real users. On one hand it's a pain. On the other hand we never had to break the internet and it's not that hard to save yourself from the trouble these days, all you need is a linter or maaaybe a type system. But back before those you just used something like lodash (
_
in the code) which promised to shield you from the weirdness of the browser compatibility landscape. If nothing you needed it for its implementation ofextend
, because for a language which was supposed to be based on prototypal inheritance there was no simple compatible way to extend prototypes.So what did JS give us that Java didn't? Simple. First class functions. Yes they are often "the opposite" of writing a program in an imperative style, but time has shown that bone-headed programmers aside, the patterns are solid. Even Java eventually saw the light and added lambdas, only 20 years behind Javascript.
Admin
I have no problem with functional programming whatsoever. And I'm fully aware of the browser compatibility and the 87 different frameworks aimed at working around the differences. And absolutely nobody is suggesting we should start removing features from JavaScript because they don't conform to modern language quality standards.
My point is, given the choice of doing something in a JavaScript-only style, such as Object.prototype.toString.call(x) == "[Object String]", or in a more universal (granted not exactly Java/C#) style, like typeof(x) == "string", why not use the latter? This has nothing to do with functional programming or lambdas; typeof worked since the beginning (or at least for many years). Also, are there really any browsers which don't support [].filter? Why not add Array.prototype.AddRange = function AddRange(array) { this.push.apply(this, array); } for readability similar to other languages? etc.
For prototype extension, what was the problem with good old: function Class() { this.field = "abc"; } Class.prototype.Foo = function Foo() { return this.field; } ?
Admin
Why not use the perfectly acceptable array methods like filter? Maybe because if this code targeted IE 8, filter didn't exist. Also, relying on javascript's unique handling of boolean logic and "weird behavior of operators" is the point: if the language provides it, why subvert it and code as if it didn't? Having '10' == 10 is a feature, very useful for example when reading from a number input element. JS is meant to look like JS, not C.
Admin
I'm not suggesting the
[Object string]
code is good. Goodness knows why they did that. It's really not smart to add arbitrary extensions to builtin because it's very hard to know if the implementation that was loaded is the one you expected, leading to weird bad stuff like bugs that show up only in prod...The problem with the prototype code you've written is that while you've created a prototype you haven't extended one. Can you make a
ChildClass
? Hint: now you can do it withObject.create
but that didn't exist back then.Admin
I'm not even sure that this phenomenon is restricted to CS courses.
Many years ago now (and in a programming environment), a colleague with a degree in Maths from a reputable UK university asked me:
"How do you invert a 2x2 matrix?"
Back in 1990, and even despite the fact that my degree is in Modern History, I suppose I was the equivalent of Google. I sort of got there in the end.
But in general, my theory is that all but the elite university courses let you get away with learning cook-book answers for three/four years. And after those three/four years, you lose the bookmarks in the cook-books. And you can't read through the grease. And so you just ask someone else. Who is, if you are lucky, an Oxford History graduate with about two weeks' worth of linear maths. Or if you are unlucky and it is no longer 1990 -- Google!
Admin
Fore reference, btw, google "convert cartesian plane to parametric." You will see some disgracefully stupid stuff out there, all dressed up in "mathematical" notation.
Admin
I have a physics PhD and I couldn't invert a 2x2 matrix by hand with just pen and paper reliably. I might be able to rederive the formula, but I'd probably just google it.
Memorizing stuff is not the point of a degree, and these days looking up the formulas is easy, if you vaguely remember keywords about it. Interviews, where having memorized trivial stuff is expected sound like a big red flag.
Addendum 2021-05-20 13:25: Once you actually NEED a specific detail frequently, it sticks quickly enough.
Now of course, if you never understood them in the first place, and seeing a problem can't jog your memory, ... That's a different problem.
Admin
At my university, the CS curriculum is all Java except for the occasional deviating course (e.g. using Octave in one). There was a course about low-level programming; People outright skipped the assembler part ("I don't need it to pass") and were heavily confused about pointers in the C part. Which begs the question just how they thought object references work in Java...
Admin
I assumed sublines was for assemblies of some sort. The line item is the Juggernaut 7000 but that is made up of One jEngine 7K-B, Four jWheelz 7K-W7, Flaming Red Paint (1 Can of 7K-PC) and so on.
Admin
IE is irrelevant. And no, just because "10"==10, doesn't mean you should do it. Your input element should have validation, either using type attribute set to "number", or custom Javascript, maybe parseInt, with a message saying please enter a number.
Admin
I know about the downside of extending on web pages with code from multiple sources, but that's a problem in itself: you shouldn't have pages with scripts from various sources you don't control. Security issues aside, what about reliability, loading times, etc. That's a bad practice with or without extensions.
Inheritance has worked forever: function SubClass() {} SubClass.prototype = new Class(); SubClass.prototype.constructor = SubClass;
Admin
True ... well, yes, you are on point there. It's just reading that article I don't think Remy or the OP know that definition, I think they were considering a small purple fruit that helps you poo better.
Admin
I just looked up matrix multiplication and inversion and I'd say if I had a math major, I would be expected to remember it. (I'm not and I don't know it, but I'm not a math major. ) I agree with you that your colleague, God bless him, probably doesn't deserve his degree.
Admin
It's a little more complicated than that, in the general case to which I was arguing.
It's not a matter of "deserving" a degree, whatever that means. It's a matter of "expectations." And, specifically, "management expectations."
You send a mark your resume. It includes details of your degree. You may or may not be asked simple questions such as "how do you invert a 4x4 matrix?" (An answer to which, incidentally, will demonstrate a far deeper knowledge of how matrix inversion works than a simple 2x2, because it involves a recurring pattern.)
You get the job. The mark assumes you are an expert. Nobody questions whatever idiot nonsense you come out with, because management (with some thankful exceptions) has no knowledge of, nor interest in, the subject matter you claim to understand. In fact, they will admire your ready recourse to either Google or a History Major. That's initiative, baby!
Of course, the customer knows even less about the internals than does management. So it's a win all round for incompetents.
Strangely, the inverse rarely applies. If I interview for a job, the first thing they notice is that I am a History major. The fact that I actually understand how linear algebra works (though not to a very deep degree) is actually, for some reason, a negative in job interviews, because they assume I just looked it up on Google the night before the interview.
Admin
When I wrote "deserve", I meant exactly what you demonstrated - "expectations". I was trying to say the same thing in fewer words. :)
Addendum 2021-05-20 15:27: Not demonstrated but described.
Admin
Deep philosophical thought: is this how nature works, where the balance between BS-talking incompetents and those who actually know stuff, is constantly maintained more or less at the same level? Just like the balance between our immune system and all the microbes constantly attacking it? Is there a more universal pattern to these phenomena?
Or I'm just inventing nonsense :)
Admin
Um, eek.
But to be fair, there is no earthly reason to learn Assember in a degree course these days. Nor C. Nor pointers. (You can always pick these things up later if you need to. I did.)
Using Java as a teaching language is, I would submit, around 20 years out of date. Python would make more sense. And god forbid that a University should sell its soul to either Microsoft or Xamarin.
But you do need to learn the abstractions. More than ever, a background in functional programming is an essential part of any useful academic course.
And your comments on pointers and Java references? These are now, officially, abstractions. (Unless you want to write your own JVM, Java Container Libraries, or Garbage Collector.)
To extemporise on John Keats ( "Beauty is truth, truth beauty,—that is all / Ye know on Earth, and all ye need to know"), the two following items summarise the lot:
That's basically it. But don't get me started on recursion.
I said, don't get me started on recursion.
I said ...
Admin
I believe it is a quantum relationship.
I cannot prove this, but my theory is that, eventually, the bullshit continuum will collapse into a point.
Admin
Mmmm, I'll respectfully disagree. People should learn pointers, and basic assembly, and basic C/C++, and basics of stack and memory allocation, and how it all came from CPU design (with the ESP register, etc.) Then, they'll understand what Java does, even if you're not writing your own JVM, they'll know what the existing one does behind the scenes. And please, no Python. That language should be killed and forgotten. (I saw benchmarks how it's 50 times slower than C#, and C# is only twice slower than C; so Python is about 100 times slower than it needs to be.)
And what's with MS hatred? C# is today many steps ahead of Java. Yes Java itself is "open source", whatever that means, but so is .NET, and both are owned by big corporations (if you are the big corporation hating type). If anything, Oracle is more evil than MS in many ways.
Admin
A while back there was an article that suggested to name your JavaScript functions as verbs. That way, you can do order.prune(). I think what this does is if you have two line items, it sums their quantity and makes it one line item. Better to add it to the database as is, and run an aggregate when viewing the cart. Use declarative state in your components, something like Relay, on the front end. Leave all this stuff until the very end. It may be helpful to know if the user clicked the add button twice, or typed in the number of items.
Admin
I'm pro-Microsoft. I'm pro-Xamarin. I'm pro-C#. I'm pro-Linq. Obviously the Sarcasm was Weak in that one,
Teaching languages do not need to be "efficient" in machine terms. They need to be "efficient" in pedagogical terms. And it helps if the language in question has a whole heap of libraries for disciplines other than straight CS (Numpy, etc.)
And it helps if they have a lovely, easy, mechanism for adding unit tests to things that can reasonably be described as "units." JUnit, NUnit, and god ferbid MSTest do not qualify here, on pedagogical (if not other) terms.)
So, what you said. But with fewer words. (Which will appeal to you.)
Admin
Also, there is absolutely no such thing as "basic" C++.
To avoid misinterpretation here, I am a big fan of C++ and have worked with it for twenty years. But in those twenty years, and right up until now, every time somebody describes their programming as "basic C++," all they mean is "totally botched C, hopefully C99, probably ANSI, at least K&R, maybe it sort of works in gcc" C++.
It's astonishing what these total incompetents get away with, as long as they can flourish a completely irrelevant degree.
Admin
I can see two purposes for sublines.
But if someone orders Widget A by itself, your pick list will be "Widget A", and your packing list will be "Widget A"
Admin
Grr. I meant "You may not stock Combo as a separate SKU". It's a convenience order item to get all three in your basket and any discounts that may apply to package deals.
Admin
I think something may have been lost in the anonymization, or in the keeping track of the code over the years. I think
match[re] = [];
will throw, because in that branchmatch
doesn't exist yet.Admin
I agree with there not being such thing as basic C++ professionally, I mean basic C++ for the purposes of explaining the bridge from C to managed frameworks like .NET. They can learn how "this" is basically the first hidden parameter; field offsets in memory from start of class instance; etc.
Man I need to establish my own programming school.
Admin
Regarding Python, I agree it's efficient to teach in it because it's easy. But it has 2 problems. 1, students aren't exposed to the reality of programming; they are shielded from understanding what's going on. 2, they then use that skill given the choice. Today, as a result of this, Python is gaining, while the much more superior .NET is waning. It's tragic if you ask me.
Admin
I'm probably going to catch some flak for saying this, but C# and Java are basically interchangeable. C#'s syntax is nicer in some ways and weirder in others.
async
/await
blowsCompletableFuture
s out of the water, but Java's collections do the same to C#'s, and it's really frustrating how C#'s standard library just doesn't bother implementingequals
. There are a lot of other differences, but I mostly can't bring myself to care about them. I do appreciate extension methods, but I'm not a fan of the C-style enums. It pretty much comes out in the wash.I could totally buy that I'm just used to my chosen language's quirks, but I really do find the standard library so much easier to work with that it makes up for the features Java doesn't have. Of course, I'm not nearly as experienced in C#, so there's some killer feature that I'm just not aware of. Please feel free to speak up if there is!
Admin
What is sublime written in?
Admin
Properties. The ability to create what to everyone on the outside looks like a field but internally has an optional getter and setter with variable access rights with the added bonus you don't have ugly getX and setX methods poluting your program is just invaluble. Once you get used to using them there is no going back. Also regions, although that's more of a Visual Studio thing. Also, LINQ is better than its Java alternative.
But yea, the two are basically variants on the same idea and thus 90% interchangable. I always like to call C# "Java, but done right".
Admin
I would regard the question as relevant IF it was in the context of as programming language that had features for transposing with some kind of mathematical functionality. Question be better as: what function do I use for transposing matrices
Admin
When you write "doesn't bother implementing equals", what do you mean?
I do agree that if I did Java the whole time, I'd probably be happy partially due to not being exposed to .NET but mostly because it does accomplish most things.
Admin
I'm not sure I've seen that before. It's not really correct, since you're invoking the Subclass constructor which may have code to set up instance data, except that now anything that was supposed to be on the instance is actually shadowing a copy of its default value that exists on the prototype chain. In most cases that won't matter, but that doesn't make it right. The workaround that you had to do (or had to have a library do) was to assign your
Class
prototype to an empty scratch function and then make a new instance of the scratch function, which you could then use as theSubclass
prototype.I am going to disregard the suggestion that modifying shared prototypes is fine because "all pages should have scripts from only one source". Even if the only source of scripts is you, remember that if you ever make any breaking change to a function you put on the prototype, you must modify all broken call sites of the function at the same time. In a real deploy structure that may not even be possible.
Admin
It's nice to see that people are creating weird code in JavaScript because they weren't otherwise programmers, similar to the days 20 years ago when people were creating weird code in Perl having come to Perl as their first programming language. Ahh, the memories...
Admin
Please see this fiddle: https://jsfiddle.net/xfnL5re1/ This worked for years across all browsers. It also has base ctor invocation, and you can use Object.defineProperty to make C#-style properties which have virtual getters and setters (I didn't write that part).
Regarding the changing a function breaking call sites, well that's a challenge with every language and framework in the world that has functions, which is 99.99% of software. However, I don't like redefining built-in "members", at least not without ensuring that existing set of arguments will produce the exact same outcome. This is mostly about adding new "methods" to existing classes, such as: Date.prototype.getCentury = function getCentury() { return Math.ceil(this.getFullYear() / 100); } (admittedly a pretty useless function, for demo purposes only).
Addendum 2021-05-21 12:16: https://jsfiddle.net/xfnL5re1/1/ - added calling base class function like base.Foo() in C#
Addendum 2021-05-21 12:18: Your scratch workaround idea would also work. In any case, my point stands: class inheritance is doable with vanilla JS.
Admin
In retrospect, "philosophically opposed to implementing
Equals
" would have been a better way to put it.I mean that the .NET standard libraries seem to use reference equality where the analogous Java library classes provide a specialized
equals
instead. I think the collections libraries are a great example. In Java,assert Set.of(1, 2, 3).equals(Set.of(1, 2, 3))
holds, but the equivalent with C#'sImmutableHashSet
wouldn't. (Set#of
returns an immutable set, so I think that's the best comparison.)Now, I know the .NET standard libraries also provide specialized comparisons, and that that particular example would work with
SetEquals
. That helps, but it's not always an adequate replacement. Exposing a bunch of internal members¹ just so some other class can do a value comparison seems wrong to me, and not everything can even be expressed that way - what would you expose to let someone decide if two instances of a strategy are equal? That aside, if an API doesn't accept anIComparer
(I believe that's the right name), there's not a whole lot you can do.It might seem like a little thing, but value equality is such a cornerstone of my coding style that working with a standard library that doesn't assume it has been really frustrating. I guess this turned into a rant, but I guess if I have a point here, it's that a lot of Java's "deficiencies" seem more like different preferences. And I'm sure the reverse holds, too - I might be frustrated by some of .NET's decisions, but I know there are many people who prefer them.
I have more to say on this, but just ran into the character limit.