OOPs : Suggest design for the following scenario - java

I have a Product object. The Product is taxed at different rates in different places/situations.
Some of the products are not taxable at all (Example : Medicine)
For example , buying the product may cost $X in shop A and $Y at shop B . It can cost differently in two different states(state taxes are different).
My question is , can we have the attributes to determine the taxes inside the Product object itself.
For example is it a good idea to have attributes such as
Boolean isImported ;
Boolean isTaxable ;
Or do we have a better design pattern to do this ?

First of all, I believe there is no single, good answer to this question.
You can have the attributes to determine the taxes inside a Product. However, I would recommend to have a separate class (TaxCalculator?) that would calculate the tax of a Product based on its origin, type, transaction, etc. The motivation is that the Product should represent a product data only; why should e.g. a bottle of wine care what are the taxes assigned to it? Something else should do it, something that is specialised in calculating the tax based on the product.
But that is only my opinion and I do not claim it is the best one. I would like to hear from some more experienced users.

Products need not to know about the tax. Tax is logically related to a sale, so is the product price. In our app we have the following (simplified):
public class Invoice {
private InvoiceItem[] invoiceItems;
}
public class InvoiceItem{
private ProductPrice productPrice;
private BigDecimal taxRate;
}
public class ProductPrice{
private Product product;
private BigDecimal price;
private String currencyCode;
}
public class Product{
....
}

You can certainly put those attributes in the Product class.
Or you can create a separate interface (TaxStrategy?) that would take a Product and return a Money tax amount:
public interface TaxStrategy {
Money calculateTax(Product p);
}
That way you can have different implementations of the interface that compute taxes in different ways. Products need not know that they're taxable. It separates the thing that you sell from the way that you price it.

Related

Hints about OptaPlanner configuration to solve Vehicle Routing (real-time)

I would be glad for any kind of opinion on this setup for a Vehicle Routing Problem.
First of all, these are my first steps with this tool, so please forgive me if I'm totally out of scope :-)
I've made an algorithm without optaplanner, to test a basic rules setup.
It worked for a single Vehicle, but optaplanner looked very similar to my original idea to assign points to each satisfied rule, then select the vehicle with the higest score.
It's also configurable, and for sure it's better than what I made before.
Let's begin
Looking at the docs, and some videos, seems that VRP problems are solved when all the pickup points have been already defined in a dataset feeded into the Solver.
What about finding a Vehicle for each request in real-time, refusing it in case no vehicle can satisfy the constraints? Consider that there are calls to external (paid) Maps services, that are making the process slower, and have a cost. It's better to avoid redundancy in these calls.
Pickup requests can be done for any future date, but not the current day.
Planning Entity - the pickup request
#PlanningEntity
public class FindBestVehicleRequest
{
#PlanningId
private Long id;
// Shadow variable candidate
private Double requiredSpace;
// Shadow variable candidate
private int requiredAutonomy;
private String pickupAddress;
// Shadow variable candidate
private LatLng pickupPosition;
private LocalDateTime pickupDateTime;
#PlanningVariable(valueRangeProviderRefs = "vehicle")
private Vehicle vehicle;
...
}
Calculations involved in each request
I've read into the docs about shadow variables, I'm still far from understanding how to define them, but I suppose that are useful in my case: as stated before, for each request I need to call the Maps Service(Google, OpenStreetMaps, ...) in order to calculate the distance to reach the pickup address from vhere the vehicle is located.
Obtain the Vehicle origin position,
some pseudo code of the logic:
if (vehicle.hasOrdersBefore(pickupDateTime) {
LatLng origin = vehicle.lastOrderBefore(pickupDateTime).getPosition();
String destination = pickupAddress;
Integer distance = mapsServer.getDistance(origin, destination);
return distance;
}
There are more calculations like this one involved, but there's no need to list all of them, they're similar.
I'm studying all the available algorithm types to find the one that's more indicated for this problem.
ConstraintProvider implementation
public class BestVehicleConstraintProvider implements ConstraintProvider {
#Override public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
return new Constraint[]{
vehicleHasAutonomy(constraintFactory)
};
}
// One HARD constraint
private Constraint vehicleHasAutonomy(ConstraintFactory constraintFactory) {
return constraintFactory.from(FindBestVehicleRequest.class)
.groupBy(FindBestVehicleRequest::getVehicle, sum(FindBestVehicleRequest::getRequiredAutonomy))
.filter((vehicle, requiredAutonomy) -> requiredAutonomy > vehicle.getVehicleTypeProperties().getMaxKmAutonomy())
.penalize("vehicleHasAutonomy", HardSoftScore.ONE_HARD,
((vehicle, requiredSpace) -> vehicle.getVehicleTypeProperties().getMaxKmAutonomy() - requiredSpace));
}
}
And the final part,
the Solution class
#PlanningSolution
public class FindBestVehicleSolution
{
#PlanningEntityCollectionProperty
private List<FindBestVehicleRequest> processes;
#ProblemFactCollectionProperty
#ValueRangeProvider(id = "vehicle")
private List<Vehicle> vehicles; // <----- I'm fetching a list of active Vehicles in
// the requested pickupDate, and passing it here
#ProblemFactProperty
private String pickupAddress;
// private LatLng pickupAddressPosition; // shadow variable ? how to call the map server
// and populate this field ?
#PlanningScore
private HardSoftScore score;
...
}
Ok, so I think that all the code is here. I'm looking for suggestions on proper ways to:
- call the maps server to get diestances in an efficient way
- avoid repeating the same calculations
- (IMPORTANT!) if a Vehicle satisfy certain rules, like if it has no assigned orders in the selected day, end the evaluation process directly (vehicle found!)
Yes I'm asking too much maybe, but the documentations is a bit hard to adapt to this situation, I think that with time I will get better, but I'd like to make some simulations with Optaplanner Workbench soon :-)
Thanks for anyone that will give any kind of suggestion!

