WebAssembly without the browser - <AUTHOR> https://alexene.dev/2020/08/17/webassembly-without-the-browser-part-1.html <comment><USER2> Author of wasmex[1] here (an elixir package which allows runnung WASM).

Next to the mentioned wasmtime, wasm3, and wamr, there is also wasmer[2] I would add to the list of capable WASM runtimes.

The great things these runtimes offer are how easy they are to integrate into other programming languages environments. E.g. with wasmex you could easily run WASM from your elixir application (or with wasmer from ruby[3] or many other languages if you want).

Imagine building shopify, but without needing to invent your own template language for customers to extend their shop-template[4]. They could provide a WASM extension API where shop-owners could let sandboxed WASM files render their shop. This would let allow shop-owners to write templates in their favorite language instead of e.g. liquid and still be secure.

[1] [https://github.com/tessi/wasmex/](https://github.com/tessi/wasmex/) [2] [https://github.com/wasmerio/wasmer](https://github.com/wasmerio/wasmer) [3] [https://rubygems.org/gems/wasmer](https://rubygems.org/gems/wasmer) [4] [https://github.com/Shopify/liquid](https://github.com/Shopify/liquid)

</comment><comment><USER3> One area that I'm hoping WebAssembly will help with is running native extensions in a portable sandbox. That way libraries like nokogiri can be compiled to wasm ahead of time, then executed on a wasm runtime. There will be a perf hit but not having to wait for nokogiri to compile native extensions will be worth it.

<comment><USER4> I think the ability to run unknown code in a sandbox is probably the most interesting use case. This is particularly compelling in P2P computing projects.

<comment><USER5> I am really hoping the mobile platforms like iOS offer pure wasm sandbox APIs for this use case. This could be a powerful way to support programmability, app extensions, etc outside of the appstore. It could appease both Apple for security and developers for flexibility.

<comment><USER6> What is the advantage of wasm sandbox over the native sandbox?

<comment><USER7> proponents of wasm claim that the wasm sandbox was designed with security in mind from the very start. From apple point of view they could offer a runtime with very specific and limited permissions and trust that the plug-ins will respect them.

</comment></comment></comment></comment></comment><comment><USER8> Interested to see a number of people mention one of the attractions with WebAssembly being the sandbox &customisation angles.

Sandboxed in-game avatar customisation was one of the motivations behind the "WebAssembly Calling Card" (WACC) project I released within the past couple of weeks, posted a Show HN here: [https://news.ycombinator.com/item?id=24072304](https://news.ycombinator.com/item?id=24072304)

"WACC: Like an avatar but WASM!"

The WACC specification defines how three 32-bit ints (returned via 3 calls to a function in a WASM module) get turned into triangles:

* 256x256 coord system.

* 15 bit color + 1 bit alpha per vertex triangles.

* 1 FPS!

In part, WACC & the WACC Viewer app is a demonstration of a WIP add-on for the Godot game engine that wraps the libwasmtime WebAssembly runtime so desktop Godot games/apps can call functions in WebAssembly modules. (The other demo app is a tool to help explore `.wasm` files: [https://gitlab.com/RancidBacon/wasm- exploder](https://gitlab.com/RancidBacon/wasm-exploder))

The other main goal with WACC is to provide more visually interesting "first run" experiences for people embedding WASM runtimes and/or provide a creative outlet for starting to play around with generating/writing WebAssembly.

So, if you're interested in playing around with some non-browser WASM you might like to have a play with WACC--maybe implement the spec for a different host or create your own Calling Card. (I would particularly like to see it running on standalone hardware like a badge or similar.)

Main site here: [https://wacc.rancidbacon.com/](https://wacc.rancidbacon.com/)

</comment><comment><USER9> > _This is powerful because you [can] use Rust or C++ as your scripting > language._

Do people really want to use such complex, heavyweight languages for scripting?

> _WebAssembly enables predictable and stable performance because it doesn't > require garbage collection like the usual options (LUA /JavaScript)._

Do garbage collection pauses cause significant issues when embedding Lua or JavaScript? If so, I would expect implementations of those languages to switch to reference counting, but none of them are doing so.

> _Extremely fast programs in environments where you can't JIT for reasons._

To get good performance, don't WebAssembly implementations need to use JIT- compilation internally?

<comment><USER10> > Do people really want to use such complex, heavyweight languages for > scripting?

This is a surprising reaction to me, given the history of Javascript and NodeJS in general, but you're not the only person I've seen bring this up.

Ask yourself, 'do people want to use such a strange, high-level language as Javascript for programming servers?' Of course they do, because the primary factor in choosing a language isn't whether or not it's perfectly suited for a specific task, it's how familiar you are with it and how much tooling you already have built up and available around it.

Being able to program your back-end and front-end in the same language is a _massive_ productivity win. It allows you to do all kinds of cool things with architecture and code reuse, and most importantly you don't need to switch mental contexts as often while you're programming.

So if it was reasonable for JS devs to bring their scripting language to the server, it is just as reasonable for Rust/C++ devs to want to bring their server language to the browser. It's not about the language semantics; if someone is primarily familiar with Rust then they'll be faster building web apps in Rust than they would be in Javascript.

</comment></comment><comment><USER11> This seems to me like WebAssembly works basically like Java, but the bytecode can be compiled to from multiple languages.

Is this correct?

<comment><USER12> It is like Java bytecode, but design geared more towards supporting C.

Wasm in many ways is dumb. They could have easily adopted CLR or JVM bytecode. But no, the web is too "cool" for that. It's better to have a brand new VM that's slower and missing GC and a standard library.

<comment><USER10> > missing GC and a standard library.

Many of us consider these points to be features. We don't want a runtime that's as complicated as CLR or JVM bytecode.

<comment><USER12> Any popular VM inevitably becomes as complex as those. Look at V8, it's grown into a JVM sized beast.

It would save countless hours of human effort to just adapt what's out there. It will be a decade before WASM has the kind of support JVM and CLR do. By then it will have the same huge codebase that causes vulnerabilities

</comment></comment></comment></comment><comment><USER13> I doubt that WASM is good as an embedded language, unless performance requirements outweigh the inconvenience.

Dynamic languages are great for experimentation and exploring the system, e.g. a console in the browser is the fantastic tool and web dev people tend to try things there first. By embedding wasm, you are making tinkering with the system you provide less enjoyable for your users.

One could argue that since many languages compile to wasm, you can pick whichever suites you best. But in reality, you are probably limited to languages with thin runtimes, e.g. Rust or C. Otherwise you will end up with a huge wasm blob. Imagine, there are 2 Java extensions, a C# one and something in Python, all running simultaneously. It means 3 different runtimes with a footprint by far exceeding that of the application logic in an extension.

Another burden is the bridging between the host and an extension. Unlike lua or js you can't pass and inspect objects, the only option is to marshal data as a byte blob. So if you were to pick up a language no one used to write extensions for the particular application before, the very first think you have to do is writing marshalers.

Last but not least, I disagree with the article calling S-expressions ugly and strongly believe in the opposite.

<comment><USER14> IMHO WASM is the perfect replacement for native plugin DLLs for DCC tools like Maya or Photoshop (but not a replacement for a scripting interface which such applications usually offer too in addition to DLL plugins).

Instead of having to distribute a multitude of DLLs for each OS/CPU combination, you only distribute a single WASM module, and the WASM runtime that's integrated into the DCC tool takes care of the platform-specific details. And WASM is also easier to sandbox than DLLs, so a crash in the WASM plugin can't take down the entire application.

<comment><USER15> IMO in this regard WASM is pretty much the same as Java/C# except slower and less mature.

In Java, distributing libraries as cross-platform "jars" is very common.

</comment></comment></comment><comment><USER16> > WebAssembly enables predictable and stable performance because it doesn't > require garbage collection like the usual options (LUA/JavaScript).

GC is a small part of that - the much bigger factor is dynamic optimization is necessary for fast Lua or JavaScript. Wasm is designed to not need that (like most languages that are not dynamically typed).

<comment><USER17> Some wasm runtimes, eg V8 and Spider monkey, do tiered compilation, where all code is first compiled with a high throughput streaming compiler, and then only the hot paths get recompiled with an optimizing compiler.

<comment><USER16> True, good point!

Tiered compilation in general does dynamic optimizations, definitely in JavaScript (runtime type collection, etc.) but also to a lesser extent in C# or Java (inlining, etc.). In wasm none of the tiers do dynamic optimizations AFAIK, but tiered compilation definitely helps there too, mostly with startup times.

</comment></comment></comment><comment><USER18> I'm not sure I understand the use case of the author. He mentions languages (Rust, C++ etc) that can be natively compiled to (almost) any platform, so what's the point of running them in web assembly ? Like Java write once run everywhere ?

<comment><USER19> My speculation: WASM will be used as default for edge computing and further cloud based containers. Cloud vendors will develop custom silicon optimized for WASM that won't be available for general public, maybe on ARM or RISC-V.

<comment><USER20> > custom silicon optimized for WASM

I doubt it. Like Java, WASM is intended to be used with an optimising JIT compiler. It doesn't make sense to try to implement Java or WASM directly in hardware.

ARM used to offer _Jazelle_ , which could run Java bytecode directly on the CPU. It's now long dead. It makes more sense to use a sophisticated optimising JIT to produce efficient machine-code, than to make hardware to directly run an unoptimised IR.

<comment><USER19> I'm sure it is already in the works. WASM is the key to be independent of the ISA and allows to switch to custom silicon without having the customers to know. That's how cloud vendors will drive the future in the race to get independent from x86 and ARM (very likely that a future owner of ARM will limit the licensing business). So even if there is no performance gain possible due to the reasons you have pointed out, it's probably the abstraction layer of the future for pretty much everything.

<comment><USER20> > I'm sure it is already in the works.

Why? As I just said, this kind of hardware approach doesn't make technical sense.

> WASM is the key to be independent of the ISA and allows to switch to custom > silicon without having the customers to know.

We already have ISA-independence with JavaScript, Java bytecode, .Net, Python, and other high-level languages.

Again, WASM isn't intended for direct execution on hardware, it's intended to be fed to an optimising JIT compiler. Direct execution on hardware isn't how you get good performance out of an IR like this.

> That's how cloud vendors will drive the future in the race to get > independent from x86 and ARM

I don't think cloud vendors care all that much who they buy their CPUs from. AWS offer instances on Intel, AMD, and ARM CPUs. If they really want ISA- freedom, their best bet is RISC-V.

> even if there is no performance gain possible due to the reasons you have > pointed out, it's probably the abstraction layer of the future for pretty > much everything.

There will never be a single abstraction layer for everything. Compiler engineering doesn't work that way.

</comment></comment></comment></comment></comment><comment><USER21> Without proper security audits on wasms runtimes they can only be used as hypothetical tools. The main purpose of wasm is a sandbox that's well defined, but that doesn't matter if it's implimentations are vulnerable.

You could use it to just "deploy software anywhere", and that's a neat idea, but it's not 'web' assembly, there's no protections thst make it fit to run arbitrary code from the web.

</comment><comment><USER22> There's a working proof of concept of WASM as a scripting foundation in a WIP programming game called Robot Rumble:

[https://github.com/robot-rumble](https://github.com/robot-rumble) [https://rr-docs.readthedocs.io/en/latest/technical-details.h...](https://rr- docs.readthedocs.io/en/latest/technical-details.html)

<comment><USER23> Are there screenshots or demos of what it's like to play? Their website is down and their docs don't really have any cool pics.

</comment></comment><comment><USER24> (shameless plug)

I gave a talk, about a year ago, covering history of the problem statements from which WASM was born and the various forms it is taking.

[https://labs.imaginea.com/talk-the-nuts-and-bolts-of- webasse...](https://labs.imaginea.com/talk-the-nuts-and-bolts-of-webassembly/)

Welcome thoughts/comments/corrections/additions.

<comment><AUTHOR> This is a really good article. I will include it in my reading materials at the end of the post :)

</comment></comment><comment><USER25> I found this writeup to be fairly well-written and detailed, but I lack the WebAssembly knowledge to comment on its other merits.

</comment><comment><USER26> I wish things like this could be used to break free from mobile app stores.

Download a virtual machine via the app store and then run any app written in any languages and compiled only once.

Almost like JAVA..

</comment><comment><USER27> Things like this is how we got NodeJS. Sigh.

<comment><USER28> I don't see how this is a problem. A lot of good came with the bad. This is like when people complain about Visual Basic or PHP. They were awful in so many ways, but they got a lot of people into programming, and those people did a lot of cool things.

</comment></comment><comment><USER29> If you are going to target WebAssembly outside of a browser environment, uh, why not just target LLVM, GNU, or uh, you know, Assembly... X86_64 or ARM are pretty standardized. Another part 1/1 "tutorial" with some brilliant insight as per usual.

<comment><USER30> LLVM bitcode is, I believe, not portable. Neither is Assembly. Nor are the resulting binaries of that processed something that is run within a sandbox.

<comment><USER31> This, i think webassembly is the sweet spot. It has portability but doesn't have any opinion about how the code should be structured. No opinion about GC or objects etc.

Works really really great with Rust.</comment></comment></comment>


Ask HN: What is your best advice for a developer to write better code? - <AUTHOR> <comment><USER3> When "better" means "fewest bugs":

1) Use the best language you can get away with. This means using a language that eliminates entire classes of run-time errors via some or all of:

      a) Strong typing

      b) Static typing

      c) Managed memory

      d) Immutable data

2) Assume that your code will be maintained by somebody who doesn't know your programming language as well as you do.

