Vain attempt to get a lower phone bill

Thank you for choosing AT&T. A representative will be with you shortly.
You are now chatting with Ana G.
Ana G: Hello my name is Ana G. Thank you for allowing me to be your specialist today. How may I assist you?
Ana G: Hi, I’m sorry for any delay in reaching me. I see that you have been speaking to another representative. Please allow me a moment to review your previous conversation and I will be happy to assist you further.
Humberto A Sanchez II: thanks I dropped the connection
Ana G: To make sure I understand you correctly, you have a question about the promotions on the account; Is that correct?
Humberto A Sanchez II: Well in general since september 2014 my bill has increased; I lost my $21 discount; My receiver fees went from $8 to $9 each; internet went from $56 to $57, u200 went from $77 to $80;
Humberto A Sanchez II: Feel like you are nickel and diming me $1 at a time;
Humberto A Sanchez II: I want my bill to be $150 not $200
Ana G: Thank you for confirming.
Humberto A Sanchez II: too much
Ana G: I can help you with that!
Ana G: Please allow me a moment, while I access your account.
Ana G: I see that you have now you U200 TV plan + 18 mbps internet.
Ana G: I apologize for the inconvenience you have experienced.
Ana G: My goal is to fully resolve this issue for you today and ensure you do not have to contact us back. While I am accessing your account I would like to thank you for being a valued AT&T customer.
Ana G: I will be glad to address your concerns because it is our goal to provide the highest quality service available.
Ana G: Let me assure you that your concern has been taken care of. I will assist you with the all out & perfect resolution.
Ana G: I see great promotional deals on your account.
Humberto A Sanchez II: Ok
Ana G: I am sure you will be interested to know about it.
Humberto A Sanchez II: cool
Ana G: I can get you U450 TV plan + 18 mbps Internet for a monthly bill of $164.95 + taxes.
Ana G: I would like to inform you that U450 is the highest Tv plan that we offer to valuable customers just like you.
Ana G: U450(Include more than 450 channels, HD, HBO, Cinemax, ENCORE, STARZ, Showtime, Movies Pack, Sport Pack and many more).
Ana G: With U450 Tv plan you will get HD services free of cost which normally is $10/month.
Ana G: You will also get HBO/Cinemax free of cost with this deal which normally is $26/month.
Humberto A Sanchez II: can you give me the the same plan except $150 and the U200 package
Ana G: I would like to inform you that the promotions are available with the upgraded plans only.
Ana G: However, I would like to mention that the Internet part of the deal is for 12 months.
Ana G: With $12.05 discounts added to it.
Humberto A Sanchez II: yeah, I am going to have to shop around suddenlink here in town; that option is out of my budget
Ana G: And on the TV part I am adding $32 discounts.
Ana G: I have another option for you.
Humberto A Sanchez II: ok
Ana G: I can get you U300 Tv plan + 18 mbps for $159.95 + taxes.
Ana G: U300 TV package which offers up to 360 channels, including local channels as well as History, MTV, etc. Plus, enjoy the convenience of our Total Home DVR with an additional receiver at no monthly charge for as long as you keep the qualifying service. This package also includes our most popular premium channels at no additional cost (The Movie Channel Starzョ, Encoreョ, SHOWTIMEョ and Flix).
Humberto A Sanchez II: Hmm
Humberto A Sanchez II: So right now I have the main DVR plus two receivers
Humberto A Sanchez II: does that change the pric
Ana G: So how does this sounds to you?
Humberto A Sanchez II: price
Ana G: Yes.
Ana G: This $159.95 + taxes includes everything.
Humberto A Sanchez II: including the equipment I have right now?
Ana G: The DVR, two recievers, the modem, TV services and also the Internet.
Humberto A Sanchez II: $159.95?
Ana G: This will be the total monthly bill for the services.
Ana G: Yes.
Ana G: I value you as our customer and I will do my best to make you very satisfied.
Ana G: I will go extra miles to serve you the best customer service.
Ana G:
Humberto A Sanchez II: Sorry, not clear; does the $159.95 include taxes or not?
Ana G: No, $159.95 + taxes.
Ana G: The taxes are 7-10%, depending on the regions.
Humberto A Sanchez II: yeah, taxes will put it back to $200 which is where we started; I am happy with the u200 package I have right now and the internet service, I just want to pay $150 in total including taxes
Ana G: No.
Ana G: Be rest assured about it.
Ana G: It will come around $15.
Humberto A Sanchez II: thinking
Ana G: And I would like to inform you that now you have U200 TV plan and 18 mbps Internet and the monthly bill for the services is for $173 + taxes.
Humberto A Sanchez II: I know that;
Humberto A Sanchez II: as I said that is too much money
Humberto A Sanchez II: I want to pay less
Humberto A Sanchez II: not get more services
Ana G: I truly appreciate you that you are so much concern about your bills.
Ana G: We just need the customers like you.
Humberto A Sanchez II: I want to pay what I was paying in September of 2014 before all the price increases
Ana G: Absolutely, I’m committed to resolve it for you. As I said I’m trying to put myself in your shoes and then work from that aspect.
Ana G: I am just trying to help you make some savings with this deal.
Ana G: I am getting you the same Internet speed.
Ana G: Just that I am upgrading the TV plan as I can see that with the upgrade I can add the discounts.
Humberto A Sanchez II: My total bill including taxes was $148.81; I am giving you a break and asking for my same package for $150;
Ana G: This is helping to lower the monthly bill.
Humberto A Sanchez II: I do not want upgrades; I don’t even watch what I have now
Ana G: I understand that.
Humberto A Sanchez II: hmm
Ana G: But that was an introductory offer, which my system will allow me to add only once.
Humberto A Sanchez II: I understand; But you got me used to those prices
Humberto A Sanchez II: I am hooked
Ana G: After the expiration of the Introductory offer, we can add only the promotional discounts.
Humberto A Sanchez II: on the lower prices
Humberto A Sanchez II: So can you come up with some combination of promotions that let me keep my same plan for $150?

