Here is the structure of a classic Dart project represented as a tree diagram:
├──bin
│ └── main.dart
├──lib
│ ├── model
│ │ └── user.dart
│ └── services
│ └── auth.dart
├──test
│ ├── model_test.dart
│ └── services_test.dart
├── web
│ ├── index.html
│ ├── main.dart
│ └── styles.css
│ ├──.analysis_options.yaml
│ ├──.gitignore
│ └── pubspec.yaml
Some important points to note:
The lib folder contains the source code files that make up your library. It is organized into sub-folders like model, services etc.
The bin folder contains executable Dart files like main.dart which you can run directly.
The test folder contains test files that test the code in the lib folder.
The web folder contains files specific to web apps - HTML, CSS and the Dart entry point main.dart.
The pubspec.yaml file contains metadata and dependencies for your project.
The .gitignore file tells Git which files to ignore when committing.
The .analysis_options.yaml file contains config for the Dart Analyzer.
Hope this tree diagram representation helps visualize the structure of a classic Dart project! Let me know if you have any other questions.
File extension
The extension .dart is only used for Dart source files, i.e. files that contain Dart code.
Other file types used in Dart projects include:
.html: For HTML files used in web apps
.css: For CSS files used in web apps
.js: For JavaScript files
.yaml: For YAML configuration files like pubspec.yaml
.gitignore: For the Git ignore file
.analysis_options.yaml: For the Dart Analyzer config file
So in summary:
The .dart extension is used for Dart source files only, i.e. library files, executable files, test files, web entry points and part files.
Other file types used in Dart projects like HTML, CSS, JS, YAML and text config files use their standard extensions like .html, .css, .js, .yaml etc.
Hope this clarifies that the .dart extension is specific to Dart source files, and is not used for all file types in a Dart project.
Project Type
You can build a wide variety of projects with the Dart programming language, including:
• Web applications - Dart can compile to JavaScript, so it's perfect for building fast and secure web apps.
• Server-side applications - Dart has a native server-side runtime called Dart VM, so you can build server-side APIs, microservices, and command-line tools.
• Desktop applications - With Dart's native desktop runtime, you can build desktop apps for Windows, macOS and Linux.
• Mobile applications - Using the Flutter framework, you can build native mobile apps for both Android and iOS from the same Dart codebase.
• Games - Dart is a great choice for building 2D and 3D games thanks to libraries like StageXL and DartFX.
• Backend services - Dart's support for asynchronous programming and its efficient runtime make it suitable for building high performance backend services.
• ML/AI applications - Libraries like Dart ML and Tensor Flow provide APIs to build machine learning and AI applications in Dart.
• IoT applications - Dart's native runtimes allow you to build apps for devices like Raspberry Pi and Arduino.
• Cross-platform applications - Since Dart can compile to JavaScript and also has native runtimes, you can build apps that run on the web, mobile and desktop from the same codebase.
So in short, you have a lot of flexibility in the types of projects you can build with Dart - from simple web apps to complex AI/ML applications, games, and cross-platform apps. The choice of project depends mainly on your requirements and preferences.
Packages & Libraries
Packages and libraries are two ways to organize Dart code. Here's the difference:
Packages:
Packages are self-contained units of Dart code that can be imported and used by other Dart projects.
They are defined in a pubspec.yaml file.
This file specifies the package name, version, description and dependencies.
Packages can contain one or more libraries.
Libraries:
Libraries are individual units of Dart code that define APIs using classes, functions, types, etc.
They are defined in .dart files.
Libraries are usually organized based on functionality. For example, a UI library, a utility library, etc.
Libraries are exposed as part of packages. A package can contain one or more libraries.
So in summary:
Packages are the highest level of modularity in Dart. They define the scope of an API.
Libraries define the actual APIs within a package. They contain the Dart code - classes, functions, enums, etc.
When you import a package in another Dart project, you are actually importing the libraries defined within that package. For example:
import 'package:some_package/some_library.dart';
Here you are importing the some_library library which is defined within the some_package package.
main()
The main() function in Dart acts as the entry point for executing a Dart program.
The main() file in a Dart project usually has the following:
- The main() function - This is where the execution of the program starts. It has the following signature:
void main(){
// program starts executing from here
}
Imports - Any libraries or packages used in the project are imported atDart Libraries and Packages the top of the main file.
Variables - Any global variables used throughout the program can be declared here.
Function declarations - Any utility functions used in the program can be declared here.
The main logic - The main logic and workflow of the program is written inside the main() function.
For example, a simple main.dart file could be:
import 'package:some_package/some_library.dart';
void main() {
var name = 'John';
sayHello(name);
}
void sayHello(String name) {
print('Hello $name!');
}
Here:
We imported a library
Declared a global variable
name
Declared a function
sayHello()
The main logic is in the
main()
function which callssayHello()
So in summary, the main.dart file:
Contains the main() entry point function
Imports any required libraries/packages
Declares global variables
Defines utility functions
Contains the main logic of the program
Main is unique
No, a Dart project can only have one main() function. Having multiple main() functions is not allowed and will result in an error.
The main() function acts as the entry point of the program, so logically only one main() function makes sense.
If you want to split up the logic in your program, you should:
Define utility functions in libraries and import those libraries
Call those utility functions from your single main() function
For example:
// util.dart
void doSomething() {
// some logic...
}
void doSomethingElse() {
// some other logic...
}
// main.dart
import 'util.dart';
void main() {
doSomething();
doSomethingElse();
}
Here we have:
Defined 2 utility functions in util.dart
Imported util.dart in main.dart
Called those utility functions from our single main() function
So the best practice is to split up your logic into reusable functions and libraries, but still have a single main() function that acts as the entry point.
Public classes
There is no limit to the number of public classes you can create in a Dart file. You can have as many public classes as you want in a single file.
However, as mentioned in the previous answer, it is considered good practice to:
Keep related classes in the same file
Keep files focused - one or a few closely related classes per file
This results in code that is organized, clean and easy to navigate.
Also, note that:
Public classes can be used anywhere in your Dart app
Private classes (prefixed with _) can only be used within the file they are defined
For example:
// user.dart
class User {
// Public class
}
class _PrivateClass {
// Private class - can only be used within this file
}
You can then use the User class anywhere like this:
import 'user.dart';
void main() {
User user = User();
}
But you cannot use the _PrivateClass outside of user.dart.
So in summary:
There is no limit on the number of public classes per Dart file
But for code organization, focus each file on 1-3 closely related public classes
Use private classes to encapsulate implementation details within a file
Folders
Yes, in Dart a package is closely related to a folder.
A Dart package consists of:
A folder - Contains the Dart files that make up the package
A pubspec.yaml file - Contains metadata about the package
For example, a simple Dart package structure could look like this:
my_package/
├── lib/
│ ├── util.dart
│ └── main.dart
└── pubspec.yaml
Here:
my_package
is the package folderlib
is the lib folder, which contains the Dart files that make up the packageutil.dart
andmain.dart
are the Dart source filespubspec.yaml
is the package metadata file
So in summary:
A Dart package consists of a folder
This folder contains:
Dart source files (in a
lib
folder by convention)A
pubspec.yaml
file
The folder structure organizes and contains the files that make up the package
The pubspec.yaml
file then provides metadata about the package like:
Package name
Version
Dependencies
Authors
Description
Yaml files
Yaml files in Dart use the YAML syntax. Some key points about the YAML syntax:
It uses indentation to indicate nesting, instead of curly braces {} or parentheses ()
Uses dashes - to indicate lists
Uses colons : to associate keys with values
For example:
name: my_package # String value
version: 1.0.0 # String value
description: A useful Dart package # String value
authors: # List of strings
- John Doe
- Jane Doe
dependencies: # Map
crypto: ^2.0.0
http: any
Here:
name
,version
,description
are keys associated with string values using:
authors
is a list denoted by the dash-
dependencies
is a map with package names as keys and version constraints as values
The indentation indicates nesting, so the list items under authors
are indented once, and the map values under dependencies
are indented twice.
Some other points:
Strings can be single/double quoted
Boolean values are
true
andfalse
(no quotes)Comments start with
#
CLI Create
You can use the Dart CLI (command line interface) to create a new Dart project using the dart create
command.
To create a new Dart project from the CLI, follow these steps:
Open your terminal or command prompt.
Run the
dart create
command with the project name:
dart create <project_name>
For example:
dart create my_first_app
- This will create a folder with that name and generate the basic project structure:
A
lib
folder containing amain.dart
fileA
test
folder for testsA
pubspec.yaml
fileA
.gitignore
file
- Change directory into your new project:
cd <project_name>
- You can then run Dart commands from within your project folder, for example:
dart run bin/main.dart # Runs your app
dart test # Runs unit tests
dart pub get # Downloads dependencies
- You can also use VS Code or any IDE to open your new Dart project folder.
So in summary, the basic steps are:
Run
dart create <project_name>
cd <project_name>
Run Dart commands from the project folder
Open in VS Code or IDE
Interpretor
Dart is an interpreted language. This means that Dart code is not compiled to machine code before execution. Instead, Dart code is compiled to an intermediate bytecode which is then interpreted at runtime.
This is in contrast to compiled languages like C++ and Java, where the code is first compiled to machine code, and then the machine code is executed directly by the CPU.
Some benefits of Dart being an interpreted language are:
Faster development cycle: Since the code does not need to be compiled before each run, developers can make changes and run the code quickly.
Easier debugging: Since the original source code is available at runtime, debugging is simpler compared to compiled languages.
Cross-platform: The Dart bytecode can be interpreted to run on different platforms.
However, interpreted languages also tend to be slower than compiled languages, since the interpretation layer introduces some overhead.
To overcome this, Dart uses an optimizing compiler called "Just-in-Time (JIT) compiler" which compiles Dart bytecode to machine code at runtime. This helps improve the performance of Dart applications.
So in summary, yes Dart is an interpreted language. Dart code is first compiled to an intermediate bytecode which is then interpreted at runtime (with some JIT compilation optimizations). This allows Dart to have a fast development cycle while still achieving good performance.
Execution
You can execute a Dart project from the command line and pass parameters using the dart run
command.
To pass parameters when running a Dart project, you use the syntax:
dart run [options] <entry-point> -- [arguments]
Where:
options
are optional Dart VM options<entry-point>
is the path to your Dart file to run, usuallybin/main.dart
--
is used to separate Dart options from your program arguments[arguments]
are the arguments you want to pass to your Dart program
For example, if you have a bin/main.dart
file like this:
void main(List<String> arguments) {
print(arguments);
}
You can run it and pass arguments like this:
dart run bin/main.dart -- hello world
The output will be:
[hello, world]
You can pass as many arguments as you want, separated by spaces:
dart run bin/main.dart -- arg1 arg2 arg3
The arguments will be available in the arguments
list that is passed to your main()
function.
You can also define a --help
option in your program to print usage information:
void main(List<String> arguments) {
if (arguments.contains('--help')) {
print('Usage: dart_program arg1 arg2');
}
}
And then invoke it with:
dart run bin/main.dart -- --help
So in summary, you use dart run <entry-point> -- [arguments]
to execute a Dart program from the command line and pass arguments to it.
Disclaim: I have used Rix (AI) to create this article. If you have reach this article, congratulation. Many other do not. Please do not tell anybody about my article. These are my private notes to learn Dart.