Pergunta

I am curious about the very early steps that a programmer's mind takes when it first encounters a problem that it is supposed to solve. How do you start reasoning about it ? What are the first questions you ask yourself ??.

Ok, let me make it more concrete for those of you who think the question is too vague or entirely situation dependent. Pick any of the following requirements and think out loud about your very first hunches/impressions/tendencies about how to solve it.

1) build a simple word processor with about as much functionality as MS Word Pad
2) design a single person card game (e.g. Solitaire)
3) build a scientific calculator
4) Any problem of your choosing with similar scale/complexity as the above three

Foi útil?

Solução

1) Get it running. Even if it does nothing but say hi.

2) Analyze. Figure out what it needs, what would be nice, etc.

3) Have at it. Add features one a time testing between each one.

Outras dicas

1) Specify. Break the problem down into core parts and figure out how they're supposed to work. When the problem is already well-defined, such as a card game with known rules, a fair amount of this step can be glossed over, but it's good to go over it just to make sure you understand the problem domain as well as you think you do.

2) Set up a source control repository for the project. Very important to do this before you even start writing any code.

3) Pull up your IDE and start hacking.

Mentally I do the following, very quickly and abstractly

1) Requirements Gathering - I quickly create a mental list of functionality and how it may be implemented

2) Methodology - I try to figure out which technologies are best suited for the job

3) Identify Problems - Before even starting the project I try to identify any problems that may arise and how to avoid them from the get-go

In Process I do the following:

1) Requirements Gathering - I'll almost always create a Project Specification which lists all of the features, how the features work, what they do, what they don't do and which user groups will be using them. I think this is key, as it clearly defines goals for all parties and can aid in testing & Q.A. as well as provide an outline for development.

For paid projects, it also ensures clients have no unmet expectations, however I do this for Internal projects as well.

2) Development - Development for me includes setting up a development environment separate from the production environment, setting up Version Control (Git for me), and getting each feature done, doing some testing along the way.

3) User Experience - The UX phase involves having a Graphic Designer style all elements on the site/application as I'm a programmer and shouldn't be allowed to make any design decisions :P

It also involves testing the application and making any required tweaks. At the end of this phase the application/software/website should be ready for an initial release.

1. Does the program already exist? If the program already exists in the market, can I do significantly better? Is anybody interested in a better version?

2. Would developing that program be interesting to me? Would it be a growthful experience? With experience, developers generally have more opportunities to do programming than they have available time.

3. What ressources do I have? Not enough? Negotiate. Now is the right time.

Basically, when I have a opportunity of developing a program, or solving a problem, my first thoughts always revolve around the question: Do I want to be involved?

Managers often think that they can get an engineer to solve anything. It is important to take care of oneself to avoid getting into a mess.

In order:

  1. Already exists?
  2. Seems complex? Do I really know how it should work?
  3. Lets try a prototype!
  • My first instinctive response is to enter solutions mode. My brain starts looking for solutions, small and large immediately. This happens faster than it takes to read the problem statement.

  • But pretty soon, I catch myself going down that (bad) path, and consciously force myself into pro mode and I take a step back.

  • Once in pro mode, I write a test.

My first question is always "What is the business need/problem we are trying to solve?". Too many times, I have been asked to build a solution that ends up not actually addressing the customers problem.

If I can understand their needs and goals, I can make sure that what I am building will be useful to them. This also helps reduce misinterpretation of requirements and reduces the number of iterations needed to get something usable into production.

  1. What am I wanting exactly? What does a solution look like,e.g. is it a new program, fixing a bug in an existing application, replacing a system, or something else? This is probably similar in lots of ways to Mason Wheeler's answer. Note that this is just what is the finished product, not necessarily what parameters are on it.

  2. What parameters does this problem have? For example, am I trying to solve this within the hour, day, week, month, year, etc.? How big of a solution am I trying to create,e.g. replacing a content management system for a web site may be quite different in scale than creating a form to track earned time off on the company intranet? What is the priority of getting this done? Am I expected to work at this 24/7 to solve it or is it just when I am in the office and it isn't something that has to get solved soon or the company is dead?

  3. Who is coming with me to implement this solution? This is where after I know what I'm trying to get and nailing down some details on how, why, when and where it'll be, next on my list of things to do is see if this is something that I can do alone, do I pass this request along to some other department as if the fix is a change to a firewall this may not be something I can do on my own, or could I pull in others to help on this? Sometimes a problem may come up that has an "all hands on deck" feel where multiple developers are trying to find solutions, not unlike how the various doctors on House try to propose various differential ideas.

