49 comments

[ 4.3 ms ] story [ 111 ms ] thread
(comment deleted)
>"Consuming abstractions produced by others and building our own abstractions on top of them to solve our own local business problem. This is what programming really is for me."

This is not programming, just like how following a recipe is not cooking.

I'm pretty sure following a recipe is generally considered cooking.
Isn't following a recipe to make food exactly the definition of cooking? Maybe they meant that a chef has to invent original dishes but I think the whole cooking metaphor fails to map to programming since its mass production vs programming being essentially always custom one off.
If I dictated every ascii character of Romeo and Juliet to you, would you then call yourself a playwright?

I would call you a good typist.

EDIT: I never cook with a recipe and do everything by taste, feel, and instinct.

Then you should have used Romeo and Juliet example instead of cooking example.

Following receipt is in fact cooking. You can go by feel, but you don't have to. Majority of cooking is following receipt, whether written or not.

what happens when you burn the food because you have no concept of how hot is too hot?

what happens when you get a null pointer because you have no concept of exception handling?

Did the recipe say "burn the food"?

Ok, then you didn't follow it.

"Did the programming tutorial say 'watch out for flipped bits in your hello world'"
What happens is you learn, and next time you have a concept. That doesn't mean you stopped using recipes.
Of course it is. You don't write a new web framework when you want to build a website.
which framework do i use to translate my cool idea for a game into a triple aaa title, merely through speech alone?
This is literally how some of my coding friends told me they learned to code and created their own programs.

And yes following a recipe is cooking otherwise chefs would never do it, it’s called standardization

"A submarine propelling itself through water? Pfft, that's not swimming."
It's strictly not. Marine soldiers are not asked to pass a submarine piloting test, they're asked to complete a swimming test.

Why is this important? Because how can one import a library for a problem that currently has no solution?

It's a reference.

"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim." - Dijkstra

Literally all programming fits that sentence. Your language is an abstraction, the opcodes it compiles to are an abstraction, the machine code is an abstraction and the microcode it translates to - also. The engineering software for hardware is a highly simplified abstraction based upon physics and math. The physics and math, ...an abstraction for reality we barely understand.

We all stand on the shoulders of giants.

But maybe you create your own universe from scratch and program it without abstraction, who knows.

A computer "follows the recipe", the programmer writes it. Sometimes the programmer runs parts of the program in his head.

A chef creates recipes and sometimes follows them. He can also extemporise.

Is football hard? It depends.

Is a group of 8 years old kicking a ball between two poles football? Or only world class teams playing the Champions League? What about everything in between?

I think that's a better way to frame it. I'm confident I could teach someone with no prior experience to cobble together code to do some simple tasks in a relatively short time. Will they be able to create production-ready code for a world class company? Not really.

For me the hard question is whether anyone has the potential to write that world class software, much like asking whether anyone has the potential to play the Champions League.

I mean gauging peoples potential I feel is meaningless since history has shown you can never really predict it. I am sure there’s some sort of baseline assessment you can create though to increase probability such as height and basketball for the elite level.
There are plenty of ways to gauge potential. Does one of the 8 year olds kick the ball extremely accurately? Can he run around significantly longer than his peers without getting tired? When teaching him skills through drilling, how quickly does he improve? Does he show a dogged perseverence when training or get bored and want to just fuck around?

There is an entire industry of talent scouts that predict the performance of kids as young as 12, and many of them are good at what they do.

Yup and what good does that do them? Look at sports, how often does the childhood prodigy turn into the adult phenom? Very very rarely.

So even your example with kids is false, there’s a book talking about this fetishism called Late Bloomers. I encourage you to check it out.

The only thing that really resonated to me from reading this are the two quotes found in the introductory paragraphs. Fred Brook defining programming and the other by Terry Crowley on abstractions. Thanks for bringing those to my attention.

Beyond that, I'm not sure I agree with much else. Following the insightful introduction, the author smears Terry's definition of abstraction by claiming the concepts of "usefulness or power" are missing. Double downing on this claim we're then lead through a series of technologies the author has experienced through the lens of "power to cognitive load" ratio while neglecting to meaningfully connect with the ideas of Fred and Terry.

it doesn't seem to handle debugging in the depth required to really discuss the difficulties of programming, debugging of course can be considered as the process of trying to understand the abstractions but that is generally simple debugging, there is also debugging in finding out how someone else messed up the abstraction they were going for, or finally the interplay between abstractions in different levels of the system that have created emergent problems with the system as a whole that people did not foresee.

