Hacker News new | past | comments | ask | show | jobs | submit login
Keep your source code SIMPLE (medium.com/kevingoslar)
71 points by kevingoslar on Nov 10, 2019 | hide | past | favorite | 74 comments

My feeling is these paradigms, SOLID and SIMPLE, boil down to basically: small objects, connected minimally, though interfaces.

SIMPLE appears to be leaning even more towards the functional programming side of things; I think we should probably just get it over with and accept that composition of functions operating on immutable data structures is just the right way to go.

Is there a language that leans heavily towards immutable data, but steers clear of the, shall we say, dorkier side of functional programming?

This is Clojure. It's functional, but more as a side effect of focusing intently on simple, immutable, persistent data structures and their compositions. I'd strongly recommend looking into it, along with many of the presentations by its initial author Rich Hickey.

Imo no Lisp variant can claim to not be in the "dorkier" side of things ("dorkier" being read as "hard to approach" in my eyes).

I'd say Kotlin over Clojure.

I’d suggest you watch Rich’s talk “Simple made easy”. [1]

It’s one of his main points that something like a language being “hard to approach” can be overcome by spending a little effort to learn it (as opposed to sticking with something like Kotlin just because its easy to pick up because it’s familiar). The benefits of learning the unfamiliar (in his case, he’s speaking specifically about Clojure) being that it allows you to write code that is much simpler to reason about.

I have no particular beef with Kotlin (or most any languages... right tool for the job and all), but I have lately become infatuated with Clojure and many of Rich’s viewpoints.

[1] https://www.infoq.com/presentations/Simple-Made-Easy/

Eh, I've used languages that were "hard to approach", one of my favorites (Erlang) is one of those (I use quotations especially because learning all of Erlang's syntax takes about a day).

This is a misapplication of the presentation really. It speaks to a level above selecting a language and is really about the design of systems.

Picking up Kotlin or Clojure is not "harder to approach" by virtue of what's provided in this context, it's harder because Clojure syntax uses parenthesis.

Like that's literally it.

Clojure with the same exact constructs represented with more C-like syntax would, at the level the presentation speaks to, allow the same level of simplicity.

I think a lot of developers feel "It looks funny" is not a fair critique of a useful tool, but just look at Erlang vs Elixr. I love Erlang, much more than I like Elixr, but Elixr gained mind share in large part because it's Ruby-like.

Cognitive overhead is lower working with a language that at least "looks like", what you're used to, and more developers know C-like languages, thus a language like Kotlin is "easier to approach" but necessarily "easier" in the way the presentation talks about

> Clojure with the same exact constructs represented with more C-like syntax would, at the level the presentation speaks to, allow the same level of simplicity.

I don't think this is true. I think it would be easier for "most people," but definitely not simpler. Easy meaning close at hand, simple meaning one strand, one braid, independent, less context necessary. Clojure syntax is the AST of the program, right there in front of you, in literal notation. There are fewer special cases, fewer moving parts interacting. C syntax requires spinning up a virtual machine in your mind and executing multiple statements. C is easier because we've already spent the time and effort to familiarize ourselves with it, but it has more complexity. Compare a 954 line ANTLR grammar for C [1] with a 261 line Clojure grammar [2].

> Cognitive overhead is lower working with a language that at least "looks like", what you're used to, and more developers know C-like languages, thus a language like Kotlin is "easier to approach" but necessarily "easier" in the way the presentation talks about.

I would agree, using Rich's definitions of simple and easy, that Kotlin is easier for the majority of developers than Clojure. This follows immediately from the definition of easy.

> This is a misapplication of the presentation really. It speaks to a level above selecting a language and is really about the design of systems.

I would recommend Rich Hickey's talk "The Language of the System" [3]. The programming language(s) used are part(s) of the system and have an effect on its design. I don't think this is a misapplication of the "Simple made Easy" presentation, I think it hits the nail on the head.

[1] https://github.com/antlr/grammars-v4/blob/master/c/C.g4 [2] https://github.com/antlr/grammars-v4/blob/master/clojure/Clo... [3] https://www.youtube.com/watch?v=ROor6_NGIWU

I feel like this comment is throwing semantics in a blender and pouring it out into the shape you want... but I guess that's the thing about arguing semantics, it usually devolves to that...

