DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Latest Articles - DZone

article thumbnail
AlertDialog and DialogFragment Example in Xamarin Android
Dialog is like any other window that pops up in front of current window, used to show some short message, taking user input or to ask user decisions.
July 14, 2015
by Nilanchala Panigrahy
· 33,067 Views
article thumbnail
Using Camel Routes In Java EE Components
You can start using Apache Camel routes in Java EE components by integrating Camel with the WildFly App Server, using the WildFly-Camel Subsystem.
July 14, 2015
by Markus Eisele
· 10,898 Views · 1 Like
article thumbnail
Unit Testing w/ JUnit Using Maven and IntelliJ - Pt.1
Take your first steps in using JUnit to unit test your Java code with the help of tools like Maven, a build tool, and IntelliJ IDEA, a popular IDE.
July 13, 2015
by John Thompson
· 59,771 Views · 5 Likes
article thumbnail
Using the H2 Database Console in Spring Boot with Spring Security
H2 as a memory database for Spring-based applications is lightweight, easy to use, and emulates other RDBMS with the help of JPA and Hibernate.
July 13, 2015
by John Thompson
· 102,767 Views · 6 Likes
article thumbnail
Installing WebSphere Liberty Profile Server Then Adding Features
IBM WebSphere Liberty Profile is a really fast and easy to to use application server that is now Java EE 6 Web Profile-certified.
July 13, 2015
by Belal Galal
· 13,655 Views · 1 Like
article thumbnail
JAX-RS and HTTP ‘OPTIONS’
The JAX-RS specification defines sensible defaults for the HTTP OPTIONS command. I actually stumbled upon this by chance!
July 13, 2015
by Abhishek Gupta DZone Core CORE
· 7,422 Views · 2 Likes
article thumbnail
Design Patterns in Automated Testing
Learn how to make your test automation framework better through Page Objects, Facades, and Singletons.
July 13, 2015
by Anton Angelov
· 81,195 Views · 7 Likes
article thumbnail
Sending Simple SMS Using Kannel
Sending SMS via HTTP GET Sending SMS via HTTP GET package com.simpleget; import java.io.IOException; import java.net.URI; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.utils.URIBuilder; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; public class simpleGet { public static void main(String[] args) { //Create Http client CloseableHttpClient httpclient = HttpClients.createDefault(); HttpGet httpGet = null; CloseableHttpResponse response = null; HttpEntity entity = null; try{ //Create GET URL URI uri = new URIBuilder() .setScheme("http") .setHost("localhost:13003") .setPath("/cgi-bin/sendsms") .setParameter("username", "abc") // kannel username .setParameter("password", "xyz") // kannel password .setParameter("smsc", "send") // smsc name .setParameter("dlr-mask", "31") .setParameter("from", "Test") // sender of message (can be any string or number) .setParameter("to", "980010.....") // destination (must be a mobile number) .setParameter("text", "hello sending test message") // message to send .build(); httpGet = new HttpGet(uri); LOG.info(httpGet.getURI()); httpGet.setHeader("content-type", "text/plain"); response = httpclient.execute(httpGet); LOG.info(response.getStatusLine()); entity = response.getEntity(); EntityUtils.consume(entity); } catch (Exception e) { e.printStackTrace(); } finally { try { response.close(); } catch (IOException e) { e.printStackTrace(); } } } } Sending SMS via HTTP POST package com.simplepost; import java.io.IOException; import java.io.InputStream; import org.apache.commons.io.IOUtils; import org.apache.http.Consts; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; public class SimplePost { public static void main(String[] args) { String url = "http://localhost:13013/cgi-bin/sendsms"; CloseableHttpClient httpClient = HttpClients.createDefault(); HttpPost httpPost = new HttpPost(url); CloseableHttpResponse response = null; StringEntity entity = null; //For sending SMS using POST method requires whole message to be in xml string format. It has all the parameters that are in get only in xml format. String inputXML= "9780.....Test SenderHello +estingabcxyzsend"; // While using HTTP POST you have to set content type to "text/xml" or else it wont work InputStream in ; entity = new StringEntity(inputXML, ContentType.create("text/xml", Consts.UTF_8)); entity.setChunked(true); try { httpPost = new HttpPost(url); httpPost.setEntity(entity); response = httpClient.execute(httpPost); System.out.println(response.getStatusLine()); in=response.getEntity().getContent(); String body = IOUtils.toString(in); System.out.println(body); EntityUtils.consume(entity); } catch (Exception e) { e.printStackTrace(); } finally { try { response.close(); } catch (IOException e) { e.printStackTrace(); } } } } Kannel is an open source SMS Gateway which is used widely for sending SMS (single or bulk SMS). You can get most of the information about how to configure and use kannel in the user guide The code snippet provided above have simple way to send SMS using Kannel via HTTP POST and HTTP GET.
July 9, 2015
by Kirti Mandwade
· 12,465 Views · 3 Likes
article thumbnail
Docker in Action: The Shared Memory Namespace
In this article, excerpted from the book Docker in Action, I will show you how to open access to shared memory between containers. Linux provides a few tools for sharing memory between processes running on the same computer. This form of inter-process communication (IPC) performs at memory speeds. It is often used when the latency associated with network or pipe based IPC drags software performance below requirements. The best examples of shared memory based IPC usage is in scientific computing and some popular database technologies like PostgreSQL. Docker creates a unique IPC namespace for each container by default. The Linux IPC namespace partitions shared memory primitives like named shared memory blocks and semaphores, as well as message queues. It is okay if you are not sure what these are. Just know that they are tools used by Linux programs to coordinate processing. The IPC namespace prevents processes in one container from accessing the memory on the host or in other containers. Sharing IPC Primitives Between Containers I’ve created an image named allingeek/ch6_ipc that contains both a producer and consumer. They communicate using shared memory. Listing 1 will help you understand the problem with running these in separate containers. Listing 1: Launch a Communicating Pair of Programs # start a producer docker -d -u nobody --name ch6_ipc_producer \ allingeek/ch6_ipc -producer # start the consumer docker -d -u nobody --name ch6_ipc_consumer \ allingeek/ch6_ipc -consumer Listing 1 starts two containers. The first creates a message queue and starts broadcasting messages on it. The second should pull from the message queue and write the messages to the logs. You can see what each is doing by using the following commands to inspect the logs of each: docker logs ch6_ipc_producer docker logs ch6_ipc_consumer If you executed the commands in Listing 1 something should be wrong. The consumer never sees any messages on the queue. Each process used the same key to identify the shared memory resource but they referred to different memory. The reason is that each container has its own shared memory namespace. If you need to run programs that communicate with shared memory in different containers, then you will need to join their IPC namespaces with the --ipc flag. The --ipc flag has a container mode that will create a new container in the same IPC namespace as another target container. Listing 2: Joining Shared Memory Namespaces # remove the original consumer docker rm -v ch6_ipc_consumer # start a new consumer with a joined IPC namespace docker -d --name ch6_ipc_consumer \ --ipc container:ch6_ipc_producer \ allingeek/ch6_ipc -consumer Listing 2 rebuilds the consumer container and reuses the IPC namespace of the ch6_ipc_producer container. This time the consumer should be able to access the same memory location where the server is writing. You can see this working by using the following commands to inspect the logs of each: docker logs ch6_ipc_producer docker logs ch6_ipc_consumer Remember to cleanup your running containers before moving on: # remember: the v option will clean up volumes, # the f option will kill the container if it is running, # and the rm command takes a list of containers docker rm -vf ch6_ipc_producer ch6_ipc_consumer There are obvious security implications to reusing the shared memory namespaces of containers. But this option is available if you need it. Sharing memory between containers is safer alternative to sharing memory with the host.
July 9, 2015
by Jeff Nickoloff
· 39,446 Views · 1 Like
article thumbnail
Mapping Complex JSON Structures With JDK8 Nashorn
Wondering how you can map a complex JSON structure to another JSON structure using Java? Read this awesome tutorial on mapping complex JSON structures.
July 8, 2015
by Jethro Bakker
· 13,075 Views
article thumbnail
Troubleshooting VisualVM
Today I encountered a strance error opening both Java Mission Control and VisualVM: “Could not open PerfMemory” and “Local Java applications cannot be monitored”: After searching and testing for quite a while, I read the solution at the VisualVM troubleshooting guide: Local Applications Cannot Be Monitored (Error Dialog On Startup) Description: An error dialog saying that local applications cannot be monitored is shown immediately after VisualVM startup. Locally running Java applications are displayed as (pid ###). Resolution: This can happen on Windows systems if the username contains capitalized letters. In this case, username is UserName but the jvmstat directory created by JDK is %TMP%\hsperfdata_username. To workaround the problem, exit all Java applications, delete the %TMP%\hsperfdata_username directory and create new %TMP%\hsperfdata_UserName directory. That's it for this post. Hope I helped someone searching a little less for a solution for this little bugger. :)
July 8, 2015
by Steven Schwenke
· 9,006 Views · 3 Likes
article thumbnail
How to Add Watermark to a MS Word Document Inside Android Applications
This technical tip explains how to add a watermark to a document in Microsoft Word document inside Android Applications. Sometimes you need to insert a watermark into a Word document, for instance if you would like to print a draft document or mark it as confidential. In Microsoft Word, you can quickly insert a watermark using the Insert Watermark command. Not many people using this command realize that such “watermark” is just a shape with text inserted into a header or footer and positioned in the centre of the page. While Aspose.Words doesn't have a single insert watermark command like Microsoft Word, it is very easy to insert any shape or image into a header or footer and thus create a watermark of any imaginable type. The code below inserts a watermark into a Word document. [Java Code Sample] package AddWatermark; import java.awt.Color; import java.io.File; import java.net.URI; import com.aspose.words.Document; import com.aspose.words.Shape; import com.aspose.words.ShapeType; import com.aspose.words.RelativeHorizontalPosition; import com.aspose.words.RelativeVerticalPosition; import com.aspose.words.WrapType; import com.aspose.words.VerticalAlignment; import com.aspose.words.HorizontalAlignment; import com.aspose.words.Paragraph; import com.aspose.words.Section; import com.aspose.words.HeaderFooterType; import com.aspose.words.HeaderFooter; public class Program { public static void main(String[] args) throws Exception { // Sample infrastructure. URI exeDir = Program.class.getResource("").toURI(); String dataDir = new File(exeDir.resolve("../../Data")) + File.separator; Document doc = new Document(dataDir + "TestFile.doc"); insertWatermarkText(doc, "CONFIDENTIAL"); doc.save(dataDir + "TestFile Out.doc"); } /** * Inserts a watermark into a document. * * @param doc The input document. * @param watermarkText Text of the watermark. */ private static void insertWatermarkText(Document doc, String watermarkText) throws Exception { // Create a watermark shape. This will be a WordArt shape. // You are free to try other shape types as watermarks. Shape watermark = new Shape(doc, ShapeType.TEXT_PLAIN_TEXT); // Set up the text of the watermark. watermark.getTextPath().setText(watermarkText); watermark.getTextPath().setFontFamily("Arial"); watermark.setWidth(500); watermark.setHeight(100); // Text will be directed from the bottom-left to the top-right corner. watermark.setRotation(-40); // Remove the following two lines if you need a solid black text. watermark.getFill().setColor(Color.GRAY); // Try LightGray to get more Word-style watermark watermark.setStrokeColor(Color.GRAY); // Try LightGray to get more Word-style watermark // Place the watermark in the page center. watermark.setRelativeHorizontalPosition(RelativeHorizontalPosition.PAGE); watermark.setRelativeVerticalPosition(RelativeVerticalPosition.PAGE); watermark.setWrapType(WrapType.NONE); watermark.setVerticalAlignment(VerticalAlignment.CENTER); watermark.setHorizontalAlignment(HorizontalAlignment.CENTER); // Create a new paragraph and append the watermark to this paragraph. Paragraph watermarkPara = new Paragraph(doc); watermarkPara.appendChild(watermark); // Insert the watermark into all headers of each document section. for (Section sect : doc.getSections()) { // There could be up to three different headers in each section, since we want // the watermark to appear on all pages, insert into all headers. insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_PRIMARY); insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_FIRST); insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_EVEN); } } private static void insertWatermarkIntoHeader(Paragraph watermarkPara, Section sect, int headerType) throws Exception { HeaderFooter header = sect.getHeadersFooters().getByHeaderFooterType(headerType); if (header == null) { // There is no header of the specified type in the current section, create it. header = new HeaderFooter(sect.getDocument(), headerType); sect.getHeadersFooters().add(header); } // Insert a clone of the watermark into the header. header.appendChild(watermarkPara.deepClone(true)); } }
July 8, 2015
by David Zondray
· 18,970 Views
article thumbnail
Where Am I? Collecting GPS Data With Apache Camel
In this article I will tell you how Apache Camel can turn a full-stack Linux microcomputer (like Raspberry Pi) into a device collecting the GPS coordinates.
July 8, 2015
by Henryk Konsek
· 5,774 Views · 1 Like
article thumbnail
How to Address Your Coworker’s Bad Code
You’re sitting at your desk, trying to “track” down a bug that’s been reported, when it happens. The hunt takes you into some method that inspires you to do a double take. It’s about 1,200 lines long, it has switch statements nested three deep, and you think (but you aren’t sure) that it does the same thing two or three times in a row for no particular reason. You look at the source control history and see that this is another “Bob special.” After seeing this, you start thinking about finally having a long overdue talk with Bob so that you don’t have to keep cleaning up these messes. That sure won’t be a fun talk. So how do you approach it? Philosophically Speaking Let’s be clear about something up front. Getting really good at telling teammates that their code is littered with problems is like getting really good at breaking into your car after locking yourself out of it: it’s tactically useful in the moment but indicative that you need a better overall strategy. Your goal shouldn’t be to master gently telling coworkers about their bad code but rather to make the mastery unnecessary. And I say that not as some kind of meta cop-out, but rather to put your strategy into context as an attempt to start or further a relationship. “Getting really good at telling teammates that their code is littered with problems is like getting really good at breaking into your car after locking yourself out of it.” Tweet This Quote When you’re part of a team, someone on your team who is committing bad code is a failure of everyone on the team—yourself included. So as you prepare for the intervention you’re planning with the person in question, keep in mind that you aren’t some kind of neutral crime scene investigator, sizing things up antiseptically. You’re part of the problem, and you share in the responsibility. Your team. Your code. Your problem. The good news is that if you approach this conversation constructively, you’re taking the first step toward fixing the problem, the code, and thus the team. So the key is making it constructive. 5 Ways to Not Make Code Criticism Constructive Before I go into detail about how to approach this conversation, I’ll give you a quick rundown of 5 things not to do. Don’t have the conversation when you’re frustrated or angry. Instead, wait until you’re calm and rational. Don’t get into this unless there’s a demonstrable problem. If you and he just have different casing preferences or something, the tension you create is probably going to nullify the benefits of standardization. Cosmetic coding standards and other relatively minor concerns can and should be addressed with automated static analysis. Don’t rely on seniority or status in any way. There’s no faster way to breed resentment than forcing people to do things they don’t agree with “because you say so.” Don’t expect to revolutionize someone’s entire approach in a single sitting and make the conversation a marathon affair. You want to have a clear and relatively concise message so that you get your point across without exhausting the other person. Improvement will happen over the long haul. Finally, don’t say that the code is “” That’s a useless, subjective way to categorize. Everything in software is about trade offs, so what you want to do is show Bob that he’s paying for quick and dirty coding with maintenance headaches for the rest of the team. Build A Constructive Code Strategy and Environment You’ve already prepared a bit by reading what not to do, so now it’s time to complement that with what to do. There needs to be three main components to this preparation: (1) the gaps you want to address (2) the support for your argument (3) the outcome for which you’re hoping. These three things are going to frame the discussion you intend to have. The gaps are actual, specific problems with Bob’s code. You don’t want to stroll over to Bob’s desk, pull up a chair, sit on it backwards and say, “So, Bob, you’re pretty bad at this programming thing…great talk!” You need to decide what tangible items you want to address during this discussion. What’s the most egregious source of problems? Is it the gigantic methods? The nested switch statements? The duplicate code? Pick one or maybe two of these things to cover. Just as you don’t want to be critical and vague, you also don’t want to be critical and devastatingly specific, reading off 95 of Bob’s greatest coding flaws like some kind of departmental Martin Luther. There may be 95 things wrong with Bob’s code. But if you want to fix all of them, it’s important to lay the groundwork for a mentoring relationship because you’re definitely not going to fix all of them in one day. Building Support: Do Your Research. Let’s say that you’ve decided to focus on method length as the topic to address. The next thing to do is build support for your argument. It’s a lot more credible to cite some supporting studies or widely respected industry figures on the matter than to march over to Bob and declare that his methods are too long. Build a case with evidence for the principle that you want to cover, and then also find specific, problematic instances in the code base to discuss. The last thing you want is to be hand-wavy about the problem—you want to be able to point at it and say, “for instance, this right here is a really big method.” The Outcome Should Be Actionable Having picked your issue and built a case, the last thing to do is choose an outcome toward which to steer the conversation. So you’ve shown Bob a giant method that he wrote and convinced him of the evils of giant methods. “Uh, okay,” he’ll say. “So what now?” Decide ahead of time that you want to work together to break the method into X number of smaller methods or that you want to leave the code in a state where no refactored method is longer than Y lines. Whatever it is, pick something actionable so that you and Bob can cap the conversation off with a joint win. Be courteous At this point, you’re ready to have the hard conversation. If you do it right, it won’t be nearly as hard as you might think, and it will serve as a productive starting point for a series of subsequent conversations that will be easier and perhaps even pleasant. This article originally appeared at SmartBear's Blog, written by Erik Dietrich.
July 8, 2015
by Erik Dietrich
· 14,423 Views · 2 Likes
article thumbnail
Java 8: Master Permutations
Using Permutations, you can try all combinations of an input set.
July 7, 2015
by Per-Åke Minborg
· 39,915 Views · 11 Likes
article thumbnail
Refactoring with Loops and Collection Pipelines: Part 1
The loop is the classic way of processing collections, but with the greater adoption of first-class functions in programming languages the collection pipeline is an appealing alternative. In this article I look at refactoring loops to collection pipelines with a series of small examples. I'm publishing this article in installments. This adds an example of refactoring a loop that summarizes flight delay data for each destination airport. A common task in programming is processing a list of objects. Most programmers naturally do this with a loop, as it's one of the basic control structures we learn with our very first programs. But loops aren't the only way to represent list processing, and in recent years more people are making use of another approach, which I call the collection pipeline. This style is often considered to be part of functional programming, but I used it heavily in Smalltalk. As OO languages support lambdas and libraries that make first class functions easier to program with, then collection pipelines become an appealing choice. Refactoring a Simple Loop into a Pipeline I'll start with a simple example of a loop and show the basic way I refactor one into a collection pipeline. Let's imagine we have a list of authors, each of which has the following data structure. class Author... public string Name { get; set; } public string TwitterHandle { get; set;} public string Company { get; set;} This example uses C# Here is the loop. class Author... static public IEnumerable TwitterHandles(IEnumerable authors, string company) { var result = new List (); foreach (Author a in authors) { if (a.Company == company) { var handle = a.TwitterHandle; if (handle != null) result.Add(handle); } } return result; } My first step in refactoring a loop into a collection pipeline is to apply Extract Variable on the loop collection. class Author... static public IEnumerable TwitterHandles(IEnumerable authors, string company) { var result = new List (); var loopStart = authors; foreach (Author a in loopStart) { if (a.Company == company) { var handle = a.TwitterHandle; if (handle != null) result.Add(handle); } } return result; } This variable gives me a starting point for pipeline operations. I don't have a good name for it right now, so I'll use one that makes sense for the moment, expecting to rename it later. I then start looking at bits of behavior in the loop. The first thing I see is a conditional check, I can move this to the pipeline with a . class Author... static public IEnumerable TwitterHandles(IEnumerable authors, string company) { var result = new List (); var loopStart = authors .Where(a => a.Company == company); foreach (Author a in loopStart) { if (a.Company == company) { var handle = a.TwitterHandle; if (handle != null) result.Add(handle); } } return result; } I see the next part of the loop operates on the twitter handle, rather than the author, so I can use a a . class Author... static public IEnumerable TwitterHandles(IEnumerable authors, string company) { var result = new List (); var loopStart = authors .Where(a => a.Company == company) .Select(a => a.TwitterHandle); foreach (string handle in loopStart) { var handle = a.TwitterHandle; if (handle != null) result.Add(handle); } return result; } Next in the loop as another conditional, which again I can move to a filter operation. class Author... static public IEnumerable TwitterHandles(IEnumerable authors, string company) { var result = new List (); var loopStart = authors .Where(a => a.Company == company) .Select(a => a.TwitterHandle) .Where (h => h != null); foreach (string handle in loopStart) { if (handle != null) result.Add(handle); } return result; } All the loop now does is add everything in its loop collection into the result collection, so I can remove the loop and just return the pipeline result. class Author... static public IEnumerable TwitterHandles(IEnumerable authors, string company) { var result = new List (); return authors .Where(a => a.Company == company) .Select(a => a.TwitterHandle) .Where (h => h != null); foreach (string handle in loopStart) { result.Add(handle); } return result; } Here's the final state of the code class Author... static public IEnumerable TwitterHandles(IEnumerable authors, string company) { return authors .Where(a => a.Company == company) .Select(a => a.TwitterHandle) .Where (h => h != null); } What I like about collection pipelines is that I can see the flow of logic as the elements of the list pass through the pipeline. For me it reads very closely to how I'd define the outcome of the loop "take the authors, choose those who have a company, and get their twitter handles removing any null handles". Furthermore, this style of code is familiar even in different languages who have different syntaxes and different names for pipeline operators. Java public List twitterHandles(List authors, String company) { return authors.stream() .filter(a -> a.getCompany().equals(company)) .map(a -> a.getTwitterHandle()) .filter(h -> null != h) .collect(toList()); } Ruby def twitter_handles authors, company authors .select {|a| company == a.company} .map {|a| a.twitter_handle} .reject {|h| h.nil?} end while this matches the other examples, I would replace the final reject with compact Clojure (defn twitter-handles [authors company] (->> authors (filter #(= company (:company %))) (map :twitter-handle) (remove nil?))) F# let twitterHandles (authors : seq, company : string) = authors |> Seq.filter(fun a -> a.Company = company) |> Seq.map(fun a -> a.TwitterHandle) |> Seq.choose (fun h -> h) again, if I wasn't concerned about matching the structure of the other examples I would combine the map and choose into a single step I've found that once I got used to thinking in terms of pipelines I could apply them quickly even in an unfamiliar language. Since the fundamental approach is the same it's relatively easy to translate from even unfamiliar syntax and function names. Refactoring within the Pipeline, and to a Comprehension Once you have some behavior expressed as a pipeline, there are potential refactorings you can do by reordering steps in the pipeline. One such move is that if you have a map followed by a filter, you can usually move the filter before the map like this. class Author... static public IEnumerable TwitterHandles(IEnumerable authors, string company) { return authors .Where(a => a.Company == company) .Where (a => a.TwitterHandle != null) .Select(a => a.TwitterHandle); } When you have two adjacent filters, you can combine them using a conjunction. class Author... static public IEnumerable TwitterHandles(IEnumerable authors, string company) { return authors .Where(a => a.Company == company && a.TwitterHandle != null) .Select(a => a.TwitterHandle); } Once I have a C# collection pipeline in the form of a simple filter and map like this, I can replace it with a Linq expression class Author... static public IEnumerable TwitterHandles(IEnumerable authors, string company) { return from a in authors where a.Company == company && a.TwitterHandle != null select a.TwitterHandle; } I consider Linq expressions to be a form of , and similarly you can do something like this with any language that supports list comprehensions. It's a matter of taste whether you prefer the list comprehension form, or the pipeline form (I prefer pipelines). In general pipelines are more powerful, in that you can't refactor all pipelines into comprehensions.
July 7, 2015
by Martin Fowler
· 4,001 Views
article thumbnail
Martin Fowler—Bliki: Yagni ("You Aren't Gonna Need It")
yagni originally is an acronym that stands for "you aren't gonna need it". it is a mantra from extremeprogramming that's often used generally in agile software teams. it's a statement that some capability we presume our software needs in the future should not be built now because "you aren't gonna need it". yagni is a way to refer to the xp practice of simple design (from the first edition of the white book the second edition refers to the related notion of "incremental design"). like many elements of xp, it's a sharp contrast to elements of the widely held principles of software engineering in the late 90s. at that time there was a big push for careful up-front planning of software development. let's imagine i'm working with a startup in minas tirith selling insurance for the shipping business. their software system is broken into two main components: one for pricing, and one for sales. the dependencies are such that they can't usefully build sales software until the relevant pricing software is completed. at the moment, the team is working on updating the pricing component to add support for risks from storms. they know that in six months time, they will need to also support pricing for piracy risks. since they are currently working on the pricing engine they consider building the presumptive feature for piracy pricing now, since that way the pricing service will be complete before they start working on the sales software. yagni argues against this, it says that since you won't need piracy pricing for six months you shouldn't build it until it's necessary. so if you think it will take two months to build this software, then you shouldn't start for another four months (neglecting any buffer time for schedule risk and updating the sales component). the first argument for yagni is that while we may now think we need this presumptive feature, it's likely that we will be wrong. after all the context of agile methods is an acceptance that we welcome changing requirements. a plan-driven requirements guru might counter argue that this is because we didn't do a good-enough job of our requirements analysis, we should have put more time and effort into it. i counter that by pointing out how difficult and costly it is to figure out your needs in advance, but even if you can, you can still be blind-sided when the gondor navy wipes out the pirates, thus undermining the entire business model. in this case, there's an obvious cost of the presumptive feature - the cost of build : all the effort spent on analyzing, programming, and testing this now useless feature. but let's consider that we were completely correct with our understanding of our needs, and the gondor navy didn't wipe out the pirates. even in this happy case, building the presumptive feature incurs two serious costs. the first cost is the cost of delayed value. by expending our effort on the piracy pricing software we didn't build some other feature. if we'd instead put our energy into building the sales software for weather risks, we could have put a full storm risks feature into production and be generating revenue two months earlier. this cost of delay due to the presumptive feature is two months revenue from storm insurance. the common reason why people build presumptive features is because they think it will be cheaper to build it now rather than build it later. but that cost comparison has to be made at least against the cost of delay, preferably factoring in the probability that you're building an unnecessary feature, for which your odds are at least ⅔. often people don't think through the comparative cost of building now to building later. one approach i use when mentoring developers in this situation is to ask them to imagine any refactoring they would have to do later to introduce the capability when it's needed. often that thought experiment is enough to convince them that it won't be significantly more expensive to add it later. another result from such an imagining is to add something that's easy to do now, adds minimal complexity, yet significantly reduces the later cost. using lookup tables for error messages rather than inline literals are an example that are simple yet make later translations easier to support. reminder, any extensibility point that’s never used isn’t just wasted effort, it’s likely to also get in your way as well -- jeremy miller the cost of delay is one cost that a successful presumptive feature imposes, but another is the cost of carry . the code for the presumptive feature adds some complexity to the software, this complexity makes it harder to modify and debug that software, thus increasing the cost of other features. the extra complexity from having the piracy-pricing feature in the software might add a couple of weeks to how long it takes to build the storm insurance sales component. that two weeks hits two ways: the additional cost to build the feature, plus the additional cost of delay since it look longer to put it into production. we'll incur a cost of carry on every feature built between now and the time the piracy insurance software starts being useful. should we never need the piracy-pricing software, we'll incur a cost of carry on every feature built until we remove the piracy-pricing feature (assuming we do), together with the cost of removing it. so far i've divided presumptive features in two categories: successful and unsuccessful. naturally there's really a spectrum there, and with one point on that spectrum that's worth highlighting: the right feature built wrong. development teams are always learning, both about their users and about their code base. they learn about the tools they're using and these tools go through regular upgrades. they also learn about how their code works together. all this means that you often realize that a feature coded six months ago wasn't done the way you now realize it should be done. in that case you have accumulated technicaldebt and have to consider the cost of repair for that feature or the on-going costs of working around its difficulties. so we end up with three classes of presumptive features, and four kinds of costs that occur when you neglect yagni for them. my insurance example talks about relatively user-visible functionality, but the same argument applies for abstractions to support future flexibility. when building the storm risk calculator, you may consider putting in abstractions and parameterizations now to support piracy and other risks later. yagni says not to do this, because you may not need the other pricing functions, or if you do your current ideas of what abstractions you'll need will not match what you learn when you do actually need them. this doesn't mean to forego all abstractions, but it does mean any abstraction that makes it harder to understand the code for current requirements is presumed guilty. yagni is at its most visible with larger features, but you see it more frequently with small things. recently i wrote some code that allows me to highlight part of a line of code. for this, i allow the highlighted code to be specified using a regular expression. one problem i see with this is that since the whole regular expression is highlighted, i'm unable to deal with the case where i need the regex to match a larger section than what i'd like to highlight. i expect i can solve that by using a group within the regex and letting my code only highlight the group if a group is present. but i haven't needed to use a regex that matches more than what i'm highlighting yet, so i haven't extended my highlighting code to handle this case - and won't until i actually need it. for similar reasons i don't add fields or methods until i'm actually ready to use them. small yagni decisions like this fly under the radar of project planning. as a developer it's easy to spend an hour adding an abstraction that we're sure will soon be needed. yet all the arguments above still apply, and a lot of small yagni decisions add up to significant reductions in complexity to a code base, while speeding up delivery of features that are needed more urgently. now we understand why yagni is important we can dig into a common confusion about yagni. yagni only applies to capabilities built into the software to support a presumptive feature, it does not apply to effort to make the software easier to modify. yagni is only a viable strategy if the code is easy to change, so expending effort on refactoring isn't a violation of yagni because refactoring makes the code more malleable. similar reasoning applies for practices like selftestingcode and continuousdelivery . these are enabling practices for evolutionary design , without them yagni turns from a beneficial practice into a curse. but if you do have a malleable code base, then yagni reinforces that flexibility. yagni has the curious property that it is both enabled by and enables evolutionary design. yagni is not a justification for neglecting the health of your code base. yagni requires (and enables) malleable code. i also argue that yagni only applies when you introduce extra complexity now that you won't take advantage of until later. if you do something for a future need that doesn't actually increase the complexity of the software, then there's no reason to invoke yagni. having said all this, there are times when applying yagni does cause a problem, and you are faced with an expensive change when an earlier change would have been much cheaper. the tricky thing here is that these cases are hard to spot in advance, and much easier to remember than the cases where yagni saved effort . my sense is that yagni-failures are relatively rare and their costs are easily outweighed by when yagni succeeds.
July 7, 2015
by Martin Fowler
· 3,544 Views
article thumbnail
Optional Parameters in Java 8 Lambda Expressions
Yeah, they don't really exist, but we can use polymorphism, method overloading and default methods instead to make it a bit more convenient to use our APIs. As an example, here's an event bus implementation where I can register event handlers with an optional header parameter. Bus bus = new Bus(); bus.register(event -> System.out.println("I gots an event")); bus.register((event,header) -> System.out.println("I gots an event w/ header")); Here are the dirty details on how you can do this (and - when dispatching - events, use default methods to avoid type coercion.
July 7, 2015
by Jochen Bedersdorfer
· 7,650 Views · 1 Like
article thumbnail
Standalone Java application with Jersey and Jetty
I’ve built a small example of running a standalone Java application that both serves static HTML, JavaScript, CSS content, and also publishes a REST web service.
July 7, 2015
by Alan Hohn
· 40,057 Views · 3 Likes
article thumbnail
Modern Database Design by Example
The database design task, which was once monotonous, has now become an exciting task which requires a lot of creativity.
July 6, 2015
by Anh Tuan Nguyen
· 13,306 Views · 1 Like
  • Previous
  • ...
  • 1453
  • 1454
  • 1455
  • 1456
  • 1457
  • 1458
  • 1459
  • 1460
  • 1461
  • 1462
  • ...
  • Next
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook
×