An example to illustrate the: "Coding is just abstracted p‌r‌o‌b‌l‌e‌m solving" point to a complete layman? - logic

I was talking to someone in a bar not too long ago, and the inevitable question of "What do you do?" Came up. My response "Oh, I just recently graduated; I work in company X. I'm a programmer" didn't quite satisfy her.
I've had this conversation a hundred times and people are never quite happy with the answer. They always have more questions. I think this is because, for the mostpart, people don't really know what a programmer does. The answer to this question normally gives you an insight into a person (sort of): Accountants might be analytical and good with numbers, lawyers might be good with words and debate etc. 'programmer' doesn't.
so I tried to give an answer that would give that sort of insight.
I tried to illustrate my point of "Well It's basically fancy problem solving" with an example of a classic programming problem.
The first thing that jumped into my head (for some reason) was the smallest subset problem... but I'd have to explain arrays, time complexity, etc
I thought of n-queens problem, but she'd never seen a chessboard in her life (yeah, I know)
Towers of hanoi was too hard to envision in general...
So I Was stuck and the topic changed.
Can you guys think of an example of a problem; that a complete lay(wo)man can understand, which would give someone an idea of the kind of thinking programmers have to do? (and by extension save me answering awkward questions about how I make my living)

I get asked what I do too, and basically, all I say is that You wouldn't understand much about it, which will get you one of two responses: "Try me" and shes interested ->move to next section of comment, or she will just shut down and think that you think she's not intelligent. USE WITH DISCRETION.
Now, if she says try me, you have a challenge. Obviously what you do is going to be over her head, but you know you can explain a little to her. Basically, what I try to explain is that I am a logician, kinda like a magician. When the computer needs to be told to do something, and no one else knows how to tell it, they call me up. Sometimes it's simple, other times, its likes climbing Mt. Everest with your fingers on some impossibly difficult task. Imagine the worlds largest word search, and you don't know what words you're looking for. That's what I do. I find those words. So as you could imagine, I'm quick to notice little things and remember them. ;)
That should elicit the kind of response out of any women worth your time.
Good Luck!

Related

When debugging, how do you estimate if you should rewrite or keep looking?

