Attention Agile Programmers: Project Management is not Software Engineering

I’m happy to see so many software developers who are enthusiastic about Agile methods. It’s nice when people enjoy their work. However, I think there is a problem: Some teams are giving too much emphasis to Project Management activities, while at the same time they appear to have forgotten some basic Software Engineering practices. In this post I will present some examples of this lack of balance between the two.

Drawing Burn-down Charts vs. Drawing UML Diagrams

DailyBurndownBurn-down charts help us track the progress being done. They present clearly how much work has been completed, and how much work is left until the end of an iteration. By taking a look at the chart, it’s easy to know if the project is behind or ahead of schedule. But the burn-down chart tells us nothing about the quality of the software being produced, and neither has it any value after the iteration has been completed. Burn-down charts are a project management artifact, they are not a deliverable of the software development process.

UML diagrams are an essential part of the software development process. They are required by the person doing the design to conceive and compare several alternatives. They are needed to present these alternatives and allow design reviews. They serve as part of the documentation of the code that is actually implemented. Drawing UML diagrams is a software engineering activity, and these diagrams are part of the deliverables of the software development process.

However, it seems that some Agile programmers invest very few time drawing UML diagrams. Perhaps they think that these diagrams are only needed in Big Design Up Front, and not when you do Emergent Design or TDD. In my opinion this is a mistake. If you spend more time drawing burn-down charts than UML diagrams, then you are doing more project management than software engineering.

Estimating User Stories vs. Computing Algorithms Complexity

PlanningPokerIn an Agile project the User Stories are the basic unit of work, and it is very important to estimate the effort that will be required to implement these stories. Techniques such as the Planning Poker were invented to make this estimation process as accurate as possible, since iterations are very short and there is not much margin for errors. However, the time spent in effort estimation does not affect the quality of the software. Effort estimation is a project management activity.

Professional software developers must be able to compute the complexity of the algorithms they are adopting in their systems. Actually, they should base their design decisions on the different time and space complexities of diverse algorithms and data structures. They should understand the differences between best, worst, and average case complexities. Computing algorithm complexity is a software engineering activity, essential to assure the quality of the systems being developed.

However, it seems that some Agile programmers don’t ask themselves many questions about the complexity of the algorithms they are using. They just go to the library and choose the Collection with the most convenient API. Or they always choose the simplest possible solution, because of KISS and YAGNI. But if you spend more time estimating user stories than computing time and space complexity, then you are doing more project management than software engineering.

Measuring Velocity vs. Measuring Latency and Throughput

velocity-imgIn Agile projects, the team members are constantly measuring their Velocity: How many units of work have been completed in a certain interval. Of course people want to be as fast as possible, assuming that your velocity is an indication of your productiveness, efficiency and efficacy as a software developer. But the velocity gives us no indication of the quality of the software being produced. On the contrary, it is common to see Agile teams working very fast on the first iterations just to slow down considerably when they start doing massive Refactorings. Thus measuring the Velocity is just a project management activity with dubious meaning.

Many software developers today are working on client/server systems such as Web sites and Smartphone Apps. These systems are based on the exchange of requests and responses between a client and a server. In such systems, the Latency is the time interval between the moment the request is sent and the moment the response is received. The Throughput is the rate the requests are handled, i.e., how many requests are responded per unit of time. In client/server systems it is essential to constantly measure the latency and the throughput. A small code change, such as making an additional query to the database, may have a big impact on both.

However, it seems that some Agile programmers are constantly measuring their velocity, but they have absolutely no idea of what are the latency and throughput of the systems they are developing. They may ignore non-functional requirements and choose simplistic design alternatives that have a huge negative impact in the system’s performance. Thus if you measure your own velocity more frequently than you measure latency and throughput, you are doing more project management than software engineering.

Meetings and Retrospectives vs. Design and Code Reviews

meetingAgile projects normally have daily meetings to discuss how the team is making progress: What have been done, what will be done, are there any obstacles. These meetings do not include any technical discussion. Projects may also have retrospective meetings after each iteration, with the goal to improve the process itself. These meetings are project management activities, they do not address software quality issues.

Design and code reviews focus on software quality. In a design review, an alternative should be chosen based on non-functional quality attributes such as extensibility and maintainability. Code reviews are an opportunity to improve the quality of code that should be already correct. Code reviews should also be used to share technical knowledge and make sure that the team members are really familiar with each other’s work. These kinds of reviews are software engineering activities, with a direct effect on the deliverables of the software development process.

