Download PDF Node js design patterns master best practices to build modular and scalable server side

Page 1


Node js Design Patterns Master best practices to build modular and scalable server side web applications 2nd Edition Casciaro

Visit to download the full and correct content document: https://textbookfull.com/product/node-js-design-patterns-master-best-practices-to-buil d-modular-and-scalable-server-side-web-applications-2nd-edition-casciaro/

More products digital (pdf, epub, mobi) instant download maybe you interests ...

Node js web development server side development with Node 10 made easy Fourth Edition. Edition David Herron

https://textbookfull.com/product/node-js-web-development-serverside-development-with-node-10-made-easy-fourth-edition-editiondavid-herron/

Pro Express js Master Express js The Node js Framework For Your Web Development Mardan Azat

https://textbookfull.com/product/pro-express-js-master-expressjs-the-node-js-framework-for-your-web-development-mardan-azat/

RESTful Web API Design with Node js 10 Learn to create robust RESTful web services with Node js MongoDB and Express js 3rd Edition English Edition Valentin Bojinov

https://textbookfull.com/product/restful-web-api-design-withnode-js-10-learn-to-create-robust-restful-web-services-with-nodejs-mongodb-and-express-js-3rd-edition-english-edition-valentinbojinov/

Learning Node js Development Learn the fundamentals of Node js and deploy and test Node js applications on the web 1st Edition Andrew Mead

https://textbookfull.com/product/learning-node-js-developmentlearn-the-fundamentals-of-node-js-and-deploy-and-test-node-jsapplications-on-the-web-1st-edition-andrew-mead/

Django Design Patterns and Best Practices 2nd Edition Arun Ravindran

https://textbookfull.com/product/django-design-patterns-and-bestpractices-2nd-edition-arun-ravindran/

Node js 8 the Right Way Practical Server Side JavaScript That Scales 1st Edition Jim Wilson

https://textbookfull.com/product/node-js-8-the-right-waypractical-server-side-javascript-that-scales-1st-edition-jimwilson/

Node js for Embedded Systems Using Web Technologies to Build Connected Devices 1st Edition Patrick Mulder

https://textbookfull.com/product/node-js-for-embedded-systemsusing-web-technologies-to-build-connected-devices-1st-editionpatrick-mulder/

Node js MongoDB and Angular Web Development The definitive guide to using the MEAN stack to build web applications Developer s Library 2nd Edition Brad Dayley & Brendan Dayley & Caleb Dayley

https://textbookfull.com/product/node-js-mongodb-and-angular-webdevelopment-the-definitive-guide-to-using-the-mean-stack-tobuild-web-applications-developer-s-library-2nd-edition-braddayley-brendan-dayley-caleb-dayley/

Ultimate Node.js for Cross-Platform App Development: Learn to Build Robust, Scalable, and Performant ServerSide JavaScript Applications with Node.js (English Edition) Kumar

https://textbookfull.com/product/ultimate-node-js-for-crossplatform-app-development-learn-to-build-robust-scalable-andperformant-server-side-javascript-applications-with-node-js-

1

Welcome to the Node.js platform

Some principles and design patterns literally define the Node.js platform and its ecosystem; the most peculiar ones are probably its asynchronous nature and its programming style that makes heavy use of callbacks. It's important that we first dive into these fundamental principles and patterns, not only for writing correct code, but also to be able to take effective design decisions when it comes to solving bigger and more complex problems.

Another aspect that characterizes Node.js is its philosophy. Approaching Node.js is in fact way more than simply learning a new technology; it's also embracing a culture and a community. We will see how this greatly influences the way we design our applications and components, and the way they interact with those created by the community.

In addition to these aspects it's worth knowing that the latest versions of Node.js introduced support for many of the features described by ES2015, which makes the language even more expressive and enjoyable to use. It is important to embrace these new syntactical and functional additions to the language to be able to produce more concise and readable code and come up with alternative ways to implement the design patterns that we are going to see throughout this book.

In this chapter, we will learn the following topics:

The Node.js philosophy, the Node way Node 5 and ES2015

The reactor pattern: the mechanism at the heart of the Node.js asynchronous architecture

The Node.js philosophy

Every platform has its own philosophy-a set of principles and guidelines that are generally accepted by the community, an ideology of doing things that influences the evolution of a platform, and how applications are developed and designed. Some of these principles arise from the technology itself, some of them are enabled by its ecosystem, some are just trends in the community, and others are evolutions of different ideologies. In Node.js, some of these principles come directly from its creator, Ryan Dahl, from all the people who contributed to the core, from charismatic figures in the community, and some of the principles are inherited from the JavaScript culture or are influenced by the Unix philosophy.

None of these rules are imposed and they should always be applied with common sense; however, they can prove to be tremendously useful when we are looking for a source of inspiration while designing our programs.

You can find an extensive list of software development philosophies in Wikipedia at http://en.wikipedia.org/wiki/List_of_software_development _philosophies

Small core

The Node.js core itself has its foundations built on a few principles; one of these is, having the smallest set of functionality, leaving the rest to the so-called userland (or userspace),the ecosystem of modules living outside the core. This principle has an enormous impact on the Node.js culture, as it gives freedom to the community to experiment and iterate fast on a broader set of solutions within the scope of the userland modules, instead of being imposed with one slowly evolving solution that is built into the more tightly controlled and stable core. Keeping the core set of functionality to the bare minimum then, not only becomes convenient in terms of maintainability, but also in terms of the positive cultural impact that it brings on the evolution of the entire ecosystem.

Small modules

Node.js uses the concept of module as a fundamental mean to structure the code of a program. It is the brick for creating applications and reusable libraries called packages (a package is also frequently referred to as just module; since, usually it has one single module as an entry point). In Node.js, one of the most evangelized principles is to design small modules, not only in terms of code size, but most importantly in terms of scope.

This principle has its roots in the Unix philosophy, particularly in two of its precepts, which are as follows:

Small is beautiful. Make each program do one thing well.

Node.js brought these concepts to a whole new level. Along with the help of npm, the official package manager, Node.js helps solving the dependency hell problem by making sure that each installed package will have its own separate set of dependencies, thus enabling a program to depend on a lot of packages without incurring in conflicts. The Node way, in fact, involves extreme levels of reusability, whereby applications are composed of a highnumber of small, well-focused dependencies. While this can be considered unpractical or even totally unfeasible in other platforms, in Node.js this practice is encouraged. As a consequence, it is not rare to find npm packages containing less than 100 lines of code or exposing only one single function.

Besides the clear advantage in terms of reusability, a small module is also considered to be the following:

Easier to understand and use

Simpler to test and maintain

Perfect to share with the browser

Having smaller and more focused modules empowers everyone to share or reuse even the smallest piece of code; it's the Don't Repeat Yourself (DRY) principle applied at a whole new level.

Small surface area

In addition to being small in size and scope, Node.js modules usually also have the characteristic of exposing only a minimal set of functionality. The main advantage here is an increased usability of the API, which means that the API becomes clearer to use and is less exposed to erroneous usage. Most of the time, in fact, the user of a component is interested only in a very limited and focused set of features, without the need to extend its functionality or tap into more advanced aspects.

In Node.js, a very common pattern for defining modules is to expose only one piece of functionality, such as a function or a constructor, while letting more advanced aspects or secondary features become properties of the exported function or constructor. This helps the user to identify what is important and what is secondary. It is not rare to find modules that expose only one function and nothing else, for the simple fact that it provides a single,

unmistakably clear entry point.

Another characteristic of many Node.js modules is the fact that they are created to be used rather than extended. Locking down the internals of a module by forbidding any possibility of an extension might sound inflexible, but it actually has the advantage of reducing the use cases, simplifying its implementation, facilitating its maintenance, and increasing its usability.

Simplicity and pragmatism

Have you ever heard of the Keep It Simple, Stupid (KISS) principle? Or the famous quote:

Simplicity is the ultimate sophistication.

Leonardo da Vinci

Richard P. Gabriel, a prominent computer scientist coined the term worse is better to describe the model, whereby less and simpler functionality is a good design choice for software. In his essay,The rise of worse is better, he says:

The design must be simple, both in implementation and interface. It is more important for the implementation to be simple than the interface. Simplicity is the most important consideration in a design.

Designing a simple, as opposed to a perfect, feature-full software, is a good practice for several reasons: it takes less effort to implement, allows faster shipping with less resources, is easier to adapt, and is easier to maintain and understand. These factors foster the community contributions and allow the software itself to grow and improve.

In Node.js, this principle is also enabled by JavaScript, which is a very pragmatic language. It's not rare, in fact, to see simple functions, closures, and object literals replacing complex class hierarchies. Pure object-oriented designs often try to replicate the real world using the mathematical terms of a computer system without considering the imperfection and the complexity of the real world itself. The truth is that our software is always an approximation of the reality and we would probably have more success in trying to get something working sooner and with reasonable complexity, instead of trying to create a near-perfect software with a huge effort and tons of code to maintain.

Throughout this book, we will see this principle in action many times. For example, a considerable number of traditional design patterns, such as Singleton or Decorator can have a trivial, even if sometimes not foolproof implementation and we will see how an uncomplicated, practical approach most of the time is preferred to a pure, flawless design.

Introduction to Node 5 and ES2015

At the time of writing the most recent major versions of Node.js (Node 4 and Node 5) come with a great addition to the language: a wide support for many of the new features introduced in the ECMAScript 2015 specification (in short ES2015 and formerly known also as ES6) which aims to make the language even more flexible and enjoyable.

Throughout this book, we will widely adopt some of these new features in the code examples. These concepts are still fresh within the Node.js community so it's worth having a quick look at the most important ES2015 specific features currently supported in Node.js. Our version of reference is Node 5, more specifically version 5.1.

Many of these features will work correctly only when the strict mode is enabled. Strict mode can be easily enabled by adding ause strict; statement at the very beginning of your script. For the sake of brevity, we will not write this line in our code examples but you should remember to add it to be able to run them correctly.

