The following classes display the concept of Composition in Java:
//Imagine constructors, accessors & mutators has already been created..
class Person{
private String name;
private Job job; //Person has Job
}
class Job{
private String name;
private double salary;
}
My question is: If I want to get the salary from Person, which of the following 2 options is a better practice?
1. Get job of person, then get salary from job of person
System.out.println( person.getJob().getSalary() );
OR
2. Create a getSalary method in person, so I can do this:
System.out.println(person.getSalary());
Create a method to get salary from job first.
class Person{
private String name;
private Job job;
public static double getSalary(){ //Is doing this redundant and bad practice?
job.getSalary();
}
}
Method 2 is a little bit better than method 1 because the code that gets the salary from a person is not dependent on any kind of Person->Salary relation implementation. You are free to change the way the salary is computed. In real life you can ask somebody what is is salary without knowing anything about his job. In your code, a liar can even returns an imaginary salary for him, etc.
To be honest I insist on the fact that method 1 cannot be considered as bad or false in any way, it has only small disadvantage in common situations...
Generally and personally I like method 1 because every redirection (how call this right?) make code a little bit more complicated. Imagine whole code has redirections for every relation. Even it's harder to communicate: 'do you mean Person.Salary or Person.Job.Salary?'.
But in your example I prefer method 2 because I can imagine extend Person to have multiple jobs or jobs beside pension or like.
There is a "Law" saying that option number 1 should be avoided, it's the Demeter's law aka principle of least knowledge
in particular
an object A can request a service (call a method) of an object
instance B, but object A should not "reach through" object B
to access yet another object, C, to request its services
HTH,
Carlo
Related
If we have a Class Book and we want to calculate the score of a Book following some rules like "if the number of pages is lower than X then we need to substract Y from the score" and using an Hexagonal Architecture. Should we place this method calculateScore() in a separate Service in case this logic changes in the future using different fields or this reponsibility should be in the Domain itself?
1st approach
package com.xxx.domain;
[...]
public class Book {
[...]
public Double score() {
[...]
}
[...]
}
2nd approach
package com.xxx.application;
[...]
public interface ScoreService {
[...]
void calculateScore(Book book);
[...]
}
Should we place this method calculateScore() in a separate Service in case this logic changes in the future using different fields or this reponsibility should be in the Domain itself?
First the clean architecture is very clear when it comes to the question "Where should business logic be placed?".
Application agnostic business logic in the entities layer.
Application specific business logic in the use case layer.
But I think your question is about something a bit different, it's about anemic or rich domain models. I can't tell you every of my thoughts here, but I have written down most of them in the blog I linked in the sentence before.
The condensed statement of mine is
rich domain models combine data and logic while anemic models separate them.
Let's think about the anemic way...
If you place the logic in a separate service it usually means that you have to expose all properties of the book. You will make them public or at least package scope if the service is in the same package.
Your question also focuses on change. You make the statement that logic changes can be better handled if the logic is put in a separate service. That's true, but it comes at a cost.
It's true that an anemic model let you add logic easier, but it is also true that each logic (each service) must have the same interpretation of the anemic model. I mean each service must know how to modify the data structure properly to keep it consistent and that will be hard to maintain when the number of services grows.
But implementing the service can also be a good intermediate step, because it will give you a hint about cohesion. The cohesion usually shows you where to place a method. E.g.
public class ScoreService {
public BookScore calculateScore(Book book, BookRentals rentals){
int pageCount = book.getPageCount();
Author author = book.getAuthor();
// calculate a new value based on pageCount and the author
// ...
OtherValue ov = book.getSomeOtherValue();
// do something with ov
int rentalCount = rentals.getCountSince(someDate);
// ... and so on
}
}
When you look at the calculateScore above you will recognize that there are a lot of get invocations on Book and less on BookRentals. This is a hint that most of the data that calculateScore needs is placed in the Book. Thus the calculateScore's cohesion is higher to Book and the method might be placed in the Bookclass. E.g.
public class Book {
public BookScore getScore(BookRentals rentals){
int pageCount = this.getPageCount();
Author author = this.getAuthor();
// calculate a new value based on pageCount and the author
// ...
OtherValue ov = this.getSomeOtherValue();
// do something with ov
int rentalCount = rentals.getCountSince(someDate);
// ... and so on
}
}
The difference is obvious:
the number of method parameters decreases. Maybe you apply DDD and Book is an aggregation root and also has access to BookRentals. Then your parameters might decrease to zero.
Since most of the properties that getScore needs are located in the Book class, you might want to lower their visibilily to private. So that uncontrolled access is not allowed.
One question that often arises when developers put the logic in the entities is: "How can an entity access data from a data store?"
My solution is to just pass a repository to the methods that need it. E.g.
public class Book {
public BookScore getScore(BookRentalRepository repo){
// ...
int rentalCount = repo.getRentalCountSince(this, someDate);
}
}
Whatever way you want to go, anemic or rich, keep the logic in a POJO. Also keep in mind that a POJO can be more than a simple data structure.
I hope my answer helps you to make a decision for your specific application.
If the calc of the score depends only on the book state, i would create a method in the book entity to calc it.
Otherwise, if it depends on other domain objects also, i would create a domain service for calculating it.
Regarding to persist the score. I would persist it just if the calc process is very complicated and takes a lot of time. Otherwise, I wouldn't persist it and calc it when need it.
In case you persist jt, you have to consider that you have to recalculate it and persist the new value every time the other values it depends on change too.
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
Folks I'll start by apologising as I'm sure this has been answered elsewhere - I just can't find an answer that explains it in a way I understand! I'm doing an MSc conversion course and there are some elementary basics that I'm still struggling with this, including this one - why making a variable private is better.
Say I have a Java class called Person, with a print method. I could create it and define it as such:
public class Person
{
public String name;
public String telephoneNumber;
public void print()
{
System.out.println(name + " " + telephoneNumber);
}
}
Then, in a main class, I could write the following code:
class testPerson
{
public static void main(String[] args)
{
Person test;
test = new Person();
test.name = "Mary";
test.telephoneNumber = "01234 567890";
test.print();
}
}
If I did this, the test.print(); would produce the output:
mary 01234 567890
However, I know this is considered poor coding. Variables should be private inside a public class, as we don't want to allow people to see how this information is stored or to be able to edit information without authorisation.
So now, I'll edit the Person class to declare the two Strings private and add get and set methods, like so:
private String name;
private String telephoneNumber;
public void setName (String name)
{
this.name = name;
}
public void getName()
{
return name;
}
// same code for telephone methods.
Now, in the main class, I would change the methods of setting name and telephone to the following:
mary.setName("Mary");
mary.settelephoneNumber("01234 567890");
According to the lecture notes I'm following, this is more efficient (although could be made even more efficient by adding in a Person() method to allow for instantiation etc.)
However, I'm struggling to see why this is better.
In the former method of doing things, the user could directly access the variables. But even though by hiding the variables they can't directly access them, the user can indirectly access and modify them which produces the exact same outcome.
Why is it that this is preferred and what no doubt silly thing am I missing/overlooking?
Pizza Delivery Analogy
You order a Pizza for delivery.
Pizza boy knocks the door and expects you to pay for it.
You take out the money from your purse and hand it over to the delivery boy. (You are in control of hiding the internal details (drivers license etc.)) Alternatively,
You could hand over the purse to the delivery boy and ask him to take the money from it. By doing this you are no longer in control. You are exposing internal details.
Read about Information Hiding and Encapsulation is not information hiding.
It's not that it's more efficient, it's that it's more maintainable and a good practice.
For example, with setter methods, you could have your setTelephoneNumber actually check that the String is a valid telephone number before you actually do the setting. You couldn't possibly do that if you made the variable public. Using a setter from the very beginning means that you can go back and e.g. add validation later on, whereas if you had made the variable public, you would have to add a setter and modify all your users everywhere to use the setter instead of modifying the variable directly.
People will give you a million regurgitated reasons why it is better, but it is only better in some cases, not in all of them unequivocally. For example, take Java's own class GridBagConstraints—it has no methods at all (if you don't count clone, which it has anyway; all Java classes inherit it from Object). Why? Because there's a case where this is in fact more practical. And GridBagConstraints is a Java Bean in the purest sense: it's all about properties, no business logic there.
Let me report on another fact from practice: no setter ever validates its input; no getter ever calculates its result. In the world of JavaBeans, any such behavior will soon get in the way of the universal assumption that setters set, and getters get. Basically, if you diverge in any way from the exact equivalent of public fields, you lose.
The modern Java APIs, like Hibernate, acknowledge this fact by accepting naked public fields on an equal footing with JavaBean-style properties. Earlier versions didn't allow that, but as experience with Java accrues, the realization is finally dawning that public fields are OK.
You have to operate on the assumption that, at some point, someone else will use your code - and that someone else could be you, a year down the line. If you see a public property on a class, you should be able to assume that it's free for you to manipulate, if it's not to be directly modified you shouldn't be able to see it externally.
A good literal example would be the dimensions of a bitmap object. Most machines wouldn't like it if you tried to draw a bitmap of dimensions -10x-10, because such a thing would obviously be impossible to represent on a screen. If the width/height properties of this bitmap were simply public variables, it's possible they might be set to invalid values later on by a well-meaning coder (NEVER assume that it wouldn't happen), and when it came to render it - bang, you've got a frozen computer.
By hiding the variables and using a setter, you can prevent this ever happening:
private int _width = 10;
public void setWidth(int value)
{
//Prevent the value moving into invalid range:
if(value < 1)
value = 1;
if(value > 4096)
value = 4096;
//Now apply it
_width = value;
}
However, for speed and convenience you don't have to develop your code like this at first - just make sure you go through it afterward and hide what you need to!
there are also security issues to consider. a common example is a bank account. you have a balance, and you use deposit to put in money, and withdrawal to remove money. if balance was public, it could be modified without depositing or withdrawing money. that could be VERY bad.
within a method, you can put checks on things, such as making sure you don't take more money out of an account than actually exists. you can't really do that if you're accessing the values directly. it's about control.
So I am surprised that doing a search on google and stackoverflow doesn't return more results.
In OO programming (I'm using java), how do you correctly implement a one-to-many relationship?
I have a class Customer and class Job. My application is for a fictious company that completes jobs for customers. My current implementation is so that the Job class doesn't have anything to do with the Customer class, there is no reference to it at all. The Customer class uses a collection and methods to hold, retrieve and modify information about the Jobs that have been assigned by and/or completed for a customer.
The question is, what if I'd want to find out for which customer a particular Job has been done? I've only found this article that's relevant: http://www.ibm.com/developerworks/webservices/library/ws-tip-objrel3/index.html.
According to the implementation of the author, I would let the Job constructor take a Customer parameter, and store it so I can retrieve it. However, I see no guarantee at all that this model can be consistent. There are no restirctions to set the related customer for a job as a customer that the job was not for, and add jobs to customers that were done for someone else. Any help on this would be appreciated.
There's no 100% surefire way to maintain the integrity.
The approach which is usually taken is to use one method to construct the relationship, and construct the other direction in that same method. But, as you say, this doesn't keep anyone from messing with it.
The next step would be to make some of the methods package-accessible, so that at least code which has nothing to do with yours can't break it:
class Parent {
private Collection<Child> children;
//note the default accessibility modifiers
void addChild(Child) {
children.add(child);
}
void removeChild(Child) {
children.remove(child);
}
}
class Child {
private Parent parent;
public void setParent(Parent parent){
if (this.parent != null)
this.parent.removeChild(this);
this.parent = parent;
this.parent.addChild(this);
}
}
In reality, you won't often model this relationship in your classes. Instead, you will look up all children for a parent in some kind of repository.
Maybe you didn't expect a complex (and zero-code) answer, but there is no solution to build your bombproof API the way you intend it. And it's not because the paradigm (OO) or the platform (Java), but only because you made a wrong analysis. In a transactional world (every system that models real life problems and their evolution over time is transactional) This code will ever break at some point:
// create
Job j1 = ...
Job j2 = ...
...
// modify
j1.doThis();
...
// access
j2.setSomeProperty(j1.someProperty);
because at the time j1.someProperty is accessed, j1 and j2 could not even exist :)
TL;DR
The long answer to this is immutability, and it also introduces the concepts of life cycle and transactions. All other answers tell you how to do it, instead I want to outline why. A one-to-many relationship has two sides
has many
belongs to
Your system is consistent as long as if Customer A has Job B, the Job B belongs to Customer A. You can implement this in a number of ways, but this must happen in a transaction, ie a complex action made of simple ones, and the system must be unavailble until the transaction has finished execution. Does this seem too abstract and unrelated to your question? No, it isn't :) A transactional system ensures that clients can access system's objects only if all these objects are in a valid state, hence only if the whole system is consistent. From other answers you see the amount of processing needed to solve some problems, so that guarantee comes at a cost: performance. This is the simple explanation why Java (and other general purpose OO languages) can't solve your problem out of the box.
Of course, an OO language can be used to both model a transactional world and accessing it, but special care must be taken, some constraints must be imposed and a special programming style be required to client developers. Usually a transactional system offers two commands: search (aka query) and lock. The result of the query is immutable: it's a photo (ie a copy) of the system at the very specific moment it was taken, and modifying the photo has obviously no effect on the real world. How can one modify the system? Usually
lock the system (or parts of it) if/when needed
locate an object: returns a copy (a photo) of the real object which can be read and written locally
modify the local copy
commit the modified object, ie let the system update its state based on provided input
discard any reference to (now useless) local objects: the system has changed changed, so the local copy isn't up to date.
(BTW, can you see how the concept of life cycle is applied to local and remote objects?)
You can go with Sets, final modifiers and so on, but until you introduce transactions and immutability, your design will have a flaw. Usually Java applications are backed by a database, which provides transactional functionalities, and often the DB is coupled with an ORM (such as Hibernate) to write object oriented code.
You can ensure that there are no duplicates by using a Set implementation like HashSet instead of using other data-structure.
And instead of adding Job to a customer, create an final inner class in Job class that has private constructor. That ensure that the wrapper inner class can only be created by a job object. Make you Job constructor take in jobID and customer as parameter. To maintain consistency -if customer is Null throw Exception as dummy jobs shouldn't be created .
In add method of Customer, check to see if the Job wrapped by JobUnit has the same customer ID as the its own id, if not throw Exception.
When replacing a customer in Job class remove the JobUnit using the method provided by Customer class and add itself to the new customer and change the customer reference to the newly passed customer.
That way you can reason with your code better.
Here's what your customer class might look like.
public class Customer {
Set<JobUnit> jobs=new HashSet<JobUnit>();
private Long id;
public Customer(Long id){
this.id = id;
}
public boolean add(JobUnit unit) throws Exception{
if(!unit.get().getCustomer().id.equals(id))
throw new Exception(" cannot assign job to this customer");
return jobs.add(unit);
}
public boolean remove(JobUnit unit){
return jobs.remove(unit);
}
public Long getId() {
return id;
}
}
And the Job Class:
public class Job {
Customer customer;
private Long id;
final JobUnit unit;
public Job(Long id,Customer customer) throws Exception{
if(customer==null)
throw new Exception("Customer cannot be null");
this.customer = customer;
unit= new JobUnit(this);
this.customer.add(unit);
}
public void replace(Customer c) throws Exception{
this.customer.remove(unit);
c.add(unit);
this.customer=c;
}
public Customer getCustomer(){
return customer;
}
/**
* #return the id
*/
public Long getId() {
return id;
}
public final class JobUnit{
private final Job j;
private JobUnit(Job j){
this.j = j;
}
public Job get(){
return j;
}
}
}
But one thing I'm curious about is why do you even need to add jobs to a customer object?
If all you want to check is to see which customer has been assigned to which job, simply inspecting a Job will give you that information. Generally I try not to create circular references unless unavoidable.
Also if replacing a customer from a job once its been created is not necessary, simply make the customer field Final in the Job class and remove method to set or replace it.
The restriction for assigning customer for a job should be maintained in database and the database entry should be used as a checking point.
As for adding jobs to customer that were done for someone else, you can either check for customer reference in a job to ensure that the customer to which a job is being added is the same one it holds or even better-simply remove any reference in customer for Job and it will simplify things for you.
If the Customer object owns the relationship then you can possibly do it this way:
Job job = new Job();
job.setStuff(...);
customer.addJob(Job job) {
this.jobs.add(job);
job.setCustomer(this); //set/overwrite the customer for this job
}
//in the job class
public void setCustomer(Customer c) {
if (this.customer==null) {
this.customer = c;
} // for the else{} you could throw a runtime exception
}
...if the ownership is the other way around, just substitute customer for job.
The idea is to have the owner of the relationship maintain consistency. Bi-directional relationships generally imply that the consistency management sits in both entities.
Make a proper setter-function that maintains consistency. For instance, whenever you create a job, you supply the customer in the constructor. The job constructor then adds itself to the customer's list of jobs.
Or whenever you add a job to a customer, the add function has to check that the job's customer is the customer it's being added to.
Or some combination of this and similar things to what suits your needs.
Just implement some sort of collection in the object that has the other objects
For example in customer you could say:
private List<Job> jobs;
then by using getters and setters you can add values jobs to this list.
This is basic OO stuff, I don't think you searched enough on the internet. there is a lot of info available on these subjects.
Btw, you can use all sort of collections (Sets, Lists, Maps)
I know this is late but I think another way to this would be to look at the problem a bit differently. Since customer holds a collection of all jobs assigned by or completed for a customer, you could consider the job class to be a sub class of customer with extra information of having all the jobs completed by the customer. Then you would only have to maintain customer id in the main class and it would be inherited. This design would ensure that each job can be linked to a customer. Also if for a customer you want to find out how many jobs are present that too also would be got.
I am sorry I know this is very late but I have come across a similar problem where I feel the best solution is to follow a inheritance model. Think of job as being jobs done/asisgned by a particular customer. So in that case the Customer would be a super class with the Job(Lets call is customer job) being a sub class since a Job cannot exists without a customer. A customer would also have a list of jobs primarily for ease of data fetching. Intutively this does not make sense since Job and Customer done seem to have any relation, however once you see that Job cannot exist without a customer, it just becomes an extension of customer.
I can call variables 2 ways.
One is just to do it like this:
MyClass myClass = new MyClass();
myLocalVar = myClass.myVarVal;
And the other way is to use a getter like this:
myLocalVar = myClass.getMyVarVal();
Both ways are working fine, but I was wondering what would be the most efficient/proper way of doing this?
Thanks
Both techniques are terrible, but using the getter is the common (and safer) practice.
In order to access a public data member (a.k.a. public field or public property) of a class, you must know the implementation details of the class (the data member name and the data member type). This is a bad thing; it breaks the OOP concept "information hiding" and increases "coupling".
Using a getter is also bad (as in a bad OOP practice) because objects are not just wrappers around data; objects are supposed to encapsulate functionality and data. "store this here value so I can get it later" is not functionality; it is hoot functionality (as in a monkey in a cage hooting). Getters are; however, an accepted practice in java (and other OOP-lite languages like c++ and c#).
Lest you think I am some ivory tower purest, of course I use getters; I use java, so I use getters.
Getters are fine for getting the work done (no pun), just don't walk around believing that "I R gud OOP Prgmr", because if you use getters you are not a "good oop programmer", you are just a programmer who gets work done.
Edit: Perhaps a better way.
The better way is to not use getters, but to instead design your classes so they expose functionality not data. In practice, there is a point where this breaks down; for example, if you need to display an address on a JSP page, you put a bean in the request (or session or blah) with the address and expose the values using getters. A "more oop pure" way would be to put a bean that exposed "display the address on a jsp" functionality.
Edit2: Perhaps a better example.
Say I work for a phone company, in the USA, and I have an object that represents a customers phone number. This might look like the following:
public class CustomerPhoneNumber
{
private String npa; // numbering plan area (google search nanp for more details)
private String nxx; // exchange.
private String serviceNumber;
public String toString()
{
return "(" + npa + ") " + nxx + "-" + serviceNumber;
}
public boolean equals(Object object)
{
... standard equals implementation (assume this works)
}
}
Now say I get a phone number as an input from a web page in the form String inputPhoneNumber. For the purposes of discussion, the class that receives this input is called "the servlet".
How can I answer this question: "Is the input phone number in my list of CustomerPhoneNumber objects?"
Option 1 is make the npa, nxx, and serviceNumber data members public and access them. This is terrible.
Option 2 is provide getters for npa, nxx, and service number and compare them with the input. Also terrible, too many internal details exposed.
Option 3 is provide a getter that returns the formatted phone number (I called this toString() above). This is smarter but still terrible because the servlet has to know the format that will be used by the getter and ensure that the input is formatted the same way.
Option 4 (I call this "Welcome to OOP") provide a method that takes a String and returns true if that matches the customer service number. This is better and might look like this (the name is long, but sufficient for this example):
public boolean doesPhoneNumberMatchThisInput(final String input)
{
String formattedInput;
String formattedCustomerPhoneNumber = npa + nxx + serviceNumber;
formattedInput = ... strip all non-digits from input.
return StringUtils.equals(formattedCustomerPhoneNumber, formattedInput);
}
This is the winner because no implementation details are exposed. Also the toString can be used to output the phone number on a JSP page.
StringUtils is part of Apache Commons Lang.
For the sake of encapsulation you should always go with the second alternative.
myLocalVar = myClass.getMyVarVal();
Efficiency wise you most likely won't notice a difference.
Do ALWAYS use getter and setter to access your properties!
You should also take a look at this.
myClass.getMyVarVal() is slower since it is a method call and so it creates entrance on the stack for return value, etc. But it is better OOP practice to use getters.
Just create object and object.variablename; or object.methodName(); can be used to make non-static reference...no use of getter is required.
myLocalVar = myClass.getMyVarVal();
it will be good to use it if you are working with OOP concept
Tomcat + Heroku + Maven project:
How to reference Main class static variable:
HEROKU_PRJ_FOLDER\src\main\java\servlet\HelloServlet.java:
import launch.Main;
String my_str = Main.TEST_STRING;
HEROKU_PRJ_FOLDER\src\main\java\launch\Main.java
package launch;
....other imports here....
public class Main {
public static final String
TEST_STRING = "[TEST_STRING]";
public static void main(String[] args){
...somelogic...
};
};
This will probably work for any Tomcat project,
but I did this using Tomcat+Heroku+Maven. Posted answer because
the closest question I could find was this, which I already knew
how to do, just the exact import paths I found a bit confusing for
my particular problem.
I am writing an application that uses the observer pattern. The client class needs to know when an Employee object's state changes. It also needs to know the state of the employee at the current time (before any updates have been made). At the moment i am using a getEmployee() method and then registering an employee observer:
public class MyClass implements EmployeeObserver{
...
Employee employee= subjectClass.getEmployee();
subjectClass.registerEmployeeObserver(this);
...
}
Is there anything wrong with combining these methods so that an Employee object is returned in the same method call that the observer is registered in? :
Employee employee = subjectClass.getAndObserveEmployee(this);
I know this may seem a bit strange, but i only need the getEmployee method when the observer class is initialised and the subjectClass already has quite a large interface that i want to keep to a minimum. So, is this acceptable or is it bad practice to combine two actions into a single method call?
It's cleaner to separate the two.
On a separate note, why does the Employee itself not have an addObserver() method? There could be a perfectly valid reason but that would be my first guess of where to find it if I were searching for it. Either that or there would be some kind of service that manages employees and has the addObserver(int employeeIdToObserver) or something like that (implying that you already have a reference to the employee before you observer it.
Also, one way you could write the pattern is...
public interface EmployeeObserver {
public void stateChanged(State oldState, State newState);
}
...for observers that need to know what the state was before the change.
If sometimes you don't need the employee you have to do
subjectClass.getAndObserveEmployee(this);
which looks strange. or if sometimes you need emploee but not to register:
Employee employee = subjectClass.getAndObserveEmployee(null);
which again is not nice. If, let say you want to change the register part, (i.e. one more arg), you have to change the places where you use the function only for get() also.
I would not do that, except if necessary like in case of
oldVal = ConcurrentMap.replaceValue();
in this case two operations must be combined in one method because in concurrent system between two calls the state can change.