42

I've recently poured a couple of hours into JavaScript because I wanted to benefit from the massive userbase. Doing that I have noticed a pattern that most people attribute to dynamic languages. You get things working really quickly, but once your code reaches a certain size you waste much time with type, spelling and refactoring errors in general. Errors a compiler would normally spare me from. And not have me looking for errors in the logic when I just made typo in another module.

Considering the incredible following JavaScript and other dynamically typed languages have I am lead to believe that there's something wrong with my approach. Or is this just the price you have to pay?

To put it more concisely:

  • How do you approach a JavaScript (or any other dynamic language for that matter) project with ~2000 LOC?
  • Are there tools to prevent me from making those mistakes? I have tried flow by Facebook and JSHint which somewhat help, but don't catch typos.
TomTom
  • 531

5 Answers5

37

Specifically speaking of JavaScript, you could use TypeScript instead. It offers some of the things you are referring to. Quoting the website:

Types enable JavaScript developers to use highly-productive development tools and practices like static checking and code refactoring when developing JavaScript applications.

And it is just a superset of JS, meaning some of your existing code will work with TS just fine:

TypeScript starts from the same syntax and semantics that millions of JavaScript developers know today. Use existing JavaScript code, incorporate popular JavaScript libraries, and call TypeScript code from JavaScript.

VinArrow
  • 484
19

There are some approaches which can help:

Unit testing

Write unit tests where possible. Solely relying on manual testing or finding bugs in the wild is hit-and-miss.

Use frameworks

Rather than rolling your own and risking the introduction of bugs, use established frameworks where possible.

Prefer CSS/high-level languages

Where you can cede functionality to CSS or whatever high-level language you're writing in.

Refactor

Refactor to reduce the amount of code. Less code = less places for things to go wrong.

Reuse

Reuse existing code where you can. Even if code isn't an exact match, it can be better to copy, paste and modify rather than writing something afresh.

IDEs

Modern IDEs generally have at least some Javascript support. Some text editors are also Javascript aware.

Robbie Dee
  • 9,823
2

One tool that hasn't been yet mentioned is simple, file-local or project-wide text search.

It sounds simple, but when you include some regular expressions you can do some basic to advanced filtering, e.g. search for words located in documentation or source code.

It has been an effective tool for me (besides static analyzers), and given your project size of 2k LOC, which isn't particularly large in my opinion, should hopefully work wonders.

mucaho
  • 681
1

I am currently refactoring several thousand lines of code on a large AngularJS project. One of the biggest hassles is to figure out the exact contract of a given function. I sometimes ended up reading API documentation because elements of the raw API response were assigned to variables that went through 6 layers of code before being modified and returned through 6 more layers of code.

My first advice is to design by contract. Take specific input, produce specific output, avoid side effects, and document those expectations using TypeScript or at least JSDoc.

My second advice is to implement as many checks as possible. We follow the AirBnB standard and use eslint on our entire code base. Commit hooks verify that we always follow the standard. We naturally have a battery of unit and acceptance tests, and all commits must be reviewed by a peer.

Switching from a text editor (Sublime Text) to a proper IDE (WebStorm) also made it much easier to work with code in general. WebStorm will use JSDoc to give hints about expected parameter types and raise error if you supply the wrong type or use the a return value in the wrong way.

In JavaScript, new features such as symbols and getter/setters can help enforce a certain level of quality by adding assertions to variable assignment (e.g. make sure the integer is within range, or that the data object has certain attributes).

Unfortunately, I don't think there's a true solution to prevent dynamic language mistakes, only a series of measures that can help reduce their frequency.

nicbou
  • 111
0

My answer to the question “How do you approach a JavaScript (or any other dynamic language for that matter) project with ~2000 LOC?”

I develop PDF form applications. I approach my JavaScript software development project (regardless of source code size) using Petri’s net elements and annotations. The method is not tied to any particular programming language technology. Thus it may be used for other “programming languages”.

I create a diagram of the application logic. To keep the diagram uncluttered I add most of my annotations to a form that I use with the diagram. The entries in the form include references to properties or functions. Then I write out the source code based on the information in the diagram and entries in the form. The method is systematic because every source code written is directly mapped from the diagram and entries in the form. The source code can be easily checked because I also follow naming and coding conventions when I write the code.

For example, I have chosen a convention that all functions are prototypes. If performance become an issue then it can be improved by declaring the functions in the constructor. For some properties I use arrays. Again if performance becomes an issue then it can be improved by using direct references.

I also use eval. This can greatly reduce the size of source code. Because of performance issues, I use eval at the beginning or initialization part of my application; I never use it in the “runtime logic” – this is another coding convention that I follow.