The following list is not meant to be exhaustive but just an introduction to the ES2015 features supported in Node, so that you can easily understand all the code examples in the rest of this book.

Arrow Function

One of the most appreciated features introduced by ES2015 is the support for arrow functions. Arrow function is a more concise syntax for defining functions, especially useful when defining a callback. To better understand the advantages of this syntax let's see first an example of a classic filtering on an array:

var numbers = [2, 6, 7, 8, 1];

var even = numbers.filter(function(x) { return x%2 === 0; });

This code above can be rewritten as follows using the arrow function syntax:

var numbers = [2, 6, 7, 8, 1];

var even = numbers.filter((x) => x%2 === 0);

The filter function can be defined inline, the keyword function is removed, leaving only the list of parameters, which is followed by => (the arrow), which in turn is followed by the body of the function. When the body of the function is just one line there's no need to write the return keyword as it is applied implicitly. If we need to add more lines of code to the body of the function, we can wrap them in curly brackets, but beware that in this case the

return is not automatically implied, so it needs to be stated explicitly, as in the following example:

var numbers = [2, 6, 7, 8, 1]; var even = numbers.filter((x) => { if (x%2 === 0) { console.log(x + ' is even!'); return true; } });

But there is another important feature to know about arrow functions: arrow functions are bound to their lexical scope. This means that inside an arrow function the value of this is the same as in the parent block. Let's clarify this concept with an example:

function DelayedGreeter(name) { this.name = name; }

DelayedGreeter.prototype.greet = function() { setTimeout( function cb() { console.log('Hello ' + this.name); }, 500); };

let greeter = new DelayedGreeter('World'); greeter.greet(); // will print "Hello undefined"

In this code we are defining a simple greeter prototype which accepts a name as argument. Then we are adding the greet method to the prototype. This function is supposed to print Hello and the name defined in the current instance after 500 milliseconds it has been called. But this function is broken because inside the timeout callback function (cb), the scope of the function is different from the scope of the greet method and the value of this is undefined

Before Node.js introduced support for arrow functions, to fix this we needed to change the greet function using bind as follows:

DelayedGreeter.prototype.greet = function() { setTimeout( (function cb() { console.log('Hello ' + this.name); }).bind(this), 500); };

But since we have now arrow functions and since they are bound to their lexical scope, we can just use an arrow function as callback to solve the issue:

DelayedGreeter.prototype.greet = function() { setTimeout( () => console.log('Hello ' + this.name), 500); };

This is a very handy feature, most of the time it makes our code more concise and straightforward.

Let and Const

Historically JavaScript offered only function scope and global scope to control the lifetime and the visibility of a variable. For instance if you declare a variable inside the body of an if statement the variable will be accessible even outside the statement, whether or not the body of the statement has been executed. Let's see it more clearly with an example:

if (false) { var x = "hello"; }

console.log(x);

This code will not fail as we might expect and it will just print undefined in the console. This behavior has been cause of many bugs and frustration and that is the reason why ES2015 introduces the let keyword to declare variables that respect the block scope. Let's replace var with let in our previous example:

if (false) { let x = "hello"; } console.log(x);

This code will raise a ReferenceError: x is not defined because we are trying to print a variable that has been defined inside another block scope.

To give a more meaningful example we can use the let keyword to define a temporary variable to be used as an index for a loop:

