No Compromises

Interfaces are a great tool for writing maintainable applications, but it is possible to go "too far" with abstraction. Or maybe, it's a bad use of time to write an abstraction up front before you really know you need it. We discuss some trade-offs and examples.

  • (00:00) - Life before interfaces in PHP
  • (02:30) - Going too far with interfaces
  • (04:45) - A discussion with payment gateways
  • (07:30) - Abstracting the database as another trap
  • (09:15) - Laravel makes good use of interfaces
  • (10:05) - Silly bit

Need some perspective on your Laravel project? We offer a code review service. Get in touch to learn more.

Creators & Guests

Host
Aaron Saray
Host
Joel Clermont

What is No Compromises?

Two seasoned salty programming veterans talk best practices based on years of working with Laravel SaaS teams.

Joel:

Welcome to no compromises. A peek into the mind of 2 old web devs who have seen some things. This is Joel.

Aaron:

And this is Aaron. So PHP isn't the only language I know how to program. And Laravel isn't the only framework. And so over the years, you run into other programming languages and you see the different tool sets that they have, like overloading or interfaces and all that kind of stuff. And especially when you started PHP far back when I did, there wasn't any interfaces, that you could test against.

Aaron:

Or at least I didn't know about them, but I'm pretty certain there wasn't.

Joel:

Okay.

Aaron:

And, so I remember putting together some sort of code that had these plugins. And I wanted to release a whole plugin ecosystem. And in order for a plugin to work in your PHP software library, you had to validate with method method exist to make sure that it had all the methods that you plan to call on it, whatever. Yep. And so, like, if you have 3 methods you plan to call on it, like, hooks or whatever, you have to make sure those work.

Aaron:

And and then they release interfaces or I became aware of them or however that little I mean, this was years years ago. However, that came about, I started realizing, oh, I can just check on the instance of that interface. Or as as, PHP moved on further, now we can type into our parameters. And so when we're registering things, we know they're an interface of whatever. And and that was great.

Aaron:

And I think when a lot of people discovered, the value of those interfaces, myself included, I was just, this is amazing. Now, I can really finally swap things out and make different instances of logic and strategy patterns and all that kind of stuff, I'm I'm pretty excited.

Joel:

All your nerd brain cells are firing. I I've just I gotta pick my jaw up off the floor, because there's other languages besides PHP and there's other frameworks besides Laravel. How dare you, sir. How dare you bring that into a Laravel podcast like this? But, no, I I was wracking my brain too thinking about when did interfaces get introduced to PHP.

Joel:

But, yes, you're right. There was a point in time, I can't think of the version number off the top of my head, where we didn't have those things, and it is really nice that we have those now. So I think what you're saying is we should use those everywhere, and we should take that pattern as far as possible.

Aaron:

I'm just I'm just guessing.

Joel:

To the extreme . Yes.

Aaron:

No. And so it kinda started making me think about some of the earlier implementations of dependency injection Mhmm. That I had done and, you know, registering those contracts, those interfaces in case of a, you know, a service or a concrete instance of something. And, I just I started realizing that, Oh, boy. I I really overdid it sometime in my career.

Aaron:

And so that was kinda the point of this, what I wanted to bring up is, sometimes you don't have to use all the tools that you have available to you. Yep. And then other time I mean and then keep in mind, like, what is it that you're actually building in? What are the chances that this thing will actually get swapped out or make use of those tool sets or that you don't have an editor with IDE completion or whatever or, you know, all these different things. I'm not I'm not talking about, like, just going, like, completely lazy and not putting any structure in things.

Aaron:

But there there is at some point, you have to start saying, like, okay. So our business maybe is working with Stripe. And they've been working with Stripe for the last 3 years. And the chances of us moving off of Stripe is very low. So I'm not gonna make a payment charging interface.

Aaron:

I'm just gonna implement my Stripe in the interface. Or Yeah. Or or, you know, I'll I will put in a payment service, but it's just gonna be Stripe related stuff. I'm not gonna make an interface, inject only my instance. I'm just gonna inject the code that I know is gonna be working.

Aaron:

But with a on the flip side, there are times when you know that you're gonna swap these things out or that the user might have choice. Maybe the user has the ability to pay with multiple different types of payment methods. And so you have to you you actually give the user a choice on what payment method. And then in the background, you're gonna use a strategy, if you will, of how to charge them. Right.

Aaron:

And then, that makes it more sense to have, you know, these interfaces because depending on which one, you might have different, you know, requirements that those services have to do, etcetera. But you you're calling coach and have to know about that. So that might make sense to have one of these interfaces. And and so but the whole point is, like, just because you have a tool it's it's that whole that whole, phrase, like, just because you have a hammer doesn't mean everything's a nail.

Joel:

Very true. Now so just to to get a little more concrete, because, like, payment gateways is a great example of this. This is, like, something where it seems, well, we might switch at some point. Maybe they'll jack up their fees or this or that.

Aaron:

But the amount of work that it requires and cost to make them swappable

Aaron:

Right. Is usually not worth it. And and, like, again, we work with a lot of startups, so it's a little bit different in some of these cases. But your goal is to get to market. You have to have, you know, the perfect swappable code for some time in the future.

Aaron:

Like, you know, it's when these people build these these tools, these programmers for like, if we're gonna scale huge. Mhmm. You gotta get the product done before you scale.

Joel:

Yeah. Yeah. That's pretty obvious, Ivy, but maybe not. Maybe maybe it's fun to write the code. But but, like, what what I was trying to tease out is, like so you mentioned a payment service.

Joel:

That payment service talks to Stripe.

