Initiating an action based on product type
up vote
1
down vote
favorite
I am starting my studies with Ruby and OO and I have received a test to do about OO. I am looking for new ways to improve the scenario following object-oriented concepts. Is there a better way to develop this design applying polymorphism?
Here is my problem:
If the product is physical, I have to generate a shipping label.
If it's a book, I have to mention that this product doesn't have taxes.
If the product is a membership, I have to activate the signature and notify the buyer via email.
If the product is digital, I have to send an email for the buyer and give a $10 discount for this product.
class Product
attr_reader :name, :description, :type, :amount
include Shipping
include Discount
def initialize(name, description, type, amount)
@name = name
@description = description
@type = type
@amount = amount
end
end
class Physical < Product
def initialize(name, description, type, amount)
super(name, description, type, amount)
end
def shipping
case @type
when :book
create_shipping_label
notify_buyer_product_without_taxes
else
create_shipping_label
end
end
def discount
discount_for_physical_product = 0.0
return discount_for_physical_product
end
end
class Membership < Product
attr_reader :membership_status
def initialize(name, description, type, amount)
super(name, description, type, amount)
end
def activate_membership()
@membership_status = true;
end
def shipping
notify_buyer_via_email
activate_membership
end
def discount
discount_for_membership_product = 0
return discount_for_membership_product
end
end
class Digital < Product
def initialize(name, description, type, amount)
super(name, description, type, amount)
end
def shipping
notify_buyer_via_email
end
def discount
discount_for_digital_product = 10.00
return discount_for_digital_product
end
end
module Discount
def prepare_discount(order)
total_discount = 0
order.get_items.each do |item|
total_discount += item.product.discount
end
return total_discount
end
def discount
discount_default = 0.0
return discount_default
end
end
object-oriented ruby
bumped to the homepage by Community♦ 21 hours ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
add a comment |
up vote
1
down vote
favorite
I am starting my studies with Ruby and OO and I have received a test to do about OO. I am looking for new ways to improve the scenario following object-oriented concepts. Is there a better way to develop this design applying polymorphism?
Here is my problem:
If the product is physical, I have to generate a shipping label.
If it's a book, I have to mention that this product doesn't have taxes.
If the product is a membership, I have to activate the signature and notify the buyer via email.
If the product is digital, I have to send an email for the buyer and give a $10 discount for this product.
class Product
attr_reader :name, :description, :type, :amount
include Shipping
include Discount
def initialize(name, description, type, amount)
@name = name
@description = description
@type = type
@amount = amount
end
end
class Physical < Product
def initialize(name, description, type, amount)
super(name, description, type, amount)
end
def shipping
case @type
when :book
create_shipping_label
notify_buyer_product_without_taxes
else
create_shipping_label
end
end
def discount
discount_for_physical_product = 0.0
return discount_for_physical_product
end
end
class Membership < Product
attr_reader :membership_status
def initialize(name, description, type, amount)
super(name, description, type, amount)
end
def activate_membership()
@membership_status = true;
end
def shipping
notify_buyer_via_email
activate_membership
end
def discount
discount_for_membership_product = 0
return discount_for_membership_product
end
end
class Digital < Product
def initialize(name, description, type, amount)
super(name, description, type, amount)
end
def shipping
notify_buyer_via_email
end
def discount
discount_for_digital_product = 10.00
return discount_for_digital_product
end
end
module Discount
def prepare_discount(order)
total_discount = 0
order.get_items.each do |item|
total_discount += item.product.discount
end
return total_discount
end
def discount
discount_default = 0.0
return discount_default
end
end
object-oriented ruby
bumped to the homepage by Community♦ 21 hours ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I am starting my studies with Ruby and OO and I have received a test to do about OO. I am looking for new ways to improve the scenario following object-oriented concepts. Is there a better way to develop this design applying polymorphism?
Here is my problem:
If the product is physical, I have to generate a shipping label.
If it's a book, I have to mention that this product doesn't have taxes.
If the product is a membership, I have to activate the signature and notify the buyer via email.
If the product is digital, I have to send an email for the buyer and give a $10 discount for this product.
class Product
attr_reader :name, :description, :type, :amount
include Shipping
include Discount
def initialize(name, description, type, amount)
@name = name
@description = description
@type = type
@amount = amount
end
end
class Physical < Product
def initialize(name, description, type, amount)
super(name, description, type, amount)
end
def shipping
case @type
when :book
create_shipping_label
notify_buyer_product_without_taxes
else
create_shipping_label
end
end
def discount
discount_for_physical_product = 0.0
return discount_for_physical_product
end
end
class Membership < Product
attr_reader :membership_status
def initialize(name, description, type, amount)
super(name, description, type, amount)
end
def activate_membership()
@membership_status = true;
end
def shipping
notify_buyer_via_email
activate_membership
end
def discount
discount_for_membership_product = 0
return discount_for_membership_product
end
end
class Digital < Product
def initialize(name, description, type, amount)
super(name, description, type, amount)
end
def shipping
notify_buyer_via_email
end
def discount
discount_for_digital_product = 10.00
return discount_for_digital_product
end
end
module Discount
def prepare_discount(order)
total_discount = 0
order.get_items.each do |item|
total_discount += item.product.discount
end
return total_discount
end
def discount
discount_default = 0.0
return discount_default
end
end
object-oriented ruby
I am starting my studies with Ruby and OO and I have received a test to do about OO. I am looking for new ways to improve the scenario following object-oriented concepts. Is there a better way to develop this design applying polymorphism?
Here is my problem:
If the product is physical, I have to generate a shipping label.
If it's a book, I have to mention that this product doesn't have taxes.
If the product is a membership, I have to activate the signature and notify the buyer via email.
If the product is digital, I have to send an email for the buyer and give a $10 discount for this product.
class Product
attr_reader :name, :description, :type, :amount
include Shipping
include Discount
def initialize(name, description, type, amount)
@name = name
@description = description
@type = type
@amount = amount
end
end
class Physical < Product
def initialize(name, description, type, amount)
super(name, description, type, amount)
end
def shipping
case @type
when :book
create_shipping_label
notify_buyer_product_without_taxes
else
create_shipping_label
end
end
def discount
discount_for_physical_product = 0.0
return discount_for_physical_product
end
end
class Membership < Product
attr_reader :membership_status
def initialize(name, description, type, amount)
super(name, description, type, amount)
end
def activate_membership()
@membership_status = true;
end
def shipping
notify_buyer_via_email
activate_membership
end
def discount
discount_for_membership_product = 0
return discount_for_membership_product
end
end
class Digital < Product
def initialize(name, description, type, amount)
super(name, description, type, amount)
end
def shipping
notify_buyer_via_email
end
def discount
discount_for_digital_product = 10.00
return discount_for_digital_product
end
end
module Discount
def prepare_discount(order)
total_discount = 0
order.get_items.each do |item|
total_discount += item.product.discount
end
return total_discount
end
def discount
discount_default = 0.0
return discount_default
end
end
object-oriented ruby
object-oriented ruby
edited Feb 8 '17 at 6:16
Jamal♦
30.2k11115226
30.2k11115226
asked Feb 8 '17 at 4:10
junis087678
112
112
bumped to the homepage by Community♦ 21 hours ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
bumped to the homepage by Community♦ 21 hours ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
up vote
0
down vote
You have a conditional based on the type of object. You can apply the Replace Conditional with Polymorphism refactoring pattern.
In this case, you might have a base class Product
, with subclasses DigitalProduct
and PhysicalProduct
which each implement discount()
. I don't think it's sensible to have a MembershipProduct
class - membership should be related to the buyer. From an OO perspective, it should feel wrong when you have methods like discount_for_X()
- the method should be part of the respective class so that you can make use of polymorphism.
thank you ! One question, if business rules for shipping and discount are in product class is not wrong ? I mean would it be better if I use the polymorphism in this case and call methods from shipping and discount module to deal with it ? This way I would use polymorphism and follow the first's SOLID rule )Single responsibility principle). Thank you!
– junis087678
Feb 8 '17 at 5:33
It's a bit difficult to understand what you're asking. To follow site rules, you should post a completed sample in order to get appropriate feedback. See on-topic.
– jsuth
Feb 8 '17 at 5:39
add a comment |
up vote
0
down vote
Disclaimer: I'm not a Ruby expert
Type parameter
The main thing that bothers me with you code is the type
parameter given when constructing a Product
's instance. This goes against OO principles and leads to bad code for the following reason: you have to manage conditional explicitely in code with control structures (if, switch) instead of delegating this responsibility to the compiler/interpreter by using polymorphism.
Removing this would need to introduce a both Book
class and a GenericProduct
class which is basically representing all physical products but books.
Common discount method
Another thing is that the discount
method is common to all products and differs only in the data (and not in the behavior). This can be implemented in Product
and request the discount value in the constructor.
Create local variable and directly return it
This is useless and only introduce visual noise. You can directly return the value.
Similitude between Membership
and Digital Product
It looks like Membership
is also a special kind of digital product and that a relationship between them can exist (they both require to send an email when shipping). However I'm not entirely sure about that so feel free to ignore the end of the resulting code listing.
Reviewed code
class Product
attr_reader :name, :description, :amount, :discount
include Shipping
include Discount
def initialize(name, description, amount, discount)
@name = name
@description = description
@amount = amount
@discount = discount
end
def discount
return @discount
end
end
class PhysicalProduct < Product
def initialize(name, description, amount)
super(name, description, amount, 0.0)
end
def shipping
create_shipping_label
notify_buyer_product_without_taxes if free_of_taxes
end
end
class GenericProduct < PhysicalProduct
def initialize(name, description, amount)
super(name, description, amount)
end
def free_of_taxes
return false
end
end
class Book < PhysicalProduct
def initialize(name, description, amount)
super(name, description, amount)
end
def free_of_taxes
return true
end
end
class DigitalProduct < Product
def initialize(name, description, amount, discount = 10.00)
super(name, description, amount, discount)
end
def shipping
notify_buyer_via_email
end
end
class Membership < DigitalProduct
attr_reader :membership_status
def initialize(name, description, amount)
super(name, description, amount, 0.0)
end
def activate_membership()
@membership_status = true;
end
def shipping
super
activate_membership
end
end
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
You have a conditional based on the type of object. You can apply the Replace Conditional with Polymorphism refactoring pattern.
In this case, you might have a base class Product
, with subclasses DigitalProduct
and PhysicalProduct
which each implement discount()
. I don't think it's sensible to have a MembershipProduct
class - membership should be related to the buyer. From an OO perspective, it should feel wrong when you have methods like discount_for_X()
- the method should be part of the respective class so that you can make use of polymorphism.
thank you ! One question, if business rules for shipping and discount are in product class is not wrong ? I mean would it be better if I use the polymorphism in this case and call methods from shipping and discount module to deal with it ? This way I would use polymorphism and follow the first's SOLID rule )Single responsibility principle). Thank you!
– junis087678
Feb 8 '17 at 5:33
It's a bit difficult to understand what you're asking. To follow site rules, you should post a completed sample in order to get appropriate feedback. See on-topic.
– jsuth
Feb 8 '17 at 5:39
add a comment |
up vote
0
down vote
You have a conditional based on the type of object. You can apply the Replace Conditional with Polymorphism refactoring pattern.
In this case, you might have a base class Product
, with subclasses DigitalProduct
and PhysicalProduct
which each implement discount()
. I don't think it's sensible to have a MembershipProduct
class - membership should be related to the buyer. From an OO perspective, it should feel wrong when you have methods like discount_for_X()
- the method should be part of the respective class so that you can make use of polymorphism.
thank you ! One question, if business rules for shipping and discount are in product class is not wrong ? I mean would it be better if I use the polymorphism in this case and call methods from shipping and discount module to deal with it ? This way I would use polymorphism and follow the first's SOLID rule )Single responsibility principle). Thank you!
– junis087678
Feb 8 '17 at 5:33
It's a bit difficult to understand what you're asking. To follow site rules, you should post a completed sample in order to get appropriate feedback. See on-topic.
– jsuth
Feb 8 '17 at 5:39
add a comment |
up vote
0
down vote
up vote
0
down vote
You have a conditional based on the type of object. You can apply the Replace Conditional with Polymorphism refactoring pattern.
In this case, you might have a base class Product
, with subclasses DigitalProduct
and PhysicalProduct
which each implement discount()
. I don't think it's sensible to have a MembershipProduct
class - membership should be related to the buyer. From an OO perspective, it should feel wrong when you have methods like discount_for_X()
- the method should be part of the respective class so that you can make use of polymorphism.
You have a conditional based on the type of object. You can apply the Replace Conditional with Polymorphism refactoring pattern.
In this case, you might have a base class Product
, with subclasses DigitalProduct
and PhysicalProduct
which each implement discount()
. I don't think it's sensible to have a MembershipProduct
class - membership should be related to the buyer. From an OO perspective, it should feel wrong when you have methods like discount_for_X()
- the method should be part of the respective class so that you can make use of polymorphism.
edited Feb 8 '17 at 5:28
answered Feb 8 '17 at 5:15
jsuth
597214
597214
thank you ! One question, if business rules for shipping and discount are in product class is not wrong ? I mean would it be better if I use the polymorphism in this case and call methods from shipping and discount module to deal with it ? This way I would use polymorphism and follow the first's SOLID rule )Single responsibility principle). Thank you!
– junis087678
Feb 8 '17 at 5:33
It's a bit difficult to understand what you're asking. To follow site rules, you should post a completed sample in order to get appropriate feedback. See on-topic.
– jsuth
Feb 8 '17 at 5:39
add a comment |
thank you ! One question, if business rules for shipping and discount are in product class is not wrong ? I mean would it be better if I use the polymorphism in this case and call methods from shipping and discount module to deal with it ? This way I would use polymorphism and follow the first's SOLID rule )Single responsibility principle). Thank you!
– junis087678
Feb 8 '17 at 5:33
It's a bit difficult to understand what you're asking. To follow site rules, you should post a completed sample in order to get appropriate feedback. See on-topic.
– jsuth
Feb 8 '17 at 5:39
thank you ! One question, if business rules for shipping and discount are in product class is not wrong ? I mean would it be better if I use the polymorphism in this case and call methods from shipping and discount module to deal with it ? This way I would use polymorphism and follow the first's SOLID rule )Single responsibility principle). Thank you!
– junis087678
Feb 8 '17 at 5:33
thank you ! One question, if business rules for shipping and discount are in product class is not wrong ? I mean would it be better if I use the polymorphism in this case and call methods from shipping and discount module to deal with it ? This way I would use polymorphism and follow the first's SOLID rule )Single responsibility principle). Thank you!
– junis087678
Feb 8 '17 at 5:33
It's a bit difficult to understand what you're asking. To follow site rules, you should post a completed sample in order to get appropriate feedback. See on-topic.
– jsuth
Feb 8 '17 at 5:39
It's a bit difficult to understand what you're asking. To follow site rules, you should post a completed sample in order to get appropriate feedback. See on-topic.
– jsuth
Feb 8 '17 at 5:39
add a comment |
up vote
0
down vote
Disclaimer: I'm not a Ruby expert
Type parameter
The main thing that bothers me with you code is the type
parameter given when constructing a Product
's instance. This goes against OO principles and leads to bad code for the following reason: you have to manage conditional explicitely in code with control structures (if, switch) instead of delegating this responsibility to the compiler/interpreter by using polymorphism.
Removing this would need to introduce a both Book
class and a GenericProduct
class which is basically representing all physical products but books.
Common discount method
Another thing is that the discount
method is common to all products and differs only in the data (and not in the behavior). This can be implemented in Product
and request the discount value in the constructor.
Create local variable and directly return it
This is useless and only introduce visual noise. You can directly return the value.
Similitude between Membership
and Digital Product
It looks like Membership
is also a special kind of digital product and that a relationship between them can exist (they both require to send an email when shipping). However I'm not entirely sure about that so feel free to ignore the end of the resulting code listing.
Reviewed code
class Product
attr_reader :name, :description, :amount, :discount
include Shipping
include Discount
def initialize(name, description, amount, discount)
@name = name
@description = description
@amount = amount
@discount = discount
end
def discount
return @discount
end
end
class PhysicalProduct < Product
def initialize(name, description, amount)
super(name, description, amount, 0.0)
end
def shipping
create_shipping_label
notify_buyer_product_without_taxes if free_of_taxes
end
end
class GenericProduct < PhysicalProduct
def initialize(name, description, amount)
super(name, description, amount)
end
def free_of_taxes
return false
end
end
class Book < PhysicalProduct
def initialize(name, description, amount)
super(name, description, amount)
end
def free_of_taxes
return true
end
end
class DigitalProduct < Product
def initialize(name, description, amount, discount = 10.00)
super(name, description, amount, discount)
end
def shipping
notify_buyer_via_email
end
end
class Membership < DigitalProduct
attr_reader :membership_status
def initialize(name, description, amount)
super(name, description, amount, 0.0)
end
def activate_membership()
@membership_status = true;
end
def shipping
super
activate_membership
end
end
add a comment |
up vote
0
down vote
Disclaimer: I'm not a Ruby expert
Type parameter
The main thing that bothers me with you code is the type
parameter given when constructing a Product
's instance. This goes against OO principles and leads to bad code for the following reason: you have to manage conditional explicitely in code with control structures (if, switch) instead of delegating this responsibility to the compiler/interpreter by using polymorphism.
Removing this would need to introduce a both Book
class and a GenericProduct
class which is basically representing all physical products but books.
Common discount method
Another thing is that the discount
method is common to all products and differs only in the data (and not in the behavior). This can be implemented in Product
and request the discount value in the constructor.
Create local variable and directly return it
This is useless and only introduce visual noise. You can directly return the value.
Similitude between Membership
and Digital Product
It looks like Membership
is also a special kind of digital product and that a relationship between them can exist (they both require to send an email when shipping). However I'm not entirely sure about that so feel free to ignore the end of the resulting code listing.
Reviewed code
class Product
attr_reader :name, :description, :amount, :discount
include Shipping
include Discount
def initialize(name, description, amount, discount)
@name = name
@description = description
@amount = amount
@discount = discount
end
def discount
return @discount
end
end
class PhysicalProduct < Product
def initialize(name, description, amount)
super(name, description, amount, 0.0)
end
def shipping
create_shipping_label
notify_buyer_product_without_taxes if free_of_taxes
end
end
class GenericProduct < PhysicalProduct
def initialize(name, description, amount)
super(name, description, amount)
end
def free_of_taxes
return false
end
end
class Book < PhysicalProduct
def initialize(name, description, amount)
super(name, description, amount)
end
def free_of_taxes
return true
end
end
class DigitalProduct < Product
def initialize(name, description, amount, discount = 10.00)
super(name, description, amount, discount)
end
def shipping
notify_buyer_via_email
end
end
class Membership < DigitalProduct
attr_reader :membership_status
def initialize(name, description, amount)
super(name, description, amount, 0.0)
end
def activate_membership()
@membership_status = true;
end
def shipping
super
activate_membership
end
end
add a comment |
up vote
0
down vote
up vote
0
down vote
Disclaimer: I'm not a Ruby expert
Type parameter
The main thing that bothers me with you code is the type
parameter given when constructing a Product
's instance. This goes against OO principles and leads to bad code for the following reason: you have to manage conditional explicitely in code with control structures (if, switch) instead of delegating this responsibility to the compiler/interpreter by using polymorphism.
Removing this would need to introduce a both Book
class and a GenericProduct
class which is basically representing all physical products but books.
Common discount method
Another thing is that the discount
method is common to all products and differs only in the data (and not in the behavior). This can be implemented in Product
and request the discount value in the constructor.
Create local variable and directly return it
This is useless and only introduce visual noise. You can directly return the value.
Similitude between Membership
and Digital Product
It looks like Membership
is also a special kind of digital product and that a relationship between them can exist (they both require to send an email when shipping). However I'm not entirely sure about that so feel free to ignore the end of the resulting code listing.
Reviewed code
class Product
attr_reader :name, :description, :amount, :discount
include Shipping
include Discount
def initialize(name, description, amount, discount)
@name = name
@description = description
@amount = amount
@discount = discount
end
def discount
return @discount
end
end
class PhysicalProduct < Product
def initialize(name, description, amount)
super(name, description, amount, 0.0)
end
def shipping
create_shipping_label
notify_buyer_product_without_taxes if free_of_taxes
end
end
class GenericProduct < PhysicalProduct
def initialize(name, description, amount)
super(name, description, amount)
end
def free_of_taxes
return false
end
end
class Book < PhysicalProduct
def initialize(name, description, amount)
super(name, description, amount)
end
def free_of_taxes
return true
end
end
class DigitalProduct < Product
def initialize(name, description, amount, discount = 10.00)
super(name, description, amount, discount)
end
def shipping
notify_buyer_via_email
end
end
class Membership < DigitalProduct
attr_reader :membership_status
def initialize(name, description, amount)
super(name, description, amount, 0.0)
end
def activate_membership()
@membership_status = true;
end
def shipping
super
activate_membership
end
end
Disclaimer: I'm not a Ruby expert
Type parameter
The main thing that bothers me with you code is the type
parameter given when constructing a Product
's instance. This goes against OO principles and leads to bad code for the following reason: you have to manage conditional explicitely in code with control structures (if, switch) instead of delegating this responsibility to the compiler/interpreter by using polymorphism.
Removing this would need to introduce a both Book
class and a GenericProduct
class which is basically representing all physical products but books.
Common discount method
Another thing is that the discount
method is common to all products and differs only in the data (and not in the behavior). This can be implemented in Product
and request the discount value in the constructor.
Create local variable and directly return it
This is useless and only introduce visual noise. You can directly return the value.
Similitude between Membership
and Digital Product
It looks like Membership
is also a special kind of digital product and that a relationship between them can exist (they both require to send an email when shipping). However I'm not entirely sure about that so feel free to ignore the end of the resulting code listing.
Reviewed code
class Product
attr_reader :name, :description, :amount, :discount
include Shipping
include Discount
def initialize(name, description, amount, discount)
@name = name
@description = description
@amount = amount
@discount = discount
end
def discount
return @discount
end
end
class PhysicalProduct < Product
def initialize(name, description, amount)
super(name, description, amount, 0.0)
end
def shipping
create_shipping_label
notify_buyer_product_without_taxes if free_of_taxes
end
end
class GenericProduct < PhysicalProduct
def initialize(name, description, amount)
super(name, description, amount)
end
def free_of_taxes
return false
end
end
class Book < PhysicalProduct
def initialize(name, description, amount)
super(name, description, amount)
end
def free_of_taxes
return true
end
end
class DigitalProduct < Product
def initialize(name, description, amount, discount = 10.00)
super(name, description, amount, discount)
end
def shipping
notify_buyer_via_email
end
end
class Membership < DigitalProduct
attr_reader :membership_status
def initialize(name, description, amount)
super(name, description, amount, 0.0)
end
def activate_membership()
@membership_status = true;
end
def shipping
super
activate_membership
end
end
answered Jul 24 at 8:33
Spotted
54928
54928
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f154772%2finitiating-an-action-based-on-product-type%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown