220 likes | 296 Vues
Web Applications – Design Issues. Data. Requirements Persistent Consistent (no corruption even if server fails) Concurrent updates Transactions Solution: Database Relational or schema-less (Also, SQL is a great DSL for data queries). Distributed Environment.
E N D
Data • Requirements • Persistent • Consistent (no corruption even if server fails) • Concurrent updates • Transactions • Solution: Database • Relational or schema-less • (Also, SQL is a great DSL for data queries)
Distributed Environment • Two Languages, Two processes • No pointers • Speaking in IDs
Entities Need Dedicated IDs (Even if they have unique names) • Domain may change – names may stop being unique • There's a need to support renaming • (But not re-IDing) • Creating a new entity • A temporary name such as "xyz398556" is weird
The Agony of ID-based data • Several objects representing the same entity • (same id) • Each one is updated due to a different client request • Still, they all reflect the same “entity” and should exhibit the same data • References are often useless • Caching & memory managements problems • Counter intuitive to OOP style
Multiple Services • Recall • Entities • Values • Services • Web applications • Many services • Many configurations of services • Configurations • Deployment • Testing • Development • Admin • Console • Database A vs. Database B
Encapsulation • Maintaining consistency of the data • (Invariants) • Example: a vector class • size, items.length need to be aligned class Vector { public Object[] items = new Object[10]; public int size = 0; public void add(Object o) { items[size++] = o; }
Web of objects • OOP: Objects communicating via messages • (Calls to overridable methods) • Some of the objects are likely to be encapsulated • (preserve invariants)
Invariants in Web of Objects • Database Manager • OracleQueryBuilder, OracleDataSource • MySqlQueryBuilder, MySqlDataSource • Communication Channel • XMPPListener, XMPPMessage • …
Example: Model Class • Two fields: queryBuilder, dataSource • Option 1: Initialized inside the class • High Safety: no mismatch • Low flexibility: Hard to reuse/adapt to new contexts • Option 2: Injected from the outside • Not as safe • More flexible
One Computation - Many Webs • Eventually, there is a computation that needs to be carried out • Many options regarding where sub-computations reside • Developer can decide on borders of responsibility
High Fan Out • One object is doing many things • Low cohesion • Fine-grained control – objects can be easily replaced
Low Fan Out (Telescopic Structure) • Difficult to replace an object • (recall: some of these objects are encapsulated) • Often the first object determines the entire chain • Changing an object requires many new subclasses • (Just to override the "new X()" expressions
Static is evil • Static access: • static methods • new X() • super calls • Constructors • form unbreakable links between two pieces of code • Cannot be overridden
Can we Change the value of s in f()?(without re-implementing B.f()) public class A { public String f(String s) { return s.toUpperCase(); } } public class B extends A { @Override public String f(String s) { s = super.f(s); int n = g(s.length()); // do some processing h("s=" + s + " n=" + n); // send it to the output return s; } public int g(int n) { return n*n; } private void h(String text) { System.out.println(text); } } public static void main(String[] args) { B b = new B(); b.f("abc"); // Output? }
Delegation to the Rescue public class B { private A a; public B(A a) { this.a = a; } public B() { this(new A()); } public String f(String s) { s = a.f(s); int n = g(s.length()); // do some processing h("s=" + s + " n=" + n); return s; } // no change in g(), h() } public static void main(String[] args) { B b = new B(new A() { @Override public String f(String s) { return "*" + s + "*"; } }); b.f("abc"); }
Ideal Web • Each object interacts with few collaborators • Doing some work, but not too much • Chains to leaves are not long • Collaborators can be specified from the outside • => Behavior of the web can be tweaked • w/o too much subclassing • w/o reconstructing large (sub) parts of the web • Testability leads to such a structure • (In particular, Mock-based testing) • See also: http://misko.hevery.com/code-reviewers-guide/
Web-of-objects Building Strategies • Hard wired “new” expression – no flexibility • A Typed Singleton factory • A multi-interface Typed Singleton factory • An untyped singleton factory • A propagating factory object • Dependency Injection
Dependency Injection Containers(Java World) • Guice • http://code.google.com/p/google-guice • Spring • http://www.springsource.org • Pico • http://www.picocontainer.org
Dependency Injection • Sometimes called: Inversion of Control • (IOC) • Slogan: "Don’t call us we’ll call you" • (The Hollywood principle) • Class has only setters/constructor args • Completely unaware of a factory • Thus, it is a POJO • Container uses reflection to initialize instances
Benefits of DI • Classes can be used w/o a factory • Explicit (“manual”) injection of dependencies • Support for multiple scopes • Objects are not depending on a factory • Dependencies are explicit in the signatures
Injection Kinds • Constructor • Setter • Field • Lookup key • Type • Name