So I guess I'll just keep my recommendation to Kotlin and you can keep your recommendation to Clojure

> I feel like this comment is throwing semantics in a blender and pouring it out into the shape you want

I don't think it is, though. But it is clear that you are arguing with absolute confidence about a thing you have never given a heartfelt attempt to try first. You are debating like a medieval 13th-century mathematician that Roman numerals are elegant and more comfortable to understand, and people been using them for centuries and no need for this Indo-Arabian numeral non-sense that Leonardo, son of Bonacci so passionately keeps talking about.

I don't want to sound patronizing (I guess I'm already are, although not intentionally), but let me give you an advice - never trust your inner skepticism, fight it, dig for the answer - why are you so skeptical about it. Progress pushed forward by individuals who continuously challenge their beliefs. And from what I can see - you are not a mere consumer of progress, you too, do want to be at the front line where it is being made.

That is very, very far from the truth. You obviously haven't probably tried Clojure.

I think, among all the languages being actively used in the industry (in business, not academy), Clojure perhaps can be crowned as the simplest of them all. The ingenious of Rich Hickey was to design it the way that the essentials were made simple and complicated stuff either unnecessary or pushed onto the edges of the ecosystem.

Clojure can be learned à la carte - from the basics to more advanced things. Or if you want to dive straight into more difficult topics, you still can do it, and preliminaries would be minimal.

I can argue that Clojure is easier to learn than Kotlin, Python, Javascript, or Ruby. That is not a mere opinion - I know many people for whom Clojure was the very first language. And they tried to apprehend other PLs later, and it was a confusing and frustrating experience for them.

It is easy to start with Clojure. One simply needs to be less skeptical about things that people (mostly those who are unfamiliar with the language) criticize it for:

- They say, "It is hosted on JVM. JVM means Java, and I hate Java", and therefore ignore the fact that JVM is a very robust piece of tech, and you don't need to write any Java at all to use Clojure, you don't even really need to know Java.

- They say, "JVM has a slow startup time." But once you try Clojure's REPL (which is a real REPL, unlike in other, non-lispy languages), it becomes a non-issue.

- They say, "It is a Lisp, and parentheses look scary." But once you learn structural editing idioms, it becomes so frustrating to deal with all the punctuation in other languages.

- They say, "It is dynamically typed." But once you learn Clojure.Spec you may discover that you can do things with it, that most type-systems simply can't.

I encourage everyone to try to learn some Clojure, because it is fun.

Ha, I've used Clojure, see my thoughts above in the other thread.

By the way, I love Java, love Kotlin even more. Don't bring the JVM and other languages down to Clojure's level just because Clojure is clutching onto the JVM's coattails.

I couldn't answer in the other thread because your reply got downvoted (and rightfully so) and went "dead." I get it. You personally hate Clojure. The reasons though objectively, are your own personal and nothing to do with the design of the language.

You felt that Clojure doesn't bring any value. Well, there are thousands of people who think differently, not just me. I have grown to distrust fanboys, and even more so, haters. If you hate a programming language that consistently being ranked among others at the top of "the most loved" category, there's something wrong with your assumptions about that language.

Please don't waste your energy trying to write another lengthy comment. Your argumentation is flawed, but I won't spend my time trying to prove you wrong because you wouldn't see the truth even if it hit you right between your eyes.

Clojure notoriously known for attracting older, experienced, "grumpy" developers. Programmers with years of experience and seasoned in many other languages, because it simplifies many things. "Out of the Tar Pit" - as the phrase and as the widely known paper, accurately characterizes principles that Clojure has built on. And If your only take on the language (I quote your own words), is: "Clojure is a garbage language," then I guess I misjudged your programming experience level. Maybe you haven't struggled enough with other PLs to the point that it gets so tiresome you start thinking about retirement.

Please, how long of a response is there to a comment that boils down to:

"I have no concrete rebuttal so I'm going to refute your objective points about it's shortcomings with nonsense about retirement age programmers and whining you weren't nice while systematically listing all the things wrong with it and all the alternatives beat it at it's own game"