However, it seems that some Agile programmers focus too much on the process and not enough on the product. Successful software development is much more than having a team managing itself and constantly improving its processes. If the quality of the software is decaying, if technical debt is accumulating, if there is too much coupling among modules and if the classes are not cohesive, then the team is not performing its goal, no matter how efficient the process seems to be. If you are spending more time in stand-up and retrospective meetings than on design and code reviews, then you are doing more project management than software engineering.

In Summary

Drawing burn-down charts, estimating user stories, measuring your velocity and participating in retrospectives are project management activities. Drawing UML diagrams, computing the complexity of algorithms, measuring latency and throughput and participating in design reviews are software engineering activities. If you are a software engineer, you should know what is more important. Don’t let your aspiration to become a Scrum Master make you forget the Art of Computer Programming. Good luck!

Posted in Agile, Programming, Software Architecture | Tagged , , | 16 Comments

Software Product Line Engineering

PaulClementsLast week I had the opportunity to participate in a Product Line Engineering (PLE) seminar by Dr. Paul Clements, who is one of the global experts on this subject and author of the book “Software Product Lines: Practices and Patterns” among others. For many years, Paul has been at SEI, the Software Engineering Institute at Carnegie-Mellon University.

Here is Paul’s definition of Product Line Engineering:

“The disciplined engineering of a portfolio of related products using a common set of shared assets and a common means of production.”

Paul adopts the factory paradigm, in which the shared assets are like the items in the factory’s supply chain. A set of features describe capabilities that may vary among products. Then, the assets are configured according to feature profiles, generating concrete products.

Paul’s seminar was naturally focused on Software Product Lines (SPL). Here is the definition of SPL from SEI:

“A software product line (SPL) is a set of software-intensive systems that share a common, managed set of features satisfying the specific needs of a particular market segment or mission and that are developed from a common set of core assets in a prescribed way.

Software product lines are emerging as a viable and important development paradigm allowing companies to realize order-of-magnitude improvements in time to market, cost, productivity, quality, and other business drivers. Software product line engineering can also enable rapid market entry and flexible response, and provide a capability for mass customization.”

Software Product Lines are not only about the software

For many years I’ve been developing software systems and trying to make them highly configurable, through interchangeable components, well-defined interfaces, low coupling and high cohesion. Using the right Design Patterns, it’s easy to add degrees of freedom to an application, defining relationships between abstract components. That’s the basic idea of plug-ins, which may indeed be used to extend a system and create new variations.

In some of my previous posts I’ve defined my approach of Adaptable Design Up Front (ADUF), which promotes the definition of frameworks or platforms that serve as the basis for a family of products. Such a family can be formed by:

  • Several products coexisting at the same point in time.
  • Several instances (versions) of a product over a period of time.

In both cases, the several products in the family are the result of an evolutionary process, which in my opinion should be planned as much as possible. Thus, ADUF can be seen as a methodology to create a shared software architecture to support this evolution.

However, Software Product Lines are not only about the software. They are about all the artifacts generated during the software development process, including:

  • Requirements
  • Design diagrams
  • Documentation
  • Test cases
  • User guides

Clearly, each member in the family will have its own instances for each one of these artifacts, and each artifact should support configuration through the same variation points as the software itself. If the software system is configurable but the other artifacts are not, we cannot really say we have a product line.

I believe every software developer has experienced the difficulty of keeping all artifacts coherent during software evolution. I hope new tools will make this task easier. What has been your personal experience? Please share with us using the comments below.

Posted in Adaptable Design, Software Architecture, Software Evolution | Tagged , , | 3 Comments

35 Agile Development Best Practices

ninjaHow Agile are you? It seems that nowadays most software developers claim they are doing Agile. However, it is also a well-known fact that many teams are only following part of the practices that characterize Agile software development. In the case of Scrum, this is called “Scrum-but”: Doing Scrum but adapting it to your own taste.

