David Scott Bernstein's Blog, page 6

April 15, 2020

Refactor to Learn an Existing System

One of the best opportunities to refactor code is when you’re starting to get to know it. This not only helps improve the code but it also improves your understanding of the code and helps everyone else who touches the code in the future.


There are many kinds of refactorings that one can do to existing code that is not under test which are safe and helpful for embedding understanding code. When we have a bunch of existing code that’s not under test it can be dangerous to make major changes to it but these safer refactorings allow us to make small, safe, and incremental changes to code in ways that can also help us learn a system.


One of my very favorite refactorings to help me learn a system is Rename. Rename is a really simple refactoring but one I use all the time. It’s not uncommon to find methods that have misleading names and when I come across this I often use the automated Rename Method refactoring in my IDE to change the name to one makes more sense. I find that just this one refactoring, Renaming Methods, can vastly improve the clarity of a system and that helps me learn it much faster.


Since the Rename refactoring is a nondestructive refactoring and one that many IDE’s have automated, it is very safe to use, even on software that’s not under test. However, if I’m very concerned about the safety of a method and I may have callers that are external to my code then one thing I can do is leave the existing method alone and simply wrap it in another method of my own with the name of my choosing. That way I can change all of my internal callers to use the wrapping method with the new name so that it’s clearer on what they’re actually doing and external callers are still able to call the original method with its original name directly.


I and others have written a lot about what makes a good name for a method. I won’t go into that now except to say in a nutshell that the goal of the name of a method should clearly state what it does. Think of a method name as a promise to provide some kind of behavior or service to its callers. When a behavior is given the right name then much of the system starts to make sense that didn’t before.


Renaming methods can help bring clarity to legacy code and is a really excellent way to improve my knowledge of that code while making it just a little bit better for the next person who comes along and needs to work with it. Because Rename is among the safest of all the refactorings, I feel that I can use it in almost any situation and this helps me embed knowledge into an existing system, improving the system, as well as improving my understanding of what the system does.


Note: This blog post is based on one of the “Seven Strategies…” sections in my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software.


The post Refactor to Learn an Existing System appeared first on To Be Agile.

 •  0 comments  •  flag
Share on Twitter
Published on April 15, 2020 08:49

April 8, 2020

Why Practice 9: Refactor Legacy Code

Having put the words “legacy code” in the title of my book, people often confuse my book with Michael Feathers’ book, Working Effectively with Legacy Code.


On one hand, it’s great to be in such esteemed company. I love Michael’s book and I refer to it often. It’s full of great techniques for taming legacy code that most developers should know.


But my book is different, it’s not about that at all. My book is called Beyond Legacy Code and the keyword here is “beyond.” My book is about how to get beyond legacy code or how not build legacy code in the first place. It’s about the value of the technical practices and why agile software development requires specific technical practices in order to effectively build software incrementally.


I noticed there was a disconnect between developers and their managers in terms of understanding what the most valuable use of their time and energy is. My book discusses why the technical practices are valuable, both from a developer’s perspective and from a manager’s perspective, so that both developers and non-developers can get on the same page and understand why it’s valuable to do these practices.


This is the piece of information that I saw was missing in our industry. There are a lot of how-to books for software developers and managers. How-to learn a new language. How to use a framework. How to do the latest and greatest things. But I rarely see what I would call of why-to book that tells us why these practices are valuable in the first place.


This is what my book addresses, why the technical practices are valuable. And so it’s content is easily relatable to both software developers and non-developers who have an interest in the software industry, such as managers and executives.


The nine practices that I describe in my book help us build software more cost-effectively while also dropping the cost of ownership for the software that we build. Given that over 80% of the cost of software happens after it is released, dropping the cost of ownership for the software we build represents a major saving for most software development.


Although eight of the nine practices in my book do not directly address legacy code and only the last one, practice 9, Refactor Legacy Code, addresses legacy code directly, it’s important to understand the other eight practices first, before we address existing code, because, in order to refactor bad code into something better, we have to first understand what something better means. And so we spend most of the book discussing what good code is about and once we understand this we can look at legacy code and address how to refactor it safely using many of the same techniques that we discussed to create good code by simply apply it to our existing code.


