Là một dự án mã nguồn mở, chriskiehl/Deoplice đã đạt 58 sao trên GitHub, ngôn ngữ Java. Very spicy additions to Lombok's annotations
Tóm tắt dựng từ metadata GitHub của chính dự án — chưa có bài review TopGit. Trang sẽ tự động cập nhật khi bài review đầy đủ được xuất bản.
VÌ SAO CHƯA CÓ REVIEW
TopGit viết bài đầy đủ cho repo có nhiều sao nhất và được yêu cầu nhiều nhất. Trang này là snapshot trong thời gian chờ — xem README gốc ở tab READ ME.
Deoplice is java library that automatically generates an API for transforming your immutable POJOs. It's symbiotic with Lombok and picks up where @Value and @With leave off. Say goodbye to tedious boilerplate when updating complex nested objects! With Deoplice, complicated, multi-level updates become trivial one liners.
Note! Deoplice is currently in alpha and may have some bugs lurking around. If you encounter any problems, pop over to the issues and let me know.
Installation
Deoplice is on Maven and installable via your build tool of choice.
Just like Lombok, Deoplice works off annotations. To generate an API for your classes, all you've got to do is add the @Updatable annotation to any class that's also annotated with Lombok's @With.
Here's a tiny set of data classes we'll use throughout the docs:
import deoplice.annotation.Updatable;
@With
@Value
@Updatable // ← Check it out! All we have to do! ^_^
class PurchaseOrder {
String number;
Approval approval;
Integer version;
}
@With
@Value
class Approval {
ApprovalStatus status;
Array<Comment> comments;
Confirmation confirmation;
}
@With
@Value
class Confirmation {
UserAlias alias;
LocalDateTime updatedOn;
}
With the annotation in place, at build time, Deoplice will parse your class and recursively generate a full suite of immutable setters and update functions for every field it finds. These generated API methods allow you to express complex data transformations like this:
On top of that, Deoplice will generate a rich set of method delegations for popular collection types. This means you'll never again have to be crushed by the boilerplate of pulling a collection out of an object, copying it, transforming it, and then withing it (often down several levels) back into place. You can compose together extremely complex actions with ease using Deoplice's generated APIs.
All of the API methods generated by Deoplice are plain ol' Java Functions. This means you can use them anywhere Function is used and freely mix/match them with all your existing code.
For instance, got a collection of PurchaseOrders and need to modify the Confirmation date that's three levels deep? That's a one-liner!
Updaters are for when you need to compute a value based on what's currently there. e.g.
updateApprovalVersion(version -> version += 1);
A rich set of collection delegations
Deoplice has first class support for the standard collection types in java.util.collection as well as io.vavr.collection!
This means that you get an immutable API with Java's mutable collections for free! Usually, trying to treat java's collections as immutable leads to code that is punishingly verbose.
Adding an item generally involves pulling the list out of the POJO, making a copy, doing the transform, and then withing it back into place.
Deoplice does all of this copy-on-write for you behind the scenes! You get to enjoy the quality of life that comes from immutable data structures all while using the standard mutable java collection ones! It turns all of the hullabalo above into this one-liner:
It also works for Vavr's collection types! If you know then you know: Vavr is the best.
class MyStuff {
Array<String> things;
}
appendThings("myNewItem").apply(mystuff);
How to find and use the generated files
Deoplice generates two sets of files. The first is the top-level API. It will have the exact same name as your annotated class, but have a suffix of API added.
So, if your class looks something like this
package foo.bar;
class Foo {
// ...
}
You'll find a generated file in your default build directory called FooAPI.java under the same package.
build/
|-- foo.bar
|-- FooAPI.java
You'd import them like anything else:
import foo.bar.FooAPI;
and you're off to the races!
But the easier way is to...
Ignore all the specifics of build systems, annotation processing directories, and what goes where and just let your IDE figure it all out (it's very good at this!). Just type either set, update, and a collection method like add/append and your IDE will pull up all the options
Lower level lens API
Behind the scenes, Deoplice's compositional API magic is achieved by generating a set of Lenses for every field in each of your annotated classes. What exactly is a Lens? It's some gobbledygook from functional programming. They're basically getters and setters that compose together really well. They're what gives Deoplice the ability to cleanly perform updates on deeply nested objects.
Want to learn more about how lenses are constructed? Checkout this blog post
You'll find these lens classes in the build directory along side the generated API files.
@With
@Value
@Updatable
class Car {
String make;
Driver driver;
}
@With
@Value
class Driver {
String name;
Interger age;
}
Each class is suffixed with Lens filled with field accessors like this:
public static Lens<Car, String> $make = makeLens(Car::getMake, Car::withMake);
public static Lens<Car, String> $model = makeLens(Car::getModel, Car::withModel);
...
public static Lens<Car, String> $model = makeLens(Driver::getName, Driver::withName);
public static Lens<Car, String> $model = makeLens(Driver::getAge, Driver::withAge);
These form the primitives that the higher level API is built from.
These are exposed so that you can build your own higher level APIs. For instance, if you use a different collection library that the ones natively supported by Deoplice, you add support for it as a layer ontop of the lenses with very little code.
Current quirks & limitations
Generics
@Value
public class MyFoo<A> {/*...*/}
Deoplice doesn't currently have the smartest support for classes with generics. The alpha release uses wildcards in the generated API for simplicity. This means that calls where the root object is generic will need casting in order to help the compiler understand the target type.
This is on the roadmap to fix because it's annoying.
Wildcards
class Bar {
List<?> items; // This will be ignroed
}
Wildcarded type params are ignored. Unless a type is specified, there's no way for Deoplice to create delegated methods like add. (because void add(? input) {...} is invalid).
chriskiehl/Deoplice có 58 sao GitHub — tải lại trang để xem số mới nhất, hoặc xem trực tiếp github.com/chriskiehl/Deoplice. TopGit phản chiếu số sao của GitHub nhưng không cam kết đến từng phút.
chriskiehl/Deoplice có phải mã nguồn mở không?
Có — chriskiehl/Deoplice phát hành theo license MIT, nghĩa là mã nguồn mở để đọc, fork và (tùy license) tái sử dụng. Mã: github.com/chriskiehl/Deoplice.
chriskiehl/Deoplice có website riêng không?
TopGit chưa ghi nhận URL trang chủ cho chriskiehl/Deoplice. Phần README ở tab phía trên thường có link demo, hoặc xem mô tả GitHub của repo.
chriskiehl/Deoplice là gì?
chriskiehl/Deoplice (chriskiehl/Deoplice) là dự án Java trên GitHub. Theo mô tả gốc: Very spicy additions to Lombok's annotations
Đọc thêm về chriskiehl/Deoplice ở đâu?
Trang TopGit này là một snapshot — tab "Readme" hiển thị nguyên văn README của repo (đã bỏ link, giữ ảnh). Repo GitHub ở github.com/chriskiehl/Deoplice là nguồn chính thức.
Đọc đầy đủ README ở tab phía trên.
Muốn nghe thêm một ý kiến về Deoplice?
Hỏi một AI đọc được trang này — một cú bấm là có ngay nhận định về Deoplice.