问:
Testing a file that relies heavily on a static array
I have a .c file that basically manages its own little database of people. There are add, remove, edit and search functions among some others. It has a static array which it uses to store the data.

What is a good way to go about unit testing a file like this? Because the array is static I can't put in my own data.

Should I employ some trickery and make a function that passes out a pointer to the array that gets compiled out in the production version? Should I just test the functions as is and make the data they way I want it via a series of adds and removes? What is the best way to test a file like this?

答: As Joel said in Things You Should Never Do, you should never rewrite the code. You can write your test codes to call the add, remove, edit and search functions in this file which verify the correctness of the functions and the static array. If the test codes can judge the testing result automatically, you have the base to refactor the code. Every programmer wants to change the original codes to their own, but the key element lies in whether the original codes are stable or not. Otherwise you will just do the useless work.</p>


问:
Abstract Data Type and Data Structure
It's quite difficult for me to understand these terms. I searched on google and read a little on Wikipedia but I'm still not sure. I've determined so far that:

Abstract Data Type is a definition of new type, describes its properties and operations.

Data Structure is an implementation of ADT. Many ADT can be implemented as the same Data Structure.

If I think right, array as ADT means a collection of elements and as Data Structure, how it's stored in a memory. Stack is ADT with push, pop operations, but can we say about stack data structure if I mean I used stack implemented as an array in my algorithm? And why heap isn't ADT? It can be implemented as tree or an array.

答:
ADT is to an interface (what it does) what a data structure is to a class (how it does it).

A few examples:

```<code>ADT: List
DS:  ArrayList, LinkedList...

ADT: Map
DS:  HashMap, TreeMap...
</code>```

I guess you get the point.

ContentLicense: CC BY-SA 3.0

Title: Abstract Data Type and Data Structure

Body:
ADT is to an interface (what it does) what a data structure is to a class (how it does it).

A few examples:

ADT: List
DS:  ArrayList, LinkedList...

ADT: Map
DS:  HashMap, TreeMap...

I guess you get the point.


问:
New senior developer tasks
I've got a senior developer with eight years of .NET experience starting tomorrow to work on a 11,000-lines-of-code application. In the team there's myself and another programmer. We've both got about three years experience each.