You have all met this scenario. I am using a new algorithm for the first time, and I am sitting at my computer trying to find out if it is some syntax problem or if I have misunderstood the algorithm. In a scenario like this, I would sooner rewrite the program than spend time staring at the screen. But this raises the general question, that I am curious to hear from programmers more experienced than myself:
How do you judge when it is the right time to rewrite, or should you continue sitting there staring at your code looking for the bug?
Are there any useful heuristics that professional programmers use?
This doesn't sound right to me at all. As long as you don't understand the (required) algorithm you should not write code. That's called trial and error and is a pretty sure way to end up with poor and buggy code. Think before you act.
As food for thought a bit provocative statement:
Writing code is the last thing to do. Being a coder might sound like
you should be typing a lot but in fact if I count how many characters
an average programmer commits each day and ask some secretary to type
the same amount he/she would be done in under 30 minutes.
It's a very difficult question and really depends on your case.
Typically, there are two cases :
the algorithm is simple and you will find the bug fast. A rewrite is generally not necessary unless you want to optimize it.
the algorithm is really complex : it's difficult to find the bug. But It can be difficult to rewrite because you can miss some subtile features of the algorithm. The risk is to have a new algorithm but with new bugs !
I don't think there is a clean answer to that problem. I would say that it's better to find the bug than rewriting all. Rewriting is necessary when you need to optimize or clean the code (not because you don't find a bug).
That's my two cents.
You should never rewrite something that has already gone through testing more than once.. the theory being that if you went through it at least once, you've already ironed out bugs. Trying to recreate the end-result of those resolved bugs is very difficult. Joel has a very good article on this, and I tend to agree, even though I have been in the position you are, and my inclination was to just throw it away and rewrite it..
http://www.joelonsoftware.com/articles/fog0000000069.html

Problem solving/ Algorithm Skill is a knack or can be developed with practice? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
Every time I start a hard problem and if can not figure out the exact solution or can not get started, I get into this never ending discussion with myself, as below:
That problem
solving/mathematics/algorithms skills
are gifted (not that you can learn
by practicing, by practice, you only
master the kind of problems that you
already have solved before)
only those who went to good schools can do it, as they learned it early.
What are your thoughts, can one achieve awesomeness in problem solving/algorithms just by hard work or you need to have that extra-gene in you?
I spent a big part of my life wondering whether talent was something you developed or something you were born with. Then it occurred to me that the answer was irrelevant, at least if you want to achieve things yourself. Even if you have talent, it will only help you if you act as if talent only comes from practice, because you will work that much harder.
With regards to algorithms, as well as any other really difficult skill, it takes practice to get good. Whether or not you have to have some amount of talent too, I don't know. I do know for a fact, however, that people have made huge improvements in competitions like TopCoder by practicing. I myself have learned a lot from that.
If you set up a systematic training program, you will be way ahead of the pack, even if it is not perfect. I have written a few hundred programs on TopCoder by now and it has affected my thinking in a profound way. I have learned a lot of things that could only ever be learned by doing them wrong and then fixing my mistake. A friend of mine has written several thousand programs on TopCoder and he is way better than I am, even though his stats were worse when he started out than mine were. That is no coincidence.
EDIT:
I just came across this answer at math.stackexchange. I think it is one of the best explanations of how to learn algorithms I have read, even though he writes about chess and math.
1) Don't try to solve the problem in its most general abstraction.
2) Choose the right time when your mind is working at maximum.
I got the first point as an advice from a math instructor. It works! try to do different examples and scenarios of the problem. This helps greatly in identifying the edge cases which are the hardest to understand in most problems.
My favorite time for solving this kind of problems is the dawn(4-6 AM). Have a good sleep the night before, and wakeup ready to solve the problem. Silence is your friend.
I do believe that some people have extra intelligence than others, but it is not the most important factor. It is how you utilize this intelligence to solve the problem.
I took magic lessons in a group setting when I was twelve years old. The magician's name was Joe Carota. He did a magic trick one time and I blurted out, "How did you do that?" He said something that day that has stuck with me ever since.
Joe's response, "Michael, if you really want to know how that trick is done you must figure out how you would do it yourself."
Well of course that's not what I wanted to hear but it did get my mind focused on problem solving. This was problem solving from my perspective. If my first attempt at solving the problem took seventeen steps and was really klunky, the good news was I solved the problem.
Then by looking at the solution I had developed and further looking for ways to refine that solution I would learn how to streamline the end result. Later on in my computer programming life I found out that this process was called "Stepwise Refinement".
It worked back in 1971 and it still works today.
For me, i think it's a bit talent, but much more important is experience and practice. If you know many problems and the best solutions to them, you can come up more easily with a solution to a new problem.
Example from my own past: There was some programming contest (good for training, btw) and I did not find a good solution. The winner solved the problem mainly by using a KD-Tree. To come up with this, you first of all need to know what, in this case, a KD-Tree is, and where it's useful. Today, this is clear to me and if i'd encounter a similar problem again, i'd be able to solve it really quickly.
Hardwork beats talent if talent doesn't work hard.
This above statement defines what the true potential of persistence is.Any skill in this world can be developed by practice.This process is analogous to nailing a nail in the wall.It not only requires correct magnitude but also appropriate direction.
To answer the question, first we need to find the ingredients for the capability to solve an issue.
There is a so-called natural talent. This is the talent you are born with. This predetermines your potential. People born with more gray matter will tend to perform better than people with whom nature was less generous with. This means that a person having better talent has a higher probability to perform better than a person not as talented if they had the same parameters (education, personality, resistance to stress, willpower). If one observes that he or she tends to consume a great time to absorb new information until he or she is able to apply it, then the wisest decision for the person is to leave programming and prevent a life full of frustration. Naturally, one cannot expect as a beginner to be able to instantly understand the most complex phenomenon, but if a beginner is too slow to understand beginner concepts, then programming is not his or her cup of tea.
Developed talent. One has a natural talent, but that is, in itself not enough to solve problems. I have never seen newborns writing code. One has to get some education. The earlier, the better. Also, the quality of school is of high importance. We should never deny the fact that a person who did not have the chance to learn programming at a good school early, then he or she has a handicap in the race for success. However, if someone misses good schools early, then the handicap can be covered with hard work. For instance, my wife had an education in another field, but after finishing the university, she did not find proper jobs. So I started to educate her. After a month she learned how to learn and was able to solve almost any problems presented to her, but she was not yet effective. She gradually became to start learning in auto-didacting manner. After a year she was already a professional coder. She does not have a paper from a school that she can code, but she is doing a fantastic job. So, she missed early education, but was later able to neutralize the handicap. Developed talent can be described as the set of information learned and known, along with the right attitude, the scientific approach to new types of challenges.
Practice: Practice is good to increase the level of developed talent, yet, it SHOULD not be the sole source of developing talent. Along with practice, the theoretical horizons must be regularly expanded.
Working strategy: One can be extremely talented, can have a lot of knowledge. If he or she does not have a right working strategy, then he or she has a handicap. Whenever a new task is given, the right questions should be asked:
what was the closest task to this one? Can I reuse my solution to an extent?
what should I learn to be able to solve this problem?
how can I write clear and efficient code to solve the problem?
So the answer is: while it is good to have excellent education as early as possible, it is not necessary. Do not forget, that life is the best school and you can recuperate the lost opportunity later if you have talent, willpower and source of information. Practice is not only showing you the right steps to solve a problem, it also widens your horizons. For instance, if one understands number systems, then he or she will be able to understand a variety of things later, like colors in CSS, PSD, or number overflows. If one learns how to code in Java, then he or she will understand C# very quickly. So, practice is giving you knowledge about the solution to a given problem type, but also, gives new theoretical knowledge which will be useful in various areas. The core skill one has to develop is the ability to learn quickly.
There have been many examples of people having extraordinary talent with minimum success. You see such examples in sports,politics,business and also in general around you. So, I feel after a certain limit, talent is a meaningless virtue. Its mostly the hard word that rewards you with greater success. If you follow cricket, here is a link with good example.
I feel same principle applies to algorithm and problem solving. An year back I use to pick up algorithmic problems to solve and used to find myself completely lost. An year invested in reading algorithmic books, solving its exercises and also practicing some more programming problems, I am confident that now I can solve most problems ( I still have a long way to go in making myself efficient in it). But the point is smart work is enough to develop this knack of solving problems.
Talent is cheap and useless without hardwork. Talent can only take you to some extent, but with hardwork and practice anybody can reach great heights
- Josh Waitzkin, 8-time National Chess Champion, a 13-Time National and 2-time World Champion
He himself says this in his voice over in Chessmaster Grandmaster Edition

