Jerry Yoakum's thoughts on software engineering and architecture from experience working with code, computer science, python, java, APIs, NASA, data mining, math, etc.
Showing posts with label design. Show all posts
Showing posts with label design. Show all posts
Thursday, January 16, 2020
Communication Skills Are Essential
When recruiting personnel for your project, don't underestimate the importance of teamwork and communication. The best software architect becomes a poor asset if he or she is unable to communicate, convince, listen, and compromise.
Communication breakdowns can occur at any process level. The effects of these problems are not independent. For instance, fluctuating requirements increase a development team's need for communication both with customers and with the project's other teams.
Exceptional architects are skilled at communicating their technical vision to other project members. They usually possess exceptional communication skills and often spend much of their time educating others about the application domain and its mapping into computational structures. In fact, much of their design work is accomplished while interacting with others. The integrative role of an exceptional designer compounds itself. This happens because those perceived as most knowledgeable will become communication focal points, providing them more knowledge about the system to integrate into a more comprehensive model.
Reference:
Curtis, B., Krasner, H., and Iscoe, N., "A Field Study of the Software Design Process for Large Systems," Communications of the ACM, November 1988.
Labels:
architecture,
design,
management,
software-engineering
Location:
Springfield, MO, USA
Monday, January 07, 2019
Design Is Multidimensional
When designing a home, architects represent it in many ways to fully understand and convey its essence to builders, buyers of materials, and home buyers: elevations, floor plans, framing, trusses, electrical routing, plumbing routing, concrete shape, door and window framing details, and other points of view. The same is true of software design.
A complete software design includes at least:
- Packaging. Often drawn as a hierarchy chart, this captures "what is part of what?" It often implies data visibility. It also shows encapsulation, such as data and functions within objects.
- Needs hierarchy. This captures "who needs whom?" Drawn as a network of components, arrows indicate which components need something. The needs might be data, logic, or any other information.
- Invocation. This captures "who invokes whom?" Drawn as a network of components, arrows indicate which components "call," "interrupt," or "send messages to" others.
- Processes. Sets of components are packaged together as asynchronous processes. These are copies of components that are running simultaneously with other processes. Zero, one, or more copies may exist at one time. This should also specify conditions that cause a process to be created, executed, stopped, and destroyed.
Reference:
Witt, B., Baker, F., and Merritt, E., Software Architecture and Design, New York: Van Nostrand Reinhold, 1994.
Labels:
architecture,
design,
software-engineering
Location:
Springfield, MO, USA
Saturday, December 22, 2018
Provide All The Information The User Needs And Nothing More
A key part of the design process is the precise definition of each and every software component in the system. This specification will become the "public" part of the component. It must include everything a user needs, such as its purpose, its name, its method of invocation, and details of how it communicates with its environment. Anything that the user does not need should be specifically excluded. In most cases, the algorithms and internal data structures used should be excluded. For if these were "visible," users might utilize this information. Subsequent enhancement or modification then becomes profoundly more difficult because any change to the component has a cascading effect on all components that use it (related to encapsulation).
Reference:
Parnas, D., "A Technique for Software Module Specification with Examples," CACM (May 1972).
Labels:
architecture,
Chicago,
coder,
design,
requirements,
software-engineering
Location:
Springfield, MO, USA
Tuesday, December 04, 2018
Software Reliability Can Be Achieved Through Redundancy
In hardware systems, high reliability or availability (Specify Reliability Specifically) is often achieved through redundancy. Thus, if a system component is expected to exhibit a mean-time-between-failures of x, we can manufacture two or three such components and run them in either:
- Parallel. For example, they all do all the work and, when their responses differ, one is turned off with no impact on overall system functionality.
- Or cold standby. A backup computer might be powered on only when a hardware failure is detected in the operational computer.
Manufacturing cost is slightly more than doubled. Design cost increases slightly. Reliability increases exponentially.
In software systems, we cannot use the same approach. If we make two copies of the same software, no increase in reliability will be achieved. In one fails, the other will as well. What can be done, however, is to design (using two different design teams) two versions of the software from the same requirements specification, and deploy them in parallel. Development cost doubles. Reliability increases exponentially. Notice that, in the case of hardware, design increases in cost only slightly, whereas software design cost (the primary cost of software) doubles. Ultrahigh reliability in software is very expensive (High Quality Software Is Possible).
Reference:
Musa, J., et al., Software Reliability, New York: McGraw Hill, 1987.
Labels:
architecture,
design,
software-engineering
Location:
Springfield, MO, USA
Monday, December 03, 2018
"Garbage In, Garbage Out" Is Incorrect
Many people quote the expression "garbage in, garbage out" as if it were acceptable for software to behave like this. It is not. If a user provides invalid input data, the program should respond with an intelligent message that describes why the input was invalid. If a software component receives invalid data, it should not process it, but instead should return an error code back to the component that transmitted the invalid data. This mindset helps diminish the domino effect caused by software faults and makes it easier to determine error causes by 1) catching the fault early and 2) preventing subsequent data corruption.
Reference:
McConnell, S., Code Complete, Redmond, WA: Microsoft Press, 1993.
Labels:
design,
software-engineering
Location:
Springfield, MO, USA
Thursday, November 29, 2018
You Can Reuse Without A Big Investment
When salvaging you got to be the tug that pulls what you need to the surface. |
The most effective way to reuse software components is from a repository of crafted, handpicked libraries that were tailored specifically for reuse. However, this requires considerable investment in both time and money. It is possible to reuse in the short term through a technique called salvaging.
Salvaging is asking others in your organization if they have built a software component that does X. You find it, you adapt it, you employ it. This may not be efficient in the long term, but it certainly works now; and then you have no more excuses not to reuse.
To my experience, few organizations are willing to allocate time for the proper care and upkeep of a repository of reusable software components. Salvaging might be your only option. And it gets you talking to your peers on different teams. This communication is like grease that will make future interactions smoother.
Labels:
design,
software-engineering
Location:
Springfield, MO, USA
Wednesday, November 28, 2018
Know Your Application
No matter how well the requirements have been written, the selection of optimal architectures and algorithms is very much a function of knowing the unique characteristics of an application. Expected behavior under stress situations, expected frequency of inputs, life-critical nature of response times, likelihood of new hardware, impact of weather on expected system performance, and so on are all application-specific and often demand a specific subset of possible alternative architectures and algorithms.
Reference:
Curtis, B., et al, "A Field Study of the Software Design Process for Large Systems," CACM, November 1988.
Labels:
design,
Seattle,
software-engineering
Location:
Seattle, WA, USA
Thursday, April 26, 2018
Great Designs Come From Great Designers
The Design of Everyday Things
Labels:
Chicago,
design,
software-engineering
Location:
Chicago, IL, USA
Keep It Simple
A simple architecture or a simple algorithm goes a long way toward achieving high maintainability. Remember KISS. Also, as you decompose software into subcomponents, remember that people have difficulty comprehending more than seven (plus or minus two) things at once. C.A.R. Hoare has said:
There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies and the other is to make it so complicated that there are no obvious deficiencies.
Labels:
architecture,
design,
software-engineering
Location:
Springfield, MO, USA
Tuesday, April 17, 2018
Build Flexibility Into Software
A software component exhibits flexibility if it can be easily modified to perform its function (or a similar function) in a different situation. Flexible software components are more difficult to design than less flexible components. However, such components are more run-time efficient than general components and are more easily reused than less flexible components in diverse applications.
Labels:
architecture,
design,
Singapore,
software-engineering
Location:
Singapore
Monday, April 16, 2018
Build Generality Into Software
A software component exhibits generality if it can perform its intended functions without any change in a variety of situations. General software components are more difficult to design than less general components. They also usually run slower when executing. However, such components:
- Are ideal in complex systems where a similar function must be performed in a variety of places.
- Are more potentially reusable in other systems with no modification.
- Reduce maintenance costs for an organization due to reduced numbers of unique or similar components. Think about the hassle of maintaining multiple different repositories and build plans.
When decomposing a system into its subcomponents, stay cognizant of the potential for generality. Obviously, when a similar function is needed in multiple places, construct just one general function rather than multiple similar functions. Also, when constructing a function needed in just one place, build in generality where it makes sense - for future enhancements.
Labels:
architecture,
design,
software-engineering
Location:
Springfield, MO, USA
Friday, April 06, 2018
Transition from Requirements to Design Is Not Easy
Requirements engineering culminates in a requirements specification, a detailed description of the external behavior of a system. The first step of design synthesizes an optimal software architecture. There is no reason why the transition from requirements to design should be any easier in software engineering than in any other engineering discipline. Design is hard. Converting from an external view to an internal optimal design is fundamentally a difficult problem.
Some methods claim transition is easy by suggesting that we use the "architecture" of the requirements specification as the architecture. Since design is difficult here are three possibilities:
- No thought went into selecting an optimal design during requirements analysis. In this case, you cannot afford to accept the requirements specification implied design as the design.
- Alternative designs were enumerated and analyzed and the best was selected, all during requirements analysis. Organizations cannot afford the effort to do a thorough design (typically 30 to 40 percent of total development costs) prior to baselining requirements, making a make/buy decision, and making a development cost estimate.
- The method assumes that some architecture is optimal for all applications. This is clearly not possible.
Labels:
design,
software-engineering
Location:
Springfield, MO, USA
Thursday, April 05, 2018
Trace Design to Requirements
All these needs can be satisfied by the creation of a table with rows corresponding to all completed software components and columns corresponding to every released requirement in the software requirements specification (SRS). A check in any position indicates that this design component helps to satisfy this requirement. Notice that a row void of checks indicates that a component has no purpose and a column void of checks indicates an unfulfilled requirement. Some people argue that this table is very difficult to maintain. I would argue that you need this table to design or maintain software. Without the table, you are likely to design a software component incorrectly, spending exorbitant amounts of time during maintenance. The successful creation of such a table depends on your ability to refer uniquely to every requirement.
----
STOP. Do not dismiss the above because it doesn't sound like an agile practice. There is nothing to stop you from creating, maintaining, and using the above table within the framework of scrum. This is really about design and documentation. Being able to document where work for specific requirements is to be, and was, done will drive development toward modular (in its many forms) design.
I have worked with development teams that track this.. kinda. The specification for a project is stored in JIRA with each issue representing each requirement. When an issue is marked resolved the issue is linked to the commit history, code review, and test documentation. It lacks a high-level view but a sufficiently large table would also suffer from the same difficulty. Anyway, it is immensely useful to be able to query JIRA for issues related to a specific feature and have a subset of commits to look at first.
Labels:
design,
software-engineering
Location:
Springfield, MO, USA
Evaluate Alternatives
A critical aspect of all engineering disciplines is the elaboration of multiple approaches, trade-off analyses among them, and the eventual adoption of one. After requirements are agreed upon, you must examine a variety of architectures and algorithms. You certainly do not want to use an architecture simply because it was used in the requirements specification. After all, that architecture was selected to optimize understandability of the system's external behavior. The architecture you want is the one that optimizes conformance with requirements.
For example, architectures are generally selected to optimize throughput, response time, modifiability, portability, interoperability, safety, or availability, while also satisfying the functional requirements. The best way to do this is to enumerate a variety of software architectures, analyze (or simulate) each with respect to the goals, and select the best alternative. Some design methods result in specific architectures; so one way to generate a variety of architectures is to use a variety of methods.
Labels:
architecture,
design,
software-engineering
Location:
Springfield, MO, USA
Wednesday, April 04, 2018
Design Without Documentation Is Not Design
Sometimes you'll hear a software engineer say, "I have finished the design. All that's left is its documentation." This makes no sense. Can you imagine a building architect saying, "I have completed the design of your new home. All that's left is to draw a picture of it," or a novelist saying, "I have completed the novel. All that's left is to write it"? Design is the selection, abstraction, and recording of an appropriate architecture and algorithm onto paper or other medium.
Labels:
architecture,
design,
software-engineering
Location:
Springfield, MO, USA
Wednesday, August 23, 2017
Encapsulate
Information hiding is a simple, proven concept that results in software that is easier to test and easier still to maintain. Most software modules should hide some information from all other software. This information could be the structure of data; the contents of data; an algorithm; a design decision; or an interface to hardware, to a user, or to another piece of software. Information hiding aids in isolating faults because, when the hidden information becomes unacceptable in some manner (such as when it fails or it must be changed to accommodate a new requirement), only the piece of software hiding that information need be examined or altered. Encapsulation refers to a uniform set of rules about which types of information should be hidden. For example, encapsulation in object-oriented design usually refers to the hiding of attributes (data) and methods (algorithms) inside each object. No other objects may affect the values of the attributes except via requests to the methods.
Reference:
Parnas, D., "On the Criteria to Be Used in Decomposing Systems into Modules," Communications of the ACM, December 1972.
Labels:
architecture,
design,
software-engineering
Location:
Springfield, MO, USA
Tuesday, April 25, 2017
Don't Reinvent the Wheel
When electrical engineers design new printed circuit boards, they go to a catalog of available integrated circuits to select the most appropriate components. When architects design homes, they go to catalogs of prefabricated doors, windows, moldings, and other components. All this is called "engineering." Software engineers usually reinvent components over and over again; they rarely salvage existing software components. It is interesting that the software industry calls this rare practice "reuse" rather than "engineering."
Labels:
architecture,
design,
Seattle,
software-engineering
Location:
Seattle, WA, USA
Saturday, January 07, 2017
Avoid Numerous Special Cases
There are often exceptional situations to an algorithm's design. Exceptional situations cause special cases to be added to the algorithm. Every special case makes it more difficult to debug, modify, maintain, and enhance an algorithm.
If you find too many special cases, you probably have an inappropriate algorithm. Rethink and redesign the algorithm.
Labels:
architecture,
design,
software-engineering
Location:
Springfield, MO, USA
Wednesday, December 14, 2016
Minimize Intellectual Distance
Edsger Dijkstra defined intellectual distance as the distance between the real-world problem and the computerized solution to that problem. Richard Fairley argues that the smaller the intellectual distance, the easier it will be to maintain the software.
To do this, the structure of the software should as closely as possible mimic the structure of the real world. You can minimize intellectual distance using any design approach. Be aware that the structure of the real-world is not unique. As pointed out so well by Jawed Siddiqi in his March 1994 article in IEEE Software, entitled "Challenging Universal Truths of Requirements Engineering," different people often perceive different structures when examining the same thing and thus construct quite diverse constructed realities.
Labels:
architecture,
design,
software-engineering
Location:
Springfield, MO, USA
Keep Design Under Intellectual Control
A design is under intellectual control if it has been created and documented in a manner that enables its creators and maintainers to fully understand it.
An essential attribute of such a design is that it is constructed hierarchically and with multiple views. Hierarchies enable readers to comprehend the entire system abstractly, and then comprehend finer and finer levels of details as they move down the hierarchy. At each level the component should be described from an external point of view only. Furthermore, any single component (at any level in the hierarchy) should exhibit simplicity and elegance.
Labels:
architecture,
design,
software-engineering
Location:
Springfield, MO, USA
Subscribe to:
Posts (Atom)