Translated from: medium.com/hackernoon/…

Many linguists believe that the natural language people speak affects thinking itself. Does the same idea apply to computer languages? Programmers using different programming languages often come up with radically different solutions to the same problem. To take an extreme example, computer scientists have eliminated the GOto statement in order to encourage more structured programming (not quite like the 1984 novel in which totalitarians deliberately eliminated heterodox words from natural language to eliminate thought crime, but not quite).

But what does this have to do with Flutter and Dart? Quite a lot, actually. The early Flutter team evaluated more than a dozen languages and chose Dart because it best suited the way they built their user interface.

Dart is a big reason why many developers love Flutter. As this tweet puts it:

Here is a quick list of Dart features, all of which together make Dart indispensable to Flutter.

  • Dart supports AOT (Ahead Of Time) compilation to generate machine code that performs fast and predictably. This allows almost all Flutter components to be implemented with Dart. This not only makes Flutter perform quickly, but also makes virtually everything (including all widgets) customizable.
  • Dart also supports JIT (Just In Time) compilation, which greatly speeds up the development process and even disrupts workflow (including Flutter’s popular sub-second thermal state-maintaining updates).
  • Dart makes it easy to write an animation that runs smoothly at 60fps. Dart also does object memory allocation and garbage collection without locking. And just like Javascript, Dart avoids preemptive task scheduling and memory sharing (and thus locks). Because Flutter applications are compiled into machine code, they do not need inefficient Bridges to communicate between different domains (e.g., Javascript to native).
  • Dart enables Flutter to eliminate the need for a separate declarative layout language such as JSX or XML, as well as a separate visual interface builder, because Dart’s declarative, programmable layout is easier to read and visualize. And because all layouts are written in one language in one place, Flutter makes it easier to provide advanced tools to make layout a breeze.
  • Developers have also found Dart particularly easy to learn because it contains features familiar to users of both dynamic and static languages.

Not all of these properties are unique to Dart, but the wonderful chemical reactions produced by the combination of these properties make Dart uniquely powerful for Flutter. So much so that it’s hard to imagine that Flutter could have been as powerful without Dart.

The rest of this article will explain in more depth the features (including its standard library) that make Dart the best language to implement Flutter.

Compile and execute

(If you are familiar with static/dynamic languages, AOT/JIT compilation, virtual machines, etc., you can skip this section.)

Historically, computer languages have been divided into two groups: static languages (such as Fortran or C, where variables are fixed to static types at compile time) and dynamic languages (such as Smalltalk or Javascript, where variable types can be changed at run time). Static languages are usually compiled into machine code or assembly code of the target machine so that they can be executed directly by the hardware at run time. Dynamic languages usually require the interpreter to execute and do not generate machine code.

Of course, as you can see, things end up getting more complicated. The concept of a virtual machine (VM) became popular, but it was really just software that mimicked the high-level interpreter of a hardware machine. Virtual machines make it easy to port languages across different hardware platforms. In this case, a virtual machine’s input language is usually an intermediate language. For example, a programming language (Java) is compiled into an intermediate language (bytecode) and then executed by a virtual machine (JVM).

In addition, there are now just-in-time (JIT) compilers. A JIT compiler runs while the program is being compiled. So the original compiler that compiled the generator before it ran is now called an AOT compiler.

In general, only static languages are suitable for AOT compilation to generate machine code because machine languages usually need to know the type of data, whereas dynamic languages are not typed until run. Therefore, dynamic languages are usually interpreted or JIT compiled.

AOT compilation usually results in less efficient development at the development stage (it takes longer to modify the code to the point where you can execute the program and see the results). But AOT compilation produces program execution that is more predictable and does not need to be paused for run-time analysis and compilation. Aot-compiled programs also start faster (because they’ve already been compiled).

In contrast, JIT compilation provides greater development efficiency, but results in relatively slow and erratic execution. In particular, JIT compilers are slower to start because the JIT compiler needs to analyze and compile the code before the program can run. Many studies have shown that users are more likely to abandon an application if it starts a few seconds late.

So that’s enough background information. Wouldn’t it be great to combine the advantages of AOT and JIT compilation? Read on.

Compile and execute Dart

Dart’s team members had done pioneering work on advanced compilers and virtual machines before they developed Dart, These include dynamic languages (such as Javascript’s V8 engine and Strongtalk for Smalltalk) and static languages (such as Java’s Hotspot compiler). They use that experience to make Dart unusually flexible and resilient for compilation and execution.

Dart is one of the few (and probably the only “mainstream”) languages that is suitable for both AOT and JIT compilation. This is also an important advantage of Dart and especially Flutter.

JIT compilation is used in the development phase to obtain an extremely fast development experience. When the application is ready for release, it is compiled by AOT. With the help of advanced tools and compilers, Dart achieves the best of both worlds: extremely fast development efficiency and fast startup and execution.

Dart’s flexibility in compilation and execution doesn’t end there. Dart, for example, can also be compiled into Javascript, so it can be executed by a browser. This allows you to reuse code between mobile and Web applications. Developers have reported that they can reuse up to 70% of their code between mobile and Web applications. Dart is also available on the server side and can be compiled to machine code for execution or compiled to Javascript to run in Node.js.

Finally, Dart also provides a separate virtual machine that itself executes Dart as intermediate code (which is essentially an interpreter).

Dart can be efficiently AOT or JIT compiled, interpreted, and translated into other languages. Not only that, it compiles and runs fast.

Hot updates to maintain status

One of the most popular features of Flutter is its extremely rapid thermal renewal. In the development phase, Flutter was JIT compiled to update and continue executing code within 1 second. The state of the application is also preserved when possible, so the application remains in its original state after updating.

It’s hard to appreciate how fast (and reliable) hot updates are important to development until you’ve played with them yourself. Some developers report that this has changed the way they create apps, as if it has brought them to life.

Here’s what one developer had to say about the Flutter thermal update:

I wanted to test the hot update, so I changed a color and saved my changes, and… I fell in love with ❤️.

This feature is really amazing. I thought “Edit & Continue” in Visual Studio was as good as it got, but this is shocking. I think this is the only way mobile developers can double their productivity.

It’s been a huge change for me. Whenever I used to deploy my code, it took so long that I lost focus on doing other things. By the time I turned my attention back to the simulator or device, I had forgotten what I needed to test. What could be more frustrating than wasting 5 minutes adjusting a control by 2 pixels? With Flutter, all this has become a fleeting thing.

The thermal renewal of Flutter makes it faster and easier to try out new ideas or alternatives, thus greatly enhancing creativity.

So far, we’ve discussed how Dart is developer-friendly. Let’s look at how Dart makes it easier to develop smooth, pleasing applications.

Avoid shaking

It’s good that your app runs fast, but it’s even better if it runs smoothly. If an animation has jitter even fast it is bad. However, avoiding jitter is difficult because it can occur for a variety of reasons. Dart has a number of features to avoid these common causes of jitter.

Of course, just like in any other language, you can still write bad apps with Flutter. Dart makes development results more predictable and gives developers more control over writing smooth applications, making it easier than anyone to achieve the best user experience.

So what’s the conclusion?

Flutter rendering at 60fps is much better than other cross-platform frameworks.

Not much better than other cross-platform frameworks, or even as good as native apps.

The UI is so smooth… I’ve never seen an Android app so smooth.

AOT compilation and “Bridges”

One feature we’ve discussed that helps smooth out applications is that Dart can be compiled into machine code via AOT. Pre-compiled AOT code is more predictable than a JIT because execution is not paused for analysis and compilation at run time.

Aot-compiled code also has the huge advantage of avoiding the “Javascript bridge.” When a dynamic language (such as Javascript) needs to interact with the platform’s native code, they need to communicate through a bridge, which leads to context switching and thus requires storing large amounts of state data (possibly to secondary storage). These context switches are a double whammy to performance. They not only make your application run slower, but they also cause serious thrashing.