Java and Kotlin and Erlang (again, literally my "pet favorite language" since, predictably you're going "lalalalala you just dont get simple languages lalalalal") are all languages known to be used by programmers to make useful stuff, at a success rate much much higher than Clojure.

In my opinion Erlang (and by extension Elixir) are functional-ish languages that are at their core very pragmatic about not being too _dorky_.

Kotlin for me. Val is immutable and they differentiate collections, i.e. list vs mutableList. This is still hampered by the JVM but it works.

Combine that with multi platform productivity. If you do want to get dorkier there are fully functional libraries.

What is 'dorky' WRT functional programming?

Offhand, I’d say “too much theoretical math in the starting and middle stages of mastering the language.” Syntax that is based around/descended from APL. Lambda calculus prominently featured in the learning process. Things like that.

It’s definitely a feel argument, and thus highly subjective.

I'm not a FP expert, but I do try to use FP as much as possible and yes, I agree that there is some serious dorkiness possible with certain PLs.

Anecdote, not data, but I've found that Rust, Erlang, and F# (if MS stack) tend to be in the sweet spot of expressive enough without drowning in symbols, without being as mushy as, say, Python/Ruby/pick something.

Julia is pretty good at this. Immutability is the default with functional composition. It is primarily intended for numerics though.

JS with React is great if you use an immutable data structures library and compose functions.

ES6 and newer JS is a great functional language.

That said, I do not recommend immutable libraries. Here are the reasons:

1. They provide false comfort. Nothing in JS is truly immutable. People are just going to end up breaking the rules (purposely or inadvertently).

2. Boxing and unboxing regular JS objects becomes a pain in the ass and a maintenance horror show. You'll never know what an object is and you'll have to jump through countless hoops to get plain old JS objects to do anything with anyway.

Much better is to educate developers, and make sure code is properly reviewed before merging. Immutability doesn't need to be built into the language. Code customs and practices can go a long way.

Scala / Dotty, or its smaller brothers like Kotlin or Swift




> ... composition of functions operating on immutable data structures is just the right way to go

Yeah. No. Maybe. The cost of immutability can be high. Immutability can be very elegant when it's right, but mutability can be clearer other times. As another respondent said, there's no silver bullet. There's no 'right way to go'; as ever it depends.

> The cost of immutability can be high

If you analyze expenses for software projects of 1960-80ies and compare them with recent years, you probably see that the most expensive item now is at the bottom. The most costly thing used to be hardware. The not so expensive - developer's time. Now it's the opposite - the equipment is cheap, and the software developer's salary is the most expensive thing. Of course, that does not apply to every single case, but for the majority of projects, that is true.

Immutability by default (baked into the language), offers enormous benefits, and increases programmer's productivity, it simplifies many things, especially concurrency and parallelism. Languages like Erlang and Clojure are good examples. The price you are talking about does matter. But very often, the benefits outweigh the small cost.

Nice reply, thanks. I fully understand the benefits and we agree then, except possibly for the issue of the cost.

I haven't checked the value of eg. for{} in scala vs a mutable/procedural loop, but I wouldn't be surprised if it was an order of magnitude or two different. Figures are needed, and I don't have them (nor the time to benchmark them now, simple though it is).

Please note that the article merely encourages the application of some of the best practices introduced by functional programming - strong typing and more mindfulness around mutability and side effects - into all forms of programming.

Functional programming as it exists today takes these ideas to a somewhat extreme form. That has its place and value, but as experience in the real world shows, as long as it feels so mathematical, it isn't everybody's cup of tea. Hopefully, over time we find more intuitively accessible abstractions for the really useful principles that functional programming is based on.

> as long as it feels so mathematical, it isn't everybody's cup of tea.

Languages like Elm, Elixir and Clojure don't feel "so mathematical".

>I think we should probably just get it over with and accept that composition of functions operating on immutable data structures is just the right way to go.

It can provide an incremental improvement but it is https://en.wikipedia.org/wiki/No_Silver_Bullet

> Error: ENOENT, no such file or directory '~/foorc'

I can’t count how many times I’ve seen error messages that look like this, often with no context at all, in JavaScript apps, even widely used ones like npm and webpack. Proper error handling is never easy, but the JS community seems particularly given to avoiding it.

Complexity is combinatorial. If you compose your code of overly complex components the end result will have much more emergent behavior.

If everything at the bottom is straightforward, then people will spot more overarching concerns, instead of bogging down in minor details.

I’d really love to see some cognitive science applied directly to UX and code quality concepts. Surely some of the things we espouse but don’t enforce are spot on, and others are cargo culting. Refining that list might make it harder to ignore.

can author of that medium post show real world example of an app, build with those principles and rules from start to end?

it would be also very educational to see decision and design process of an app build with those rules.

I couldn’t agree more.

Also; keep it clean. Don’t over-comment, but comment.

Yes, please comment! I was once on a project where commenting was prohibited presumbely because your code should be self explanatory? Give me a break.

Comments are often a code smell indicating that the code was written in a hard to understand way. On a top notch code base - the kind that almost nobody works on - they probably should be sparse and mostly unnecessary.

Moreover, when a lot of people are asked to comment they write stuff like "this function does x to y" when the function is named "x_to_y". No shit sherlock comments I call them.

I'd always prefer to have good comments, but I've worked on a lot of code bases where no comments wouldn't really have been any worse.

Comments are critical for explaining the code that isn't there. I'm skeptical about "sparse".

I'm not sure what you mean. Comments are for explaining code that IS there.

"This looks like a good case for a binary tree but it doesn't scale well under load."

"We would add support for this motherboard that looks a lot like the one we do support, but it doesn't offer feature X."

"We want to add more detailed logs here but we haven't figured out how to cope with the performance hit."

Closely related, comments are also useful for explaining why code that looks wrong/poorly optimized/obsolete isn't actually, which is something that the code itself can't explain.

comments shouldn't explain code period; they are to clarify intent.

Comments are there to clarify whatever is not easily understood in the code. If that's intent, sure, it's intent that should be commented.

It's not always the intent that needs clarification.

Check out the CPython code base sometime, as an example of a top notch code base. Are the comments sparse?

Depends on the area of the code you look at, but they can be fairly sparse, yes:


I'd say that redis is probably a better example of gold standard clean C code, though, and they follow the rule of "don't comment unless it's decidedly non-obvious" pretty assiduously:


Those two files do have a low ratio of comments. However a large number of files in those code bases have quite a lot more comments... I personally don't think these two code bases have sparse comments, overall, although perhaps it's subjective or my bias is affecting my judgement :)

