🎙 Develpreneur Podcast Episode

Audio + transcript

The Bridge Pattern

This episode discusses the bridge pattern, a design pattern that decouples an abstraction from its implementation. It's a conceptual class that ties a couple of implementation approaches together, allowing the interface to stay very thin.

2024-10-05 •Design Patterns •Podcast

Summary

This episode discusses the bridge pattern, a design pattern that decouples an abstraction from its implementation. It's a conceptual class that ties a couple of implementation approaches together, allowing the interface to stay very thin.

Detailed Notes

The bridge pattern is a design pattern that allows for decoupling an abstraction from its implementation. This means that the interface and the implementation can vary independently, which is useful in a cross-platform world where you want to swap out some libraries and have things work fine. The bridge pattern is not like a code word or syntax that ties two things together, but rather a conceptual class that ties a couple of implementation approaches together. This allows the interface to stay very thin and the implementation to be where the rubber meets the road. The bridge pattern is useful in many situations, including when you want to enforce security by swapping out interfaces in different versions of a product. It's also a simple and easy-to-implement design pattern, making it a great choice for many developers. One of the key benefits of the bridge pattern is that it allows for flexibility and scalability. This means that you can easily swap out implementations without affecting the interface, which is useful in a cross-platform world. The bridge pattern is also a way to enforce security, by swapping out interfaces in different versions of a product.

Highlights

  • Decouple an abstraction from its implementation so that the two can vary independently.
  • The bridge pattern is not like a code word or syntax that ties two things together.
  • It's a conceptual class that ties a couple of implementation approaches together.
  • It allows the interface to be in the object-oriented world, it allows the interface to stay very thin.
  • The implementation is where the rubber meets the road.

Key Takeaways

  • The bridge pattern decouples an abstraction from its implementation.
  • It's a conceptual class that ties a couple of implementation approaches together.
  • It allows the interface to stay very thin and the implementation to be where the rubber meets the road.
  • It's useful in a cross-platform world where you want to swap out some libraries and have things work fine.
  • It's also a way to enforce security by swapping out interfaces in different versions of a product.

Practical Lessons

  • Use the bridge pattern to decouple an abstraction from its implementation.
  • Use a conceptual class to tie a couple of implementation approaches together.
  • Leave the interface thin and the implementation where the rubber meets the road.
  • Use the bridge pattern to enforce security by swapping out interfaces in different versions of a product.

Strong Lines

  • Decouple an abstraction from its implementation so that the two can vary independently.
  • The bridge pattern is not like a code word or syntax that ties two things together.
  • It's a conceptual class that ties a couple of implementation approaches together.

Blog Post Angles

  • The bridge pattern: a design pattern for decoupling abstraction from implementation.
  • The benefits of using the bridge pattern in software development.
  • How the bridge pattern can be used to enforce security in software development.
  • The practical applications of the bridge pattern in software development.
  • The limitations and challenges of using the bridge pattern in software development.

Keywords

  • Bridge pattern
  • Design pattern
  • Decoupling
  • Abstraction
  • Implementation
  • Flexibility
  • Scalability
  • Security