Note: Even compiled code needs to interact with platform code in some way, which can also be called a bridge. But this is usually a much faster bridge than a dynamic language requires, by an order of magnitude. In addition, Dart allows for things like Widgets to be packaged into an application, so the bridge dependency is lower.

Preemptive scheduling, time sharding, and shared resources

Many computer languages support multithreaded parallel execution (including Java, Kotlin, Objective-C, and Swift), switching between threads through preemptive multitasking. Each thread is allocated a slice of time to execute, and if execution exceeds its allotted time it is preempted by another thread through a context switch. However, if preemption occurs when a shared resource (such as memory) is being updated, this can cause race problems.

Races are also a double whammy because they can cause serious bugs, including crashes and data loss, that are hard to reproduce and fix because they depend on the relative execution times of individual threads. It’s all too common that race problems don’t show up when you run your application in Debugger mode.

A typical way to fix race problems is to protect shared resources by blocking other threads from executing by locking them. But the lock itself can also cause jitter and other more serious problems (including deadlocks and starvation).

Dart takes a different approach to this problem. Threads in Dart are called isolates and do not share memory, which avoids the use of most locks. The Isolate transmits information through channels, much like actors in Erlang or Web workers in Javascript.

Dart, like Javascript, is single-threaded, which means it doesn’t allow for preemptive multitasking at all. Instead, the thread explicitly cedes control (by using async/await, Future, or Stream). This gives the developer more control over the implementation. Single-threading helps developers ensure that important features, including animations and transitions, are fully executed and not preempted. This is a huge advantage not only for user interface development, but also for other client-server code.

Of course, if the developer forgets to yield control, this can block other code execution. However, we found that forgetting to cede control was much easier to find and fix (because races are really hard to find) than forgetting to lock.

Memory allocation and garbage collection

Another source of serious jitter problems is garbage collection. In fact, this is just another special form of access to shared resources (memory) by locking mechanisms in many languages. The lock may cause the entire application to stop executing during memory reclamation. The difference is that Dart can do garbage collection almost entirely without locking.

Dart uses an advanced generational garbage collection and memory allocation mechanism, which is fast for handling many short-life objects (especially for responsive user interfaces such as Flutter, which builds an immutable view tree each time). Dart can allocate objects using single-pointer collisions (no locks required). Again, this results in smooth scrolling and animation without any jitter.

Unified layout

Another benefit of Flutter using Dart is that it does not need to separate the layout from the application. It also does not require templates or another layout language such as JSX or XML, nor does it require a separate visual layout tool. Here is a simple Flutter view written in Dart:

new Center(child:
  new Column(children: [
    new Text('Hello, World!'),
    new Icon(Icons.star, color: Colors.green),
  ])
)
Copy the code

                                           

Even if you haven’t used Dart, you can visualize the layout visually from the code.

Note that Flutter now uses Dart 2 and the new keyword is optional, so the layout is simpler and clearer. The static layout code above could be written more like a declarative layout language, like this:

Center(child:
  Column(children: [
    Text('Hello, World!'),
    Icon(Icons.star, color: Colors.green),
  ])
)
Copy the code

Still, I know you’re wondering — why is the lack of a specialized layout language an advantage? But this is a groundbreaking change. One developer in the article “Why Native App Developers Should Take Flutter seriously” wrote:

In Flutter, the layout is written in Dart and nothing else. No XML/ template language, no visual design tools/script design tools.

I have a feeling that many of you are going to cringe a little bit when you hear this. That was my initial reaction. Wouldn’t it be easier to use a visual layout tool? Wouldn’t it be too complicated to write all the layout constraint logic in code?

My answer to the above question is no. You know, it was an eye-opener.

The first part of the answer is the hot updates already mentioned above.

I can’t stress enough that this is light years ahead of Android’s Instant Run or other similar solutions. It works so well, even in large applications. And it’s really fast. That’s what Dart gives you.

