Friday, November 18, 2022

Daughter - killer of trees (and tires too)

 So my daughter was known as "killer of trees" when she ran into a recently planted peach tree with her dirtbike and knocked it flat over.  Now she is also "killer of tires" after a blowout on I4 between Lakeland and Plant city.  



We were blessed that it wasn't raining and we were not up north in the snow.  The worrisome aspect was that she was on I4 (which is notoriously busy) around 7pm (dark at that point) and in a section with concrete barriers and very little room.  We were very impressed she got the car over safely and didn't bump the barrier.  She was only a few inches from the barrier on the right side though.  Before my dad and I got there to help her - I asked her to get out the right-hand side and see if the tire could be patched, etc - it took her a few minutes to get out but she came back with a "I don't think so Dad.." which is pretty self-evident now. I had thrown in a small "pancake" air compressor which I had pre-filled just in case.  Didn't need to bother. 

She only had few feet on the drivers side front (which is where the tire blew).  My dad parked behind and hugged the side of the road a bit to "convince" drivers to stay to the left a bit.  That helped a bunch.  I had not had the spare tire and jack out of this car before - was wishing I had brought a speed jack.  I just slowly worked the jack up - taking a bit of a rest here and there for my knees and to enjoy the very cool breeze from the tractor trailers speeding by a few feet away.

As I was sitting there getting the car jacked up, I started to wonder how she got out of the car from the passenger side - it seemed like there was no room.  All I could visualize was her climbing out the window onto the concrete barrier (with a drop-off on the other side) - sort of "The Dukes of Hazzard" style. She told me later she had just enough room to squeeze the door open and get out - only because she was at slight angle was that possible.  

It is kind of funny the way some obvious things escape a person at certain moments. When I was getting the jack, etc out of the back of the car, I found a short bright rod/stake which I thought was in with the jack, etc.  It was just cheap plastic and my mind just jumped to guess it was one of the "emergency items" which you could use to either wave cars around you or put out behind a car to make it more "visible".  I wasn't impressed by the cheap plastic though.  The next day though - I went back out and found it again..  As I looked at it in the daylight I was thinking "something is odd"..


I rotated it a bit and when I saw our last name "Case" written on it, I suddenly knew what was odd.  It wasn't an emergency item - it was out of an old kids horse shoe game and this stake simply ended up in with the spare tire, etc.   I got to laughing with my mom and I told her about it and said I was glad I didn't have my daughter out behind the car waving it at traffic.  We got a big laugh out of that thought.



Trying to find replacement tires now - it is an odd size of course.  Seems like only one or maybe two (less common) brands even make tires in the required size.  I had planned on putting run flat tires on as replacements but there are none in that size.  It is hard enough to find someone with a set of those tires from the 2 tire types.  


1 Thessalonians 5:18
King James Version

18 
In every thing give thanks: for this is the will of God in Christ Jesus concerning you.


Sunday, November 13, 2022

Reasons for poor quality Software Systems

I've seen issues with software system quality over the years - it wasn't just one type of organization or domain. Why is this true even with continued innovation and best practices? I would expect to see improvements over time.  There are plenty of tools to help improve software quality.

Great IDE's

  • IntelliJ
  • Eclipse
  • Visual Studio

Language and compiler improvements

  • Java 11-19

Source scanning tools

  • PMD
  • SonarQube
  • FindBugs
  • CheckStyle
  • SpotBugs
  • VeraCode & Twistlock
    • more related to security but IMO there is a relationship between security and quality

Code generation tools

  • Lombok

Additionally, features like Java annotations are leveraged heavily nowadays which simplify configuration and lower overall code quantity/complexity.

I've found two common aspects across a number of organizations which I think are related to the quality issues.  The first aspect is lack of attention to the warnings listed in common IDE's.  I've seen some applications showing over a thousand warnings when I first worked with them.  This crosses implementation languages/run-times as well - Java, Python, JavaScript, NodeJS, etc. Of course, often IDE's only show the first 100 or so warnings so you don't even have a complete list typically.  

