I\'m at the point where I\'m getting into the freelance development of some comp
ID: 647437 • Letter: I
Question
I'm at the point where I'm getting into the freelance development of some complex web apps, and I would like to develop a light weight framework for my personal use, but I'd like to get some advice from more experienced programmers first about one aspect of my big-picture design for the framework.
It's heavily prototype / OOP based. The framework is set up to know how to handle each prototype, and to know that certain objects for example, a socketIO construct, can utilize other specific objects, the IP of a server for example, and also the socketPort of that server.
It facilitates this practice with the programmer's own functionality as well, helping to keep all code decoupled, object oriented, and "wireless".
The outcome of this is code that looks "wireless" -- What I mean by that, is instead of passing data as function parameters, the framework's objects know which objects to look for and read from. The developer can pass an object in as the parameter, but if he doesn't the framework will search for it and find it if it exists within the appropriate scope.
Is what I have described a good programming practice/design?
I like the code structure that it helps me to achieve more quickly, but it's important to me that I don't spend time on something that is broken (a bad model).
I want to know if this practice where the data isn't visually passed around / transferred is an acceptable approach to development.
My concern is that the communication between related objects "behind the scenes" may confuse programmers who aren't privy to the design of the framework.
Here's some "mock" client side engine code that would work after the completion of the this framework that I'm currently calling Air JS. It's commented to explain itself, because it's my blueprint, of sorts, so feel free to skim through it without bothering with every detail.
App.Engine = new engine({
/*
Air JS's Engine Model
---------------------
When developing web apps, the engine
gets complex quickly, both on the
client and server side. Without a
framework promoting the use of good
JS OOP coding patterns, the code can
very quickly become a tangled mess!
By utilizing object prototypes, Air
JS accesses relevant objects and will
find things like IPs, Ports,
extensions, and other information
relevant to a specific task, without
the developer needing to manually
connect things. For example, when
creating a socket.IO connection, if
a server object exists that owns a
socketPort object, Air will find the
port! No strings attached.
*/
Server : new server({
/*
The server constructor allows all
relevant server information to be
gathered into one place. Sky JS
objects such as:
socketIO object
AJAX object
that utilize server information
will dynamically locate and utilize
the information "wireless", without
the need to be passed in.
*/
location : new location({
url : new URL("www.website.com"),
IP : new IP("1.2.3.4.5"),
ports : new portList({
default : new defaultPort("8080"),
socket : new socketPort("4545")
}),
paths : new pathList({
app : "App",
login : "Login",
register : "Register",
getData : "Get"
});
}),
auth : new authentication({
username : new username(App.Client.Username),
password : new password(App.Client.Password)
}),
}),
"Socket" : new socketIO({
open : new socketListener("open", function(){
// handle event
}),
}),
/*
The socketIO object expects an object
containing socketListeners as its first
parameter.
The SocketIO object accepts a server object,
portList, socketPort, or port string / int
as its second parameter:
App
Server
App.Engine
App.Engine.Server
App.Engine.Server.ports
App.Engine.Server.ports.socket
"4545"
4545
This is an example of how Air.JS works
"wireless" -- If the relevant object exists
within the same engine, it will be found,
without the developer passing the object or
information in as a parameter. This is called
wireless association in Air JS.
Wireless association will be discussed later
on in this program, and is the primary proponent
of the clean, de-coupled code that Air JS
promotes.
In this situation, the relevant object is a
socketPort. If a server object exists that
owns a portList containing a socketPort,
it will grab the port.
If there are multiple server objects, the
framework will choose the first one that owns
a portList and / or a socketPort.
If no socketList object is found in a server
object, the framework will search the main
scope of the server object. If no socketPort
object is found in a server object, or no
server object is found in the engine object,
the framework will check for a socket object
in the engine object's main scope.
Ultimately,
if no socketObject exists, and the developer
does not provide the port via parameters, an
error will be thrown, pointing to the missing
data.
*/
});
App.init();
The functionality demonstrated here are object prototypes assigned within the framework, as shortcuts. For programmer models of new engine pieces/components, the framework would facilitate the use of objects that "know" certain prototypes. For example, the user creates the prototype Car and lists carDoor as one of its related objects, so a Car instance will look for any carDoors, without the developer feeding it a carDoor through parameters.
Explanation / Answer
This is essentially a dependency injection framework. They are very commonly used in server-side development. Spring and Guice are two frameworks used in the Java world. Grails uses a similar convention as you have defined, specifically injecting ovjects
Dependency injection supports the Inversion of Control principle. This is important for modularity and testability. It promotes self-contained elements that declare the components they depend on, making them easy to mock or stub out for tests as well as making the structure easier to understand.
You've highlighted what, in my opinion, in the greatest weakness of framework driven dependency injection: Programmers unfamiliar with the patterns may have a hard time understanding what's going on, and may start directly instantiating components rather than injecting them. This isn't a problem at my shop since everyone is familiar with the concept. Older versions of Spring used XML to wire objects together rather than annotations to call for components to be injected; this was nice for being able to see the structure of the system but made it difficult to understand individual components.
I recommend you take a look at Angular and Ember, two Javascript frameworks that heavily use dependency injection. If they may meet your needs exactly, you should strongly consider using them to make it easier for other programmers since they have documentation and define their own conventions. This will keep you from having to train as many people on a custom framework.
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.