0% found this document useful (0 votes)
5 views18 pages

Technical Overview Document - Juan Molina

This document provides a technical overview of two projects by Juan A. Molina, focusing on his experiences as an entry-level developer. The first project involves improving code quality and implementing object-oriented programming principles in Unity3D games, while the second project details the installation and configuration of a full-stack web application with a database on a Linux system. Molina expresses his desire to continue growing and learning in his field, particularly at the University with CADSWES.

Uploaded by

officialmaxiani
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views18 pages

Technical Overview Document - Juan Molina

This document provides a technical overview of two projects by Juan A. Molina, focusing on his experiences as an entry-level developer. The first project involves improving code quality and implementing object-oriented programming principles in Unity3D games, while the second project details the installation and configuration of a full-stack web application with a database on a Linux system. Molina expresses his desire to continue growing and learning in his field, particularly at the University with CADSWES.

Uploaded by

officialmaxiani
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 18

---------------------------------------------------------------------------------------------------------------------

Technical Overview Document


By Juan A. Molina

Intro:
The purpose of this document is to provide a brief overview of the main projects I have
participated in building during the past years.
Instructions:
The structure and steps for this document will be as follows:

1. It will be divided into 2 specific projects.


a. Project #1
b. Project #2

2. Each project will start with an example as:


a. Problem.

3. Provide a solution that includes:


a. Description.
b. Items used.

4. Steps of the process that can include:


a. Analysis.
b. Images.
c. Source code with explanations.
d. Challenges and discussions.

Final message:
Before you begin, I want to say that I am still an entry-level developer maturing and I
worked with other lead developers who advised me. However, I do want to say that I
gained plenty of experience and to master basic and intermediate understandings.
Part of why I want to work at the University with CADSWES is because I want to keep
growing, learning and apply new skills alongside the specialization of my master’s
degree.

Thank you!
---------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------
Project #1
Games in Unity3D

Problem:
When I first started at the Bolder Game’s organization, the previous DevOps and some
senior developers quit. They left a project that was malfunctioning, had no proper
documentation and games with old code. The principal was worried the projects would
shut down and eventually die because it had no adaptability and readability for future
developers.

Solution:
Therefore, I decided to improve the code quality by implementing the right OOP
principals and re-make old games. To do this, I had to inspect and refactor code,
implement new UI and non-UI elements, and run tests on specific chunks of code for
games built in Unity3D. I had to completely restructure existing C# code to improve its
design while preserving functionality.

Items used:
a. SOLID principles.
b. C# writing standards.
c. UI and C# events.
d. Unit Testing.

Process:

Assignment #1: Refactor code

As a small example, in one of the games there was a functionality to highlight a material
on selection. It was a manager script with more than 100 lines of code (not good), so I
decided to apply the object-oriented paradigm.

The selection class basically was responsible of three things. Selecting, deselecting and
listening to a ray from the virtual camera every frame to decide selection.

Here is the example:

using UnityEngine;

public class SelectionManager : MonoBehaviour


{
[SerializeField] private string selectableTag = "Selectable";
[SerializeField] private Material highlightMaterial;
[SerializeField] private Material defaultMaterial;

private Transform _selection;

private void Update()


{
if (_selection != null)
{
var selectionRenderer = _selection.GetComponent<Renderer>();
if (selectionRenderer != null)
{
selectionRenderer.material = defaultMaterial;
}
}

var ray = Camera.main.ScreenPointToRay(Input.mousePosition);

_selection = null;
if (Physics.Raycast(ray, out var hit))
{
var selection = hit.transform;
if (selection.CompareTag(selectableTag))
{
_selection = selection;
}
}

if (_selection != null)
{
var selectionRenderer = _selection.GetComponent<Renderer>();
if (selectionRenderer != null)
{
selectionRenderer.material = highlightMaterial;
}
}
}
}

1. I first applied the single responsibility principle rule which says that every class
should be responsible only for a single piece of function. Hence, I break the
selection manager down on what is doing in each part.

using UnityEngine;

public class SelectionManager : MonoBehaviour


{
[SerializeField] private string selectableTag = "Selectable";
[SerializeField] private Material highlightMaterial;
[SerializeField] private Material defaultMaterial;

private Transform _selection;

private void Update()


{
// Deselect/Selection Response
if (_selection != null)
{
var selectionRenderer = _selection.GetComponent<Renderer>();
if (selectionRenderer != null)
{
selectionRenderer.material = defaultMaterial;
}
}

#region Creating a Ray and determining selection on what ray hits

var ray = Camera.main.ScreenPointToRay(Input.mousePosition);

_selection = null;
if (Physics.Raycast(ray, out var hit))
{
var selection = hit.transform;
if (selection.CompareTag(selectableTag))
{
_selection = selection;
}
}
#endregion

// Deselect/Selection Response
if (_selection != null)
{
var selectionRenderer = _selection.GetComponent<Renderer>();
if (selectionRenderer != null)
{
selectionRenderer.material = highlightMaterial;
}
}
}
}

2. Then I make responsibilities into their own method, so the selector manager is
responsible only to delegate tasks. Then start to follow the open/close principle
to simply open a new method for modification to extend without having to add
more code.

using UnityEngine;

public class SelectionManager : MonoBehaviour


{
[SerializeField] private string selectableTag = "Selectable";
private HighlightSelectionResponse _selectionResponse;
private Transform _selection;

private void Update()


{
// Deselect/Selection Response
if (_selection != null)
{
_selectionResponse.OnDeselect(_selection);
}

#region Creating a Ray and determining selection on what ray hits

// Deselect/Selection Response
if (_selection != null)
{
_selectionResponse.OnSelect(_selection);
}
}
}

internal class HighlightSelectionResponse : MonoBehaviour


{
[SerializeField] public Material highlightMaterial;
[SerializeField] public Material defaultMaterial;

public void OnSelect(Transform selection)


{
var selectionRenderer = selection.GetComponent<Renderer>();
if (selectionRenderer != null)
{
selectionRenderer.material = this.highlightMaterial;
}
}

public void OnDeselect(Transform selection)


{
var selectionRenderer = selection.GetComponent<Renderer>();
if (selectionRenderer != null)
{
selectionRenderer.material = this.defaultMaterial;
}
}
}

3. Next I applied the Liskov substitution principle to take advantage of the


polymorphisms of the object-oriented paradigm. Therefore, I derived an
interface from the behavior and rely on that interface to be completely
replaceable.

internal interface ISelectionResponse


{
void OnSelect(Transform selection);
void OnDeselect(Transform selection);
}

4. Then I implement brand new behavior without having to extend the selection
manager. Following again the open and closed principle.
public class OutlineSelectionResponse : MonoBehaviour, ISelectionResponse
{
public void OnSelect(Transform selection)
{
var outline = selection.GetComponent<Outline>();
if (outline != null) outline.OutlineWidth = 10;
}

public void OnDeselect(Transform selection)


{
var outline = selection.GetComponent<Outline>();
if (outline != null) outline.OutlineWidth = 0;
}
}

5. Then split up the interface selection manager to sperate responsibilities that get
their own interface. Which follows the interface segregation principle of saying
that you can take more advantage of the nature of object-oriented design by
having many specific interfaces.

internal class HighlightSelectionResponse : MonoBehaviour, ISelectionResponse


{
[SerializeField] public Material highlightMaterial;
[SerializeField] public Material defaultMaterial;

public void OnSelect(Transform selection)


{
var selectionRenderer = selection.GetComponent<Renderer>();
if (selectionRenderer != null)
{
selectionRenderer.material = this.highlightMaterial;
}
}

public void OnDeselect(Transform selection)


{
var selectionRenderer = selection.GetComponent<Renderer>();
if (selectionRenderer != null)
{
selectionRenderer.material = this.defaultMaterial;
}
}

6. Finally, all the selection manager now depends on is an abstraction of selection


response and not a concrete/absolute behavior; it just knows that on deselect it
will have a different behavior somewhere else in the code. This follows the
dependency inversion principle.

This way in the future I can add new behavior that can simply inherit from the universal
interface and I do not need to extend the class by adding more lines of code.
Assignment #2: Create unit tests and clean code

One of the games had a health system for a player class that showed the change by a
heart image and text. In order for me to test the function, I decided to write a unit test
function and algorithm.

1. First, I start by creating a Test Script.


a. Delete everything
b. Add the using statements for the namespace that I need

using NUnit.Framework;

public class TestPlayer {


}

2. Write a Summary
a. Write a suppose statement.
b. Write goal assignment.
c. State a problem to prove from the assignment.
i. How this will help me write the code for the assignment.
d. Write a list of requirements.
i. Parameters.
ii. Methods.

/// <summary>
/// Suppose: What if a player increases its health and gets shown in the UI?
/// Goal: Display a health bar in the form of text and image for a player.
/// Problem: Can health be increased using text and image feedback?
///
/// List of requirements:
/// 1. Player: Class.
/// 3. Heart Graphic: Image
/// 4. Text: Text
/// 5. Increase Method.
/// </summary>

3. Follow my Test Syntax

a. Write [Test] initializer

[Test]

b. Method: Write literally what I need to prove from this test.


public void CanHealthIncrease_By50_WithTextAndHealthFeedback()

c. Assert: Action that will prove test.

Assert.AreEqual(actual: 100.ToString(), expected: _text.text);


Assert.AreEqual(actual: 1, expected: _image.fillAmount);

d. Arrange: Get things I need for test.


i. Also create classes as need
ii. I want to increase health by 50 and see if my image fill would
change and the text.

//ARRANGE
int _health = 50;
float _fill = 0.5f;

var _text = new GameObject().AddComponent<Text>();


_text.text = _health.ToString();

var _image = new GameObject().AddComponent<Image>();


_image.fillAmount = _fill;

Player _player = new Player(_text, _image);

iii. In Unity3D, I needed to add these namespace libraries to access


UI functions like image and text.

using UnityEngine;
using UnityEngine.UI;

iv. Then I create the player class inside this same test script, following
the Open/Close Principle. With its constructor that I know deals
with a text and an image. Also, include a increase health method.

internal class Player


{
private Text _text;
private Image _image;

public Player(Text text, Image image)


{
_text = text;
_image = image;
}

public void IncreaseHealth(int amount, float fill)


{
int sum = 50 + amount;
_text.text = sum.ToString();
_image.fillAmount += fill;
}
}

e. Act: On the question.

_player.IncreaseHealth(50, 0.5f);
f. Use Test Runner. In the editor of Unity3D I could run these tests and see
if my test script would be successful.

public void CanHealthIncrease_By50_WithTextAndHealthFeedback()


{
//ARRANGE
_text.text = 50.ToString();
_image.fillAmount = 0.5f;

//ACT
_player.IncreaseHealth(50, 0.5f);

//ASSERT
Assert.AreEqual(actual: 100.ToString(), expected: _text.text);
Assert.AreEqual(actual: 1, expected: _image.fillAmount);
}

After I was done doing the test script, I went and refactored the code to improve the
design.

4. Clean code
a. Start noticing patterns
b. Adding regions.
c. Add Global Parameters

public class TestPlayer


{
#region Global Parameters
private Image _image;
private Text _text;
private Player _player;
#endregion

d. Add Setup for function to run before test.

[SetUp]
public void BeforeTests()
{
_image = new GameObject().AddComponent<Image>();
_text = new GameObject().AddComponent<Text>();
_player = new Player(_text, _image);
}
e. Following the SOLID principle of Liskov Substitution Principle and Derive
Inversion Principle.

i. I separate responsibilities to each get their own interface to inherit


from the same base class in order to avoid concretions.

#region Health Methods


public class IncreaseHealthMethods: TestPlayer {
}
#endregion

f. Follow the Single Responsibility Principle and Interface Segregation


Principle.

i. Separating the internal player his own Player.cs script.


ii. Extracting an interface from the player class to separate specific
interfaces. This way what if we need to test more objects in our
game like monsters, NPCs, etc. It can inherit from the same player
interface.

public interface IPlayer


{
void IncreaseHealth(int amount, float fill);
}

using UnityEngine.UI;

public class Player : IPlayer


{
private Text _text;
private Image _image;

public Player(Text, Image image)


{
_text = text;
_image = image;
}

public void IncreaseHealth(int amount, float fill)


{
int sum = 50 + amount;
_text.text = sum.ToString();
_image.fillAmount += fill;
}
}
g. Final TestPlayer.cs

Assignment #3: UI of Re-make of Tablet Game for Kids

As I was re-making one of their old tablet games. One of the challenges was that how
was I going to translate an entire old swift code game from MAC. Well I simply decided
to implement that from scratch with the help of Unity3D’s editor-based UI system

Here is the basic UI example.


1. To start, I designed on paper that I wanted to include a MenuController.cs
manager that would handle the entire UI as its sole responsibility.

a. Then would have independent functions to handle specific buttons in the


UI, like this one triggering the info button. I would change the menu to the
info menu by deactivating or activating game object.
/// <summary>
/// Trigger opening info.
/// </summary>
public void OpenInfo()
{
if (infoMenu != null)
{
mainMenu.SetActive(false);
infoMenu.SetActive(true);
}
}

2. With the Unity graphical editor UI system, I added a button function component
that has an OnClick() event that calls my menu controller script.
Then I was challenged with how I would make the game know when the info or the help
menu are closed, etc. Therefore, I decided to make non-UI event for this case by an
event delegate model with C#.
1. I first created a new class that would handle events as a service for my scripts.
This would act as a listener for references of event methods. In this case of
closing.
public class ListenerInfoMenu : MonoBehaviour
{
public EventContainer containor; // may assign from inspector

void Awake()
{
containor.OnClose += Containor_OnClose;
}

void Containor_OnClose(float obj)


{
Debug.Log("Info Menu Closed and called at : " + obj);
}

2. Then, I simply added action events to my MenuController script, acting as an


object to fire and signal the occurrence of an action.

public class MenuController : MonoBehaviour


{
public event Action<float> OnClose;

void Close()
{
Debug.Log("OnClose event fired");
if (OnClose != null)
{
OnClose(Time.time); // passing float value.
}
}
}
--------------------------------------------------------------------------------------------------------------------
Project #2
Install Full Stack Web Application with Database in Linux Distro

Problem:
The Bolder Games organization was almost at the end of an important product delivery
of a war simulation for one of their clients. The engineering principal was worried
because still at that point, they had not been successful to provide a successful end-to-
end test. Moreover, they needed to show an automated build service of the product to
compete with others.

Solution:
Therefore, I volunteered to provide him a solution to acquire its end-to-end test by
learning and helping to install and configure an object-relational database with an
intelligence web application on a Linux distro virtual machine.

Items used:
a. PostgREST databse that extends and uses SQL.
b. Apache Superset web application that integrates SQL speaking relational
data bases for with Object-Relational query databases and provides with
an intelligent environment for visualizations of the data.
c. VirtualBox to create Virtual Machine of Ubuntu OS.
d. Docker container.
e. Object Relational Database knowledge.

Process:

Assignment #1: Install and Configure ORDB with Superset on Linux Virtual Machine

First, I decided to start by planning out the design as the first consideration. From the
data storage container with the PostgREST database to the superset web application
that will show data visualizations inside web client with Mapbox.

Also, consider the purpose of this DB which is to portray data visualizations based on
metrics gained from a war simulation.

Diagram:
Then, we considered the metrics we needed to use also to decide the naming
convections and datatypes to use when designing the schematics for the database.

Confirmed Metrics:

1. Fuel consumption: FLOAT


2. Ammo consumption: INT
3. Start Time: TIMESTAMPTZ
4. Location (longitude / latitude): REAL
5. Distance (change in longitude / latitude): UNSIGNED_FLOAT
6. Weapon: VARCHAR(100)
7. Id: SERIAL PRIMARY KEY
8. CREATE TYPE SCOPE_TYPE AS ENUM ('MEU', 'battalion', 'company');
9. CREATE TYPE TEAM_FORCE_TYPE AS ENUM ('red_team', 'blue_team');
10. CREATE TYPE COMMAND_TIER_TYPE AS ENUM ('unit', 'fire_team', 'squad',
'platoon', 'company', 'battalion');
Also, as part of me creating an end-to-end test, I had to install an entire full-stack pipeline
inside a Linux VM

Then installed superset inside a Docker container. That packages software into
standardized units called containers that have everything the software needs to run
including libraries, system tools, code, and runtime. The advantage of doing this is that
it makes it easier to deploy and run applications repeatably.

$ sudo docker-compose run --rm superset ./docker-init.sh


We discussed maybe starting with MongoDB, this is where my application stores data
document-based way.

1. An advantage is that it stores data on disk in the binary json format pretty well
which provides support for various data types to be nested inside each other.

However, the disadvantage in our case was that MongoDB is not relational, so we would
not be able to exchange or join. And, we knew that we were going to need queries to
manipulate data and that our data would be changing from the simulation!

So, we determined the usage pattern for this database can be simple as data stored in
object tabular form with postgREST and superset because it would create an object
relational database.

Example of Database Creation Script w/ Units Table Creation:

CREATE DATABASE tripoli;


\c Tripoli

CREATE SCHEMA tripoli;

DROP TABLE IF EXISTS tripoli.units CASCADE;

CREATE TABLE tripoli.units


(
id SERIAL PRIMARY KEY,
designer_config_id INT NOT NULL,
unit_type_id INT,
unit_group_id INT,
starting_pos_lat REAL,
starting_pos_lon REAL,
FOREIGN KEY (designer_config_id) REFERENCES tripoli.designerConfig (id) ON DELETE CASCADE,
FOREIGN KEY (unit_type_id) REFERENCES tripoli.unitTypes (id),
FOREIGN KEY (unit_group_id) REFERENCES tripoli.unitGroups (id)
);

grant all on tripoli.units to tripoli_role;

GRANT USAGE, SELECT ON SEQUENCE tripoli.unitTypes_id_seq TO tripoli_role;

List of Relations:
Then by installing a postgREST database with a REST API which for its database access.

With this, our chosen relational database (postgREST) with the basic form of tables
containing rows and columns components can be combined with an object-oriented
database model in its schemas by its modeling function. By providing the connection of
a relational database system and the mapping of the relational model thanks to the
apache superset web application. This is when object-relational databases come in
handy to fit purely relational databases into the object-oriented frameworks.

Superset Web Interface:


http://localhost:8088/

--------------------------------------------------------------------------------------------------------------------

You might also like