Book Image

Mastering Dart

By : Sergey Akopkokhyants
Book Image

Mastering Dart

By: Sergey Akopkokhyants

Overview of this book

Table of Contents (19 chapters)
Mastering Dart
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Modularity and a namespace


Complex things are the foundation of our world. To understand the complexity of the things around us, it is necessary to understand the parts that make them up. The evolution of complex things is due to functional and behavioral modularity. Functional modularity is the composition of smaller independent components with clear boundaries and functions. Behavioral modularity is mainly about traits and attributes that can evolve independently.

Modularity is nothing new. Earlier, product manufacturers figured out ways to increase the output and quality of the product, while still managing to reduce the cost pressures. They accomplished this through modularity. Modular design can be seen in automotive industry, buildings, and many other industries. Henry Ford introduced the notion of modularity in his assembly line with standardized and interchangeable parts. As a result, he reduced the production cycles and costs to achieve the mass production of his automobiles. A lot of these concepts are still used by many companies today.

Modularity in software development

Representation of complex things as a set of parts is called decomposition. By analogy, the real-world complex software may be broken into functional parts called modules. Each module can be created, changed, tested, used, and replaced separately.

Let's take a look at the benefits of modularity. For the sake of simplicity, we divide them into development and postproduction phases. Each of these phases has its own specific tasks to be solved in the scope of that phase.

The development phase has the following benefits:

  • Each module requires less code.

  • New features or changes can be introduced to modules in isolation, separate from the other modules.

  • Errors can be easily identified and fixed in a module.

  • Modules can be built and tested independently.

  • Programmers writing the modules can collaborate on the same application.

  • The same modules can be reused in many applications.

  • Applications have a main module and many auxiliary modules. Each module encapsulates a specific functionality and each one is integrated through loosely coupled communication channels provided by the main module.

The postproduction phase has the following benefits:

  • Modules kept in a versioning system can be easily maintained and tested

  • Fixed and noninfrastructural changes in a module can be done without affecting other modules

One significant disadvantage of modularity is that it increases complexity when managing many modules, especially when each one is individually versioned, updated, and has dependencies on the other modules.

Modularity in Dart

The Dart language was designed by keeping the modules in mind. Modularity in Dart is realized through packages, libraries, and classes.

A library exposes functionality as a set of interfaces and hides the implementation from the rest of the world. As a concept, it's very similar to the separation of concern between objects in object-oriented programming (OOP). Separating an application into libraries helps minimize tight coupling and makes it easier to maintain the code. A library can be implemented as a simple function, a single class, several classes, or a collection of parts representing the entire API of a library. The Dart application is a library as well.

A package is simply a directory that contains a pubspec.yaml file and may include any number of libraries and resources. The pubspec.yaml file contains significant information about the package, its authors, and its dependencies on other packages. Here is a sample pubspec.yaml file:

name: animation_library
version: 0.1.0
author: Sergey Akopkokhyants
description: Animation library for Web application
dependencies:
  browser: any

The real pubspec.yaml file can have more fields as specified at https://www.dartlang.org/tools/pub/pubspec.html.Before a package can be used, it must be published to a package management system, which is available as an online resource called pub at https://pub.dartlang.org/. To publish and retrieve packages from pub, we use a utility application of the same name. The pub utility uses information about dependencies from the pubspec.yaml file to retrieve all the necessary packages from the following locations:

Dart Editor manages dependencies automatically for you. You can publish your packages right in Dart Editor.

Libraries

A namespace is a container for all the members of a library. A namespace is defined by the library name. A library that is implicitly named has an empty namespace. This results in a conflict when trying to import libraries with the same namespaces. Import library namespace conflicts can be easily avoided with a prefix clause (as) and a name prefix.

The following is an implicitly named library in which all the resources from dart:html are made available within the scope of our library with the prefix dom:

/**
 * Implicitly named library.
 * The dart:core library is automatically imported.
 */
import 'dart:html' as dom;

/**
 * Get [Element] by [id].
 */
dom.Element getById(String id) => dom.querySelector('#$id');

The library namespace make sense only in the Dart environment.

Note

The code that is compiled in JavaScript loses all the library information.

Dart implements encapsulation through privacy. Each member or identifier of a library has one of the two levels of access: private or public. Private members are visible only inside the library in which they are declared. Conversely, members with a public access are visible everywhere. The difference between them is the underscore prefix (_), as shown in the following code:

// Animation library.
library animation;

// Class publicly available everywhere.
class Animation {
  // ...
}

// Class visible only inside library.
class _AnimationLibrary {
  // ...
}

// Variable publicly available everywhere.
var animationSpeed;

The preceding code shows an animation library with two classes and one variable. The Animation class and the animationSpeed variable are public, and therefore visible outside the library. The _AnimationLibrary class is private and it can be used only in the library.

Public access can be managed with the show and hide extensions of the import statement. Use the following show extension with a specific class, which will then be available inside the library in which it is imported:

import 'animation.dart' as animation show Animation;

// Main entry into Dart Web application.
main() {
  // Animate
  new animation.Animation();
}

The animation prefix in the import statement defines the namespace to import the animation.dart library. All members of the animation.dart library are available in the global namespace via this prefix. We are referring to an Animation class with the animation prefix, as shown here:

Use the hide extension with a specific class, which will then be unavailable inside the library in which it is imported; everything else from the library will be available, as shown in the following code:

import 'animation.dart' as animation hide Animation;

// Main entry into Dart Web application.
main() {
  // Animate
  var speed = animation.animationSpeed;
}

Now we hide the Animation class, but all the other public members in the namespace animation are still available, as seen in the following screenshot:

As you can see, the members of the imported library become invisible. This happens because the library exports members from the public namespace. It can be possible to re-export the imported library with the export statement if this necessary export statement can be managed with show and hide as it was for the import statement, as shown in the following code:

library animation.css;

import 'animation.dart' as animation;
export 'animation.dart' show Animation;

class CssAnimation extends animation.Animation {
  // ...
}

The preceding code shows the animation.css library. We export the Animation class as part of the library namespace. Let's take a look at how we can use them:

There are the exported Animation and original CssAnimation classes available for use in our main code. Without the export, the Animation class would be inaccessible in the main code.