Below is a list of 35 Agile Best Practices. You can go over it and check how many of these practices your team is currently following:

  1. Priorities (product backlog) maintained by a dedicated role (product owner)
  2. Development process and practices facilitated by a dedicated role (Scrum master)
  3. Sprint planning meeting to create sprint backlog
  4. Planning poker to estimate tasks during sprint planning
  5. Time-boxed sprints producing potentially shippable output
  6. Mutual commitment to sprint backlog between product owner and team
  7. Short daily meeting to resolve current issues
  8. Team members volunteer for tasks (self-organizing team)
  9. Burn down chart to monitor sprint progress
  10. Sprint review meeting to present completed work
  11. Sprint retrospective to learn from previous sprint
  12. Release planning to release product increments
  13. User stories are written
  14. Give the team a dedicated open work space
  15. Set a sustainable pace
  16. The project velocity is measured
  17. Move people around
  18. The customer is always available
  19. Code written to agreed standards
  20. Code the unit test first
  21. All production code is pair programmed
  22. Only one pair integrates code at a time
  23. Integrate often
  24. Set up a dedicated integration computer
  25. Use collective ownership
  26. Simplicity in design
  27. Choose a system metaphor
  28. Use class-responsibility-collaboration (CRC) cards for design sessions
  29. Create spike solutions to reduce risk
  30. No functionality is added early
  31. Refactor whenever and wherever possible
  32. All code must have unit tests
  33. All code must pass all unit tests before it can be released
  34. When a bug is found tests are created
  35. Acceptance tests are run often and the score is published

I’ve tried to provide links to all important concepts in the list above, in the case you would like to learn more about them. The list itself is from the paper: “What Do We Know About Scientific Software Development’s Agile Practices?”

So, how many of these practices do you follow? Please leave a comment below.

Posted in Agile, Programming | Tagged , | 25 Comments

Avoiding Technical Debt: How to Accumulate Technical Savings

sisyphusThe metaphor of Technical Debt has been widely accepted as part of the current reality of software development. Programmers agree that they frequently need to make sacrifices in order to meet deadlines, and the consequences of these sacrifices are modules that should be redesigned in the future.  In order to “pay” the technical debt, Refactoring became a routine in the development process, and Test-Driven Development helps assure that these constant refactorings do not break working code.

I don’t feel comfortable with this reality. I think that software developers should not incur technical debt so easily. And I think software developers are wasting too many efforts with constant refactorings, what has been called “Refactor Distractor”. In my opinion, the right way to fight technical debt is to accumulate Technical Savings.

Technical Savings: Well-designed code, planned to satisfy future needs. Technical Savings are a form of wealth that makes a module more maintainable, extensible or reusable.

Now the question is: How do we accumulate Technical Savings?

We can save money when we earn more than we spend. If our earnings are the result of our work, then if we are saving money we could say that we are actually working more than we need. But we all understand the importance of having savings in our bank account, because we know that we may have more needs in the future.

Exactly in the same way, Technical Savings are the result of some extra work. We must invest in the design of our modules so that they are indeed more maintainable, extensible and reusable. But we must believe that this investment will pay itself in the future. If done right, the efforts invested in accumulating Technical Savings should be smaller than the efforts required in the alternative of incurring technical debt and then paying this debt through successive refactorings.

Technical Savings and Adaptable Design Up Front

In some of my previous posts, I’ve described my approach of Adaptable Design Up Front (ADUF). The key idea is that software systems must evolve, and that this evolution must be supported through well planned, adaptable designs.

In other words, there will always be changes, either in the form of new features or modifications in the original requirements. One option is to implement these successive changes as they happen, what inevitably will cause technical debt and the need for refactoring. Another option is to be aware that these changes will happen, and to plan our systems to accommodate these changes as easily as possible. A design that is planned to accommodate change is an adaptable design.

In one of my posts I explain how adaptable designs can be implemented through frameworks and platforms. In this same post I talk about the importance of decoupling through Design Patterns and about the need of Domain Modeling.

In another post I explain how adaptable designs should actually be an application of the Open-Closed principle. Our design will be really adaptable only if it has some parts that do not need to be changed, and if the parts that may change are easy to change.

In Summary

It is possible to avoid the trap of constant debt and refactoring. We may accumulate Technical Savings, a form of wealth that makes our modules more maintainable, extensible and reusable. One approach to acquire these Technical Savings is trough Adaptable Design Up Front.

Posted in Adaptable Design, Refactoring, Software Evolution, Software Reuse, Technical Savings | Tagged , , , | 24 Comments

On Technical Debt and the Psychology of Risk Taking

roulette-wheel-320x180I recently read the following message in a developers’ forum (rephrased here):

“I’m facing a dilemma. I must deliver the product by the end of this quarter, but there are still many tests I would like to execute. The product seems to be working, but even so I would like to run additional tests. However, if I do so I will miss the deadline. What should I do?”