Transcript Text
This is Building Better Developers, the Develop-a-newer podcast. We will accomplish our goals through sharing experience, improving tech skills, increasing business knowledge, and embracing life. Let's dive into the next episode. And here we are again, continuing our jaunt through the software patterns, the design patterns from the Gang of Four book. And we're going to talk about the bridge pattern this time around. No, this is not a game that your grandparents played or something that you've got to burn occasionally or sometimes you've got to cross it when you get to it. This is a pattern that is essentially tying a couple of implementation, a couple of approaches together. And it's not as tightly defined. It's not really in the code. It's more of a conceptual class. So this was our design pattern. This is going to be a little different. This is the second of the structural patterns that we're going through. We talked about the adapter last week. This time around, we're going to talk about the bridge pattern, as I mentioned. And we'll jump right into our usual intent from the original Gang of Four book. Quote, decouple an abstraction from its implementation so that the two can vary independently, unquote. Well, decoupling abstraction from implementation actually very similar to something we hear now on a regular basis. And that is MVC, Model View Controller, or all of the variants of that now where there's like an MVVC and all of those others that are out there. But essentially we've learned, as we've seen with a lot of these other popular patterns, that you want to have that level of abstraction to allow you some flexibility, to allow you to write code without having to sort of design yourself into a corner. And that's exactly what the bridge pattern is for. It's not like you have a code word or syntax that says bridge that ties two things together. Instead, they're tied together because of your inheritance and of your implementation, your using of an interface. We see this actually quite a bit in the generators that are out there, like the object relational mapping generators that are out there. If you're looking at Spring and some of the standard practices in there, or Hibernate and some of those kinds of tools, what you'll often see is a data access object, a DAO, and then you'll see in DAO-IMPL, which is the data access object implementation, which is a bridge. You have the interface, the features, the methods that are implemented, and then separately you have something that implements that interface. The nice thing when you have this is that if you want to extend the interface, you can do so without touching the implementation. Or if you want to extend the implementation, you can do that without dealing with the interface. You have essentially two extension points from that one, I'd say object, but it's not like an object in a one conceptual object, not an object in the literal sense and the code sense, but an object as far as conceptually. You have the interface to it and then you have the implementation. And although those could be one thing, if it is one thing, then that means if you extend one, you have to extend the other. If you change one, you have to change the other. And it can cause some issues, particularly if you're running into a situation where you may have multiple implementations of the interface, because then what you'd end up doing is having to extend it and override it. Or you'd have to have an interface and you'd have to create all these implementations that are essentially again child objects. They're doing some extensions or doing a lot of overriding, and it becomes sort of confusing quickly in that kind of a hierarchy. So if you use a bridge pattern, then it's a lot easier to see directly what it is that your intent is when you extend either the interface or the implementation side of it. It's sort of when you're implementing it, when you're doing this in your code, if you've got a C or C++ background, you can think of it sort of in the way of a .h file versus a .c file or .hpp versus cpp. And there's some other languages that have that same concept. I believe Ada used to have it, I haven't seen it in a long time, but I think it had the same thing. We have a file and you have a place where you define the interface. Separately, you define the implementation. It allows the interface to be in this world, in the object-oriented world, it allows the interface to stay very thin. And of course, the key in the implementation is that the interface should not have any implementation in it. It should be an abstract interface. The implementation is where the rubber meets the road, as it were. And in doing so, we've actually seen this, how we would approach this more or less, a couple of times in the past, where you essentially have an interface out of the two classes that make the bridge. One is an interface and the other is a class that just happens to implement that interface. And then from there, you can extend, you can inherit from the implementer, or you can actually extend from an interface and go from there, giving you effectively a many, many, many-to-many relationship with your interfaces to your implementations. So if you've got something that you want to do a lot of switching around of how something is implemented, and maybe it's got a couple different interfaces, a lot of times you see this in graphical controls. If you go into a lot of the examples that I saw as looking into this one, points back to that. Because you've got to think about it, is that you have conceptually something that's roughly the same. If you go from, let's say, Mac to Windows to X Windows, if you're looking across those, that you have things that are conceptually roughly the same, like a button or a radio button or a drop-down, a text field. Obviously, the implementation is very different because you have a different set of information that you're working with. It's a different environment. So implementation is going to be different across those. But also the interface is going to be a little different because there's certain things that are not going to be supported, depending on what environment you're in. So you're going to actually have, and we see this also in the web a lot, where you have browsers that have certain things to implement, and sometimes they don't implement something, even if it's part of the W3C consortium, the W3C, which is very hard to say quickly, part of those standards. If you look out at just about any, especially the HTML5 tags, you'll see that they've got almost everywhere, as you're going to see, that's a good definition example site. You're going to see which browsers support it, and a lot of times you'll see at least a couple don't, or they have a partial support of this tag or this attribute. Well, that's roughly what you're dealing with with the bridge, is you're going to say, Okay, overall, I've got these couple of primary interfaces, and I've got a bunch of different implementations of them. As you keep all of it separate, you can, particularly in a cross-platform world, it actually works out really nice, because then you can swap out some libraries, and next thing you know, it's still functioning. It's something where you don't have to carry everything everywhere. You can change a couple things you link to, and the next thing you know, you've got it working fine because you've abstracted that implementation out of the interface, or maybe there's some interfaces you don't even need. As we've talked about before, it also is a way that you can actually enforce some security, because you could have a situation where you have a version that is the administrator user, or the professional version versus the free version, something like that. And you can actually swap out interfaces so things just wouldn't exist in the light version, but they are there in the fully implemented version. And when you apply it, the nice thing, a couple of them, actually several of them now that we've looked at, whether your language is Java or C-sharp or C++ or PHP or whatever, it's all going to be basically the same. Once again, you've got an interface. You have an interface available in all of those. The key is that in the languages where you are not forced to have an abstract interface, that you have an abstract interface. If you put code, if you implement anything in the interface, then basically you're not building a bridge. You're screwing it up because then that implementation has got to go everywhere. That suddenly has tied down that interface, which you don't want to, which honestly could lead to some of the arguments of why would you ever implement in an interface? And I'm sure there would be plenty of people that could give you some really good examples of doing so. We don't want to fight that battle right now. We'll just stick to talking about the bridge pattern. So this is one that you see probably fairly often. You see it implemented, I think. A lot of the libraries, a lot of the frameworks that I've dealt with over the years, the bridge concept is there. You can see that pattern used in a couple different places, particularly from a framework point of view, because what it does is it allows them to define everything up to that API or that interface wall. And then you can use your framework, but you can extend it pretty much wherever you need to. It gives you multiple ways to extend the framework to whatever your customizations or your needed use happens to be. If you're using a bridge and you're building just an application, not using framework, you're building your own internal application. You may not see as many reasons to use a bridge, particularly if you're on like a single platform in a single focus. You're not trying to build something that's going to scale to a lot of different platforms, a lot of different users, a lot of different integrations into other systems. But if you are, then you probably can find some use in using the bridge pattern. Now, it's not... I say that you see it a lot. I have not seen it properly utilized enough. I've seen a lot of cases where people go in, particularly with frameworks where the source is part of it, an open source framework, or at least where the generated code is available, where it's not sealed off or anything, where you can edit it. And they'll just go in and start throwing code into those, whatever that core class or interface is. And that's exactly what you're not supposed to do. And if you ever do something like that, if you customize a framework that's built that way and they do an upgrade or a fix or something like that, then you are much more likely to have to go do a lot of recoding because their change will then step on changes you've made or you've stepped on changes they've made. If you leave that clear distinction between their code or their generated code and your code or your customizations, your extensions, then it allows them to do upgrades essentially in place. Then all you have to do is maybe do a rebuild or relink or something like that to pick up the fresh libraries, the new source that they've... Actually, I guess binaries probably, the new code that they've generated for you. And you're off and running. That's the bridge pattern. There's really not a whole lot to it. It's very simple, very easy to implement. Leaving us, the challenge of the week is go find one. Whatever you're currently working in, sort of flip back through your code and see is the bridge pattern used anywhere. Or actually, I guess better yet, is it set up to be used anywhere? And are you actually utilizing it properly? Are you going in and maybe monkeying with and adding some code where you shouldn't be? If you should, slap yourself on the wrist and then fix it accordingly. You don't have to slap yourself on the wrist, but hey, if you do, if that helps you remember to do it right next time, then so much the better. That's it. We're going to wrap this one up. We'll keep it nice and short. So we'll get back to our coding, back to our patterns, and we'll continue through the structural patterns next time around. So go out there, have yourself a great day, a great week, and we will continue working through those patterns next time. Thank you for listening to Building Better Developers, the Developer Noir podcast. For more episodes like this one, you can find us on Apple Podcasts, Stitcher, Amazon, and other podcast venues. Or visit our site at developernoir.com. Just a step forward a day is still progress. So let's keep moving forward together.