Object oriented design principle Abstraction - oop

While reading about abstraction, I came across the following statement
"Abstraction captures only those details about an object that are relevant to the current perspective"
For eg.
From the driver's perspective, Car class would be
public class Car
{
void start();
void applybrakes();
void changegear();
void stop();
}
From the mechanic's perspective, Car class would be
public class Car
{
void changeOil();
void adjustBrakes();
}
My question,
While designing a system, do we design for one user perspective(either driver or mechanic) or can
we design for multiple user perspective and further abstract out based on user type?
Hope my question is clear.
Thanks

Depending on your use case you might need to deign for multiple users. In your example, if your car will be used by both the mechanic and the driver, then you cannot just ignore one set of users. In that case, you can still abstract details by using Interfaces.
You could design your object like this:
interface IDrivable {
void start();
void applyBrakes();
void changeGear();
void stop();
}
interface IFixable {
void changeOil();
void adjustBrakes();
}
public class Car : IDrivable, IFixable {
// implement all the methods here
}
Now, when a mechanic wants the car, you don't give him a Car object, instead give him an IFixable object. Similarly, the driver gets an IDrivable object. This keeps the relevant abstraction for both sets of users simultaneously.
class Driver {
private IDrivable car;
public Driver(IDrivable car) {
this.car = car;
}
public driveCar() {
this.car.start();
this.car.accelerate();
//this is invalid because a driver should not be able to do this
this.car.changeOil();
}
}
Similary, a mechanic won't have access to the methods in the interface IDrivable.
You can read more about interfaces here. Even though this is the MSDN link and uses C#, all major languages support interfaces.

I think you may be inferring too much from "perspective." I wouldn't take perspective here to mean a person or user so much as a vantage point. The idea of a view here is maybe not even a good metaphor. What we're really talking about here is division of responsibility between the smaller objects that we use to compose the larger objects.
The whole point of this idea is decoupling and modularity. You want objects that you can pull out and replace without changing everything around them. So you want your objects to be coherent, for their methods and variables to be closely related.
You might be able to get some mileage from the user metaphor in terms of the interface-client relationship between objects.

Related

Why does an object's type refer to its interface? (Design Patterns: Elements of Reusable Object-Oriented Software book)