Better way to write many if statements in Java?

So I have this homework where I need to build a vending machine, and I assigned a coordinate to every product (A1, A2, A3..) and when the user enters the coin value I have to calculate if he can buy the product that he chose and if yes calculate the change, since i'm still new to programming I now have ended up with many statements like this
if ("a1".equals(choice)) {
System.out.println("You chose SNICKERS!");
if (money < 50) {
System.out.println("This is not enough money to buy this product");
} else if (money >= 50) {
System.out.println(" Price = 50 Your change = " + (money - 50));
}
}
where the only things changing are the coordinates (a1, a2, a3, a4, b1, b2 and so on) and the prices. What would be a better way to do this?
You could use a more OO approach.
Make a class called Product:
class Product {
private String name;
private int price;
public String getName() { return name; }
public int getPrice() { return price; }
public Product(String name, int price) {
this.name = name;
this.price = price;
}
}
Then, create a HashMap<String, Product> and add all your products and their coordinates in:
HashMap<String, Product> productMap = new HashMap<>();
productMap.put("A1", new Product("Snickers", 50));
productMap.put("A2", new Product("Something else", 40));
// do this for every coordinate...
Now, you can just use this code:
Product chosenProduct = productMap.get(choice);
System.out.println("You chose " + chosenProduct.getName() + "!");
if (money < chosenProduct.getPrice()) {
System.out.println("This is not enough money to buy this product");
} else {
System.out.println(" Price = " + chosenProduct.getPrice() + " Your change = " + (money - chosenProduct.getPrice()));
}
This is a common moment in programming and you're right to think there's a better way to go about it.
In your particular case, where you have a similar structure of code in many places, you should try using a function. Try writing a private function in the same class that takes in some of the parameters that change. Depending on the level of complexity you end up with you might end up with a large function with a lot of parameters which isn't great either. Regardless, writing a function is probably the first place you should go when you encounter this situation.
Secondarily, consider what this segment of code is doing. Making a generic function to replace the whole code segment might not be ideal but could you easily write a function to do a small part of it? If so, is it now easy to make the rest into another function? Keep track of any variances you have across your many similar code segments, if any, and try to create functions that address those variations.
Finally, depending on what is in scope for your current level of programming, you might be able to create data structure to help with the identification of the choice. For example, maybe you could make a map where you could store each of the choices and an associated object that contains all of the data you need to respond to the user (i.e. cost, item name, etc.). With that kind of approach you can pre-populate all of those options in a straightforward manner and have your code simply look up the set of data associated with the choice and call of function to print the necessary output.
Ultimately, how you go about this and future situations like it is highly dependent upon what your level of experience with programming, how many choices there are, and how complex the data associated with each choice is.
Continue to trust your instincts though, they will serve you well.
Switch case is the desired functionality.
switch(choice) {
case 'a' : <some code>
break;
case 'b': <some other code>
break;
default: <if none of the choices matched>
}
The only caveat is that your choice value has to be a char or an int
EDIT:
This was a bad answer from my side. Clearly, you need a more cleaner way to write your vending machine.
A good way to structure it would be to first create a Product class which can store the name and the price of the product.
class Product {
private String name;
private String price;
// Implement a constructor and an equals() method to equate two
// instances of product
}
You could then create a function (which could be used in your main()) which takes the text input from your user and map it to an actual product.
public static Main(String[] args) {
// ...
private Product processUserInput(String productName) {
// Add logic to process the string and return a Product
}
// ...
}
Then you could add a function that would process the Product and the amount the user has and return the change remaining or maybe -1 if the product costs more than the available amount.
public static Main(String[] args) {
// ...
private int processUserProductChoice(Product product, int amountAvailable) {
// Add logic to process the product and amount
// Probably use switch case now.
}
// ...
}

Constructing object