The second aspect is the use of technology, such as general annotations and also Lombok, without paying attention to all the details regarding how each related annotation works (for default and non-default settings).   Default behavior isn't always the required behavior. An example of this is:

create a class such as:

@Data

@AllArgsConstructor

@NoArgsConstructor

public class BaseData

{

/**

* Represent identity; lombok generated equals() should

* utilize this to determine result.

*/

@NonNull

private String baseDataId;

}

 

which is fine on its own.  Note that the name-prefix "Base" easily implies that you may create sub-classes though. Let's do that here;


@Data

@RequiredArgsConstructor

public class DerivedData extends BaseData

{

/**

* Represent identity; lombok generated equals() should

* utilize this to determine result.

*/

@NonNull

private String derivedDataId; 

}

No compile error is generated.  Will this work?  It depends - how are you expecting to use this class?  If you expect that the equals() method will account for both the baseDataId and derivedDataId then you will have an unhappy surprise. 

If you pay attention to warnings in your IDE though you will note a warning is generated. 

Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.

I've not seen PMD, Sonar, etc complain about this so those tools leave you feeling like "everything is awesome".  

Add some unit tests which exercise the equals() method in the situation where you are using the DerivedData class and have instances with matching derivedDataId values but different values for baseDataId.  You'll probably write the test indicating the instances should be non-equal.  Will you be surprised when the tests you setup indicating instances should be non-equal actually fail?

The reason it fails is that the generated equals() in the DerivedData class doesn't know anything about the members of the BaseData class.  So equals() in the derived class only uses the derivedDataId member. 

If you review the warnings in your IDE, you will find that it implies how to resolve this if it wasn't intentional - add annotation '@EqualsAndHashCode(callSuper=true)'.  But notice I said "it implies" because it directly tells you how to ignore the warning about this default behavior.  So a good question is - how often is the default behavior correct versus the logic always calling superclass equal() / hashCode()?  I suspect that the current default is opposite from what would be a safer default.

And this brings us back to IDE warnings being ignored.  If you ignore / hide those warnings you easily end up missing these types of errors which can show up as "anomalous production issues" at some point.

I think that an aspect of all this is the attempt to (over)simplify everything. So many details are abstracted away that developers won't see implications of all the "defaults" and "configuration by exception", etc that occurs is so many systems.

Thanks for reading..

Scott


Wednesday, November 9, 2022

Application Architecture and Design (and cloud aspects)

 Let's say you work for some organization and there is a need for a new application.  If you are responsible for the architecture / design then 

My initial post was going to end up being a "ancient" IT history book with some extra stuff. I decided that wasn't very helpful - not many people want to read a book in a "blog format".

I'm condensing the content down to the following. 

  • Use standard practices for
    • project management
    • design techniques
  • Understand the reasons/basis for soft/hard requirements - This covers why a requirement exist and why a specific requirement was chosen over other similar prospective requirements.
    • Examples reasons are;
      • development / operational / infrastructure costs
      • time to market /  speed of handling requirement changes
      • maintainability
      • performance / scalability / availability
  • Carefully evaluate technology choices.
    • Consider the risk of using any technology that could become unsupported before the end of the useful life of your application. New "amazing" technologies may only be around for a short period of time before something new replaces it.
  • Make plans to keep 3rd party frameworks, libraries and languages/run-times up-to-date with regard to the most current versions.
    • Consider the risk, for example, of using early versions of SpringBoot such as 2.1 which are not maintained now - if a new security flaw comes up, it may be very hard to fix the issue.

With regard to standard practices, use whatever is appropriate for your organization and the project need. Many organizations are trying follow "Agile" practices but that doesn't mean that "Waterfall" is always bad to use. Use what is appropriate for the situation.

Understanding the reasons used for requirement selection helps to keep requirements aligned with each other and provides useful context for handling business changes over time.

Technology comes and goes.  Don't love or hate particular technology - it is a tool.  Use appropriate technology and if needs change then consider more appropriate technology.  Don't select technology just because it is considered "great" by any person or group - consider the positive and negative aspects in-depth for your use-case.  

