TL;DR:
How to avoid duplicates for certain classes in a Decorator chain?
Long version
I'm trying to implement the Decorator pattern as described in the book Head First Design Patterns. The example they give is a cash register for a Starbucks-like coffee store, where the beverages and the various condiments are classes, and the purpose of the system is to calculate the price.
I started with an iBeverage interface, exposing the public method getName() and getPrice().
Implementations of iBeverage are the various beverage classes (though a shared baseclass called Beverage; these are SlowDripCoffee, Latte and Cappuccino), and various condiments.
The condiments are implemented as iBeverageDecorators (an interface extending iBeverage). In their constructor they accept an instance of iBeverage, which is stored internally. Calls to getName() and getPrice() are implemented as "call getPrice() on child, add your own price, return the value."
Example of how one would create a Tall Soy Caramel Latte:
$drink = new SoyMilk(new CaramelSyrup(new Latte(Beverage::TALL)));
$price = $drink->getPrice();`
My issue: How can I restrict - for some decorators only - the total amount of times they end up in the call stack? For example: what if the store wants to restrict syrups to three per beverage, or they want to make sure employees only add one type of milk to an order?
My basic instinct was to add some reflection, so that during construction we can examine the entire object graph and determine whether or not it is a valid target for the decorator... is this the right way to go? Or is the pattern I'm applying here not suitable for this task? Any advice is much appreciated.
This is just something I set out for myself to do and find out.
Normally this should be an issue, you build your chain either manually (you hard coded it) or you have a builder that adds the decorators to the chain where you can control this.
I wouldn't put any code for this in the decorator classes itself because then you are spreading the rules about this all over the place and making this inflexible and hard to maintain.
The example you used is all about being able to cope with changed rules and ingredients.
Related
I am writing a data export application that is used for many scenarios (Vendors, Customers, Cost Centers, REFX Contracts, etc).
In the end there are two main ways of exporting: save to file or call webservice.
So my idea was create an interface if_export, implement a class for each scenario.
The problem is, the call webservice code differs slightly at the point of the actual call: the called method has a different name each time.
My ideas for dealing with this so far are:
Abstract cl_webservice_export with subclasses for each scenario. Overwrite method containing the actual call.
cl_webservice_export with member type if_webservice_call. class for each scenario implementing if_webservice_call method call_webservice()
Dynamic CALL METHOD webservice_instance->(method_name) inside
concrete cl_webservice_export method containing the actual call and passing (method_name) to cl_webservice_export.
My code:
export_via_webservice is the public interface provided by cl_webservice_export or via if_export
METHODS export_via_webservice
IMPORTING
VALUE(it_xml_strings) TYPE tt_xml_string_table
io_service_consumer TYPE REF TO ztnco_service_vmsoap
RETURNING
VALUE(rt_export_results) TYPE tt_xml_string_table.
METHOD export_via_webservice.
LOOP AT it_xml_strings INTO DATA(lv_xml_string).
call_webservice(
EXPORTING
io_service = io_service_consumer
iv_xml_string = lv_xml_string-xmlstring
RECEIVING
rv_result = DATA(lv_result)
).
rt_export_results = VALUE #( BASE rt_export_results (
lifnr = lv_xml_string-xmlstring
xmlstring = lv_result ) ).
ENDLOOP.
ENDMETHOD.
Actual webservice call, overridden or provided by if_webservice_call
METHODS call_webservice
IMPORTING
io_service TYPE REF TO ztnco_service_vmsoap
iv_xml_string TYPE string
RETURNING
VALUE(rv_result) TYPE string.
METHOD call_webservice.
TRY.
io_service->import_creditor(
EXPORTING
input = VALUE #( xml_creditor_data = iv_xml_string )
IMPORTING
output = DATA(lv_output)
).
CATCH cx_ai_system_fault INTO DATA(lx_exception).
ENDTRY.
rv_result = lv_output-import_creditor_result.
ENDMETHOD.
How would you solve this problem, maybe there are other, better ways of doing it?
I know three common patterns to solve this question. They are, in ascending order of quality:
Individual implementations
Create one interface if_export, and one class that implements it for each web service export variant that you need, i.e. cl_webservice_export_variant_a, cl_webservice_export_variant_b, etc.
Major advantages are the intuitive simplistic class design and complete independence of the implementations that avoids accidental spillover from one variant to the other.
Major disadvantage are the probably massive portion of code duplication between the different variants, if their code varies in only few, minor positions.
You already sketched this as your option 2, and also already highlighted that it is the least optimal solution for your scenario. Code duplication is never welcome. The more so since your web service calls vary only slightly, in some method name.
In summary, this pattern is rather poor, and you shouldn't actively choose it. It usually comes into existence on its own, when people start with variant a, and months later add a variant b by copy-pasting the existing class, and then forgetting to refactor the code to get rid of the duplicate parts.
Strategy pattern
This design is commonly known as the strategy design pattern. Create one interface if_export, and one abstract class cl_abstract_webservice_export that implements the interface and includes most of the web service-calling code.
Except for this detail: The name of the method that should be called is not hard-coded but retrieved via a call to a protected sub-method get_service_name. The abstract class does not implement this method. Instead, you create sub-classes of the abstract class, i.e. cl_concrete_webservice_export_variant_a, cl_concrete_webservice_export_variant_b, etc. These classes implement only the inherited protected method get_service_name, providing their concrete needs.
Major advantages are that this pattern completely avoids code duplication, is open for further extensions, and has been employed successfully in lots of framework implementations.
Major disadvantage is that the pattern starts to erode when the first variant arrives that does not completely fit, e.g. because it does not only vary the method name, but also some parameters. Evolving then requires in-depth redesign of all involved classes, which can amount to considerable cost. Another disadvantage is that the inheritance setup can make it cumbersome to write unit tests: for example, unit-testing the abstract class requires to make up a test double that sub-classes it and overwrites the protected method with sensing and mocking code - all possible but not as neatly as with interfaces between the classes.
You already sketched this as your option 1. In summary, I would recommend to choose this pattern if you have control over all involved classes and are willing to spend some extra-effort to keep the pattern clean in case it doesn't fit completely.
Composition
Composition means avoiding inheritance in favor of loose interaction between indepdent classes over classes. Create the interface if_export and individual concrete implementations of it as cl_webservice_export_variant_a, cl_webservice_export_variant_b, etc.
Move out the shared code to a class cl_export_webservice_caller that receives whatever data and variant (e.g. method name) it needs. Let the variant classes call this shared code. To complete the class design, introduce another interface if_export_webservice_caller that decouples the variants classes from the caller class.
The major advantages are that all classes are independent from each other and can be recombined in several different ways. For example, if in the future you need to introduce a variant X that would call its web service in a completely different way, you can simply add it, without having to redesign any of the other involved classes. In contrast to the strategy pattern, writing unit tests for all involved classes is trivial.
There are no real disadvantages to this pattern. (The seeming disadvantage that it needs one more interface is not really one - object orientation has the aim to clearly separate concerns, not to minimize the overall number of classes/interfaces, and we shouldn't be afraid to add more of those if it adds clarity to the overall design.)
This option sounds similar to the option 3 you sketched, but I am not 100% sure. Anyway, this would be the pattern I would vote for.
I've created the custom class ZMaterial that can be instantiated passing an ID to the constructor which sets the properties for a single material using SELECTs and BAPIs. This class is basically used to READ and UPDATE a single material.
Now I need to create a service to return a list of materials. I already have the procedural code for it in a static method (for now actually a function module), but I would like to keep using a full OOP approach and instantiate a list of my custom material object. The first approach I found is to enhance the static method to instantiate a list of my single material object after the selects are executed and I have the data in internal tables, but it does not seem the most OOP.
The second option in my mind is to create a new class ZMaterialList with one property being a list of objects ZMaterial and then a constructor with the necessary input parameters for the database select. The problem I see with this option is that I create a full class just for the constructor.
What do you think is the best way to proceed?
Create a separate class to produce the list of materials. The single responsibility principle says each class should do exactly one thing. In all but the most simple cases, using a thing is a different responsibility than producing it.
Don’t make a ZMaterialList class. A list’s focus would be managing the list items, i.e. adding, removing, iterating, sorting etc. But you should be fine with a regular STANDARD TABLE OF REF TO ZMaterial.
Make a ZMaterialReader, -Repository, -Query or -Factory class or the like, depending on the precise way you want to produce the ZMaterials. Readers read by keys, repositories read and write, queries use varying sets of selection criteria, factories instantiate with possibly different sets of inputs.
You can well let that class use the original FUNCTION underneath. It’s good style to exploit what’s already there. Just make sure you trust that code, put it in a test harness, and keep it afar from the rest of your oo code.
Extract all public interaction of ZMaterial to an interface and use only that interface. That allows you to offer alternative implementations of ZMaterial, ones that differ in the way they are produced or how they store their data.
Split single production from mass production. Reading MARA to retrieve a single material is okay. But you don’t want thousands of ZMaterials reading MARA individually - that wrecks performance.
Now you’ve got the interface, you could offer a second implementation of ZMaterial whose constructor receives all relevant data and relies on it already having been validated to avoid additional SELECTs.
You could also offer an implementation that doesn’t store its data at all but only stores pointers to rows in internal tables somewhere else. See the flyweight pattern for ideas.
If you expect mass updates on the materials, such as “reclassify all of these as B”, consider extracting these list-oriented operations to separate classes as well.
I have the following design problem:
I have many lines of object oriented source code (C++) and our customers want specific changes to our code to fit their needs. Here a very simplified example:
void somefunction() {
// do something
}
The function after I inserted the customer wishes:
void somefunction() {
// do something
setFlag(5000);
}
This looks not so bad, but we have many customers which want to set their own flag values on many different locations in the code. The code is getting more and more messy. How can I separate these customer code from my source code? Is there any design pattern?
One strategy to deal with this is to pull the specifics "up" from this class to the "top", where it can be setup or configured properly.
What I mean is:
Get the concrete settings out of the class. Generalize, make it a parameter in the constructor, or make different subclasses or classes, etc.
Make all the other objects that depend on this depend on the interface only, so they don't know about these settings or options.
On the "top", in the main() method, or some builders or factories where everything is plugged together, there you can plug in the exact parameters or implementations you need for the specific customer.
I'm afraid there is no (correct) way around refactoring these classes to pull all of these specifics into one place.
There are workarounds, like getting configuration values at all of these places, or just creating different branches for the different versions, but these do not really scale, and will cause maintenance problems in my experience.
This is a pretty general question, so the answer will be quite general. You want your software to be open for extensions, but closed for modifications. There are many ways to achieve this with different degrees of openness, from simple ones like parameters to architecture-level frameworks and patterns. Many of the design patterns, e.g. Template method, Strategy deal with these kinds of issues. Essentially, you provide hooks or placeholders in your code were you can plug-in custom behavior.
In modern C++, some of these patterns, or their implementation with explicit classes, are a bit dated and can be replaced with lambda functions instead. There are also numeruous examples in standard libraries, e.g the use of allocators in STL containers. The allocator let's you, as a customer of the STL, change the way memory is allocated and deallocated.
To limit the uncontrolled writing of code, you should consider to expose to your customer a strong base class(in the form of interface or abstract class) with some(or all) methods closed to modification.
Then, every customer will extend the base class behaviour implementing or subclassing it. Briefly, in my thought, to every customer corresponds a subclass CustomerA, CustomerB, etc.. in this way you'll divide the code written by every customer.
In my opinion, the base class methods open to modification should be a very limited set or, better, none. The added behaviour should stay only in the added methods in the derived class, if possible; in this way, you'll avoid the uncontrolled modification of methods that mustn't be modified.
This question may seem open-ended but I am not sure where or how else to ask this. When writing object-oriented code one must determine the objects, methods and properties associated with what they're writing. I have a hard time doing this and so I am wondering if there is software or some sort of template that is out there to help me out with this.
For example if my object is a Car a few methods could be .engineStart(), .closeDoor(doorNumber) and a few properties could be color, make, licensePlateNumber.
Does anyone have a format or technique that they use to identify all the objects, methods, and properties before they actually start coding?
A class should handle a single aspect of the system to be built in the context of the chosen design.
An interface should be minimal (no sugar and convenience functions). This means that if you can realize a use case with a subset of the interface a function which would realize that use case should not be a member function.
Example:
class Foo
{
public:
void TurnLeft(uint32_t radians);
void TurnRight(uint32_t radians);
// Bad - interface not minimal and this is a convenience function.
void TurnLeftThenRight(uint32_t radiansLeft, uint32_t radiansRight);
};
A class should be an abstraction of sorts. This means, that it should not require all implementation details of the class and the full understanding of all its requirements used to implement it when using the class. Using the class correctly should be easier than implementing it.
A class should not simply "export" all state it encapsulates by means of properties as then it would not be an abstraction but simply a group of data.
For a class to be of practical use, it will make assumptions about the context it finds itself in and the general architecture. (Threading, memory usage policies, stack usage (recursions yes/no), exceptions yes/no, ...). Trying to factor all that out of the class or turn it into a multiple template parameter monster usually is not an optimal strategy for application programming.
A class implementation should have a unit test and some form of documentation about it's constraints and assumptions taken.
Class methods should be implemented in a defensive style. I.e. before optimization and tuning phase, a class should check input arguments and if possible also its output arguments and state against its constraints.
When thinking about the design of your program take into account:
The classes, methods and data needed.
Relationships among and between your classes.
How the information will be stored, etc.
So just try making a very detailed description of your program and what you want it to do. Then run through your description and pick out certain nouns and verbs that could help you specify things such as objects, attributes, and methods. From here you can then see how you would like to maybe organize your classes and data. Try not to make one class too complex or too small either.
Not sure if this is what you wanted, but I hope I could help.
Well when you start coding you need to determine what needs to be associated with what. Meaning, I know I have a car with all of these properties. So I need a car class with the following properties: color, make, plate number, gas mileage. Now I want to know how much this car is average. I can make a function in the car class specifically for the object that can be called to generate a price based off of parameters I input OR by the properties of the object itself.
This might not help or make sense but as you code you will see when and where to use classes.
I have a question with regard to encapsulation. As I know, encapsulation enables to hide the implementation details using private/protected data members and provides public methods and properties to operate on the data. The idea here is to prevent the direct modification of the data members by the class consumers.
But I have a concern with the property getters or other public methods which return private/protected data members. For ex: if I have class like this
public class Inventory
{
private List<Guitar> guitars = new List<Guitar>();
public void AddGuitar(string serialnumber, string price)
{
Guitar guitar = new Guitar(serialnumber, price);
guitars.Add(guitar);
}
public List<Guitar> GetGuitars()
{
return guitars;
}
}
Now if the Inventory class consumer calls GetGuitars, he is going to get the list of guitars being maintained in the Inventory class. Now the consumer can modify the list, like delete/add/modify the items. For me it looks like we are not encapsulating. I think that I should be returning a copy of the Guitar list items in the GetGuitars(). What do you think?.
Is my understanding of the encapsulation right?.
Thanks
Encapsulating lists of objects can be achieved quite nicely by restricting access to them using a suitable interface.
I think you're right to control additions to your list via your AddGuitar method as you can exert control over what goes in. You can reinforce this design, IMHO, by altering GetGuitars to return IEnumerable instead of List.
This reduces the control the caller has on your list, whilst also being non-committal in returning an abstract type. This way your internal data structure can change without the public interface needing to also.
You are right. With a setter like that clients are able to modify the list. If adding a guitar requires some special handling, this is not desired. In this case you have two choices:
Return a copy of the list (as you already suggested).
Wrap it with ReadOnlyCollection within the getter.
Both cases should be documented in method description so that clients are not "surprised" when they attempt to modify the list externally.
if u want your List array cannot be modified, why u dont use AsReadOnly method: http://msdn.microsoft.com/en-us/library/e78dcd75.aspx
about encapsulation inside members are only writable and readable through the methods where members are not available from outside.
In terms of risk, it is indeed better if you return a copy of your list of make it unmodifiable (create a whole new unmodifiable list when you add a guitar, functional programming-style).
In terms of encapsulation, it would be better to get rid of the getGuitars() method and then Inventory class should offer the functionality associated with it ( for example, printInventoryReport() or whatever). This way, no client class needs to know at all how you store your guitars and you keep the related code into the Inventory class. The tradeoff is that this class gets bigger and every time you need something new from the guitar list you need to modify the Inventory.
I recommend a good article : http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html
It was quite incendiary back in the day, but i think there's a lot of truth in there.
And if you stay with the getter, a small tip would be to choose if you need it to be a List or a Collection can do. Maybe even an Iterable! This way you tell as less as possible about your implementation, which results in better encapsulation.
I would agree that returning the list leaves something to be desired in terms on encapsulation. You may want to consider writing a getter for individual items, or possibly an iterator. The list seems like an implementation detail, so other classes really have no business accessing it directly.
There are (at least) two issues here.
The first is about hiding the implementation. You could change the "guitars" field to an array or a database but you could leave the signature of the methods AddGuitar and getGuitars unchanged so client code wouldn't break.
The second is about whether or not you want to return a defensive copy of the guitar list or not. Once you have the list of guitars do you want to add and delete elements? Since you have a method to add guitars I would assume not.