Skip to content

Philosophy

Think in Features, Not Layers

The design of SliceFlow is guided by a core set of principles aimed at maximizing developer productivity and long-term maintainability. We believe that the best foundation for an application is one that is simple, pragmatic, and helps you move quickly without sacrificing quality.

Traditional software architectures often organize code by technical concern. You’ll have folders for Controllers, Services, Repositories, and Models. When you want to build a new feature, you have to jump between all these folders, creating a small piece of the feature in each one. This separation scatters the logic for a single use case across the entire project, making it difficult to understand and modify.

SliceFlow champions Vertical Slice Architecture. The idea is simple: organize your code by feature.

Everything required for a single feature—the API endpoint, its request and response models, its validation, and its specific business logic—is located together. This creates a high degree of feature cohesion. When you need to work on the “Assign User Permissions” feature, you know exactly where to look, and all the relevant code is right there. This drastically reduces cognitive overhead and makes the codebase easier to navigate. You stop thinking in technical layers and start thinking in application features.

Pragmatism Over Dogma: Resisting Premature Abstraction

In software development, we’re often taught principles like “Don’t Repeat Yourself” (DRY). While well-intentioned, a dogmatic adherence to DRY can lead to a much bigger problem: high coupling and the wrong abstractions.

Consider managing a user’s subscription. You might have three distinct use cases:

  1. UpgradeSubscription
  2. DowngradeSubscription
  3. CancelSubscription

The initial, “DRY” temptation is to create a single UpdateSubscription endpoint that takes a new subscription plan. But what happens next?

  • Upgrading might require an immediate payment and a call to the Stripe API.
  • Downgrading might only take effect at the end of the billing cycle and requires scheduling a background job. The request might also need a reason_for_downgrade field.
  • Canceling needs to send a “sorry to see you go” email and doesn’t require a new plan ID at all.

The single UpdateSubscription endpoint quickly becomes a tangled mess of if statements, optional request parameters, and complex logic. The truth is, these three use cases were unrelated, even though they all touched the Subscription entity. By trying to be DRY, we coupled them together, and now a change to the cancellation flow risks breaking the upgrade flow.

The SliceFlow approach is to create three distinct endpoints: UpgradeSubscriptionEndpoint, DowngradeSubscriptionEndpoint, and CancelSubscriptionEndpoint. Yes, they might share a few lines of code at first. But they can evolve independently as their unique business logic grows. We prefer a little duplication over creating the wrong abstraction that will cause massive headaches down the road.

This pragmatism extends to how we use third-party libraries. SliceFlow encourages you to use tools like Entity Framework Core directly. Hiding powerful, well-documented tools behind your own leaky abstractions (like a generic repository) often limits their power and creates a new, internal API that your team has to learn and maintain. Trust the tools and the experts who built them.

Our Guiding Principles

To summarize, our philosophy can be distilled into the following principles:

We Believe In…Because…
SimplicityComplex solutions are harder to debug, maintain, and extend. We prefer the simplest path that solves the problem effectively.
Feature CohesionKeeping all the code for a single feature in one place makes the system easier to understand and reduces the cost of change.
Pragmatic DuplicationA small amount of code duplication is often a much smaller problem than the high coupling introduced by a premature or incorrect abstraction.
Serving the FrontendThe backend’s primary job is to empower the frontend. We shape our APIs to provide clients with exactly the data they need, in the format they need it.
We Avoid…Because…
Premature AbstractionIt’s nearly impossible to get an abstraction right the first time. It’s better to wait until a clear pattern emerges from real, duplicated code.
High CouplingWhen unrelated features are tied together, a change in one can unexpectedly break another, making the system fragile.
Needless PhilosophizingEndless debates about whether a piece of logic is a “service” or a “handler” are unproductive. We focus on delivering features.

This philosophy is a guide, not a set of rigid rules. The goal is to keep you moving fast, iterating with confidence, and building software that is simple, pragmatic, and a pleasure to maintain.