标签:
上学期学的OOP,最近把期末复习笔记拿出来温习,共享一发。
Polymorphism means many different form
If you have inheritance, you have polymorphism
Inheritance
Polymorphism
Abstraction
Encapsulation
Information hiding
Loose coupling
Hello.exe (an executable)
Hello.dll (an assembly of a library)
What is an assembly?
The smallest unit of a binary file in .NET, contains byte code from several source files in a project.
Static means global function
Main() is the entry point of an application
string[] list = { “apple”, “banana”, “cherry” };
List<string> list = new List<string>() { “apple”, “banana”, “cherry” };
Prefer Container over Array
Function overloading à You can have many functions with the same name, as long as their signatures are different. Signature = function name + parameter list.
return value is not part of signature
Single responsibility principle
OPEN-CLOSED PRINCIPLE (Bertrand Meyer)
Closed for modification
Don’t change existing code
Open for extension
Can add new code to satisfy the new requirements
Class level method
static keyword
Invoke by the class name, don’t need an object
E.g. Account.Foo()
Class method cannot have object attributes
If attributes are needed, they must be static
Class level attribute (static attribute)
Global attribute, access by class name
One copy per class
Access by class name, not object name
public methods and properties
Mark all word boundaries in uppercase
e.g. PascalCasing
private interfaces and parameters
first letter is in lowercase
e.g. camelCasing
Since the object’s size may change at run time, the object cannot be stored in the stack
Parameter passing in C# is default by passing value (the copy of it, whatever it is int type or reference type).
Pass by value is safe because the caller’s program is not affected by the method
ref: Pass by reference .If you want to modify caller’s data
in: Parameter is passed by value, the default
out: Same as ref, but caller doesn’t need to initialize the value
params: To pass a varied number of parameters as a single argument
e.g. like the printf() in C
main() {
Account s1=new Account(”001”);
Account s2=new Account(”002”);
Foo(s1, s2); //s1,s2 pass as params list
}
public static void Foo(params Account[] list){
foreach (Account s in list)
Console.WriteLine(s.Id);
}
Why Upcasting is safe –
Because subclass supports all methods in baseclass
Upcasting is automatically allowed
Downcasting is dangerous
Treat baseclass as an subclass(object)
subclass may have more methods than baseclass
baseclass may not be able to support all methods in subclass
Can’t create a baseclass and use it as subclass
class can have both interface and implementation(code)
interface doesn’t have implementation(no attributes and no method detailed code), only function declaration or property
abstract class is a class that cannot be instantiated
The main purpose is to provide a base class that serves like interface, but also can have attribute and code
Difference between interface and abstract class
Interface
No implementation
Cannot be instantiated
Intent: purely for interface inheritance
Abstract base class
Can have interface and implementation
Cannot be instantiated
Solution to the diamond problem
RTTI – run time type identification
Cyclic Dependency may lead to problems
Solution:
No cyclic dependency within an assembly
Then make sure that there is no cyclic dependency (acyclic) between assemblies
Value Type class is a subclass of System.Object that overrides and changes the methods from reference-based to value-based
Shallow copy and deep copy
Shallow copy :
Student s1 = new Student(7,”James”);
Student s2 = s1; //shallow copy
Only the address of s1 is copied to s2
For deep copy, use Clone() in ICloneable
考虑被调用的时候和返回值的时候来理解这个principle。 因为subclass能代替baseclass来执行功能。 baseclass调用的条件一定能适用subclass à subclass weaken pre-condition; subclass 返回值 一定要适用于原本接收baseclass返回值的条件 àsubclass strengthen post-condition |
Example:
Base class--
accept positive real number, return positive real number
Subclass--
Pre-condition
Accept all real number (OK)
Accept positive integer (Not OK)
Post-condition
Return all real number (Not OK)
Return positive integer (OK)
IEnumerable
Can’t use foreach because foreach does not know how to access StudentList since it is a user-defined container
Solution
Implement the IEnumerable interface
GetEnumerator() returns an IEnumerator object that is used by foreach to access the container
public Interface IEnumerable {
IEnumerator GetEnumerator();
}
public class StudentList : IEnumerable {
private ArrayList list;
. . .
public IEnumerator GetEnumerator() {
//return the object that implements IEnumerator
return list.GetEnumerator();
}
}
foreach uses GetEnumerator() to get an IEnumerator object
The IEnumerator object has only three functions, but can be used to get objects in the container one by one
The three functions are
Reset( )- make 1st element as current object
MoveNext()– next object as current object
Current – Property that return the current object
Two keys features in generic programming
Template
Replace type by a parameter
One template for all types
Iterator 迭代
An abstraction of all kinds of sequential containers
It separates algorithms from data structures
Extremely useful
??Delegate object
Design pattern:
Creational pattern:
Parameterized factory methods
Factory method needs a new subclass for new product
Require many subclasses
Parameterized factory method
Use a parameter (instead of a new subclass) to identify a new kind of product
Reduce the number of subclasses
Abstract Factory provides an interface for creating families of related or dependent objects without specifying their concrete classes.(一套的class。 自由组合? Decorator pattern? Prototype (factory)pattern 能自由组合)
(builder 有点像另一个pattern?(答:template pattern,区别见template pattern)确定运作顺序,具体的操作不确定。但是builder仍然是做一套的class.)
Cilent 自己组织由abstractFactory 制作出来的classes。 |
Compare between AbstractFactory and Builder
Builder 最后给的是成品。实际上只是construction的设计区别?不,builder的操作都是内部操作,最后得出的是一个builder.product().通常由director class的一个method来调用builder及设计构造的流程。 http://zhenyulu.cnblogs.com/articles/37378.html
|
Prototype (factory)pattern:
由prototypeFactory 的constructor 引进不同部件的组合。而具体的构造过程,调用了相应部件的clone()。从而实现了部件自由组合的factory method。 |
以上四种pattern的对比总结
Factory Method Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses。
Abstract Factory Provide an interface for creating families of related or dependent objects without specifying their concrete classes。(侧重于一套class,好比一套主题,一套服装搭配。但选用这个套装的哪些组件却由client决定,不是非要一整套全使用。)
Builder Separate the construction of a complex object from its representation so that the same construction process can create different representations。(reuse 构造的过程和顺序,比如炒菜,炒肉片和炒青菜的流程是一样的,但是其中加的原料,佐料却可能不同。最终获得的是完整的一道菜。)
Prototype Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype。(随意自由组合classes,关键在于constructor和clone)
--------------------分割线--------------------------------------------------------------------------
Singleton pattern:
关键在于2个private, 2 个static 和1个public。 |
Structural patterns:
Adapter pattern:两种类型,C#只支持object adapter
Intent
Convert the interface of a class into another interface clients expect.
Adapter lets classes work together that couldn’t otherwise because of incompatible 不相容的 interfaces
How about inherit the old system’s implementation and the new system’s interface? Still has problem - cannot hide the old implementation OldSystem can be exposed by casting ClassAdapter newSystem = new ClassAdapter() OldSystem oldSystem = (OldSystem) newSystem; |
Class and object adapters have different trade-offs.
A class adapter
· adapts Adaptee to Target by committing to a concrete Adapter class. As a
consequence, a class adapter won‘t work when we want to adapt a class and
all its subclasses.
· lets Adapter override some of Adaptee‘s behavior, since Adapter is a
subclass of Adaptee.
· introduces only one object, and no additional pointer indirection is needed
to get to the adaptee.
An object adapter
· lets a single Adapter work with many Adaptees—that is, the Adaptee itself
and all of its subclasses (if any). The Adapter can also add functionality
to all Adaptees at once.
· makes it harder to override Adaptee behavior. It will require subclassing
Adaptee and making Adapter refer to the subclass rather than the Adaptee
itself.
不同的平台用同样的interface实现不同的功能 |
Decorator:
从最特殊的开始,has-a 较普通的;较普通的has-a 更普通的。运作的时候,顺序刚好相反,最普通的先运作···顺序很重要,应确保满足特殊操作的前提条件。在此例中,最后的文字阅读取决于阅读流已经解码。
待补充--- 每次运作,检查携带的decorator是不是null,不是就让它先执行操作;接着执行自己的操作 |
class Program
// In Facade pattern, classes A and B in FacadeDLL assembly are hidden. Only the Facade //object is exposed.
// Facade object is usually a singleton, but it is not implemented here.
{
static void Main(string[] args)
{
Facade facade = Fa?ade.Instance();//singleton
facade.Foo(); // act like a single simple object
facade.Bar();
Mainsystem和subsystem 经常是不在一个assembly里面,在subsystem里创建一个fa?ade class作为public的代表,用has-a的关系调用其他internal class,运用delegate来执行操作。Fa?ade 用singleton来保证唯一性。 |
Console.ReadLine();
}
}
public class Facade //key word -- public
{
A objA;
B objB;
public Facade()
{
objA = new A();
objB = new B();
}
public void Foo()
{
objA.Foo(); //delegate
}
public void Bar()
{
objB.Bar();//delegate
}
}
internal class A //key word -- internal
{
internal void Foo()
{
Console.WriteLine("A Foo() visited");
}
}
internal class B //key word -- internal
{
internal void Bar()
{
Console.WriteLine("B Bar() visited");
}
}
class ImageProxy : Graphic
{
Image image; /* ImageProxy has a pointer to Image */
public override void Draw() /* initially, the new object only has a null reference */
{ /* Only when it is called to execute some function */
/* it create the actual object */
if (image == null)
{ // do all the expensive processing here, e.g. get a large image file
image = new Image()
{
name = "-->large image file created"
精华在于偷懒,一开始放一个廉价的reference,真正被调用的时候才去“抱佛脚”创建真的object |
};
}
image.Print();
}
}
Flyweight:
Behavioral patterns
How to use objects in a collaborative way
The key - identify the responsibilities of the objects```
Command pattern
Some relationship with delegate pattern? |
Chain of Responsibility
Actually, in lecture case, also apply when need to satisfy all nodes’ requirement. |
Core codes:
public override bool Enrol(Student s)/* the parameter is student type*/
{
bool flag = true; //default is true, because enroll is a kind of request should //satifsfy all requirement
if (s.courses.Count > 2)
flag = false; /* the student‘s courses can not be more than 2 */
if (flag == false)
{
Console.WriteLine("University: Enrol failed, university does not allow student to enrol to more than 2 courses");
return false;
}
else if (parent != null) /* i.e.if flag == true,parent!= null */
return parent.Enrol(s); // if flag == true, do further checking with parent
else
return true; /*i.e.if flag == true,parent== null,return true */
}
/* check whether meet with own requirement first,if yes then check the parent‘s */
Another typical example:
public abstract class Handler
{
protected Handler successor; //继承者,及上级或者父级
public void SetSuccessor(Handler successor)
{
this.successor = successor;
}
public abstract void HandleRequest(int request);
}
public class ConcreteHandler2 : Handler //具体的handler
{
public override void HandleRequest(int request)
{
if (request >= 10 && request < 20) //如果请求在其解决能力内,就自行解决
{
Console.WriteLine("{0} handled request {1}", this.GetType().Name, request);
}
else if (successor != null) //如果无法解决,并且拥有上级,那就递交请求给上级
{
successor.HandleRequest(request);
}
}
}
class Program
{
static void Main(string[] args)
{
// Setup Chain of Responsibility
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();
h1.SetSuccessor(h2); //设置好继承者
h2.SetSuccessor(h3);
Chain of responsibility 和 decorator 的区别:Chain of responsibility大部分情况下只需要将请求递交到有权限的handler手里处理了之后,就结束了该流程。Decorator 则需要遍历所有的操作,直到没有下一个decorator。 |
// Generate and process request
int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 };
foreach (int request in requests)
{
h1.HandleRequest(request);
}
}
}
Observer pattern:
Core codes:
C# ‘s delegation pattern ?delegation object ? keyword ?
My own example:
class Program
{
static void Main(string[] args)
{
Calculator cal = new Calculator();
Call myCall = new Call(cal.check);
Console.WriteLine("5 is {0} ", myCall(5));
myCall = new Call(Calculator.flag);
Console.WriteLine("-3 is used {0}", myCall(-3));
Console.ReadLine();
}
}
public delegate string Call(int n); //do not know what exactly “Call” is; seems to be a //class,because can be initialized;also like a //method,because it can accept parameters and return //values.
public class Calculator
{
public string check(int n)
{
if (n > 0) return "positive";
else if (n < 0) return "negative";
else return "zero";
}
public static string flag(int n)
{
if (n > 0) return " + ";
else if (n < 0) return " - ";
else return " 0 ";
}
}
http://www.cnblogs.com/hyddd/archive/2009/07/26/1531538.html
Mediator
// Intent: to communicate via a central coordinator which is called the mediator
// Observer pattern can also be used to communicate between different parties, but it is done
//without a central coordinator
class Program
{
static void Main(string[] args)
{
Director dir = new Director(); //the mediator
Widget listBox = new ListBox(dir);
Widget entryField = new EntryField(dir);
listBox.Changed(); // director is notified, and dir.WidgetChagned(ListBox w) is invoked, and all entryField are notified
entryField.Changed(); // director is notified, and dir.WidgetChagned(EntryField w) is invoked, and all listBox are notified
Console.ReadLine();
}
}
class Director //the mediator
{
List<ListBox> listBoxList = new List<ListBox>();
List<EntryField> entryFieldList = new List<EntryField>();
public virtual void Add(ListBox w) // function overloading
{
listBoxList.Add(w);
}
public virtual void Add(EntryField w)
{
entryFieldList.Add(w);
}
public virtual void WidgetChanged(Widget w) // function overloading
{
}
public virtual void WidgetChanged(ListBox w) //if ListBox change , notify entryField
{
foreach (EntryField item in entryFieldList)
{
item.SetText();
}
}
public virtual void WidgetChanged(EntryField w)
{
foreach (ListBox item in listBoxList)
{
item.GetSelection();
}
}
}
class Widget
{
protected Director dir; // contain a mediator pointer
public virtual void Changed()
{
dir.WidgetChanged(this);
}
}
class ListBox : Widget
{
public ListBox(Director dir) //constructor set up the association with mediator
{
this.dir = dir;
dir.Add(this);
}
public override void Changed() //when changed, notify mediator
{
dir.WidgetChanged(this);
}
public void GetSelection()
{
Console.WriteLine("EntryField changed: ListBox is notified, GetSelection() is updated");
}
}
class EntryField : Widget
{
public EntryField(Director dir) //constructor set up the association with mediator {
this.dir = dir;
dir.Add(this);
}
public override void Changed()//when changed, notify mediator
{
dir.WidgetChanged(this);
}
public void SetText()
{
Console.WriteLine("ListBox changed: EntryField is notified, SetText() is updated");
}
}
Comparision between observer pattern and mediator pattern:
Mediator pattern is a kind of abserver pattern with a central coordinator, and mediator is more indirectional than observer.
Template pattern:
Template pattern somehow like the builder pattern, however builder pattern focuses on creating objects , template pattern could do more. In template pattern, only the methods could be overridden, and the secquencial steps are usually encapsulated inside a method(e.g. Run()) |
与builder的区别:builder的construction流程控制在director class的method里;template的操作流程在自己的run()里。而且,builder的作用是创造一堆object;template 是进行一系列操作。 |
State pattern:
My understanding:
Object à receive a request à delegate to its state by passing itself as parameter(for changeState of object later) à the state override the meaningful request’s handler, process the request and change object’s state by calling object.changeState() OR ignore the meaningless request whose handler method is defaultly defined in state base class.
Note: the state class could use singleton pattern because stateless (have no memory ,no local attributes)
Example codes:
// The state machine below describes the state of a Book
// A book has 2 states - IN or OUT
// If a book is IN, and is invoked by a CheckOut command, then the state changed to OUT
// If a book is OUT, and is invoked by a Return command, then the state changed to IN
// Otherwise any other commands are ignored (e.g. a book is IN, and is invoked by a Return
//command, which is not meaningful
class Program
{
static void Main(string[] args)
{
Book r = new Book();
r.Return(); //ignored
r.CheckOut(); //print CommandAB, move to state B
r.CheckOut(); //ignore
r.Return(); //print CommandBA, move to state A
Console.ReadLine();
}
}
class Book
{
State state;
public Book()
{
state = In.Instance(); //singleton
}
public void ChangeState(State nextState)
{
state = nextState;
}
public void CheckOut()
{
state.CheckOut(this); //delegate to state , and pass itseif as parameter
}
public void Return()
{
state.Return(this); //delegate to state , and pass itseif as parameter
}
}
class State
{ /* Base class TCPState provides the dummy假的 default */
public virtual void CheckOut(Book r) { Console.WriteLine("ignored"); }
public virtual void Return(Book r) { Console.WriteLine("ignored"); }
}
class In : State
{
private static In objectIn;
private In() { } //for singleton
public override void CheckOut(Book r) //only checkout request is meaningful to In state
{
Console.WriteLine("Checkout");
r.ChangeState(Out.Instance());
}
public static State Instance() //for singleton
{
if (objectIn == null)
objectIn = new In();
return objectIn;
}
}
class Out : State
{
private static Out objectOut;
private Out() { }
public override void Return(Book r)// //only return request is meaningful to Out state
{
Console.WriteLine("Return");
r.ChangeState(In.Instance());
}
public static State Instance()
{
if (objectOut == null)
objectOut = new Out();
return objectOut;
}
}
Strategy Pattern:
Use delegation to encapsulate an algorithm so that your software can select between different algorithms flexibly
Compared with State pattern:
Visitor pattern:
to add new functionality to a system.
Node usually has a tree (composite) structure
The visitor object transverses all nodes in the tree
Each node callbacks to the visitor; visitor provides the new functionality
To add new functionality
simply add a new subclass of visitor,
no need to modify the object structure (Node)
Sometime we would like to treat callback from Course and NodeList differently:
Solution by function overloading
Overload the callback function Visit(), so as to treat Course and NodeList differently
class Visitor {
public void Visit(Course n) {//. . .}
public void Visit(NodeList n){//. . .}
}
Another usage of Visitor Pattern – solve Double dispatch 派遣
Cause: C# and Java support only single dispatch . Polymorphism is limited to the type of one object. (In other words, only when the object is the positive method executor, could it perform the factory method(be distinguished and execute different overridden methods))
Solution 1: if-then-else block (…)
But it is low level
Memento pattern:
Participants
· Memento (SolverState)
-- stores internal state of the Originator object.
-- protects against access by objects other than the originator.
(Mementos have effectively two interfaces. Caretaker sees a narrow
interface to the Memento—it can only pass the memento to other objects.
Originator, in contrast, sees a wide interface, one that lets it
access all the data necessary to restore itself to its previous state.
Ideally, only the originator that produced the memento would be
permitted to access the memento‘s internal state.)
· Originator (ConstraintSolver)
-- creates a memento containing a snapshot of its current internal
state.
-- uses the memento to restore its internal state.
· Caretaker (undo mechanism)
-- is responsible for the memento‘s safekeeping.
-- never operates on or examines the contents of a memento
An approximate implementation in C# (Java)
Use internal so that only classes within the assembly can see the hidden information
OR C# Nested Class : A class inside a class, so that the inner class cannot be seen from outside of the class.
Interpreter pattern:
MVC pattern:
Linq Topic:
To add new functionality to an existing type:
1. Visitor pattern
2. Create an external method and pass the Account object to this method
3. Helper Class static method, e.g. Helper.Deposit(Acc,10)
4. Extension method
4.1. Extension method by delegate
4.2. Action - system provided generic delegate
Action – delegate with no return value
e.g. Action <T1>, Action <T1,T2>```
Func – delegate with return value
e.g. Func<TResult>,Func<T1,TResult>,Func<T1,T2,TResult>```
Predicate 断言-- Take an object of type T and return true or false
E,g. Predicate<T>```
4.3. Anonymous method
5. Linq:
List<int> mylist = list.Where(x=>x%2==0).ToList();
Difference between List and IEnumerable:
IEnumerable<int> mylist = list.Where(x=>x%2==0);
Can only supports the IEnumerator’s methods, cannot support indexing, e.g. mylist[2]
Usually work together with foreach
List<int> mylist = list.Where(x=>x%2==0).ToList();
Smart array, support indexing
Linq operations:
1. Filtering -- Current type is not changed, just processed
e.g. List<int> mylist = list.Where(x=>x%2==0).ToList();
e.g. var sortedList = list.OrderBy(x=>x.region).ThenBy(x=>x.branch).ThenBy(x=>x.ID)
2. Projection -- Return a new type
e.g. var idList = list.Select(x=>x.ID).ToList();
// idList is a list of List<string>; Select() actually is not only “selecting” but “converting”
Find the total sum of balance:
Double sum = list.Sum(x=>x.balance);
Find the total sum in every branch office and stored them in a dictionary:
var branchSum = list.GroupBy(x=>x.branch) .ToDictionary(x=>x.Key, x=>x.Sum());
Expression<Func<int, int, int>> f1=(a,b)=>a*b;// Expression<>是种参数为delegate的函数
Func<int, int, int> mult = f1.Compile();//转化为能执行的函数
int result = mult(1,2);
Console.WriteLine(“Result {0}”, result);
(总结:第一步,Expression先定义出具体操;第二步,Compile()转化为能执行的函数;最后,调用函数)
Methodology:
Common 5 stages approach:
1. Requirement model
To capture the users requirements
2. Analysis model
Initial rough model of the system
3. Design model
Detailed model, one-to-one mapping between the classes diagram and the implementation model
4. Implementation model
The code
5. Test model
Use-case approach
Use cases describe how the system is used from a user view point, written in the language of users.
WaterFall mode
The traditional approach, still widely used
Main problem
Single Long cycle, can take a year to complete
Modern approaches prefer shorter cycle (from a day to a few weeks) that build the work incrementally, so that
Continuous and fast feedback to the users
Risks can be discovered earlier
Changes can be made more rapidly
The main problem with a waterfall model is that the development is based on a single and long cycle. Problems that were identified at later stage become expensive to correct. Both RUP and XP use an Iterative and Incremental Development approach. Development is based on many short cycles. Each cycle resembles a mini-waterfall model. It is more likely that problems can be discovered earlier and therefore are less expensive to correct.
The process is iterative
Describe the system in the language of the users
Traditional approach
requirements are in the form“the system shall do this and that . . . ”
Use cases approach
requirements from users’ point of view “actor shall do this and that . . . ”
Identify the Actors
Actor is external to the system
Actors help us to find the use cases
Actors e.g. Borrower, Librarian ,System administrator
Testing:
Unit testing
To test one and only one unit, usually a class
Specification test (black box test) -- Equivalent partitioning: An equivalent set is a set of conditions for which an object is supposed to behave similarly, so as to reduce the number of test cases
structure test (white box test)-- every statement has to be executed at least once
Integration testing
Usually use cases based -- Test one use case at a time
Integration and unit tests can be done together
System testing
Testing the entire system, typically from an end-user view
Test techniques:
Regression test 回归测试
Run the test every time you change the system
Main purpose is to verify old functionality still work
Important test, must be automated (e.g. JUnit)
Operational test
Test the system in normal operation over a long period
Use the system in the intended manner
Only normal mistakes are made
Measure mean-Time-To-Failure (MTTF)
Full-scale test
run the system on its maximum scale
System is used by many users
Performance test or capacity test
Measure the system performance under different loads
Overload test
Goes one step further than the full-scale test to see how the system behaves when it is overloaded
Should not expect normal performance but at least the system should not go down and catastrophe not to occur
Negative tests
Stress test that try to use the system in ways it is not designed for, so as to reveal system weaknesses
e.g. incorrect network configuration, insufficient hardware capacity, impossible work load
Tests based on requirements
Tests based on requirement specifications
Testing of the user documentation
to check the consistency一致性 between manuals and system behavior
…
Test-driven development (TDD)
TDD Golden Rule
Never write code unless you have a test that requires it
Assert.AreEqual(expect, actual, 0.001, "Account not debited correctly");
RUP (Rational Unified Process):
RUP development is divided into four phases:
Inception开始
Elaboration 详细阐述
Construction 构建
Transition 转换
Each phase is divided into iterations
Each iteration has 9 workflows (now called disciplines)
Business Modeling
Requirements
Analysis and Design
Implementation
Test
Deployment
Configuration and Change Management
Project Management
Environment
Each phase ends with a milestone
If the milestone cannot be met, ABORT the development
Extreme Programming (XP)
A lightweight and efficient approach, emphasizes on “continuous integration, relentless testing”
Uses short iterations
Very short iterations (a day to a few weeks)
Because requirements change, scheduling must be flexible
Continuous integration testing
Once code is ready, do integration test
Very fast development
Less emphasis on analysis and design
Requirements change, so spending too much time on analysis and design is costly
Rely on refactoring
Instead of spending much time on initial architecture, rely more on continuous redesign of the code
Emphasize on fast coding
Code, test, system integration in a few hours
Fast coding lead to messy code
Rely on simple design, refactoring and automatic testing
Less emphasis on documentation
Reliance on oral communications, tests and source code to communicate system structure and intent
Standup meeting
Pair programming
Workspace has no partition
CMM (Capability Maturity Model)
Purpose of CMM
To evaluate the software process capability of an organization
标签:
原文地址:http://my.oschina.net/Bruce370/blog/379985