Small example of considerations - given a service expecting high transaction rates; what technology stacks might be considered and what are the trade-offs?

  1. Python
    1. Positives
      1. Increasingly used in enterprises
      2. OpenSource
    2. Negatives
      1. Library ecosystem isn't as mature as for Java
        1. You want a library to help with web requests?  Which option do you pick? What version of Python are you on?
          1. https://pypi.org/search/?q=web+requests&page=1
    3. Considerations
      1. Security
        1. https://www.theregister.com/2021/07/28/python_pypi_security/
        2. https://medium.com/ochrona/arbitrary-code-execution-during-python-package-installation-3a60990350ef
        3. https://snyk.io/blog/python-security-best-practices-cheat-sheet/
      2. Some libraries need local compilation
      3. Cross-version compatibility
      4. Transitive dependency handling
      5. Long term maintenance questions
        1. https://medium.com/codex/python-4-0-will-never-arrive-3d994dce54f1
      6. Runtime aspects
        1. Python global lock
          1. https://wiki.python.org/moin/GlobalInterpreterLock
        2. Memory management - also consider context including containers
          1. https://www.askpython.com/python/examples/memory-management-in-python
        3. Threading
          1. https://docs.python.org/3/library/threading.html
  2. Java
    1. Positives
      1. Heavily used in enterprises
      2. Generally has useful features and reasonably performance
      3. Many enterprise level libraries and frameworks
    2. Negatives
      1. New version every 6 months by Oracle can cause some thrashing of work
      2. OpenSource vs Oracle licensing
    3. Considerations
      1. Alternative JDK / JVM / run-times
        1. Oracle JRE
        2. OpenJDK
        3. Azul
        4. IBM OpenJ9
        5. Eclipse Temurin
        6. Amazon Corretto
      2. SpringBoot vs JEE
      3. Cross-version compatibility
      4. Transitive dependency handling
I highly recommend reading about and understanding the runtime aspects of Python. Consider the effects of memory pressure within and across container instances (i.e. Docker, Kubernetes, etc) - especially in a cloud environment and / or where you are cost / latency sensitive. 

Regarding compatibility and transitive dependency handling - I've had people with architect and team lead titles make comments to me along the lines of:
  • "Java versions are backward compatible so keeping up with current versions isn't important."
  • "We are pinning the SpringBoot version at version 2.3 instead of upgrading to 2.7+ because it improves stability by preventing changes."
I believe these statements reflect some general misunderstandings or lack of knowledge. There are very instances of 100% cross-version compatibility for operating systems or programming languages over significant spans of time. You also have to clarify whether you are talking about things like source code / binary compatibility and forward / backward version compatibility. Try running a bunch of games written for Windows 95 on Windows 11 - how many will work?  In my opinion - likely few.  For operating systems, computer languages and frameworks - features are added and deprecated / removed across releases.  API's change due to needs such as performance, security, new features, etc. If OpenSource is brought up as a solution to these type of issues - I'll claim it isn't reasonable.  There are support matrices for most major OSs, computer languages and library / frameworks - they don't maintain old versions forever. If you are outside a support matrix - you have no guarantee that anything will work and getting help will likely be somewhere between hard and impossible. Needing help for a major security issue or something that breaks a critical system is not the time you want to find out that no one can help you or can't help you quickly. Some common support / compatibility matrices below..

  • OpenJDK support matrix from RedHat
    • https://access.redhat.com/articles/1299013
  • SpringBoot support matrix
    • https://spring.io/projects/spring-boot#support
  • SpringBoot / SpringCloud compatibility matrix
    • https://spring.io/projects/spring-cloud#overview
  • Django support matrix / roadmap
    • https://www.djangoproject.com/download/
  • Nx / NodeJS / TypeScript compatibility matrix
    • https://nx.dev/packages/workspace/documents/nx-nodejs-typescript-version-matrix

Thanks,

Scott