I do note that that is an atypical experience to extending programs in general, and I don't have the alternate, functional approach to compare it to (the emulator was written in a very old version of Java + Swing).
This case sounds simple, but I still expect the functional approach to save you from a lot of line noise coming from Java class bureaucracy. But in more complex cases, it may be a difference between a couple dozen lines and a couple dozen files.
Wrote something small like that for a random data generator for an in-house properties tester in Java a short while back. It makes it easier, in my opinion, when you have all the code available in a single screen than if it’s spread out.
(although it might sometimes serve well as a configuration language alongside high-performance C++ code like in gamedev...)
The C++/gamedev "data-oriented programming" is about structuring your in a way that's friendly to CPU cache. It turns the programmer-friendly abstractions inside-out in order to make execution as efficient as possible.
The Clojure/Lisp/functional "data-oriented programming" is about building your (programmer-level) abstractions around basic data structures like lists and maps. It's meant to simplify your code and make it more robust.
The two "data-oriented programming" paradigms are pretty much opposites in every way except the name. They both focus on data, but the resulting data structures are vastly different.
On a related note, this is also why I don't like at all the current C#/Java "modern" style of dozens of files with perhaps one or two actual useful lines of code (the bulk of those files being boilerplate fluff and stupid comments like "// @return the return value".) Debugging is especially irritating since stepping through the code becomes substantially nonlinear with deep call stacks.
There are conversational styles you can apply to code that make it simple to test (or in his case, make coherent assertions about) that still keep the methods small but cleave it in a way that you can still track in your working memory.
It’s a style I aspire to, and put a great deal of time and energy into. But reading my old code I can say it’s harder than it sounds and it doesn't sound that easy to begin with.
(A CPU must almost by definition must be simple to implement.)
O(n) is short hand for here is "what happens when n gets large, but it I'm telling you nothing about when n is small". For example some sorts are O(n log(n)) and some are O(n^2). Naturally for big sorts O(n log(n)) is preferable - but when n is 5 say the O(n^2) will often be faster. People use O(n) precisely because it carries all this unsaid nuance.
In your example you probably have upwards of 30 instructions but possibly hundreds, which sits comfortably in the big side of things. If there was a way to reduce that to an O(1) solution (which implies that if you can add many new instructions without adding lines of code) then you've coded it badly - but we all know that's not possible for a micro controller emulator.
In his example he used O(n), but implied a O(1) solution is possible. The same logic applies. His use of Big-O means for large n, it's possible to add many new cases without adding code. If that is true, his solution is far better than the one wanted by the interviewer. However, it's likely n was small because this code had to be written for a job interview. It's entirely possible he managed to find a enough commonality in those small number of cases to reduce it to being 6 lines, while in the real world problem is indeed O(n). In that case the correct solution depends on the instructions he was given - whether he was asked to solve this particular problem in an optimal fashion, or demonstrate how he would solve the problem in general using those n cases as an illustration.
He doesn't say, so we don't know. His use of O(n) does hint - but the grey beards among us would like to see proof the problem really can be solved with O(1) and the interviewer was demanding an O(n) solution despite that. It does seem like a really weird thing to demand.
If someone has invested a lot of time trying to understand OO and design patterns like this, and had the feeling of accomplishment when it all comes together, then the are going to want to apply them where they can.
I think all that stuff is invaluable knowledge but people shouldn’t fall into the trap of doing something one way just because they have invested the most time in learning how to do it that way.
Also, many software professionals probably find simplicity boring. Simplicity should be taken more seriously as a goal in software development. Sigh.
Analogously, code is cost, infra is cost, only our sold product is revenue.
A thing I did not understand for a long time is the effect this has on value. Something that produces a low value over a long time may well have been value-negative over the period because of the hidden carrying cost.
Also there may be a balance between "some hierarchy in the code so it can evolve" and adhoc code that just works for the current problem. Only having to write a new class for a new feature because everything else is handed smoothly is a bliss.
There are some other aspects to this idea of code economy: correctness and reusability. This definitely depends on the programming language.
In Java(or oop for that matter) you can get correctness but to get reusability you need a whole hierarchy of classes, lots of added code/cost.
In Python you get more reusability out of the box but to get correctness you need to add swaths of unit tests, lots of cost.
In contrast with a functional language such as Haskell you get both with less effort, fp plus a rich type system reduce code enourmosly.
I wish Rust would have gone with an ML syntax though, in particular the Hindley-Milner type signatures allow me to reason better about code reusability, the "fn" and braces just adds noise to me, too much Haskell I guess.
For example I could write a massive list comprehension in Python in one line that could solve my problem, but it would be much more difficult to read and would be a pain to modify. I'd much rather work with the 10 lines of code it would take to actually spell it out.
Complexity creates opportunities for fiefs, little areas only one person understands.
I think we don't recognize what drives a good portion of people, in the tech industry. People pretend to, and are often expected to understand more than they do. Complexity helps us when reporting or manage (up and down). It's harder to grill you, challenge you or commit you to things when everything is complex. Complex requires more people, which is the main scorecard for corporate success.
It's also just unintuitive that simple is harder and better than complicated. Even if you get it, someone else won't.
I've come to the same one. I think it explains a great deal of what we see. Even in the hiring process and such. It's actually very primitive at its core. Who's part of who's tribe and who is jockeying for status in that tribe.
It wasn't clear if that was a shift in thinking or just improving ones skills at a particular way of thinking. In other words, no evidence of any loss just a shift in score on a right/left test. The other notable thing he said is that the right brained people who complete an engineering degree were rather likely to spend some time working in the field and then just change to something completely different.
I remember this well because I tested as a dominant right-brain thinker and have always had this odd feeling that I might want to just stop and do something completely different. Fortunately I've been able to find ways to use creativity in engineering :-)
The logical/creative dichotomy is bullshit based on fake science.
In reality the left brain (dominant for most people) prefers sequential, step-by-step thinking, while the right brain prefers simultaneous and spatial thinking.
Math professionals are actually biased towards right brain people. (It's hard to get anywhere in real math using step-by-step algorithms.)
>> In reality the left brain (dominant for most people) prefers sequential, step-by-step thinking, while the right brain prefers simultaneous and spatial thinking.
I've never seen anyone make such a direct contradiction so clearly ;-) You define left-brain thinking the same way the "bullshit" does, and then you define the right brain in a way that reflects creativity - at least to me.
But can it really be simultaneous (at the same time)? I mean there's still a "micro sequence" involved. it seems that the real skill here is context switching, pattern recognition and applying patterns to different contexts.
When I have to think about something hard I try to do it without words in my mind. I believe this makes it easier for the brain to subconsciously work on those, without having to "translate" it first.
However I still use "pictures" in my mind. I wonder if it's possible to actively think about something without using things linked to our physical senses (hearing, seeing, touch,..).
Sounds like intuition based on experience, where a new situation is compared against your experience, with the brain filling in the gaps.
>When I have to think about something hard I try to do it without words in my mind.
Hard in the sense of difficult to solve and unfamiliar, or in the sense of the level of focus or concentration?
For example, I know a heavily right-brained person, and when he reads a book, instead of the intuitive sequential pattern (even page-odd page-even-odd-even-odd) he may read it in a zig-zag (even-even-odd-odd-even-even).
The analogy is synchronous processing (left brain) vs multithreaded (right brain).
On the other hand, right-brained people seem to have problems doing 'obvious' things like finishing chores in order, telling left from right or positioning something on a blank page.
1: https://www.health.harvard.edu/blog/right-brainleft-brain-ri...
Yes, there really is, but the way it's described in American media is a load of crap. I don't think anybody published actual real science about this in English.
Coming in, I was told that the specs were difficult, the tech had to be nailed, and they had already tried and failed.
I took a week getting used to the customer, stack, and team. Digging through what they had? They needed two lines of code. It was the same exact situation.
That was one of the more difficult consulting assignments I had. It took me quite a while to gently get the lead architect on-board. I had to position it so it looked like his idea. If I would have pushed hard, he would have pushed back...perhaps getting rid of me and hiring more of a team player.
I've seen this a lot, in a lot of teams, and I think it has its roots in OO/Platonism, although it happens all over. I think the key things most of these teams are missing is that all structure is derivative. That is, there's not a line of code that's in your app that isn't in there for a reason. You're either really careful about that reason....or you add stuff because it looks good or you might need it someday, you can "imagine" how it might be helpful, the guy sitting next to you said you had to have it, and so on.
If you do it differently or with a different language, there must be some negativity to latch onto in order to justify the way they did it. The simple ability to say "Oh...cool! Hey Bob, come look at what Jim figured out!" is a rare find.
And very likely that's what really happened. I have been in such interviews and it is sometimes hard to guess whether the interviewer wants the practical answer (calling a library function) from engineering standpoint or the conceptual answer (demonstrating that I can implement the inner workings of the function) from CS standpoint. Often I would just ask a follow up question to clarify exactly at which level of abstraction does the interviewer want my solution to be in?
In situations where I offer a solution that does not match the interviewer's expectation, they clarify the expectations.
Sure I can teach constant vs. linear time. But what incentive or reason do I have to spend time teaching these fundamental concepts when I can just hire an engineer who demonstrates the understanding of basic CS at the interview time itself?
Given two candidates with all things equal except that one demonstrates the understanding of CS fundamentals and other does not, why would I want to hire the second person and spend our time teaching him those concepts?
Someone commented on here recently that they would take motivated candidates over knowledgeable candidates. That's one reason. I can easily think of at least two others.
There are balance points here that vary according to all sorts of things.
I mean if there are two candidates who are equally motivated and are more or less equal in all things except that one is strong at CS fundamentals and another isn't, is there a good reason to reject the candidate who is good at CS fundamentals.
In many hiring decisions, I am faced with a similar choice, and I go for the person who is good at CS fundamentals. If two candidates are good in all other ways, then the understanding of CS fundamentals becomes a tie breaker. I see no rationale for selecting the guy who does not demonstrate his strength in CS fundamentals.
A real life task might be implementing a much more complex library over several days or weeks. Asking the person to implement a simple function like shuffle is the closest you can get in the span of an hour.
She thought of a different method and wrote it out, and they dismissed it again. After that, she said that she didn't know what they wanted, and they condescendingly told her that she should just use the equivalent of a string.reverse() function (I don't remember which language it was).
And on the other side, if the interviewers are looking to identify whether a candidate knows about String.reverse() and the candidate starts writing out some 20 line algorithm on the whiteboard, why would you just sit there and watch instead of being like "actually, we're looking for something else, let me ask it a different way; do you know how to reverse a list using the standard library? We're looking for a one-liner here, not an full algorithm implemented on the board."
If your story is true, then apparently there are at least some interviewers willing to just sit there while a candidate writes out 2 completely different algorithms on a whiteboard without interrupting and communicating what they actually want. Such an interviewer is either socially incompetent or trying to make a fool out of the candidate. Either way it doesn't reflect well on the company.
I think CS interview questions can be hard because sometimes you don't know what sort of "model of computation" are you operating on. Am I on a totally abstract setting where all I have is an abstract machine. Or do I literally have an Intel CPU running Linux? Or am I even higher level than that and can think in terms of the abstraction of python. I think sometimes this is not clarified.
One other time in a different interview, I was asked "how does OS free memory in constant time". Having implemented malloc etc a few times I thought this was a stupid question because it depends on the C library implementation of malloc/free as one could also implement free in O(logn) using tree-like structures. Anyway, said something like "it just clears the pointer in the linked list in sbrk()'d space so that node is inaccessible" which apparently was the "correct" answer.
Which may be the point, they want you to ask "what am I optimising for", to be aware that there's no simple best answer without needing prompting. Also that the optimisation might be at the business level, like time critical implementation, or use of excess resources gleaned from some other part of the corporation.
So instead of telling you they want a one-liner, you saying "what are our constraints; how long have I got to implement it, ...".
It's always better to demonstrate in an interview that you have a lot of knowledge about whatever that is being asked. It's not just being able to code, but also the ability to explain why and how it works.
It all comes down to the question asked, if they were literally asked to randomize a list then OP gave the correct answer, if they were asked to implement a list randomizer they were wrong. If the interviewee didn't make this explicit they were wrong.
Granted, there should be 1-3 people around who can be tapped for algo knowledge when bottlenecks need to be addressed. However the rest of the dev team just needs to worry about productionizeable code...
That's just proving the point of the person that you replied to, though. If you could give a crap then you obviously care about it.
Of course, the follow-up question is going to be: Randomize a list that doesn't fit into memory.
I don't get the fuss about interviews. They seem to largely consist of basic programming exercises.
You don't need to know the solution before hand and it is easily intuited on-the-fly. I would never hold it against someone to miss some corner-cases or maybe go for a naive implementation first.
I remember a few years ago, someone was complaining that they had been rejected for not being able to reverse a binary tree even though they had a copious amount of OSS.
The thought process is simple and it's an exercise that students do within the first few weeks of their freshman year.
(struct node (value left right))
(define (reverse-tree root)
(cond
[(equal? root 'EMPTY) root]
[else
(node (node-value root)
(reverse-tree (node-right root))
(reverse-tree (node-left root)))]))
A tree is intuitively defined as a recursive data-structure.There is one base case: when we reach a leaf.
We want to reverse the left and right subtree at every stage of recursion.
Combine all of this and it's done. I would even be content with a pseudo-code implementation.
I've asked similar questions and if I forget all the constraints just a simple, hah that's clever + reframe the problem is a reasonable approach and doesn't come off as being a jerk(keep in mind the candidate is interviewing you/company as well).
I would want the candidate to ask me whether they can use their language's standard library. I would say no/yes depending on how the question is framed.
The absolute worst is when question is framed like 1) - the candidate just makes an unwanted assumption, and then acts outraged or smug when I tell them I expect them to demonstrate that they aren't oblivious to the underlying implementation.
Then we venture off whether they can make improvements/trade-offs if the list becomes 10K, 1MM, 1B, etc. records of N bytes etc.
Then I come across candidate B who shosw up on time, with a good attitude, takes heat and shares credit, builds people up, isn't afraid to speak their mind and offers a genuine and insightful answer to a problem designed to evaluate whether the candidate understands the underlying concepts.
I am definitely going to hire candidate B.
The point of a library function is that I don't have to worry about how it works, so I can focus on writing things that are not already in libraries!
The point of a library function is so it doesn't have to be re-implemented everywhere, not so you can be oblivious to how it works. If your oblivious to what is going on behind every function call you will write terrible code.
99% of developers at Google are doing commodity work. It is are practically IBM or HP now.
It's obvious that you should use a library function if there is a library function.
I don't see why. For example, imagine a graphical editor. GUI events will trigger some actions and those actions will trigger some commands being execute (and placed in an undo buffer etc.). I don't see where that central place should be and why you would need it at all.
And now imagine a large project with different ways to execute commands ("execute", "executeWithUndo", "executeInTransaction",...), people composing new commands from existing ones, etc. Soon grep becomes your best friend. Or just press Ctrl-H or whatever in your favorite Java IDE to see the class hierarchy.
Because in the functional model, you're not abusing the filesystem or inheritance hierarchy to do your bookkeeping.
Also, I said functions, not necessarily anonymous ones. There are ways to solve this use case. You can stash your actions as named public static functions in a "Commands" class. Or you can create one dummy class with @Functional on its only method, that essentially forwards the call. So in your UI handlers, you do button.setOnAction(new Command(someFunctionSomewhere));, instead of having a separate class for every possible action. You can now find all actions by looking up calls to Command c-tor(s), and you can build subtypes of Command as you need some special functionality. Note that this way, you don't commit yourself early to a huge type hierarchy.
In my experience, even in large projects, Command objects tend to sit in the filesystem, wasting space and people's time. But if you're absolutely sure you'll need this pattern, then go ahead and use it. It just shouldn't be the default, go-to way of solving this problem.
I've noticed in myself a tendency towards programming "aesthetics" that just "feel" right. Sometimes that intuition seems to overlap with faculties that help avoid complexity and find elegant solutions... but there's also plenty of times when it's either habit based in a collection of odd assumptions or even apparently arbitrary, and so it's something I've been working to interrogate.
OO approaches specifically have something like three decades of pop-tech discussion as being professional and sophisticated. That's a kind of conditioning that's hard to overcome.
The right hemisphere is visuospatial. Also, the right hemisphere 'sees' time/process.
The left hemisphere puts together contextless symbolic model. So I see where your question comes from: the left hemisphere can do the contextless proofs. In this case (and in many cases) the more complex solution "works" and the left brain can "prove" it works.
But a 'simplicity' proof seems better suited to the right hemisphere (I am no expert here, mind you) .... So in my anecdote the "simpler" solution is the one that I would guess the right brain "sees" as simpler: i.e., it is visually much smaller, also much easier to manipulate (over time), etc.
The book is "The Master and His Emissary".
It's quite possible he was trying to test something else and the answer you gave didn't give him a meaningful answer to that question.
So while your solution may have been fine, it's not something you're going to run into in production code. But that hierarchy+command pattern is probably used in a more appropriate situation. And he wanted to see if you could deal with the pattern itself.
Of course, I could be wrong. He could just be enamored with the overly complex solution because it's more "clever".
Interviews are weird.
The point of a 'command pattern' is in effect it's generality, i.e. it implies less coupling in the scenario. The most classic example would be the 'action' that might be passed to a UI button when it's clicked.
So, if the situation calls for command pattern, use it, if not, don't. It's not a matter of 'in your face complexity'.
The notion of doing '3 things with 3 functions' is pedantic: it's obvious. It wouldn't make the basis of a 'question' so it'd be rather pointless to do it.
Maybe there was some confusion as to the point of the question ...
You don't need that at all.
Here is a "proof" of sorts: http://mishadoff.com/blog/clojure-design-patterns/#episode-1...
But either it makes sense to use Command Pattern or not in any given situation and it has nothing to do with complexity really.
I don't see how someone could possibly use a command pattern when simple function would do - that would be beyond pointless. Which makes me believe that there must have been something to the nature of the problem question ...
(Though Lambda's wipe out so many of the simpler use cases of command pattern ...)
First to go was the distinction between accessible and non-accessible seating, partially obscured views, basically any extra info about seats except their identity. Okay, great, that simplifies things.
Likewise any idea of redundancy or failover. "Just let the process restart. You should be able to ensure no failures anyway." Okay, that's kind of opposite to how I've thought in the past, but I'll keep my mouth shut and roll with it.
Just to check, I asked if I should support a concept of buying tickets for assigned seats. Nope, no assigned seating. Okay... so are there different price classes for each event? "No, the tickets are all the same!" Okay. Each event has a single price and a single pool of tickets.
But to sell the ticket the user has to be able to buy it, right? Nope. No payment process. Great! I said. So there's no need to put a hold on a ticket while the user has it in his cart. The interviewer looked like he was going to burst a blood vessel.
Then I said, okay, at minimum I think we need to record who we've sold tickets to so we can send them tickets or in some way ensure that the right people can be let into the concert and people who haven't bought tickets can be turned away. Um... right? "No, don't bother. If they say they bought a ticket, they did." Okay. Moving on.
You wouldn't think the requirements could get much simpler than that, but you would be wrong. It turns out that the system didn't need to know when a concert was happening so it could stop selling tickets at some point. Ticket sales for a concert would go on forever. What should I do if the concert sells out? "Don't worry about that. It won't happen." At this point, I wanted to scream, "Your honor, permission to treat the witness as hostile!"
It also turned out there was no need to track different events or venues. There's only one concert, it has an unlimited capacity, and it never happens.
In the end it emerged that he just wanted a simple TCP service that listened on a port and served a random long integer (a "ticket") to anyone who connected without repeating the same value, unless it got rebooted, in which case it was okay to potentially serve some of the same numbers that it served during its last lifetime, as long as it didn't exhibit any patterns that might enable an attacker to predict upcoming values.
What #%$%ing similarity does that have to selling concert tickets? I mean, in the phrase "sell" "concert" "tickets" "online" three out of the four words were completely irrelevant and misleading. I'm guessing it was just what he was working on that week, and in his system the values were called "tickets" so he threw out "let's sell concert tickets" in an interview hoping I would solve his problem for him. We were out of time, so we didn't have time to discuss it. I didn't get an offer and wouldn't have accepted one.
okay, so what do I do when I need to dynamically load an additional command by name from an external .jar ? that's like, the most basic thing Java was meant for.
Asking first to understand the needs and intention of the application should be a first step anyhow. Diving into the deep-end face first and coding is rarely the correct approach (except maybe a startup racing for market-share).
Reminds me of a blog post I read,
https://www.sebastiansylvan.com/post/the-perils-of-future-co...
At what point does it become over-engineering?
I can't remember a situation where undergeneralized code came back to bite me. I have however seen (and admittedly written some) prematurely generalized code that became messy legacy code.
Also, the answer should not be "large dependency injection framework".
Yes you can load Java classes into the JVM. But why not have a serialization format that is independent of the vagaries and specifities of the JVM?
Still, even if you lean on the JVM, that changes nothing about this particular problem. You don't need command pattern. You don't need a type hierarchy.
He told me he took a ukulele to the interview. Each time when interviewer asked him a question, he would play ukulele untill he found the answer.
He got the job even when his interviews went wrong.
His job offer arrived months after an interview because he was the only guy who the interviewer could remember.
Often you hire for a spot in a company, after sometime that person leaves and management asks you to name any other person and when you try to recall last interviewee batch, the ukulele guy is only one the interviewer is able to remember.
I didn't have enough money to buy new clothes at the time, so instead I've picked the shoes with the largest amount of holes and would never do any grooming before hands. I would come stoned to the interview. So the gist: instead of trying to appear on the lower mid end, I went all the way through to the lowest low end.
Thinking retrospectively I think that's pretty much the reason why I barely received any negative responses unless I had miserably failed at the technical side of things (e.g. I didn't know how to use generators in Python at the time and the whole list of questions would be about them and their syntax).
I have to admit that in this scenario I was quite good at the technical side of things. But the general philosophy was that if I don't try to appear too good - people will assume that I was better. Put humility and definite sprinkle of character on top of that.
Speaking of complexity worship...
Big O notation seems totally irrelevant here, unless the question involved scaling to arbitrary number of types of operations. Why not just say "we ended up with a class for every operation?"
A system that has O(n) code artifacts for n "business requirements" (e.g.) is far more costly than one that has O(1), say.
I understand what you are saying, I'm just objecting to how you are saying it. Unless you are interested in the limiting behavior as the number of "business requirements" goes to infinity, big O is the wrong tool. An O(1) approach that requires a foundation of 1M LOC is probably worse than an O(n) approach that requires 100 LOC per business requirement.
Sorry to obsess over the details here - I just think big O is overused in general and saw an opportunity to make a bad pun on complexity worship.
I.e. it's coder slang now.
> Never use a foreign phrase, a scientific word, or a jargon word if you can think of an everyday English equivalent. - orwell
RE that Orwell quote, I have mixed feelings. I agree with it in so far as it means "pick easiest words for your audience at the precision level you need". But in general, words are not equivalents, even if they're listed as synonyms - each word has its own specific connotation. Say, "car" and "automobile". Technically, they refer to the same thing, but they feel different. That subtle emotional difference may not be important in formal setting, but it's an extra dimension of communication in informal cases (like e.g. this comment thread).
Like the word "orthogonal" - always know I'm talking to a techie when that one rears its head.
I guess there just comes a point where you've solved so many optimization problems that it's hard to not think of a bunch of solutions with different attributes as being embedded in an N-dimensional space?
Versus
That is an entirely different concern.
The second is more approachable but requires an adverb to have the same meaning, and adverbs are also discouraged. I think orthogonal is fine.
So I guess we could nitpick over "entirely" and "basically" just as easily. Maybe he should have just singled out the engineers and other pedants.
I tend to use "mutually independent" instead of "orthogonal" when talking with non-tech people.
It feels analogous to the widespread use of "exponentially" to mean "a lot" or "quickly" which is a really bad, silly thing. The difference is that few physicists and mathematicians misuse "exponentially" in casual conversation, whereas you are claiming that software people deliberately misuse "Big O". I'm not sure I believe you but either way this seems regrettable.
Take the context of a high-profile art magazine, Frieze. (I googled "frieze increased exponentially"). This is shooting fish in a barrel—but the most egregious example in the first page of hits is this one:
"Seppie in nero’ – squid in its own ink – is my favourite Venetian delicacy. Although customarily served with polenta, I prefer it on thick spaghetti since pasta exponentially increases the naturally squirmy quality of the creatures’ tentacles, creating a Medusa-like mound of inchoate, salty matter."
So you've got an art critic writing slightly pretentiously about food, and he throws in an "exponentially" which has nothing to do with a rate.
This and similar usages of "exponentially" are extremely widespread now. People talk about exponential increases without any mental model of the rate of growth as a function of time at all—just the woolly idea that something is growing fast.
"The term "exponentially" is often used to convey that a value has taken a big jump in short period of time, but to say that a value has changed exponentially does not necessarily mean that it has grown very much in that particular moment, but rather that the rate at which it grows is described by an exponential function."
https://books.google.ie/books?id=aVovDwAAQBAJ&pg=PA36&lpg=PA...
The battle is lost on this word, as it is with "literally". To the man on the street "exponentially" really just means "a huge amount" now.
The Orwell quote is valid at the heuristic level, but when
a) there's an installed base of people who know the jargon, and
b) the everyday English equivalent takes a lot more words to say the same thing, and
c) something coherent is meant by the jargon that could be so translated if necessary,
then that's exactly when you should use the jargon.
Give me "a^2 + b^2 = c^2" over "the sum of the squares of the lengths of a and b is equal to the square of the length of c".
And in fact approaches to system design that try to make the code size independent of number of bussiness requirements and their possible changes in future lead to exactly the kind of "complexity worship" discussed in TFA (various ad-hoc turing complete VMs that interpret code represented as rows in bunch of relational tables and what not).
FWIW, Big-O itself, even in technical contexts, gets imprecise with e.g. calling hashtables O(1), which is not possible, even under the idealized computer model (instant memory access, etc).
Is there a shorter way of saying "scales proportionally with n" that you would suggest the tech community prefer because of its greater precision?
> What we ended up with was O(n) _classes_ (where n = the number of computation operations).
vs.
> what we ended up with was several classes for each operation.
The second is shorter, and says no more than what is relevant.
It would be wrong in both cases because the context can make clear what a variable or pronoun refers to. If the problem context makes clear what the binding constraint is and you just need to talk about scaling behavior, then it is indeed shorter to say "O(1) rather than O(n)" vs "doesn't depend on the operations rather than being directly proportional".
>>what we ended up with was several classes for each operation.
>The second is shorter, and says no more than what is relevant.
It says less: the O notation is used to indicate that as you add more operations, you will need to add more classes, rather than only needing to add classes when there is logic the operations don't yet implement.
Speaking of brain hemispheres, the left hemisphere doesn't get jokes like the one you made. The right hemisphere handles jokes, metaphors, etc.
Looks like I'm a left-hemisphere-dominant pot calling the kettle black...
My view is that, even in algorithm analysis, Big-O has been overused. Too many people will point out crap like "That is 4 items per entity!" When I point out we only have 50 entities and that 200 is an easily handled number, I just get evil glares.
Wikipedia describes why people use the Strassen algorithm in real-world implementations, despite its inferior asymptotic time complexity [0] :
> unlike the Strassen algorithm, it is not used in practice because it only provides an advantage for matrices so large that they cannot be processed by modern hardware.
[0] https://en.wikipedia.org/wiki/Coppersmith%E2%80%93Winograd_a...
Basically, I was hoping some of the optimized methods were competitive nowdays. Spoiler, still not practical. :(
(It's also faster to write, or even say out loud, "O(n)", than it is to write/say "proportional to number of").
Or, to put that another way: there is a constant cost in human parsing complexity when writing "O(n)", but the number of parse-nodes in the text when using "O(n)" only increases as O(n), whereas without "O(n)", it increases with O(n^1.3). ;)
I have two monitors on my desk. If I am stuck on anything I drag my emacs from one side to the other and look at the same code there. It works pretty well!
What happened was that you showed off how you're better than him at finding a better solution. He's probably a top dog looking for underlings. That's the reality of this world.
It's like they are trying to prove that they are really, really smart without anyone asking them to prove it. But here is my challenge: anyone can overcomplicate anything, but if one is really smart, make a complex thing simple.
What we ended up with was O(n) _classes_ (where n = the number of computation operations).
I remained in Java, but took a functional and dynamic approach yielding a three-line implementation of the engine where each command was simply a function. All the tests passed.
I was kind of holding my breath at this point. What will he say? We just went from this huge implementation to three lines. I thought he was going to love it. The crazy simplicity of it all.
But to my draw-dropping surprise he muttered something about adding new types and how he liked that the commands were coupled to the engine.
Is this complexity worship? Or what is this? It's almost as if his brain was refusing to see the solution. Like it couldn't possibly believe that the solution could be that simple. So it just ejected it, put a big black censorship block over it.
I'm currently reading a book on brain hemispheres. Apparently experiments have shown that the left hemisphere will completely and blatantly reject obvious evidence even if the right hemisphere 'has a clear counter proof'. Sometimes I think our industry suffers from an abundance of left hemispheric dominance. Or something like this...