-
-
Notifications
You must be signed in to change notification settings - Fork 267
Specs
Specs, short for Specification(s), are an unique design philosophy adopted by Discord4J to handle requests that contain multiple optional properties. They are very similar to the common builder pattern, but with two very important differentiating characteristics:
- The end-user does not construct the builder.
- The end-user does not construct the finalized object.
These two characteristics provide Discord4J with tremendous flexibility when it comes to constructing requests without breaking the API at a future date. Different requests to Discord may require different procedures and Specs allows Discord4J to "construct" these requests in an implementation-dependent manner while still providing the end-user control in "building" the request parameters using a singular syntax that is consistent across the API.
All Specs that an end-user interacts with will be provided via a Consumer
. For example, for MessageChannel#createMessage
:
messageChannel.createMessage(spec -> /* manipulate the spec */)
One may note that all Spec
instances have an asRequest
method. This method is an internal behaviorally implementation-specific method and should never be called by the end-user. Once the Spec has been "built", simply leave it alone.
Mono<Message> message = messageChannel.createMessage(messageSpec -> {
messageSpec.setContent("Content not in an embed!");
// You can see in this example even with simple singular property defining specs the syntax is concise
messageSpec.setEmbed(embedSpec -> embedSpec.setDescription("Description is in an embed!"));
});
It is a very common pattern, especially when dealing with embedded messages, to provide a "template" that can later be edited to fit a specific use-case. Using Consumer#andThen
allows this pattern to be implemented easily:
Consumer<EmbedCreateSpec> template = spec -> {
// Edit the spec as you normally would
};
...
// embedSpec can be edited as you normally would, but the edits from template will already be applied
Mono<Message> message = messageChannel.createMessage(messageSpec -> messageSpec.setEmbed(template.andThen(embedSpec -> {})));
This pattern additionally helps protect the end-user from accidentally sharing specs across multiple invocations, as the state is never "reset" and mutating Spec
instances is not thread-safe.
- Getting Started
- Lambda Tutorial
- Reactor (Reactive) Tutorial
- Music Bot Tutorial (v3.0+)
- Frequently Asked Questions
- Migrating from v2.x to v3.1
- Migrating from v3.0 to v3.1