Monday, 8 October 2012

Step Builder Pattern - WIKI-Definition


Definition


The step builder pattern is an extension of the builder pattern that fully guides the user through the creation of the object with no chances of confusion. [1]

Contents


The intent of the Step Builder design pattern is to separate the construction of a complex object from its representation by creating defined steps and exposing to the user only selected methods per time.

Advantages of using the Step Builder over the Builder pattern

    • The user will see only one or few selected methods per time during the Object creation.
    • Based on the user choice different paths can be taken during the Object creation.
    • The final build step will be available only at the end, after all mandatory steps are completed, returning an Object in a consistent state.
    • The user experience will be greatly improved by the fact that he will only see the next step methods available.

    Examples

    Java

     /** "Product" */
     class UserConfiguration {
        private final String name;
        private final String filePath;
        private ServerDetails serverDetails;
     
        public UserConfiguration(String name, String filePath){
           this.name = name;
           this.filePath = filePath;
        }
        public void setServerDetails(ServerDetails serverDetails)     { this.serverDetails = serverDetails; }
     
        //all the getters
        ...
     }
     
    class ServerDetails {
        private final String host;
        private String user;
        private String password;
     
        public ServerDetails(String host){
           this.host = host;
        }
        public void setUser(String user)     { this.user = user; }
        public void setPassword(String password)     { this.password = password; }
     
        //all the getters and isLocalhost() method
        ...
     }
     
     
     
     /** "Step Builder" */
    public class UserConfigurationBuilder {
       public static NameStep newBuilder() {
          return new Steps();
       }  
       private UserConfigurationBuilder() {}
     
       public static interface NameStep {
          /**
           * @param name unique identifier for this User Configuration
           * @return FileStep
           */
          FileStep name(String name);
       }
     
       public static interface FileStep {
          /** 
           * @param filePath absolute path of where the User Configuration exists.
           * @return ServerStep
           */
          ServerStep filePath(String name);
       }
     
       public static interface ServerStep {
          /**
           * The hostname of the server where the User Configuration file is stored will be set to "localhost".
           * @return BuildStep
           */
          public BuildStep onLocalhost();
     
          /**
           * The hostname of the server where the User Configuration file is stored.
           * @return CredentialsStep
           */
          public CredentialsStep onRemotehost(String host);
       }
     
       public static interface CredentialsStep {
          /**
            * Username required to connect to remote machine
            * Password required to connect to remote machine
            * @return BuildStep
            */
           public BuildStep credentials(String user, String password);
       }
     
       public static interface BuildStep {
          /** 
           * @return an instance of a UserConfiguration based on the parameters passed during the creation.
           */
          public Profile build();
       }
     
       private static class Steps implements NameStep, FileStep, ServerStep, CredentialsStep, BuildStep {
     
          private String name;
          private String host;
          private String user;
          private String password;
          private String filePath;
     
          @Override
          public FileStep name(String name) {
             this.name = name;
            return this;
          }
     
          @Override
          public ServerStep filePath(String filePath) {
             this.filePath = filePath;
             return this;
          }
     
          @Override
          public BuildStep onLocalhost() {
             this.host = "localhost";
             return this;
          }
     
          @Override
          public CredentialsStep onRemotehost(String host) {
             this.host = host;
             return this;
          }
     
          @Override
          public BuildStep credentials(String user, String password) {
             this.user = user;
             this.password = password;
             return this;
          }
     
          @Override
          public UserConfiguration build() {
             UserConfiguration userConfiguration = new UserConfiguration(name, filePath);
             ServerDetails serverDetails = new ServerDetails(host);
             if (!serverDetails.isLocalhost()) {
                serverDetails.setUser(user);
                serverDetails.setPassword(password);
             }
             userConfiguration.setServerDetails(serverDetails);
             return userConfiguration;
          }
       }
    }
     
     
     /** A user creating a configuration. */
     class StepBuilderExample {
        public static void main(String[] args) {
            // A local user configuration
            UserConfiguration localUserConfiguration = UserConfigurationBuilder
                                                  .newBuilder()
                                                  .name("aLocalConfiguration")
                                                  .filePath("/opt/conf/user.txt")
                                                  .onLocalhost()
                                                  .build();  
            // A remote user configuration
            UserConfiguration remoteUserConfiguration = UserConfigurationBuilder
                                                  .newBuilder()
                                                  .name("aRemoteConfiguration")
                                                  .filePath("/opt/conf/user.txt")
                                                  .onRemotehost("172.x.x.x")
                                                  .credentials("user","password")
                                                  .build();  
        }
     }

    C#

    namespace StepBuilder
    {
        class Program
        {
            static void Main(string[] args)
            {
    
    
    
             UserConfiguration localUserConfiguration = UserConfigurationBuilder                        .CreateNewBuilder()
                            .SetName(@"aLocalConfiguration")
                            .SetFilePath(@"/opt/conf/user.txt")
                            .OnLocalhost()
                            .Build();
    UserConfiguration remoteUserConfiguration = UserConfigurationBuilder .CreateNewBuilder() .SetName(@"aRemoteConfiguration") .SetFilePath(@"/opt/conf/user.txt") .OnRemoteHost("172.x.x.x") .SetCredentials("user", "password") .Build(); } } public class UserConfiguration { public UserConfiguration(string name, string filePath) { Name = name; FilePath = filePath; } private ServerDetails _serverDetails; public string Name { get; private set; } public string FilePath { get; private set; } public void SetServerDetails(ServerDetails serverDetails) { _serverDetails = serverDetails; } } public class ServerDetails { public ServerDetails(string host) { Host = host; } public string Host { get; private set; } public string User { get; set; } public string Password { get; set; } public bool IsLocalhost { get { return Host == "localhost"; } } } public class UserConfigurationBuilder { public static INameStep CreateNewBuilder() { return new Steps(); } private UserConfigurationBuilder() { } public interface INameStep { /// <param name="name">Unique identifier for this User Configuration</param> IFileStep SetName(string name); } public interface IFileStep { /// <param name="filePath">Absolute path of where the User Configuration exists</param> IServerStep SetFilePath(string filePath); } public interface IServerStep { /// <summary> /// The hostname of the server where the User Configuration file is store will be set to "localhost". /// </summary> IBuildStep OnLocalhost(); /// <param name="host">The hostname of the server where the User Configuration is stored</param> ICredentialsStep OnRemoteHost(string host); } public interface IBuildStep { /// <summary> /// Returns an instance of a UserConfiguration based on the parameters passed during the creation. /// </summary> UserConfiguration Build(); } public interface ICredentialsStep { /// <param name="user">Username required to connect to remote machine</param> /// /// <param name="password">Password required to connect to remote machine</param> IBuildStep SetCredentials(string user, string password); } private class Steps : INameStep, IFileStep, IServerStep, IBuildStep, ICredentialsStep { private string _name; private string _host; private string _user; private string _password; private string _filePath; public IFileStep SetName(string name) { _name = name; return this; } public IServerStep SetFilePath(string filePath) { _filePath = filePath; return this; } public IBuildStep OnLocalhost() { _host = "localhost"; return this; } public ICredentialsStep OnRemoteHost(string host) { _host = host; return this; } public UserConfiguration Build() { UserConfiguration userConfiguration = new UserConfiguration(_name, _filePath); ServerDetails serverDetails = new ServerDetails(_host); if (!serverDetails.IsLocalhost) { serverDetails.Password = _password; serverDetails.User = _user; } userConfiguration.SetServerDetails(serverDetails); return userConfiguration; } public IBuildStep SetCredentials(string user, string password) { _user = user; _password = password; return this; } } } }

    Thursday, 20 September 2012

    Review Check box


    One good and necessary practice when developing software is the code review.

    Code review it's an excellent process to reduce bugs in the code and to raise up the quality of the software you are working on.

    Basically, it means that before committing your changes to the repository, you ask to another developer to look at your code and see if everything looks fine.

    But what is everything?

    Well, this can vary between companies standards, but the following can be a good starting point:

    OVERALL DESIGN
    (Is the current design the best design (i.e. is it scalable, maintainable, Are the algorithms following the best practise in order to have the best performances? etc.)       
    FUNCTIONALITY
    (Does the code do what is supposed to do? Are we covering all the possible cases?)       
    CODE READABILITY
    (Is the code EASY to understand? etc.)       
    UNIT TEST   
    (Are the tests covering all possible scenarios? Are the tests reusable? If the developed code does not have 100% code coverage, why not?)  
    ACCEPTANCE CRITERIA    
    (What are the Acceptance Criteria, and if the criteria haven't been expressed as an automated test, why not?)    
    ERROR HANDLING
    (Do we really need checked exceptions? etc.)
    WARNING   
    (Are the eclipse/intellij warnings acceptable?)
    LOG      
    (Is the log useful in order to find issue? Is the log communicating what is necessary? Etc.)

    Print this list and stick it in each developer desk. It will help during the review process.

    Wednesday, 19 September 2012

    The Meetings ERA


    You just opened your outlook calendar and you feel horrified from what you see??4 meetings in the same day??And maybe you really care about half of them??

    I think it’s good to know how to handle meetings and these are few suggestions coming from Robert C. Martin in his “The clean coder” book.


    I highlighted the key part on each paragraph, so if you are in rush you can just read the paragraph title and the part in bold ;)

     

    Meetings

    Meetings cost about $200 per hour per attendee. This takes into account salaries, benefits, facilities costs, and so forth. The next time you are in a meeting, calculate the cost. You may be amazed.
    There are two truths about meeting.
    1. Meetings are necessary.
    2. Meetings are huge time wasters.
    Often these two truths equally describe the same meeting. Some in attendance may find them invaluable; others may find them redundant or useless.
    Professionals are aware of the high cost of meetings. They are also aware that their own time is precious; they have code to write and schedules to meet. Therefore, they actively resist attending meetings that don’t have an immediate and significant benefit.

    Declining

    You do not have to attend every meeting to which you are invited. Indeed, it is unprofessional to go to too many meetings. You need to use your time wisely. So be very careful about which meetings you attend and which you politely refuse.
    The person inviting you to a meeting is not responsible for managing your time. Only you can do that. So when you receive a meeting invitation, don’t accept unless it is a meeting for which your participation is immediately and significantly necessary to the job you are doing now.
    Sometimes the meeting will be about something that interests you, but is not immediately necessary. You will have to choose whether you can afford the time. Be careful—there may be more than enough of these meetings to consume your days.
    Sometimes the meeting will be about something that you can contribute to but is not immediately significant to what you are currently doing. You will have to choose whether the loss to your project is worth the benefit to theirs. This may sound cynical, but your responsibility is to your projects first. Still, it is often good for one team to help another, so you may want to discuss your participation with your team and manager.
    Sometimes your presence at the meeting will be requested by someone in authority, such as a very senior engineer in another project or the manager of a different project. You will have to choose whether that authority outweighs your work schedule. Again, your team and your supervisor can be of help in making that decision.
    One of the most important duties of your manager is to keep you out of meetings. A good manager will be more than willing to defend your decision to decline attendance because that manager is just as concerned about your time as you are.

    Leaving

    Meetings don’t always go as planned. Sometimes you find yourself sitting in a meeting that you would have declined had you known more. Sometimes new topics get added, or somebody’s pet peeve dominates the discussion. Over the years I’ve developed a simple rule: When the meeting gets boring, leave.
    Again, you have an obligation to manage your time well. If you find yourself stuck in a meeting that is not a good use of your time, you need to find a way to politely exit that meeting.
    Clearly you should not storm out of a meeting exclaiming “This is boring!” There’s no need to be rude. You can simply ask, at an opportune moment, if your presence is still necessary. You can explain that you can’t afford a lot more time, and ask whether there is a way to expedite the discussion or shuffle the agenda.
    The important thing to realize is that remaining in a meeting that has become a waste of time for you, and to which you can no longer significantly contribute, is unprofessional. You have an obligation to wisely spend your employer’s time and money, so it is not unprofessional to choose an appropriate moment to negotiate your exit.

    Have an Agenda and a Goal

    The reason we are willing to endure the cost of meetings is that we sometimes do need the participants together in a room to help achieve a specific goal. To use the participants’ time wisely, the meeting should have a clear agenda, with times for each topic and a stated goal.
    If you are asked to go to a meeting, make sure you know what discussions are on the table, how much time is allotted for them, and what goal is to be achieved. If you can’t get a clear answer on these things, then politely decline to attend.
    If you go to a meeting and you find that the agenda has been high-jacked or abandoned, you should request that the new topic be tabled and the agenda be followed. If this doesn’t happen, you should politely leave when possible.

    Stand-Up Meetings

    These meetings are part of the Agile cannon. Their name comes from the fact that the participants are expected to stand while the meeting is in session. Each participant takes a turn to answer three questions:
    1.  What did I do yesterday?
    2. What am I going to do today?
    3. What’s in my way?
    That’s all. Each question should require no more than twenty seconds, so each participant should require no more than one minute. Even in a group of ten people this meeting should be over well before ten minutes has elapsed.

    Iteration Planning Meetings

    These are the most difficult meetings in the Agile canon to do well. Done poorly, they take far too much time. It takes skill to make these meetings go well, a skill that is well worth learning.
    Iteration planning meetings are meant to select the backlog items that will be executed in the next iteration. Estimates should already be done for the candidate items. Assessment of business value should already be done. In really good organizations the acceptance/component tests will already be written, or at least sketched out.
    The meeting should proceed quickly with each candidate backlog item being briefly discussed and then either selected or rejected. No more than five or ten minutes should be spent on any given item. If a longer discussion is needed, it should be scheduled for another time with a subset of the team.
    My rule of thumb is that the meeting should take no more than 5% of the total time in the iteration. So for a one week iteration (forty hours) the meeting should be over within two hours.

    Iteration Restrospective and Demo

    These meetings are conducted at the end of each iteration. Team members discuss what went right and what went wrong. Stakeholders see a demo of the newly working features. These meetings can be badly abused and can soak up a lot of time, so schedule them 45 minutes before quitting time on the last day of the iteration. Allocate no more than 20 minutes for retrospective and 25 minutes for the demo. Remember, it’s only been a week or two so there shouldn’t be all that much to talk about.

    Arguments/Disagreements

    Kent Beck once told me something profound: “Any argument that can’t be settled in five minutes can’t be settled by arguing.” The reason it goes on so long is that there is no clear evidence supporting either side. The argument is probably religious, as opposed to factual.
    Technical disagreements tend to go off into the stratosphere. Each party has all kinds of justifications for their position but seldom any data. Without data, any argument that doesn’t forge agreement within a few minutes (somewhere between five and thirty) simply won’t ever forge agreement. The only thing to do is to go get some data.
    Some folks will try to win an argument by force of character. They might yell, or get in your face, or act condescending. It doesn’t matter; force of will doesn’t settle disagreements for long. Data does.
    Some folks will be passive-aggressive. They’ll agree just to end the argument, and then sabotage the result by refusing to engage in the solution. They’ll say to themselves, “This is the way they wanted it, and now they’re going to get what they wanted.” This is probably the worst kind of unprofessional behavior there is. Never, ever do this. If you agree, then youmust engage.
    How do you get the data you need to settle a disagreement? Sometimes you can run experiments, or do some simulation or modeling. But sometimes the best alternative is to simply flip a coin to choose one of the two paths in question.
    If things work out, then that path was workable. If you get into trouble, you can back out and go down the other path. It would be wise to agree on a time as well as a set of criteria to help determine when the chosen path should be abandoned.
    Beware of meetings that are really just a venue to vent a disagreement and to gather support for one side or the other. And avoid those where only one of the arguers is presenting.
    If an argument must truly be settled, then ask each of the arguers to present their case to the team in five minutes or less. Then have the team vote. The whole meeting will take less than fifteen minutes.

    Thursday, 30 August 2012

    Some development tips and tricks


    These are just some tips and tricks I learnt over my career that I'd like to share. This list does not contains silver bullets and it doesn't pretend to be complete or be an absolute truth. It's just a list that I hope may be helpful for someone.

    1 )  Push the coding to the last

    This point can be also be read as think before coding. I found myself, lots of times, especially in the beginning of my career, in rush of writing classes, methods, interfaces as soon as I was receiving a spec for a new functionality.
    This impulse turned out 90% of the times into a PAINFUL situation. The spec was unclear and so unclear was my code; The spec was too "code oriented" and so blindly coding this was producing wrong design/ implementation that needed to be trashed out and completely re-designed;
    Many other are the disadvantages of writing code straight away after receiving a spec. So, lesson learnt and this is what I'm doing now after receiving a spec/story to develop:
    1. I stay away from the keyboard!
    2. I print the spec (sorry amazonian jaguars ) and I take my time to read them carefully. Do not think that everything you will read there is exempt of mistakes or cannot be done in better and simpler ways. At the end of the day, people who wrote the specs, know little or nothing about the software, what they know is how to make more money with new functionality.
    3. If something is not clear to you, it will not clarify magically by itself if you start to code. Ask questions to other colleagues, to the business, clarify as much as possible and only when you feel confident, when you see the real pitcure of what they really want, then and only then you can switch the monitor on and click on the eclipse icon...

    2 )  Simple = perfect

    Make the 2 famous principles, KISS and YAGNI,   part of your blood, skin and bones. Strive for simplicity, forget about the trends,  focus on the most basic thing that will give you what is needed. Don't think straight about XML configuration, spring/seam framework, drools, aspects, multithreading solutions, ejbs, or whatever complex/cool technology you know or you heard out there, nobody really cares about the technologies you use.
    What everyone cares is that your code does what is supposed to do, it is READABLE and it is MAINTAINABLE.
    Pure java is enough to cover 90% or more of everything you need. Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live. Make him happy, write simple, clear straightforward code.
    I remember I read somewhere that, if you read your code after 1 or 2 years and you immediately understand everything is doing and you cannot simplify it more, than your code is PERFECT.

    3 )  Paper and pen

    I never found a tool more useful than paper and pen to design software.
    Before writing software I usually spend a bit of time trying to put the idea of the design down on paper.
    I then , if in doubt, go through it with a colleague. Because it is on paper I can fast go to the point with my pair and he can quick tell me if I'm missing something.
    Knowing that you are missing something in a piece of paper, it's far way better then knowing that you are missing something in the code!
    So don't waste time using UML tools, unless what you are doing is big-fantastic-amazing-new  architectural prototype.

    4 )  Don't leave for tomorrow what you can do today

    If you are fixing a bug or adding new functionality and you notice in the existing code, DUPLICATION or BAD NAMES  or a POSSIBLE BUG then FIX IT IMMEDIATELY.
    Don't wait for the next sprint and don't add a technical story in the technical backlog. Technical stories laid in the backlog for long time, when/if  it will be the time to work on it, it will be more complicated to re-understand the context of the problem and fix it.
    The exception it's when the fix/refactoring is too complex and required long time, then it's appropriate to create a story in the technical backlog!

    5 )  You have time!

    Really, you have time! Don't rush. There is no competition and you are not at the programming Olympics.
    Your job is to deliver good quality code. That's it. This is your job!
    If you feel that a task takes longer that what you initially estimated, just make the team aware in the next stand up and that's it.
    If a client/manager is screaming above your shoulders because he wants something faster than you can deliver, it's not your problem!!! When they say "I want this functionality to be ready asap" translated in Truthlish it means "I want this functionality to be PERFECT with NO BUGS asap". They will be happier to wait more and have less bugs than having a fast release full of issues.
    So take your time and be intransigent on the quality level of your software and forget about external pressures!

    6 ) Implement leaves first

    So, you just received a brand new story to develop and you want to implement it right.
    For example the story is about calculating item prices. One price for each item. Each price is obtained with a different calculation.
    Choose one item price logic and as first thing write a unit test against this logic. Don't be stressed about implementing the whole design or writing interfaces, abstract classes etc. Focus on one small leaf per time!
    When the first leaf is finished, start with a second test for the second small logic you want to implement. The design will come out almost by itself. The tests will tell you which direction is best to take.

    7 ) Do Pair programming!

    I fully applied this technique only recently (less than 1 year ago) and I have to say, it's powerful! It is twice productive than working alone, the quality of the code is superior, the development speed is increased.
    A strength of this technique is the fact that is funny. being funny and so more stimulating means that you are more focused and you pay more attention to details.
    You can learn a lot doing pair programming, so push for it as much as you can!

    8 ) Rarely use checked Exceptions

    Every time I use an API that force me to put around its method call the try and catch block, it makes me nervous, like a violent psychopath, but often I don't know where they leave. Especially if there is nothing I can do about the exception. What the hell I' m supposed to do with this error?
    If you want to use checked Exception used them ONLY if the client can reasonably recover from it at run time! Remember that checked exceptions will spread all over your design in case you need to extend the behavior!

    9 ) Say NO to Hacks

    Programming is like sex. One mistake and you have to support it for the rest of your life. (Michael Sinz). And Hacks ARE mistakes!

    Simply don't implement hacks. I did it in the past, for whatever reasons ( no time,pressure, desire to release a feature as soon as possible, managers screaming, Orcs, Leprechauns, whatever), and now after years we need to maintain them. Hacks are difficult to understand,they break the normal logic flow of your code and they are hard to die! You implement an hack today and tomorrow (1 year after maybe ) someone else will need to fix a bug on this hack and ..well good luck with that!
    Spend more time on the spec if the hack is a business request, and explain why this will cost a lot to maintain. Propose other solutions, discuss it with your team, a better solution is on the way!

    10 ) Forget about comments, just write proper names!

    Write proper names when writing packages, classes, methods and variables.
    Write names that make sense, ask a review before committing your code, but don't explain verbally what you have done, try first letting your reviewer read the code, and see how good you were in writing self explanatory code!
    Comments need to be maintained, otherwise they are misleading. How often did you fix a bug in the code and you changed the class documentation?me, rarely!Use javadoc only if it is really necessary!and if you do,then remember to update them every time you change the code and enforce the same behavior in your team!

    11 ) Reinvent the wheels

    Read books, blogs, tutorial, etc as much as possible, but always with a critical and open mind! The same apply when listening to your team or leader. Don't be fooled by authorities, think always with your own mind.
    If you decide to go for some approach it must be because you believe in it. Because you see good reasons to do so. If you feel that something could be done better or you see problems in the approach you are using , discuss it with your team and try to clarify your doubts. If after talking to the team you still feel that things should be done differently, then push for better approaches and fight for your ideas!
    Sometimes, to progress, you need to reinvent the wheels or at this time we were all developing in FORTRAN.

    Thursday, 2 August 2012

    A simple way to test distributed applications

    So, testing distributed applications is not easy, we all know it.
    Too many variants to take in considerations which usually lead to an high instability of the tests.

    Let say we have a front end application sending messages to a distribution engine which then forward the messages to other remote destinations. Sounds familiar?

    OK so, how you test that messages travelling correctly trough all the predefined servers?

    What if I want to keep my tests independent from any integration framework?

    My solution is in the logs.
    Why not rely on the logs to prove that your application is working as expected?

    Logs are often underrated for performance/acceptance/smoke tests, but if correctly written, they can provide all the information you need to measure the status of your software at any point of its execution.

    Testing relying on logs is a non intrusive way to test and no performances or anything will be affected. Applying this concept to an hypothetical integration test it's easy (at least in UNIX environments :) ), thanks to libraries like Grep4j:


    import static org.grep4j.core.Grep4j.grep;
    import static org.grep4j.core.Grep4j.regularExpression;
    import static org.grep4j.core.fluent.Dictionary.on;
    import static org.grep4j.core.fluent.Dictionary.executing;
    ...
    
    @Test
    public void aCreateMessageShouldPassThroughAllTheFinalDestinations() {
      List profiles =  Arrays.asList(distributionServerLog(),
                                     destination1ServerLog(),
                                     destination2ServerLog(),
                                     destination3ServerLog());
    
    assertThat(executing(grep(regularExpression("MessageId(.*)Received"), on(profiles))).totalLines(), is(4));
    
    }


    As you can see, in a very simple way you have an efficient end-to-end test across different machines.

    I think this approach is also a good option when you want to build acceptance or regression tests around legacy applications. You can treat your legacy app as a black box and just test the expected output in the log. 

    Finally, I reckon this way of test will force the developers to standardize and uniform the way to log in the code which is always good :)