Posts Mentioning RSS Toggle Comment Threads | Keyboard Shortcuts

  • Mike 9:40 pm on May 29, 2008 Permalink | Reply
    Tags:   

    Exceptional Metadata 

    Exceptions are an important part of any programming language, especially Java. Java has two types of Exceptions. No, not checked and unchecked, but rather useful and useless. The utility of the Exception is up to you, the developer. What am I talking about? Bear with me, read on, and please share your comments at the end.

    Core data

    Exceptions are comprised of some sort of primary data, for example, the name or type of Exception, and maybe the exception’s message. Take, for example, a ConnectionTimeoutException.

    You, as a developer, have a pretty good idea as to what is going on when you see this at the top of the stack trace. You may be able to read the message, if the developer provided one, and get a little more information about the exception.

    /**
    * Signals that a timeout occurred while opening the socket.
    */
    public class ConnectionTimeoutException extends IOException {
    
    /** Create an instance */
    public ConnectionTimeoutException(String message) {
    super(message);
    }
    
    }
    

    Default Metadata

    If you read a stack trace or hack the exception’s API, you can even get some more information about the it. Such as the Class that threw the Exception, or the line number where the Exception occurred. You might be able to review the hierarchy of the class to garner some information. For example, this ConnectionTimeoutException extends from IOException. That tells you something.

    The Problem

    The problem with this type of Exception is that someone, like a developer, needs to review this information in order to track down the cause of the issue. That means locating the stack trace, and determining the parameters and other configurations that were present at the time of the Exception.

    Java, however, and most any other language, provide a means for supplying pertinent metadata when an Exception occurs. They are called properties, getters and setters, or mutators. You, as the designer, just need to include those properties when you design the class.

    Example

    Consider the ConnectionTimeoutException. Wouldn’t it be nice to know the source and destination URIs of the connection? And what the timeout value was?

    /**
    * Signals that a timeout occurred while opening the socket.
    */
    public class ConnectionTimeoutException extends IOException {
    
    private long timeout;
    private String source;
    private String destination;
    
    /** Create an instance */
    public ConnectionTimeoutException(long timeout, String source, String destination) {
    
    super("failed to connect to " + destination + " within alloted " + timeout + "ms");
    
    this.timeout = timeout;
    this.source = source;
    this.destination = destination;
    }
    
    public long getTimeout();
    public String getSource();
    public String getDestination();
    }
    

    Would you agree that the Exception that knows the timeout value and destination URI is more valuable to you, the developer, than some Exception with an arbitrary message that the designer may or may not have populated with relevant information?

    Benefits

    The resulting Exception implementation provides a constructor requiring specific values. The developer who consumes this Exception no longer needs to come up with some arbitrary message. He or she just needs to provide the requested parameters, which is known or can be read from some HttpClient implementation.

    The developer who is catching and dealing with this ConnectionTimeoutException now has a few more options. Perhaps an error message will be displayed. The developer can write a custom message and use the timeout property to notify the end user what the timeout was. The developer doesn’t need to parse it from a String message property.

    If the code throwing the ConnectionTimeoutException is a framework to be used by other developers, the developer has a lot more options to handle this Exception. Perhaps they are writing a GUI for your tool and can now provide their end users with more information.

    Metadata in the Real World

    I decided to write about this topic after a user of our Architecture Rules (Assert your Architecture!) open source software asked us to enhance our Exception APIs.

    Our CyclicRedundancyException simply contained a message that described a package by its name, and then listed all of the packages involved in a cyclic dependency with said package.

    ...architecturerules.exceptions.CyclicRedundancyException:
    cyclic dependencies found:
    
    -- test.com.seventytwomiles.services
    |  |
    |  |-- test.com.seventytwomiles.model
    |  |
    |  |-- test.com.seventytwomiles.dao.hibernate
    |
    |
    -- test.com.seventytwomiles.model
    |  |
    |  |-- test.com.seventytwomiles.services
    |
    |
    -- test.com.seventytwomiles.dao.hibernate
    |
    |-- test.com.seventytwomiles.services
    

    steven.devijver asked that we provide an API to retrieve a List of the packages involved in the cycle. This way Steven can construct his own message, or wrap the data in his own domain Exception, or whatever else he had in mind. We accommodated him by providing a Map containing a key (package name) and value (List of package names involved in a cyclic dependency) pair. This should be useful when we go to write the Maven 2 plugin report for this tool.

    As another example, we inherited a DataFinderException in another project we’re working on. The only constructor for this Exception was a String named message. We introduced a new constructor and two properties — name and value — and getters for each. Now, the code that constructs DataFinderExceptions no longer needs to build some complex message with a StringBuffer before throwing the Exception.

    StringBuffer message = new StringBuffer();
    message.append("Could not find entity with");
    message.append("userId");
    message.append(" = ");
    message.append(userId);
    
    throw new DataFinderException(message.toString());
    

    became

    throw new DataFinderException("userId", userId);
    

    A cleaner execution, fewer lines of code, and useful metadata that can be passed on to the end user, logged, or handled eloquently.

    How do you design your Exceptions to provide useful metadata? Can you think of any Exception in the JDK that provide such metadata?

     
    • Jamo 2:19 pm on May 30, 2008 Permalink

      Brilliant explanations!

      No, I can not think of an existing exception that provides useful information in it (was there a right answer?).

  • Mike 9:18 pm on May 15, 2008 Permalink | Reply
    Tags:   

    Squash those Cyles 

    Two packages are said to be involved in a cyclic dependency when package A depends on package B and package B depends on package A. This is called a direct cyclic dependency. Cyclic dependencies are created in various ways at different layers within a software system. It’s also possible for a cyclic relationship in one layer to cause cycles in another.

    cycles

    Cyclic dependencies hurt a software system’s goals:

    • Understandability Understandable software is critical in managing complex systems. Software that is easily understood acts like a bridge between the problem and its solution.
    • Flexibility
    • Modularity An approach to developing software that breaks projects into smaller units designed so that they can work with other sections of the program. Modifying the way that modules work will have no adverse affects on the other components of a program
    • Modifiability Modifiability is controlled change to the system in which some parts are altered without increasing the complexity or obscuring the logic of the original structure.
    • Reliability Reliability is the extent to which a software yields consistent, stable, and uniform without any human intervention and is crucial for any software system that must operate for long periods.
    • Maintainability The ease with which a software system can be modified to change or add capabilities, improve performance, or correct defects.
    • Testability The degree to which a system or component facilitates the establishment of test criteria and the performance of tests to determine whether those criteria have been met.
    • Reusability
    • Clarity

    By using Architecture Rules to Assert your Architecture, you are taking the first step in developing a strong architecture by actively managing package relationships.

    Aside from the adverse affects on the software development goals, cyclic dependencies create these negative consequences for the system:

    • Diminish the ability to determine a package’s purpose.
    • Changes impact seemingly unrelated components of the architecture.
    • Separation of layers.
    • Packages cooperating in a cycle must be released as an atomic unit.

    Determine a Package’s Purpose

    When future developers come along to maintain the software the presence of cycles can diminish the ability for that developer to determine a package’s purpose. This hurts the software’s clarity and understandability. The end result will be the introduction of bugs, or an increase in the amount of time required to modify the software.

    Changes Impact Unrelated Components

    When a class involved in a cycle is modified, it could change the bahavior of the other class involved in the cycle. This makes it difficult to accurately assess and manage the impact of changes to the system. This directly hinders the modifiability of your software. Reliability is also attacked since changing the behavior of an unrelated class could introduce a bug.

    Affecting other components also introduces a maintenance and testing issue, since you can’t do anything to either class without possibly affecting the other. A situation exists where class A needs to compile against class B, but class B needs to compile against class A.

    Separation of Layers

    Most architectural approaches recognize the advantages of layered architectures. For example, if you develop a presentation layer, a business or logic layer, and a database access layer, you are able to swap out one implementation of a layer for another. Such as replacing a JDBC data access layer with one that utilizes Hibernate, or a JSP presentation layer for a Flash or PHP presentation layer.

    Cyclic dependencies across layers couple the layers, defeating the purpose of layering. If a cycle exists between the service layer and the data access layer, then those two layers are no longer interchangeable. Thus, modifiability of the software is lowered. The layers are no longer encapsulated.

    Packages Must be Released as an Atomic Unit

    The Spring Framework is inspiring when it comes to its modular design. The Spring Framework can be considered as a collection of smaller frameworks. Most of these frameworks are designed to work independently of each other yet provide better functionalities when used together.

    This modularity by design, allows the Spring Framework to released as a full framework (spring.jar) or modularly, so that the users can use the features that they are interested, and nothing more (spring-core, spring-ldap, spring-orm, spring-aop, spring-beans, spring-mock, and on and on…). See all of the modules here.

    When cyclic dependencies exist, your ability to make and release independent modules is removed. Packages that may not be related must be released as a single jar, or module.

    ArchitectureRules wraps JDepend, a java library which is able to identify these cyclic dependencies. Upon detecting a cyclic dependency, a CyclicDependencyException is thrown, a RuntimeException whose message notifies you of which packages are involved in a cyclic dependency:

    ...architecturerules.exceptions.CyclicRedundancyException:
    
    cyclic dependencies found:
    -- test.com.seventytwomiles.services
    | |
    | |-- test.com.seventytwomiles.dao.hibernate
    |
    -- test.com.seventytwomiles.dao.hibernate
    |
    |-- test.com.seventytwomiles.services
    

    When are Cycles Acceptable

    Generally speaking, cycles are most always accepted when in the same package. For example two domain objects in the same package, such as User and Account. A User has Accounts, and an Account has a User. Since these two classes are in the same package, the package remains encapsulated.

     
  • Mike 8:35 pm on April 13, 2008 Permalink | Reply  

    What is “Architecture”? 

    The term “software architecture” is really hard to nail down. Different people have been defining it differently since we began writing software. I am not going to be able to tell you exactly what it is, but I can give you an idea as to what people are saying. By understanding that no one agrees on what architecture means, you can throw out the term more carefully as you talk with other developers.

    First, I want to share one my favorite “white papers.” I, for many years, didn’t know what people meant when they said architecture (actually, they probably didn’t either) but after reading this 3 page paper by Martin Fowler, I finally wrapped my head around it. The document is titled “Who Needs an Architect” and can be downloaded from the author’s site. The light bulb when on for me when I read these lines…

    “Remember Johnson’s secondary definition: “Architecture is the decisions that you wish you could get right early in a project.” Why do people feel the need to get some things right early in the project? The answer, of course, is because they perceive those things as hard hard to change. So you might end up defining architecture as “things that people perceive as hard to change”

    “There is no theoretical reason that anything is hard to change about software. If you pick any one aspect of software then you can make it easy to change, but we don’t know how to make everything easy to change. Making something easy to change makes the overall system a little more complex, and making everything easy to change makes the entire system very complex. Complexity is what makes software hard to change. That, and duplication.”

    Finally, now that makes sense to me. I’d paraphrase it as “The parts of a software system that you need to get right, the first time.” In the article, there is a discussion about a building. They mention the basement. When you have a home, you can change the interior around, add new paint, take down a wall, put up a wall, even build a new addition. However, the basement is the foundation. It’s not going anywhere. You can modify a house, but you can’t modify the basement. The basement makes up the home’s “architecture,” (but don’t confuse the basement with a database.)

    Different people have been defining it differently since we began writing software.

    I made this pretty bold statement to start off this explanation. Well, I have the proof to back it up. The Software Engineering Institute has a website. At it, they bring together published Modern, Classic, and Bibliographic Definitions of architecture. They also allow the “community” to submit their own definitions. They have one to two hundred definitions from senior analysts, project managers, software architects, doctors, and other “really important people.” These definitions follow many different themes, from definitions around concrete software, to definitions based on only the concepts of the software. Check out this list of Community Software Architecture Definitions for yourself.

    We’ll finish this off by sharing some content off of page 13 of a white paper titled Building Enterprise Architecture from Endava.com

    Architecture is defined as a subset of the design. While it is difficult
    to define which subset, the following definitions help:

    “The highest-level concept of a system in its environment.”
    (IEEE)

    The organization or structure of significant components, and
    their interactions.

    An abstraction of a system’s implementation.
    The parts or aspects of the design that are considered
    important.

    The parts or aspects of the design that need to be
    understood by many people, the shared understanding of
    the system design

    The decisions that are (or are thought to be) hard to change.

    Another shining example of how many different definitions for Architecture there is.

    Want to share your definition? What did you learn architecture to be?

     
    • Richard 7:36 pm on April 15, 2008 Permalink

      Your basement analogy is a good one, but I think it’s more subtle than that. My house doesn’t have a basement, but it does have a foundation. Sure, I can change some walls around, but not all of them. I can make cosmetic changes all I want, turning a bedroom into a den, for example, and vice versa.

      Other changes are more fundamental. I could not, for example, move my kitchen to another location without repiping most of the house. I can’t add certain walls unless I address the ductwork and airflow (to prevent freezing in a closed off space). I suppose I could simply replace the furnace with something more powerful to compensate, but it seems to me that would be the same thing as upgrading a server just to compensate for crappy inefficient code.

      (I’m not a technical person, just someone who writes about technology)

    • Ocean 11:23 am on May 2, 2008 Permalink

      You could just as well reverse the conclusion: architecture is those parts of the system that are most prone to change. This would make a bit more sense since the parts that don’t change often contribute very little value.

    • Dan Sickles 11:16 pm on March 8, 2009 Permalink

c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
l
go to login
h
show/hide help
esc
cancel