Code

显示标签为“转载”的博文。显示所有博文
显示标签为“转载”的博文。显示所有博文

2011年10月10日星期一

Virtuality


This article appeared in C/C++ Users Journal, 19(9), September 2001.

 

This month, I want to present up-to-date answers to two recurring questions about virtual functions. These answers then lead directly to four class design guidelines.

The questions are old, but people still keep asking them, and some of the answers have changed over time as we've gained experience with modern C++.

Virtual Question #1: Publicity vs. Privacy?

The first of the two classic questions we'll consider is this: "When should virtual functions be public, protected, or private?" The short answer is: Rarely if ever, sometimes, and by default, respectively - the same answer we've already learned for other kinds of class members.

Most of us have learned through bitter experience to make all class members private by default unless we really need to expose them. That's just good encapsulation. Certainly we've long ago learned that data members should always be private (except only in the case of C-style data structs, which are merely convenient groupings of data and are not intended to encapsulate anything). The same also goes for member functions, and so I propose the following guidelines which could be summarized as a statement about the benefits of privatization.

Guideline #1: Prefer to make interfaces nonvirtual, using Template Method.

Interestingly, the C++ standard library already overwhelmingly follows this guideline. Not counting destructors (which are discussed separately later on under Guideline #4), and not double-counting the same virtual function twice when it appears again in a specialization of a class template, here's what the standard library has:

o

6 public virtual functions, all of which are std::exception::what() and its overrides

o

142 nonpublic virtual functions


Why is this such a good idea? Let's investigate.

Traditionally, many programmers were used to writing base classes using public virtual functions to directly and simultaneously specify both the interface and the customizable behavior. For example, we might write:

 

// Example 1: A traditional base class.
//
class Widget
{
public:
  // Each of these functions might optionally be
  // pure virtual, and if so might or might not have
  // an implementation in Widget; see Item 27 in [1].
  //
  virtual int Process( Gadget& );
  virtual bool IsDone();
  // ...
};

 

The problem is that "simultaneously" part, because each virtual function is doing two jobs: It's specifying interface because it's public and therefore directly part of the interface Widget presents to the rest of the world; and it's specifying implementation detail, namely the internally customizable behavior, because it's virtual and therefore provides a hook for derived classes to replace the base implementation of that function (if any). That a public virtual function inherently has two significantly different jobs is a sign that it's not separating concerns well and that we should consider a different approach.

What if we want to separate the specification of interface from the specification of the implementation's customizable behavior? Then we end up with something that should remind us strongly of the Template Method pattern[2], because that's exactly what it is: [Later note: Actually it's a more restricted idiom with a form similar to that of Template Method. This idiom deserves its own name, and since writing this article I've switched to calling the idiom the Non-Virtual Interface Idiom, or NVI for short. -hps]

 

// Example 2: A more modern base class, using
// Template Method to separate interface from
// internals.
//
class Widget
{
public:
  // Stable, nonvirtual interface.
  //
  int Process( Gadget& ); // uses DoProcess...()
  bool IsDone(); // uses DoIsDone()
  // ...

private:
  // Customization is an implementation detail that may
  // or may not directly correspond to the interface.
  // Each of these functions might optionally be
  // pure virtual, and if so might or might not have
  // an implementation in Widget; see Item 27 in [1].
  //
  virtual int DoProcessPhase1( Gadget& );
  virtual int DoProcessPhase2( Gadget& );
  virtual bool DoIsDone();
  // ...
};

 

Prefer to use Template Method to make the interface stable and nonvirtual, while delegating customizable work to nonpublic virtual functions that are responsible for implementing the customizable behavior. After all, virtual functions are designed to let derived classes customize behavior; it's better to not let publicly derived classes also customize the inherited interface, which is supposed to be consistent.

The Template Method approach has several benefits and no significant drawbacks.

First, note that the base class is now in complete control of its interface and policy, and can enforce interface preconditions and postconditions, insert instrumentation, and do any similar work all in a single convenient reusable place - the nonvirtual interface function. This promotes good class design because it lets the base class enforce the substitutability compliance of derived classes in accord with the Liskov Substitution Principle[3], to whatever extent enforcement makes sense. If efficiency is an issue, the base class can elect to check certain kinds of pre- and postconditions only in a debug mode, for example via a non-debug "release" build that completely removes the checking code from the executable image, or via a configurable debug mode that suppresses selected checking code at runtime.

Second, when we've better separated interface and implementation, we're free to make each take the form it naturally wants to take instead of trying to find a compromise that forces them to look the same. For example, notice that in Example 2 we've incidentally decided that it makes more sense for our users to see a single Process() function while allowing more flexible customization in two parts, DoProcessPhase1() and DoProcessPhase2(). And it was easy. We couldn't have done this with the public virtual version without making the separation also visible in the interface, thereby adding complexity for the user who would then have to know to call two functions in the right way. (For more discussion of a related example, see also Item 23 in Exceptional C++[4].)

Third, the base class is now less fragile in the face of change. We are free to change our minds later and add pre- and postcondition checking, or separate processing into more steps, or refactor, or implement a fuller interface/implementation separation using the Pimpl idiom[4], or make other modifications to Widget's customizability, without affecting the code that uses Widget. For example, it's much more difficult to start with a public virtual function and later try to wrap it for pre- and postcondition checking after the fact, than it is to provide a dumb passthrough nonvirtual wrapper up front (even if no checking or other extra work is immediately needed) and insert the checking later. (For more discussion of how a class like Widget is less fragile and more amenable to future revision and refactoring, see the article "Virtually Yours"[5].)

"But but but," some have objected, "let's say that all the public nonvirtual function does initially is pass through to the private virtual one. It's just one stupid little line. Isn't that pretty useless, and indeed haven't we lost something? Haven't we lost some efficiency (the extra function call) and added some complexity (the extra function)?" No, and no. First, a word about efficiency: No, none is lost in practice because if the public function is a one-line passthrough declared inline, all compilers I know of will optimize it away entirely, leaving no overhead. (Indeed, some compilers will always make such a function inline and eliminate it, whether you personally really wanted it to or not, but that's another story.) Second, a word about complexity: The only complexity is the extra time it takes to write the one-line wrapper function, which is trivial. Period. That's it. C'est tout. The interfaces are unaffected: The class still has exactly the same number of public functions for a public user to learn, and it has exactly the same number of virtual functions for a derived class programmer to learn. Neither the interface presented to the outside world, nor the inheritance interface presented to derived classes, has become any more complex in itself for either audience. The two interfaces are just explicitly separated, is all, and that is a Good Thing.

Well, that justifies nonvirtual interfaces and tells us that virtual functions benefit from being nonpublic, but we haven't really answered whether virtual functions should be private or protected. So let's answer that:

Guideline #2: Prefer to make virtual functions private.

That's easy. This lets the derived classes override the function to customize the behavior as needed, without further exposing the virtual functions directly by making them callable by derived classes (as would be possible if the functions were just protected). The point is that virtual functions exist to allow customization; unless they also need to be invoked directly from within derived classes' code, there's no need to ever make them anything but private. But sometimes we do need to invoke the base versions of virtual functions (see the article "Virtually Yours"[5] for an example), and in that case only it makes sense to make those virtual functions protected, thus:

Guideline #3: Only if derived classes need to invoke the base implementation of a virtual function, make the virtual function protected.

The bottom line is that Template Method as applied to virtual functions nicely helps us to separate interface from implementation. It's possible to make the separation even more complete, of course, by completely divorcing interface from implementation using patterns like Bridge[2], idioms like Pimpl (principally for managing compile-time dependencies and exception safety guarantees)[1] [4] or the more general handle/body or envelope/letter[6], or other approaches. Unless you need a more complete interface/implementation separation, though, Template Method will often be sufficient for your needs. On the flip side, I am arguing that this use of Template Method is also a good idea to adopt by default and view as a necessary minimum separation in practice in new code. After all, it costs nothing (beyond writing an extra line of code) and buys quite a bit of pain reduction down the road.

Former communist countries are learning the benefits of privatization, in those cases where privatization makes sense. The lesson of healthy privatization is likewise not lost on good class designers. For more examples of using the Template Method pattern to privatize virtual behavior, see "Virtually Yours".[5]

Speaking of that article, did you notice that the code there presented a public virtual destructor? This brings us to the second topic of this month's column:

Virtual Question #2: What About Base Class Destructors?

The second classic question we'll consider is that old destructor chestnut: "Should base class destructors be virtual?"

Sigh. I wish this were only a frequently asked question. Alas, it's more often a frequently debated question. If I had a penny for every time I've seen this debate, I could buy a cup of coffee. Not just any old coffee, mind you - I could buy a genuine Starbucks Venti double-Valencia latte (my current favorite). Maybe even two of them, if I was willing to throw in a dime of my own.

The usual answer to this question is: "Huh? Of course base class destructors should always be virtual!" This answer is wrong, and the C++ standard library itself contains counterexamples refuting it, but it's right often enough to give the illusion of correctness.

The slightly less usual and somewhat more correct answer is: "Huh? Of course base class destructors should be virtual if you're going to delete polymorphically (i.e., delete via a pointer to base)!" This answer is technically right but doesn't go far enough.

I've recently come to conclude that the fully correct answer is this:

Guideline #4: A base class destructor should be either public and virtual, or protected and nonvirtual.

Let's see why this is so.

First, an obvious statement: Clearly any operation that will be performed through the base class interface, and that should behave virtually, should be virtual. That's true even with Template Method, above, because although the public interface function is nonvirtual, the work is delegated to a nonpublic virtual function and we get the virtual behavior that we need.

If deletion, therefore, can be performed polymorphically through the base class interface, then it must behave virtually and must be virtual. Indeed, the language requires it - if you delete polymorphically without a virtual destructor, you summon the dreaded specter of "undefined behavior," a specter I personally would rather not meet in even a moderately well-lit alley, thank you very much. Hence:

 

// Example 3: Obvious need for virtual destructor.
//
class Base { /*...*/ };

class Derived : public Base { /*...*/ };

Base* b = new Derived;
delete b; // Base::~Base() had better be virtual!

 

Note that the destructor is the one case where the Template Method pattern cannot be applied to a virtual function. Why not? Because once execution reaches the body of a base class destructor, any derived object parts have already been destroyed and no longer exist. If the Base destructor body were to call a virtual function, the virtual dispatch would reach no further down the inheritance hierarchy than Base itself. In a destructor (or constructor) body, further-derived classes just don't exist any more (or yet).

But base classes need not always allow polymorphic deletion. For example, in the standard library itself,[7] consider class templates such as std::unary_function and std::binary_function. Those two class templates look like this:

 

template <class Arg, class Result>
struct unary_function
{
  typedef Arg    argument_type;
  typedef Result result_type;
};

template <class Arg1, class Arg2, class Result>
struct binary_function
{
  typedef Arg1   first_argument_type;
  typedef Arg2   second_argument_type;
  typedef Result result_type;
};

 

Both of these templates are specifically intended to be instantiated as base classes (in order to inject those standardized typedef names into derived classes) and yet do not provide virtual destructors because they are not intended to be used for polymorphic deletion. That is, code like the following is not merely unsanctioned but downright illegal, and it's reasonable for you to assume that such code will never exist:

 

// Example 4: Illegal code that you can assume
// will never exist.
//
void f( std::unary_function* f )
{
  delete f; // error, illegal
}

 

Note that the standard tut-tuts and declares Example 4 to fall squarely into the Undefined Behavior Pit, but the standard doesn't actually require a compiler to prevent you or anyone else from writing that code (more's the pity). It would be easy and nice - and it wouldn't break any standards-conforming C++ programs that exist today - to give std::unary_function (and other classes like it) an empty but protected destructor, in which case a compiler would actually be required to diagnose the error and toss it back in the offender's face. Maybe we'll see such a change in a future revision to the standard, maybe we won't, but it would be nice to make compilers reject such code instead of just making tut-tut noises in standardish legalese.

Finally, what if a base class is concrete (can be instantiated on its own) but also wants to support polymorphic destruction? Doesn't it need a public destructor then, since otherwise you can't easily create objects of that type? That's possible, but only if you've already violated another guideline, to wit: Don't derive from concrete classes. Or, as Scott Meyers puts it in Item 33 of More Effective C++,[8] "Make non-leaf classes abstract." (Admittedly, it can happen in practice - in code written by someone else, of course, not by you! - and in this one case you may have to have a public virtual destructor just to accommodate what's already a poor design. Better to refactor and fix the design, though, if you can.)