that stuff can be pretty hard, sitting around all day getting nothing done, sweating, refusing to move from the computer you're trying to interrogate.

on edit: clarified a point in first sentence.

Before I though that programing in itself was not as hard to learn, that is until I started to tutor a person that has no technical background what so ever other that playing video games.

It was my undrrstanding at a time that the mindset one needed to play games, especialy those involving puzles and problem solving would have a somewhat natural attitude towards programmming.

And it is partially correct if you are a good tutor enough to make relations of one way of problem solving into what can be done in programing, which I found out I aint.

Where I was humbled in the attempt is when I was asked questions that I took for granted simply because of the years of programming, many things where just given, and while knowing then I had a very bad time properly expalining them to a absolute beginner.

This is what in my oppinion makes programming hard or easy, after that it is just layers of layers of that.

For me, now that I recall it, getters and setters in Java made no sense so much that I only got them after maybe a year, though I dont even know why didn't they make sense at the time.

I thing that a mentor has a lot of impact in how much programming is hard, be it a person, a course, or a book.

> For me, now that I recall it, getters and setters in Java made no sense so much that I only got them after maybe a year, though I dont even know why didn't they make sense at the time.

well they don't make sense :) 99% of the time they are just a pointless ritual to appease the OOP god.

I especially love when company mandates 90% test coverage and no lombok so I get to write tests for setters and geters :)

The article is focusing on a few abstract concepts, but here's some actionable rules I've found that work.

- When all you need is a function, don't make an object abstraction.

- Restrict your abstractions to at most 2 levels of depth (a base class and derived). It becomes more intimidating to figure how the flow goes if you have deep object hierarchies. This also helps to encourage forms of composition.

- Again, don't make an abstractions that provide little to no value to suit some orthodoxy or perceived 'best practice'.

As Jon Skeet put it best, "be pragmatic, not dogmatic".

I also love YAGNI - You Ain't Gonna Need It!

+1 for more compositions, just need to manage cyclomatic complexity. Have seen some mind bendingly overcomplicated code where A is in B and B is in A etc.
I find myself making object abstractions more in languages that do not have solid support for functional programming. In OCaml, I can build dozens of useful abstractions off of a handful of small functions by using currying and partial application. Equaling that expressivity in languages that don't support those features requires making objects more often than I would like to, because the alternative is hundreds of overspecialized utility functions that do not compose well and push you towards imperative, stateful styles (I have seen this happen!).

I still stick to two levels of inheritance max though, and most of the time I only use interface inheritance. Rarely do I want behavior inherited.

The problem with "when all you need is a function don't use an object" is that's it's a recursive definition.

There are people who think they need a singleton all the time, imagine where similar definition would have brought them.

How a function is defined varies from language to language, but if we're talking about a globally accessible named function, this is in effect a singleton.

It means you can't configure this function (through construction parameters), or replace it, or mock it, etc. it's in effect a "singleton function".

BTW, abstraction != inheritance.

Purely functional style can be quite difficult to read. Especially when you end up composing functions be partially filling arguments, sending functions as arguments of other functions and so on.

Once you get at that level, objects are life savers. Because then state is explicit on code rather then hidden in deep call stack and spread over various levels of it.

I would controversially add,

- don't use interfaces until you absolutely have to, and then try and find another way.

YMMV, but in my corporate experience with OO code, I find a lot of interfaces that have one implementation. It's a waste to plan for a future that doesn't come.

I feel we're lacking something like software mindfulness. Where you stay in the moment and just solve the problem.

It depends what language you’re in. As long as you can use fakes, it doesn’t matter if you use interfaces or not. In C#, implementations are sealed by default so faking them is not feasible unless you make the function virtual.
It is largely true. One has to start out with a clear definition of the problem they are trying to solve, regardless of whether they are laying the foundations of a software architecture or implementing an incremental change. The more you understand the problem at hand and its inherent complexity, the more you can avoid any accidental complexity along the way. Good architecture is about picking a set of interdependent, multi-layered abstractions that provide a reasonable blend of efficiency and brevity of expression, for tackling a problem domain. Universal solutions to a wide class of problems almost invariably end up as a mess.
Do you think lower levels should be dependent on higher levels as well?
I meant "interdependent" in the sense that lower-level abstractions should also be geared for the problem at hand and should expose a higher-level interface which satisfies the particular requirements of higher-level abstractions.
Programming is a form of writing with equivalent difficulty. The challenge therein is relative and yet orthogonal to the reading of code. This is best described by perhaps the most prolific writer in human history: Isaac Asimov.

