Archive

Posts Tagged ‘Object-Oriented Programming’
  • Oop Compatible Enterprise Context

    A pair of glasses on a background of screens displaying code

    = Is Object-Oriented Programming compatible with an enteprise context?

    This week, during a workshop related to a Java course I give at a higher education school, I noticed the code produced by the students was mostly - ok, entirely, procedural. In fact, though the Java language touts itself as an Object-Oriented language, it’s not uncommon to find such code developed by professional developers in enterprises. For example, https://en.wikipedia.org/wiki/JavaBeans[the JavaBean specification^] is in direct contradiction of one of OOP’s main principle, https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)[encapsulation^].

    Another example is the widespread controller, service and DAO architecture found equally in Java EE and Spring applications. In that context, entities are in general https://www.martinfowler.com/bliki/AnemicDomainModel.html[anemic^], while all business logic is located in the service layer. While this is not bad per se, this design separates between state and behaviour, and sits at the opposite to true OOP.

    Both Java EE and the Spring framework enforce this layered design. For example, in Spring, there’s one annotation for every such layer: @Controller, @Service and @Repository. In the Java EE world, only @EJB instances - the service layer, can be made transactional.

    This post aims to try to reconcile both the OOP paradigm and the layered architecture. I’ll be using the Spring framework to highlight my point because I’m more familiar with it, but I believe the same approach could be used for pure Java EE apps.

    == A simple use-case

    Let’s have a simple use-case: from an IBAN number, find the associated account with the relevant balance. Within a standard design, this could look like that:

    [source,java]

    @RestController class ClassicAccountController(private val service: AccountService) {

    @GetMapping("/classicaccount/{iban}")
    fun getAccount(@PathVariable("iban") iban: String) = service.findAccount(iban) }
    

    @Service class AccountService(private val repository: ClassicAccountRepository) { fun findAccount(iban: String) = repository.findOne(iban) }

    interface ClassicAccountRepository : CrudRepository<ClassicAccount, String>

    @Entity @Table(name = “ACCOUNT”) class ClassicAccount(@Id var iban: String = “”, var balance: BigDecimal = BigDecimal.ZERO) —-

    There are a couple of issues there:

    . The JPA specifications mandates for a no-arg constructor. Hence, it’s possible to create ClassicalAccount instances with an empty IBAN. . There’s no validation of the IBAN. The full round-trip to the database is required to check if an IBAN is valid.

    NOTE: Yes, there’s no currency. It’s a simple example, remember?

    == Being compliant

    In order to comply with the no-args constructor JPA constraint - and because we use Kotlin, it’s possible to generate a synthetic constructor. That means the constructor is accessible through reflection, but not by calling the constructor directly.

    [source,xml]

    kotlin-maven-plugin org.jetbrains.kotlin ${kotlin.version} jpa org.jetbrains.kotlin kotlin-maven-noarg ${kotlin.version}

    WARNING: If you use Java, tough luck, I don’t know about any option to fix that.

    == Adding validation

    In a layer architecture, the service layer is the obvious place to put the business logic, including validation:

    [source,java]

    @Service class AccountService(private val repository: ClassicAccountRepository) { fun findAccount(iban: String): Account? { checkIban(iban) return repository.findOne(iban) }

    fun checkIban(iban: String) {
        if (iban.isBlank()) throw IllegalArgumentException("IBAN cannot be blank")
    } } ----
    

    In order to be more OOP-compliant, we must decide whether we should allow invalid IBAN numbers or not. It’s easier to forbid it altogether.

    [source,java]

    @Entity @Table(name = “ACCOUNT”) class OopAccount(@Id var iban: String, var balance: BigDecimal = BigDecimal.ZERO) { init { if (iban.isBlank()) throw IllegalArgumentException(“IBAN cannot be blank”) } } —-

    However, this means that we must first create the OopAccount instance to validate the IBAN - with a balance of 0, even if the balance is actually not 0. Again, as per the empty IBAN, the code does not match the model. Even worse, to use the repository we must access the OopAccount inner state:

    [source,java] repository.findOne(OopAccount(iban).iban)

    == A more OOP-friendly design

    Improving the state of the code requires a major rework on the class model, separating between the IBAN and the account, so that the former can be validated, and can access the latter. The IBAN class serves both as the entry point, and the PK of the account.

    [source,java]

    @Entity @Table(name = “ACCOUNT”) class OopAccount(@EmbeddedId var iban: Iban, var balance: BigDecimal)

    class Iban(@Column(name = “iban”) val number: String, @Transient private val repository: OopAccountRepository) : Serializable {

    init {
        if (number.isBlank()) throw IllegalArgumentException("IBAN cannot be blank")
    }
    
    val account
        @JsonIgnore
        get() = repository.findOne(this) } ----
    

    NOTE: Notice the returned JSON structure will be different from the one returned above. If that’s an issue, it’s quite easy to customize Jackson to obtain the desired result.

    With this new design, the controller requires a bit of change:

    [source,java]

    @RestController class OopAccountController(private val repository: OopAccountRepository) {

    @GetMapping("/oopaccount/{iban}")
    fun getAccount(@PathVariable("iban") number: String): OopAccount {
        val iban = Iban(number, repository)
        return iban.account
    } } ----
    

    The only disadvantage of this approach is that the repository needs to be injected into the controller, then be explicitly passed to the entity’s constructor.

    == The final touch

    It would be great if the repository could automatically be injected into the entity when it’s created. Well, Spring makes it possible - though this is not a very well-known feature, through Aspect-Oriented Programming. It requires the following steps:

    Add AOP capabilities to the application:: To effectively add the AOP dependency is quite straightforward and requires just adding the relevant starter dependency to the POM: + [source,xml] —-

    org.springframework.boot spring-boot-starter-aop

    + Then, the application must be configured to make use of it: + [source,java] —- @SpringBootApplication @EnableSpringConfigured class OopspringApplication —-

    Update the entity:: . The entity must first be set as a target for injection. Dependency injection will be done through autowiring. . Then, the repository be moved from a constructor argument to a field. . Finally, the database fetching logic can be moved into the entity: + [source,java] —- @Configurable(autowire = Autowire.BY_TYPE) class Iban(@Column(name = “iban”) val number: String) : Serializable {

    @Transient
    @Autowired
    private lateinit var repository: OopAccountRepository
    
    init {
        if (number.isBlank()) throw IllegalArgumentException("IBAN cannot be blank")
    }
    
    val account
        @JsonIgnore
        get() = repository.findOne(this) } ----
    

    NOTE: Remember that field-injection is evil.

    Aspect weaving:: There are two ways to weave the aspect into the , either compile-time weaving, or load-time weaving. I choose the the later is much easier to configure. It’s achieved through a standard Java agent. + . First, it needs to be added as a runtime dependency in the POM: + [source,xml] —-

    org.springframework spring-agent 2.5.6 runtime

    + . Then, the Spring Boot plugin must be configured with the agent: + [source,xml] —-

    org.springframework.boot spring-boot-maven-plugin ${settings.localRepository}/org/springframework/spring-agent/2.5.6/spring-agent-2.5.6.jar

    . Finally, the application must be configured accordingly: + [source,java] —- @EnableLoadTimeWeaving class OopspringApplication —-

    == And then?

    Of course, this sample leaves out an important piece of the design: how to update the balance of an account? The layer approach would have a setter for that, but that’s not OOP. Thinking about it, the balance of an account changes because there’s a transfer from another account. This could be modeled as:

    [source,java] fun OopAccount.transfer(source: OopAccount, amount: BigDecimal) { … }

    Experienced developers should see some transaction management requirements sneaking in. I leave the implementation to motivated readers. The next step would be to cache the values, because accessing the database for each read and write would be killing performance.

    == Conclusion

    There are a couple of points I’d like to make.

    First, the answer to the title question is a resounding ‘yes’. The results is a true OOP code while still using a so-called enterprise-grade framework - namely Spring.

    However, migrating to this OOP-compatible design came with a bit of overhead. Not only did we rely on field injection, we had to bring in AOP with load-time weaving. The first is a hindrance during unit testing, the second is a technology you definitely don’t want in every team, as they make apps more complex. And that’s only for a trivial example.

    Finally, this approach has a huge drawback: most developers are not familiar with it. Whatever its advantages, they first must be “conditioned” to have this mindset. And that might be a reason to continue using the traditional layered architecture.

    NOTE: I’ve searched Google for scientific studies proving OOP is better in terms of readability and maintainability: I found none. I would be very grateful for pointers.

    Categories: JavaEE Tags: Object-Oriented ProgrammingOOPSpring
  • Coping with stringly-typed

    :page-liquid: :experimental: :imagesdir: /assets/resources/coping-stringly-typed/

    UPDATED on March 13, 2017: Add Builder pattern section

    Most developers have strong opinions regarding whether a language should be https://en.wikipedia.org/wiki/Strong_and_weak_typing[strongly-typed or weakly-typed^], whatever notions they put behind those terms. Some also actively practice http://wiki.c2.com/?StringlyTyped[stringly-typed^] programming - mostly without even being aware of it. It happens when most of attributes and parameters of a codebase are String. In this post, I will make use of the following simple snippet as an example:

    [source,java]

    public class Person {

    private final String title;
    private final String givenName;
    private final String familyName;
    private final String email;
      
    public Person(String title, String givenName, String familyName, String email) {
        this.title = title;
        this.givenName = givenName;
        this.familyName = familyName;
        this.email = email;
    }
    ... } ----
    

    == The original sin

    The problem with that code is that it’s hard to remember which parameter represents what and in which order they should be passed to the constructor.

    [source,java] Person person = new Person(“[email protected]”, “John”, “Doe”, “Sir”);

    In the previous call, the email and the title parameter values were switched. Ooops.

    This is even worse if more than one constructor is available, offering optional parameters:

    [source,java]

    public Person(String givenName, String familyName, String email) { this(null, givenName, familyName, email); }

    Person another = new Person(“Sir”, “John”, “Doe”);

    In that case, title was the optional parameter, not email. My bad.

    == Solving the problem the OOP way

    Object-Oriented Programming and its advocates have a strong aversion to stringly-typed code for good reasons. Since everything in the world has a specific type, so must it be in the system.

    Let’s rewrite the previous code à la OOP:

    [source,java]

    public class Title { private final String value; public Title(String value) { this.value = value; } }

    public class GivenName { private final String value; public FirstName(String value) { this.value = value; } }

    public class FamilyName { private final String value; public LastName(String value) { this.value = value; } }

    public class Email { private final String value; public Email(String value) { this.value = value; } }

    public class Person {

    private final Title title;
    private final GivenName givenName;
    private final FamilyName familyName;
    private final Email email;
      
    public Person(Title title, GivenName givenName, FamilyName familyName, Email email) {
        this.title = title;
        this.givenName = givenName;
        this.familyName = familyName;
        this.email = email;
    }
    ... }
    

    Person person = new Person(new Title(null), new FirstName(“John”), new LastName(“Doe”), new Email(“[email protected]”));

    That way drastically limits the possibility of mistakes. The drawback is a large increase in verbosity - which might lead to other bugs.

    == Pattern to the rescue

    A common way to tackle this issue in Java is to use the Builder pattern. Let’s introduce a new builder class and rework the code:

    [source,java]

    public class Person {

    private String title;
    private String givenName;
    private String familyName;
    private String email;
    
    private Person() {}
    
    private void setTitle(String title) {
        this.title = title;
    }
    
    private void setGivenName(String givenName) {
        this.givenName = givenName;
    }
    
    private void setFamilyName(String familyName) {
        this.familyName = familyName;
    }
    
    private void setEmail(String email) {
        this.email = email;
    }
    
    public static class Builder {
    
        private Person person;
    
        public Builder() {
            person = new Person();
        }
    
        public Builder title(String title) {
            person.setTitle(title);
            return this;
        }
    
        public Builder givenName(String givenName) {
            person.setGivenName(givenName);
            return this;
        }
    
        public Builder familyName(String familyName) {
            person.setFamilyName(familyName);
            return this;
        }
    
        public Builder email(String email) {
            person.setEmail(email);
            return this;
        }
    
        public Person build() {
            return person;
        }
    } } ----
    

    Note that in addition to the new builder class, the constructor of the Person class has been set to private. Using the Java language features, this allows only the Builder to create new Person instances. The same is used for the different setters.

    Using this pattern is quite straightforward:

    [source,java]

    Person person = new Builder() .title(“Sir”) .givenName(“John”) .familyName(“Doe”) .email(“[email protected]”) .build(); —-

    The builder patterns shifts the verbosity from the calling part to the design part. Not a bad trade-off.

    == Languages to the rescue

    Verbosity is unfortunately the mark of Java. Some other languages (Kotlin, Scala, etc.) would be much more friendly to this approach, not only for class declarations, but also for object creation.

    Let’s port class declarations to Kotlin:

    [source,java]

    class Title(val value: String?) class GivenName(val value: String) class FamilyName(val value: String) class Email(val value: String)

    class Person(val title: Title, val givenName: GivenName, val familyName: FamilyName, val email: Email)

    This is much better, thanks to Kotlin! And now object creation:

    [source,java] val person = Person(Title(null), GivenName(“John”), FamilyName(“Doe”), Email(“[email protected]”))

    For this, verbosity is only marginally decreased compared to Java.

    == Named parameters to the rescue

    OOP fanatics may stop reading there, for their way is not the only one to cope with stringly-typed.

    One alternative is about named parameters, and is incidentally also found in Kotlin. Let’s get back to the original stringly-typed code, port it to Kotlin and use named parameters:

    [source,java]

    class Person(val title: String?, val givenName: String, val familyName: String, val email: String)

    val person = Person(title = null, givenName = “John”, familyName = “Doe”, email = “[email protected]”)

    val another = Person(email = “[email protected]”, title = “Sir”, givenName = “John”, familyName = “Doe”)

    A benefit of named parameters besides coping with stringly-typed code is that they are order-agnostic when invoking the constructor. Plus, they also play nice with default values:

    [source,java]

    class Person(val title: String? = null, val givenName: String, val familyName: String, val email: String? = null)

    val person = Person(givenName = “John”, familyName = “Doe”) val another = Person(title = “Sir”, givenName = “John”, familyName = “Doe”) —-

    == Type aliases to the rescue

    While looking at Kotlin, let’s describe a feature released with 1.1 that might help.

    A type alias is as its name implies a name for an existing type; the type can be a simple type, a collection, a lambda - whatever exists within the type system.

    Let’s create some type aliases in the stringly-typed world:

    [source,java]

    typealias Title = String typelias GivenName = String typealias FamilyName = String typealias Email = String

    class Person(val title: Title, val givenName: GivenName, val familyName: FamilyName, val email: Email)

    val person = Person(null, “John”, “Doe”, “[email protected]”)

    The declaration seems more typed. Unfortunately object creation doesn’t bring any betterment.

    Note the main problem of type aliases is that they are just that - aliases: no new type is created so if 2 aliases point to the same type, all 3 are interchangeable with one another.

    == Libraries to the rescue

    For the rest of this post, let’s go back to the Java language.

    Twisting the logic a bit, parameters can be validated at runtime instead of compile-time with the help of specific libraries. In particular, the Bean validation library does the job:

    [source,java]

    public Person(@Title String title, @GivenName String givenName, @FamilyName String familyName, @Email String email) { this.title = title; this.givenName = givenName; this.familyName = familyName; this.email = email; } —-

    Admittedly, it’s not the best solution… but it works.

    == Tooling to the rescue

    I have already written about link:{% post_url 2015-11-01-forget-the-language-the-important-is-the-tooling %}[tooling^] and that it’s as important (if not more) as the language itself.

    Tools fill gaps in languages, while being non-intrusive. The downside is that everyone has to use it (or find a tool with the same feature).

    For example, when I started my career, coding guidelines mandated developers to order methods by alphabetical order in the class file. Nowadays, that would be senseless, as every IDE worth its salt can display the methods of a class in order.

    Likewise, named parameters can be a feature of the IDE, for languages that lack it. In particular, latest versions of IntelliJ IDEA emulates named parameters for the Java language for types that are deemed to generic. The following shows the Person class inside the IDE:

    image::intellij-idea-named-parameters.png[Named parameters in IntelliJ IDEA,788,137,align=”center”]

    == Conclusion

    While proper OOP design is the historical way to cope with stringly-typed code, it also makes it quite verbose and unwieldy in Java. This post describes alternatives, with their specific pros and cons. Each needs to be evaluated in the context of one’s own specific context to decide which one is the best fit.