Ana G: Let me check that for you.
Ana G: I can help you lower down your monthly bill to $149.95 + taxes if you can remove the HD services from your account.
Ana G: Will that works for you?
Humberto A Sanchez II: No.
Ana G: As I had added all the maximum discounts available to get you the best deal.
Humberto A Sanchez II: It seems nothing has changed; I get the same service but the prices go up
Humberto A Sanchez II: Ok. So you leave me no choice but to look at another provider; Thanks for your time
Ana G: You will feel the difference after this order is processed.
Ana G: As with the U300 TV plan you will get better services.
Ana G: More channels, more options.
Humberto A Sanchez II: I do not need an upgrade
Ana G: I had a word with my manager and requested him to help you personally, please provide me your call back number so that he can call you right away.
Humberto A Sanchez II: I am not available until 2:30 p.m. CST; 512.820.3817
Humberto A Sanchez II: thanks
Ana G: Okay.

Management

A man flying in a hot air balloon suddenly realizes he’s lost. He reduces height and spots a man down below. He lowers the balloon further and shouts to get directions, “Excuse me, can you tell me where I am?”

The man below says: “Yes. You’re in a hot air balloon, hovering 30 feet above this field.”

“You must work in Information Technology,” says the balloonist.

“I do” replies the man. “How did you know?”

“Well,” says the balloonist, “everything you have told me is technically correct, but It’s of no use to anyone.”

The man below replies, “You must work in management.”

“I do,” replies the balloonist, “But how’d you know?”*

“Well”, says the man, “you don’t know where you are or where you’re going, but you expect me to be able to help. You’re in the same position you were before we met, but now it’s my fault.

Converting to Spring Data

 

Introduction

Let’s take a traditional MVC Spring project and convert it to Spring Data. Does it lead to better and more minimalistic code.? Let’s discover if it does

This document examines a traditional Spring MVC project’s DAO layer. Then it converts it Spring Data and examines the code and its maintainability.

 

2. Traditional Spring MVC Data Layer

 

2.1. DAOs

