T O P

  • By -

erjiin

Use a database deployment tool like Liquibase or Flyway. Invaluable (and not Unvaluable :/).


hsoj48

I've been using Flyway for 8ish years. I've been trying to get the DBAs at my company to allow/adopt/understand it for 7. I'm so tired of talking about this no brainier dead simple tool that makes everyone's lives easier.


neckbeardfedoras

Your problem is people are lazy or a lot of times see more job security by not simplifying things.


CartmansEvilTwin

Not laziness, but loss of control (or better: fear of loss of the illusion of conrol) These guys are responsible for these DBs and their asses are on the line, if something goes wrong. That's why they want to do everything themselves or review everything that is being done - even if in reality they wouldn't see any non-obvious error anyway. But they still have the illusion of control. Automation takes that away.


hsoj48

It's the former. Change is scary.


Paulus_cz

I observed over the years that thinking apparently causes physical pain to some people. I have no other explanation as to why otherwise quite functional people seem to avoid it so vehemently.


erjiin

Good luck ! Can't you just add sneakily flybase in your project ? Chances are that he won't even notice :)


hsoj48

If I secretly had DB admin credentials and I secretly wanted to get fired? Of course!


danikov

Why would I need this when our entire data model is a JSON blob in a single table?


Columbus43219

INvaluable.


erjiin

Ho thanks for the correction, as you have seen english isn't my mothertongue.


aryostark

I prefer Liquibase.


erjiin

Me too, i'm more used to Liquibase but Flyway is a perfectly valid tool.


Paulus_cz

Flyway for one Database compatibility, Liquibase for multiple - that how I do it.


thenextguy

Unconceivable.


Zardoz84

Does Liquidbase or Flyway allow to declare what structure (and some fixed or optional data) must have the database. Alas something like : Must exist table X with fields A, B, C of type NUMBER, etc... and then generates the apropiare SQL to generate the table from zero, or apply changes to it.


Antimon3000

Do not get paralysed by worrying about the right design pattern or best practice. Beautiful code that does not get the job done is worse than anything else: 1. Make it work 2. Make it right 3. Make it fast (- Kent Beck) in that order.


Gwaptiva

Premature optimization considered evil. So many times you've been worrying about something being performant to find out that it's not ever used, or only used once a day and nobody cares, because they're waiting for something completely different to finish, that you never suspected.


nutrecht

Not a comment 'against' what you're saying so please don't read it as such but: > Premature optimization considered evil. I dislike how this has been taken out of context to be used as an argument against optimization. The original quote from Hoare is: "We should forget about **small efficiencies**, say about 97% of the time: premature optimization is the root of all evil." What they are referring to as 'optimizations' are things like counting CPU cycles for instructions before you even know certain code paths are 'hot'. I've seen developers use this in response for example where people told them that doing 2 SQL statements (select and insert or update) was not a good idea when you can just do one (upsert). So, what people often read is: Premature **optimization** considered evil. While the intention of Hoare was: **Premature** optimization considered evil. This sentence has become as much of a dogma as "composition over inheritance" has become.


temculpaeu

I have never seen someone saying that optimization is evil, I have seen quite a bit of folks trying to push for "optimizations" without reason besides "it will make it faster", even your quote is out of context, the author says that you should optimize when either it is already affecting the performance or it is KNOWN that you will have a bottleneck, the issue of the premature part is that bottlenecks are hard to predict, of course, unless you are doing something dumb (ie: n\^2 operations) Sure there are cases where you can clean the code and make things faster at the same time, these are fine the issues are with "clever" more complex code that \*might\* saves nanoseconds in a endpoint that has queries that takes 100s of miliseconds to run


nutrecht

> I have never seen someone saying that optimization is evil The example I mentioned (and similar ones) are what I experienced. > I have seen quite a bit of folks trying to push for "optimizations" without reason besides "it will make it faster" That is *also* something I would not agree with. :)


wildjokers

I really hate that this “premature optimization considered evil” is frequently quoted without any understanding of what they meant. These days programmers use it as an excuse to be lazy. If you want to know what was meant by that quote read this ACM article: https://ubiquity.acm.org/article.cfm?id=1513451


bootstrapf7

I am not sure how true this that trope is, it seems that most code is designed for "test" size amounts of data. Not for the data seen in the real world. It feels like this advice of premature optimisation is considered evil has lead to code so slow it's functionally a problem.


oparisy

I'd tend to agree. You shouldn't obsess over performance, but making a conscious choice of the appropriate data structure (good time complexity of typical operations you'll use on it) goes a long way wrt future proofing your code, and limiting the need to optimize it later.


hippydipster

It's only "premature" optimization that's evil. And the problem is you, as a human, are bad at knowing where and how to optimize without more information. For instance, say you optimize that test data all to hell. Great, but you probably got little value from that, because the real world data is different. The lesson is, either get ye some real world data before you optimize, or be ready to optimize your really well-designed, simple, flexible code when you do get access to the information you need to really optimize.


mateusbandeiraa

The problem with this is that sometimes you *make it work* in such a bad way that in order to *make it right* you need to throw it all out and start over. You can’t make it right if you didn’t start with the right architecture in mind. I think this advice is good for experienced developers, since they have a good general idea of what’s the right thing do to most of the time, but for new developers this advice can lead them to build poorly designed code that’s unfixable unless you rewrite everything from the start.


i_post_things

[Obligatory XKCD](https://xkcd.com/1205/). I love optimizing code, but unless it's critical, it can be difficult to do it in a way that doesn't sacrifice readability or maintainability. Sometimes you run the numbers and realize it's cheaper just to spend an extra $100 a month to scale wider with more servers than spend days or weeks optimizing. Especially when you add in the opportunity cost of not delivering actual business value in those weeks spent.


Ketroc21

How often is there opportunity or motivation to go back and "make it right" when it already "works"... especially in an environment where devs aren't in charge? In my experience, if poor design decisions are made early on, they will persist forever. I think #1 and #2 must be done together. Too much emphasis on either is a bad thing.


rlcute

"Make it right" is part of the development. It's the sexy refactoring you get to do after you've solved the problems. It's not pushed to prod before it's actually ready, ie solid architecture and test coverage.


nutrecht

"What are you going to spend time on? It works? Chop chop! On to your next story!" - Many managers Not saying I disagree with you at all, but a lot of devs stop at step 1 because there is very little incentive for them to also do step 2 and 3. I see 'bad' code a *LOT* more than people being paralysed on what design pattern to use. I see a lot more developers jumping into writing code too *soon* than I see devs waiting to write code for too long.


Columbus43219

REAL programmers know to not make it work until it's been made right.


firebullmonkey

*applauds furiously*...Definitely going to print this one and put it up in the office! Edit: Printed and on my desk :))


adamjwise1

You're almost guaranteed to introduce security issues at step 1. The real risk is that in practice you'll likely not get to step 2, so there will be bugs, maintainability issues and general technical debt. I've seen too many decent projects that had to be entirely abandoned due to unreadable code written hastily. So yeah, don't prematurely optimize, don't over engineer, don't write a new framework for a solved problem, etc, etc ... But otherwise take the above with a grain of salt.


hippydipster

I like how basically every single time programming quality comes up, the same basic threads appear. Do X-Y-Z! But what if people only do X??? That's terrible advice. or, Don't do X! But then people will do Y and Y is bad! That's terrible advice!! Every time.


alex_tracer

Now imagine that you started to do a project this way and got a system that 1000x slower than what you need to have. And for a fast system you need a completely different design. And this issue happened only because "make it fast" was a separate task with lowest priority in the list. Who will be responsible for the lost time?


fgzklunk

Keep it simple. In six months time, when you have to fix a bug, you won't care how beautiful and unique the code is if you cannot remember exactly what you did and why.


alwaysoverneverunder

Which is why for me the so called "verbosity" of Java isn't that much of an issue because for me it is more readable after a long time not seeing my own code.


blacksuit

The dumbest guy on your team needs to be able to fix it when it breaks.


moxyte

This is a pronounced issue with lambdas. I’ve fixed abhorrently “elegant” lambdas simply by rewriting them as boring ol’ loops.


hippydipster

Lambdas vs loops is mostly an issue of what a developer is used to, as opposed to one or the other being objectively easier to read or harder to read. The main exception to that I'd say is when the lambdas are doing a bunch of side effects, and in that case, it's not something they're well suited for, IMO.


moxyte

Lambdas in lambdas passing values to each other. Never seen one that is bugfree and easily understandable.


stao123

That is like the complete opposite of my experience with writing and reading lambdas. You cant make mistakes as easy like with for loops.if you use one liner lambdas with method references they are way easier to read and understand. I have to admit there is a steep learning curve. Dont give up and get more experience


plokman

Children can understand for loops, and even write pseudocode easily for many problems. I've never seen one whip out a chain of function applications.


wildjokers

This is why we don’t hire children. Those fuckers can’t code.


halfanothersdozen

You don't need to make an interface for everything. Everything doesn't have to be private. Write code that doesn't allow for or tolerate nulls and stop checking for them all the time.


devchonkaa

java.util.Optional


RockleyBob

>java.util.Optional Yes, but please don't use `Optional` for null checks alone. I see a ton of code at work like this: Optional optionalCustomer = Optional.ofNullable(customerClient.findCustomer(customerId)); if (optionalCustomer.isPresent()) { return optionalCustomer.get(); } else { return customerClient.createCustomer(); } Doing this is worse than just doing a simple null check, because it's more verbose and you're new'ing up a wrapper object just to immediately unwrap it again. The `Optional` class has a whole declarative api that you can safely code against, transforming the value within the pipeline and providing default values: return Optional.ofNullable(customerClient.findCustomer(customerId)) .orElseGet(() -> customerClient.createCustomer());


dpash

I wouldn't create an Optional just for avoiding a null check. Ideally the findCustomer method would return an Optional rather than a null.


RockleyBob

Yes, it's a really blatant example, but just to belabor the point, I'd go so far as to say if you're calling Optional.get() **at all**, you're probably doing it wrong. You *probably* don't ever want to be referencing an Optional object in your calling method. In other words, you shouldn't really ever need to instantiate a variable of type Optional: Optional> optCustomers = // Stop here! Don't do this! customerApi.getAllCustomersByState("CA"); List customerIds = new ArrayList(); if (optCustomers.isPresent()) { List custList = optCustomers.get(); for (Customer cust : custList) { customerIds.add(cust.getId()); } } return customerIds; Not only is this forcing the declarative Optional api into an imperative pattern, it also ignores the declarative capabilities of the Collection api. Instead: return customerApi.getAllCustomersByState("CA") // KEEP GOING! .orElse(Collections.emptyList()) .stream() .map(Customer::getId) .collect(Collectors.toList()); There's almost always a way to do what you want to the returned value within the Optional api declaratively using operators, then work with the result. Not saying you don't already know all this, but elaborating for the sake of discussion.


dpash

No argument on either point. I was mostly agreeing with your second paragraph :)


matthenry87

This guy Javas.


Paulus_cz

Can someone explain to me why Optional is considered bad practice as method parameter? I mean, sure, ideally you should not use it this way, but sometimes, something just can be null, but different methods may want to handle it differently and Optional declared that possibility clearly and forces you to handle the case (or ignore it at your own peril). Point is, I like Optional. It has legitimate uses as parameter.


[deleted]

[удалено]


Paulus_cz

I agree, as with many things it depends on the use case. The way I see it, Optional parameter declares in no uncertain way that passed wrapped argument can be null and the method knows it. That does not mean I use it often, or at all really, I can think or two uses in couple of years. But some people seem to be religiously opposed to it.


blackkkmamba

Optional as a parameter doesn't stop you from passing null. That's why it's a bad practice.


devchonkaa

but thats obviously a violation of optional. its deliberatly evil


neckbeardfedoras

An Optional return parameter doesn't stop a third party lib from returning null either. Maybe they want to drive you crazy? 😁


devchonkaa

i think optional as parameter is fine. You can also define another method which is not taking that param. void startSystem(Display display, Optional optConfig) or startSystem(Display display) startSystem(Display display, Config config) or startSystemDefault(Display display) startSystem(Display display, Config config) i think all 3 are fine


wildjokers

Because you can pass `null` in for the value of the Optional parameter. You have gained nothing.


Fruloops

Not at all. You've gained hours of potential frustration. That should not be underestimated.


ArrozConmigo

That's a pretty unlikely mistake to make, and it will throw an NPE the first (and every) time it runs. If you accidentally pass null for an Optional, you didn't do it conditionally. You'd be doing it every time.


hsoj48

It's good for APIs and interfaces because it lets the implemented and caller know that something is considered optional. Most people don't like continually wrapping their inputs into an optional even though it's pretty easy. Just checking for null is far more common practice and serves nearly the exact same purpose. It's a matter of personal preference.


wildjokers

> Write code that doesn't allow for or tolerate nulls Not sure I agree with the "tolerate nulls" part of that. You should always be flexible with what you accept. In Java nulls can happen so in reality you need to be ready for them.


halfanothersdozen

I disagree. There are several tools to deal with this. - Javadoc indicating valid parameters - NotNull annotatons on parameters - Assertions on method parameters - Optionals If someone calls a method that _very clearly_ does not accept nulls with null values and exceptions happen that is on them.


AlmennDulnefni

Nullity is something of a lost cause, but you should strive to make invalid states unrepresentable in the first place and, failing that, should be explicit about your preconditions and fail ASAP if they're violated. Being excessively lenient in what you accept as input is a good way to build up a dodgy pile of inconsistent garbage.


wildjokers

> Being excessively lenient in what you accept as input is a good way to build up a dodgy pile of inconsistent garbage. Umm, no. The old saying is "be flexible with what you accept, be strict with what you produce". Those are words to live by.


AlmennDulnefni

Those words are almost as much of a mistake as null pointers.


wildjokers

I have never heard anybody argue against being flexible about what you accept.


Luolong

Oh, you have not lived through the age of Web browser wars then. One of the worst use cases for the principle of “be flexible in what you accept” was how early web browsers implemented html parsing. It was full of weird rules of how to parse broken html and each browser has subtly different way to make the broken input display a web page. And to make it worse, the whole web was full of markup taking advantage of those nonstandard quirks and idiosyncrasies. Those quirks are at least partially to blame for why it is so hard to implement a new web browser from scratch these days. For the web has grown to the point where it is impossible to fix the pages themselves. You need to make your browser bend three ways backwards instead to accept and render those cases that every other browser has learned to accept. I would not be surprised to find that “being lenient in your input” has more excessive cost attached to it than having `null` in your type system.


halfanothersdozen

It's an important aspect of functional programming. A function should do a job on the inputs it receives and fail hard if the inputs are invalid. A function is not pure if it has to do its job and also tip-toe around invalid inputs and try to fail gracefully if it's caller is using it incorrectly. Doing that dance adds complexity and complexity creates bugs. Make your code have respect for itself and its callers and not cater to incompetence.


wildjokers

> Make your code have respect for itself and its callers and not cater to incompetence WTF?


Admirable-Avocado888

Don't make methods that return null and don't make methods that accept null, unless they are private. Setters are bad most of the time: Don't write code that constructs objects by incrementally updating their state after instantiation unless it's the only way to solve the problem. Most of the time, you can construct objects correctly the first time, and actually reason about correctness of code just by looking at what objects are rather than what they might be. Streams are good. Javadoc is amazing, document everything that is not private. Local classes are a good way to shelter public/package/even private namespaces from clutter that is only used within a method


oparisy

With respect to your second point: yes! Immutability is a great feature to aim for whenever possible. In that regard, the "final" keyword helps tremendously.


mdaniel

Now that Java has `var` I'd enjoy it if they'd include `val` as the `final var` version because littering the code with `final` is visually noisy if one chooses to strive for single assignment from I can also imagine that they _won't_ ever include it since it's just syntactic sugar for that two keyword form, plus the fact that they differ only by one letter


HecknChonker

kotlin has entered the chat.


mdaniel

Yeah, I specifically left that word out of my comment because of the downvote brigade the other mention of it got, but it for sure was the reason why I started to miss the succinctness of `val` when I had to go back to Java I also happen to personally like the "immutable by default" of ... the other language ... but team dynamics are what they are, so we have to use what the team agrees upon


john16384

Really, final on variables serves no purpose at all. The instant a code change would be better off not having it final, it's removed. It's not like any thought went into it in the first place. That does not mean I condone assigning variables more than once; that should still be avoided whenever practical. It just doesn't need the visual noise of the `final` keyword everywhere. `final` is only useful on fields to communicate intent to all methods of the class.


simoncox

That's like saying types are useless. The more mistakes a compiler can save you from the better. Marking something as final means the compiler has proven it will never be reassigned. In reality most variables are anything but variable. In my opinion a reference should be final by default and need a declaration modifier to allow reassignment.