Aaron:

Mhmm.

Joel:

But and and we're not creating a payment service interface with with the goal that maybe there's, like, a Braintree interface or PayPal interface or whatever, you know, flavor

Aaron:

of the month. Yeah. I mean, there there there won't be a Braintree service or whatever.

Joel:

But we do I mean, I'm trying to think of how to phrase this. We would say we don't want, like, Stripe objects leaking all the way into our code either. Right? So there's kind of like a middle ground where you don't you don't create an interface to abstract it, but you do sorta isolate what that thing is. And so your your models, for example, aren't relying on certain fields that are present in a Stripe payment method.

Joel:

You might call it something different or it might be called the same thing, but you're not sticking Stripe as as a word all over your your application code.

Aaron:

Yeah. I mean, in general, like, even if you know you're not gonna swap out Stripe, you you could you can make 2 different choices. You could have, like, Stripe underscore customer ID. Sure. Or you could have, you know, external processor underscore customer ID.

Aaron:

Maybe. I mean Yeah. But but, honestly, the amount of times that I've seen people have to migrate from payment provider or, like, you know, these different things over and change some columns in their table or whatnot. As long as you're you're you know, you actually do the work and not use a field called Stripe underscore ID for your brain trust or brain tree, IDs.

Joel:

No. Don't even suggest that, Aaron.

Aaron:

Use you. I mean, it's it's it's overkill to to to make the stuff too abstract.

Joel:

Yeah. That's true. You can you can always change it later. So payment gateways is one that comes up a lot. The other one I thought of when you started talking about not going too too nuts with, like, abstracting things is like your database.

Joel:

Right? Like, oh, what if what if we're gonna switch from MySQL to Postgres or something? Like, I I assume your your logic is the same, and maybe it's even a little different because Laravel itself provides some abstractions there. We don't have to write all of these ourself. But would you agree that's another one where maybe people go a little too far?

Aaron:

Yeah. Especially when it comes to, like, the reporting and all that kind of stuff too. Like, because a lot of times in reporting, you wanna just write SQL statements. Yeah. Yeah.

Aaron:

And then people get a little too, you know, too rigid on that. Chances are, if you're switching a database engine, your data structures change in some way a little bit too. So you're gonna have to touch some of that stuff anyway. I mean, I've I I could be wrong. I absolutely could be wrong.

Aaron:

But I haven't seen a MySQL to Postgres or vice versa, conversion where everything was exactly the same.

Joel:

Yeah.

Aaron:

It was Yeah. It was changed to get some of the benefits of whatever they changed it to. But that meant you had to change some stuff anyway along the line. You know, there wasn't auto incrementing this or

Joel:

Right.

Aaron:

Window functions are different here, all that kind of stuff. So

Joel:

Yeah. And that kinda raises another reason to not do, like, a early abstraction. Like, it's the time to build it is 1, but you're also kinda targeting, like, the lowest common denominator. Right? Like, you can't fully leverage the thing you're using if you're like, well, if if Stripe doesn't have this feature that this other payment provider has, I can't use it because if I ever wanna switch, like, now I can't switch.

Joel:

Like, that that's sort of the same thing too. Like, play to the strengths of what you are using now. Don't get too hung up in what might change down the road because you can't you can't predict the future.

Aaron:

Yeah. I think the last thing that I would mention about these, interfaces and things like that is we're not anti interface, and we're not anti dependency injection or any of those different things. I mean, I I like that a lot. There's a lot of stuff in Laravel too that's behavior that's driven off of the presence of interfaces Yeah. That do that do nothing but just indicate that this is a behavior that's expected.

Aaron:

Yep. And and so we're not that. It's just more the whole concept is, like, don't abstract things out even if you have the tool sets to easily do it unless you know what you're doing. You know, it's it's we talk about interfaces. We talk about even our testing code and stuff like that if we write Yeah.

Aaron:

Some stuff. If it's reused, then it's reused in this this class.

Joel:

Mhmm.

Aaron:

If it's really reused, it's a trait. If it's reused for everything, then put it out into a base class. You know, there's there's different steps of how to do this.

Joel:

Yeah.

Aaron:

So a lot of times when we look at our elders, like you, Joel

Joel:

Go on.

Aaron:

We we think that we think that they're they're wise. Mhmm. Okay. They're they're smarter than us.

Joel:

They are. Yeah. Go on.

Aaron:

And, but I I have a I have a different theory.

Joel:

Okay.

Aaron:

As you get older, you're not just you're you're not smarter.

Joel:

Mhmm. You

Aaron:

just run out of stupid things to do. Alright. Like, all you have to as you get older, the appearance of being wise and smart is just you having a memory. Mhmm. So you you remember those stupid things, and you don't don't do them anymore.

Aaron:

And then people are like, wow. That's smart. You're like, no. Not smart. Just did it in 1973 and burnt my face off.

Aaron:

So never gonna do that again.

Joel:

I I I think there's a lot of truth to that, and I don't know why. But when you said you've already done stupid things, the immediate image that popped in my mind was as a teenager watching a friend of mine climb one of these rock exterior walls of a George Webb restaurant and falling onto a car. And I like that. I don't know why, but that was, like, the immediate image of a bad decision. You do younger life, and I didn't even do it.

Joel:

I just witnessed it. But, yeah, I think I think there's a lot of truth to that.

Aaron:

Sometimes when you're stuck in a project, it's hard to back up and get clarity that you need, so you might need someone else to take a look at it with you.

Joel:

That's something we can help with. We offer a code review service. Reach out and contact us if that's something you're interested in.