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.
Related
I'm in doubt of how to get the best of ABAP structures and class attributes.
Let's say that I have the object Operation with 4 fields: operation id, type, description and date.
Now I can create a class with this 4 attributes, but then if I want to have a constructor, I need either 4 individual parameters or a structure than needs to be mapped to each attribute. The same happens if I want to get all this object data in one structure, for instance to return via RFC. Then a method get_operation_details( ) will need to map all of them one by one.
If I use a structure type ty_operation_details as a single class attribute, then when I add a field to the structure would also keep the constructor valid and the get_operation_details( ) method would also be always OK. However it seems wrong to have something like Operation->get_details( )-operationID, instead of operation->operation_ID if I had the attribute directly in the public section with READ-ONLY. I guess the first approach is more correct in the OO world, but we lose some of the ABAP benefits.
What do you recommend to use? Maybe one thing it could allow the first option and use structures at the same time would be a CORRESPONDING statement able to map class attributes to a flat structure, but I don't think this is possible.
Like most things, your design should follow your usage. If you primarily use a set of attributes together, consider grouping them in a structure. If you primarily use them individually, or in varying recombinations, keep them separate.
Some considerations:
Grouping makes calls shorter if you always create/update/delete a set of attributes together. You already identified this advantage.
Grouping reveals logical relations between fields, that are not clear when keeping the fields separate. For example, this could reveal that one part of your parameters is mandatory, while the rest forms several optional sets.
Grouping simplifies features that operate on state, such as the Memento or the Flyweight pattern, in that it allows to extract, store, and restore the object's state as a single structure.
Also, like many other things, there may be benefit in turning this either-or question into a I'll simply use both. For example, if your class has four individual properties, why not still offer a method that sets or gets them as a structure; of course, this will add some mapping, but the mapping would remain encapsulated within your own class, while consumer get an easy-to-consume interface.
I am just practising Java OOPs concepts by building a dummy project of Library management system.
Initially I had classes for Book, Customer, Administrator (with Customer, Administrator extending abstract user class)
I then created list classes BookCollection, CustomerCollection which hold the list of instances of above classes in ArrayList (for a while am not dealing with databases) and perform add, delete, sort methods on corresponding ArrayList (just one inline question: will it be a good design practice if I replace ArrayList related code with database operation once I start dealing with database, with each xyzCollection dealing with xyzTable in database)
The main problem:
Since I thought earlier that I will have to maintain only list of books, customers across app, I made ArrayLists static. Also, I wrote enough of static methods: addXyz, deleteXyz, searchXyz, sortXyz methods However now I realize that for search of Customers or Books I may have (or rather should) to return list of them matching the name, that means I have to return another ArrayList, which should be an instance of xyzCollection, however I cant use ArrayList in these xyzCollection as it is staic shared among all instances.
Initially it was appearing I will need shared ArrayList, but am now doubting my initial decision.
What should be correct?:
Should I make ArrayList and corresponding methods non static and make any corresponding code changes at calls
Or should I return ArrayList instead of XyzCollection
What will be better in terms of code design? Or I have made definite mistake in making them all static?
I assume that you are creating collection books/customers after fetching data from DB. As you say its a library management system which means multiple users can use it simultaneously. And each request will be independent of other (like a typical distributed system).
So would suggest you to use normal class instead of static. You can use static for managing utilities like connection to db but not as placeholder like list of books/customers.
In my thinking working with database would be much easy then using the concept of array list. As by using array you have to make it shared so that values can be accessed. As I don't know your conceptual design of making it so consider it just an opinion.
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.
I have a data class which encapsulates relevant data items in it. Those data items are set and get by users one by one when needed.
My confusion about the design has to do with which object should be responsible for handling the update of multiple properties of that data object. Sometimes an update operation will be performed which affects many properties at once.
So, which class should have the update() method?. Is it the data class itself or another manager class ? The update() method requires data exchange with many different objects, so I don't want to make it a member of the data class because I believe it should know nothing about the other objects required for update. I want the data class to be only a data-structure. Am I thinking wrong? What would be the right approach?
My code:
class RefData
{
Matrix mX;
Vector mV;
int mA;
bool mB;
getX();
setB();
update(); // which affects almost any member attributes in the class, but requires many relations with many different classes, which makes this class dependant on them.
}
or,
class RefDataUpdater
{
update(RefData*); // something like this ?
}
There is this really great section in the book Clean Code, by Robert C. Martin, that speaks directly to this issue.
And the answer is it depends. It depends on what you are trying to accomplish in your design--and
if you might have more than one data-object that exhibit similar behaviors.
First, your data class could be considered a Data Transfer Object (DTO). As such, its ideal form is simply a class without any public methods--only public properties -- basically a data structure. It will not encapsulate any behavior, it simply groups together related data. Since other objects manipulate these data objects, if you were to add a property to the data object, you'd need to change all the other objects that have functions that now need to access that new property. However, on the flip side, if you added a new function to a manager class, you need to make zero changes to the data object class.
So, I think often you want to think about how many data objects might have an update function that relates directly to the properties of that class. If you have 5 classes that contain 3-4 properties but all have an update function, then I'd lean toward having the update function be part of the "data-class" (which is more of an OO-design). But, if you have one data-class in which it is likely to have properties added to it in the future, then I'd lean toward the DTO design (object as a data structure)--which is more procedural (requiring other functions to manipulate it) but still can be part of an otherwise Object Oriented architecture.
All this being said, as Robert Martin points out in the book:
There are ways around this that are well known to experienced
object-oriented designers: VISITOR, or dual-dispatch, for example.
But these techniques carry costs of their own and generally return the
structure to that of a procedural program.
Now, in the code you show, you have properties with types of Vector, and Matrix, which are probably more complex types than a simple DTO would contain, so you may want to think about what those represent and whether they could be moved to separate classes--with different functions to manipulate--as you typically would not expose a Matrix or a Vector directly as a property, but encapsulate them.
As already written, it depends, but I'd probably go with an external support class that handles the update.
For once, I'd like to know why you'd use such a method? I believe it's safe to assume that the class doesn't only call setter methods for a list of parameters it receives, but I'll consider this case as well
1) the trivial updater method
In this case I mean something like this:
public update(a, b, c)
{
setA(a);
setB(b);
setC(c);
}
In this case I'd probably not use such a method at all, I'd either define a macro for it or I'd call the setter themselves. But if it must be a method, then I'd place it inside the data class.
2) the complex updater method
The method in this case doesn't only contain calls to setters, but it also contains logic. If the logic is some sort of simple property update logic I'd try to put that logic inside the setters (that's what they are for in the first place), but if the logic involves multiple properties I'd put this logic inside an external supporting class (or a business logic class if any appropriate already there) since it's not a great idea having logic reside inside data classes.
Developing clear code that can be easily understood is very important and it's my belief that by putting logic of any kind (except for say setter logic) inside data classes won't help you achieving that.
Edit
I just though I'd add something else. Where to put such methods also depend upon your class and what purpose it fulfills. If we're talking for instance about Business/Domain Object classes, and we're not using an Anemic Domain Model these classes are allowed (and should contain) behavior/logic.
On the other hand, if this data class is say an Entity (persistence objects) which is not used in the Domain Model as well (complex Domain Model) I would strongly advice against placing logic inside them. The same goes for data classes which "feel" like pure data objects (more like structs), don't pollute them, keep the logic outside.
I guess like everywhere in software, there's no silver bullet and the right answer is: it depends (upon the classes, what this update method is doing, what's the architecture behind the application and other application specific considerations).
A lot of the time I will have a Business object that has a property for a user index or a set of indexes for some data. When I display this object in a form or some other view I need the users full name or some of the other properties of the data. Usually I create another class myObjectView or something similar. What is the best way to handle this case?
To further clarify:
If I had a class an issue tracker and my class for an issue has IxCreatedByUser as a property and a collection of IxAttachment values (indexes for attachment records). When I display this on a web page I want to show John Doe instead of the IxCreatedByUser and I want to show a link to the Attachment and the file name on the page. So usually I create a new class with a Collection of Attachment objects and a CreatedByUserFullName property or something of that nature. It just feels wrong creating this second class to display data on a page. Perhaps I am wrong?
The façade pattern.
I think your approach, creating a façade pattern to abstract the complexities with multiple datasources is often appropriate, and will make your code easy to understand.
Care should be taken to create too many layers of abstractions, because the level of indirection will ruin the initial attempt at making the code easier to read. Especially, if you feel you just write classes to match what you've done in other places. For intance if you have a myLoanView, doesn't necessarily you need to create a myView for every single dialogue in the system. Take 10-steps back from the code, and maybe make a façade which is a reusable and intuitive abstraction, you can use in several places.
Feel free to elaborate on the exact nature of your challenge.
One key principle is that each of your classes should have a defined purpose. If the purpose of your "Business object" class is to expose relevant data related to the business object, it may be entirely reasonable to create a property on the class that delegates the request for the lookup description to the related class that is responsible for that information. Any formatting that is specific to your class would be done in the property.
Here's some guidelines to help you with deciding how to handle this (pretty common, IMO) pattern:
If you all you need is a quickie link to a lookup table that does not change often (e.g. a table of addresses that links to a table of states and/or countries), you can keep a lazy-loaded, static copy of the lookup table.
If you have a really big class that would take a lot of joins or subqueries to load just for display purposes, you probably want to make a "view" or "info" class for display purposes like you've described above. Just make sure the XInfo class (for displaying) loads significantly faster than the X class (for editing). This is a situation where using a view on the database side may be a very good idea.