Every programmer has been faced with this dilemma. And we all know what always happen in this case: The product is delivered on time, even with the risk of having some bugs. Meeting the deadline is considered more important than assuring 100% correctness.

There are many other situations in which a developer may make sacrifices to meet the deadline. This happens because the developer’s work is Multi-Objective. He must:

  • Deliver on time.
  • Deliver correct code.
  • Deliver code with good design.
  • Deliver well-documented code.

Frequently, there is not enough time to invest in all objectives, so some of them are assigned lower priority. This is the root of Technical Debt: A developer decides to postpone some task he should do now, because he does not have enough resources to satisfy all his objectives.

Now the question is: How do programmers decide what to postpone? How do they assign priorities to their conflicting tasks?

We would like to imagine that these decisions are being taken consciously and systematically. However, there are several unconscious and psychological influences. One of them is known as Loss Aversion.

Loss Aversion

Loss Aversion and its consequences are discussed by Daniel Kahneman in his book “Thinking, Fast and Slow”.

“Loss Aversion refers to people’s tendency to strongly prefer avoiding losses to acquiring gains. Some studies suggest that losses are twice as powerful, psychologically, as gains.”

In one experiment people are presented with the following options:

  • A certain loss of $100.
  • A 50% risk of losing $200, with a 50% chance of not losing anything.

The first option represents the sure loss of a smaller amount, and the second option represents a risk of losing a higher amount. It was proved that most people prefer the second choice. In other words, in this situation most people would take the risk of losing a higher amount. As Kahneman’s writes:

“In bad choices, where a sure loss is comparable to a larger loss that is merely probable, diminishing sensitivity causes risk seeking.”

Let’s now see how this applies to software developers and their multiple objectives.

Risk Taking in Software Development

Going back to the programmer’s dilemma we presented in the beginning of this article, suppose a software developer is presented with the following choices:

  • Continue testing the system and miss the deadline.
  • Deliver the system as-is, with the risk of a serious bug being found afterwards.

The first option is a sure loss: The deadline is missed. The second option represents the risk of a higher loss: Perhaps the system has a serious bug, but perhaps not. Thus, because of Loss Aversion, the second option will be chosen by most programmers.

What makes things worse is that, for some objectives, quality is not being measured. So when a programmer decides not to invest in a task, he is not only taking a risk on the consequences of this decision. Actually, programmers gamble with the probability that their lack of investment will never be detected.

For example, it is hard to measure design quality. Very often, code-reviews are not systematic and technical debt is considered an acceptable “fact of life”. Technical debt may never be “paid”, and when it is paid, it will probably be paid by someone else.

It is also hard to measure documentation quality. There are not appropriate tools, and sometimes documentation is considered “nice-to-have”. Some programmers believe that documentation is superfluous and that code should be self-explainable.

Regarding testing, traditional development uses QA teams and it is expected that code will have bugs. Developers are not supposed to deliver 100% bug-free code.

However, in Test-Driven Development (TDD), developers are responsible for unit testing, and if the tests don’t run the code cannot be delivered. The programmer has an immediate feedback on the quality of his code, so there is no place left for risk taking.

Conclusions

In order to improve the quality of software systems, we should avoid risk-taking behaviors. Because of Loss Aversion, if we want to avoid risk-taking, each software development task should have its own tools and methods that allow programmers to receive immediate feedback on the quality of the code they are writing.

Posted in Agile, Efficacy, Psychology of Programming, TDD | Tagged , , , | 27 Comments

The Etrog, Idealism and Concrete Choices

etrogIn the holiday of Succot, Jews make a blessing over the Four Species, including a special fruit called the Etrog. The Etrog is similar to a lemon, but it has a different shape and delicious smell. In the past the Etrog was considered a rare fruit, and it could be very expensive. When observant Jews chose an Etrog for the blessing, they looked for a beautiful one, which is called an “Etrog Mehoudar”.

There is an old tale about an Etrog dealer who arrives in a small village in Eastern Europe. The habitants of this village wanted to buy beautiful Etrogs to say the blessing, but they were not sure about how to choose a good one. So they would ask the Etrog dealer to give them a beautiful Etrog, and then go ask the Rav if it is really a good one.

When they arrived in the Rav’s house with the Etrog, they would ask:

“Rav, is this Etrog beautiful? Is it Mehoudar?”

Then the Rav would examine carefully the Etrog and answer:

“I’m sorry, but this Etrog is not Mehoudar.”

Then the person would return the Etrog to the dealer, claiming that the Rav said it was not Mehoudar.

After this happened several times, the dealer understood that he would not be able to sell any of his Etrogs, and then he decided to talk to the Rav. He went to his house and said:

“Rav, you must help me, no one wants to buy my Etrogs.”

The Rav answered:

“I’m sorry, but if they ask me if the Etrog is Mehoudar, I must say the truth.”

Then the dealer insisted:

“But Rav, if no one buys my Etrogs I will lose everything, and no one will have an Etrog to say the blessing.”

The Rav analyzed the situation and then proposed:

“Instead of giving a single Etrog to each person, you will give two Etrogs. Then, when they come to me, they will ask: ‘Which one among these two Etrogs is the most Mehoudar?’ And in this case I will always have a positive answer.”

Idealism and Concrete Choices

The Etrog Mehoudar represents our ideals. It is a symbol of perfection, of the satisfaction of all our desires. It is extremely important to have ideals, but we must always remember that we are constrained by the concrete choices we have at a particular moment.

It is important to have an Etrog Mehoudar, but when the holiday of Succot starts it is more important to have some Etrog to say the blessing, any Etrog, even if this Etrog is not Mehoudar.

As in the quote: “A goal is a dream with a deadline.” – Napoleon Hill

If the Etrog Mehoudar is the dream, then the beginning of Succot is the deadline. The goal is to have some Etrog to be able to say the blessing.

In the solution proposed by the Rav, the two Etrogs offered by the dealer are the unique concrete choices. The two choices are a limitation, but also part of the solution.

At any specific point in time, we must be wise to understand what our concrete choices are, and then select the best one based on our ideals.

Idealism and Software Development

Software developers are proud of the products they create, and they always want them to be as good as possible. A good piece of software should have many quality attributes: It should be well designed, should be efficient, and should not have bugs. But in our quest of the perfect software, it is easy to miss the deadlines.

One symptom of excessive perfectionism in software development is Analysis Paralysis: “The state of over-analyzing (or over-thinking) a situation so that a decision or action is never taken, in effect paralyzing the outcome.” In this case, software developers may spend too much time writing documents and drawing diagrams instead of writing code.

Another symptom is Featuritis: “The ongoing expansion or addition of new features in a product.” In this case the product will never be ready, because there will always be a new feature which may be added to make it better. Just another feature to make it perfect…

A solution to avoid these mistakes is to focus on a product that is both small and has very concrete purposes. This is the idea behind the concept of Minimum Viable Product, proposed by Eric Ries in his book “The Lean Startup”.

In summary:

There is no contradiction between idealism and pragmatism, as long as:

  • We are able to identify our concrete choices.
  • We use our ideals to select the best choice.

If you celebrate Succot, I wish you a Chag Sameach!

Posted in Efficacy, Jewish Sources | Tagged , | 8 Comments

Simplicity in Software Design: KISS, YAGNI and Occam’s Razor

paperclip“Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.” – Antoine de Saint-Exupery

Simplicity is a desirable quality attribute in any software system. In this article I try to collect the main software design principles that address the importance of simplicity.

KISS

KISS means “Keep it simple, stupid”. It is probably one of the oldest principles of software design (but we keep forgetting it).

“The KISS principle states that most systems work best if they are kept simple rather than made complex; therefore simplicity should be a key goal in design and unnecessary complexity should be avoided.”

Software systems must be maintained by human developers with limited capabilities, thus any increase in a system’s complexity also augments the difficulty to maintain it.

“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” -Brian Kernighan

YAGNI

YAGNI means “You Aren’t Gonna Need It”.  It is a principle of Extreme Programming (XP) that states that a programmer should not add functionality until really necessary.

“Always implement things when you actually need them, never when you just foresee that you need them.” – Ron Jeffries

The YAGNI principle is related to the “Last Responsible Moment” concept of Lean Software Development:

“Decide as late as possible: Delaying decisions as much as possible until they can be made based on facts and not on uncertain assumptions and predictions.”

Occam’s Razor

Occam’s Razor: “A principle of parsimony, economy, or succinctness used in logic and problem-solving. It states that among competing hypotheses, the hypothesis with the fewest assumptions should be selected.”

Michael Lant has written an interesting article about Occam’s Razor applied to software development. He says:

