Novice programmers, people in a rush for a deadline or someone with simply a disturbing lack of interest, will create 'surprising' code. Not just bad code, but bad code disguised as proper quality software. There are, unfortunately, many ways to achieve such code.
Here is a few ways I have encountered that seem to keep popping up every now and then:
So what can we (programmers) do? Kent Beck has some advice for you, he actually has been advertising this advice for 20 years now. A nice, up to date summary can be found here: https://martinfowler.com/bliki/BeckDesignRules.html
He basically says there are 4 main principles to check:
Let's apply the principles to the ways listed above and see what went wrong.
1. seemingly meaningful but ultimately useless indirection
Indirection can be useful but it introduces 'elements', so it probably isn't the simplest solution. Indirection also hides or even distorts any clear intention.
Use indirection only if you really need the abstraction.
There are many cases where abstraction is useful, but usually: KISS (fewest elements).
2. reuse code but don't apply any abstractions
Let's say that some application has code for handling livestock, money and buildings. These different parts in the code might all do 'relocations': transferring money, moving resources to another building, and moving livestock to another owner. The code could be similar. A programmer in a rush could just reuse the unit that 'relocates' for buildings and apply it to money and livestock.
With this action of applying DRY, at best, all intention of the code is lost. It probably causes many other problematic effects.
The proper action would be to introduce some kind of abstraction that fits the mentioned purposes, or better, choose a better level for the abstraction and just leave some duplication in place, reveal the intention.
3. generify beyond any recognition
The problem is in the intention, and to lesser extent the fewer items. When applying DRY, a common pitfall is to go to far. Yes, a train can be expressed as a collection of movable transport item holders for resource relocation, but the downside is that no human being is able to understand the code anymore.
Making code very specific to the use case, even when reducing the ability to reuse it, is often the preferred choice (reveals intention).
4. use tech tricks for no reason
Programmers love using the latest technology. This includes 'clever' tricks. Just because a language offers advanced features, they are not suitable to every problem. In java for example, inner classes can access fields of the outer/parent class. But if the only reason to do so is to avoid passing variables, then intention is lost. The simpler solution is just a regular class with a constructor taking the variables needed. This results in a clear lifecycle for the object instantiation, avoids any risk of loading cycles, and is just many times easier to read especially by novices (both fewest elements and reveals intention).
5. translate yes, but always choose false friends
When modeling in code, using english has many benefits. Translation can be hard though, especially since naming is actually already one of the 'hard things' to start with. It gets painful when a word is chosen that actually looks like the word translated but means the exact opposite! An example would be: rare (unique, valuable) vs. 'raar' in dutch meaning just strange or weird. Make sure you properly reveal intention.
6. have detailed javadoc about the precise implementation (that has long left the building)
Old documentation is an excellent time waster. The reader can spend hours trying to understand how the code relates to the description, while it actually doesn't. Having implementation details in documentation is not DRY. Documentation is the perfect place to describe intention, let the reader know what he cannot know from the code alone. No duplication and reveal intention.
7. verify that things work -not-
Don't think about meaningful scenarios and having correct results, just verify that the code does 'whatever' it does. Instead, of course you should actually care about what it does, and more importantly: about why a test exist? This is the intention of the test that should ultimately reveal the intention of the code even more. Having tests is only really useful if they verify that the software delivers valuable output, otherwise software is only a liability. So 'passes the tests' is also a problem here.
8. use design pattern naming but never actually apply it
Fancy naming, without any comprehension about the concepts are hiding all intention. It's easy not to do the hard work of naming things properly after what they are, but instead just apply some pattern that sounds familiar. There are not many contexts in which a factory is something valid to have in your model, unless perhaps when dealing with nation wide greenhouse gas emissions for example. The context actually determines what kind of naming is suitable to properly reveal intention.
9. open up your data to endless possibilities
Data has no intrinsic intention. It needs protection against misuse. Immutability can greatly reduce the amount of ways to (mis)use code. Assertions; checks on illegal state are very practical. This is a best practice often called the 'fail early' principle. Having fewest elements helps.
Voordat je gaat geloven dat bitcoins echt geld kan zijn, het volgende.
- schaarste wordt gesimuleerd via energieverbruik: nu al meer dan een land als ierland
- enkele grondleggers hebben erg veel macht door het meeste-stemmen-geldt principe
- de transactieverwerking is veilig, maar mensen zijn niet goed in wachtwoorden en sleutels. Er is geen goede manier om normale gebruikers te beschermen tegen verlies van eigendommen
- beveiliging is gebaseerd op encryptie die per definitie op den duur onvoldoende zal zijn (al dan niet door quantum computers), er is geen mechanisme om het netwerk te voorzien van nieuwe standaarden zonder paniek/dumpen
- ook voor problemen rondom de snelheid van verwerken van transacties is geen duidelijke oplossing die het bestaande netwerk in stand houdt.
Wellicht zijn voor bepaalde problemen technische oplossingen mogelijk, maar of die doorgevoerd kunnen worden zonder dat de boel instort is maar zeer de vraag.
Misschien kunnen problemen rondom encryptie en snelheid via een veilig upgrade protocol opgelost worden?
Misschien kan het systeem van energieverbruik voor schaarste ingezet worden voor goede doelen? Algemene computer processing die dan netto geen exra verbruik kost?
Wellicht is het probleem van grote bitcoin bezitters geen probleem bij een nieuwe munt met (heel) veel initiele deelnemers?
Bij elk van deze mogelijke oplossingen kom je uit op een nieuwe electronische munt, en dus niet bitcoin.
Checkout a full working setup of running tests on a Jenkins Shared Library using grails (which can be run using...... jenkins! yay)
Firefox is back. It is truly a relief to see that Mozilla with Firefox Quantum has managed to get the browser up to speed again.
It always used to be my favorite browser (open source is the only way), and now it will stay that way for even longer.
To get Firefox quantum you will, for now, need to download it as a beta release. This means there should be flaws, but it's actually so much better than other browsers that you will probably not notice the imperfections!
A practical example about the strangulation pattern, as explained by Martin Fowler, applied to pipelines.
Read more here:
Eclipse, starting with GGTS from SpringSource used to be the best editor for working with grails projects. During the switch to Grails3 though things have changed. The GGTS Eclipse plugin is no longer being maintained.
All this was not such a problem the first months or year even. After that Eclipse, Java, Groovy and Grails kept upgrading, but the plugin did not. This lead to more and more tiny problems and failing features. The last few months the experience of using Eclipse degraded so much that effectively using it became virtually impossible.
This has lead me to use IntelliJ (Ultimate), and getting a license for it. The experience is great. I can work on grails like I used to including auto suggest, refactoring, etc.
The downside, which kept me a long while from switching, is that IntelliJ is proprietary and this does not do much good for the open source community.
For Grails3 projects, using Eclipse is fine since most of the features will be offered by either the Groovy Eclipse plugin and the Gradle Eclipse plugin, both of which are supported really well.
For Grails2 projects, Eclipse is no longer.
Eclipse Oxygen M1 (june) and Grails IDE now work together!
Below are the update site urls required to get the Grails-IDE archive (old!) working in the latest of eclipse IDE versions:
<?xml version="1.0" encoding="UTF-8"?>
<site url="http://download.eclipse.org/tools/ajdt/46/dev/update" selected="true" name="AJDT"/>
<site url="http://download.eclipse.org/technology/epp/packages/oxygen" selected="true" name="Eclipse EPP 4.7 (Oxygen)"/>
<site url="jar:file:/opt/bwijsmuller/springsource-tool-suite-3.6.4.RELEASE-e4.5-updatesite.zip!/" selected="true" name="GGTS"/>
<site url="http://dist.springsource.org/snapshot/GRECLIPSE/e4.7/" selected="true" name="GrEclipse"/>
<site url="http://download.eclipse.org/oomph/updates/milestone/latest" selected="true" name="Oomph Latest Milestone"/>
<site url="http://download.eclipse.org/releases/oxygen" selected="true" name="Oxygen"/>
<site url="http://download.eclipse.org/eclipse/updates/4.7" selected="true" name="The Eclipse Project Updates"/>
Debugging applications in eclipse is easy if you're able to run them as java application main class.
Grails3 can be started by using the Application.groovy main class, thanks to spring-boot.
I tried this, but it failed. I added the 'build' scoped libraries by adding the 'dist' folder from the grails installation to the run job classpath. It still failed (in my case) because the application.groovy was not being loaded.
The application.groovy is optional, the default application.yml was loading just fine.
The fix was to add the grails-app/conf folder also to the classpath. This makes the source file available to the running process instead of the compiled class. Spring-boot loads it and everything works ok!
There's nothing so annoying as having written some pretty cool code, but then somewhere in the surrounding code suddenly a nullpointer exception appears.
Nullpointers are evil, I think that's pretty clear, but you as a developer can actually reduce the amount of possible nullpointers!
From the experience in projects I've worked on, it helps to:
1. Use final (immutable) fields on your class where possible. For hibernate entities this is often not possible or very inconvenient, but in other classes this prevents accidentally setting the field to null.
2. Apply the 'fail early' principle. Don't let the troubles of inner components affect the outer ones. If bad things happen that cannot be resolved, such as invalid input on one of the public methods at the component, it usually means throwing a runtime exception. Don't just return null and make others do the dirty work.
3. Always describe the null case for non primitive return types on methods, in javadoc. If a method needs to return null, it is probably meaningful and worth to explain. If it never does, just say so. Clients of the component can then safely assume that the return value is nullpointer safe.
Every now and then the Grails (2) framework surprises me. Sometimes in a good way, and sometimes in the worst possible way.
It turns out that when the path your Grails project is in contains a percentage sign, the build does not work correctly. I've seen two effects (depending on various settings):
The really annoying part in this is that there is no error message, no build failure, no warnings. Just silence, and unit tests are not being run. Sigh.
The Grails build system (not Gradle) does not handle paths very well. Always make sure that the path to your project is 'simple'. This means no funny characters and staying clear of common grails artifact names (and possibly even 'conceptual' names).