When I ask software developers what they need to do to improve their existing software they often have a pretty good idea and when I asked them why they don’t do it they typically tell me it is because their manager or product owner won’t let them. We don’t want to refactor code needlessly but when we have a good reason to do it, such as the need to add new features to existing code, then we would like the opportunity to refactor that code first.


The next seven blog posts are based on the section in my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software, called Seven Strategies for Helping You Justify Refactoring. These are things that you can say to your managers or executives that will help them understand when it’s valuable and cost-effective to refactor existing code.


Note: This blog post is based on one of the “Seven Strategies…” sections in my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software.


The post Why Practice 9: Refactor Legacy Code appeared first on To Be Agile.

 •  0 comments  •  flag
Share on Twitter
Published on April 08, 2020 08:19

April 1, 2020

Practice Good Development Habits

As you can see from my last seven blog posts, doing emergent design is not for beginners. Doing emergent design is an advanced development practice.


But it’s not enough to know about good development principles and practices. It’s not enough to know about design patterns. We have to use them. We have to apply them. We have to understand them so that we can get benefit from them.


I think that many developers and their managers are under the false impression that taking shortcuts will save them time. I find that shortcuts and cutting corners, especially in terms of software quality, won’t save us time but in fact, costs us both in the long-term and often also in the short term. That doesn’t mean that I don’t make compromises because I have to if I want to stay in business but learning how to make the right trade-offs is critically important.


There are many compromises that I will make on a project in many design decisions that I will give in on but I do have some basic nonnegotiable’s. I always write code while paying attention to code quality. That’s non-negotiable for me. When I see that I’m writing some behavior that I have written before, I’ll take the time to put it in a single place and call it from both places. When I find that the behavior of a class starts to exceed its single responsibility then I’ll take the time to split the class out into multiple classes, each with its own responsibility. I do these things habitually because they save me time, not just in the long run but also in the short term.


Here’s what I’ve learned from studying thousands of professional software developers: It’s not the practices that a developer uses that makes them efficient. What makes a developer efficient are the practices that they’re used to.


Developers who are comfortable with good development habits that produce high-quality code can do so very rapidly. Developers who have poor practices and are used to turning out buggy code can typically do those practices pretty quickly as well. It’s not the practices themselves that speed us up or slow us down, it’s how familiar we are with doing them.


The key is to find good developer practices that support us in writing high quality, maintainable code and making those the practices the ones we are most familiar with. If we can do that then we will build high-quality software rapidly.


I no longer ask myself when I’m coding whether I should cut corners on code quality or not. I always write software that’s CLEAN. I no longer question whether I should do this and because I don’t need to question myself, I can be really fast. I often find that it’s not the technique that slows us down but rather questioning ourselves whether we should apply the technique in any particular situation that slows us down.


Making something a habit is simply when we cease to question it. We do this because it’s more convenient to just do the thing than to keep questioning it. Instilling good habits can be very helpful and knowing the process by which things become a habit can also help drive us to create good habits that support us in building quality code, which will help us more easily emerge designs.


Note: This blog post is based on one of the “Seven Strategies…” sections in my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software.


The post Practice Good Development Habits appeared first on To Be Agile.

 •  0 comments  •  flag
Share on Twitter
Published on April 01, 2020 08:08

March 25, 2020

Be Merciless

One of the most important characteristics that I find senior developers have is the ability to change their minds and let go of an existing design when it no longer serves its purpose. What I find time and time again is that developers become attached to the current design even in the face of changing requirements that invalidate that design.


Simply being willing the change your mind is a vital skill to have when doing emergent design because emergent design means that you are changing your design as you go. In order to do that, we have to let go of our current design in order to come up with something better.


All this changing of design in existing code might sound like it’s dangerous or inefficient but when we understand refactoring, design patterns, and have good regression tests that support refactoring then we can do it safely and efficiently.


We don’t want to get too attached to any design because things change. When requirements change, very often it implies that the design has to change as well. This is why I don’t get too attached to design and I always try to keep in mind what my options are that will allow me to go from an existing design to something else that would be more appropriate in the light of new or changing requirements.


One of my favorite quotes from one of my favorite writers, Stephen King, is “murder your darlings.” By this what I believe he meant was that we shouldn’t be too attached to anything in particular. Sometimes as a writer I find that I get particularly attached to a passage that I’ve written. Now when I do that I often delete that passage and start over again. I find that trying to force-fit everything else around a passage that I love to be difficult and can make my writing appear awkward.


When I write I spend a good deal of time and energy outlining because it allows me to immerse myself in the context of what I want to say without having to become attached to any particular way of saying it. I try to do the same thing when I code. I try to write software in such a way that I can easily refactor it in the future, as I learn more. By doing this, I recognize that I can change my design at any point that’s appropriate and so I don’t have to worry about getting it right upfront.


I think that a lot of developers think that they have to get their design right in the beginning when they hardly understand the problem to start with. I used to believe that but I don’t believe it anymore. Today I find that building systems based upon the customer’s priorities and delivering work in progress are a highly effective way of producing valuable software.


As I learned more and more about how to do emergent design well and the power of refactoring code, it allows me to go from one design to another design with minimal risk, and I begin to recognize that it doesn’t matter where I start with the design—what matters is where I end up. And having the skills to refactor my designs gives me the freedom to end up wherever I need to.


Note: This blog post is based on one of the “Seven Strategies…” sections in my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software.


The post Be Merciless appeared first on To Be Agile.

 •  0 comments  •  flag
Share on Twitter
Published on March 25, 2020 09:14

March 18, 2020

Focus on Code Quality

I believe in the Agile Manifesto. I know most of the original authors and they know that I think they’re pretty cool. They got so much right in such a short amount of space and that’s very admirable.


But there’s one thing that I think they kind of missed the mark on, so I’m going to rant about it. It’s the ninth principal of the Agile Manifesto that says, “Continuous attention to technical excellence and good design enhances agility.”


Enhances? I would like to propose that the Agile technical practices of Extreme Programming and doing emergent design requires, yes requires, continuous attention to technical excellence and good design!


If there’s anything you should take away from this blog series on emergent design, it’s that we have to focus on good design principles and practices and have high code quality in order to be successful with emergent design. There are dozens of good books on software development and software design. Understanding what code quality is and how to achieve it in software is an important set of skills.


Practice 5, Create CLEAN Code, calls out five key qualities that I see in code and recognize as virtuous. All good software development principles and practices in object-oriented programming improve these five code qualities. I describe them in detail elsewhere so here I’ll just mention what they are: cohesive, loosely coupled, encapsulated, assertive, and nonredundant. Each of these terms means something specific in code. They largely apply to object-oriented programs but other programming models and paradigms also support these qualities.


I find that when I only have a short time to spend with software developers, one of the most productive places to start is with these five code qualities because we can easily recognize them in code and when we improve these code qualities, it helps make the code more understandable and testable.


When developers tell me that they’ve tried doing emergent design but failed at it or call it undisciplined then I know that they really don’t understand how to build CLEAN code, which I believe is a prerequisite for doing emergent design.


One of the benefits of emergent design over the idea of upfront design is that in my experience all initial designs are inadequate and as we learn more it often pushes us away from our initial designs. Therefore, we must be willing to change and adapt our design as new requirements demand. This is what emergent design is all about.


If all of this sounds painful when you think about doing it in your code then clearly you have some code quality issues. CLEAN code is a prerequisite for doing emergent design and when code quality is high then emergent design is feasible.


Note: This blog post is based on one of the “Seven Strategies…” sections in my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software.


The post Focus on Code Quality appeared first on To Be Agile.

 •  0 comments  •  flag
Share on Twitter
Published on March 18, 2020 09:29

March 11, 2020

Understand Refactoring

Refactoring code is not just changing the design of code without changing its external behavior, it’s also doing it in small, safe steps that are repeatable. This is what elevates refactoring to a discipline that we can talk about and create best practices around rather than just willy-nilly ways of changing code.


It was Martin Fowler’s book, Refactoring: Changing the Design of Existing Code, that turned this practice into a true discipline. His book is now in its second edition and is really a classic for all software developers to read.


Let’s face it, if you write code you need to refactor code. Understanding that there are known transformations that you can bring code through to go from one design to another design safely is for me very freeing because it tells me that I can always change my design later when I know more. I don’t have to get it right the first time.


I think that software developers are under the illusion that they have to come up with the right design first off, even before they have a full set of requirements. Very often our initial requirements only tell part of the story and we end up committing ourselves to design choices that restrict us later from handling new requirements. New requirements mean that the world is changed, that needs have changed. This also very typically means that a design needs to change.


What I find is that most developers don’t have techniques around being able to go into existing code and change it in a safe way and then also be able to validate and verify that the changes they made didn’t break anything. Because of this, I find a huge stigma in the industry around changing legacy code, which is one of the main reasons I wrote my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software.


When you understand refactoring and know how to go from one design to another design safely and effectively because you have good behavioral tests in place, then you will find it’s easy to emerge good designs in existing systems.


“There’s nothing to fear but fear itself.” This is especially true with legacy code. I find that developers are often scared to touch legacy code for fear of breaking it but that fear is often unfounded. Just by knowing a few simple techniques for working with legacy code, we can learn a system while untangling it. Even the most intractable systems can be improved, little by little, in this way.


When you understand refactoring and design patterns then it becomes doubly good. The patterns become design goals or targets and the refactorings become code transformations that allow you to improve the design and implement the patterns. I think of design patterns and refactoring as two critical tools that go hand-in-hand when doing emergent design.


Note: This blog post is based on one of the “Seven Strategies…” sections in my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software.


The post Understand Refactoring appeared first on To Be Agile.

 •  0 comments  •  flag
Share on Twitter
Published on March 11, 2020 09:19

March 4, 2020

Understand Test-Driven Development

Another important aspect of doing emergent design is doing it safely and that means doing it while code is under test. But not just any tests, we have to write behavioral tests that don’t break when we refactor our code to emerge our designs.





These are precisely the kind of tests that I’ve been talking about when advocating for doing test-first development. Using test-first development allows us to create behavioral tests for the code we write that supports us when we refactor our code.





The advantages are many-fold. Test-first development gives us a suite of regression tests that allows us to continually validate the behaviors of the system that then becomes the basis for continuous integration and a rich level of feedback about the system as it’s being built.





But more than the regression tests that I get from doing test-first development, it helps me organize my thinking and build out a system more efficiently then if I were to do test-after development. It’s pretty well-established in the industry that having automated regression tests is valuable. From what I can see many teams builder regression tests after the code is built and oftentimes by the QA department rather than the developers who wrote the code. 





In some ways, this relegates tests to a secondary position and we end up not deriving as much benefit from them. When we write our code before we write our tests, we often end up writing code that’s difficult to test that requires us to go back and change it later to make it testable. 





That doesn’t happen when I do test-first development. Test-first development t requires that I always write testable code. When I write the test before I write my code I’m leveraging my test in several ways that help me lock down my method signature and what I expect back. It also sets my expectation for when the implementation of the behavior will be done. And I also end up getting a suite of automated regression tests. How cool is that?





Since the essence of building out a system using test-first development is really coming up with good examples and working through those examples to build out their implementations, it should be no surprise that this process is a core part of doing emergent design. In other words, doing emergent design is all about doing good design by coming up with examples and then implementing them in code. If we start simple and build on behaviors as we go then we are emerging a design.





I have seen teams take this approach and build beautiful systems. I have also seen teams pervert this approach and build big balls of mud. The difference, as far as I can tell, is whether or not they paid attention to the things that their code and that their design was telling them. 





Again, focusing on good code quality and observing what your designs need in order to be robust is a critical part of doing emergent design effectively. The unit tests that we write when doing test-first development give us a different and much-needed perspective on our system. This perspective of writing testable code helps us build systems that are more resilient to change.





Test-driven development, or test-first development as I prefer to call it, is a discipline that not only helps us get the right kind of regression tests to support us in refactoring our code, it also helps us design testable behaviors in code. These things are essential components for doing emergent design.





Note: This blog post is based on one of the “Seven Strategies…” sections in my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software.


The post Understand Test-Driven Development appeared first on To Be Agile.

 •  0 comments  •  flag
Share on Twitter
Published on March 04, 2020 09:38

February 26, 2020

Understand Design Patterns

Doing emergent design is an advanced practice that requires knowledge of a great many skills. One key skill that all professional software developers should acquire as they journey towards mastery is a deep understanding of design patterns, both in concept and in terms of the 23 design patterns called out by the Gang of Four in their book Design Patterns: Elements of Reusable Object-Oriented Software. Design patterns represent a type of knowledge that’s indispensable for doing emergent design because they embody how to build changeable code.





Sometimes developers ask me how, in this fast-paced world that we live in, can ideas from a book published over 20 years ago be relevant today? But I think that the ideas in the design patterns book are even more relevant today than they were when they were first introduced back in the mid-90s.





Back in the mid-90s, computers were slow in memory was expensive. We didn’t spend a lot of time building systems to be resilient through abstractions and indirect calls because we could not afford the overhead in terms of processor speed or space. The problems we were working on were much simpler back then but the systems were much more constrained and this drove us the focus on efficiency at all costs.





If you meet an old-timer like me in the software industry you have to be careful because when I was learning to be a professional software developer, the skills that made me excellent are actually skills that hold me back today. A lot of developers who have been in the industry as long as I have, tend to overly emphasize the performance characteristics of software because we grew up in an era where that was important. 





But today we’re less concerned about performance and more concerned about the understandability of our code, it’s maintainability and its extensibility. It would be nice if we could have everything but life doesn’t work that way. We have to make trade-offs and as a result, we find that it is more cost-effective today to build software that is understandable and extensible, even if it is a bit less performant.





I do feel a bit embarrassed that I didn’t get on the design patterns bandwagon until about 2003 or 2004 but when I did get into it, I got deeply into it. I learned about design patterns from Al Shalloway and Scott Bain at Net Objectives. I believe they have some very unique and powerful perspectives on what design patterns are and how to use them effectively, both in code and to help us understand designs more deeply.





One of the most powerful ways that I have learned to use design patterns is for encapsulating variation within a program. Variation is the thing that adds complexity to software. It also helps give software its usefulness. One way to see design patterns is as techniques for encapsulating different kinds of variations or as Scott Bain likes to say, “Design patterns make something that is varying appear to the outside as if it isn’t varying.”





I find that I use most of the 23 design patterns called out by the Gang of Four quite often. But even more valuable than those patterns is the notion of patterns in general, and how it has helped influence the way I think and understand. Patterns are about their intent, not their implementation, and being able to separate those two things out has become a major part of the way I think and understand not only software systems but also the world. I think this has helped me gain a lot of clarity about a range of areas.





Design patterns are one of my favorite subjects. They contribute significantly to my software developer superpowers. They also contribute to my general cognitive skills and my understanding in general. Design patterns are great examples of high-quality code that’s flexible. They draw on good design principles. 





The Gang of Four design patterns truly embodies the essence of object-oriented programming. In fact, I really didn’t understand object-oriented programming until I got introduced to design patterns and saw how to create complex behavior in a system through the interaction of objects rather than through just straight logic. 





I would say that having a deep understanding of design patterns is a key prerequisite for doing emergent design effectively. Unfortunately, while there are many books on software design, there is no easy recipe for doing emergent design. It’s an advanced practice that requires many skills.





Note: This blog post is based on one of the “Seven Strategies…” sections in my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software.


The post Understand Design Patterns appeared first on To Be Agile.

 •  0 comments  •  flag
Share on Twitter
Published on February 26, 2020 09:05

February 19, 2020

Understand Object-Oriented Design


The first “barrier to entry” for doing emergent design, an advanced developer practice for incrementally building software, is to understand object-oriented design and development. 





In theory, the object-oriented model should be easy to understand but I don’t often see it well-understood in industry. I’ve reviewed millions of lines of code from companies across a range of industries and while most of them use good object-oriented languages like Java or C# or C++, what I found is that much of the code I see is simply procedural code wrapped in a class statement.





So what is the difference between procedural code and good object-oriented code? What makes software object-oriented?





The answer is a matter of perspective. In procedural software, we maintain a global perspective and think of our program as a series of instructions that the computer executes step-by-step. This makes understanding the program straightforward and reasoning about what the computer is doing also straightforward because this is how we represent programs to be executed by a computer. This is also the way we think consciously. We think procedurally. We think consciously as a stream of words that are processed sequentially.





However, this is not the way the world works. There is no global perspective, at least not one that I’m aware of. The world manifests through the interaction of entities. There isn’t one global perspective but rather many perspectives and it is through the interaction of these many perspectives that things happen in the world. This is how the real world works. And so, the object-oriented programming paradigm attempts to model this.