3) Use static and dynamic assertions liberally.

4) Ease debugging. Have great formatted dumps of your internal data structures, great internal consistency checking, and great logging. Automate problem isolation, too: for example, in an optimizing compiler, at each point where a discretionary change is about to be made, call a function that logs the change, increments a counter, and returns false if the counter is past a limit that you can set in the environment; this allows an automated bisection analysis to immediately find the change that broke a test program.

5) Regression tests. Once you fix a bug, make sure that your test suite will notice recrudescence.

6) Don't hire or retain sloppy programmers.

<comment><USER4> Point 6. freaks me out, because I am not sure if I am one of them.

Also, your first three points puts Ruby pretty much out of the picture.

EDIT: Mentioned Ruby because that's what I am working on right now, after Java and Scala

<comment><USER5> You probably are not sloppy, because you are worried about being sloppy. The sloppy programmers are the ones that don't care about being sloppy. If you're conscientious, you have a huge leg up on a lot of other programmers.

<comment><USER6> Since 'sloppy' is going to be defined differently by basically everyone, this isn't true.

That someone is worried about being sloppy really only lets you assume they don't write code they consider sloppy.

<comment><USER7> Not even that. They could believe that they are in a job where they are expected to move at a pace that implies sloppy code.

Of course, that will actually mean they move much more slowly due to bug fixes, but a junior dev in an environment without a good senior dev can easily fall to the "quick and dirty" fallacy.

</comment></comment></comment></comment></comment><comment><USER8> After 25 years of programming I'll give you the lesson my first boss gave me: "Think more, type less".

It's stood the test of time, I've passed it on to many juniors.

<comment><USER9> "Weeks of programming can save hours of planning" is a favorite quote of mine.

<comment><USER10> While this is true, the opposite can also be true. That's called "Analysis Paralysis".

<comment><USER11> Most of the time analysis paralysis is a signal that you lack sufficient understanding of the needs to actually write the right code. There are two ways to break out of it: (1) understand the problem better, and (2) build something, anything, see why it wouldn't work, and then go back to the drawing board.

</comment></comment></comment></comment><comment><USER12> My rules for good code:

1) Always write code for someone else. And you don't know who it is.

2) Write tests not only to prove correctness, but also to test whether code as an interface makes sense.

3) Be defensive as much as possible. Each additional check / assertion helps to avoid accidental bugs or can help to find them early.

4) Speak about code as much as possible. If you can explain code in your own words and discuss it with someone else, code gets raised on a philosophical level and may end up to be elegant and logical for others.

5) RTFM & RTFS(pecs)!

<comment><USER13> I have to nitpick.

2) You can't prove correctness with tests. You can only state that it ran correctly for that test case(s).

<comment><USER14> "Proving correctness" is sort of windmill-tilting for today. Just don't despair of this :)

Good test vectors are a great investment, as are constraint checks and supporting instrumentation of said constraint checks.

<comment><USER13> I don't despair, because I know that to prove correctness of a program you need to use math.

For example proof assistants(like Coq, Agda, Idris, hol) are capable of proving correctness of a program.

</comment></comment></comment></comment><comment><USER15> Go read open source libraries. I started out barely knowing anything in Javascript and I had terrible code, as almost any dev could say. However, I was never afraid to follow the debugger through the code of the libraries I used. At the time these were things like Backbone and Marionette, which have incredibly clean and well documented code.

Find a library you use and have a feel for how it works, and read through their code. If you run into questions about why something is done a certain way, they'll tell you! Use git blame and see what the commit message was for those lines! Often there will be a description or issue tied to it and you can figure out the thought process they used. Then just start applying similar thinking to problems you encounter.

<comment><USER16> > Go read open source libraries.

That can be good, but some caution is required I believe. Most developers are writing programs to solve a fairly specific problem operating in a fairly specific domain in a fairly specific environment. They may choose a variety of programming styles to approach the problem (imperative, object oriented, functional, and so on). I'm going to call these kind of programs "normal" program.

Libraries are not normal programs. They are tools or components that are used by those writing normal programs. A good library tries to be accommodating to a wide variety of normal program styles, and tries not to impose too many constraints on how the library is used.

To achieve this, library coders often have to do things that would be poor style or poor design if done in a normal program.

<comment><USER17> This is an important point. Fully generalized, though, and we find idiosyncrasies in every application domain.

Maybe starting with a project like this would help? [https://github.com/aosabook/500lines](https://github.com/aosabook/500lines)

</comment></comment></comment><comment><USER18> Don't get cute. Code golf is for competitions, not production code. Even if something takes 10 lines that you can do in 1, if 10 lines is clearer, do it that way (you'll thank yourself in 6 months when you have to figure out what you were doing).

Keep your functions to one or two pages.

Keep your nesting to three levels, preferably two. If you have multiple nested if/while/for sections, break them up. (See: "cyclomatic complexity").

Follow the coding conventions of the project you're working on, even if you disagree with them, consistency is more important.

<comment><USER16> > Don't get cute. Code golf is for competitions, not production code. Even if > something takes 10 lines that you can do in 1, if 10 lines is clearer, do it > that way (you'll thank yourself in 6 months when you have to figure out what > you were doing).

Brian Kernighan put it well: "Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?"

