Avoiding if else statements and switch statements

Consider I have a cron expression as “* * */2 * ” I have to extract the recurrence on days ,hours and minutes if it is not “” . I have the below function which works as well.

public void CronDivision(string cron) { string days, value;  string[] cronDiv = cron.split(' ');  if(cronDiv[2] != "*")  {   days = "Days"   value = cronDiv[2].split('/')[1];  }  else if(cron[1] != "*)  {   //Similar logic  }  else if(cron[0] != "*)  {   //Similar logic  }  else if(cron[3] != "*)  {   //different logic for extracting weeks  } else if(cron[3] != "*)  {   //different logic for extracting years  } } 

How do I generalize the above function so that I dont want to use if else/switch statements with hardcoded numbers like1,2,3 and so on after the division of cron expression.

Can it be made more readable without the obvious solution of splitting the actual cron expression and extracting it. Basically I need a cleaner approach for this problem without usage of numbers like 1,2,3 etc?

Spring Entities, avoiding code duplication

I’ve recently stumbled upon a design problem with which I am not sure what is the best course of action.

Using Spring Data JPA to create Entity classes say I have:

INameEntity.java -- Interface CityNamesEntity.java HumanNamesEntity.java AnimalNamesEntity.java 

They all end up having identical logic, just functions addName(String name) and getName() If not for the usage of Entities I’d just write a simple class that would access the table I need and process these requests.

My question is. What is the best course of action?

  1. Leaving it as it is.
  2. Ditch Entities and implement a solution that only switches table depending on which one is being called.
  3. Database design is wrong/Choice of SQL database system is wrong in this scenario.

Or maybe there’s design pattern that still allows me to use Entities that will solve this problem in an elegant fashion.

Avoiding an authorization request for Google Scripts

I’m in the midst of trying to custom code some script that will automatically hide some sheets from some users in a shared company spreadsheet. Yesterday it seemed to be working fine, but now it seems to not be working for anyone unless they authorize the script first. This is problematic for a variety of reasons. The code is as shows:

var adminUsers = ['exampleadmin1@gmail.com','exampleadmin2@gmail.com']; var Users = ['exampleuser1@yahoo.ca','exampleuser2@gmail.com'];  function onOpen() {  SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sales Metrics').hideSheet() SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Quarterly Metrics').hideSheet() SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Monthly Metrics').hideSheet()  if (adminUsers.indexOf(Session.getEffectiveUser().getEmail()) >= 0) { SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sales Metrics').showSheet() SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Quarterly Metrics').showSheet() SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Monthly Metrics').showSheet() }     var ui = SpreadsheetApp.getUi(); ui.createMenu('Privacy')   .addItem('Say Hello', 'helloWorld')   .addItem('Privacy Lock', 'privacy')   .addItem('Privacy Unlock', 'unprivacy')   .addToUi(); }  function helloWorld() { Browser.msgBox("Hello World!"); } function privacy() {  SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sales Metrics').hideSheet() SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Quarterly Metrics').hideSheet() SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Monthly Metrics').hideSheet()  if (adminUsers.indexOf(Session.getEffectiveUser().getEmail()) >= 0) { SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sales Metrics').showSheet() SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Quarterly Metrics').showSheet() SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Monthly Metrics').showSheet() }  } function unprivacy() {  if (Users.indexOf(Session.getEffectiveUser().getEmail()) >= 0) { SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sales Metrics').showSheet() SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Quarterly Metrics').showSheet() SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Monthly Metrics').showSheet()     } } 

The trigger fires on spreadsheet open, I know this because the ‘Privacy’ button appears in the menu of people who open it. But for some reason the code that hides the specific sheets isn’t running automatically.

I don’t know if there is a way to install a trigger onto the spreadsheet itself, or if there is some piece of code I’m using that is making it harder, but anyone that can help me understand this, or even some other way that this code could be improved, it would be greatly appreciated!

Avoiding the use of ordinal() in an already-deployed enum

While reviewing a PR, I found an enum being used like this:

class Entity {     public enum STATUS { NEW, SENT, FAILED, OK }      @Column(name = "STATUS") // a NUMBER(1) column in DB     private int status; // + get/set     //... }  // Inside methods... Entity e = new Entity(); e.setStatus(STATUS.SENT.ordinal()); EntityDAO.save(e);  Entity e = EntityDAO.findByStatus(STATUS.FAILED.ordinal()); logger.info("Found entity with status: " + STATUS.values()[e.getStatus()]); 

Assume the necessary imports etc.

I find this use of ordinal() to be an antipattern, and consider that it should be avoided.
Instead, an inner field with the equivalent DB representation (e.g. NEW(1) or NEW("N")) should be used, in order to decouple the semantically meaningful representation of the enum value in the code (NEW) from the DB-optimized representation of such value when persisted (1 or 'N' or whatever).

Now, I don’t have this POV for nothing: we’ve already had bugs stemming from altering the order of enum elements that were being used based on its ordinal() value (some times because of adding new values in between, some times because someone decided the values looked better in alphabetical order ¯\_(ツ)_/¯).

That’s the case I made in the PR comments — but in the end the PR got approved anyway, reasoning that my proposed correction would add too much clutter to the enum for little gain, and that we should all just be careful with enums.
And so the enum made its way to production.

Time has passed, and now I’ve got the chance to change that enum so its usage is not tied to the ordering of its elements.
However, since this has been in production for quite some time, I have to make it so the current DB values (0, 1, 2…) are kept and still interpreted correctly (as changing the DB values or column type would be too costly now).

This is the first version I came up with:

public enum STATUS {     NEW (0),     SENT (1),     FAILED (2),     OK (3),     ;      private final int val;      STATUS (int val) { this.val = val; }      public int val() { return val; }      public static STATUS get(final int val) {         switch (val) {             case 0: return NEW;             case 1: return SENT;             case 2: return FAILED;             case 3: return OK;             default: throw new IllegalArgumentException();         }     } } 

I think this is as concise as it can get.
However, if a dev wanted to add a new enum value, they’d have to modify both the enum list and the switch inside the get(int) method. I find this to be inconvenient and, in a way, ammunition for my peers in favor of just using ordinal().
So I came up with this second version:

public static enum STATUS {     NEW (0),     SENT (1),     FAILED (2),     OK (3),     ;      private static final STATUS[] values;     static { // like caching values() but sorted by dbValue         STATUS[] st = values();         values = new STATUS[st.length];         for (STATUS s : st) {             values[s.dbValue] = s;         }     }     public static STATUS fromDB(final int dbValue) {         return values[dbValue];     }      private final int dbValue;     public int toDBValue() {         return dbValue;     }      STATUS(int dbValue) {         this.dbValue = dbValue;     } } 

In this version, adding a new enum element is as simple as adding it to the list, just like a normal enum. And getting an element from its DB value is O(1) and rather efficient (compared to, say, using Streams to filter values() by dbValue every time). But maybe it is too complex for an enum? Also, this relies on DB values being consecutive numbers, as adding e.g. CANCELLED(99) would throw an AIOOB exception upon execution.

So my question is: how can I enhance this enum so adding elements to it is as simple as possible, getting elements by value is as efficient as possible, and it doesn’t depend on ordinal()?

From Munich to Rome by train (avoiding tunnels)

I want to travel from Munich to Rome by train. There are several routes to take, for example Munich -> Bologna-> Rome or Munich -> Bolzano -> Rome or through Switzerland, etc.. I would love to know which route should I take if I want to cross as few tunnels as possible (i.e. which route is the most tunnel-free)

Bonus question : how long is the longest tunnel between on the given route?

EDIT: I want to avoid tunnels because I am claustrophobic and hate them. I can tolerate short tunnels (>1000 -1500 m). Before I rule out travelling by train I just want to be sure if there is a route without tunnels that exceed let’s say 2000 metres or not.

D&D 3.5 Overrun avoiding

I have a question regarding Overrun special attack in D&D 3.5. The rule says that, the defender can “simply avoid me“, but it doesn’t clarify if he has to perform any action or roll in order to achieve that. Is that so, that the defender only says “I’m avoiding!” and that’s it? Is there no need for any roll? Does it mean that I can pass through the defender as he wasn’t even there? Does the defender stay all the time on the same square as before while avoiding?

Opponent Avoids? The defender has the option to simply avoid you. If he avoids you, he doesn’t suffer any ill effect and you may keep moving (You can always move through a square occupied by someone who lets you by.) The overrun attempt doesn’t count against your actions this round (except for any movement required to enter the opponent’s square). If your opponent doesn’t avoid you, move to Step 3.

Thanks for your help and sorry if it is so simple.

One more question – why does this table say that Overrun doesn’t provoke AoO?