I have an ID field in the database which is a primary key. Is it a good practice to define it in the class? I will need the key to perform updates and other operations.
I have this doubt because I'm not sure, but a professor said that it is not a good practice.
EDIT:
public class Pagina {
private int id; //<--this is an good practice?
private String urlOriginal;
private String urlRedirected;
private String content;
private Link[] links;
private Date updateDate;
private Date visitDate;
private boolean visitedLinks;
}
If your class is persisted to the DB using JPA then its mandatory. If not then its still pretty useful. Hard to think of an example when it could prove to be a bad thing.
Strictly speaking, no.
Unfortunately most ORM frameworks that exist today don't support the
database's primary key transparently. Grails does as does the OODBMS db4o, but ones like Hibernate don't.
This means that you'll either have to bite the bullet and define the id in your domain class or write an additional layer to wrap your domain classes in to something that your RDBMS can talk to without exposing the persistence implementation to your business logic layer.
In Java, if you use a Map, it is often redundant to place the key in the value. However, the cost is usually trivial, as it is here. If you think it is easier to model the data this way, that is what I would do. (Even if you don't have a framework which requires it)
Clarity is usually the most important thing to consider.
If your model class persistable -- then it's mandatory to define some PK analog.
But it's not always should be named id -- in case of Page it could be it's url for example (but it`s not a good idea).
Does your professor argumentate it somehow?
According to my professor, in the UML solution of the problem, the Id should not be defined because each object is unique and don't needs an identifier attribute to this, but after, depending on which technology used, in the final project, the Id is necessary and there are no problems in using it. This not violate the good practices.
Related
What is the right way to create DTOs from business objects?
Who should be responsible for creating them? BO/DTO itself from BO/some static factory?
Where should they reside in code if I have, f.e. some core library and a specific service API library that I need DTO for? In core library next to BO(which seems incorrect)/in specific library?
If I have encapsulated fields in my BO how do DTO grab them? (obviously in case when BO is not responsible for creating DTOs)
As an example assume that I have some Person BO like this:
class Person
{
private int age;
public bool isBigEnough => age > 10;
}
I want age to be an internal state of Person but still I need to communicate my BO to some api. Or having private field in my class that I want to send somewhere already means that it should be public?
Are there any general considerations of how to use DTOs alongside business classes with encapsulated data?
___ Update:
In addition to approaches that #Alexey Groshev mentioned I came accross another one: we separate data of our BO class into some Data class with public accessors. BO wraps this data with its api(probably using composition) and when needed it can return its state as Data class as clone. So dto converter will be able to access Domain object's state but won't be able to modify it(since it will be just a copy).
There're multiple options available, but it would be difficult to recommend anything, because I don't know the details about your project/product. Anyway I'll name a few.
You can use AutoMapper to map BOs to DTOs and vise versa. I personally dislike this approach, because it's quite difficult (but possible) to keep it under control in medium/large sized projects. People don't usually bother to configure mappings properly and just expose internal state of their objects. For example, your isBigEnough would disappear and age would become public. Another potential risk is that people can map DTOs to/from EF/Hibernate objects. You can find some articles which explain why it's considered to be a bad practice.
As you suggested, a BO can create DTO by itself, but how would you implement this approach? You can add methods or factory methods to your entities, e.g. public PersonDto ToDto(). Or you can add an interface, e.g. public interface IDtoConvertable<T> { T ToDto(); }, and choose which entity or aggregate root will implement it. Your Person class would look like this class Person : IDtoConvertable<PersonDto> {... public PersonDto ToDto() {...} }. In both cases DTO namespace/assembly must to accessible by entities which sometimes can be a problem, but usually it's not a biggie. (Make sure that DTOs cannot access entities which is much worse.)
(C#) Another option is to return a delegate which creates DTO. I decided to separate it from (2), because entity doesn't really create DTO by itself, but rather exposes a functionality which creates DTO. So, you could have something like this public Func<PersonDto> ToDto() {...}. You might want to have an interface as in (2), but you get the idea, don't you? Do I like this approach? No, because it makes code unreadable.
As you see, there are more questions than answers. I'd recommend you to make a few experiments and check what works for you (your project) and what doesn't.
I think the answer to question 5 will address the other questions too.
Are there any general considerations of how to use DTOs alongside business classes with encapsulated data?
Remember, a DTO is solely to transfer data. Do not concern yourself with implementing any kind of rules in the DTO. All it is used for is to move data from one subsystem to another (NOT between classes of the same subsystem). How that data is used in the destination system is out of your control -- although as the God programmer you inherently know how it is going to be used, DO NOT let that knowledge influence your design -- and therefore there should be no assumptions expressed as behaviour or knowledge accessors -- so, no isBigEnough.
So, the topic says it all.
It is simply about how to prefix/suffix/mark special types of class members.
As we can see in sap-standard, there is no real convention, either, because of no existing guidelines, or because of too much developers or because of outsourcing to other companies, which might have their own. Of course this might become an "opinion" based discussion, so please forgive. Nevertheless I would like to hear some pro's and cons, and in this case we are only dealing with ABAP-OO.
What would You recommend / have seen mostly used / is entitled as best practice for nearly all kind's of class-members, like these, for example:
public instance methods ( ALSO GETTERS / SETTERS )
protected instance methods
private instance methods
public static methods
protected static methods
private static methods
public instance attribute TABLES ( include kind of table if you want )
protected instance attribute TABLES
private instance attribute TABLES
-->All the above stuff also for structures and simple datatypes
static public constants
static private constants
interface-members
I am on my search for a most common denominator to extract those, which convention would fit best into abap-oo and also might be near to world's
conventions of other languages.
Obviously we can say, that hungarian notation can be said as being obsolete
(means, that an instance table does not really need a "T" and a structure does not really need a "S" somewhere in their prefizes. But, according to other languages, a private counter could be named
_instance_counter, what I personally prefer).
I am already surprised by all the sap-"standard" differences, now I would like to wait for some of You.
SAP-Press has actually published a set of ABAP development guidelines.
Official ABAP development guidelines
Highlights include:
Separation of concerns
Program type and attributes
Checks for accuracy
Code formatting and organization
Comments and alternative notation
Error handling
Data storage
Data types and objects
Calculations and accesses
Fields and tables
Modularization
Dynamic programming
We could argue best practise until we're blue in the face, but in the end all you really want is consistency.
When I start at a new client I always ask for THEIR development standards, whether I agree with their standards or not isn't really relevant. However, people are usually open for discussion if you present a reasoned argument.
I'm working on a bit of code where we're creating object models but the models have generic keys. For example
class myContact {
var key;
var value;
}
And then in the code instantiating them as follows
myContact = new myContact()
myContact.key = 'address'
myContact.value = '123 my address'
myContact2 = new myContact()
myContact2.key = 'secondAddress'
myContact2.value = '123 my other address'
And then attaching them to a parent object like
myBank = new company();
myBank.addContact(myContact);
myBank.addContact(myContact2);
To me this feels wrong as the model is so loosely defined. However you do know from the class name it's going to be some sort of contact information.
At the same time I can see why this might be useful as if we want to add a different type of contact in future this kind of methodology makes it easy to do so.
Can any one explain to me if this is good practice? Bad practice and the reasons why?
My initial thoughts:
Good practice
Easy to extend contact types in future.
Easy to loop through contact information for myBank and get the data.
Bad practice
If you want to update a specific contact type you have to loop
through to find the correct key.
I've never written code like this which is why it feel like bad practice
even though it's perfectly acceptable.
Anemic model, there's no real need to be a class.
There's no defined key so we can't delete or add a contact easily without searching through them all again.
There's no definition of what a contact is or should be.
Any thoughts would be greatly appreciated.
edited: Adding some more thoughts as I go alone
in my opinion, there is nothing bad with 'custom fields'. it's rather popular in all systems that allow user to define their own fields (e.g jira, phone books, etc). usually there are some basic, predefined fields/keys like name, id, email etc, which are used e.g. for searching or authentication. the only thing i don't like in this code is the anemic model. if you make a class myClass (change that name!) and then give public access to all its fields, then why do you need a class? class is about encapsulation.
To me this feels wrong as the model is so loosely defined.
"Doctor, it hurts when I do this" - "Then don't do that".
Do you need a loose model to represent it? Then go for it. If not, if you feel it is only a burden, choose a simpler solution.
Apparently, there is no current need for it. What are the chances of this need to arise in the future? How would such a refactoring impact your codebase? Can you even make assumptions on that yet?
It may make sense in this case to apply the YAGNI principle in this case.
I have a team leader object, and have lot of team members object own by team leader.
Both team leader and team members have a function called "writeDB".
So, design 1:
Have a common writeDB function in DBUtility:
teamLeader.writeDB(); //calling DBUtility like this DBUtility.insert(self);
teamMember.writeDB(); //calling DBUtility like this DBUtility.insert(self);
design 2:
Both implementing a writeDB Interface:
teamLeader.writeDB(); //implement the write DB itself;
teamMember.writeDB(); //implement the write DB itself;
design 1 can centralize the writingDB logic into one single class, if there is any problems in writing DB, I only need to change the DBUtility class, also, if I would like change the DB, I only need to change one place.
design 2 can separate the code into two places. If one developer coding about teamLeader logic, he don't need to update the DBUtility, also, if the code move to somewhere else, he don't need to copy the useless function, for example, the DBUtility's teamMember writeDB function is not needed.
What do you think for better maintain? or the design 3 from you. Thank you.
Putting aside my concern that any model level class would have an explicit public method called writeDB, I would go for option 1
Persistence should be considered orthogonal to the core responsibilities of these classes.
The benefit comes in several parts
Cleanly separating the responsibilities will result in a more
object-oriented design. More object-oriented means more comprehensible and easier to manage over time.
In larger teams, you may well have a sub-group working explicitly on the persistence layer and they can have total responsibility for managing and optimising the code.
When you inevitably release that database X is better than database Y (or indeed that SQL is a bad idea), the persistence logic is not scattered across the code base
That pesky writeDB() method
Just to go back to my first point, you shouldn't have a public method called writeDB. You also probably don't want a more generic name such as save. The better design would allow the classes themselves to decide when they need to be persisted
Why do TeamMember and TeamLeader have to know about the database at all? I think this would be better:
DBUtility.write( teamMember );
DBUtility.write( teamLeader );
Better still is if DBUtility is not static, allowing you to see what it really depends on. Static is the same as global. Global puts an assumption in place about only ever doing it one way, and this generally causes problems later.
DBUtility dbUtility = new DBUtility( dbConnection );
dbUtility.write( teamMember );
dbUtility.write( teamLeader );
Then later, you might need to write to disk as XML. You should be able to add this feature without changing your TeamLeader and TeamMember.
XMLUtility xmlUtility = new XMLUtility( stream );
xmlUtility.write( teamMember );
xmlUtility.write( teamLeader );
I prefer to use the second design because it is more object oriented and you will benefit from separating the code.
I should go with design 2 which will force all my classes to have writeDB method, and I will use design1 to provide this functionality.
This way I will have interface for my objects Leader/Member and will have the actions grouped under on class which knows how to do the actions.
It depends. From a Separation-Of-Concerns principle this shouldn't be in the class itself, but having a class which knows about all others violates the Open-Close-Principle.
There is a third option for this kind of operation (e.g. write to DB), that is to use some metadata in the class and then some code which does write the object to the database by using the metadata information.
The second option is definatly mor OO. Eache type implements the writeDB interface.
If it makes sence when writing teamLeader to also write each teamMember then writeDB implomentation for teamLeader can call writeDB on each teamMember.
That would be the most OO solution.
Howerver, this dosen't take into account persistense layer limitations and efficencies.
I have three objects; Action, Issue and Risk. These all contain a nunber of common variables/attributes (for example: Description, title, Due date, Raised by etc.) and some specific fields (risk has probability). The question is:
Should I create 3 separate
classes Action, Risk and Issue each
containing the repeat fields.
Create a parent class "Abstract_Item"
containing these fields and
operations on them and then have
Action, Risk and Issue subclass
Abstract_Item. This would adhere to
DRY principal.
My Perspective
Let's say, if you used inheritance. Over a period you have new attributes that are common to only Action and Issue but not Risk. How will you handle this? If you put them under parent then Risk is inheriting stuff that is irrelevant (Liskov Substituon Principle knocking?). If you put then in Action and Risk separately then you are breaking DRY, the initial reason why you started inheritance. Point is Inhertence for re-use is bad. If there is no "is-a" then better not use it and when you are in doubt then there is no real "is-a".
My Preference
There are other ways of achieving DRY as shown in below example code. With this addition of new properties my be another Common2, addition of new behavior is new CommonBehavior2 if they are not applicable to all 3 classes; if they are then just change existing Common and CommonBehavior
public class Common implements CommonBehavior
{
String Description;
String title;
public void f() {}
}
public interface CommonBehavior
{
void f();
}
public class Action implements CommonBehavior
{
private Common delegate;
public void f()
{
delegate.f();
}
}
Also look at my answer to a similar question with another practical example Design pattern to add a new class
Yes, adhering to DRY is usually a very good idea except if the classes have very, very different uses (i.e. both apples and cars may be red, still I wouldn't derive both of them from a base class called ProbablyRed). In your case, however, I'd definitely go for a base class since the implementations you describe (Action, Issue, Risk) all seem to be some kind of business rule with very similar semantics.
You seem to be answering this yourself. As you say, DRY.
The abstract parent class sounds like the way to go. It will also make it possible or easier (depending on your language) to implement and use functions which act on any of the three items. For example, you could have a "Get a list of all items raised by {user}" function.
Another facet may become visible if you look at the use cases, probably dealing with different subgroups of the properties.
If for example "label", "due date" and "raised" are used in a todo like application and other properties of "Action" and "Risk" will be prevalent when working on that task, you might consider an aggregation of lets say Task (label, due date,...) and Topic which is a polymorphic reference to things like Action, Issue or whatever will come up someday
I guess I have answered the same question here
When to create a class vs setting a boolean flag?
Don't subclass just because objects share some data or operations. Consider composition as the default way to follow DRY.
In your particular case, only create a parent class if your objects are actually related, i.e. there's a semantic "is a" relationship to the parent class. For example, if Action, Issue, and Risk are all Ticket objects.