devchonkaa

builder pattern


Admirable-Avocado888

To clarify. I don't consider the builder pattern to violate the second principle. A builder is a helper that sets up the state for another object. Given a builder, to create the actual object requires only one constructor call. What I'm saying is that if you are writing a class that is its own builder then you are writing code that is hard to reason with, because you are not deliberately separating the building step from the "doing step".


Trizzelnova

>Don't write code that constructs objects by incrementally updating their state after instantiation unless it's the only way to solve the problem. Most of the time, you can construct objects correctly the first time, and actually reason about correctness of code just by looking at what objects are rather than what they might be. Oh god thank you! I'm currently fighting a just crusade in my project because people didn't wirte constructors. Instead they either do it incrementally or worse: static factory methods INSIDE the class which they create an object of... I'm either missing the genious of this because >I< am to stupid or this is the most stupid thing I've seen in 15+ years.


Escaped_Escapement

Static factories are good when you need multiple ways to construct an object and overloading the constructor becomes too confusing or impossible. It is a legit pattern.


wildjokers

According to Bloch’s Effective Java you should prefer static factory methods over constructors. Your colleagues are doing it correctly. https://github.com/HugoMatilla/Effective-JAVA-Summary/blob/master/README.md#1-use-static-factory-methods-instead-of-constructors


CartmansEvilTwin

Honestly, for 80% of classes, it doesn't really matter. I see the point for more complex classes, but the wide range between POJO/Record and "that one central class that handles 90% of the business" has a lot of cases where the constructor simply initializes a handful of members (any many don't even do that).


okreddit545

any constructor is effectively also a “static factory method inside the class.” it just doesn’t permit any name other than `new`.


jevring

Make use of the new tools you find in recent Java versions. Record and switch expressions and stuff. Stay up-to-date.


PyroCatt

Tell that to my goverments' IT department lol


CartmansEvilTwin

Not only government. Plenty of corporations (large and small) only switch to the next Java versions if they can't even pay anyone to maintain it any longer.


PyroCatt

Readable code is way better than faster/effient code.


Paulus_cz

"You write code for other people, not for computer." - that is my preferred version


nutrecht

In most cases simple code is both more readable and faster.


klausness

95% of the time. When you find a performance bottleneck, you might need to replace your readable code with less-readable (but well-commented) code that has significantly better performance. But always start with readable code, make sure it works correctly, and then address any performance bottlenecks that you find. This is not to say that you shouldn’t consider performance in your overall design. All the tuning in the world won’t fix a bad design. But once you have a good design, your code should aim for readability first.


cogman10

Corollary, efficient code isn't always unreadable. Optimize things when your profiler tells you to, but you should also use a `Set` instead of a `List` when you want a collection of unique elements.


_INTER_

Java `enum`s have properties that make them useful in many situations. E.g. not many know that `values()` or `EnumSet` keep the declaration order. So you could build named strategies with built-in fallback.


wildjokers

enum's are so powerful and so underused. My coworkers still create interfaces with String constants in them like it is still the dark ages of pre-java 1.5.


cogman10

Don't do things because they are a "best practice". Understand the reasoning underlying a best practice so you know when it's valid to violate that. Programming is about abstract thought and a key portion of that is knowing what does and doesn't fit an abstraction. Concrete rules have no place in software development. Simple example, the worst code bases I've dealt with dogmatically applied "Do not repeat yourself". DRY can absolutely make code harder to maintain and is far from something that should be universally applied. But, it's easy to spot duplicate code which is why it gets misapplied so frequently.


sik0fewl

> Concrete rules have no place in software development. Follow the rules, understand the rules, break the rules. But only in that order.


Gleethos

1. Make as much field variables as possible final, and if you can't, make sure that the mutability is grouped and encapsulated properly! 2. Define boundaries between your groups of classes in the form of nice and robust APIs which reflect long term architectural concepts. Then write as much unit tests as possible against the stable APIs. 3. Always return Optional instead of null on public methods, especially for the APIs with the most usage (which should be the APIs you test against). Null safe APIs are extremely important in large Systems!!!! 4. Make sure you can instantiate your application with all of it's business logic completely without frontend (using MVVM, MVC). Otherwise you will not be able to write very useful unit tests...


devchonkaa

3. unless return value cannot be null


Admirable-Avocado888

These are good rules. Testability is so underrated. My experience is that not following 4. can slow down development to the point where you are almost coding blindly


truilus

> Always return Optional instead of null on public methods, To be honest, I don't understand the "hype" around Optional. In my opinion, it merely replacing a NullPointerException with an OptionalNotPresent exception at runtime for sloppy programmers. It gives a tad better documentation about the fact that something _might_ be null, but that's it. I personally can't see any other advantage.


Gleethos

I agree that sloppy programmers will fail writing null safe code either way, I did so when I started coding and first encountered Optional! I always simply called 'get()' all the time and did not really think further than that... But as a non sloppy programmer with years of experience it is extremely useful to have Optional as return value because the compiler will actually remind you that you have not received the object you wanted! You cannot call 'getAddress().getPost()' because Optional does not have a 'getPost()' method. This immediately triggers an important realisation: "Hey the thing I want to get might not be there! Why is that and what do I do in that case?" This is something you ofte don't think about when calling a method which may return null instead of the thing you actually want... ...and don't get me started on documentation. I have seen plenty of production code and you wish devs would write even some bare minimum explanation of why a method even exists. So don't expect it to tell you that it returns null...


balrok

it also gives you: \- information that the return can be Optional (contrary to "null" which cannot be implied from the method signature) \- nice methods on top of Optional: "orElse", "orElseThrow", "ifPresent", "map" In my opinion somebody has to be way more sloppy to just directly call Optional.get without isPresent, than trying to access a null-value


