Exploratory coding when requirements are fuzzy
Welcome to No Compromises. A peek into the mind of two old web devs who have seen some things. This is Joel.
And this is Aaron.
I thought today we could talk through a recent feature request on a project you and I are working on together. In this case, there was two separate systems. There was a supplier of inventory that has a feed of products in their catalog that they sell, and then we had an e-commerce platform where we were going to sell those products to somebody else. You know, organize them into categories and mark them up, and all the things that you do. Both of those systems had APIs. We wanted to keep the catalog of available products in sync. So all the logic of create a new product, if it appears update it, if its price changed, remove it, if it's no longer available, all of that. And on top of that, the client, of course, wanted to be able to configure this and monitor it and see what was going on so there's a user interface element to all of that functionality.
Well, yeah, and as developers, of course, I want to see what's going on too. I want to see if my codes are running and all that stuff. I mean, I know I don't ever create bugs, but just in case I did.
Well, you work with me and I do.
Yeah, I get that. Well, for this particular project, you can't necessarily fault clients for some of the requirements. Because how do you know how to give requirements if you've never done this? But other times it's like, "Well, I just need that information from here to there," and there are no requirements and you have to figure it out. So that's a little bit more what this project was. Which is, "I have this vendor and I have this other vendor, and I've hired you as a full-service contractor. So figure it out and asked me any questions." But that client is not taking that as their job, they push it to us. Which is fine, that happens. But based off that then, you have to kind of adjust the way that you approach that project so I think that this project was a little bit unique and different compared to our normal style of work too. Because we'll sit down, plan out maybe the user interface, the functionality, develop a plan, kind of maybe even do some mockups, and start coding this. And it follows the average pattern usually, which is you might see an interface and maybe that interface is a portion done. Like, you can just see the items and there's nothing in there so it just says there's no items. Then the next iteration is we create functionality and all the functionality goes with that create, or whatever, it happens. Then you go back and you can build out your index. So when you have a more concrete set of requirements, your planning becomes more concrete and the process in which you do this programming is more concrete and predictable. So, that makes a lot of sense in more of the structured projects can, like I said. And this client, as I mentioned earlier, was more like, "Hey, figure it out. You're the full-service vendor." So before we even started this, you have to understand, as a developer, you might have to change the way you do your work even though you're familiar with doing it one way because the requirements or the way that this client wants to work are different. And that's kind of why we said, "Okay. Well, we know we can do this in one way, but how are we going to do it with this client that's not giving us a lot of requirements? Or wants us to develop the requirements ourselves?" I think that kind of leads in a little bit more into exploratory stuff.
And that's a fair point. If you just truck ahead with your normal way of approaching it, you might still get to the end result you want but it might not be the most elegant way to get there. So, yeah, you use the word exploratory, I like that because that's really what this was. Is, we were figuring out the requirements. Looking at these two different platforms, they both have products, they both have images, they both have options, but they certainly don't structure them in the same way. So, how do we reconcile that? They handle pricing data differently? How do we reconcile that? And there's all these different things that just... This was a non-technical client too, I think that's important to mention. They just came to us with a business requirement and explained to us what they needed, and we had to go figure out the technical implementation of what they were asking for.
As a developer and used to analyzing stuff, my first reaction was, "Okay, I'm going to look through all this stuff. I'm going to generate them a document with a hundred questions." Well, I'll be honest. One, because I have a hundred questions, and two, maybe a little bit to make it painful back. Like, you're going to make it painful to me, I'll make it back. I know that's a bad attitude but I'm being real honest. That was a little bit of my thought process too. But I also know that because of the way the client is asking us for this work, that if I were to throw my little fit and ask them a hundred questions, I'm not going to get worthwhile answers. I'll have wasted their time, got them mad, and I might not even be able to do my job, which I want to do for this client.
In the moment, it might feel fun and satisfying but it's not really a productive way to build a relationship or to accomplish a project. I can relate, I will be honest as well. Like, "Yeah. All right, here's what you're asking for."
So one of the things I wanted to start out with is I wanted to make a user interface right away because that's how my brain works. It's like, "Okay. Well, I want visibility just to get started here." But then I realized I don't even know what it is I'm supposed to be looking at. Basically, my visibility would've been making a endpoint that was like /dashboard and it would say, "Here is the stuff you wanted to see." I don't know anything yet. Like I said, this was more of a struggle. Like, how should we get this together? How should we do this coding? And then how can I get it to a point where as a really technical person, I can give it off to just maybe someone in the middle? Where they can play with it and then they can give me some of that feedback while not having to do all the extra work of making interfaces and stuff that are being thrown away anyway.
That person in the middle was me, Aaron. As you built this out long before we showed it to a client or demoed it for them, I played with it. And maybe let's talk a little bit. Talking about code in an audio format is always a little problematic, but maybe in a concrete sense, what did you actually build? And then I can talk about my experience using that and how it actually helped the process to get to the end requirements we needed in the first place.
Yeah, a lot of times... I mean, this isn't an architectural structure conversation so I'm just going to use some terms and whatever. But in general, I had a service class. And in that service class is where all the logic happened with some of the... Data comes in, it goes to one place or it goes to another. It can consume it at a couple of different services, et cetera. And a lot of those will get wrapped inside of jobs or automated process or console commands, even in controllers at some point. But in general, I knew I can code, like an HTTP request, inside of the service class with all my data and keep it all encapsulated. I started to build out, first of all, how do I interpret the incoming data? I build that inside of a service. It's like, well, I received a JSON feed and I've de-normalized that into maybe some models and then I will create those models in my database with Eloquent. And now it's just one method of that service. I mean, it's one step. The process is going to be multiple calls to multiple services but it was one very small thing I could break into a small little chunk I knew was working. I could write tests around it if I wanted to, at this point, I didn't yet. And I put it inside of a console command instead a temporary command saying, "Step one, this is the very first step. Run this and it will set up." It'll blow everything away in your local database and it'll set up one imported model or one interpretation of this JSON Stream.
Yeah, there's a couple of things in there I want to highlight. Because I enjoyed the way you approached this. First of all, we've sort of said right off the top, "It doesn't make sense to build a user interface." But you even went a step further, which is eventually we would have a command. Because this is mostly going to be a background nightly job where I would have to fetch the data, process the data, upload the data to the new place. You didn't even build that overall command in route console, it literally was a bunch of closure-based console routes, I guess we call them.
Yeah, with the Artisan and facade.
And one extra thing, I'll give you kudos on this. There was a big block at the top of that file with, "Here are all the scenarios that this covers." I'm testing a product that does not exist in the target system, I'm testing a product that exists but needs to be updated, I'm testing a product that has options, that has images. As I recall, there was maybe 8, 9, 10 variations. Handing that to me, number one, it really made it easy to understand, "Okay, what requirements have we implemented?" And then it gave me a really easy handle to go test those one by one. And no surprise, when I tested it we found some things that needed to be refined but it bypassed a lot of ceremony and things that would've been more expensive and time-consuming to change later while we were still in that exploratory phase.
Well, and keep in mind too. Like you said, it was documented all the different things. It wasn't set up in such a way that you could run them in any order that you wanted either. It was literally like, okay, the first command you run to blow everything away. The second command is how you get the imported stuff. The third command is doing its very small amount of work again, that you can watch but is based off of the results as if the second command had run successfully and only deals with those things. It was even more simplified, whereas when you go and start hooking these into larger things, you could run it against everything. Whereas this was, "You have to run these commands and only in this order just to verify that." It was basically coding the requirements.
Right. And the test data and things that were set up made it really obvious as well what was happening. In addition to the comments and the kind of guided workflow that you would even name in the products, like product with new image, product with removed image, or things like that. Where it just made it very easy for me to look through it. So I appreciated that. And full disclosure, this project is still in process. We have not even yet got to the point where we built that UI. But we're way down the road from where we would've been if we just took that either semi-adversarial approach of like, "Well, here's every possible question I can think of." You know, we still have questions, and every week we're going back and forth and we're refining it and we're moving forward. But that's just it, we're making progress and it doesn't feel like we're starting over each time. Because, "Oh, I didn't know about that. Now I got to rethink how I built this whole thing."
I think to wrap it up. The one thing I've learned from this though, and it's kind of opposite of all the code and everything, is that you have to work in the manner that everyone can work. And that might be less efficient for you, but it's most efficient for the end result. So the way that we're working, I don't feel is the most efficient way that I work. But if I'm at 100% they're going to be at 1%, but if I am at 75% they're going to be at 75%. And if you combine those two, that's higher.
Bigger numbers are better.
The end.
Every once in a while I catch myself checking or worrying... that might be too strong of a word, but thinking about something and then realizing, "This is not something a normal person usually thinks about." I'm going to give you a of couple examples and just jump in if you relate to any of these. For some reason I take a container of liquid out of the fridge, when I put it back I have to check twice that the lid is on securely. Do you ever do that? No?
Nope.
I could tell by the the expression. Weekly when we take our trash cans out, I put them at the end of the driveway, and then I'll start walking back to the house. And then I'm like, "Are they far enough apart? Will the truck be able to get them?" And then I'll move them two more inches apart no matter how far apart they're to begin with. It's like, "I should just play it safe." Still on my own out here? Okay.
Okay.
You're going to love this last one, Aaron, because this is the one that really, in my mind, triggered this thought. When I'm sending a piece of mail, which is not something I do a lot, but when I send a piece of mail, when I put the stamp on I panic a little bit. Like, use it upside down, because in the back of my mind if you put the stamp on upside down it's some sort of rebellious anti-government message. And the flag which is on the stamp, this is the normal US stamp, it's kind of obscure. You have to look at it to know what is the proper orientation. Because it's a flowing wave, you have to see where the flagpole is. You've felt that, you laughed at that one. I have to believe that you agree with that.
I don't agree with it, that's why I'm laughing. What? I mean, no.
I'm going to go one step worse here, because when I was thinking about sharing this with you, I'm like, "Actually, why don't I look it up?" Because I've had this thought in the back of my head, maybe it does actually mean something. Apparently, there's a whole thing in World War II when people would send postcards to soldiers overseas. There was eight different orientations of a stamp and it carried a message. Now none of them were negative messages but maybe that crept into my consciousness, I don't know. So there is something to worry about.
Oh, I thought you meant that you were looking up your symptoms to see if it actually meant that you have something.
That's exactly right. And I was right, I have it.
No, the only way I can relate to that is I have the weird honeycomb issue with the small little holes. Like, when you see too many of small little holes next to each other, like a pattern, it makes me feel really sick and I start itching and I'll start sweating and panicking.
I'll have to use that to my advantage at some point.
I mean, it'll be violent if you do. You know, we don't just do development. We will write up your requirements for you too. And in fact, Joel loves that sort of thing.
I absolutely do not love it but we will do it. So, if you'd like some help getting a project going, head over to nocompromises.io.