The most striking thing that Asimov said about writing is about correctness. A good writer produces correctness the first time. They aren’t reliant upon tools, gimmicks, or editors to catch syntax or grammar violations because these trivialities aren’t the important concerns. Drafts are for revising ideas and distilling ideas down to a clearer thought. For good writers drafts don’t waste time or focus with correctness.

In addition to writing with correctness the first time entirely from the author without a bunch of bullshit helpers good writers know what they want to write. They simply write it. They may not have a clarity of vision on how best to order or describe a given subject for their given audience but then that’s what drafts are for. Just write it. In programming revising drafts if called refactoring.

Perhaps the greatest difficulty in any writing is simplicity which is far more challenging than mere mortals consider. The quality of a written work is directly attributable to it’s simplicity.

Simplicity only ever means fewer. Fewer is directly applicable to both form and substance. Does the author rely upon an excess of syntax decoration or do the directly solve the problem? Likewise did the author take the extra effort to fold similar ideas into a single abstraction thereby reducing the number of pieces and methods of approach while simultaneously increasing the potential number of solutions?

https://github.com/prettydiff/wisdom/blob/master/Simplicity....

This is an excellent comment and illuminates what I’ve come to realise myself re. the parallels of writing and programming.

In fact, writing is a core part of my workflow: I write to problem solve. A clear problem definition and potential solution makes building the solution much, much easier.

The linked article, unfortunately, buries the lede. When the headline is “Simple Writing”, it’d be a better piece if it started with that from the first sentence.

If it was so good, they'd have followed their own advice.

It took them 250+ words to write "simplicity is good".

I have found that obtuse specificity is necessary on the subject because programmers are in general principally concerned with least effort and falsely conflate simplicity for that least effort via the word easy. It is not about good.
Not sure if that’s the point of the comment. The point of the linked text, maybe, which is why I offered my critique.

If “simplicity is good” was the only thing you took away from the comment, you might want to re-read it.

> [...] perhaps the most prolific writer in human history: Isaac Asimov.

Beware of unrelated claims that taint your message! Asimov, while a prolific writer, was certainly not the most productive. According to Wikipedia, he wrote or edited 500 books. Enid Blyton, mostly known for the Famous Five series, wrote more than 600. Even Georges Simenon had more than 500. The Guiness book mentions a little-known South-African author that wrote 904 books.

I think people should prevent themselves from using words like "abstraction", "scale" and "powerful" when they really want to talk about something.

> Designing complex conceptual structure is basically what software engineering really is

You cannot quote Brooks and assume that you are going to do something complex anyway. Otherwise you fall for the most common form of accidental complexity: sloppiness. It doesn't have to be complex. Assuming it is going to be complex is the wrong default value.

But really what the author is talking about is API design. The only way for a library or framework to reduce the essential complexity is to skip on some aspects (not implementation details - this would be an abstraction). Like making variables constants so users don't have to fill in weird parameters only an expert of the domain would know what they are about.

This is precisely those choices that matter in API design. If you don't make those choices, you end up with a complex API through which you can see all the details (remember the trend of devices with transparent shells in the 90ies? That's the image). So you make choices. There's some things your users won't be able to do because your API fill in the annoying variables for them. But of course "One man's constant is another man's variable" (applies to women too) so may you'll have to present different interfaces or sub-APIs.

This is interface segregation.

Yes, programming is hard.

Programming requires reasoning about long chains of cause and effect in an abstract realm, expressed in a very terse, symbol-dense language (computer code). Writing even a short (but nontrivial) program in BASIC is beyond the reach of most people. This isn't because they're stupid -- they just haven't had training in the necessary abstract, sequential logic. A person can live a successful life and die leaving a comfortable inheritance to their children without ever having to develop that sort of logic skill -- and putting in the work to develop it requires enormous activation energy -- so most people don't. For them, "learning to code" is a skill so far out of reach and so removed from their daily experience that they may as well not try.

And learning to code well requires even more activation energy...

difficulty of programming is not having a thick book of specification for the project so you just wing it and refactor along the way. hence you never end up with predetermined form and function. everyone wants "a thing" but nobody actually sits down and thinks about it enough to write the spec before the actual work begins. nah, let's leave it to the programmer to figure it out along the way. his hourly rate and mental health is much cheaper than actually doing the required work of coming up with the spec by a bunch of architects and senior consultants.
(comment deleted)