惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
Microsoft Security Blog
Microsoft Security Blog
B
Blog
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
爱范儿
爱范儿
博客园_首页
博客园 - 聂微东
量子位
V
Visual Studio Blog
aimingoo的专栏
aimingoo的专栏
T
The Blog of Author Tim Ferriss
J
Java Code Geeks
小众软件
小众软件
大猫的无限游戏
大猫的无限游戏
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
N
Netflix TechBlog - Medium
F
Fortinet All Blogs
The Cloudflare Blog
T
Tailwind CSS Blog
G
Google Developers Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
月光博客
月光博客
腾讯CDC

博客园 - 风轻如梦

阿里云专属推荐码nuyxa6 BUILDING ANGULAR APPS USING FLUX ARCHITECTURE TWO PHASES OF ANGULAR 2 APPLICATIONS Forms in Angular 2 CHANGE DETECTION IN ANGULAR 2 BETTER SUPPORT FOR FUNCTIONAL PROGRAMMING IN ANGULAR 2 ANGULAR 2 BITS: UNIFIED DEPENDENCY INJECTION ddd http://angular.github.io/router/ background image http://4526621.blog.51cto.com/4516621/1343369 http://www.atool.org/keytype.php#0-tsina-1-53371-397232819ff9a47a7b7e80a40613cfe1 yahoo 待做 qiangchezu car contact qq 30288891@qq.com http://depositphotos.com/ together 矢量图 耳石症
WHY JAVASCRIPT NEEDS TYPES
风轻如梦 · 2015-04-08 · via 博客园 - 风轻如梦

Types have a bad reputation for making code harder to read, adding unnecessary ceremony, and in general complicating things. In this blog post I’d like to show that a type system done right can help make code more readable and toolable without constraining the expressiveness of the language.

DOCUMENTATION FOR HUMANS AND MACHINES

First, I want to show how type annotations can be used as documentation for both humans and machines.

Let’s look at this function jQuery.ajax() and pretend that we are not familiar with it. What kind of information can we get from its signature?

    jQuery.ajax(url, settings)

The only thing we can tell for sure is that the function takes two arguments. We can guess the types. Maybe the first one is a string and the second one is a configuration object. But it is just a guess and we might be wrong. We have no idea what options go into the settings object (neither their names nor their types) or what this function returns.

There is no way we can call this function without checking the source code or the documentation. Checking the source code is not a good option – the point of having functions and classes is to be able to use them without knowing how they are implemented. In other words, we should rely on their interfaces, not on their implementation.The only option we have here is to check the documentation. And there is nothing wrong with that. Except that it takes time.

Now, contrast it with a typed version.

ajax(url: string, settings?: JQueryAjaxSettings): JQueryXHR;

interface JQueryAjaxSettings {
  async?: boolean;
  cache?: boolean; 
  contentType?: any;
  headers?: { [key: string]: any; };
  

It gives us a lot more information.

  • The first argument of this function is a string.
  • The settings argument is optional. We can see all the options that can be passed into the function, and not only their names, but also their types.
  • The function returns a JQueryXHR object, and we can see its properties and functions.

This bring us to my first point.

Types serve as documentation for the programmer.

In addition, this information enables advanced autocompletion, navigation, and refactoring capabilities. Having such tools is almost a requirement for large projects. Without them programmers are afraid to change the code, which makes large-scale refactorings almost impossible. As Anders Hejlsberg puts it, you can build a large application in a dynamically-typed language, but you cannot maintain it. Without advanced tools a large code base is always in a semi-read-only state.

Types enable advanced tools.

TYPES PROVIDE A CONCEPTUAL FRAMEWORK FOR THE PROGRAMMER

A good design is all about well-defined interfaces. And it is much easier to express the idea of an interface in a language that supports them.

For instance, imagine a book-selling application where a purchase can be made by either a registered user through the UI or by an external system through some sort of an API.

image

As you can see, both classes play the role of a purchaser. Despite being extremely important for the application, the notion of a purchaser is not clearly expressed in the code. There is no file named purchaser.js. And as a result, it is possible for someone modifying the code to miss the fact that this role even exists.

function processPurchase(purchaser, details){
}

class User {
}

class ExternalSystem {
}

It is hard, just by looking at the code, tell what objects can play the role of a purchaser, and what methods this role has. We do not know for sure and we will not get much help from our tools. We have to infer this information manually, which is slow and error-prone.

Now, compare it with a version where we explicitly define the Purchaser interface.

interface Purchaser {
  id: int;
  bankAccount: Account;
}

class User implements Purchaser {}
class ExternalSystem implements Purchaser {}

The typed version clearly states that we have the Purchaser interface, and the User and ExternalSystem classes implement it. This brings us to my next point.

Types are useful for defining interfaces/protocols/roles. They provide a conceptual framework for the programmer.

It is important to realize that types do not force us to introduce extra abstractions. The Purchaser abstraction is present in the JavaScript version of the code, but it is not explicitly defined.

I’ve spent most of my career programming in Ruby and JavaScript, and I find these languages extremely powerful and flexible. But after working on sizeable apps written in these languages, I came to the conclusion that the lack of interfaces pushes developers toward building tightly coupled systems.

In a statically typed language boundaries between subsystems are defined using interfaces. Since Ruby and JavaScript lack interfaces, boundaries are not well expressed in code. Not being able to clearly see the boundaries, developers start depending on concrete types instead of abstract interfaces. And it leads to tight coupling. It is possible to build large decoupled systems in these languages, but it requires a lot of discipline.

STATICALLY TYPED LANGUAGES?

It may seem that I am advocating statically typed languages, but I am not. The arguments against a mandatory static type system are still sound.

  1. It complicates the language. Writing a mock library in JavaScript is an exercise that almost everyone can undertake. Doing similar stuff in Java is far more difficult.
  2. It constrains the expressiveness of the language.
  3. It requires type annotations even when they are not desirable (e.g., in a domain specific language).

What we want is something that combines the power of a dynamically typed language with the benefits of having explicit interfaces and type annotations.

OPTIONAL TYPE SYSTEMS

An optional type system does not require using type annotations. Type annotations are used to help you communicate your intent and get better tooling.

Optional type systems are forgiving. You do not have to satisfy the type checker. Quite the opposite, the type checker is there to help you find typos, search, and refactor. You do not completely rewrite your program to make the types work. If you are prototyping something, and duck typing works, just do not use types. Use them only when they add value.

It would not be completely fair to say that optional typing is only good stuff without any drawbacks. It still adds some complexity to the language (nothing compared to a mandatory static type system though).Also, to fully see the benefits of such a system you need more sophisticated tools than a plain text editor. But because of the reasons I outlined in this blog post, I think it is worth paying this price.

TYPED JAVASCRIPT

I wrote the original version of this blog post some time ago, and called it “I Wish Ruby Had Interfaces”. Back then I was a Rails developer. And I was extremely frustrated by working on a very large Rails code base, where some refactorings were taking months to finish. There was no hope Ruby would get an optional type system, so it was just a rant.

This time it is different. The JavaScript community is embracing the idea of optional types. TypeScript has become a robust tool used in production at many companies. AtScript, and Flow are new projects in this area. I am really excited to see what typed JavaScript community will look like in a few years.