Your project this week is to build anything you like as long as it meets the technical criteria below. It should still be a Node/Express server-rendered application with a SQLite database, but feel free to get creative with the ideas.
This week is the culmination of your Express learning, so focus on doing everything as professionally as you can. Your app should have validation, error-handling, good user-experience etc.
Your project should include at least one of these new topics. You'll have to spend some time researching them in your group, figuring out how exactly to implement them before you start working on your project. There are minimal examples provided, but they are only one way to approach it—you should look for tutorials/blog posts etc with alternative solutions and find one you like.
Allow users to upload files to your server (like images or audio clips). View file upload example | View code
Allow users to log in using 3rd party accounts like Google or GitHub. View GitHub login example | View code
Show temporary messages after successful/failed form submissions to help the user understand what's happening. Note that this is a little complex to manage on your own: you may want to use a session middleware library from npm. View flash message example | View code
A programming paradigm is a way of thinking and structuring code that provides guidelines and patterns for solving problems. It encompasses a set of principles and techniques that determine how software is designed, organized, and executed.
Imperative
Procedural
Object-Oriented
Declarative
Functional
Logical
Reactive
Event-driven
Concurrent
Parallel
Domain-Specific
This is not an exhaustive list of all the paradigms that exist, however they are some of the more popular ones.
We will be focusing on the following 3:
Imperative
Declarative
Reactive
Imperative programming is a programming paradigm where programs consist of a sequence of instructions that explicitly state how to achieve a desired outcome. It focuses on changing the program's state through direct manipulation of variables and control flow structures.
Let's say you have a recipe for making a sandwich. In an imperative programming paradigm, you would follow a sequence of steps explicitly stated in the recipe to achieve the desired outcome of making the sandwich.
Gathering the necessary ingredients (bread, lettuce, tomatoes and mayonnaise)
Spread mayonnaise on the bread
Add the lettuce and tomatoes
Assemble the sandwich.
In this example, the recipe serves as the sequence of instructions, and you are following those instructions step by step to achieve the specific outcome of making the sandwich. Each action changes the state of the sandwich (adding ingredients, spreading condiments) until the desired state (a complete sandwich) is reached. This illustrates the imperative programming paradigm's characteristic of explicitly stating and executing a sequence of instructions to accomplish a specific task.
Let's look at a simple coding example that calculates the factorial of a number
In this example, the factorial() function calculates the factorial of a given number using an iterative approach. It initializes a result variable to 1 and then uses a for loop to multiply result by each number from 1 to n.
The code follows a sequence of steps explicitly defined in the function, executing each instruction in order to achieve the desired outcome of calculating the factorial. It represents the imperative programming paradigm by explicitly stating how to accomplish the task and manipulating the program state (the result variable) to achieve the desired result.
Declarative programming is a programming paradigm where programs specify the desired outcome or goal without explicitly stating the control flow or steps to achieve it. It focuses on describing what should be done rather than how to do it.
Consider a shopping list. Instead of specifying the exact steps to go to the store, navigate through aisles, pick up items, and pay at the counter, a declarative approach would be to simply list the items needed and let someone else handle the implementation details.
Milk
Eggs
Bread
Orange Juice
Let's look at a simple coding example that filters even numbers from an array
In this example, the filter() method is used to declaratively specify the desired outcome of extracting even numbers from the numbers array. By providing a callback function that checks if a number is even (num % 2 === 0), the filter() method takes care of iterating over the array, executing the logic, and returning a new array with the filtered results.
The code expresses the desired outcome (filtering even numbers) without explicitly stating how to perform the iteration or filtering. The declarative programming paradigm allows us to focus on the "what" (filtering) rather than the "how" (iteration and condition), letting the underlying implementation handle the details.
** Imperative **
Here you're giving the function specific instructions to create a div with the class "box" and contain a "Hello World" message.
** Declarative **
Whereas, with declarative programming you define the div element's className as "box" yourself, without giving instructions on how that div should be created.
Pros:
Simplicity: Declarative programming simplifies code by focusing on the desired outcome rather than the detailed steps, making it easier to read, understand, and reason about.
Abstraction: Declarative code promotes abstraction and encapsulation, allowing for reusable and modular components that can be composed to solve complex problems.
Cons:
Learning Curve: Declarative programming may require a shift in thinking and understanding higher-level abstractions, which can initially be challenging for developers more familiar with imperative paradigms.
Limited Control: Declarative code abstracts away control flow and implementation details, which can be limiting in certain scenarios where fine-grained control or performance optimizations are required.
Pros:
Control: Imperative programming provides fine-grained control over the execution flow, allowing developers to explicitly define the sequence of steps to achieve a desired outcome.
Flexibility: Imperative code can be more flexible and adaptable, as it allows for direct manipulation of program state and detailed control over low-level operations.
Cons:
Complexity: Imperative code can become complex and harder to reason about as programs grow in size and complexity. The explicit control flow and mutable state can lead to code that is harder to understand and maintain.
Code Reusability: Imperative code often tightly couples the logic with the specific implementation, making it less reusable in different contexts or for different tasks.
Reactive programming is a way of writing code that focuses on how data changes and flows over time. It allows developers to easily define and handle data streams in a way that is responsive and event-driven.
Here are two example of some code that take a name as a parameter and will output a h1 message "Hello, {name}".
In the above example, we utilize JSX syntax, which is commonly associated with React. JSX allows us to write HTML-like code within JavaScript, making it easier to define and render components. The Greeting component is defined as a function that receives a name prop and returns an HTML element. The App component renders the Greeting component with the name prop set to "John".
The above code example is written using vanilla JavaScript but achieves the same result as the JSX example. The Greeting component is defined as a function that creates a new HTML element, sets its text content, and returns it. The App component creates an instance of the Greeting component, appends the returned HTML element to the document body.
Comparatively, the JSX approach provides a more intuitive and concise syntax, resembling HTML, and simplifies the process of creating components.
In vanilla JavaScript, the equivalent code requires manual element creation, manipulation, and appending to the DOM.
JSX, with the help of a tool like Babel, transpiles the code into plain JavaScript, but it enhances the readability and maintainability of the code for developers working with React or JSX-based frameworks.
Amazon CloudWatch is a monitoring tool used to collect and visualise real-time logs, metrics, and event data in automated dashboards.
A quick overview of different programming paradigms with code examples.
An overview of programming paradigms with coding examples in different languages such Visual Basic, C and Fortran.
A fun little video explaining some of the programming paradigms not covered in this section.
This document provides an in-depth exploration of single-page applications (SPAs) and their role in modern web development. A particular focus is placed on the React framework, which has significantly influenced the way SPAs are developed.
The history of web development is marked by a shift from server-side rendering to client-side rendering, where much of the application logic now runs in the browser, leading to the development of SPAs.
Historically, web development relied heavily on server-side rendering. In this model, when the browser requested a page, the server processed that request and responded with HTML for the browser to render. The browser acted as a "thin client," meaning it simply displayed what the server gave it and handled minimal logic.
Client-side JavaScript was used to add a layer of interactivity (like modals) to the page, but the majority of the heavy lifting was done on the server side, with HTML serving as the source of truth*.*
Advantages of SSR:
Simplicity: Browsers automatically handle a plethora of tasks, reducing the need for developers to implement complex features via JS.
Imagine implementing links using JS. It’s easy to miss but native elements like <a>
and <form>
handle a lot of complexity.
Language Flexibility: Server-side code can be written in any language, including PHP, Ruby, Python, Java, etc., providing a broad selection for developers.
Hardware Power: Web servers typically run on powerful dedicated hardware, while client-side code runs on the user's device, which can often be an underpowered mobile phone.
Security: Server code is hidden from the user, preventing access to sensitive data and secrets, and ensuring a higher level of security compared to client-side code.
Disadvantages of SSR:
Perceived Performance: Every interaction with the site requires a request to the server and back. Full page loads can make the site feel slower to users.
Limited Interactivity: Building dynamic, interactive applications that can compete with native applications is more challenging.
Server Maintenance: Deploying, securing, and maintaining a server can be expensive and complex, especially for popular sites.
Separate Developer Skill Sets: Historically, backend and frontend development were separate skill sets, often requiring two teams to write in two different languages, which can be inefficient and costly.
With SPAs, all application logic runs in the browser, and only one HTML page (index.html
) is requested. Following this, all routing and templating occurs in the browser via JavaScript.
While database access is still server-side (for security reasons), all application logic and templating occur in the browser. The application fetches JSON data from servers (either third-party or owned) and uses this data to render dynamic Document Object Model (DOM) content. In this model, JSON becomes the source of truth.
Advantages of SPAs:
Perceived Performance: SPAs don't require full page reloads for small changes, and fetching JSON to update a section can feel faster to users.
Interactivity: More dynamic interactions are possible with SPAs. Features such as list filtering, element deletion, and animated transitions become easier to implement.
Reduced Server Needs: If an SPA uses third-party APIs, it doesn't need a server of its own. Free static hosts like Netlify can host the HTML, CSS, and JavaScript files, bypassing the complexities and expenses of server management.
Full Stack JavaScript: The same developers can write both the frontend and backend code in JavaScript, increasing efficiency.
Disadvantages of SPAs:
Complexity: Building non-trivial applications in client-side JavaScript can be challenging, particularly when managing the ongoing state of the application.
Mandatory JavaScript: SPAs can only run JavaScript in the browser, which isn't necessarily the best language for certain tasks (e.g., precision currency calculations).
Hardware Limitations: SPAs run on the user's device (often a £100 Android phone with a CPU from 5 years ago), which may not have the processing power of a dedicated web server. JavaScript can be slow to parse and execute on older devices.
Security: All code executes in the browser, which can't hide API keys or validate user input, necessitating a server to ensure security.
Rendering Delay: SPAs initially display a blank page until the JavaScript loads, parses, and executes. JavaScript is the "slowest resource per byte," meaning it takes longer to run 1KB of JavaScript than render 1KB of HTML.
Large Downloads: SPAs require users to download all the application's code, offloading processing from the company servers to the user's device.
Frameworks such as React help manage the complexity of building big applications by providing a shared structure for developers and handling lower-level DOM updates.
Advantages of Frontend Frameworks:
Shared Understanding: A framework provides patterns for structuring code within a team and often has extensive documentation available online.
User Experience: Good frameworks facilitate building cool stuff and can empower newer developers.
Developer Experience: Frameworks can make building complex apps more enjoyable and often come with built-in features that developers want.
Disadvantages of Frontend Frameworks:
Performance: Frameworks are additional code that must load before your own. They can also encourage bad habits leading to bloated apps, e.g. just ****npm install do-the-thing
.
Lock-in: React apps, for instance, can't usually use libraries written for Angular. An organization tends to commit to one technology.
Limited Control: Frameworks like React are built for specific uses (in React's case, Facebook). They might add features you don't need or refuse to add features you want.
React, a JavaScript library for building user interfaces, primarily for SPAs, offers numerous benefits for developers.
Declarative UI: Instead of instructing the browser on each step to render an element, developers can describe it using JSX (JavaScript XML), just like HTML. This approach includes event listeners, making interactions more declarative.
JSX Closeness to HTML: JSX, an HTML-like syntax used with React, allows developers to write HTML structures inside JavaScript.
Component Model: React encourages dividing your app into pieces or "components," each with its markup, styling, and behaviour, providing a logical mental model and encouraging code reuse.
"Just JavaScript": React doesn't require a special templating language. Developers use JavaScript conditionals, variables, and loops to render markup.
"UI as a Function of State": React follows the principle of "UI as a function of state," meaning for any given state, the rendered DOM should always be the same. Developers only need to update the state, and React ensures the UI stays in sync. This approach simplifies the management of the UI based on state changes and allows React to manage the underlying DOM updates.
By focusing on "UI as a function of state," React upholds the idea of "pure functions," where the output is always the same for the given input, and no other part of the system is affected. Thus, the UI is directly derived from the state of the application, simplifying the correlation between the state and what the user sees.
By embracing these features, React provides a compelling case for developers seeking to build robust, interactive web applications that need to manage complex state changes and ensure a high degree of interactivity. React helps abstract away many complexities, allowing developers to focus on building the best possible user interfaces.