From Figure 1, we can see that:

  1. This application directly accesses three tables
    1. A VERS (vehicle exception reporting system)  table — VersDAO
    2. A USER table — UserDAO
    3. An Incident table — IncidentDAO
  2. In order to reduce complexity and keep DRY[1], the code author templatized the basic CRUD capabilities in the BaseDAO<T> class.

 

StandardDAOLayer

Figure 1. Standard DAO Layer.

 

 


2.2. Real (must be watered and fed) Code

Actual code exists behind the methods (See Figure 2,)

  1. . getById ()
  2. . getAll()
  3. .saveOrUpdate()
  4. .deleteById()

RealMustBeWateredCode

Figure 2. Real “must be maintained” Code.

 


2.3. Hibernate Mapping Files

From Figure 3 we can see the Hibernate mapping files associated with this application.

Pros

  1. Auto-generated
  2. Central location

Cons

  1. Centrally located
  2. Auto-generation causes weirdly named files reflective of the tables they came from

MultipleMappingFiles

Figure 3. Multiple Mapping Files.

 


2.4. Sample Hibernate Mapping

As shown in the following redacted XML stanza for a single mapping file, Hibernate by nature generates verbose standalone XML descriptions.

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Dec 3, 2013 9:16:38 AM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
 <class name="com.uprr.autos.irsvers.domain.Vers" table="INL_VERS_EXCP">
 <id name="versExcpId" type="string">
 <column name="VERS_EXCP_ID" length="38" />
 <generator class="assigned" />
 </id>
 <property name="excpEvntDate" type="date">
 <column name="EXCP_EVNT_DATE" length="7" not-null="true" />
 </property>
 <property name="excpCrtnDate" type="date">
 <column name="EXCP_CRTN_DATE" length="7" not-null="true" />
 </property>
 .
 . <REDACTED>
 .
<set name="inlVersExcpVins" table="INL_VERS_EXCP_VIN" inverse="true"
 lazy="true" fetch="select" cascade="all">
<key>
<column name="VERS_EXCP_ID" length="38" not-null="true" />
</key>
<one-to-many class="com.uprr.autos.irsvers.domain.VersExceptionVin" />
</set>
 .
 . <REDACTED>
 .
 </hibernate-mapping>
 

2.5. Sample Generated Code

 

TheUntypedTrap

Figure 4. The Untyped Hack.

 


3. Updated to Spring Data

3.1. JPA Annotations

Figure 5, shows how the ease with which we map Java object attributes to DB table columns. This is an improvement from original hibernate generated code in that Java Set’s are now type cast removing pragmas around suppressing warnings and knowing the actual object types returned in the collections.

 

Pros

  1. Annotation closest to affected code
  2. IDE contextual help

Cons

  1. JPA annotations spread all over code

 

JPA_BasicAnnotations

Figure 5. Simple JPA Annotations.

Figure 6, depicts the typed data types that allows to refer to associated DB columns and map them to Java “contained” object sets.

CrossTableJoinNonDomainModel

Figure 6. Cross Table JPA Annotations.

 


3.2. Spring Data Repositories

Figure 7 shows the data repositories we created to replace the custom DAOs. Note that these interfaces are sub classed from the JPARepository interface.

RepositoryUML

Figure 7. Spring Data Repository Layer.

 

JPARepositoryFreeMethods

From Figure 8 we can see the plethora of functionality that we inherit from

  1. CrudRepository
  2. PagingAndSortingRepository
  3. JPARepository

Figure 8. JPA Repository ‘Free’ Methods.

 


3.3. Data Repositories Details

3.3.1. Easy

Figure 9 depicts the ease with which get the “free” functionality.

EasyJPACRUDRepositories

Figure 9. Easy JPA CRUD Functionality.

 


3.3.2. Not so easy

Spring Data makes it easy to get free functionality if you have a good domain model to DB mapping. However, sometimes we have to synthesize a domain object from several DB tables. This is harder and more “hacky”. The solution is to use Spring Data’s Query functionality. See Figure 10. Use JPA @Query annotation. This identifies both the new method name and the SQL query string to execute. Note that the returned types will not match the returned data hence we get an array of objects returned.

 