<comment><USER19> The other bit I know, besides this one, is to write comments stating what you're trying to achieve, and why. The how is redundant, but sample data right there may help.

(Someone famously pleaded for documenting the data structures, and leaving aside the processing mechanics.)

</comment></comment></comment><comment><USER20> I see study open source code and read good code, but what I think is more effective is contribute more to open source. Coding is one of the few professions in the world where some of the leading experts give away great samples and advice on a regular basis in the form of open source. Start an open source project for a need you have or submit a PR for something you've always wanted in a project you've used. Generally the comments on PR's are a great place to learn about ways people think through problems and how they're implemented.

My best piece of advice if you take this road though is that you need to check your ego at the door. The only way to truly learn to be better is to take criticism learn from it and keep moving forward.

Don't be afraid to submit PR's because of scrutiny because it will only prevent you from learning.

In my experience as a dev the solutions that you think are so simple and maybe even hacky sometimes turn out to be just steps away from a far more elegant solution than anyone else has thought of and you're hurting yourself and in many cases others by not sharing or by being too timid to share and willing to open yourself up and put yourself out there

</comment><comment><USER21> 0/ Work with other developers, ideally next to them, on the same project. Learn from them no matter you think them "good" or "bad".

1/ When given the choice between making something exist and making it not exist, lean toward the latter. ie. Minimize Everything. Remove everything that can be. Things must earn their right to exist.

2/ Choose the best names you can come up with. If you can't find a good name for something, there is a chance it shouldn't exist. There are books about this.

3/ Code should enable things, not be a problem itself. Make it the easiest to maintain and understand above all other criterion. Code like you have an audience that will be reading that code while not really caring regardless. You can't expect the maintainer to care as much as the writer, it would be impolite to do so.

4/ Think a lot about what things should be splitted in two concepts, and what concepts should be merged into one. Iterate designs until they seem impossible to enhance. If it feels wrong it is probably wrong.

5/ Recognize your weak parts and improve them, not only those that are good already.

6/ Don't confuse input errors and bugs.

7/ Create the right abstractions if necessary and at the right level. Lean toward "no abstraction" if you're unsure of the best design yet.

8/ Forget everything systematically. If you need to remember something, find a way not to have to. You need all your neurons to learn new things constantly.

9/ For the hasty: work on legacy systems. This is the "hardcore difficulty" level of programming. Do some parsers.

10/ Don't give a name and reify everything, in fear it would become a topic of mental activity. Example: since users will report the biggest problems the most, maybe there is no need to record every last user wish. If a task is faster than to record it in the todo-list, make it right away, etc.

<comment><USER22> I like 10. Massive backlogs of shit you won't do are pointless.

<comment><USER21> I use sub-TODO lists with thematic stuff (ie. freelancing-related, related to this or that product, etc). Then I get to not see it which is really helpful. A good TODO list doesn't have too many stuff in it, so why not hide parts of it. Then each day wake up and think "I'll do all that very doable backlog today".

</comment></comment></comment><comment><USER23> Less is more -- Keep the lines of code down to a minimum in a single function/method. Its name should say what it does and it should only do that one thing. Also, you should always look for code to remove/refactor to minimize its function to singular actions.

Avoid complex statements or crazy one liners when it would be better understood by 80% of developers if you just put it in a simple if statement or broke it up into 2-3 lines. Break up algorithms this way with good comments too.

Experiment with small pieces of code before committing to a specific design if you are unsure. I have quite a bit of experience and will still write small test programs all the time to test out an idea before I try it in my main code base. This lets me make sure I got my idea (and implementation) correct in the simplest form before trying to put it into a larger more complex codebase.

Don't start optimizing in places you don't know you have an issue. Write it out like you want first, then optimize later when you find it is an issue.

Don't try to "future proof" your code, no one can predict the future and writing extra code to handle what might happen is basically torture, both to yourself and the person that has to remove it all later cause your assumptions were wrong. Not to mention, this is where I find the most errors in code.

Learn data structures well, and use them properly. It drives me nuts to see how badly people abuse data structures and misunderstand their benefits and drawbacks. But see my last point too.

My personal pet peeve, don't assume the person before you did it wrong or was an idiot until you can prove it. Generally devs do something, even if it is not ideal, for a reason. Be it, business changing requirements at the last minute, or schedule crunch or a lack of domain knowledge. But before you call them an idiot or assume they were wrong, try to figure out what they did and understand why they might have done it. I have seen a lot of code get changed by new comers only to find out it was written that way for a specific use case that they just didn't understand yet. Then shit breaks, people get upset and the whole team gets frustrated.

<comment><USER24> I agree with you on the last point. Humility and assuming best intentions works very well in all settings, but especially in legacy code. I withhold judgement on everything I see now. It took a bit of time and a few instances of eating crow to get there.

<comment><USER23> Yea, totally ate my share too. For me, I also had an interesting lesson where I returned to a company like 10 years after having been there prior. I picked up some code to fix a defect and was frustrated by it, only to realize I was the "moron" that wrote it prior.

</comment></comment></comment><comment><USER25> Think really hard about the problem you are solving.

First question to ask is always: Do I need to write some code or I can solve this problem using tools already here?

If you decide to write code, then start to think really hard.

What interface should I provide? The smallest the interface the better; and be aware that any kind of configuration your interface use increase exponentially the size of the interface itself.

Now you should experiment, take your time and be sure that the interface you are providing is the smallest possible, try to see the problem from another point of view, don't be afraid to throw away code (don't write test yet if not for experimental purpose, you don't even have the interface to test) and try to keep everything stateless and pure.

During this process is important to gather feedback from your peers, they may see problem that you don't.

Once you have decided what you are going to code, write it down.

Try to keep everything so simple that test will seems pointless, write those anyway.

Be slow, take your time for thinking, don't be afraid to throw code away.

<comment><USER26> > Think really hard about the problem you are solving.

This is really good advice. Also think really hard about what is the real problem you are trying to solve and only write code to solve that problem.

The oxymoron is the best code you write is the code that you did not write.

<comment><USER27> > Think really hard about the problem you are solving.

How do you know you have thought hard enough?

<comment><USER28> This would be a good SO question.

<comment><USER29> It would be closed for being off-topic ;)

</comment></comment></comment></comment></comment><comment><USER30> Deliver real, end-to-end working functionality, at least every two weeks and ideally more frequently. Unless and until the code is used it's all meaningless. This more than anything will protect you from overengineering or building the wrong thing, which are the biggest dangers.

Delay design decisions as late as possible. Unless and until you need to make a decision to allow you to deliver some real functionality, don't make it. Avoid any planning of things like code structure. This will give you the chance to make better decisions, since you'll have more knowledge at the point when you make them.

Reduce the number of lines of code. People will say that other things are more important, that making the code longer can sometimes make it more readable. That's an intuitive view, but in my experience it's wrong. Reduce the number of lines of code, and everything else - good design, good code structure, good language choice - will follow.

<comment><USER31> Not writing code until it was _absolutely_ needed would have saved literally months of my working life, and I haven't been working all that long. Business requirements change constantly, so what you think will be needed probably won't be by the time you ship the code.