Those are aspects to my starting point with a given problem. Sometimes nailing down the problem can be a struggle, as there may be a case where a developer and a tester have different interpretations of requirements and someone has to be the judge and decide who is right and who is wrong. Sometimes both can be wrong if the person who created the requirement didn't get enough detail and various cases were left open to interpretation. After that, there may be various solutions that I'm passing along these different plans for someone else to decide which is the one to follow: A quick band aid solution that isn't likely to last long but may work in the very short term, a moderate solution that may take some more time but better better in the intermediate future, or the industrial strength solution that may be overkill but definitely solves the problem permanently.

I decompose the problem into smaller and smaller parts until I have something resembling a solution to the problem.

  • Define the different assemblies (if necessary) e.g. UI/BLL/DAL/Tests.
  • Then the 'major players' (classes) that will go in them e.g Playing Card, Game Board
  • Define the nouns (properties) and verbs (methods) for the major players. I use canned values as returns for almost everything.
  • Define the major use cases for the system (what will the user do). I usually wire up a simple UI to drive the underlying classes

After that, I start gluing the pieces together and replacing the canned values with actual functionality, refactoring as necessary.

As I write each piece of functionality I write unit and integration tests in tandem for it (I'm not totally sold on the TDD 'test first' part yet - I don't know what the interface is going to look like until I write it and if I test first I end up doing too much refactoring of test code).

All of the projects you list are non-trivial if you want to do them properly - i.e. a finished, polished, tested product. Therefore my initial steps are:

1. Requirements/Specifications. Write down what it should do and what it should not do. Prioritize the to-do items - essential (can't function without it), nice-to-have and 'if there's time to kill'. Order the items in priority order. Agree with whoever is paying for the project that this is the correct order. Stay on step 1 until you have agreement.

2. Design. Draw out the UI - what will the features look like to the user. This doesn't have to be pretty - pencil and paper will do - but it will help you work through the user workflow and out of this will come the High Level Design, the major components/modules of the application. This doesn't have to be a 'big up-front design' effort, but a poor UI or workflow will kill any chance of success. Work with the project sponsor (whoever is paying) until they're happy with the UX.

3. Iterative Development. Implement just enough code to achieve the next requirement on the prioritized list, complying with the design and workflow. Check in this code. Demonstrate to project sponsor. Goto 3.

I always try to start development with 3 questions in mind:

  • Do I understand the the real business need?

Quite often, the "presenting problem" is not the real problem.

For example, I was recenly asked to produce a complex project management framwork when all the user needed was a static list of tasks with a progress text box next to each one.

Questions like "what will the users actually use it for?" are useful in getting to the real problem.

  • Is this really a programming problem"?

Does the required functionality already exist in an application that we already have? That we can buy? Could we use pen and paper instead?

For example, the "build an simple word processor with about as much functionality as MS Word Pad" should be answered with "have you considered using WordPad" rather than a programming project.

I was once asked to build a database that would store information on industrial processes, with a series of management reports that would enumerate the processes that fell into certain categories. It turned out that a maximum of 33 records would be created in the database, and that it would be used by 3 people who sat adjacent one another. The perfect solution was a physical file containing 33 sheets of A4 paper. The users could have physically counted the pages to produce their management reports. (Curiously, management decided to buy in a system instead! At least I was free to go and do some value work).

  • Do I understand the customer's real priorities?

In any application, some features are more important than others. It is important to get clear idea of what really matters to your users. Sometimes, the things that are important to us as developers (eg. that complicated bit) are less important to our custiomers (eg. the look and feel of the application).

A fellow developer recently told me about a demo of web app that he did to verify that the app met their needs. He was frustrated becasuse the users were unable to see past the design of the pages. For these users, appearence was more initially important than functionality, so needed to be prioritised by the dev team.

In terms of deciding what to do:

  1. What is the need? Who needs it? Why? How will it make money (or achieve some other goal for non-money projects). How much is available to spend on it. Are the returns likely to justify the likley expenditure.
  2. What are the most valuable features. What are the features that are most unknown; likely to be the most risky (that is to say, most unpredictable). Try to break down the features into the smallest chunks the customer can still recognise (accept) as features. You don't need to identify all the features, just try to get a few that have high value to the customer.
  3. Implement the most risky, most valuable feature (trade off to get maximum value and remove maximum risk at the start of the project).

In terms of deciding how to do it:

  1. Is there any existing code/technology/product/service that already solves the problem, can I use or adapt that?
  2. If not, what are the domain concepts involved and technical constraints on the solution.
  3. Implement the feature trying to achieve the simplest expression of the parts of domain model required for this feature. Decouple the domain model as much as practical from any technical considerations (e.g database technology, OS, client machine vs cloud, etc). I generally use a test driven approach to accomplish this.
Licenciado em: CC-BY-SA com atribuição
scroll top