I have a query in constructing an object and storing it in database in json format.
Its in air domain industry. Need to construct an ojbect and store it in database in json format so the other applications can use the same object for various test automation scripts.
What i have done is i have created a class called PassengerDetails and inserted to station, from station etc., as below.
class PassengerDetails{
private String toStation;// Origin
private String fromStation;// destination
private String noOfAdults;
and getters and setters.
}
The passenger type also changes, like infants, companions etc., and i am not understanding how to handle it in class PassengerDetails. I have a guess like i have to add another class for PassengerType. Please correct me if i am wrong and suggest me how to add that passengertype details.
And I have created one ticket class (one ticket for each passenger, if 3 adults are there then 3 tickets and and three tickets are associated with one unique PNR). Here we have to store how the ticket is purchased, i mean by cash or credit card
class PaymentDetails{
private String creditCardType;
private String creditCardNo;
private String creditCardHolderName;
private String cash;
getters and setters.
}
We are having different payment types like Creditcard, cash, vouchers, refund amount etc., I am in confusion again how to handle this in the above PaymentDetails Class and how to link this class with TicketInformation and PassengerDetails
class TicketInformation{
private List<PassengerDetails> passengerDetails;
Getters and setters...
}
For multiple tickets, we have one PNR.
class PNRDetails{
List<TicketInformation> ticketInformationList = new ArrayList();
getters and setters.
}
Now i have a query like, if there is modification in flights or dates etc., new ticket will be issued. Now the question is how to store this new tickets and old tickets so that the user who retrieves the list of tickets can understand that there is a modification and hence there are new tickets and old tickets.
The other scenario is that if there is an addition of additonal passenger then not only the ticket changes but also the PNR changes, Now the question is i want to store both new and old PNRs and associated tickets.
For multiple PNR's how to write the class, do i have to write a class where it has List as instance variable. I messed up the code and i am in confusion. Could any one suggest better approach in modifications of code.
Here's an example on how to create an object and storing in json format:
var myObj = { "name":"John", "age":31, "city":"New York" };
var myJSON = JSON.stringify(myObj);
window.location = "demo_json.php?x=" + myJSON;
This is a very simple example of course.
Go through this website for more information and tutorials:
https://www.w3schools.com/js/js_json_intro.asp

I have been tasked to create a foodstore that I can add and take food from, does my code achieve this?

I have been asked to model a foodstore that contains different types of food. I should be able to add a given quantity of a food type by using the addFood method and remove food using the takeFood method. The addFood must take the form addFood(String, int) and the takeFood must take the form takeFood(String), i.e. addFood("Steak", 5) would add 5 items of steak to the foodstore. I have attempted to make this class and wondered whether this meets what I have been tasked to do. For the sake of this example I will only use 2 food items but in reality there is much more.
public class Foodstore {
public void addFood(String food, int quantity) {
addFood("steak", quantity);
addFood("hay", quantity);
}
public void takeFood(String food) {
takeFood("Steak");
takeFood("hay");
}
}
Thanks in advance
Your food store is missing a warehouse
Map<String,Integer> warehouse = new HashMap<>();
and, as it is, when you add food you're ignoring the food you were told to add, not a good idea.
These are just some starting point, reorganize your code and explore your warehouse when you add data to make sure you're doing well.
I don't think so, you would need some kind of register where you actually save the information, like a Map:
Map<String,Integer> register = new HashMap<>();
You would have to rewrite your functions sth like this (have not been able to type it in an editor, but just so that you get the idea of it):
public void addFood(String food, int quantity) {
if (register.containsKey(food)) {
Integer newAmount = register.get(food) + quantity;
register.put(food,newAmount);
}
else {
register.put(food,quantity);
}
}
PS. You are (mis)using recursion, and I don't think it's what you want in your case. Your function addFood calls itself again and again without an end.

Aggregation of cartesian product of two hierachical trees using Java

Need to do aggregation of Cartesian product of two hierarchical tree structures using Java, Please suggest some good methods or API to do this.
Tree Structure:
Country Tree :
Node|Id|ParentId
World|1|1
Asia|2|1
Europe|3|1
India|4|2
China|5|2
UK|6|3
Hungary|7|3
Cyprus|8|3
Profit Tree:
Node|Id|ParentId
Profit|1|1
Revenue|2|1
Expense|3|1
Cartesian product of these two products would give me 24 combinations (8 X 3). I need to aggregate values for each of the combination.
For example, I want to know Total revenue of Europe, Asia and World, Total Profit of Europe etc
It's a bit hard to answer without details of the structures. But I'll guess what they might be and you can extrapolate to your structures.
enum EconomicDataType {
PROFIT, REVENUE, EXPENSE;
}
interface GeographicNode {
int getEconomicData(EconomicDataType type);
}
class Region implements GeographicNode {
private List<GeographicNode> geographiesInRegion;
public int getEconomicData(EconomicDataType type) {
return geographiesInRegion.stream()
.mapToInt(geog -> geog.getEconomicData(type))
.sum();
}
}
class Country implements GeographicNode {
private EnumMap<GeographicNode, Integer> economicData;
public int getEconomicData(EconomicDataType type) {
return economicData.get(type);
}
}
I have modelled economic data as a map rather than a tree because, frankly, it makes no sense to me to make it a hierarchy given there's nothing hierarchical about the data.
I also haven't handled the situation in which data is missing. Not hard to add with a containsKey check before getting the data from the map.
Retrieving someing like total revenue for europe is:
europe.getEconomicData(EconomicDataType.REVENUE);
Simple :-)

Categories