What is the developer experience like at your organization? Do you have a platform engineering team? We want to hear from you!
Stop letting outdated access processes hold your team back. Learn how to build smarter, faster, and more secure DevOps infrastructures.
Stats
Reputation: | 6565 |
Pageviews: | 2.2M |
Articles: | 34 |
Comments: | 68 |
Comments
Sep 25, 2018 · Lindsay Burk
And Groovy has the "call" method!
Aug 03, 2017 · John Vester
Another point is that oftentimes when people join a team, they have to go through a period of getting used to the team's standards. This is the time in which a lot of low value (gold plating) changes are done, but it's temporary - eventually the person catches up and starts "automatically" producing code of desired quality, hence no extra gold plating is needed.
Aug 03, 2017 · John Vester
I've got mixed feelings about this. On one hand, once you've produced a quality solution that meets all the requirements, you should call it a day. On the other, once every so often I get to review code that is so hard to read that I can't effectively reason whether it's correct or not. At the same time, I'd expect that the person who wrote it is convinced that I'm pushing him/her towards gold plating.
Jul 16, 2017 · Przemyslaw Magda
Actually, it does. I just follow a simple practice: eliminate nulls at architectural boundaries and don't use null anywhere else. Works like a charm for me, haven't seen a prod NPE in my projects for a very long time.
Jul 14, 2017 · Przemyslaw Magda
I don't agree with the method parameters point. Passing null as an argument to other objects is a very bad practice as it forces you to check all the calling logic whether a null value is possible. Therefore, I never pass nulls as arguments to objects public methods. If you eliminate that, you've got to choose either an Optional argument or overloading. The second implies more testing and often a null check on the callee side as well.
Jul 14, 2017 · Grzegorz Ziemoński
Following this line of thought, there's no difference between a library and a framework, as you can argue that any kind of API frames my work. That would probably make Apache Commons one of the most popular frameworks in the world. I think that a more restrictive definition of "frame" needs to be used to have a productive discussion about frameworks.
Jul 13, 2017 · Grzegorz Ziemoński
Thanks for all the comments guys, regardless of whether you liked the post or not. Since I could not participate in the discussion actively when it took place, I decided to prepare a recap with a bunch of my thoughts as a separate article. You can check it out here: https://dzone.com/articles/discussion-recap-to-framework-or-not-to-framework
Jun 22, 2017 · Grzegorz Ziemoński
You're right about me triggering that kind of discussions. My fault :)
Jun 21, 2017 · Grzegorz Ziemoński
Ugh. Should've known that this kind of post will bring the "my language is better" kind of comments :)
Jun 06, 2017 · Grzegorz Ziemoński
Don't get me wrong. I think that verify is useful sometimes e.g. you want to make sure you send 1 email to the customer instead of 5. I just think that people are often overusing it for simple cases like getting some data out of an object.
Jun 06, 2017 · Grzegorz Ziemoński
You should be glad you haven't come across such people. I did :)
Jun 06, 2017 · Grzegorz Ziemoński
There's "every single" in there. If I have a single query method, why would I check for the number of calls made? Unfortunately, I have seen such cases in code.
Apr 28, 2017 · Grzegorz Ziemoński
Actually, you don't jump that much (in most cases not at all). If you stick to the stepdown rule, you're always going in one direction when reading the code - downwards. You read the first, most general implementation of the method. If that's enough for you, then bam, you're done with this piece of code, trivial. If you need more, you go a level down. And so forth.
Apr 28, 2017 · Grzegorz Ziemoński
The "graph of interactions" between the methods created like this is trivial. And it's way faster to analyze 7 trivial methods than a single convoluted one. Also, extracting methods is rarely a technique to reduce complexity (it's still the same code), but rather to increase readability.
Mar 25, 2017 · Grzegorz Ziemoński
You need to run it with the -comfy parameter e.g. '-conf src/main/conf/config.json' :)
Mar 20, 2017 · Grzegorz Ziemoński
The point of this mini project and post was to experiment; to see if creating a reactive flavor of Clean Architecture is even possible. I didn't mean to teach anyone any of the underlying concepts or to show how cool the solution is.
Mar 20, 2017 · Grzegorz Ziemoński
Everybody's showing easy use cases because they're simpler to understand for the readers. If I've built a complicated application and tried to explain it here, it would take 10k words and nobody would read it. It would also take a considerable amount of time to produce the code just to explain a simple concept. Hence, most bloggers provide easy examples and hope that people will treat them as a starting point to build something bigger instead of complaining about incomplete solutions.
Mar 17, 2017 · Grzegorz Ziemoński
Then I'm doing half-OO or even not doing OO in your understanding. I model domains, not business functions. Hence, the entities to perform domain stuff any only it. The application-related business functions are taken care of by the use case and MVC objects in my world.
Mar 17, 2017 · Grzegorz Ziemoński
1. That's a bold statement. I'd say that it depends on the kind of object you're talking about, problem domain and advancement of the project. You can have objects in your system that simply do nothing yet, or they never will because their business purpose it to store data (e.g. a blog post in a simple blogging platform).
2. That's nitpicking. Obviously when saying "reading data", I meant ultimately displaying it to the user.
3. That's one way to think about packages, but it basically crushes most (if not all) feature-oriented architectures. Unless you consider a use case + bunch of interfaces a feature.
4. Oh, well. I agree that it's not much work to ensure ID immutability. To be honest, I started this little experiment by mimicking Uncle Bob's code in my project and then didn't bother to change it.
5. Same as in point 2.
Mar 17, 2017 · Grzegorz Ziemoński
Let me (try to) explain:
Anemic Objects - that's what you have when the only operation in your system is reading data
Higher packages referring to packages below - packages don't necessarily need to be grouped by business "importance", hence a view in the same package as use case and references to packages "below" (if I understood the point correctly)
Non-final IDs - I guess that's assuming that you're not working with idiots and that a bunch of setters is simpler than builders and final fields
More technical terms than business terms - can happen in a boring domain when you have reading as the only operation (again)
Separation of data from function - what function? there's only reading (again, again)
Mar 14, 2017 · Grzegorz Ziemoński
I don't find this text a rant against object-orientation. I find it a rant against the way we produce object-oriented software using current languages. The authors argue that apart from objects that communicate together, there are also interactions between objects that should belong to neither of them. It's not that decomposing a system into objects is too hard. It's just that following just that decomposition style is artificial.
Mar 14, 2017 · Grzegorz Ziemoński
Hm. 2002.. I was 9 then :) Thanks for linking this up, I will definitely check it!
Mar 14, 2017 · Grzegorz Ziemoński
I messed up this sentence, I corrected it already. So the role needs some access to the data objects state e.g. that printer needs to know the title and description to do its job. At the same time, it probably shouldn't happen via direct field access - we need a way to protect the object's invariants. The trygve language shows this relationship nicely:
role Ball {
public void erase() {
ThePanel.setColor(new Color(239, 237, 239));
ThePanel.drawCircle(getX, getY, radius())
}
// stuff
} requires {
int getX();
int getY();
// stuff
}
Mar 13, 2017 · Grzegorz Ziemoński
I don't mean a Big Design Up Front. I mean learning the domain up front. Also, I'm trying to show "Lean Architecture as I understanding it" point of view here, not necessarily my own :)
Mar 13, 2017 · Grzegorz Ziemoński
Because it can mean rework, hacking and/or unexpected functionality at times. Imagine you're writing a Pet Clinic, something like the Spring one, and you made the decision that each visit has an assigned pet. You created an UI that matches this, a lot of other functionality makes use of this fact too. Then, after a few months, you're asked to add sending a notification to the pet owners about an upcoming visit. For the most part, it works fine, but those that come with a few pets at once are going crazy. Why the hell am I getting 5 messages about the same appointment? So you're asked to fix that behavior. Now, there's a problem, because you're either hacking the domain by handling the multi-pet visit in the module responsible for sending the notifications, or you're reworking half of your application to use a collection of pets on a visit, instead of a single one. Sounds impossible? I've seen the customers who didn't mention important facts like this for a long, long time, hacking the system by their own instead of getting it corrected as soon as they notice. That's just an example, but it should help you why it's nice to get things right as early as possible.
Mar 13, 2017 · Grzegorz Ziemoński
Yes, they would. You got it right! :)
Mar 13, 2017 · Grzegorz Ziemoński
Of course, you can't know it all, but you can know a lot more than people usually do at the start of the project. The right way to think about the data is not "data you need to capture", but the domain model that supports my application development. The former leads to naive design e.g. I've seen a guy who deleted an order date from the class Order because there was no UI yet and it wasn't accessed anywhere in the code. The latter should help you avoid surprises e.g. learning that a bank account is, in reality, a log of transactions instead of a class that has a "BigDecimal balance" inside could save you a lot of trouble later in the project.
Mar 13, 2017 · Grzegorz Ziemoński
In Lean Architecture (the book I mentioned), there is a lot of accent on getting as much of the data objects right upfront as possible. You're working with the users, domain experts, business people etc. to get a stable, comprehensive picture of the domain even if not all elements of this picture are currently used. You don't have to necessarily implement it all, but you need to know it all and represent it somehow e.g. unimplemented interface method. So in this approach, the data objects shouldn't grow much after the design phase is over (although in practice they might).
As for the relationships between objects, the data part seems like a perfect place to capture such relationships. The fact that one account can have many owners and one owner can have many accounts comes directly from the domain - that's how it works in the banks.
Mar 08, 2017 · Grzegorz Ziemoński
I don't think there's any disagreement :) I stated that most systems will outlive major releases as well. I included the point just to avoid people saying "you rarely need to change your web framework or a database" or "you don't need to change frameworks in one-off applications". I had a glance at your example and it looks really interesting. I'll give it more time later, thanks for sharing!
Mar 08, 2017 · Grzegorz Ziemoński
I meant idiomatic usage rather than an idiomatic framework. I meant the kind of constructs spread widely among developer's community e.g. using Spring's @Component annotations to create beans.
Mar 08, 2017 · Grzegorz Ziemoński
I believe that they didn't finish this one :)
Mar 04, 2017 · Grzegorz Ziemoński
Well, most people have a definition of a feature - they just package an object with services related to it. But I feel that it's a really flawed view for two reasons:
1. If your domain objects have a two-way relationship your "features" will have a cyclic dependency in one way or another.
2. Often the use cases themselves require you to link data from multiple services and your features get tangled anyway.
Mar 04, 2017 · Grzegorz Ziemoński
Sounds like you guys do a great job. Keep it up!
Mar 04, 2017 · Grzegorz Ziemoński
Good points! Many people miss the point that if you build all your Maven modules at once and they're always using the current codebase version of each other, much of the benefit of splitting into modules is effectively gone.
Mar 03, 2017 · Grzegorz Ziemoński
Thanks for sharing your experiences! I'm curious, how big are your features (modules)? Are they more of the size of a bounded context or rather a single aggregate with services related to it?
Mar 03, 2017 · Grzegorz Ziemoński
Yes, my next post is going to be about his one! It's coming out on Monday on my blog and a day or two later on DZone :)
Feb 28, 2017 · Grzegorz Ziemoński
Next in the architecture series is Package by Feature, then we'll tackle Clean Architecture :)
Feb 18, 2017 · Grzegorz Ziemoński
Well, it's nobody's fault that Spring Pet Clinic contained just a few entities.
The thing with the domain layer is that I'd put there all the domain stuff - entities, services, factories, exceptions, even repository interfaces. Then, has it grown to a significant size, I might actually chop it into smaller pieces e.g. domain "layers" or package-per-aggregate. But I wouldn't think about reusability at this point, I'd think about the clarity of my domain model. If then, at some point, I'd have to share a piece of that model, I'd extract that to a shared artifact.
Also, as I said in another comment, my intention with this article was to explain to the beginners what layers are about and to show some non-beginners that layers themselves are not the source of all evil in their projects. I didn't mean to say that packaging-by-layer is the only architectural decision that I'd make in my projects, far from that!
Feb 17, 2017 · Grzegorz Ziemoński
Obviously, I meant that technical decomposition is not enough when the project grows. And I didn't mean to say that you cannot mix it with functional decomposition, I meant that Layered Architecture by itself gives you nothing in this area. I'd contrast this with styles like Package By Feature, which let you scale much, much more.
Feb 17, 2017 · Grzegorz Ziemoński
Sure they do. But I'm not sure why is everyone pushing it so much in comments to this article. I had two types of people in mind when writing this piece:
- those who don't understand the term at all - for them it would be way too much information
- those who blame the concept of layered architecture for everything that's wrong with their projects - they need to understand that layering is just about separating stuff and it's not enough for a big system. That's why I put accent on code organization and I said that you need to complement it with techniques from DDD or similar and that layers by themselves don't scale - you need another kind of slicing
Feb 17, 2017 · Grzegorz Ziemoński
The domain in the example is in a separate package. Just bash it into a JAR or copy it and you're on your way to reuse. You won't do it so easily with Controllers, Formatters and similar in place, would you? What I'd perceive as real problem with that project is either that the domain was actually scattered around the application and not only in the domain layer, or you wanted to reuse something from other layers and it required some vertical slicing.
Feb 17, 2017 · Grzegorz Ziemoński
That's a pretty good text. In general, I agree that almost every system will require vertical slicing at some point (little caveat: https://dzone.com/articles/bind-your-contexts-dont-hurt-them). At the same time, I would not bash too many concepts into the "Layered Architecture" term i.e. domain layering, Clean Architecture, packaging-by-feature, packaging-by-component etc. I like to think about Layered Architecture as about technical code organization style. All other terms are similar concepts or modifications of it, but not the same thing.
Feb 17, 2017 · Grzegorz Ziemoński
When does this article say Layered Architecture and further decomposition are mutually exclusive? I even pointed out the need to further decompose in the drawback point about scalability.
Feb 16, 2017 · Grzegorz Ziemoński
Thanks for the comment. I believe that many people might interpret things just like you, so I provided a longer, a little ranty response as a separate article:
http://tidyjava.com/bind-contexts-dont-choke/
TL;DR Some public methods on domain objects are a low cost for not cutting your domain too much or squeezing it with objects like controllers.
Feb 16, 2017 · Mike Gates
Yep, good comment! With the caveat that it's even more indirection and more classes to deal with, which might not be suitable for simple applications that don't benefit from the extra decoupling.
Feb 16, 2017 · Mike Gates
Thank you for reading and commenting! Feel free to point mistakes or missing insights if you find any - it's an honor to learn from the greatest.
Grzegorz
Feb 13, 2017 · Grzegorz Ziemoński
I simply use "separation of concerns" for any kinds of concerns that should be separated. I think that the problem most people have with layers is not that we need to separate presentation from the domain. It's the fact that we apply this layering at package- or even deployment level, while class level separation would suffice.
Feb 03, 2017 · Saral Khare
Java Devs, brace yourselves! The winter of mocks is coming!
Jan 26, 2017 · Mike Gates
That's what the second point is about?
Jan 19, 2017 · Mike Gates
Well, this one might not be the best, but it is just our opinion. Corporate developers who do JSP daily might think differently :)
Jan 19, 2017 · Mike Gates
So, you partly answered your question: everyone who exposes REST servies with Spring uses Spring MVC.
About JSP and similar technologies, I know companies that use it and there are good reasons like security or backwards compatibility. Don't get me wrong, I believe that you can solve the same problems using modern technologies with a better result, but if you consider how the enterprises make decisions and how reluctant management people can be to push new technologies, it should be obvious that technologies like JSP are far from dead.
Jan 19, 2017 · Mike Gates
Unless you have a really good reason, you shouldn't write all of that by yourself. Spring Boot is a way more viable option for starting Spring projects right now :)
Nov 15, 2016 · Tim Spann
I'm glad to hear that! Will do my best!
Nov 05, 2016 · Tim Spann
Thanks! It's nice to see that technologies like Swing are still used and extended. GUI is one of the places where reusability is a really important concern. It's also probably the best place to play with various design patterns. I see a real challenge in moving the concepts of reusability, patterns etc. to the world of back-end software without introducing needless complexity, hence the post.
Oct 25, 2016 · Sarah Davis
How much pair programming have you done in your life?
Sep 28, 2016 · Shirish Bari
What you should really do in such case is use a company-wide artifact repository like nexus or artifactory.
Aug 24, 2016 · Duncan Brown
That comment wasn't targetted at you/this particular example. It's a general thought that I wanted to share. In many cases people use regex, while it's possible to state rules in a more comprehendible way.
Aug 24, 2016 · Duncan Brown
Regex usage is a code smell :)
Aug 18, 2016 · Dave Fecak
I didn't put that chimpanzee there, some DZone editor did :)
Jul 06, 2016 · grspain
Thanks for the advice :)
Jul 05, 2016 · grspain
C'mon I cut SOLID of OL cuz I couldn't find the right explanation for these :)
Jul 05, 2016 · grspain
http://tidyjava.com/dependency-inversion-in-java/
Jul 05, 2016 · grspain
Ye, the word 'architect' makes me energetic :)
Jun 06, 2016 · Sam Atkinson
My favorite example of abusing Java 8 is getting first element in a collection (there's a lot of that in integrating services):
elements.stream().findFirst().get();
Each time I see it, I want to cry :D
May 23, 2016 · Grzegorz Ziemoński
Well, I think we're just operating at different levels.
When I'm talking about design patterns being blueprints, I literally mean the problem in the book/source e.g.:
Problem: I need to be able to add/exchange algorithms easily without modifying the class that's using them. I cannot/don't want to use inheritance, because the inheritance tree is organized around something else and would grow very big or any other reason.
Solution: Strategy pattern as a blueprint.
If I understand correctly, what you mean is:
Problem: Choosing an algorithm at runtime
Solution: Simplest thing that fits my needs, no blueprints.
May 10, 2016 · Grzegorz Ziemoński
I knew you meant jOOQ, just playing with you ;-)
Honestly, when writing the text, I didn't mean to say that ORM is the only way to handle the mapping. In the "separate model" solution (which should be called something like "manual mapping"), "Database entity" could also mean a plain-old ResultSet or a Record or whatever else.
May 10, 2016 · Grzegorz Ziemoński
Sure, you could do that in the mapping solution. It's just.. ORM's are evil, but convenient and SQL is just evil ;-) One example, I like swapping DBs for testing and it's not always possible with SQLs in the code.
May 09, 2016 · Grzegorz Ziemoński
Thanks for your insight!
Yes, you can use XML files. But that's just moving the problem from .java to .xml, isn't it?
The article didn't mention DAOs (maybe it should), but I'd even say that the DAO/Repository/call-it-whatever interface should be the part of the domain layer to preserve correct dependency direction.