Object Oriented Programming
Last updated
Was this helpful?
Last updated
Was this helpful?
Was this helpful?
Polymorphism
Tight cohesion
Loose coupling
Responsibility - where to write code?
Creation - Dependency Injection
Configuration
Services, components - Business logic
Data - Entities, DTOs
Layers
Logging - Framework or AOP
The paradigm
A.k.a. Inversion of Control, IoC
Always depend from the abstraction
The more abstract, the more robust
Example: What is inverted in DI?
Implementation of the Dependency Inversion
Mostly done by a DI framework -Spring, Java EE, ...
Easy to test -using mocks, test doubles
Example: Bad: Without dependency injection
Example: Good: Dependency injection by a DI framework
Do not use instanceof and isAssignableFrom()
it adds dependency
it adds duplication
refactor to polymorphism or patterns
Too strict
Hard to develop - one child changes a certain way the other one does not
Do not use inheritance only for a "common" code
Parent and children are be changed together - spaghetti code
Favor composition to inheritance - Item 16 in Effective Java (2nd Edition, Joshua Bloch, 2008)
Overridden methods are unreadable and fragile - Item 17 in Effective Java (2nd Edition, Joshua Bloch, 2008)
Parent must be changed when children change, abstract methods should be added
The parent's name is "Common..." - a class should have an intentional business name
Real polymorphism
Polymorphic usage - declared as a "parent" type
Design patterns
"Only talk to immediate friends"
Do not depend on the implementation details other classes
Use only one level of abstraction
"Wallet" rule
"Count of dots" rule - But not simply a dot counting law
It depends on that the used class is procedural or a data structure (see Classes)
Example: Bad:
Not in the book but also Uncle Bob.
A class should have only one reason to change
Only a change in the specification should affect the implementation of the class
Software entities should be open for extension, but closed for modification
It can be more general:
Software entities should NOT be open for extension
Any class should be closed for modification - not only parent classes
Objects should be replaceable with instances of their subtypes without altering the correctness of that program.
See also design by contract
Many client-specific interfaces are better than one general-purpose interface.
Depend on Abstractions. Do not depend on concretions.
Dependency injection is one method of following this principle.
public class FileHistoryService {
// Factory - Hard to replace implementation, hard to test
private IFileHistoryDao fileHistoryDao = DaoFactory.getFileHistory();
// Instantiation - Depends on implementation, may be more complex
private FileHistoryToFileHistoryDtoAssembler fileHistoryAssembler = new FileHistoryToFileHistoryDtoAssembler();
// Static methods - Depends on implementation, not polymorphic
private FileHistory createFileHistory() {
HttpHistoryAuthorHelperTAFile.fillAuthorFromHttpRequest(fileHistory);
}
}
@Component
public class FileHistoryService {
@Autowired
private IFileHistoryDao fileHistoryDao;
@Autowired
private FileHistoryToFileHistoryDtoAssembler fileHistoryAssembler;
@Autowired
private HttpHistoryAuthorHelperTAFile authorHelper;
}
// Depends on implementation of neighbors of neighbors...
String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();
// More levels of abstraction, reaches through layers
public boolean checkPassword(String name, String pwd) {
userService.checkPassword(pwd); // It already uses UserDao
User user = userDao.findUser(name); // It should not
}