按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
with a specific ponent。 You knew which type to instantiate; which interface to use; and
which project to reference。 In these cases; you; as the developer; are in plete control; and
when your application is built; all of the assemblies pop out as a nice; neat package。
But what works for the developer might not necessarily work for others。 Let’s go back to
the lighting system presented in Chapter 8。 We created a kernel that was responsible for turning
on and off the lights。 The implementations of the individual rooms were in a predetermined
project with a specific name。 This architecture would not work with a third…party library; because
the kernel expected a project of a certain name。 You might be thinking; “Heck; that’s easy to
solve—I just delete the old project and rename my project to match the old name。” That tech
nique would work; but it would also be an administrator’s nightmare。 The solution is to tell the
program; “For lighting room implementations; look at this project and these types。” And to
give the program this information; you define some text in a file。 A file that tells a program to do
some task is called a runtime configuration file。
This chapter focuses on two areas: using application configuration files and dynamically
loading code。 A related topic is how much dynamically executed code should be configuration
and how much should be convention。
Convention over Configuration
The question of how to reference and instantiate classes is both philosophical and pragmatic。
Consider the architecture shown in Figure 12…1; which is a modular interface and implementation
that was presented as an alternative architecture for the lighting system example in Chapter 8。
In this figure; each of the boxes represents a single project: a project that contains the interface
definitions; a project that contains the implementations; and a project that contains the kernel。
The idea of all of these projects is to make it possible to update a single project without needing
to update all of them。 However; what is not indicated in the picture is the fact that your appli
cation must be able to reference all three projects。 If one of those projects is missing; you have
a problem; because your program cannot function。
313
…………………………………………………………Page 336……………………………………………………………
314 CH AP T E R 1 2 ■ L E A R N I N G A B OU T A PP L I CA TI O N CO N F I G U R AT IO N AN D D Y N A M I C L O AD I N G
Figure 12…1。 How ponents can be defined
The referencing of individual projects is not an issue。 The issue is how each project learns
about the others。 In previous chapters; I said that you should use a factory; because a factory
takes away the decision of what implementation to use。
Let’s look at this from the perspective of code。 Suppose the following interface definition
is in a project that contains all interface definitions。
Public Interface IMyInterface
End Interface
A class that implements the interface is defined in a project called Implementations。
Class MyImplementation : Implements IMyInterface
End Class
If a class in another project wants to use the functionality of MyImplementation; then this
factory is created:
Public Module Factory
Public Function Instantiate() As IMyInterface
Return New MyImplementation()
End Function
End Module
Because MyImplementation is not declared as Public; the Factory module must be defined
in the project Implementations。 This implies that the project that uses the functionality has a
reference to Implementations。
…………………………………………………………Page 337……………………………………………………………
CH AP T E R 1 2 ■ L E AR N IN G AB O U T AP P L I CAT I ON CO N F IG U R AT IO N A N D D Y N A M IC L O AD IN G 315
Using a factory is acceptable and solves the problem of decoupling so that the user of the
implementation does not need to know about the implementation。 The user does not have to
know the name of the implementation; but does need to know in which project the implemen
tation resides。 This means when you develop the code; you need to reference the appropriate
project while coding。 This is called ponent architecture; in that you decouple the interface
from the implementation; but you couple the projects。
You want to decouple the ponents at runtime (when the application runs) to solve the
problem illustrated in Chapter 8; where we created a lighting kernel; but did not know the lighting
implementations ahead of time。 Using configuration; you could have an end user “plug in” lighting
implementations that are controlled by the kernel。 Developers like to call runtime decoupling
a plug…in architecture ( http://en。wikipedia。org/wiki/Plugin)。 And this is where configuration
and convention e into play。 “Convention over configuration” is a Ruby on Rails philosophy。
The idea is that developers define only the nonconventional parts of their applications。
Decoupling Using a Configuration Architecture
In a runtime configuration scenario; the architecture of Figure 12…1 is not altered; it still has the
definitions; implementations; kernel; and user assemblies。 What is altered is how the references to
each of the pieces are created。
Let’s start with a simple situation。 You have a question; and you happen to know who would
know the answer。 You know the person and you know she has a telephone。 What you don’t
know is her telephone number。 Translated into programming terms; the telephone acts as an
interface