Continuously refactor your code to remove duplication (See Don't Repeat Yourself / DRY). If you find yourself copying and pasting boilerplate code over and over, it's probably time to refactor, otherwise you find one bug and have to fix it 20 times. Good testing helps you to refactor fearlessly because the tests will tell you if you screw up.

Whatever happens you'll always cringe reading old code - but see the positive, it just shows that learning is a continuous process and that you are now older and hopefully wiser than you once were.

One thing that's been on my mind lately is an old article by Joel Spolsky [1] about accurate estimating. I'm absolutely terrible at estimating but I'm using Joel's method to improve that. Better estimates mean better code. Why? Because if you estimate 1 day for a task that really takes 2 days, you'll be rushing, stressed and tempted to cut corners by the start of day 2. If you've planned 2 days for it, you can use the time more effectively.

[1] [http://www.joelonsoftware.com/items/2007/10/26.html](http://www.joelonsoftware.com/items/2007/10/26.html)

<comment><USER30> > One thing that's been on my mind lately is an old article by Joel Spolsky > [1] about accurate estimating. I'm absolutely terrible at estimating but I'm > using Joel's method to improve that. Better estimates mean better code. Why? > Because if you estimate 1 day for a task that really takes 2 days, you'll be > rushing, stressed and tempted to cut corners by the start of day 2. If > you've planned 2 days for it, you can use the time more effectively.

Only if you were using that planning for something. Is the business value of that feature really so marginal that you want to do it if it takes 2 days but not if it takes 1? I find it's more useful to prioritize, limit work in progress, set a cap on how long any one task is allowed to take before you reassess, but explicit estimation isn't worth it.

</comment></comment></comment><comment><USER32> Become an excellent debugger. It's sorely neglected as a skill that goes along with development, but is not the same thing as being a good coder.

Read this book: [https://www.amazon.com/Debugging-Indispensable-Software- Hard...](https://www.amazon.com/Debugging-Indispensable-Software-Hardware- Problems/dp/0814474578/ref=sr_1_1?s=books&ie=UTF8&qid=1467224249&sr=1-1&keywords=debugging)

It's short and sweet and applies to any technology problem.

<comment><USER33> +1 to this.

</comment></comment><comment><USER34> Learn how to type well (>30wpm). Literally everything else is secondary. You don't have to be the fastest or most accurate typist, but not having to look at the keyboard while typing pretty quickly and accurately is foundational.

Not having to use the mouse for common tasks (closing a window, switching applications, etc...) is another core skill.

Everybody else's comments focus on important stuff but I've seen programmers absolutely hobbled by not having these basic skills.

<comment><USER35> I suggest reading Steve's post [0] on the touch typing and programmers.

[0]: [https://steve-yegge.blogspot.com/2008/09/programmings- dirtie...](https://steve-yegge.blogspot.com/2008/09/programmings-dirtiest- little-secret.html)

</comment></comment><comment><USER36> I'm still fairly green to the trade (1 yr in as a jr dev) but as best as I've been able to determine the best thing I have done is simply read a lot of code.

Reading code from people who are just getting started gives you perspective of how far you've come (hopefully). You can also use this to help people out fairly effectively.

Reading code from people who are more experienced is good for getting styles down while maintaining the context of where certain practices are acceptable.

Switching languages is also advantageous in that you can (hopefully) identify why different languages have different stylistic practices. This works better if the syntax of the language is pretty distinct - so C# to Java wouldn't be excellent at this. But C# to Python is great at it.

Of course writing code helps - especially if you can convince someone else to read that code and give some meaningful feedback!

</comment><comment><USER37> Read more good code and emulate after you fully understand it.

There are lots of projects that are good examples.

[https://news.ycombinator.com/item?id=4331688](https://news.ycombinator.com/item?id=4331688)

<comment><USER9> The problem is that good code isn't so obvious that it is good, its just kind of there and understandable (as it should be). Bad code on the other hand is obvious that its bad, as it takes you ages to understand what is going on.

<comment><USER38> Which is why I usually generalize this advice to "Read code". The majority of what you read should ideally be good code, but seeing both a good way and a bad way of doing the same thing is sometimes necessary.

</comment></comment></comment><comment><USER11> Stick around on a codebase that's used by real people.

Most of the lessons about programming I learned by designing and coding sets of features, shipping them, and then being the one handling all the bug reports and feature requests. Performance tuning, defensive coding, debugging technique, ui design, codebase architecture, developer team coordination, ... the list of things to be learned by sticking around for the long haul is endless and hard to replace with book smarts.

</comment><comment><USER39> My main two:

1) "Overview and Zoom" is a common UI technique where you give an overview and then let a user click on stuff for more detail. In programming, this means writing the "intention" as a method that's very easy to read, then have a bunch of helper functions with the details. This also forces you to only use one level of abstraction per method.

2) Only have one thing happen per line. This forces you to give what you're doing a proper name (as a variable assignment before you use it). This makes it easier to read, but makes all text processing tools work much better with your code. Nothing is more annoying than seeing a diff in a pull request where one line changes, but there are 10 things happening in that line and only one changed.

</comment><comment><USER40> Don't waste time trying to learn and develop style. Don't waste time studying other code just for the sake of learning how to write better code. Don't waste time reading generic things on how to write better code.

Put the effort in to learning new concepts, programming languages, methodologies, programming language history, computer science, and even broader subjects dealing with humans and how we think and form ideas. There are countless ways to write code and without having a broad knowledge of them you will only at best reach a local optimum and rarely choose the most effective solutions and designs. The worst thing you can do is stop learning and seeing other perspectives.

<comment><USER17> Which subjects would you recommend?

<comment><USER40> * Programming languages

* Software development methodologies, things like Mythical Man Month

* Computer Science history and basic theories and concepts

* Compiler implementation techniques.

* Anthropology and related subjects. Programs are written by people and for people so understanding people helps a lot.

The biggest thing is to approach things from all perspectives and an open mind. Learning programming languages of different types is great because the different language families highlight different techniques, concepts, and ways of thinking. No one approach or language is the perfect solution to everything. Try to aim for the largest perspective: functional, homioconic, machine like, pure OO, strict, lose, etc. You can look at the lineage of programming languages and what developed and derived from what and learn one from each group to get the broadest perspective.

Learning CS history and basic theories might not be directly applicable to your life but the knowledge that comes from it will show up in everything you do and knowing how to leverage it makes a big difference.

The value in learning about compilers, GCs, etc comes from being forced to learn, in depth, languages themselves and concepts behind them. If there was anything you didn't learn in depth in other areas they will probably show up here.

Everything you learn about programming and CS is ultimately dependent on humans and how we interact with computers. Understanding how we think will help you develop long lasting programs that are easier to understand and use.

Depending on your goals it may be useful to learn about the basics of how the hardware works, although that is more related to performance optimization than good design and good code.

Edit:

Learning about so much is a long process and never ends but if you want to write solid code long term, and not just do what's popular at the time, it's the best way to go. Just take it slow and do it at whatever pace works. It works best if you have toy (and not toy) programs to make in each language as you go. After you've started getting a broader perspective, in things like programming languages, it all becomes a lot easier and faster. You'll be able to learn completely new languages in a matter of days and be better at them than people that have been doing it for years, because you can break it down in to its fundamental concepts and all you have to do is learn the language libraries and syntax, which also starts coming quickly after awhile.

<comment><USER17> I think I take a lot of the above for granted. It all sounds like a solid CS education to me, something which many students already have.

So I think your point about being open minded is the strongest. Additionally, you bring up some excellent summaries of what each discipline is about. A lot of the time the failure here is lack of comprehensiveness, or coverage; coverage in space (what's out there) and coverage in time (what's been done historically). Current favorite example is APL: [http://isomorphism.es/post/146379365169/unlike-many- language...](http://isomorphism.es/post/146379365169/unlike-many-languages- apl-arrays-are-just-a)

But as far as material goes, I suspect pure, bare metaphysics is underrated. Bearing with me, this talk by Hickey quotes a lot of Whitehead: [https://www.infoq.com/presentations/Are-We-There-Yet-Rich- Hi...](https://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey)

Whitehead spearheaded Process philosophy: [https://en.wikipedia.org/wiki/Process_philosophy](https://en.wikipedia.org/wiki/Process_philosophy)

Most metaphysics is crap, but there are a few gems. Whitehead, Russell, Quentin Meillassoux, Wittgenstein, Northrop, Peirce, Kripke. Dealing with fundamental conceptions of space, material, time, cause, and uncertainty can go a long way when it comes to modeling code and understanding when it will correspond to reality. Programming languages give you enough flexibility to reach your ass and fuck yourself over. That needs to be constrained.

 _tl;dr_

We're in agreement, I just like hearing myself talk.

</comment></comment></comment></comment><comment><USER41> Write a lot of it, and keep a critical eye. Try to find the issues that tend to come back to bite you and avoid them in the future.

Dealing with the consequences of bad code is a very good teacher :D

EDIT: Also take notice when other people's code cause you trouble, what can you do to save trouble to a future colleague?

</comment><comment><USER42> Intentionally build a style. Keep it stable for a period of time. Finally critique and improve it.

You often hear "The worst code I have ever seen is code I wrote six months ago" While on the one hand that may be true, on the other hand it is trite bullshit. If the depth of your introspection and reflection on past code is "Wow what a pile of shit!". Guess what you are going to be saying about your code in six months?

With a real honest critique you will see flaws and things that you did well. Don't just dwell on what doesn't work. When you see things in your code that work well try to figure out why they work well so that it can guide your deliberate changes to what doesn't work. Also if you don't keep your style constant for a period of time you won't have enough experience with it, nor a large enough body of code to review to have a full view of what works and what doesn't.

Last but most important read the code of others to pick up ideas on how to improve your style of coding. Some of the best bits of my coding style I have picked up from others.

<comment><USER43> When you refer to style what sorts of aspects are you looking at? Simple things like bracket placement, naming conventions?

<comment><USER44> It's all kinds of things. I recently read a suggestion that you should be able to remove everything from a function's source except the declaration and the comments, and still know exactly what it does. I'm thinking about adopting that stylistic choice, and after a few weeks/months come back to reevaluate if it's worthwhile or overwrought. Or it will just be so obviously great that it becomes a permanent part of my stylekit.

</comment></comment></comment><comment><USER45> Write a lot of code, continually rewrite it for the dumbest version of yourself.

Writing code should be highly iterative, and learning to code is as well. The more you write the better you get, and the more you will realize how crappy your old code is. Refactoring should be constant to keep the complexity and amount of code to a feasible minimum.

So, now and again, look over the code you've written, does it seem a bit overwhelming complex, are methods starting to feel bloated? Does some new feature or concept feel artificially grafted on? Then sit down and try to figure out the best way to refactor it into something more streamlined and manageable.

A good way to realize how bad one's code is to take a few weeks break from it, and if when you return you have trouble understanding the full scope of it it's time for a rewrite :)

Be sure to dedicate some time to sharpening your saw, researching new tools, technologies etc. It's easy to do something just because it's the "way I know to do it" rather than putting in the time to learn a better way.

</comment><comment><USER46> Depends on what your weaknesses are.

For me, pair programming has been the _by far_ best way to improve my coding.

</comment><comment><USER47> Test your code, every which way. Think of edge cases, security holes, do research on how code fails and internalize those lessons, and constantly test - test test test. Manual tests, unit tests, etc.

Code that works reliably is (IMHO) better than beautiful code that doesn't work at all, or falls apart under strain.

</comment><comment><USER48> Study the source code of major open source projects & try to contribute - <USER2> will see techniques for better code in their natural habitat, and through code review.

</comment><comment><USER49> Go back to code you wrote 5 years ago or even 3 years ago and refactor it. You will most likely cringe but it will force you to write it better.

Also - write code that would be easy to understand for a jr developer. I see so many developers trying to be creative with their code but it's hard to understand.

</comment><comment><USER50> 1) Learn the limits of your own brain and of the average human brain. On average someone can remember about 7 items. So do not write functions with more variables. Cut problems in many stupid little problems which are easy to reason about and debug. So whenever you see a function gets to 25 lines cut it up in to pieces. Because of your own/average brain limits large functions are garanteed (95% sure) to have bugs. 2) Test all your assumptions you make about code and build on those assumptions and build tests to check them. So you keep building on a solid code base that does not "surprise" you. 3) Be crazy about Good variable names and clear functions names and avoid abreviations because those costs brain cycles.

</comment><comment><USER51> 1\. Try to understand the problem you want to solve and only solve this one in the shortest and cleanest way you can.

1.1. Write tests for this problem you solve.

1.2. Do not over-engineer on that problem.

1.3. Optimize later. If the code is clean the performance is usually good enough. If the code is clean you can easily optimize on it.

2\. The choice of the language does not matter so much, as long you know the caveats of it. If you use dynamically typed languages you should write more tests covering possible input and output or use asserts to validate it.

3\. Know your tools. Try to understand each tool you are using first before using it for your production code.

4\. Learn to communicate your thoughts clearly. Honestly it is one of the biggest advantages for any developer. You will write better code as a result.

</comment><comment><USER52> Write a "how this piece of incredibly complicated software works" document for a piece of software you have no idea of the workings.

I have never actually published any, but have done this several times. The process is unlike any other form of writing; you are constantly rewriting all parts to reflect your incremental gains in understanding.

P.S. I believe there is an inversely proportional documentation to complexity rule, where at some point the adequate amount of documentation to describe the complexities becomes unmaintainable. In this case, the code becomes a better descriptor of the code than any amount of documentation ever could.

Examples I've worked with include the go compiler and Scala's slick library.

</comment><comment><USER53> It's not as difficult as people tend to imagine. Most of the time people fall into the trap of thinking that experts in any given field are experts because they know some secret way of doing things that is difficult to learn. The reality is that most experts (whether it's in rock climbing, bread baking, or coding) have a superior mastery of the fundamentals. In code the best thing to concentrate on is writing clear code that works correctly. The clearer the code the easier it is to figure out whether or not it works as it's supposed to, which is win/win.

In general I'd recommend every developer read the book "Refactoring", because the lessons in there are so fundamentally important to development everyone should have them in front of mind as often as possible. Learning about "code smells" and how to transform code from one way of working to another cleanly is hugely important, and that's the "bread and butter" of what good coding is like day to day. Specifically I'd say learn to use extract method and use it incessantly. Don't worry about creating small methods that only get called once (the compiler will optimize for you). Don't worry about creating "too many methods". Don't fret about having "meaty methods" that do "meaningful work" instead of just "trivial stuff", break down your code into components that have semantic meaning, even if they are small components. And if you end up with too many methods it likely means you're mixing up functionality for different things in one spot and need to split it out or you have a more fundamental design problem that needs to be addressed through simplification.

Overall, strive to make code readable and understandable. Learn the magic of well named variables and methods and pretty soon your code will start reading like an open book. Above all else, remember to be kind to your future self and others who might come along your code in the future. It's always tempting to leave a mess because it's "just temporary" or "you'll get back to fix it up later" but try to develop some basic levels of code sanitation so that you're not dumping garbage in the codebase all the time.

</comment><comment><USER54> It depends on your experience. When you're starting out you want to write as much and as often as you can. Practice solving the same problems using different solutions and adding constraints.

If you're an intermediate developer you need to turn to predicate calculus, logic, and formal mathematics. Learn a specification language and a theorem prover. Learn to think above the code. Learn to identify what the invariants are and then see what you can cut away from your code. Know what pre-and-post conditions must be held strongly and which can be relaxed. Etc.

</comment><comment><USER55> Fully understand what each line of the code does.

Third party libraries, copy & pasted code from Internet, helper functions from a framework, and more often hides critical information the coder needs to be aware. Many inexperienced coders simply put together code and produces working code without good understanding of why/how their code works.

I found that deeper understanding of the code not on the first level but all the underlying libraries and functions, lets me write more concise, bug resistant, and easy to understand/maintainable code.

</comment><comment><USER56> Keep asking yourself constantly: does this code make sense?

I think that's actually a very high bar and most code I've seen doesn't "make sense" in that if some non-developing stakeholder looks at it they won't go "oh, ok, I see what this is about" but instead "ok this is a bunch of technobabble that I couldn't possibly understand."

And read or at least skim the "Domain Driven Design" book by Eric Evans. His concept of a "ubiquitous language" is necessary for code that makes sense.

</comment><comment><USER57> Expose yourself to criticism.

This one is tricky, because (implicitly) it means surrounding yourself with people who are better than you. Which means getting hired on such teams, which is tricky if you can't bring the skills to the table (or mind-hack their interviewing process)... leading to a vicious circle.

But if you can find a way to "quantum-tunnel" through that barrier, and always try to wind up on teams better than those you've worked with up until then -- that's a big step in the right direction, at least.

</comment><comment><USER58> How I guide my development teams:

1\. Write code that does something correctly. Let it do that thing for a while, keep an eye on it.

2\. Then come back to it with fresh eyes a few weeks/months later and refactor it. Maybe just a critical chunk, maybe top-down.

3\. Repeat.

By revisiting your own code and iterating on it, you also update the design patterns you intuitively apply when faced with a problem. And importantly, you upgrade your ability to a better version of yourself.

I've tried giving examples, setting coding standards, etc; but it's really hard to code in someone else's style. We can't all be Jeff Dean or Salvatore Sanfilippo, and their styles/languages/approaches don't suit every intuition. Also, that "great" code is rarely where the project began, so it's like comparing a beginner's first draft with Hemmingway.

Code reviews are difficult for the opposite reason. Even feedback from a much more senior developer usually lacks the contextual knowledge to really know what's going on, so they're just shooting from the hip. Code reviews catch edge cases well precisely because they take the reader out of the "expected" control flow; and they generate lots of "cute trick" advice at a tiny tactical level. They're good correctness & social tools, but not so helpful for self- improvement.

<comment><USER28> > keep an eye on it.

Yup! Also, I would really like the computer to keep an eye on itself by simulating running the program a billion times or something like that.

</comment></comment><comment><USER59> I would say a developer who writes good code is one who:

1.) Uses comments & documentation as a last resort.

