Engineering approach in practice - CraftByte Studio standards
Michał Andrzejewski - Content Director
2025-03-23

Engineering approach in practice - CraftByte Studio standards

In the world of modern software development, the most important factors are quality, delivery speed, and scalability of solutions. Software houses like CraftByte Studio rely on an engineering approach – that is, working methods derived from industry best practices – to deliver reliable systems to clients. In this article, we’ll explore the key pillars of this approach: CI/CD (Continuous Integration/Continuous Deployment), system architecture, and testing. We’ll discuss how these elements are implemented in practice without a marketing tone – focusing on the technical perspective and drawing from the experience of recognized companies such as ThoughtWorks, Shopify, Basecamp (37signals), and Vercel.

CI/CD – continuous integration and deployment

Continuous Integration (CI) and Continuous Deployment/Delivery (CD) are the foundation of the modern software development process. CI means continuously merging changes made by developers into a shared codebase and immediately running automated tests on each merge. This way, the team quickly detects integration issues, significantly reducing the risk of delayed feature delivery. CD extends this process by automatically deploying approved changes to test, staging, and finally production environments – often without human intervention if all tests pass.

In practice, CraftByte Studio uses modern CI/CD tools such as GitHub Actions, GitLab CI/CD, or Jenkins, depending on project preferences. Each code change (pull request or push to the main branch) triggers a CI pipeline – a set of automated steps. A typical pipeline includes:

A key element of CI/CD is maintaining stability at every stage. At CraftByte Studio, we follow the rule that a build must not be "red" – if the pipeline fails (e.g., due to failed tests), fixing it becomes the team’s top priority. This discipline follows the practices described by Martin Fowler, where broken integration should be fixed immediately before developers move on. As a result, the main branch is always in a deployable state.

Deployment automation (CD) goes hand in hand with continuous integration. We draw inspiration from companies like Vercel, which introduced the concept of preview deployments for every change. In practice, this means each pull request automatically spins up a preview environment, where you can click through the app with the implemented change. This allows both developers and clients to continuously verify the results before merging. After merging to main, the pipeline automatically pushes the app to production or the next environment – this is the essence of continuous deployment. This approach shortens time-to-market – new features can reach users within minutes of being written, provided they pass all tests and reviews.

The CI/CD tech stack in a modern software house often includes containerization and infrastructure as code. CraftByte Studio uses Docker to create consistent runtime environments and Terraform to define cloud infrastructure. The pipeline can not only test and build code but also provision cloud resources for new environments. This eliminates the infamous "works on my machine" – ensuring the app runs the same everywhere: locally, in CI, and in production.

It’s worth noting that our CI/CD practices are inspired by industry experience. ThoughtWorks – a pioneer in Agile and DevOps – has promoted continuous integration for years as a way to maintain a healthy software development process. SaaS giants like Shopify, and teams at Facebook and Google, have also stated that fast, automated pipelines are key to delivering value to users frequently. CraftByte Studio has adapted these lessons, building its pipelines on solid, proven patterns.

Architecture – well thought out before the first line of code

The second pillar of the engineering approach is system architecture. Before implementation, it's crucial to design the solution at a high level: break it into modules, choose the right design patterns, define context boundaries (if using DDD), and plan for scalability. CraftByte Studio puts great emphasis on the architecture phase, drawing from practices like Domain-Driven Design (DDD) and Clean Architecture.

Domain-Driven Design focuses on modeling software around business domain concepts. In practice, this means close collaboration with the client and domain experts to create a domain model – a set of business terms and rules the system should reflect. According to DDD principles, we aim to isolate business logic from technical details (e.g., databases, UI). ThoughtWorks captured the essence of DDD well: it’s about separating business rules from infrastructure concerns, keeping the system’s core clean and understandable. CraftByte Studio applies these principles by defining bounded contexts in complex projects – each context encapsulates a coherent part of the business model, simplifying system understanding and enabling independent module development.

Another key architectural influence is Clean Architecture (and related concepts like Onion Architecture or Hexagonal Architecture). They all aim to separate concerns through a layered system structure. As Robert C. Martin (Uncle Bob) wrote, these approaches divide software into inner layers containing business rules and outer layers handling interfaces with the outside world. At CraftByte Studio, a typical project has several key layers:

This approach has tangible benefits. First, the system is framework-independent – frontend tech or specific ORMs are tools, not architectural foundations. Second, it’s easily testable, since business logic can run without a web server or database. Third, it offers flexibility in scaling and changes – e.g., changing the data access layer (switching cloud providers) doesn’t require rewriting the entire app.

CraftByte Studio also draws architectural inspiration from companies like Shopify. Shopify ran a massive Rails monolith (over 2.8 million lines of Ruby). Instead of rewriting it as microservices, the team modularized the monolith using tools like Packwerk, allowing the app to be split into independent components inside one repo. This made working on each module feel like working on a small app. CraftByte Studio adopted this lesson – in projects of appropriate scale, we prefer a modular monolith: one codebase internally divided into modules or components. Each module has a clear API and is owned by a specific sub-team. This reduces integration complexity, simplifies refactoring (as long as contracts are upheld), and speeds up feedback (devs can run tests only for the module they’re working on).

