Photo by Nathan Queloz on Unsplash

I assume that everyone knows about this very first principle in the SOLID abbreviation — Single Responsibility Principle(SRP).

Robert C. Martin expresses the principle as,

A class should have only one reason to change.

OR more detailed explanation

Gather together the things that change for the same reasons. Separate those things that change for different reasons.

Uncle Bob gives a really good explanation. And I highly recommend you watch this video if you haven’t seen it yet.

SRP may seem the simplest and clear, but is it really so? Does this statement sound simple enough for you? I bet…


Photo by Holger Link on Unsplash

This is the second part of the series “How MVC frameworks taught us bad habits.”

This time we will investigate why the default MVC Framework architecture does not always work well. We will trace the path of the application from the MVP to the monolith. Finally, think about what we can do to avoid the difficulties of maintaining our application

MVC Complexity Balance

When we talk about MVC frameworks, we usually supposed such a picture.


Let’s look back in the past and try to figure out how frameworks taught us not to notice the wrong things.

Bad habits

Intro

Let’s go back in 200X. It was a boom of MVC frameworks. Ruby on Rails, Django, ZendFramework, Spring, etc. Various frameworks in different programming languages created, copied, and improved various features.

Frameworks have taken a really huge step in web development. And they brought a lot of good things into the industry and forbade doing bad things for developers. Using frameworks made it easy for beginners to start. My career as a web developer began in 2007. For several years I used the frameworks without thinking about the architecture and tools that these frameworks provided.

We are so used to…


Check reflection state in Typescript

The reflection we are used to.

Languages like C#, Java, PHP have a reflection mechanism.

Reflection is a feature in the Java programming language. It allows an executing Java program to examine or “introspect” upon itself, and manipulate internal properties of the program. For example, it’s possible for a Java class to obtain the names of all its members and display them.

Reflect has been introduced in Javascript. But that’s not what we’re used to in other languages. Most of the features have been available via “proxy handler” or raw Object. Reflect functionality is quite poor. …


As software developers, we deal with classes, interfaces, modules every day. But why do we need them? Yes, this is a stupid question — and you would probably say that they help simplify our programs. Let’s think about some fundamental questions — why is it difficult for our brain to understand and work with spaghetti code 🤯.

brain blows up

Why do we need classes, interfaces, modules, etc?

Computers don’t care how many classes, functions, or interfaces in your program. In the end, our program will be converted to bytecode without classes, functions, interfaces. Computers don’t care if your program is a terrible spaghetti code or a well-designed solution. They will…


Come on, it is a frontend, we never used Dependency Injection

We are used to using DI in the backend. It has complex logic, the dependency tree is large, it’s likely that we can change some Logger / Caching / HttpClient library to another. What about the frontend… do we really need this?

DI decouples our code, making it easier to modify and understand. But what if my code is simple enough and I don’t need to modify it.

// api.jsexport default {
saveOrder(orderData) {
const url = `${process.env.API_URL}/orders`;
// do POST request to URL
}
}
// OrderForm.tsx
import api from "path/to/api.js"
function OrderForm() {
submitOrder(orderData) {
api.submitOrder(orderData) …

Is it worth using Apollo with Saga

Long-time ago there was a post — Apollo Client: GraphQL with React and Redux from Sashko Stubailo. He claimed Apollo gave us simple, transparent data flow. And yes… hard to disagree. Nowadays apollo provides super simple hooks

function Dogs({ onDogSelected }) {
const { loading, error, data } = useQuery(GET_DOGS);
if (loading) return 'Loading...';
if (error) return `Error! ${error.message}`;

return (
<select name="dog" onChange={onDogSelected}>
{data.dogs.map(dog => (
<option key={dog.id} value={dog.breed}>
{dog.breed}
</option>
))}
</select>
);
}

You get data directly in your component and don’t care about writing/reading it from the redux state.


Problem

Let’s take a very common example when we have 1:M relation between 2 tables.

And we need to test postsupdates. Let’s imagine how our test would look in the simplest version.

We need to seed some initial data - fixtures. So we can test updates of the existing post. But the problem is —when our table grows we need to add more initialization code.

The other thing is the related tables. Basically we don’t needusersrecord to be presented in the DB for our test. But the foreign key in the posttable requires users record. …


Problem

React effectively has dependency injection built-in. Dependencies are essentially injected via properties.

It’s possible to inject scalar data and functions, or services that will be responsible for logic that remains outside of the component.

Why this approach doesn’t work.

What if we need to access the history object or a backend / API object that has been initiated in App.ts in a child component.

App -> UpdateProductPage -> ProductForm

It’s a really simple case but in order to use “built-in” React dependency injection, we will need to pass ALL the properties required in child components from App to the very last item in the chain…


Let’s think about an alternative approach to build your sagas.

How do your sagas look like?

Let’s take some common scenario — you have a form that updates a product/user/whatever via backend API. I assume you have something like this

Why does it look like this and not otherwise? The answer is quite obvious — because it’s how it’s suggested in official docs. And that’s why we do the same :)

What’s wrong with it?

This approach works well for a demo. But in real life things get complicated. In real life, you will have much more sagas and configureSaga function will grow a lot. Saga registration and management become uneasy but still, it’s not a big issue.

The…

Sergey Radzishevskii

Enjoy turning complex systems into intelligible architectures chilling in my garden.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store