I've been trying to keep coupling down in my code, but I think I may not fully understand it. My basic understanding is that coupling is "how dependent classes are on each other and know about the behavior of each other." I know that dependency injection is one way to reduce coupling and IoC.
The following is an quick example I came up of a Student, Professor, and Course. A course has a list of students and a professor. I have a controller (using MVC) that injects the Student and Professor objects.
Would the following still be considered coupled, or tightly coupled? This also would be an example of DI, correct?
Student class
public class Student {
private String firstName;
private String lastName;
private int studentID;
private int address;
private int telephone;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getStudentID() {
return studentID;
}
public void setStudentID(int studentID) {
this.studentID = studentID;
}
public int getAddress() {
return address;
}
public void setAddress(int address) {
this.address = address;
}
public int getTelephone() {
return telephone;
}
public void setTelephone(int telephone) {
this.telephone = telephone;
}
}
Professor Class
public class Professor {
private String firstName;
private String lastName;
private int professorID;
private int address;
private int telephone;
private int salary;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getProfessorID() {
return professorID;
}
public void setProfessorID(int professorID) {
this.professorID = professorID;
}
public int getAddress() {
return address;
}
public void setAddress(int address) {
this.address = address;
}
public int getTelephone() {
return telephone;
}
public void setTelephone(int telephone) {
this.telephone = telephone;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
Course Class
import java.util.List;
public class Course {
private List<Student> students;
private Professor professor;
public Professor getProfessor() {
return professor;
}
public void setProfessor(Professor professor) {
this.professor = professor;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
}
I have a controller (using MVC) that injects the Student and Professor objects. Would the following still be considered coupled, or tightly coupled?
Since all references are Classes, you have a tightly coupled design. A good approach is to use interfaces in your code. This will allow you to change implementation any time you want and it will not affect the rest of your application.
This also would be an example of DI, correct?
If your Course, Professor and Student are configured beans, and you specify somewhere how to inject instances during bean instantiation, it will be a DI example. By now it is just three POJO classes.
What you have put here seem to be the Model part of your MVC implementation which have limited functionality other than setter-getters. To have a good example of decoupling and DI, you probably have Model, View and Controller classes that implement some interfaces. They are decoupled as each class's implementation is not aware/dependent on the other implementations. They only relate based on interfaces that well encapsulate and isolate components.
Probably you also have some fake/test implementation of those interfaces too
Then, there is a IoC setup that controls what implementation of each component will be resolved.
Related
This question already has answers here:
Why use getters and setters/accessors?
(37 answers)
Closed 1 year ago.
Recently I was going through the concept of Encapsulation in Java. I was wondering if making data variables private along with public setter methods really make sense in simple POJO class? Please refer below POJO:
public class Employee{
private String id;
private String name;
private String department;
private int age;
public Employee(){
}
public Employee(String id, String name, String department, int age){
this.id = id;
this.name = name;
this.department = department;
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
I mean why am I making the name variable private when I can anyway change it using the setter method?
In the general case, it'll be the very basic
public void setName(String name) {
this.name = name;
}
Where it's identical to just doing employee.name = "william hammond". But imagine a case where you'd like to do implement something like a private String normalize(string username) method where you maybe make it all lower case, check for a valid name or prevent unicode entries. If you make name public initially you'll have users doing employee.name = "whatever they want :) 123" and you'll lose the ability to enforce that constraint.
Also see Why use getters and setters/accessors?
Using getters/setters is just considered good practice, but it can often be overkill - like in your example.
If you have methods that mutate the variable before setting, then it's nice to have getters/setters for the basic fields as well to maintain consistent code style.
Here's a good article on it:
https://dzone.com/articles/getter-setter-use-or-not-use-0
Let's have an example:
public class Example {
private String firstName;
private String lastName;
public Example(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getFullName() {
return firstName + " " + lastName;
}
}
This class has 3 properties (firstName, lastName, fullName), but only two fields (firstName, lastName). It makes sense, because a full name can be retrieved by combining first and last name.
However, I've noticed that I call getFullName() a lot of times in my program, but I almost never call getFirstName() and getLastName(). This slows down my program, because I need to create a new string each time getFullName() is called. So, I've refactored my code to have a better performance:
public class Example {
private String fullName;
public Example(String firstName, String lastName) {
this.fullName = firstName + " " + lastName;
}
public String getFirstName() {
return fullName.split(" ")[0];
}
public String getLastName() {
return fullName.split(" ")[1];
}
public String getFullName() {
return fullName;
}
}
Now my code works faster when calling getFullName(), but slower when calling getFirstName() and getLastName(), however It's exactly what I needed. From outside the class, nothing really've changed.
As you can see by the given example, fields describe how your class uses the computer's memory, but not necessarily which properties your class has. This is why fields should be considered an implementation detail and therefore be private to a class.
I have found different implementations of the Builder pattern when learning about design patterns. Some implementations use an interface/abstract-class to represent the builder, others use just an static class.
Which one is the right way to implement the Builder Design Pattern?
Below, an implementation using an abstract class (ComputerBuilder) (Source)
public class LaptopBuilder : ComputerBuilder
{
Computer computer;
public LaptopBuilder()
{
computer = new Computer("Laptop");
}
public override void BuildOS()
{
//TODO
}
public override void BuildDevice()
{
//TODO
}
public Computer ComputerType
{
get { return computer; }
}
}
public class DesktopBuilder : ComputerBuilder
{
Computer computer;
public DesktopBuilder()
{
computer = new Computer("Desktop");
}
public override void BuildOS()
{
//TODO
}
public override void BuildDevice()
{
//TODO
}
public Computer ComputerType
{
get { return computer; }
}
}
Below, another implementation, Neither using abstract class nor interface, but an static class instead. (Source)
public class User
{
//All final attributes
private final String firstName; // required
private final String lastName; // required
private final int age; // optional
private final String phone; // optional
private final String address; // optional
private User(UserBuilder builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
}
//All getter, and NO setter to provde immutability
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
public String getPhone() {
return phone;
}
public String getAddress() {
return address;
}
#Override
public String toString() {
return "User: "+this.firstName+", "+this.lastName+", "+this.age+", "+this.phone+", "+this.address;
}
public static class UserBuilder
{
private final String firstName;
private final String lastName;
private int age;
private String phone;
private String address;
public UserBuilder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public UserBuilder age(int age) {
this.age = age;
return this;
}
public UserBuilder phone(String phone) {
this.phone = phone;
return this;
}
public UserBuilder address(String address) {
this.address = address;
return this;
}
//Return the finally consrcuted User object
public User build() {
User user = new User(this);
validateUserObject(user);
return user;
}
private void validateUserObject(User user) {
//Do some basic validations to check
//if user object does not break any assumption of system
}
}
}
If you actually read the second article you may notice that it fairly early on states that
"I want to make it clear that the builder pattern which I am going to discuss in this post, is slightly different from what is mentioned in GangOfFour “Design Patterns” book." (Author's emphasis)
A little later, he or she writes:
"For me, a builder pattern is more like fluent interface."
Notice the little qualifier, for me.
This should tell you that what you see isn't the 'canonical' representation of the pattern, but a variation.
That said, these representations are variations of the same underlying idea.
It's okay to look at alternative ways to express a concept. We should be careful that we don't elevate the Gang of Four book to unassailable status.
For me (pun intended) Builder is the best example of a GoF pattern that has been improved since the book was published. I believe it was Josh Bloch's version from Effective Java that popularized the static approach; but there are versions originating from blog posts that are more useful and/or less complicated than the GoF version.
As often as I refer back to the GoF book, I never reread the Builder chapter, because better alternatives are available. Of course, you have to decide which alternative is better for you.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
Let's assume we have User and UserBuilder class in their own package, that we want to be immutable and at consistent state before initialization, defined as follows:
public class User {
private final String firstName, lastName;
private final int age;
private final String adress;
protected User(UserBuilder buildUser) { //constructor acessible only in same packge
this.firstName = buildUser.lastName;
this.lastName = buildUser.lastName;
this.age = buildUser.age;
this.adress = buildUser.adress;
}
public String getFirstName() {
return firstName;
}
... // and other getters
}
And the builder class as follows:
public class UserBuilder {
public final String firstName;
public final String lastName;
public int age;
public String adress;
public UserBuilder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public UserBuilder setAge(int age) {
this.age = age;
return this;
}
public UserBuilder setAdress(String adress) {
this.adress = adress;
return this;
}
public UserBuilder getUser() {
return this;
}
public User build() {
return new User(getUser());
}
}
And finally we build the user in class that is in another package:
public static void main(String[] args) {
User user = new UserBuilder("John","Doe")
.setAge(22)
.build();
// User user = new User(UserBuilder) //error protected constructor
}
Is this considered safe and good design? If not, why?
My suggestions:
Place the Builder inside the User, so it is more trivial what the
Builder builds and User can access the private fields of the
Builder, therefore no getter needed in the builder.
Make User constructor private, because protected means derived classes can access the constructor, so immutability can broke.
the getUser() method is unnecessary.
Here is my example:
public final class User {
private final String firstName, lastName;
private final int age;
private final String address;
private final List<User> friends;
private User(Builder builder) {
this.firstName = builder.lastName;
this.lastName = builder.lastName;
this.age = builder.age;
this.address = builder.address;
this.friends = Collections.unmodifiableList(new ArrayList<>(builder.friends)); //immutable list
}
public String getFirstName() {
return firstName;
}
public List<User> getFriends() {
return friends;
}
/**
* other getters;
*/
public static class Builder {
private String firstName, lastName;
private int age;
private String address;
private List<User> friends = new ArrayList<>();
public Builder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public Builder setAge(int age) {
this.age = age;
return this;
}
public Builder setAddress(String address) {
this.address = address;
return this;
}
public Builder addFriend(User friend) {
this.friends.add(friend);
return this;
}
public User build() {
return new User(Builder.this);
}
}
public static void main(String[] args) {
User johnSmith = new User.Builder("John", "Smith").setAge(33).setAddress("New York").build();
}
}
Place UserBuilder inside User
Create constructor of User taking first/last name, address, age
Make constructor of User private
protected is not accessible ONLY in the same package, but in sub-classes as well.
Include the Builder class as nested class in User.
This approach is described here.
You are retrieving inmutable object, so this is right. But you are creating a User object aware of the builder object, and I think this is not right because the User class does not have to know that there is a builder class, you are coupling the two classes, i mean, User depends directly on UserBuilder, without UserBuilder User can not compile and this is not a good design
I Think you would have a better design following the another answers to the questions, with those examples you will delete the classes coupling
Good day,
I am new to JAVA'm learning this language and what I have learned it seems a fantastic language. My question is in relation to the following:
Suppose I have a class like this:
public class Person{
private String firstName;
private String lastName;
private int age;
private String entireName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEntireName() {
return entireName;
}
public void setEntireName(String entireName) {
this.entireName = entireName;
}
public static void Main(String args[]){
Person person = new Person();
person.setFirstName("Jhon");
person.setLastName("Adams");
person.setAge(20);
//Atention this line
person.setEntireName(person.getFirstName()+person.getLastName());
}
}
The language allows me to do this: person.setEntireName(person.getFirstName()+person.getLastName());
and it works fine however I would like to know how is best to do this, how it behaves at the object level and how high or low the performance.
Thank you ..
What you do is perfectly valid, but not very logical. Why not just drop the setEntireName() since it just combines two existing fields?
public String getEntireName() {
return firstName + " " + lastname;
}
This is valid. There is no performance difference, becasue JIT compiler optimize this code if needed (simply replace method with fields access).
Typically it is easier to eliminate the entireName property and its setter, and use the getter to perform the concatenation like so:
public String getEntireName() {
return firstName + " " + lastName;
}
This is also easier to maintain than updating entireName every time firstName or lastName is changed.
Recently I am doing a coding exercises I need to make my project , and so far I am practicing it with the code below what I want to ask is that, is this a has a relationship? am I doing the right practice? look at my code, sorry for my bad english
public class Personal {
private String firstName;
private String middleInitial;
private String lastName;
private int age;
public Personal(String firstName,String middleInitial , String lastName , int age){
setFirstName(firstName);
setMiddleInitial(middleInitial);
setLastName(lastName);
setAge(age);
}
public void setFirstName(String firstName){
this.firstName = firstName;
}
public String getFirstName(){
return firstName;
}
public void setMiddleInitial(String middleInitial){
this.middleInitial = middleInitial;
}
public String getMiddleInitial(){
return middleInitial;
}
public void setLastName(String lastName){
this.lastName = lastName;
}
public String getLastName(){
return lastName;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
public String toString(){
return String.format("First Name: "+getFirstName()+"\nMiddle Initial: "+getMiddleInitial()+
"\nLast Name: "+getLastName()+"\nAge: "+getAge());
}
}
Contact Class
public class Contact {
private String address;
private String email;
private String contactNumber;
public Contact(String address,String contactNumber, String email){
setAddress(address);
setContactNumber(contactNumber);
setEmail(email);
}
public void setAddress(String address){
this.address = address;
}
public String getAddress(){
return address;
}
public void setEmail(String email){
this.email = email;
}
public String getEmail(){
return email;
}
public void setContactNumber(String contactNumber){
this.contactNumber = contactNumber;
}
public String getContactNumber(){
return contactNumber;
}
public String toString(){
return String.format("Address: "+getAddress()+"\nContact Number: "+getContactNumber()+
"\nEmail Address: "+getEmail());
}
}
Employee Class
public class Employee {
private Personal personal;
private Contact contact;
public Employee(Personal personal, Contact contact){
this.personal = personal;
this.contact = contact;
}
public void setFirstName(String firstName){
this.personal.setFirstName(firstName);
}
public String toString(){
return String.format(personal.toString()+contact.toString());
}
}
And the Test class
public class TestClass {
public static void main(String[] args){
Personal personalHerp = new Personal("John","M","Doe",18);
Contact contactHerp = new Contact("88 Herp Derp St U mad New york","724-15-70","fido.com");
Employee employeeHerp = new Employee(personalHerp,contactHerp);
System.out.println(employeeHerp);
}
}
Well, since Employee doesn't extend Personal it has a Personal and a Contact.
I guess you'd rather like Employee to be a Personal and thus it should look like this:
public class Employee extends Personal {
private Contact contact;
...
}
So to summarize:
is-a means a class/object extends another class or implements an interface, i.e. A is-a B if A extends B or A implements B
has-a means that a class/object has a variable of that type, like Contact contact in your Employee class, which means Employee has-a contact.
Yes, this is a "has-a" relationship (exactly as we discussed in your other question).