Trying to understand the concept of encapsulation, I came across this definition "Combining the attributes and methods in the same entity in such a way as to hide what should be hidden and make visible what is intended to be visible".
But practicing the same, I am not sure which of the following code is more apt for OOP:
public class Square {
//private attribute
private int square;
//public interface
public int getSquare(int value) {
this.square = value * value;
return this.square;
}
}
or
public class Square {
//private attribute
private int square;
//public interface
public int getSquare(int value) {
this.square = calculateSquare(value);
return this.square;
}
//private implementation
private int calculateSquare(int value) {
return value * value;
}
}
Combining the attributes and methods in the same entity in such a way as to hide what should be hidden and make visible what is intended to be visible
This is a potentially misleading statement. You are NOT hiding anything from anyone. It is also not about methods or fields. Unfortunately this is the way things are worded in almost every place.
How
When writing any piece of program, (be it a function, class, module, or library) we think of the piece we are working on as my code, every other code as my client code. Now assume that all the client code is written by someone else, NOT you. You write just this code. Just assume this, even if you are the only one person working on the entire project.
Now the client code needs to interact with my code. So my code should be nice and decent to talk to. The concept of encapsulation says, that I partition my code in two parts, (1) that the client code should be bothered with, (2) that the client code should NOT be bothered with. The OO way of achieving encapsulation is by using keywords like public and private. The non OO way of achieving this is naming convention like leading underscores. Remember, you are not hiding, you are just marking it as none-of-your-business.
Why
So why should we encapsulate things? What should be organize my code into public and private regions? When someone uses my code, they are of-course using the whole thing, not just public thing, so how come private is something that is none-of-their-business? Note here words like someone and their could refer to yourself - but only while working on the other piece of code.
The answer is easy testability and maintainability. A complete project if tested exhaustively, can be quite a task. So at minimum, when you are done coding, you just test the public aspects of my code. You do not test any of the client code, you do not test any of the private aspects of my code. This reduces test effort while preserving sufficient coverage.
Another aspect is maintainability. My code will NEVER be perfect, it WILL need revisions. Either because of bugfix or enhancement, my code will need tinkering. So when a new version of my code is available, how much is client code impacted? None, if changes are in private regions. Also, while planning a change, we try to confine it as much as possible in private regions. So the change, from client's perspective becomes a no-impact. A change in public aspects of my code, will almost always require changes in client code, now that will need testing. While planning the big picture of my code, we try to maximize the area under private regions and minimize the area under public regions.
And more
The idea of encapsulating links with the idea of abstracting which in turn links with idea of polymorphism. None of these are strictly about OO. Even in non OO world like C or even Assembly, these apply. The way to achieve these differ. Even this applies to things beyond computers.
The process of sewage management, for example, is
encapsulated within the public interface of drains. The general public bothers only with the drains. The treatment, the disposal, the recycling are none of general public's business. Thus, the sewage management could be treated as an -
abstract entity - an interface with just the drains. Different government and companies implement this in their own way. Now an city may have a permanent system of sewage management, or it can periodically -
switch providers. In fifty years of government operation, the situation was bad, but once they contracted that BigCorp Inc, now people can breathe free. We just did polymorphism. We switched implementations, keeping the public interface same. Both government and the BigCorp Inc use the same drains, but their own processing facilities, which are encapsulated away and polymorphically switchable.
In your code
In both your codes you chose to encapsulate the storage, the field is made private. This is a nice approach and certainly OO way. In both of your codes, the algorithm is also encapsulated - i.e not visible to the client. Nice. In your second code, you went ahead and extracted the algorithm in a separate non-public method. This is commendable approach, although obviously an overkill for doing something trivial. Better OO none the less.
What you did in second code even has a name: the strategy pattern. Even though here it is useless (and overkill), it could be useful in a scenario when let say you are dealing with extremely large numbers, such that calculating their squares take very long time. In such a scenario, you could make your calculateSquare method protected, have a class FastButApproxSquare extends Square, and override the calculateSquare method with a different algo which calculates an approx value much faster. This way you could do Polymorphism. Whoever needs exact value will use the Square class. Whoever needs approx value will use FastButApproxSquare class.
Encapsulation is about hiding implementation and structure details from client code. In addition it is about coherence: keep things close together which are highly related to each other.
For example consider a class which manages players of a football team:
public class FootballTeam {
public final List<Player> players = new ArrayList<>();
}
Client code would have access to the list of players, to look them up, to add players and so on:
public class FootballManager {
private final FootballTeam team = new FootballTeam();
public void hirePlayer(Player player) {
team.players.add(player);
}
public void firePlayer(int jerseyNo) {
Optional<Player> player = team.players.stream()
.filter(p -> p.getJerseyNo() == jerseyNo)
.findFirst();
player.ifPresent(p -> team.players.remove(p));
}
}
Now, if someone decides to change the field FootballTeam.players into a Map<Integer, Player>, mapping the players jersey number to the player, the client code would break.
In addition the client code deals with aspects / features closely related to a player. To protect the client code and to ensure changeability of the FootballTeam implementation hide all implementation details, keep player related functionality close to the structure, representing the team and reduce the public interface surface:
public class FootballTeam {
private final Map<Integer, Player> players = new HashMap<>();
public void addPlayer(Player player) {
players.put(player.getJerseyNo(), player);
}
public Optional<Player> lookupPlayer(int jerseyNo) {
return Optional.ofNullable(players.get(jerseyNo));
}
public void remove(Player player) {
players.remove(player.getJerseyNo());
}
}
public class FootballManager {
private final FootballTeam team = new FootballTeam();
public void hirePlayer(Player player) {
team.addPlayer(player);
}
public void firePlayer(int jerseyNo) {
team.lookupPlayer(jerseyNo)
.ifPresent(player -> team.remove(player));
}
}
If any code serves the purpose of encapsulation then that code is correct. The purpose of encapsulation is to provide a process of hiding the variables from other classes (i.e. by making the variable as private) and also to provide a way for other classes to access and modify the variables. Both of your code serves this purpose correctly.
If you would have used "calculateSquare(int value)" method as "public" then there would have been a problem. Other class could call this method directly without using set/get method. So as far as your this method is "private" I think both the codes are all right.
Related
I have a situation where my 'agent' objects contain a vast amount of data, including graphics, physics, and now also ai.
I was previously coding components of these 'agents' in separate objects, that were parallel. Now I realize, since the agents are contained in a re-sizable ArrayList, that if one of the agents is destroyed, the indices will no longer be parallel to the ai components.
Truth be told, the agent class is already 10 pages long, and it is very sensible to contain the ai methods and data in a separate object. One issue with this, of course, is that the methods will be 'reproduced' in a way, because instead of having one ai object that will accept and process the data from the many agents, I need one ai object per every agent object.
I asked about this once before and was told that having multiple instances of methods has no effect on performance or memory bloat, so that shouldn't be an issue.
I am not sure how I can solve this problem, except by possibly storing an agent_id in the agent object as well as the ai object and then running a search on each list whenever I need to call them. Needless to say, that is terrible way of doing things performance wise.
In C++, the simple solution to this problem would be a pointer, where the pointer to the proper ai instance would be contained in the agent data. I don't know how to do this, so my best solution is to just cram more data into the agent object and have it passed as an argument to the ai object.
Is there any better way to solve this 'parallel mismatching' problem.
Edit>>>
I know I can stuff all of the data into the agent class. What I was taught, is having a 30 page class is an example of bad oop structure.
My question is, how can I create a /reference/ to store in the agent class, while keeping all of the ai data encapsulated in the ai module.
Edit>> Example
public class Agent{
//pseudo code that represents what I need (yes the class declaration order is wrong)
AI_ref = new Reference(ai_module);
Graphics_ref = new Reference(graphics_module);
int[][] physics_data; //Like I said, 10 pages of this
void method1(){}
void method2(){}
//....
}
public class graphics_module{
int[][] graphics_data; //this is also about 10 pages
void method1(){}
void method2(){}
//....
}
public class ai_module{
int[][] ai_data; //this will likely span 5ish pages
void method1(){}
void method2(){}
//....
}
}
Parallel arrays are a 1960's construct developed when Basic and Fortran were modern languages. These languages had no other data structures.
Since the 1990s with OO development, if you have several different types of data that belong together, you create an object to hold references to those bits of data such that you don't need to worry about parallel anything.
I strongly suggest you refactor your code to modern best practices and use objects. Since you've provided no explicit details, this is about the most explicit answer that can be given.
To create your references, try
public class Agent{
//pseudo code that represents what I need (yes the class declaration order is wrong)
ai_module AI_ref = new ai_module();
graphics_module Graphics_ref = new graphics_module();
int[][] physics_data; //Like I said, 10 pages of this
void method1(){}
void method2(){}
//....
}
As for your parallel arrays, your example doesn't really provide enough detail to demonstrate what you are trying to do.
//pseudo code that represents what I need (yes the class declaration order is wrong)
Do you mean defining Agent before defining ai_module and graphics_module is wrong? It's not. The java compiler will have no issue with that.
You should probably work through a basic java tutorial. I think it will address many of your issues.
In an e-commerce application, below are the high level API
interface Order{
public List<PaymentGroup> getPaymentGroups();
}
interface PaymentGroup{}
class PaymentGroupImpl implements PaymentGroup{}
class CreditCard extends PaymentGroupImpl{}
class GiftCard extends PaymentGroupImpl{}
class OrderManager{ //Manager component used to manipulate Order}
There is a need to add some utility methods like hasGiftCard(), hasCreditCard(), getGiftCards(), getCreditCards()
Two approaches -
1) Add these in Order. However, this would result in coupling between Order and PaymentGroup implementors (like CreditCard, GiftCard) Example -
interface Order {
public List<GiftCard> getGiftCards();
}
2) Move these to OrderManager.
class OrderManager{
public List<GiftCard> getGiftCards(Order order){}
}
I personally prefer 2), am just curious would there be any reason to choose 1) over 2)
I have two answers. One is what I'll call Old Skool OOP and the other I'll call New Skool OOP.
Let's tackle New Skool first. The GoF and Martin Fowler changed the way people look at OOP. Adding methods like hasGiftCard() leads to adding conditional logic/branching into the code. It might look something like this:
if (order.hasGiftCard()) {
//Do gift card stuff
} else {
//Do something else
}
Eventually this kind of code becomes brittle. On a big application, lots of developers will be writing predicate methods. Predicate methods assert something and return true or false. These methods usually start with the word "has", "is" or "contains". For example, isValid(), hasAddress(), or containsFood(). Still more developers write conditional logic that uses those predicate methods.
To avoid all of this conditional logic software engineers changed how they thought about object-orientation. Instead of predicate-methods-and-conditional-logic, they started using things like the strategy pattern, visitor pattern, and dependency injection. An example from your problem domain might look like this:
//Old Skool
if (this.hasCreditCard()) {
orderManager.processCreditCard(this.getCreditCards());
}
Here is another approach to solving the same problem:
//New Skool
for(PaymentItem each : getPaymentItems()){
each.process(this);
}
The New Skool approach turns the problem on its head. Instead of making the Order and OrderManager responsible for the heavy lifting the work is pushed out to the subordinate objects. These kind of patterns are slick because:
they eliminate a lot of "if" statements,
the code is more supple and it is easier to extend the application, and
instead of every developer making changes to Order and OrderManager, the work is spread out among more classes nd code merges are easier.
That's New Skool. Back in the day, I wrote a lot of Old Skool object-oriented code. If you want to go that route, here are my recommendations.
IMHO, you don't need both a PaymentGroup interface and a PaymentGroupImpl class. If all payment classes extend PaymentGroupImpl, then get rid of the interface and make PaymentGroup a class.
Add methods like isCreditCard(), isGiftCertificate() to the PaymentGroup class. Have them all return "false".
In the subclasses of PaymentGroup, override these methods to return true where appropriate. For example, in the CreditCard class, isCreditCard() should return "true".
In the Order class, create methods to filter the payments by type. Create methods like getCreditCards(), getGiftCertificates(), and so on. In traditional Java (no lambdas or helper libraries), these methods might look something like this
List getCreditCards() {
List list = new ArrayList();
for(PaymentGroup each : getPaymentGroups()){
if(each.isCreditCard()) {
list.add(each);
}
return list;
}
-In the Order class, create predicate methods like hasCreditCards(). If performance is not an issue, do this:
boolean hasCreditCards() {
return !getCreditCards().isEmpty();
}
If performance is an issue, do something more clever:
boolean hasCreditCards() {
for(PaymentGroup each : getPaymentGroups()){
if(each.isCreditCard()) {
return true;
}
return false;
}
}
Realize that if you add a new payment group, a code must be added in a lot of places in the Old Skool paradigm.
I'm currently currently working with a rather massive project with several classes of over 20, 000 lines. This is because it was someone's bright idea to mix in all the generated swing code for the UI with all of the functional code.
I was wondering if it would incur any extra cost in terms of memory or run time, to move most of the non-UI related functions into a separate class.
To provide an example, this is something along the lines of what I'm building.
public class Class1{
private Class1Util c1u;
List<String> infoItems;
...
public void Class1(){
c1u = new Class1Util(this);
}
public void btnAction(ActionListener al){
...
c1u.loadInfoFromDatabase();
}
}
public class Class1Util{
private Class1 c;
public void Class1Util(Class1 c){
this.c = c;
}
public void loadInfoFromDatabase(){
c.infoItems.add("blah");
}
}
Eventually, I'd also like to move some of the fields like infoItems over as well, which would result in a reverse relationship, with Class1 accessing c1u.infoItems.
no, separation of concerns is a good object oriented design practice. it will not cost you anything meaningful in terms of performance and will gain you many, many benefits in terms of maintenance, extensibility, etc.
You may get a tiny performance hit for an extra level of dereferencing, but it would not be noticeable in a UI code, and you will get so much extra clarity in return that you wouldn't regret it.
Eventually you may want to externalize state keeping into a third class, and then use that state from both your hand-written and generated code, or use the Generation Gap Pattern to manage complexity introduced by the need to integrate with the generated code.
I am developing a game in which the user can turn on / off certain effects. These effects cause a drain on the users' energy and various parts of the program must be able to check if an affect is active. Currently, I'm using an enum type to store and check the effects:
public static enum Effects { SUPER_FIRE, FIRE_SHIELD }
if (someEffect == Effects.SUPER_FIRE) {
// Breath fire etc..
}
Saying this, I have to store other variables for each effect - such as the level required to use it or the rate at which it drains energy. So, the other method I thought of was to use a class:
public class SuperFire extends Effect {
public static int levelRequired = 10;
public static int drainRate = 5;
public boolean active() {
// Check if it's active
}
public boolean activate() {
}
public boolean deactivate() {
}
}
SuperFireEffect sfe = new SuperFire();
sfe.activate();
if (sfe.active()) {
energyLevel -= sfe.drainRate;
}
sfe.deactivate();
Which implementation (or any other) is the best for this situation?
I hesitate to say "best" in any case, but it would appear that your second example is "better" in the "more flexible" meaning of the word.
Of course, from your very small code snippets, you are not encapsulating the functionality very well, so it would appear you may wish to do some more design work first.
In the end, you want to have the game code think in terms of the Effect base class and what it can do, and not have to know anything about the implementation of things like SuperFireEffect.
I would probably choose the second one as it is more "object-oriented" in my opinion. Plus if you start to add a lot of effects it will be more easily maintainable, and you can benefit from inheritance for super-effects.
The 2nd implementation is better since you mention about the effects which are specified with their own set of features / properties / fields / attributes like "levelRequired, drainRate". So following this approach, you should well define your classes / entities and their features and common characteristics. Object Oriented Programming principles should be conveyed.
This might sound like a weird idea and I haven't thought it through properly yet.
Say you have an application that ends up requiring a certain number of singletons to do some I/O for example. You could write one singleton and basically reproduce the code as many times as needed.
However, as programmers we're supposed to come up with inventive solutions that avoid redundancy or repetition of any kind. What would be a solution to make multiple somethings that could each act as a singleton.
P.S: This is for a project where a framework such as Spring can't be used.
You could introduce an abstraction like this:
public abstract class Singleton<T> {
private T object;
public synchronized T get() {
if (object == null) {
object = create();
}
return object;
}
protected abstract T create();
}
Then for each singleton, you just need to write this:
public final Singleton<Database> database = new Singleton<Database>() {
#Override
protected Database create() {
// connect to the database, return the Database instance
}
};
public final Singleton<LogCluster> logs = new Singleton<LogCluster>() {
...
Then you can use the singletons by writing database.get(). If the singleton hasn't been created, it is created and initialized.
The reason people probably don't do this, and prefer to just repeatedly write something like this:
private Database database;
public synchronized Database getDatabase() {
if (database == null) {
// connect to the database, assign the database field
}
return database;
}
private LogCluster logs;
public synchronized LogCluster getLogs() {
...
Is because in the end it is only one more line of code for each singleton, and the chance of getting the initialize-singleton pattern wrong is pretty low.
However, as programmers we're supposed to come up with inventive solutions that avoid redundancy or repetition of any kind.
That is not correct. As programmers, we are supposed to come up with solutions that meet the following criteria:
meet the functional requirements; e.g. perform as required without bugs,
are delivered within the mandated timeframe,
are maintainable; e.g. the next developer can read and modify the code,
performs fast enough for the task in hand, and
can be reused in future tasks.
(These criteria are roughly ordered by decreasing priority, though different contexts may dictate a different order.)
Inventiveness is NOT a requirement, and "avoid[ing] redundancy or repetition of any kind" is not either. In fact both of these can be distinctly harmful ... if the programmer ignores the real criteria.
Bringing this back to your question. You should only be looking for alternative ways to do singletons if it is going to actually make the code more maintainable. Complicated "inventive" solutions may well return to bite you (or the people who have to maintain your code in the future), even if they succeed in reducing the number of lines of repeated code.
And as others have pointed out (e.g. #BalusC), current thinking is that the singleton pattern should be avoided in a lot of classes of application.
There does exist a multiton pattern. Regardless, I am 60% certain that the real solution to the original problem is a RDBMS.
#BalusC is right, but I will say it more strongly, Singletons are evil in all contexts.
Webapps, desktop apps, etc. Just don't do it.
All a singleton is in reality is a global wad of data. Global data is bad. It makes proper unit testing impossible. It makes tracing down weird bugs much, much harder.
The Gang of Four book is flat out wrong here. Or at least obsolete by a decade and a half.
If you want only one instance, have a factory that makes only one. Its easy.
How about passing a parameter to the function that creates the singleton (for example, it's name or specialization), that knows to create a singleton for each unique parameter?
I know you asked about Java, but here is a solution in PHP as an example:
abstract class Singleton
{
protected function __construct()
{
}
final public static function getInstance()
{
static $instances = array();
$calledClass = get_called_class();
if (!isset($instances[$calledClass]))
{
$instances[$calledClass] = new $calledClass();
}
return $instances[$calledClass];
}
final private function __clone()
{
}
}
Then you just write:
class Database extends Singleton {}