How would you code a washing machine? - oop

Imagine I have a class that represents a simple washing machine. It can perform following operations in the following order: turn on -> wash -> centrifuge -> turn off. I see two basic alternatives:
I can have a class WashingMachine with methods turnOn(), wash(int minutes), centrifuge(int revs), turnOff(). The problem with this is that the interface says nothing about the correct order of operations. I can at best throw InvalidOprationException if the client tries to centrifuge before machine was turned on. I can also use a separete Program class that will pass centrifuge revs and wash minutes to the WashingMachine and will simplify these methods.
I can let the class itself take care of correct transitions and have the single method nextOperation(). The problem with this on the other hand, is that the semantics is poor. Client will not know what will happen when he calls the nextOperation(). Imagine you implement the centrifuge button’s click event so it calls nextOperation(). User presses the centrifuge button after machine was turned on and ups! machine starts to wash. I will probably need a few properties on my class to parameterize operations, or maybe a separate Program class with washLength and centrifugeRevs fields, but that is not really the problem.
Which alternative is better? Or maybe there are some other, better alternatives that I missed to describe?

I'd have a 'high level' State Machine class which controls the entry/running/exit of each state (where states could be things like 'filling', 'washing', 'rinse', 'emptying', 'spin dry', etc)
Draw up a State Transition Diagram of all the states you need, including (for each state)
what requirements there are before you enter the state (entry conditions)
what needs to happen when you enter the state (entry actions)
what happens during the state (the task itself)
what requirements there are before you can leave the state (exit conditions)
what happens when you exit the state (exit actions)
You may or may not need the entry/exit conditions (e.g. you can force the conditions with an entry/exit action in some cases). For safety reasons though, some conditions can be good (e.g. exiting from a 'standby' state or entry into a 'dangerous' state like spin dry)
You also create Transitions, which define the links between states. A transition has
a 'from' state
a 'to' state
transition conditions (can the transition happen?
transition actions (what needs to happen when you transition)
Again, you may not need all of these, and many transitions will have only the 'from' and 'to' states specified.
In both cases, try to keep each State and Transition as simple as it needs to be (try to put the conditions/actions where they make the most sense, obviously there's potential double-up of these to be defined in a State and a Transition because of the generic design)
It should be pretty obvious at this point that you can make a fairly generic State class which includes abstract/overloadable functions for all of these things, and likewise for the Transition class. The State Machine class can call each of these member functions as required, based on the transitions requested of it.
If you make it especially generic, then the States and Transitions can be registered with the State Machine at construction time, or you might just code the State Machine to contain them all.
You can then request transitions, either from within states (i.e. a particular state can know when it has ended, and know which state to go to next) or you could have an external class which controls the state transitions (each state is then very simple, purely taking care of its own actions, and the external class decides the order and timing of transitions).
In my experience with these things, it's a good idea to separate the high level logic of deliberate order/timing of each action and the low level logic of reaction to some hardware event (e.g. transition out of the 'filling' state when the water level is reached).
It's a really generic design though, and you can achieve exactly the same functionality a bunch of different ways -- there's rarely a single right way of doing things...

I think that turnOn(), wash(), centerfuge() etc. should be private/protected methods. The public interface should be doTheWash(WashMode mode). The washing machine itself knows the modes it supports and how to make them work, the user of the washing machine need not get involved with the order or duration of operations. It is reasonable to expect the author of the washing machine class to call the private methods in a sensible order.

Most western washing machines use a timer to move from cycle to cycle. This timer can be thought of as a state machine of sorts. However, it's important to realize that a wasching machine runs itself, not the user. The user sets the initial mode, and then it goes on about its business.
So internally, you may have Wash, Rinse, Spin private functions, the actual interface would be SetCycle() and Start() and Stop(). You may also have some additional properties, like Water Level, Agitation Speed, Water Temperature, etc...
Start causes the time to advance, which after a period of time enters the next state, until finally it is complete.

Every washing machine has a controller and a program. For older and simple machines, program and controller are integrated into a rather complicated knob, modern and more expensive machines have a computer.
In either case, the machine has additional subsystems and the controller notifies the subsystems to perform some action, like lock the door, heat water until 40°C or spin the drum.
The Controller itself knows the sequence, which is pretty linear and timer based for old machines or complex for modern systems which vary the sequence based on sensor data. But in either case it executes a series of commands which may notify sensors and actors.
If you look at the washing system from this perspective, you may want to make use of the Command pattern inside the controller to model the washing program and of the Observer pattern for notifying the subsystems (Like: The door switch listens to the controller for a signal to lock the door).

The first is exactly what I'd do. wash and centrifuge would check the flag that tracks if the machine is on and throw an exception if it's not, but otherwise there is no mandatory order of operations; you could call centrifuge before wash if you really felt the need

Erm, a little weird but here goes;
I'd be looking at even delegates. So for a particular wash cycle type, heave, light, suddsy, economic etc I'd have say an interface for each.
Then, with the use of generics, I'd create the appropriate wash type I want.
The wash type would then have a wash event which delegates, in order, the cycles to perform.

The washing machine should know how to properly run a load. Perhaps before washing a load, certain configuration items are expected to be set (with defaults, if unset), like what type of load (lights vs darks) or size (small, medium, large). The user (another class) should know how to properly configure a load to run, but for washing a load, the washing machine should only need to expose one method, something like washLoad. Internally it would manage what needs to be called when to wash a load of laundry.
Alternatively, you could still expose public functions for turning the washer on and off, then if washLoad were called when the washer was off, it would be appropriate to throw an exception. Additionally, in this scenario, I would probably make the settings for the washer set via a single method setLoadOptions that would take another class the would be something like LoadOptions and defined whatever characteristics you wanted configurable. I would have this method also throw an exception if the washer was not on.

On my washing machine you have access to two knobs. I'm a little confused as to what the limitations are in your case.
Load size (Small, Medium, Large)
Cycle knob (Perm Press, Knits & Delicates, Regular)
Each cycle contains different "Phases" at which it can be activated at
When you "Activate" a cycle (by turning the knob), the machine will begin running if you turn it to the middle or beginning of a cycle.
Here is a really, really basic example of how I would translate this into a class:
class WashingMachine
{
public void Activate(Cycle c, LoadSize s);
...
}

Lately I have been going functional and using immutable objects with Martin Fowler/JQuery chaining fluent style.
I use the type system as much as possible as it makes refactoring.
With my method the compiler will force you to do it right.
Because the objects are somewhat immutable its easier to prove that mathematically this state machine is deterministic.
code:
public class Washer {
public void exampleRun() {
new On()
.wash(30)
.spin(100)
.turnOff();
}
public abstract static class State {}
public static class On extends State {
public Wash wash(int minutes) {
return new Wash(minutes);
}
}
public static class Wash extends State {
private int minutes;
public Wash(int minutes) {
super();
this.minutes = minutes;
}
public Spin spin(int revs) {
return new Spin(revs);
}
}
public static class Spin extends State {
private int revs;
public Spin(int revs) {
super();
this.revs = revs;
}
public Off turnOff() {
return new Off();
}
}
public static class Off extends State{}
}

Option A is like a manual washer while option B is like an automatic washer. Both options are useful to their targeting users:
A user of option A can enjoy manually programming the whole process (like doubling the washing circle, or teaching the little one what if you turn off the machine while it's in centrifuging circle).
A user of option B can enjoy the simplicity and write a dummy serials - teach your self washing in 21 seconds:-)

Related

encapsulation vs abstraction real world example

For an example of encapsulation i can think of the interaction between a user and a mobile phone. The user does not need to know the internal working of the mobile phone to operate, so this is called abstraction. But where does encapsulation fit in to this example? Could someone please shed some light on this?
Encapsulation is a way to achieve "information hiding" so, following your example, you don't "need to know the internal working of the mobile phone to operate" with it. You have an interface to use the device behaviour without knowing implementation details.
Abstraction on the other side, can be explained as the capability to use the same interface for different objects. Different implementations of the same interface can exist. Details are hidden by encapsulation.
Abstraction : you'll never buy a "device", but always buy something more specific : iPhone, GSII, Nokia 3310... Here, iPhone, GSII and N3310 are concrete things, device is abstract.
Encapsulation : you've got several devices, all of them have got a USB port. You don't know what kind of printed circuit there's back, you just have to know you'll be able to plug a USB cable into it.
Abstraction is a concept, which is allowed by encapsulation. My example wasn't the best one (there's no real link between the two blocks).
You can do encapsulation without using abstraction, but if you wanna use some abstraction in your projects, you'll need encapsulation.
Encapsulation is to hide the variables or something inside a class, preventing unauthorized parties to use. So the public methods like getter and setter access it and the other classes call these methods for accessing
Abstraction involves the facility to define objects that represent abstract "actors" that can perform work, report on and change their state, and "communicate" with other objects in the system.
Consider the below real time example:
Encapsulation:
As a driver you know how to start the car by pressing the start button and internal details of the starting operations are hidden from you. So the entire starting process is hidden from you otherwise we can tell starting operation is encapsulated from you.
OR
The driving wheel is encapsulated the process of rotating the wheel from you.
Abstraction:
Before mentioning anything about abstraction, we can take three different users here (I am calling them as entity)
1) You 2) Local Mechanic 3) Expert
You Entity: Since you know only to start the car by pressing a button and all other operations behind the scene are abstracted from you.
Local Mechanic Entity: Our local mechanic knows some of the implementation of starting the car, i.e. he can open car's bonnet and check the battery cable or chock etc. So in short Local Mechanic Entity knows some of the implementations of the car.
Expert Entity: Since our expert (Designer of the car) mechanic knows all the operations of our car, he can repair it very quickly. So in short Expert Entity knows all the implementations of the car.
The car's operation is completely abstracted from you and it is partially implemented to Local Mechanic Entity and fully implemented to Expert Entity. So you are an abstract class having only abstract methods, Local Mechanic Entity has extended You(Since he is also an ordinary user) and he implemented some of the methods and last our expert Entity extending Local Mechanic and implementing all the methods.
I think this is a good example.
In General words,Abstraction is Just Hiding the complex things behind a particular Procedure to make the procedure look simple.
Example:Monitor ON/OFF::--The user doesn't need to know much about all the chips functioning that happens when Monitor is switched ON or OFF..All he needs to know is On Function ON-Monitor is On and on function OFF-Monitor is off...
Or Better Look for a car--Everyone Knows that There's a special Gear machine Which changes the gear,nobody bother to know what all functionality undergoes for a gear to change..So,That's abstraction(avoiding unwanted implementations to prevent Complexity).
So,If a developer provides a good abstraction, users won't be tempted to peek at the object's internal mechanisms.
Abstraction is achieved by making class abstract having one or more methods abstract. Which is nothing but essential characteristic which should be implemented by the class extending it.
e.g. when you inventing/designing a car you define a characteristics like car should have 4 doors, break, steering wheel etc… so anyone uses this design should include this characteristics. Implementation is not the head each of abstraction. It will just define characteristics which should be included.
Encapsulation is restricting a user to follow a particular procedure to access control of a particular process.It Just provides safety and ensures system robustness.
Example:We can consider The HR in a company as a person that works on the principle of Encapsulation.i.e. we cannot talk to other departments directly we need to communicate through them through HR.This ensures security and better maintenance of company's records.
Together we can take example of a UNDER CONSTRUCTION BUILDING..where we can say that things like 'no. of managers' required,Types of Materials,No of workers etc as abstraction as they need to there in every Building Construction.
But,at the same time,Inclusion of every such field into a CONTRACTOR which acts as a mediator between the workers and the Building-Investor can be looked upon as Encapsulation.
As,It hides all the above properties into one Entity.
Hence If you would have understood till now you can say that
abstraction is just a subset of ENCAPSULATION.i.e.Every entity that
performs abstraction is encapsulated internally but every thing that
shows encapsulation need not be abstraction always.
e.g. .ToString() Method defined in almost every class is implementation of Abstraction because We don't the functionaltiy Within,all we care is that it changes almost everything to string.And as it assembles a s a unit,it is encapsulated too..But,The private members that we hide and access through Properties is an example of encapsulation only as it is done basically keeping data security in mindd..!!
Hope This answers your Question..!!
Everything has many properties and behaviours so take whatever object you want TV, Mobile, Car, Human or anything.
Abstraction:
Process of picking the essence of an object you really need
In other words, pick the properties you need from the object
Example:
a. TV - Sound, Visuals, Power Input, Channels Input.
b. Mobile - Button/Touch screen, power button, volume button, sim port.
c. Car - Steering, Break, Clutch, Accelerator, Key Hole.
d. Human - Voice, Body, Eye Sight, Hearing, Emotions.
Encapsulation:
Process of hiding the details of an object you don't need
In other words, hide the properties and operations you don't need from the object but are required for the object to work properly
Example:
a. TV - Internal and connections of Speaker, Display, Power distribution b/w components, Channel mechanism.
b. Mobile - How the input is parsed and processed, How pressing a button on/off or changes volumes, how sim will connect to service providers.
c. Car - How turning steering turns the car, How break slow or stops the car, How clutch works, How accelerator increases speed, How key hole switch on/of the car.
d. Human - How voice is produced, What's inside the body, How eye sight works, How hearing works, How emotions generate and effect us.
ABSTRACT everything you need and ENCAPSULATE everything you don't need ;)
The wording of your question is odd - Abstraction vs Encapsulation?
It should be - someone explain abstraction and encapsulation...
Abstraction is understanding the essence of the thing.
A real world example is abstract art. The artists of this style try to capture/paint the essence of the thing that still allows it to be the thing. This brown smear of 4 lines captures the essence of what a bull is.
Encapsulation is black boxing.
A cell phone is a great example. I have no idea how the cell phone connects to a satellite, tower, or another phone. I have no idea how the damn thing understands my key presses or how it takes and sends pictures to an email address or another phone number. I have no idea about the intricate details of most of how a modern smart phone works. But, I can use it! The phones have standard interfaces (yes - both literal and software design) that allows someone who understand the basics of one to use almost all of them.
How are the two related?
Both abstraction and encapsulation are underlying foundations of object oriented thought and design. So, in our cell phone example. The notion of a smart phone is an abstraction, within which certain features and services are encapsulated. The iPhone and Galaxy are further abstractions of the higher level abstraction. Your physical iPhone or Galaxy are concrete examples of multiple layers of abstractions which contain encapsulated features and services.
Abstraction
Means We focus on the essential qualities of some thing rather than one specific example and we automatically discard what is unimportant or irrelevant.
Example
We are writing a bank account class,essential qualities of bank account are Opening date, Account title,Account number,Balance etc...
Encapsulation
Means the idea of capsulation or surrounding some thing not just to keep the content together but also to protect and restrict form accessing out side.Along with secrecy It's about reducing dependencies between different parts of the application.
Example
In our Bank account class Someone accessing the attribute of Balance and trying to change it ,Attempt can be successful if there is no encapsulation.
Encapsulation is hiding information.
Abstraction is hiding the functionality details.
Encapsulation is performed by constructing the class. Abstraction is achieved by creating either Abstract Classes or Interfaces on top of your class.
In the example given in the question, we are using the class for its functionality and we don't care about how the device achieves that. So we can say the details of the phone are "abstracted" from us.
Encapsulation is hiding WHAT THE PHONE USES to achieve whatever it does; Abstraction is hiding HOW IT DOES it.-
Encapsulation helps in adhering to Single Responsibility principle and Abstraction helps in adhering to Code to Interface and not to implement.
Say I have a class for Car : Service Provider Class and Driver Class : Service Consumer Class.
For Abstraction : we define abstract Class for CAR and define all the abstract methods in it , which are function available in the car like : changeGear(), applyBrake().
Now the actual Car (Concrete Class i.e. like Mercedes , BMW will implement these methods in their own way and abstract the execution and end user will still apply break and change gear for particular concrete car instance and polymorphically the execution will happen as defined in concrete class.
For Encapsulation : Now say Mercedes come up with new feature/technology: Anti Skid Braking, while implementing the applyBrake(), it will encapsulate this feature in applyBrake() method and thus providing cohesion, and service consumer will still access by same method applyBrake() of the car object.
Thus Encapsulation lets further in same concrete class implementation.
I feel like encapsulation may make more sense to discuss when you see HOW NOT TO DO in programming. For example, consider a Car class as below.
class Car{
public float speed =0;
public boolean isReverse = false;
public boolean isStarted = false;
}
The client code may use above car class as below.
class Main{
public static void main(args String[]){
Car car = new Car();
// No need to start??
car.speed = 100; // Turbo mode directly to 100
car.speed = 0; // Turbo break
}
}
See more at: http://brevitaz.com/encapsulation-example-benefits-java/
This is uncontrolled access to car speed and other variables. By encapsulation, Car class can have complete control over how the data variables within car class can be modified.
Any concrete entity that has some behavior is example of Encapsulation. The behavior is provided by wrapping up something and hiding something from client.In case of mobile, it is signals, chips, circuits, battery and so on.
For abstraction of the same example - normal user may say I am ok with anything using which I can make calls and receive calls. This abstraction can be substituted by any concrete mobile. Check out Abstraction examples.
Let me give my 2 cents of a real-world example-analogy close to IT.
Lets say you have a subscription site, e.g a wordpress site
Each user has a role, eg admin, subscriber and so on. Many users can be admins, subscribers etc..
So abstraction here is reflected in the fact that any user with admin role can do a set of things, it does not matter which specific user this is (this is an example of abstraction).
On the other hand, subscriber users do not have access to certain settings of the site, thus some internals of the application are encapsulated for plain subscribers (this is an example of encapsulation)
As one can see abstraction and encapsulation are relative concepts, they apply with respect to something specific.
One can follow this line of reasoning and explain polymoprhism and inheritance.
For example super-admin users could do all the things admin users could do, plus some more. Moreover, if admin roles get an update in functionality, super-admins would get the same update. Thus one can see here an example of inheritance, in that super-admin roles inherit all the properties of admin roles and extend them. Note that for most part of the site, admins are interchangeable with super-admins (meaning a super-admin user can easily be used in place of an admin user, but not vice-versa in general).
I guess an egg shell can be consider the encapsulation and the contents the abstraction. The shell protects the information. You cant have the contents of an egg without the shell.,,LOL
If you have seen important TV machine, TV connections and TV color tube is hidden inside the TV case which is not been exposed for viewers like us and exposed only neccessary things of a TV like TV Channel keys, TV volume keys, ON/OFF switch, Cable Switch and TV remote control for viewers to use it.This means TV machine, TV connections and TV color tube is an unwanted data and not needed for viewers to see is been hidden from outside the world
So encapsulation means hiding the important features of a class which is not been needed to be exposed outside of a class and exposing only necessary things of a class.
Here hidden part of a class acts like Encapsulation and exposed part of a class acts like Abstraction.
Just think of Abstraction as hiding the keypad and display screen details,
Encapsulation as hiding the internal circuitry that binds them.
Abstration which hide internal detail to outside world for example you create a class(like calculator one of the class) but for end use you provide object of class ,With the help of object they will play and perform operation ,He does't aware what type of mechanism use internally .Object of class in abstract form .
Encapsulation is the technique of making the fields in a class private and providing access to the fields via public methods. If a field is declared private, it cannot be accessed by anyone outside the class, thereby hiding the fields within the class. For this reason, encapsulation is also referred to as data hiding.For example class calculator which contain private methods getAdd,getMultiply .
Mybe above answer will help you to understand the concept .
Abstraction
It is used to manage complexities of OOPs. By using this property we can provide essential features of an object to the user without including its background explanations. For example, when sending message to a friend we simply write the message, say "hiiii" and press "send" and the message gets delivered to its destination (her,friend). Here we see abstraction at work, ie we are less concerned with the internal working of mobile that is responsible for sending and receiving message
Abstraction
We use many abstractions in our day-to-day lives.Consider a car.Most of us have an abstract view of how a car works.We know how to interact with it to get it to do what we want it to do: we put in gas, turn a key, press some pedals, and so on. But we don't necessarily understand what is going on inside the car to make it move and we don't need to.
Millions of us use cars everyday without understanding the details of how they work.Abstraction helps us get to school or work!
A program can be designed as a set of interacting abstractions. In Java, these abstractions are captured in classes. The creator of a class obviusly has to know its interface, just as the driver of a car can use the vehicle without knowing how the engine works.
Encapsulation
Consider a Banking system.Banking system have properties like account no,account type,balance ..etc. If someone is trying to change the balance of the account,attempt can be successful if there is no encapsulation.
Therefore encapsulation allows class to have complete control over their properties.
Let me explain both abstraction and encapsulation with the help of the example given by you about the mobile phone.
Abstraction
The inner working on the mobile phone is hidden from the user. The user is interacting with the mobile through screen/buttons. This is equivalent to interacting with the class through an object. Here class is the mobile and the object is the screen/buttons.
Encapsulation
In a mobile phone, we can see that the battery, CPU, RAM, Camera and so on are contained together inside a box/container. This is similar to how class encapsulates all its methods and variables. The methods and variables are contained inside the class.
Also, you can't access the inner components of the mobile phone right? You need special screwdrivers for that. The components inside the mobile phone are secured. Similarly, we can secure the components or variables inside a class. We secure it with private access modifiers. Private access modifiers are the containers of the mobile phone. We can access the private fields with the help of setters and getters. These getters and setters are like special screwdrivers.

Best solution to an OOP organization issue

I have a quick question about the organization of a particular OOP problem.
Say I have a Terrain class, full of Tiles. There are multiple derivatives of class Tile, namely Door. The Door class has a method called open() which opens the door, and close() which closes the door. This makes perfect sense until both of these methods need to check for something in the way before opening and/or closing. How do I make a Door check for an object in the way without it knowing about its parent?
A simple solution would be to check for something in the way before calling open(), but if there was a different kind of door that needed to be check in a different shape, it creates clutter on the higher level.
It seems like this would have a simple answer, but it also seems like I run into this problem more often than not.
One answer is that Doors should know how to open and close themselves and know if they are blocked. If Door is a class, then both the state (is_open, is_blocked) and the behavior (open_the_door, close_the_door) should reside in the Door class. Encapsulation is a fundamental principle of the object-oriented paradigm.
But the real-world answer is usually more subtle. Can you provide some background on the application and what it needs to accomplish? There are clean, simple solutions that will work well for toy applications, but bigger apps are going to need something more sophisticated.
How to handle door is_blocked presents some design issues. There is no one right design, but there are good design and bad designs. Separating the good ideas from the bad ideas depends on more than just design principles-- it depends on the context of the problem.
If I had to take a guess, I'd guess that your application is a game. Maybe the tiles represent the area of the game board or map. You have identified that many different objects might have to interact and that it would be mess if they all referenced each other directly.
Games often have a master object called "Game" or "Board" or "Map". Let the master object hold the collection of things in the Tile hierarchy (tiles, doors, etc).
Let the master object also hold the collection of things that can block doors or otherwise interact with tiles and doors.
Now create a method named update() on the Tile class that accepts an object as a parameter.
And create a boolean attribute for the Door class called "blocked".
The update method for the Door might do something like this:
Door::update(BlockingObject object) {
if(object.location == this.location)
blocked = true
}
The method on the superclass of door might do nothing. Like this:Tile::update(BlockingObject obj) {
//tiles cannot be blocked
}
Now, inside the game loop, include a step where all the doors are set to blocked = false.
The create some loops ask all of the tiles to check if they are blocked. It might look something like this in pseudo code:
For each tile {
For each blocking object {
tile.update(object)
}
}
This is a naive, but straight forward design that holds true to the OO paradigm.
The design gives tiles/doors and objects a chance to interact once per turn, without forcing them to hold references to one another.
The design will work fine for a few hundred tiles and objects, but it would become very slow for thousands of tiles.
Is it a good design?
The answer depends on the needs of the application.

What is the point of defining Access Modifiers?

I understand the differences between them (at least in C#). I know the effects they have on the elements to which they are assigned. What I don't understand is why it is important to implement them - why not have everything Public?
The material I read on the subject usually goes on about how classes and methods shouldn't have unnecessary access to others, but I've yet to come across an example of why/how that would be a bad thing. It seems like a security thing, but I'm the programmer; I create the methods and define what they will (or will not) do. Why would I spend all the effort to write a function which tried to change a variable it shouldn't, or tried to read information in another class, if that would be bad?
I apologize if this is a dumb question. It's just something I ran into on the first articles I ever read on OOP, and I've never felt like it really clicked.
I'm the programmer is a correct assumption only if you're the only programmer.
In many cases, other programmers work with the first programmer's code. They use it in ways he didn't intend by fiddling with the values of fields they shouldn't, and they create a hack that works, but breaks when the producer of the original code changes it.
OOP is about creating libraries with well-defined contracts. If all your variables are public and accessible to others, then the "contract" theoretically includes every field in the object (and its sub-objects), so it becomes much harder to build a new, different implementation that still honors the original contract.
Also, the more "moving parts" of your object are exposed, the easier it is for a user of your class to manipulate it incorrectly.
You probably don't need this, but here's an example I consider amusing:
Say you sell a car with no hood over the engine compartment. Come nighttime, the driver turns on the lights. He gets to his destination, gets out of the car and then remembers he left the light on. He's too lazy to unlock the car's door, so he pulls the wire to the lights out from where it's attached to the battery. This works fine - the light is out. However, because he didn't use the intended mechanism, he finds himself with a problem next time he's driving in the dark.
Living in the USA (go ahead, downvote me!), he refuses to take responsibility for his incorrect use of the car's innards, and sues you, the manufacturer for creating a product that's unsafe to drive in the dark because the lights can't be reliably turned on after having been turned off.
This is why all cars have hoods over their engine compartments :)
A more serious example: You create a Fraction class, with a numerator and denominator field and a bunch of methods to manipulate fractions. Your constructor doesn't let its caller create a fraction with a 0 denominator, but since your fields are public, it's easy for a user to set the denominator of an existing (valid) fraction to 0, and hilarity ensues.
First, nothing in the language forces you to use access modifiers - you are free to make everything public in your class if you wish. However, there are some compelling reasons for using them. Here's my perspective.
Hiding the internals of how your class operates allows you to protect that class from unintended uses. While you may be the creator of the class, in many cases you will not be the only consumer - or even maintainer. Hiding internal state protects the class for people who may not understand its workings as well as you. Making everything public creates the temptation to "tweak" the internal state or internal behavior when the class isn't acting the way you may want - rather than actually correcting the public interface of internal implementation. This is the road to ruin.
Hiding internals helps to de-clutter the namespace, and allows tools like Intellisense to display only the relevant and meaningful methods/properties/fields. Don't discount tools like Intellisense - they are a powerful means for developers to quickly identify what they can do with your class.
Hiding internals allows you to structure an interface appropriate for the problem the class is solving. Exposing all of the internals (which often substantially outnumber the exposed interface) makes it hard to later understand what the class is trying to solve.
Hiding internals allows you to focus your testing on the appropriate portion - the public interface. When all methods/properties of a class are public, the number of permutations you must potentially test increases significantly - since any particular call path becomes possible.
Hiding internals helps you control (enforce) the call paths through your class. This makes it easier to ensure that your consumers understand what your class can be asked to do - and when. Typically, there are only a few paths through your code that are meaningful and useful. Allowing a consumer to take any path makes it more likely that they will not get meaningful results - and will interpret that as your code being buggy. Limiting how your consumers can use your class actually frees them to use it correctly.
Hiding the internal implementation frees you to change it with the knowledge that it will not adversely impact consumers of your class - so long as your public interface remains unchanged. If you decide to use a dictionary rather than a list internally - no one should care. But if you made all the internals of your class available, someone could write code that depends on the fact that your internally use a list. Imagine having to change all of the consumers when you want to change such choices about your implementation. The golden rule is: consumers of a class should not care how the class does what it does.
It is primarily a hiding and sharing thing. You may produce and use all your own code, but other people provide libraries, etc. to be used more widely.
Making things non-public allows you to explicitly define the external interface of your class. The non-public stuff is not part of the external interface, which means you can change anything you want internally without affecting anyone using the external interface,
You only want to expose the API and keep everything else hidden. Why?
Ok lets assume you want to make an awesome Matrix library so you make
class Matrix {
public Object[][] data //data your matrix storages
...
public Object[] getRow()
}
By default any other programmer that use your library will want to maximize the speed of his program by tapping into the underlying structure.
//Someone else's function
Object one() {data[0][0]}
Now, you discover that using list to emulate the matrix will increase performance so you change data from
Object[][] data => Object[] data
causes Object one() to break. In other words by changing your implementation you broke backward compatibility :-(
By encapsulating you divide internal implementation from external interface (achieved with a private modifier).
That way you can change implementation as much as possible without breaking backward compatibility :D Profit!!!
Of course if you are the only programmer that is ever going to modify or use that class you might as well as keep it public.
Note: There are other major benefits for encapsulating your stuff, this is just one of many. See Encapsulation for more details
I think the best reason for this is to provide layers of abstraction on your code.
As your application grows, you will need to have your objects interacting with other objects. Having publicly modifiable fields makes it harder to wrap your head around your entire application.
Limiting what you make public on your classes makes it easier to abstract your design so you can understand each layer of your code.
For some classes, it may seem ridiculous to have private members, with a bunch of methods that just set and get those values. The reason for it is that let's say you have a class where the members are public and directly accessible:
class A
{
public int i;
....
}
And now you go on using that in a bunch of code you wrote. Now after writing a bunch of code that directly accesses i and now you realize that i should have some constraints on it, like i should always be >= 0 and less than 100 (for argument's sake).
Now, you could go through all of your code where you used i and check for this constraint, but you could just add a public setI method that would do it for you:
class A
{
private int i;
public int I
{
get {return i;}
set
{
if (value >= 0 && value < 100)
i = value;
else
throw some exception...
}
}
}
This hides all of that error checking. While the example is trite, situations like these come up quite often.
It is not related to security at all.
Access modifers and scope are all about structure, layers, organization, and communication.
If you are the only programmer, it is probably fine until you have so much code even you can't remember. At that point, it's just like a team environment - the access modifiers and the structure of the code guide you to stay within the architecture.

Any sucess using UI-based program structuring?

Have you ever structured your source code based on your user interface parts? For example if your UI consists of:
GridView for showing some properties
3D rendering panel
panel for choosing active tools
, then you name and group your variables and functions more or less in the following way:
class Application
{
string PropertiesPanel_dataFile;
DataSet PropertiesPanel_dataSet;
string[] PropertiesPanel_dataIdColumn;
void PropertiesPanel_OpenXml();
void PropertiesPanel_UpdateGridView();
string ThreeDView_modelFile;
Panel ThreeDView_panel;
PointF[] ThreeDView_objectLocations;
void ThreeDView_RenderView();
string ToolPanel_configurationFile;
Button[] ToolPanel_buttons;
void ToolPanel_CreateButtons();
}
What's your opinions on this? Can this architecture work in long run?
PS. Even though this solution might remind you of Front-ahead-design april-fool's joke http://thedailywtf.com/Articles/FrontAhead-Design.aspx my question is serious one.
EDIT
Have been maintaining and extending this kind of code for half a year now. Application has grown to over 3000 lines in the main .cs file, and about 2000 lines spread out in to smaller files (that contain generic-purpose helper-functions and classes). There are many parts of the code that should be generalized and taken out of the main file, and I'm constantly working on that, but in the end it doesn't really matter. The structure and subdivision of the code is so simple, that it's really easy to navigate though it. Since the UI contains less than 7 major components, there's no problem in fitting the whole design in you head at once. It's always pleasant to return to this code (after some break) and know immediately where to start from.
I guess one the reasons this gigantic procedural-like structure works in my case is the event-like nature of UI programming in c#. For the most part all this code does is implementation of different kinds of events, that are really specific to this project. Even though some event-functions immediately grow into couple of pages long monsters, coupling between event-handlers is not that tight, so it makes it easier to refactor and compress them afterwards. That's why Iam intentionally leaving generalization and refactoring for later time, when other projects start to require the same parts of implementation that this project uses.
PS to make it possible to navigate through 3000 lines of code I'm using FindNextSelection- and FindPrevSelection-macros in visual studio. After left-clicking on some variable I'm pressing F4 to jump to the next instance of it, and F2 to the previous instance. It's also possible to select some part of variable name and jump between partial-name matches. Without these shortcuts I would most defenetly lost my way long time ago :)
That looks very procedural in concept and is completely bypassing the value of OOD. The sensible approach would be to create objects for each of your elements and the values you have given would be properties of those objects, i.e.
class PropertiesPanel
{
public string DataFile { get; set; }
public DataSet DataSet { get; set; }
public string[] DataIDColumn { get; set; }
etc...
I think you get the idea so I'm not going to type the whole lot out. That's a first stage and there may be further work you could do to structure your application appropriately.
The best advice I ever received for OOD was to look to the smallest object that each logical branch of your app can be distilled to, it probably on has native types for properties (with .NET there no point in reinventing Framework objects either so they can be in your base class) and then using inheritance, polymorphism and encapsulation to expand on those base classes until you have an object that encapsulates the logical branch.
At the time I was writing an app that pushed data to an I2C device so I started with a class that put a bit onto an I2C bus, that was inherited by a class that put a byte onto a bus, inherited by a class that put an array of bytes onto the bus, and finally a class that put an address and an array of bytes. This is rather extreme OOD but it produced very clean code with each class being very small and very easy to debug.
It's possibly more work up front in thinking about the problem but in the long run it save soooooo much time it's just not funny.
It's OK to structure your user interface code based on your UI parts, but the non-UI related logic of your program should be kept separate.
But event on the UI part you shouldn't just smash everything into one class. Instead you should divide your UI code into several classes, so that every class only deals with one UI component and doesn't deal with others it doesn't need to know about:
class Application
{
PropertiesPanel
ThreeDView
ToolPanel
}
class PropertiesPanel {
string dataFile;
DataSet dataSet;
string[] dataIdColumn;
void OpenXml();
void UpdateGridView();
}
class ThreeDView {
string modelFile;
Panel panel;
PointF[] objectLocations;
void RenderView();
}
class ToolPanel {
string configurationFile;
Button[] buttons;
void CreateButtons();
}
What's your opinions on this?
It’s a mess.
Can this architecture work in long
run?
No. (At least not without a lot of sweat.)
The names are insanely verbose. If you think about it, the long name prefixes are there to create a kind of separate ‘namespace’, to group related things together. There already is a better language construct for this very kind of thing – it’s classes. But the main problem is elsewhere.
User interfaces change often, concepts change seldom. If your code structure mirrors the user interface, you are locked to this particular interface. This makes reusing and refactoring the code quite hard. If you structure the code around the base concepts from the problem domain, you have a better chance to reuse already existing code as the software develops – the design will adapt to changes. And changes always happen in software.
(I hope that the ‘base concepts from the problem domain’ part is clear. For example, if you create a system for a local theater, you should base your design on the concepts of a Movie, Visitor, Seat, and so on, instead of structuring it around MovieList, SeatMap, TheaterPlan and such.)
Most of the time it is a good idea to decouple the core code from the GUI as much as possible (This is exactly what the Model–View–Controller design system is all about.) It is not an academic excercise, nor it is only required if the interface is going to change. A great example of decoupling the GUI from the rest of the code is the GUI programming on Mac OS X, with the Interface Designer, bindings and such. Unfortunately it takes a while to get into, you cannot simply skim the docs on the web and be enlightened.

When do you stop encapsulating?

I have some event handler on a boundary class that manages a persistence mechanism for a given generic transaction:
void MyBoundaryClass::MyEventHandler(...)
{
//retrieve stuff from the UI
//...
//declare and initialize trasaction to persist
SimpleTransaction myTransaction(.../*pass down stuff*/);
//do some other checks
//...
//declare transaction persistor
TransactionPersistor myPersistor(myTransaction, .../*pass down connection to DB and other stuff*/);
//persist transaction
try
{
myPersistor.Persist();
}
catch(...)
{
//handle errors
}
}
Would it be better to have some kind of TransactionManager to wrap SimpleTransaction and TransactionPErsistor objects?
Is there any useful rule of thumb to understand if I need a further level of encapsulation?
At the moment the rule of thumb I follow is "if the method gets too big - do something about it". It is hard sometimes to find the right balance between procedural and object oriented when dealing with boundary event handlers.
Any opinion?
Cheers
Considering that:
the concept of encapsulation is about defining a container, and
object-oriented design is based on the concept of message passing (invocation of methods)
I would argue that the API is a good indication about the pertinence of a new high-level encapsulation (I.e. the definition of a new object)
If the services (i.e the API) offered by this new object are coherent, and are better exposed to the rest of the program when regrouped in one special object, then by all means, use a new object.
Otherwise, it is probable an overkill.
Since you expose a public API by creating a new object, the notion of test may be easier to do within that new object (and a few other mock objects), rather than create many legacy objects in order to test those same operations.
In your case, if you want to test the transaction, you must actually test MyEventHandler of MyBoundaryClass, in order to retrieve data from the UI.
But if you define a TransactionManager, that gives you the opportunity to lower coupling of different architecture levels (GUI vs. data) present in MyBoundaryClass, and to export data management into a dedicated class.
Then, you can test data persistence in independent test scenario, focusing especially on limit values, and database failure, and not-nominal conditions, and so on.
Testing scenario can help you refine the cohesion (great point mentioned by Daok) of your different objects. If your tests are simple and coherent, chances are that your objects have a well-define service boundary.
Since it can be argued that Coupling and Cohesion are two cornerstones of OO Programming, the cohesion of a new class like TransactionManager can be evaluated in term of the set of actions it will perform.
Cohesive means that a certain class performs a set of closely related actions. A lack of cohesion, on the other hand, means that a class is performing several unrelated tasks. [...] the application software will eventually become unmanageable as more and more behaviors become scattered and end up in wrong places.
If you regroup behaviors otherwise implemented in several different places into your TransactionManager, it should be fine, provided that its public API represent clear steps of what a transaction involves and not "stuff about transaction" like various utility functions. A name in itself is not enough to judge the cohesiveness of a class. The combination of the name and its public API is needed.
For instance, one interesting aspect of a TransactionManager would be to completely encapsulate the notion of Transaction, which would :
become virtually unkown by the rest f the system, and would lower coupling between the other classes and 'Transaction'
reinforce the cohesiveness of TransactionManager by centering its API around transaction steps (like initTransaction(), persistTransaction(), ...), avoiding any getter or setter for any Transaction instance.
Elaborating on VonC's suggestion, consider the following guidelines:
If you expect to invoke the same functions elsewhere, in the same way, it's reasonable to encapsulate them in a new object.
If one function (or one object) provides a set of facilities that are useful individually, it's reasonable to refactor it into smaller components.
VonC's point about the API is an excellent litmus test: create effective interfaces, and the objects often become apparent.
The level of encapsulating should be directly linked to the cohesion of your object. Your object must do a single task or must be divided in multiple class and encapsulate all its behaviors and properties.
A rule of thumb is when it's time to test your object. If you are doing Unit Testing and you realize that you are testing multiple different thing (not in the same area action) than you might try to split it up.
For you case, I would encapsulate with your idea of "TransactionManager". This way the "TransactionManager" will handle how transaction works and not "MyBoundaryClass".