“Modern interpretation is often quoted as ‘The simplest solution is almost always the best’. The modern interpretation, however, misses the important point that ‘simplest’ as meant by Occam means the ‘fewest assumptions’.”

Thus, we should as much as possible avoid basing our design on assumptions. In this sense the principle of Occam’s Razor is aligned with YAGNI.

Complex Designs

When the simplicity principles above are not observed, the resulting software systems may have complexity in the form of:

  • Unneeded features.
  • Over-engineering.

The first case is that of systems with more features than necessary:

Feature Creep: “The ongoing expansion or addition of new features in a product. Extra features go beyond the basic function of the product and so can result in over-complication rather than simple design.”

Feature Creep is particularly common in software systems, in which it is relatively easy to add new features that were not part of the original design. One of the consequences of this feature expansion is known as Software Bloat.

Software Bloat: “A process whereby successive versions of a computer program become perceptibly slower, use more memory or processing power, or have higher hardware requirements than the previous version whilst making only dubious user-perceptible improvements.”

The second case of high complexity is that of systems which are over-engineered:

Over-engineering: “The designing of a product to be more robust or complicated than is necessary for its application.”

A typical example of over-engineering is that of having too many abstraction layers.

“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 way is to make it so complicated that there are no obvious deficiencies.” – C.A.R. Hoare

Simplistic Designs

Of course we want to eliminate complexity from our designs. But when trying to do a simple design, we must be very careful to avoid the trap of Simplistic Designs. This is the definition of “simplistic” from a dictionary:

Simplistic: “Treating complex issues and problems as if they were much simpler than they really are.”

A simplistic software design may be one that focuses only on present requirements and ignores future needs such as maintainability, extensibility and reusability. As I’ve discussed in a previous post, wise developers foresee the consequences of their design.

I think that the danger of simplistic design is very well expressed by this quote:

“Keep it simple, as simple as possible, but not simpler.” – Albert Einstein

What do you think? How do you cope with complexity in software systems? Please share your experience in the comments below.

Posted in Agile, Software Architecture | Tagged , | 32 Comments

IASA Israel meeting – Daniel Gross on Architectural Description Languages

The International Association of Software Architects (IASA) in Israel organized a special event with the participation of Dr. Daniel Gross, who talked about “Architectural Description Languages”.

Synopsis: In this talk Daniel reviews main findings of a recent international survey on the utility and adapted use of Architectural Description Languages in industry, and proposes some requirements for architectural design and documentation tools to support next generation ADLs.

Bio: Daniel received his PhD from the Faculty of Information at the University of Toronto, Canada. Daniel’s research focuses on developing socio-technical modelling and analysis techniques to support business and architectural decision-making in organizational settings. Daniel currently works as a knowledge representation researcher for a European FP7 R&D project (Risk and Cost Management during Open Source Software Adoption), and as a freelance Requirements Analyst. Daniel previously worked at the IBM in Belgium and Austria, in the areas of object-oriented methodology development and insurance business modelling, and in areas related to Workflow management. He holds UK, US and Canadian software patents to support recipient controlled communications mechanisms dealing with messaging related information overload.

These are the original slides of Daniel’s presentation:

Here is the video of the entire talk (in Hebrew):

This meeting was sponsored by SAP Labs Israel. Special thanks to Dima Khalatov who helped with the organization.

To participate in our future meetings, please join the IASA IL group on LinkedIn.

Feel free to share your comments below. Thanks!

Posted in IASA Israel, Software Architecture | Tagged , | Leave a comment

IASA Israel meeting – Hayim Makabee on Adaptable Design Up Front

The International Association of Software Architects (IASA) in Israel organized a special event with the participation of Hayim Makabee, who talked about “ADUF – Adaptable Design Up Front”.

Synopsis: This talk tries to answer the question: “How much Design Up Front should be done in an Agile project?” Hayim presents his approach of Adaptable Design Up Front (ADUF), describing it’s rationale, applications in practice and comparison to other approaches such as Emergent Design.

Bio: Hayim Makabee was born in Rio de Janeiro. He immigrated to Israel in 1992 and completed his M.Sc. studies on Computer Sciences at the Technion. Since then he worked for several hi-tech companies, including also some start-ups. Currently he is a Research Engineer at Yahoo! Labs Haifa. He is also a co-founder of the International Association of Software Architects (IASA) in Israel. Hayim is the author of a book about Object-Oriented Programming and has published papers in the fields of Software Engineering, Distributed Systems and Genetic Algorithms. Hayim’s current research interests are Data Mining and Recommender Systems.