In brief, then, you're left with one of two situations. Either: a) you want to allow polymorphic deletion through a base pointer, in which case the destructor must be virtual and public; or b) you don't, in which case the destructor should be nonvirtual and protected, the latter to prevent the unwanted usage.

Summary

In summary, prefer to make base class virtual functions private (or protected if you really must). This separates the concerns of interface and implementation, which stabilizes interfaces and makes implementation decisions easier to change and refactor later. For normal base class functions:

o

Guideline #1: Prefer to make interfaces nonvirtual, using Template Method.

o

Guideline #2: Prefer to make virtual functions private.

o

Guideline #3: Only if derived classes need to invoke the base implementation of a virtual function, make the virtual function protected.


For the special case of the destructor only:

o

Guideline #4: A base class destructor should be either public and virtual, or protected and nonvirtual.


True, the standard library itself does not always follow these design criteria. In part, that's a reflection of how we as a community have learned over the years.

 

Notes

1. H. Sutter. More Exceptional C++ (Addison-Wesley, 2002).

2. Gamma, Helm, Johnson, and Vlissides. Design Patterns: Elements of Reusable Object-Oriented Software (Addison-Wesley, 1995).

3. B. Liskov. "Data Abstraction and Hierarchy" (SIGPLAN Notices, 23(5), May 1988).

