Format markup
This commit is contained in:
parent
fcd30a80ad
commit
2de3c512e3
2 changed files with 109 additions and 37 deletions
|
@ -1,23 +1,38 @@
|
|||
# Architecture of the imag code
|
||||
|
||||
The imag codebase has a rather simple overall architecture. But before introducing the reader to it, a few things have to be introduced.
|
||||
The imag codebase has a rather simple overall architecture. But before
|
||||
introducing the reader to it, a few things have to be introduced.
|
||||
|
||||
## Crate types
|
||||
|
||||
There are different types of crates in the imag world. A crate is a rust project.
|
||||
There are different types of crates in the imag world. A crate is a rust
|
||||
project.
|
||||
|
||||
First of all, there are core crates. These crates provide the very core of imag and almost all other crates use them:
|
||||
First of all, there are core crates. These crates provide the very core of imag
|
||||
and almost all other crates use them:
|
||||
|
||||
* libimagstore - The imag store is the abstraction overbthe filesystem. It provides primitives to get, write and manipulate store entries and their header information.
|
||||
* libimagrt - The runtime library, which provides functionality to create a store object from libimagstore, helps with configurarion loading and commandline argument handling (through the external "clap" crate).
|
||||
* libimagerror - Error handling library for handling errors the imag way. Used in all other crates, even the store itself. It also offers functionality to log and trace errors as well as exiting the application, if necessary.
|
||||
* libimagstore - The imag store is the abstraction overbthe filesystem. It
|
||||
provides primitives to get, write and manipulate store entries and their
|
||||
header information.
|
||||
* libimagrt - The runtime library, which provides functionality to create a
|
||||
store object from libimagstore, helps with configurarion loading and
|
||||
commandline argument handling (through the external "clap" crate).
|
||||
* libimagerror - Error handling library for handling errors the imag way. Used
|
||||
in all other crates, even the store itself. It also offers functionality to
|
||||
log and trace errors as well as exiting the application, if necessary.
|
||||
* libimagutil - Utilities.
|
||||
|
||||
The next type of imag crates are entry extension libraries. Those provide extensional functionality for the types from libimagstore. For example, there is "libimagentrylink" which provides functionality to link two entries in the store.
|
||||
The next type of imag crates are entry extension libraries. Those provide
|
||||
extensional functionality for the types from libimagstore. For example, there is
|
||||
"libimagentrylink" which provides functionality to link two entries in the
|
||||
store.
|
||||
|
||||
The next kind of crate is the one that offers end-user functionality for a imag aspect, for example "libimagtodo" provides functionality to track todos.
|
||||
The next kind of crate is the one that offers end-user functionality for a imag
|
||||
aspect, for example "libimagtodo" provides functionality to track todos.
|
||||
|
||||
And last, but not least, the commandline frontend crates provide the user interface. These are the kind of crates that are not library crates, but binaries.
|
||||
And last, but not least, the commandline frontend crates provide the user
|
||||
interface. These are the kind of crates that are not library crates, but
|
||||
binaries.
|
||||
|
||||
## Architecture of an imag module
|
||||
|
||||
|
@ -47,22 +62,44 @@ With the things from above, a module could have the following architecture:
|
|||
+-----------------------------------+---------+
|
||||
```
|
||||
|
||||
The foundation of all imag modules is the store, as one can see from the image. Above this there is the libimagrt, which provides the basic runtime and access to the `Store` object. Cross-cutting, there is the error library (and possibly the util library, but we do not care about this one here), which is used through all levels. The highest level of all imag modules is the commandline interface on top of the domain library.
|
||||
In between can be any number of entry extension libraries, or none if not needed.
|
||||
The foundation of all imag modules is the store, as one can see from the image.
|
||||
Above this there is the libimagrt, which provides the basic runtime and access
|
||||
to the `Store` object. Cross-cutting, there is the error library (and possibly
|
||||
the util library, but we do not care about this one here), which is used through
|
||||
all levels. The highest level of all imag modules is the commandline interface
|
||||
on top of the domain library. In between can be any number of entry extension
|
||||
libraries, or none if not needed.
|
||||
|
||||
## Types
|
||||
|
||||
The imag core, hence the libimagstore, libimagrt and libimagerror, provide a set of types that a user (as in a library writer) should be aware of.
|
||||
The imag core, hence the libimagstore, libimagrt and libimagerror, provide a set
|
||||
of types that a user (as in a library writer) should be aware of.
|
||||
|
||||
First of all, there is the Runtime type which is provided by the libimagrt. It provides basic access to whether debugging or verbosity is enabled as well as the most important core object: The `Store`.
|
||||
First of all, there is the Runtime type which is provided by the libimagrt. It
|
||||
provides basic access to whether debugging or verbosity is enabled as well as
|
||||
the most important core object: The `Store`.
|
||||
|
||||
It is provided by the libimagstore library, the heart of everything.
|
||||
|
||||
When interacting with the store, two types are visible: `FileLockEntry` and `Entry` whereas the former derefs to the latter, which basically means that the former wraps the latter.
|
||||
The `FileLockEntry` is a necessary wrapper for ensuring that when working concurrently with the store, an entry is only _borrowed_ once from the store. It also ensures that the object is alive as long as the store is.
|
||||
When interacting with the store, two types are visible: `FileLockEntry` and
|
||||
`Entry` whereas the former derefs to the latter, which basically means that the
|
||||
former wraps the latter. The `FileLockEntry` is a necessary wrapper for
|
||||
ensuring that when working concurrently with the store, an entry is only
|
||||
_borrowed_ once from the store. It also ensures that the object is alive as long
|
||||
as the store is.
|
||||
|
||||
The `Entry` type provides functionality like reading the actual content, its header and so on. Extensions for its functionality are implemented on this type, not on the `FileLockEntry`.
|
||||
The `Entry` type provides functionality like reading the actual content, its
|
||||
header and so on. Extensions for its functionality are implemented on this type,
|
||||
not on the `FileLockEntry`.
|
||||
|
||||
The `Entry` provides access to its header, which is a `toml::Value`, where toml is the toml-rs crate (external project). Conveniance functionality is provided via the `toml-query` crate, which is an external project which was initiated and extracted from the imag project.
|
||||
The `Entry` provides access to its header, which is a `toml::Value`, where toml
|
||||
is the toml-rs crate (external project). Conveniance functionality is provided
|
||||
via the `toml-query` crate, which is an external project which was initiated and
|
||||
extracted from the imag project.
|
||||
|
||||
Error types are also important. All errors in the imag prijects are generated by libimagerror usage and are interoperable. User code hardly handles the actual `Error` type but its inner one, `ErrorKind`, which is an enum where each member can be mapped to a representing text. Imag error types do never contain payload (they can via extensions, though it is not really practical and there is no usage for it).
|
||||
Error types are also important. All errors in the imag prijects are generated by
|
||||
libimagerror usage and are interoperable. User code hardly handles the actual
|
||||
`Error` type but its inner one, `ErrorKind`, which is an enum where each member
|
||||
can be mapped to a representing text. Imag error types do never contain payload
|
||||
(they can via extensions, though it is not really practical and there is no
|
||||
usage for it).
|
||||
|
|
|
@ -1,58 +1,93 @@
|
|||
# Conventions, best practices
|
||||
|
||||
This section goes about best practices in the imag codebase. It is mainly focused on developers, but a user may read it for getting to know how imag works.
|
||||
This section goes about best practices in the imag codebase. It is mainly
|
||||
focused on developers, but a user may read it for getting to know how imag
|
||||
works.
|
||||
|
||||
Lets work our way up from the store and how to extend it to the commandline user interface.
|
||||
Lets work our way up from the store and how to extend it to the commandline user
|
||||
interface.
|
||||
|
||||
## Store and Entry functionality
|
||||
|
||||
A `Entry` does not offer much functionality by itself. So its the job of libraries to _extend_ their functionality. This should never be done by wrapping the `Entry` type itself but by providing and implementing an extension trait on it.
|
||||
A `Entry` does not offer much functionality by itself. So its the job of
|
||||
libraries to _extend_ their functionality. This should never be done by wrapping
|
||||
the `Entry` type itself but by providing and implementing an extension trait on
|
||||
it.
|
||||
|
||||
Same goes for extending the `Store` type: never wrap it, always provide an extension trait for it.
|
||||
Same goes for extending the `Store` type: never wrap it, always provide an
|
||||
extension trait for it.
|
||||
|
||||
These two rules ensure that the type does not lose any functionality from a wrapping. `Deref` could do that, but not over muliple levels, so extension traits it is. It also most likely results in functions inside the extension trait which all return a `Result<_, _>`.
|
||||
These two rules ensure that the type does not lose any functionality from a
|
||||
wrapping. `Deref` could do that, but not over muliple levels, so extension
|
||||
traits it is. It also most likely results in functions inside the extension
|
||||
trait which all return a `Result<_, _>`.
|
||||
|
||||
## Libraries
|
||||
|
||||
In the next few sections, conventions and best practices for writing a imag library are written down.
|
||||
In the next few sections, conventions and best practices for writing a imag
|
||||
library are written down.
|
||||
|
||||
A developer of imag should read this carefully, a user may skip this section or cross-read it for better understanding of the imag project.
|
||||
A developer of imag should read this carefully, a user may skip this section or
|
||||
cross-read it for better understanding of the imag project.
|
||||
|
||||
### Library naming
|
||||
|
||||
Libraries which provide functionality for entries or the store (most likely entries or both) should be named "libimagentrything" whereas "thing" stands for what the library provides.
|
||||
Libraries which provide functionality for entries or the store (most likely
|
||||
entries or both) should be named "libimagentrything" whereas "thing" stands for
|
||||
what the library provides.
|
||||
|
||||
All other libraries should be prefixed with "libimag" at least. Most likely, one will not write such a library but rather a "libimagentrything" library.
|
||||
All other libraries should be prefixed with "libimag" at least. Most likely, one
|
||||
will not write such a library but rather a "libimagentrything" library.
|
||||
|
||||
### Library scope
|
||||
|
||||
A library should never introduce utility functionality which could be useful for other libraries as well. If there is no such functionality available, the "libimagutil" might be a place where such a function would be put, or, if not yet available, a "libimagentryutil" could be created.
|
||||
A library should never introduce utility functionality which could be useful for
|
||||
other libraries as well. If there is no such functionality available, the
|
||||
"libimagutil" might be a place where such a function would be put, or, if not
|
||||
yet available, a "libimagentryutil" could be created.
|
||||
|
||||
If a library has to introduce free functions in its public interface, one should think hard whether this is really necessary.
|
||||
If a library has to introduce free functions in its public interface, one should
|
||||
think hard whether this is really necessary.
|
||||
|
||||
### Library error types/kinds
|
||||
|
||||
Libraries must use the "libimagerror" tools to create error types and kinds. Most likely, a library needs some kinds for wrapping the errors from underlying libraries, such as the store itself.
|
||||
Libraries must use the "libimagerror" tools to create error types and kinds.
|
||||
Most likely, a library needs some kinds for wrapping the errors from underlying
|
||||
libraries, such as the store itself.
|
||||
|
||||
A library must _never_ introduce multiple error types, but is free to introduce as many error kinds as required. Indeed, more kinds is better than fewer.
|
||||
A library must _never_ introduce multiple error types, but is free to introduce
|
||||
as many error kinds as required. Indeed, more kinds is better than fewer.
|
||||
|
||||
### Libraries with commandline frontends
|
||||
|
||||
Libraries with commandline frontends provide end-user functionality. Normally, they depend on one or more "libimagentrything" libraries. They should be named "libimagthing", though. For example: "libimagdiary", "libimagtimetrack" or "libimagwiki", whereas the commandline frontends would be "imag-diary", "imag-timetrack" and "imag-wiki", respectively.
|
||||
Libraries with commandline frontends provide end-user functionality. Normally,
|
||||
they depend on one or more "libimagentrything" libraries. They should be named
|
||||
"libimagthing", though. For example: "libimagdiary", "libimagtimetrack" or
|
||||
"libimagwiki", whereas the commandline frontends would be "imag-diary",
|
||||
"imag-timetrack" and "imag-wiki", respectively.
|
||||
|
||||
If such a library needs to depend on another "libimagthing", for example if "libimagdiary" needs to depend on "libimagnote", one should think about this and whether the functionality could ve outsourced to a more general "libimagentrything". It is not forbidden, though.
|
||||
If such a library needs to depend on another "libimagthing", for example if
|
||||
"libimagdiary" needs to depend on "libimagnote", one should think about this and
|
||||
whether the functionality could ve outsourced to a more general
|
||||
"libimagentrything". It is not forbidden, though.
|
||||
|
||||
A library which implements a functionality for imag may contain helper functions for commandline stuff, but that is discouraged.
|
||||
A library which implements a functionality for imag may contain helper functions
|
||||
for commandline stuff, but that is discouraged.
|
||||
|
||||
### Library testing
|
||||
|
||||
All libraries should be tested as much as possible. Sometimes it may not be possible without a lot of effort, but still: more tests = better!
|
||||
All libraries should be tested as much as possible. Sometimes it may not be
|
||||
possible without a lot of effort, but still: more tests = better!
|
||||
|
||||
## Commandline tools
|
||||
|
||||
The next few sections describe how the commandline frontends are implemented. Each imag functionality (or module) has its own library and a commandline frontend for it.
|
||||
The next few sections describe how the commandline frontends are implemented.
|
||||
Each imag functionality (or module) has its own library and a commandline
|
||||
frontend for it.
|
||||
|
||||
The commandline frontends do contain little to no functionality. They simply translate the commandline parameters and options to calls to the appropriate library functions.
|
||||
The commandline frontends do contain little to no functionality. They simply
|
||||
translate the commandline parameters and options to calls to the appropriate
|
||||
library functions.
|
||||
|
||||
## Commandline tool testing
|
||||
|
||||
|
|
Loading…
Reference in a new issue