I'm writing spring app for storing and manipulating recipes. I wrote ShoppingList service which generates, based on UUIDs of recipes, shopping list. This is my current model for which i wrote tests and works as intended.
Service uses another service called IngredientConverter
which converts to response models. Now i wanted to move some dependency to ShoppingList
as this function is jealous of functions, but approached a problem. How can a this class use IngredientConverter
service without ugly passing it to ShoppingList
function? Are there any tips you could give my code and structure planning?
@Service
@AllArgsConstructor
public class ShoppingListService {
private final RecipeService recipeService;
private final IngredientConverter ingredientConverter;
public ShoppingList generateShoppingList(List<UUID> uuidsOfRecipes) {
List<Recipe> recipes = recipeService.getAllByIDIn(uuidsOfRecipes);
ShoppingList shoppingList = ShoppingList.empty();
Map<Ingredient, Integer> ingredients = new HashMap<>();
recipes.forEach(recipe ->
recipe.getIngredients().forEach(
ingredientQuantity ->
ingredients.compute(
ingredientQuantity.getIngredient(),
(key, value) ->
value == null ?
ingredientQuantity.getAmount() :
value + ingredientQuantity.getAmount())));
ingredients.keySet().forEach(
ingredient ->
shoppingList.getIngredients().add(
ingredientConverter.convertWithAmount(
ingredient.getName(),
ingredients.get(ingredient),
ingredient.getUnit())
)
);
return shoppingList;
}
}
@Data
@AllArgsConstructor
public class ShoppingList {
private final List<IngredientQuantity> ingredients;
public static ShoppingList of(List<IngredientQuantity> ingredients) {
return new ShoppingList(ingredients);
}
public static ShoppingList empty(){
return ShoppingList.of(new ArrayList<>());
}
}
@Service
public class IngredientConverter {
public IngredientQuantity convertWithAmount(String name, int amount, Unit unit) {
return IngredientQuantity.builder()
.amount(amount)
.ingredient(convert(name, unit))
.build();
}
}
@Data
@Entity
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class IngredientQuantity extends IdentifiableEntity {
private int amount;
@ManyToOne
private Ingredient ingredient;
}
@Data
@Getter
@Entity
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class Ingredient extends IdentifiableEntity {
private String name;
@Enumerated(EnumType.STRING)
private Unit unit;
}
@Getter
@NoArgsConstructor
@SuperBuilder
@MappedSuperclass
public class IdentifiableEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID ID;
}
```