SynthethicDomainObjects

Figure 10. Synthetic Domain Objects.

 

In Figure 11, we can see that all we get back are generic objects. We will have to re-compose these into real ContactInformation domain model objects.

GenericObjectMapping

Figure 11. Generic Object Mapping.

 

Figure 12 illustrates the non-intuitive code to convert from generic objects to a list of real domain model objects.

  • Initialize the returned list and the loop counter to traverse generic list
  • Get generic object out of list and cast it to an array of Objects
  • Use well-known indices to get the following values
    1. User ID
    2. Contact Group ID
    3. Contact ID
  • Update the ContactInformation object
    1. The integer value of the User ID
    2. User name and UP user id from well known safe indices
  • Provide null value of CG id or its integer representation
  • Provide integer value of Contact id

CustomObjectListToDomainModelMapping

Figure 12. Custom Object List to Domain Model Mapping.

 


3.4. Changes made to Services

In Figure 13, we are trying to determine what code changed in the service layer when we switched from DAOs to the spring data repositories. At first glance, it appears that we added much more code. However, notice that in the original version it was using methods provided by the generic template class.

CompareToTemplateInstance

Figure 13. Compare to template instance.

 

From Figure 14, we see that our repository object is auto wired. In addition, other than a few naming changes to comply with the Spring data naming conventions, the changes are trivial. Converting this BaseServiceImpl template class to use the repository was outside the scope of this change and the topic of a future refactoring.

RealServiceComparison

Figure 14. Real Service Change.


3.5. Using Spring Boot

I really had a high want to use the Spring Boot with its opinionated dependencies. See Figure 15. However, could not quite get the “magic” to work for this JPA SQL project.[2]

SpringBootDependencies

Figure 15. Spring Boot Simple Dependencies.

 


3.6. Or not Using Spring Boot

The result was a more “traditional” Spring dependency list as depicted in Figure 16.

StandardSpringDependencies

Figure 16. Standard Spring Data POM.

[1] Don’t Repeat Yourself

[2] Interestingly the figure noted came from a Neo4J project that used this simple dependency stanza.

Java Class Design (Prefer composition over inheritance)

This article provides an example of extending an ETL application to include additional functionality.  The new feature was to include detailed record counts for the migrated database records.  The simple approach was to add additional properties and methods to the base transformation service.  This article walks the reader through the simple approach and leads her through the refactoring process of using composition to achieve better code reuse, extensibility, and reuse.   The following figure shows the unmodified base interface and class, TransformService and TransformServiceImpl that needs updating to include additional record counting diagnostics  .

 

UnmodifiedClass

 

The next figure shows the updates to include additional properties and accessors that provide the needed record metrics.  At first blush, this seems like a simple update. However, consider if we needed to update the ETL service to include counts of failed transformations or metrics around timings of persisting the database record hierarchy.  I assert that adding that functionality directly to the service violates the single responsibility principle.

 

InhertitanceBasedUpdateToClass

The following figure shows the refactor to extract the TransformCountingService into a separate interface and class.

CompositionBasedClassStructure

From a code point of view, the former code looked as follows.

protected   int globalRecCount; 
protected   int globalAssignmentCount; 
protected   int globalVinCount; 
protected   int globalDetailCount; 
. 
. 
. 

globalRecCount++; 
globalAssignmentCount += retRecord.getInlVersExcpAsgns().size(); 
globalVinCount        += retRecord.getInlVersExcpVins().size(); 
globalDetailCount     += retRecord.getInlVersExcpDtls().size(); 

The refactored code shows the delegation to the contained class.

@Autowired
private TransformCountingService    countingService; 
. 
. 
. 
countingService.updateGlobalRecCount(1);
countingService.updateGlobalAssignmentCount(retRecord.getInlVersExcpAsgns().size());
countingService.updateGlobalVinCount(retRecord.getInlVersExcpVins().size());
countingService.updateGlobalDetailCount(retRecord.getInlVersExcpDtls().size());