2.) Tailors the complexity of their code to the intended audience. There's nothing inherently wrong with 'being cute' or utilising the full feature set of a language if this will make future developers' lives easier. Conversely, if the project is to be maintained by someone that is fresh out of college, KISS is best.

3.) Prefers tried-and-true over bleeding-edge for production-level projects (it's called bleeding edge for a reason, 9/10 times you'll bleed).

4.) Produces code that conforms to what-is rather than what-should-be. Blindly sticking to ideology will perhaps produce more 'beautiful', but not necessarily more maintainable, code.

5.) Is aware of the expected lifetime of the project. No need for defensive programming if this is an MVP that you know will be scrapped in six months time. If this is the backbone of a major banking system then extra checks and being paranoid makes sense.

6.) Follows the conventions of the project and ecosystem. Consistent code is more important than personal style.

7.) Perhaps I'm in the minority here but: is not over-reliant on IDEs. Tools like IntelliSense encourage you to offload part of your mental model to a program; I feel like this inhibits your reasoning abilities.

</comment><comment><USER60> Learn how to write good tests.

This includes writing tests for code that doesn't have tests (often requires refactoring or some careful engineering)

And possibly writing tests before you even have the code aka TDD (although I'm not on that bandwagon I have done it at times with great results).

If your code is easy to test it is probably better code than otherwise.

Also depending on the organization a-careful-not-very-productive programmer can be worse than a loose-prolific-code-cowboy but generally that is not the case.

</comment><comment><USER61> I read something, somewhere, a while back that really stuck with me.

> It is impossible to make your code faster, you can only make it do less. The > only way to 'speed-up' a process is to achieve the same result with less > code (or really, less cpu cycles).

This is along the lines of less is more, but it is also something that really helped drive home the need to reduce, refactor and refine code instead of just piling more code on top of what you already have.

<comment><USER62> Your quote makes me feel like you are targeting code lines/chars.

Less cpu cycles != less lines of code.

For example, bubble sort would be little more than 10 lines where merge sort would be twice as that.

<comment><USER61> What I was really trying to express is the fact that you cannot make code run faster (on the same machine), but this is something we all say - we made xyz faster. Every line of code you write has a price, both in performance and in security/bugs. Security issues and bugs typically are tied to lines of code, but performance is definitely not.

To really understand this, you have to understand how machines work. Merge sort is faster because the processor does less work for the same input compared to the bubble sort. How many lines of code you have is rarely a good mapping of how much work your processor is doing. You have to take into account the complexity (i.e. O(n) or O(N^2)), the framework your are using (just because you have 3 lines of code in a Rails controller, doesn't mean you are executing 3 lines of code, etc.

</comment></comment></comment><comment><USER63> Spend a lot of planning time breaking up the design into separate components/modules/packages/whatever, where each piece exposes a small, well- documented interface. Naturally these pieces will have inter-dependencies, but try to keep that to a minimum. You don't want to have a single module that every other module directly imports. It takes a lot of thought, but this makes it a lot easier to fix bugs and make improvements with minimal fuss.

Another thing that is really helpful is keeping a dev journal: a sort of stream-of-consciousness record of what you're thinking/doing. Include things you thought about trying but decided against, links to blog posts/stack overflow questions, frustrations or pain points with the design, code snippets, just anything really. This can serve as a rough draft for documentation, and forces you to articulate your thought process into words. It takes discipline to keep adding to the journal, and I've fallen out of the habit recently, but it is super helpful.

</comment><comment><USER64> Maintain it over time and changes. Writing "working" code isn't that hard, but we've all had the pains of bad code:

* Hard to extend/modify

* Confusing to understand

* Full of exceptions and not-quite-repetitions

That last point is what accumulates due to the first two. The best way to learn how not to do the first two is to actually maintain your own code over changes. That teaches you how to make code that you can return to with less confusion and how to code for changes. ( A lot of code patterns are extensible, but grow cumbersome if break a fundamental assumption )

Ultimately, once you learn to avoid universally "bad" practices, you are left with a lot of conditionally good/bad ones. The same practice that makes a solid, extensible structure for one use case is what gives you a monolithic inflexible mess in another EVEN WITH THE SAME CODE QUALITY.

So I'd say focus on that: too often we feel like it if works and is "pretty" it's good, but that's not always the case. Some seeds bear fruit, others eventually give you weeds.

</comment><comment><USER65> Be nice to 'future you' \- if in 6 months you open up the code and can't figure out whats going on right away, you've done something wrong. Just because you understand everything now, you won't when it comes time to refactor down the road. Make sure that you don't screw future you over by trying to be cute, take shortcuts, or rush something.

</comment><comment><USER66> Here's what Rob Pike has to say about the best advice he got from his fellow developer Ken Thompson. Build the mental model of the software before touching code: [http://www.informit.com/articles/article.aspx?p=1941206](http://www.informit.com/articles/article.aspx?p=1941206)

<comment><USER67> > _Build the mental model of the software before touching code_

This x1000.

This goes for starting fresh, and coming back to existing code. Too many times I have seen horror that was the result of developers diving right in to coding without spending any time at all having a complete mental model of what they're doing.

</comment></comment><comment><USER68> For JavaScript in particular.

1) TDD. Since JS offers so few static guarantees, unit testing your components and utilities as you build is important; arguably more so even than in other languages. Besides test-as-you-go, this includes building things to be testable in the first place. "How would I test this?" should be an up-front question that heavily informs the approach you end up taking. Even if you write no tests, this approach will improve your code.

2) Linting. This goes beyond just enforcing code style preferences. It turns out there are lots of potential bugs you can prevent from a simple static analysis—despite JS's lack of static guarantees—and catching them early will avoid errors and make you more productive.