Eg, to me this is well-commented and I wouldn't call it sparse.


Good readable code has very few comments.

Writing good readable code is hard, and you don't get it just by banning comments.

Much like how you don't lose weight by buying smaller sized clothes :)

I would much rather be on a project where commenting is prohibited then where it is mandatory, e.g., the senseless babbling that goes along with javadoc/doxygen/PEP-8-like comments. That is such absolute garbage. At some point it even becomes hard to spot the code in between the garbage. Yes, even with syntax highlighting....

Write a docstring for a function before you write the body of that function. Keep it short. Don't overthink it. At this point, it doesn't even have to be syntactically correct.

If, in a brief sentence, written in plain English (or any other language of your choice), you can't explain the idea, you need to "go back to the drawing board." Resist the urge writing it in a programming language before you can explain it in English.

When you're done writing the function, go back to the docstring, revise it; in some cases, you can even remove it.

The purpose of a docstring is to help humans to quickly scan the code and discern the meaning, the idea of the function without having to read its source. Like a trailer for a movie - it should give you the general idea, but not give away the implementation details.

Think about docstrings as "type annotations" for humans. We use types and type hints "to help the compiler understand our code better" because computers do not understand plain English, but very often, we have no empathy for fellow programmers.

Comment the why, not the what.

It's good to comment the what too if it's hard to discern what it's doing from the code.

There have been a number of cases where, for instance, I had to call a bizarrely named API and do something unexpected in order to get an unintuitive outcome and in that case a "what" comment isn't such a bad idea.

Comment the intentions and motivations for behavior.

Can you define "over-comment"? Without a clear definition, it's just subjective opinion.