4. H. Sutter. Exceptional C++ (Addison-Wesley, 2000).

5. J. Hyslop and H. Sutter. "Virtually Yours" (C/C++ Users Journal Experts Forum, 18(12), December 2000).

6. J. Coplien. Advanced C++ Programming Styles and Idioms (Addison-Wesley, 1992).

7. ISO/IEC 14882:1998(E), Programming Languages - C++ (ISO and ANSI C++ standard).

8. S. Meyers. More Effective C++ (Addison-Wesley, 1996).



My Notes:
In C++ every class function is final by default.
In Java every class function is virtual by default.
This is one reason Java is slower than C++.
virtual functions add much overhead.

2011年9月28日星期三

re: An open letter to those who want to start programming

An open letter to those who want to start programming


First off, welcome to the fraternity. There aren’t too many people who want to create stuff and solve problems. You are a hacker. You are one of those who wants to do something interesting.

“When you don’t create things, you become defined by your tastes rather than ability."

– WhyTheLuckyStiff

Take the words below with a pinch of salt. All these come from me – a bag-and-tag programmer. I love to get things working, rather than sit at something and over-optimize it.

Start creating something just for fun. That’s a great start! There’s no way you will start if you say you “need to learn before doing”. Everybody’s got to start somewhere. Fire up your editor and start writing code.