</comment><comment><USER9> Good code isn't obvious that it is good. Bad code _is_ obvious that it is bad. (Its like TV presenters - you notice a bad one, but good ones are the norm, so it just seems "average").

Get a job maintenance programming on someone else's crappy code. Every time you think "WFT!", ask what would have made it easier.

Likewise, if you are working on a long term project that you have written, then a month or two later revisiting the code you should be able to understand the code you wrote quickly. If you don't understand your own code straight away, ask yourself what it would have looked like to make it easier to understand. Refactor it and try to improve it.

</comment><comment><USER69> \- Add the occasional expositive comment to help clarify intent (in places where it might be ambiguous).

\- If writing in a language with weak ability to do this through its syntax, establish critical runtime invariants. This can also make intentions and system constraints obvious to the reader. I recommend invariant.js for javascript.

\- Write your tests so they can all run by themselves, and do not depend on state created by other tests.

\- If something is hard to name this usually means the design needs work.

\- If you realize something was incorrectly named, take the time to fix it and refactor, rather than imposing the burden of working with an incorrectly named thing on other readers of the code.

</comment><comment><USER70> Mild digression, but my 2 cents would be to document as much as you can. Some people say, Good code should be self explanatory. Building something on top of existing code, debugging can be a real pain in the butt with that attitude.

</comment><comment><USER71> No (useful) code lives in a vacuum. What you write WILL need to be maintained if it is of any value to someone other than yourself.

Write code so that others can read, understand and maintain.

Don't be a code 'Magician'. Few people other than yourself will appreciate your 'Magic'.

Its ok to be a 'Code Ninja' (whatever that means). In fact I think its demanded that you call yourself that so that you can bypass the recruiting/HR firewalls. Also make sure you note down that you have 10 more years of experience than the age of the technology itself. After all thats what the job posting said is the minimum experience needed.

</comment><comment><USER72> 1.) Comment! Not only does it make the code easier to interpret, but it can also bring logic errors to light as you think through why you implemented something in a specific fashion.

2.) If the language supports error handling (try catch/except) learn it and use it.

3.) Use descriptive variable and function names. Even if it means more typing, the readability is worth the effort.

4.) Use proper code style. Most languages have conventions for style that include what should be capitalized, whether to use camel case or underscores etc.. Learn them and use them.

5.) Write a lot of code. I don't think that there is any real substitute for experience.

<comment><USER73> I'd caution not to use commenting as a crutch, though. Code really ought to be readable and easy to follow all on its own. I don't think code should be littered with comments just narrating what's going on, since those can get out of sync easily when code is modified. The code itself ought to be descriptive enough to "tell its own story", so to speak. Comments ought to explain _why_ something is happening if the author feels the code may be unclear.

<comment><USER74> Agreed. If I find myself typing a detailed comment past TODO FIX THIS TOMORROW, I refactor. It is rare code should need a comment. Pulling a clever trick to trick the JIT into inlining a function call? Cool add a comment. Just loading junk form a database to show a user? Should not use a comment.