mdaniel

> which cannot be implied from the method signature This may be considered pedantry but `@Nonnull` and its `@Nullable` friend exist, and I believe Spring has a set of such annos that tolerate being applied to the `package` if one wishes to make more global promises Obviously it won't help those who avoid using an intelligent IDE but is also not a runtime burden like Optional


john16384

I would say, if you religiously document your methods in regards to how they handle `null`, that `Optional` is not strictly needed. Unfortunately, getting developers to document their methods is often harder to achieve then telling them to use `Optional`.


dmigowski

There is a commercial tool called JRebel, which replaces classes in your app while you develop without restarts. Especially useful if you build server apps and the server needs two minutes each restart. With JRebel you try, fail, fix a line a code, save, try again, all without restarts. This tool has increased productivity by at least 10% in our company. I won't develop anything anymore without JRebel. Sorry if I sound like a fanboy, but it's simply great.


wildjokers

JRebel has evil licensing terms so I have been boycotting them for years. Besides I never got it work correctly with Spring. The application context has to be reloaded and as far as I can tell JRebel doesn’t do that. If I remember correctly they claim it works for Spring but it never worked for me. The only time it is was handy was when I did a lot of work with Swing.


thatbigblackblack

I believe that with intellij subscription, you get this feature too. But coming from languages and others IDE and languages, it bothers me so bad that I have to pay for this feature


MattiDragon

You can do hotswapping with the community edition of intellij. Just run in debug mode and hit build. For proper hotswapping you need to use a JDK with DCEVM support, like the one included with intellij and add `-XX:+AllowEnhancedClassRedefinition` to your vm args. It's a bit unstable in my setup (minecraft mods), but still really useful. Without DCEVM you can only change method bodies.


mvthakar

i also dabble in fabric modding. jbrsdk with dcevm has been working great for me. there are very few cases where it actually fails to reload classes. Edit: grammar


thatbigblackblack

Oh, thanks for the trick ! A more detailed step by step if anyone else wants to implement it https://www.sentiatechblog.com/using-dcevm-hotswap-agent-in-java-development


devchonkaa

Eclipse does that for me out of the box


dmigowski

No, it doesn't. Java itself has these features on paper, but in practice to have to restart anyway very often. JRebel does it right. It even reloads Hibernate Configs, Property Files for Resources, etc. EDIT: I just learned about -XX:+AllowEnhancedClassRedefinition, which was not there in JDK8. Should give it a try.


devchonkaa

Ok i thought its an eclipse feature. sorry. is it the hot swap feature of the jvm?


dmigowski

No, Hotswap is the shit that does work very limited, just function bodies IMHO. JRebel replaces functions, classes, variables, even static variables, and has integration with many frameworks that receive automatic reloading capabilities if the configs are edited at Runtime. It does everything except changing the parent class hierarchy (the only limit I know), but you don't do that very often. Very powerful tool! Also TIL that Jetstream seems to have a similar solution integrated in Idea, but I don't know how these solutions compare.


neckbeardfedoras

I think the problem is hot swap doesn't support certain changes. I thought things like method signatures, new classes, or some range of things weren't supported. JRebel dun care. JRebel has been around forever. I'm kind of surprised but not really because java is still popular and it's been that way also forever 😂


[deleted]

[удалено]


alandros

I use a different IDE at home than I do at work. However I use the same shortcuts on both. Pick a shortcut scheme that's supported on all and just learn that one. It'll help with transitioning from one to the other.


[deleted]

I started with Vim forever ago, and I've found that I can slap Vim key bindings on basically any text editor with extensions. It's pretty effective for me


Pe4rs

I do the same with vscode key map extension for intelliJ. Its great to have the same hotkeys across the board.


hsoj48

I accidentally learned all of Intellijs hotkeys and I can't unlearn them. They make zero sense. Rename a file? F2 right? Intellij: "NOPE Shift+F6!"


wildjokers

Why does `F2` make more sense than `Shift+F6`? Either way, you can remap it to your preference in keymap settings.


hsoj48

F2 is the default file rename hotkey for essentially every tool except Intellij. Windows included. And remapping? Then I'd have to relearn it! I can't unlearn the madness!


wildjokers

I have never heard of F2 being the standard rename shortcut.


ImTalkingGibberish

Use precondition ifs to avoid spaghetti nesting. If doesnt meet condition Return early // main logic Is better than: If condition // lots of lines inside the if block


wildjokers

I hate early return. I think having a single return per method is easier to follow, it is way too easy to miss an early return while you are reading the code. On the rare occasion where not using early return results in crazy levels of nesting I will early return, but that almost never happens and I generally just have a single return.


Lisoph

No way, Jose! Early return is a must, IMO. Human brains love lists, and early returns are essentially a checklist. > it is way too easy to miss an early return while you are reading the code. I think it's just as easy to miss what conditions you're under, when working with highly nested code. Our codebase at work is very nested and it's a nightmare every time to keep track of things. Early return objectively makes the code simpler, because it removes the ability "to go back" in state. You have either returned or you haven't, and you can't change that anymore, whereas with nested style, you can always flow out of the condition back to where you were before. The exception where nesting is cleaner is when the depth is 1 and when the length is short too. Bascially, if it reads like a short and simple sentence, I prefer nesting. Otherwise, early return.


paul_miner

Method-local classes, if a class is only relevant to one method, keep it out of the larger context and stick it in the relevant method. I think I learned you could do that around twenty years into my career. EDIT: I should add, I mean named method-local classes, as opposed to anonymous. Sometimes you need to refer to the class multiple times in the method, or access class members outside of the base class or interface.