In practice, this makes visual editors redundant.

Dart creates a concise, easy-to-understand layout and then lets you see the results instantly with hot updates that are “incredibly fast.” Also, this includes the dynamic parts of your layout. I don’t even miss XCode’s pretty good auto layout.

The result is that WITH Flutter(Dart), I am much more productive in layout than I was with Android/XCode before. Because you don’t have to change context frequently, you reduce the considerable mental burden. Because your brain no longer has to switch to design mode, pick up the mouse and click around, and then start wondering if or how something needs to be programmed. Everything in Flutter is programmed into order. And the API design is pretty good. This layout will quickly become intuitive and much more powerful than the constructors provided by Auto layout or XML layout.

As an example, the following code shows how to programmatically add a dividing line (horizontal line) to a list item at every interval:

return new ListView.builder(itemBuilder: (context, i) {
  if (i.isOdd) return new Divider(); 
  // rest of function
});
Copy the code

In Flutter, all layouts are together, whether static or containing procedural logic. Building complex and beautiful layouts is easier by using some of the new Dart tools, including the Flutter Inspector and Outline View, which take full advantage of all layouts together.

Is Dart a proprietary language?

No, Dart (like Flutter) is completely open source and has a clean open source license as well as an ECMA standard. Dart is popular both inside and outside Google. It is the fastest growing language within Google, used by Adwords, Flutter, Fuchsia, and others; Outside, the Dart repository has over 100 external code contributors.

Another sign of a better Dart openness is the growth of the Dart community outside of Google. For example, we can see that there is a very stable output of Dart related articles and videos from third parties (including Flutter and AngularFlutter), some of which I referenced in this article.

Outside community participants actively develop the Dart package in addition to submitting code to Dart itself. There are now over 3,000 packages in the public Dart package repository, covering Firebase, Redux, RxDart, internationalization, encryption, databases, routing, data sets, and more.

Are Dart programmers easy to hire?

If there aren’t many programmers who know Dart, isn’t it hard to hire a qualified Dart programmer? Dart, on the other hand, makes it easier to recruit programmers because it’s a very easy language to learn quickly. Programmers who already understand languages such as Java, Javascript, Kotlin, C#, or Swift can almost jump right into Dart development. On top of that, hot updates encourage programmers to have fun playing with Dart and trying new things, which makes learning Dart faster and more enjoyable.

One programmer wrote in an article titled “Why Flutter will Take off in 2018” :

Dart, as the language for developing Flutter applications, is simply silly to learn. Google has experience creating simple, well-documented languages like Go. Dart reminds me of Ruby so far, and it’s been a real pleasure to learn. And it’s not just about mobile development, it’s also about web development.

Another article titled “Why Flutter? Not the X frame, right? Or more precisely, why do I put my heart into Flutter? “The article reads:

The Dart language that Flutter uses was also created by Google. To be honest, I’m not a fan of strongly typed languages like C# or Java, but I don’t know why Dart seems to code differently. I feel very comfortable writing code with Dart. Maybe it’s that it’s easy to learn, very straightforward.

Dart is intentionally designed to feel familiar and easy to learn through extensive user experience research and testing. For example, the Flutter team conducted a user experience study with eight developers in early 2017. We gave them a brief introduction to Flutter and then let them play with it for an hour or create a simple view. All participants were able to start programming right away, even if they had never used Dart before. They can focus on writing responsive views rather than the language itself. Dart is amazing.

At the end of the experiment, one participant (who was the fastest at the task) didn’t mention anything about the language, so we asked them if they were aware of which language they were using. They don’t know. Language doesn’t matter; They can start programming with Dart in a matter of minutes.

The hard part of learning a new system is not the language itself, but the language’s libraries, frameworks, tools, patterns, and best practices for writing good code. Dart’s libraries and tools are exceptionally good and well documented. “As an added bonus, they care a lot about the code base and they have some of the best documentation I’ve ever seen,” reads one article. So any extra time you save by learning Dart easily can be used to learn something else.