What to do when faced with a seemingly unsolvable situation with a time limit?

I am a computer sciences student and I usually have really tough programming assignments. I don't know if it is only happening to me but sometimes, particularly when deadline is approaching, I find myself in a harsh situation.
I cannot find my mistake in the code or come up with a another great idea. Then boredom comes in and the problem begins to seem unsolvable.
I would like to learn their ideas to cope with this situation. Is it better to focus on something else for a while? Or try again? Or try harder and harder and look for the solution on the net, etc?
I alway like talking about the solution with another programmer. Just talking makes me use a different part of my brain and most of the time I hear myself talk through a solution.
Sleep is good, or if not sleep then at least taking a break, going for a walk in the fresh air etc.
Brainstorming the problem with colleagues / fellow students can help. Even just explaining the issue to someone else can be enough to make the solution click in your brain.
Failing all the above, ask on Stackoverflow :-)
Try breaking down the problem into smaller, easier problems, and solve those. Don't try and tackle everything at once, and avoid trying to hack your way through.
If you're still stuck, taking a break can be good. Sometimes the answer is suddenly obvious when looking through a refreshed pair of eyes. Solutions to problems often come to me in my sleep, and I'll wake up knowing the answer.
For me, I encountered a couple of times where I took quite a bit of time (10 to 30 mins) to define the problem in writing as to submit the question on SO, and got ideas that led to the eventual solution while typing out the question.
I find that when I document your problem in a way that others can understand without having to understand the unrelated parts of the your entire application/project, I consciously break down the problem into isolated, independent parts which helps me or another developer analyze and decide the next course of action.
Just my two cents :)
In your case (school work) I would probably seek out the instructor/professor or TA. While they will certainly not "give" you the answer at the very least you might learn something else in the process.
Specifically I would explain to the the difficulty you are having, what you have done to try to solve it and any other things to show that you did work.
A lot of times while walking though this on your own you might come up with solutions. They can probably give you hints or suggestions as well.
Worst case scenario is that they tell you to go away and to leave them alone.
Others have posted sleep (#sjobe, &Vicky) and asking someone is good (#Christopher Altman). BTW, that is often referred to as "rubber-ducking".
My personal problem is wanting to see something through and getting consumed in getting to the finish, almost always to my own determent. What I've learned over the years if a little research doesn't help (< 30 minutes) and talking it through doesn't explain it and you can't or don't want to sleep on it, do something for the mind, body and spirit: Go outside!
Seriously, go for a 30-45 minute bike-ride, run, walk, swim, whatever. Try to think of something else. Tell yourself a story or mentally work on another problem if you must. Cool down and return. You'll be amazed at how refreshed you'll feel. The endorphins will help.
If you're embarking on career driving a desk, it's a great habit to get into as well.
-Cheers
The entire art of surviving or rather conquering in situations like this is about staying to have a solution oriented approach . By this I mean staying positive that even if a solution is not working it , have faith that your tries are getting you closer to it .
Yes I strongly agree that taking a break is an integral step of reaching your goals but take a break to return back with stronger spirits to solve a problem .
Involve yourself into different solution finding strategies along with a spirit to enjoy the same .
The solution finding strategies may involve :
Talking to your friends who dont understand the problem to a good level and help them understand . It will help you explore the ins and outs of the scenarios . Sometimes explaining other people helps us understand the problem in a much better scenarios .
Sit down with a paper and a pen or its better to have a diary where jot down all the ideas as they strike you . Take your diary with you always as it helps to jot down the ideas otherwise later we forget . Also sometimes the game is about connecting the dots . An idea from morning first half and evening time can be perfect mix to resolve the problem .
Go out on a brainstorming session with couple of friends and entertain all the ideas that they put on table for once and consider them . Remember no idea is an stupid idea . Either it is solution or a contributing step towards a solution .
There may be times when you need to visit an industry expert or a researcher to dig deeper into concepts of technology . Before you visit an industry expert keep all your research documents and brainstorming ideas collected . Share it with the researcher correctly . Also have a SWOT analysis of the person you are trying to meet so that you get to understand in which part is the person strong and can help you . Also carry a recorder with you such meetings because jotting down everything becomes difficult .
Dont believe in what ever is always suggested make sure to come home and do entire research on internet on whatever is shared . That will help you increase your knowledge .
Do some experiments . Some hits and tries randomly and based on results reach to conclusions .
Each of these steps plays a very important role in brainstorming and reaching to a solution . Looking forward to hear from you what were your experiences trying these out .
A similar question has already been asked here https://stackoverflow.com/questions/427532/what-do-you-do-when-youre-stuck.
Sleep is my personal favorite though, although if you're like most college students, you're probably doing a lot of last minute coding and you don't have enough time to sleep and submit your work on time [I was guilty of this too].
What I like to do when I'm stuck on a problem, I usually try to draw out my problems. I just get myself a piece of paper and write down the problems that I encouter. While doing this I like to make Class diagrams/Sequence Diagrams, just to clearify the situation in. Really helps to just get back to old skool pen and paper and not look at your screen for a while.
As a student I also face this problem from time to time. What helps me quite often is to get away from the computer, take a pencil and some paper and start to write down the code by hand. I don't know why but often it is easier for me to solve it on paper than by using an IDE/editor. Probably because your brain works differently then.

How do you "get it" when it comes to proofs? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
When we start getting into algorithm design and more discrete computer science topics, we end up having to prove things all of the time. Every time I've seen somebody ask how to become really good at proofs, the common (and possibly lazy) answer is "practice".
Practicing is all fine if you have the basics down, but how do you get into the mind set for mathematical proofs? When did induction click? What resources are best for teaching these topics? What foundation topics should be researched prior to indulging in proof-writing?
They aren't being lazy, practice is the only way. Take classes you have to do proofs in and look online for class notes and old tests with answers from other colleges that go over proofs.
I'll start off my answer by admitting that as a CS student, I had a really tough time grasping a formal way of thinking, and it's never easy, unless you have a talent for it.
I'm afraid there is no better answer than practice and study.
A formal mathematical and algorithmic way of thinking and visioning problems is a skill which first demands a very deep understanding of the subjects you are dealing with. Second, it requires you have good knowledge of existing proofs. Try to envision yourself as some of the great scientists who came up with the algorithms you are studying. Understand how you would have tried to tackle that specific problem. Then see how they proved the correctness of their algorithm.
I can only recommend the greatest textbook in this subject which is Intro to Algorithms by CLRS. If you go through it from start to finish, including every exercise, you will enhance your skills.
Practice is really the only way, but it can helped along by reading proofs as well. I won't touch on practice because the other answerers have covered everything that I can think of, so I'll just talk about what I mean by reading.
Textbooks are very fond of writing out the "important" proofs. Its very nice, because they often prove very powerful statements, and are really fancy. But just as you shouldn't learn to be a world-class gymnast from day 1 by emulating an Olympian (as in, you'll probably break your spine), you shouldn't read any really big proofs (at first). What I found was helpful was reading smaller proofs, usually from returned homework (I assume you're a student) or occasionally a textbook that wisens up.
The reason why I think reading proofs is helpful is because there are a small set of "tricks" or "ideas" that constitute huge chunks of schoolwork proofs, and even more advanced ones. Data structure qualities and recurrence relations usually involve thinking related to proof by induction, proofs involving computability with finite state machines sometimes use the pigeonhole principle, and more rarely the idea of diagonalization (very infrequent, don't worry about it). And of course, just about every other proof uses proof by contradiction. I'm sure there are other handy tools that have slipped my mind, but I hope you get the idea.
Figuring out when, how, and why you'd approach a problem with one particular method or another is what takes practice and experience. I suggest reading proofs in addition to practice because it can often show you creative ways of using a proving method you've already encountered.
As a final note, try to remember when you first learned to program. How did you get better? Proving things and programming things are not too dissimilar, in my opinion. :)
You get into the mind set for doing mathematical proofs by becoming a mathematician. I don't mean the last statement in a tautological way, but realize that a mathematical proof, as published in a mathematical journal, is something of a rhetorical artifact; i.e., it is a proof because a body of mathematicians agree that it is a proof. Ideally, the arguments in the proof could all be reduced to symbolic logic, but this is not how it is done in practice. The utter failure of computer-generated proofs to do valuable mathematics provides some evidence for this.
I get into the mind set by doing proofs and having them accepted by other mathematicians. I agree with the others that "practice" is essential. You don't do proofs unless you try, try, and try. Often the light dawns slowly.
The best resources are, of course, other mathematicians, and reading proofs. There are very few, if any, who can do true mathematical proofs without being part of the mathematical community.
I'm afraid that "practice" really is the best answer here.
Its very similar to programming: once you get the hang of it, you find patterns which solve problems particularly well, and you can create a picture of the high-level design of novel systems which you've never implemented before. However, neophyte programmers aren't aware of patterns: they hack away at code until they accidentally stumble on some solution which appears to "work".
When you're given a problem to prove, you can usually identify properties ("Do I have a set of distinct objects?", "Am I generating permutations?", "Am I looking to minimize/maximize some value?", etc). Sooner or later, proofs will clump together into vaguely similar group, where techniques used to solve one problem can easily apply to novel variations.
Recommended reading:
The Algorithm Design Manual by Steven Skiena.
I have no idea. Probably the same way you get good at composing music.
When I try to prove something I'm not following some fixed strategy, I just think about the problem. Then [undefined amount of time] later, my mind returns a result and I jump up to write it down.
But practicing definitely helps. When I started trying to prove extremely simple statements, like DeMorgan's laws, I was completely hopeless. So I sat down and did the fifty or so optional example problems on a worksheet we were given. Now it feels natural to prove something.
Practice and study makes perfect sense, agreed. Some tricks, that I found useful:
Make notes on everything you study (I've tried just to read books -- a lot of material just passes through).
In addition to previous point: do all (or most) proofs by youself, use book/lecture notes as a guide; a lot of proofs contains phrases like "we can see now, that XXX". And XXX is not always trivial conclusion.
Make exercises; for example, in CLRS book there are dozens of exercises. Exercises are good way to get the ideas behind algorithms/correct proofs.
If you want to better understand the internals of algorithm -- consider participating in online programming contests like UVa's.

How do you fight design complexity? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I often find myself fighting overengineering -- the person in charge of designing the software comes up with an architecture that's, way, way overcomplicated.
It's all fine and dandy to have all the esoteric features that users will never know about and get that sense of achievement when you're doing something that all the magazine articles are telling you is the latest, cool thing, but we are going to spend half of our engineering time on this monument to our cleverness, and not, you know, the actual product that our users need and upper management expects to be completed within a reasonable or at least a bounded time frame.
And you'll probably just have to revert back to the simpler solution anyway when you start running out of time, that is, if you get that chance.
We've all heard the refrain: Keep It Simple, Stupid™.
How do you fight with overcomplexity in your team?
One example I've had to work with repeatedly lately is when the decision has been made to go to a fully denormalized database design rather than an RDBMS. "because it's faster!" Fully denormalized databases are really hard to get right, and are only appropriate for really specialized data problems like Flickr or ebay, and which can be extremely expensive in terms of developer time relative to the rest of your development.
Tooth and nail, and sometimes you lose. The problem is that it's always easy to be tempted to build something cool.
Why build something simple and efficient when it can be complicated and wonderful?
Try to remind people of the XP rule of building the simplest thing that can possibly work.
Make sure to bounce any ideas you have off of someone else. Oftentimes, we get so wrapped up in doing things a certain way that it takes another set of eyes to set you right. There've been many times that I've figured out difficult problems by having somebody else there to say "do we really need that?" This helps make my code simpler.
On the point of dealing with people you disagree with, Ward Cunningham has a good point:
It was a turning point in my programming career when I realized that I didn't have to win every argument. I'd be talking about code with someone, and I'd say, "I think the best way to do it is A." And they'd say, "I think the best way to do it is B. I'd say, "Well no, it's really A." And they'd say, "Well, we want to do B." It was a turning point for me when I could say, "Fine. Do B. It's not going to hurt us that much if I'm wrong. It's not going to hurt us that much if I'm right and you do B, because, we can correct mistakes. So lets find out if it's a mistake. ... Usually it turns out to be C. It's a learning experience for both of us. If we decide without the experience, neither of us really learns. Ward won, and somebody else didn't. Or vice versa. It's too much of a battle. Why not say, "Well, let's just code it up and see what happens. If it doesn't work, we'll change it.""
My advice? If you want to do something better, come up with a simple prototype that demonstrates that it's better. Opinions are great, but code talks.
I have seen this formula somewhere:
skill = complexity of problem / complexity of solution http://img39.imageshack.us/img39/1586/whatisskill.png
In other words, it requires skill to create a simple solution to a complex problem. If somebody purposefully designs and takes pride in complex overengineered solutions, then he is unconsciously incompetent.
Personally, what helps me to keep my designs simple, is the TDD cycle. First write a test that specifies what you're trying to reach, and then produce "the simplest thing that could possibly work". And every now and then, reflect on what you have produced, and think about how to make it more simple.
Never build extra flexibility and abstraction layers into the system, until it is required by something that you have now. Changing the code is easy, when you have a good unit test suite, so you can add those abstraction layers later, when the need arises, if it ever arises. Otherwise, "you ain't gonna need it".
Some symptoms of too complex design are when writing tests is complicated. If the tests require a long setup code, maybe you have too many dependencies or in some other way too much complexity. If you run into concurrency bugs, then maybe you should think about how to design the system so that concurrency is restricted to the absolute minimum number of classes. Maybe use a message-passing architecture, such as the Actor model, and make practically every component single-threaded, even though the system as a whole is multi-threaded.
At least for me, the bigger issue is that it's often hard to tell what feature is in there because of its buzzword-friendly, magaziney enterprisey goodness and which is in there because it adds a level of flexibility that will be useful in the future.
It's been shown that people are generally terrible at anticipating future complexity, and side-effects of current decisions. Unfortunately this doesn't always mean simplest is best - in my case, there've been loads of things I thought were too complicated at first and didn't see the value of until much later (er... spring). Also things I thought made sense that turned out to be wildly overcomplicated (EJB1). So I know that my intuition about these things is faulty.
Best bet - any kind of indirection layer should be supported with an argument supporting the value of the flexibility it adds vs. its added dev complexity.
However, people who are dogmatically maintaining a particular db setup on abstract grounds are probably in the "building it because I read that it's the right thing" camp. It might be unrealistic, but some people might be convinced if you build a test version and benchmark, especially if the results show more effort leading to an insignificant performance increase.
It's all fine and dandy to have all
the esoteric features that users will
never know about and...
This would be feature creep, not unnecessarily complicated design. It's different from your example on databases.
One example I've had to work with
repeatedly lately is when the decision
has been made to go to a fully
denormalized database design rather
than an RDBMS. "because it's faster!"
In this case several things may be going on. One of them is, you might be wrong and these people could really know what they are saying because they have worked with very similar examples. Another is they might be wrong, i.e. their design doesn't offer the speed advantages they claim. In this case there could be two different situations: (1) They are giving speed too much weight in their design, or (2) speed is really critical. If speed is indeed so relevant, the team shouldn't rely only in assumptions - they should try different prototypes and evaluate their speed in the critical paths. You don't build an F1 car in one way just "because it's faster", instead you keep trying several alternative design solutions and pick the fastest one which still doesn't increase maintenance costs too much.
Sometimes you can argue it and reach an agreement, sometimes you can't. It's life.
A final word, though. You don't fight complexity. You treat it. You identify the really important things and act accordingly.
I assume you mean "fully denormalized database design rather than a normalized (e.g., third or fourth normal form) model", because a relational model is managed by an RDBMS regardless of how normalized it is.
Can't judge without knowing more about your requirements, your abilities, and those of your teammates.
I fear that your KISS admonition might not work in this case, because one big, denormalized table might be defended as the simplest thing possible.
How does anybody solve these kinds of problems? Communication, persuasion, better data, prototypes of alternative technologies and techniques. This is what makes software development so hard. If there was only one way to do these things, and everyone agreed on them, we truly could script it or get anyone to develop systems and be done with it.
Get some data. Your words might not be enough. If a quick prototype can demonstrate your point, create it.
"Strong opinions, lightly held" should be your motto.
Sometimes a technical point isn't worth alienating your entire team. Sometimes it is. Your call.
You fight someone else's overdesign/feature creep in several ways:
Request feature priority, based on actual user requirements. Mock up features for alpha and beta testers, and ask if they would trade N months of delay for it.
Aggressively refactor to avoid special-casing. Break code into layers or modular components whenever appropriate. Find a balance between "works just fine now" and "easy to extend later".
Notify your management when you disagree with design decisions, prepare to be overruled, and accept the decision. Don't go over anyone's head or sabotage code.
The best way I have found is to relentlessly ask - again and again - 'What is the business problem we are trying to solve' and 'How does this decision help to solve that problem'.
I find that too often folks jump to solutions instead of being crystal clear on what the problem is.
So in your example of how to organize a database, my question would be 'What do we think are the transaction requirements for this project today, next month, next year, five years from now'. It could be that it makes sense to spend a lot of time to get the data model right, it could be a waste of time. You don't know what the parameters are until you get the problem definition clear.
You may suffer from "too many architects in the team" syndrome. One or two people at most should design/architect a system which will be coded by a team of 5 to 10 people. Input is welcome from everyone but architectural decision makers should be few and experienced.
(the numbers are semi-random and could be different depending on other factors as well)
I try to be open when discussing matters. But when i am discussing with someone else between something that seems simple and another one complicated, i get as stubborn as can be. It helps quite a lot, so long as you are very coherent from one decision to another.
Your example isn't really a complicated design, it's a design choice that you don't agree with. Since you're working on the code, you could easily be right because many of these decisions are made by people reading an article in an article and thinking it sounds like a good goal, or the decision could have been made by someone who ran into problems before and was trying to prevent it from happening again.
Personally I've done a lot of stuff the easy way and a lot of it the hard way, and I'm never happy when I choose doing something the easy way over the hard way. Now I've learned tricks like "never pass around a naked collection, always wrap it in a business class".
If I were to explain the reasoning behind that to someone who hadn't been through the same experiences, they wouldn't understand it until they tried comparing the "easy way" to the "hard way" a few times.
The solution should be no more complex than the problem.
The question intertwines itself with the thought of essential complexity. A sort must touch each element, by its essence. How much more complex must it then get, to solve the problem, given the technical constraints existing on it?
Do the people involved have enough time and incentive to find a simple solution? Without care, complexity will increase. If you spend most of your time trying to do the quickest possible bug fix or feature addition then saying "keep it simple" will not be enough.
Ensure that there are some people on the team with war wounds from maintaining large programs, and people with experience of refactoring, and then give them time to sort the software out. If you can arrange that certain features and opportunities are out of scope, that will help people remove unneeded code. If you want a metric, aim to reduce lines of code; but try not to obsess over it. Improve the test coverage; consider eliminating bits of code which are hard to test.
Don't try to do everything at a stretch. Break every problem/task into manageable chunks. Then prioritize, keeping KISS and YAGNI in mind. This will help you focus on building what you need. If you've done it right, you'll have a good core you can add to later, given time, money, resources and inspiration.

Resources