Why does object's type refer to its interface? Why the term type is used here? In terms of C++ I am not able to understand it.
Gamma, Erich. Design Patterns: Elements of Reusable Object-Oriented
Software (Addison-Wesley Professional Computing Series) (Kindle
Locations 593-596). Pearson Education. Kindle Edition.
An object’s class defines how the object is implemented. The class
defines the object’s internal state and the implementation of its
operations. In contrast, an object’s type only refers to its
interface—the set of requests to which it can respond. An object can
have many types, and objects of different classes can have the same
type.
An oversimplification...
Interface - a list of things that a class have and the things that it can do... a list of things that answer the "Whats"
Implementation - answers the question on "How" the "Whats" are accomplished.
Example:
An interface IPackageMover that does 2 things and 2 classes (types) that actually implements the interface (and also do other things aside from the interface requires)
// the interface
public interface IPackageMover
{
string GetName();
void public void MoveTo(Package package, string newAddress);
}
// the "type" that has the implementation
public class JoeThePackageMover : IPackageMover
{
public string GetName()
{
return "Joe";
}
public void MoveTo(Package package, string newAddress)
{
PickUp(package);
Drive(newAddress);
DropOff(package);
}
public void PickUp(Package package)
{
// do stuff
}
public void Drive(string newAddress)
{
// do stuff
}
public void DropOff(Package package)
{
// do stuff
}
}
// another "type" with the same interface
public class PassTheBuckPackageMover : IPackageMover
{
public string GetName()
{
return "What do you want it to be?";
}
public void MoveTo(Package package, string newAddress)
{
var joe = new JoeThePackageMover();
joe.MoveTo(package, newAddress);
}
public void Chill()
{
//do stuff
}
}
Why does object's type refer to its interface? Why the term type is used here? In terms of C++ I am not able to understand it.
Objects in OOP are not very different from the real world. For example :
A Car IS-A Vehicle. By this definition, a Car has the ability to transport people/cargo from one place to another.
A Car is also a Car. By this definition, it has the ability to be driven using a steering wheel.
In the above example, a Car IS-A Car and a Car is also a Vehicle because it can be driven using a steering wheel to move cargo/people from one place to another. In other words, the type of an object in the real world is defined by the things you can do with it (vis-à-vis it's interface.)
If we use the above analogy in programming, Car is a subclass of Vehicle and code that has a Car object can use all functions from Vehicle as well as Car. This would mean that a Car IS-A Vehicle and a Car. In conclusion, the type of object is defined by its interface, i.e the set of operations it supports.

Different interpretation of internal state based on what client wants

A Model object which has some private internal state. A component of this state is exposed to the clients. But one of the clients wants a different component of the internal state to be exposed. How should this be dealt with?An example
public GarageModel {
private Vehicle car;
private Vehicle truck;
public Vehicle getMostInterestingVehicle() {
//exposes car as the most interesting vehicle but
//one of the client wants this to return a truck
return car;
}
}
It is hard to say given your sample, you could apply a strategy pattern on your GarageModel class for each different client and override that single method to cater to each of their needs. This only works if you can provide different garage models to your clients though.
Polymorphism is always the answer as a teacher of mine used to say
An example would be
public TruckGarageModel: GarageModel {
public override Vehicle getMostInterestingVehicle(){
return truck;
}
}
public CarGarageModel: GarageModel {
public override Vehicle getMostInterestingVehicle(){
return car;
}
}
Then you would pass the appropriate decorated version of your GarageModel to each different client
You could provide method with parameters which will define criteria by which your client sees most interesting vehicle.
public Vehicle getMostInterestingVehicleByCriteria(VehicleCriteria vehicleCriteria){
// logic which selects correct vehicle in simple way it will be just
if(vehicleCriteria.getMostInterestingVehicleType().equals(VehicleType.TRUCK){
//do your logic
}
// In case of multiple objects you should refactor it with simple inheritance/polymorphism or maybe use some structural pattern
}
public class VehicleCriteria{
VehicleType mostInterestingVehicle; // enum with desired vehicle type
public VehicleCriteria(VehicleType mostInterestingVehicle){
this.mostInterestingVehicle = mostInterestingVehicle;
}
}
If the client knows what type it wants, then let the client say so with a generic argument (C# assumed):
public T getMostInterestingVehicle<T>() where T : Vehicle { }
You can then use a dictionary of 'things' (factories maybe?) that will get a vehicle, keyed by the type they return. This could be a static collection created on construction or resolved by IoC:
private Dictionary<T, Vehicle> _things;
You can then use this to do the work:
public T getMostInterestingVehicle<T>() where T : Vehicle
{
FactoryThing thing;
if (_things.TryGetValue(T, out thing))
{
return thing.GetVehicle();
}
}
Apologies if it's not C# you're working with and if the syntax/usage is incorrect, but I think you'll get my point...
You might have to consider quite a few things before making a decision about the implementation, some questions are these-
Do you expect newer implementations of Vehicle to be added later?: If yes, you might have to provide a factory that could register newer types without you making changes in the factory again and again. This provides an example. That way you avoid many if-else as well.
Do you want to decide what Vehicle to return at runtime?: Then Strategy Pattern helps as pointed in other answers.
Hope this helps a little bit.

Real Life example of Polymorphism from Class Room

Once my teacher asked me to give example of polymorphism from class room.
I told him that you are best example of polymorphism. As in college you are a teacher and in home you are husband or father. So your are one method but in different states you are behaving accordingly. And also you are extending human so you can be treated polymorphically as human.
(Considering in mind definition of polymorphism: Acquiring more than one form)
Can it be consider as good example of polymorphism ?
Thanks.
In your example, you give different behaviours for different states.
In OOP this is expressed through interfaces.
So, it would be modelled something like this:
class Human
{
Date Birthdate;
}
interface ITeacher
{
void Teach();
}
interface IHusband
{
void Pray();
}
interface IFather
{
void Love(); // methods in IFather and IHusband can be interchanged
}
class Person extends Human implements ITeacher, IHusband, IFather
{
// implementations inserted here
}
Now you can use those behaviours and the fact that he is a human in different cases.
Like:
Human yourTeacher = new Human("1970/05/01");
Class class = new Class();
class.Teachers.Add(yourTeacher); // expecting that it is a collection of ITeachers.
Pub pub = new Pub();
pub.DrunkPeople.Add(yourTeacher); // accepting only humans older than 21 here
So, polymorphism is about ONE object that behaves different in different cases... and inheritance.

How do you implement type-specific functionality when using polymorphism does NOT make sense?

A common red flag that an OOP language is not being leveraged properly looks like this:
if (typeof(x) == T1)
{
DoSomethingWithT1(x);
}
else if (typeof(x) == T2)
{
DoSomethingWithT2(x);
}
The standard "fix" for such design issues is to make T1 and T2 both share an interface, either through inheritance of a base type or implementation of a common interface (in languages that support it); for example, in C# a solution might be:
public interface IT
{
void DoSomething();
}
However, sometimes you want to implement functionality that differs based on the type of an object but that functionality does not belong within that object's type; thus polymorphism seems the wrong way to go.
For example, consider the case of a UI that provides a view of a given clump of data. Supposing this view is capable of rendering various layouts and controls depending on the type of data being presented, how would you implement this type-specific rendering without a bunch of if/else statements?
For reasons that I hope are obvious, putting the rendering logic in the type itself strikes me as a very bad decision in this case. On the other hand, without coupling the type of data object to its visual presentation I have a hard time seeing how the if/else scenario is avoided.
Here's a concrete example: I work on a trading application which utilizes many different pricing models for various market products. These different models are represented by types inheriting from a common PricingModel base; and each type is associated with a completely different set of parameters. When the user wants to view the parameters for a particular pricing model (for a particular product), currently these are displayed by a form which detects the type of the model and displays an appropriate set of controls. My question is how this could be implemented more elegantly than it is currently (with a big if/else block).
I realize this probably seems like a very basic question; it's just one of those gaps in my knowledge (of solid OOP principles? design patterns? common sense?) that I figured it's about time to fix.
We are injecting (Spring.Net) such functionality into dictionaries by type.
IDictionary<Type, IBlahImplementor> blahImplementors;
blahImplementors[thingy.GetType()].Do(thingy);
This dictionary could be managed by a kind of repository which provides the functionality.
As an implementation detail, the implementor usually knows the type it depends on an can provide it itself:
interface IBlahImplementor
{
Type ForType { get; }
void Do(object thingy);
}
Then it is added to the dictionary like this:
IEnumerably<IBlahImplementor> blahImplementors;
foreach (var implementor in blahImplementors)
{
blahImplementors.Add(implementor.ForType, implementor);
}
Remark: IMHO, it is very important to understand that some things do NOT belong into a class, even if providing subtype-specific implementations would make life much easier.
Edit: Finally understood your concrete example.
It is actually about instancing the right UI control to show the pricing models parameters. It should be possible with the pattern I described above. If you don't have a single UI control for a pricing model, you either create it or you write a UI configurer or something like this which sets up the required controls.
interface IPricingModelUiConfigurer
{
Type PricingModelType { get; }
void SetupUi(Control parent, IPricingModel model);
}
you can use common interface approach as you describe and Command pattern to trigger methods with "functionality does not belong within that object's type". I think this won't break solid OOP principles.
What you described is pretty much exactly the use case for the Visitor Pattern.
EDIT: For your concrete example, you could apply the visitor pattern like this:
// interface used to add external functionality to pricing models
public interface PricingModelVisitor {
void visitPricingModel1(PricingModel1 m);
void visitPricingModel2(PricingModel2 m);
...
}
// your existing base-class, with added abstract accept() method to accept a visitor
public abstract class PricingModelBase {
public abstract void accept(PricingModelVisitor v);
...
}
// concrete implementations of the PricingModelBase implement accept() by calling the
// appropriate method on the visitor, passing themselves as the argument
public class PricingModel1 : PricingModelBase {
public void accept(PricingModelVisitor v) { v.visitPricingModel1(this); }
...
}
public class PricingModel2 : PricingModel {
public void accept(PricingModelVisitor v) { v.visitPricingModel2(this); }
...
}
// concrete implementation of the visitor interface, in this case with the new
// functionality of adding the appropriate controls to a parent control
public class ParameterGuiVisitor : PricingModelVisitor {
private Control _parent;
public ParameterGuiVisitor(Control parent) { _parent = parent; }
visitPricingModel1(PricingModel1 m) {
// add controls to _parent for PricingModel1
}
visitPricingModel2(PricingModel2 m) {
// add controls to _parent for PricingModel1
}
}
now, instead of using a big if-else block when you need to display the edit-controls for the parameters of a specific subtype of PricingModelVisitor, you can simply call
somePricingModel.accept(new ParameterGuiVisitor(parentControl))
and it will populate the appropriate GUI for you.

When is an "interface" useful?

OOP interfaces.
In my own experience I find interfaces very useful when it comes to design and implement multiple inter-operating modules with multiple developers. For example, if there are two developers, one working on backend and other on frontend (UI) then they can start working in parallel once they have interfaces finalized. Thus, if everyone follows the defined contract then the integration later becomes painless. And thats what interfaces precisely do - define the contract!
Basically it avoids this situation :
Interfaces are very useful when you need a class to operate on generic methods implemented by subclasses.
public class Person
{
public void Eat(IFruit fruit)
{
Console.WriteLine("The {0} is delicious!",fruit.Name);
}
}
public interface IFruit
{
string Name { get; }
}
public class Apple : IFruit
{
public string Name
{
get { return "Apple"; }
}
}
public class Strawberry : IFruit
{
public string Name
{
get { return "Strawberry"; }
}
}
Interfaces are very useful, in case of multiple inheritance.
An Interface totally abstracts away the implementation knowledge from the client.
It allows us to change their behavior dynamically. This means how it will act depends on dynamic specialization (or substitution).
It prevents the client from being broken if the developer made some changes
to implementation or added new specialization/implementation.
It gives an open way to extend an implementation.
Programming language (C#, java )
These languages do not support multiple inheritance from classes, however, they do support multiple inheritance from interfaces; this is yet another advantage of an interface.
Basically Interfaces allow a Program to change the Implementation without having to tell all clients that they now need a "Bar" Object instead of a "Foo" Object. It tells the users of this class what it does, not what it is.
Example:
A Method you wrote wants to loop through the values given to it. Now there are several things you can iterate over, like Lists, Arrays and Collections.
Without Interfaces you would have to write:
public class Foo<T>
{
public void DoSomething(T items[])
{
}
public void DoSomething(List<T> items)
{
}
public void DoSomething(SomeCollectionType<T> items)
{
}
}
And for every new iteratable type you'd have to add another method or the user of your class would have to cast his data. For example with this solution if he has a Collection of FooCollectionType he has to cast it to an Array, List or SomeOtherCollectionType.
With interfaces you only need:
public class Foo<T>
{
public void DoSomething(IEnumerable<T> items)
{
}
}
This means your class only has to know that, whatever the user passes to it can be iterated over. If the user changes his SomeCollectionType to AnotherCollectionType he neither has to cast nor change your class.
Take note that abstract base classes allow for the same sort of abstraction but have some slight differences in usage.