As direct evidence, there is a large project within Google that wants to port their apps to iOS. They wanted to hire some iOS programmers but decided to give Flutter a try. They looked at how long it took developers to become proficient with Flutter. Their result was that a programmer could master Dart and Flutter development in three weeks. In contrast, they have observed that it takes 5 weeks to familiarize a programmer with Android development (not to mention the fact that they had to hire and train iOS developers).

Finally, in the article “Why we chose Flutter and How it can Make our company better”, they migrated their large enterprise applications on all three platforms (iOS, Android and Web) to Dart. Their conclusion:

Easier to recruit. We now only hire the best candidates, whether they’re from the Web, iOS or Android.

Now we have three times the development capacity because all of our teams are unified into the same code base.

Knowledge sharing has never been more efficient.

With the Dart and the Flutter, their productivity tripled. That’s not really surprising, given what they’ve done before. They, like many other companies, develop three separate apps for three platforms (Web, iOS and Android), using different languages, tools and programmers. By switching to Dart, they no longer had to hire three different programmers. It is also fairly easy to migrate existing applications to Dart.

They and other companies found that once programmers started using Flutter, they fell in love with Dart. They like the simplicity of the language. They like features of the language such as cascading calls, named parameters, async/await, and stream. In addition, they also liked some of Flutter’s features, such as the thermal updates that Dart made possible, and the beautiful, high-performing applications Dart helped them build.

Dart 2

Dart 2 was released at the same time this article was published. Dart 2 is designed to improve the experience of creating client applications, including speed of development, improved developer tools, type safety, and more. Dart 2, for example, implements a complete type system and type inference.

Dart 2 also makes the new keyword optional. This means that the Flutter view can be described without any keywords, making the view code simpler and more readable. As follows:

Widget build(BuildContext context) =>
  Center(child:
    Column(children: [
      Text('Hello, World!'),
      Icon(Icons.star, color: Colors.green),
    ])
  )
Copy the code

Dart 2 makes the use of the const keyword optional in many places through type inference. In a const context, the const keyword becomes redundant. For example, the following declaration:

const breakfast = {
   const Doughnuts(): const [const Cruller(), const BostonCream()], 
};
Copy the code

Can now be replaced with:

const breakfast = {
   Doughnuts(): [Cruller(), BostonCream()],
};
Copy the code

Because breakfast is const, everything else is inferred to be const.

Focus is the secret

Dart 2 focuses on optimizing the client development experience. However, Dart will still be a great language for building server-side, desktop, embedded systems, and other applications.

Focus is good. Almost all long-popular languages benefit from concentration. Such as:

  • C is a system programming language for developing operating systems and compilers. It’s becoming more and more focused on that.
  • Java is a language designed for embedded system development.
  • Javascript is a scripting language for browsers (!) .
  • Even the much-maligned PHP succeeded because of its focus on writing Personal Home Pages, hence its name.

On the other hand, there are many languages that have clearly tried (and failed) to become universal, such as PL/1 and Ada, among others. Their biggest problem is lack of concentration and they have become known as kitchen sinks.

Many of the features that make Dart great for client-side development also make it a good language for server-side development. For example, Dart’s avoidance of preemptive multitasking gives it the same server-side development advantages as Node, with a better and more secure type.

The same applies to embedded system development. Dart’s ability to handle multiple concurrent inputs is key.

Finally, Dart’s success on the client side will inevitably lead to more interest in using it on the server side, just as it did with Javascript and Node. Why force developers to build client-server software in two different languages?

conclusion

These are exciting times for Dart. People who have used Dart love it, and the new features in Dart 2 make it a worthy addition to your toolkit. If you haven’t used Dart yet, I hope this article provides valuable information about how Dart is new and different, and then hopefully you’ll try it as well as Flutter.

(Welcome to pay attention to the front-end weekly translation public account)