It's my first project as a manager (I'm also a developer on the project) and this is the first time I've ever had to introduce someone to an already established code base. Obviously I'll be going over each module, the deployment process, etc., and handing them the location of the source control repository, documentation (which isn't the best), etc.

How long should I give them before they're ready to start writing new features and fixing bugs?

答:
In open source community, everyone who wanted to join the project first deals with some tiny problems. If he or she can handle the problem very well, the more important task will be assigned to him or her. In this way, they would become a core developer of the project.

This senior developer has eight years of .NET experience, so you could assign him some simple bugs to fix. If it is easy for him to deal with them, you could assign him complex problems to help him familiar with the whole application. After that, he could start writing new features and analyzing weird problems. Just do it , there has no setup time!

Title: New senior developer tasks


问:
Suggestions for Programs to develop for learning
i wonder apart from those very simple hello world apps, what other programs should i try developing for learning. i am entering uni next year and wonder what kind of programs will be developed in that environment.

this is not really a language specific thing, but if you want to know what i use currently mainly

windows: C#/WPF - i studied java/vb etc in poly but i think C# is the way to go, maybe even F#

web: PHP/MySQL, Zend Framework/Doctrine, + HTML/CSS/JS(jQuery) of course. looking to try google app engine with python too.

for now, i am thinking of

todo lists

apps that integrate with api eg. twitter/tumblr which i use

text editor - i am currently trying to develop a text editor that uses markdown and generates html files for viewing (link to blog entry). not very pratical after i started developing it. cos when editing theres no formatting and in HTML format, i cannot edit directly

blog software (for web)

答: CodePlex.com lists many open source projects that were made using C#. You could take a look at the site to get some ideas.</p>

ContentLicense: CC BY-SA 2.5


答:
The answer is: it depends.  If you want him to fix an off by one error on something or change the color of a GUI element, then about 5 minutes (here's where we keep our code), if you want a total redesign of the entire architecture of the app that will require a bit longer.

It really depends upon the task that you expect him to perform.

Title: New senior developer tasks

Body:
I've got a senior developer with eight years of .NET experience starting tomorrow to work on a 11,000-lines-of-code application. In the team there's myself and another programmer. We've both got about three years experience each.

It's my first project as a manager (I'm also a developer on the project) and this is the first time I've ever had to introduce someone to an already established code base. Obviously I'll be going over each module, the deployment process, etc., and handing them the location of the source control repository, documentation (which isn't the best), etc.

How long should I give them before they're ready to start writing new features and fixing bugs?


问:
Efficient ways to model cars moving along a road
This has never come up, so I've never thought how a data or programming model should work that simulates (a) bird's eye view of cars moving and some rudimentary physics, (b) how the cars would follow a road layout and (c) how an efficient data structure for roads would look like.

Obviously, this question also means to ask how the road data structures would interact with cars.

Any recommendations, or reviews of such data models?

答:
I don't know whether you need life-perfect simulation or not, just one of my previous project as an example.

This was a part of the program for studying highway code (I'm not sure this is the correct word). It was developed in 1996 for Window 3.1 so the computer resources were much more limited that today. The program consisted of multiply random moving vehicles and single handled by the user (blue one on the screenshot). I divided the area with 40x40 cells that could be visually distinct but from the point of view of a car this was a single unit of analyzing and decision making. So for a virtual area of 4000x3000 pixels the program needed only 100x75 array of different data specific to road traffic and positions of the vehicles. The crosses were a more complex structures with the states of allowed directions and intentions of the participants appearing as temporal states and available for others also.


问:
What exactly comprises 'Documentation'?
When we say 'documentation' for a software product, what does that include and what shouldn't that include?

For example, a recent question asked if comments are considered documentation?

But there are many other areas that this is a valid question for as well, some more obvious than others:

Manuals (obviously)

Release notes?

Tutorials

Comments

Any others?

Where is the line drawn. For example, if 'tutorial' is documentation, is 'video tutorial' documentation, or is it something else?

Generally, something in software isn't 'done' until it is implemented, tested and documented. Hence this question, what things should we consider as part of documention to consider something 'done'.

Question inspire from recent customer feedback at our conference indicating that our doc needed more 'samples', which we previously hadn't been as good at considering as we should have been.

Audience: Software developers using our database(s), programming languages and associated tooling (such as admin clients to said DB)

答:
Documentation is stuff intended to be read without modifying it.

I think you can't go wrong with purpose-based definition... but only if you define purpose properly.

Properly defining documentation purpose is not quite simple. Straightforward (naive if you wish) distinction that naturally comes to mind is that documentation is everything that is intended for reading - while, for comparison, code is anything intended for computer execution. Sounds nice at the surface doesn't it? but it really turns out quite ugly once you dig deeper.

Thing is, good code takes into account readability concerns, along with execution correctness - this makes "readability" distinction pretty useless in defining documentation.

The very samples you mentioned show what's wrong with it. Clients typically expect these to be clearly written and execute correctly. Compromising either of readability or correctness can bring a waterfall of the customer complaints. Naive distinction doesn't help to figure whether samples are code or documentation.

Using naive distinction will get even more messy if you imagine working with open source. You download, build and run it - you don't read it, it's just the code right? Wait, things somehow went wrong and you get to the code to read what's going on there... hey you read not execute - is this documentation now? And, finally, you find bug in the source and fix it - now this is really the code, it is not something normally called documentation, no matter how carefully you read it to make that fix.

For the 'samples' you are going to provide, read-not-modify distinction might turn out quite important.

Look, if some sample fails when run unchanged, in the documented reference environment, it's your bug - bug in your documentation, one you have to accept and fix, fine.

Now, if there is a problem with modified sample or environment, it's not your fault anymore - I mean no bug in the documentation, since docs are not intended for modification. Whatever help you provide users in case like that, would fall under support category, not a bugfix.

Title: What exactly comprises 'Documentation'?


问:
What popular "best practices" are not always best, and why?
"Best practices" are everywhere in our industry.  A Google search on "coding best practices" turns up nearly 1.5 million results.  The idea seems to bring comfort to many; just follow the instructions, and everything will turn out fine.

When I read about a best practice - for example, I just read through several in Clean Code recently - I get nervous.  Does this mean that I should always use this practice?  Are there conditions attached?  Are there situations where it might not be a good practice?  How can I know for sure until I've learned more about the problem?

Several of the practices mentioned in Clean Code did not sit right with me, but I'm honestly not sure if that's because they're potentially bad, or if that's just my personal bias talking.  I do know that many prominent people in the tech industry seem to think that there are no best practices, so at least my nagging doubts place me in good company.

The number of best practices I've read about are simply too numerous to list here or ask individual questions about, so I would like to phrase this as a general question:

Which coding practices that are popularly labeled as "best practices" can be sub-optimal or even harmful under certain circumstances?  What are those circumstances and why do they make the practice a poor one?

I would prefer to hear about specific examples and experiences.

答:
Might as well throw this into the ring:

```<code>Premature optimization is the root of all evil.
</code>```

No, it's not.

The complete quote:

"We should forget about small
  efficiencies, say about 97% of the
  time: premature optimization is the
  root of all evil. Yet we should not
  pass up our opportunities in that
  critical 3%."

That means that you take advantage of specific, strategic performance enhancements throughout your design process.  It means that you use data structures and algorithms that are consistent with performance objectives.  It means that you are aware of design considerations that affect performance.  But it also means that you do not frivolously optimize when doing so will give you minor gains at the expense of maintainability.

Applications need to be well-architected, so that they don't fall down at the end when you apply a little load on them, and then you wind up rewriting them. The danger with the abbreviated quote is that, all too often, developers use it as an excuse to not think about performance at all until the end, when it might be too late to do anything about it. It's better to build in good performance from the start, provided you're not focusing on minutiae.

Let's say you're building a real-time application on an embedded system.  You choose Python as the programming language, because "Premature optimization is the root of all evil."  Now I have nothing against Python, but it is an interpreted language.   If processing power is limited, and a certain amount of work needs to get done in real-time or near real-time, and you choose a language that requires more processing power for the work than you have, you are royally screwed, because you now have to start over with a capable language.

Body:
Might as well throw this into the ring:

Premature optimization is the root of all evil.

No, it's not.

The complete quote:

"We should forget about small
  efficiencies, say about 97% of the
  time: premature optimization is the
  root of all evil. Yet we should not
  pass up our opportunities in that
  critical 3%."

That means that you take advantage of specific, strategic performance enhancements throughout your design process.  It means that you use data structures and algorithms that are consistent with performance objectives.  It means that you are aware of design considerations that affect performance.  But it also means that you do not frivolously optimize when doing so will give you minor gains at the expense of maintainability.

Applications need to be well-architected, so that they don't fall down at the end when you apply a little load on them, and then you wind up rewriting them. The danger with the abbreviated quote is that, all too often, developers use it as an excuse to not think about performance at all until the end, when it might be too late to do anything about it. It's better to build in good performance from the start, provided you're not focusing on minutiae.

Let's say you're building a real-time application on an embedded system.  You choose Python as the programming language, because "Premature optimization is the root of all evil."  Now I have nothing against Python, but it is an interpreted language.   If processing power is limited, and a certain amount of work needs to get done in real-time or near real-time, and you choose a language that requires more processing power for the work than you have, you are royally screwed, because you now have to start over with a capable language.


问:
Reducing number of php files used in project
I am developing an application in which I have a Class containing various methods. The problem is that i need to call most of the methods on form submission. For that reason, I have to create a new file on each form submission. On every file, I have to create an instance of the same class and then call the appropriate method.

Is there any better way to call methods in such situation so that I don't have to create multiple files having similar functionality in php? I surely don't want to use any framework.

答:
Can't you use the include function? Make your file with the Class once, include it in projects that use the methods.</p>

```<code>include 'vars.php';
</code>```

Body:
Can't you use the include function? Make your file with the Class once, include it in projects that use the methods.

include 'vars.php';


问:
DB technology for efficient search in tabular data?
We have a repository of tables. Around 200 tables, each table can be thousands of rows, all tables are originally in Excel sheets.

Each table has a different scheme. All data is text or numbers.

We would like to create an application that allows free text search on all tables (we define which columns will be searched in each table) efficiently - speed is important.

The main dilemma is which DB technology we should choose.

We created a mock up by importing all tables to MS SQL Server, and creating a full text index over them. The search is done using the CONTAINS keyword. This solution works well for a small number of tables, but it doesn't scale.

We thought about a NoSQL solution, but we don't yet have any experience in it.

Our limitations (which unfortunately I can not effect): Windows servers only. But we can install on them whatever we want.

答:
If you were to go the NoSQL route, or even if you weren't, I'd suggest looking at Lucene (also has a .NET implementation) for your indexing needs. It is a very high performance component and would actually yawn at the numbers you're quoting.

If it's a little low level for you, look at RavenDb. It's a NoSQL solution that uses Lucene for its indexing. It's a .NET solution though (you never mentioned which language/platform you're using), if you are using .NET it really shines with its support for LINQ. I would consider another alternative (like MongoDB) if you're not using .NET because there aren't currently any RavenDB clients implemented for other platforms.

I would say try them both if you have the time (it sounds like you're still in the prototyping stage of your application). There are advantages to each. As I mentioned, RavenDB really shines for a .NET application because of how deeply ingrained LINQ is in it's API. You define indexes using LINQ, you query with LINQ...it's really powerful stuff. MongoDB is older and can be used easily with other platforms if you have that need.

Hope this helps.


答:
The goal of documentation is to describe and explain the software product, so you could define the documentation to be the set of artefacts that contribute to that description or explanation. You'd probably not consider related actions as part of the documentation: e.g. a week-long training course is not documentation but the course materials are; a five-minute whiteboard chat is not documentation but an image of the whiteboard is.

Keeping the goal (explaining the software) in mind, the documentation is finished when the customer is satisfied with the explanation: just as the software is finished when the customer is satisfied with the software. Bear in mind that the customer for the documentation is not always the same as the customer paying for the software: support personnel, testers, salespeople and others will all need some understanding of what the software does and how it works.

This helps understand where your boundary for what should be included in the documentation lies. Using "reader" as a convenient shorthand, though we accept that videos or audio could be included: anything that helps the reader gain the information they need about the software is documentation they can use, everything else isn't. If your customer needs detailed walk-throughs of all their use cases, then that needs to be part of the documentation. Your developers probably need source code, information about your version control repository and build instructions: that's documentation for them, but as described above it wouldn't be part of the customer's documentation.

Title: What exactly comprises 'Documentation'?

Body:
When we say 'documentation' for a software product, what does that include and what shouldn't that include?

For example, a recent question asked if comments are considered documentation?

But there are many other areas that this is a valid question for as well, some more obvious than others:

Manuals (obviously)

Release notes?

Tutorials

Comments

Any others?

Where is the line drawn. For example, if 'tutorial' is documentation, is 'video tutorial' documentation, or is it something else?

Generally, something in software isn't 'done' until it is implemented, tested and documented. Hence this question, what things should we consider as part of documention to consider something 'done'.

Question inspire from recent customer feedback at our conference indicating that our doc needed more 'samples', which we previously hadn't been as good at considering as we should have been.

Audience: Software developers using our database(s), programming languages and associated tooling (such as admin clients to said DB)


问:
If you were the manager of a team of 25 developers, how would you motivate them?
Imagine yourself hired by a new startup backed with few millions coming from venture capitalists.

Your mission: organize the development of the next killer app.

25 developers is too much to take care of each individually, so what decision(s) you would make to motivate them?

I will appreciate any answers from stock options to free cookies ;)

Of course the trick here (unless you are really a manager of a such startup), is put yourself in the shoes of one of those programmers.

EDIT: it's an imaginary context. The purpose of this story is to stimulate your wishes. I want to capture what motivates developers.

答:
Sub teams (DB, middle layer, GUI)

Wot no testers? Replace some code monkeys

Wot no analysts? Replace some code monkeys

Who will manage tools/source control/wiki/infrastructure/environments? Replace some code monkeys

Free coffee, free water, free fruit

Friday beers


问:
Do I have to remove my app from app store? (Copyright infringement)
I just got an copyright infringement notice that says my app infringes on the usage policies of the services my app uses.

However, this mail does not come directly from the company that runs the website I pull information from.
The mail comes from a company that has some paid apps in the same category on the app store (mine is free), so they obviously want me gone.

My question is, can I just ignore this mail until I hear directly from the company that runs the website? Judging from their (the company that contacted me) website, they have no connection what so ever to the company that I fetch information from.

答:
I would let your span filter eat the email and see what happens next, in the meanwhile see if you can conformation from the data provider that what you are doing is OK.

It is very possible that you will never get troubled by them again, even if the email is from someone that can take legal action against you, they will consider the cost before getting their lawyer to right to you most likely by smail.

(Given that over 50% of this type of email is span, it is reasonable for your span filter to hide the email from you)


问:
Open Source license compatibility checker
Is there a tool available for checking if various combinations of open source licenses are compatible with each other?

I'm planning on building various tools that use an Apache license for distribution because Apache's licence seems to strike a good balance between being permissive and being enforceable in law.  However, I'd like to include components from other open source projects in my code base, or make adaptors available to allow the end user to integrate such components into my code base.

For example, I want to include a rich HTML editor such as CKEditor or TinyMCE in the package, but would doing so violate the licence of either project?  I'm pretty sure that if I used GPL code it would force me to make my project GPL as well and I really don't want to do that.  But what about MPL, LGPL, etc?

I'd rather make such decisions purely on technical grounds but if you're doing open source it would be silly to ignore the wishes of other open source projects.

I've tried looking for tools to help decide whether license X is compatible with license Y, if so which direction they're compatible in (X can include Y without issue, but if Y includes X then there could be problems, etc), and what the consequences on your licensing terms are if you include code with alternate licensing terms.  All I've managed to find so far, however, is lists and charts that tend to be geared to comparing other licenses against GPL.  If there is a tool out there to help with licensing issues I'd appreciate being pointed in the right direction.

答:
I think you're looking for Black Duck Protex.

...solution for managing open source compliance. Protex integrates with existing development tools to automatically scan, discover and identify software origins, an integral step in the development process and essential for enforcing license compliance and corporate policy requirements.


问:
Commented short fancy code vs. uncommented longer easy-to-understand code - which is preferred?
Sometimes an algorithm can be written in two ways:

The short, fancy way; or

The longer, easy-to-understand way.

For example, here is a longer, easier way of copying a string source to dest in C:

```<code>*dest = *source;
while (*source != '\0') {
    source++;
    dest++;
    *dest = *source;
} (true);
</code>```

And here is a short, fancy way.

```<code>// Copy string source to dest
while (*dest++ = *source++);
</code>```

I've always heard and read that fancy code should be avoided, and I tend to agree. But what if we take comments into account? Assume that, as in the examples above, we have an uncommented, longer and supposedly easier-to-understand code, and a well-commented, short, fancy code? Is the non-fancy code still preferred?

EDIT: Many have commented on variable names, so I've modified the example code as to not make that a factor when preferring on over the other. I tried to remove the double assignment in the first example, but that only made the code less readable.

Perhaps this wasn't the best of examples because many find the 'fancy' code more readable and understandable than the longer code. The idea was to have one longer code which was much easier to understand than a very short but complicated code.

EDIT2: Here's a new examle I got from SO:

Commented fancy version:

```<code>//direct formula for xoring all numbers from 1 to N
int Sum = (N & (N % 2 ? 0 : ~0) | ( ((N & 2)>>1) ^ (N & 1) ) );
</code>```

Non-commented long version:

```<code>int Sum = 0;
for (int i = 1; i < N; ++i)
{
   Sum ^= i; //or Sum = Sum ^ i;
}
</code>```

答:
It of course entirely depends upon the circumstances. but in general, i find this to be a good rule of thumb:

Debugging is twice as hard as writing the code in the first place.
  Therefore, if you write the code as cleverly as possible, you are, by
  definition, not smart enough to debug it.

~ Brian Kernighan


问:
Is it considered bad practice to run different JavaScript for IE
Is it considered bad practice (and how bad) to run different JavaScript for IE? Currently im writing some JavaScript and the simplist way to work arround IE quirks seems to be to check for browser version and run different code

```<code>var browserName = navigator.appName;

if (browserName == "Microsoft Internet Explorer") {
  //Do some stuff
}
else
{
//Do other stuff
}
</code>```

It's quick and works well but does lead to duplication of code and feels "hacky".

答:
It’s ok when it’s valid JS and there are no abstractions

It's not exactly bad practice, even though it got better, browsers aren’t 100% identic.

But, before starting special cases, look carefully, if they are really special cases and not just idiosyncracies of another browser. In this case, you should search for a solution using standards all browsers share (caniuse.com is of great help for that).

When you are sure that it is indeed browserspecific, imho you should look if you can use a library that hides this detail from you. Cross Browser Compatibility is a hard thing to get right, so if someone did it for you, just profit.

As a last resort, do what you have to do ;)


问:
How to encrypt data using the private key?
I understand that in asymmetric crypto systems:

The public key is generally used to encrypt data and only the private key can be used to decrypt that data.

It's trivial to derive a public key from the private key (see this SO question).

Firstly, is this correct?

My goal is to supply data with my application that is difficult to decrypt and impossible to change, and so I want to be able to encrypt my data using a private key (which only I have) and allow my application to decrypt that data during runtime (hiding the public key as much as possible).

I understand that this isn't fool-proof, however, I want to stop casual re-use of the data supplied with my application.

Can anyone suggest an algorithm (preferably part of openssl) that can be used to achieve my goal?  Looking at RSA_private_encypt, for example, shows that the encrypted data is of size RSA_size() (something like 128-bytes), which is because that function is used to generate signatures, not encrypted data.  Is there a private encryption algorithm that generates data equal to the size of the plaintext data?

答:
If you both encrypt and decrypt than you don't need public key.

You can use one of Rijndael implementations to encrypt your data before shipping the application and decrypt during runtime.

You might even want to use a license file with unique salt for Rijndael (that same salt should be used to encrypt the data). This way your data could not be used with another installation without copying the license key.


问:
What would be the Impact of P=NP?
I am preparing for a test and I can't find a clear answer on the question: What would be the impact of proving that PTIME=NPTIME. I checked wikipedia and it just mentioned that it would have "profound impact on maths,AI,algorithms.." etc.

Anyone can give me an answer?

答: First thing that comes to mind is that the security of public-key cryptography currently depends on being unable to brute-force math problems that are in the NP difficulty class.  If P = NP, everything that depends on PKC (including HTTPS, which means the entire modern, worldwide ecommerce infrastructure) would have to be reworked!

Title: What would be the Impact of P=NP?


问:
How can I apply OOP concepts to building a simple, but real-world, web app?
I've been trying now for a long time to wrap my head around OOP. I see its advantages. I've read many, many tutorials and watched an equal amount of videos on the subject. I get the animal/cat/dog examples, I get the car/drive examples. What I'm struggling with is how to apply these concepts in a real-world application. So, I've set out to build one using OOP.

I am not asking for help with syntax or writing specific code — I can find that myself in documentation and by searching forums etc.. What I really need is some guidance, and a push in the right direction every now and then. Are there any seasoned programmers willing to mentor me?

As my learning project I would like to build a simple classifieds "web app". Something similar to Craigslist but way watered down in terms of scope. I would like to use PHP5 and MySQL, because I am familiar with them.

Let's say there are only these 2 use cases:

Posting something for sale

Browsing/searching for something to buy

What "things" should be objects? I can imagine that each item could be an object, but at what point? And why?

So for example, the user fills out the "post item for sale" form, should that form get turned into an object which gets passed to another object which inserts the values into a database?

What about when another user is browsing and requests to see all items of category C? Does it make sense that whenever the app has to connect to its database it creates a database object and then gets a bunch of item objects and displays them on the page? …writing this out certainly makes me realize how clueless I still am about OOP. Please help me fix that.

If in your opinion this is not a good project to start wading into OOP with, please feel free to suggest another idea!

答:
Here is how you can use OOP to buy and sell your pets, the same methodology could be used to sell cars or planes ;p</p>

```<code><?php
// define a superclass .. no instances will be made of 'animal' itself,
// but it is useful to define common characteristics and behaviours
// (ie: properties and methods) of all our classes of animals
class Animal {

    // this constructor function is called whenever a new instance
    // of the Animal class is created (or any class that inherits from Animal)
    function Animal ($colour) {

        // install the argument as an attribute of any instances of Animal
        $this->colour = $colour;
    }

    // this method will be available to all classes that inherit from Animal
    function report () {
        return "This ".$this->colour." ".get_class($this)." has ".$this->legs." legs.<br />";
    }
}

// this class inherits from Animal
class Cat extends Animal {

    // set the legs attribute
    public $legs = 4;

    // create a method that can be called from any instances of Cat
    function make_noise () {
        echo "MEOW!<br />";
    }
}

// this class inherits from Cat, and from Animal
class Panther extends Cat {

    // specifies the colour attribute
    public $colour = "black";

    // overwrites the constructor function that would otherwise be
    // inherited from Animal, with a blank constructor.
    function Panther () {}

    // overwrites the method inherited from Cat
    function make_noise () {
        echo "ROARRRR!<br />";
    }
}

// this class inherits from Animal
class Snake extends Animal {
    public $legs = 0;
}

// this class is unrelated to the others
class PetShop {

    // set up an array to store the pets that the shop will stock
    public $pets = array ();

    // set up a variable to store the total cash in the pet shop
    public $cash;

    // this method creates a new object and adds it to the pets array
    function add_pet ($petclass, $price, $colour) {

        // set up a variable containing the number of elements in the pets array
        $n_pets = count($this->pets);

        // add to the pets array, a new instance of the class specified as
        // the first argument in this method, using the last argument as the
        // colour argument that is passed to the specified class's constructor
        $this->pets[$n_pets] = new $petclass($colour);

        // add a 'price' attribute to the pet object
        $this->pets[$n_pets]->price = $price;
    }

    // this method removes the specified pet from the array and adds the price
    // to the pet shop's cash variable
    function sell_pet ($n) {

        // add pet's price to the cash total
        $this->cash += $this->pets[$n]->price;

        // remove the pet object from the array
        array_splice($this->pets, $n, 1);

        // give a message about the sale
        echo "SALE: Pet no. ".$n." sold. Total cash is now \$".$this->cash.".<br /><br />";
    }

    // this method reports on the pet shop's stock
    function show_pets () {

        // show the number of pets available
        echo "<B>Shop stock:</B><br />We have ".count($this->pets)." pets for sale.";
        echo "<br /><br />";

        // iterate through the pets array and show information about each one
        for ($i = 0; $i < count($this->pets); $i++) {
            echo "<B>Pet No. ".$i.": </b>".$this->pets[$i]->report();
            echo "Price: \$".$this->pets[$i]->price."<br />";
        }
        echo "<br />";
    }
}

// instantiate a new PetShop object
$shop = new PetShop ();

// add three pets to the shop
$shop->add_pet(cat, 20, "tabby");
$shop->add_pet(snake, 40, "brown");
$shop->add_pet(snake, 60, "black");

// show the pet's stock
$shop->show_pets();

// sell the first pet in the stock
$shop->sell_pet(0);

// show the pet's stock after the sale
$shop->show_pets();
?>
</code>```

OwnerDisplayName: Bern

Body:
Here is how you can use OOP to buy and sell your pets, the same methodology could be used to sell cars or planes ;p

<?php
// define a superclass .. no instances will be made of 'animal' itself,
// but it is useful to define common characteristics and behaviours
// (ie: properties and methods) of all our classes of animals
class Animal {

    // this constructor function is called whenever a new instance
    // of the Animal class is created (or any class that inherits from Animal)
    function Animal ($colour) {

        // install the argument as an attribute of any instances of Animal
        $this->colour = $colour;
    }

    // this method will be available to all classes that inherit from Animal
    function report () {
        return "This ".$this->colour." ".get_class($this)." has ".$this->legs." legs.<br />";
    }
}

// this class inherits from Animal
class Cat extends Animal {

    // set the legs attribute
    public $legs = 4;

    // create a method that can be called from any instances of Cat
    function make_noise () {
        echo "MEOW!<br />";
    }
}

// this class inherits from Cat, and from Animal
class Panther extends Cat {

    // specifies the colour attribute
    public $colour = "black";

    // overwrites the constructor function that would otherwise be
    // inherited from Animal, with a blank constructor.
    function Panther () {}

    // overwrites the method inherited from Cat
    function make_noise () {
        echo "ROARRRR!<br />";
    }
}

// this class inherits from Animal
class Snake extends Animal {
    public $legs = 0;
}

// this class is unrelated to the others
class PetShop {

    // set up an array to store the pets that the shop will stock
    public $pets = array ();

    // set up a variable to store the total cash in the pet shop
    public $cash;

    // this method creates a new object and adds it to the pets array
    function add_pet ($petclass, $price, $colour) {

        // set up a variable containing the number of elements in the pets array
        $n_pets = count($this->pets);

        // add to the pets array, a new instance of the class specified as
        // the first argument in this method, using the last argument as the
        // colour argument that is passed to the specified class's constructor
        $this->pets[$n_pets] = new $petclass($colour);

        // add a 'price' attribute to the pet object
        $this->pets[$n_pets]->price = $price;
    }

    // this method removes the specified pet from the array and adds the price
    // to the pet shop's cash variable
    function sell_pet ($n) {

        // add pet's price to the cash total
        $this->cash += $this->pets[$n]->price;

        // remove the pet object from the array
        array_splice($this->pets, $n, 1);

        // give a message about the sale
        echo "SALE: Pet no. ".$n." sold. Total cash is now \$".$this->cash.".<br /><br />";
    }

    // this method reports on the pet shop's stock
    function show_pets () {

        // show the number of pets available
        echo "<B>Shop stock:</B><br />We have ".count($this->pets)." pets for sale.";
        echo "<br /><br />";

        // iterate through the pets array and show information about each one
        for ($i = 0; $i < count($this->pets); $i++) {
            echo "<B>Pet No. ".$i.": </b>".$this->pets[$i]->report();
            echo "Price: \$".$this->pets[$i]->price."<br />";
        }
        echo "<br />";
    }
}

// instantiate a new PetShop object
$shop = new PetShop ();

// add three pets to the shop
$shop->add_pet(cat, 20, "tabby");
$shop->add_pet(snake, 40, "brown");
$shop->add_pet(snake, 60, "black");

// show the pet's stock
$shop->show_pets();

// sell the first pet in the stock
$shop->sell_pet(0);

// show the pet's stock after the sale
$shop->show_pets();
?>

OwnerDisplayName: Lawrence Cherone


答:
The best thing to do is to find a way of concentrating on the core of your application - "post", "user", "post::FindByName()", "user->Validate()" etc., and not worry too much about the plumbing - how to glue posts to database tables, how to keep the display for a post consistent between different searches, and how to glue the "enter post" form to a database record.

Luckily, there are lots of frameworks that do this for you; the dominant paradigm in OO web applications is "Model-View-Controller", also known as MVC; in PHP, there are a number of off-the-shelf MVC frameworks you can use.

Whilst this expands your need to learn - you now have to learn about MVC as well as OO - it means that your OO efforts are mostly constrained to the "Model" layer, which represents your business domain; that's where OO is most natural and expressive. Most of the MVC frameworks allow you to define your "model" layer, and then automagically create a web site around that using a technique known as scaffolding - that way, you get a quick way of experimenting with different implementations for your domain model, without having to unpick all the plumbing.

Title: How can I apply OOP concepts to building a simple, but real-world, web app?

Body:
I've been trying now for a long time to wrap my head around OOP. I see its advantages. I've read many, many tutorials and watched an equal amount of videos on the subject. I get the animal/cat/dog examples, I get the car/drive examples. What I'm struggling with is how to apply these concepts in a real-world application. So, I've set out to build one using OOP.

I am not asking for help with syntax or writing specific code — I can find that myself in documentation and by searching forums etc.. What I really need is some guidance, and a push in the right direction every now and then. Are there any seasoned programmers willing to mentor me?

As my learning project I would like to build a simple classifieds "web app". Something similar to Craigslist but way watered down in terms of scope. I would like to use PHP5 and MySQL, because I am familiar with them.

Let's say there are only these 2 use cases:

Posting something for sale

Browsing/searching for something to buy

What "things" should be objects? I can imagine that each item could be an object, but at what point? And why?

So for example, the user fills out the "post item for sale" form, should that form get turned into an object which gets passed to another object which inserts the values into a database?

What about when another user is browsing and requests to see all items of category C? Does it make sense that whenever the app has to connect to its database it creates a database object and then gets a bunch of item objects and displays them on the page? …writing this out certainly makes me realize how clueless I still am about OOP. Please help me fix that.

If in your opinion this is not a good project to start wading into OOP with, please feel free to suggest another idea!

OwnerDisplayName: Neville K


答:
I honestly think that the advice here has been terrible for new OO learners so far.  It's not a good idea to immediately start thinking of objects as representations of a specific instance of a "thing" defined by some class.  It's better to think of them as compartmentalized components of a machine that have some interaction with one another, but not each others' internals.  Each of these components maintains state

If you want to use an ORM (object-relational-mapping) for DB interactions, whatever framework you use or create will probably have some shallow objects representing tables, which are probably collections of "things," but I don't like ORMs personally, and I don't think they necessarily represent ideal OO practices, but they are popular for large web-apps.

Besides that, you will probably have some important components that the web-app machine needs to run such as one or more DB connections (you can create a class that maintains a connection and you can run prepared queries from -- PDO is great on its own, but I would wrap it), and perhaps a template system for your views.  You may want your controllers to be PHP objects as well.  If you have a form to fill out, you may have an object that maintains form values for P/R/G, a CSRF-protection token, and can perform validation on its inputs.

You shouldn't try to look for "things" to turn into objects when constructing your web-app design and object graph.  Instead, you should think about the logical components that come together to create it.  I don't think you should try to force this, and it should come fairly naturally, but it's very hard to do correctly and you will definitely end up having to change some design decisions along the way.

My final advice is this: composition over inheritance is the way to go.

OwnerDisplayName: tandu


答:
On request of OP I'll share my guestbook code.

Message class:

```<code><?php
Class message
{
    private $db;
    private $messageID;
    private $message;
    private $name;
    private $mail;

    public function setmessageID($messageID)
    {
        $this->messageID = $messageID;
    }

    public function getmessageID()
    {
        return $this->messageID;
    }

    public function setmessage($message)
    {
        $this->message = $message;
    }

    public function getmessage()
    {
        return $this->message;
    }

    public function setname($name)
    {
        $this->name = $name;
    }

    public function getname()
    {
        return $this->name;
    }

    public function setMail($mail)
    {
        $this->mail = $mail;
    }

    public function getMail()
    {
        return $this->mail;
    }
}
</code>```

Message Data Access Object Class:

```<code><?php
class messageDAO
{
    private $db;
    private $aantalMessages;
    private $messages;
    private $message;

    //bij laden roept hij automatisch Db class aan (en de daarbij gezeten functies)
    public function __construct(Db $db)
    {
        $this->db = $db;
    }

    public function getMessages()
    {
        return $this->messages;
    }

    public function getAantalMessages()
    {
        return $this->aantalMessages;
    }

    //Function to retrieve messages
    public function findMessages($args)
    {
        $dbh = $this->db->DBH();

        //$offset for pagination
        $offset = ($args['currentPage'] - 1) * $args['itemsPerPage'];

        $sth = $dbh->prepare("SELECT    SQL_CALC_FOUND_ROWS
                                                    messageen.messageID,
                                                    messageen.message,
                                                    messageen.name,
                                                    messageen.mail
                                            FROM    `messageen`
                                            ORDER BY messageen.datumToegevoegd DESC
                                            LIMIT   ?, ?");
        $sth->bindParam(1, $offset, PDO::PARAM_INT);
        $sth->bindParam(2, $args['itemsPerPage'], PDO::PARAM_INT);
        $sth->execute();
        $sth->setFetchMode(PDO::FETCH_ASSOC);

        $messages = array();

        while($row = $sth->fetch())
        {
            $message = new message();
            $message->setMessageID(htmlentities(strip_tags($row['messageID'])));
            $message->setSessage(htmlentities(strip_tags($row['message'])));
            $message->setName(htmlentities(strip_tags($row['name'])));
            $message->setMail(htmlentities(strip_tags($row['mail'])));
            $messages[] = $message;
        }

        $sth = $dbh->prepare("SELECT FOUND_ROWS() as numberOfMessages");
        $sth->execute();
        $sth->setFetchMode(PDO::FETCH_ASSOC);
        $this->numberOfMessages = $sth->fetch();

        return $messages;
    }

    public function setMessageToEdit($args)
    {
        $sth = $this->db->DBH()->prepare("SELECT    messages.message
                                            FROM    `messages`
                                            WHERE   messages.messageID = ?");
        $sth->bindParam(1, $args['messageID']);
        $sth->execute();
        $sth->setFetchMode(PDO::FETCH_ASSOC);
        //return the retrieved message
        while($row = $sth->fetch())
        {
            $message = new message();
            $message->setMessage(htmlentities(strip_tags($row['message'])));
            $message->setMessageID(intval($args['messageID']));
        }

        return $message;
    }

    //functie om messageen aan te passen
    public function save(message $message)
    {
        //insert part
        //if(isset($message->getname()) && isset($message->getmessage()) && isset($message->getMail()))
        //{
            $sth = $this->db->DBH()->prepare("INSERT INTO   `messages`
                                                    SET     messages.name = ?,
                                                            messages.mail = ?,
                                                            messages.message = ?,
                                                            messages.dateAdded = NOW()");
            $sth->bindParam(1, $message->getName());
            $sth->bindParam(2, $message->getMail());
            $sth->bindParam(3, $message->getMessage());
            $sth->execute();
        //}

        //update part
        /*if(isset($message->getmessageID()) && isset($message->getmessage()))
        {
            $sth = $this->db->DBH()->prepare("UPDATE    `messageen`
                                                SET     messageen.message = ?
                                                WHERE   messageen.messageID = ?
                                                LIMIT   1");
            $sth->bindParam(1, $message->getmessage());
            $sth->bindParam(2, $message->getmessageID());
            $sth->execute();
        }*/
    }
}
</code>```

index.php

```<code><?php
//include file loader.php
include("includes/loader.php");

$guestbook = new guestbook($db);
$user = new user($db);
$messageDAO = new messageDAO($db);

//Make a array named error
$error = array();

//Get action (login/setmessage/editmessage/deletemessage)
if(isset($_GET['action']))
{
    switch ($_GET['action'])
    {
        //if login submit is pressed
        case 'login':
            //Check if filled
            if(isset($_POST['username']) && isset($_POST['username']))
            {
                $error['usernameEmpty'] = (bool) !strlen(trim($_POST['username']));
                $error['passwordEmpty'] = (bool) !strlen(trim($_POST['password']));
            }

            if(in_array(1, $error))
            {
                //Assign $error to smarty
                $smarty->assign('error', $error);
            }

            else
            {
                if(isset($_POST['username']) && isset($_POST['username']))
                {
                    $user->setLoggedIn(array('username'=>$_POST['username'],
                    'password'=>$_POST['password']));

                    if($user->getLoggedIn() != true)
                    {
                        $smarty->assign('loggedInError', $user->getLoggedIn());
                    }
                }
            }
            break;

        //Als if "place message" is pressed
        case 'placemessage':
            //if user is not logged in
            if($user->getLoggedIn() != true)
            {
                //Controleren of message-velden wel zijn ingevuld
                $error['nameEmpty'] = (bool) !strlen(trim(htmlentities(strip_tags($_POST['messagename']))));
                $error['mailEmpty'] = (bool) !strlen(trim(htmlentities(strip_tags($_POST['messageMail']))));
                $error['messageEmpty'] = (bool) !strlen(trim(htmlentities(strip_tags(str_replace('place message...','', $_POST['messageInput'])))));

                if($error['mailEmpty'] != 1)
                {
                    $error['mailInvalid'] = !filter_input((INPUT_POST), 'messageMail', FILTER_VALIDATE_EMAIL);
                }

                if(in_array(1, $error))
                {
                    $smarty->assign('error', $error);
                }

                else
                {
                    $message = new message();

                    $message->setname($_POST['messagename']);
                    $message->setMail($_POST['messageMail']);
                    $message->setmessage($_POST['messageInput']);

                    dump($message);

                    //place message
                    $messageDAO->save($message);
                }
            }

            //if user is logged in
            else
            {
                //is message filled?
                $error['messageEmpty'] = (bool) !strlen(trim(htmlentities(strip_tags(str_replace('place hier uw message...','', $_POST['messageInput'])))));

                if($error['messageEmpty'] != 1)
                {
                    $user->setUser();

                    $guestbook->placemessage(array('name'=>$user->getLoggedInUsername(),
                    'mail'=>$user->getLoggedInUserMail(),
                    'messageInput'=>$_POST['messageInput']));
                }

                else
                {
                    $smarty->assign('error', $error);
                }
            }
            break;

        case 'deletemessage':
            $user->setUser();

            if($user->getLoggedInUserAdmin() == 1)
            {
                if(isset($_GET['messageID']) && is_numeric($_GET['messageID']) && isset($_GET['key']))
                {
                    $guestbook->setURLKey($_GET['messageID']);

                    if($guestbook->getURLKey() == $_GET['key'])
                    {
                        $guestbook->verwijdermessage(array('messageID'=>$_GET['messageID']));
                    }
                }
            }
            die(header("location: /index.php"));
            break;
    }
}

if(isset($_GET['pagina']) && is_numeric($_GET['pagina']))
{

    $currentpage = $_GET['pagina'];
}

else
{
    //$currentpage is 1
    $currentpage = 1;
}

$user->setUser();

//assign var to smarty
$smarty->assign('messages', $messageDAO->findmessages(array('currentpage'=>$currentpage, 'itemsPerPagina'=>10)));
$smarty->assign('user', $user);

//Pagination

$numbermessages = $messageDAO->getnumbermessages();

$totalpages = ceil($numbermessages['numbermessages'] / 10);

if($currentpage < 1)
{
    //$currentpage is 1
    $currentpage = 1;
}

if($currentpage > $totalpages)
{

    $currentpage = $totalpages;
}

$smarty->assign('numbermessages', $messageDAO->getnumbermessages());
$smarty->assign('guestbook', $guestbook);
$smarty->assign('currentpage', $currentpage);
$smarty->assign('totalpages', $totalpages);

//display index.tpl
$smarty->display('index.tpl');
</code>```

I renamed some of the variables and function to make sense to you (translated from dutch to english :P ) so you might find some weird sentances sometimes because i just did a quick replace etc. Have fun with it. Also this isnt the whole code because that would result in me posting like 20 files worth of code :P

Body:
On request of OP I'll share my guestbook code.

Message class:

<?php
Class message
{
    private $db;
    private $messageID;
    private $message;
    private $name;
    private $mail;

    public function setmessageID($messageID)
    {
        $this->messageID = $messageID;
    }

    public function getmessageID()
    {
        return $this->messageID;
    }

    public function setmessage($message)
    {
        $this->message = $message;
    }

    public function getmessage()
    {
        return $this->message;
    }

    public function setname($name)
    {
        $this->name = $name;
    }

    public function getname()
    {
        return $this->name;
    }

    public function setMail($mail)
    {
        $this->mail = $mail;
    }

    public function getMail()
    {
        return $this->mail;
    }
}

Message Data Access Object Class:

<?php
class messageDAO
{
    private $db;
    private $aantalMessages;
    private $messages;
    private $message;

    //bij laden roept hij automatisch Db class aan (en de daarbij gezeten functies)
    public function __construct(Db $db)
    {
        $this->db = $db;
    }

    public function getMessages()
    {
        return $this->messages;
    }

    public function getAantalMessages()
    {
        return $this->aantalMessages;
    }

    //Function to retrieve messages
    public function findMessages($args)
    {
        $dbh = $this->db->DBH();

        //$offset for pagination
        $offset = ($args['currentPage'] - 1) * $args['itemsPerPage'];

        $sth = $dbh->prepare("SELECT    SQL_CALC_FOUND_ROWS
                                                    messageen.messageID,
                                                    messageen.message,
                                                    messageen.name,
                                                    messageen.mail
                                            FROM    `messageen`
                                            ORDER BY messageen.datumToegevoegd DESC
                                            LIMIT   ?, ?");
        $sth->bindParam(1, $offset, PDO::PARAM_INT);
        $sth->bindParam(2, $args['itemsPerPage'], PDO::PARAM_INT);
        $sth->execute();
        $sth->setFetchMode(PDO::FETCH_ASSOC);

        $messages = array();

        while($row = $sth->fetch())
        {
            $message = new message();
            $message->setMessageID(htmlentities(strip_tags($row['messageID'])));
            $message->setSessage(htmlentities(strip_tags($row['message'])));
            $message->setName(htmlentities(strip_tags($row['name'])));
            $message->setMail(htmlentities(strip_tags($row['mail'])));
            $messages[] = $message;
        }

        $sth = $dbh->prepare("SELECT FOUND_ROWS() as numberOfMessages");
        $sth->execute();
        $sth->setFetchMode(PDO::FETCH_ASSOC);
        $this->numberOfMessages = $sth->fetch();

        return $messages;
    }

    public function setMessageToEdit($args)
    {
        $sth = $this->db->DBH()->prepare("SELECT    messages.message
                                            FROM    `messages`
                                            WHERE   messages.messageID = ?");
        $sth->bindParam(1, $args['messageID']);
        $sth->execute();
        $sth->setFetchMode(PDO::FETCH_ASSOC);
        //return the retrieved message
        while($row = $sth->fetch())
        {
            $message = new message();
            $message->setMessage(htmlentities(strip_tags($row['message'])));
            $message->setMessageID(intval($args['messageID']));
        }

        return $message;
    }

    //functie om messageen aan te passen
    public function save(message $message)
    {
        //insert part
        //if(isset($message->getname()) && isset($message->getmessage()) && isset($message->getMail()))
        //{
            $sth = $this->db->DBH()->prepare("INSERT INTO   `messages`
                                                    SET     messages.name = ?,
                                                            messages.mail = ?,
                                                            messages.message = ?,
                                                            messages.dateAdded = NOW()");
            $sth->bindParam(1, $message->getName());
            $sth->bindParam(2, $message->getMail());
            $sth->bindParam(3, $message->getMessage());
            $sth->execute();
        //}

        //update part
        /*if(isset($message->getmessageID()) && isset($message->getmessage()))
        {
            $sth = $this->db->DBH()->prepare("UPDATE    `messageen`
                                                SET     messageen.message = ?
                                                WHERE   messageen.messageID = ?
                                                LIMIT   1");
            $sth->bindParam(1, $message->getmessage());
            $sth->bindParam(2, $message->getmessageID());
            $sth->execute();
        }*/
    }
}

index.php

<?php
//include file loader.php
include("includes/loader.php");

$guestbook = new guestbook($db);
$user = new user($db);
$messageDAO = new messageDAO($db);

//Make a array named error
$error = array();

//Get action (login/setmessage/editmessage/deletemessage)
if(isset($_GET['action']))
{
    switch ($_GET['action'])
    {
        //if login submit is pressed
        case 'login':
            //Check if filled
            if(isset($_POST['username']) && isset($_POST['username']))
            {
                $error['usernameEmpty'] = (bool) !strlen(trim($_POST['username']));
                $error['passwordEmpty'] = (bool) !strlen(trim($_POST['password']));
            }

            if(in_array(1, $error))
            {
                //Assign $error to smarty
                $smarty->assign('error', $error);
            }

            else
            {
                if(isset($_POST['username']) && isset($_POST['username']))
                {
                    $user->setLoggedIn(array('username'=>$_POST['username'],
                    'password'=>$_POST['password']));

                    if($user->getLoggedIn() != true)
                    {
                        $smarty->assign('loggedInError', $user->getLoggedIn());
                    }
                }
            }
            break;

        //Als if "place message" is pressed
        case 'placemessage':
            //if user is not logged in
            if($user->getLoggedIn() != true)
            {
                //Controleren of message-velden wel zijn ingevuld
                $error['nameEmpty'] = (bool) !strlen(trim(htmlentities(strip_tags($_POST['messagename']))));
                $error['mailEmpty'] = (bool) !strlen(trim(htmlentities(strip_tags($_POST['messageMail']))));
                $error['messageEmpty'] = (bool) !strlen(trim(htmlentities(strip_tags(str_replace('place message...','', $_POST['messageInput'])))));

                if($error['mailEmpty'] != 1)
                {
                    $error['mailInvalid'] = !filter_input((INPUT_POST), 'messageMail', FILTER_VALIDATE_EMAIL);
                }

                if(in_array(1, $error))
                {
                    $smarty->assign('error', $error);
                }

                else
                {
                    $message = new message();

                    $message->setname($_POST['messagename']);
                    $message->setMail($_POST['messageMail']);
                    $message->setmessage($_POST['messageInput']);

                    dump($message);

                    //place message
                    $messageDAO->save($message);
                }
            }

            //if user is logged in
            else
            {
                //is message filled?
                $error['messageEmpty'] = (bool) !strlen(trim(htmlentities(strip_tags(str_replace('place hier uw message...','', $_POST['messageInput'])))));

                if($error['messageEmpty'] != 1)
                {
                    $user->setUser();

                    $guestbook->placemessage(array('name'=>$user->getLoggedInUsername(),
                    'mail'=>$user->getLoggedInUserMail(),
                    'messageInput'=>$_POST['messageInput']));
                }

                else
                {
                    $smarty->assign('error', $error);
                }
            }
            break;

        case 'deletemessage':
            $user->setUser();

            if($user->getLoggedInUserAdmin() == 1)
            {
                if(isset($_GET['messageID']) && is_numeric($_GET['messageID']) && isset($_GET['key']))
                {
                    $guestbook->setURLKey($_GET['messageID']);

                    if($guestbook->getURLKey() == $_GET['key'])
                    {
                        $guestbook->verwijdermessage(array('messageID'=>$_GET['messageID']));
                    }
                }
            }
            die(header("location: /index.php"));
            break;
    }
}

if(isset($_GET['pagina']) && is_numeric($_GET['pagina']))
{

    $currentpage = $_GET['pagina'];
}

else
{
    //$currentpage is 1
    $currentpage = 1;
}

$user->setUser();

//assign var to smarty
$smarty->assign('messages', $messageDAO->findmessages(array('currentpage'=>$currentpage, 'itemsPerPagina'=>10)));
$smarty->assign('user', $user);

//Pagination

$numbermessages = $messageDAO->getnumbermessages();

$totalpages = ceil($numbermessages['numbermessages'] / 10);

if($currentpage < 1)
{
    //$currentpage is 1
    $currentpage = 1;
}

if($currentpage > $totalpages)
{

    $currentpage = $totalpages;
}

$smarty->assign('numbermessages', $messageDAO->getnumbermessages());
$smarty->assign('guestbook', $guestbook);
$smarty->assign('currentpage', $currentpage);
$smarty->assign('totalpages', $totalpages);

//display index.tpl
$smarty->display('index.tpl');

I renamed some of the variables and function to make sense to you (translated from dutch to english :P ) so you might find some weird sentances sometimes because i just did a quick replace etc. Have fun with it. Also this isnt the whole code because that would result in me posting like 20 files worth of code :P


问:
TDD adding simple properties
I am currently doing my first real project with TDD.

I have written tests, and implemented most of the logic for the application.

However, there are properties I know I need to have on the UI, however, there is really no way to write a useful test which will cause their creation.

For example, a description field.  It's the ID that is really cared about in the logic of the application, but the actual description is just carried along from when it's populated and sent to the UI.

How would you go about writing a test that is worthwhile, since a new property is literally nothing more than.

```<code>public string foo { get;set; }
</code>```

答:
I wouldn't bother writing tests for something that doesn't have any logic in it. If your properties are really that simple, writing unit-tests for them is a bad idea. Those tests will be brittle, and will almost never catch any bugs. You're not really testing anything at all. I'm not sure how this advice works with pure TDD, but from a practical point of view, you should only write tests for things that involve logic.

However, it's possible to have more complicated properties that contain some logic. In this case, it might be good to write unit tests for them. For example, if a setter enforces some data valid data range (0 <= property value <= 100), then you can write tests that ensure that this works.

Title: TDD adding simple properties


答:
Maybe this is a good point to start applying some design patterns and good old OOP princiles.

AFAIK having many files isn't bad as long as the application is structured correctly.

If you follow the SOLID principles of OOP you will end with a loosely coupled and well structured application.

Actually following the first principle (Single responsibility principle) will result in more classes (and files eventually), but ur code will be more cohesive.

Title: Reducing number of php files used in project

Body:
I am developing an application in which I have a Class containing various methods. The problem is that i need to call most of the methods on form submission. For that reason, I have to create a new file on each form submission. On every file, I have to create an instance of the same class and then call the appropriate method.

Is there any better way to call methods in such situation so that I don't have to create multiple files having similar functionality in php? I surely don't want to use any framework.


问:
Style for control flow with validation checks
I find myself writing a lot of code like this:

int myFunction(Person* person) {
  int personIsValid = !(person==NULL);
  if (personIsValid) {
     // do some stuff; might be lengthy
     int myresult = whatever;
     return myResult;
  }
  else {
    return -1;
  }
}
```

<p>It can get pretty messy, especially if multiple checks are involved.  In such cases, I've experimented with alternate styles, such as this one:</p>

<pre class="lang-c prettyprint-override"><code>int netWorth(Person* person) {
  if (Person==NULL) {
    return -1;
  }
  if (!(person->isAlive))  {
    return -1;
  }
  int assets = person->assets;
  if (assets==-1)  {
    return -1;
  }
  int liabilities = person->liabilities;
  if (liabilities==-1) {
    return -1;
  }
  return assets - liabilities;
}
</code>```

I'm interested in comments about the stylistic choices here.  [Don't worry too much about the details of individual statements; it's the overall control flow that interests me.]

答:
One thing that I've seen work particularly well is introducing a validation layer into your code. First you have a method that does all the messy validation and returns errors (like -1 in your examples above) when something goes wrong. When the validation is done, the function calls another function to do the actual work. Now this function doesn't need to do all those validation steps because they should already be done. That is to say, the work function assumes that the input is valid. How should you deal with assumptions? You assert them in the code.

I think this makes the code very easy to read. The validation method contains all the messy code to deal with errors on the user side. The work method cleanly documents it's assumptions with asserts and then doesn't have to work with potentially invalid data.

Consider this refactoring of your example:

int myFunction(Person* person) {
  int personIsValid = !(person==NULL);
  if (personIsValid) {
     return myFunctionWork(person)
  }
  else {
    return -1;
  }
}

int myFunction(Person *person) {
  assert( person != NULL);
  // Do work and return
}
```


答:
I find it easier to move validation to its own function, it helps keep the intent of other functions cleaner, so your example would be like this.

int netWorth(Person* person) {
    if(validPerson(person)) {
        int assets = person->assets;
        int liabilities = person->liabilities;
        return assets - liabilities;
    }
    else {
        return -1;
    }
}

bool validPerson(Person* person) {
    if(person!=NULL && person->isAlive
      && person->assets !=-1 && person->liabilities != -1)
        return true;
    else
        return false;
}
```

Title: Style for control flow with validation checks

Body:
I find myself writing a lot of code like this:

int myFunction(Person* person) {
  int personIsValid = !(person==NULL);
  if (personIsValid) {
     // do some stuff; might be lengthy
     int myresult = whatever;
     return myResult;
  }
  else {
    return -1;
  }
}
```

<p>It can get pretty messy, especially if multiple checks are involved.  In such cases, I've experimented with alternate styles, such as this one:</p>

<pre class="lang-c prettyprint-override"><code>int netWorth(Person* person) {
  if (Person==NULL) {
    return -1;
  }
  if (!(person->isAlive))  {
    return -1;
  }
  int assets = person->assets;
  if (assets==-1)  {
    return -1;
  }
  int liabilities = person->liabilities;
  if (liabilities==-1) {
    return -1;
  }
  return assets - liabilities;
}
</code>```

I'm interested in comments about the stylistic choices here.  [Don't worry too much about the details of individual statements; it's the overall control flow that interests me.]


答:
Most NP complete problems have "interesting" real life applications. P=NP will have lot of consequences :

It will be possible to solve exactly optimization problems which are currently approximated. This is the case of the Travelling Salesman Problem and Job Scheduling Problem

It breaks some security measures which are based on the fact that required computational time is enormous. For instance lots of encryption schemes and algorithms in cryptography are based on number factorization, the best known algorithm having exponential complexity. These algorithms will becomes useless if a polynomial algorithm is found.

The bottom line is on the nature of the problems known to be NP-complete. These are not just problems created by few scientists in a remote location to entertain each other. They can be expressed in business terms. In fact, some job interviewers like to conceal NP-complete problems in their questions in order to test candidates.

Title: What would be the Impact of P=NP?

Body:
I am preparing for a test and I can't find a clear answer on the question: What would be the impact of proving that PTIME=NPTIME. I checked wikipedia and it just mentioned that it would have "profound impact on maths,AI,algorithms.." etc.

Anyone can give me an answer?


答:
You dont need to create a separate PHP file for each form submission.

```<code><form method="post" action="myapp.php">
 <input type="hidden" name="action" value="useraccount">
 ...
</form>
</code>```

On the PHP side of things, just check the posted 'action' variable, and respond accordingly.

Actually, what you want to do is to have a master 'view' controller that handles the interface, and load templates of the pages you need through that.  This way you dont have a single php page per web 'page' that the user sees - just the one.  Then you're not creating massive amounts of PHP files, and not duplicating all the include()'s on every page.  If you then have a need to make it look like separate pages for some reason, you use mod_rewrite.

Body:
You dont need to create a separate PHP file for each form submission.

<form method="post" action="myapp.php">
 <input type="hidden" name="action" value="useraccount">
 ...
</form>

On the PHP side of things, just check the posted 'action' variable, and respond accordingly.

Actually, what you want to do is to have a master 'view' controller that handles the interface, and load templates of the pages you need through that.  This way you dont have a single php page per web 'page' that the user sees - just the one.  Then you're not creating massive amounts of PHP files, and not duplicating all the include()'s on every page.  If you then have a need to make it look like separate pages for some reason, you use mod_rewrite.


答:
For this kind issues Martin Fowler proposed Specification pattern:

...design pattern, whereby business rules can be recombined by chaining the business rules together using boolean logic.

  A specification pattern outlines a business rule that is combinable with other business rules. In this pattern, a unit of business logic inherits its functionality from the abstract aggregate Composite Specification class. The Composite Specification class has one function called IsSatisfiedBy that returns a boolean value. After instantiation, the specification is "chained" with other specifications, making new specifications easily maintainable, yet highly customizable business logic. Furthermore upon instantiation the business logic may, through method invocation or inversion of control, have its state altered in order to become a delegate of other classes such as a persistence repository...

Above sounds a bit high-brow (at least to me), but when I tried it in my code it went quite smoothly and turned out easy to implement and read.

The way I see it, main idea is to "extract" code that does the checks into dedicated method(s) / objects.

With your netWorth example, this could look about as follows:

int netWorth(Person* person) {
  if (isSatisfiedBySpec(person)) {
    return person->assets - person->liabilities;
  }
  log("person doesn't satisfy spec");
  return -1;
}

#define BOOLEAN int // assuming C here
BOOLEAN isSatisfiedBySpec(Person* person) {
  return Person != NULL
      && person->isAlive
      && person->assets != -1
      && person->liabilities != -1;
}
```

<p>Your case appears rather simple so that all the checks look OK to fit in a plain list within a single method. I often have to split to more methods to make it read better.</p>

<p>I also typically group / extract "spec" related methods in a dedicated object, although your case looks OK without that.</p>

<pre class="lang-c prettyprint-override"><code>  // ...
  Specification s, *spec = initialize(s, person);
  if (spec->isSatisfied()) {
    return person->assets - person->liabilities;
  }
  log("person doesn't satisfy spec");
  return -1;
  // ...
</code>```

This question at Stack Overflow recommends a few links in addition to one mentioned above:
Specification Pattern Example. In particular, answers suggest Dimecasts 'Learning the Specification pattern' for a walkthrough of an example and mention "Specifications" paper authored by Eric Evans and Martin Fowler.

Body:
For this kind issues Martin Fowler proposed Specification pattern:

...design pattern, whereby business rules can be recombined by chaining the business rules together using boolean logic.

  A specification pattern outlines a business rule that is combinable with other business rules. In this pattern, a unit of business logic inherits its functionality from the abstract aggregate Composite Specification class. The Composite Specification class has one function called IsSatisfiedBy that returns a boolean value. After instantiation, the specification is "chained" with other specifications, making new specifications easily maintainable, yet highly customizable business logic. Furthermore upon instantiation the business logic may, through method invocation or inversion of control, have its state altered in order to become a delegate of other classes such as a persistence repository...

Above sounds a bit high-brow (at least to me), but when I tried it in my code it went quite smoothly and turned out easy to implement and read.

The way I see it, main idea is to "extract" code that does the checks into dedicated method(s) / objects.

With your netWorth example, this could look about as follows:

int netWorth(Person* person) {
  if (isSatisfiedBySpec(person)) {
    return person->assets - person->liabilities;
  }
  log("person doesn't satisfy spec");
  return -1;
}

#define BOOLEAN int // assuming C here
BOOLEAN isSatisfiedBySpec(Person* person) {
  return Person != NULL
      && person->isAlive
      && person->assets != -1
      && person->liabilities != -1;
}

Your case appears rather simple so that all the checks look OK to fit in a plain list within a single method. I often have to split to more methods to make it read better.

I also typically group / extract "spec" related methods in a dedicated object, although your case looks OK without that.

  // ...
  Specification s, *spec = initialize(s, person);
  if (spec->isSatisfied()) {
    return person->assets - person->liabilities;
  }
  log("person doesn't satisfy spec");
  return -1;
  // ...

This question at Stack Overflow recommends a few links in addition to one mentioned above:
Specification Pattern Example. In particular, answers suggest Dimecasts 'Learning the Specification pattern' for a walkthrough of an example and mention "Specifications" paper authored by Eric Evans and Martin Fowler.


答:
In TDD unit test are not your only source of tests, you have to include Acceptances tests as well with a framework like Selenium in the case of Web development. To bullet proof your application even more, using a build automation upon each commit like Jenkins which you can combine with Apache Ant to run all your tests and different code analysis.

For more information you can look at this presentation. Even without the presenter talking, you can understand where he is going.

Title: TDD adding simple properties

Body:
I am currently doing my first real project with TDD.

I have written tests, and implemented most of the logic for the application.

However, there are properties I know I need to have on the UI, however, there is really no way to write a useful test which will cause their creation.

For example, a description field.  It's the ID that is really cared about in the logic of the application, but the actual description is just carried along from when it's populated and sent to the UI.

How would you go about writing a test that is worthwhile, since a new property is literally nothing more than.

```<code>public string foo { get;set; }
</code>```


问:
Do DVCSes discourage continuous integration?
Say there is a team of ten agile developers. Every day they each pick a task from the board, commits several changes against it, until (by the end of the day) they have completed the task. All developers check in directly against trunk (Google-style, every commit is a release candidate, using feature toggles etc).

If they were using a centralized CVS like SVN, every time one of them commits, the build server will integrate and test their changes against the other nine developers' work. The build server will be pretty much running continuously all day.

But if they were using a DCVS like git, the developer may wait until they complete the task before pushing all their local commits together up to the central repository. Their changes will not be integrated until the end of the day.

In this scenario, the SVN team is continuously-integrating more frequently, and discovering integration problems much faster than the git team.

Does this mean DVCSs are less suitable for continuous teams than older centralized tools? How do you guys get around this deferred-push issue?

答: I'd say the DVCS is more conducive to continuous integration. Merges are not as irritating with them. It does require more discipline however. You should follow a local commit with a pull from the base to merge and then push when your task is complete (before going to the next).</p>


问:
Where has Cloud Computing gone?
I have been hearing about this term for close to 5 years now. I have read about services from Microsoft (Azure), but I have never saw it adopted in the mainstream usage. The thing I am trying to understand is this:

What happened to cloud computing? Is the infrastructure at present insufficient to implement this?

Is it still in its infancy?

Is it being used in other forms, like all the services Google seems to provide (plus Plus Google OS, etc)?

If it has failed, then why?

答:
Mate, it has not gone away. It was not over hyped, niether has it failed. I will try to take a moderate approach to answering this. We are still years behind in using the cloud to full potential. It is a paradigm shift not just a technology adoption. Also adopting a new technology takes years to be in practise. The Mainframes never went away ? There are solutions scalable enough to run Mainframe Applications but they are not getting adopted, why ?

A clear problem with the cloud is the Application Readiness. So your Application can run in the Cloud but the Applications that provides your App Security are they Cloud ready ? Is your customer Ok to host his data on the Cloud ? Are there any compliances which certify that your data will be safe in the Cloud ? Some of these things are in Progress and will take time to come in.

Also all the Applications that are going to provide Software As A Service are good candidates for Cloud. Most of them are actually having thier own Clouds, they might/will eventually move to the Cloud with better standards and adoption of the Technology.

Title: Where has Cloud Computing gone?


答:
These possibilities are covered in Impagliazzo's Five Worlds.

Here's some takeaway points:

Artificial Intelligence would be able to make a giant leap. For example, with enough "training data," the shortest-circuits to produce the correct outputs from the inputs would represent the best method of translation. In particular, it would become trivial to have perfect speech recognition and language translation. Taking this idea further, if your training data is Oscar winning movies, it can generate more Oscar winning movies for you.

Algorithms as taught in schools would be radically different. Instead of learning so many different algorithmic techniques, courses would focus on reducing problems to verification of correct answers. This would greatly simplify programming.

The economy would become vastly more efficient. There would be disruption, including maybe displacing programmers. The practice of programming itself would be more about gathering training data and less about writing code. Google would have the resources to excel in such a world.

Because public key cryptography would be "out," Amazon would need to send you a one-time-pad on a thumb drive in order to do secure transactions.

Mathematical proofs could be automatically generated and verified.

Overall, it would introduce a technological singularity; the implications of P=NP would be far reaching. Also, Lance Fortnow addresses this point in a separate blog post that you should read.

Title: What would be the Impact of P=NP?


答:
If by "do some stuff" you mean "use IE specific facility x" and by "do some other stuff" you mean "use more common facility y", then it is better practice to just check for the presence of x or y.

I'm guessing that you are currently not using any external Javascript library.  In that case, I would check to see if jQuery supports the task you are trying to accomplish.  If it does, I would use it.

Title: Is it considered bad practice to run different JavaScript for IE

Body:
Is it considered bad practice (and how bad) to run different JavaScript for IE? Currently im writing some JavaScript and the simplist way to work arround IE quirks seems to be to check for browser version and run different code

```<code>var browserName = navigator.appName;

if (browserName == "Microsoft Internet Explorer") {
  //Do some stuff
}
else
{
//Do other stuff
}
</code>```

It's quick and works well but does lead to duplication of code and feels "hacky".


问:
Why is putting something on the stack called "push"?
According to http://dictionary.reference.com

push

verb (used with object)

to press upon or against (a thing) with force in order to move it away.

to move (something) in a specified way by exerting force; shove; drive: to push something aside; to push the door open.

to effect or accomplish by thrusting obstacles aside: to push one's way through the crowd.

to cause to extend or project; thrust.

to press or urge to some action or course: His mother pushed him to get a job.

This IMO fits to FIFO queues. Is there an explanation for this?

答:
The illustrations using cafeteria plates or trays, pez dispensers, and piles of books all came later.  From Wikipedia: (with references)  </p>

<p>"The stack was first proposed in 1946, in the computer design of Alan M. Turing (who used the terms "bury" and "unbury") as a means of calling and returning from subroutines."  Additional work and patents by others followed in 1957.  The current illustrations of stacks we use today may have caused Turing's original terms of bury and unbury to evolve into push and pop.  Maybe these terms just sound better.  </p>

<p>Finding exactly where or when this happened is the answer to the OP's question.  Maybe the answer is buried in one of the Wikipedia references like "Verfahren zur automatischen Verarbeitung von kodierten Daten und Rechenmaschine zur Ausübung des Verfahrens." </p>

Body:
The illustrations using cafeteria plates or trays, pez dispensers, and piles of books all came later.  From Wikipedia: (with references)

"The stack was first proposed in 1946, in the computer design of Alan M. Turing (who used the terms "bury" and "unbury") as a means of calling and returning from subroutines."  Additional work and patents by others followed in 1957.  The current illustrations of stacks we use today may have caused Turing's original terms of bury and unbury to evolve into push and pop.  Maybe these terms just sound better.

Finding exactly where or when this happened is the answer to the OP's question.  Maybe the answer is buried in one of the Wikipedia references like "Verfahren zur automatischen Verarbeitung von kodierten Daten und Rechenmaschine zur Ausübung des Verfahrens."


答:
My small team switched to a DVCS a year or two ago, and the rest of my company followed suit a couple of months ago. In my experience:

People using a centralized VCS still tend to hold off on commits when they are doing a large project. This isn't a problem unique to DVCSes. They'll have change sets that wait several days before doing a commit. The big difference is that if they make a mistake at some point during this time, or if the computer crashes, it requires vastly more effort to fix it.

We use a commit workflow where each developer works on their own named branch, and only the person who reviewed their code is allowed to merge their changes into the head. This reduces the likelihood of a commit causing problems, so people really pay attention when the build server produces an error message. It also means that other developers can continue working on their own branches until the head gets fixed.

On a DVCS, people do tend to spend more time programming before merging their code in with the head. So it does tend to introduce a little lag into the continuity of the build. But the difference is not significant enough to counter the advantages of the DVCS.

Title: Do DVCSes discourage continuous integration?

Body:
Say there is a team of ten agile developers. Every day they each pick a task from the board, commits several changes against it, until (by the end of the day) they have completed the task. All developers check in directly against trunk (Google-style, every commit is a release candidate, using feature toggles etc).

If they were using a centralized CVS like SVN, every time one of them commits, the build server will integrate and test their changes against the other nine developers' work. The build server will be pretty much running continuously all day.

But if they were using a DCVS like git, the developer may wait until they complete the task before pushing all their local commits together up to the central repository. Their changes will not be integrated until the end of the day.

In this scenario, the SVN team is continuously-integrating more frequently, and discovering integration problems much faster than the git team.

Does this mean DVCSs are less suitable for continuous teams than older centralized tools? How do you guys get around this deferred-push issue?


答: If you need a property, you have a feature that requires that property to be there. In the course of writing unit tests for that feature, you will reference that property and thus its existence will be validated by a unit test.</p>

Title: TDD adding simple properties


问:
Are there advantages to agile practices other than having a working build between sprints?
I recently became interested in agile practices in software development and I since have seen a lot of articles point out that these practices allow for reduced overall costs.

The logic behind that usually goes like this: if your requirements change, you can reflect this change in the next sprint backlog and this will lead to reduced cost, because designing the new feature and implementing it is close together in terms of time, so the cost goes down, according to the famous rule that the later you need to make a change to your requirements the more expensive it will be to satisfy that requirement.

But mid to big software projects are complex. A sudden change to requirements does not mean you won't have to touch other parts of your system in order to satisfy that requirement. In a lot of cases the architecture will need to be modified very significantly, which will also mean you'll need to re-implement all the features that relied on the older architecture. So the whole point of reduced costs kinda goes away here. Of course if a new requirement calls for a new independent part of the system, that's not a problem, the old architecture just grows, it doesn't need to be rethought and reimplemented.

And the opposite. If you are using waterfall and you suddenly realize that a new requirement has to be introduced, you can go and change your design. If it requires that existing architecture is altered, you redesign it. If it does not really mess with it but just introduces a new part of the system, then you go and do all the work, no problem here.

With that said, it seems to me like the only advantage agile development has is working feature complete builds between sprints, and for a lot of people and prjects this is not critical. In addition, agile seems like it results in bad software architecture overall, because features kinda get slapped one onto another, agile teams only care that a feature works, not how it works. This seems like that when systems grow in complexity with time, agile development practices actually increase chaos in the overall product architecture, thus eventually resulting in higher costs, since it will be increasingly more difficult to introduce changes, whereas waterfall allows you to perfect your architecture before you release anything.

Can somebody please point me as to where I'm going wrong here, because obviously a lot of people use agile in production environments, so I must be wrong somewhere.

答:
In a lot of cases the architecture will need to be modified very
  significantly, which will also mean you'll need to re-implement all
  the features that relied on the older architecture.

If your architecture needs to be modified significantly as a result of a requirements change, you have either bad architecture or a bad requirements.  Good architecture allows you to defer as many decisions as possible and decouple components of your system.  Good (user) requirements aren't things like "use a different database".

So, let's operate under the assumption that we have a good working architecture.  If that is the case, then agile development methodologies lose this "wash" with big-up-front-design methodologies.  After all, a core feature of agile development methodologies is practices like TDD that promote loose coupling in code, allowing the project to continue at a high velocity whether it's near the beginning or very mature.


问:
Design patterns - do you use them?
Being an IT student, I was recently given some overview about design patterns by one of our teachers. I understood what they are for, but some aspects still keep bugging me.

Are they really used by the majority of programmers?

Speaking of experience, I've had some troubles while programming, things I could not solve for a while, but Google and some hours of research solved my problem. If somewhere in the web I find a way to solve my problem, is this a design pattern? Am I using it?

And also, do you (programmers) find yourself looking for patterns (where am I supposed to look, by the way?) when you start the development? If so, this is certainly a habit that I must start to embrace.

UPDATE: I think when I ask if programmers do use them, I'm asking if when you have a problem to solve you think "Oh, I should use that pattern".

答:
I've programmed for about 7 years in C++ and learned patterns about 2 years ago.  Most patterns probably have some applications, but in my usage, some are better than others.  You have to think why you are using them.

The iterator pattern has actually made my code more confusing and has added unnecessary complexity.  I can get the same maintainability using typedefs for STL vector types.  And any changes I make to the class being iterated I also have to make to the iterator class.

The factory method, however, has been extremely useful, based on the polymorphism it provides.  I forget who said it, but the statement "reusability means that old code can use new code", is definitely true with the factory pattern.

I've used the template method pattern for years without even knowing it was a "design pattern".

The Observer pattern has been helpful in some cases, sometimes not.  You have to sometimes predict complexity to determine if the overhead complexity of the Observer pattern is worth it.  We have a program that uses about 10 subscribers and there could be many more, so the observer/subscriber pattern has been helpful.  Another program, however, has two GUI displays.  I implemented the observer pattern for this program, and it has been largely unnecessary, simply because it added complexity and I don't anticipate adding more displays.

I think those who say to always use patterns assume that your program is going to be infinitely complex, but like with everything, there is a break-even point in terms of complexity.

Title: Design patterns - do you use them?


问:
Programming with voice recogition software
I used Dragon Naturally Speaking very briefly a few years ago and was thinking if it would be a viable solution for programming?

I was thinking more so if you break your arm or something that would be a major hinderance to programming.

This same question on SO but was never answered.

答: For a working professional programmer (where time is money) with severe carpal tunnel or hand injuries (etc.), it may be far more efficient to hire a junior/intern "pair programmer", and let them do the "voice recognition" and typing.</p>