for (let i=0; i < 10; i++) { // do something here } console.log(i);

As in the previous example, this code will raise a ReferenceError: i is not defined error.

This protective behavior introduced with let allows us to write safer code, because if we accidentally access variables that belong to another scope we will get an error that will

allow us to easily spot the bug and avoid potentially dangerous side effects.

ES2015 introduces also the const keyword. This keyword allows to declare read-only variables. Let's see a quick example:

const x = 'This will never change'; x = '...';

This code will raise a TypeError: Assignment to constant variable error because we are trying to change the value of a constant.

Constants are extremely useful when you want to protect a value from being accidentally changed in your code.

Class syntax

ES2015 introduces a new syntax to leverage prototypical inheritance in a way that should sound more familiar to all the developers that come from classic object oriented languages such as Java or C#. It's important to underline that this new syntax does not change the way objects are managed internally by the JavaScript runtime, they still inherits properties and functions through prototypes and not through classes. While this new alternative syntax can be very handy and readable, as a developer is important to understand that it is just a syntactic sugar.

Let's see how it works with a trivial example. First of all, let's describe a Person using the classic prototype based approach:

function Person(name, surname, age) { this.name = name; this.surname = surname; this.age = age; }

Person.prototype.getFullName = function() { return this.name + ' ' + this.surname; }

Person.older = function(person1, person2) { return (person1.age >= person2.age) ? person1 : person2; }

As you can see a person has a name, a surname and an age. We are providing to our prototype a helper function that allows us to easily get the full name of a person object and a generic helper function accessible directly from the Person prototype that returns the

older person between two Person instances given as input.

Let's see now how we can implement the same example using the new handy ES2015 class syntax:

class Person {

constructor (name, surname, age) { this.name = name; this.surname = surname; this.age = age; }

getFullName () { return this.name + ' ' + this.surname; }

static older (person1, person2) { return (person1.age >= person2.age) ? person1 : person2; } }

This syntax results more readable and straightforward to understand. We are explicitly stating what is the constructor for the class and declaring the function older as a static method.

Both implementations are completely interchangeable, but the real killer feature of the new syntax is the possibility of extending the Person prototype using the extend and the super keywords. Let's assume we want to create the PersonWithMiddlename class:

class PersonWithMiddlename extends Person { constructor (name, middlename, surname, age) { super(name, surname, age); this.middlename = middlename; }

getFullName () { return this.name + ' ' + this.middlename + ' ' + this.surname; } }

What is worth noticing in this second example is that the syntax really resembles what is common in other object oriented languages. We are declaring the class from which we want to extend, we define a new constructor that can call the parent one using the keyword super and we override the getFullName method to add support for our middle name.

Enhanced Object literals

As long with the new class syntax, ES2015 introduced an enhanced object literals syntax. This syntax offers a shorthand to assign variables and functions as members of the object, allows to define computed member names at creation time and also handy setters and getters methods.

Let's make all of this clear with some examples:

let x = 22; let y = 17; let obj = { x, y };

obj will be an object containing the keys x and y, respectively with the values 22 and 17.

We can do the same thing with functions:

module.exports = { square (x) { return x * x; }, cube (x) { return x * x * x; }

};

In this case we are writing a module that exports the functions square and cube mapped to properties with the same name. Notice that we don't need to specify the keyword function.

Let's see in another example how we can use computed property names:

let namespace = '-webkit-'; let style = { [namespace + 'box-sizing'] : 'border-box', [namespace + 'box-shadow'] : '10px 10px 5px #888888' };

In this case the resulting object will contain the properties -webkit-box-sizing andwebkit-box-shadow

Let's see now how we can use the new setter and getter syntax by jumping directly to an example:

let person = { name : 'George', surname : 'Boole',

get fullname () { return this.name + ' ' + this.surname; },

set fullname (fullname) { let parts = fullname.split(' '); this.name = parts[0]; this.surname = parts[1]; } }

console.log(person.fullname); // "George Boole" console.log(person.fullname = 'Alan Turing'); // "Alan Turing" console.log(person.name); // "Alan"

In this example we are defining three properties, two normal name and surname and a computed property fullname through the set and get syntax. As you can see from the result of the console.log calls, we can access the computed property as if it was a regular property inside the object for both reading and writing the value. It's worth noticing that the second call to console.log prints Alan Turing . This happens because by default every set function returns the value that is returned by the get function for the same property, in this case get fullname.

Map and Set collections

As JavaScript developers we are used to create hash maps using plain objects. ES2015 introduces a new prototype called Map that is specifically designed to leverage hash map collections in a more secure, flexible and intuitive way. Let's see a quick example:

let profiles = new Map(); profiles.set('twitter', '@adalovelace'); profiles.set('facebook', 'adalovelace'); profiles.set('googleplus', 'ada');

profiles.size; // 3 profiles.has('twitter'); // true profiles.get('twitter'); // "@adalovelace" profiles.has('youtube'); // false profiles.delete('facebook'); profiles.has('facebook'); // false profiles.get('facebook'); // undefined for (let entry of profiles) { console.log(entry); }

As you can see the Map prototype offers several handy methods like set, get, has and delete and the size attribute. We can also iterate through all the entries using the for ... of syntax. Every entry in the loop will be an array containing the key as first element and the value as second element. This interface is very intuitive and self-explanatory.

But what makes maps really interesting is the possibility of using functions and objects as keys of the map and this was something that is not entirely possible using plain objects, because with objects all the keys are automatically casted to strings. This opens new opportunities, for example we can build a micro testing framework leveraging this feature:

let tests = new Map();

tests.set(() => 2+2, 4);

tests.set(() => 2*2, 4); tests.set(() => 2/2, 1);

for (let entry of tests) {

console.log((entry[0]() === entry[1]) ? ' ' : ''); }

As you can see in this last example, we are storing functions as keys and expected results as values. Then we can iterate through our hash map and execute all the functions. It's also worth noticing that when we iterate through the map all the entries respect the order in which they have been inserted, this is also something that was not always guaranteed with plain objects.

Along with Map, ES2015 also introduces the Set prototype. This prototype allows us to easily construct sets, which means lists with unique values.

let s = new Set([0, 1, 2, 3]);

s.add(3); // will not be added s.size; // 4 s.delete(0); s.has(0); // false

for (let entry of s) { console.log(entry); }

As you can see in this example the interface is quite similar to the one we have just seen for

Map. We have the methods add (instead of set), has and delete and the property size. We can also iterate through the set and in this case every entry is a value, in our example it will be one of the numbers in the set. Finally, sets can also contain objects and functions as values.

WeakMap and WeakSet collections

ES2015 defines also a weak version of the Map and the Set prototypes called WeakMap and WeakSet.

WeakMap is quite similar to Map in terms of interface, there are only two main differences: there is no way to iterate all over the entries and it allows to have only objects as keys. While this might seem as a limitation there is a good reason behind it, in fact the distinctive feature of WeakMap is that it allows objects used as keys to be garbage collected when the only reference left is inside a WeakMap. This is extremely useful when we are storing some metadata associated to an object that might get deleted during the regular lifetime of the application. Let's see an example:

let obj = {}; let map = new WeakMap(); map.set(obj, {metadata: "some_metadata"}); console.log(map.get(obj)); // {metadata: "some_metadata"} obj = undefined; // now obj and metadata will be cleaned up in the next gc cycle

In this code we are creating a plain object called obj. Then we store some metadata for this object in a new WeakMap called map. We can access this metadata with the map.get method. Later, when we cleanup the object by assigning its variable to undefined, the object will be correctly garbage collected and its metadata removed from the map.

Similarly, to WeakMap, WeakSet is the weak version of Set: it exposes the same interface of Set but it allows to store only objects and cannot be iterated. Again the difference with Set is that WeakSet allows objects to be garbage collected when their only reference left is in the weak set.

It's important to understand that WeakMap and WeakSet are not better or worse than Map and Set, they are simply more suitable for different use cases.

Template Literals

ES2015 offers a new alternative and more powerful syntax to define strings: the template

literals. This syntax uses back ticks (`) as delimiters and offers several benefits compared to regular quoted (') or double-quoted (") delimited strings. The main ones are that template literals syntax can interpolate variables or expressions using ${expression} inside the string (this is the reason why this syntax is called template ) and that strings can finally be multiline. Let's see a quick example:

let name = "Leonardo"; let interests = ["arts", "architecture", "science", "music", "mathematics"];

let birth = { year : 1452, place : 'Florence' }; let text = `${name} was an Italian polymath interested in many topics such as ${interests.join(', ')}.

He was born in ${birth.year} in ${birth.place}.`; console.log(text);

This code will print:

Leonardo was an Italian polymath interested in many topics such as arts, architecture, science, music, mathematics. He was born in 1452 in Florence.

A more extended and up to date list of all the supported ES2015 features is available in the official Node.js documentation: https://nodejs.org/en/docs/es6/

The reactor pattern

In this section, we will analyze the reactor pattern, which is the heart of the Node.js asynchronous nature. We will go through the main concepts behind the pattern, such as the single-threaded architecture and the non-blocking I/O, and we will see how this creates the foundation for the entire Node.js platform.

I/O is slow

I/O is definitely the slowest among the fundamental operations of a computer. Accessing the RAM is in the order of nanoseconds (10e-9 seconds), while accessing data on the disk or the network is in the order of milliseconds (10e-3 seconds). For the bandwidth, it is the same story; RAM has a transfer rate consistently in the order of GB/s, while disk and network varies from MB/s to, optimistically, GB/s. I/O is usually not expensive in terms of CPU, but it adds a delay between the moment the request is sent and the moment the operation completes. On top of that, we also have to consider thehuman factor; often, the input of an

application comes from a real person, for example, the click of a button or a message sent in a real-time chat application, so the speed and frequency of I/O don't depend only on technical aspects, and they can be many orders of magnitude slower than the disk or network.

Blocking I/O

In traditional blocking I/O programming, the function call corresponding to an I/O request will block the execution of the thread until the operation completes. This can go from a few milliseconds, in case of a disk access, to minutes or even more, in case the data is generated from user actions, such as pressing a key. The following pseudocode shows a typical blocking read performed against a socket:

//blocks the thread until the data is available data = socket.read(); //data is available print(data);

It is trivial to notice that a web server that is implemented using blocking I/O will not be able to handle multiple connections in the same thread; each I/O operation on a socket will block the processing of any other connection. For this reason, the traditional approach to handle concurrency in web servers is to kick off a thread or a process (or to reuse one taken from a pool) for each concurrent connection that needs to be handled. This way, when a thread gets blocked for an I/O operation it will not impact the availability of the other requests, because they are handled in separate threads.

The following image illustrates this scenario:

The preceding image lays emphasis on the amount of time each thread is idle, waiting for new data to be received from the associated connection. Now, if we also consider that any type of I/O can possibly block a request, for example, while interacting with databases or with the filesystem, we soon realize how many times a thread has to block in order to wait for the result of an I/O operation. Unfortunately, a thread is not cheap in terms of system resources, it consumes memory and causes context switches, so having a long running thread for each connection and not using it for most of the time, is not the best compromise in terms of efficiency.

Non-blocking I/O

In addition to blocking I/O, most modern operating systems support another mechanism to access resources, called non-blocking I/O. In this operating mode, the system call always returns immediately without waiting for the data to be read or written. If no results are available at the moment of the call, the function will simply return a predefined constant, indicating that there is no data available to return at that moment.

For example, in Unix operating systems, the fcntl() function is used to manipulate an existing file descriptor to change its operating mode to non-blocking (with the O_NONBLOCK flag). Once the resource is in non-blocking mode, any read operation will fail with a return code, EAGAIN, in case the resource doesn't have any data ready to be read.

The most basic pattern for accessing this kind of non-blocking I/O is to actively poll the resource within a loop until some actual data is returned; this is called busy-waiting. The following pseudocode shows you how it's possible to read from multiple resources using

non-blocking I/O and a polling loop:

resources = [socketA, socketB, pipeA]; while(!resources.isEmpty()) { for(i = 0; i < resources.length; i++) { resource = resources[i];

//try to read var data = resource.read();

if(data === NO_DATA_AVAILABLE)

//there is no data to read at the moment continue;

if(data === RESOURCE_CLOSED)

//the resource was closed, remove it from the list resources.remove(i); else

//some data was received, process it consumeData(data); } }

You can see that, with this simple technique, it is already possible to handle different resources in the same thread, but it's still not efficient. In fact, in the preceding example, the loop will consume precious CPU only for iterating over resources that are unavailable most of the time. Polling algorithms usually result in a huge amount of wasted CPU time.

Event demultiplexing

Busy-waiting is definitely not an ideal technique for processing non-blocking resources, but luckily, most modern operating systems provide a native mechanism to handle concurrent, non-blocking resources in an efficient way; this mechanism is called synchronous event demultiplexer or event notification interface. This component collects and queues I/O events that come from a set of watched resources, and block until new events are available to process. The following is the pseudocode of an algorithm that uses a generic synchronous event demultiplexer to read from two different resources:

socketA, pipeB; watchedList.add(socketA, FOR_READ); //[1] watchedList.add(pipeB, FOR_READ); while(events = demultiplexer.watch(watchedList)) { //[2] //event loop foreach(event in events) { //[3]

//This read will never block and will always return data data = event.resource.read();

if(data === RESOURCE_CLOSED)

//the resource was closed, remove it from the watched list

demultiplexer.unwatch(event.resource); else //some actual data was received, process it consumeData(data);

These are the important steps of the preceding pseudocode:

The resources are added to a data structure, associating each one of them with a 1. specific operation, in our example a read.

The event notifier is set up with the group of resources to be watched. This call is 2. synchronous and blocks until any of the watched resources is ready for a read. When this occurs, the event demultiplexer returns from the call and a new set of events is available to be processed.

Each event returned by the event demultiplexer is processed. At this point, the 3. resource associated with each event is guaranteed to be ready to read and to not block during the operation. When all the events are processed, the flow will block again on the event demultiplexer until new events are again available to be processed. This is called the event loop.

It's interesting to see that with this pattern, we can now handle several I/O operations inside a single thread, without using a busy-waiting technique. The following image shows us how a web server would be able to handle multiple connections using a synchronous event demultiplexer and a single thread:

The previous image helps us understand how concurrency works in a single-threaded application using a synchronous event demultiplexer and non-blocking I/O. We can see

that using only one thread does not impair our ability to run multiple I/O bound tasks concurrently. The tasks are spread over time, instead of being spread across multiple threads. This has the clear advantage of minimizing the total idle time of the thread, as clearly shown in the image. This is not the only reason for choosing this model. To have only a single thread, in fact, also has a beneficial impact on the way programmers approach concurrency in general. Throughout the book, we will see how the absence of in-process race conditions and multiple threads to synchronize, allows us to use much simpler concurrency strategies.

In the next chapter, we will have the opportunity to talk more about the concurrency model of Node.js.

The reactor pattern

We can now introduce the reactor pattern, which is a specialization of the algorithms presented in the previous section. The main idea behind it is to have a handler (which in Node.js is represented by a callback function) associated with each I/O operation, which will be invoked as soon as an event is produced and processed by the event loop. The structure of the reactor pattern is shown in the following image:

This is what happens in an application using the reactor pattern:

The application generates a new I/O operation by submitting a request to the 1. Event Demultiplexer. The application also specifies a handler, which will be invoked when the operation completes. Submitting a new request to the Event Demultiplexer is a non-blocking call and it immediately returns the control back to the application.

When a set of I/O operations completes, the Event Demultiplexer pushes the new 2. events into the Event Queue. At this point, the Event Loop iterates over the items of the Event Queue. 3. For each event, the associated handler is invoked. 4. The handler, which is part of the application code, will give back the control to 5. the Event Loop when its execution completes (5a). However, new asynchronous operations might be requested during the execution of the handler (5b), causing

new operations to be inserted in the Event Demultiplexer (1), before the control is given back to the Event Loop. When all the items in the Event Queue are processed, the loop will block again on 6. the Event Demultiplexer which will then trigger another cycle.

The asynchronous behavior is now clear: the application expresses the interest to access a resource at one point in time (without blocking) and provides a handler, which will then be invoked at another point in time when the operation completes.

A Node.js application will exit automatically when there are no more pending operations in the Event Demultiplexer, and no more events to be processed inside the Event Queue.

We can now define the pattern at the heart of Node.js.

Pattern (reactor): handles I/O by blocking until new events are available from a set of observed resources, and then reacting by dispatching each event to an associated handler.

The non-blocking I/O engine of Node.js libuv

Each operating system has its own interface for the Event Demultiplexer: epoll on Linux, kqueue on Mac OS X, andI/O Completion Port API (IOCP) on Windows. Besides that, each I/O operation can behave quite differently depending on the type of the resource, even within the same OS. For example, in Unix, regular filesystem files do not support nonblocking operations, so, in order to simulate a non-blocking behavior, it is necessary to use a separate thread outside the Event Loop. All these inconsistencies across and within the different operating systems required a higher-level abstraction to be built for the Event Demultiplexer. This is exactly why the Node.js core team created a C library called libuv, with the objective to make Node.js compatible with all the major platforms and normalized the non-blocking behavior of the different types of resource; libuv today represents the low-level I/O engine of Node.js.

Besides abstracting the underlying system calls, libuv also implements the reactor pattern, thus providing an API for creating event loops, managing the event queue, running asynchronous I/O operations, and queuing other types of tasks.

A great resource to learn more about libuv is the free online book created by Nikhil Marathe, which is available at http://nikhilm.github.io/uvbook/

The recipe for Node.js

The reactor pattern and libuv are the basic building blocks of Node.js, but we need the following three other components to build the full platform:

A set of bindings responsible for wrapping and exposing libuv and other lowlevel functionality to JavaScript.

V8, the JavaScript engine originally developed by Google for the Chrome browser. This is one of the reasons why Node.js is so fast and efficient. V8 is acclaimed for its revolutionary design, its speed, and for its efficient memory management.

A core JavaScript library (called node-core) thatimplements the high-level Node.js API.

Finally, this is the recipe of Node.js, and the following image represents its final architecture:

Summary

In this chapter, we have seen how the Node.js platform is based on a few important principles that provide the foundation to build efficient and reusable code. The philosophy and the design choices behind the platform have, in fact, a strong influence on the structure and behavior of every application and module we create. Often, for a developer moving from another technology, these principles might seem unfamiliar and the usual instinctive

reaction is to fight the change by trying to find more familiar patterns inside a world which in reality requires a real shift in the mindset.

On one hand, the asynchronous nature of the reactor pattern requires a different programming style made of callbacks and things that happen at a later time, without worrying too much about threads and race conditions. On the other hand, the module pattern and its principles of simplicity and minimalism creates interesting new scenarios in terms of reusability, maintenance, and usability.

Finally, besides the obvious technical advantages of being fast, efficient, and based on JavaScript, Node.js is attracting so much interest because of the principles we have just discovered. For many, grasping the essence of this world feels like returning to the origins, to a more humane way of programming for both size and complexity and that's why developers end up falling in love with Node.js. The introduction of ES2015 makes things even more interesting and open new scenarios for being able to embrace all these advantages with an even more expressive syntax.

In the next chapter, we will get into deep of the two basic asynchronous patterns used in Node.js: the callback pattern and the event emitter. We will also understand the difference between synchronous and asynchronous code and how to avoid to write unpredictable functions.

2

Node.js Essential Patterns

Embracing the asynchronous nature of Node.js is not trivial at all, especially if coming from a language such as PHP where it is not usual to deal with asynchronous code.

With synchronous programming we are used to imagine code as a series of consecutive computing steps defined to solve a specific problem. Every operation is blocking which means that only when an operation is completed it is possible to execute the next one. This approach makes the code easy to understand and debug.

Instead, in asynchronous programming some operations like reading a file or performing a network request can be executed asynchronously in the background. When an asynchronous operation is performed, the next one is executed immediately, even if the previous (asynchronous) operation has not finished yet. The operations pending on the background can complete at any time and the whole application should be programmed to react in the proper way when an asynchronous finishes.

While this non-blocking approach can guarantee superior performances compared to an always-blocking scenario, it provides a paradigm that is hard to picture in mind and that can get really cumbersome when dealing with more advanced applications that requires complex control flows.

Node.js offers a series of tools and design patterns to deal optimally with asynchronous code and it's important to learn how to use them to gain confidence with asynchronous coding and write applications that are both performant and easy to understand and debug.

In this chapter, we will see two of the most important asynchronous patterns: callback and event emitter.

The callback pattern

Another random document with no related content on Scribd:

deux ailes d'infanterie devaient se déployer, et envelopper l'armée de Constantin, déja rompue par la cavalerie. Le prince, qui avait le coup d'œil militaire, comprit le dessein des ennemis à l'ordre de leur bataille. Il place des corps à droite et à gauche pour faire face à l'infanterie et arrêter ses mouvements. Pour lui, il se met au centre en tête de cette redoutable cavalerie. Quand il la voit sur le point de heurter le front de son armée, au lieu de lui résister, il ordonne à ses troupes de s'ouvrir: c'était un torrent qui n'avait de force qu'en ligne droite; le fer dont elle était revêtue ôtait toute souplesse aux hommes et aux chevaux. Mais dès qu'il la voit engagée entre ses escadrons, il la fait enfermer et attaquer de toutes parts, non pas à coups de lances et d'épée, on ne pouvait percer de tels ennemis, mais à grands coups de masses d'armes. On les assommait, on les écrasait sur la selle de leurs chevaux, on les renversait, sans qu'ils pussent ni se mouvoir pour se défendre, ni se relever quand ils étaient abattus. Bientôt ce ne fut plus qu'une horrible confusion d'hommes, de chevaux, d'armes, amoncelés les uns sur les autres. Ceux qui échappèrent à ce massacre voulurent se sauver à Turin avec l'infanterie: mais ils en trouvèrent les portes fermées, et Constantin, qui les poursuivit l'épée dans les reins, acheva de les tailler en pièces au pied des murailles.

Cette victoire, qui ne coûta point de sang au vainqueur, lui ouvrit les portes de Turin. La plupart des autres places entre le Pô et les Alpes lui envoyèrent des députés pour l'assurer de leur soumission: toutes s'empressaient de lui offrir des vivres. Sigonius, sur un passage de saint Jérôme, conjecture que Verceil fit quelque résistance, et que cette ville fut alors presque détruite. Il n'en est point parlé ailleurs. Constantin alla à Milan, et son entrée devint une espèce de triomphe par la joie et les acclamations des habitants, qui ne pouvaient se lasser de le voir et de lui applaudir comme au libérateur de l'Italie.

. Suites de la victoire.

Incert Pan c 7

Sigon Imp

Occ p 52

Hieron Epist ad Innocentium t. , p. 3. ed. Vallars.

Au sortir de Milan, où il était resté quelques jours pour donner du repos à ses troupes, il prit la route de Vérone. Il

Siége de Vérone

savait qu'il y trouverait rassemblées les plus grandes forces de Maxence, commandées par les meilleurs capitaines de ce prince et par son préfet du prétoire, Ruricius Pompéianus, le plus brave et le plus habile général que le tyran eût à son service. En passant auprès de Bresce [Brixia], Constantin rencontra un gros corps de cavalerie, qui prit la fuite au premier choc et alla rejoindre l'armée de Vérone. Ruricius n'osa tenir la campagne; il se renferma avec ses troupes dans la ville. Le siége en était difficile: il fallait passer l'Adige [Athesis], et se rendre maître du cours de ce fleuve qui portait l'abondance à Vérone: il était rapide, plein de gouffres et de rochers, et les ennemis en gardaient les bords. Constantin trompa pourtant leur vigilance; étant remonté fort au-dessus de la ville, jusqu'à un endroit où le trajet était praticable, il y fit passer à leur insu une partie de son armée. A peine le siége fut-il formé, que les assiégés firent une vigoureuse sortie, et furent repoussés avec tant de carnage, que Ruricius se vit obligé de sortir secrètement de la ville pour aller chercher de nouveaux secours.

Incert Pan c 8 et seq

Nazar Pan c 26

Bataille de Vérone

Il revint bientôt avec une plus grosse armée, résolu de faire lever le siége ou de périr. L'empereur, pour ne pas donner aux assiégés la liberté de s'échapper, ou même de l'attaquer en queue pendant le combat, laisse devant la ville une partie de ses troupes, et marche avec l'autre à la rencontre de Ruricius. Il range d'abord son armée sur deux lignes; mais ayant observé que celle des ennemis était plus nombreuse, il met la sienne sur une seule ligne, et fait un grand front de peur d'être enveloppé. Le combat commença sur le déclin du jour, et dura fort avant dans la nuit. Constantin y fit le devoir de général et de soldat. Il se jette au plus fort de la mêlée, et profitant des ténèbres pour courir, sans être retenu, où l'emportait sa valeur, il perce, il abat, il terrasse; on ne le reconnaît qu'à la pesanteur de son bras: le son des instruments de guerre, le cri des soldats, le cliquetis des armes, les gémissements des blessés, les coups guidés par le hasard, tant

Incert Pan c 9 et 10

Nazar Pan c 26

d'horreurs augmentées par celle d'une nuit épaisse, ne troublent point son courage. L'armée de secours est entièrement défaite; Ruricius y perd la vie: Constantin hors d'haleine, couvert de sang et de poussière, va rejoindre les troupes du siége, et reçoit de ses principaux officiers, qui s'empressent avec des larmes de joie de baiser ses mains sanglantes, des reproches d'autant plus flatteurs, qu'ils sont mieux mérités.

Pendant le siége de Vérone, Aquilée [Aquileia] et Modène [Mutina] furent attaquées: elles se rendirent, avec plusieurs autres villes, en même temps que Vérone. L'empereur accorda la vie aux habitants; mais il les obligea de rendre leurs armes; et pour s'assurer de leurs personnes, il les mit sous la garde de ses soldats. Comme ils étaient en plus grand nombre que les vainqueurs, on crut nécessaire de les enchaîner, et on manquait de chaînes; Constantin leur en fit faire de leurs propres épées, qui, forgées pour leur défense, devinrent les instruments de leur servitude. Après tant d'heureux succès, rien n'arrêta sa marche jusqu'à la vue de Rome. Il paraît seulement par un mot de Lactance, qu'aux approches de cette ville il éprouva quelque revers; mais que sans perdre courage, et déterminé à tout événement, il marcha en avant et vint camper visà-vis du Ponte-Mole, nommé alors le pont Milvius. C'est un pont de pierre de huit arches sur le Tibre, à deux milles au-dessus de Rome dans la voie Flaminia, par laquelle venait Constantin. Il avait été construit en bois dès les premiers siècles de la république; il fut rebâti en pierres par le censeur Emilius Scaurus, et rétabli par Auguste. Il subsiste encore aujourd'hui, ayant été réparé par le pape Nicolas V, au milieu du quinzième siècle.

Tout ce que craignait Constantin, c'était d'être obligé d'assiéger Rome, bien pourvue de troupes et de toutes sortes de munitions; et de faire

Prise de Vérone, d'Aquilée et de Modène.

Incert. Pan. c. 11 et seq. Nazar. c. 27.

. Constantin devant Rome.

Lact. de mort. persec. c. 44.

Fabric. descript. urb. Rom. c. 16, et alii passim.

Maxence se tient enfermé

dans Rome.

ressentir les calamités de la guerre à un peuple dont il voulait se faire aimer. Maxence, soit par lâcheté, soit par une crainte superstitieuse, se tenait renfermé: on lui avait prédit qu'il périrait, s'il sortait hors des portes de la ville; il n'osait même quitter son palais, que pour se transporter aux jardins délicieux de Salluste. Cependant affectant une fausse confiance, il n'avait rien retranché de ses débauches ordinaires. Par une précaution frivole, il avait supprimé toutes les lettres qui annonçaient ses infortunes; il supposait même des victoires pour amuser le peuple: et ce fut apparemment dans ce temps-là qu'il se fit décorer tant de fois du titre d'Imperator, qui lui est donné pour la onzième fois sur un marbre antique; vanité ridicule, qui donne à la postérité, plus exactement que l'histoire même, le calcul de ses pertes. Quelquefois il protestait hautement que tous ses désirs étaient de voir son rival au pied des murs de Rome, se flattant sans doute de lui débaucher son armée, et peu capable de sentir la différence qu'il devait y avoir entre les troupes de Sévère ou de Galérius, et des soldats conduits par Constantin et par la victoire. Il s'en fallait bien qu'il fût aussi tranquille, qu'il affectait de le paraître. Deux jours avant la bataille, effrayé par des présages et par des songes, que sa timidité interprétait d'une manière funeste, il quitta son palais, et alla s'établir avec sa femme et ses enfants dans une maison particulière. Cependant son armée sortit de Rome, et se posta vis-à-vis de celle de Constantin, le Ponte-Mole entre deux.

Ce dut être alors que Maxence fit jeter un pont de bateaux sur le fleuve, au-dessus du Ponte-Mole, apparemment vers l'endroit appelé les RochesRouges [Saxa rubra], à neuf milles de Rome. C'était le lieu qu'il avait choisi pour combattre, soit que le poste lui parût plus avantageux, soit pour obliger ses troupes à faire de plus grands efforts en leur rendant la retraite plus difficile, soit que, se défiant des Romains, il voulût livrer la bataille hors de leur vue. Ce pont était construit de manière qu'il

Incert. Pan. c. 14 et seq.

Lact., de mort. pers. c. 44.

Noris. in num. Diocl. c. 5.

. Pont de bateaux.

Euseb. vit. Const. l. 1, c. 38. Zos. l. 2, c. 15.

pouvait s'ouvrir ou se rompre en un moment, n'étant lié par le milieu qu'avec des crampons de fer, qu'il était aisé de détacher. C'était en cas de défaite un moyen de faire périr l'armée victorieuse dans le temps même de la poursuite. Des ouvriers cachés dans les bateaux devaient ouvrir le pont, dès que Constantin et ses troupes seraient dessus, pour les précipiter dans le fleuve. Quelques modernes, fondés sur le récit que Lactance, les panégyristes et Prudence font de cette bataille, nient l'existence de ce pont; ils prétendent que ce fut du pont Milvius que Maxence dans sa déroute tomba dans le Tibre, soit qu'il l'eût lui-même fait rompre avant l'action, comme Lactance semble le dire, soit que la foule des fuyards l'en ait précipité. Mais nous suivrons ici Eusèbe et Zosime, qui décrivent en termes précis ce pont de bateaux, et dont le témoignage très-considérable en lui-même, surtout quand ils s'accordent ensemble, est ici appuyé par le plus grand nombre d'anciens auteurs.

La nuit qui précéda la bataille, Constantin fut averti en songe de faire marquer les boucliers de ses soldats du monogramme de Christ. Il obéit, et dès le point du jour ce victorieux caractère, imprimé par son ordre, parut sur les boucliers, sur les casques, et fit passer dans le cœur des soldats une confiance toute nouvelle.

Le 28 d'octobre Maxence entrait dans la septième année de son règne. Si l'on en veut croire Lactance, tandis que les deux armées étaient aux mains, ce prince, encore renfermé dans Rome, célébrait l'anniversaire de son avénement à l'empire, en donnant des jeux dans le cirque; et il ne fallut rien moins que les clameurs et les reproches injurieux du peuple pour le forcer à

Aurel Vict de Cæs p 175

Vict epit p 221

Lact de mort persec c 44

Libanius, orat 3 t 11, p 105 et 106 ed Morel.

Praxag apud Phot. cod. 62.

Acta Metr et Alex. apud Phot. cod. 256.

Incert. Pan. c. 27.

Prud ad Sym l 1, va. 448.

Till note 31, sur Constantin.

Vorburg, Hist

Rom. Germ., t. 2, p. 138.

s'aller mettre à la tête de ses troupes. Mais les deux panégyristes, dont l'un parlait l'année suivante en présence de Constantin, et qui tous deux ne négligent rien de ce qui peut flétrir la mémoire du vaincu, ne lui imputent pas cet excès de lâcheté; Zosime s'accorde ici avec eux. Je vais donc suivre leur récit, comme le plus vraisemblable.

Songe de Constantin

Lact de mort persec c 44

Prud ad Sym l 1, v 488

Maxence, qui ne se lassait pas d'immoler des victimes et d'interroger les aruspices, voulut enfin consulter l'oracle le plus respecté: c'était les livres des sibylles. Il y trouva que ce jour-là même l'ennemi des Romains devait périr. Il ne douta pas que ce ne fût Constantin; et sur la foi de cette prédiction, il va joindre son armée et lui fait passer le pont de bateaux. Pour ôter à ses troupes tout moyen de reculer, il les range au bord du Tibre. C'était un spectacle effrayant, et la vue d'une armée si belle et si nombreuse annonçait bien la décision d'une importante querelle. Quoique le front s'étendît à perte de vue, les files serrées, les rangs multipliés, les lignes redoublées et soutenues de corps de réserve, présentaient un mur épais qui semblait impénétrable. Constantin beaucoup plus faible en nombre, mais plus fort par la valeur et par l'amour de ses troupes, fait charger la cavalerie ennemie par la sienne, et en même temps fait avancer l'infanterie en bon ordre. Le choc fut terrible: les prétoriens surtout se battirent en désespérés. Les soldats étrangers firent aussi une vigoureuse résistance; il en périt une multitude innombrable, massacrés ou foulés aux pieds des chevaux. Mais les Romains et les Italiens, fatigués de la tyrannie et du tyran, ne tinrent pas longtemps contre un prince qu'ils désiraient d'avoir pour maître, et Constantin se montrait plus que jamais digne de l'être. Après avoir donné ses ordres, voyant que la

Sentiment de Lactance

Lact de mort persec c 44

Calend

Buch in cycl p 286

Noris, de num Lic c 2

Till note 32 sur Constantin

Bataille contre Maxence

Incert Pan c 16 et seq

cavalerie ennemie disputait opiniâtrement la victoire, il se met à la tête de la sienne; il s'élance dans les plus épais escadrons; les pierreries de son casque, l'or de son bouclier et de ses armes le montrent aux ennemis et les effraient: au milieu d'une nuée de javelots, il se couvre, il attaque, il renverse; son exemple donne aux siens des forces extraordinaires. Chaque soldat combat comme si le succès dépendait de lui seul, et qu'il dût seul recueillir tout le fruit de la victoire. Déja toute l'infanterie était rompue et en déroute: les bords du fleuve n'étaient plus couverts que de morts et de mourants; le fleuve même en était comblé et ne roulait que du sang et des cadavres. Maxence ne perdit point l'espérance, tant qu'il vit combattre ses cavaliers: mais ceux-ci étant enfin obligés de céder, il prit la fuite avec eux et gagna le pont de bateaux. Ce pont n'était ni assez large pour contenir la multitude des fuyards qui s'entassaient les uns sur les autres, ni assez solide pour les soutenir. Dans cet affreux désordre il se rompit, et Maxence enveloppé d'une foule de ses gens, tomba, fut englouti, et disparut avec eux.

La nouvelle de ce grand événement vola aussitôt à Rome. On n'osa d'abord la croire: on craignait qu'elle ne fût démentie, et que la joie qu'elle aurait donnée ne devînt un crime. Ce ne fut que la vue même de la tête du tyran qui assura les Romains de leur délivrance. Le corps de ce malheureux prince, chargé d'une pesante cuirasse, fut trouvé le lendemain enfoncé dans le limon du Tibre; on lui coupa la tête; on la planta au bout d'une pique pour la montrer aux Romains.

Ce spectacle donna un libre cours à la joie publique, et fit ouvrir au vainqueur toutes les portes de la ville. Laissant à gauche la voie Flaminia, il traversa les prés de Néron, passa près du tombeau de saint Pierre au Vatican et entra par la porte triomphale. Il était monté sur un char. Tous

Nazar Pan c 28 et seq

Zos l 2, c 16

. Fuite de Maxence.

. Suites de la victoire.

Incert. Pan. c. 18.

Zos. l. 2, c. 17.

Anony. Vales.

. Entrée de Constantin dans Rome.

les ordres de l'état; sénateurs, chevaliers, peuple, avec leurs femmes, leurs enfants, leurs esclaves, accouraient au-devant de lui: leurs transports ne connaissaient aucun rang: tout retentissait d'acclamations; c'était leur sauveur, leur libérateur, leur père: on eût dit que Rome entière n'eût été auparavant qu'une vaste prison, dont Constantin ouvrait les portes. Chacun s'efforçait d'approcher de son char, qui avait peine à fendre la foule. Jamais triomphe n'avait été si éclatant. On n'y voyait pas, dit un orateur de ce temps-là, des dépouilles des vaincus, des représentations de villes prises de force; mais la noblesse délivrée d'affronts et d'alarmes, le peuple affranchi des vexations les plus cruelles, Rome devenue libre, et qui se recouvrait elle-même, faisaient au vainqueur un plus beau cortége, où l'allégresse était pure et où la compassion ne dérobait rien à la joie. Et si pour rendre un triomphe complet, il y fallait voir des captifs chargés de fers, on se représentait l'avarice, la tyrannie, la cruauté, la débauche enchaînées à son char. Toutes ces horreurs semblaient respirer encore sur le visage de Maxence, dont la tête, haut élevée derrière le vainqueur, était l'objet de toutes les insultes du peuple. C'était la coutume que la pompe du triomphe montât au Capitole, pour rendre graces à Jupiter et pour lui immoler des victimes: Constantin qui connaissait mieux l'auteur de sa victoire, se dispensa de cette cérémonie païenne. Il alla droit au mont Palatin, où il choisit sa demeure dans le palais que Maxence avait trois jours auparavant abandonné. Il envoya aussitôt la tête du tyran en Afrique; et cette province, dont les plaies saignaient encore, reçut avec la même joie que Rome ce gage de sa délivrance; elle se soumit de bon cœur à un prince de qui elle espérait des traitements plus humains.

Ce ne fut dans Rome pendant sept jours que fêtes et que spectacles, dans lesquels la présence du prince, auteur de la félicité publique, occupait presque seule les yeux de tous les spectateurs. On accourait de toutes les villes de l'Italie pour le voir et pour prendre part à la joie universelle.

Euseb vit

Const l 1, c 39

Incert Pan c 18 et seq

Nazar Pan c 30 et seq

Baron ann 312, § 75 . Fêtes, réjouissances, honneurs rendus à Constantin.

Incert Pan c 19 et 25

Prudence dit qu'à l'arrivée de Constantin les sénateurs sortis des cachots, et encore chargés de leurs chaînes, embrassaient ses genoux en pleurant, qu'ils se prosternaient devant ses étendards, et adoraient la croix et le nom de Jésus-Christ. Si ce fait n'est pas embelli par les couleurs de la poésie, il faut dire que ces hommes encore païens ne rendaient cet hommage qu'aux enseignes du prince, qu'on avait coutume d'adorer. Ce qu'il y a de certain, c'est que la nouvelle conquête s'efforça de combler Constantin de toutes sortes d'honneurs. L'Italie lui consacra un bouclier et une couronne d'or: l'Afrique par une flatterie païenne, que le prince rejeta sans doute, établit des prêtres pour le culte de la famille Flavia: le sénat romain après lui avoir élevé une statue d'or, dédia sous son nom plusieurs édifices magnifiques que Maxence avait fait faire; entre autres une basilique et le temple de la ville de Rome, bâti par Hadrien et rétabli par Maxence. Mais le monument le plus considérable construit en son honneur fut l'arc de triomphe, qui porte encore son nom. Il ne fut achevé qu'en 315 ou 316. On le voit au pied du mont Palatin, près de l'amphithéâtre de Vespasien, à l'occident. Il fut bâti en grande partie des débris d'anciens ouvrages et surtout de l'arc de Trajan, dont on y transporta plusieurs bas-reliefs et plusieurs statues. La comparaison qu'on y peut faire des figures enlevées des anciens monuments avec celles qui furent alors travaillées, fait connaître combien le goût des arts avait déja dégénéré. L'inscription annonce aussi par son emphase le déclin des lettres; elle porte: Que le sénat et le peuple romain ont consacré cet arc de triomphe à l'honneur de Constantin, qui par l'inspiration de la Divinité et par la grandeur de son génie, à la tête de son armée, a su, par une juste vengeance, délivrer la république et du tyran et de toute sa faction. Il est à remarquer que le paganisme emploie ici le

Nazar Pan c 32

Euseb vit

Const l 1, c 40

Aurel Vict de Cæs p 175

Prud in Sym l 1, v 491

Theoph Chr p 11

Hist Misc l 11, apud Muratori, t , p. 71.

Grut inscript p 282, no 2.

terme général et équivoque de Divinité, pour accorder les sentiments du prince avec ses propres idées; car Constantin ne masquait pas son attachement à la religion qu'il venait d'embrasser: il déclara même par un monument public à quel Dieu il se croyait redevable de ses succès. Dès qu'il se vit maître de Rome, comme on lui eut érigé une statue dans la place publique, ce prince qui n'était pas enivré de tant d'illustres témoignages de sa force et de sa valeur, fit mettre une longue croix dans la main de sa figure avec cette inscription: C'est par ce signe salutaire, vrai symbole de force et de courage, que j'ai délivré votre ville du joug des tyrans, et que j'ai rétabli le sénat et le peuple dans leur ancienne splendeur.

Les statues de Maximin élevées au milieu de Rome à côté de celles de Maxence, annonçaient à Constantin la ligue secrète formée entre les deux princes: il trouva même des lettres qui lui en fournissaient une preuve assurée. Le sénat le vengea de cette perfidie par un arrêt, qui lui conférait, à cause de la supériorité de son mérite, le premier rang entre les empereurs, malgré les prétentions de Maximin. Celui-ci avait reçu la nouvelle de la défaite de Maxence avec autant de dépit que s'il eût été vaincu lui-même; mais quand il apprit l'arrêt rendu par le sénat, il laissa éclater son chagrin, et n'épargna ni les railleries ni les injures.

Cette impuissante jalousie ne pouvait donner d'inquiétude à Constantin; cependant il ne s'endormit pas après la victoire. Tandis que les vaincus ne songeaient qu'à se réjouir de leur défaite, le vainqueur s'occupait sérieusement des moyens d'assurer sa conquête. Pour y réussir il se proposa deux objets; c'était de mettre hors d'état de nuire ceux qu'il ne pouvait se flatter de gagner, et de s'attacher le cœur des autres par la douceur et par les bienfaits. Les soldats prétoriens établis par Auguste pour être la garde des empereurs, réunis par Séjan dans un même camp près des murs de Rome, s'étaient rendus redoutables

Dispositions de Maximin Lact de mort persec c 44

Précautions de Constantin.

Incert Pan c 21.

Nazar Pan c 6.

Aurel Vict de Cæs. p. 176.

Zos l 2, c 17

même à leurs maîtres. Ils avaient souvent ôté, donné, vendu l'empire; et depuis peu, partisans outrés de la tyrannie de Maxence, qu'ils avaient élevé sur le trône, ils s'étaient baignés dans le sang de leurs concitoyens. Constantin cassa cette milice séditieuse; il leur défendit le port des armes, l'usage de l'habit militaire, et détruisit leur camp. Il désarma aussi les autres soldats qui avaient servi son ennemi; mais il les enrôla de nouveau l'année suivante pour les mener contre les Barbares. Entre les amis du tyran et les complices de ses crimes, il n'en punit qu'un petit nombre des plus coupables. Quelques-uns soupçonnent qu'il ôta la vie à un fils qui restait encore à Maxence[18]; du moins l'histoire ne parle plus ni de cet enfant, ni de la femme de ce prince, dont on ne sait pas même le nom. C'est sans fondement que quelques antiquaires l'ont confondue avec Magnia Urbica: les noms de celle-ci ne peuvent convenir à une fille de Galérius.

Till art 14

[18] Nazarius le dit assez clairement dans son Panégyrique, § 6 Constituta enim et in perpetuum Roma fundata est, omnibus qui statum ejus labefactare poterant cum stirpe deletis S -M

Ces traits de sévérité coûtaient trop à la bonté naturelle de Constantin: il trouvait dans son cœur bien plus de plaisir à pardonner. Il ne refusa rien au peuple, que la punition de quelques malheureux, dont on demandait la mort. Il prévint les prières de ceux qui pouvaient craindre son ressentiment, et leur donna plus que la vie, en les dispensant de la demander. Il leur conserva leurs biens, leurs dignités, et leur en conféra même de nouvelles, quand ils parurent les mériter. Aradius Rufinus avait été préfet de Rome la dernière année de Maxence: ce prince, la veille de sa défaite, en avait établi un autre, nommé Annius Anulinus. Celui-ci étant sorti de charge le 29 novembre, peut-être pour être envoyé en Afrique où on le voit proconsul en 313, Constantin rétablit dans cette place importante le même Aradius

Conduite sage et modérée après la victoire

Incert Pan c 20

Liban or 10 t II, p 262, ed Morel

Pagi, in Baron

Till art 15

Rufinus, dont il avait reconnu le mérite. Il lui donna pour successeur l'année suivante Rufius Volusianus qui avait été préfet du prétoire sous Maxence.

La révolution récente devait produire grand nombre de délateurs, comme on voit une multitude d'insectes après un orage. Constantin avait toujours eu en horreur ces ames basses et cruelles, qui se repaissent des malheurs de leurs concitoyens, et qui feignant de poursuivre le crime, n'en poursuivent que la dépouille. Dès le temps qu'il était en Gaule, il leur avait fermé la bouche. Après sa victoire il fit deux lois par lesquelles il les condamna à la peine capitale. Il les nomme dans ces lois une peste exécrable, le plus grand fléau de l'humanité. Il détestait non-seulement les délateurs qui en voulaient à la vie, mais ceux encore qui n'attaquaient que les biens.

. Lois contre les délateurs.

Cod. Th. lib. 10, tit. 10, leg. 1, 2, 3 et ibi God.

Incert. Pan. c. 4.

Nazar. Pan. c. 18.

Vict. epit. p. 224.

L'indignation contre eux prévalait dans son cœur sur les intérêts du fisc; et vers la fin de sa vie il ordonna aux juges de punir de mort les dénonciateurs qui, sous prétexte de servir le domaine, auraient troublé par des chicanes injustes les légitimes possesseurs. Dans le séjour d'un peu plus de deux mois qu'il fit à Rome, il répara les maux de six années de tyrannie. Tout semblait respirer et reprendre vie. En vertu d'un édit publié par tout son empire, ceux qui avaient été dépouillés rentraient en possession de leurs biens; les innocents exilés revoyaient leur patrie; les prisonniers, qui n'avaient d'autre crime que d'avoir déplu au tyran, recouvraient la liberté; les gens de guerre qui avaient été chassés du service pour cause de religion, eurent le choix de reprendre leur premier grade, ou de jouir d'une exemption honorable. Les pères ne gémissaient plus de la beauté de leurs filles, ni les maris de celle de leurs femmes: la vertu du prince assurait

Il répare les maux qu'avait faits Maxence

Nazar Pan c 33 et seq

Euseb vit Const l 1, c 41.

Soz l 1, c 8

l'honneur des familles. Un accès facile, sa patience à écouter, sa bonté à répondre, la sérénité de son visage, produisaient dans tous les cœurs le même sentiment, que la vue d'un beau jour après une nuit orageuse. Il rendit au sénat son ancienne autorité; il parla plusieurs fois dans cette auguste compagnie, qui le devenait encore davantage par les égards que le prince avait pour elle. Afin d'en augmenter le lustre, il y fit entrer les personnes les plus distinguées de toutes les provinces, et pour ainsi dire l'élite et la fleur de tout l'empire. Il sut ramener le peuple aux règles du devoir par une autorité douce et insensible, qui, sans rien ôter à la liberté, bannissait la licence, et semblait n'avoir en main d'autre force que celle de la raison et de l'exemple du prince.

C'était au profit de ses sujets que ses revenus augmentaient avec son empire. Il diminua les tributs; et la malignité de Zosime, qui ose taxer ce prince d'avarice et d'exactions accablantes, est démentie par des inscriptions. Nous verrons dans la suite d'autres preuves de sa libéralité; elle descendait dans tous les détails: il se montrait généreux aux étrangers; il faisait distribuer aux pauvres de l'argent, des aliments, des vêtements même. Pour ceux qui, nés dans le sein de l'abondance, se trouvaient, par de fâcheux revers, réduits à la misère, il les secourait avec une magnificence qui répondait à leur première fortune: il donnait aux uns des terres, aux autres les emplois qu'ils étaient capables de remplir. Il était le père des orphelins, le protecteur des veuves. Il mariait à des hommes riches et qui jouissaient de sa faveur les filles qui avaient perdu leurs pères, et les dotait d'une manière proportionnée à la fortune de leurs époux. En un mot, dit Eusèbe, c'était un soleil bienfaisant, dont la chaleur féconde et universelle diversifiait ses effets selon les différents besoins.

La ville de Rome fut embellie. Il fit bâtir autour du grand cirque de superbes portiques, dont les colonnes étaient enrichies de dorures. On dressa

. Libéralités de Constantin. Grut. inscr. p. 159, no 4.

Euseb. vit.

Const. l. 1, c. 43.

Zos. l. 2, c. 38.

. Embellissement

s et réparations des villes.

en plusieurs endroits des statues, dont quelquesunes étaient d'or et d'argent. Il répara les anciens édifices. Il fit construire sur le mont Quirinal des thermes qui égalaient en magnificence ceux de ses prédécesseurs: ayant été détruits dans le saccagement de Rome sous Honorius, ils furent réparés par Quadratianus, préfet de la ville, sous Valentinien III; il en subsistait encore une grande partie sous le pontificat de Paul V: lorsque le cardinal Borghese les fit abattre, on y trouva les statues de Constantin et de ses deux fils, Constantin et Constance, qui furent placées dans le Capitole. Non content de donner à Rome un nouveau lustre, il releva la plupart des villes que la tyrannie ou la guerre avaient ruinées. Ce fut alors que Modène, Aquilée et les autres villes de l'Émilie, de la Ligurie et de la Vénétie, reprirent leur ancienne splendeur. Cirtha, capitale de la Numidie, détruite, comme nous l'avons dit, par le tyran Alexandre, fut aussi rétablie par Constantin qui lui donna son nom. Elle le conserve encore aujourd'hui avec plusieurs beaux restes d'antiquité.

Nazar. Pan. c. 35.

Aurel. Vict. de Cæs. p. 175 et 176

Grut. inscr. p. 177, no 7

Nard Rom ant et mod

Sigon de Imp Occ l 3, p 58

Tous les savants conviennent d'après la chronique d'Alexandrie, que c'est de cette année 312, que commencent les Indictions. C'est une révolution de quinze ans, dont on s'est beaucoup servi autrefois pour les dates de tous les actes publics, et dont la cour de Rome conserve encore l'usage. La première année de ce cycle s'appelle Indiction première, et ainsi de suite jusqu'à la quinzième, après laquelle un nouveau cycle recommence. En remontant de l'an 312, on trouve que la première année de l'ère chrétienne aurait été la quatrième indiction, si cette manière de compter les temps eût été alors employée: d'où il s'ensuit que pour trouver l'indiction de quelque année que ce soit depuis Jésus-Christ, il faut ajouter le nombre de trois au nombre

. Établissement des Indictions.

Chron. Alex. vel Paschal. p. 281.

Till. art. 30.

Baron. ann. 312.

donné, et divisant la somme par quinze, s'il ne reste rien, cette année sera l'indiction quinzième; s'il reste un nombre, ce nombre donnera l'indiction que l'on cherche. Il faut distinguer trois sortes d'indictions: celle des Césars, qui s'appelle aussi Constantinienne du nom de son instituteur; elle commençait le 24 de septembre; on s'en est longtemps servi en France et en Allemagne: celle de Constantinople, qui commençait avec l'année des Grecs au 1er septembre; elle fut dans la suite le plus universellement employée: enfin celle des papes, qui suivirent d'abord le calcul des empereurs dont ils étaient sujets; mais depuis Charlemagne ils se sont fait une indiction nouvelle, qu'ils ont commencée d'abord au 25 décembre, ensuite au 1er janvier. Ce dernier usage subsiste encore aujourd'hui, ainsi la première époque de l'indiction pontificale remonte au 1er janvier de l'an 313. Justinien ordonna en 537 que tous les actes publics seraient datés de l'indiction.

Petav Doct temp l 11, c 40

Riccioli, Chron reform l 4, c 16.

Pagi, in Baron an. 312 § 20.

Justiniani, Nov 47.

[Art de vérifier les dates, t. , introduction.]

Ce mot signifie dans les lois romaines, répartition des tributs, déclaration de ce que doit payer chaque ville ou chaque province. Il est donc presque certain que ce nom a rapport à quelque taxation. Mais quel était ce tribut? Pourquoi ce cercle de quinze années? C'est sur quoi les plus savants avouent qu'ils n'ont rien d'assuré. Baronius conjecture que Constantin réduisit à quinze ans le service militaire, et qu'il fallait au bout de ce terme indiquer un tribut extraordinaire pour payer les soldats qu'on licenciait. Mais cette origine est rejetée de la plupart des critiques, comme une supposition sans fondement et sujette à des difficultés insolubles. La raison qui a déterminé Constantin à fixer le commencement de l'indiction au 24 de septembre, n'est pas moins inconnue[19] . Un

. Raisons de cet établissement.

Cod. Th. lib. 11, tit. de indict. leg. , et ibi God.

Baron. in an. 312.

Buch. cycl. p. 286.

Ludolff l 3, c 6

grand nombre de modernes n'en trouvent point d'autre que la défaite de Maxence: cet événement était pour Constantin une époque remarquable; et pour y attacher la naissance de l'indiction, ils supposent que le 24 de septembre est le jour où Maxence fut vaincu. Mais il est prouvé par un calendrier très-authentique, que Maxence ne fut défait que le 28 d'octobre. S'il m'était permis de hasarder mes conjectures après tant de savants, je dirais que Constantin, voulant marquer sa victoire et le commencement de son empire à Rome par une époque nouvelle, la fit remonter à l'équinoxe d'automne, qui tombait en ce temps-là au 24 septembre. Des quatre points cardinaux de l'année solaire, il n'y en a aucun qui n'ait servi à fixer le commencement des années chez les différents peuples. Un grand nombre de villes grecques, ainsi que les Égyptiens, les Juifs pour le civil, les Grecs de Constantinople, commençaient leur année vers l'automne[20]: c'est encore aujourd'hui la pratique des Abyssins; les SyroMacédoniens[21] la commençaient précisément au 24 septembre. Il est assez naturel de croire que Constantin a choisi celui des quatre points principaux de la révolution solaire, qui se trouvait le plus proche de l'événement, dont il prenait occasion d'établir un nouveau cycle[22] .

Noris, epoch Syro-Mac

[19] L'année macédonienne julienne, en usage dans toute l'Asie-Mineure et à ce qu'il paraît dans la province de Macédoine, commençait le 24 septembre; il est probable, sans aller plus loin, que c'est de là que vint l'usage de commencer à la même époque les années de l'indiction S -M

[20] C'est par des raisons fort diverses et très-différentes de celles qui sont indiquées ici, que plusieurs nations de l'antiquité ont placé vers l'automne le commencement de leur année. S.-M.

[21] Ce ne sont point les Macédoniens de Syrie, mais ceux de l'Asie-Mineure, qui commençaient leur année le 24 septembre En Syrie les Macédoniens plaçaient au 1er septembre le commencement de l'année. S.-M.

[22] Il est plus probable que Constantin a mieux aimé faire coïncider le renouvellement des années de cette période, avec le calendrier adopté dans presque toute la partie orientale de son empire S -M

Des soins plus importants occupaient encore le prince. Il devait à Dieu sa conquête, il voulait la rendre à son auteur; et par une victoire plus glorieuse et plus salutaire, soumettre ses sujets au maître qu'il commençait lui-même à servir. Instruit par des évêques remplis de l'esprit de l'Évangile, il connaissait déja assez le caractère de la religion chrétienne, pour comprendre qu'elle abhorre le sang et la violence, qu'elle ne connaît d'autres armes que l'instruction et une douce persuasion, et qu'elle aurait désavoué une vengeance aveugle, qui arrachant les fouets et les glaives des mains des païens, les aurait employés sur eux-mêmes. Plein de cette idée, il se garda bien de révolter les esprits par des édits rigoureux; et ceux que lui attribue Théophanes, copié par Cédrénus, ne sont pas moins contraires à la vérité, qu'à l'esprit du christianisme. Ces écrivains, pieux sans doute, mais de cette piété qu'on ne doit pas souhaiter aux maîtres du monde, font un mérite à Constantin d'avoir déclaré, que ceux qui persisteraient dans le culte des idoles auraient la tête tranchée. Loin de porter cette loi sanguinaire, Constantin usa de tous les ménagements d'une sage politique. Rome était le centre de l'idolâtrie; avant que de faire fermer les temples, il voulut les faire abandonner. Il continua de donner les emplois et les commandements à ceux que leur naissance et leur mérite y appelaient; il n'ôta la vie ni les biens à personne; il toléra ce qui ne pouvait être détruit que par une longue patience. Sous son empire, et sous celui de ses successeurs, jusqu'à Théodose le Grand, on retrouve dans les auteurs et sur les marbres tous les titres des dignités et des offices de l'idolâtrie; on y voit des réparations de temples et des superstitions de toute espèce. Mais on ne doit pas regarder comme un effet de cette tolérance, les sacrifices humains qui se faisaient encore secrètement à Rome du

Conduite de Constantin par rapport au christianisme.

Lact inst div l 1, c. 21.

Theoph Chron p. 13.

Cedren t , p 272.

Anony Vales

Prud in Sym l 1, v 615

Mem Acad Inscript t 15, p 75.

Till art 28 et note 34 sur Constantin.

[Zos l 4, c 36 ]

temps de Lactance, et qui échappaient sans doute à la vigilance de Constantin. Il accepta la robe et le titre de souverain-pontife, que les prêtres païens lui offrirent selon la coutume, et ses successeurs jusqu'à Gratien eurent la même condescendance. Ils crurent sans doute que cette dignité, qu'ils réduisaient à un simple titre sans fonction, les mettait plus en état de réprimer et d'étouffer peu à peu les superstitions, en tenant les prêtres païens dans une dépendance immédiate de leur personne. Ce n'est pas à moi à décider s'ils ne portèrent pas trop loin cette complaisance politique.

Les supplices auraient produit l'opiniâtreté et la haine du christianisme; Constantin en sut inspirer l'amour. Son exemple, sa faveur, sa douceur même firent plus de chrétiens, que les tourments n'en avaient perverti sous les princes persécuteurs. On en vint insensiblement à rougir de ces dieux qu'on se faisait soi-même; et selon la remarque de Baronius, la chute de l'idolâtrie fit même tomber la statuaire. La religion chrétienne pénétra jusque dans le sénat, le plus fort rempart du paganisme: Anicius, illustre sénateur, fut le premier qui se convertit; et bientôt, à son exemple, on vit se prosterner aux pieds de la croix ce qu'il y avait de plus distingué à Rome, les Olybrius, les Paulinus, les Bassus.

L'empereur remédia à tous les maux qu'il put guérir sans faire de nouvelles plaies. Il rappela les chrétiens exilés; il recueillit les reliques des martyrs, et les fit ensevelir avec décence. Le respect qu'il portait aux ministres de la religion, la rendait plus respectable aux peuples. Il traitait les évêques avec toute sorte d'honneurs; il aimait à s'en faire accompagner dans ses voyages; il ne craignait pas d'avilir la majesté impériale en les recevant à sa table, quelque simples qu'ils fussent alors dans leur extérieur. Les évêques de Rome, persécutés et cachés jusqu'à ce temps-là, qui ne connaissaient encore que les richesses éternelles

. Progrès du christianisme. Baron. in ann. 312.

Prud. in Sym. l. 1, v. 546.

Honneurs que Constantin rend à la religion. Euseb. vit. Const. l. 1, c. 42.

Socr. l. 1, c. 1.

Theoph. p. 11.

Martinelli, Roma sacra et les souffrances temporelles, attirèrent la principale attention de ce prince religieux. Il leur donna le palais de Latran, qui avait été autrefois la demeure de Plautius Lateranus, dont Néron avait confisqué les biens, après l'avoir fait mourir. Depuis que Constantin était devenu maître de Rome, on appelait cet édifice le palais de Fausta, parce que cette princesse y faisait sa demeure. Quoique Baronius place ici cette donation, il y a apparence qu'elle doit être reculée jusqu'après la mort de Fausta en 326. Constantin avait un palais voisin de celuilà, il en fit une basilique chrétienne qui fut nommée Constantinienne, ou basilique du Sauveur, et il la donna au pape Miltiade et à ses successeurs. C'est aujourd'hui Saint-Jean de Latran. Ce fut là le premier patrimoine des papes. Il n'est plus besoin en France de réfuter l'acte de cette donation fameuse, qui rend les papes maîtres souverains de Rome, de l'Italie et de tout l'Occident.

Plein de zèle pour la majesté du culte divin, Constantin en releva l'éclat en faisant part de ses trésors aux églises. Il augmenta celles qui subsistaient déja, et en construisit de nouvelles. Il y en a grand nombre à Rome et dans tout l'Occident qui le reconnaissent pour fondateur. Il est certain qu'il fit bâtir celle de Saint-Pierre au Vatican, sur le même terrain qu'occupe aujourd'hui la plus auguste basilique de l'univers. Celle-là était d'une architecture grossière, faite à la hâte, et construite, en grande partie, des débris du cirque de Néron. Il bâtit aussi en différents temps l'église S.-Paul, celle de S.-Laurent, celle de S.-Marcellin et de S.-Pierre, celle de Sainte-Agnès qu'il fit construire à la sollicitation de sa fille Constantine, et la basilique du palais Sessorien, qui fut ensuite appelée l'église de Sainte-Croix, lorsque ce prince y eut déposé une portion de la vraie croix. Il en fonda plusieurs autres à Ostie, à Albane, à Capoue, à Naples. Il enrichit ces églises de vases précieux et de magnifiques ornements: il leur donna en propriété des terres et des revenus

Baron. an. 312. Églises bâties et ornées

Euseb vit

Const l 1, c 42

Cod Th lib 16, tit 2, leg 14

Anastas Hist eccl p 24 et 25

Nard Rom ant p 478

destinés à leur entretien, et à la subsistance du clergé, à qui il accorda des priviléges et des exemptions. Cette même année ou au commencement de la suivante, avant que de sortir de Rome, il fit, de concert avec Licinius, un édit très-favorable aux chrétiens, mais qui limitait pourtant à certaines conditions la liberté du culte public. C'est ce qui paraît par les termes d'un second édit, qui fut fait à Milan au mois de mars suivant, et dont l'original se lit dans Lactance: l'antiquité ne nous a pas conservé le premier. Constantin l'envoya à Maximin: il l'instruisit en même temps des merveilles que Dieu avait opérées en sa faveur, et de la défaite de Maxence. Maximin, comme je l'ai dit, avait déja appris cette nouvelle avec une espèce de rage. Mais après quelques emportements, il avait renfermé son dépit, ne se croyant pas encore en état de le faire éclater par une guerre ouverte. Il porta même la dissimulation jusqu'à célébrer sur ses monnaies la victoire de Constantin. Il reçut donc la lettre et l'édit; mais il se trouva embarrassé sur la conduite qu'il devait tenir. D'un côté il ne voulait pas paraître céder à ses collègues; de l'autre il craignait de les irriter. Il prit le parti d'adresser comme de son propre mouvement une lettre à Sabinus, son préfet du prétoire, avec ordre de dresser un édit en conformité; et de le faire publier dans ses états. Dans cette lettre il fait d'abord l'éloge de Dioclétien et de Maximien, qui n'avaient, dit-il, sévi contre les chrétiens, que pour les ramener à la religion de leurs pères; il prend ensuite avantage de l'édit de tolérance qu'il avait donné après la mort de Galérius, et ne parle de la révocation de cet édit que d'une manière ambiguë et enveloppée; il déclare enfin qu'il veut qu'on ne mette en usage que les moyens de douceur pour rappeler les chrétiens au culte des dieux, qu'on laisse liberté de conscience à ceux qui persisteront dans leur religion; et il défend à qui que ce soit de les maltraiter. Cette ordonnance de Maximin ne

Constantin arrête la persécution de Maximin.

Euseb hist eccl l 9, c 9

Lact de mort persec c 48

Notæ in Pagium, apud Baron. ann. 312. Banduri, Num. imp. Rom. t. 2, pag. 164.

[Eckhel, Doct. num. vet. t. , p. 54.]

Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.