These are the original slides of Hayim’s presentation:

Here is the video of the entire talk (in Hebrew):

This meeting was sponsored by SAP Labs Israel. Special thanks to Dima Khalatov who helped with the organization.

To participate in our future meetings, please join the IASA IL group on LinkedIn.

Feel free to share your comments below. Thanks!

Posted in Adaptable Design, Agile, IASA Israel, Software Architecture, Software Evolution | Tagged , , , , | Leave a comment

Adaptable Design Up Front and the Open/Closed Principle

The Open/Closed principle is one of the SOLID principles of software design:

“The Open/Closed Principle states that the design and writing of the code should be done in a way that new functionality should be added with minimum changes in the existing code. The design should be done in a way to allow the adding of new functionality as new classes, keeping as much as possible existing code unchanged.”

camera with lensesThe picture on the right illustrates the application of this principle to an object we know very well: Professional cameras can be attached to several types of lenses. The camera itself does not need to be changed, it is simply extended. It is “closed” but also “open”.

The Open/Closed principle was originally proposed by Bertrand Meyer: “Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.”

strategyA simple example of the Open/Closed principle is the Strategy design pattern. In this pattern, the Strategy is a component, and the same composite class may be associated to several types of strategies. The composite class using the strategy never needs to be changed to use a new type of strategy, and in this sense it is “closed”. But it is also “open”, because its behavior can be
extended through associations to new concrete strategies.

It is easy to understand the meaning of the Open/Closed principle in the context of relationships between pairs of classes, such as inheritance and composition. It is also relatively simple to use it in low-level design, and actually many design patterns apply this principle. But it is interesting to ask ourselves how the Open/Closed principle may affect the high-level design.

The Open/Closed Principle Applied to High-Level Design

The approach of Adaptable Design Up Front (ADUF) is an application of the Open/Closed principle to high-level design. It focuses on the early definition of the “closed” aspects of the design while at the same time allows easy evolution by making this design open to extensions.

The design is “closed” when it captures the essential aspects of the system: The main entities and relationships. These are the aspects that are not expected to change.

The design is “open” when it can be easily extended without changes. Through these extensions, the closed part of the design can be adapted to changing requirements.

ADUF starts with a domain model defining the main entities and relationships. We then design a framework for this model, in which the relationships among entities are implemented as associations among classes.

The associations must be closed: An object of type A must have a reference to an object of type B. But polymorphism allows this association to be also open: An object of type A can be associated to an instance of a subclass of B, even subclasses that did not exist when A was created.

ADUF also promotes the usage of Plug-ins as an application of the Open/Closed principle to high-level design. The same module may be associated to diverse plug-ins without any need of change. The module associated to the plug-ins may appear to be completely opaque and monolithic from the point-of-view of the plug-in developer.

Enough Design Up Front

Question: How much design should be done up-front?

Answer: The design up-front should capture all the “closed” aspects of the system. Besides that, we should invest to make this design “open”, in order to allow it to evolve through specialization. This may be done with appropriate Design Patterns.

Thus, there are several kinds of mistakes when doing the design up-front:

  • Too much design up front: Capturing aspects that are not essential as if they were such. The consequence is that the design may need to change, and if it needs to change then it is not really “closed”. This also happens when specific details are not generalized. If the details change, the design must be changed.
  • Not enough design up front: Leaving away some of the essential aspects of the system. The consequence is that these aspects will need to be added to the design when other parts of the system are already implemented. If the original design was not “open” enough, the new additions may cause conflicts.
  • Not enough openness: The design captures all essential aspects, but there are not mechanisms that allow this design to be easily extended. For example, if there are Interfaces or Abstract classes that represent the main entities, there should be also creational patterns such as Factories to instantiate specific subclasses.
  • Too much openness: The design is over engineered, resulting in complexity not really necessary. For example, it is always possible to reduce the coupling between modules through additional layers of indirection. However, if there are many such layers, it becomes more difficult to locate the places in the code where the business logic is actually implemented.

In summary:

According to the ADUF approach, the design up front should be:

  • Closed: Capturing the essential aspects that are not going to change.
  • Open: Allowing the initial design to be easily extended and adapted.

What do you think? Have you used similar approaches? Please share your experience in the comments below.

Posted in Adaptable Design, Design Patterns, OOD, Software Architecture, Software Evolution | Tagged , , , , | 11 Comments