📜 ⬆️ ⬇️

Introducing the Green-forest Framework

Green-forest Logo
I want to tell the Habr Java community about a small, but very useful (personal experience) framework called Green-forest . This framework can be used both independently and in the context of JEE or Spring.

How it can be used to simplify the application code will be found under the cut.


')
In the beginning we consider the problem for the solution of which Green-forest is intended.

Problem


Very often, the architecture of a large project has the following form:


In this case, the business layer and the data layer consist of classes of services that provide the public API to the outside world.
An example of such a service:
public interface UserService { User createUser(Object someData); void activateUser(long id); User updateUser(User updatedUser); void blockUser(long id); void unblockUser(long id); } 


As the application grows, the number of methods in such services grows, which means the cumbersome implementation-class increases:
 public class UserServiceImpl implements UserService { //  1-   public User createUser(Object someData) { //  10-15  } // 16-   public void activateUser(long id) { //  10-15  } // .. //  1000-   public void unblockUser(long id) { //  10-15  } } 


As a result, classes appear that contain dozens of methods and 1000 lines of code. Search and maintain code in such classes becomes difficult and dreary.

Classic solution



The obvious solution seems to be the division of one large service into many smaller ones:
 public interface UserBasicService { User createUser(Object someData); void activateUser(long id); User updateUser(User updatedUser); } public interface UserModerationService { void blockUser(long id); void unblockUser(long id); } 


However, besides simplicity, this approach has several disadvantages:

The difficulty of uniform separation : it is difficult to divide the service into equal parts. In one new service, 3 methods remain, in the other - 10.

The ambiguity of separation : it is difficult to determine which child service to transfer a specific method. As a result, methods are transferred illogically and the API is complicated to understand.

Elimination of symptoms, but not the reasons: in fact, we did not solve the problem, because with the growth of methods in new services, they also risk turning into bulky 1000 line implementations.

Let's try to solve the problem of bulky service in a new way.

Solution through atomic functions


Since our simple division of the service into several similar ones does not provide a complete solution to the problem, let us ask ourselves, can we divide it into more atomic entities? Of course we can! After all, the purpose of any service is its methods, which means that by creating a lot of individual methods, we will get rid of the shortcomings voiced above:

There are no problems of uneven and ambiguous separation : the set of methods is divided evenly and unequivocally by its definition.

The growth problem has been solved: when new methods appear, we simply create new classes without increasing the size of the old ones.

Implementation of the solution in Green-forest



The Green-forest Framework uses the Action-Handler architecture, illustrated by the diagram:


Consider the components of this scheme:

  1. Action


    The Action class represents an atomic "method" that can be "called." Inside the class contains input and output data:
     // Action     - String   - Integer public class SomeAction extends Action<String, Integer>{ public SomeAction(String input) { super(input); } } 

  2. Handler


    The Handler class contains a specific implementation for this Action type:
     @Mapping(SomeAction.class) public class SomeHandler extends Handler<SomeAction>{ @Inject SomeService service; public void invoke(SomeAction action) throws Exception { String input = action.getInput(); Integer result = service.doSomeWork(input); action.setOutput(result); } } 


  3. Framework


    The Engine Framework object provides the link between Action and Handler objects:
     //  Engine Engine engine = new Engine(); //  engine.putHandler(SomeHandler.class); //  Integer result = engine.invoke(new SomeAction("some data")); 



Usage example


So, we have considered the key classes of the framework. Using them, we will refactor the example with our UserService service.

At the beginning, we will inherit the UserService from the ActionService service interface:
 import com.gf.service.ActionService; public interface UserService extends ActionService { //    -    ActionService } 


Next, create a set of Action classes:
 import com.gf.Action; public class CreateUser extends Action<Object, User> { public CreateUser(Object someData){ this(someData); } } public class ActivateUser extends Action<Long, Void> { public ActivateUser(Long id){ this(id); } } /*  .  : UpdateUser.java BlockUser.java UnblockUser.java ... */ 


It remains to create handlers for these classes. For example:
 @Mapping(CreateUser.class) public class CreateUserHandler extends Handler<CreateUser>{ public void invoke(CreateUser action) throws Exception { Object input = action.getInput(); User user = ... action.setOutput(user); } } 


An example of the final implementation of the UserServiceImpl implementation:
 import com.gf.Action; import com.gf.core.Engine; public class UserServiceImpl implements UserService { Engine engine; public UserServiceImpl(){ engine = new Engine(); // Handler     engine.scanAndPut("some.package"); } public <I, O> O invoke(Action<I, O> action) { return engine.invoke(action); } public <I, O> O invokeUnwrap(Action<I, O> action) throws Exception { return engine.invokeUnwrap(action); } } 


As a result, we divided the large UserService interface into a set of Action classes, and the implementation of the UserServiceImpl into a set of Handler classes.

Conclusions and references


We considered the problem of concentrating logic in one class and ways of solving, including the division into atomic class methods. Next, we met the Green-forest Framework, which implements the latter approach using the Action-Handler architecture. Using Green-forest, you can simplify and structure the code of your application.

Enjoy your work, colleagues!

References:
Green-forest Framework
Documentation

Source: https://habr.com/ru/post/168855/


All Articles