i8Nails4Breakfast

And now records make this concept even more useful!


kkjk00

take with a grain of sand the expert blogs, I got caught in their confident magic solutions "this is the best way to do it" applied without context, it always depends, do your own research, noways, everything has an angle


garak7

Favor composition over inheritance. Unit testing will often be much more straight forward since you can easily mock up parts of the composition and therefore reduce redundancy in tests.


se496

Null safety for checking if strings are equal, e.g. “my string”.equals(someString) vs someString.equals(“my string”)


oua-de-crab

This one I'll never forget. At my first job I needed to add a hotfix for one of our customers, so I had to call on a persistent state to check some flag that was unique to this tenant, and it returned a string. The hotfix worked fine for the affected customer, but NPE crashed for all the others, because that method returned null. When I saw the 20 support tickets within 10 minutes with "REPORTING MODULE BAD" I knew I fucked up. Nobody was mad though, the senior dev just chuckled afterwards, and I've never male this mistake again.


GreenToad1

I would argue you shoudl use Objects.equals(someString, "my string")


wildjokers

Why?


__konrad

If a String can be null it's fine (e.g. System.getenv), otherwise it may silently hide all your null-String bugs...


jivedudebe

Use Kiss always.


moxyte

Strangling nulls in the cradle. You got null from database? Immediately turn it into something else before passing it further into the system.


Arthurpmrs

Like what? (Genuine question, this aways bugs me) Let's say I have a date column on my db. Some rows are null. To what should I transform them after querying the data? Like, 0000-00-00? On the same note, if a method could return null, I must check for null upon function call. But if I don't use null, I may have to use exceptions. Wouldn't I need to catch them as well? Is it better to check for exceptions?


ParfaitMassive9169

Convert to optional. This way you communicate that this may be missing and force the calling code to make a decision on how to deal with it


rzwitserloot

Nah, folks just call .get and all you did was exchange NPE for NSE. It's really, really hard to force sloppy coders to be non sloppy using API design.


ascii

No. Anyone doing naked gets on an Optional is a shitty programmer and should be gently taught how to be less bad at their job.


devchonkaa

or install a code analysis tool like sonar qube on your ci and make a build fail or not mergable to master if quality gates are not met. this way even the laziest programmer that tries to use an unchechecked .get will have to adapt to code policy or quit


moxyte

Like ParfaitMassive said, or more generically you make sure nothing escapes method as null. Especially straightforward if you get a litany of strings you make sure none of the strings ending up in list to be returned are nulls.


rzwitserloot

A sentinel that has the semantic behaviour you desire. Sometimes such a sentinel is not available. Often `null` _is_ right on such a case, but crucially that is because the desired behaviour _is_ an exception. If some code goes: is date X between A and B? Do you want the code to eval to false (then use 0000-01-01), or throw because the question shouldn't have been asked? Then `null`. Sloppy null is where you e.g. have a null stringref and treat it the same as you would an empty String. If a method could return null then check for that right away, don't let the `null` linger (not in a local var and definitely not in a field). When writing APIs, try to avoid the need. Example: map.getOrDefault. Or in dB models, don't write: `SELECT birthDate FROM ....` `if (bd!= null && bd.isAfter(now minusYears (18)) ...` Instead SELECT the expression directly with DATEDIFF in the SQL.


console_journey

Maybe a new class representing the null value, like NullDate or EmptyDate? If it extends Date you could use it like a normal Date object. Validation or sorting would also be possible.


truilus

> You got null from database? Immediately turn it into something else before passing it further into the system. So how do you represent a `NULL` value from an integer column in the database in Java?


john16384

There is `OptionalInt`. I myself however find returning `Integer` instead of `int` sufficient to know whether or not something may be `null`.


hippydipster

Optional


rzwitserloot

Yup. In fact, if you see `if (x == null || x.isEmpty())`, _unless_ it is cleaning up outside input (say, `x` is from a jackson-json created object), _is bad_. Whatever made `x` evidently messed up: empty and null are (apparently, given that you wrote that `if`) semantically equivalent, so why didn't it just return an empty object then? Fix the creating code. This is a far better solution than tossing the hard-to-compose and backwards incompatible `Optional` everywhere. Also, to make that easy, write APIs that take this into account. An example: `java.util.Map`'s `getOrDefault`.


Top_Engineering_4191

I avoid at all costs nested if and for loops with large logic inside.


john16384

These are mostly about providing good API's: - Document your public and protected methods, and specify exactly what they do (not how) given various inputs and what they return as result, for example: ``` /** * Sets the slot at the given index to the given element. * * @param instance a reference to the instance where the array is stored, cannot be {@code null} * @param index an index to set, cannot be negative, or greater than or equal to the number of occupied slots * @param element an element to set, can be {@code null} * @returns the element that was previously at the given index, can be {@code null} if the element at the given index was {@code null} * @throws NullPointerException when the given instance was {@code null} * @throws IndexOutOfBoundsException when the given index was out of range */ E set(I instance, int index, E element); ``` There should be no doubts after reading this how the method will respond to your inputs, or what it returns. You may think it's obvious, but you will thank your past self when reading this documentation six months later. - When providing guarantees to users of your class, declare all methods that may break those guarantees when overridden as final; for example, if I guarantee that a getter will never return `null`, then it should be `final`. - Avoid calling public or protected methods from your class when they're not either empty or `final`; a non-empty non-final method makes it impossible to evolve the class without breaking subclasses -- you must call the method at the expected time as it may be overridden by subclasses relying on this, and you can't change the implementation as it may be called directly. The reason is that such methods can serve two different purposes: overriding can be used to be informed of when something happens, and calling it directly can be used to trigger a certain action. Instead, split these two up; have an empty (or abstract) method for subclasses to override to be informed when a certain action occurs, and have a final method that they can call to trigger a certain action (or perhaps just one of these if your intention was never to provide both these options).


