Overcoming Intuition In Programming (amasad.me)
An anonymous reader writes: Amjad Masad, a programmer who works at Facebook, has put up a post about intuition and programming. It's based on a series of experiments (PDF) into how the presentation of a problem affects the learning involved in solving it. Researchers found that if they made a test deliberately hard to understand, those taking the test would exhibit greater understanding after solving it than those who were presented with a more intuitive wording of the same problem. Masad discusses how the research applies to software engineering: "Programming is an intellectually challenging task, but luckily we invent tools to make it manageable. I find that up to a certain point, the intuitive and easy properties of a given language, framework, or library might start to have negative effects.
From personal experience and from mentoring beginners I noticed that when using tools that allow us to reason within our intuition, anytime we're faced with some difficulty we feel that we've done something wrong. And although we might have the necessary skills to overcome the difficulty, we often start questioning and revising our work." He concludes, "Code reuse, libraries, sharing, and open-source are very important to software engineering, but we should be careful to not enable the belief that programming should be as easy as gluing things together."
From personal experience and from mentoring beginners I noticed that when using tools that allow us to reason within our intuition, anytime we're faced with some difficulty we feel that we've done something wrong. And although we might have the necessary skills to overcome the difficulty, we often start questioning and revising our work." He concludes, "Code reuse, libraries, sharing, and open-source are very important to software engineering, but we should be careful to not enable the belief that programming should be as easy as gluing things together."
"Code reuse, libraries, sharing, and open-source are very important to software engineering, but we should be careful to not enable the belief that programming should be as easy as gluing things together."
That is the management view of programming and a major corporate goal. This way it reduces the skills needed to complete the task, and hence you can pay less for the less skilled laborers.
Why do you think the average salary of a Windows Admin is lower than that of a Unix/Linux Admin? Because Microsoft pushed the "we've made it simple, just push the button" marketing drek and aimed it squarely at the management crowd -- who bought it hook, line and sinker.
"They made it easy, so I shouldn't have to pay you as much because anyone can do it. I'll just hire some kid with the latest MS cert..."
Learning HOW to think is more important than learning WHAT to think.
Because that's what OO design is. Build a lego brick from lots of little prefabbed framework bricks to solve bigger problems. Put those bits together and you get to solve bigger problems. This sounds like the ramblings of a C weilding academic to me. Wow, problems that are phrased well are easier to understand? Say it ain't so. Coincidentally, that is a key skill for interfacing with non-technical team members.
Like this
X 3 3÷9 Y DATA[DATA] A comment
I really don't mourn APL's passing.
It is nice to see that programming as a discipline has reached the point where it questions it's great successes.
Sure must be some people getting their ears boxed at Facebook HQ over the epoch bug.
Alternatively they may be owning up to how bullshit interview questions are: you're a psychological experiment guinea pig!
The purpose of computer languages, frameworks and libraries is to solve business problems not to do your CS homework. That's why introductory programming classes don't use lean on frameworks (thanks Niklaus Wirth!) but real-world programmers do.
TL/DR: educational psychology study results should be applied in educational settings, not in business settings.
*grumble* Stupid kids can't see the forest for all the trees...
> but luckily we invent tools to make it manageable.
This idiot thinks the tools we have make this shit "manageable"?? Is he kidding?
More often than not the tools are just half baked abominations, gimping along just well enough to get through some crisis, and never looked at again. All incarnations of make, the so-called "auto-tools", cvs, svn, hell, even git is a complete pain in the ass. No sane person calls these tools "manageable".
And compilers? LInkers? Project management? Yeah those tools are so easy to use that we have to build abortions like Visual Studio and Xcode because we have no possibility of remembering how they work. Then we have to glom "package managers" like nuget et.al. onto the side because who the hell knows what dependencies this shit has.
AFAIC the tooling we have is shit, and every methodology that anybody ever dreamed up to manage this shit is also shit. And I'm sorry but "gluing things together" is ALL programming is anymore, or at least since 1983. We glue the shit that shit-makers like Facebook, google, Microsoft, Twitter, and 99 kajillion other web api and platform vendors give us to glue.
Stop trying to make it something it's not.
Researchers found that if they made a test deliberately hard to understand, those taking the test would exhibit greater understanding after solving it than those who were presented with a more intuitive wording of the same problem.
Paid for by the society of project managers and business software analysts.
Repeal the 17th Amendment TODAY! Also Please Read http://www.gnu.org/philosophy/right-to-read.html
We may refer to this as the framework intuitive space. On the other hand we may refer to the rest of the space that framework doesn’t solve or have an opinion on as the framework negative space.
"framework intuitive space" ?!
"framework negative space."?!
I suggest the author gets out of the advertising business ( like facebook) and go to work for a tech company where he can work on some intelligent and socially useful projects.
From what I gather from his long winded essay using made up terms to sound more important is that if programming gets hard, figure it out and don't slap togehter shit you find of the Internet.
I never understood all the self-introspection and rumination and hoops like Agile methodology that programmers go through. Just write the software. It isn't terribly complex to just do it. I've been doing it for decades, and I am not particularly bright. If you make a mistake, just rewrite/correct it. It is called SOFTware for a reason. It is easily changeable. Just do it.
Code reuse, libraries, sharing, and open-source are very important to software engineering, but we should be careful to not enable the belief that programming should be as easy as gluing things together
This is the wrong conclusion. Most of the time, we should give preference to tools and practices that have already become best practices, without necessarily questioning each one every time. Of course, there is room for challenging best practices and libraries, but that's for people who are interested more in the best practices and libraries, than for the people trying to use them to create something useful to end users.
You don't need to know how to repair a car to drive one. The guy who repairs your car doesn't need to know how to build a motor or a transmission, only how to install them. The guy who assembles the motor doesn't need to know the finer points of metallurgy. The guy who refines the metals doesn't need to know the finer points of mining. Each of these stages of production can have their own issues that need to be resolved, but the guy driving the car needs to worry only about staying safe on the road and reaching his destination.
Programming should be the same way. I shouldn't have to debug the IP stack to make my program connect to the Internet, nor should I have to reinvent build systems to produce a product.
Specialize!
This is a consideration for students and other people involved in learning a new language or skill set. In that case, yes, it makes sense to make the student work somewhat harder (within reason) to figure it out
On the other hand, in a business context, you're not trying to develop understanding; you're trying to accomplish a specific task as quickly, easily and cheaply as possible. In that case, intuitive presentation of the problem is desirable and fostering development of deep understanding may be neither necessary nor cost effective.
Please do not read this sig. Thank you.
C weilding academic to me
Say what? I don't know too many (computer science) academics who'd touch C with a ten foot pole. Those of us who use C do it for real work (and like it/won't get off it).
If I want to live in an ivory tower I'd either a) use the latest theory compliant language/compiler du jour or b) refuse to code at all since that is an implementation issue, and instead pontificate on what is missing from latest language.
but we should be careful to not enable the belief that programming should be as easy as gluing things together.
This pablum passes for wisdom nowadays. Actually, Church's Lambda Calculus proves the opposite. But, yes boys and girls, programming can be hard
lol
A better title might be "Why Hipster Coders Shouldn't Think Super-High-Level JS-Framework-of-the-Month Calls Mean You're a Good Programmer"
It's hard not to extend this to a #kidstoday rant, and I'm by no means arguing to go back to assembly, but at some point forcing large amounts of programming to the lowered-barrier of entry just reduces the percentage of folks who actually know what they're doing and can critically analyze the situation.
Hire a Linux system administrator, systems engineer,
Careful, C++ has its own share of unintuitive weirdness. Take the following example:
This prints out:
Nothing unusual there, right? std::map iterators are non-invalidating and you're not touching "iter", so it should be (and is) remaining the same. But what if we use reverse iterators (and correspondingly switch the side of the iterator we do the insert on)?
Despite sounding like the same sort of thing ("iterators"), forward and reverse operators have some very different properties in a key area. A non-invalidating forward iterator will always remain pointing to the exact same element regardless of what happens with other parts of the container. This does not apply to reverse iterators, as they are implemented in a rather unintuitive way - they actually point to the element after the element that they pretend to point to, and so changes to other elements can change what they appear to point to.
There's a lot of things like this in C++ that can slip past a person for years before it actually bites them. Don't get me wrong, I love C++ and think C is a rather dangerous language (from a memory safety standpoint) that requires that its authors reinvent the wheel over and over again. But C++ does have some weirdness in places that can pose hazards. For example, from a more beginner-perspective, what percentage of users have at one point been frustrated by trying to understand why a pointer in one of their classes is getting freed unexpectedly, due to not realizing the dangers of the implicit copy constructor/assignment operator when it comes to pointers? I bet that's bit almost everyone at some point in their career. Sure, you can "reason out" that that would happen, but most people learn it by being bitten once or twice.
Shiny New Australia.
and instead pontificate on what is missing from latest language.
you mean you'd be a software architect complaining how so and so's code doesn't follow SOLID principles?
Gluing things together is how programming works. You start by gluing the small bits together to make bigger bits and so on and so on. Eventually you come to realize that when you need to use "Super Glue" to hold the bits together it's probably broken. Usually you glue bits together at discrete places, if you have to work on bits that have had the glue brushed on in large amounts, that's call accretion, avoid those bits, maybe put a layer of wax around them with tiny spots for glue.
Having just finished a stint in academia, this. This 1000 times over. I actually worked along side someone who didn't understand why python wasn't used for firmware programming going on about how using it would fix all sorts of issues. Trying to make him understand the problems with resource limitations was completely useless. He just couldn't grasp that infinity was just a concept that didn't actually exist.
Not really OO design but modular design. OO is just a way to this end, functional programming is another one. And you can be modular in C, too, there are plenty of excellent C APIs out there, starting with the libc iteslf. ...).
As for the Lego brick metaphor, it is very theoretical. In practice, abstractions leak. Which mean that to use the brick properly, you need to know what's inside the brick. Like, for example, garbage collectors that should manage the memory for you and yet, you need to help it in some cases (cycles,
>> we should be careful to not enable the belief that programming should be as easy as gluing things together
I just helped my daughter do the princess-themed exercises on code.org. Code.org is ALL about "gluing things together" and issuing a "computer science" certificate at the end. Is this post Facebook's dig against code.org or this just one random guy?
I think the main problem is that by "intuitive", a lot of people mean "sloppily glossing over distinctions as if they don't matter". Sometimes people try to simplify problems by treating new or difficult ideas or operations as if they're like other more common things, but this leads to problems insofar as those things actually differ. Intuition is hugely important and valuable in problem solving, but your intuition doesn't tell you the truth if you've trained it by thinking of things as being something other than what they are.
High level constructs should map in as straightforward way as possible to the more complex, low level details they represent. For example, if something is a pipeline, and a user finds pipelines conceptually difficult, trying to make the interface hide the fact that its a pipeline doesn't actually make it less difficult. The thing is still a pipeline, and can't be dealt with correctly any other way, so hiding that fact makes the problem even more difficult by making it less clear.
But if you've been thinking about it in the right way, then your intuition points you at creative and effective ideas about how to use it, without having to first reason through the details. Its as if you have a correct model of the thing somewhere in your mind that you can feel, even when you don't trouble yourself with the details, so what you feel about it tends to be right. In general, in my experience, most things that seem 'counter-intuitive' usually seem that way because they weren't explained and understood in an accurate way, not because they would seem counter-intuitive otherwise.
TDD. Whether you're OO or event-driven, creating the unit test first keeps you at an honest level of difficulty; I don't get surprised by my frameworks.
I can program best in C++ because it's less intuitive and so it makes me think.
Sorry, I'm not interested in the recipe for a poison pudding.
... you don't become good at doing it.
Wow, news at 11, guys.
Video of some good progressive thrash music
If I say something to you and I use extremely poor grammar and vocabulary, you're likely to attempt to confirm you understood what I said by repeating it back to me as you understood it.
And that's all programming is: Converting things into a language you understand well enough to teach a computer what to do.
That's my experience as well, at least, as of the middle 90's. Why use a mainstream, commercial language, when you could use a theoretically complete one? One where they recognize that features like "output" and "input" are dirty exceptions that spoil the purity of your program when you're trying to get a good hard proof using Hoare logic.
Better not clutter up the syntax either by using confusing, pre-existing symbols to form constructs, not when you can add whole new symbols requiring a special (APL) keyboard!
I remember having a TA once challenge me - I had written an algorithm to operate iteratively, rather than recursively, because I had noticed the program would run out of memory if I did it the other way when fed large data sets - because to him, recursion was theoretically perfect and not using it was a personal affront. The fact that my code worked and his crashed after 4-5 minutes didn't matter.
To paraphrase a professor of mine, "There's absolutely no reason for a computer scientist to use a computer."
This sort of attitude was pretty rampant all throughout my college career, fairly startling having already been employed in the industry for some years prior. No concept of real world usage at all, or worse, some strange bias against it.
There are a couple outcomes of this that I don't think they quite understand correctly:
1) I'm not sure whether we're really using a different part of our brain here but just having to dig deeper into the problem. The more time you have to spend figuring out how the code works to then find how it is not working the more you will understand that code. That's not a leap of imagination there it's straight cause and effect. As it is this inherently works its way into a new developer's role in a new company. Your first tasks will generally be fixing or augmenting other people's code not writing your own from scratch. You will therefore need to spend that time learning the existing code to then fix it hopefully gaining deeper understanding along the way.
2) Tooling and Frameworks are their own separate case. Disclaimer: It is a good thing that modern developers should not have to reinvent the wheel on every task. That being said: The developers using these previously invented wheels no longer are exposed to the inner bits required to make that thing roll and so will inherently have a shallower understanding of how it works and therefore will not understand what's going on when it does quite work the way they want it to. If the Frameworks / Tooling worked exactly as spec'd with no fuzziness this would not be *that terrible but that's not the world we live in. Because of this newer devs are less equipped to diagnose an issue when their Frameworks and Tools are letting them down or not quite getting the job done.
Modifying collections while iterating them is exactly the sort of bad idea good programmers have always avoided, regardless of the language. C++ doesn't protect fools from the consequences of being foolish.
There's a lot of things like this in C++
There are lots of stupid things good programmers avoid out of habit.
Mmmmm, the "what will C++ do now?" quiz show is one of my favorites. here's a little gem showing off the bizarrities of EOF, peek, and ignore.
There's a lot of things like this in C++ that can slip past a person for years before it actually bites them. Don't get me wrong, I love C++ and think C is a rather dangerous language (from a memory safety standpoint) that requires that its authors reinvent the wheel over and over again. But C++ does have some weirdness in places that can pose hazards.
Seeing things like this make me glad that I gave up C++ ten years ago.
Oh dear dog, not that mess. As someone who spent many years in c before moving to c++ that mess still confuses me. Yes I get it when I read it (again), but still...
Problems in the real world typically don't rephrase themselves for the benefit of the person trying to fix them.
Doing so in a test does a dis-service to the student.
I also once met an idiot, worked with an idiot, went to school with an idiot, and am an idiot!
In Figure 1 of the paper, which one is the drummer?
USB, USB, USB!
But the usefulness of OO comes from modifying the behavior of objects not just replicating them.
I've heard it argued that perl programmer's tend to understand object-oriented programming better than programmer's from other languages, because they have to think about it harder... there are a lot of different ways of doing perl objects with different pluses and minuses, and you have to decide what aspects of OOP you really care about.
I knew someone in late 90s who was upset that we weren't using Java for a highly complex embedded system used for medical work, and instead used something archaic like C++ (seriously, he thought it was archaic in its heyday). We'd explain to him that we can't throw out all the work and start from scratch without spending years, that Java at the time was terribly slow, that there were no distinct advantages of changing or reductions in complexity, etc. But it was his first job after his master's. Later on he started a (tiny) company and gave a keynote address at a Java conference where I heard third hand that he had put down his former employer for being such a dinosaur. It wasn't even that this guy was an academic idealist but that he merely was caught up in fandom.
CS is a large academic area. It covers a range from CS academics who use C, assembler, as well as functional language purists, and even those who don't even use computer languages.
I had a TA ask me once why I had spend so much effort making my Lisp program completely recursive instead of using PROG or PROGN, and I said I thought that's how it was supposed to be done. It was a good academic exercise though to think about how to program in a different way from normal procedural programming.
Or in C, "x = ++x++ + ++x++;"
The KISS principle always applies and has not become obsolete.
If something is made hard enough then only the most capable will survive the selection process. Can you imagine the quality of programmer that would exist if we only did everything in ASM? While the understanding that ASM programming might induce would be beneficial the reality is that maybe only 1 programmer in 20 would continue the process. Also productivity would be shot in the face.
For instance I really hate APIs where you have to have this huge pile of boilerplate with all kinds of factory classes pooping out this and that that you assemble into something that every other person using the API will do. Maybe it gives you a better peek into the internals but I would rather some kind of Init or Create function that gives me the end product that I and every other programmer wants. All that boilerplate might make my code look intimidating and keep the weak minded away but it didn't make me a better programmer by any amount to be worth the wasted time.
Holy shit, that's scary! Doesn't the school you're thinking of teach compilers, embedded computing, or high-performance computing?
"[Regarding the 'cloud,'] ownership was what made America different than Russia." -- Woz
But C++ does have some weirdness in places that can pose hazards. For example, from a more beginner-perspective, what percentage of users have at one point been frustrated by trying to understand why a pointer in one of their classes is getting freed unexpectedly, due to not realizing the dangers of the implicit copy constructor/assignment operator when it comes to pointers? I bet that's bit almost everyone at some point in their career. Sure, you can "reason out" that that would happen, but most people learn it by being bitten once or twice.
This is why I vastly prefer Qt with QObjects that disable the copy constructor, structuring the application like a hierarchy with managers that act as resource owners. Consider the pot at a poker table, you could model it as players pushing money into the pot and the winner grabbing it. Screw up your winning logic and two players might try to grab the pot (double free). But if you model it with a dealer collecting the bets and handing it out to the winner you have a single resource owner controlling the resource. Sure, your logic may still be faulty but the result is far more likely to just be incorrect, not a crash. Same way I'd have a seat manager to make sure two players don't grab the same seat. If this is a big tournament, maybe I have a table manager and a player manager too, each holding their collection of objects. It is a lot, lot easier to see the logic - or flaws in it - from a bird's eye perspective.
Live today, because you never know what tomorrow brings
C++ doesn't have "weirdness," C++ has bad design. Literally anything that you might think C++ would be good for is better solved by either C#, C, or a combination of both.
"[Regarding the 'cloud,'] ownership was what made America different than Russia." -- Woz
Sure this guy can do the needful.
Civilization advances by extending the number of important operations which we can perform without thinking about them.
-- Alfred North Whitehead
Right, be tough on them, makes them perform better. Except, maybe just in a statistical significant manner. And maybe a lot less people solved it if you made it deliberately hard. And maybe they understood it better because they spent more time on it.
... "careful to not enable the belief that programming should be as easy as gluing things together."
The fact that you believe gluing things together is easy tells me you've never glued things other than paper together.
Identifying information which is of importance to underlying goals is the essence of (software) systems programming.
We encourage you to re-engage your primary role as aesthetically complementary to your environment.
Thank you,
The management
I've sometimes been accused of doing something similar. Good abstractions allow one to be productive by not having to micro-manage details; snapping together high-level modules like Logo's. But, they indeed can also entrap you when new requirements don't fit their design grain, or grow too confusing for new developers to figure out.
I've since been leaning toward abstractions that you "date instead of marry". The "test" is that one should be able to toss the abstraction if needed without too much code rework. It should be considered a "helper", not an "API kingdom".
A helper function can save you a dozen lines of code, but you shouldn't be obligated to use if you want to take advantage of the rest of the framework or helper utilities.
For example, it's nice to have a compact function or object to draw and validate form fields. However, it should also be possible to hand-draw the form field (raw markup) and/or do the validation separate without the drawing part. One shouldn't be forced to use it for all form fields or all validation to have the form work smoothly.
You may end using the shortcut function on say 80% of the fields, but can still do 20% outside the function/framework. Plus, it can simplify the helper functions/objects by not having to put every possible feature in there. Forceful frameworks often have to include every bell in whistle because one "should not" have to go outside the framework; making the framework have to handle every contingency. A function/object that only has to cover 80% of the cases is usually far simpler than one that has to cover 100%.
(That's one thing I don't like about Microsoft's API's and frameworks: you are either forced to be all in or all out; they don't make the middle ground very easy. I suspect this is to lock you into their world so that you have to buy more MS in the future.)
Table-ized A.I.
Have you read what some people think about C here on Slashdot? They have to come from somewhere.
A competent compiler should complain about that last postincrement.
If you want to make things really confusing you should use decrements instead since those can be interpreted as negation.
Corrections and clarifications:
Re: "...snapping together high-level modules like Logo's"
Should be "Lego's".
Re: "...often have to include every bell in whistle"
Should be "...bell and whistle".
Re: "One shouldn't be forced to use it for all form fields or all validation to have the form work smoothly."
Clarified: "One shouldn't be forced to use it for all form fields or all validation in order that the form work smoothly or properly."
Table-ized A.I.
Holy shit, that's scary! Doesn't the school you're thinking of teach compilers, embedded computing, or high-performance computing?
You can make compilers, and do embedded and high-performance computing with modern programming languages. If you are still writing your software in C, you are wasting a lot of time and effort in developing, testing, and debugging. C is simply a language of lowest common denominator that is well known and suitable for churning out programs that leak memory like a sieve and are remote code exploits.
Software systems are not physical things. End of.
I really wish people would stop with physical systems/software systems analogies. It's facile and wrong. Where this came from, I don't know but it's been around for years.
Software systems are abstract entities. They do not suffer from wear and tear. They are not built by armies of drones on an assembly line. A small amount of software can power an entire company or nation. A large amount of software can be needed to perform a seemingly "simple" task, sometimes necessarily and sometimes unnecessarily. There is little correlation between software size and "work done". Efficiency is an envelope. Software can be arbitrarily layered and combined to form highly complex systems unhindered by physical world constraints, often in ways completely unimagined by the designers. Software can be replicated or copied trivially. Software allows itself to be deployed and running "instantly" (in meatbag terms) anywhere and all at once all over the planet. And in fact, people go to great lengths to constraint software's abstract lack of physical limitations. Components can be reused but this requires both care of design and adaptation in use. Or sometimes not, just creative abuse. A piece of metal can only be bent as much as the laws of physics allow. A piece of software can be bent only as far as your imagination will allow.
Try doing that with a car or a bridge or a house.
Harumph! If that's the way you feel, so be it. But please turn in your type-ball to the TA.
If your C code leaks memory, you don't know WTF you're doing -- which is exactly why a department of CS professors who don't use C is so damn scary.
And I don't give a shit if you think you don't need to use pointers; that's fine. You still need to understand them so that -- if for no other reason -- you understand why in Java or C# not every IEnumerable should be a List.
Also, if you think a high-level language will save you from remote code exploits, I've got a bridge to sell you.
"[Regarding the 'cloud,'] ownership was what made America different than Russia." -- Woz
If you need a port, hire me to write it for your different CPU because it's already in my head as I had to have a deep understanding of the problem before I could write a solution in assembler.
“Common sense is not so common.” — Voltaire
Say what? I don't know too many (computer science) academics who'd touch C with a ten foot pole
Donald Knuth, for one (albeit with a literate programming pre-processor).
"First they came for the slanderers and i said nothing."
I remember having a TA once challenge me - I had written an algorithm to operate iteratively, rather than recursively, because I had noticed the program would run out of memory if I did it the other way when fed large data sets - because to him, recursion was theoretically perfect and not using it was a personal affront. The fact that my code worked and his crashed after 4-5 minutes didn't matter.
Tail recursion optimization usually takes care of problems like that, assuming the problem was running out of stack.
In a band? Use WheresTheGig for free.
Please tell me you don't write code that controls something important.
What if I want the compiler to enforce resource and exception safety for me without using garbage collection (which only works on memory, anyway)?
What if I want to pass an anonymous function to a function without using a function pointer?
What if I want to tell the compiler that I want a particular function to be evaluated at compile-time?
Show me how to do those things with C alone, C# alone, or C# and C combined.
Masad is perhaps guilty of the very problem he identifies. He reads a science paper, latches onto the word "intuitive", misapplies it, and so misses a key point in the paper.
In the original study, the authors present the same cognitive test to two different groups, one time using Myriad 12pt, the other gray italicized Myriad 10pt. In another experiment they changed the masthead of a document to introduce nonsense characters like @$Ã. In a third experiment, they had one group furrow eyebrows while doing a test. In each case, they found that the group with the "disfluent" condition (small gray font, @$ characters in the masthead, furrowed eyebrows) performed better than the control condition. From this they conclude that their experiments support the cognitive theory that we have two distinct reasoning systems, a rapid "intuitive" reasoning system and a slow "analytical" reasoning system, and something about disfluency prompts us to switch from our rapid to slow reasoning, leading to improved scores.
Masad summarizes: "The theory behind this is that people will default to relying on the automatic, effortless, and primitive system for reasoning. But if things are counter-intuitive or harder to understand we switch to the deeper, deliberate and analytical mode of thinking." Note how "intuitive" has jumped ship. In the original paper, "intuitive" was a label for our fast reasoning system, contrasted with our slow analytical reasoning system. For Masad, "intuitive" refers not to one of our cognitive reasoning systems but rather to the -input-, he suggests that if the input (e.g. the software framework) is counter-intuitive or harder to understand then we use our more analytical reasoning. There is nothing to support that conclusion in this study ... there is nothing counter-intuitive about using a gray 10 point font. The conditions with higher scores weren't harder to understand or more counter-intuitive, they were less legible and more difficult to read. If we translate this study to programming, as Masad proposes, it suggests that if you change your IDE to Myriad 10 pt gray italic, then all of a sudden your code will get better. Hey, go ahead, try it!
Ok, sure, what Masad is actually doing is using a science paper as a prompt, a poetic license for thinking about frameworks and coding. But the kinds of shortcuts he makes are informative - so I'm going to take some poetic license of my own...
First, I think Masad overlooks the importance of reading. The science paper suggests that something about how we read changes how we think. One thing I've noticed about beginner programmers is that they tend to be poor/lazy readers of code. They skim, treating a library or framework function as if it is are magic black box, never to be questioned or investigated. I've had many experiences where I've sat down with a programmer, cracked open a source browser, read the actual source of the library function they are relying on, and heard a gasp, as they realize their assumptions that the framework code is perfect/threadsafe/performant etc. fall away. "You mean every time I do this, it does a linear search through my entire dataset. OMG" "Well, yes, its just code. All you have to do is read it." Promoting code reading has nothing to do with whether or not the framework is intuitive or hard to understand or has "negative space". Its much more about business management priorities and deadlines and culture.
Second, its significant that Masad took a paper from one context and used it to think imaginatively about a very different problem space. Bouncing ideas around freely like that is precisely what the fast/intuitive (if potentially incorrect) style of reasoning is good for. His claim that we need to "overcome intuition" is wrong, in my opinion - its exactly how we stimulate new ideas and debate. His own thought-provoking post proves it.
I did not use C since 30 years, and C++ on,y sporadicly since 1999.
The companies I worked for make billions, yes, billions in earnings, with my Java code. (E.g. EnBW.com)
No idea what your 'real work' is supposed to mean.
Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
The thing is, iterators are presented as the preferred alternative to container indices or pointer incrementation over a container. Both of which are modification safe. So you either need to have them match the capabilities, or accept that they're not an alternative.
Shiny New Australia.
that leak memory like a sieve
I've worked on a number of very large software projects in C and have never had to do dynamic memory allocation. In fact, it's never been allowed.
Follow MISRA. Avoid weirdness.
I do find that easy interpreted languages that mostly do right thing tend to make you lazy in understanding.
Try for example the following two in python
a=[1,2]; b=a; b=b+b; print a,b
vs
a=[1,2]; b=a; b+=b; print a,b
Results are actually different, even if they should "intuitively" be the same. I found that after spending 3 years of hard coding in C++ made me appreciate what exactly is going on under the hood much better, even for python.
Is this a complaint about typo's, or light/leaky abstractions? If the second, I do agree that certain kinds of applications require "tighter" or bigger frameworks. For accounting or medical applications, for example, time-saving abstractions are less important than reliable software, at the expense of requiring more coding time. Large, overarching frameworks are common and expected for such.
But if say it's a tracking system for internal restroom supplies, then nobody's going to want to spend the resources for ultra-reliable software to prevent toilet paper from occasionally getting lost. I'm not saying such is good or bad, only that by experience I know that time-saving "light" abstractions are more welcome and/or expected for such by management and/or owners. They don't want enterprise bills for non-enterprise stuff.
Table-ized A.I.
This, times 1000. I love C++ and use it professionally, and prefer it to a lot of languages - but if someone tells me they're a C++ expert I'll laugh in their face unless they're Stroustrup or Herb Sutter or someone like that.
I've been using C++ seriously for more than 5 years, and the more I learn about C++ the less I know. A few of my favorite are "what's the correct way to call swap" (and ADL in general) and reference lifetime extension. Gotta love stuff that seems like it obviously works when you don't understand it, until you realize what you're actually doing, and then it shouldn't work - but there's a special case that makes it work. Then you wonder "why did they support this?" and realize that this tiny little insane corner is crucial to making the language make sense. Just don't think about it too hard. For argument-dependent lookup, it's why you can print strings. For reference lifetime extension, it's why a ranged-for over a temporary container works (among a few other things).f
I have developed a truly marvelous proof of this comment, which this signature is too narrow to contain.
Indeed, and the documentation is not always clear or accurate. One often has to fiddle to experiment, adjust, and find work-arounds for glitches.
That's where skill comes in such that it's often not as simple and sticking parts together and filling in parameters: that's the easy part.
Lego's with personality quirks is probably a better metaphor. The long blue Lego may not like being connected to the short yellow Lego on Tuesdays for reasons only known to Microsoft, Oracle, Google, or God.
Table-ized A.I.
Literally anything that you might think C++ would be good for is better solved by either C#, C, or a combination of both.
This makes literally no sense. With minor caveats, C++ is C with more stuff. Even if you only use (say) namespaces or a modest amount of ad-hoc overloading, C++ is a better C.
The main cause of problems with C++ is using it as an object-oriented language, but you'd have the same problem in C#. What Alex Stepanov rightly said about Java equally applies to C#: "I spent several months programming in Java. Contrary to its authors prediction, it did not grow on me. I did not find any new insights - for the first time in my life programming in a new language did not bring me new insights. It keeps all the stuff that I never use in C++ - inheritance, virtuals - OO gook - and removes the stuff that I find useful."
sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
I love C++ and use it professionally, and prefer it to a lot of languages - but if someone tells me they're a C++ expert I'll laugh in their face unless they're Stroustrup or Herb Sutter or someone like that.
I consider myself a C++ expert. (I actually refer to myself as a "language paralegal" as opposed to "language lawyer"; I used to have a desk next to someone on the standards committee.) The main reason why I think I can confidently call myself this is that I know enough to know where the limits of my knowledge are. You really don't have to be Myers or Sutter to get past the Dunning-Kruger barrier.
It's interesting that you mention ADL. Anyone who used C++ templates in a non-trivial way before two-phase lookup was standardised had to learn the new rules because they almost certainly had to port their code to the new standard. As breaking changes go, it wasn't too bad, since the effect was to make some previously legal code illegal and the fix was just to qualify some identifiers. Still, many C++ programmers of a certain age know the ADL rules for that reason alone.
sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
The companies I worked for make billions, yes, billions in earnings, with my Java code.
But they obviously don't rely on your reading comprehension.
Everyone is always trying to grab the pot.
That's fine for your own projects, but the problem comes in with dealing with other's code. Everyone seems to have their own subset of C++ they like to use. The problem is that everyone's subset is a bit different. So you have to be at least aware of everything in C++, just so you know it when you run across it. (once again, this doesn't apply for your own projects)
Or you're using it wrong because you don't understand how it works when it's translated into procedural instructions.
int foo(int bar){ return 1+foo(bar); }
may not be the same as
int foo(int bar){ return foo(bar)+1; }
which may not be the same as
int foo(int bar){ return foo(bar+1); }
If you're working in embedded systems, you shouldn't even be doing any memory allocations once the program has initialized. There are not many languages other than C that allows you to NOT make any allocations during runtime.
He's probably referring to you attempting to correct someone's mistakes with your own mistakes. Your misuse of apostrophes does not make you seem particularly careful, which is rarely (never?) a good quality in a developer.
Let me preface this by saying that I'm a horrible programmer but I wrote many lines (many of which were not needed) in C back in the day.
Eventually, I reached the point where maintaining and improving that code was simply beyond my time limits and my ability. I am not a programmer. I learned because I had to. So, I hired professionals. They taught me a lot but, alas, I am still not a programmer.
If we go back to my initial comment, we see that I wrote many lines of code, many of which were not needed. So, we started a project where these kindly programmers had had enough and wanted to rewrite all of my code. They wanted to use this language called C++. As tempting as it was to deny such requests, I let them write it in C++. Why?
Well, I hired them because I code for shit. They were better than I - that's why I paid them money. If they wanted a tool then, it seemed to me, that they know better than I how to do their job. If I knew better then they, I'd not have had to hire them - I could have just hired monkeys and told them how to do it.
Point is, what's the point of getting in the way of letting the people you hired do the job you hired them to do? If you ask them to complete a task and trust them to complete the task them give them the tools they ask for, shut the hell up, and get out of the way. If your program worked while his broke after some minutes then I don't want him working for me unless he's able to make his program behave like your program.
I may not be the brightest bulb but I've learned a few things and one of them is that if you shut the hell up and get out of the way - you get pretty good results if you have good people. Don't get me wrong, I tried the micromanaging thing. Yeah... Don't do that. Fortunately, I'd hired people who had the brains and balls enough to tell me to shut up and get out of the way. I imagine most people would have fired them for doing so but programmers were a bit different back then so, eventually, I learned to get the hell out of the way and just give them the tools they asked for. Strangely enough, it worked.
"So long and thanks for all the fish."
One of my favorites:
https://xkcd.com/163/
"So long and thanks for all the fish."
There is no such thing as a Lego. There is such a thing as an idiot, and you're one.
My brain is turning to mush as I've been a passive consumer for far too long. I'm delving back into programming and, don't hate me, getting back into some PHP and going to learn some Python. I'll probably pick up Perl 6 just to say I can.
That said, I used to program in C. A lot... Like a whole bunch - except I am actually not a programmer. Well, not a good one at any rate. Oh, things worked, eventually. The many hours spent sleepless and hoping someone would help me out via USENET were plentiful and, eventually, we had enough contracts completed to actually hire competent people. Yay! Go me! Anyhow, that was a lot of years ago...
I don't like this mushy brain feeling and I'm getting older and the mush is getting more resilient. It may sound odd, if you're young, but you can actually sense it when it is happening. They say the brain becomes more plasticine (or is it less?) and that things get more difficult as the brain, literally, undergoes a physiological change due to aging.
So, I've always preferred good answers - innate selfishness, I presume. You, being an expert and I, having seen enough of your replies to have no doubts as to the validity of your claim means you're likely to be a good source of my preferred answer type. (In common vernacular, you're smart and I have the stupid.)
Where's a good place to get into C++? I've some, vague, familiarity with the language and have even actually learned some - years ago, as that was what my C was ported to by the afore mentioned hired programmers. I'm very much able to pay for instruction but I do not wish to return to academia. I can afford any/all resources but am not so interested as to hire a private tutor, at least not one locally. I'm not needing a full, deep, instruction but just enough to code a few things. I don't even have any specific problems that need solving.
Anything that you'd recommend? Any works of your own making, in book form perhaps, to look into?
"So long and thanks for all the fish."
Or in C, "x = ++x++ + ++x++;"
I'm pretty certain that that is undefined behaviour. It might work, it might crash, it might give you the "correct" answer the first 10000 times and then give you a different answer. In short - what that does is not predictable, which is different from 'weird'.
I'm a minority race. Save your vitriol for white people.
To be honest I prefer faulty logic to produce a crash and not inaccurate results.
I'm a minority race. Save your vitriol for white people.
"Legos" in common usage and "Lego bricks" according to the company that makes them.
"Lego's" makes me wonder "Lego's what?" because the apostrophe indicates the possessive.
Neckbeard Lego Kit for you
Speaking of correcting mistakes with mistakes...
(hint: check the usernames)
Oh hi Johnny, I didn't know it was you.
More is not necessarily better. Although a few features of C++ might be "nice to have" in C, the fact that all the other shit is also available means there's too much unnecessary complexity, especially in code written by other people (who might have a different opinion of which subset of C++ is valuable).
I spent the last two years programming professionally in C#, and recently changed jobs to a C++ shop. You clearly have no idea how much nicer C# is to use than C++, especially due to the facts that C# has real generics instead of preprocessor templates, that Visual Studio's debugger works much better with C# code (by showing the actual hierarchical members of your objects instead of vtable pointers everywhere, for example), and that LINQ exists. Also, having private members be actually private (rather than being exposed in the header file) is nice, if for no other reason than that you don't have to recompile everything that uses the class just because you added a new private method. (And those are just a few things off the top of my head; C# has lots of other advantages.)
Also, the article you cited is based on an archaic version of Java; what applied then does not apply now. (He talks about AWT, which as far as I know nobody's used in decades, and the question he's answering was about Java's lack of generics, which it has had for quite a while.)
"[Regarding the 'cloud,'] ownership was what made America different than Russia." -- Woz
Then there are the idiots that are ideologically prejudiced against CS, Scheme, functional programming, etc and will go out of their way to sabotage it because they find it 'confusing' or because it 'makes debugging harder'.
The only thing you could do is to transform the tail-recursive algorithm into an iterative one by hand, and nicely document it into a big comment & warnings above it. That's almost like writing in assembly.
I won't get into an argument about whether and when to "be careful" about such. (If you pay me, generally I'm more careful about such and look up rules as needed.)
But I would point out that there are a fair number of coders who are not native English speakers and otherwise write pretty solid code, if you ignore their comment and documentation grammar.
I can always find something to complain about in other people's comments and documentation if I wanted to. A lot of it is not "formal" mistakes, but otherwise poor decisions such as unnecessary words. It's easy to find crap to complain about in writing.
Table-ized A.I.
In a course on theory one should not spend 90% of the time for a task on reorganizing the instructions. Software engineering, sure. Operating system design? No.
True, but it's useful to know it is undefined, and useful to know possibly what was intended. Because some sorts of code might have that and you end up being asked to fix the bug. I see a lot of people in interviews or online who refuse to concern themselves with weird stuff like that because it's not how they write code, even though most of the job deals with reading and modifying other people's code.
If you have some sort of system that will expand arrays as needed to hold what you put in, in C you will have a test to see if the array is full, and realloc it when it is. That will invalidate all pointers. std::map does not invalidate iterators, but std::vector can.
"When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
You clearly have no idea how much nicer C# is to use than C++, especially due to the facts that C# has real generics instead of preprocessor templates, that Visual Studio's debugger works much better with C# code (by showing the actual hierarchical members of your objects instead of vtable pointers everywhere, for example), and that LINQ exists.
I have used both C# and Haskell in anger. C# "generics" are more applicable than C++ templates, but C# generics are not a sweet spot. If you think of C++ templates as generative programming (as opposed to generic programming), they make a lot more sense. C# generics are comically clunky if you've experienced parametric polymorphism as you find in Hindley-Milner languages.
Incidentally, debugging C++ can be done extremely well (Xcode is far superior to VS at this), but the state of debugging on Linux is terrible just in general.
Also, the article you cited is based on an archaic version of Java; what applied then does not apply now.
His main point still applies: Java keeps the "OO gook" of C++ and leaves the interesting stuff (e.g. compile-time code generation).
sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
(In common vernacular, you're smart and I have the stupid.)
It's probably more accurate that you have the ignorant. There's no shame in not knowing, right?
Where's a good place to get into C++?
I honestly don't know! The best I can suggest is borrow a Scott Myers book from a library (latest edition of Effective C++), have a copy of the FAQ at the ready and join a reasonably welcoming open source project.
Why Scott Myers? Because one of his books will give you a sense of the difference between C and C++.
sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
Oh, I should have said something about LINQ.
LINQ is interesting. The idea of a 21st century language leveraging baroque 1970s SQL syntax is bizarre, but it works. I worked on (as in, partly wrote) an embedded language which had a very similar feature about 15 years ago, only it was much more flexible within its domain. It didn't link to SQL databases, but you could do almost all of XPATH in it.
I've never used LINQ, but every time I see an example, I can't help thinking that its main purpose is to reuse SQL programmers, not to make querying collections easier. I've never liked SQL, and was always happier when Datalog or relational algebra was available.
sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
"Language paralegal" is awesome. And for the record, "sitting next to someone on the standards committee" is expert-level qualification in my book. (In any case, "laughing in faces" is too bombastic for my tastes.) It means you work at a shop that 100% gets the complexity of the language. I'm in awe of such people. I've met Stroustrup once and managed to find a few compiler bugs but there's a lot I don't pretend to understand. And everything I know I'm shaky on, I learned existed in the first place from working near the proper experts.
What I mostly meant was there's a lot of people who put "C++ expert" on their resume - and it usually means they're an expert in the 30% of the language they know exists. Which doesn't mean they're not capable - that 30% is pretty much all you need for most things - it just means they've underestimated the language. I was one of those people after about 9 months of using C++. The problem is eventually you have to peek beneath the covers to interoperate with some template monstrosity or you otherwise get a bit too clever and blow your foot off (as the saying goes) so it pays to be a bit skeptical in general.
I have developed a truly marvelous proof of this comment, which this signature is too narrow to contain.
Ah good. Oddly enough, I have that book. I ordered and received it not long ago. The site is added to my favorites. Thanks!
"So long and thanks for all the fish."
The validity of this whole argument depends on what you think you mean by 'intuition'. It was been defined as far back as the '80s as "arrival at valid conclusions without recourse to inference", whereas most people merely use the term as a loose synonym for wild guesswork. It is (roughly) the use of simultaneous as opposed to sequential thinking, so it's a process, not a result, and for it to work you have to be already in possession of the required knowledge.
The use of 'intuitive' in the context of this article is therefore incorrect. Substitute 'simple', 'easily understood', or 'familiar' for 'intuitive' and it does make sense, but it's not talking about intuition.
However intuition is a powerful mental mechanism that is insufficiently cultivated in our techno cultures, so the last thing we should be aiming for is to 'overcome' it - there's not enough of it around anyway.
What you describe is the C equivalent of std::vector, not std::map. std::map is built around a red-black tree, not an array.
Shiny New Australia.