Writing code makes the difference between a mediocre architect and an outstanding one. There are a number of factors that influence this thinking, least of which being, architects are essentially programmers with additional responsibilities. Part of thinking like a programmer is thinking in code and part of thing like an architect is thinking like a programmer. That is, as an architect, essentially what you're doing, no matter how many practices and procedures stand between yourself and the software, code must be written.
What is the best way to make this happen? After all, the big picture falls to the architect to sort out. All the stakeholder's expectations must be aligned with what we're actually able to produce. So, then, maybe I can help by contributing some code, or at the very least, reading some code and reviewing it. But does that leave time for my other important architectural activities. Too often, code and the process of curating it, is neglected by not just architects, but the development process as a whole. Developers recognize that the success of any modern organization rests heavily on the shoulders of it's technical foundation. It's ability to write and understand code.
When an architect suggests that they have other activities to perform — ones that seem to place code on the back-burner — its no wonder the negative stigma surrounding software architecture is so prevalent. Architects are just big picture guys, out to do nothing but draw diagrams without consideration of the technological challenges facing developers. That, and other negative perceptions about software architecture, could be partially resolved if architects wrote code.
Team Player
Writing code is a team sport — you try out, you make the team, you pass the ball around, you win, you lose. A narrow analogy might place the architect in the role of coach. Observing the game, commentating on events as they happen, providing feedback, and devising plans. That might work well if software development teams were structured the same as organized sports teams. We often don't have a fixed roster of developers. The teams we're up against are often composed of many more players than ours. Despite these limitations, there an obstruction in sports that doesn't exist in software development.
The architect can throw on a pair of skates, jump over the boards, and score a goal or two. It's as simple as that really. Being a team player, that is, getting your hands dirty and helping out with the code-level work will bode well for team morale. This is how, as an architect, you can earn some serious respect. Bend over backward to make life easier for programmers, and they'll return the favor, I assure you. Put this way, the architect is playing the role of captain and coach.
Now, this certainly isn't an easy feat. Architects can't simply ignore their duty of ensuring stakeholder satisfaction. As much fun as programming in the wild west can be, architects are programmers with additional responsibilities. Let me put it this way — you're still supposed to look after the architectural description, and basically ensure that the software system itself maintains it's architectural integrity. So no, don't forget about those things. Don't drop what you're doing and start your new programmer position just yet — these purely architectural day-to-day jobs are important. Make sure you do get involved with the code from time to time. Even if you're not capable of contributing functional components, ask questions. Earn some respect by taking an active interest in the nuts and bolts.
Nuts and Bolts
Beyond earning respect from developers, it is important that architects understand the nuts and bolts used to glue their system components together. Understanding the big picture and the impact it has on every stakeholder is the most important deliverable in any software architecture. This includes the nuts and bolts.
Developers that disregard the software architect role as nothing more than big up-front design have good reason for this attitude. If we're merely handing down ideals without sympathizing as to how difficult these implementation jobs actually are, than we're doing big up-front design while leaving reality as an afterthought. Reality cannot be an afterthought. Reality is the low-level details, the subtle but important code we need to write that realizes the requirements of the stakeholders.
As an architect, you're also a programmer — never forget that. Like it or not, if you don't understand the nuts and bolts, you had better make sure you allot time to study them. The low-level components have a big impact what what is ultimately delivered as a software product. This impact ripples from the bottom, all the way up to the users, touching on every use case we've put together that ensures the software can satisfy all requirements. If the implementation was executed well, these nuts and bolts will be encapsulated inside robust APIs that we've designed. As you know, abstractions only go so far in protecting ourselves against unanticipated behaviour of the nuts and bolts.
The software architect is in a good position to understand the quality of the system's abstractions and how vigorously they're prepared to defend against unexpected behaviour. To approach this job, I would look at things in two directions. First, the top down approach, looking at the requirements and conversing with the stakeholders who may or may not know what they want. This is the business side of the game, important to understanding what the software must do. For everything else, I would take the bottom up approach, starting with the nuts and bolts. Along this route, you'll eventually meet you're your business path. Eventually, not immediately — this is an iterative approach to software architecture.
Showing posts with label code. Show all posts
Showing posts with label code. Show all posts
Monday, June 25, 2012
Friday, November 12, 2010
API Documentation
Creating API documentation is a tedious task at best. Automating this process removes most drudgery involved. Programmers glimpse at API documentation at several points throughout the day. We do this to confirm doubts or to make sure that the function was in fact returning an integer type. Not only does automated documentation generation safe us effort, it is also a time saver. Is there a need for human intervention, given that we have tools at our disposal to write API documentation for us? Are the tools really that good? And if not, if they're still lacking in one respect or another, will they ever replace us entirely?
What exactly do automatic code generators do? Put simply, they collect oodles of software system information and render it in a programmer-friendly format. The basic idea is to parse the source code tree of the project and write the documentation output. The format of the documentation can be anything really, but common forms are PDF and HTML. HTML is probably the best in most situations as it is easier to navigate and usually looks better.
Automatically generated API documentation depends largely on code higher-level code structures, not necessarily the low-level file operations and so-on. Modules, classes, and functions are the preeminent descriptions that make API documentation useful. Finer details about these high-level units can also be included by the documentation generator. Function parameters, return types, and class attributes - all relevant things programmers want to read about.
We annotate these these high-level language constructs using comments which are also captured by some of these documentation-generating tools. If you use Python, you have the added privilege doc-strings, which are part of the code objects themselves. In either case, you, the developer, have the ability to extend the content of the generated API documentation. You're effectively writing documentation and code at the same time. Sounds great, doesn't it? The difficulty with this approach is intent. Are code documentation and API documentation the same thing?
Documenting code is all about explaining the "nitty-gritty" to those with the misfortune of reading your code. You've agonized over strenuous details and need to walk any reading eyes through it. Probably this isn't the kind of thing we care to see in API documentation. If I need to look up something specific in the API documentation, I don't want to be bothered by big chunks of "this attribute needs to be reset after the....". Encapsulation also applies to documentation.
How do programmers format the comments lifted from the code by generators? Documentation tools do a fine job of formatting language constructs like classes, functions, variables, etc. What they can't do is format text embedded inside an explanation. In the documentation of a function, I'll sometimes want to see a brief paragraph that tells me why the state of the file object stored in an output stream queue changes. It is helpful to format text inside these explanations as well as link to other documents. A popular format for writing API documentation seems to be reStructuredText. What this amounts to is programmers using a markup language within the programming language. This adds an unnecessary burden - especially since comments should be geared more toward the low-level.
There really is no substitute for automatically generating the code structure used in API documentation. The only alternative is to do it manually, which is excessively tedious. But at the same time manually writing the API documentation gives you freedoms you don't necessarily have when generating it via code comments. For one thing, you're not legally bound for life to a single tool. You can format as you deem necessary. You're also not restricted by the configuration constraints generation tools impose - you can document as much or as little code as you want. Whichever method you choose, just be sure that good documentation is the result.
What exactly do automatic code generators do? Put simply, they collect oodles of software system information and render it in a programmer-friendly format. The basic idea is to parse the source code tree of the project and write the documentation output. The format of the documentation can be anything really, but common forms are PDF and HTML. HTML is probably the best in most situations as it is easier to navigate and usually looks better.
Automatically generated API documentation depends largely on code higher-level code structures, not necessarily the low-level file operations and so-on. Modules, classes, and functions are the preeminent descriptions that make API documentation useful. Finer details about these high-level units can also be included by the documentation generator. Function parameters, return types, and class attributes - all relevant things programmers want to read about.
We annotate these these high-level language constructs using comments which are also captured by some of these documentation-generating tools. If you use Python, you have the added privilege doc-strings, which are part of the code objects themselves. In either case, you, the developer, have the ability to extend the content of the generated API documentation. You're effectively writing documentation and code at the same time. Sounds great, doesn't it? The difficulty with this approach is intent. Are code documentation and API documentation the same thing?
Documenting code is all about explaining the "nitty-gritty" to those with the misfortune of reading your code. You've agonized over strenuous details and need to walk any reading eyes through it. Probably this isn't the kind of thing we care to see in API documentation. If I need to look up something specific in the API documentation, I don't want to be bothered by big chunks of "this attribute needs to be reset after the....". Encapsulation also applies to documentation.
How do programmers format the comments lifted from the code by generators? Documentation tools do a fine job of formatting language constructs like classes, functions, variables, etc. What they can't do is format text embedded inside an explanation. In the documentation of a function, I'll sometimes want to see a brief paragraph that tells me why the state of the file object stored in an output stream queue changes. It is helpful to format text inside these explanations as well as link to other documents. A popular format for writing API documentation seems to be reStructuredText. What this amounts to is programmers using a markup language within the programming language. This adds an unnecessary burden - especially since comments should be geared more toward the low-level.
There really is no substitute for automatically generating the code structure used in API documentation. The only alternative is to do it manually, which is excessively tedious. But at the same time manually writing the API documentation gives you freedoms you don't necessarily have when generating it via code comments. For one thing, you're not legally bound for life to a single tool. You can format as you deem necessary. You're also not restricted by the configuration constraints generation tools impose - you can document as much or as little code as you want. Whichever method you choose, just be sure that good documentation is the result.
Friday, April 23, 2010
Designing Code
Designing code is one of the most essential jobs of a programmer. That is, programmers do more than just design code. They also write it, document it, and read it. Hence, the term writing code. You never hear a programmer say they're going to spend some time designing code. It is writing code that matters. You could design software for several months and it wouldn't make a world of difference in the mind of a programmer. If no code has been written, no progress has been made.
This is where programmers actually are designing, while they are writing code. When they are sitting there with an editor open, they can see what needs to happen in order to solve the problem at hand. In fact, it is even easier for programmers to debug existing code rather than start from scratch and right something completely new. There is something about code that enables us to see structural and behavioral design and that serves as a reference in our mind.
But every programmer has a different logical representation of the system at hand in their own mind. Two perfectly acceptable solutions to a given problem may be completely incorrect to two opposing programmers. How can this be? Even in the same programming language, two wildly differing solutions are available to solve the same problem. The problem is that in software development, the problem at hand is never just the problem given to us. There are too many environments in the computer universe in which software may run.
These problems given to programmers to solve are only the half of it. The stakeholders really don't care that system X doesn't support interpreter Y and therefore cannot use language feature Z. Programmers will find a way around these limitations. But the problem is that unless you are the programmer doing the implementation, you really can't wrap your head around the full details of implementing a full solution. It really comes down to the fundamental software development concept of having a separation of concerns. Stakeholders in software development projects don't necessarily need to know all the low-level implementation details. They just need to be aware that they exist.
This isn't always the case with stakeholders. Imagine you had an environment in which to implement their solution aligned with what the stakeholders sometimes envision; you write the code to solve their problem and there are no implementation surprises. In a scenario like that, writing code to directly solve their problem is a feasible approach. But that will most definitely not happen any time soon, if ever. So in the mean time, we are stuck dealing with implementation details that fall outside the scope of the business problem.
When programmers write code, they have two tightly-coupled problems. There is the problem of making the software do what it was intended to do, the business problem. There is also the problem of the the other, unforeseen implementation details, the implementation problem. When we begin to write code for the business problem, the implementation problem doesn't really exist yet. How can it? These are unanticipated problems. They don't come into being until you can see them. This makes sense to a certain extent because if you start thinking about potential implementation problems too much before some design activities have started, no code would ever be written.
So what is the real benefit to separating these two problems, if any? It doesn't seem very obvious what the exact benefit of separating the business problem from the implementation details is at first. But one problem with not doing so is apparent. Since implementation detail problems do not really exist until the code is being written, they often affect the business problem implementation once they come about. That is, if a programmer spends time designing some ideal code for the business problem, depending on how specific that design is, an implementation detail problem could put the whole design in jeopardy.
Since code is so tightly coupled with the implementation of a running system, a good way to represent the business problem is with a model. A model is not part of the running system but it is an artifact of the process used to create the running system. UML models are a good way to represent any given software system. They can show almost any level of detail one might be interested in seeing. There is, however, a similar problem with models. You have the ability to start getting into implementation details.
This goes to show that modeling your code before actually writing it isn't a magic way to fix your code design. The common problem with creating models is that they tend to evolve too quickly without writing any code. If the level of specificity in your model gets too high, you've not only taken a waterfall approach but you're also taking a risky path by assuming there will not be any seemingly small implementation issues. Models are a good way to start off the business domain model as long as they are general enough. The level of specificity cannot be too high before code is written. Even then, it doesn't need to delve into too much detail just for the sake of it. Model details are better left out until they become a requirement.
Now lets take a step back and think about this for a moment. We now have a business problem that we're going to solve with software. In order to build this software, we need to write code that will implement the solution to the business problem. We know that there are going to be changes because our computing environments are disparate enough that we has humans cannot predict exactly how our code will behave. In order to help distance our business problem from any potential implementation problems, we build a high-level model of the business problem.
We should now be all set to start coding and hope for the best, right? Starting to code is definitely the right answer. Hoping for the best suggests an uncontrolled level of uncertainty. This can be at least somewhat controlled by expecting unexpected implementation details. Remember that your code and your model will always change throughout iterations of the project. The model you build will also have some overlap with the implementation. This is necessary unless the stakeholders are only expecting a model of the software and not the software itself.
Once these implementation detail issues do exist, is it worth modeling these issues? Only if it is separated from the business problem within the model somehow. It might even make more sense to create a completely separate model for implementation details. But only if it adds value. Modeling the nuances of implementing software isn't an exact science because chances are, these same details will become irrelevant in five years.
To sum this all up, remember that there is value in upfront code design centered around the business problem at hand. This doesn't necessarily mean modeling, it could be as straightforward as prototyping a command line interface simply for the purpose of testing how well the abstractions in your domain work. Modeling does offer a visual design aspect that often cannot be gleaned from code itself.
This is where programmers actually are designing, while they are writing code. When they are sitting there with an editor open, they can see what needs to happen in order to solve the problem at hand. In fact, it is even easier for programmers to debug existing code rather than start from scratch and right something completely new. There is something about code that enables us to see structural and behavioral design and that serves as a reference in our mind.
But every programmer has a different logical representation of the system at hand in their own mind. Two perfectly acceptable solutions to a given problem may be completely incorrect to two opposing programmers. How can this be? Even in the same programming language, two wildly differing solutions are available to solve the same problem. The problem is that in software development, the problem at hand is never just the problem given to us. There are too many environments in the computer universe in which software may run.
These problems given to programmers to solve are only the half of it. The stakeholders really don't care that system X doesn't support interpreter Y and therefore cannot use language feature Z. Programmers will find a way around these limitations. But the problem is that unless you are the programmer doing the implementation, you really can't wrap your head around the full details of implementing a full solution. It really comes down to the fundamental software development concept of having a separation of concerns. Stakeholders in software development projects don't necessarily need to know all the low-level implementation details. They just need to be aware that they exist.
This isn't always the case with stakeholders. Imagine you had an environment in which to implement their solution aligned with what the stakeholders sometimes envision; you write the code to solve their problem and there are no implementation surprises. In a scenario like that, writing code to directly solve their problem is a feasible approach. But that will most definitely not happen any time soon, if ever. So in the mean time, we are stuck dealing with implementation details that fall outside the scope of the business problem.
When programmers write code, they have two tightly-coupled problems. There is the problem of making the software do what it was intended to do, the business problem. There is also the problem of the the other, unforeseen implementation details, the implementation problem. When we begin to write code for the business problem, the implementation problem doesn't really exist yet. How can it? These are unanticipated problems. They don't come into being until you can see them. This makes sense to a certain extent because if you start thinking about potential implementation problems too much before some design activities have started, no code would ever be written.
So what is the real benefit to separating these two problems, if any? It doesn't seem very obvious what the exact benefit of separating the business problem from the implementation details is at first. But one problem with not doing so is apparent. Since implementation detail problems do not really exist until the code is being written, they often affect the business problem implementation once they come about. That is, if a programmer spends time designing some ideal code for the business problem, depending on how specific that design is, an implementation detail problem could put the whole design in jeopardy.
Since code is so tightly coupled with the implementation of a running system, a good way to represent the business problem is with a model. A model is not part of the running system but it is an artifact of the process used to create the running system. UML models are a good way to represent any given software system. They can show almost any level of detail one might be interested in seeing. There is, however, a similar problem with models. You have the ability to start getting into implementation details.
This goes to show that modeling your code before actually writing it isn't a magic way to fix your code design. The common problem with creating models is that they tend to evolve too quickly without writing any code. If the level of specificity in your model gets too high, you've not only taken a waterfall approach but you're also taking a risky path by assuming there will not be any seemingly small implementation issues. Models are a good way to start off the business domain model as long as they are general enough. The level of specificity cannot be too high before code is written. Even then, it doesn't need to delve into too much detail just for the sake of it. Model details are better left out until they become a requirement.
Now lets take a step back and think about this for a moment. We now have a business problem that we're going to solve with software. In order to build this software, we need to write code that will implement the solution to the business problem. We know that there are going to be changes because our computing environments are disparate enough that we has humans cannot predict exactly how our code will behave. In order to help distance our business problem from any potential implementation problems, we build a high-level model of the business problem.
We should now be all set to start coding and hope for the best, right? Starting to code is definitely the right answer. Hoping for the best suggests an uncontrolled level of uncertainty. This can be at least somewhat controlled by expecting unexpected implementation details. Remember that your code and your model will always change throughout iterations of the project. The model you build will also have some overlap with the implementation. This is necessary unless the stakeholders are only expecting a model of the software and not the software itself.
Once these implementation detail issues do exist, is it worth modeling these issues? Only if it is separated from the business problem within the model somehow. It might even make more sense to create a completely separate model for implementation details. But only if it adds value. Modeling the nuances of implementing software isn't an exact science because chances are, these same details will become irrelevant in five years.
To sum this all up, remember that there is value in upfront code design centered around the business problem at hand. This doesn't necessarily mean modeling, it could be as straightforward as prototyping a command line interface simply for the purpose of testing how well the abstractions in your domain work. Modeling does offer a visual design aspect that often cannot be gleaned from code itself.
Labels:
code
,
design
,
modeling
,
programming
,
uml
Thursday, April 22, 2010
Cheating Computer Science
Apparently new computer science students these days love to cheat. I wonder how this will affect these students once they have completed school and have jobs. Will this rigorous process of plagiarism detection lead to less code reuse and constantly reinventing the wheel?
Thursday, April 15, 2010
Programming Sprints
Here is an interesting question, how many hours in a given week can you program? If you've got your head down and the code is just flowing out nicely, it isn't difficult to be very productive for hours at a time. But these sprints come in bursts. This code inspiration needs to come from somewhere. That is the other part of programming that isn't viewed as productivity. I'd say at least half, if not more, of a programmers time is devoted to reading. Either other code, a specific technology, technology in general, or something completely unrelated. Code sprints are spawned from doing this, not perpetually writing code.
Labels:
code
,
development
,
programming
,
reading
,
sprint
Thursday, April 8, 2010
The Face Of Bad Code
Lets face it, we've all written bad code at one point or another. If we hadn't, we probably would never release any functional software. Remember, code that isn't ideal doesn't equate to code that doesn't run and help someone else accomplish some task. Code can always be re-factored, and, it should be re-factored.
I often find myself testing my own software from and end user perspective and thinking about the code that is running when I perform certain actions. I think "well, it works, but just barely". I have to force myself to think "well, it works, and that is all the user cares about; it can be re-factored later".
Don't be tempted to re-factor before you get something functional into the hands of the end users. Make notes on what doesn't work well and fix it in conjunction with the user-provided feedback. If you don't release, you don't get the feedback. Only you as the developer know what needs to be re-factored, only the end user knows how well your software solves their problem.
I often find myself testing my own software from and end user perspective and thinking about the code that is running when I perform certain actions. I think "well, it works, but just barely". I have to force myself to think "well, it works, and that is all the user cares about; it can be re-factored later".
Don't be tempted to re-factor before you get something functional into the hands of the end users. Make notes on what doesn't work well and fix it in conjunction with the user-provided feedback. If you don't release, you don't get the feedback. Only you as the developer know what needs to be re-factored, only the end user knows how well your software solves their problem.
Tuesday, April 6, 2010
Optimizing For Readability
How does one measure the readability of a given piece of code? What makes this especially challenging is that developers all have their own unique preferences and style when it comes to reading and writing source code. But readability isn't necessarily the same thing as coding style. Readability should trump style preference.
There are certain aspects of code that make it readable. For instance, meaningful variable names aren't that hard to come up with and make a world of difference when someone else needs to read your code. Adding some space rather than cramming constructs together will always increase readability. At the same time, however, conciseness is always a readability enhancement.
Simple things add up in the long run. There are only larger structural pieces of code that affect code readability. For instance, the location of a class, the modularity affects the difficulty of locating things. These are larger concepts that are more closely related to style than readability. Readability in this context refers to what the developer can see on the screen at any given time.
There are certain aspects of code that make it readable. For instance, meaningful variable names aren't that hard to come up with and make a world of difference when someone else needs to read your code. Adding some space rather than cramming constructs together will always increase readability. At the same time, however, conciseness is always a readability enhancement.
Simple things add up in the long run. There are only larger structural pieces of code that affect code readability. For instance, the location of a class, the modularity affects the difficulty of locating things. These are larger concepts that are more closely related to style than readability. Readability in this context refers to what the developer can see on the screen at any given time.
Labels:
code
,
development
,
programming
,
readability
,
style
Wednesday, March 10, 2010
Code Bubbles
The Code Bubbles project looks like an incredibly cool way to edit code. Rather than have to navigate through an editor, it groups code elements into bubbles. There is much more to it than that but the general idea of better grouping programming language constructs in the IDE seems like a good idea to me.
After watching the demo, I can see a nice UML integration point for Code Bubbles.
After watching the demo, I can see a nice UML integration point for Code Bubbles.
Labels:
code
,
codebubbles
,
ide
,
prgramming
,
uml
Monday, March 1, 2010
Math And Code Design
I was reading about the debate on math education reform in Scientific American and the argument for giving kids more context in which to apply theory is similar to applying the re-factoring approach to software development. Trying to design perfect software the first time around is an exercise in futility. Better to quickly bang something out that works, then go back and re-factor the code so that it is better designed. This way, you have a real-world context as well as real-world constraints in which to design your existing code. Maybe this approach isn't suited well for learning math concepts but it certainly couldn't hurt in introductory programming classes.
Labels:
code
,
design
,
development
,
math
,
refactoring
Monday, January 4, 2010
Documenting Code
There are many reasons why developers are told to document their code. As Jason Baker shows, many of these common reasons for commenting code are mythical. That is to say, the added benefit for documenting a piece of code may be misguided in certain contexts.
For instance, comments need to be updated as the code is updated. This means more in-depth maintenance for comments. Unless you strive to keep comments simple and generic enough. This is usually the best approach.
Often, the best way to document your code is to spend a short amount of time and overview your code as though you were someone else. If that person needs an explanation for some section of code, give it to them. But keep it simple.
You can still document trivial methods that are self explanatory. The best reason for doing this is consistency.
For instance, comments need to be updated as the code is updated. This means more in-depth maintenance for comments. Unless you strive to keep comments simple and generic enough. This is usually the best approach.
Often, the best way to document your code is to spend a short amount of time and overview your code as though you were someone else. If that person needs an explanation for some section of code, give it to them. But keep it simple.
You can still document trivial methods that are self explanatory. The best reason for doing this is consistency.
Labels:
code
,
commonsense
,
documentation
,
myth
,
simple
Sunday, January 3, 2010
Simple Code Editors
This question on Slashdot asks about VIM text editing capabilities in more modern integrated development environments. The answers to the question seems to indicate that a number of options are available for those that want to bring development capabilities to newer code editors.
So, is it that we want to bring enhanced text editing capabilities, that have worked for years with VIM, into an IDE? Or should this text-editing capability be brought to the more modest code editors, not necessarily IDEs.
In most cases, integrated development environments get in the way more than they lend a hand in producing quality code. In other, niche, cases, they can be the perfect tool for the job.
So what is wrong with VIM exactly? Nothing. That is, there is nothing wrong with VIM for using it as a simple code editor. It just so happens that simple code editors are in huge demand these days and so VIM is still the editor of choice for many developers for its advanced text editing capabilities.
I find the main beneficial feature that newer code editors bring to the table are hierarchical class navigators. It isn't a matter of being able to navigate by class; VIM can do that. It is more a matter of being able to visualize the classes in the given more you are editing.
So, is it that we want to bring enhanced text editing capabilities, that have worked for years with VIM, into an IDE? Or should this text-editing capability be brought to the more modest code editors, not necessarily IDEs.
In most cases, integrated development environments get in the way more than they lend a hand in producing quality code. In other, niche, cases, they can be the perfect tool for the job.
So what is wrong with VIM exactly? Nothing. That is, there is nothing wrong with VIM for using it as a simple code editor. It just so happens that simple code editors are in huge demand these days and so VIM is still the editor of choice for many developers for its advanced text editing capabilities.
I find the main beneficial feature that newer code editors bring to the table are hierarchical class navigators. It isn't a matter of being able to navigate by class; VIM can do that. It is more a matter of being able to visualize the classes in the given more you are editing.
Labels:
code
,
editor
,
hierarchical
,
ide
,
simple
Wednesday, December 2, 2009
Ugly Comments
This entry over at IT world talks about ugly comments in code and what that means about the code itself. Well, the basic assumption made is that if the comments in the code are ugly, so is the code. This assumption is derived from the principle of attention to detail. This attention to detail required by the programmers who write the code are not exempt from focusing attention to comments.
The problem is that the functional code and the non-functional comments really aren't all that different. I would argue that the comments are as much a part of the running program as the functional code is. They live in the same source files and are one in the same.
Writing great code doesn't really solve the problem of crappy comments either. In fact, the better the code, the more the sub-par comments will stick out. This doesn't mean going into great depths in annotating a piece of functionality. That will often add to the confusion. Go into depth explaining things outside of the source file. Make your comments in the source files concise but complete. Correct spelling doesn't hurt either.
The problem is that the functional code and the non-functional comments really aren't all that different. I would argue that the comments are as much a part of the running program as the functional code is. They live in the same source files and are one in the same.
Writing great code doesn't really solve the problem of crappy comments either. In fact, the better the code, the more the sub-par comments will stick out. This doesn't mean going into great depths in annotating a piece of functionality. That will often add to the confusion. Go into depth explaining things outside of the source file. Make your comments in the source files concise but complete. Correct spelling doesn't hurt either.
Labels:
code
,
comments
,
meaning
,
prgramming
,
ugly
Friday, October 16, 2009
When To Generate Code
Code generation can be a blessing, a complete nightmare, or a combination of both for developers. It is a blessing when the right tools and the right know-how are employed. It is a nightmare when the wrong tool is used and much time has been vested in it. It is both a blessing and a nightmare when all appears to be going well until the maintenance of the code become unmanageable.
The whole point of using code generation in the first place is to eliminate the need for developers having to write mundane, boiler-plate code. Another use, although still considered boiler-plate in most circumstances, is generating GUI code. Many GUI builder tools allow for this in many programming languages.
Whether the boiler-plate code was generated by a UML modeling tool or by a GUI builder tool, the generated code should be imported by some other application module. This is necessary in order to promote isolation between the generate code and the human-designed code. The hand-crafted stuff created by a human developer usually doesn't interact well with the generated stuff. It is always going to make more sense to let the developer find a way to make the generated code work with the other application code. The reverse isn't true; the generated code isn't smart enough to work with the developer code.
So the use case for code generation is quite obvious; to save development time. In the case of developing user interface code, it is nearly impossible to maintain due to the level of verbosity. This is necessary and there really isn't any way around it other than to maintain the user interface graphically with a design tool that generates the code. So always generate GUI code, but always import it.
The classes associated with the problem domain generally store data and don't much behavior if any. These classes are good candidates for code generation. The reason being that the lack of behavior is a good thing when it comes to behavior. This is because the code that is being generated is a static artifact and the code it contains should be mostly conceptually static. Attempting to implement behavior inside a model that is then transformed into running code is a bad idea because method signatures aren't trivial to maintain and because behavior generally grows more complex.
The whole point of using code generation in the first place is to eliminate the need for developers having to write mundane, boiler-plate code. Another use, although still considered boiler-plate in most circumstances, is generating GUI code. Many GUI builder tools allow for this in many programming languages.
Whether the boiler-plate code was generated by a UML modeling tool or by a GUI builder tool, the generated code should be imported by some other application module. This is necessary in order to promote isolation between the generate code and the human-designed code. The hand-crafted stuff created by a human developer usually doesn't interact well with the generated stuff. It is always going to make more sense to let the developer find a way to make the generated code work with the other application code. The reverse isn't true; the generated code isn't smart enough to work with the developer code.
So the use case for code generation is quite obvious; to save development time. In the case of developing user interface code, it is nearly impossible to maintain due to the level of verbosity. This is necessary and there really isn't any way around it other than to maintain the user interface graphically with a design tool that generates the code. So always generate GUI code, but always import it.
The classes associated with the problem domain generally store data and don't much behavior if any. These classes are good candidates for code generation. The reason being that the lack of behavior is a good thing when it comes to behavior. This is because the code that is being generated is a static artifact and the code it contains should be mostly conceptually static. Attempting to implement behavior inside a model that is then transformed into running code is a bad idea because method signatures aren't trivial to maintain and because behavior generally grows more complex.
Labels:
architecture
,
code
,
design
,
generation
,
uml
Thursday, October 8, 2009
Self Assuring Code
The notion of self assuring code sounds a little like a spin on writing code that incorporates well-written exception handling. This is probably true for the most part but if exception handling can be taken up a notch, developers can build programs that are resilient beyond expectations.
One way to write self assuring code is to do just that; write exceptions handling code for just about every possible exception that might be raised. Exception handling works great for handling any type of exceptional occurrence such as type errors. Custom exceptions are another common construct in many exception handling implementations. The custom exception classes typically inherit from the primitive error types of the implementation language. What is useful about this approach is that the developer is extending the notion of what constitutes an exceptional occurrence.
Something that even the best exception handling cannot do is give the same type of feedback to the developer that is brought about by quality assurance that is brought about by human test users. This is especially effective if the users have never used the software before. This is because there is no bias involved. These users haven't had questionable experiences in certain parts of the application and are not lenient if it just barely works.
Is it even possible then, to have self assuring code? Can developers take exception handling to the next level and build it into the code? Think of trying to find a really difficult bug. What does the developer do? They put debug log messages in places that don't necessarily make sense. But as most developers know, it is these messages, these just by change debug notes in strange places that often end up solving the problem.
The question becomes, how elaborate must these exceptions become? Do they try and predict future failures best on how well the current execution is going? Maybe. This whole idea is very context dependent. But experimentation with creative exceptions might be worth exploring.
One way to write self assuring code is to do just that; write exceptions handling code for just about every possible exception that might be raised. Exception handling works great for handling any type of exceptional occurrence such as type errors. Custom exceptions are another common construct in many exception handling implementations. The custom exception classes typically inherit from the primitive error types of the implementation language. What is useful about this approach is that the developer is extending the notion of what constitutes an exceptional occurrence.
Something that even the best exception handling cannot do is give the same type of feedback to the developer that is brought about by quality assurance that is brought about by human test users. This is especially effective if the users have never used the software before. This is because there is no bias involved. These users haven't had questionable experiences in certain parts of the application and are not lenient if it just barely works.
Is it even possible then, to have self assuring code? Can developers take exception handling to the next level and build it into the code? Think of trying to find a really difficult bug. What does the developer do? They put debug log messages in places that don't necessarily make sense. But as most developers know, it is these messages, these just by change debug notes in strange places that often end up solving the problem.
The question becomes, how elaborate must these exceptions become? Do they try and predict future failures best on how well the current execution is going? Maybe. This whole idea is very context dependent. But experimentation with creative exceptions might be worth exploring.
Sunday, September 20, 2009
HTTP Response Schema
The HTTP protocol is by far the most prominent protocol on the web today. Most people browsing the web aren't even aware of its existence. They just see a strange "http://" string in front of where they want to go. The great part is that most users of the web don't need to know what HTTP is or how it works. The browser and the web server have a firm understanding of how to use the protocol.
Web clients, including the browser need to understand how to handle HTTP responses. Contained within each HTTP response is a numeric code indicating the status of the request. Although HTTP is a stateless protocol, the client needs to know what happened with each request made to the server. One may consider the response code to be a meta state. The response code can still support statelessness on the server.
Each HTTP response code has a distinct explanation for why the requested responded the way it did. The client can also interpret a more general category, or nature of the response because of the ranges in which each specific code falls under. Here is a brief idea of what the ranges mean:
• 200 - Success.
• 300 - Client action required.
• 400 - Client error.
• 500 - Server error.
In an object-oriented design, these ranges of HTTP response codes can be broadly generalized. This helps to conceptualize how the client can handle several specific response codes in the same way as is illustrated below.
Web clients, including the browser need to understand how to handle HTTP responses. Contained within each HTTP response is a numeric code indicating the status of the request. Although HTTP is a stateless protocol, the client needs to know what happened with each request made to the server. One may consider the response code to be a meta state. The response code can still support statelessness on the server.
Each HTTP response code has a distinct explanation for why the requested responded the way it did. The client can also interpret a more general category, or nature of the response because of the ranges in which each specific code falls under. Here is a brief idea of what the ranges mean:
• 200 - Success.
• 300 - Client action required.
• 400 - Client error.
• 500 - Server error.
In an object-oriented design, these ranges of HTTP response codes can be broadly generalized. This helps to conceptualize how the client can handle several specific response codes in the same way as is illustrated below.
Friday, August 28, 2009
Making Deadlines
Lets face it, in the software development world, there are unrealistic deadlines that need to be met. This entry talks about some dirty coding tricks that were necessary to meet a deadline. Although these types of tricks would make any rational developer recoil in disgust, they are sometimes necessary. In fact, most production software isn't ideal code wise. Ask any developer who has code running in the wild if they would like to re-factor at least a portion of that code. Odds are that you'll find many.
Is there an acceptable limit to exactly how dirty these tricks can be in order to meet a deadline? Some dirty coding tricks are so horrific that fixing the repercussions of them in the future will be a project on its own. However, all that matters is shipping the software on time. And that it works. So if crossing some kind of ugly code threshold results in shipping on time, do it. Otherwise, you may not get a chance to re-factor that code later on.
And, lessons can be learned about the project as a whole when resorting to dirty code tricks. These lessons can impose new constraints and new policies on future releases.
Is there an acceptable limit to exactly how dirty these tricks can be in order to meet a deadline? Some dirty coding tricks are so horrific that fixing the repercussions of them in the future will be a project on its own. However, all that matters is shipping the software on time. And that it works. So if crossing some kind of ugly code threshold results in shipping on time, do it. Otherwise, you may not get a chance to re-factor that code later on.
And, lessons can be learned about the project as a whole when resorting to dirty code tricks. These lessons can impose new constraints and new policies on future releases.
Friday, August 14, 2009
Enhanced Code Completion
Most modern development environments for virtually any programming language come complete with code completion. What exactly is code completion? Code completion makes developers life easier by giving them names to select from when typing the beginning of the name. So, for instance, if you were to start typing the name of a class "My", the editor would then give you a list of names that begin with "My", allowing you to select the name you want to use. It makes their life easier by recognizing that they are attempting to use a name that is defined in the current context such as a class or function name. Code completion also works when developers attempt to use members of a class such as attributes or methods. Once the developers engages the dot notation, the code completion engine is able to present the developer with the available members of that class or instance.
So is this as productive as it gets in regards to code completion? I think code completion in open source development environments could be enhanced. Geany serves as an example of how code completion could be enhanced. If a developer already has a function or method name is use, then the developer should be able to edit sections of the name and be presented with a list of available names. A common scenario is to change the prefix of a name. This however, will not give the developer a list of choices in most editors.
So is this as productive as it gets in regards to code completion? I think code completion in open source development environments could be enhanced. Geany serves as an example of how code completion could be enhanced. If a developer already has a function or method name is use, then the developer should be able to edit sections of the name and be presented with a list of available names. A common scenario is to change the prefix of a name. This however, will not give the developer a list of choices in most editors.
Labels:
code
,
codecompletion
,
development
,
enhancement
,
geany
,
ide
Friday, July 10, 2009
How To Volunteer Code
Have you ever had someone ask you what open source is all about? Once you tell them, do they in turn ask why would people volunteer their time for free? The latter is a much more difficult question to answer because more often than not, you have to be part of the open source community to "get it". Some people might answer along the lines of "its a cause we are fighting for" or "I simply don't like Microsoft". The good news is that you don't really need a justifiable reason for becoming part of the open source community. One answer to the question of why bother contributing my efforts to the open source community that isn't likely to be heard that often is that it is a world leading learning environment for technology. Open source is, well, open. So, by that virtue alone, one can take the necessary steps to learn. If you have a question about some aspect of some project, it is there for you to figure out on your own if need be.
Trying to dive right into open source project source code may not be the best approach to newcomers to the open source community. If not, then how do people get started with open source? The thing is, the method in which to contribute something back to the community varies on a project to project basis. This can be both good and bad. It is good because there are no restrictions on the development methodology used and other annoying restrictions found in proprietary environments. It is bad because some projects do a great job of letting newcomers know how they can contribute and other projects not so much. As for the projects that don't make clear how additional help could be applied, it is unfortunate since there are many very talented developers out there who are just getting started in their careers. If they would like to put their skills to use in the open source community but don't have a good starting point, those skills are waisted.
Also, as discussed here, There is also the prospect of starting a new open source project. This is another challenging problem since identifying valuable problems in which to solve in the open source world isn't easy. Another problem is there aren't any learning resources from other developers when starting a new project. The lack of mentors available isn't a big a problem for more experienced developers who start their own open source projects. However, younger, inexperienced developers might have a rough go of it own their own.
The best way to join an existing project of interest is simply to ask. But also give those concerned an idea of what you are capable of at the same time. This will also give you an indicator of what working with this particular community would be like.
Lastly, people can also volunteer data as is described here. This is geared toward non-developers who have an interest in contributing to the open source community.
Trying to dive right into open source project source code may not be the best approach to newcomers to the open source community. If not, then how do people get started with open source? The thing is, the method in which to contribute something back to the community varies on a project to project basis. This can be both good and bad. It is good because there are no restrictions on the development methodology used and other annoying restrictions found in proprietary environments. It is bad because some projects do a great job of letting newcomers know how they can contribute and other projects not so much. As for the projects that don't make clear how additional help could be applied, it is unfortunate since there are many very talented developers out there who are just getting started in their careers. If they would like to put their skills to use in the open source community but don't have a good starting point, those skills are waisted.
Also, as discussed here, There is also the prospect of starting a new open source project. This is another challenging problem since identifying valuable problems in which to solve in the open source world isn't easy. Another problem is there aren't any learning resources from other developers when starting a new project. The lack of mentors available isn't a big a problem for more experienced developers who start their own open source projects. However, younger, inexperienced developers might have a rough go of it own their own.
The best way to join an existing project of interest is simply to ask. But also give those concerned an idea of what you are capable of at the same time. This will also give you an indicator of what working with this particular community would be like.
Lastly, people can also volunteer data as is described here. This is geared toward non-developers who have an interest in contributing to the open source community.
Labels:
code
,
community
,
contribute
,
opensource
,
volunteer
Tuesday, March 3, 2009
ECP and the ActualMachine
The ActualMachine class in the Enomaly Elastic Computing platform is the abstraction layer that interacts with Libvirt to control virtual machines. Not every method of this class interacts with Libvirt directly. In fact, most methods in the ActualMachine class don't directly interact with Libvirt. There are plenty of methods in this class. The ECP development team is in agreement that this number can certainly be brought down to something a little more cohesive.
To start, we'd like to focus on maintaining the handful of ActualMachine methods that interact directly with Libvirt. As an example, the shutdown() method directly interacts with Libvirt. This is necessary in order to shutdown the virtual machine.
The reason we are going to tackle these Libvirt-coupled methods first is because they are absolutely critical to ECP. Without a clear understanding of how these primitive abstractions behave, we hit a brick wall. I think the ActualMachine class gained a lot of weight in turns of the sheer number of methods because we didn't understand what was happening at the primitive level. By primitive, I mean the primitive reason for ActualMachine's existence. Once we are able to hammer out what it is that the ActualMachine is responsible for, we can lose a lot of the current functionality. Losing it is a good thing in this case. It will come back in a much nicer form.
For an idea of what is happening with the ActualMachine class, take a look at this.
To start, we'd like to focus on maintaining the handful of ActualMachine methods that interact directly with Libvirt. As an example, the shutdown() method directly interacts with Libvirt. This is necessary in order to shutdown the virtual machine.
The reason we are going to tackle these Libvirt-coupled methods first is because they are absolutely critical to ECP. Without a clear understanding of how these primitive abstractions behave, we hit a brick wall. I think the ActualMachine class gained a lot of weight in turns of the sheer number of methods because we didn't understand what was happening at the primitive level. By primitive, I mean the primitive reason for ActualMachine's existence. Once we are able to hammer out what it is that the ActualMachine is responsible for, we can lose a lot of the current functionality. Losing it is a good thing in this case. It will come back in a much nicer form.
For an idea of what is happening with the ActualMachine class, take a look at this.
Monday, March 2, 2009
Writing bad pseudo code
Is it possible to entirely screw up your design by writing bad pseudo code? I like to think so. Pseudo code is a useful tool for quickly jotting down a proposed solution to a problem you just thought of. But don't base your actual implementation on this pseudo code. Especially if you are developing in an object oriented language.
No matter what paradigm you use to develop software, pseudo code is an extremely powerful tool for quickly measuring the feasibility of an implementation to a specific problem. These problems are generally in the context of functions or short algorithms. It would be very hard to comprehend even trivial object oriented relationships using only pseudo code. If you develop using a functional language such as C, a series of flowcharts and pseudo code illustrations may suffice.
However, using an approach like this when the implementation involves an object oriented language such as C++ or Python, you will most assuredly run into problems. The UML is by far the superior approach to modeling object oriented systems. It covers the entire range of elements needed and is also extensible. However, it need not be the UML you use to visualize your system under construction. You can invent your own (as long as multiple readers wouldn't be an issue and it will). The important idea is that the elements you visualize be graphic shapes.
Here is where we run into problems with pseudo code. Pseudo code is generally tightly coupled to the implementation language. And when I say generally, I mean close to one hundred percent of the time. How often do developers write pseudo code without an implementation language in mind. Additionally, pseudo code can be written in implementation languages!
Lets say we already know we are writing a C application. So, during our design/implementation/testing, we can write pseudo code that is biased toward the C language. No harm done right? I would say that even in this scenario, you are likely to create bad pseudo code. Just because the it is pseudo, doesn't make it any less of a programming language. It only makes it less executable. I think when using pseudo code exclusively as a design tool for "real code", you are bound to miss important design issues that are not visible at this level of thought.
The superior approach, I think, is to start out by visually modeling some elements. Not the entire system, just some important functions, classes, or methods. Then, where things aren't clear, get down to the pseudo level. But don't spend any real time on it. Go back and forth. Visual modeling doesn't give developers any kind of immunity to design errors. I does, however, give a third floor view of the problem.
No matter what paradigm you use to develop software, pseudo code is an extremely powerful tool for quickly measuring the feasibility of an implementation to a specific problem. These problems are generally in the context of functions or short algorithms. It would be very hard to comprehend even trivial object oriented relationships using only pseudo code. If you develop using a functional language such as C, a series of flowcharts and pseudo code illustrations may suffice.
However, using an approach like this when the implementation involves an object oriented language such as C++ or Python, you will most assuredly run into problems. The UML is by far the superior approach to modeling object oriented systems. It covers the entire range of elements needed and is also extensible. However, it need not be the UML you use to visualize your system under construction. You can invent your own (as long as multiple readers wouldn't be an issue and it will). The important idea is that the elements you visualize be graphic shapes.
Here is where we run into problems with pseudo code. Pseudo code is generally tightly coupled to the implementation language. And when I say generally, I mean close to one hundred percent of the time. How often do developers write pseudo code without an implementation language in mind. Additionally, pseudo code can be written in implementation languages!
Lets say we already know we are writing a C application. So, during our design/implementation/testing, we can write pseudo code that is biased toward the C language. No harm done right? I would say that even in this scenario, you are likely to create bad pseudo code. Just because the it is pseudo, doesn't make it any less of a programming language. It only makes it less executable. I think when using pseudo code exclusively as a design tool for "real code", you are bound to miss important design issues that are not visible at this level of thought.
The superior approach, I think, is to start out by visually modeling some elements. Not the entire system, just some important functions, classes, or methods. Then, where things aren't clear, get down to the pseudo level. But don't spend any real time on it. Go back and forth. Visual modeling doesn't give developers any kind of immunity to design errors. I does, however, give a third floor view of the problem.
Labels:
architecture
,
code
,
design
,
opinion
,
pseudocode
Subscribe to:
Posts
(
Atom
)