Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
LanceUy authored Mar 18, 2024
2 parents 87a907a + f07394a commit 9e61f1f
Show file tree
Hide file tree
Showing 183 changed files with 9,015 additions and 101 deletions.
Binary file removed .DS_Store
Binary file not shown.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,25 @@ Potential Topics--
1. Set up
9. Unity
1. Introduction to Unity Basics
2. A Beginner's Guide for Unity UI Design
2. How to Organize Unity Projects
3. A Beginner's Guide for Unity UI Design
4. Unity ML Agents Tutorial
5. Unity 2D Top-down Character Controller Tutorial
10. Python
1. Pythonic iteration patterns
11. Debugging in Python
12. Spring
1. Learning Spring Data JPA
13. TinyMCE API with ReactJS
14. SQL

15. TipTap
16. Tailwind

- Software Tools
1. Git
1. Git Workflows
2. VS Code
- Software Engineering
1. Methodologies & Frameworks
1. Agile
Expand Down
Binary file removed Topics/.DS_Store
Binary file not shown.
4 changes: 3 additions & 1 deletion Topics/Dev_Ops.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
## Resources for Deploying Applications

### [Deploying Django to AWS](./Tech_Stacks/Deploying_Django_to_AWS.md)
### [Deploying Django to AWS](./Tech_Stacks/Deploying_Django_to_AWS.md)

### [Build an Android React Native App Using GitHub Actions](./Tech_Stacks/build-android-app-using-github-actions.md)
6 changes: 5 additions & 1 deletion Topics/Development_Process.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,4 +199,8 @@ This is only a simplification of what "Clean Architecture" is; the topic is so v
### [Intro to Request for Comments (RFCs)](./Development_Process/Technical_Documents/Intro_to_rfcs.md)


### [API documentation with SwaggerHub](./Development_Process/Documentation/Swagger_API_Documentation.md)
### [API documentation with SwaggerHub](./Development_Process/Documentation/Swagger_API_Documentation.md)

## Ubuntu Server Edition 20.04

### [Guide for setting up a home server with Ubuntu Server Edition](./Development_Process/Ubuntu_server_edition/ubuntu.md)
178 changes: 178 additions & 0 deletions Topics/Development_Process/Code Smells/Code_Smells.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# Code Smells

