PhD Research On Software Design Principles?
cconnell writes "I am working on a PhD in software engineering at Tufts University. My interest are the general principles of good software design, and I am looking for links/references on this topic. The question is: What design/architecture qualities are shared by all good software? Good software means lacking in bugs, maintainable, modifiable, scalable, etc... Please don't tell me 'use object oriented methods' or 'try extreme programming.' These answers are too narrow, since there is good software written in COBOL, and by 1000-person teams for DoD projects. I am looking for general design principles. If it helps, I am trying to build on the ideas in this article from some years back."
The sell any one piece knows about the other pieces, the better off the system will be.
Badass Resumes
Download the latest OpenBSD source code and read up. It's well written, well maintained and very well documented.
This is an excellent place to start:
http://www.cc2e.com/
AC
Personally I only do extreme, object oriented programming in COBOL, so I have nothing new to offer.
If brevity is the soul of wit, then how does one explain Twitter?
Simple is beautiful :)
I can't call that English
Make sure the programmers know the application they are writing. I have seen programmers that wrote apparently competent code but it didn't do what it was supposed to because they didn't know what they were supposed to be accomplishing with the code. If the coders can't perform the task with pencil and paper (I know, how old school) then they can't possibly do it with code. This is from an accountant that has had a "home" computer since Bill Gates did tech support.
I mean what percentage of your PhD will be mine? Is it your PhD or our PhD. You want the degree, son? Earn it.
sed -e 's/Chuck Norris/Rajnikant/g' joke > fact
then have a shot of whiskey
if you still can read that line, code another one.
http://objectmentor.com/resources/publishedArticles.html
Seems to be a good starting point for Design principles.
Last semester we had software architecture and design and we used Software Architecture in Practice as reference. I found it pretty good and I'm sure it'll hold lots of information relevant to PhD students, too.
Good code avoids putting variables or functions unnecessarily in the global namespace. This means that the likelihood of name collisions is less likely so your code project is more likely to play nice with other code projects.
It's also good practice to try and make all of your code non-reentrant and threadsafe. As processors sprout an increasing number of cores, it is important to make sure your code can take advantage of the extra power.
It's also a good idea to COMMENT your code and DOCUMENT your processes. There's nothing worse than stumbling across something you wrote 10 years ago and having no idea how it works.
You could always read a text book on Software Engineering.
From what I can see, the real answer, process. Having a documented process that you follow to ensure that code is free of bugs, and that code is readable. How you accomplish those things isn't exactly important. For making sure code is readable and maintainable, you can have formalized code walkthroughs, or you could just have another coder read it over before it is accepted into the project. Ensuring that the software doesn't have any bugs is another issue. You should have a repeatable test environment, whether it be unit tests, or even just a list of actions peformed by an actual person, in order to check that everything is working correctly. Some approaches work better than others. But the real important thing in the end, is to have a defined process, and ensure that it is being followed.
Anthropic principle: We see the universe the way it is because if it were different we would not be here to see it.
Dear Mister PhD,
do your own damn homework.
Love,
the management
Read books by Ed Yourdon written in the 1970s.
Dave Barnes 9 breweries within walking distance of my house
Found this article
...
http://www.faqs.org/docs/artu/ch01s06.html
from this search
http://www.google.co.uk/search?q=art+programming+simplicity+clarity&sourceid=navclient-ff&ie=UTF-8&rlz=1B3GGGL_enGB223GB224
Have fun
http://www.htdp.org/
I'd recommend the book Object Thinking. The methods can be applied to any programming language. I'd also recommend that anyone working on the project have a strong background in computer science and experience to go with it.
Intel transfer the difficult from Hadware to software, for get more power, programmer need more technology. -- chinaitn
Use object oriented methods or, in the alternative, try extreme programming. Refactor whenever possible. Dissect and redistribute. Make sure the team is cohesive and factionalized. Compensate for all scalable factors on a frequent basis, using randomization approaches. Never, and this is not set in stone, allow the project to objectify to the point of opacity. This cannot be overemphasized: you can never add too much manpower to software tasks.
Solve specific problems, and avoid generic "frameworks."
Reduce configurability, dare to code business/core logic.
Know your domain; If a problem seems complicated, the solution tends to be complicated.
(And if you know nothing, all problems seems complicated.)
Iterate. Refine.
The article from earlier today seems to tell you how not to do it.
From my experience, I think the biggest thing is trust. The managers need to trust the developers to do what's right, and listen to the developers when they make suggestions on how to do it better. The developers need to trust that the managers won't get in their way, but will keep them on track and keep them insulated from distractions. Developers need to trust each other, that everyone's code works well etc, and trusts each other enough to ask for help when they need it. Once everyone trusts everyone else and can work well together, the project will be more successful.
Little secret: this goes for any project.
In my experience the single most important part to a software project is good requirement gathering and analysis. As for development, every program that i know uses some concept of divide and conquer. Breaking up a large problem in to a set of connected smaller problems simplifies writing good code. It's easier to write small bug-free modules then it is to write a large program all at once.
It would be interesting to find the cutoff point where a problem should be further divided and when it is discreet enough. Also, it would be interesting to know when a developer begins to introduce bugs or less optimized code. Like after x many lines or like y many hours.
It would be interesting to try and quantify code elegance. I forget who said it but there's a saying "code that looks good is good"
I came to the datacenter drunk with a fake ID, don't you want to be just like me?
I'm happy I don't have to tell him to use "Ask Slashdot".
Yahoo! Pipes are awesome. How awesome? http://pipes.yahoo.com/jesdynf/slashdot
// Comments.
Good software has:
I laugh at these eggheads who dont know real world conditions.
could get you shot
Write code that doesn't have bugs. Make sure it is as simple as possible, and no simpler.
Seriously, isn't this kind of thinking what *you* are supposed to be doing for this thesis?
Good software is written by good people. There is no general rules you can follow to automagically make your software good.
Sure some rules will tend to make your software a little bit better: KISS design principle, release early release often, unit tests, etc. But fundamentally it's all about people.
Then you might ask "what makes a good developer good". Well's that's not so easy to answer.
You need three things
...
1: A bottle of your favorite alcoholic beverage.
2: Three seasons of Southpark.
3: Make that two bottles, and some snacks
4: An internet connection.
5:
Um, I forget where I was going with this, which pretty much sums up my first year. Ah, I have such fond memories of trying to find papers when I was starting. Now I'm writing up I can look down upon you first year phd noobs and laugh, oh yes, perhaps even 'heartily'.
Well anyway, there's always google scholar. Worked for me, its an extremely useful tool.
A learning experience is one of those things that say, 'You know that thing you just did? Don't do that.' - D. Adams
When you say "good design" do you consider efficiency to be a part of that? I work for one of those "1000 person teams" and what I have noticed is that processes(CMMI level 4) keep the schedule and quality on track. That's not really news since that's what a 1000 case studies have said before. However, I would not want to take all of that baggage to a 10 person team that needs to remain agile to compete in their market.
IMO, designing with scalability in mind always helps, but I have no evidence beyond anecdotal to back this up.
There are a number of nice books on software design patterns and anti-patterns. See http://en.wikipedia.org/wiki/Design_pattern_(computer_science)
and etc. The pattern I love to contemplate the most is "big ball of mud" aka "spaghetti code".
A software project is only as good its documentation. Look at successful open source projects -- many of these have excellent project documentation that tells you all about the architecture, structure, features, coding practices, standards implemented, data formats, data validation information and so forth.
WHat kills so many projects is a lack of good documentation -- if no one can figure out how to pick up the ball and code a feature or a bugfix or whatever, then the code will wither. This applies even to closed source projects -- one of the things that screwed Vista over, for instance is that much legacy code was in need of rewrite -- except there no one new what the code did anymore.
My blog
When you finish something, hide it until the deadline. This is because if you ever give your boss something before the deadline, he will pull some nonsense out of his rear that he thinks he needs added to the project.
Plus whatever your shortest turnaround time is, that is what he will expect in the future, no matter how complex the task.
In general, try deceive and ignore your boss as much as possible.
The QUINT-2 model (extended from ISO 9126) is a model to discuss various aspects of software product quality, see: http://www.serc.nl/quint-book/
Check the Quint-2 browser if you like a nice visual representation: http://complexitymap.com/quint2/
Hope this helps. Don't hesitate if you have additional questions.
* Hide details that client code doesn't care about
* Expose details that client code does care about
* Consider building everything as event driven state machines
* For distributed processes, read http://research.microsoft.com/users/lamport/pubs/time-clocks.pdf
* WRITE TESTS FIRST
* No, I really mean it. WRITE TESTS *BEFORE* YOU WRITE "REAL" CODE.
* Design for the known specifications, only design to support expected spec changes if you're sure those particular spec changes will happen
* Break down the system into units cohesive within themselves, but not cohesive with other units. (Duh)
That's it, off the top of my head.
default deny (whitelist not blacklist)
no documentation, and variable names based on the names of the programmer's girlfriends
intellectual property law is philosophically incoherent. it is your moral duty to ignore it or sabotage it
seriously, your PhD thesis is THIS broad? And you have to go to slashdot even to get started on it? I feel bad for you....
Monstar L
Options should be where they belong. Configuration/installation should offer as many options as are needed and then more. (Since when is an "advanced installation" really just one or two options?) Remember that not all of us use a mouse all the time so keep keyboard navigation easily available. Read some of the UseIT articles. Keep the layout consistent throughout the application.
There, those are some design fundamentals that I think are important. As for the code, don't be afraid to comment. Someone, like me, might come along after you and be pretty much inept without the comments so try to be clear.
"So long and thanks for all the fish."
Most good software I've seen follows the KISS principle internally: Keep It Simple, Stupid. Pieces of it know what they're supposed to do and they do just that. They don't mix in functionality for several things. They don't have embedded knowledge of how they relate to the rest of the system. They've got clean, modular interfaces that let you test just that one part to make sure it's doing what it should and not doing what it shouldn't, without having to haul in large parts of the rest of the system. They either don't make assumptions about what the rest of the system will hand them or they've got those assumptions clearly documented in the interface and they test that their input conforms to those assumptions and produce a clear error if it doesn't. Eventually some pieces will have to embody the design and logic, understand how all the individual pieces fit together to make the system work, but that's their job: to orchestrate the work being done, not to actually do it.
Another indicator is that good software is designed with the certainty that it will change, that it will be extended and altered over time. Good software has that assumption built in. Bad software, by comparison, is often flagged by statements like "Don't worry, we're never going to change that." or "We don't need to worry about doing that.". Software designed not to change or be extended is either bad software or rapidly becomes bad software once it hits production.
And no, nothing particularly new there. It's been this way for about 50 years.
After years of debating on usenet and C2.com wiki, I've concluded that software engineering is largely a psychological process if one is looking beyond just performance issues. Due to Turing Complete principle, there are many many solutions to any given problem (same output). The solution that people prefer seems to be the one that best fits the way they think or the way they think about the domain (problem-space). The problem is that until we can dissect an entire working brain, psychology varies per person and is a "soft science".
Those who claim they have objective evidence of the Golden Paradigm/Technique are probably full of squishy brown stuff.
Table-ized A.I.
Do your own homework.
Don't allow the executive accountant to tell how the software will work as you won't allow the executive accountant to tell where the ceiling in the hose will go.
Don't allow the PHB to tell how long it'll take to develop as you won't allow the PHB to tell how long it will be to build the bridg.
Don't allow the beancounter to decide on the developers' profiles as you won't allow the beancounters to decide that a mason can take the architect's role.
Finally don't allow the company to decide to get in in projects where it's obvious the company lacks the maturity, the workforce and the professional profiles to take the deal as you won't allow a company to build an airport with two masons and a plimply young engineer.
Ok, ok, let's return to real world: current software is just OK. People wanting to pay for it clearly shows it. The paper you cite obviates reality: "if a house were like too many software projects, people wouldn't dare to go into". Well, but they *do* dare to "go into" the software and pay good bucks for it, so who cares?
I've personally written one medium size project(around 100k). As the project scaled I found there were a few things that really made a difference. Modularity with high boundaries and simple interfaces between modules. What I mean by this is that as a program grows more complex if you reduce the number of dependencies maintainability increases greatly. Also, if it's possible to use the standard data types(i.e. deque instead of MyReallyCoolIntegerDeque) for communication between modules it's much easier to maintain compatibility between modules. Also, one thing I can never seem to get across to developers is to write readable code. This means naming functions according to their function and not as some cryptic acronym. It means naming variables what they are, even if their name has to be a sentence(Though, usually a simple and obvious name can be found if you think hard enough.)
I strongly suggest you see if you can get a few weeks of academic internship with these people. Also know as 'Those who write the right stuff. They actually do know how to write software.
... whatever. And while people will start bickering that Apache or Blender code is oh so crappy in this or that area, rest asured that all projects of that kind, *incuding* the aforementioned *all* have core team members who are very well aware of the downsides of their software. And thus can help you out in your pursuit for details on professional software developement, because they also know the pitfalls.
Other places to look for: Linux Kernel team. Donald Knuths Tex/Latex.
Or, believe it or not, Blizzard Entertainment. They actually are the only entertainment software company I know of with a proven track record of extremely high quality software compared to others in the field.
But any core team of non-trivial low-level open source software technology will do actually. Python core team, PHP core team, your favourite Linux IO crew, Apache, OpenLaszlo, KDE, Haxe, Blender,
Bottom line: Join some tight crew of people that build stuff everybody uses or many people rely on to work. Hang with them for a month or two, then you'll have a better idea how exactly to approach your topic.
We suffer more in our imagination than in reality. - Seneca
I've been programming for almost 15 years and have spent alot of that time very gradually refining my own design principles. Here are my basics:
1. Modular designs. Modular code is generally more maintainable and more scalable.
2. Self-documenting code. If you read my code, you can understand whats going on just by the code. There are very few comments, because very few are needed.
3. Occam's Razor: The simplest solution is often the best/most correct solution. Over-complicating things often leads to maintainability issues later on.
I am currently working on a project that requires me to share code with several other people. None of them have needed much direction when picking up my code and re-using it because I've used sound design principles when writing it.
There really is no single answer that handles all situations. I use some more specific principles when doing different types of projects, depending on whether I'm doing Database design, web development, stand-alone applications or complex application systems.
System design is very subjective, every person seems to have a different way of doing things. One thing I always ask myself is this: Will I be able to work with this code 6 months from now? If the answer is no... then I have work to do to improve the design.
Thomas A. Knight
Author of The Time Weaver
The maturity of the management and its ability to insulate the coders from the noise from corporate is important to good code development.
Having an experienced architect is vital. Enforcement of the values of the team, especially with respect to interface specifications, is important.
Best regards.
I'm intrigued by this question, because I would assume that by the time you've reached this level (i.e. have a Master's in CS or something related) you would already have an idea as a starting point. Furthermore, I thought that the first part of any PhD-level research was an intensive Literature Review.
So, in other words, you should search LexisNexis, EBSCO, etc., and find some journal articles that talk about this. Read some books like Gang of Four or Mythical Man Month. Lastly, do your own data gathering. Find a bunch of Post-Mortems and start to put your own patterns together.
Oh, wait, all that would require work.
Seriously...I teach college-level courses and have multiple graduate degrees...and I'm continuously amazed at the quality that schools put out nowadays.
"You cannot find out which view is the right one by science in the ordinary sense." - C.S. Lewis on Intelligent Design
In some countries you have to submit a project in order to enroll into a doctorate programme, in others you become part of an ongoing project and your work will be a spinoff from that. Either way, I can't see how you are already working on your PhD and still making these sorts of questions.
How can you do PhD work on software design principles if you haven't delved into all forms of programming for yourself and applied them to real world scenarios? Please don't tell me you are an academic writing some paper to then stay school-side and claim you are an expert. You should get a job, assuming you don't have one already, in the corporate jungle like the rest of us and do the research for yourself. A /. doctor, is this a first? How do you put that in your thesis and defend it? If you are an industry expert soliciting opinion only, then more power to you.
1) Affordable.
2) Good foundation.
---
1) is where most software and management people both fail.
managers refuse inexpensive updates to keep the software robust because there is "No R.O.I." until they then buy or have written a new "wonder package" at much higher expense than the deferred maintenance.
Meanwhile developers (and users) design systems that are nice but so expensive they really can't be done.
2) Software, unlike buildings, is constantly changing- and usually it is equivalent to adding new floors onto buildings more than adding new wings. This means as you add more and more floors, the foundation must be made stronger. This work is rarely allowed (see #1) so when you write software, you need the experience to say, "I can inexpensively make this foundation strong enough to handle 3 new floors of upgrades and triple the expected load... however i can see that making it handle 5 times the load is so expensive the project won't happen.
---
So you have such basics as
Reasonably normalized data.
Abstraction layers so that you can replace a layer without breaking anything.
Fields big enough to hold at least 3 digits more than you ever expect to happen in reality.
Foundation library classes that are well-defined, obviously reusable- and not too many of them (maybe 80-100 max - more than that and people start rewriting them because they can't find them).
---
the worst bit is that now managers think
1) programmers can maintain skill without actually working on code
2) programmers are generic resources and that a college grad or indian resource can step right in at full productivity.
3) languages and platforms will not expire within 3-4 years because the old mainframe programs never did (but they do today-- they are all so interdependent on each other).
She was like chocolate when she drank... semi-sweet at first and then increasingly bitter.
I hope you have more of a frame work to build your thesis on. Have you read many PhD dissertations? They are usually centered around in-depth research on a very specific problem. You are describing getting some general design principles that might make a great book on the subject, but not a thesis.
C.f. "Good building techniques" with "Primary cause of premature failure of self sealing stem bolts in extra-solar habitation facilities". See the difference?
Slashdot won't be doing the PhD work for you.
--- Eat my sig.
Literate Programming by Donald E. Knuth
Beautiful Code: Leading Programmers Explain How They Think by Andy Oram and Greg Wilson
But the real answer is: since there is no professional testing / licensing for software engineers or software managers; most of them are actually incompetent and/or inexperienced.
I don't have an answer to your question, but it might be helpful if we could get some examples of projects people think embody the idea of "good software." Then discuss principles these projects used which made them "good software."
"My interest are the general principles of good software design, and I am looking for links/references on this topic."
FAIL. You might squeak by on a masters thesis with that kind of topic. Maybe.
2: Three seasons of Southpark.
That's The Simpsons for coding. Southpark is for debugging.
Man, you obviously have no idea. One of the critical skills is to choose the right tools for the right job.
We used to have a Bill of Rights. Now, with the rights gone, all we have left is the bill.
Dear Slashdot,
I thought getting my PhD would make me uber 1337. Well, I finally got accepted into a PhD program, and now I find myself completely over my head. I don't even have a topic for my thesis!
Could someone do my homework for me? Also, could you supply your name, address and phone number? I'm going to need someone to go in and defend my dissertation for me. kthxbai.
I find that good software is usually grown. It is not about specifying everything upfront and building it. But also good software doesn't always mean popular or user-friendly. It is simply modular and has easily replaceable pieces that communicate with more(mostly) or less well defined interfaces. This to alleviate the growing pains when the software evolves. Plan9 comes to mind or Unix shell utilities.
Specifically, the group that wrote the software for the space shuttle. With a defects-per-line rate less than 1/1000th of the average, they're doing something right.
http://www.fastcompany.com/magazine/06/writestuff.html
Of course, with a full pages of documentation for every 10 lines of code, and an average daily output of roughly a dozen lines of code, their process is much more time consuming and expensive than can be supported by most development budgets.
But they serve as an example of the wide spectrum of approaches to software development.
I've been reading Code Complete by Steve McConnell at home and he really hits the nail on the head on how do design and write good software.
He now has a second version of his book out, I highly recommend it as a study on good software.
bleuchez!
In my experience, the best litmus test for good software design is if the application, when finished, can accomplish useful tasks that were never in the original requirements. I've seen numerous such occurrences.
For example, a month after deployment, a customer has called and said, "I need a report for X". Then, I've responded with something like, "Go to this report, filter on this field, and sort by that field". In this manner, one can accomplish some specific task without making a single change to the application. And, it's not just limited to reports. I've seen various non-report examples as well.
If written well, the application has a built-in X factor that anticipates future needs.
Not that a reasonable schedule always results in good software, but an unreasonable one always seems to result in bad software.
...thing about the study of software design is good analogies. Without good analogies, your thesis won't make any sense at all.
Compare software development to carpentry, automotive repair, civil engineering, cooking, music composition, sex, stamp collecting, spelunking, bird-watching... software developers can't understand treatises on software development unless there's metaphor involved.
And mix it up a bit. If you use carpentry in a paragraph about class modeling, make sure to use automobiles in a paragraph about unit testing.
Or, if you find mixed metaphor lacks grace, just stick with cars.
--I'm so big, my sig has its own sig.
-- See?
If you consider good software to the clear, effective, and durable communication of heuristics then one might look to other aspects of the human condition where this has become necessary or brought forth fruit. Law? Math? Economics? The Art of War? If you can identify the over-arching ideas that seem to lead to good heuristics, how they're expressed in software should become more obvious, and then you can work on devising some system of quantifiying the meaningful attributes.
since everything related to design and implementation are generally defined by the datelines and budget that is available. you may have to define what the context for 'good' is.
Read radical news here
You want princples, the Open-Closed Principle would be a big one:
http://www.objectmentor.com/resources/articles/ocp.pdf
Too bad 95% of the code bases out there suck a**. Which is why I don't do software development anymore. I'll stop there.
Sytems Admin/Integrator,
-M
..published by the Microsoft Press.
I kid you not.
Sit down because what I'm about to say is very profound and could make you tear up.
I've heard that the key to good programs is.......GOOD PROGRAMMERS
Beer! It's what's for breakfast!
If researching your Ph.D. thesis involves an "Ask Slashdot", change topics or drop out now. This is akin to asking the undergraduate Math club for ideas on your thesis, is it not? We are not (and should not) be anywhere near the level of knowledge you already have on this topic...
TFA:
"Most software design is lousy. Most software is so bad, in fact, that if it were a bridge, no one in his or her right mind would walk across it. If it were a house, we would be afraid to enter."
If you want to define what quality software is, you must first use accurate analogies. Software is not like a bridge or a house.
Software is more like a tool. You may have an ax that's not as sharp as you like and it may have splinters. But you still use it because its nearly impossible to cut down a tree using your teeth.
TFA states software developers "get away" with poor implementations because poor design is hidden, but architects can't "get away" with poor implementations because bridges and houses are visible. This is not entirely true because end-users do notice bugs and poorly designed interfaces. The reason software developers "get away" with poor implementations is because it still acts as a useful tool.
Remember, house foundations are also hidden, but architects do not "get away" with building poor foundations. A basic need of a house is to weather storms and not kill its inhabitants. When most software crashes, it usually does not kill the person who used it.
The basic need quality software fulfills is to make work easier. While it would be nice if the software did not have bugs, it is not an essential attribute.
From one of the most respected developer/managers in the business, The Joel Test is a checklist that may help you with your ideas. http://www.joelonsoftware.com/articles/fog0000000043.html
Keep it simple, stupid.
That along with some comments and a clear writing style to include readable indentation levels, consistency of style, reasonably descriptive variable names, data structure fields, or object member names...
And as much as you might try to write a "beautiful algorithm," some of the best ones are simpler, have less feature creep, and can be used along with other simplistic ones that will achieve the same results.
OCO is Loco
or CiteSeer. Man, that site is useful. Nothing like a bit of "reference surfing" from paper to paper to get a feel of an unfamiliar topic.
I would say that in many cases the answer to your question depends on the purpose of the software in question.
:-)
:-)
/JS
Common for most (i don't know about "all") succesfull software products is the fact that they are implemented using one or more Software Design Patterns. For instance you will find that Model-View-Controller (MVC) is extremely widespread in administrative software and similar database-driven applications, while it is probably not really usable in many other types of software (like graphics editors or a spreadsheet app).
But I would say that "Uses an established Design Pattern" is one aspect you need to include.
Another aspect might be the method in which the actual programming is planned and controlled during implementation. A documented and proved method for the implementation, such as Unified Process (UP) or similar, may be something you could consider adding to your answer.
- Jesper
P.S. Please forgive me for adding Wiki-links. Having a PhD in Computer Science I am sure none of this is new to you. They are mostly provided for other readers
My security clearance is so high I have to kill myself if I remember I have it...
by "performance issues", I mean computer hardware speed, not people productivity.
Table-ized A.I.
seriously!
Okay since its your PhD thesis you should aim high. Try to come up with a new metaphor. The tired, oft-wrong, and certainly too-broad-to-have-any-real-value metaphor of the "building" or "house" as software needs to be retired. I don't really know many professional software engineers who also design skyscrapers, but I know that my architect friends aren't using software engineering terminology, such as, "no code dup" to reason about how many doors we might want to stick on their new projects.
The metaphor should be helpful. It should make us believe that the same principle which governs one domain is applicable in another domain where reasoning is often more difficult. The metaphor breaks down however when we try so hard to "fit" it to the second domain.
I am saying that the parts of the building metaphor which fit -- we get (that doesn't mean we design correctly). Its the parts that don't really fit that are interesting. This might be were software design is somehow different than building design.
and a general solution is going to be difficult.
I assume you're read the Mythical Man-Month (at least as a start) and realize the 4 types of software project/products out there. Some of the answers people have given you are solutions depending on the type of software project.
Generally though, good software faithfully implements the model it is designed under, with the limitation of the model being known and accepted by all the principles involved.
Furthermore, the code is sufficiently engineered to allow for changes demanded by the customer in a timely manner (ie: upkeep, bugs, etc).
HAving not long been on a large dev project(multi user, networked _ control of external hardware) doing exactly what you have mentioned made the project smoother and reduced problems during code merges(multiple devs) and integration testing.
The only time specialist types were used was when absolutely required.
Read the DO-178B document.
Before you even start any software design, nail down the requirements of the project. This is critical. How can you, or anyone else, design software when it hasn't been established what that software is supposed to do?
Work out how the mathematics of software development works.
Deleted
xxxx:0100 NOP
You've heard the saying, "garbage in garbage out", right? Modularity is important from a code perspective, and obviously simplicity and scalability matter. However, it all dials back to the design principles that drove the solution in the first place.
Many software design projects are driven by a core set of requirements developed by a small collection of SMEs or business stakeholders with a supposition about their client or target users but little in the way of hard data. From this ungrounded starting point bad projects just start spiraling; developers inevitably go in 50 directions due to conflicting requirements and a lack of any cohesive "strategic vision", their solution is further undermined when the same business users invariable "tweak" and redesign aspects of the app on the fly, and are even further undermined when parts of the app are wholesale redeveloped due to user dissatisfaction.
In contrast, UCD basically advocates allowing user needs, tasks, routines, and missions to drive application design. You conduct detailed research and investigation up front to determine the competitive landscape, business priorities, and user context and goals, you marry these into a collection of critical directives and capabilities matrix, and you then develop a comprehensive design that supports this from an application perspective. Because you defined and designed the application from the perspective of user need you are much closer to providing exactly what is required, but you are also better able to dial extensibility into the application both from a feature perspective and an architecture perspective. THIS means that you've accounted for all those changes and modifications users will expect, which means that it is far more likely the developers will be able to build out the application in a logical, modular, and scalable way that requires less churn, less rewrite, and less compromises.
Anyway, that's my perspective as a design lead whose worked on a lot of different engagements ranging from knowledge mananagement systems to rich applications, etc. Like anything else, if you take the time to build a sensible framework it will generally go better than if you fly by the seat of your pants. The issue is that this framework pushes all the way to requirements, not just within the development thread, and you need to think about the different project phases as a continuous and inter-dependant thread.
-rt
For your insightful contribution to Slashdot, I dub thee Doctor of Philosophy in the field of computer science, for the thesis "Good Software Design Principles", and award you all the rights and privileges due thereunto. Rise, Doctor Kevin Conaway.
sed -e 's/Chuck Norris/Rajnikant/g' joke > fact
Someone (or some group) understands the software.
Anyone (or any group) that is knowledgable enough can learn to understand the software.
What makes anything easier to understand? Good teachers/documentation, good organization, and good semantics (in this case, the correspondence between the components of the software and the components of the task domain).
Kudos to the editors for posting this (apparently) un-edited. I got a chuckle out of it.
"Dudes! I totally need to graduate. Write my thesis for me!"
Please identify essential design principles common to all of the following items:
Nuclear Reactor
Airplane
Baseball Bat
Lawn chair
Stumped? Thats because there aren't any.
The idea that there are one-size-fits-all design principles is fundamentally flawed. There are design principles that lead to maintainable software, and ones that aid in developing extremely complex software, and ones that minimize initial development cost, and ones that encourage faster understanding of the problem domain, and ones that improve execution speed, or memory footprint, etc. If you try to use all of them at the same time, you product will be a mess.
So, fundamental principles:
1) Understand the problem you are trying to solve.
2) Use the best tools for solving that particular problem.
between modules and high intra module cohesion: http://en.wikipedia.org/wiki/Coupling_(computer_science)
Just be sure to add your Slashdot research to your .bib file:
@MISC{Slashdot:2008,
AUTHOR = "Level 70 Opinionated Geeks",
TITLE = "Musings on Software Design Principles",
HOWPUBLISHED = "Randomly Moderated Posts",
MONTH = "June",
YEAR = "2008",
NOTE = "Results from Ask Slashdot when I was too lethargic to look up CS articles online",
}
One of the most useful principles I've found for making "good" software is to design very clean, very powerful interfaces. Focusing on "modularity" often puts the focus in the wrong spot, namely on the center of the module. The point is that the details there *shouldn't matter* because you can abstract away all sorts of fiddly detailed functionality.
It is difficult to make clean and powerful interfaces, however. You really have to understand the nature of the problem you're trying to solve in order to pick the most natural groups of functionality. Very often, if you're trying to get something done in a reasonable amount of time and don't need to maintain the code for that long (though beware--you'll find yourself using, a decade later, programs that you thought you'd rewrite "next month"), it's better to code something quick and specific.
The cleanliness of an interface basically boils down to how little information you can pass to it, and how little information you need from it, in order for it to do what you want; and to what extent all information and data goes through explicitly defined interface elements (e.g. an interface in Java). (Here I'm drawing a distinction between data, e.g. the content of a character stream, and information, which is "hey, there's a character stream here, go work on it".)
The power of an interface basically boils down to how many different high-level operations can be constructed from mixing and matching components of the interface. For example, compositing operations tend to be powerful (e.g. take A, take B of the same type, perform some operation to produce C of the same type from A and B).
There are lots of other generally useful strategies, but I find this one of the most overlooked, especially by otherwise really talented coders (who can tend to make interfaces more complex because they are talented enough to work with something that complicated).
Object Oriented Design Principles have been distilled and are known by 3 letter codes (OCP = Open Closed Principle, LSP = Liskov Substitution Principle). Google that. The best book I know of on this subject is "Object Oriented Software Construction" by Bertrand Meyer.
try googling jakob nielsen's work.
one link: http://www.useit.com/papers/heuristic/heuristic_list.html
or, just http://www.useit.com/jakob
as nothing works unless you can use it.
---- Teach Peace. It's Cheaper Than War.
I thought one of the criteria for gaining a doctorate was that your thesis make a novel contribution to the field of human knowledge.
Not, for instance, simply listing a load of things thought up by others and playing compare and contrast.
Or am I just being old fashioned?
Why would a PhD student solicit for information on a social website? Shouldn't you be doing the research yourself??
I don't think you should be asking for help for your PhD on the internet. I sincerely hope your professors are cool with this, are you may be in for a nasty surprise.
There are tons of books written on the subject.
That being said, I think prototyping is best...
Rapid
Application
Development
Now go buy or read some books, before your professors discover what your doing out here...
I sure hope you have better focus than "good design principles" for your thesis. Seems a vacuous subject as "good business management principles".
Fuck systemd. Fuck Redhat. Fuck Soylent, too. Wait, scratch the last one.
Easy. Start by reviewing the state-of-the-art in Software Design. A quick search on ACM's Digital Library can yield interesting results.Try looking particularly to the proceedings of the OOPSLA and ESEC/FSE conferences. Furthermore, don't forget to check SIGSOFT's Website for other conferences in the area.
And, last but not least, read seminal papers on the topic, check references/citations. It'll probably take you one entire year to have the feeling about the entire (relevant) state-of-the-art in your PhD topic. Trust me, it took me that long too. But it's worth it.
var sig = function() { sig(); }
Check out Lakos, "Large Scale C++ Design".
Good design is "Process Improvement." If the application is successful, users will naturally accept it as their preferred work method. Too often, software is designed such that it is more cumbersome to the user than the legacy process it was intended to replace.
Now now, any serious PhD student in software engineering automatically knows the answer is "It depends...", especially if you've studied with Jim Collofello...
...But I digress (sorry bad class project experience last semester)...Point is, it's an exciting time to be looking at software because most of the academic research up to this point has been focused on DoD projects with more archaic system architectures and development methodologies. Try looking at some of the emerging paradigms/technologies and seeing what jumps out at you.
If you're looking specifically at Design and architecture you might want to check out Design Patterns by the Gang of Four...if you're looking for general concepts, Pressman is a good friend to go back to (you'll probably appreciate the book more now than in undergrad software engineering classes)
If you're mainly trolling for research ideas, I've got one for you (since my own research seems to be taking me in a different direction): namely what's the major role that Software Configuration and Project Management play in determining quality Open Source Software?
For example: Web Content Management Systems are a new and burgeoning area of development. Architectures such as WordPress, Joomla, and Drupal offer "easy, modifiable solutions" to the challenge of creating dynamic websites.
Drupal in particular features a framework of hooks (non-object oriented, written in PHP) and a completely open documentation and development policy...
This means that any Tom and Jane who know *nothing* about software development or how to write a for-loop can develop "Yet Another RSS Module" and contribute it directly to the project homepage (or write a help doc!), leading anyone who *actually knows what they're doing* to SPEND HOURS digging through poorly documented (or in some cases just suboptimal/just plain incorrect) and poorly implemented piles of crud that offer nothing close to the concepts of Polymorphism, Inheritance, or a Unified programming model to work with, and yet by most accounts it is a successful and powerful piece of software...! (>o)
What makes for good general design? Here are some general bits.
Localization of information--minimize the scope of all identifiers: localize variables, minimize coupling of subroutines.
Descriptiveness or understandability--name identifiers in an intuitive manner, provide comments that explain the purpose of each section of code as well as any tricky constructs.
Defensiveness or robustness--each piece of a design assumes it will be misused and handles misuse gracefully.
Well defined interfaces--each design item has a clearly defined purpose, input and output ranges, pre-conditions and post-conditions, and error states.
Peer review--each bit of design is inspected per some criteria as well as their personal expertise.
I am sure there are more of these...just off the top of my head.
All these papers can be found online, if your library gives you access to IEEE and ACM pubs. These are the classic papers so you might might see who cites these papers (Google Scholar) to get more recent refs.
Parnas discusses modularity:
[Par72] D. L. Parnas, "On the Criteria to be Used in Decomposing Systems into Modules", CACM: 15:12 1972.
Another good read for a critique of software engineering (but not what you are looking for):
[Par85] Parnas, D. "Software Aspects of Strategic Defense Systems." Communications of the ACM, 28(12), 326-335, 1985.
Boem is the person you want to read though:
B. W. Boem, J. R. Brown and M. Lipow, âoeQuantitative Evaluation of Software Quality.â Proceedings of the 2nd international conference on Software engineering, 1976.
B. W. Boehm, "Software Engineering," IEEE Trans Computers, Dec. 1976, pp. 1226-1241.
B. W. Boehm, âoeSoftware Engineering â" As It Is.â Proceedings of the 4th international conference on Software engineering, 1979.
Hope that helps. Email me if you can't find the papers.
This doesn't sound like a grad student that I would like to have in my department. This sounds like a high school or undergraduate project.
I read a book about that years ago. I wish I could provide you the name of the book, but I can't remember it any longer. It had five principles of which I still remember only two. They were stated "module strength should be as great as possible" and "module coupling should be as low as possible." Great module strength is achieved when a module only does one thing. For example, you shouldn't have a flag where the module extracts the square root for one value of the flag and returns the absolute value for another. Low module coupling is achieved when all the variables that the module references and all variables that the module modifies are passed through the argument list. Sorry about losing the other three.
-Loyal
I aim to misbehave.
Any of line code that is written can fail; any line of code that is not written will never need to be debugged, documented, examined, nor will it ever crash.
Based on that principle, the ideal program consists of the minimum number of lines of code that leads to the desired result. In many situations you will find that you cannot get away with having zero lines of code; in the lines that _are_ necessary, strive for maximum clarity above all else. Always ruthlessly cut everything that does not need to be there.
Try to make the code as boring as you possibly can; always strive to use the same patterns for everything where possible and appropriate. Seeing an alternative implementation then automatically becomes a flag, warning about potential mistakes and unusual circumstances.
_Do not_ maximize comment density. Whenever you _should_ write a comment, consider if you can use variable or function naming to achieve the same effect.
Don't use variables; only use constants (i.e. prefix declarations where possible with 'const'). Minimize their scope. You will find that only a very small number of the things that you think of as "variables" today are in fact variable.
Make your code checkable by the compiler as much as you can. This is not the same as turning on all warnings, and then peppering the code with workarounds for nonsensical warnings. It is ok to turn off silly warnings, such as 4800, 4100, or 4786 in Visual C++.
I could write another ten pages, but this should get you started. For the record, my credentials mostly include C++ software used to control and test spacecraft. Software failures can in principle lead to "loss of item under test", with associated astronomical price tag. So I have some appreciation for good code.
There is plenty of good material posted here...I would say you probably need to take a step back. What are the metrics you want to use? Are they relevant? Why - or why not? What are the strengths and weaknesses of each? That is probably a PhD thesis in its own right. I would argue that this is largely defined by the domain in which you are working. In the case of my doctorate (in industrial automation), I decided that code was largely irrelevant - and what was of most importance was the process. Conversely, another member of the research group chose to look at the same codes - but by applying a series of standard software engineering metrics. It doesn't matter which way you go, provided you have justification for your approach. Off course you need to do better than reference an open forum on slashdot ;-)
There's an article in the forthcoming articles in the IEEE Transactions on Automation Science and Engineering which might give you more detail on what I'm getting at...
Mail-order Ph.D FTW!
Real engineers watch Futurama.... South Park and the Simpsons is for programmers and QA testings....
Muhahahah
Once you know what those techniques were, and the way things are done today (that require 10 times the resources to do a fraction as much), you'd have a fairly decent baseline I'd think.
The short answer is: Python.
If brevity is the soul of wit, then how does one explain Twitter?
To go even further on this path, abstraction and frameworks have improved my code quality and reduced my time to production.
Abstracting code as much as appropriate allows you to reuse a significant portion of your code base. And with designing a framework for your applications that utilize that abstracted functionality to allow for a modular design of the actual business logic will greatly improve almost all projects.
The business layer should have no idea what the database is or how it works.
The presentation layer should have no idea what the business layer is doing or how it works.
We really pushed these principals on a project I worked on a few years ago. We had a reporting system that had to access 3 different databases, 2 3rd-party systems, and interface with business rules over 4 different departments and employees/sales in 3 different states. We created a custom data access layer that handled all of the data-related functionality for us. So in the business layer code, we never had to care about the data source, we had objects that represented the data in memory that all inherited from the same base data object/collection. Each specific report or functionality was based on one of 4 specialized frameworks that handled Crystal Reports, Office automation, work flow, and HTML generation. Each of the frameworks was based off of an even more basic type that handled the underlying multi-threading and work flow of the process. And all of that functionality was designed to be abstracted from the user interface so that we could build a Windows based interface to start with, and as the 3rd party apps gained more flexibility we could directly call our application's business logic and work flow from the other applications.
Anyway, one of the first projects I look at when stepping into a new project or job is to get the abstraction and design cleaned up. There is no sense beating on business logic when the underlying technology is going to cause you more headaches and piss off your users. And once you get that technology straightened out, you can focus on business logic and get the users a product that not only meets their needs, but also meets your needs in support and maintenance requirements.
-Rick
"Most people in the U.S. wouldn't know they live in a tyrannical state if it walked up and grabbed their junk." - MyFirs
>"I am working on a PhD [...]
Why would you want to be a doctor when you could be a MASTER?
Sean
It's kinda in that link, but I cannot stress enough organizing the code files themselves. Unless you have a very tiny project, you probably have bunches of stuff like the main application, some GUI work, support functions, classes/libraries, different architectures, translations, documentation, meta-documentation, build files, configuration...
.bat files, perl, and normal make, and the resulting executable is a mess of UPX'ed 7-zipped SFX with the 7z stub UPX'ed and that just gets you to the NSIS setup.exe installer. What a disaster it is! And not organized!
I know you're not (necessarily) talking about open-source, but it's easy to pick on. There is nothing worse in open-source than downloading a promising application's source code and having hundreds of files in the root folder with no obvious organization, and having to do a full text search on "main" to see where the ignition key is.
You may not release your code to the public, but think of the poor guy/gal who replaces the guy who just retired/quit. How long will it take him to figure out where everything goes? Taking the perspective of a new user and organizing the files so you can find the entry point, or the platform-independent sections, or the file-format logic. It forces you to think about where things belong, or don't belong, and what to keep private versus exposed.
I would just be belabouring a point if I didn't have my latest example, Firefox. The windows build is buried way at the bottom in a non-intuitive location, and the installer code actually seems to be copied (with different versions of some files, sometimes one folder is newer, sometimes the other) in another location ("moztoolkit" versus "xpinstall"). I honestly can't see the difference or figure out where each is called out or which one actually runs without doing a full-text search on the whole source tree. The installer build itself is in
Lay out your code like you lay out a book - so you can just go to a specific chapter and read the parts you want. If you need to add something, you should be able to find where it goes, and may be surprised to find it already exists. It makes porting, library replacement, task distribution, and many other things a lot easier. If listing just the folder names doesn't add any clarity or value, you probably need t reorganize.
100,000 monkeys and a IBM PC-AT keyboard.
Here's one idea:
http://michaelfeathers.typepad.com/michael_feathers_blog/2008/06/the-flawed-theo.html
Personally I think good software is a result of re-using what works in the form of libraries or design patterns, keeping things as simple as possible, and utilizing developer experience and judgement.
There's somebody who got into the Ph.D. program at Tufts, who can ask such questions?
Dude, write your own dissertation.
Oh, and by the way: Parent was posted using Firefox 3.
:-D
:-)
Get it NOW and join the attempt to set a new official world record in software downloads
http://www.spreadfirefox.com/
And before you go marking this post as "offtopic", perhaps we could suggest that "number of downloads" could be added to the answer? A high number of downloads could very well (but not always) be a sign of good software quality - at the very least from an end-user perspective.
- Jesper
My security clearance is so high I have to kill myself if I remember I have it...
It would be interesting to try and quantify code elegance. I forget who said it but there's a saying "code that looks good is good"
I have to disagree. If you factor out the duplication/repetition, the result is rather compact and non-uniform. Repetition of form is what makes code *look* neat, but lots of repetition is generally considered poor form.
Also those big verbose asterisk box banners some developers put in their code to make it look "professional" just waste space. A lot of that info should be in the source code tracker or is redundant in one way or another.
Table-ized A.I.
is quite simple, actually.
First, if it's not invented here, then it's crap.
Second, I'm the only one I trust to write it correctly.
Third, I work alone, and I don't write comments - see number two.
If you do what you always did, you get what you always got.
Without specifying the scenario, the answers to this question is pointless.
If you have a bunch of professionals working together, their ability to follow processes and perform will be different than if you are managing a bunch of monkeys. If all your programmers only speak Japanese, giving them a bunch programming principles written in English is not going to help. If your programming team is full of people who have been programming in Java for their entire careers in enterprise applications, then toss them into a low-level hard real-time embedded system C-only programming environment, it's going to be interesting. People apply their own perceptions and prejudices (and blind-spots) when following software design principles (or when they *think* they are following principles.)
If the only common language your programming team knows between all of them is BASIC, your application is going to end up in BASIC. If all your programmers are OO folks, your application is going to be built OO. etc. If you have a mixed team of local programming teams in different product groups in a company with different priorities vis-a-vis the project, some contractors, stuff out-sourced to a group in Asia, etc. etc. etc. Theory in software design principles can take a flying leap. Each situation is different and the importance of the skills and experience of the people involved can trump the technology or design principles.
If your vaunted software design theory ends up pounding square people into round software princple holes, things can go amazingly badly. This does not mean that the software design principle is bad. It does not mean that people are bad. It means that the design principles are not being applied properly. A herd of cats is managed and is better at different things than a pack of dogs. If you are trying to manage a group of distributed developers who are more varied than zoo, then software design principles take second stage to management principles. First, you need to figure out roughly what each group is good at, and then you can apply the proper design strategy/development principles to each groups.
This sort of theorizing is only valid in the laboratory or for small target groups in reasonably controlled circumstances. The personnel and personality issues (internal team conflicts, design blind-spots, personnel turn-over, etc.) and outside influences (changing target market/customer requirements, abrupt budget cuts, scheduling changes, etc.) tend to trump design principles in practice. In order to make such design principles work in practice, it takes a combination of constraining the domains being worked on and resources to create a (mostly) controlled environment in which to apply the principles. Few design principles can cope with situations where the outside world (or internal personality issues) are allowed free reign to interfere with the development.
So, first posit a controlled situation and specify your group of developers, and then maybe you could come up with principles that apply. Sometimes, principles that apply to one situation don't actually work in another. (Generally, for instance, commenting the code is a good idea, for instance, but the person writing the comments needs to be able to write *good* comments. If the person doing the commenting is only putting in unimportant stuff, or not aware of what they ought to be documenting, then they product crappy comments. If the person who is then going to be dealing with the comments is not experienced enough to tell good information from bad, this situation can be harmful because it creates the illusion of understanding. So, do you have a team where most of the people are inexperienced? If so, then the group design/management/development principles may need to be organized so that the experienced people are in the path to check on the work of the inexperienced, and you don't have the inexperienced people cross-checking their own code without a sanity check.)
Epigrams on Programming by Turing-award laureate Alan Perlis.
EOM
Here are a couple of starting points for a citation search. You are going to get a lot of stuff but if you are doing a PhD you should be prepared to read a lot of papers, and reading them in historical order for a evolving subject like this is probably as good an approach as any - at least if you hope to produce any original ideas, which ought to be a goal of a Doctoral Candidate.
"Goto Considered Harmful" by Edsger Dijkstra. (You probably want to discard about a million ensuing (X considered Y) papers from Sigplan immediately)
You might also see what comes up for "Sale AHJ. 'Proposal for extension to Pascal', SIGPLAN Notices, 16, 4, 98-103. " - it might be more focussed.
Another interesting starting point would be anything by C.A.R Hoare and the papers on Majester Stacks. You should also look at the works of Niklaus Wirth.
The beginning point for object oriented programming was Simula-67 so references to the original paper on that are another path forward. Ada is another language that was designed with programming methods in mind.
For applicative (functional) styles, start with Lisp and FP (Floyd Productions I think it stands for) and "Applicative Programming". Two other names to look for are Church and Rosser.
A lot of language design (but not C++) has been closely tied to ideas about what constitutes "good" programming and the two subjects were closely linked for a long time.
Squirrel!
I believe during the cold war the DoD wasted a ton of money on shoveling ADA on people. This was to prevent the superior mathmeticians and other russian "ivan geeks" from having a chance to continue dominating the field with clean terse code and innovative resource stretching algorithms.
...I've been feeling nostalgiac lately.
If you really look at it hard, why is it every program seems to grow by 5 or 10 or 50 megs for every revision?
Bloatware is a concept that defines modern programming. Because hardware changes so rapidly, and people find enhanced job security in being able to show off something "new" they tend to keep upsizing their code.
Really though, I've seen some interesting hacks where people were watching divx in 4 color on 8086 machines using assembly and higher level languages.
A move away from object oriented programming actually could help refocus the field...I mean come on, what WOULD happen exactly if you could update the drivers to windows 3.1's basic graphics/sound/and io bus....It would scream...I mean the entire win 3.1 install was what? 4-6 1.44 meg floppies?
of course
Now, if Slashdot is his ONLY source, it's a different story. But I find that rather unlikely. This seems like a pretty good shot in the dark that might yield some interesting leads that he can research further.
Maybe it's just me, but exploring a wide variety of sources seems like GOOD research rather than poor.
8 of 13 people found this answer helpful. Did you?
Horns are really just a broken halo.
The only way you get software with few bugs that is easy to maintain is if you are developing simple software against known requirements. Unfortunately, almost all the interesting commercial software has unknown software requirements.
In embedded systems, which often have simple programs, the enemy is unforeseen conditions. What happens to this system in actual use? If the system is always doing the same thing, then the software may have lots of "software engineering" bugs, but in practice has a very low bug count. Alternatively, the inputs could be relatively unknown, things could be constantly changing, and lots of practical problems (bugs) will happen. Bottom line: the real world makes it impossible to predict the environment that embedded software will execute in. This causes lots of problems for an embedded application.
Leaving the embedded world, you have programs that interact with people. Getting accurate requirements information on them is next to impossible. How are you supposed to write a "bug-free, maintainable, modifiable, and scalable program" when you don't actually know what the program is supposed to do? Many people related applications involve user-interface design, requirements analysis and business processes. Software engineers gradually learn about the intended application through a process of iterative improvement. The constant iterations cause the complexities in software that drive bugs, make code difficult to maintain, create endless modifications, and add scalability as a last minute requirement.
About the only category of program that is easy to get bug-free is something that is designed to interact with another program, or a program that takes very defined inputs and has very defined outputs. Compilers are often in this category. Even with compilers, there are complexities. Theoretically, you can formally prove a complier correct. In practice, I am just not sure that once software programs become large (like gcc), that it can be proven correct and optimal Formal methods can get stuck on rather complex proofs. For instance, given an idealized computer, one might hope to prove a C compiler generates code as intended. However, this would be an idealized compiler generating code for an idealized computer architecture.
In the real world, the IA-32 computer architecture is a mess. Intel doesn't even know how all possible instruction sequences should execute. To help solve the problem, Intel created a software model of their own microprocessor, and this model became the Intel internal standard. Intel has not released this model to the general public. Further, if Intel did release it, the formal methods people would likely find obscure bug cases that also exist in silicon. Thus even something obvious like proving a compiler generates correct code, becomes a very difficult when one realizes that the real-world lacks proper mathematical definitions.
Real-life contains much grey. The greyness drives the software problems.
What design/architecture qualities are shared by all good software?
Honesty, clarity, thoroughness.
Do what needs to be done.
Bad software cuts corners on those, and suffers accordingly.
Sounds stupidly simple, but that's really all it is.
Can we get a "-1 Wrong" moderation option?
Then move onto the metaphysics of quality.
From there the rest is easy.
I'm continuously amazed at the quality of educator that schools hire nowadays.
Then again, we all know where those who can't "do" end up...
Componentization is a time-honored tradition in the hardware industry where it has been a huge success for decades. Componentization is the key to reusability. It is based on plug compatibility and makes drag-and-drop software construction possible, thereby openning programming to the masses. The reason that the same has not happened in the software world is that software is inherently sequential whereas hardware is parallel and signal-based. We need to go beyond the Turing ideal of sequential computing and adopt a computing model that is inherently parallel and signal-based. For more info on this topic see Why Software Is Bad and What We Can Do to Fix It. See also Parallel Computing: The End of the Turing Madness, although I would not recommend the latter to Turing worshippers as they might take offence.
Can someone please cite me a DOD software project that doesn't suck? Please? Because I was an air force comm officer for 4 years, and now I'm a Systems Engineering contractor, and I shudder if fear every time I find out I'm going to have to work with a GOTS product. Seriously...these morons couldn't figure out how to update the mouse driver include in GDSS2, saying that it was going to cost them half a million and two spirals to make mouse scroll work on their windows client.
Or have you only comfort...that stealthy thing that enters the house and guest then becomes host, then master - KG
Care to site any studies supporting these claims that design patterns such as MVC and UP objectively improve the quality of software produced by a given number of people in a given amount of time? If not, your opinion, despite your merits, remains only that - otherwise how could we call ourselves scientists?
Do some statistical analysis of software projects as part of your research. Here is one way is has been done:
http://www.enerjy.com/papers.html
The key to a good software project is the ability to apply several different design principles in the most efficient manner. You want to have a clean code-base that manages memory in the most efficient way. For example, a Singleton Constructor would be ideal for a database connection to prevent accidentally opening multiple database connections and causing things like memory leaks, while things like Interface elements would probably want to be created from a base Factory class, allowing for minimal customizations to describe UI elements. . Also, keep your class interfaces as loosely-coupled as possible. That is, keep only a bare minimum of properties and methods of one class visible to outside classes. When coding, a class or function should never know or rely on the internal workings of another class. . So, good software design principles come down to a good hacker knowing the most efficient method to accomplish his/her goal.
As a Comp Sci PH.D. student myself, This seems like a really weird way of doing research. Are you going to cite slashdot? I'd love to see that.
can be applied broadly with great success. See: The Art of Unix Programming by Eric Steven Raymond http://www.catb.org/esr/writings/taoup/html/ch01s06.html
Clear Unambiguous Testable Requirements.
Good software is written for people to read and only incidentally for computers to execute.
Karl O. Pinc
This is the foundation for your doctoral thesis?
This is the answer you need:
Close your books, withdraw from the program, thank your academic advisers, but politely inform them that you are too stupid to be pursuing a PhD.
http://steve-yegge.blogspot.com/2008/05/dynamic-languages-strike-back.html
Good management is the biggest factor in any project, not just software. The management must:
... I think a lot of their problem is they had too much money, not too little. The sales staff kept thinking up new products and selling them without asking engineering if they could even make them, much less by the deliver date they promised to the customer.
A. Know what they want and how to measure it.
B. Know how to hire staff they trust and stand behind them.
C. Listen more than talk.
D. Be decisive when needed.
E. Provide adequate resources.
F. Encourage the staff to tell the truth and be willing to hear it.
I've been doing engineering projects for thirty years; both hardware, firmware and software. I've worked on a few projects that were well managed. They all succeeded and were fun. I've worked on many more projects that were managed okay or badly. These did not fare as well and were not much fun.
In one company the president threatened the programmers with a baseball bat and knocked a hole in a cubicle wall with it. In another incident at the same company the chief engineer threatened to get his cattle prod out of his truck (this is in Texas) and use it on some of the staff.
Thankfully that company went out of business. Funny thing though
I only did a quick look down the replies, so sorry if someone has already mentioned this. But it sounds like you're talking about "Design Patterns". Wikipedia has a post on it and if you Google it you'll get something on the order of 9 million hits. That should get you started anyway.
I'm not sure such a thing as "beautiful code" or "good software" really exists outside of a context (referencing the article the OP posted). It's like saying "tell me about beautiful woodwork". If I'm framing a house, then "beautiful woodwork" is straight studs and solid fasteners. If I'm talking about fine furniture then "beautiful woodwork" is mahogany wood crafted slowly and carefully, usually by hand, and usually by a skilled master. If I'm talking about a dog house, then "beautiful woodwork" is any structure that Fido won't quickly destroy that keeps him cool in the summer and warm in the winter, and has half way straight corners and edges.
So, the "beauty" or "goodness" of woodworking depends totally on the context. The form / function dichotomy has to be considered when discussing software quality. Is it "beautiful" to build a 3 story dog house with a flat screen TV, toilet, bunk bed, and working plumbing? Probably not (more like excessively extravagant). Is it beautiful to build fine furniture out of MDF with robot labor? It might be fast, and maybe inexpensive, but it's probably not beautiful. So, to some extent I actually disagree with the idea that there are generic principles for beauty in software design, unless you define "beauty" to include some means of establishing context.
To a large extent that's why we tolerate so-called "bad code". When a house is designed and built, the consequences of poor design or building choices are often obvious (to those skilled in building trades) and often dangerous. If I have walls that cannot handle the load of my roof, the roof sags and might collapse and kill someone. Software is rarely in such an important role... and software that is in that role is usually HEAVILY tested at great expense, and changed very rarely with additional expensive testing. So, generically speaking, the context (in which most software runs) defines "beauty" as including two major drivers: cost and delivery date. If a copy of Windows Vista cost $17,999, came out in 2015, but never had any problems because every single line of code had been reviewed three times by skilled craftspeople, and all rough edges were worked through to completion, would anybody care? Would anybody buy it? Probably not. They'd use whatever Linux had evolved into because it was free, was at least reasonably stable, and had surpassed the functionality of "Windows Vista 2015" back in 2008.
Over time, core concepts (how to frame a house, how to build a fine quality musical instrument, how to write a kernel) begin to coalesce into a standard way of doing things, where further refinements provide little or no marginal improvement, and begin to be considered detrimental. I would argue that software design simply hasn't been around long enough for that to happen, whereas building construction certainly has. However, certain "saints" of data processing exist out there to help point us in some directions: Knuth, Von Neumann, Turing, Torvalds (couldn't resist)... by studying the writings and code of these folks, we can begin to see areas where things are coalescing or have already coalesced.
Finally, there's the instability of the platforms themselves that contributes to code "ugliness". Windows and Linux (as we know them today anyway) didn't really exist 20 years ago. Can you imagine what municiple building codes would look like if things like concrete slab construction had been invented only 20 years ago?
So, coupled with the "context" problem, the "coalescing" problem, and the general state of operating system platforms themselves, I'm not sure such a thing exists (yet) as "beautiful code." Things are all still in a state of relative chaos, and cost is likely to remain king in most software design for a long time.
needs it's own methods.
The most basic techniques would be using small readable chunks of code, as well as getting sign of of the features.
BUt good comes in many forms.
I oeice of crappy code that gets the job done now can be far more valuable to an organization then spending 8 months laying out every possible scenerio. SO to the organization the get it down now is 'good'.
Water fall methodoligy a poor one that fails in practicality most of the time.
This is because managment wnats to push an application out the door the moment they hear the code has been written, even thought here should be several more runs and refinements.
Using a method that you completly design up front is likely to go out with fewer bugs because they have been worked through, so when managemnt pushed to go out before proper QA, your odds of success are highr.
If tyou want ONE(1) common reason for all good software, it would ahve to be disciplen.
The fact that you consider Agile or OO not good examples of methodologies makes me thing you aren't qualified to be doing this.
For the record, Agile and OO aren't for the same thing. You can do Agile with OO.
Are you sure you should be doing this?
The Kruger Dunning explains most post on
Forget software. Are there principles to good architecture? Please don't answer the question in terms of bamboo, wood, steel, straw or bricks. Name the principles that apply to all buildings, everywhere, in any climate, for any use.
Now, for those with deep software-crafting experience: Is architecture even an accurate metaphor here? Code is, after all, something you write. Yet are there principles to good poetry architecture? Maybe you like iambic pentameter; yet plenty of excellent poetry has no meter at all. Should we ask how good an architect James Joyce was?
Or are we in a "writing about music is like dancing about architecture" zone? Is architecture a completely different art, with not much to suggest to coders, even metaphorically?
Would agriculture be a better metaphoric soil? Do we grow good code? How about hunting? How does one shoot for the perfect algorithm? The principles of the best software creation may be quite different from what the architectural metaphor suggests. Even so, some architects believe form should follow function. Yet if we try to program in an "architecturally" correct way, we're expecting function to follow form. That's sort of a Turing machine thing: that some form should be universal, capable of all functions. Even so, are the best programs all general purpose machines? Hardly.
"with their freedom lost all virtue lose" - Milton
Here is an a good graduate studies problem:
Pit several software teams against each other.
Instruct one team to use one set of methods.
Instruct another team to use another set of methods.
Each team is given a time budget.
Give them each a unit test framework.
Their project is not complete until it passes.
Now, change requirements, and do it all over again,
several times.
the method showing consistently lower overall cost
might be considered "better" than others with
higer costs.
The best design principle is that you should code for re-use and never forget to code for the failure paths. You can't call software "working" unless it can deal correctly with failure conditions.
Coding for reuse generally means that one should be able to use a piece of software without understanding its internals (it's a black box). That requires good documentation, a clean and clear interface and clean understanding how it should be integrated.
To be honest, your question is wrong. Commercial code too often lacks experienced engineers that understand that design, information analysis and architecture is the most important step in the process (and not coding the project). So good code is derived from those projects that were granted sufficient time for design, evaluation and architecture, done in such a way that it has been given the right foundation for evolution.
In my experience, most software is 95% glue and 5% wood. (i.e. 95% interfaces, and 5% algorithms). So suggestions such as modularity, encapsulation, information hiding, class hierarchies and so on are useful, as they serve to help us with the glue.
Good luck with your thesis. You might get more use from others if you ask them, not for solutions to your problem, but rather as for a characterization of the class of problems associated with software design itself.
I totally understand. In college (early 90's) I had an Amiga 1200 that could do more than my roomates Mac- with only a fraction of the resources. I think the biggest factor in bloatware is simply the speed with which people want projects done. If it "Just Works" then there is no longer a business reason to go back and make it work better, even if it would make for better code. Even a savings in speed may or may not be worth it, especially if the difference is only a handful of seconds.
If brevity is the soul of wit, then how does one explain Twitter?
Process, testing, documentation... all necessary disciplines, but they only provide a framework to help prevent the writing of bad software. Software is written once, read many times and used many more. Writing good software is about empathy. Empathy for the reader of software. Empathy for the user of software. I'm sorry... software isn't about computers, its about the humans that use them.
"Good software means lacking in bugs, maintainable, modifiable, scalable, etc..."
I disagree with all but the first one.
Software is a tool. A hammer is a tool, too, but we don't expect it to be maintainable, modifiable, or scalable. There are different kinds of hammers for different tasks, just as there are different kinds of software. Yet we do expect a good hammer to be lacking in bugs: a design flaw that makes the hammerhead splinter into jagged shards upon impact would be considered unacceptable.
I would say that Good Software is that which has reliable behavior, and is well suited to its intended task. That's all.
This is a weak thesis, since it does not contain a shred of scientific principle. Where is your hypothesis? I don't see that anything in your text is testable. Asking for opinions on Slashdot is cool and all...but _I_ certainly wouldn't want to go before a dissertation committee armed with only opinions!
All it needs is the tried and trusted combination of
- sufficient time and budget
Without these features you will not get top grade product, no matter what development methodologies you use. If you do have these factors in your favour, the methodology, tools or standards won't matter.politicians are like babies' nappies: they should both be changed regularly and for the same reasons
Having worked in an environment like that for more than a few years, I'll say that it is oppressive. You hardly ever see your code run and have to trust interface testing to prove you did what you were supposed to do. Not very fulfilling.
OTOH, I also worked on the space shuttle flight software for 5 years. I still get joy from watching every landing - knowing my code is controlling both the elevons and nose wheel steering. I'll have that job satisfaction and KNOW that was the code with the least number of bugs of any project I've ever worked on
Oh, for an out of date reference that still applies - http://findarticles.com/p/articles/mi_m0ISJ/is_n1_v33/ai_15103437 employees were empowered to stop the "software assembly line," if quality issues arose. This was completely true when I was there.
Language, environment, or any buzzword from the last 20 years don't make or break a project (although they certainly can be the proverbial straw that breaks the camel's back).
The development team needs to be as small as possible. If it's more than about 10, it needs to have technical leaders who own areas with team(s) under them. A good seasoned architect (or two) should lead the project. You cannot have 3 (or more) co-leads, they will have trouble agreeing and may fracture the project. A hierarchy tends to work best, with clear ownership.
Balance leadership with team experience--plan on the leads doing mostly mentoring if the rest of the team is inexperienced.
There needs to be more effort in the schedule working on testing then on development. If developers write tests, try to have them not own testing their own code.
Integrate often, and set up processes so that it is more work for developers to do "the wrong thing" than the right thing. Examples: make it more work for developers if they check in code which doesn't compile (immediately eject their code, adopt other penalties as you see fit); reduce overhead as much as possible when developers are following the right processes; automate builds and releases.
Reward the testing team for finding bugs. Reward the development team for quickly fixing bugs. Plan on a lot of bugs. Use a bug tracker. Don't let bugs get old.
The most successful teams are usually doing something similar to what the technical leads have done before (so the problem is well understood), following known methods. Limit new major risk areas to 2, maybe 3. (E.g., switching to a new language or platform which no one has experience on would be one new major risk; going from unthreaded to a high-thread-count design would be another; using a new buzzword-compliant tool/strategy would be another; etc.). Try to have realistic fallback plans for at least one risk, or carefully watch any risk without a fallback plan.
The above pretty much are true of any successful engineering group.
1. http://citeseer.ist.psu.edu/
2. If you have an ACM membership:
http://portal.acm.org/portal.cfm
3. If your university gives you access to engineering village:
http://www.engineeringvillage2.org/controller/servlet/Controller
IEEE transactions on software engineering
4. http://csdl2.computer.org/persagen/DLPublication.jsp?pubtype=t&acronym=ts
5. Google:
http://www.google.com/
Beyond this, its upto you to do your own research.
is Humor. You know that someone, most likely not you, will have to read your code at some point. Others have spoken about documentation and readability, but even coders are human. Put a joke or three in there. How long a variable name is in the source code doesn't affect the size or speed of the compiled binary. If you only need that variable once or twice, make it funny. Better yet, tell a short story or quote a movie. Some of my personal examples: When I opened the employee file for a payroll application, I used the filehandle "the.downtrodden.masses." One of my favorites was when I assigned a few variables ahead of time and was able to write (and use) open(the.pod.bay.doors, please.HAL) else print Im.sorry.Dave.I.cant.do.that Contributing to a happy workplace is essential to good code!
On the one hand you take life too seriously, and on the other, you do not take playful existence seriously enough. Seth
Quite right. This page contains links to pages that may of interest.
But wouldn't "PhD research" in Software Design be akin to PhD research in modern art principals? While I am sure you can point out some useful information to the executive set and the novice, I suspect this might never exist in the real world.
Taking the time constraints of most projects coupled with the established "bad manners" of any given development team and their own entrenched "best practices" and design patterns, will your findings make any real impact on practical development?
I would suspect that unless you were given carte blanche and an iron fist to rule with, you would find the vast majority of your ideals flying out the window when put to a real life development cycle.
You have already assumed that there are principles common to all good software and that those that are remain so without the context in which they formed.
Neither should be assumed.
Good code could be like a good novel. Certain characteristics are shared between all good novels: compelling story, strong characters, good flow, and interesting dialogue.
Good code is more like a documentary. Purposeful, segmented for easy understanding, comprehensible to the lay person.
No spaghetti; modular; well commented.
The rest makes the difference between fair, good, and great programmers.
The book How to Design Programs specializes in this topic. It is available for free online, it was written by a programming languages specialist at Northeastern University (a 30 minute T ride from Tufts) and published at MIT (a 15 minute T ride from Tufts).
Yes, it's very academic in nature -- it uses Scheme as its base language (well, a very simplified/gimped Scheme) under the premise that it's not your standard procedural language (so you won't fall into old habits) yet it is easy to pick up and learn the fundamentals of programming rather than the specifics of a useless language (e.g. whatever language-of-the-day is liked by industry).
I'm sure there are several research papers tied to the book, and I'm also sure that Matthias Felleisen (its author, trustee professor at Northeastern University) would be happy to sit down and talk to you about it.
Use my userscript to add story images to Slashdot. There's no going back.
I read an interesting article about how it's impossible to write a max (as in, which of these two values is the maximum) function in C++ that simultaneously satisfies a list of seemingly reasonable requirements. Hell if I can find the dang thing, but it was a good article.
My point is that we write programs to express the way to solve problems, and for even the simplest of problems, there's a lot of debate about the best way to do it.
So, what are the attributes of the best software? It's good enough, it's readable enough, and it's easy enough to modify. (Also, it's fast enough, but too many people worry too much about that one.)
Education is the silver bullet.
You should research software security in the agile setting.
The primary thing missing from today's software is safety, accountability, robustness, and resilience. Modern software is disgustingly weak when it comes to meeting core non-functional requirements.
The agile mindset - deliberately - has no place for non-functional requirements, and in fact often calls them "constraints".
This is exactly like saying the engineers who designed Tacoma Narrows bridge built a successful bridge. Which fell down in moderate winds due to harmonics brought on by winds not unusual for the site. Therefore, designing bridges after then to take into account seismic activity, load, winds and harmonics - truly non-functional elements - are "constraints" !!
Security is not a constraint - it's an enabler that allows secure business. Imagine if the user stories for Amazon went like this:
Allow an anonymous buyer to add an item to their cart (this is true today)
Allow a buyer to checkout their cart by obtaining their address
Ship item(s) to that address
Amazon would be out of business in a matter of hours. A solid security architecture is a fundamental requirement, and in fact, the ONLY requirement shared by ALL applications.
Andrew van der Stock
Read 'Code Complete', by Steve Mcconnell. Then tell your advisor that you just found this great new book (that's been in print for 15 years and happens to be part of most good undergraduate CS programs.) And yes, you should have read it already-- part of getting a PhD is problem solving, and part of that is actually looking up the relevant works in the field _before_ asking your neighbors "hey, how do I do this?" There'a fancy place called a 'library' at most schools that also can come in handy.
And if you answer that "Oh, I've already read it", remember that part of writing a good research question is mentioning the research you've done before, so you lose points for not citing it in your query. So either way, you're one point down. Why are you still reading this, instead of 'Code Complete'? I'm not your advisor, you don't have to listen to my rants! Get back to work! Geeze, students today, they expect everything handed to them. Why, in my day... (voice trails as sleep descends...)
A.
If you are creating software intended to be used by Humans, you need to consider designing interfaces which work well with them. Apple's Apple Human Interface Guidelines remain remarkably unchanged from the first days of the Macintosh. Here is the basic bullet point topic list.
http://developer.apple.com/documentation/UserExperience/Conceptual/AppleHIGuidelines/XHIGHIDesign/chapter_5_section_2.html#//apple_ref/doc/uid/TP30000353-TPXREF130
Metaphors
Reflect the User's Mental Model
Explicit and Implied Actions
Direct Manipulation
User Control
Feedback and Communication
Consistency
WYSIWYG (What You See Is What You Get)
Forgiveness
Perceived Stability
Aesthetic Integrity
Modelessness
Managing Complexity in Your Software
The single, fundamental software design principle that underlies every other one is this: every decision should ideally be implemented in one place, or as close to one place as possible.
That's why good programmers often like terse languages. Terseness often makes things difficult to read, but it makes repetition and dependencies stick out like a sore thumb.
Sometimes the principle is referred to as DRY -- Don't Repeat Yourself, but in fact it's even more fundamental than that. Repeating yourself is lazy, but sometimes you doom yourself to future repetitions before you've begun repeating.
This explains why the initial versions of J2EE were bad. Too much ink was spilled over the amount of configuration and bookkeeping style programming forced on programmers. Some people rightly pointed out that it's really not that much to learn your way around these things, given what J2EE tries to do for you. But the real issue was the way that the decision to use the framework extruded itself into so many places, which was symptomatic of a faulty design. When Spring came along, the people who hated J2EE because of all the configuration took to it, even though Spring requires its own configuration files. The difference was a given decision clearly belonged in one and only one place: in the code or in the deployment configuration. Spring freed you, once more, to concentrate on one problem at a time.
Good design is a pleasure to work with for this reason, because it presents you with well contained problems to solve. Bad design is tedious to work with, because you must adjust your approach to each problem to so many prior "solutions".
Aside from that, I wonder if there is really that much practical value in researching new design principles. There's some value of course, but the worst perpetrator of bad designs is not bad design theories (which do exist), but bad organizations. You'd really need to work with a sociologist or anthropologist to describe why nearly everyone does less good design than they're capable of.
Post may contain irony: discontinue use if experiencing mood swings, nausea or elevated blood pressure.
I don't see much potential for building a good Ph.D. thesis on that kind of fluff piece.
As a practical matter, getting a Ph.D. in software engineering or software design may be a good academic choice. It's a bit like getting a Ph.D. in art history or sociology, in that there there is a wide variety of approaches and no clear right/wrong; and if your math and science is a little weak, it doesn't matter. Unlike art history, with a Ph.D. in software engineering, you will have good employment prospects.
Still, as a Ph.D. choice, that kind of topic never made much sense to me. If your heart is in software development, you're better off just working as a software developer. And if your heart is with academia, then there are better and more interesting academic subjects.
Maintainable code is code that isn't tricky, doesn't use every piece of the language just cause you can, and isn't written to showcase how clever you are. You don't know the skill of the person following you, so keep it straightforward.
"Actually, I enjoyed this in the same vague, horrible way I enjoyed the A-Team" P. Opus
The most important single thing about good code is that the source is easy to understand, because every other thing you do with it (fix bugs, improve performance, add features, add test cases, document it, etc.) hinges on your ability to understand the darn thing and then modify it.
So if I were you, I would rephrase the question as, "What sort of source code is easy or difficult for a human to understand?" This sounds much easier to design experiments around than the more open-ended original question.
You really, really, really have to narrow your question down or the whole thing is transparently a load of BS.
There's good practical advice out there, some on this thread, much more in the books referenced... but extracting advice from uncorrelated sources does not make for a phd or even necessarily anything particularly useful, because some advice applies best in some situations, and other, possibly conflicting advice applies best in other situations.
Here's are some themes of things to avoid..
A good business analyst is worth their weight in gold in a large project. Determining what the relevant requirements are, in a form that both the user community and the programming staff understand is the most important piece of a software project as far as I'm concerned. I've only had a little over 20 years experience but this seems to be the deciding factor for all the projects I've participated in. Not only that but when the BA makes the users sign off on the requirements, you have a reference to go back to when the users try to claim that something wasn't coded the way they wanted it. It sounds petty but it's amazing how often users will try to add features to a project by claiming something was forgotten or coded incorrectly.
Also heavy use of environmental variables makes maintenance and code migration so easy that it's something you don't even think about... until you don't have it anymore. I started in shops where environmental variables were *always* used and didn't realize how great it was until I went to another shop that recoded everything that went into prod and the drop in productivity is astounding. I never had a failed implementation until I went to a sloppy shop.
Document in the code. Always. Even if you have robust documentation, document in the code. I have praised and cursed many programmers whose code I ad to support based mainly on this criteria.
I wasn't going to comment because I thought it was obvious, but it looks like most people are answering some other question than the one you asked... You asked about design principles and people are giving you process answers. (Hm... but then you muddled things with XP as a non-example.)
I would start with Parnas. His papers on principles of modularity are the foundation for OOP. Keywords to search for on: coupling/cohesion, cross-cutting concerns, stable interfaces, encapsulation, fan-in and fan-out, architecture, frameworks.
A meta-point though is that software design is a huge area. You need to get much more narrow. Your advisor should provide guidance on how broad to start, how quickly to narrow, and what path to take to get there.
Universal and eternal software design and programming quality criteria from Structured Programming's time even older than Yourdon's Structured Analysis and Design from the 70s.
Loose couplings (externally) - Different components/modules/methods/functions/whatever should be loosely coupled with well-defined, relatively simple input and output data structures. One module should not know the inner workings and data structures of another module.
Strong bindings (internally) - Internally all program code in each component/module/method/function/whatever should be directly related to one task and one task only. Different tasks should be split into different components/modules/methods/functions/whatever. Different input parameters should not trigger different functionality (except for "controllers" which only determine which other components/modules/methods/functions/whatever to run depending on the input parameters.
There were different classifications of bindings and couplings but unfortunately I do not have these or any old book references at hand.
Loose coupling, strong cohesion.
...
From that axiom you can derive all other design criteria. E.g encapsulation, information hiding, abstractions, patterns,
The key to quality software is to never hire a PhD in software engineering from Tufts University, because whatever part of the project you give them, they'll just post something to Slashdot asking people to figure it out for them.
Man, you obviously have no idea. One of the critical skills is to choose the right tools for the right job.
[Sings] We're gonna need a montage!
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
I would suggest that you have a look at Basili's GQM-Method and develop a overall quality model for software design. Then select a appropriate number of projects. And then answer the metrics.
As a result you get projects divided into "good" and "bad" projects. Then you can extract their design structure and voila you have your "good" software design pattern.
I hope this is not your whole PhD thesis. As this could easily answered in a 6 month master thesis.
we're against the idea that /. can contribute anything meaningful to a doctorate thesis, unless we're talking about a degree in some social engineering field.
/.
A doctorate is the attempt to establish oneself into uppermost levels of a given field, into the most respected and generative sphere of that field. The submitter should be thanking everyone who points out the folly of starting a doctorate research by asking
You're welcome, future expert.
General rules:
1) Unrelated code should not be capable of interfering with each other (liberal use of unique package-name-spaces)
2) Load order should not affect the outcome of the application (php/jsp/javascript include-files)
3) Transient data should naturally expire (block-scope or ref-counting or garbage-collection)
4) Side effect programming should be avoidable.
5) Where possible, data should be immuteable (a specialization of item 4)
6) Where possible, code should reflect hierarchical abstractions, where the least amount of information is needed to follow or use a code snippet (this encompases data-hiding, procedures/functions with minimal input parameters, function-names / variable-names that naturally match the intended execution).
7) Code (the language) should be expressive and concise. You should be able to do a powerful thing with a few lines of code. A regular expression, a SQL statement, a lex/flex BNF-form expression, a prolog-rule. These are well-thought-out highly capable and flexible sub-languages. To whatever degree your code can leverage multiple languages (presumably by leveraging libraries that interpret syntax differently at different sections of your code), your code will have fewer bugs, be easier to make small changes that have radically different outcomes, and be easier to read - At the expense of more training time for new coders.
8) A language should be a building block, such that coders do not need to start from scratch - but instead search for the module/capability, and instead of coding, you are 'wiring' the 3'rd party library to act as you intend. This is as much a social issue as a language issue. If a language has a single repository / standard, it's easier for this social dynamic to occur. If, like C, most vendors do not play well with one another, you will be hard pressed to expand on a repurposeable building block.
9) Code should lend itself to run-time analysis. Debugable, steppable, stack-traceable, efficient and run-time configureable log-file emmission (log4j and friends is a nice framework), live thread-execution analysis (with little or no obstruction), memory allocation analysis (histograms of data-types, both count and size).
10) Code should be unit-testable. This isn't as easy as it sounds.. This means all references to dates and other OS resources need to be abstracted such that a unit-test can mock an OS resource. This also means the setup of a code resource (beit a class instance or the setup of global variables (ick)) should be sufficiently simple that the unit-test does not need to test the configuration aspect of the code; just the code itself. Note that unit tests don't necessarily need to have 100% code-coverage (as many philosophies dictate), BUT when there is a production-environment issue that needs resolution, the ability to divide-and-conquer the problem by QUICKLY throwing together specific unit-tests is indescribably valuable. Code that is not designed with the idea that it MIGHT be unit-tested is almost impossible to do this with. Languages that facilitate unit-testing are also invaluable.
11) Naming conventions should be consistent within a project.. And ideally across the language. XXImpl, XXBean, xx getXxx(), setXxx(xx), XXFactory, XXAdaptor, XXReader, XXWriter, XXController, XXDAO, etc, reduces the learning curve for any API.
12) Inputs and Outputs of any function/procedure must be absolutely clear.. If you're sadly using a language that requires 30 input parameters for a procedure/function, and the language doesn't have sensible defaulting capabilities (overloading or default field parameters) then A) shoot-yourself B) write an adaptor which minimizes the inputs. Create XXAdaptor adaptor code with setXX(x) and xx run(); that uses appropriate/sensible defaults.. This should work for most any language.
13) Reduce the impedance mismatch between unrelated code. A standard imposed by the language (InputStream, OutputStream, Runnable, Method, Reader, Writer, Co
-Michael
You've spent x years as an undergrad, y years doing post grad and NOW you want US to tell YOU how to design software for your PhD? Go and start doing something useful with your life. WRITE CODE.
People that care... Tools and Language are very unimportant in producing good software.
Caring is defined as: Fewer lines are better and clearer. If you are cutting and pasting a lot (duplicating code), then you are doing it wrong. Parameterize and remove duplication. Minimize the definitions while keeping the functionality.
Take (or be given) the extra time to make a pass at just cleaning up duplication.
Decide if a variable is a locally used item or globally used item and declare it accordingly.. Change your definitions to match reality as the software develops.
If your team gets this, then you will end up with good software... If your team does not, then you will get working software, but it will be slow/inefficient and hard to maintain.
People who are logical and desire simplicity are the key.
>> I am looking for general design principles.
.h for each .cpp (or as appropriate for other languages) and the .h's each should individually represent a re-useable, unit-testable module that accomplishes a distinct goal in the overall project. Other modules must use the published interface to get things done (no hidden APIs, little or no "friend" access).
Clearly people are more frustrated with being overridden by management than they are with design issues. I can't fault them for that, for I know of which they speak.
Leaving that issue aside, here are some of my personal design principles, no particular order:
* push for written project specifications. if nobody can be bothered to write down exactly what they expect the software to do, then it's extremely unproductive to proceed any further. i don't mean low productivity, I mean negative. if you don't have a spec, anything you do may have to be undone at some point in the future.
* make an effort to understand the problem space. i usually don't go out and talk to experts or take courses, I just pick up a well-regarded reference book to get a good grounding in what kinds of things are going on for the people who are going to use the software. then when someone asks me a question about the design or the code, I don't have to answer them with a nerdy coder answer... I can either point to the specific area of the problem space that's at issue, or at the very least make a metaphor that they'll understand. on rare and shining moments, a knowledgeable user can have some surprisingly useful insight. do not let this go to waste.
* write code such that every layer is a useful API. Module A uses module B which is a subclass of C etc, okay fine things can get complicated, but there should be a
* Every piece of code should be a model for others to follow. You should be able to look at some minor code that converts strings to uppercase, and say to yourself, that's exactly the best way to do that, and immediately see how you could extend or re-use it to say, convert to lowercase, or make it understand UTF.
* Be object oriented if you wish, but don't abuse the class hierarchy. Specious subclassing is a rampant problem, and debugging stuff that has multiple superclasses and/or a surprising link in its chain of superclasses is a nightmare.
* regardless of OO-ness, the code should be well balanced in terms of calling other functions to get things done vs. just doing it right there. Hard to give a guideline beyond that, but it's pretty clear something is questionable when someone is using an SQL statement to get the current date or using system("sort") instead of qsort.
* don't just write a bunch of code and hope it sticks together, make clearly defined areas like basic data type tools, enabling technologies, glue or wrapper code, metadata management, plug-ins, client/server tools, business rules, report generators, auditing. Some stuff (security, performance) is transcendent and needs to be brought up over and over, but once you get linked-lists working you should be able to use that without any further drama. as the project proceeds, having things divided up makes it clear where the enhancements and new features need to go, and since all the knowledge of that area is embodied in one place the change can be integrated into the existing code neatly and fully.
* abstraction, symmetry, factoring, normalization, whatever is appropriate for the project. in multi-person projects things can get chaotic very quickly. somebody needs to be on the lookout to make sure that various APIs, tools, objects, tables, that you've worked so hard to maintain in the correct modules actually fit together in a way that works well overall. I personally have kind of a twisted view where I look at function parameters as if they were rows in a table and ponder whether the function would be more apt if it referred to a column, a row, or a view instead of what was naively
There are two problems here:
...
...
... think India + China population
1. There is, because the subject is very young, very little real design practice, time tested, to rely on. Almost all quote 'advances' are really just snake oil.
2. It turns out that good programmers can write quality software 30-80 times better and more quickly than the average guy, which occurs in no other human endevour, and dosnt seem to be teachable and is 1% of the population
This is a very hard area, but hint it scales with human numbers and can easily be lost during formal education
So EU + USA must isolate, educate and cosset these guys
so you don't need to be a Harvard MBA with a pre-schooler's understanding of statistics to understand that the USA has a huge problem due to "no Child left behind" mentality.
You need to deal with the brightest, most able
and best otherwise you wont have the tax dollars
I was beaten repeatedly after school for continually using goto's, or maybe that was something else ..it's all a blur, actually.
What was the question?
First of all, like you said, using OO and Extreme Programming will be critical to designing good software. Also, shoot for a nice SOA architecture and use Ruby on Rails if possible. For the UI, use AJAX because if the browser never has to post back, the end users really like that. Store all of your data using XML, because its self-describing. Split your classes up into several tiers and make sure you have a tier called the Facade, that one is the most critical, plus it sounds really cool when you say it... Facade.
Finally, I read this book one time called the "Magical Man Month" (I think) that said no matter how far behind a project gets, you can always catch up by adding more developers to the project. So just remember that if the project starts to slip away.
Best of luck with your PhD, and let us know how it goes!
I Heart Sorting Networks
If you really want to find out how to make programs as efficient as possible, read The Story of Mel. I've never heard of anybody who could optimize code so well. Find out if he's still alive, and if so, ask him your questions.
Good, inexpensive web hosting
I read a set of articles in the November 2007 Journal of the ACM that seem to address the questions you ask. In the section on "experimental algorithms" a study was published on the software design principles e.g. at NASA that led to successful software for the agency (people factors), while other articles in the section looked at how asymptoctic analysis could lead to more effecient software (software design factors).
I read a printed copy of the publication but I guess it might also be available online.
DW White
Minimize entropy.
It sounds facetious, and it's certainly not simple to apply, but it's ultimately the one we always come back to.
Your god may be dead, but mine aren't!
Normally I don't post here, but I was less than impressed with the answers given here. Of course, I don't have a perfect answer either, but I'll tell you about some things that seem to help.
Far and away the most important thing about software (source) is that people need to understand it. Programmers can make code easier to understand with the following techniques:
* Use consistent style. If you ever break style, have a good reason and highlight it.
* Use line ordering and whitespace sparingly to highlight similarities and differences between lines of code. Group similar lines together, and leave oddball lines ungrouped, or grouped with other oddball lines.
* Keep functions/objects small and coherent. Coherent is more important than small. No not permit side effects. Ideally a programmer should be able to read the name of a function/object and understand what it does (also, what it's supposed to do).
* Make well defined concepts that naturally break down a problem.
* As far as possible, give functional areas to individuals to own. Ownership is incredibly important, even in professional software development. Unowned code will be bad code, because anyone will hack it, and nobody will clean it up. Furthermore, the owner will be your expert on that code.
* Use interfaces between functional areas. Do not allow deep penetration between functional areas unless you're desperate for performance gains. Interfaces can be changed (relatively) easily, but if external code knows details about internal data structures and algorithms, it becomes very difficult to change code.
Some other ideas:
* Strongly consider moving common code into helper 'objects'. These objects can be used, tested, and even optimized much better than dozens of instances of similar code.
* Let the compiler/environment help you. Write code that allows the c/e to show you mistakes, and as far as possible, do your work for you.
* If you have more developers than natural functional areas, either assign area leads with a small team, or assign (senior) developers to global concepts multi-threading performance. In the latter case, ensure that developers communicate, or previously owned areas will become a dumping ground!
* Adapt to the situation. Don't be afraid to change things. Don't be afraid to break 'rules', if you understand the consequences.
I hope this helps. Looking at the highly ranked comments in this story is frightening, honestly. Unit tests? Frequent releases? Documentation as the most important element in a project? Paying customers? Those items can be very important, *in some situations* *on some projects*. The advice I've given is all relevant for any[1] project with more than one person, and mostly relevant to single developer projects as well. In fact, the only good bit of advice I see from a Score:5 comment is requirement gathering, and even that isn't universal (yes, it really isn't).
You may notice that the advice I've given is vague. That's intentional. Developers need to apply these 'rules' as appropriate given the project and situation.
[1] Projects with less than 500 lines of code can easily break all of these rules and still be acceptable. Projects that small can do almost anything and still be comprehensible.
I have a mantra that I follow that has served me well over the years. It's somewhat abstract but it goes something like this: Model the concept of what your software is doing and not the physical world or procedures. If you model a concept correctly, the result will be equally useful 10 years from now because a concept, in the most abstract sense of the word, does not change over time. Modeling a concept as it pertains to software ultimately means designing an API.
[I can hear people sarcastically saying "So what you're saying is that if you do it right it will be right - whatever dude."]
Let's say you do an analysis of a task that your software is supposed to perform and you identify parts X, Y and Z. Most people are compelled to simply write some code that does X and then some more that does Y and then a bit that does Z. But I would stop and ask myself "What is X, what's it's relationship to Y and do I really need Z at all?".
If you philosophize over the task enough you should begin to identify patterns. Those patters outline the concepts involved in the task. Those patterns and concepts dictate the API.
The purpose of all of this is of course normalization. As you develop a tool-chest of modules and libraries that implement each concept the end result is highly normalized code. The chances of running into a problem that transcends the codebase is greatly decreased and the flexibility of the codebase is greatly increased. If you do encounter a problem it is more likely to be isolated and therefore easily replaced. That is what makes good software.
The single greatest attribute to good software is that the group or individual responsible for it both really wanted to write the software, and really wanted it to work well. This is typically attributed, not to much of a surprise, by the ego of the individual or collective ego of the group responsible.
The things that makes software good, in my opinion, is having created a program that performs a collection of tasks which solve the problem for which the program was intended, and doing it without unexpected errors and within the parameters of it's environment. This means web software that scales to load, desktop software which doesn't -- but scales to features, and software that in general...works. No stack traces (except in a log, maybe) and no null pointer exceptions, and naturally no segfaults.
One thing java programmers should learn is to treat NPEs like they are segfaults -- because, if this wasn't java, they would be.
All of the best programs, never mind how horrendously ugly their code might be, must be tested thoroughly...this typically requires support from developers to accomplish effectively. That being said, the best programs that most programmers will ever write, are the programs that they themselves will *use every day*. They thoroughly use it, and use it regularly. This tends to lead to a lot of really good QA. Unless they are lazy.
Start with Yourdon and Constantine, "Structured Design". Nothing significant has been said about software quality since this book appeared.
- partitioning of problems
- well defined interfaces
- trained/experienced software engineers
- adequate time
yeah, I know, it's a dream...Maximum cohesion
Minimum coupling
I'll leave the rest to you..
You asked not to point you towards XP, but a lot of practices in XP result in "good" (as in maintainable, low bug-count) software.
Use of TDD (BDD) results in testable (duh!), low-cyclomatic complexity code (which tends to have less bugs). Check "Peripatetic Axiom" blog (http://peripateticaxiom.blogspot.com/) - Keith Braithwaite has some interesting statistics about that.
I also recommend "Agile Software Development, Principles, Patterns, and Practices" by Robert Martin. Check the "Agile Design" section of the book, it explores the building blocks of good design.
hope this helps,
-Dmitri
In my opinion, the hard part of software engineering is not finding the best solution, but picking a solution when there isn't a best solution.
Let's say you have a simple but slow algorithm and an alternative which is fast but complex. Whether one is better than the other depends on a lot of factors: Can you prove the complex one to be correct? Does it have a significant impact on the system performance as a whole? Will the people who have to maintain it understand it?
The most common tradeoff is development time: often you know what the "right" way is to do something, but a shortcut is possible that can be implemented much quicker. Whether you should use the shortcut again depends on many factors: How much time does it save and how important is that for the project? Is the shortcut bad design (could lead to future bugs) or will it produce wrong results (immediate bug)? In the latter case, do you know when it will be wrong? If so, can you prove those cases do not occur in today's use of the code? Or is it acceptable to have the program fail in those cases? Will the right solution have to be implemented eventually? If so, does taking the shortcut now increase the amount of work to be done then?
There are many other tradeoffs: Do you use an existing library for certain functionality or write it yourself? Do you optimize for CPU use or memory use? Do you use advanced language features or do you avoid them? Do you prefer a simple interface that requires a lot of code to implement or a more complex interface that can be implemented with less code?
I think the real skill in design is to make good decisions regarding these tradeoffs. So I am not so sure it is possible to say all good software shares the same qualities. There are qualities you want to have in all software and you should try to get all the ones that are not conflicting and the most important qualities (for your project) that are conflicting. But in most cases you cannot have them all, certainly if you take development time into concern.
Abstract
Long time Pythoneer Tim Peters succinctly channels the BDFL's
guiding principles for Python's design into 20 aphorisms, only 19
of which have been written down.
The Zen of Python
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
Read
Lakos, "Large-Scale C++ Software Design"
I love it..
Regards,
Lars
1) Understand the business problem
2) Solve the business problem
3) Profit
"You graduated from Tufts, can you name a good school in Massachusetts?"
Read anything by David Pye.
For a short course, try:
Design and Aesthetics
And I find it incredible that you've reached the Ph.D. level in Software Engineering without ever _thinking_ about this topic.
Lazy bastard.
... then write the code top-down.
This means you need one person who groks the entire project but you can have many people writing the code. See Feynman's critique of the design process used in for the Space Shuttle.
We don't see the world as it is, we see it as we are.
-- Anais Nin
Actually, when you realise what sort of horrors are present in a house you realise that the author of the linked document is drawing a false analogy. Both in houses, and in software, various shortcuts are taken for pragmatic reasons, and these are often because the shortcuts do not undermine what is the primary function of the "house" or the "software". For example, the concrete floor in my house is lousy rubbishy stuff. Probably doesn't meet the codes, yet except when the carpet layer has a hard time laying I never notice, nor really am I too concerned, about the failure to meet some "ideal" standard. So in doing research in this area, a reality check is required and the article you have chosen to refer to starts out with a poor example to prove a point ... I am not convinced.
Oh! Wait. The architect, Gates Windows PROFIT!!!
All your database are belong to U.S.
I can see it now. "We have to use methodology X because this smart PhD guy researched it and concluded this is the way...." Little does the boss know he was soliciting information from slashdot :-) Please just use this investigation for your own personal education and do your dissertation on something else :-)
I had a uch longer post but I wasn't logged in - when I logged in, slashdot ate my homework. so, shorter and more to the point this time:
1) the most important feature set a language can offer, and the most important thing that separates intermediate from awesome programmers is proper packaging of concepts in code. I don't mean packaging for the language, or for the IDE... I mean for the human to solve a problem at one level of abstrction, maintain it at that level, and use it at another level of abstraction without thinking about it too much. Java got this mostly right with packages (and the little used package-level access modifier), and is one of the reasons I still like Java so much. This is also one of the reasons Ruby is such a nice language - I can bundle abstractions up in declarative statements that start to look like keywords in the language - think of the way Rails does things like "belongs_to" and "validates_presence_of". I was on the JSR for the upcoming Java Module System, so this is something I have thought about.
2) regardless of the process methodology, configuration management is something that has to be disciplined for real software development. I don't just mean version control - I mean requirements management (work backlog), version control, branching, merging, repeatable builds, continuous integration, defect tracking, deploys, backup and restore, reconstitution plan, and a bunch of other things that about to project-wide afety nets and 'undo' operations. Rather than try to build the perfect softare, we (very zen-like) embrace the fact that we can't write perfect software and plan accordingly. This makes the software better.
If you want to get some real thought provoking converation about this, I would suggest that you find the nearest NFJS conference to you (www.nofluffjuststuff.com), and hang out with the speakers some saturday night as we drink scotch in a hotel bar and discuss this kind of stuff until we annoy everyone else out of the area.
-db
... could give some insight: http://faculty.washington.edu/ajko/papers/Ko2008Dissertation.pdf
Engineers make design decisions carefully. Programmers always take short cuts. A computer program is a rough abstract of a real world problem, but programmers were trained to work with SPEED SPEED in mind.
Safety were important in engineers, but programmers were rush to speed and ignore anything else.
The education of programmers do not teach them to review, to re-examine, to verify, ask for peer review, examine.
They never explore all possibilities before code.
Engineers were humble, but programmers having a cultural that they were god. The programmers never care about the users. Because they are god and users do not known any thing about code.
It is very difficult to find a program to prepare for changes in real world. It is design as if the problem never change, it is so designed that things happen in a normalized way, they do not prepare for surprise.
The whole education and cultural should be changed in order to have a new generation of programmer to produce safe engineering level code.
As of coding practice, if you start it without wanting to code for real, how do you expect got a good result?
Slight correction:
You are talking about architectural patterns here, not design patterns.
Design patterns are generally ways to solve much smaller problems than the architecture of a system.
I've always been iffy about calling MVC a design pattern too, it seems very difficult to fit into the original GOF specification.
- Using what you write -- systems like the original Unix(tm) operating system (as opposed to what
got released later, commercially, by AT&T) were actually used and maintained by the people that
wrote them, every day. This is partly why things like version 6 unix are so readable and maintainable.
This is also largely true of Linux and much other Open Source. For all of
the Cathedral vs Bazaar type discussions out there, I think this "eating your own dog food" approach
is critical. If instead you use a big IDE to develop software that other people use, but not you,
you have a different attitude about it. On the other hand, Microsoft claims to do this -- that is,
use their own produtcs -- however I'm not sure how often the developers themselves use the packages
that they write in their daily work....
- Having to explain your code. There are pushes for this -- code reviews, literate programming, etc. but these
often actually diverge from explaining how the code works, and thus falter. In my formative years I used to be a site consultant at the Purdue University computing center, and I found that most people who came up to ask why their program didn't work would figure it out on their own if you asked them to explain how the program worked. There is also the IBM research on "clean room" software development, which pushed this to the extereme, where people never got to run their software, they only got to discuss it with their coworkers and hand it over to a build and test team. This got really good quality, delivered on time software, the only problem was that none of the developers would ever agree to do it again.
- What is now called testing by design -- you work in a mode where you define test sets first, then the test harness, and then write the code; module by module.
So combining these, I think you get a system where you design tests, discuss the tests with your team and justify them, then design code & discuss it with the team, and ensure it passes the test suite, and then you spend a noticable portion of your time using the software for its intended task. That is, if you're writing hotel management software, you should be spending a chunk of your time at a checkout desk at a hotel, filling in in the kitchen off hours, etc. using the system the way a real user does. Failing that, you should spend a chunk of your time on the support hotline with real customers finding out how they use the software, and what they like and don't like about it.I don't see much of this in many of the software methodologies I hear discussed.
- "History shows again and again how nature points out the folly of men" -- Blue Oyster Cult, 'Godzilla'
The true secret to software design: Did it meet the user's needs? If it was a public company, did the design make money for the company? Buggy, poorly documented software can make a lot of money. If it was for a government/military organization: Did it kill your enemies/save the lives of your own folks. Did it pay your folks their monthly allotment on time? If it was open source: Did others use it? The best design in the world is worthless if it does not meet the needs of others.
Having designed and developed software for 30 years, and used a half-dozen different methodologies (and at least twice that many languages/IDEs/toolchains/etc) I thought I'd offer these observations:
..." approach.
1) Software design is not science. It's art. Ask any hardcore developer or designer what they mean by "elegance" and you'll start to get a clue about what I mean.
2) Methodologies (Agile, XP, RUP, etc. - I've experienced them all) are just different (and sometimes useful) ways to look at the same process. In the end it always comes down to talent. Talented people create good software. Less talented people can be prevented from creating truly bad software by implementing a particular methodology, but it will never be good.
3) Most designers and developers cringe when you mention either documentation or testing - generally it's because they're not good at it. In many cases it's a waste of time and talent to make them do it. When possible, hire people who are passionate about documentation and/or testing to do those jobs.
4) No single methodology, language, IDE, etc. is good for all projects. A good designer will always give serious thought to the appropriate environment and tools for a given job (and team) rather than taking the "I always use
5) Too many people get sucked in by the common mythologies these days. These include "portability", "object oriented programming", "top down design", and so on. These are great concepts, but, like anything else, should only be used where they make sense.
You could try Trustworthy Systems by Bernstein. I own the book, but never actually read it because the lectures from Bernstein's associates at Stevens Institute of Technology did a sufficient job to explain the examples and concepts in the book.
Another favorite of mine is the work of Nancy Levenson and her students at MIT.
Support the 30 Hour Work Week!!!
Butler W. Lampson. Hints for computer system design. Proceedings of the Ninth ACM Symposium on Operating Systems Principles, Bretton Woods, New Hampshire (October 10-13, 1983), pages 33-48. Published as Operating Systems Review 17, 5 (1983)
you said design. look at cohesion and coupling from the structured programming era. also uncle bob's o-o design principles: http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf. in architecture, the dependency inversion principle and http://en.wikipedia.org/wiki/Hollywood_Principle in http://en.wikipedia.org/wiki/Inversion_of_control frameworks like spring. you should expect to see o-o design patterns
vice chair orange county java users group (ocjug.org).
Is there a high-level language which can be used to write requirements (input, output), conditions, constraints etc that are usually translated into while, if, do etc. Writing the requirements in a human language can be done precisely, but it takes so much work to do so. So, some form of simpler, easy-to-write, mathematical, analytical specification language would be nice. Yes.. there are UML and other tools.. I have yet to see a complete full project that does not go through customization. The trick would be to be able state the customizations at a higher level than writing C code. If that were so, an automaton could just create the programs and get all the programmers back to the job market. Seriously, I am sick of some of my team programmers not testing if the software meets the requirements.
I disagree with the suggestion for the Lockheed internship to gain experience. I have known people who have worked for Lockheed and their stories are similar to other work I've done in the "process heavy world of the CMMI" and have to say that the best practices are only as good as the practitioners who are applying them.
I also disagree with the suggestion that Open Source development experience will teach good design. The Open Source world isn't documented well enough to serve as an example for a PhD student in pursuit of the "best of the best".
I would stick to the latest and greatest theory that has come from veterans in academia. In another post within this article, I link to several examples of what I think the best of the best is. (click my username above, and then find the first response I made to this story).
Support the 30 Hour Work Week!!!
One thing I have found over the years is that the principles of good design apply regardless of the area
A could discussion of the principles alibet with an art bias can be found at http://www.bluemoonwebdesign.com/art-lessons.asp
Balance - a feeling of equality of weight, attention, or attraction of the various elements within the composition as a means of accomplishing unity
Movement - the suggestion of action or direction, the path our eyes follow when we look at a work of art
Repetition and rhythm - the act of repeating an element either regularly or irregularly resulting in a rhythm of the repeating elements
Emphasis - the stress placed on a single area of a work or unifying visual theme
Simplicity (a.k.a. visual economy) - the elimination of all non-essential elements or details to reveal the essence of a form
Contrast - the difference between elements or the opposition to various elements
Proportion - the relation of two things in size, number, amount, or degree
Space - the interval or measurable distance between objects or forms (two dimensional or three dimensional)
Unity - the relationship between the individual parts and the whole of a composition
source
How many times did the light bulb filament fail until the birth of the light bulb?
Maybe you should be looking for what NOT to do!
Given that Chuck Connell is not really asking us to do his research for him, but is actually conducting a survey of what people think good programming principles are, I wonder if this section of his research isn't really sociological? If so, did he get IRB approval for human research?
(Sorry, this is just a really bad university bureaucracy joke, IRBs make me glad I'm not a social scientist.)
Yes, there are useful libraries, frameworks, and components out there, but they succeed precisely because they are low level and therefore don't apply to the high-level requirements.
I DO believe that it will get you an A+ on the paper however, as I am a previous software engineering grad student.
Design is a creative activity, so your developers also have to understand the domain of possible solutions. Case in point: the Therac 25 disaster, where the developer's lack of understanding of concurrency contributed to the death or maiming of several people (e.g. http://courses.cs.vt.edu/~cs3604/lib/Therac_25/Therac_1.html .)
you're unlikely to meet them.
Agile programming is a lot like what is described in the paper you linked to.
http://www.pragprog.com/titles/pad/practices-of-an-agile-developer
http://product.half.ebay.com/_W0QQprZ45402847QQcpidZ1294591165
I'm a big fan of agile, and each one of the points in that paper. I hope you do well; you can't put a price on good design principles!
One problem with examining good design principles is that a lot of successful projects seem to succeed in spite of what would be considered poor design by any computer science theory. A lot of large open source projects are famous for just how disorganized, unmaintainable, and poorly documented they are. They barrel forward by sheer volumes of code that are submitted and are perpetually in a state of being put together with patchwork. There just isn't a metric for the scalability level of one project is versus another. Scalable, maintainable, etc. are common buzzwords but nobody really has been able to say project x has a maintainability level of 5 while project y has a maintainability level of 8. Current software publishers pretty much use their bottom line to determine good design principles. And the vast majority of software doesn't have a long enough life cycle to extract any realistic data about what's maintainable and what isn't.
I'm an exceptional programmer - I started building international enterprise systems when I was 18. Humility is a strong area too, second only to sarcasm.
Sometimes there's too much focus on the brilliance of computers, doing precisely what they are told. And too little recognition of the fact that the computers telling them what to do are deeply flawed and ineffective at doing so.
Good long term code factors in the programmer's flaws, where they will likely trip up, anticipate common errors they might accidentally introduce. It either forces them to avoid those errors, or anticipates them, handling them in advance.
Some specific tips:
1) The downside of being an awesome programmer, is that while I was comfortable with a great deal of system complexity, and built systems accordingly - it became damn near impossible to pass the code onto anyone else, even with documentation.
The lesson learnt: keep your code as legible, simple, and straightforward, for the next poor soul who'll look after it.
Even sacrifice a little performance in favor of clarity and simplicity. Do you really need to triple the amount of code, just to squeeze out another 5% performance?
2) Build code that can go wrong, and still work. Never make assumptions about what inputs will be (even internally). Never assume that the code you're about to write to call this code will be correct. We're humans, we stuff up.
Years from now, you or someone else make work on the code, and enough time has passed to make you forget that "Yeah I can't pass Nulls to that parameter, it's OK I'll remember".
On a public web service server, this rigor is vital - use the same rigor internally in your code.
3) And that's why I like consistent coding and naming conventions. Consistency makes it easier for the next poor bastard.
-The Consistent Coder
that is powerful, elegant, comprehensive, consistent, and clear to its users (after sufficient training; specialized software might require a specialized degree). Perhaps more accurately, the software must present a set of models which can interact with each other in powerful ways; the facilities of the Unix shell are a good example.
Once the users have grasped the model(s), they can begin to think creatively about using the software to solve problems, perhaps even while away from their computer; while driving a car, for example.
Many of the issues being discussed in this thread - design patterns, modularity, loose coupling and the like - are important, but they must be subservient to getting the basic external architecture right in the first place. Otherwise you could hire Bill Joy, John Carmack, and Alex Stepanov as programmers and still not come up with a product that customers will love.
I once had a signature.
I saw your first line in the preview, and immediately thought, 'have you never forgotten to unlock a mutex?' Failure to check return codes or catch exceptions also fall into the same category of missing code that causes failure. Nevertheless, I am in complete agreement with your general principles: from my experience, I have come to consider the prevalence of inordinate and gratuitous complexity as being the least-recognized problem in software design today - though it's really a symptom of a deeper problem, in how developers think about design, for which I have no solution.
I am in complete agreement with you on the value of compile-time checking, and I have found the Gimpel Lint to be helpful with C++, though only with code that was written from the start to be checked this way.
I don't believe that code can be truly self-documenting (at least not in C++ and similar languages), and I see that, unlike some other responders to this question, you don't take an absolute position on this. The problem lies in dealing with interactions between textually and temporally separated aspects of the code: two components whose interaction preserves some invariant; "we need to do this / it's safe to do this because..."; "this is better than {the obvious solution} because...". Design needs to be understood, and to be understood, it needs to be explained where not self-evident (is there a self-documenting C++ implementation of the qwiksort algorithm? Even if there is, it's too small in scope in comparison to real-world software engineering problems.) Nevertheless, I agree that naming is important, and for this reason: if you can't give a good name to a component of your code, that's a warning that it has ill-defined semantics.
The idea that good design should be readable is not new: Donald Knuth, no less, wrote about 'Literate Programming' three decades ago. The technology has moved on, but the principle remains sound.
http://vijaymathew.wordpress.com/2008/05/06/on-software-design/
I don't want to come off harsh, but this guy is from a good university, in a graduate program, and he needs help in basic research on his dissertation? Look at the question, this isn't a survey: "...I am looking for links/references on this topic."
Having gone through a similar process several years ago, I can tell you that this guy is trying to get started on his dissertation, and he's already lost.
Even a half-assed google on software design strategy can turn up stuff on the utilization of quality control techniques from aerospace programming in medical devices, the application of evolutionary theory to software design, even a nifty little blog called Coding Horrors. And he can't find this himself?
He also needs to ask himself certain basic questions. What is a good program? What is a bad program? Do their failures and successes arise from the design environment? Or do they arise from the choices about the actual program that programmers made while constructing it, regardless of the "design environment"? What strategies do good programmers use? The article he cited can be challenged conceptually is about five different ways.
Doesn't this guy have a faculty adviser? I had an entire freaking committee, and I had to scoot around to five different guys and get their feedback on every aspect of my work.
Here's an idea. Arrive at a list of good software products, then seek out the design teams and interview them. Find out what effective people do and why they do it. If a real answer is desired, the work will be immense, and the project will take a couple years.
My advice? Read, research, read, refocus your research, talk to anyone who'll sit still for five seconds, read somemore, and keep your committee clued in to what you are doing. If you don't do these things, you're boned.
Elegance is simplicity of form and function. Coding remarks are good. Simple code is better. There was a time when "systems analysis" was used to get the "lay of the land" to find what the business objectives were, then start coding, then document the code (for future programmers) and the associated processes (for end users and management). Back in the day I wrote a data translation program that was "in service" for nine years. It never had or needed any revisions because it did what it was intended to do. To address the "general question" posed: Elegance of form and function in most things (not just software) is something that can be usefully investigated when looking at the subject from the view point of "Systems Theory" http://en.wikipedia.org/wiki/Systems_theory
You should always strive to get the job done with the least amount of effort -- Taking the entire product lifecycle into account including all the effort needed by your end user to be productive.
Asking a general question and expecting a specific answer in return is one sure-fire way to fail in any endeavour.
What the fuck? You don't deserve a PhD if you honestly think you can just ask for one of the most complex answers from a website of the most ignorant and arrogant teenage programmers who think they know EVERYTHING and pray for the day Microsoft goes bankrupt.
"Facts and fallacies of Software Engineering" by Robert L. Glass. Good stuff, and lot of references to more good stuff. For a PhD thesis, you rather want to cite academic work than the /. crowd, won't you?
Unfortunately most of the objected_oriented/patterns/agile/your_buzz_word_here is fairly worthless or at least only useful rules of thumb used to prevent the average programmer from having to think too much. (They also make a good PhD thesis) It just isn't worth the time to handcraft the code for the average application. It would take too long; cost too much. It is much better to take the Microsoft approach and burden your users with the problems you didn't want to spend the time/money solving because they have no other choice. Knuth's approach is to force the programmer into expressing the solution both in code and in language. The extra effort requires the programmer to understand the problem with both sides of the brain which leads to better algorithms, fewer bugs more maintainable code (its documented what a concept). Unfortunately this leads to literate programmers which is a nightmare most companies cannot deal with. No company wants employees to actually think because it makes things take to long and cost too much.
Bertrand Meyer has written a lot around good design and software reliability.
This is the flip side of a principle with an old name: Separation of Concerns. Separation of Concerns means "to do one thing at a time." This refers not to multithreading but to what is happening in one place in a program.
... the list is endless and the list of good practices is endless, too. Unfortunately, we don't pay enough attention to the good practices.
Reading an essay in which multiple arguments are mixed across paragraphs is hard. It becomes much easier when each argument is given paragraphs of its own and when they are grouped. Only when it is necessary to bring the points together are they combined, in the simplest way possible.
Likewise in programming, you should not litter a decision with deep details needed to implement it, nor let your reader forget why you have written it.
Separation of Concerns is the foundation of many approaches: modularity, information hiding, object orientation, aspect orientation, etc.
(Some people will be able to identify me from the following; so be it.)
There are just four things which make programs unclear: Disorganization, Obfuscation, Poorly Chosen Representation and Recondite Algorithm.
Disorganization I have covered above and will cover further below. It is by far the greatest cause of unclear programs.
Obfuscation is any violation of "say what you mean, simply and directly" (Kernighan and Plauger). Different things may be obfuscative in different contexts: Using extremely long variable names for control variables in short loops, splitting simple computations across multiple lines, failing to structure "external variables" and enums in structs/classes/your-language's-constructs so that they are given a context to provide meaning,
Poor choice of representation often shows up in the use of state variables in a loop that would be much clearer with early exit or early restart. Sometime's it's the opposite: contorted branching in a computation that would much better be represented by state variables. The use of functions that return a hard-to-use type is another problem.
Recondite algorithm is the rarest type of unclarity, and the only one for which commenting is the correct cure. Every attempt should be made to summarize the computation, with appropriate references to places needed for study. References should not be too much relied upon, however: One very early UNIX password algorithm was based on the Hagelin rotor machine. The commentary was limited to identifying what the variables did, naming the major steps (one sentence or less, each) and giving the patent number of the machine. More is needed!
Concerning organization: I like a 'radical' definition of cohesion and coupling. It's radical in that it goes to the root of the issue: the relationship between the problem and the solution embodied in the program. A program is cohesive to the degree that each problem element appears in just one place in the program; it is decoupled to the degree that each element of the program represents just one element of the problem.
For the program to be stable under minor changes in the problem or increases in the program's scope, its hard-to-change elements must represent the unchanging, core parts of the problem; the connections between them must be flexible enough to deal with the changes and rearrangements that will occur in the problem or its definition as time goes by.
Whew! Lots of words. But a good starting point.
Let me add one another issue: surface versus volume complexity. A moderately complex algorithm/data structure is safe to use and robust under change to the environment only to the extent that there is a stable and simple interface for it. The complexity of understanding (I am not speaking of computational complexity) needed to use it depends on the surface complexity at that interface. Its independence and stability under changes in the other parts of the program also depends on its innards being independent of what lies on the other side of the interface.
Clear designs result in good implementations. Object-oriented syntax is the vocabulary in which design is expressed. Clarity of expression is key to making solid systems that are self-documenting, robust, and interchangeable. Modular software design maximizes the value of its all its constituent parts.
C++ and Apple's Objective-C 2 each provide access to a strong set of data models - like arrays and dictionaries - in the form of STL and CoreFoundation. The best runtime libraries let you start working without needing to reinvent data storage. Garbage collection reduces typing.
The best APIs and libraries use consistent and clear semantics in their naming conventions, which allow the casual reader of the code to get a good idea of the system, algorithm, or process expressed.
Languages with flexible semantics can help you express systems at higher levels, and the growing set of code design tools is making it easier to visualize inheritance and container relationships before generating any of the interface code.
The best code doesn't have to be the fastest, it only has to be fast enough. Sometimes that does mean, as optimized as possible. In code-world, less code equals more speed. The more instructions you run through, the more complex the branching, and the more scattered the memory access, the longer the processor will take to crunch through your tasks. The best code minimizes these hits through intelligent data organization, indexing, feeding the compiler what it likes to optimize, and using threads smartly to take advantage of multiple cores.
If optimizations lead to obfuscations, kind programmers unroll it in a comment. A good idea for their own future reference.
Code at even the highest levels may not in any way express what you end up with in the output. The code to generate the Mandelbrot fractal has no turtles or curlicues in it. When you look at the algorithm carefully, though, you see that it expresses ideas not only about fractals and the endless complexity that even a simple iterative process can produce, but the language itself embodies connected ideas about the limited nature of the FPU and the square cartesian grid... which itself speaks to the way humans take in data.
Good code therefore recognizes both the low level, concrete resources it maps onto, and respects the clarity of all that it models, all the way from the naming conventions it applies for an auto variable, up to the balletic organization of the master controller's minions.
The end result of really good code is that someone can sit down at a BASH terminal and express in 6 lines of generic shell-speak a powerful transformation of input to output, which provides insight through and into the system it embodies.
Graphical interfaces and such should embody ideas differently than the internal models. Database designers often make bad interface designers because they expect end users to think in their own inverted fashion about child-parent relationships. Freudian as that sounds, it means end-users should relate to the data at the overview level, so that casual scanning and targeting can be applied to interact and modify what is there.
The best code expresses the interface (e.g., in the "View" corral of an MVC program) in its own internally-consistent manner, relating interactivity to controller messages. Controllers act as mediators between Views and Models.
Things I shouldn't say... Good code uses Doxygen or something like it to document at the model and interface level. Good code avoids putting inlines in headers, and good compilers will inline when optimizing for speed. Good code keeps interface and implementation separated. Good code is code you can return to in a year and still comprehend quickly.
The best code teaches you something you didn't know about the world, reveals subtle patterns in systems, unfolds its own unique sphere of creation, immerses and engages human minds, and has a loose, organic quality that is sensed rather than known.
Did I forget to mention encapsulation? Good code encapsulates what it should, how it should. It streamlines clear thinking.
-- thinkyhead software and media
Time and (not so) common sense in your working environment.
If you're looking for "what design/architecture qualities are shared by all good software, lacking in bugs, maintainable, modifiable, scalable, etc, then your best bet is *a sane environment*. That is, enough time to actually do the job without having to crunch through 80% of it, and no unbridled pointy-hairs or ever-changing requirements (that old walking on water joke).
If you have that, the actual tools you're given to work with are a secondary matter. Really.
"Good news, everyone!"
Well, from my own experience (which is in no way related to huge programs),and from common sense, I'd say
...) ... ... but these langages are definitively not mainstream. It's better to concentrate on stable well known langages and avoid those with too much zealotery behind them (like .NET, Python, ...)
1) Keep it simple.
No need for convoluted algorithms that noone can understand or for complex class hierarchy. If it can't be easily understood and need complex documentation, it's going to fail in the long term
2) Don't over-feature it.
Useless features takes time to be programmed and are source of bugs which could easily have been avoided by NOT implementing these...
3) Functions/méthods/procedures should be understandable
If you need lots of comments and documentation to understand what a procedure do, it's time to rethink it. Meaningful function name, consistent coding (loop index using the same variable set in the same order everywhere, consistent indentation,
4) Use the proper tool/langage
Programming a text-parser from scratch in C/C++/... can be "fun" but doing it using Lex/Yacc is much more efficient, less prone to errors and easier to maintain. Using C/C++ for web coding when a simple PHP script could do the same is looking for trouble,
5) Avoid marginal or zealot langages
If can be cool to program in WinDev, Forth, Lisp,
Langages like C/C++/Java/PHP can solve most of the problems, share a common syntax and are not rewrotten every second year.
6) beware of OOP
Object Oriented programming often allows reusing the same components again and again... But this has a cost : each class is like a new library added to the program, with it's API and so on...
Newcomers to the projects could easily need to have to study half of the code to make a minor change (or to read tons of documentation).
Inheritance (and worse, multiple inheritance) can easily make the program hard to understand and bring cascades of bugs if the base class has to be changed.
Process does not mean anything. If I follow the process at my workplace, I'd still come up with code but it is highly unlikely that it will work. Experienced developers have learned the hard way and unfortunately some people never learn so spending a lot of time doesnot necessarily mean experience either.
Is this an attempt to make the community to work for your PhD? Well, if it is then will your dissertation be published under GPL license?
I believe the question is wrong. Because there are many ways to reach maintainable/solid software, there are likely no qualities beyond those you list shared by all such software. Most, maybe, but not all.
Eivind.
Doubting the existence of evolution is like doubting the existence of China: It just shows that you're uninformed.
All good software has source code that can be easily understood. This statement is not as trivial as it sounds, because arranging something complicated so that it is easily understood is significantly challenging.
Nonetheless, this is the metric you have to use. If every piece of software can be understood, then all the pieces are good. If the interactions of all the pieces can be understood, then the combined behavior will be good.
To figure out what can be easily understood, put down your computer science books and open up a psychology book to learn about the limits of human cognition. Free hint: Look up short term memory (aka "working" memory).
Good luck on the PhD process.
good for what? good in what way? good for whom?
I'm not just being an asshole here. For good answers you need to ask the right questions.
assignment != equality != identity
In fact, confusing this sort of question with plagiarism would mean that you would consider reading trade journals, talking to practitioners, and reading Open Source coding as "plagiarism" too. In fact, posting on slashdot might, to some limited extent, be considered part of "talking to practitioners".
Whatever people answer here, it won't be anything near what you can put into a Ph.D. thesis because you can't, in any significant way, prove or demonstrate that the ideas thrown up idea are valid. If you could, it would have been published it already and the originator would be a well-known software engineering theoretician. At the very most it's a suggestion for a line of research; all the hard work (telling real from bogus and understanding why) is yet to be done.
You might want to read: Design Patterns Explained. There's useful information in there as to what good software design principles are. The gist of what the book says is that all software is bound to change and evolve over time, and that a good design is one that allows us to make these changes with minimum cost by judiciously encapsulating the variable pieces. They go on to explain how all design patterns essentially are built on this core idea.
If you're looking for great software design principles, start with the greats: Liskov, Fowler, Martin. Go to Object Mentor's published articles, click on "Design Principles", and start reading.
These handful of articles changed the way I look at software, particularly OO software, but not necessarily restricted to OO, and highlighted the importance of controlling dependencies. All of the Gang of Four design patterns use one or more of the principles laid out in these white papers. I would go so far as to say that good architecture and design primarily revolves around managing dependencies correctly around your functional requirements and points of future extension, no matter what language you're in.
These concepts are going to become ever more important as we have to scale across more cores and more machines using functional languages like Erlang and Scala and techniques like map/reduce (see Hadoop, for Java).
but have you considered the following argument: shut up.
I try to keep the code modules from being so long that I cannot read them over with a minimum of scrolling. By the time they are over four pages long, there is usually something there that can be factored out and placed in a separate function . For easier maintenance files longer than that are hard to comprehend.
in that particular order.
Simplicity: In good software I see that if two things do the same thing the simplest solution is favored.
Readability: In good software I see that code that is more readable for humans is favored.
Testability: Good software is easy to test (by design)
These properties are usually attained by aiming for separation of concerns, the right abstraction level and the proper granularity. Some methodologies like XP, SCRUM and other Agile seem to be more successful in delivering good software, but it is not a property of the software itself that it is made using CI, TDD and what have you.
Show a man some news, distract him for an hour. Show a man some mod points, distract him for the rest of his life.
I am the anti-process. I am not a cowboy coder. But rules and formality are never a substitute for an actual human thinking about what makes sense. Written formal process ends up being an impediment to getting work done *and* followed only in word, not spirit. This results in all the costs of process with none of its benefits. Instead, decide what you mean by quality, spot check it, and punish/reward accordingly. I agree the actual practices you mention are the way to go in almost all cases. But what matters is if it works, and the documentation is adequate and correct. How they got there is of no importance. It is even less important that they get to that point in the same way every time. Consistency leads to stagnation.
refactor the law, its bloated, confusing and unmaintainable.
Your question to the audience was: What design/architecture qualities are shared by all good software? However, this question has the inherent assumption that for good software design/architecture qualities are relevant. Is this the case? Do some research on what "good software" is and you will discover a very ugly multi-headed monster. The perspective on "good software" radical differs between software engineers, management, customers, and society as a whole.
Here's another way to test the quality of code ...
http://www.osnews.com/story/19266/WTFs_m
.
I really think that it would depend on your circumstances. Your approach towards developing a product suite (where testability, maintainability, reliability are key) would be completely different to developing a once-off import tool.
In general however, the main underlying concept IMHO would be managing complexity. Different paradigms use different approaches, but modular design, service-orientation, encapsulation, etc, are all directed at managing complexity - layering / packaging things in such a way that the overall level of complexity of the entire solution is lowered.
Bad software typically has very little concern for managing complexity, leaving a solution which is difficult to understand, debug, modify, etc. What separates good software from average software is that the overall approach to managing complexity has been successfully executed. I say "executed" specifically because designs often do not stand up to changing requirements and environments, even if they initially look good. Once again, there are many different approaches to achieving this, such as an architecture-oriented approach (I recommend the book "Managing the Object-Oriented Project" by Booch), or the more modern, iterative approaches involving TDD, refactoring, etc.
Unfortunately I don't think I've said anything new here (flipping through the article you mention, I get the feeling that I have kind of summarised what they are saying), but I hope this helps.
Probably this will never be seen by anyone. But oh well....
Programming is a work of writing. Sure, it's written in a strange language. Sure it's constrained by having to actually do something useful. But from an asthetic point of view, it's still just writing.
What is good writing in English? If you can come up with a sound bite that is concise, exhaustive and true, then you are a great person. The same is true for programming.
You can find *examples* of good writing. You can argue if it is really good or not (and everyone will have their opinion). But this is not something you can define easily (or possibly at all).
If I were you I'd go from the exact opposite direction. I'd look for good design. Then I'd talk to the people who wrote it. I'd ask them, "What do you think is important in order to create good design". Then I'd write down what they said.
Finally, I would start a practice of design criticism. Review design. Write about it. Start a dialog with others.
In other words, do what English PhD candidates are doing...
Take a look at http://www.praxis-his.com/sparkada/ and "correctness by construction" design process. Something good came out of DoD ;)
I think the article that the author refers to hints at the answer. The way to build good software is the same as the way to build good buildings.
To build a good building, we have building codes that have been carefully thought out and they're enforced by law. In software we have the design fad du jour and programmers get defensive when you suggest that anyone, even a peer, review their code. Suggesting that they be legally bound to a set of principles simply sends them off the deep end (see the stream of flames that this will generate for an example). But think about it - we require enforced standards in buildings for quality and safety. Why shouldn't we require the same thing in software?
In the building industry we have licensed contractors who should know the codes and follow them. In software, anyone can do it. A lot of them aren't very good.
In the building industry, if you want a nail, you walk into Home Depot and there's an entire aisle full of them. There are long nails and short ones, thin and fat ones, nails that are coated to prevent rust, nails with wide heads for roofing, nails with a square shaft that's twisted so they spiral in, skinny nails with a dimple so they can be counter sunk (finishing nails) etc. etc. Oh, and that doesn't even begin to talk about the slight variations on nails. There are screws (nails that burrow in), staples (two connected nails), spikes, and on and on and on.
The point is that there's a nail for each specific need.
Now consider the sofware industry. Suppose you need a list. I'm a C++ programmer and until a few years ago, if you needed a list, you rolled your own or maybe used one from a commercial library. Only just recently have templates made lists easy and only more recently has the STL given us a standard. But if you want a list you have 1 choice.
If software was like the building industry, I could open a catalog and choose from all sorts of lists: singly linked lists, doubly linked lists, lists that own the objects within them and lists that don't, lists that are thread safe and ones that aren't, lists that allow callback functions when you insert/delete, lists that keep ref counts, lists that ensure an item can only be on one of them at a time, etc. etc. etc.
The point is that there would be a standard component to do almost anything I want. Today we write and rewrite the same stuff over and over again and each time someone new does it, they make some of the same mistakes, both obvious and subtle.
If people built houses the way we build software, there would be a sawmill at every job site and the contractor would be using studs of his own favorite size. There would be a metal forge there too where the they'd be making nails in whatever dimensions seemed handy and out of whatever metals they felt like.
1. GO TO THE LIBRARY - read every paper that they have on software design principles from books and periodicals - follow the reference chain and order more - use inter-library loan to get everything you need.
...I'd be happy to dispense more patronizing advice on demand :)
2. Elementary Internet research - this is a good link http://www.cetus-links.org/top_architecture_design.html its one of literally thousands - and is an excellent starting point for architecture and design principles
3. Find an original angle - I presume you (the original poster) wrote that paper? No offense but it doesn't leap out at me as an original paper - it isn't bad - but it certainly isn't the basis for a PhD at the moment. You need to find an original angle, something that will add to the body of knowledge - not a rehash of other peoples written observations - thats degree or MS level, you need to say something that hasn't been said before.
4. Drop the architecture / building / bridge analogies - thats nice in a software architecture 101 class to give an undergraduate a basis to understand what it actually is - otherwise its nonsense - like comparing chip design with book writing, yes they both have structure buts that where the analogy ends. Such a justification for good design has no place in a thesis.
I must have been having a bad day or something yesterday, because this morning when I re-read my post even I thought it was awfully harsh.
Its just that at first glance this question struck a personal pet peeve. My frustration comes from being a college teacher. I have many, many students who don't take any of their own initiative to learn anything. I can provide them books, articles, methods, lectures, tutoring, and yet they just want me to hand it to them on a platter. For example, if I teach them the step-by-step process for calculating the 95% or 99% confidence interval they have no problem if I just give them N, u, Z, etc. But if I give a word problem to calculate the CI for the average bowling scores in a league, they are stumped. Remember the article on Slashdot about this the other day?
I did not take the initiative to read the poster's background. He is definately not some "wet-behind-the-ears" grad student. But I'm still intrigued by this question. My experience working at graduate-level computer science is that a professor would chew me out for using something like Slashdot as a research point. (Although I can see why the editors would post this story, if only because the answers from people experienced in the field would be interesting.) My education is from public southern universities...looking at Tufts' background its a different "flavor" of school.
"You cannot find out which view is the right one by science in the ordinary sense." - C.S. Lewis on Intelligent Design
Process is worthless unless people follow its spirit to the letter, and no process can completely enforce 100% good behavior. I've been a professional software developer for over 10 years and it has become quite clear to me that the most important two factors in software development are selecting the right people to work on it and managing those people well.
Moderator hint: a comment is neither "Flamebait" nor "Troll" if it is true.
Routine work is defined as work where both the problem and solution is known. In problem solving, the problem is known, but not the solution. The hardest group is problem definition, where neither the problem nor the solution is known.
When people are comparing software development with building a house (a ridicules metaphor but one that seems to stick around), they are talking about routine work and to some degree problem solving. Software development in these two categories can benefit from rigid processes control and following some form of software development method.
There have been a few articles about the teams that build software for the space shuttle program and space probes and how well they build software, with close to zero bugs, delivery on time and within scope. It can be useful to look at their techniques, methods and tools as well as the development process. However keep in mind that these groups build software mainly in the problem solving and routine work category. Building software after a stable blueprint is "easy" and as long as you have good developers and follow a proven process it is hard to fail. Not that I don't admire those guys, but I am not surprised that they succeed.
However, the reason software projects often fails spectacularly is because they fall into the problem definition category. That is; no one really knows what the problem is and there is no clear solution. In this case, the target (i.e. realization of the specification) is fluctuating and because of this, it is very hard if not impossible to create a good project plan, allocate resources and estimate the cost.
Projects in the Problem solving and Routine work category will almost always succeed no matter which software development method, techniques and tools are used. In fact, the often debunked waterfall method can be useful for many of these projects.
For projects in the problem definition category, using such methods will be fatal. Instead some form of iterative evolutionary development process must be used to try and narrow the scope, follow the target and at the same time have some form of forward progress. There is no silver bullet as Fred Brooks concluded a long time ago. If you only have one set of tools (method) in your box, like most consulting companies, you will fail sooner or later.
The solution is to realize that each software project is different and to have a box full of tools, techniques, principles that can be applied to different situations and problems. And in this case; "death to methods!" Following a software development method for projects mainly in the Problem definition category is fatal.
Take a look at the chapter 3 of the Software Engineering Body Of Knowledge. It's the most complete source of information I've ever found on the subject (and the project is managed by the University where I did my master's degree !! ). Of course, check the list of recommended references for more information.
- I am also doing standard academic literature surveys, in several different ways.
- I am not conducting an opinion poll. I asked for links/references to known work.
- I am asking "the software development community" for input because software engineering is different from some other disciplines. It is unlikely a physics researcher would get new ideas about gravity from a public discussion forum. But there is a lot of good work about software engineering that does not come from the academic world, and is not published in academic journals. Some is not in printed format at all.
- If someone tells me an original idea, or a new take on an old idea, I will cite them in my paper.
- Asking people for ideas is not "getting someone else to do my homework for me". Anyone who thinks that it is has never done anything difficult.
Chuck Connell
References:
Norman, D., Things that make us smart. Defending human attributes in the age of the machine. 1993, Cambridge, MA: Perseus Books. 290.
Vincente, K., The Human Factor. Revolutionizing the way people live with technology. 2003, Canada: Alfred A. Knopf. 351.
Here's a quote from 'the best developer' from a particular work unit on a major DoD project regarding published data:
"While it might be good coding style to initialize [variable x], I'm pretty sure [our software unit] has no requirements to provide any logic for determining [the value of this variable]...."
So they had an interface unsupported by requirements, but they kept the interface.
I think infoq.com has some wonderful resources on "general principles of good software design". In particular, I recommend reading Jean Jacques Dubray's terrific mini-book on composite software construction, which will definitely give you some serious food for thought.
Speaking for myself, I think perhaps the most important principle is to keep thinking until it's really right.
I've been around some extremely intelligent people in my time, and none of them ever got it right on the first pass. You think of solution "A", which leads you to think of solution "B", which finally lands you on solution "C", the right one. The point is, the only way you COULD have gotten to solution "C" is by way of "B", and so on.
Naturally, this means one has to spend enough time upfront to come up with the right idea. It is a mistake to think that EVERYTHING needs to be documented up front (the classic "waterfall" method), but you've really got to have the essential idea and its approach before you even touch that code.
To me, UML has become an increasingly important design tool for expressing the essence of a system before we get down into the trenches.
"We receive as friendly that which agrees with, we resist with dislike that which opposes us" - Faraday
The subject says enough. Pick up Software Fundementals: A collection of his papers. It is the foundation of the accredited software engineering in Canada
No, "good software" is a subjective measure.
Charles Connell asserts that "Most software is so bad, in fact, that if it were a bridge, no one in his or her right mind would walk across it." How would a layman know if the design of a bridge was bad; or if the bridge was functionally sound despite an outward appearance of rot or corrosion? Many people are afraid of rope bridges, but this negative user experience doesn't prevent them from being useful for particular applications.
The correct definition of "good software" involves quality attributes that are agreed on by all interested parties. Quality cannot be defined in the absence of the consumer. Given real-world budgetary constraints a slow application with a buggy UI may be acceptable to a customer if data reliability is guaranteed. An imperfect tool is often more valuable than no tool at all.
The most important reference you need is ISO 9126 which provides a quality model for software. The Wikipedia page on Software quality is also worth reading, and you may find ISO/IEC 14598 (Software Product Evaluation) worthwhile as well.
i-name =twylite [http://public.xdi.org/=twylite], see idcommons.net
The question is: What design/architecture qualities are shared by all good software? Good software means lacking in bugs, maintainable, modifiable, scalable, etc...
This is a very academic way of looking at "Good Software". Good software does not have to be all those things because those attributes are not of primary importance in all situations.
A one time import script does not need to be maintainable, modifiable, or scalable. However, it is sometimes very important that it is bug free or that it is written quickly.
One place I worked, we developed very expensive packaged software that was often installed in remote locations. It was important that it work and work the first time. Another place I worked programmed for inhouse systems and there the primary driving force was always speed and features. This resulted in some crappy code which was considered to be good software by the business because it was what they needed when they needed it.
Had I spent the same amount of time and care developing at the second job as I did at the first, I would have been rightly labeled incompetent. It didn't matter that the code was difficult to maintain because the most oft overlooked requirement for maintainability is profitability.
My point is just that your definition of good software really only makes sense in an abstract sense, when looking at software in isolation from its intended purpose, or in very specific situations where those attributes are overriding concerns.
Not sure if anyone has mentioned this but have you looked into Design Patterns? I am an undergrad double majoring with Business and Computer Science and i have taken Design patterns and its really useful.
The ones that commonly get used are:
Bridge Pattern,
MVC (Model-View-Controller),
Factory,
etc.
You can also find more info with regard to encapsulation of variability, flexibility, reliability, usability, and some other "requirements" for good code.
Also look into software life cycles, and avoid using the life cycles that microsoft's vista uses (sends the prototype to users and change with feedback using users as the QA dept)
Look for stuff from the authors of Code Complete, Design Patterns (aka. Gang of Four), Programming Pearls, The Pragmatic Programmer, and Refactoring:Improving the Design of Existing Code.
Donald Knuth, Steve McConnell, and Martin Fowler stand out, because they're pretty vocal.
The bibliography for Code Complete also has a number of great research references.
Wow, a lot of very vague stuff here. If he/she hasn't already the poster really needs to take a good hard look at software design patterns. Its pretty well established that the majority of software problems are not unique and that we don't need to come up with clever new solutions to them every time we encounter them. The real trick is in recognizing which pattern applies to a given situation. Most of these patterns are applicable to many different technologies although there are also a handful of domain or technology specific design patterns as well.
I'm not real big on the fishing expedition either, but...
If he does see a few responses that hit on points he is researching, he could attempt to contact those specific people and conduct more traditional interviews. And interviewing industry professionals, last I heard, is an acceptable form of research. Not enough to write a thesis on, but enough to get some more detailed statements than can be quoted and attributed as supporting arguments.
-Rick
"Most people in the U.S. wouldn't know they live in a tyrannical state if it walked up and grabbed their junk." - MyFirs
Glad ye asked, sonny. *spit*
90% of the software life cycle is maintenance so any o these here design "principles" you fancy-schmancy PHDs come up with that don't create code that's *trivially* easy to maintain is bullsheet *spit*
Dip into the little book "The Martian Principles for Successful Enterprise Systems: 20 Lessons Learned from NASA's Mars Exploration Rover Mission" by Ronald Mak (John Wiley & Sons - ISBN 9780471789659) for a smattering of generic language-and-project-size-agnostic Good Processes.
Now help me get my walker so ins I kin git me tobaccy *spit*
Prof. Manuel Caeiro in University of Vigo (Spain) works on Software Engineering Principles, focusing on formal design. He is part of the GRIS (Grupo de Redes e IngenierÃa del Software - Software Engineering and Networks Group), the website of the group is http://www-gris.det.uvigo.es.
Good luck with your PhD!
i do not repla http://www.google.com/
I think studying how different kinds of software fail will help you to understand what is a good software design principle e.g. M$ addressed blue screen of death. Software can fail in many dimensions e.g. cost, performance, time-to-market. Each dimension demands different approach. So I guess by addressing these topics, they should get you somewhere for your thesis.
You might want to consider changing your topic to how much information you can actually obtain from people on social sites such as slashdot. I should hope you learned your lesson today... ...see you around campus, I guess.
I agree that the principles, practices, qualities, wisdom about good software are not confined to OO technologies (I've seen design patterns used in Fortran, and my friend Amir Kolsky once taught a TDD course in COBOL). However, they are easist to see/discuss/outline in OO, because OO sprang from them. Here's a link to a talk I did about the subject: http://www.netobjectives.com/resources/books/emergent-design (click on the link "Watch Scott's webinar about Emergent Design (1 hour)" It's a multi-media (camtasia) recording, so be a little patient if your bandwidth is limited.
Any time spent dealing with overhead is time not spent being creative and solving problems. All the overhead keeps people frustrated.
Don't use an environment that needs makefiles. Pick an environment that manages compiling issues for you. Or one that doesn't need make files at all.
Write mini-compilers that generate code from config files for you, rather than spend hours hacking out code in languages that weren't designed for the purpose they are being used for.
Use very strong data types. That way, bugs get stopped at compile time.
Use very strict naming conventions: either camelHump or underline_no_caps - no frustration!
Should variables have plurals? Yes or no? Naming conventions for the file system: caps or no caps, underscores_or_not. If you make everything singular, there will never be confusion or the variable names.
Code review is essential. Make everything look the same, so you can't tell who wrote what.
Don't use comments - use conventions.
Use opensource. Its less likely to stop a developer over technical issues, like windows does. And opensource grows old and fades like bluejeans rather than suddenly exploding for unknown reasons, as closed source does.
"Spec" the hardware the software will run on.
"Spec" the software the hardware will run.
Stop pretending databases can effectively abstract data and still maintain acceptable performance. Just spec the hardware.
Publish performance expectations, rather than just say "We'll optimize as needed". What the hell kind of spec is that?
Plan the project around remote developement techniques.
Make part of the project GPL/commercial licensed and roll the code into a Linux distro.
Be proactive in keeping one individual from having too much influence and becoming so important that the project can't function without him.
Find people dedicated to helping one another at all costs, instead of jerks who want to do it their way, is nice (hire some women).
Get rid of the CEO who didn't used to be a techie.
Get rid of the CEO who thinks the engineers should speak to him using "CEO-speak"
Hire someone who's sole goal is to sit between the developers and the bosses and translate.
Figure out what the programmers needs and goals are for their lives, and figure out a way to help them, rather than present some static employment deal that requires them to fabricate need as a means leveraging their career.
Donate money to local causes. A lot of money.
Let developers work from home.
Cover 100% of their health benefits.
Honestly, there is no technical limitation that a skilled individual can't overcome. Now, market and interpersonal limitations... That's where the real road block comes in. It doesn't matter how good your code or environment is - no matter how smart your people are. If you boss is a dumb ass, that's the person who will stop you project from being successful.
It seems to me that all great software I have encountered either has limited scope. The fewer things a piece of software does, the more likely it is that the software will be excellent.
Yes, there are a huge # of criticism, but I still got some useful comments and links.
Chuck
When i first started coding, i listened to the senior coders for hours on how the reservations, sales, and acct software worked together. That told me what files to code.
Then i went and stayed in the Sales floor for a month and found out how it really worked.
I went to the Accounting dept. and found the workarounds they used every day, to bypass our software.
I even made a sale to test the whole thing!
Long story short, coders don't use software. Seriously, they don't. They don't know how, because they know how it works.
they bypass things in their head, they don't answer to anybody. Go find the Standard Operating Procedures and see how closely they are followed. Go do the job, be the tester. Everything else is useless assumption.
Don't apologize for your own behaviour.
Not sure if it is of interest, but my own book, High-Assurance Design (2005, Addison-Wesley; http://assuredbydesign.com/haa/) attempts to identify a useful set of "principles" pertaining to both security and reliability for practical software engineering. I tried to target practicing software architects, and so the book is not written as a "security book" or a "reliability textbook", but a handbook of sorts. The taxonomy includes about 180+ principles, each explained in detail, with design patterns. It is not a programmer's book, as there is not alot of code in it, but rather a book about design. It also contains a taxonomy of social engineering techniques, which you might not find elsewhere. The book has a foreword by Peter G. Neumann, one of the pioneers of Multics and of secure design in general. I hope it is of value. Best regards, - Cliff.
Hi Folks
/.lers - simply the 'right people'.
Reading through many answers, the funny and the earnest ones, I honestly think that your are ALL mislead. 'Good software', what makes good software? WHAT _MAKES_ GOOD SOFTWARE? It can certainly not be pinpointed on the requirements, the architecture, the design nor the code: Good softwaree is made by the 'right people at the right time from end to end'. You might have the perfect architecture, design and code. However, if the business analyst screwed up, the software is crap. You can turn it as you want. In the end if you had the right people to work with - hopefully including the customer - everyone will happily think back about his time on this project and the final result. You do not even require the market hot shots - or
Regards
Chatzi
I've published that list before, so credit me if you use it. If you want to know more, just email me. You can figure out my address with the info provided here.
Only an interesting reference:
Beautiful Code
by Andy Oram, Greg Wilson
June 2007
To be honest, The best software development starts with good architecture. Good architecture is usually Simple, straight forward, and follows the way the architect thinks. Too many people try to do things in too complex a fashion. If a function can be used to add numbers, adding 10 parameters to make it add objects is not very useful.
Developers should not try to who off either. Just write what is necessary to fit into the overall architecture. Document the architecture. Programs without a solid architecture are not good programs.
I did get some good ideas within all the hate. (And of course this is not my only method of research.)
Chuck (OP)
Most bad software is rushed, created by bored programmers, in a corporate decision to create another boring and faulty-by-design software system.
Most good software is written by a small team of very excited developers who love what they do, are given the resources to do so, and who couldn't even think of a more exciting system to build.
You can add all the modularity or simplicity or readability or whatever you need, but unless it is made with love, it won't be beautiful.
No matter which kind of software. A good software design needs a good previous analysis. Software "usually" has an objective. If it's soft to be used by human beings. A good point to start is asking what the user need, by figuring wich are his objectives. Once you have a good user-model to ask what he need, you'll need to figure the context in which the user is going to work. May be you'd like to read Cooper, Saffer, Weimberg,... a little recomendation list I found:
http://astore.amazon.co.uk/ricdevass-21/026-1329438-3042066?_encoding=UTF8&node=2
I'll argue strenuously with #4. Many of the principles of good prose (organization, omit needless words, say what you mean simply and directly) apply very well indeed to software.
As to architecture: if we strip the application-area details, architecture is neither more nor less than the relationship by which the parts become the whole. Given that almost all programs are organized from smaller parts, architecture is a critical consideration at every level above the individual variable or constant.
To describe an architecture, you must identify the whole and the parts and, for each part, identify what it does, what resources it uses from other parts, and what it contributes to the whole by doing it.
Regarding the old input-process-output view, a similar view may help when looking at the architecture. The uppermost 'layer' of software provides certain semantics at its top. Its interior expresses those semantics in terms of what the lower layers/modules provide. This continues downward until the semantics are provided by the programming language, the hardware, libraries, or some external facility (perhaps at the other end of a socket or pipe).
Oh, I'm the AC who wrote above about Separation of Concerns and the radical definitions of coupling and cohesion.
Read this book. Then read it again. One of the best books written on the subject in recent years. I think it's been updated recently, so you may want to get that one, but this version is excellent.
We must realize that one of the most critical users of the program is the next generation of the same software. If it cannot be modified as needed without introducing bugs, it will not meet the needs of the users. The program must have a stable design (change in code is roughly proportional to change in problem definition), which requires that the right things are flexible and, as a corellary, that the right things are fixed.
One problem is that software managers prefer young programmers. They are cheaper and have less experience to get in the way of getting it done now.
... especially if you need to modify that code for the next version of the product.
Somewhere in the last few weeks, physorg.com captured an article which reported that while older people often work more slowly, it is not always that they are slower by nature but that they have more experience to bring to bear.
Getting 1500 lines of code written in a week sounds good until you discover that it takes six weeks to go through test. If an older programmer got the same results with 1100 lines and those lines took two weeks to write but only two to go through test, you have a considerable win
I can't agree with the idea of making code boring. Boring code makes the reader careless.
Nor should the code be challenging; challenging code leads to the reader skipping it.
Code should be interesting in that the reader should be able to learn about the problem solution while reading it. It should turn a hard problem into a simple one.
And, if it can, it should be exciting in how well it expresses the problem.
If you can get your hands on the source code for the very early Unix OS versions (v5, v6) and Dennis Ritchie's C compiler, I suggest you do them. There is much to criticize, but far more to revel in; this is exciting code in the amount it accomplishes with relatively few lines; if you are still malleable it may change your code permanently--for the better.
You've chosen a wonderful topic ... I won't point to specific URLs, but you will find a lot of information around software design/development best practices. You will quickly realize that this discipline is part science and part art (arguably, the latter is more important).
You are correct - OO, XP are not stand alone answers, but such methodologies do provide very good pillars to lean on.
And while there are well implemented COBOL applications, I would argue that OO does matter - 20 years of history tells us that an OO approach tends to yield more stable and maintainable systems when applied properly (and that's key!).
I believe the answers you seek are multi faceted - rooted in technology, approach, teamwork, management ... discipline - what we do is often called a 'discipline'. There's a double meaning there.
I'll call out a few specifics:
1 - design/implement at the right levels of abstraction. Push complexity down to it's proper level. If 80% of a code base looks like pseudo code, a good job was done.
2 - Separation of concerns can't be over stated. Modularity is great, but only if each module minds its own business.
3 - Pick a language / technology whose expressiveness / facilities match the problem at hand ... life will go a lot smoother.
4 - Only a project that takes refactoring seriously, and builds in the overhead for refactoring cycles will succeed in the long term, and yield an elegantly designed & implemented solution. Management that poo-poo-s such measures as wasteful play time is doomed to fail - in a business sense and in the context of your thesis.
5 - The team must work with a common mindset and apply principals intended to yield a system that has the qualities your thesis wishes to quantify.
I would strongly suggest - along with your other research - to take a breeze through "The Pragmatic Programmer" by Hunt & Thomas.
It's a must read.
Good luck with your project.
Would love to offer feedback as you proceed - feel free to ask - louis.iacona@verizon.net
-- Louis Iacona
Martin Fowler has published a lot work in this space. While very little is original, he is a great communicator and ties various concepts together well.
You can start by reading what people who have written good software have to say: The Creators of 30 Programming Languages: pages, biographies, blogs, interviews
www.littletutorials.com
In my opinion good properly designed software has to do a lot with "who" and less with "process and how". If you look carefully you will see real people behind good software. You should try to find out how these real people think and work, what are their values. If you consider for example the most important programming languages as examples of well designed software (sometimes debatable, I know), you could try to read more about them: The Creators of 30 Programming Languages: pages, biographies, blogs, interviews
www.littletutorials.com
Given that every reply you got here basically says something different, I'd say that although many people have very strong opinions on this subject, nobody really knows. The same goes for me, and I have been developing for 24 years, I have a PhD in Computational Linguistics, worked in industry, taught software engineering courses etc. Of course you should be aware of methodologies such as waterfall, XP etc. But if you take a closer look you will see there is neither much of a theoretical nor an empirical basis for them, it always comes down to some guys saying 'this is how you should do it, trust us'. Think about it, would you buy a mortgage backed bond from somebody who tells you that documentation is a bad thing? Only in software engineering will you hear such a thing. So, the truth of the matter is, nobody knows. I think heavy engineering-type approaches generally do not work and are not used in practice. As an example, take OO programming. Almost any programmer will tell you that principles like inheritance, data encapsulation etc help you write better code. But, as far as I know, nobody bothered to check whether this is actually true (in a scientific way) until Les Hatton did, and guess what: he claims that OO code is significantly more buggy than non-OO . It seems counter-intuitive, but there you go. Another disturbing finding is that software quality has steadily decreased over the last few decades. I don't think his work has had much impact on how code is written nowadays. Another example, Cleanroom. It sounds good, the most scientific approach to software development I know of (http://en.wikipedia.org/wiki/Cleanroom_Software_Engineering). Case studies have indicated that it's really good for delivering high-quality, cost-effective code. So good in fact that, as far as I know, nobody has ever adopted it. Cleanroom is an extreme case, but I could give many more such examples. The main reason for bad software is not technical, it's caused by the way the industry works. It's run by the kind of people that believe in motivational posters. That kind of mentality is dangerous in any engineering discipline, where you need to think defensively. Another problem is that there is no regulation as found in any other industry (food, aviation, civil engineering, healthcare etc). The way I see it, there's a war going on between professionals and 'generalists', and in ICT the latter have been on top for decades. Compared to say lawyers and surgeons, software developers have very little status. I hope I don't sound too cynical, of course I think there's a place for SE and I wish you the best of luck with your research. But I'm very sceptical about software quality going up in the near future as a result of SE research. There is hope though. If a team manages to steer clear of worst practices, and uses some kind (any kind!) of methodology, it would already produce code that's way beyond industry standard. The things you read on http://thedailywtf.com/ are just the tip of the iceberg. I've seen industry-grade code which had an implementation of bubble sort (in C). Some of the worst practices imho: - hiring the most uneducated and uncaring people you can find. All large IT firms do this, they're cheap, malleable, and motivated by money, which is something any manager can understand. Also, managers don't like to have people work for them that are better educated than they are. So as a customer, you pay extortionist prices to have art history majors and ex-cons build your back-office software. Another problem is that, even if a firm does not have this kind of policy, recruiters tend to be clueless bimbos. I've heard one of them complain about not being able to find C-programmers, "only C++, and what use are those!". I've also heard a recruiter proudly proclaim "we only do projects for large companies, the others can't afford us". - hiring antisocial, narcissistic people. Obviously arrogant behaviour is an indication of high market value. Never mind that such people check in non-comp
Don't take this the wrong way, but this is a worrying question for someone who is allegedly going to complete a PhD in this area.
Be aware there is a risk you will spend the next year or two procrastinatng, then becoming hugely depressed and ultimately giving up your PhD. Get your s**t together now, son, or start doing something else.
A bit of explanation: my background for most of the last ten years has been in building frameworks that get mostly used by others - specifically, applications/libraries that get used to write tests and/or build field tools for hard disk drives. An awful lot of this was "oh shit" sort of work - someone comes running to my group after discovering an issue on a product after it's shipped, and they need a tool to fix the problem, and they need it a week ago. So a lot of my designs grew out of the need for extremely flexible code that could be repurposed quickly - in other words, the ultimate in code reuse and modularity. Most of it also needed to run on three different OS families (and they would have liked a couple more).
Here are the ones that I try to follow; most of them apply to design of just about anything, not just code:
0) Using performance as a reason to bypass any of the following rules is acceptable only once you've demonstrated a problem with a profiler. "Programmers are notoriously bad at predicting how their programs actually perform."
1) Decide before you start what toolboxes you're going to require. Invest (money, time, whatever) in the best tools you can afford. If you have to spend time wondering whether your tools are broken, you've probably chosen poorly.
2) Spec your functionality, then design your public interface. Write to the interface. Do your damndest not to change that interface after you "ship" your module.
3) Do not include anything in your interface that falls outside the toolboxes you've selected in item 1.
4) Decouple your modules. I cannot possibly over-emphasize this. No "convenience exceptions"; the time you save by tying two modules together will be lost the moment one of them needs to get used somewhere you didn't plan for... and you *will* need to.
5) Along with decoupling, try to keep your functions as general as possible (but see also rule 0). It's a bit more work to write a general-case function than a specific one, but when you end up needing a variant of that function later, you'll be glad you did.
6) When possible, write portable code; you never know when you'll need it to run somewhere else. This also provides you the ability to use additional debugging tools that might not be available to you on your first platform. How to accomplish this is a topic worth its very own list...
7) Pivot the world around configuration files. That doesn't necessarily mean a file on the end-user's drive - it can mean a compiled-in source file which configures the program's behaviour. But don't hard-wire it into the function.
Sig broken, watch for
Sure they do. But they also have many places where using an MVC would slow down performance without justifying the benefit. So perhaps they use it in some places, but I can't imagine they do it for every single pixel/cell you can edit :-)
- Jesper
My security clearance is so high I have to kill myself if I remember I have it...
- Jesper
My security clearance is so high I have to kill myself if I remember I have it...
I respectfully disagree :-)
An MVC implementation can be quite lightweight and small. And used in very small apps where data is altered from multiple sources and the view needs to be kept up to date automatically.
- Jesper
My security clearance is so high I have to kill myself if I remember I have it...
It's still difficult to program with large amounts of persistant data. Object/Relational mapping needs to be much better; and this might mean blending aspects of SQL into traditional OO languages; and making relational databases a little more friendly to objects.
No, I will not work for your startup
Don't forget the parent could just as easily be doing PH.D work on the pshycology of web boareds and how they effect software engineering concepts then the question would be a really good one to ask ;)
âoeTolerance applies only to persons, but never to truth. Intolerance applies only to truth, but never to persons.
Start with the Roman author Vitruvius. Writing in the 1st century AD about architecture, he recommended three principles: firmness, commodity, and delight. In other words: It works, it does what it's supposed to, and it's a pleasure to use.
- Jim Hoekema
Google it:
http://www.google.com/search?q=Software+Design+Principles+conference
Oh, see, there's even a conference as 1st link. Read the papers of the previous conferences, look at their references, get more papers to read, more conferences/workshops to look for. Submit to that conference, get accepted, present and discuss with people there.
Citeseer is also helpful sometimes: http://citeseer.ist.psu.edu/
Search also in LNCS (Springer), ACM or IEEE
Concerning your paper: mmyaaaa, I didn't read it, but still, I won't bother even skimming through it as there's no references (except Code Complete).
Read what is asked for.
It asks "general principles of good software design", such as maintainability, and reuse-ability . Or is the question about QA and catching bugs?
quote - "object oriented methods' or 'try extreme programming". OO design or paradigm.
The question don't make sense and I confused myself!!!!
Do your own PHD or atleast know a little about what you are asking