Series Outline Link to heading

  1. Overview
  2. Framework analysis and selection: Delving into the specifics of framework selection and application.
    1. Core Components: Database management, modularization, internal RPC, AMQP.
    2. Web and API: Web Server, GraphQL API.
    3. Application Development: Web, CLI, desktop, and mobile app development.
    4. Miscellaneous Tools: Observability, logging, machine learning.
  3. Boilerplate project: A comprehensive guide including setup instructions for selected frameworks, architectural diagrams, and development environment configurations.

Modularization Link to heading

Modularization is important in big software projects. It’s like building with Lego blocks – each piece of code is its own little block. This makes it easier for different teams to work on their own parts without messing up the whole thing. It’s also great for fixing bugs and adding new features, since you only have to change one block at a time. Plus, you can reuse these blocks in other projects, saving time and hassle. In short, modularization keeps everything organized, flexible, and easy to handle, especially when things need to change fast.

In the realm of Java, frameworks like Spring, J2EE (Java 2 Platform, Enterprise Edition), and OSGi provide robust support for modularization, each offering its own approach to structuring and managing large-scale applications. For .NET, a similar role is played by frameworks like .NET Core and ASP.NET, which offer a comprehensive set of tools for building modular applications. These frameworks provide features like dependency injection, modular components, and a suite of libraries for various functionalities, mirroring the modular capabilities found in Java’s enterprise frameworks.

Rust, on the other hand, doesn’t have a direct equivalent to these comprehensive enterprise frameworks. While Rust’s package manager, Cargo, and its module system offer basic modularization capabilities, they don’t fully address the complexity of enterprise application development. Therefore, Rust developers often rely on external frameworks and libraries to fill this gap. Frameworks like Actix for actor oriented development, or Tower for service-oriented architectures, provide some structure and tools for building modular applications. However, the Rust ecosystem is still evolving in this regard, with a growing number of libraries and frameworks that aim to offer more comprehensive solutions for enterprise-level application development.

CrateDownloadsDependentsGithub StarsGithub ContributorsGithub Used ByNotes
tower40M5003.5k792.9kComponents/services oriented. I really like this. Simple. Clean, well supported, popular
actix6M (20 if we include actix-web)2508.1k125?Actor-oriented. Also very popular - but pretty tied into actix-web at this point.
bevy-ecs880k16028k (for bevy…)80112.7kECS, different take on Components - a bit different, but might work. Very big community - but, for games…

Note 1: The following were removed because they’re too small or too risky or both: sai, norpc, ecs-rust.

Note 2: While researching AMQP, I found “ntex” - this looks very interesting, and appears to be more of a “full thought” - but, early days, so, not recommended at this time. It brings together web, rpc, and messaging into a single framework. Definitely worth keeping an eye on, use it on a smaller project.

Database Access Link to heading

When it comes to database access in software development, the choice between using an ORM (Object-Relational Mapping) and raw SQL is not a matter of which is universally better, but rather which is more suitable for a given context. ORMs offer a high-level, abstracted way to interact with databases, making code more readable and reducing the amount of boilerplate code. However, they can sometimes obscure complex queries and impact performance. On the other hand, raw SQL gives you fine-grained control and can be more efficient for complex operations, but it can lead to more verbose and harder-to-maintain code. The best choice depends on the specific needs and goals of your project, such as the complexity of the database operations, performance requirements, and the team’s familiarity with SQL.

In Java, Hibernate is a popular ORM (Object-Relational Mapping) framework that abstracts and manages database access, making it easier to work with relational data in an object-oriented way. In the .NET ecosystem, the equivalent is Entity Framework. Entity Framework is a highly regarded ORM tool that enables .NET developers to work with a database using .NET objects, eliminating the need for most of the data-access code that developers usually need to write. It supports LINQ queries, change tracking, updates, and schema migrations, among other features.

In Rust, the ORM landscape is more nascent and less mature compared to Java and .NET. However, there are still some notable ORMs and database access libraries. Diesel is one of the more prominent ORM libraries in Rust, offering a safe, expressive API to interact with databases. It provides strong compile-time guarantees about query validity and integrates smoothly with Rust’s type system. Another option is SeaORM, which is relatively newer and focuses on being async-friendly and feature-rich.

CrateDownloadsDependentsGithub StarsGithub ContributorsGithub Used ByNotes
diesel7.6M30611.1k31327kORM, has a DSL, pretty comfortable, well documented, lots of users.
sqlx9.2M49510.3k35121kGeneralized raw SQL client. Also well documented, lots of users.
ormx17k02585803Meh. its simple, probably not robust enough for most of what we need to do.
seaorm1.3M715.2k1762.5kPretty serious, has a growing ecossytem around it

Internal RPC Machine to Machine Link to heading

Machine-to-machine (M2M) remoting within a distributed application refers to the communication between different software components or services that run on separate machines or processes. This concept is crucial in systems where components are spread across different servers or containers, often in a microservices architecture.

In such setups, each component or service operates as an independent unit, handling a specific part of the application’s functionality. M2M remoting comes into play to enable these distributed components to communicate with each other, often over a network. This communication can be done through various protocols and methods, such as Sockets, gRPC, or more specialized protocols like AMQP (Advanced Message Queuing Protocol), depending on the needs of the application.

CrateDownloadsDependentsGithub StarsGithub ContributorsGithub Used ByNotes
actix-net638k1648721.8kSockets. Experimental way to expose actor on network socket. Pretty raw
tonic29M6428.1k20422.7gRPC. Well documented, clean, simple, good practices built in.
lapin1.6M59900341.6kAMQP 0.9.1
amiquip98k91694501AMQP 0.9.1 (assumed…)
amqprs21k411516?AMQP 0.9.1 (assumed…) Officially mentioned in rabbit docs. Known for high performance.
eventific2k0103?This is a series of utilities for event sourcing using kafka, postgres, rabbitmq, sns or sqs), may be useful to use on top of whatever we choose. Uses lapin for rabbitmq.

Note 1: The following were removed because they’re too small or too risky or both: volo, zino, motore, cqrs, datacake-rpc.

Note 2: There are numerous AMQP 1.0 clients - but most are similar - low 1000’s in downloads, small number of devs. Some of them are: dove, oasis-amqp and fe2o3-amqp.

Summary Link to heading

In our exploration of the Rust landscape, I’ve pinpointed two predominant frameworks for modularization: Actix and Tower. Tower has shown its extensive capabilities, being utilized by six major Rust projects each with a download count exceeding 20 million. This impressive statistic underscores Tower’s effectiveness and adaptability in diverse scenarios. On the flip side, Actix stands out with its dynamic community and an abundance of tutorials, making it an accessible and popular choice. Yet, it’s worth noting that Actix’s focus seems to be shifting increasingly towards its web framework, with less apparent emphasis on internal modularization.

When it comes to database management, the choice essentially boils down to whether to employ an ORM (Object-Relational Mapping) or to directly interact with SQL. If ORM isn’t a necessity, SQLx is the go-to option, recognized for its simplicity and efficiency. On the ORM front, I personally lean towards Diesel, given its well-established feature set and reliability. Nonetheless, SeaORM deserves a look as well, especially considering its ambitious vision which includes a GraphQL interface for database interactions. Although I’m not entirely convinced by their current execution of this feature, SeaORM’s forward-thinking approach indicates it could evolve into something more compelling in the future.