## Table of Contents
1. [What is code smell?](#what-is-code-smell)
2. [Duplicate Code](#duplicate-code)
3. [Improper Names](#improper-names)
4. [Dead Code](#dead-code)
5. [Middle Man](#middle-man)
6. [Feature Envy](#feature-envy)
7. [Long Functions](#long-functions)
8. [Data Clumps](#data-clumps)
9. [Additional Resources](#additional-resources)

### What is a code smell?

Code smells are indicators of potential issues or weaknesses in software code. They are not bugs or errors, but rather patterns or practices that may lead to problems in the future.

## Common Types of Code Smells and How They Can Harm your Code

There are a vast number of code smells and they differ from project to project and developer to developer, and business to business.

So, it is crucial to thoroughly understand the organization’s design and development standards before handling any code smell.

Here are the most common code smells that developers usually encounter with:

### Duplicate Code

In simple terms, duplicate code happens when two code fragments look almost identical. Consider this piece of code:

```
def calculate_rectangle_area(length, width):
return length * width
# Duplicate code
def calculate_square_area(side):
return side * side
```

In this example, the `calculate_square_area` function duplicates the functionality of the `calculate_rectangle_area` function but only for squares. This coding habit makes it harder to debug a program because any changes or bug fixes need to be applied to multiple places. Also, duplicated code makes the codebase harder to read and understand. Developers might need to analyze multiple sections of code that are essentially doing the same thing.

### Improper Names

If your variables, classes, and functions lack proper names, this can be an indicator that your code isn’t clean. For example,

```
def func(a, b):
return a + b
```
This function is simple enough to understand despite its naming issue. However, imagine that we have a big function to perform some backend tasks for our program,
then it would be more problematic for other developers. Without additional context or comments, it's not immediately clear what the function is supposed to do.
This can lead to confusion for others who encounter this code later or who need to work with it.

### Dead Code

Dead code is code that’s in the application but not in use. Here is an example,

```
public class Calculator {
public int add(int a, int b) {
return a + b;
}
// This method is never called, making it dead code
public int subtract(int a, int b) {
return a - b;
}
}
```

The `subtract` method is never called from any part of the application. It remains in the codebase, occupying space and potentially causing confusion for developers who might assume it serves a purpose.

### Middle Man

This code smell refers to a situation where an object or method serves mainly as a pass-through or intermediary, delegating most of its functionality to another object or method without adding significant value or functionality of its own. This can introduce unnecessary complexity and reduce the clarity and efficiency of the codebase.

```
class DataManager:
def __init__(self, data):
self.data = data
def process_data(self):
data_processor = DataProcessor()
return data_processor.process(self.data)
class DataProcessor:
def process(self, data):
# Some complex data processing logic here
processed_data = data * 2
return processed_data
```

In this example, the `DataManager` class serves as a middle man that merely delegates the data processing to the `DataProcessor` class. It doesn't add any additional functionality or logic of its own and exists primarily to pass data to another class.

### Feature Envy

This happens when a method accesses the data of another object more than its own data. Consider this piece of code:

```
class ShoppingCart:
def __init__(self):
self.items = []
def add_item(self, item):
self.items.append(item)
def total_price(self, tax_rate):
total = 0
for item in self.items:
total += item.price
total *= (1 + tax_rate)
return total
class Item:
def __init__(self, name, price):
self.name = name
self.price = price
class User:
def __init__(self):
self.shopping_cart = ShoppingCart()
def calculate_total_price(self, tax_rate):
return self.shopping_cart.total_price(tax_rate)
```

The `User` class has a method calculate_total_price that calculates the total price of items in the user's shopping cart. However, instead of directly accessing the user's shopping cart and performing the calculation there, it invokes the `total_price` method of the `ShoppingCart` class. This leads to poor encapsulation and violate the principle of encapsulation, where each class should encapsulate its own behavior and data.

### Long Functions

Long functions is a code smell that occurs when a function or method is excessively long, containing a large number of lines of code. Long functions can be difficult to understand, maintain, and test. They often violate the Single Responsibility Principle, which states that a function should only have one reason to change.

```
def process_order(order):
# Step 1: Validate order data
if not order:
return None
# Step 2: Fetch product information
product_info = fetch_product_info(order.product_id)
# Step 3: Calculate total price
total_price = order.quantity * product_info.price
# Step 4: Apply discounts
if order.discount_code == 'DISCOUNT10':
total_price *= 0.9
# Step 5: Apply taxes
total_price *= 1.15 # Assuming 15% tax rate
# Step 6: Generate invoice
invoice = generate_invoice(order, product_info, total_price)
# Step 7: Send confirmation email
send_confirmation_email(order.email, invoice)
```

In this example, the `process_order` function performs multiple steps, including validation, fetching product information, calculating total price, applying discounts and taxes, generating an invoice, and sending a confirmation email. The function is long and complex, which makes it difficult to understand and maintain.

### Data Clumps

Data clumps occur when multiple pieces of data go together. One easy way to spot a data clump is when one component doesn’t make sense in isolation but makes sense as a group. Here's an example to illustrate the data clumps:

```
def create_user(name, email, phone):
# Function to create a user using name, email, and phone
pass
def update_user_email(user_id, new_email):
# Function to update user's email
pass
def send_notification(email, message):
# Function to send email notification
pass
```

In this example, the `name`, `email`, and `phone` parameters are frequently passed together in various functions. This suggests that these pieces of data are closely related and should be put together in the same class.


# Additional Resources
1. [Refactoring Guru](https://refactoring.guru/refactoring/smells)
2. [What is a code smell?](https://linearb.io/blog/what-is-a-code-smell)
101 changes: 101 additions & 0 deletions Topics/Development_Process/Docker_AWS_ECR_ECS_CD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# CD for a Dockerized application using Github Actions, Amazon ECR and Amazon ECS

## Introduction
Containerized applications are becoming more popular due to the consistency they provide accross different machines and portability to different cloud providers. It is becoming increasingly valuable to build applications with dockerization in mind. With that comes the need to streamline deployment of these containerized applications.

## Pre-Requisites
- [Dockerizing an app](./Docker.md)
- [Github Actions](./Github_Actions.md)

## Step 1 (Setting up your application & AWS):
- Essentially you want to follow the same steps as this tutorial [Deploy Node.js Docker AWS](./Deploy_Node.js_Docker_AWS.md), adjusting your dockerfile according to language and tools you are using for your application. The main goals are to
- Containerize your application
- Create an amazon ECR repository
- Create an ECS cluster, service as well as task definition

**NOTE**: It's important that your ECR repository and ECS cluster are defined on the same AWS region otherwise you may have to sign into aws twice throughout the workflow


## Step 2 (Setting up the workflow -- triggers):
```
on:
push:
branches:
- production
```
- With the above code we ensure that the workflow created in this guide is run only on pushes to the "production" branch
- Generally you only want to deploy your application on pushes to some branch designated as your production branch to avoid wasting github actions minutes and deploying when development is underway

## Step 2 (Setting up the workflow triggers):
Create a new job
```
jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
environment: production
steps:
```
- We'll be creating a new job called deploy that runs on an ubuntu instance
- All subsequent steps will fall under the "steps:" section in the code block above

## Step 3 (Checking out the repo)
```
- name: Checkout
uses: actions/checkout@v4
```
- Create a new step for checking out the current repo. This ensures that in subsequent steps you have access to all code within your current repo

## Step 4 (Signing into AWS)
```
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@0e613a0980cbf65ed5b322eb7a1e075d28913a83
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: <YOUR_AWS_REGION>
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@62f4f872db3836360b72999f4b87f1ff13310f3a
```
- For details on how to quickly set up your AWS credentials, view the following video: https://www.youtube.com/watch?v=gswVHTrRX8I
- From the above video, you should have recieved an access key as well as a secret access key which you should then set in your [Github Secrets](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions)
- Setting secrets ensures that you have access to your credentials within your workflow without explicitly writing them out in the workflow file
- We are using an action defined by someone else to aid us in signing into aws for subsequent steps

## Step 5 (Building/tagging your image and pushing it to your ECR repo)
```
- name: Build, tag, and push image to Amazon ECR
id: build-image
run: |
docker build -t <ECR_REGISTRY>/<ECR_REPOSITORY>:latest <DOCKERFILE_FOLDER_PATH>
docker push <ECR_REGISTRY>/<ECR_REPOSITORY>:latest
```
- Just like how we build the docker image in order to run a container locally, we should build, tag and push our image to our ECR repository so that ECS can pull from it in a future step
- The `DOCKERFILE_FOLDER_PATH` is the path to the folder containing the dockerfile to build your application
- The `ECR_REGISTRY` and `ECR_REPOSITORY` can be retrieved from the repository URI
<img width="791" alt="Screenshot 2024-03-17 at 9 41 59 PM" src="https://github.com/learning-software-engineering/learning-software-engineering.github.io/assets/58835213/5dd3ce35-6094-48db-980e-a0456becc663">

## Step 6 (Deploying the application)
```
- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@df9643053eda01f169e64a0e60233aacca83799a
with:
task-definition: <PATH_TO_TASK_DEFINITION>
service: <ECS_SERVICE>
cluster: <ECS_CLUSTER>
wait-for-service-stability: true
```
- Once again, using an existing action, we will deploy the app by specifying some additional information
- The task definition, ECS service and ECS cluster are defined as per [Deploy Node.js Docker AWS](./Deploy_Node.js_Docker_AWS.md)
- For `<PATH_TO_TASK_DEFINITION>` you should link to that path of your aws task definition JSON file in your repository. If you don't have one in your repository you can generate one by visiting the task definitions page in Amazon ECS <img width="1022" alt="Screenshot 2024-03-17 at 9 30 22 PM" src="https://github.com/learning-software-engineering/learning-software-engineering.github.io/assets/58835213/8144e7cf-21b7-4c8c-89ad-130e04b5f5a6">


- `wait-for-service-stability` keeps the workflow from passing until the ECS service has become stable given the most recent deployment

## Conclusion
Congrationations, you have reached the end of this tutorial! After a push to your production branch you should be able to sit back and watch your newest workflow deploy your app for you!

## Reference
This guide is inspired by this github actions guide [Deploying to amazon elastic container service](https://docs.github.com/en/actions/deployment/deploying-to-your-cloud-provider/deploying-to-amazon-elastic-container-service)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 9e61f1f

Please sign in to comment.