diff --git a/homework/src/HW1/submissions/partA/README.md b/homework/src/HW1/submissions/partA/README.md deleted file mode 100644 index cd40819..0000000 --- a/homework/src/HW1/submissions/partA/README.md +++ /dev/null @@ -1 +0,0 @@ -Add your submissions for part A of the homework here. \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/airbnb/BookingService.java b/homework/src/HW1/submissions/partA/erictran/airbnb/BookingService.java new file mode 100644 index 0000000..be27ae8 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/airbnb/BookingService.java @@ -0,0 +1,5 @@ +package HW1.submissions.partA.erictran.airbnb; + +public interface BookingService { + int calculateTotalPrice(Hotel hotel, int numberOfNights); +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/airbnb/BookingServiceImpl.java b/homework/src/HW1/submissions/partA/erictran/airbnb/BookingServiceImpl.java new file mode 100644 index 0000000..0f7a67a --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/airbnb/BookingServiceImpl.java @@ -0,0 +1,12 @@ +package HW1.submissions.partA.erictran.airbnb; + +public class BookingServiceImpl implements BookingService { + @Override + public int calculateTotalPrice(Hotel hotel, int numberOfNights) { + int totalPrice = hotel.calculateTotalPrice(numberOfNights); + if (hotel instanceof DiscountedHotel) { + totalPrice -= 50; + } + return totalPrice; + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/airbnb/DiscountedHotel.java b/homework/src/HW1/submissions/partA/erictran/airbnb/DiscountedHotel.java new file mode 100644 index 0000000..b168154 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/airbnb/DiscountedHotel.java @@ -0,0 +1,4 @@ +package HW1.submissions.partA.erictran.airbnb; + +public class DiscountedHotel extends Hotel { +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/airbnb/ExtraFeesService.java b/homework/src/HW1/submissions/partA/erictran/airbnb/ExtraFeesService.java new file mode 100644 index 0000000..dba743b --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/airbnb/ExtraFeesService.java @@ -0,0 +1,5 @@ +package HW1.submissions.partA.erictran.airbnb; + +public interface ExtraFeesService { + int calculateExtraGuestsFees(Hotel hotel, int numberOfGuests); +} diff --git a/homework/src/HW1/submissions/partA/erictran/airbnb/ExtraFeesServiceImpl.java b/homework/src/HW1/submissions/partA/erictran/airbnb/ExtraFeesServiceImpl.java new file mode 100644 index 0000000..de99faf --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/airbnb/ExtraFeesServiceImpl.java @@ -0,0 +1,8 @@ +package HW1.submissions.partA.erictran.airbnb; + +public class ExtraFeesServiceImpl implements ExtraFeesService{ + @Override + public int calculateExtraGuestsFees(Hotel hotel, int numberOfGuests) { + return hotel.calculateExtraGuestsFees(numberOfGuests); + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/airbnb/Hotel.java b/homework/src/HW1/submissions/partA/erictran/airbnb/Hotel.java new file mode 100644 index 0000000..f091788 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/airbnb/Hotel.java @@ -0,0 +1,14 @@ +package HW1.submissions.partA.erictran.airbnb; + +public class Hotel { + int calculateTotalPrice(int numberOfNights) { + return numberOfNights * 100; + } + + int calculateExtraGuestsFees(int numberOfGuests) { + if (numberOfGuests > 6) { + return (numberOfGuests - 6) * 30; + } + return 0; + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/airbnb/Main.java b/homework/src/HW1/submissions/partA/erictran/airbnb/Main.java new file mode 100644 index 0000000..a1fe2b8 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/airbnb/Main.java @@ -0,0 +1,20 @@ +package HW1.submissions.partA.erictran.airbnb; + +public class Main { + public static void main(String[] args) { + Hotel regularHotel = new Hotel(); + DiscountedHotel discountedHotel = new DiscountedHotel(); + + BookingService bookingService = new BookingServiceImpl(); + ExtraFeesService extraFeesService = new ExtraFeesServiceImpl(); + int regularHotelTotalPrice = bookingService.calculateTotalPrice(regularHotel, 3); + int discountedHotelTotalPrice = bookingService.calculateTotalPrice(discountedHotel, 3); + int regularHotelExtraGuestsFees = extraFeesService.calculateExtraGuestsFees(regularHotel, 7); + int discountedHotelExtraGuestsFees = extraFeesService.calculateExtraGuestsFees(discountedHotel, 8); + + System.out.println("Regular Hotel Total Price: $" + regularHotelTotalPrice); + System.out.println("Discounted Hotel Total Price: $" + discountedHotelTotalPrice); + System.out.println("Regular Hotel Extra Guests Fees: $" + regularHotelExtraGuestsFees); + System.out.println("Discounted Hotel Extra Guests Fees: $" + discountedHotelExtraGuestsFees); + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/airbnb/README.md b/homework/src/HW1/submissions/partA/erictran/airbnb/README.md new file mode 100644 index 0000000..3ac42cd --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/airbnb/README.md @@ -0,0 +1,46 @@ +# 'Airbnb' Violation of SOLID + +This code violates the "L" in SOLID, which stands for Liskov Substitution Principle +
+
+It officially states that "Objects of a superclass shall be replaceable with objects of its subclasses without breaking the application." +In other words, if you have a reference to a base type object, you should be able to use it to refer to a subtype object without any issues. +In this case, the 'DiscountedHotel' class changes the behavior of the 'calculateTotalPrice()' method. +Consider how the 'calculateTotalPrice' method in the 'Hotel' class returns the number of nights multiplied by the nightly rate while in the 'DiscountedHotel' class +it returns the total price minus a discount. +
+
+Hence, we cannot substitute a 'DiscountedHotel' object for a 'Hotel' object without breaking the code. +For example, if we passed a 'DiscountedHotel' object to the bookService.calculateTotalPrice() method, the total price may be calculated incorrectly. +
+
+A better design approach for this is to move the discount logic to the 'BookingServiceImpl' class. +
+
+Lets start off by removing the 'calculateTotalPrice' method from the 'DiscountedHotel' class: +``` +public class DiscountedHotel extends Hotel { + +} +``` +Now, lets refactor the 'calculateTotalPrice' in the 'BookingServiceImpl' class so that it checks if the current instance is a 'DiscountedHotel' object before applying the discount. +``` +public class BookingServiceImpl implements BookingService { + @Override + public int calculateTotalPrice(Hotel hotel, int numberOfNights) { + int totalPrice = hotel.calculateTotalPrice(numberOfNights); + if (hotel instanceof DiscountedHotel) { + totalPrice -= 50; + } + return totalPrice; + } +} +``` +After making the following changes, the code now adheres to the Liskov Substitution Principle of SOLID. +
+
+We have a Main class to test the new code. It should produce the following output: +``` +Regular Hotel Total Price: $300 +Discounted Hotel Total Price: $250 +``` \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/doordash/Customer.java b/homework/src/HW1/submissions/partA/erictran/doordash/Customer.java new file mode 100644 index 0000000..0bada33 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/doordash/Customer.java @@ -0,0 +1,13 @@ +package HW1.submissions.partA.erictran.doordash; + +public class Customer { + private String name; + + public Customer(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/doordash/DeliveryService.java b/homework/src/HW1/submissions/partA/erictran/doordash/DeliveryService.java new file mode 100644 index 0000000..de46259 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/doordash/DeliveryService.java @@ -0,0 +1,5 @@ +package HW1.submissions.partA.erictran.doordash; + +public interface DeliveryService { + void deliverFood(Restaurant restaurant, Customer customer); +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/doordash/FoodDeliveryService.java b/homework/src/HW1/submissions/partA/erictran/doordash/FoodDeliveryService.java new file mode 100644 index 0000000..1038c3b --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/doordash/FoodDeliveryService.java @@ -0,0 +1,8 @@ +package HW1.submissions.partA.erictran.doordash; + +public class FoodDeliveryService implements DeliveryService { + @Override + public void deliverFood(Restaurant restaurant, Customer customer) { + System.out.println("Food delivered from " + restaurant.getName() + " to " + customer.getName()); + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/doordash/Main.java b/homework/src/HW1/submissions/partA/erictran/doordash/Main.java new file mode 100644 index 0000000..ade3f41 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/doordash/Main.java @@ -0,0 +1,17 @@ +package HW1.submissions.partA.erictran.doordash; + +public class Main { + public static void main(String[] args) { + Restaurant restaurant = new Restaurant("Chick-fil-a"); + Customer customer = new Customer("Bobby"); + + DeliveryService deliveryService = new FoodDeliveryService(); + PackageTrackingService trackingService = new PackageTrackingService(); + + deliveryService.deliverFood(restaurant, customer); + + trackingService.trackPackage("123456789"); + + trackingService.calculateEstimatedDeliveryTime(100, 55); + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/doordash/PackageTrackingService.java b/homework/src/HW1/submissions/partA/erictran/doordash/PackageTrackingService.java new file mode 100644 index 0000000..0f83e54 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/doordash/PackageTrackingService.java @@ -0,0 +1,14 @@ +package HW1.submissions.partA.erictran.doordash; + +public class PackageTrackingService implements TrackingService { + @Override + public void trackPackage(String trackingNumber) { + System.out.println("Package with tracking number " + trackingNumber + " is being tracked."); + } + + @Override + public void calculateEstimatedDeliveryTime(double distanceInMiles, double deliverySpeedMPH) { + double estimatedDeliveryTime = distanceInMiles / deliverySpeedMPH; + System.out.printf("Package will be delivered in approximately %.2f hours.\n", estimatedDeliveryTime); + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/doordash/README.md b/homework/src/HW1/submissions/partA/erictran/doordash/README.md new file mode 100644 index 0000000..235c33e --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/doordash/README.md @@ -0,0 +1,62 @@ +# 'DoorDash' Violation of SOLID + +This code violates the "I" in SOLID, which stands for Interface Segregation Principle. +
+
+It officially states that "Clients should not be forced to depend on methods they do not use." +Examining the "FoodDeliveryAndTrackingService" class, it has two responsibilities, one +being delivering food and the other being tracking packages. +Though, clients that only need to deliver food do not need to depend on the trackPackage() method. +
+
+A better design approach is to split the "FoodDeliveryAndTrackingService" class into two. +For example, we can split the code into "FoodDeliveryService" and "PackageTrackingService." +
+
+We need to alter 'DeliveryService' interface so that it focuses on Food Delivery only: +``` +package doordash; + +public interface DeliveryService { + void deliverFood(Restaurant restaurant, Customer customer); +} +``` +We create a new 'FoodDeliveryService' class that focuses on Food Delivery only: +``` +package doordash; + +public class FoodDeliveryService implements DeliveryService { + @Override + public void deliverFood(Restaurant restaurant, Customer customer) { + System.out.println("Food delivered from " + restaurant.getName() + " to " + customer.getName()); + } +} +``` +We create a new 'TrackingService' interface so that it focuses on Package Tracking only: +``` +package doordash; + +public interface TrackingService { + void trackPackage(String trackingNumber); +} +``` +We create a new 'PackageTrackingService' class that focuses on Package Tracking only: +``` +package doordash; + +public class PackageTrackingService implements TrackingService { + @Override + public void trackPackage(String trackingNumber) { + System.out.println("Package with tracking number " + trackingNumber + " is being tracked."); + } +} +``` +After making the following changes, the code now adheres to the Interface Segregation Principle. +of SOLID. +
+
+We have a Main class to test the new code. It should produce the following output: +``` +Food delivered from Chick-fil-a to Bobby +Package with tracking number 123456789 is being tracked. +``` \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/doordash/Restaurant.java b/homework/src/HW1/submissions/partA/erictran/doordash/Restaurant.java new file mode 100644 index 0000000..9b3a5a1 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/doordash/Restaurant.java @@ -0,0 +1,13 @@ +package HW1.submissions.partA.erictran.doordash; + +public class Restaurant { + private String name; + + public Restaurant(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/doordash/TrackingService.java b/homework/src/HW1/submissions/partA/erictran/doordash/TrackingService.java new file mode 100644 index 0000000..a8d8853 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/doordash/TrackingService.java @@ -0,0 +1,7 @@ +package HW1.submissions.partA.erictran.doordash; + +public interface TrackingService { + void trackPackage(String trackingNumber); + + void calculateEstimatedDeliveryTime(double distanceInMiles, double deliverySpeedMPH); +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/facebook/ImagePost.java b/homework/src/HW1/submissions/partA/erictran/facebook/ImagePost.java new file mode 100644 index 0000000..7d8f3a1 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/facebook/ImagePost.java @@ -0,0 +1,24 @@ +package HW1.submissions.partA.erictran.facebook; + +public class ImagePost extends Post { + private String imageUrl; + + public ImagePost(String text, String imageUrl) { + super(text); + this.imageUrl = imageUrl; + } + + public String getImageUrl() { + return imageUrl; + } + + public void setImageUrl(String imageUrl) { + this.imageUrl = imageUrl; + } + + @Override + public void display() { + System.out.print("Image post: "); + System.out.println(imageUrl); + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/facebook/LiveVideoPost.java b/homework/src/HW1/submissions/partA/erictran/facebook/LiveVideoPost.java new file mode 100644 index 0000000..7fe8ec1 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/facebook/LiveVideoPost.java @@ -0,0 +1,24 @@ +package HW1.submissions.partA.erictran.facebook; + +public class LiveVideoPost extends Post { + private String liveVideoUrl; + + public LiveVideoPost(String text, String liveVideoUrl) { + super(text); + this.liveVideoUrl = liveVideoUrl; + } + + public String getLiveVideoUrl() { + return liveVideoUrl; + } + + public void setLiveVideoUrl(String videoUrl) { + this.liveVideoUrl = videoUrl; + } + + @Override + public void display() { + System.out.print("Video post: "); + System.out.println(liveVideoUrl); + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/facebook/Main.java b/homework/src/HW1/submissions/partA/erictran/facebook/Main.java new file mode 100644 index 0000000..9202164 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/facebook/Main.java @@ -0,0 +1,32 @@ +package HW1.submissions.partA.erictran.facebook; + +public class Main { + public static void main(String[] args) { + TextPost textPost = new TextPost("This is a text post."); + ImagePost imagePost = new ImagePost("Check out this image!", "https://example.com/image.jpg"); + VideoPost videoPost = new VideoPost("Watch this video!", "https://example.com/video.mp4"); + LiveVideoPost liveVideoPost = new LiveVideoPost("Join my stream!", "rtmp://facebook.com/live"); + + System.out.println("Text Post Test:"); + textPost.display(); + System.out.println("\nImage Post Test:"); + imagePost.display(); + System.out.println("\nVideo Post Test:"); + videoPost.display(); + System.out.println("\nLive Video Post Test:"); + liveVideoPost.display(); + + textPost.setText("Updated text post."); + System.out.println("\nUpdated Text Post:"); + textPost.display(); + imagePost.setImageUrl("https://example.com/image2.jpg"); + System.out.println("\nUpdated Image Post:"); + imagePost.display(); + videoPost.setVideoUrl("https://example.com/video2.mp4"); + System.out.println("\nUpdated Video Post:"); + videoPost.display(); + liveVideoPost.setLiveVideoUrl("rtmp://facebook.com/live2"); + System.out.println("\nUpdated Live Video Post:"); + liveVideoPost.display(); + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/facebook/Post.java b/homework/src/HW1/submissions/partA/erictran/facebook/Post.java new file mode 100644 index 0000000..cfdeb72 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/facebook/Post.java @@ -0,0 +1,21 @@ +package HW1.submissions.partA.erictran.facebook; + +abstract class Post { + protected String text; + + public Post(String text) { + this.text = text; + } + + public void setText(String text) { + this.text = text; + } + + public String getText() { + return text; + } + + public void display() { + System.out.println(text); + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/facebook/README.md b/homework/src/HW1/submissions/partA/erictran/facebook/README.md new file mode 100644 index 0000000..acffab0 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/facebook/README.md @@ -0,0 +1,119 @@ +# 'Facebook' Violation of SOLID + +This code violates the "O" in SOLID, which stands for Open-Closed Principle. +
+
+It officially states that "Classes should be open for extension, but closed for modification." +That means we should be able to add new functionality to a class without having to alter its existing code. +In this case, the second iteration of the 'Post' class has been extended to handle text, images, and videos +from pure text posts in the first iteration of the 'Post' class. However, the modification was done directly +in the 'Post' class rather than through some extension mechanism. +
+
+A better design approach is to use inheritance, creating separate classes for different types of posts like +'TextPost,' 'ImagePost,' and 'VideoPost,' each extending from the base 'Post' class. +
+
+Lets recall that the original 'Post' class looks like the following. We will make it an abstract class instead: +``` +abstract class Post { + protected String text; + + public Post(String text) { + this.text = text; + } + + public void setText(String text) { + this.text = text; + } + + public String getText() { + return text; + } + + public void display() { + System.out.println(text); + } +} +``` +Now, we can write our 'TextPost' class that extends from the base 'Post' class: +``` +public class TextPost extends Post { + public TextPost(String text) { + super(text); + } +} +``` +Now, we can write our 'ImagePost' class that extends from the base 'Post' class: +``` +public class ImagePost extends Post { + private String imageUrl; + + public ImagePost(String text, String imageUrl) { + super(text); + this.imageUrl = imageUrl; + } + + public String getImageUrl() { + return imageUrl; + } + + public void setImageUrl(String imageUrl) { + this.imageUrl = imageUrl; + } + + @Override + public void display() { + System.out.print("Image post: "); + System.out.println(imageUrl); + } +} +``` +Now, we can write our 'VideoPost' class that extends from the base 'Post' class: +``` +public class VideoPost extends Post { + private String videoUrl; + + public VideoPost(String text, String videoUrl) { + super(text); + this.videoUrl = videoUrl; + } + + public String getVideoUrl() { + return videoUrl; + } + + public void setVideoUrl(String videoUrl) { + this.videoUrl = videoUrl; + } + + @Override + public void display() { + System.out.print("Video post: "); + System.out.println(videoUrl); + } +} +``` +After making the following changes, the code now adheres to the Open-Closed Principle of SOLID. +
+
+We have a Main class to test the new code. It should produce the following output: +``` +Text Post Test: +This is a text post. + +Image Post Test: +Image post: https://example.com/image.jpg + +Video Post Test: +Video post: https://example.com/video.mp4 + +Updated Text Post: +Updated text post. + +Updated Image Post: +Image post: https://example.com/image2.jpg + +Updated Video Post: +Video post: https://example.com/video2.mp4 +``` \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/facebook/TextPost.java b/homework/src/HW1/submissions/partA/erictran/facebook/TextPost.java new file mode 100644 index 0000000..be4ea76 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/facebook/TextPost.java @@ -0,0 +1,7 @@ +package HW1.submissions.partA.erictran.facebook; + +public class TextPost extends Post { + public TextPost(String text) { + super(text); + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/facebook/VideoPost.java b/homework/src/HW1/submissions/partA/erictran/facebook/VideoPost.java new file mode 100644 index 0000000..35f75a2 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/facebook/VideoPost.java @@ -0,0 +1,24 @@ +package HW1.submissions.partA.erictran.facebook; + +public class VideoPost extends Post { + private String videoUrl; + + public VideoPost(String text, String videoUrl) { + super(text); + this.videoUrl = videoUrl; + } + + public String getVideoUrl() { + return videoUrl; + } + + public void setVideoUrl(String videoUrl) { + this.videoUrl = videoUrl; + } + + @Override + public void display() { + System.out.print("Video post: "); + System.out.println(videoUrl); + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/paypal/Account.java b/homework/src/HW1/submissions/partA/erictran/paypal/Account.java new file mode 100644 index 0000000..16d98f0 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/paypal/Account.java @@ -0,0 +1,13 @@ +package HW1.submissions.partA.erictran.paypal; + +public class Account { + private String accountID; + + public Account(String accountID) { + this.accountID = accountID; + } + + public String getAccountID() { + return accountID; + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/paypal/Main.java b/homework/src/HW1/submissions/partA/erictran/paypal/Main.java new file mode 100644 index 0000000..d635fb8 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/paypal/Main.java @@ -0,0 +1,11 @@ +package HW1.submissions.partA.erictran.paypal; + +public class Main { + public static void main(String[] args) { + PaymentGateway paymentGateway = new PayPalGateway(); + PaymentProcessor paymentProcessor = new PaymentProcessor(paymentGateway); + Account account = new Account("1"); + paymentProcessor.processPayment(account,100.0); + paymentProcessor.processRefund(account, 100.0); + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/paypal/PayPalGateway.java b/homework/src/HW1/submissions/partA/erictran/paypal/PayPalGateway.java new file mode 100644 index 0000000..acf3792 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/paypal/PayPalGateway.java @@ -0,0 +1,13 @@ +package HW1.submissions.partA.erictran.paypal; + +public class PayPalGateway implements PaymentGateway { + @Override + public void processPayment(Account account, double amount) { + System.out.println("Processing payment of $" + amount + " for account " + account.getAccountID() + " using PayPal."); + } + + @Override + public void processRefund(Account account, double amount) { + System.out.println("Processing refund of $" + amount + " for account " + account.getAccountID() + " using PayPal."); + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/paypal/PaymentGateway.java b/homework/src/HW1/submissions/partA/erictran/paypal/PaymentGateway.java new file mode 100644 index 0000000..5fb4028 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/paypal/PaymentGateway.java @@ -0,0 +1,7 @@ +package HW1.submissions.partA.erictran.paypal; + +public interface PaymentGateway { + public void processPayment(Account account, double amount); + + public void processRefund(Account account, double amount); +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/paypal/PaymentProcessor.java b/homework/src/HW1/submissions/partA/erictran/paypal/PaymentProcessor.java new file mode 100644 index 0000000..2a1fc3b --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/paypal/PaymentProcessor.java @@ -0,0 +1,17 @@ +package HW1.submissions.partA.erictran.paypal; + +public class PaymentProcessor { + private PaymentGateway paymentGateway; + + public PaymentProcessor(PaymentGateway paymentGateway) { + this.paymentGateway = paymentGateway; + } + + public void processPayment(Account account, double amount) { + paymentGateway.processPayment(account,amount); + } + + public void processRefund(Account account, double amount) { + paymentGateway.processRefund(account, amount); + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/paypal/README.md b/homework/src/HW1/submissions/partA/erictran/paypal/README.md new file mode 100644 index 0000000..9ec327a --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/paypal/README.md @@ -0,0 +1,60 @@ +# 'PayPal' Violation of SOLID + +This code violates the "D" in SOLID, which stands for Dependency Inversion Principle. +
+
+It officially states that "High-level modules should not depend on low-level modules. Both should depend on abstractions." +In this case, the 'PaymentProcessor' class depends directly on the 'PayPalGateway' class. +Hence, it makes it difficult to test the 'PaymentProcessor' class just by itself and update the 'PaypalGateway' class in the future. +
+
+A better design approach for this is to introduce abstraction for the 'PaypalGateway' class. +
+
+Lets start off by creating an interface called 'PaymentGateway' and define a single method called 'processPayment()': +``` +public interface PaymentGateway { + public void processPayment(Account account, double amount); +} +``` +Now, lets update the 'PaymentProcessor' class to depend on the 'PaymentGateway' interface: +``` +public class PaymentProcessor { + private PaymentGateway paymentGateway + + public PaymentProcessor(PaymentGateway paymentGateway) { + this.paymentGateway = paymentGateway; + } + + public void processPayment(Account account, double amount) { + paymentGateway.processPayment(account, amount); + } +} +``` +Now, lets update the 'PayPalGateway' class so that it implements the 'PaymentGateway' interface: +``` +public class PayPalGateway implements PaymentGateway { + @Override + public void processPayment(Account account, double amount) { + System.out.println("Processing payment of $" + amount + " for account " + account.getAccountID() + " using PayPal."); + } +} +``` +Now, lets update the 'Main' class to pass a new instance of the 'PayPalGateway' class to the 'PaymentProcessor' constructor: +``` +public class Main { + public static void main(String[] args) { + PaymentGateway paymentGateway = new PayPalGateway(); + PaymentProcessor paymentProcessor = new PaymentProcessor(paymentGateway); + Account account = new Account("1"); + paymentProcessor.processPayment(account, 100.0); + } +} +``` +After making the following changes, the code now adheres to the Dependency Inversion Principle of SOLID. +
+
+We have a Main class to test the new code. It should produce the following output: +``` +Processing payment of $100.0 for account 1 using PayPal. +``` \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/uber/Main.java b/homework/src/HW1/submissions/partA/erictran/uber/Main.java new file mode 100644 index 0000000..e049cdc --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/uber/Main.java @@ -0,0 +1,17 @@ +package HW1.submissions.partA.erictran.uber; + +public class Main { + public static void main(String[] args) { + Ride ride = new Ride(1,1); + User user = new User(); + user.setUsername("john_doe"); + + RideCalculator rideCalculator = new RideCalculator(); + NotificationManager notificationManager = new NotificationManager(); + PaymentManager paymentManager = new PaymentManager(); + + double fare = rideCalculator.calculateRideFare(ride); + notificationManager.sendNotification(user, "Your ride fare is: $" + fare); + paymentManager.processPayment(user, fare); + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/uber/README.md b/homework/src/HW1/submissions/partA/erictran/uber/README.md new file mode 100644 index 0000000..edf9535 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/uber/README.md @@ -0,0 +1,54 @@ +# 'Uber' Violation of Solid + +This code violates the "S" in SOLID, which stands for Single Responsibility Principle. +
+
+It officially states that "A module should be responsible to one, and only one, actor." +In this case, the 'RideManager' class has two responsibilities: +1. To calculate the fare for a ride +2. To send notifications to users + +These two responsibilities are completely unrelated. +
+
+A better design approach for this is to split the 'RideManager' class into two separate classes. +
+
+Lets start off by renaming the 'RideManager' class to 'RideCalculator' that will handle calculating the ride's cost ONLY, removing the 'sendNotification' logic: +``` +class RideCalculator { + private final double BASE_FARE = 5.0; // Base fare in dollars + private final double PER_MILE_RATE = 2.0; // Fare per mile in dollars + private final double PER_MINUTE_RATE = 0.5; // Fare per minute in dollars + + double calculateRideFare(Ride ride) { + double distanceInMiles = ride.getDistanceInMiles(); + int durationInMinutes = ride.getDurationInMinutes(); + + // Calculate fare based on distance and time + double distanceFare = distanceInMiles * PER_MILE_RATE; + double timeFare = durationInMinutes * PER_MINUTE_RATE; + + // Calculate total fare including base fare + double totalFare = BASE_FARE + distanceFare + timeFare; + + return totalFare; + } +} +``` +Now, lets make a new class called 'NotificationManager' that will handle sending out notifications to the user ONLY, putting the 'sendNotification' logic here: +``` +class NotificationManager { + void sendNotification(User user, String message) { + // Code for sending notifications to the user + System.out.println("Notification sent to user: " + user.getUsername() + " - " + message); + } +} +``` +After making the following changes, the code now adheres to the Single Responsibility Principle of SOLID. +
+
+We have a Main class to test the new code. It should produce the following output: +``` +Notification sent to user: john_doe - Your ride fare is: $7.5 +``` \ No newline at end of file diff --git a/homework/src/HW1/submissions/partA/erictran/uber/RideManager.java b/homework/src/HW1/submissions/partA/erictran/uber/RideManager.java new file mode 100644 index 0000000..1c9f2b2 --- /dev/null +++ b/homework/src/HW1/submissions/partA/erictran/uber/RideManager.java @@ -0,0 +1,73 @@ +package HW1.submissions.partA.erictran.uber; + +class RideCalculator { + private final double BASE_FARE = 5.0; // Base fare in dollars + private final double PER_MILE_RATE = 2.0; // Fare per mile in dollars + private final double PER_MINUTE_RATE = 0.5; // Fare per minute in dollars + + double calculateRideFare(Ride ride) { + double distanceInMiles = ride.getDistanceInMiles(); + int durationInMinutes = ride.getDurationInMinutes(); + + // Calculate fare based on distance and time + double distanceFare = distanceInMiles * PER_MILE_RATE; + double timeFare = durationInMinutes * PER_MINUTE_RATE; + + // Calculate total fare including base fare + double totalFare = BASE_FARE + distanceFare + timeFare; + + return totalFare; + } +} + +class NotificationManager { + void sendNotification(User user, String message) { + // Code for sending notifications to the user + System.out.println("Notification sent to user: " + user.getUsername() + " - " + message); + } +} + +class PaymentManager { + void processPayment(User user, double amount) { + System.out.println("Payment processed for user: " + user.getUsername() + " - Amount: $" + amount); + } +} + +class Ride { + private double distanceInMiles; + private int durationInMinutes; + + public Ride(double distanceInMiles, int durationInMinutes) { + this.distanceInMiles = distanceInMiles; + this.durationInMinutes = durationInMinutes; + } + + public double getDistanceInMiles() { + return distanceInMiles; + } + + public void setDistanceInMiles(double distanceInMiles) { + this.distanceInMiles = distanceInMiles; + } + + public int getDurationInMinutes() { + return durationInMinutes; + } + + public void setDurationInMinutes(int durationInMinutes) { + this.durationInMinutes = durationInMinutes; + } +} + +class User { + // User details + private String username; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } +} \ No newline at end of file diff --git a/homework/src/HW1/submissions/partB/README.md b/homework/src/HW1/submissions/partB/README.md deleted file mode 100644 index e4aa9c2..0000000 --- a/homework/src/HW1/submissions/partB/README.md +++ /dev/null @@ -1 +0,0 @@ -Add your submissions for part B of the homework here. \ No newline at end of file diff --git a/homework/src/HW1/submissions/partB/erictran/README.md b/homework/src/HW1/submissions/partB/erictran/README.md new file mode 100644 index 0000000..89e9f08 --- /dev/null +++ b/homework/src/HW1/submissions/partB/erictran/README.md @@ -0,0 +1 @@ +https://github.com/Trannics/HW1CS151JavaFX