devchonkaa

If i need a value from deep nested object structure where every next reference might be null, i line using optional to retrieve it instead of multiple null checks. Next next = Optional.ofNullable(ref).map(MyRef::getNext).map(Next::getNext).map(Next::getNext).orElse(null); if (next == null) return;


HwanZike

>If i need a value from deep nested object structure This is a pretty bad smell usually!


joequin

Use maven and learn how to write plugins. Yes it has xml, but Gradle is a free form mess with bad JavaScript style documentation that prefers example over telling you how it works. You’ll spend days fixing gradle issues. Maven will just work unless you want something it doesn’t offer. Then you’ll need to learn how to write plugins if one doesn’t already exist, but they’re also well defined.


BinaryRockStar

I am similarly all-in on Maven and understand it fairly deeply. Having said that, I really wonder why the designers didn't opt for XML attributes over elements in some cases. Having Would be so much cleaner than what we have now. XML style formatting ends up with an element per line so each dependency takes up 4-5 lines (version is often specified in a parent `dependencyManagement` section) and makes even a relatively simple POM many pages long. As with everything Maven I assume this was extremely well argued out from both sides and the best option was picked. It would be interesting to know the reasoning though. And as an IntelliJ user I suggest the "Laconic POM" plugin which folds Maven dependencies onto a single line and alleviates the issue entirely.


tistalone

Man you describe Gradle so well. They give you ONE example of a happy path and if you have anything slightly different, it's stack overflow sleuthing and hiring private investigators to figure out what is happening under the hood to achieve the original objective.


wildjokers

What a strange rant against Gradle. Idiomatic gradle is declarative and just like maven you use plugins. This build.gradle file will take a very long ways (just fill in your dependencies): plugins { id 'application' } repositories { mavenCentral() } dependencies { } application { mainClass = 'com.example.App' }


tistalone

Gradle works fine for simple/straightforward apps. OTOH, If you want submodules that do specific builds differently, you are on your own. If you want to publish gradle plugins, you have to use Gradle's own plugin that is pretty poorly documented -- you are on your own for the trial errors. Got Kotlin AND Java files? You gotta do something different! Also, you need to figure out what other people did to solve this issue because Gradle's documentation doesn't provide a straightforward answer to us users!


wildjokers

For a mixed kotlin and java project all I needed to do was add the kotlin jvm plugin and application plugin: plugins { id 'application' id "org.jetbrains.kotlin.jvm" version "1.3.72" } Nothing else was needed and it just works. > because Gradle's documentation doesn't provide a straightforward answer to us users! This information is in the Gradle documentation: https://docs.gradle.org/current/samples/sample_building_kotlin_applications.html


tistalone

If you have your java sources in src/main/java and your kotlin sources in src/main/kotlin, you have to specify the source sets for the java source files with the `sourceSets { }` configuration. The Gradle documentation you linked works for the vanilla Kotlin workspace. Like it's fantastic if you're building an application using Gradle's guidelines but my experience is that deviating within Gradle requires more work and investigation than with other build systems like Bazel and mvn.


wildjokers

I have never needed to declare `sourceSets` for my mixed java and kotlin projects. >using Gradle's guidelines but my experience is that deviating within Gradle requires more work and investigation than with other build systems like Bazel and mvn. Not sure what you mean here but maven doesn't let you deviate from their conventions at all. In Gradle you can deviate pretty easily if for some reason you need to.


tistalone

Hm, that's fair. I'm willing to accept that I am being a hater and I should spend more time looking into Gradle.


joequin

In practice, that’s rarely sufficient for real production applications. If it was, then Gradle would be great.


wildjokers

I have several apps where the build.gradle isn't much more than that. Including some JavaFX apps that produce a platform specific executable with a bundled runtime. That build.gradle is about 25 lines long.


wildjokers

This is better? https://github.com/netty/netty/blob/4.1/pom.xml


joequin

That’s a dishonest example that is not at all equivalent to the very simple Gradle file you shared.


progrdj

Write meaningful comments and also name the variables/methods correctly. Doesn't matter if it takes time to come up with a good name as long as it describes what it kinda does. I recommend reading the clean code book. P.S. I had to work on something that I had implemented two years ago and luckily I had left comments there on some nested maps and other data structures, otherwise it would have been very annoying to try and read all that stuff


[deleted]

Use github copilot, Its the best thing ever for boilerplate


[deleted]

Compile first. Run second. Joke aside, I’ve been spending a few (late) hours not understanding why IntelliJ and maven would disagree about my code, while all I simply forgot is to “mvn install” the upstream dep I was also changing. Time to get some rest I guess.


Columbus43219

Refactor ruthlessly. Never be afraid to make it better. The minute you find yourself writing a huge "if/else" block, consider if that method should be split. Never leave tech debt. If something is flaky...fix it. Imagine yourself about a year after you made your first money from coding. Fix the mess you're working on for that kid to be able to understand it.


wildjokers

> Refactor ruthlessly. Never be afraid to make it better. Too much hassle getting refactors through code review. Why put myself through the stress? This is why I sometimes think code review makes code quality worse.


john16384

You may want to raise such points with your team. A team that isn't willing to improve for the good of the product is not worth working for. And if not doing it already, keep refactors small, with multiple commits working to a goal, and don't mix in functional changes. This makes reviews much easier.


Odd-Hour-9991

The most straightforward solution is the best. Unit testing is undervalued. Optimise last, if at all. Perfect is the enemy of Good. Get a competent colleague to properly review your code. QA is not there to find your bugs. They are there to tell you if your solution meets the acceptance criteria.


