DEV Community

Cover image for Abstraction in OOP: Hiding Complexity Without Hiding Capability
Ashay Tiwari
Ashay Tiwari

Posted on

Abstraction in OOP: Hiding Complexity Without Hiding Capability

In the previous article, we discussed Encapsulation and how objects should control changes to their own state.

Now let's talk about another fundamental concept of Object-Oriented Programming: Abstraction.

Like always, let's start with a problem.


The Problem

Imagine you own a car.

To drive it, you do a few simple things:

  • Start the engine.
  • Press the accelerator.
  • Apply the brakes.
  • Turn the steering wheel.

You don't need to know:

  • How fuel is injected into the engine.
  • How the pistons move.
  • How the gearbox changes gears.
  • How combustion generates power.

All that complexity is hidden from you.

You simply interact with a straightforward interface.

Software systems work in a very similar way.


A Real-World Example

Suppose we need to send an email.

The application code might look like this:

emailService.send({
  to: "john@example.com",
  subject: "Welcome!",
  body: "Hello John"
});
Enter fullscreen mode Exit fullscreen mode

Looks simple.

But what actually happens behind the scenes?

Potentially a lot:

  • Validate the email address.
  • Create an SMTP connection.
  • Authenticate with the provider.
  • Build the message.
  • Retry if sending fails.
  • Log failures.
  • Close the connection.

As consumers of email service, we don't care about those details.

We only care that:

If I call send(), the email should be sent.

This is exactly the problem Abstraction tries to solve.


The Problem with Exposing Everything

Imagine if sending an email required every caller to do this:

connect();
authenticate();
buildMessage();
sendMessage();
disconnect();
Enter fullscreen mode Exit fullscreen mode

Every single time.

Suddenly:

  • Every consumer knows too much.
  • Every consumer is responsible for the implementation.
  • Changing the implementation becomes painful.

What if we switch from SMTP to a third-party email provider?

Now every place that sends emails needs to change.

The consumers have become tightly coupled to implementation details.


The Idea Behind Abstraction

Abstraction is about exposing what an object can do while hiding how it does it.

Instead of exposing every implementation detail, we expose only what consumers need.

For example:

emailService.send(email);
Enter fullscreen mode Exit fullscreen mode

The caller doesn't need to know:

  • Which provider we're using.
  • How authentication works.
  • How retries are handled.
  • How messages are constructed.

Those details remain hidden.

Consumers interact with a simple and stable interface.

Abstraction Is Not the Same as Encapsulation

These two concepts are often confused.

Encapsulation asks:

Who should be allowed to change the object's state?

Abstraction asks:

What details should consumers be aware of?

Encapsulation protects data.

Abstraction hides unnecessary complexity.

They often work together, but they solve different problems.


What's Next?

So far, we've discussed:

  • How objects protect their state using Encapsulation.
  • How objects hide complexity using Abstraction.

Next, we'll look at another question developers faced:

If multiple objects share similar behavior, do we really need to write that code repeatedly?

This leads us to one of the most well-known—and sometimes controversial—concepts in OOP:

Inheritance.

Top comments (0)