3 added 4 characters in body
source | link

YAGNI and SOLID (or any other design methodology) are not mutually exclusive. However, they are near-polar opposites. You do not have to adhere 100% to either, but there will be some give-and-take; the more you look at a highly-abstracted pattern used by one class in one place, and say YAGNI and simplify it, the less SOLID the design becomes. The reverse can be true as well; many times in development, a design is implemented SOLIDly "on faith"; you don't see how you will need it, but you just have a hunch. This could be true (and is more and more likely to be true the more experience you gain), but it could also put you in as much technical debt as a slap-dash "do it light" approach; instead of a DIL "spaghetti code" codebase, you may end up with "lasagna code", having so many layers that simply adding a method or a new data field becomes a days-long process of wading through service proxys and loosely-coupled dependencies with only one implementation. Or you could end up with "ravioli code", which comes in such small bite-size chunks that moving up, down, left or right in the architecture takes you through 50 methods with 3 lines each.

I've said it in other answers, but here it is: On the first pass, make it work. On the second pass, make it elegant. On the third pass, make it SOLID.

Breaking that down:

When you first write a line of code, it simply has to work. At this point, for all you know, it's a one-off. So, you don't get any style points for building an "ivory-tower" architecture to add 2 and 2. Do what you gotta do, and assume you'll never see it again.

The next time your cursor goes in that line of code, you have now disproved your hypothesis from when you first wrote it. You are revisiting that code, likely either to extend it or to use it elsewhere, so it's not a one-off. Now, some basic principles like DRY (don't repeat yourself) and other simple rules for code design should be implemented; extract methods and/or form loops for repeated code, extract variables for common literals or expressions, maybe add some comments, but overall your code should self-document. Now, your code is well-organized, if still maybe tightly-coupled, and anyone else looking at it can easily learn what you're doing by reading the code, instead of tracing it line-by-line.

The third time your cursor enters that code, it's probably kind of a big deal; you're either extending it yet again or it's become useful in at least three different other places in the codebase. At this point, it's a key, if not core, element of your system, and should be architected as such. At this point, you usually also have the knowledge of how it's been used so far, which will allow you to make good design decisions regarding how to architect the design to streamline those usages and any new ones. Now the SOLID rules should enter the equation; extract classes containing code with specific purposes, define common interfaces for any classes that have similar purposes or functionality, set up loosely-coupled dependencies between classes, and design the dependencies such that you can easily add, remove, or swap them. 

From this point on, should you need to further extend, reimplement or re-use this code, it's all nicely packaged up and abstracted in the "black box" format we all know and love; plug it in wherever else you need it, or add a new variation on the theme as a new implementation of the interface without having to change the usage of said interface.

YAGNI and SOLID (or any other design methodology) are not mutually exclusive. However, they are near-polar opposites. You do not have to adhere 100% to either, but there will be some give-and-take; the more you look at a highly-abstracted pattern used by one class in one place, and say YAGNI and simplify it, the less SOLID the design becomes. The reverse can be true as well; many times in development, a design is implemented SOLIDly "on faith"; you don't see how you will need it, but you just have a hunch. This could be true (and is more and more likely to be true the more experience you gain), but it could also put you in as much technical debt as a slap-dash "do it light" approach; instead of a DIL "spaghetti code" codebase, you may end up with "lasagna code", having so many layers that simply adding a method or a new data field becomes a days-long process of wading through service proxys and loosely-coupled dependencies with only one implementation. Or you could end up with "ravioli code", which comes in such small bite-size chunks that moving up, down, left or right in the architecture takes you through 50 methods with 3 lines each.

I've said it in other answers, but here it is: On the first pass, make it work. On the second pass, make it elegant. On the third pass, make it SOLID.

Breaking that down:

When you first write a line of code, it simply has to work. At this point, for all you know, it's a one-off. So, you don't get any style points for building an "ivory-tower" architecture to add 2 and 2. Do what you gotta do, and assume you'll never see it again.

The next time your cursor goes in that line of code, you have now disproved your hypothesis from when you first wrote it. You are revisiting that code, likely either to extend it or to use it elsewhere, so it's not a one-off. Now, some basic principles like DRY (don't repeat yourself) and other simple rules for code design should be implemented; extract methods and/or form loops for repeated code, extract variables for common literals or expressions, maybe add some comments, but overall your code should self-document. Now, your code is well-organized, if still maybe tightly-coupled, and anyone else looking at it can easily learn what you're doing by reading the code, instead of tracing it line-by-line.

The third time your cursor enters that code, it's probably kind of a big deal; you're either extending it yet again or it's become useful in at least three different other places in the codebase. At this point, it's a key, if not core, element of your system, and should be architected as such. At this point, you usually also have the knowledge of how it's been used so far, which will allow you to make good design decisions regarding how to architect the design to streamline those usages and any new ones. Now the SOLID rules should enter the equation; extract classes containing code with specific purposes, define common interfaces for any classes that have similar purposes or functionality, set up loosely-coupled dependencies between classes, and design the dependencies such that you can easily add, remove, or swap them. From this point on, should you need to further extend, reimplement or re-use this code, it's all nicely packaged up and abstracted in the "black box" format we all know and love; plug it in wherever else you need it, or add a new variation on the theme as a new implementation of the interface without having to change the usage of said interface.

YAGNI and SOLID (or any other design methodology) are not mutually exclusive. However, they are near-polar opposites. You do not have to adhere 100% to either, but there will be some give-and-take; the more you look at a highly-abstracted pattern used by one class in one place, and say YAGNI and simplify it, the less SOLID the design becomes. The reverse can be true as well; many times in development, a design is implemented SOLIDly "on faith"; you don't see how you will need it, but you just have a hunch. This could be true (and is more and more likely to be true the more experience you gain), but it could also put you in as much technical debt as a slap-dash "do it light" approach; instead of a DIL "spaghetti code" codebase, you may end up with "lasagna code", having so many layers that simply adding a method or a new data field becomes a days-long process of wading through service proxys and loosely-coupled dependencies with only one implementation. Or you could end up with "ravioli code", which comes in such small bite-size chunks that moving up, down, left or right in the architecture takes you through 50 methods with 3 lines each.

I've said it in other answers, but here it is: On the first pass, make it work. On the second pass, make it elegant. On the third pass, make it SOLID.

Breaking that down:

When you first write a line of code, it simply has to work. At this point, for all you know, it's a one-off. So, you don't get any style points for building an "ivory-tower" architecture to add 2 and 2. Do what you gotta do, and assume you'll never see it again.

The next time your cursor goes in that line of code, you have now disproved your hypothesis from when you first wrote it. You are revisiting that code, likely either to extend it or to use it elsewhere, so it's not a one-off. Now, some basic principles like DRY (don't repeat yourself) and other simple rules for code design should be implemented; extract methods and/or form loops for repeated code, extract variables for common literals or expressions, maybe add some comments, but overall your code should self-document. Now, your code is well-organized, if still maybe tightly-coupled, and anyone else looking at it can easily learn what you're doing by reading the code, instead of tracing it line-by-line.

The third time your cursor enters that code, it's probably kind of a big deal; you're either extending it yet again or it's become useful in at least three different other places in the codebase. At this point, it's a key, if not core, element of your system, and should be architected as such. At this point, you usually also have the knowledge of how it's been used so far, which will allow you to make good design decisions regarding how to architect the design to streamline those usages and any new ones. Now the SOLID rules should enter the equation; extract classes containing code with specific purposes, define common interfaces for any classes that have similar purposes or functionality, set up loosely-coupled dependencies between classes, and design the dependencies such that you can easily add, remove, or swap them. 

From this point on, should you need to further extend, reimplement or re-use this code, it's all nicely packaged up and abstracted in the "black box" format we all know and love; plug it in wherever else you need it, or add a new variation on the theme as a new implementation of the interface without having to change the usage of said interface.

2 added 375 characters in body
source | link

YAGNI and SOLID (or any other design methodology) are not mutually exclusive. However, they are near-polar opposites. You do not have to adhere 100% to either, but there will be some give-and-take; the more you look at a highly-abstracted pattern used by one class in one place, and say YAGNI and simplify it, the less SOLID the design becomes. However, theThe reverse can be true as well; many times in development, a design is rarely true; usuallyimplemented SOLIDly "on faith"; you don't see how you will need it, but you just have a program becomeshunch. This could be true (and is more SOLID when stricter adherenceand more likely to be true the SOLID principles is necessary;more experience you ARE gonna need that interfacegain), or to have this codebut it could also put you in its own method or classas much technical debt as a slap-dash "do it light" approach; instead of being inlined. If adhering to SOLID does violate YAGNIa DIL "spaghetti code" codebase, we usually callyou may end up with "lasagna code", having so many layers that "ivorysimply adding a method or a new data field becomes a days-tower architecture"long process of wading through service proxys and it will usually become a hindrance to further productivityloosely-coupled dependencies with only one implementation. Or you could end up with "ravioli code", incurring its own "technical debt"which comes in such small bite-size chunks that moving up, down, left or right in the architecture takes you through 50 methods with 3 lines each.

The next time your cursor goes in that line of code, you have now disproved your hypothesis from when you first wrote it. You are revisiting that code, likely either to extend it or to use it elsewhere, so it's not a one-off. Now, some basic principles like DRY (don't repeat yourself) and other simple rules for code design should be implemented; extract methods and/or form loops for repeated code, extract variables for common literals or expressions, maybe add some comments, but overall your code should self-document. Now, your code is well-organized, if still maybe tightly-coupled, and anyone else looking at it can easily learn what you're doing by reading the code, instead of tracing it line-by-line.

The third time your cursor enters that code, it's probably kind of a big deal; you're either extending it yet again or it's become useful in at least three different other places in the codebase. At this point, it's a key, if not core, element of your system, and should be architected as such. At this point, you usually also have the knowledge of how it's been used so far, which will allow you to make good design decisions regarding how to architect the design to streamline those usages and any new ones. Now the SOLID rules should enter the equation; extract classes containing code with specific purposes, define common interfaces for any classes that have similar purposes or functionality, set up loosely-coupled dependencies between classes, and design the dependencies such that you can easily add, remove, or swap them. From this point on, should you need to further extend, reimplement or re-use this code, it's all nicely packaged up and abstracted in the "black box" format we all know and love; plug it in wherever else you need it, or add a new variation on the theme as a new implementation of the interface without having to change the usage of said interface.

YAGNI and SOLID (or any other design methodology) are not mutually exclusive. However, they are near-polar opposites. You do not have to adhere 100% to either, but there will be some give-and-take; the more you look at a highly-abstracted pattern used by one class in one place, and say YAGNI and simplify it, the less SOLID the design becomes. However, the reverse is rarely true; usually, a program becomes more SOLID when stricter adherence to the SOLID principles is necessary; you ARE gonna need that interface, or to have this code in its own method or class instead of being inlined. If adhering to SOLID does violate YAGNI, we usually call that "ivory-tower architecture" and it will usually become a hindrance to further productivity, incurring its own "technical debt".

The next time your cursor goes in that line of code, you have now disproved your hypothesis from when you first wrote it. You are revisiting that code, likely either to extend it or to use it elsewhere, so it's not a one-off. Now, some basic principles like DRY (don't repeat yourself) and other simple rules for code design should be implemented; extract methods and/or form loops for repeated code, extract variables for common literals or expressions, maybe add some comments, but overall your code should self-document.

The third time your cursor enters that code, it's probably kind of a big deal; you're either extending it yet again or it's become useful in at least three different other places in the codebase. At this point, it's a key, if not core, element of your system, and should be architected as such. At this point, you usually also have the knowledge of how it's been used so far, which will allow you to make good design decisions regarding how to architect the design to streamline those usages and any new ones. Now the SOLID rules should enter the equation; extract classes containing code with specific purposes, define common interfaces for any classes that have similar purposes or functionality, set up loosely-coupled dependencies between classes, and design the dependencies such that you can easily add, remove, or swap them.

YAGNI and SOLID (or any other design methodology) are not mutually exclusive. However, they are near-polar opposites. You do not have to adhere 100% to either, but there will be some give-and-take; the more you look at a highly-abstracted pattern used by one class in one place, and say YAGNI and simplify it, the less SOLID the design becomes. The reverse can be true as well; many times in development, a design is implemented SOLIDly "on faith"; you don't see how you will need it, but you just have a hunch. This could be true (and is more and more likely to be true the more experience you gain), but it could also put you in as much technical debt as a slap-dash "do it light" approach; instead of a DIL "spaghetti code" codebase, you may end up with "lasagna code", having so many layers that simply adding a method or a new data field becomes a days-long process of wading through service proxys and loosely-coupled dependencies with only one implementation. Or you could end up with "ravioli code", which comes in such small bite-size chunks that moving up, down, left or right in the architecture takes you through 50 methods with 3 lines each.

The next time your cursor goes in that line of code, you have now disproved your hypothesis from when you first wrote it. You are revisiting that code, likely either to extend it or to use it elsewhere, so it's not a one-off. Now, some basic principles like DRY (don't repeat yourself) and other simple rules for code design should be implemented; extract methods and/or form loops for repeated code, extract variables for common literals or expressions, maybe add some comments, but overall your code should self-document. Now, your code is well-organized, if still maybe tightly-coupled, and anyone else looking at it can easily learn what you're doing by reading the code, instead of tracing it line-by-line.

The third time your cursor enters that code, it's probably kind of a big deal; you're either extending it yet again or it's become useful in at least three different other places in the codebase. At this point, it's a key, if not core, element of your system, and should be architected as such. At this point, you usually also have the knowledge of how it's been used so far, which will allow you to make good design decisions regarding how to architect the design to streamline those usages and any new ones. Now the SOLID rules should enter the equation; extract classes containing code with specific purposes, define common interfaces for any classes that have similar purposes or functionality, set up loosely-coupled dependencies between classes, and design the dependencies such that you can easily add, remove, or swap them. From this point on, should you need to further extend, reimplement or re-use this code, it's all nicely packaged up and abstracted in the "black box" format we all know and love; plug it in wherever else you need it, or add a new variation on the theme as a new implementation of the interface without having to change the usage of said interface.

1
source | link

YAGNI and SOLID (or any other design methodology) are not mutually exclusive. However, they are near-polar opposites. You do not have to adhere 100% to either, but there will be some give-and-take; the more you look at a highly-abstracted pattern used by one class in one place, and say YAGNI and simplify it, the less SOLID the design becomes. However, the reverse is rarely true; usually, a program becomes more SOLID when stricter adherence to the SOLID principles is necessary; you ARE gonna need that interface, or to have this code in its own method or class instead of being inlined. If adhering to SOLID does violate YAGNI, we usually call that "ivory-tower architecture" and it will usually become a hindrance to further productivity, incurring its own "technical debt".

I've said it in other answers, but here it is: On the first pass, make it work. On the second pass, make it elegant. On the third pass, make it SOLID.

Breaking that down:

When you first write a line of code, it simply has to work. At this point, for all you know, it's a one-off. So, you don't get any style points for building an "ivory-tower" architecture to add 2 and 2. Do what you gotta do, and assume you'll never see it again.

The next time your cursor goes in that line of code, you have now disproved your hypothesis from when you first wrote it. You are revisiting that code, likely either to extend it or to use it elsewhere, so it's not a one-off. Now, some basic principles like DRY (don't repeat yourself) and other simple rules for code design should be implemented; extract methods and/or form loops for repeated code, extract variables for common literals or expressions, maybe add some comments, but overall your code should self-document.

The third time your cursor enters that code, it's probably kind of a big deal; you're either extending it yet again or it's become useful in at least three different other places in the codebase. At this point, it's a key, if not core, element of your system, and should be architected as such. At this point, you usually also have the knowledge of how it's been used so far, which will allow you to make good design decisions regarding how to architect the design to streamline those usages and any new ones. Now the SOLID rules should enter the equation; extract classes containing code with specific purposes, define common interfaces for any classes that have similar purposes or functionality, set up loosely-coupled dependencies between classes, and design the dependencies such that you can easily add, remove, or swap them.