Upskill tutorial for bridge patterns

Hud Wahab
4 min readJul 30, 2023

--

Day 29: Protocol. Callable. property.

Hi 👋 I am Hud, a postdoc for engineering data science at the AI Manufacturing Center in Laramie, Wyoming. My funding is running out (AaAaaA !), so while I am actively looking for a new job, instead of doing the 205th coding certificate to prove my worthiness — I thought I’d do design challenges and document how I spend my time upskilling so other engineers can do the same.

Nowadays, certificates are everywhere. Documenting small upskill projects that you can later show off is the best way to get recognition as a professional engineer.

This is day 29 of a 30-day design challenge. Follow along and let me know if you get stuck!

TL;DR tasks

Download the provided code for the challenge.

Task 1: Implement the Bridge design pattern

  • Create an abstraction for the media items and the views using separate interfaces or abstract classes.
  • Refactor the existing code to use the interfaces/abstract classes for media items and views instead of directly calling the view function.

Task 2: Create concrete implementations

  • Implement concrete classes for different types of media items (e.g., Movie, Series, Documentary) that inherit from the media item interface/abstract class.
  • Implement concrete classes for different types of views (e.g., FullView, Preview, Teaser) that inherit from the view interface/abstract class.

Task 3: Connect media items with views using the Bridge pattern

  • Update the media item classes to hold a reference to a view object, allowing them to delegate the view functionality to the view object.
  • Update the view classes to interact with the media item objects through the view interface/abstract class.

Task 4: Test adding a Documentary media item

  • Add a new media item class for Documentary and test that it integrates seamlessly with the existing view functionality without needing changes to the view code.

Task 5: Test adding a “teaser” view

  • Add a new view class for Teaser that displays only the first 10 characters of the description text and test that it integrates smoothly with all existing media item classes without needing changes to their code.

Task 6: Validate that the Bridge pattern works

  • Run the application with the added Documentary media item and “teaser” view to ensure that the Bridge pattern successfully decouples media items and views, allowing for easy addition of new types without affecting existing code.

The problem

I’d like to think that the code follows a good design principle — I am using polymorphism to handle different types of objects — that’s good enough right? Well, it seems there is some mixing of concerns in printing and formatting the output with the logic of selecting which information to display based on the view_type parameter. This means that if we wanted to add a new view_type or a new type of item, we would need to modify the existing view function, which violates the Open-Closed Principle of SOLID design. What can we do?

The solution

This is where the bridge pattern comes to the rescue! But how does that look like — we turn back to using the Protocol class, as we’ve done many times in past challenges (see challenges here, here , here or here)— I dont know .. maybe I am an abstraction junkie. If we see the contents of the view function above, we see that only three outputs: heading, subheading, and text. This is how we break these down:

In the code we define a set of attributes that a class must implement in order to be considered a MediaItem. This allows us to define a common interface for different types of media items, such as Movie and Series, without having to use inheritance.

By using a Protocol, we can ensure that any class that implements the required attributes can be treated as a MediaItem, regardless of its inheritance hierarchy. This makes the code more flexible and easier to maintain, as we can add new types of MediaItems without having to modify the existing code.

Next, we could’ve used a class object for MediaView, but again, since it’s just doing a single function, let’s just use some functionals with Callable. Then, we just break the large view function into smaller functions with single responsibilities.

Finally, that’s how we implement the bridge pattern. But to really test that it works — we’ll add a new view type and see the output:

# without view_teaser
Spirited Away
Spirited Away
Hayao Miyazaki
Spirited Away
Hayao Miyazaki
Chihiro ...
Fullmetal Alchemist: Brotherhood
Fullmetal Alchemist: Brotherhood
64 episodes
Fullmetal Alchemist: Brotherhood
64 episodes
Edward ...

# with view_teaser
Spirited Away
Spirited Away
Hayao Miyazaki
Spirited Away
Hayao Miyazaki
Chihiro ...
Spirited Away
Chihiro .....
Fullmetal Alchemist: Brotherhood
Fullmetal Alchemist: Brotherhood
64 episodes
Fullmetal Alchemist: Brotherhood
64 episodes
Edward ...
Fullmetal Alchemist: Brotherhood
Edward ......

Conclusion

Congratulations! You finished Day 29 from the 30-day design challenge.

If you have reached this far, you know how to:

  • Use the bridge pattern

We’re finally THERE! Check out the FINAL challenge as we obliterate multiple inheritances!

Also, you can access the full 30-day GitHub repository here.

💡 My goal here is to help engineering data scientists upskill in design. I’d like to hear from you! Was this helpful? Anything I can improve? Connect with me on LinkedIn | Medium

--

--

Hud Wahab

🤖 Senior ML Engineer | Helping machine learning engineers design and productionize ML systems. | Let's connect: https://rb.gy/vb6au