I've a class which calls a service which returns makes different types of predictions. The API returns the confidence score for each label for each prediction type. Currently I call the service and then store all the scores returned by the service. However after doing some investigation, I've found that in my use case I'll need to change the thresholds for the labels returned by the service for one prediction type.
So for example: I called the service for predicting whether an image is of an animal or not and the service has two labels True or false.
{
predictedValue: True,
details: {
True: 0.65,
False: 0.35
}
}
The predictedValue field is what the prediction service owner thinks the image is based on it's thresholds. But my results from the API indicates that unless the True confidence is greater than 0.70 it never is an animal.
public class PredictionResults {
String prediction;
Map<String, Double> details;
}
public class PredictionServiceDataLoader {
public void getAndStorePredictionResults(String predictionType, String id) {
PredictionResults predictionResults = getPredictionByCallingPredictionService(predictionType);
saveResults(predictionResults, id);
}
}
Now since I want to override the results returned by the service and one way of doing that is:
public void getAndStorePredictionResults(String predictionType, String id) {
PredictionResults predictionResults = getPredictionByCallingPredictionService(predictionType);
if(predictionType.equals("detectAnimal")) {
//Override value based on threshold
if(predictionResults.getDetails().get("True") < 0.70) {
predictionResults.setPrediction("False");
}
}
saveResults(predictionResults, id);
}
Now if I want to remove the responsibility of changing the results based on threshold outside PredictionServiceDataLoader then I was thinking of implementing in the following way:
public interface PredictionResultsOverride {
public String getPreditionType();
public String getPredictionResults(PredictionResults predictionResults);
}
public class AnimalPredictionResultOverride implements PredictionResultsOverride {
#Override
public String getPreditionType() {
return "detectAnimal";
}
#Override
public String getPredictionResults(PredictionResults predictionResults) {
if(predictionResults.getDetails().get("True") < 0.70) {
predictionResults.setPrediction("False");
}
}
}
Then my PredictionServiceDataLoader will do delegate the responsibility of modifying the results to a different class in the following way:
public class PredictionServiceDataLoader {
#Autowired
private List<PredictionResultsOverride> predictionResultsImpl;
public void getAndStorePredictionResults(String predictionType, String id) {
PredictionResults predictionResults = getPredictionByCallingPredictionService(predictionType);
Optional<PredictionResultsOverride> predictionResultsOverrideImpl =
predictionResultsImpl.stream()
.filter(x -> x.getType().equals(predictionType))
.findFirst();
predictionResults = predictionResultsOverrideImpl.map(x -> x.getPredictionResults(predictionResults)).orElse(predictionResults);
saveResults(predictionResults, id);
}
}
Is this the best way to delegate the responsibility of overriding thresholds to a different class? Is there a different approach I can take? In my opinion the responsibility of PredictionServiceDataLoader class should be just to call the prediction service and store the results.
"In my opinion the responsibility of PredictionServiceDataLoader class should be just to call the prediction service and store the results."
You are correct, PredictionServiceDataLoader, ideally, should retrieve the results and store it.
Your requirement is to override the results based on some criteria. This can be taken care just before showing it to end-users (or before using it for further processing). This way, you will have raw results stored and can be referred in case of modified overridden criteria (for ex. true should be >=80%). If you store the results after overriding it then you will have to keep additinal details (like isOverridden, criteria etc ) along with the result.
Related
I follow one example with small modifications: https://dzone.com/articles/spring-webflux-first-steps
My ServiceImpl looks like:
private final HotelRepository hotelRepository;
private final HotelByLetterRepository hotelByLetterRepository;
public HotelServiceImpl(HotelRepository hotelRepository, HotelByLetterRepository hotelByLetterRepository) {
this.hotelRepository = hotelRepository;
this.hotelByLetterRepository = hotelByLetterRepository;
}
#Override
public Mono<Hotel> save(Hotel hotel) {
if (hotel.getId() == null) {
hotel.setId(UUID.randomUUID());
}
Mono<Hotel> saved = hotelRepository.save(hotel);
saved.then(hotelByLetterRepository.save(new HotelByLetter(hotel)));
return saved;
}
After Hotel entity is saved logic try to save HottelByLetter.
In repository I inject ReactiveCassandraOperations and for a save method I just call insert method.
#Repository
public class CassandraHotelRepository implements HotelRepository {
private final ReactiveCassandraOperations cassandraTemplate;
public CassandraHotelRepository(ReactiveCassandraOperations cassandraTemplate) {
this.cassandraTemplate = cassandraTemplate;
}
#Override
public Mono<Hotel> save(Hotel hotel) {
return cassandraTemplate.insert(hotel);
}
}
After service call only Hotel is saved, HotelByLetter is not saved.
After debug I found that:
In ReactiveCqlTemplate method createFlux is called properly two times with correct ReactiveSessionCallback.
protected <T> Flux<T> createFlux(ReactiveSessionCallback<T> callback) {
Assert.notNull(callback, "ReactiveStatementCallback must not be null");
ReactiveSession session = getSession();
return Flux.defer(() -> callback.doInSession(session));
}
But, callback.doInSession(session) is executed only once for insert new hotel.
I try also to extend ReactiveCrudRepository, but same issue.
I'm using: org.springframework.data/spring-data-cassandra/2.0.0.RELEASE
TL;DR;
You need to work with the results of each publisher operator to apply the actual operation which created the Publisher.
Explanation
Project Reactor's fundamental concept is to never mutate a Publisher through operators but rather returning a new instance. That's different in contrast to say a Future like CompletableFuture where you're able to register callbacks, and you're not obliged to reuse the result of the callback registration method to make it work.
The code of your HotelServiceImpl should look like the following:
class HotelServiceImpl implements HotelService {
// …
#Override
public Mono<Hotel> save(Hotel hotel) {
if (hotel.getId() == null) {
hotel.setId(UUID.randomUUID());
}
Mono<Hotel> saved = hotelRepository.save(hotel);
return saved.then(hotelByLetterRepository.save(new HotelByLetter(hotel)));
}
}
Calling saved.then(…) creates a new Mono. Dropping (not using) that Mono will result in not executing the .then(…) operator. Instead, returning the result of saved.then(…) will do also save HotelByLetter.
We've implemented the adapter design pattern whose job is the following:
Act as a liaison between service and data access layers.
Convert raw data (from data source, internal or external) to domain specific data. Do necessary validation and massaging.
Sometimes, making the DAO calls may depend on data not readily available from input parameters or additional service calls may need to be made based on input data. In other words, the adapter can't always do a 1:1 mapping between the service and the DAO. It may map the same call from service to different DAO calls based on the input parameters.
Item #3 is starting to worry me as the adapters are becoming more complicated than I'd originally imagined. I'm not aware of a design pattern to trim down an adapter. Is there one? Suggestions?
You've used what I like to call the "swiss army knife" pattern.
Point 1 is broker pattern (or similar)
Point 2 is adapter pattern (or similar)
Point 3 is content based routing (or similar)
Best practice says you should break up your class into at least 3 classes, one for each concern.
Instead of using an adapter or a full Repository(CRUD operations), i would use an IReader interface for reading and visitor pattern for insert update delete, so you can separate domain logic from infraestructure(persistance) details, Here is the idea:
public class MyBusinessObject : IAcceptBusinessVisitor, IAcceptMyBusinessIdVisitor
{
private readonly string _id;
private string MyPrivateProp { get; set; }
//Fully encapsulated object
public MyBusinessObject(string id, string myPrivateProp)
{
_id = id;
MyPrivateProp = myPrivateProp;
}
public void UpdateMyProp(string newProp)
{
if (string.IsNullOrWhiteSpace(newProp)) throw new ArgumentNullException(nameof(newProp));
//Business rules ...
MyPrivateProp = newProp;
}
public void Accept(IMyBusinessObjectVisitor visitor)
{
if (visitor == null) throw new ArgumentNullException(nameof(visitor));
visitor.Visit(_id, MyPrivateProp);
}
public void Accept(IMyBusinessIdVisitor visitor)
{
if (visitor == null) throw new ArgumentNullException(nameof(visitor));
visitor.Visit(_id);
}
}
public interface IAcceptBusinessVisitor
{
void Accept(IMyBusinessObjectVisitor visitor);
}
public interface IAcceptMyBusinessIdVisitor
{
void Accept(IMyBusinessIdVisitor visitor);
}
public interface IMyBusinessObjectVisitor
{
void Visit(string id, string prop);
}
public interface IMyBusinessIdVisitor
{
void Visit(string id);
}
public class SavePersistanceVitor : IMyBusinessObjectVisitor
{
public void Visit(string id, string prop)
{
//Save to Database
}
}
public class UpdatePersistanceVitor : IMyBusinessObjectVisitor
{
public void Visit(string id, string prop)
{
//Update to Database
}
}
public class DeleteVitor : IMyBusinessIdVisitor
{
public void Visit(string id)
{
//Delete in Database
}
}
Here for Reading:
public interface IMyBusinessObjectReader
{
MyBusinessObject Read(string id);
}
class MyBusinessObjectReaderFromDb : IMyBusinessObjectReader
{
public MyBusinessObject Read(string id)
{
//Read from database
string myPrivateProp = "";
return new MyBusinessObject(id, myPrivateProp);
}
}
the next step could be adding generics for reading and the visitors. In this case you end up having little tiny classes and gain flexibility and the benefits of solid principles like single responsability, interface segregation, etc. So you can create a rich encapsulated domain and extend its functionality with some desing principles.
Regards!
I have an object which has a few arrays as fields. It's class roughly looks like this:
public class Helper {
InsuranceInvoices[] insuranceInvoices;
InsuranceCollectiveInvoices[] insuranceCollectiveInvoices
BankInvoices[] bankInvoices;
BankCollectiveInvoices[] bankCollectiveInvoices;
}
All of the invoice types have a mutual marker interface Invoices.
I need to get all of the invoices to invoke another method on them.
Helper helperObject = new Helper();
// ...
for (InsuranceInvoices invoice : helperObject.getInsuranceInvoices()) {
Integer customerId = invoice.getCustomerId();
// ...
}
for (BankInvoices invoice : helperObject.getBankInvoices()) {
Integer customerId = invoice.getCustomerId();
// ...
}
// repeat with all array fields
The problem is that all invoices only have the marker interface in common. The method getCustomerID() is not defined by a mutual interface or class. This is a behaviour I cannot change due to a given specification.
The code repetition inside the for-each-loop is something that bugs me. I have to do the exact same thing on all invoice objects in the four different arrays. Hence four for-each-loops that unecessary bloat the code.
Is there a way that I can write a general (private) method? One idea was:
private void generalMethod(Invoice[] invoiceArray){
// ...
}
But this would require four instanceof checks because the class Invoice doesn't know the method getCusomterId(). Therefore I would gain nothing; the method would still contain repetitions.
I'm thankful for every possible solution to generalize this problem!
Possible solutions to generalize the problem (ordered from best to worst):
Using wrapper class
public class InvoiceWrapper {
private String customerID;
public String getCustomerID() {
return customerID;
}
public InvoiceWrapper(BankInvoices invoice) {
this.customerID = invoice.getCustomerID();
}
public InvoiceWrapper(InsuranceInvoices invoice) {
this.customerID = invoice.getCustomerID();
}
// other constructors
}
Upd If I understood correctly, you need to do something with IDs in all arrays. To use InvoiceWrapper, you also need to implement iterator in Helper class, that will walk through arrays and return a wrapper for each entry. So, you will have code that works with 4 arrays anyway.
Using instance of casts
public class CustomerIdHelper {
public static String getID(Invoice invoice) {
if (invoice instanceof InsuranceInvoices) {
return ((InsuranceInvoices) invoices).getCustomerID();
} else if ...
}
}
Calling methods by name via Reflection
public class CustomerIdHelper {
public static String getID(Invoice invoice) {
Method method = invoice.getClass().getDeclaredMethod("getCustomerId");
return (String) method.invoke(invoice);
}
}
It's not pretty, but you could use reflection to look up the getCustomerId Method and then invoke() it, cf. Class.getDeclaredMethod().
private void generalMethod(Invoice[] invoiceArray){
try {
for (Invoice invoice : invoiceArray) {
Method getCustomerId = invoice.getClass().getDeclaredMethod("getCustomerId");
getCustomerId.invoke(invoice);
}
} catch (Exception e) {
// ...
}
}
Do note that this is untested.
If you are not allowed to change the classes you are handling by adding a custom interface to them. The best thing you can do is wrap them with a custom class that does have the desired properties.
This way you will have one class with all 'not so nice' code that converts the classes you can not touch to nice classes that match a proper and useful design.
For instance you could have a class WrappedInsuranceInvoice that extends WrappedInsurace and contains a member field InsuranceInvoice. If you don't need to keep the original class you would be off even better by copying the data. This way you could for instance lose the arrays and use lists instead.
Let's say I have a manufacturing scheduling system, which is made up of four parts:
There are factories that can manufacture a certain type of product and know if they are busy:
interface Factory<ProductType> {
void buildProduct(ProductType product);
boolean isBusy();
}
There is a set of different products, which (among other things) know in which factory they are built:
interface Product<ActualProductType extends Product<ActualProductType>> {
Factory<ActualProductType> getFactory();
}
Then there is an ordering system that can generate requests for products to be built:
interface OrderSystem {
Product<?> getNextProduct();
}
Finally, there's a dispatcher that grabs the orders and maintains a work-queue for each factory:
class Dispatcher {
Map<Factory<?>, Queue<Product<?>>> workQueues
= new HashMap<Factory<?>, Queue<Product<?>>>();
public void addNextOrder(OrderSystem orderSystem) {
Product<?> nextProduct = orderSystem.getNextProduct();
workQueues.get(nextProduct.getFactory()).add(nextProduct);
}
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy())
factory.buildProduct(workQueues.get(factory).poll());
}
}
Disclaimer: This code is merely an example and has several bugs (check if factory exists as a key in workQueues missing, ...) and is highly non-optimal (could iterate over entryset instead of keyset, ...)
Now the question:
The last line in the Dispatcher (factory.buildProduct(workqueues.get(factory).poll());) throws this compile-error:
The method buildProduct(capture#5-of ?) in the type Factory<capture#5-of ?> is not applicable for the arguments (Product<capture#7-of ?>)
I've been racking my brain over how to fix this in a type-safe way, but my Generics-skills have failed me here...
Changing it to the following, for example, doesn't help either:
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy()) {
Product<?> product = workQueues.get(factory).poll();
product.getFactory().buildProduct(product);
}
}
Even though in this case it should be clear that this is ok...
I guess I could add a "buildMe()" function to every Product that calls factory.buildProduct(this), but I have a hard time believing that this should be my most elegant solution.
Any ideas?
EDIT:
A quick example for an implementation of Product and Factory:
class Widget implements Product<Widget> {
public String color;
#Override
public Factory<Widget> getFactory() {
return WidgetFactory.INSTANCE;
}
}
class WidgetFactory implements Factory<Widget> {
static final INSTANCE = new WidgetFactory();
#Override
public void buildProduct(Widget product) {
// Build the widget of the given color (product.color)
}
#Override
public boolean isBusy() {
return false; // It's really quick to make this widget
}
}
Your code is weird.
Your problem is that you are passing A Product<?> to a method which expects a ProductType which is actually T.
Also I have no idea what Product is as you don't mention its definition in the OP.
You need to pass a Product<?> to work. I don't know where you will get it as I can not understand what you are trying to do with your code
Map<Factory<?>, Queue<Product<?>>> workQueues = new HashMap<Factory<?>, Queue<Product<?>>>();
// factory has the type "Factory of ?"
for (Factory<?> factory: workqueues.keySet())
// the queue is of type "Queue of Product of ?"
Queue<Product<?>> q = workqueues.get(factory);
// thus you put a "Product of ?" into a method that expects a "?"
// the compiler can't do anything with that.
factory.buildProduct(q.poll());
}
Got it! Thanks to meriton who answered this version of the question:
How to replace run-time instanceof check with compile-time generics validation
I need to baby-step the compiler through the product.getFactory().buildProduct(product)-part by doing this in a separate generic function. Here are the changes that I needed to make to the code to get it to work (what a mess):
Be more specific about the OrderSystem:
interface OrderSystem {
<ProductType extends Product<ProductType>> ProductType getNextProduct();
}
Define my own, more strongly typed queue to hold the products:
#SuppressWarnings("serial")
class MyQueue<T extends Product<T>> extends LinkedList<T> {};
And finally, changing the Dispatcher to this beast:
class Dispatcher {
Map<Factory<?>, MyQueue<?>> workQueues = new HashMap<Factory<?>, MyQueue<?>>();
#SuppressWarnings("unchecked")
public <ProductType extends Product<ProductType>> void addNextOrder(OrderSystem orderSystem) {
ProductType nextProduct = orderSystem.getNextProduct();
MyQueue<ProductType> myQueue = (MyQueue<ProductType>) workQueues.get(nextProduct.getFactory());
myQueue.add(nextProduct);
}
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy())
buildProduct(workQueues.get(factory).poll());
}
public <ProductType extends Product<ProductType>> void buildProduct(ProductType product) {
product.getFactory().buildProduct(product);
}
}
Notice all the generic functions, especially the last one. Also notice, that I can NOT inline this function back into my for loop as I did in the original question.
Also note, that the #SuppressWarnings("unchecked") annotation on the addNextOrder() function is needed for the typecast of the queue, not some Product object. Since I only call "add" on this queue, which, after compilation and type-erasure, stores all elements simply as objects, this should not result in any run-time casting exceptions, ever. (Please do correct me if this is wrong!)
I am working on a component which is supposed to:
receive data (collection of items) from some external calculation component. I expect about 100-1K of items on input on each request.
validate data, calculate some attributes if missing
persist data
There are about ten types of items. I use inheritance to model items. I have a base item class with common attributes and calculations and subclasses implementing type specific problems. Similar to following example:
public abstract class BaseItem {
String name;
boolean valid = true;
public void postCalucate() {
//common calculation
valid = valid && (name != null);
}
}
public class ItemA extends BaseItem {
BigDecimal value;
#Override
public void postCalucate() {
//some A specific calculations
super.postCalucate();
}
}
public class ItemA1 extends ItemA {
BigDecimal extraValue;
#Override
public void postCalucate() {
//some A1 subtype specific calculations
valid = isA1ItemValid();
super.postCalucate();
}
}
public class ItemB extends BaseItem {
Integer size;
#Override
public void postCalucate() {
//some B specific calculations
super.postCalucate();
}
}
Is there any better way/pattern to do my task? Any advices?
The pattern you are trying to use is fairly sound. In general, I would probably suggest the use of an interface instead of a BaseItem class, since it might not contain that much common functionality.
In general, most people seem to recommend defining interfaces for your classes to implement. If absolutely you want to share common code in an AbstractClass, I would recommend that class implementing the interface, since this pattern would lend itself to greater extensibility and flexibility in the future.
As such, you would first begin by defining what an Item is for you. For me, it seems that an Item is three things in your use case: one, it must define the postCalculate() method that will be called on all Items. Second, it must provide an isValid() method. And third, it should also provide a getName() method.
public interface Item {
void postCalucate();
boolean isValid();
String getName();
}
Then you would begin implementing your Abstract class. Do this only if it really is necessary to share a codebase between all your items.
public abstract class BaseItem implements Item {
String name;
boolean valid = true;
public void postCalucate() {
//common calculation
valid = valid && (name != null);
}
public boolean isValid() {
return valid;
}
public String getName() {
return name;
}
}
If BaseItem.postCalculate() is something that will need to be done for all items, this is a good way to do it. If you're not entirely sure, it might be a good idea instead to define a method somewhere in a Helper or Tool class that performs this common calculation for items, and is called by the postCalculate() methods:
public class ItemTools {
public static boolean meetsRequirements(Item item) {
return item.isValid && item.getName() != null;
}
}
This, many would argue, gives you an easier time as your requirements on BaseItem may change over time.
Regardless of which route you go there, now you'll just have to define your actual items:
public class ItemA extends BaseItem {
BigDecimal value;
#Override
public void postCalucate() {
//some A specific calculations
super.postCalucate();
}
}
While the general advice is to avoid over-usage of inheritance, this is no case of over-usage. So, go ahead with this approach.
Apart from that: Your code shows problems with encapsulation. You shouldn’t have all these non-private field. As a reminder: no visibility at all is package-visibility (visible in the whole package and to all sub-classes). Make your fields private.
A priori, your proposal seems reasonable.
But to be sure, you have to look at all the events of the life cycle of your objects:
instantiation
use, read
collaboration
persistence
...