What is the essence of good software design
Moderator: General Moderators
Re: What is the essence of good software design
haha yeah my dad helped write the F22 software, and yeah the house burning down was just a metaphor. Don't take it literally. I just think the phases of development aren't actually as distinct as you make them out to be, in actual practice.
Re: What is the essence of good software design
If you were referring to me - those are not the phases of development, those are practices I employ throughout the development process. Domain modeling might be concentrated in one specific phase, but it never ends there.
As I said, I follow the ZF coding standards - so yes, one class per file. I've never measured the SLOC my code base has, as this is not relevant to me as metric. I would like you to explain to me why you consider it soDo you keep more than one class per file? How many comments/line of SLOC does your codebase have?
-
alex.barylski
- DevNet Evangelist
- Posts: 6267
- Joined: Tue Dec 21, 2004 5:00 pm
- Location: Winnipeg
Re: What is the essence of good software design
SDLC phases should be agile...being able to jump back and forth from one to the other regardless of where you are in terms of milestones, completion, etc.... I just think the phases of development aren't actually as distinct as you make them out to be, in actual practice.
I have never subscribed to that theory so when I became of aware of Agile/XP I was like: Finally...I told my teachers in school software didn't have to be developed the hard way.
But each phase should be done to the best of your abilities...not saraficing code quality over end user satisfaction because that is what drives software. If you do both right, you get both benefits, not one or the other...
I guess what I am saying, is software quality (from a technical perspective) and quality from a end user perspective are not mutually exclusive...it is not one or the other, not both...it's quite possible to achieve both. Ignoring quality metrics is just taking the easy way out.
Simple really...SLOC will have a direct impact on the complexity of your code...complex things break by nature. When a design is simplified it's less likely to break, have bugs, etc.As I said, I follow the ZF coding standards - so yes, one class per file. I've never measured the SLOC my code base has, as this is not relevant to me as metric. I would like you to explain to me why you consider it so
The more atomic you keep your files, modules, classes, methods, etc...not only does your code become easier to maintain through modularity and reuse but the context is far more descriptive at which point you begin to have self documenting code.
I have maybe 30 comment lines in my entire project. Mostly TODO: statements to keep track of what needs to get done each day.
Re: What is the essence of good software design
Right, and when you put a method on a class that you feel is responsible for that method, but the user's context introduces an entirely different paradigm, then you have just made a negative design decision, and should refactor to the better design. Although the first scenario might have mad more sense to you originally, it caused the design to drift off course, whether or not you are ignorant of its effects. This is what I believe was meant by objective vs subjective. I agree decomposing to modules is imperative, I'm just saying I'd rather have the modules semantically correct, then have low cycle complexity. You can always go back and do mechanical refactorings, but a context change down the road "costs" more. Having the context correct to begin with can increase speed of completion for the project, which you said was one of the things you consider an attribute of a good design.
All good designs will also serve the developer, in addition to the end user. A developer is using the code therefore his needs have a play into the design quality as well. When (not if ) you have to change the context the design should be supple and easy to bend like a crumbled up piece of paper, not rigid like a piece of cardboard. If you continuously update the design to reflect the user contexts, your axies of variation will naturally fall into place. Like the crumbled up piece of paper all the places the paper needs to fold have already been identified, you're not changing anything new. If the design has not experienced any context changes during it's design, it is more likely to have unpredictable results. There's no way you can plan for what needs to change, unless you're re-inventing the wheel.
All good designs will also serve the developer, in addition to the end user. A developer is using the code therefore his needs have a play into the design quality as well. When (not if ) you have to change the context the design should be supple and easy to bend like a crumbled up piece of paper, not rigid like a piece of cardboard. If you continuously update the design to reflect the user contexts, your axies of variation will naturally fall into place. Like the crumbled up piece of paper all the places the paper needs to fold have already been identified, you're not changing anything new. If the design has not experienced any context changes during it's design, it is more likely to have unpredictable results. There's no way you can plan for what needs to change, unless you're re-inventing the wheel.
http://softwareengineering.vazexqi.com/ ... ple-designEric Evans wrote:A lot of overengineering has been justified in the name of flexibility. But more often than not, excessive layers of abstraction and indirection get in the way. Look at the design of software that really empowers the people who handle it; you will usually see something simple.
Re: What is the essence of good software design
In my opinion you're really over simplifying it. LOC definitely do not correlate to complexity - often very condensed lines that attempt to do a lot of things simultaineously can be broken into several simpler, more readable lines. Also, while refactoring I move a lot of small chunks of logic into it's own methods, adding LOC of code that are only structural and not logical, while hopefully raising the quality of my code.Simple really...SLOC will have a direct impact on the complexity of your code...complex things break by nature. When a design is simplified it's less likely to break, have bugs, etc.
Self documenting code is an ideal which we all like to strive for, however there will always be places that require commenting, and especially doc-blocks before methods and classes are important for generating manuals from the source code and for the benefit of auto-completing tools embedded in IDE's.The more atomic you keep your files, modules, classes, methods, etc...not only does your code become easier to maintain through modularity and reuse but the context is far more descriptive at which point you begin to have self documenting code.
I really don't think that having only 30 comment lines is something to be proud of. And for todo's I use tests in the code to show me what needs to be done.I have maybe 30 comment lines in my entire project. Mostly TODO: statements to keep track of what needs to get done each day.
-
alex.barylski
- DevNet Evangelist
- Posts: 6267
- Joined: Tue Dec 21, 2004 5:00 pm
- Location: Winnipeg
Re: What is the essence of good software design
I'm missing something. Obviously refactoring is something we need to live with, so what?and when you put a method on a class that you feel is responsible for that method, but the user's context introduces an entirely different paradigm, then you have just made a negative design decision, and should refactor to the better design. Although the first scenario might have mad more sense to you originally, it caused the design to drift off course, whether or not you are ignorant of its effects
I'm confused again.This is what I believe was meant by objective vs subjective. I agree decomposing to modules is imperative, I'm just saying I'd rather have the modules semantically correct, then have low cycle complexity. You can always go back and do mechanical refactorings, but a context change down the road "costs" more
Low cycle complexity? Mechanical refactorings? I have never heard of these terms before, the latter I find very confusing and the former I am totally lost.
There are in my experience superfical changes to code, such as renaming text or updating XHTML. Then there are refactorings like moving a method from class A to class B. Lastly there are changes which often require complete re-writes, such as when there is a bad decision made at architectural conception.
I think I know what you mean by context...but the end user experience is constantly changing...so you must design the architecture in such a way that accomodates quick and rapid change...that was my point.Having the context correct to begin with can increase speed of completion for the project, which you said was one of the things you consider an attribute of a good design.
Good lord man...did you just read a book by Donald Knuth? Your not writing a PhD thesis are you? Is it really neccesary to use such easily misinterpreted words? While I can admire excellent command of the English language and your attempt at eloquence, your dropping words which I am not familiar with at least given the context of software development. Take it easy on me, I'm an old dumb man.If you continuously update the design to reflect the user contexts, your axies of variation will naturally fall into place. Like the crumbled up piece of paper all the places the paper needs to fold have already been identified, you're not changing anything new
For the sake of this disscussion, lets organize design into two distinct categories:If the design has not experienced any context changes during it's design, it is more likely to have unpredictable results. There's no way you can plan for what needs to change, unless you're re-inventing the wheel
1. Front end design
2. Back end design
#1 being the design responsible for meeting the users requirements, how well the interface is designed both in beauty and ergonomics. If the interface solves the problems of the user, in this design context it doesn't matter how the solutions are implemented.
#2 being the design or architecture of a software system.
Cheers,
Alex
Re: What is the essence of good software design
Cyclomatic*PCSpectra wrote: Low cycle complexity? Mechanical refactorings?
mechanical refactorings = http://www.refactoring.com/catalog/
"abstract refactorings" = refactoring on a larger scale, such as refactoring the design of the domain
a mechanical refactoring would be moving a % calculation on a loan app from one class to the next, a change to the domain would realize the user views this is a pie chart, and not a series of calculations, and thus refactoring your design to the user's perceived context.
Re: What is the essence of good software design
Its "you're", not "your". Since when can a person have possession of a verb?PCSpectra wrote:While I can admire excellent command of the English language and your attempt at eloquence, your dropping words which I am not familiar with at least given the context of software development. Take it easy on me, I'm an old dumb man.
( just raggin on you, I see TV ads using the words out of context too, such a disgrace )
http://www.wordinfo.info/words/index/in ... =B&spage=3
This is an example of how contexts can alter our perceptions.
Last edited by josh on Tue Nov 18, 2008 8:27 pm, edited 1 time in total.
-
alex.barylski
- DevNet Evangelist
- Posts: 6267
- Joined: Tue Dec 21, 2004 5:00 pm
- Location: Winnipeg
Re: What is the essence of good software design
This is true. However in my experience any method more than 50 or 100 lines is likely overly complex and can be further decompoed into private methods, etc.In my opinion you're really over simplifying it. LOC definitely do not correlate to complexity - often very condensed lines that attempt to do a lot of things simultaineously can be broken into several simpler, more readable lines. Also, while refactoring I move a lot of small chunks of logic into it's own methods, adding LOC of code that are only structural and not logical, while hopefully raising the quality of my code.
It's not an exacting metric I admit, however it's better than nothing and perhaps more importantly, if you look at good examples of bad design, you will see many of those projects have outrageous SLOC per file, function, etc.
Any function over 500 lines of code is insane and I gaurantee you I coudl refactor that function into at least 5 clearly defined sub-routines, leading to more explicit code.
Why? Honestly man...I have no comments except to hilite hacks or caveats which might arise when something is changed. In these cases I try and write automated tests or self testing code to raise errors when something is done which would cause hard to trace bugs.Self documenting code is an ideal which we all like to strive for, however there will always be places that require commenting, and especially doc-blocks before methods and classes are important for generating manuals from the source code and for the benefit of auto-completing tools embedded in IDE's.
As for doc blocks. Meh. I hate that much green. It's a serious hassle to maintain when your methods are constantly being refactored, updated improved, etc. I use a slightly different approach, in that I generate the API on each release and any methods who's signature has changed since last documentation gets reviewed and updated accordingly.
This keeps my API docs far more accurate and keeps all those comments out of my code.
That is my opinion. Honestly man, when I started programming in Assembler I commented like mad...you had to...identical instructions could have widely different results depending on context.I really don't think that having only 30 comment lines is something to be proud of. And for todo's I use tests in the code to show me what needs to be done.
Then I found myself commenting heavily in C/C++ but slightly differently. No longer was I saying
Code: Select all
// Initialize variable A to ZEROCode: Select all
// Increment pointer by X to quickly jump forward in bufferI try and make my code read like english...the idea is that eventually I will write specifications in low level english and pass that specification to a generator which will build my application for me, at least a semi-complete application whihc only needs some tweaks.
I'm getting closer and closer each and every day but still have a long way to go until I have something really worth mentioning.
-
alex.barylski
- DevNet Evangelist
- Posts: 6267
- Joined: Tue Dec 21, 2004 5:00 pm
- Location: Winnipeg
Re: What is the essence of good software design
Cool. I like that idea...a concrete list of possible refactorings...I'm always working on refactoring tools so this should prove helpful.mechanical refactorings = http://www.refactoring.com/catalog/
"abstract refactorings" = refactoring on a larger scale, such as refactoring the design of the domain
Bahaha...I hate when people do that...I have an English Lit major friend who constantly corrects my English. Lucky for her she's a chick and I won't slam down a rear naked choke hold...maybe rear and perhaps naked but no chokehold.Its "you're", not "your". Since when can a person have possession of a verb? what's a "dropping word"?
( just raggin on you, I see TV ads using the words out of context too, such a disgrace )
Re: What is the essence of good software design
Not buyingThis is true. However in my experience any method more than 50 or 100 lines is likely overly complex and can be further decompoed into private methods, etc.
It's not an exacting metric I admit, however it's better than nothing and perhaps more importantly, if you look at good examples of bad design, you will see many of those projects have outrageous SLOC per file, function, etc.
Any function over 500 lines of code is insane and I gaurantee you I coudl refactor that function into at least 5 clearly defined sub-routines, leading to more explicit code.
It doesn't matter whether its one function with 500 lines, or 50 methods with 10 lines each, it's the same count of LOC (actually, 50 methods add 50 opening and close lines, not to mention comments
Also, suppose I put the entire Zend Framework library under my project, though I don't know yet exactly what components I will be using. I will raise the LOC considerably without having written one line of implementation - how is this a good metric for the quality of my project?
I won't deny that commenting is personal preference, though most serious projects have significant portions of it. As for docblocks, I add them mostly for public methods (ie, my API) so they shouldn't change often. They are also conveniently generated by my IDE from the method definition.As for doc blocks. Meh. I hate that much green. It's a serious hassle to maintain when your methods are constantly being refactored, updated improved, etc. I use a slightly different approach, in that I generate the API on each release and any methods who's signature has changed since last documentation gets reviewed and updated accordingly.
This keeps my API docs far more accurate and keeps all those comments out of my code.
When I see well commented code (not over commented, not under commented) I appreciate the effort the developer went through to allow others to ease in to their project. Remember that comments are mainly for other developers (since most developers believe their own code is very readable, which it is but mainly to them).
Re: What is the essence of good software design
There's actually a book that goes with it, ( that puts it in contextPCSpectra wrote:Cool. I like that idea...a concrete list of possible refactorings...I'm always working on refactoring tools so this should prove helpful.mechanical refactorings = http://www.refactoring.com/catalog/
"abstract refactorings" = refactoring on a larger scale, such as refactoring the design of the domain
http://www.amazon.com/Refactoring-Impro ... 0201485672
-
alex.barylski
- DevNet Evangelist
- Posts: 6267
- Joined: Tue Dec 21, 2004 5:00 pm
- Location: Winnipeg
Re: What is the essence of good software design
50 methods is going to be easier to maintain and less buggy was all I was saying.It doesn't matter whether its one function with 500 lines, or 50 methods with 10 lines each, it's the same count of
Not so much as a metric itself.
With 500 lines I am sure I could find code reuse but its not just about code reuse its about readability/clarity and context.You'll possibly argue that you simplify logic in the process, saving some LOC - but from my experience, unless some code reuse could be put in place no meaningful reduction in LOC would occur.
I didn't quite mean it in that way...SLOC as a total number of lines is useless, yes...bigger applications will likelly have more lines of code...but when you add context, such as lines per module, per method, per class, those numbers become much more useful.Also, suppose I put the entire Zend Framework library under my project, though I don't know yet exactly what components I will be using. I will raise the LOC considerably without having written one line of implementation - how is this a good metric for the quality of my project?
Like I said I have very few comments and no bugs or security holes that I am aware of...just unfinshed pieces.won't deny that commenting is personal preference, though most serious projects have significant portions of it
Most serious projects? The last 5 projects I have worked on had such poor commentation I had to figure out the code by stepping through it manually anyways, so what was the point of having the comments other than to distract me from reading the code?
Can you give me an example of a complete function where you needed comments? Also make sure the comments are specific to the context of the function only. That is your not commenting on the fact that if a variable is removed it will have a reaction, etc...
I'd like to see an complete example before I would agree. Just find a function with no or minimum dependencies and use that.
Even the public API changes frequently in my case...obviously between versions I would not change an API once others were using it but until it's set in stone I treat it like a private or protected and refactor when needed.As for docblocks, I add them mostly for public methods (ie, my API) so they shouldn't change often. They are also conveniently generated by my IDE from the method definition.
I realize that. Comments are best written by someone else for that very reason. Have a period of time when someone who has no knowledge of the implementation go in and comment the code. Recording the steps and caveats as they go will prove far more helpful than the original developer hammering out what he thinks makes sense at the time of implementation.When I see well commented code (not over commented, not under commented) I appreciate the effort the developer went through to allow others to ease in to their project. Remember that comments are mainly for other developers (since most developers believe their own code is very readable, which it is but mainly to them).
Then ask yourself...if you have to comment...is there any way you can simplfy your codebase so that the code was self describing and didn't need comments.
Note: While I don't comment I do document quite thouroughly. Before entering the codebase one might read the docs and become effective as a developers within hours, not days, weeks or months.
Re: What is the essence of good software design
This is from Joomla, the comment describes the outwards black box behavior of the method, someone calling this function could read the comment and learn everything it does, without overloading their mental capacity with file system details, without the comment the meaning of some of the stuff would be kind of ambiguous unless you read and understood the code, which violates "mental encapsulation". The point of encapsulation is so that you don't have to think about thingsPCSpectra wrote:Can you give me an example of a complete function where you needed comments? Also make sure the comments are specific to the context of the function only. That is your not commenting on the fact that if a variable is removed it will have a reaction, etc...
I'd like to see an complete example before I would agree. Just find a function with no or minimum dependencies and use that.
Code: Select all
/**
* Copies a folder
*
* @param string $src The path to the source folder
* @param string $dest The path to the destination folder
* @param string $path An optional base path to prefix to the file names
* @param boolean $force Optionally force folder/file overwrites
* @return mixed JError object on failure or boolean True on success
* @since 1.5
*/
function copy($src, $dest, $path = '', $force = false)
{
// Initialize variables
jimport('joomla.client.helper');
$FTPOptions = JClientHelper::getCredentials('ftp');
if ($path) {
$src = JPath::clean($path.DS.$src);
$dest = JPath::clean($path.DS.$dest);
}
// Eliminate trailing directory separators, if any
$src = rtrim($src, DS);
$dest = rtrim($dest, DS);
if (!JFolder::exists($src)) {
return JError::raiseError(-1, JText::_('Cannot find source folder'));
}
if (JFolder::exists($dest) && !$force) {
return JError::raiseError(-1, JText::_('Folder already exists'));
}
// Make sure the destination exists
if (! JFolder::create($dest)) {
return JError::raiseError(-1, JText::_('Unable to create target folder'));
}
if ($FTPOptions['enabled'] == 1)
{
// Connect the FTP client
jimport('joomla.client.ftp');
$ftp = & JFTP::getInstance($FTPOptions['host'], $FTPOptions['port'], null, $FTPOptions['user'], $FTPOptions['pass']);
if(! ($dh = @opendir($src))) {
return JError::raiseError(-1, JText::_('Unable to open source folder'));
}
// Walk through the directory copying files and recursing into folders.
while (($file = readdir($dh)) !== false) {
$sfid = $src . DS . $file;
$dfid = $dest . DS . $file;
switch (filetype($sfid)) {
case 'dir':
if ($file != '.' && $file != '..') {
$ret = JFolder::copy($sfid, $dfid, null, $force);
if ($ret !== true) {
return $ret;
}
}
break;
case 'file':
//Translate path for the FTP account
$dfid = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $dfid), '/');
if (! $ftp->store($sfid, $dfid)) {
return JError::raiseError(-1, JText::_('Copy failed'));
}
break;
}
}
} else {
if(! ($dh = @opendir($src))) {
return JError::raiseError(-1, JText::_('Unable to open source folder'));
}
// Walk through the directory copying files and recursing into folders.
while (($file = readdir($dh)) !== false) {
$sfid = $src.DS.$file;
$dfid = $dest.DS.$file;
switch (filetype($sfid)) {
case 'dir':
if ($file != '.' && $file != '..') {
$ret = JFolder::copy($sfid, $dfid, null, $force);
if ($ret !== true) {
return $ret;
}
}
break;
case 'file':
if (!@ copy($sfid, $dfid)) {
return JError::raiseError(-1, JText::_('Copy failed'));
}
break;
}
}
}
return true;
}-
alex.barylski
- DevNet Evangelist
- Posts: 6267
- Joined: Tue Dec 21, 2004 5:00 pm
- Location: Winnipeg
Re: What is the essence of good software design
For someone so concerned about mental encapsulation I'm surprised you don't see the function as overly complex.without the comment the meaning of some of the stuff would be kind of ambiguous unless you read and understood the code, which violates "mental encapsulation". The point of encapsulation is so that you don't have to think about things
Personally I would not have a FTP and local file copy within the same function.
Secondly:
Code: Select all
// Initialize variables1. Were initializing variables
2. Were re-assigning variables
Seeing as the variable does not exist before it's assignment, one could probably assume it's being initialized. If it's a global, that is exactly why it's a bad practice...because now you have to find out where it's declared/initialized first.
Code: Select all
// Eliminate trailing directory separators, if any
$src = rtrim($src, DS);
$dest = rtrim($dest, DS);
Are you serious, you find that a helpful comment? Maybe you should read a beginners book again.
I know what rtrim() does and Joomla docs should tell me what DS constant is (but I can guess and assume directory separator) so I should already know what is going on there...
The meaning of $src and $dest are implied by the method name and it's class context.
Code: Select all
// Make sure the destination exists
if (! JFolder::create($dest)) {
return JError::raiseError(-1, JText::_('Unable to create target folder'));
}
It's not just checking if the destination folder exists...it's creating it too. Confusing.
Whats all this business below about?
Code: Select all
if ($FTPOptions['enabled'] == 1)Again, I think comments are mostly a habit from Yesterday's programmers teaching Today's youth.
Cheers,
Alex