(not OP, but here's my 2c) comments should explain why you choose to write the corresponding line of code. It's a "meta-communication" between the original author (even a previous-month you) and the reader. Code reading should be "boring". The code lines (and so the meaning) should be obvious. A good comment, IMHO, should convey the information "I'm sorry for this complexity here, but you need to take care of this edge case..."

That's a reasonable attempt at defining what over-commenting is by trying to define what it isn't. However, it's not a very subjective definition. I tend to write fairly long comments anywhere I think it might help me in the future. I can't predict what I'll forget. I can't predict what will help me understand my code in the future. I have almost never looked at a comment and wished that someone would have written less (aside from comments that just mimic the code, e.g. "increment x"). It's almost always the opposite. I almost always wish I (or the other dev) had left more information.

Literate programming comes to mind as an extreme counter example of not enough comments. https://en.wikipedia.org/wiki/Donald_Knuth#Literate_programm...


The beginnings of functions, for instance, are great places to comment, perhaps even including a definition of some of the subroutines within it.

In the case of an exceptionally large subroutine, commenting within the subroutine may be advantageous - but at that point you may consider another function to replace that larger chunk.

Variable names that are perhaps obscure and are not practical to rename for whatever reason can also use comments.

Class headers are of course also a great place to comment, to explain the purpose of the class.

Good comments can lead to better code. :)

You didn't really answer my question though. I didn't ask where you should comment. I asked for an objective definition of what over-commenting would be.

> I asked for an objective definition of what over-commenting would be.

I don't think what you're asking for is possible. It's an inherently subjective standard.

If an objective definition were possible, then it'd be possible to write a static analysis tool that reads both your code and the comments and flags "over-commenting on line 23, under-commenting on line 457". That could be done with sufficiently advanced AI, but at that point it would just be the subjective opinion of the tool's author being enforced.

over-commenting is explaining in pseudo-english what you've written in code. Prentend you are at the United Nations but you speak all the langauges, so you don't need a word-for-word translation. You don't understand to motivations of every speaker though, nor their cultural influences and a million other factors, so context is super important. In the briefings you get some of the information is not new; but if the vast majority of what you're told is obvious or discernable from what people say, you're looking at over commenting. It's not a yes-no thing but a balance of evidence, subjective opinion.

JSDoc. It's a fucking tragedy on code bases.

I've seen it happen many times now. A nice, clean, easy-to-read code base turns into a forest of unreadable shit thanks to the introduction of parsed comment tags. Perl, Ruby, Python, JS. Doesn't matter what tool or language.

Please, people. I beg you. Stop putting this shit in code. Not everyone is using the same bloated IDE as you, nor do we care to maintain your silly block text and parameter text that is outdated the day you wrote it. If your function needs a block text to explain how to use it, you need to find a new job. I'm serious. You're not good at your job. If it's not self-evident what the file you're looking at does and the function within the file does, then refactor it. Cut it down. Make it make sense.

I've seen code in which the development team added a revision comment in the source file for every revision to the source file, instead of just letting the version control system handle it.

Some of it is an art, and thereby subjective opinion.

Nothing wrong with that!

  //increment i in for loop
  For (i=0;i++....

  Var x; //define variable x

  X=4; //give value of 4 to x
Everyone knows what that code does. The comments aren't necessary.

That's a good concrete example of bad comments. I suppose you could throw that in the "over-commenting" category.

And, strangely, it's the only response to the gp's request to define of over-commenting, yet it is downvoted to below definitions of good commenting.

So. Weird. The other responses didn't properly implement the requirement specification.

I am so confused.

This is what I’m saying by over-commenting. I stated comments at the beginning of functions - what are the arguments? - what does it return - or at the beginning of class names are the wise go.

Yes it's an example of over commenting, which is exactly what the gp wanted.

This is instructive to new coders, on how NOT to comment.

That's what was asked for! Why on earth is the comment that properly delivers the expectation being discussed as though it's wrong?

I noticed the downvote and upvoted, plus acknowledged the anti-pattern. Sometimes intent is lost in text.

If you can't give clear advice on commenting, please don't give such advice.

But wait, I want all my code to work in linear space and time, look like assembly code and scale to 4 billion servers.

Please don't post unsubstantive comments here.

"Keep the story going. Sign up for an extra free read. You've completed your member preview for this month, but when you sign up for a free Medium account, you get one more story."

Sorry, can't read behind paywall.

Agreed, sorry for the paywall. Is there a better place to post such stories than Medium?

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact