Dependency Injection
Model, View, Controller, Logic, Handler - a hyper-modular approach to application design.
By extending the MVC architecture to include separate code for the Logic and the Handlers you will have a (relatively) intuitive way to begin exploring modular application design. You'll see how to repackage the same core functionality for deployment in different environments, or how to easily swap out functionality in an application already built for one environment.
You'll be reading, running, diagramming and documenting code. No writing code this time.
Index
Learning Objectives
- Dependency Injection
- App/Component Architecture
- Source code vs. Build-time vs. Run-time
- Core app vs environment
- Reading & analyzing modular projects
- Design Patterns
Dependency Injection
As you've already seen by using pseudocode and using specs to study source code, functionality and implementation are not the same thing. This idea is central to Dependency Injection, also known as "developing to an interface".
A Thought Experiment
Imagine a basic VC application with Controller & View objects. Notice that the controller object needs it's view object to have a function called render that takes in a String. But it doesn't care what that function actually does! :
View: Object
METHODS: 1
render: Function
ARGS: 1
phrase: String
Purpose: To be drawn onto the UI, for the user to see
RETURNS: undefined
BEHAVIOR: Writes _phrase_ into the UI
Controller: Object
PROPERTIEs: 1
view: A view object, as defined above
INITALIZED: empty
METHODS: 1
show_this: Function
ARGS: 1
phrase: String
Purpose: A string to be displayed to the user
RETURNS: undefined
BEHAVIOR: Calls this.view.render() with _phrase_ as an argument.
Let's explore three different implementations of the view object:
let browser_view = {
render: function(phrase) {
let text_box = document.getElementById('text_box');
text_box.innerHTML = phrase;
}
};
let console_view = {
render: function(phrase) {
console.log(phrase);
}
};
let bogus_view = {
render: function(phrase) {
this.render(phrase);
};
};
A controller object would just as happily use any 3 of these objects; all of them match the view specs. They all have a method called "render" that takes in a String. This is developing to an interface. By simply changing which view object our controller has (ie. injecting a dependency), we can run our app in the browser, terminal, or callstack purgatory!
Try it out yourself. Write the controller object and practice using it to write to the DOM or the Console using the view objects provided.
Specifications
No programming here. You'll be reading and analyzing the code provided in this project's repo. The App/Component architecture is a way of organizing code that lets you mix & match functionalities, making it easy to adapt your applications for different environments and use cases.
There are 8 total applications built from reusable components. Each application is significantly different in some little way, though they all use mostly the same source code. Your task is to run, analyze, and document each separate application. Your finished project will be a repository organized with branches. Each branch will analyze a singe application.
The finished product for this project will be a repo with 3 branches:
- A master branch with:
- README: Project overview, links to branches, notes
- 2 code branches - dom-console-node & mix-match-operations. Each will contain:
- A main README
- About this code
- Links to this branch's app files
- Install instructions
- Ascii file structure
- Notes
- A markdown for each app
- About the app
- Purpose, user stories, use cases
- Use instructions
- Sourcecode specs
- Build-time diagram
- Run-time specs
- About the app
- The source code
- A main README
- Get and give at least one code review for this project.
Build-Time Diagram
The build-time diagram is a way for you to explore how applications are dynamically assembled and built when you run them. Understanding this is key to understanding source code, designing applications, and even debugging! If you have difficulty mapping between source code and runtime code even the most basic runtime error can be indecipherable.
You can see an example here.
Resources
Project resources:
Dependency Injection:
- Funfunfunction:
- Dependency Injection
- Inversion of Control (Trickier)
- Fleeboy Article
- Krasimirtsonev
- src specs, build-time, runtime specs
Other Resources:
- Exporting & Requiring
- Navigating CodeBase
- Visualizing Git Branches
- Simpler Code to Practice Reading
- DI & Testing
- JS Runtimes
- What is Node.js
Challenge Articles: