TDD, Scrum and Architecture: KISS Conflict and Complexity

I work now, starting a year after Scrum, TDD, Domain Driven Design, and Uncle Bobโ€™s recipes. But I have some doubts that we apply various principles, mainly when reading "Java Application Architecture" (now JAA) always from Martin's series. Please correct me if I am wrong! (and I hope) The problem starts with TDD and Scrum, stating that we must develop a system that implements the requirements after they appear, avoiding pre-development. This makes me work by leaving all extensibility points open, (ab) using all kinds of extensibility patterns all the time. This is truly the "dark side": the complexity of the entire system. I do not know in advance if a certain part of my code should develop further.

BUT, as correctly stated everywhere (and very often on the JAA), you should add complexity only when necessary. This IMHO concludes that a worthy analysis should be made at the front ... contrary to other recipes ...

So the loop .... aaargh I hate circular dependencies !!!

Should we reorganize things to reduce complexity after the function is "confirmed"? Should we use the simplest way, allowed and only if necessary, expand it? For example, do not create super-untied things when you do not need them yet?

(Any suggestion to improve the style and content of the question is welcome, I'm new to stackoverflow)

+4
source share
5 answers

Should we reorganize things to reduce complexity after the function is "confirmed"? Should we use the simplest way, allowed and only if necessary, expand it? For example, do not create super-untied things when you do not need them yet?

Yes Although this is rather subjective, I do not like systems that have the flexibility to change every thing that needs to be changed, while you will not use all these flexibility. Your statement is contradictory: Test Driven Development taught me to "do the simplest thing that could work."

If more functionality is required, you can add tests and then reorganize and extend the code to make sure that it does what you want. Since you have tests in place, you can be sure that you are not breaking existing code.

In short: don't create flexibility because you can. You must build flexibility because the situation dictates to you. I strongly believe that on-demand refactoring makes the build time of your project shorter than the built-in flexibility. With your checks, on-demand refactoring should not take too much time.

In short: keep it simple, stupid .;)

+8
source

I believe that there is a balance between simple things and a deep architectural understanding of the system.

I am trying to separate short-term planning from long-term planning. In short-term planning, I think that only a couple of steps forward, if this function is likely to be expanded / changed / updated at the next iteration, then I will try to do it for this. But if I do not foresee any expansion, I will simply follow the KISS principle.

In long-term planning, I think at least six months in advance. What will be the interactions, what is the possible roadmap? This gives me basic ideas on where I will make things a bit more advanced.

IMHO should make informed decisions between planning and fulfilling short-term goals.

+4
source

I suspect that experienced designers continue an element of intuition. There are "obvious" architectural decisions made, stratification, separation of problematic solutions, "discarding". The trick is to avoid paralysis analysis and over engineering.

As the granularity increases, as we get closer to the code, the mantra becomes "more important" - it is too easy to get attachment to beautiful flexibility. But you can enable future flex with a few simple approaches. For example, expressing relationships between components in terms of (in Java) interfaces. You can't go for a full-fledged abstract Factory Pattrern, but if the consumer is encoded in an interface, it's pretty easy to enter. Likewise, not scattering string literals around your code, but collecting them in one place can greatly simplify future internationalization or dynamic configuration, even if you don't need to export strings right now.

The really good designers that I see seem like a game in Chess or Go, they expect future moves, but, of course, do not play the answers until they need it. (It might be worth considering the term Go aji-keshi .)

Ha, this is funny: I looked that the aji-keshi link explains the term only to find that the author applied this term to system design, addressing exactly this question!

+2
source

No doubt you should add code that does the simplest thing first, but the added code should adhere to SOLID principles.

Do not enter complexity (e.g. design patterns, frameworks, etc.), just thinking about what changes may happen in the future.

The essential complexity of the problem you are solving cannot be changed. This requires preliminary thinking, brainstorming, but Unhappy complexity is added with speculation.

There is a regular review of reviews for peer codes. If your colleague can read and understand the code without raising his eyebrows, then I think that everything should be fine.

+1
source

This makes me work by leaving all extensibility points open, (ab) using all kinds of extenisibilty patterns all the time. This is truly the "dark side": the complexity of the entire system. I do not know in advance if any part of my code needs further development.

Should we use the simplest way, allowed and only if necessary, expand it?

I think that at least part of the puzzle can be solved by customizing your definitions of simplicity and complexity.

JAA "recipes", SOLID principles, etc. - All these are shortcuts for managing connectivity and connectivity in design. If you define the โ€œsimplicityโ€ of a design as the degree to which you achieve maximum cohesion and minimal connectivity, you can say that these principles and patterns are designed to keep your design simple .

Therefore, according to this definition, what you call "extensibility points" is actually the result of simplified design and therefore not complicated. In addition, whether they will be used in the future with the aim of extending passes, since the purpose of the simple design is to facilitate future changes .

The phrase "the simplest thing that could work" refers more to the choice of what needs to be built and to the smaller code design. For example, if you need to display an HTML page, create an HTML page, not a web application.

So, if you adhere to the definition of simplicity above, how you maintain your design, and you build a minimum to solve any problem, your code base will be smaller, your design will be less complicated and your application will suggest the changes necessary for the future addition of functions.

One final note: Pay attention to what your tests have to say about your design. Grip and grip problems often manifest as bulky testing instruments. When you see this, it indicates that you have skipped some of the necessary refactoring steps.

+1
source

All Articles