We consider ourselves a .NET shop. Our tools are usually Visual Studio, C#, MSSQL Server, IIS/Azure, ASP.NET MVC, EntityFramework, etc. We have an incredible amount of institutional knowledge of these technologies. We’ve found the pain points. We’ve developed work arounds. We have best-practices. We have thousands of lines of code to use as examples.
We were recently tasked with building a new Ecommerce site on a completely different technology stack: PhpStorm, PHP, MySQL, Laravel, Nginx, DigitalOcean, Eloquent.
Except for using Typescript and Knockout, not a single one of our accustomed technologies was available to us. And yet, we weren’t afraid to take it on. This is due in no small part to our core values around software development.
Regardless of the technology used, we believe in:
- Information Hiding
- Loose Coupling
- Volatility based decomposition
- Service Oriented
- Test Driven Design
We pride ourselves in our processes and dedication to quality, and we believe these are our true differentiators. While we know that processes alone can’t save us, and that having people is also needed, having some guiding principles that drive what we do gave us the confidence that we could bring this project to life.
Starting the Project
When starting a new project, we typically have an Iteration 0. This is when we set up development environments, build servers, QA environments, continuous integration, etc. We usually schedule a week or two for iteration 0, depending on the project. In this case, it took a little over a month before we really had our infrastructure nailed down. That was a disappointment, but there was a lot of learning and uncertainty surrounding the sheer number of new tools we had to orchestrate.
Thankfully, we knew the tools and techniques we needed to support our core values, even if we didn’t know exactly how to implement them on a new technology stack:
- Unit/Integration testing
- Dependency Injection
- Automated builds on Pull Requests
- Automated deployment
- Automated Database migrations
With this well-defined list of goals, it was a matter of “How do we do these specific things on this new platform” and not “How do we write software on this new platform.”
Putting our Values into Practice
Testing, logging, and database migrations were all provided by the Laravel framework, and worked pretty much as expected. Automated builds and deployments were handled with a combination of GitHub, Travis CI, and Laravel’s Forge hosting service.
The first real technical issue we needed to solve was dependency injection. Laravel supports dependency injection and provides a way to map interfaces to implementations. However, we were looking for something a little more structured than what was in the box.
We ended up creating a static “Injector” class. This class held the string constants that represented our fully-qualified interface and class names. It also contained static functions that abstracted out Laravel’s “resolve” global function. We were able to “strongly type” these methods using PHP 7 type hinting.
The second-largest technical hurdle was object mapping. Laravel uses the Eloquent library for an active record-style data access model. We wanted to avoid passing Eloquent models out of our data access layer (DAL), so we need to map the models to our own data-only data contracts.
We created a static “Mapper” class to handle this for us. Using reflection, we map the attributes from the Eloquent models to matching fields in a given data contract. This was one area where the dynamic nature of PHP really shined. It’s now one line of code to map between Eloquent models and our datacontracts.
The final piece that really made things click for us was getting PHPStorm for our IDE. We have been continually impressed by this tool. When paired with PHP 7, and some disciplined PHPDoc comments, we’ve achieved a near-“Visual Studio plus C#” development experience.
After tackling these challenges, I think we’re operating at about 90% of the velocity we would normally achieve on our “normal” technology stack. We are currently meeting our release schedule, and creating quality code and generating value.
We’ve always known that our processes and practices were technology agnostic, and that our team’s ability to “fill in the gaps” is what sets us apart. The success of this project proved that we’re definitely on the right track. We’ve managed to maintain quality, velocity, and design even though we were working with (almost entirely) different tools.
In the end, the project reinforced for us the fact that even when we don’t have knowledge in a particular technology stack, our processes (which at certain levels are pretty tech-agnostic) and our team’s ability to execute with them help ensure the same level of quality, predictability, code coverage, and manage complexity throughout projects.
This project is just one example of how our processes and team aptitude have seen us through. If you’d like to learn about some of our experiences, leave a comment below or drop us a line at firstname.lastname@example.org. We love sharing about what we continue to learn.