So, what is the object-oriented paradigm? I’ll give you a couple of ways to think about this. I’ll describe one way that I like to think about object-oriented programming and then in my next blog post, I’ll discuss a different way of thinking about object-oriented programming.





Let’s start with instantiation. Instantiation gets to the very core of what object-oriented programming is all about. It’s about separating out the responsibilities of creating an object versus using the object. This is actually a pretty familiar concept because it’s how biological systems work. We all went through embryogenesis before we were born. It’s also how many other things in the world work. 





For example, the way fractals are drawn is through iterating simple mathematical formulas over and over again. One way to draw a fractal is through successive refinement where it starts in low resolution and then, through a series of iterations, gradually increases in resolution so that a high-resolution fractal emerges. Fractals, like many things in the world, are an emergent phenomenon. 





In object-oriented programming, the responsibilities of a system are broken out into different objects. This helps us manage and scale large systems. In object-oriented systems, every object should have a single responsibility. We should be able to represent the entities responsible for the behaviors that we want to create and show their relationship to each other. Doing this helps us gain clarity in our design and it also helps it become more understandable to others. 





When object-oriented programming is done well then systems are scalable and understandable because they’re clearly defined. When object-oriented systems are done poorly then systems tend to be tightly coupled and resistant to change. Object-oriented programming, like the very best medicine, can either cure you or kill you depending upon how you use it.





Note: This blog post is based on one of the “Seven Strategies…” sections in my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software.

 •  0 comments  •  flag
Share on Twitter
Published on February 19, 2020 08:59

February 12, 2020

Why Practice Eight: Implement the Design Last


By now you’ve probably figured out that I am a weirdo and that I like doing things differently than other people. In fact, I am an advocate of doing things backward.





But I’m not being random here. As it turns out, the way most people build software includes some of the worst inefficiencies that I can imagine, so doing almost anything differently can be an improvement. In traditional software, we put testing off to the very end of a project but I say let’s write our test first so we can set our expectations on what we want to build.





Conversely, most of the time people think about doing their design upfront before they actually build their system. Well, I’m not advocating that we do all of our design at the end of development, but I find that there are many aspects of design that we can put off until later and when we do it gives us the flexibility to make better decisions towards the end of development.





The fourth principle in Lean Software Development, which is an Agile software development methodology, says to “Defer important decisions until the last responsible moment.”





This is because will know more about the problem we’re solving later. We will be smarter and more informed later so if we can, it’s better to wait before making important decisions. This forces us to think about creating an optimal sequence for the decisions we need to make. In my experience, understanding this can make massive improvements in productivity… and few people do it.





Practice 8, Implement the Design Last, is also based upon a set of techniques that I have been finding valuable for building out behaviors in a system. Rather than doing my design upfront, I may acknowledge that there is a pattern in my requirements but I don’t go there initially. Instead, I write a simple implementation to make my behavioral tests pass. This gets me good tests that are in the green, which means that I can refactor safely. 





It’s in the refactor step that I start injecting patterns and good design into my systems. I find that taking this approach is highly efficient and effective. Essentially I am emerging a system or a feature or a behavior incrementally. I find this a highly effective and efficient way of building software and so has the thousands of developers I shared these techniques with.





The following seven blog posts are based on a section in my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software, called Seven Strategies for Doing Emergent Design.





Emergent design is not sloppy design or irresponsible development. It’s a shame when people who don’t understand it give it that label but it’s also understandable when newbies try to apply this very advanced practice.





I believe that emergent design is one of the most disciplined and advanced practices in software development and I consistently have seen it produce high-quality results, but only once you understand a great deal. There is a reason that it is an advanced practice. It requires experience and a diverse skillset. You need to have good design skills, understand object-oriented programming and design patterns, understand good principles and practices, plus a host of other things.





Just starting a project saying that you’ll do emergent design and then not follow good software development principles and practices—not looking to discover and recognize design patterns—isn’t doing emergent design. Emergent design requires a strong adherence to code quality where software is constantly refactored and kept clean.





In these next seven blog posts, I will attempt to briefly describe seven key skills for effectively doing emergent design. These skills are easy to name but can take a lifetime to master.





Note: This blog post is based on one of the “Seven Strategies…” sections in my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software.

 •  0 comments  •  flag
Share on Twitter
Published on February 12, 2020 08:22