Here’s something important which people might call bad advice, but I’m sure you’ll stand by me when I’m finished saying why. Initially, screw the algorithms and data structures. They do not have generic use-cases in most simple applications. You can learn them later when you need them. Over a period of time, you’ll know what to apply in situations. Knowing their names and what they do would suffice to be able to pick some paper, dust it and implement it. And that is… if no library (other programmers' re-usable code) is available, to do it in the programming language of your choice.

Choose a good language. One that you think you can produce something useful in short time.

So let C not be your first language. That might give you the satisfaction of doing things the really old-n-geeky way. C was the solution to the problem Assembly Language was. It offers better syntactic sugar than it’s prominent predecessor – Assemble Language. But today, C (or C++) is not a language that you can produce something very quickly. I would suggest that you use a dynamic language – I won’t sideline any options. Choose a language whose syntax (and documentation) you think you might be comfortable with. For this, you might want to spend some time trying out different languages for a few hours. The purpose of choosing such a language is not to make you feel better and that programming is easy. Completing stuff faster and being able to see the output keeps you motivated. Don’t choose a language that requires a special heavy-weight IDE (tool that helps you write code and run it) to program better in the language. All you should need is a text editor.

Choose a good editor.

An editor is to a programmer, like how a bow is to an archer. Here are some editors to get started with…

  • SublimeText 2 – recommended if you are just starting.
  • Emacs – huge learning curve. Complex key shortcuts. And to be able to customize it, you’ll need to learn Emacs Lisp.
  • Vim – used by many for it’s simplicity and the fact that it comes with linux distros by default. I used Emacs for 2yrs and then switched to Vim to run away from emacs’s complex key strokes and when my little finger on both hands started hurting. Knowing vim keystrokes is a must. When you work remotely and try to type out code on some server from your computer, you’ll know that the only editor available from the command line without any installs, is Vim.

Watchout! Emacs and Vim might be really old. But they both have some features which even most modern editors don’t have.

Use an operating system that’ll teach you something.

Windows won’t teach you anything. The only thing you learn using Windows is to click the .exe file to install the software and use it. It may seem cool in the beginning, but in the long run when you have to deploy applications, especially if you are aspiring to be a web developer, you’ll need atleast basic knowledge of linux. Linux also allows you to customize stuff the way you need them to be. Macs are cool too, but I assume that you cannot afford one of those now.

Don’t copy-paste files to backup stuff.

It’s usual among amateur programmers to copy-paste files to some temporary directory in order to backup them. That’s the only way they seem to know. Stop that! Use a version control software. I strongly suggest Git, since it’s popular and easy to use. It has nice community and resources to support new-comers. (Apart from Git, There’s mercurial, darcs, fossil, etc. But just start with Git. I’m not going to bother you with the reasons for suggesting Git).

Know where to get help.

Join a community that you can relate to (with the tools you use). StackOverflow is Facebook for programmers. There are no status messages and comments. Instead there are questions and answers. Also learn to use the IRC. It’s an old form of chatrooms and is now being used by mostly developers to share information and helping each other.

Develop your netiquette.

Know when to ask questions. Most problems you face might have been stumbled upon by others who might have already posted on the internet for answers. Before asking on IRC or any forums, google first (or should I say blekko first) to see if there’s already a solution to your problem. IRC needs patience. Remember people are helping you for free out of goodwill. Sometimes it might take hours, for someone in the chatroom to respond to you. So wait until they do. Besides, be polite. It's a small world. Karma, good or bad, comes back.

Meet people, because books only teach you routine stuff (oh and the "book" is dead they say).

There are some street smarts that you’ll learn when you tinker with stuff or learn from those who do it. Roam, meet people and say hello. You are not the only programmer in your place. Make friends and do stuff with them. If you've noticed, when a couple geeks get together, whatever the starting point of the conversation be, it always ends up getting technical. It's bound to happen. Enjoy it. Programming for a good number of years, I can tell you that I learnt nothing more than what the books and articles said, until I starting meeting people and getting technical with them 6yrs back. So I always say that I’ve been programming for 6yrs, because that’s when I started meeting people and feel I really started to learn.

Write opensource code.

Writing opensource code is giving back. It’s much more than charity. You are leaving code that others can use and improve on (maybe) for years to come. It also helps you refine your skills when someone else adds to your code or suggests changes. Code that you opensource doesn't have to be big. It can even be a useful little program that downloads youtube videos. Moreover, you’ll be surprised, that your code will often help you start and have interesting conversations with people.

Lastly, when years pass, return this favour, by writing a similar letter to someone else who asks you for such help. And possibily correct me.

--
For a hacker, by a hacker
Akash Manohar

P.S: Wise men say, it takes 10 years or 10000 hours to get good at something. So don’t hurry.


2011年9月24日星期六

你真的需要重构软件吗?

Joel on Software
Things You Should Never Do, Part I
by Joel Spolsky
Thursday, April 06, 2000

Netscape 6.0 is finally going into its first public beta. There never was a version 5.0. The last major release, version 4.0, was released almost three years ago. Three years is an awfully long time in the Internet world. During this time, Netscape sat by, helplessly, as their market share plummeted.

It's a bit smarmy of me to criticize them for waiting so long between releases. They didn't do it on purpose, now, did they?

Well, yes. They did. They did it by making the single worst strategic mistake that any software company can make:

They decided to rewrite the code from scratch.

Netscape wasn't the first company to make this mistake. Borland made the same mistake when they bought Arago and tried to make it into dBase for Windows, a doomed project that took so long that Microsoft Access ate their lunch, then they made it again in rewriting Quattro Pro from scratch and astonishing people with how few features it had. Microsoft almost made the same mistake, trying to rewrite Word for Windows from scratch in a doomed project called Pyramid which was shut down, thrown away, and swept under the rug. Lucky for Microsoft, they had never stopped working on the old code base, so they had something to ship, making it merely a financial disaster, not a strategic one.

We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by incremental renovation: tinkering, improving, planting flower beds.

There's a subtle reason that programmers always want to throw away the code and start over. The reason is that they think the old code is a mess. And here is the interesting observation: they are probably wrong. The reason that they think the old code is a mess is because of a cardinal, fundamental law of programming:

It’s harder to read code than to write it.

This is why code reuse is so hard. This is why everybody on your team has a different function they like to use for splitting strings into arrays of strings. They write their own function because it's easier and more fun than figuring out how the old function works.

As a corollary of this axiom, you can ask almost any programmer today about the code they are working on. "It's a big hairy mess," they will tell you. "I'd like nothing better than to throw it out and start over."

Why is it a mess?

"Well," they say, "look at this function. It is two pages long! None of this stuff belongs in there! I don't know what half of these API calls are for."

Before Borland's new spreadsheet for Windows shipped, Philippe Kahn, the colorful founder of Borland, was quoted a lot in the press bragging about how Quattro Pro would be much better than Microsoft Excel, because it was written from scratch. All new source code! As if source code rusted.

The idea that new code is better than old is patently absurd. Old code has been used. It has been tested. Lots of bugs have been found, and they've been fixed. There's nothing wrong with it. It doesn't acquire bugs just by sitting around on your hard drive. Au contraire, baby! Is software supposed to be like an old Dodge Dart, that rusts just sitting in the garage? Is software like a teddy bear that's kind of gross if it's not made out of all new material?

Back to that two page function. Yes, I know, it's just a simple function to display a window, but it has grown little hairs and stuff on it and nobody knows why. Well, I'll tell you why: those are bug fixes. One of them fixes that bug that Nancy had when she tried to install the thing on a computer that didn't have Internet Explorer. Another one fixes that bug that occurs in low memory conditions. Another one fixes that bug that occurred when the file is on a floppy disk and the user yanks out the disk in the middle. That LoadLibrary call is ugly but it makes the code work on old versions of Windows 95.

Each of these bugs took weeks of real-world usage before they were found. The programmer might have spent a couple of days reproducing the bug in the lab and fixing it. If it's like a lot of bugs, the fix might be one line of code, or it might even be a couple of characters, but a lot of work and time went into those two characters.

When you throw away code and start from scratch, you are throwing away all that knowledge. All those collected bug fixes. Years of programming work.

You are throwing away your market leadership. You are giving a gift of two or three years to your competitors, and believe me, that is a long time in software years.

You are putting yourself in an extremely dangerous position where you will be shipping an old version of the code for several years, completely unable to make any strategic changes or react to new features that the market demands, because you don't have shippable code. You might as well just close for business for the duration.

You are wasting an outlandish amount of money writing code that already exists.



Is there an alternative? The consensus seems to be that the old Netscape code base was really bad. Well, it might have been bad, but, you know what? It worked pretty darn well on an awful lot of real world computer systems.

When programmers say that their code is a holy mess (as they always do), there are three kinds of things that are wrong with it.

First, there are architectural problems. The code is not factored correctly. The networking code is popping up its own dialog boxes from the middle of nowhere; this should have been handled in the UI code. These problems can be solved, one at a time, by carefully moving code, refactoring, changing interfaces. They can be done by one programmer working carefully and checking in his changes all at once, so that nobody else is disrupted. Even fairly major architectural changes can be done without throwing away the code. On the Juno project we spent several months rearchitecting at one point: just moving things around, cleaning them up, creating base classes that made sense, and creating sharp interfaces between the modules. But we did it carefully, with our existing code base, and we didn't introduce new bugs or throw away working code.

A second reason programmers think that their code is a mess is that it is inefficient. The rendering code in Netscape was rumored to be slow. But this only affects a small part of the project, which you can optimize or even rewrite. You don't have to rewrite the whole thing. When optimizing for speed, 1% of the work gets you 99% of the bang.

Third, the code may be doggone ugly. One project I worked on actually had a data type called a FuckedString. Another project had started out using the convention of starting member variables with an underscore, but later switched to the more standard "m_". So half the functions started with "_" and half with "m_", which looked ugly. Frankly, this is the kind of thing you solve in five minutes with a macro in Emacs, not by starting from scratch.

It's important to remember that when you start from scratch there is absolutely no reason to believe that you are going to do a better job than you did the first time. First of all, you probably don't even have the same programming team that worked on version one, so you don't actually have "more experience". You're just going to make most of the old mistakes again, and introduce some new problems that weren't in the original version.

The old mantra build one to throw away is dangerous when applied to large scale commercial applications. If you are writing code experimentally, you may want to rip up the function you wrote last week when you think of a better algorithm. That's fine. You may want to refactor a class to make it easier to use. That's fine, too. But throwing away the whole program is a dangerous folly, and if Netscape actually had some adult supervision with software industry experience, they might not have shot themselves in the foot so badly.

原址

2010年12月16日星期四

Seven signs you're a healthy man

Fitness
To test your fitness, you don't have to run for miles or do 200 push-ups.

Experts say that the average person should be able to walk a mile in 15 minutes, carry two bags of shopping to the car, and climb the stairs in a house without getting breathless.

But that doesn't take into account age or gender. More specifically, a 30-year-old man with above average strength and fitness should be able to do over 25 push-ups in a minute and over 35 squats.



Vital signs
As long as you have a watch and the ability to count, you can measure a couple of your vital signs from the comfort of your armchair.

A resting pulse of around 70 beats per minute and a respiratory rate of around 16-20 breaths per minute don't make you an athlete, but they do make you a normal, healthy adult.



Nails
Men don't pay much attention to their fingernails, but they can give vital clues to general health.

Yellow nails are suggestive of respiratory disease, spoon-like nails curving outwards can mean iron deficiency anaemia, and lines going across the nails may be a symptom of diabetes.

Go to the doctor if there's any major change in the look or feel of your fingernails. Firm, pink nails, on the other hand, can be evidence of a decent general level of health.



Toilet time
If you're about to have lunch, it might be wise to skip this bit till you've finished. In a word, we're talking stools, because stools can speak volumes about overall health.

It's not so much how often you pass them that's important (unless this suddenly changes) - once a day, three times a day, or even every other day can all be healthy depending on the individual - but consistency and colour.

A good stool is torpedo shaped, soft and easy to pass. Colour can depend on what you've eaten, but it shouldn't generally be grey, very pale, too dark or bright red. A mid-brown stool, passed easily and regularly without any sudden change in bowel habits is one sign of decent digestive health.



Urine
And to continue the theme, if you have pale yellow pee you're drinking enough fluids and - in the absence of other symptoms - probably don't have any urinary tract infections.

A good colour is also a sign that your liver is working efficiently. Don't worry if you drink a lot of water and you're urine turns almost clear - apart from the inconvenience of all those trips to the toilet, that's no problem.

A darker yellow probably just means you've been drinking less - drink more to avoid the symptoms of dehydration.
But dark or red-tinged urine - or pee with a sweet or strange odour - can be a symptom of health problems.



Shiny, healthy hair
A fine and luscious head of shiny hair not only looks good, it's also a sign that good things are happening in your body.

In particular, healthy hair can be a sign of a healthy diet. Dull, dry and brittle hair can be caused by a lack or protein, vitamin E or essential fatty acids. Hair so healthy women want to run their fingers through it may be evidence that you're absorbing plenty of body-friendly nutrients.



Tongue
Doctors can tell a lot from your tongue.

A tongue with a warm, pinkish colour is one clue that you are absorbing sufficient iron, folic acid and vitamin B12.
An overly pale and smooth tongue can be a sign of anaemia, while a yellowish tint can suggest fungal infection.

2010年9月17日星期五

转载: EA看好Android手机游戏市场 增加投入


美国艺电公司(Electronic Arts)的首席财务官埃里克·布朗(Eric Brown)表示公司正在定位其手机业务,未来的几年,在Android操作系统方面的业务将会有所增加。

在德意志银行2010年科技大会上,布朗引用了一份来自IDC的报告,在2014年,相比苹果设备的11%,Android将会有25%的市场占有率。布朗指出:“所以未来我看好Android,我们正在利用这个趋势定位我们的手机业务。”

同时布朗表示对EA目前的智能手机游戏业务每年2-2.25亿美元的收入比较满意,其中主要以销售iPhone游戏为主,但是苹果在市场上的主导地位不会永远持续下去。[来源:GameRes.com]他认为下一个能推动手机领域增长的大浪潮是Android操作系统,所以在德意志银行2010年科技大会上,布朗明确表示从长期考虑,Android将逐渐占取市场份额。

Android操作系统已经有一个应用程序商店,但是布朗希望未来谷歌能够增加其它功能,另外,其他供应商,比如美国一家电信公司Verizon正在开发他们自己的Android应用程序商店。

布朗指出,从上个季度的智能手机硬件销量来看,带有Android操作系统的设备销量首次超过iPhone,证明了未来的趋势,尽管EA的游戏销售还没有反映出这个趋势。

在移动手机市场,从移动电话慢慢转化到智能手机如iPhone和Android就像以前从PS2到PS3的过渡一样。

在最赚钱的iPhone和iPad应用程序榜单中,EA游戏最近频繁出现,例如《老虎伍兹》、《极品飞车》、《FIFA》、《疯狂橄榄球》、《俄罗斯方块》、《大富翁》等,显示出强劲的业绩。

最近游戏开发商id和ngmoco都在招聘Android程序开发人员,看来不是只有EA看好这个新兴的操作系统,Epic在把虚幻3引擎技术带入苹果后,获得了超过100万的下载量,也正在考虑把它带入Android操作系统。

Current Android Phones on Market

2010年9月1日星期三

“狗日的”腾讯 搅局者还是终结者?

“有什么业务是腾讯不做的吗?”美团网CEO王兴的语气中难掩郁闷。

7月9日,腾讯QQ团购网上线,这让王兴如闻惊雷,也如坐针毡。从2003年回国到现在,王兴先后创办了校内、海内、饭否和美团4个网站,而美团网被他视为“最靠谱”的一次创业。3月初上线的美团网是国内第一家团购网站,创立仅仅4个月,美团网已经能够盈亏平衡。

就在这时候,一直悄无声息的腾讯杀了进来,这让王兴完全猝不及防,也让处于草创时期的数百家团购网站倒吸了一口凉气。

谁也不知道,这一次,这个“企鹅仔”将是搅局者、掠食者,还是终结者。

“狗日的”腾讯
别上腾讯盯上其实,王兴应该早就想到会有这么一天。因为在中国互联网发展历史上,腾讯几乎没有缺席过任何一场互联网盛宴。它总是在一开始就亦步亦趋地跟随、然后细致地模仿,然后决绝地超越。比如当初的游戏。

“从QQ游戏平台上线那天起,联众的失败就已经注定了。”多年以后,在北京知春路的一家咖啡馆,联众创始人鲍岳桥谈起当年腾讯对联众的围剿和逼迫,仍然耿耿于怀。在两个小时的采访中,他连续抽了两包烟。

联众是中国最早做游戏平台的公司,一度占有在线棋牌游戏市场85%以上的市场份额,在新浪、搜狐等门户网站亏损缠身的时候,联众是最早实现赢利的中国互联网企业,一时风光无两。

2003年8月,腾讯QQ游戏第[来源:GameRes.com]一个公开测试版本正式发布。鲍岳桥发现,从平台到游戏设计,QQ游戏完全是联众游戏的翻版。愤怒之余,“感到危险很大”的鲍岳桥首先想到的是“主动低头”寻求合作,于是他赶赴深圳,约见马化腾和时任腾讯公司首席运营官的曾李青,但是遭到了腾讯方面的拒绝。

“现在想来,那时候是太天真了。”鲍岳桥说,“与大型网游不同,棋牌类游戏规则固定,没有技术门槛,玩家又与QQ用户高度重合,腾讯很容易模仿。”

2004年9月,QQ游戏平台将联众赶下了中国第一休闲游戏门户的宝座。而在此之后,联众的业绩一路下滑,出售、转型,经历了一系列风波后,联众在中国网络游戏市场份额已不足1%。

腾讯则扶摇直上,在今年一季度,QQ游戏同时在线人数达到了680万。而更重要的是,依托QQ游戏平台,腾讯终于在2009年第二季度超越盛大,坐上了中国网络游戏领域的头把交椅。

对鲍岳桥来说,腾讯就是自己的终结者。2006年底,鲍岳桥离开了江河日下的联众,成为了一名天使投资人。他告诉记者,现在他做投资的原则之一就是:只做腾讯不会做、不能做的项目。所以三年来,他绝对不碰游戏,已经投资的医疗器械和数据存储项目都跟腾讯毫无关联。
而这个终结者又有了新的目标,那就是“站长之王”蔡文胜的4399小游戏平台。

“说不担心QQ竞争那是骗人的。”蔡文胜在微博上表达了自己的忧虑,直接原因就是今年7月初,腾讯旗下小游戏平台3366.com上线公测。
据记者调查,去年蔡文胜买下的4399小游戏平台,通过广告联盟和联合运营网页游戏,月营收已达3000~5000万元,正在筹备国内A股上市。而腾讯刚刚上线的3366,在游戏种类和网站设计上与4399几无二致。

而且这只“企鹅仔”似乎更加来势汹汹。从7月1日开始,不断有网友看到QQ弹窗对这一游戏平台的推广信息,而截止记者发稿时,3366.com同时在线人数已突破10万。

只要是一个领域前景看好,腾讯就肯定会伺机充当掠食者。除了王兴和蔡文胜,腾讯最近还“默默地”动了另外一个人的奶酪,他就是奇虎360董事长周鸿祎。

5 月31日,杀毒领域两大巨头360与金山的一场口水战激战正酣,腾讯的QQ医生3.3升级版却悄然上线。很快人们就发现,这款原本只是用来查杀QQ盗号木马的防护软件,已经了包含云查杀木马、系统漏洞修补、实时防护、清理插件等多项安全防护功能,甚至还搭载了免费半年的诺顿杀毒。

此前,周鸿祎曾在多个公开场合对腾讯创始人马化腾在产品上的功力赞不绝口,同时还声称,腾讯绝不会成为360的竞争对手,因为“腾讯是一个娱乐公司,在安全方面,应该由一个很专业的公司更专注地去解决问题”。

很显然,马化腾毫不客气地给了周鸿祎当头一棒。

在腾讯还没有出手的互联网领域,小企鹅那些潜在的竞争对手们仍是战战兢兢,如履薄冰。比如暴风影音CEO冯鑫。自从2008年9月腾讯发布了本地播放软件 QQ影音首个Beta版本,冯鑫恐怕就没睡过一天好觉。因为这款无广告、无插件播放软件,让暴风影音的盈利模式变得岌岌可危。

而在各大视频网站因为版权打得不可开交,频频对簿公堂之时,同样有一种声音在业内流传:无论你们现在打得多欢实,等市场培育得差不多了,就该轮到腾讯来收场了。事实确实如此,QQLive的平台早就搭好了,拼版权,中国的互联网公司谁敢说自己比腾讯更有钱?

这就是腾讯,中国第一、全球第三大互联网公司,一家全球罕见的互联网全业务公司,即时通讯、门户、游戏、电子商务、搜索等等无所不做。它总是默默地布局、悄无声息地出现在你的背后;它总是在最恰当的时候出来搅局,让同业者心神不定。而一旦时机成熟,它就会毫不留情地划走自己的那块蛋糕,有时它甚至会成为终结者,霸占整个市场。

“某网站贪得无厌,没有它不染指的领域,没有它不想做的产品,这样下去物极必反,与全网为敌,必将死无葬身之地。”6月29日,新浪网总编陈彤以“老沉”为名发布了一则微博,言辞之激烈,让人震惊。这条微博迅速被转发了500多次,无数的人力挺“老沉”。

谈起此事,一位互联网创业者几乎是脱口而出,“狗日的腾讯!”


始终“贪得无厌” “既没有马云那么好的口才,也没有李彦宏那么帅。”马化腾曾经多次自嘲,说自己“很不幸”,“大家都是圈地,他们(马云、李彦宏)圈的都是楼,可以直接住。我们圈到的却是荒地,只能从铲沙、挖土开始,建自己的楼。”

实际上,马化腾算不上纯粹的“草根创业”。据传,在腾讯创立初期,其父马陈术曾开着奔驰前来给儿子做账。在11年的发展历史上,腾讯只是在早期遭遇过资金困局,从获得第一笔融资开始就一直是稳扎稳打,先利用无线增值服务实现盈利,转而依靠互联网增值服务壮大,布局网络游戏和门户业务。2010年最新一季财报显示,腾讯的网络广告业务收入为2990万美元,已经远远超过网易的1340万美元,稳居门户第三。

马化腾在业界以低调、务实著称,这在一定程度上决定了腾讯的企业风格:其疾如风,其徐如林,侵掠如火,不动如山。

2006 年7月,QQ同时在线突破2000万人,腾讯公司内部决定办一个庆功会,会上腾讯联席CTO熊明华问了马化腾一个问题:QQ同时在线人数何时能够到1亿?马化腾一笑:“这辈子我可能看不到了。”事实上,2010年3月5日,他就看到了。熊明华一定很后悔,没有和马化腾打赌“裸奔”。

实际上,马化腾有很多值得“裸奔式”庆祝的理由。目前,腾讯是中国最赚钱的互联网公司,公司现金储备达到15亿美元;拥有中国本土用户量最大的即时通讯软件,账户数近10亿;是中国第一流量的门户;在网络游戏市场排名第一,占据超过20%以上的市场份额;电子邮箱流量也已经超过网易,雄踞榜首。

资本市场对这只彪悍的企鹅也是极力追捧。在香港,腾讯的股价一度高达每股171.80港元,上市6年间腾讯股价上涨了超过了35倍。要知道,被世界公认为近年来最具创新能力的苹果,其股价增幅才只有腾讯的一半。


腾讯为什么还不满足?一只企鹅为何如此贪婪?

是的, “腾讯不是一般的有钱”,但股东的钱不是用来供着的,腾讯必须不断寻找新的利润增长点。蔡文胜就曾表示,腾讯现在什么都想做,从中可以看出它面对快速增长的巨大压力,这个压力终有一天会压垮腾讯。

在美团网创始人王兴看来,腾讯之所以染指团购,是因为这模式已经被证明“能赚钱”。“做团购没有技术门槛,盈利模式又清晰,腾讯没有理由不做。”王兴指出,团购与他之前创办的校内和饭否最大的不同在于,“网站从上线第一天开始就有收入”。——如此唾手可得的生意,腾讯怎么可能放过?

搜索也将是腾讯的下一个目标。今年3月,马化腾与李彦宏在深圳有过一场对话。李彦宏问马化腾,“腾讯凭什么做搜索?”马化腾给出了两点理由:一是用户需要,腾讯这个一站式互联网服务平台中的很多环节都需要搜索功能;二是搜索能赚钱,腾讯拥有全球最大互联网社交网络系统,社区的盈利模式中,除了个人收费以外,未来还要结合页面内容分析,匹配相关性的广告。因此,已有业内人士指出,而在这一类似于Google的AdWords模式的探索过程中,腾讯未来必将对百度正在培育的广告联盟形成威胁。

也许,在马化腾看来,无论是搜索,还是团购,甚至是将来的视频,这些业务都是腾讯水到渠成的业务延伸。因为马化腾为腾讯未来的构想是,一站式互联网服务提供商。——围绕腾讯QQ打造“在线生活社区”,也就是“用户要什么,腾讯就有什么”。百度董事局主席兼CEO李彦宏对腾讯所谓的“在线生活”、“一站式服务”的评价是:基本上就是不给别人任何空间。

在CSDN总裁蒋涛看来,腾讯之所以什么都做,是因为它是一家以人(用户)为中心的企业,同类型的企业还有软件巨头微软,两家公司的产品战略更是惊人的相似。

长期以来,以操作系统为核心的微软也是个典型的“全民公敌”。为了“抓住”用户,微软每个阶段都会根据市场变化,布局新的应用,以巩固其用户终端的垄断地位。在个人消费领域上,微软先后推出了浏览器IE、邮件系统Hotmail、即时通讯MSN、邮件客户端outlook、免费杀毒软件MSE,以及今年5 月刚刚发布的在线版Office软件。

而从另一方面讲,腾讯的进攻也是一种防御。互联网产业往往形势突变,Google市值超越雅虎,Facebook流量超越Google都发生在旦夕之间。腾讯最怕的就是突然冒出一个企业,被一种意想不到的商业模式或竞争策略打败。所以腾讯对于任何一个互联网的新应用都不敢掉以轻心。

“360安全卫士、暴风影音的装机量都已经上亿了,如果周鸿祎或者冯鑫有一天跟新浪合作,也推新闻弹出框,马化腾不就郁闷了?”蒋涛认为,腾讯的产品策略之一就是:所有的互联网应用,只要用户量到了一定级别,腾讯一定要有,别人的产品可以暂时比腾讯做得好,但腾讯绝不会让它不可替代。

当被问及腾讯的核心竞争力时,腾讯CTO熊明华给记者的答案不是超过10亿的QQ的注册用户,也不是某一项产品、技术方面优势,而是“耐心”:懂得在合适的时间推出合适的产品。”
因此,究竟腾讯还会做什么,没有人知道。


腾讯从来不做第一个吃螃蟹的人,却总能在成熟的市场中找到空间,横插一杠子。然而它选择的路径也使其饱受争议,那就是模仿,有时甚至是肆无忌惮地“山寨”。

早在2006年,新浪网创始人王志东就公开指责马化腾是业内有名的“抄袭大王”,而且是明目张胆地抄袭。几年以来,类似的声音一直不绝于耳。直到最近,DCCI互联网数据中心主任胡延平还在质疑腾讯的创新能力,说它不仅不是卓越创新者,反倒是中小互联网企业的“创新天敌”。

从模仿 ICQ推出自己的第一款产品OICQ(腾讯QQ的前身)开始,腾讯似乎就埋下了自己的“模仿基因”——先是从韩国引入了QQ秀和其他一系列增值服务,又模仿新浪建起了门户网站;在网游领域,学联众开发平台,跟着盛大引进国外网友,随着网易自主研发,之后布局的C2C电子商务网站拍拍,以及第三方支付财付通,无一不是“山寨货”,这也是腾讯遭人恨的根本原因。

“微博、杀毒、电子商务到今天的团购,这些领域的商业模式在那儿摆着,人人都在抄,你凭什么要求腾讯高抬贵手,不去挣这个钱了?”互联网资深人士谢文在接受记者采访时表示,业界这种对腾讯的埋怨,就像“小孩儿撒娇”,是五十步笑一百步。

对于模仿的指责,马化腾的回应是:模仿是最稳妥的创新。

“创新可以分为三个层次:技术创新、产品创新和应用创新,产品和应用层面的创新比较容易被人忽略。”一位资深互联网产品经理告诉记者,几乎腾讯的每款产品都能找出市场上其他同类产品所没有的优点,如腾讯QQ的群和显示最近联系人功能,QQ邮箱的超大附件功能,QQ游戏平台一上线就号称能承载上千万的同时在线,QQ还解决了困扰很多IM产品的联通、电信的互联互通问题等等。

事实上,腾讯获得突破的领域往往得益于应用层面的创新,腾讯总是能够通过QQ用户行为习惯的把握,将新产品与腾讯QQ这一核心进行结合,使其用户的优势得到发挥。同为技术出身,奇虎360董事长周鸿祎坦言如果同是做即时通讯,自己在产品细节和技术上能够比马化腾做得好,但很难比QQ成功。因为马化腾是把互联网产品当成服务来做,其成功在于“打动人心”。

CSDN总裁蒋涛在接受本报记者采访时也表示,虽然从商业竞争的角度,腾讯通过复制别人的商业模式进行无限扩张,是无可厚非的,但在客观上必然会扼杀一些创新的好苗头。这也和胡延平的观点一致,从某种程度上说,腾讯是互联网创新者的杀手。

腾讯的麻烦四面制造麻烦的腾讯并非每次都能凯旋而归,甚至给自己惹上了不少麻烦。2009年6月,搜狐就因为输入法将腾讯告上法庭,称腾讯侵犯了其旗下搜狗拼音输入法的软件自主知识产权,并且利用QQ拼音输入法破坏搜狗拼音输入法服务,对搜狗实施不正当竞争,因此请求法院判令腾讯停止不正当竞争行为,并索赔 2000万元。

能够让同为互联网巨头的搜狐撕下脸面,腾讯“与全网为敌”所招致的民愤可见一斑。

不过,身为山寨之王的腾讯也在遭遇“被山寨”。2005年成立的51.com,几乎腾讯每推出一个新的功能与应用,它都会加以“学习”、“消化”,并迅速在自己的平台上开发出来。如目前在51.com平台上的“51商城”、“51群组”、“51秀”、“51问问”,它甚至曾经开发出彩虹QQ,免费提供IP地址探测、显示隐身好友等腾讯QQ的“增值”功能。


“能不能给大家一点建议,怎样才能抗衡腾讯呢?”在2009年游戏产业年会的高峰对话环节,当主持人抛给腾讯游戏总裁任宇昕这样一个问题时,除了任宇昕自己一脸骄傲,举坐皆苦笑。这位中国最大互联网公司的游戏业务负责人也不谦虚: 只有跟腾讯合作,共同把市场一同做大。

在外界看来,腾讯庞大的身躯,依然潜伏着诸多暗流。实际上,因为腾讯在互联网界“无耻模仿抄袭”的恶名,使得腾讯全线树敌,成为众矢之的。当越来越多的互联网企业开始时时提防着腾讯的时候,腾讯将不再像以前那样收放自如。比如,为应对腾讯的搜索,百度就将搜索的提成比例从10%提升到15%。

而且,腾讯还算不上真正强大。互联网资深人士谢文则表示,腾讯的模仿充其量只能让保持强大的现状,却不能使其引领潮流,真正走向伟大。“事实上,如果腾讯一味模仿下去,随着平台上的服务越来越多,单个服务的效率会大幅降低。”谢文表示,“而且,如果腾讯只是针对现有的QQ用户群体开发应用,未来QQ用户的人口特性将被固定在年轻群体的娱乐需求上,随着网民年龄结构的变化,腾讯就会被最终边缘化,而开心网、人人网及新浪微博的崛起已经为腾讯的迟钝敲下了警钟。”

在很多人眼中,腾讯是最近接近Google的一家本土互联网公司。因为虽然Google目前的主要盈利点还是围绕其搜索产品的 AdSense和AdWords,但它也是邮箱、地图、音乐无所不做,腾讯也是如此,虽然号称全民公敌,但它的主要收入仍然来自IM和网络游戏所带来的互联网增值服务。

但谢文却指出这只是表面现象:“腾讯和Google完全不在一个档次上”。他指出,Gmail、Google地图、 Google Earth等产品虽然不赚钱,但是它们之所以被开发都是围绕着一个核心理念:就信息整合与信息呈现。相比之下,腾讯的产品则显得杂乱无章,IM、网游、电子商务与门户业务之间并不必然的关联,其他公司单独做也能成功。据此,谢文认为,腾讯只是利用先发优势抓住了一大批用户,产品研发都是针对用户市场展开,追求短期效益,而对自己的未来缺乏清晰地规划。

“建立在用户群上的腾讯是不牢靠的。”蒋涛认为,一旦未来人们更喜欢用Facebook和Twitter这样的工具彼此联络,不再以IM为中心,腾讯的“大本营”就被攻克了,这意味其虚拟货币系统必将被超越,而网游、门户这些现有盈利点也不能保证一直有市场竞争力。

“如果人们未来都不再依赖PC,改用Ipad和手机的话,微软无疑就完蛋了”蒋涛说。微软的今天可能就是腾讯的明天,IT产业往往形势突变,用户习惯的变化又是在旦夕之间,看看facebook和google所带来的一场场变革,腾讯当以微软和雅虎为戒。

原文地址:http://bbs.ce.cn/forum/viewthread.php?tid=2087&page=1&extra=page%3D1

我觉得,腾讯的做法就是唯利是图。并没有把发展中国互联网作为自己的责任。在中国,腾讯相当实施垄断,这是政府保护政策的结果。没有外国企业进入中国,就没有人能够跟腾讯抗衡。要知道,腾讯有钱也有用户群,做什么都很容易。另一个,我对腾讯扼杀创新的说法非常赞同,腾讯是中国进步的绊脚石。