Of course, microservices make sense in some cases – e.g., when system parts need to scale independently or use very different tech stacks. CraftByte Studio uses microservices judiciously, mindful of their complexity (distributed transactions, service monitoring, etc.). Often, we opt for a hybrid architecture: the core system as a modular monolith, with small separate services where it makes the most sense (e.g., a standalone AI module, or a high-load service scaled horizontally).

To sum up, thoughtful architecture upfront avoids many issues during development and maintenance. We invest time in the design phase because we know we’re "paying ahead" for future simplicity. This approach contrasts with chaotic "quick coding", which often ends with full rewrites. Inspired by DDD, Clean Architecture, and companies like Shopify, CraftByte Studio builds systems that are flexible, easy to evolve, and resilient to change.

Testing – focusing on what brings value

The third pillar is testing. There’s a saying in the industry: "Write tests. Not too many. Mostly integration." – coined by Guillermo Rauch (creator of Vercel) and popularized by Kent C. Dodds. It captures our core belief: high-level tests simulating real system behavior provide the most value, not endless isolated unit tests.

CraftByte Studio of course writes unit tests where it makes sense – for standalone functions or complex logic that works in isolation. But our priority is integration tests and end-to-end (E2E) tests, which validate component interactions and user flows. Why? Because they best verify whether the app truly works as expected in real environments. A unit test can say a function returns the right result for fake data, but only an integration test shows if the whole path – from HTTP request to DB and back – works flawlessly.

We share a similar view with the creators of Ruby on Rails at Basecamp (formerly 37signals). David Heinemeier Hansson (DHH), Basecamp co-founder, has long criticized overreliance on unit tests and excessive mocking. He warns of "test-induced design damage" – distorting app architecture just to make it easier to unit test. DHH notes that engineers often add unnecessary abstraction layers, break simple dependencies, or use patterns (e.g., hexagonal architecture with ports/adapters) not for business needs but to please tests. The result: more complex production code, harder to maintain – the opposite of what’s intended. At CraftByte Studio, we avoid this trap. We design code for readability and simplicity, not to serve unit tests. Tests serve us, not the other way around.

That’s why mocking (injecting fake objects) is limited. Like the authors of the famous "Is TDD dead?" discussion – DHH, Martin Fowler, Kent Beck – we "mock almost nothing". Instead, we use real components in integration tests: real databases (in-memory or Dockerized), real API calls (sometimes to stubbed services, but via real HTTP). This gives us confidence that the scenario works. We don’t wonder if something was mocked wrong or if assumptions mismatched reality.

Of course, E2E tests are slowest and hardest to maintain, so we use them wisely. We use modern tools (e.g., Cypress, Playwright, Selenium) for browser/API automation. Key user flows (the happy path and critical edge cases) are covered by E2E tests in our CI/CD pipeline to prevent regression. Integration tests (e.g., service layer with DB) give module-level confidence – run locally and in the pipeline, forming the base of the "testing pyramid" (or rather, the testing trophy, per Dodds’ metaphor).

Our testing approach draws on leaders’ experience. ThoughtWorks warns against "Tautological TDD" – an anti-pattern where tests know too much about implementation and become fragile due to over-mocking. At CraftByte Studio, we prefer black-box tests: checking what the system does, not how (no peeking into internals). Basecamp/37signals (DHH) showed it’s possible to build complex systems (like Basecamp or Hey.com) relying mostly on integration tests while keeping code simple. Vercel proved rapid production deployments are only possible with strong trust in the test suite – hence the focus on tests that actually provide that trust (integration and E2E). That’s why we live by the Rauch/Dodds motto every day.

Also, automated tests aren’t everything. At CraftByte Studio, we believe in a holistic quality approach: code reviews are a standard part of the process – every change gets at least one teammate’s eyes. We also sometimes run exploratory testing by QA on preview environments (thanks to CI/CD, any feature can be clicked through before production). This mix of automation and human insight catches both obvious bugs and usability or spec gaps no test would catch.

Summary

The engineering approach to software creation, practiced by CraftByte Studio, is based on three main pillars: CI/CD, well-thought-out architecture, and valuable testing. All of these serve one goal – deliver high-quality software to clients quickly and effectively, without compromising stability. This is not a marketing slogan but a proven methodology, backed by the experience of industry leaders.

By using CI/CD, we ensure continuous deployability and fast feedback on every change, just like teams at Google or Shopify. Designing architecture upfront, we build solid foundations, following the philosophy of DDD and Clean Architecture – so the system is ready for growth and change, as confirmed by ThoughtWorks and other tech leaders. Testing smartly, we focus on what really boosts confidence in the app’s behavior, following Basecamp’s path and expert advice that prioritizes integration over isolation.

For clients, this means transparency and trust: they see the project is run professionally, with care at every stage – from coding, through integration, to deployment and quality verification. This article aimed to show this technical perspective on modern software creation, explaining how CraftByte Studio works and why this approach leads to better end products. No fluff – just substance, because that’s what ultimately determines a project’s success.

Sources and inspiration: We used respected industry publications, including Martin Fowler (Continuous Integration), Shopify’s experience (modular monolith), ThoughtWorks articles (DDD, limited mocking), statements from David Heinemeier Hansson (unit test criticism), and practices promoted by Kent C. Dodds and Guillermo Rauch (Testing Trophy, integration testing). All of these shape our engineering approach – refined, modern, and built on the best the industry has to offer.

Articles