I have the following question.
Assume we have third party software that send us transaction (atm cards) information in following style:
atm card 4**5048 debited 42$. 231$ Left.
So, I have debited sum, sum left and card no in each transaction.
So I create class
class Transaction {
private String mCardNo;
private Double mAmount; // Actually. I dont store money as double, but let it be:)
private Double mSumLeft;
}
One day second software appears and starts to send the info:
atm card 4**5048 debited 42$: purchase at Apple Store. 231$ Left.
And I think that its awesome to have info about place, where user made a purchase.
There are two options: extend Transaction class or add a new attribute "place".
One day new software is added and now I have to support 3 types of message!
atm card Visa Classic 4**5048 debited 42$: purchase at Apple Store. 231$ Left.
Oh, God! and Im pretty sure that it will be more than 100 types of messages containing unique numbers of attributes (because I have about 50 now!)
So what is the best way to store additional attributes?
If there's so much variability in the number of attributes, maybe you should store them in a single class (to avoid an explosion of subclasses) as values in a series of Map attributes and identify them with a String key (say, Map<String, Double>, Map<String, Integer>, etc.)
You can go several routes with this.
Keep your transaction class as is and use it as a base class, inherit from it and build new classes from it for each message type.
Add all the properties that you will need to the one trasaction class - you don't have to populate all of the properties when you use it.
I have personally used the second approach more often, it's easier to keep track of.
It depends on many other factors, such as how do you store data, is data being normalized or not make any difference or not, will there by millions of transactions or just hundreds, etc.
But, judging only by what you have provided, if you have tens of variations of transaction, then it is probably not practical to have separate class for each type. A generic Transaction class is a better approach. But, choosing one of the approaches is only half the work. The other half is, no matter which one you chose, to make sure that you design your class(s) properly right from the beginning. This requires that you spend some time, before doing actual design, to study transactions and various types that you have, or might get in the future. After having a comprehensive of the problem (business domain) itself, you will be able to devise a much better solution.
Related
Recently I have fallen in a situation like this. I'm generalizing the problem because I think it relates more to the structural design than the specific problem.
General problem
There is a hierarchy of classes: an abstract base class Base and some concretions D1, D2, D3 that inherit from it. The class A contains an object's collection of type Base. A requires a computation from some service-class B but B.process() method accepts only a collection of type D1. Let's say that is important because if the input collection contains any other type the value returned is just wrong.
A have an interface that allows clients to add elements to the internal collection, which is not exposed in any other way. The classes in the hierarchy can be constructed for the same clients and pass the new values to A; A have not enough context to construct them itself.
Attempts, questions and thoughts
The major concern for me was the need to determine at runtime the type of each element in the A collection, so can filter the right ones and pass to B.process(). Even if it is possible (it is in my particular problem, more later on) it just seems wrong! I think the object who contains references to the abstract base class shouldn't have to know the concrete instances it holds.
I try to:
Change the parameter type to B.process(c: Base[]) so A doesn't have to downcast the type, but it doesn't solve anything: A still needs to filter the elements or the computation will be wrong.
Pass the complete collection Base[] to B.process() but just defer the problem of selection/downcasting to B.
Put a process() method in Base so D1 can override the behavior (well known polymorphism). The problem here is that a process() returning a SomeValue type just have sense for D1.
Separate the interface that add elements so a more specific A.addD1Element(e: D1) method could allow put D1 objects in a different collection and pass that to B. It should work but also looks... don't know, weird. If method overload based on parameter type is possible at least the process won't be so cumbersome for clients of the class.
Just separate the D1 class of the hierarchy. This is a more aggressive variation of the previous one. The issue is that D1 seems related to the whole hierarchy except for the specific requirements of B.
Those were some of my thoughts on the problem.
For instance, the language used have support to check the type of an object at runtime (instanceof) and it is easy to filter the collection based on that check. But as I say my question is more related to the paradigm. What about a language, say for instance C++, where is less handy to make a check like that?
So what could be a solution to this kind of problem? What kind of refactoring or design pattern could be applied so the problem is easy to treat with or simply fades away?
This question looks related, but I believe this is more general (although I provide a more specific context). The most upvoted answer suggest to split in different collections. This is also a think i'm considering, but that forces to change A implementation every time a new type is added.
Context (problem in action)
I'm asking in a general way because it really intrigues me on that way, but I know most of the time a design can be analyzed only with the context of the particular problem it tries to solve.
The problem at hand is similar to this:
A is a class (some kind of entity, like a DDD entity) that models a sort of agreement or debt a customer incurs for a service. It has different costs including a monthly pay. Base and related classes are Payments of different types. They share a lot in common, although most of it is data (date, amount, interests, etc); but there is at least one type of payment that have different, additional information: the monthly payment (D1). Those payments need to be analyzed carefully so a different class (B) is responsible for that, using more contextual information and all the payments of that type at once. The service needs the additional data that is specific to those payments so cannot receive an abstract Payment type (at least not in that design). Other payments doesn't have the specific information MonthlyPayment does and so they cannot generates the values that business requires and B is generating (doesn't have sense in other payment types).
All payments are stored in the same collection so other methods of the class can process all payments in a generic way.
This is mostly the context. I think the design is not the best, but I fail to see a better one.
Maybe separating only MonthlyPayment (D1) in a different collection as described earlier? But it is not the only payment that requires additional processing (it is the most complex, though), so I could end with different collections for every payment type and no hierarchy at all. Right now there are four payments types and two of them requires additional, specific analysis, but more types can be added later and the issue of need to modify the implementation every time a new type is added persists.
Is this, more discrete approach of different collections by type, a better one here? The abstract base class Payment can still be used for payments that can be manipulated trough the common interface. Also I can use a layer super type or something like that to allow reutilization of common functionality (the language allows a kind of mixing as well) and stop using the base class as root from a hierarchy.
Uf. I am sorry for the length of the text. I hope it is at least readable and clear. Thank you very much in advance.
How many abstract function declaration of an Abstract class is too many?
For example, for a membership based payment system :
Multiple payment modes are supported :
Credit Card
Token (a Credit Card payment but using a token)
Redirect (i.e Paypal)
Manual (admin charging manually the user)
I have an abstract class PaymentMode and different modes above extend to this class.
Each mode has its own unique logic of the methods below and i have to declare abstract methods in PaymentMode class for these
// each mode has own way of validating the customer data
validate();
// own logic of cleaning customer data (e.g removing/adding/updating)
preparePaymentData();
// returns a string for saving in database, subclass must implement so developers plan to extend the PaymentMode abstract will be forced to return the correct value
getModeOfPayment();
// each mode has its own logic when determining payment gateways to attempt
getGatewaysToAttempt();
// before sending the payment to gateway, each mode has its own logic when adding specific data
addCustomDataSpecificForGateway();
// check if transaction has failed, different payment modes has different logic of determining a failed transaction
isTransactionFailed()
There 6 unique logic for each mode, I've managed to commonized the common codes already and put it inside the PaymentMode class.
This number may grow as we implement new features that is unique to each mode.
In my mind, im concerned that if any future developer extends my PaymentMode class, he has to implement all the abstract function declarations.
So does a large number of abstract function declarations an indication of a BAD DESIGN? How much is too many?
If its a bad design then, can you recommend any techniques or Design Patterns that will solve this issue
Thanks
It's hard to answer without specifics, but:
Obviously there is no hard limit on abstract methods (methods in interfaces or abstract classes), although less is always clearer and easier to understand.
What is indicating a suboptimal design however is that you need to modify your abstraction of a payment method with each new payment method. That to me indicates a failing abstraction. OOP is not just about pulling common code out, avoiding duplication, it is about abstractions also.
What I would look into is to somehow transfer the control (the real control) to the payment method. Trust the payment method, delegate the task of making the payment to it.
What I mean by that is, you retain control somewhere, where you ask the payment method to do specific parts of its job (with the parts being different for different concrete methods). Steps like validate(), prepare...(). And also, you expect it to give you the "gateway", so now code outside the payment method (even if it's the superclass) must know what that is, or how to handle it.
Instead of doing all that, try to come up with a design, that transfers full control over to the payment method, so it can do it's job without outside code assuming any particular set of steps.
For example:
public interface PaymentMethod {
Receipt payFor(Bill bill);
}
The PaymentMethod here is responsible for doing everything itself. Redirecting the user, saving the receipt in the database, whatever is needed. Once you feel comfortable with this "main" abstraction (it covers all use-cases), you can work to create smaller abstractions that cover details like saving to database, if it is the same for all methods.
In relation to that: don't use abstract parent classes as a way to share code between classes, that is not exactly what inheritance is for. Create proper abstractions for the different "pieces of code", and let them be used by "bigger" abstractions (i.e. composition).
There is no such number of abstract functions declarations that is BAD although the huge number could mean the design has flaws. Just pay attention to Single responsibility principle.
You have already defined that you have 4 modes - so i think you should do 4 interfaces for each mode in your case. After doing this you can see what is the common for all 4 of them and extract the base interface. You may consider to extract 6 unique logics for all of them also as interfaces...
I'm confused as where I should place the operation/function when identifying classes. The following example--taken from the lecture slides of object-oriented design using UML, patterns and Java--particularly confuses me.
In this example 3 classes are identified from the following part of use case description "The customer enters the store to buy a toy".
2 functions are also identified, one is enters() (placed in the Store class) and the other is buy() (placed in the Toy class).
Why those functions are not associated with the Customer who perform them? Is there any heuristic to help with operation placement?
Your example is extremely simple, and it's hard to say something about it without a context. Anyway, I'll try to answer your question. So, first of all: oo modeling is not about building your classes in a "natural" way. The reason is very simple: even if we wanted to model the "real world" objects, it's simply impossible. The relations between real-world (Customer, Store, Toy) objects are almost infinitely complex. Let's think about your case for a while. When a customer enters a store, there is a lot of things happening, let's try to order them:
Customer enters a store
Customer needs to interact with the "Store gateway" somehow, for example with a door. Even this interaction can be complex: store can be closed, full, an accident can happen, door can be blocked, etc
When customer finally is inside the store, maybe there's a special store policy to greet customers (or every n-th customer). We can also imagine a lot of other things.
Finally, the customer wants to buy a toy. First, she needs to find that toy, which might not be so easy (how would you model this interaction?).
When the desired toy is found, she needs to take it and add to the shopping basket.
Then, customer goes to the queue and waits for her turn.
When waiting is over, the customer interacts with the cashier (a lot of small things, like take the toy, check it's price, maybe some quick chat...)
Finally, the customer can pay for the toy (check if she have enough money, select the paying method (cash, card, nfc?), leave the queue...).
The customer leaves the store (similar to the "enters a store" interaction, plus maybe security checking).
I'm absolutely sure I forgot about something. As you can see, the simple scenario is in fact very complex in real world. That's why it's impossible to model it exactly the same way. Even if we tried, the naive 1-to-1 mapping would probably lead to the design, where almost every action is a method of the Customer class: customer.enter(), customer.leave(), customer.buy(), customer.findToy(), customer.interactWithCashier(), customer.openDoor()... and lot more. This naive mapping would be entirely bad, because every step in the "Customer enters a store" scenario is in fact a collaboration of multiple objects, each somehow connected with another. From the other hand, if we tried to implement this scenario with all interactions, we would create a system that would take years to build and would be simply impossible to deal with (every change would require insane amounts of hours).
Ok, so how to follow ood principles? Take just a part of the interaction. Do not try to model it exactly the same way as it works in the real world. Try to adjust the model to the needs of your client. Don't overload your classes with responsibility. Every class should be easy to understand, and relatively small. You can follow some of the basic principles of software modeling, such as SOLID, YAGNI. Learn about design patterns in practice (find some GOF patterns and try to implement them in your projects). Use code metrics to analyze your code (Lack of Cohesion of methods, Efferent coupling, Afferent coupling, Cyclomatic complexity) to keep your code simple.
Let's get back to your specific example. According to the rules I mentioned before, the very important part of object modeling is to place methods where they belong. So, the data and the methods should be "coherent" (see Lack of Cohesion of Methods metric). So, your classes should generally do one thing. In your example, the responsibility of the Store class could be, for example, to allow customers to buy toys. So, we could model it this way:
public class Store {
public void buyToy(Toy toy, Customer customer)
throws ToyNotAvailableException, InsufficientFundsException {
// some validation - check* methods are private
if(!checkToyIsAvailable(toy)) {
throw new ToyNotAvailableException();
}
if(!checkCustomerHasFunds(customer, toy.price())){
throw new InsufficientFundsException();
}
// if validation succeeds, we can remove the toy from store
// and charge the customer
// removeFromStore is a private method
removeFromStore(toy);
customer.charge(toy.price());
}
}
Keep in mind that this is just a simple example, created to be easy to understand and read. We should refine it many times to make it production-ready (for example handle payment method, number of items etc).
I am currently implementing something similar to an hospital intra site, where doctors can see info about their patients.
Currently, I have a LOT of info regarding each Client: his full name, date of birth, blood type, where he lives, diseases he had, etc.
My first attempt was something of the form:
class Client {
private string fullName;
private Date dateOfBirth;
...
public Get/Set FullName()
public Get/Set DateOfBirth()
...
}
which is basically putting everything together under the same class.
After a while I decided that maybe I should pack together similar concepts into a more general one. For example, I can encapsulate both userName and password into the same concept -- LoginInfo, for example.
If doing this, should I provide all the getters/setters on the Client class that delegate the work to the correct inner concepts, or should I just put getters for the concepts themselves? The first approach would shield the outside world to the Client class implementation, but then maybe, we wouldn't win that much by having all these innner concepts.
Should code outside the Client class even know the different kinds of concepts that'd use inside it?
Any other idea / approach?
I still don't know much about what methods I'll need to have on the Client class. Maybe if there are a lot, it'd be definetely good idea to use small inner concepts to group similar methods in themselves, instead of having such a loose coupled big class.
The data of Client will all be persisted using a standard database, if that makes any difference.
I would say it is useful to pack related pieces of data into common classes. I would only provide delegating getters/setters in Client for very commonly used properties though (if even then - it should be a case by case decision). If a concept makes sense in the problem domain, it is fine to expose it to the outside world too. Your LoginInfo is a marginal detail in this regard, but disease history, health check results etc. etc. are prime candidates for this.
I would also recommend you check out Martin Fowler's excellent Analysis Patterns, which dedicates a chapter to health care patterns; you may probably get some useful ideas out of it.
Something to consider when deciding how to organize data: are there any requirements for tracking history of data. For example, do you need to know what the patient's address was 5 years ago (in addition to knowing their current address, of course)? If so, making that "historically-sensitive" data its own class, will likely make it easier for you down the road. Of course, some data won't be "historically-sensitive" - date of birth for example. :)
Something else to consider: what data will be shared among patients? If you maintain data about family medical history, should that data be shared among siblings? If so, then encapsulating that data in its own object will save you lots of copy/synchronization pain later.
These aren't the only considerations when analyzing your data. But they're definitely part of the puzzle.
I'm designing an application which deals with two sets of data - Users and Areas. The data is read from files produced by a third party. I have a User class and an Area class, and the data is read into a Users array and an Areas array (or other appropriate memory structure, depending on the technology we go with).
Both classes have a unique ID member which is read from the file, and the User class contains an array of Area IDs, giving a relationship where one user is associated with many Areas.
The requirements are quite straightforward:
List of Users
List of Areas
List of Users for Specified Area
List of Areas for Specified Users
My first thought was to leave the data in the two arrays, then for each of the requirements, have a seperate method which would interrogate one or both arrays as required. This would be easy to implement, but I'm not convinced it's necessarily the best way.
Then I thought about having a 'Get Areas' method on the User class and a 'Get Users' member on the Area class which would be more useful if for example I'm at a stage where I have an Area object, I could find it's users by a property, but then how would a 'Get Users' method on the Area class be aware of/have access to the Users array.
I've had this problem a number of times before, but never really came up with a definitive solution. Maybe I'm just making it more complicated than it actually is. Can anyone provide any tips, URLs or books that would help me with this sort of design?
UPDATE:
Thank you all for taking your time to leave some tips. Your comments are very much appreciated.
I agree that the root of this problem is a many-to-many relationship. I understand how that would be modelled in a relational database, that's pretty simple.
The data I receive is in the form of binary files from a third party, so I have no control over the structure of these, but I can store it whichever way is best when I read it in. It is a bit square pegs in round holes, but I thought reading it in then storing it in a database, the program would then have to query the database to get to the results. It's not a massive amount of data, so I thought it would be possible to get out what I need by storing it in memory structures.
this is really a many-to-many relationship,
User <<--->> Area
break it up into 3 objects, User, Area, and UserArea:
User: Id, name, etc.
Area: Id, name, etc.
UserArea: UserId, AreaId
Very basic, but the idea is:
struct/class Membership
{
int MemberID;
int userID;
int areaID;
}
This class implements the "user belongs to area" membership concept.
Stick one of these for each membership in a collection, and query that collection for subsets that meet your requirements.
EDIT: Another option
You could store in each Member a list of Areas, and in each Area, a list of Members.
in Area:
public bool addMember(Member m)
{
if (/*eligibility Requirements*/)
{
memberList.add(m);
m.addArea(this);
return true;
}
return false;
}
and a similar implementation in Member (without the callback)
The advantage of this is that it's pretty easy to return an iterator to walk through an Area and find Members (and vice versa)
The disadvantage is that it's very tightly coupled, which could cause future problems.
I think the first implementation is more LINQ friendly.
Does an area belong to multiple users? If yes, it's a technically a many-to-many relationship. If you were to transform the data into a relational database, you'd create a table with all the relationships. I guess if you want to work with arrays, you could create a third array. Or if you actually want to do this in an OO way, both classes should have arrays of pointers to the associated areas/users.
I'm sorry, but this is not an object-oriented problem. It is a relational problem. Hence all the references to cardinality (many-to-many). This is relational database modeling 101. I don't mean to criticize Gavin, just to point out a new perspective.
So what good is my rant. The answer should be to integrate with a relational data store, not to pound it into a object oriented paradigm. This is the classic square peg, round hole issue.
Why not use DataTables with relations, if .NET is involved? You may want to look into Generics as well, again, if .NET is involved.
Agree with dacracot
Also look at DevExpress XPO
One option is to use a dictionary for each of the last 2 requirements. That is, a Dictionary<Area, List<User>> and a Dictionary<User, List<Area>>. You could build these up as you read in the data. You might even wrap a class around these 2 dictionaries, and just have a method on that class for each of the requirements. That would allow you to make sure the dictionaries stay in sync.