Website to Web Applications: Lessons from Software Evolution
Why do we need software frameworks?
Why do you think that a code that can be written in 80 to 100 lines should need different, different classes? Or separation of concerns?
For example, here is the code of a simple Node.js program having the user entity and its CRUD operation exposed as REST API using Express Framework.
// Sample Express code snippet handling CRUD for user entity
const express = require('express');
const { Pool } = require('pg');
const app = express();
app.use(express.json()); // Middleware to parse JSON bodies
// PostgreSQL pool connection setup
const pool = new Pool({
user: 'your_username',
host: 'localhost',
database: 'your_database',
password: 'your_password',
port: 5432,
});
// Create a new user
app.post('/users', async (req, res) => {
const { name, email } = req.body;
const query = 'INSERT INTO users(name, email) VALUES($1, $2) RETURNING *;';
try {
const result = await pool.query(query, [name, email]);
res.status(201).json(result.rows[0]);
} catch (err) {
console.error(err.stack);
res.status(500).send('Server error');
}
});
// Get a user by ID
app.get('/users/:id', async (req, res) => {
const { id } = req.params;
const query = 'SELECT * FROM users WHERE id = $1;';
try {
const result = await pool.query(query, [id]);
res.json(result.rows[0]);
} catch (err) {
console.error(err.stack);
res.status(500).send('Server error');
}
});
// Update a user
app.put('/users/:id', async (req, res) => {
const { id } = req.params;
const { name, email } = req.body;
const query = 'UPDATE users SET name = $1, email = $2 WHERE id = $3 RETURNING *;';
try {
const result = await pool.query(query, [name, email, id]);
res.json(result.rows[0]);
} catch (err) {
console.error(err.stack);
res.status(500).send('Server error');
}
});
// Delete a user
app.delete('/users/:id', async (req, res) => {
const { id } = req.params;
const query = 'DELETE FROM users WHERE id = $1;';
try {
await pool.query(query, [id]);
res.send('User deleted successfully');
} catch (err) {
console.error(err.stack);
res.status(500).send('Server error');
}
});
// Start the server
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
It's a single file of application which actually does all the four operations and looks okay to us. Right? It doesn't require any special treatment on the first look.
In a way, if this is the only application you need and the only feature you require, and it's never going to change, you might not need anything else.
In one of my initial companies, we used to create dynamic websites for customers. Back then, websites with typical 4 to 5 pages - homepage, about us, products we offer, contact us - were sufficient.
Clients needed the website just to have an internet presence for their company. So we used to write similar kinds of PHP programs where each file was self-sufficient for that particular page. The database connection, business logic, dynamic text, HTML - all of these things used to be in one single file.
Recommended by LinkedIn
To be frank, the design was not at all an important because the timelines were tight and our company had found a set way of delivering websites. We were asked to deliver projects quickly
In today's world, applications are much more complex than before. Even micro-applications don't resemble the websites we used to create. We're living in a dynamic world where agility and security are paramount. Software evolves rapidly, necessitating frameworks and principles like SOLID.
In this fast-paced world of software development, embracing frameworks and design principles is not just a choice – it's a necessity. They empower developers to build applications that are not only agile and responsive
In the following articles, we delve into the reasons behind and methods for refactoring applications to enhance their agility and maintainability.
#SoftwareDevelopment #SOLIDPrinciples #Agility #SoftwareEvolution