</comment></comment></comment><comment><USER75> I like to think about cohesion and coupling for non-trivial projects [https://en.wikipedia.org/wiki/Cohesion_(computer_science)](https://en.wikipedia.org/wiki/Cohesion_\(computer_science\))

Recently, I've been using a tool to show the dependency graph of my program and I've found it to be quite helpful. Perhaps a bigger point is to find and use tools for your environment that really help!

I like others also favor minimizing changing global state, unit testing (increases odds your code's interface is more well designed), code reviews..

</comment><comment><USER76> Just code a lot and do it daily. If there is nothing to code on your day job or just old legacy cruft to maintain then try code golfing.

Code Golf is about programming as short as possible and it's also a section on StackExchange [1] where you find daily tasks and many people solving them in many languages. You learn so much because...

\- You code really every day and you code _new stuff_

\- Motivation is at its max and you want to be faster than the others and have the shortest piece of code; so you still keep coding after your submission to shave every byte away

\- And you learn tons of stuff; reason: you spent thinking hours about your solution, how to tweak it etc and suddenly, you see somebody popping in the answers who did it way better than you, so you analyze and study their implementation for hours like you would never read others' source code, adapt their algorithm and learn; especially when it's about array or bit manipulation StackExchange's Code Golf has a vast selection of tasks and some many awesome programmers there; it's just insane, some guys deliver 10 byte long solutions within minutes while I need 2 hours and 150 bytes

\- I want to stress–and this might be the most important topic—writing code is one part of coding but there at Code Golf, you learn that the approach, the core algorithm is more important, and can vary so much, so coding is not just writing commands in a text editor, no it's thinking about the right approach and second about writing it down.

\- And you see and learn how same problems are solved in different languages

\- One thing which you need to get used to are all these golfing languages which are indeed esoteric but every task is solved in all the mainstream languages as well; at the beginning I didn't like all these golfing languages like Jelly, Pyth, MATL but they grew on me and now I understand them better but find them still a bit awkward; so I like more the JS, Java, C, Python solutions; but again you find _everything_ there, lots of solutions in Haskell, Brainf __*, PowerShell, TIBasic, x86 assembler, Vimsrcipt, Mathematica and so on

Compared to standard day routine coding where you glue one API to another Code Golf is ultra refreshing and I'd never had so much fun when programming and learned that much at the same time.

I think there are other code golf communities but I think the one on StackExchange is the biggest.

[1] [http://codegolf.stackexchange.com/](http://codegolf.stackexchange.com/)

</comment><comment><USER77> The number one thing you can do to write better code is get together a group of people and do code reviews on each other's code constantly. Have people in the group point out things they like and dislike about the code, along with why. Then create a "cheat sheet" where you try to summarize the principles behind all the suggestions people make for your code.

Beyond that, try to find "good" code look at how it is structured. Then try to emulate the practices in regards to language feature use, layout, etc.

<comment><USER43> Work it work best in a work setting or a friends settings?

<comment><USER77> It can work anywhere. If your work isn't doing peer code review, they should be - I read somewhere that code reviews are the single biggest driver of high quality software. It is also easy to start up a code review session at hackathons.

</comment></comment></comment><comment><USER78> Take some turns doing tech supp, test, QA. Especially for your own products (code). The embarrassment from fixing your own stuff will condition you to do better work upfront.

</comment><comment><USER79> Communicate about it. Whether it's writing internal documentation, user documentation, discussing things with another developer, or just talking to a rubber duck, just forcing the concepts into sentences can really help you think about them. Several times I've been like "this code seems ok" but then when I had to think through it and explain what it does I thought "no, that's too embarrassing, I need to improve that."

</comment><comment><USER40> What do you mean by better code? Good design is totally different than small tweaks and style changes. I'd argue putting in the effort to learn how to create good designs is the best way to write better code but it takes a lot more time and effort but more than pays off in the long run.

And there is no silver bullet. Advice like "Strong typing" or "functional programming" are not always going to be the best code for the task at hand.

</comment><comment><USER80> Read and learn from ruby code, because it clarifies intention and is expressive. Express intention, instead of code. Name variables, functions, logically in the problem domain where you are coding for. If you write your code in such a way that you can read the intention of the developer, such the contract/api, the future you, or your colleague can rewrite the guts of your methods but the signature would still communicate the intent.

</comment><comment><USER81> 7 things I live by:

1\. "Appear weak when you are strong, and strong when you are weak."

2\. "The supreme art of war is to subdue the enemy without fighting."

3\. "If you know the enemy and know yourself, you need not fear the result of a hundred battles.

4\. "When cold revenge is served, the dish is always very good"

5\. "One man can cut four thousand throats in a single night, if he is continually running."

6\. "Only a fool fights in a house that continues to burn."

7\. "Pity the warrior that kills all his enemies!"

</comment><comment><USER82> Practice, you cannot get better at coding by just reading blogs or books.

You have to get your hands dirty trying things.

Always try to keep things simple and short and choose good names. You may have to come back to your code months later, and being able to quickly grok what you wrote pays dividends.

Pick a side project working on something you enjoy. If you work at a corporate job during the day, you may not always have a good opportunity to grow and try new technologies.

</comment><comment><USER83> Contribute to a FOSS project that has great reviewing system, for instance Servo. See this paragraph at [http://nikkisquared.github.io/2016/02/22/things- ive-learned....](http://nikkisquared.github.io/2016/02/22/things-ive- learned.html#reviews)

> ... In contrast to either of those, everything I write for Servo receives > in-depth review and feedback ...

</comment><comment><USER84> Give a ____. I 've seen so much bad code that's a result of just simply being sloppy. If you care, your code will be that much better.

</comment><comment><USER85> Porting and maintenance. Take an existing code base (your own, open source, etc) and make it run on another platform. Go fix some of the bugs in the code base.

Then you'll start deeply appreciating what good and bad code looks like. You'll see how helpful comments actually are, how layers of indirection help or not, and all sorts of little details that help or hinder your efforts.

</comment><comment><USER86> Study Design patterns, follow the SOLID principles while working on some pet projects or even while solving a simple problem may be.

You will be amazed on the benefits you get out of these principles. You will be able to describe your entire design in few English words.

Speak to senior developers and get your class design reviewed, a little bit of "why do it this way" questions will help you a understand a lot of things.

</comment><comment><USER87> Make a habit of reading the code you're calling, easier if you're building on an os where you have access to the source. This will give you exposure to other coding styles, likely other languages, and deeper knowledge of your platform. You can do this occasionally -- if the documentation is unclear for something, check the source instead of the internet, for example.

</comment><comment><USER88> Imagine _you_ will have to go back to the code and work with it, after not having spent a single thought on the project for 12 months.

<comment><USER88> ...and possibly during those 12 months have 12 people try to murder your code, i.e. expand its functionality. If the overall architecture, layout is clear, there is a chance that they will expand, improve your code in the way that you originally intended. If it is messy and unclear, it will get more messy. (I'm currently doing a re-write of a huge project that grew over time, using these principles, trying to learn from what was not so nice in the old codebase)

</comment></comment><comment><USER89> Don't be afraid to throw away code. I just decommissioned a home grown middleware routing system today. I cut my Java teeth on it 5 years ago and it was time to go. Replaced it with an apache camel program that is so much better. I did the happy dance when we turned my code off for good.

</comment><comment><USER90> Here are slides from a talk I gave on just that subject: [http://diiq.org/5questions.pdf](http://diiq.org/5questions.pdf)

tl/dr: Some useful vocab for phrasing questions you can ask yourself about your code, as you write it, in order to improve it.

</comment><comment><USER91> \- Analyze, design and coding.

\- static typing programming language is not verbose, if you know how much comments and unnecessary unit tests you have to write.

\- focus on conceptual and system level evolve, stop argue and jump between different programming languages for your work just because some of them are cool.

</comment><comment><USER92> At the very beginning I think the advice I want to give is to check out standard library codebase. All the design patterns or classical methods are found everywhere in the exemplary codebase. Just steal them and apply to your own code.

</comment><comment><USER93> Read The book Code Complete 2.

</comment><comment><USER94> Learn the tools and languages you hate the most.

That's my cheap advice. It's terribly annoying but you always come out on the other side having learned something valuable from the perspective you didn't want. Always.

</comment><comment><USER95> Study programming languages in different paradigms than you're used to

</comment><comment><USER96> Always think for the next developer who will maintain your code.

</comment><comment><USER97> Avoid writing code to begin with by leveraging existing tools, or build better tools so you don't have to write better code (and share with the rest of the world :).

<comment><USER98> Doesn't that lead you into a place where you can't modify the constraints of your application without sending the patches upstream (for example we hit limits with the mysql connector for C++ all the time, but they are our application specific).

Also, how do you mitigate another leftpad disaster?

</comment></comment><comment><USER99> My highest benefit/cost habit is viewing the diff immediately before each commit.

It's simple, concrete, and not onerous. The benefits are amazing.

</comment><comment><USER100> Read at least two style guides for the lang of choice. Adopt the good ideas. Personally, I like the style guides published by Google.

</comment><comment><USER101> try to do as much as junk code and as many possibilities of coding for a solution. Don't try with one solution and remove it if not working. just comment it and try with some other solution. so that once the code is working fine then clean the code before making it to production.

</comment><comment><USER102> Don't try to use every feature of a language.

A two-liner is sometimes more efficient and readable than a one-liner.

</comment><comment><USER103> Pair up, review code, you will be amazed how much you can learn from others both novices and experts.

</comment><comment><USER104> I'm self taught, and have been doing this professionally for 20 years. I started by learning the fundamentals, and then I started implementing RFC's myself (for things like web servers, ftp servers, SMTP, etc...). Then I went, and compared my solutions to the open source solutions, and tried to see what concepts I was missing. A reason I think this definitely helped me is because when I was creating my own projects, it's easy to decide not to implement a feature if you get stuck trying to figure out how to implement it, and becomes self limiting. Following a spec is going to be a lot closer to how you will work in the real world, and you aren't allowed to decide to just not include a feature because you get stuck.

The comments about writing lots of code are absolutely true, the more you write, the more mistakes you make, the more bugs you have will increase your experience with edge cases and common issues. It's invaluable.

When it comes to actual tips for the code quality itself, a good aim is to make the code readable, as opposed to understandable. Use longer variable names, and avoid single letter variable names. The goal is to make it obvious what your code is doing, you want to limit the comments to sections of the code that NEED them. Far too many developers get the "Comment all the things" dogma, and this just creates a mess. I see this far far too often:

        class Person {

            // Returns the first name of the person
            function FirstName() {...}

        }

This is beyond useless. And remember code will begin to smell, but comments will begin to stink, so you want to make them only when clarification or additional information is required. If you find you have to comment all the time, then you need to work on your code composition and naming.

For flow, you want to make your code work, then refactor it to clean it up. Refactoring should be something you allow time for on any feature implementation. Never move onto another features saying "I'll clean that up later", you won't, or you will eventually because you've created a brittle mess.

Read other peoples code, and run it through a debugger. While I normally eschew debuggers except in fairly rare occasions, they can be invaluable about learning about patterns that you're not familiar with.

Try ditching the IDE. IDE's make your life easy, and they also often make you ignorant as to how your application actually works. Heavy handed namespacing languages like C# and Java are a little trickier to work with this way, but you will learn so much more about your application than you will being spoon fed everything. The reason this is important is something will eventually break, and it's far better to understand those underpinnings when building the app than when something breaks when you're staring down a deadline.

Read books about patterns, languages, etc..., and re-read them after you have been using the techniques for a while. Become familiar with the GoF design patterns, so you understand them, and understand when they're useful. Do not use them as a gospel. Pigeonholing in patterns where they don't belong will create worse code than if you hack together your own more appropriate method. But definitely use them when they fit.

Create an open source side project, and put it up on github. Good code involves interacting with other developers, and even if only 10 people are using your repo, you will learn all about pull-requests and merging, etc...

Teach what you know. You will be amazed at how much better you will understand a lot of concepts once you have to explain how they work. Even if it's just to a rubber duck.

Speaking of rubber ducks, when you get stuck on a problem, or you have a bug that seems illogical and you don't have someone handy to ask for help, explain the issue to a rubber duck. On our team, we'll often call another developer over, and while we explain the problem to them, before we're done explaining, we've already figured out what's wrong. Language uses a different area of the brain, and I suspect that by talking things out, your brain will approach the problem in a way different from the state we use for coding. (this is pure blatant speculation on my part).

Unit test, unit test, unit test. However, ignore coverage metrics, that's a huge waste of time. When you're starting out, write all the tests, but be sure to observe all the instances where the unit test actually identified an issue in the application. You'll always want to unit test your business logic, but avoid testing everything and never test for things that are impossible to occur. Also never test anything but your own code, I've seen fat too many instances of unit tests that simply add a suite of tests to jQuery or some other library. But do assure that you are able to handle bad input, regardless of here it comes from.

Don't be clever. Sure, you can make an easily readable 7 lines of code into a clever one liner that only you understand because you're oh so smart. But don't do it. When you're writing code, you're doing it at the height of your understanding of the system at the time. So even if you're the only eyes that see it, as you move on to other projects, you will no longer be as 'smart' in that codebase. This is especially true when you switch between languages frequently. Beyond that, you probably won't be the only person looking at your code, so write the code (as much as possible) to allow a non-developer to be able to get a sense of what's going on.

Avoid magic strings. What this means is that a string generally shouldn't be used to determine the execution path of code. A simple spelling mistake can be very difficult to detect, and there aren't any tools that can assist. Enums, constants, or named integers are far safer.

Take breaks, get exercise, and don't try to code for every waking hour. If you're in flow, and making real progress this is fine, but if you're just working the hours and aren't making a lot of headway, a good nights sleep will go a lot further than another 4 hours of a fatigued brain. Seriously, sleep at least 8 hours, your ability to learn and remember is entirely based on your REM cycles, when the brain essentially writes from it's cache to permanent storage and cleans up the toxins from the day. Without sufficient sleep, you will not remember what you did, and you will not learn from the mistakes you made and new understandings you would have otherwise acquired.

Never copy and paste from SO or other snippet that you find to solve your problem. Read the example and understand what is going on in the snippet. Then hide the browser and type it in as you understand it to work. I came up with a rule for my first team 15 years ago, and that was to never insert code into a project that you don't understand. If you don't understand it when you add it, you won't understand it any better when that code breaks.

</comment><comment><USER105> Write cross-platform code

</comment><comment><USER96> Always think of the next developer who will maintain your code

</comment><comment><USER106> Work on larger projects and make mistakes to learn from them.

</comment><comment><USER107> Always trust absolutes, and assume all input is good.

</comment><comment><USER108> Never reassign a variable with a different value.

</comment><comment><USER109> try to come up with more than one solution to a problem. don't marry the first idea.

</comment><comment><USER110> My three pieces of advice to developers aren't specifically about code, but they will eventually lead to better code:

First, slow down. Slow, slow, slow, slow down. Take the time to test and to write tests. Take the time to think about your code. Do it as right as you can the first time. Don't let anyone tell you you don't have time to do it -- you always have time to do it.

Your boss might say "deadline is 5pm", but push back if you can't do it right. It's always, always worth it to slow down. Build testing into your timeline estimates. (My rule of thumb: double the estimate. 1x for writing code, 1x for testing).

Second, don't overwork yourself for no reason. I used to be the support engineer for a startup. Half of my job entailed fixing all the bug reports that came in each day. I would reproduce the bug, add a test, and push a fix as quickly as possible. I used to come in at 9 and stay until 7 or 8pm. One day I cleared out the queue. No more bugs in the list. The next day I came in and had 10 more items. Realization #1 happened there.

I sent an email to a colleague at one point, and he didn't respond until 11am the next day, but I barely noticed. And realization #2 happend then.

The realizations were simple: 1) there will always be more work tomorrow, and 2) nobody realistically expects a response within minutes. In fact, if you send an email after 4pm, you probably don't expect a response until the following morning.

Both of those realizations caused an attitude shift: I leave work at 5, 5:30 every day. I spend more time at home with my fiancee and friends. When I come in, if I have a few more emails than I did the day before, that's fine. They're not expecting instantaneous responses -- and if they are, that's _their_ problem, not mine.

Each support ticket got resolved in 24 hours or less -- far exceeding our customers' expectations -- but I went from working 60 hour weeks to 40 hour weeks. Much happier, much more productive, much less stressed out, and our customers will still exceedingly happy.

A friend of mine works 60+ hour weeks and checks his email constantly, even when he's not at the office. I told him to just wait until morning and email them then. He says, "If I do that, I'll never get anything done, because I'll have 100 emails from my boss in the morning." Well, that's not his problem -- that's his boss's problem. He should go back to his boss and say "If you want me to get X, Y, and Z done, then you need to either email me much less frequently, or get more headcount on the project."

Don't overwork yourself. Don't work more than 40 hours a week without extra compensation. Don't stress out about work -- I guarantee they're not stressing out about you.

Finally, eliminate the phrase "it works for me" from your vocabulary. When someone sends you a bug report, whether it's a customer, a manager, or a fellow developer, your first action should be to confirm that it is, indeed, broken. They would not send you a bug report if there wasn't _something_ wrong. It might be your code, or it might be them, but you owe it to yourself to make sure you have bug-free code, and you owe it to that person to give them the benefit of the doubt.

And one thing you do NOT want to do is go back to someone and tell them THEY were wrong, and then have it turn out that it actually was a bug.

Do your due diligence and rule out a bug. If you can't recreate it, go back and say "Hey, I'm having trouble recreating this. Can you give me more information?" Only when you have ruled out a bug by reproducing the behavior, do you go back to your customer and explain that they made a mistake or something.

Those are the three biggest mistakes I see with new developers (and even people that aren't developers). Slow down, don't work too hard, and start off with the assumption that the customer is right.

My two cents.

</comment><comment><USER111> Write better tests.

</comment><comment><USER112> Write less of it.

</comment><comment><USER113> Take your time.

</comment><comment><USER80> s</comment>


Show HN: Pop Theories - The place to share Fan Theories - <AUTHOR> https://poptheories.com <comment><AUTHOR> In case anyone was wondering, here is the stack I use :

* React

* Styled-Components

* GraphQL/Apollo

* Java backend, Spring Boot and GraphQL library

* Couchbase as DB

* Auth0

Quite unusual I would say, but it works quite nicely !</comment>


The Introverted Issue - <AUTHOR> http://blog.shawndumas.com/post/142027095788/the-introverted-issue <comment><USER2> Sounds like Dumas is a Highly Sensitive Person

[https://en.wikipedia.org/wiki/Highly_sensitive_person](https://en.wikipedia.org/wiki/Highly_sensitive_person)

I am one myself, to a considerable degree. I need to have quiet time after social occasions, and spend a lot of time processing what happened.

<comment><AUTHOR> very interesting... haven't heard of this. ty

</comment></comment><comment><USER3> How about stop feeling sorry for being yourself.

<comment><AUTHOR> Well yes and no. If I know that I have this proclivity it's on me to plan accordingly. I usually know better and reserve time but I forgot to yesterday.

But from their point of view they've just been snubbed after working up the courage to ask. It's uncomfortable to be rejected.

That's why it's the _introverted_ that so often is labeled offensive.

<comment><USER3> From [http://introvertspring.com/thing-introverts-do-that-piss- off...](http://introvertspring.com/thing-introverts-do-that-piss-off- extroverts/)

> I don't think constantly adapting our behavior to please extroverts is the > answer. Helping people understand introversion is a far better approach.

And by "helping to understand introversion" I would suggest to first check your own MBTI personality type and - if possible - let your social partners do the test as well. But as I know Extraverts, they don't give a shit about "deeper" stuff. So the interaction stays superficial and I just stopped caring how they interpret my behaviour.

You can make the test here: [https://www.16personalities.com](https://www.16personalities.com)

<comment><AUTHOR> I = 22%, N = 88%, F = 12%, J = 33%

I am attempting to inform via my blog post; I am not changing me just taking responsability for me.

And thank you for responding!</comment></comment></comment></comment>


Defense Distributed's 3D-printing gun files are back online - <AUTHOR> https://www.theverge.com/2020/3/30/21199519/defense-distributed-defcad-3d-printed-gun-library-launch-vetting <comment><USER2> The idea behind plastic guns is philosophical.

The government should not be able to forbid a person form effectively defending his or herself ; it's a natural right which can't be taken away by any government. 3D printed guns gives you back that right if your state has taken it away i.e. China. They are hard to detect so this is another plus ion the same vein as the first.

This is the point of the project as I understand it, as per the project's creator.

</comment><comment><USER3> Why won't these articles die? It's pure sensationalism since no sane person would 3D print a gun which in all likelyhood would just blow up in your hand.

You have always been able to do effectively the same thing for less money and with more reliability using some pipe at a hardware store. However, when someone adds the phrase "3D printing" it becomes a huge issue that people want to regulate. It's incredibly frustrating

<comment><USER4> There are plenty of functional 3D printed AR-15 lower receivers. The upper receiver and barrel is where the explosion happens, and these are not restricted parts, or recognized as a firearm as such, so can be purchased freely and manufactured as a commercial product from eg. steel.

<comment><USER3> OK, good point. Looking them up, it's effectively a fairly simple hunk of metal. However, they are restricted parts.

It reminds me of a story from a friend about how strange some laws about gun registration are in the US. He was telling me of one model of gun which became restricted, but existing instances were grandfathered in. To get around this, before the ban went in place companies manufactured "unmachined lower recievers" which were literally just hunks of aluminum or steel with serial numbers on them. However, because they are registered firearms those specific chunks of metal are heavily regulated and can't be taken on planes without being locked up for instance.</comment></comment></comment>


I slammed this company on social media. Here's how the CEO responded - <AUTHOR> https://www.techinasia.com/talk/wins-for-farm-fresh-ceo/ <comment><USER2> The CEO has my respect. Amazing response and showing the customer they care.

<comment><USER3> yeah, indeed.

</comment></comment><comment><USER4> What a strangely clickbaitish title for HN.</comment>