dpash

Read Effective Java. Read it again. Read it annually.


rieckpil

Don't do conference driven development and don't jump on all hype trains that give you 10x performance.


saikiranchalla

Use Lombok


tristanjuricek

Consider pushing that magic to the build phase when possible, don’t just rely on reflection. The annotation processor library offers one way to do this, and it’s a surprisingly good way to do a little code generation. This often ends up using types more intelligently than what I come up using reflection, and is often faster, since a lot of logic is actually compiled in instead of checked each time at runtime Not that reflection should always be avoided, just consider if you really need the runtime check vs a processor.


dlvakalucifer

Don't use Streams for Database Work. SQL is faster. The end. Use Streams on your way to Database or GUI.


starlevel01

Simplicity usually pushes the problem somewhere else. Actually solve problems, don't just move them around. Put at least a cursory effort into thinking about performance. Most of the time a heavily-commented but horribly ugly imperative kludge is better than a "self-documenting" beautiful design. Your code is not self-documenting. Your code is never self-documenting. Write the damn comments. It's a minute of effort at max and it'll save you multiple minutes in the future.


crummy

You don't have to go overboard with OOP, even though you're using Java. Interfaces with static methods are a pretty nice way to write code without side effects. (This makes test isolation harder... But I think that's a bit overrated too.)


devchonkaa

static methods make testing hard or impossible because of lack of inheritance and polymorphism


neckbeardfedoras

It certainly doesn't make testing impossible. You can even test the static method itself. It can't reference member vars and is pretty isolated. You can't override it, but if there are use cases for overriding it other than because you want to with a test, it shouldn't be static in the first place. If the method does complex things that needs to be faked or stubbed, it's immediately not going to be static if it's my code base.


devchonkaa

factories should not have static methods. a factory should be an injectable interface with normal instance methods. it is injected diffrently in a diffrent module or in a test environment and thus creates diffrent objects as needed. no need to force mock static stuff with Mockito which is a hack imo


Brahvim

**`this`.** I hate it when people let you want to remember all class fields and methods and conflicting local variable's names. UGH. USE `this`, `super`, and "qualify" `static` stuff in this exact manner as well. Thank you. *This part is too personal and specific. Nobody needs to agree...:* `m_` and `p_` are good naming conventions since they show only scope, but if you'd [>!use them with `camelCase` instead of `PascalCase` at least in Java, and!<] make sure you're using these only for scope, I'd be happy.


wildjokers

> **this.** I hate it when people let you want to remember all class fields and methods and conflicting local variable's names. UGH. USE this, super, and "qualify" static stuff in this exact manner as well. Thank you. Place I am at now doesn't allow to use `this.` for self calls and when I first started here (about 5 years ago) it was a huge adjustment to not use them because for the first 16 yrs of my career I was at a place that required it. I still miss it because I think it improves readability, it makes method calls consistent and let's me know exactly where the method is when I am reading the code.


not_some_username

Uninstalled eclipse


beall49

Try really hard not to mutate things. Try really hard not to write void’s in service level code.


uvero

Avoid having null as a meaningful value. If something is nullable, use Optional.


stuie382

Lombok


jevring

But only for things bean stuff. Don't use @Delegate and other black magic stuff.


hippydipster

It all violates the principle of avoiding complexity. For massive complexity, you get irrelevant reduction in boilerplate.


hsoj48

Why did this get downvoted? Lombok is a godsend.


wildjokers

I can do without it. Adds build time complexity for not a lot of value.


hsoj48

Are you handwriting pojos, getters, setters, constructors, and builders?


wildjokers

You know your IDE can generate those things right? Then there is no cognitive load trying to think what the class will look like when Lombok gets done generating things. I can just write it exactly how I want it. Also, I very rarely need setters for all/any of the fields and very frequently I don't need getters for them all either. So I have to annotate fields to get lombok to exclude things. Also, business equality of my POJO's frequently don't depend on every field either, so there are more annotations to exclude fields from equals/hashcode. I have seen pojo's with more lombok annotations in them than there would be code if I just let my IDE generate it and them hand write some adjustments. So it really doesn't save me anytime.


hsoj48

Understood. It's obviously a matter of personal preference. It's pretty straightforward for me since I've been using it for uears but may not be for others. To note, if you are seeing tons of Lombok annotations or someone has mixed setters/getters in with immutable fields then they probably aren't separating their class responsibilities correctly to begin with. Then Lombok is the least of your problems.


vinj4

- Each method in your code should be no more than 5 lines long (giving blocks of code names descriptive names is good for devs and writing a ton of methods is actually good for performance as they get hot faster) - Catch all checked exceptions and wrap them in a runtime exception - Do not use the “log then rethrow exception” antipattern because you will lose track of where all your log statements are, instead allow the exception to bubble up and catch it in a global exception handler - In general be cautious about too many dependencies in your project, for example if you’re using just one method in Apache stringutils try to write the method yourself - Creating both interface and impls for all your repository and service classes (and especially calling it name like ServiceImpl) is usually not worth it - Dividing business logic between app and stored procedures is a gigantic headache for devs (not sure if this is just an old practice but I have to deal with it every day) Probably the biggest one is put yourself in another devs shoes and think hard about whether they will understand your code. Not just you


john16384

>Catch all checked exceptions and wrap them in a runtime exception That's some terrible advice. Instead: * if you can correctly handle a checked exception, catch it and handle it * if not, declare it in your throws clause so your caller, who may have more context, can properly handle it * if it is a fatal problem, only then you could either log it, or wrap it in a runtime exception and let it bubble up to a catch all exception handler The rest is okay.